summaryrefslogtreecommitdiffstats
path: root/dbaccess
diff options
context:
space:
mode:
Diffstat (limited to 'dbaccess')
-rw-r--r--dbaccess/AllLangMoTarget_dba.mk13
-rw-r--r--dbaccess/CppunitTest_dbaccess_RowSetClones.mk117
-rw-r--r--dbaccess/CppunitTest_dbaccess_dialog_save.mk109
-rw-r--r--dbaccess/CppunitTest_dbaccess_dialogs_test.mk69
-rw-r--r--dbaccess/CppunitTest_dbaccess_embeddeddb_performancetest.mk73
-rw-r--r--dbaccess/CppunitTest_dbaccess_empty_stdlib_save.mk109
-rw-r--r--dbaccess/CppunitTest_dbaccess_firebird_test.mk70
-rw-r--r--dbaccess/CppunitTest_dbaccess_hsqlbinary_import.mk114
-rw-r--r--dbaccess/CppunitTest_dbaccess_hsqldb_test.mk84
-rw-r--r--dbaccess/CppunitTest_dbaccess_hsqlschema_import.mk102
-rw-r--r--dbaccess/CppunitTest_dbaccess_macros_test.mk102
-rw-r--r--dbaccess/CppunitTest_dbaccess_nolib_save.mk109
-rw-r--r--dbaccess/CppunitTest_dbaccess_tdf119625.mk114
-rw-r--r--dbaccess/CppunitTest_dbaccess_tdf126268.mk114
-rw-r--r--dbaccess/Executable_odbcconfig.mk31
-rw-r--r--dbaccess/IwyuFilter_dbaccess.yaml162
-rw-r--r--dbaccess/JunitTest_dbaccess_complex.mk51
-rw-r--r--dbaccess/JunitTest_dbaccess_unoapi.mk14
-rw-r--r--dbaccess/Library_dba.mk138
-rw-r--r--dbaccess/Library_dbahsql.mk51
-rw-r--r--dbaccess/Library_dbaxml.mk72
-rw-r--r--dbaccess/Library_dbu.mk252
-rw-r--r--dbaccess/Library_sdbt.mk46
-rw-r--r--dbaccess/Makefile14
-rw-r--r--dbaccess/Module_dbaccess.mk99
-rw-r--r--dbaccess/PythonTest_dbaccess_python.mk26
-rw-r--r--dbaccess/README.md5
-rw-r--r--dbaccess/UIConfig_dbaccess.mk96
-rw-r--r--dbaccess/UIConfig_dbapp.mk34
-rw-r--r--dbaccess/UIConfig_dbbrowser.mk25
-rw-r--r--dbaccess/UIConfig_dbquery.mk22
-rw-r--r--dbaccess/UIConfig_dbrelation.mk20
-rw-r--r--dbaccess/UIConfig_dbtable.mk20
-rw-r--r--dbaccess/UIConfig_dbtdata.mk24
-rw-r--r--dbaccess/inc/bitmaps.hlst34
-rw-r--r--dbaccess/inc/core_resource.hxx68
-rw-r--r--dbaccess/inc/dbaccess_slotid.hrc108
-rw-r--r--dbaccess/inc/dbadllapi.hxx32
-rw-r--r--dbaccess/inc/helpids.h110
-rw-r--r--dbaccess/inc/pch/precompiled_dba.cxx12
-rw-r--r--dbaccess/inc/pch/precompiled_dba.hxx274
-rw-r--r--dbaccess/inc/pch/precompiled_dbahsql.cxx12
-rw-r--r--dbaccess/inc/pch/precompiled_dbahsql.hxx56
-rw-r--r--dbaccess/inc/pch/precompiled_dbaxml.cxx12
-rw-r--r--dbaccess/inc/pch/precompiled_dbaxml.hxx107
-rw-r--r--dbaccess/inc/pch/precompiled_dbu.cxx12
-rw-r--r--dbaccess/inc/pch/precompiled_dbu.hxx247
-rw-r--r--dbaccess/inc/pch/precompiled_sdbt.cxx12
-rw-r--r--dbaccess/inc/pch/precompiled_sdbt.hxx48
-rw-r--r--dbaccess/inc/query.hrc35
-rw-r--r--dbaccess/inc/strings.hrc455
-rw-r--r--dbaccess/inc/strings.hxx269
-rw-r--r--dbaccess/inc/templwin.hrc57
-rw-r--r--dbaccess/qa/complex/dbaccess/ApplicationController.java159
-rw-r--r--dbaccess/qa/complex/dbaccess/Beamer.java127
-rw-r--r--dbaccess/qa/complex/dbaccess/CRMBasedTestCase.java63
-rw-r--r--dbaccess/qa/complex/dbaccess/CopyTableInterActionHandler.java37
-rw-r--r--dbaccess/qa/complex/dbaccess/CopyTableWizard.java194
-rw-r--r--dbaccess/qa/complex/dbaccess/DataSource.java68
-rw-r--r--dbaccess/qa/complex/dbaccess/DatabaseApplication.java73
-rw-r--r--dbaccess/qa/complex/dbaccess/DatabaseDocument.java995
-rw-r--r--dbaccess/qa/complex/dbaccess/FileHelper.java35
-rw-r--r--dbaccess/qa/complex/dbaccess/Parser.java183
-rw-r--r--dbaccess/qa/complex/dbaccess/PropertyBag.java302
-rw-r--r--dbaccess/qa/complex/dbaccess/Query.java107
-rw-r--r--dbaccess/qa/complex/dbaccess/QueryInQuery.java177
-rw-r--r--dbaccess/qa/complex/dbaccess/RowSet.java942
-rw-r--r--dbaccess/qa/complex/dbaccess/RowSetEventListener.java102
-rw-r--r--dbaccess/qa/complex/dbaccess/SingleSelectQueryComposer.java351
-rw-r--r--dbaccess/qa/complex/dbaccess/TestCase.java232
-rw-r--r--dbaccess/qa/complex/dbaccess/UISettings.java132
-rw-r--r--dbaccess/qa/complex/dbaccess/makefile.mk93
-rw-r--r--dbaccess/qa/extras/dialog-save.cxx102
-rw-r--r--dbaccess/qa/extras/empty-stdlib-save.cxx114
-rw-r--r--dbaccess/qa/extras/hsql_schema_import.cxx210
-rw-r--r--dbaccess/qa/extras/macros-test.cxx51
-rw-r--r--dbaccess/qa/extras/nolib-save.cxx104
-rw-r--r--dbaccess/qa/extras/rowsetclones.cxx133
-rw-r--r--dbaccess/qa/extras/testdocuments/RowSetClones.odbbin0 -> 33734 bytes
-rw-r--r--dbaccess/qa/extras/testdocuments/fdo84315.odbbin0 -> 3592 bytes
-rw-r--r--dbaccess/qa/extras/testdocuments/testDialogSave.odbbin0 -> 34059 bytes
-rw-r--r--dbaccess/qa/extras/testdocuments/testdb.odbbin0 -> 3700 bytes
-rw-r--r--dbaccess/qa/python/fdo84315.py76
-rw-r--r--dbaccess/qa/unit/data/dbaccess-dialogs-test.txt111
-rw-r--r--dbaccess/qa/unit/data/firebird_empty.odbbin0 -> 2148 bytes
-rw-r--r--dbaccess/qa/unit/data/firebird_integer_ods12.odbbin0 -> 77617 bytes
-rw-r--r--dbaccess/qa/unit/data/hsqldb_empty.odbbin0 -> 2345 bytes
-rw-r--r--dbaccess/qa/unit/data/hsqldb_migration_test.odbbin0 -> 3949 bytes
-rw-r--r--dbaccess/qa/unit/data/tdf119625.odbbin0 -> 6350 bytes
-rw-r--r--dbaccess/qa/unit/data/tdf126268.odbbin0 -> 5015 bytes
-rw-r--r--dbaccess/qa/unit/data/tdf132924.odbbin0 -> 3148 bytes
-rw-r--r--dbaccess/qa/unit/dbaccess-dialogs-test.cxx61
-rw-r--r--dbaccess/qa/unit/dbtest_base.cxx86
-rw-r--r--dbaccess/qa/unit/embeddeddb_performancetest.cxx358
-rw-r--r--dbaccess/qa/unit/firebird.cxx125
-rw-r--r--dbaccess/qa/unit/hsql_binary_import.cxx101
-rw-r--r--dbaccess/qa/unit/hsqldb.cxx47
-rw-r--r--dbaccess/qa/unit/tdf119625.cxx121
-rw-r--r--dbaccess/qa/unit/tdf126268.cxx97
-rw-r--r--dbaccess/qa/unoapi/dbaccess.props24
-rw-r--r--dbaccess/qa/unoapi/dbaccess.sce32
-rw-r--r--dbaccess/qa/unoapi/knownissues.xcl80
-rw-r--r--dbaccess/qa/unoapi/testdocuments/TestDB/testDB.dbfbin0 -> 949 bytes
-rw-r--r--dbaccess/qa/unoapi/testdocuments/TestDB/testDB.dbtbin0 -> 512 bytes
-rw-r--r--dbaccess/source/core/api/BookmarkSet.cxx204
-rw-r--r--dbaccess/source/core/api/BookmarkSet.hxx57
-rw-r--r--dbaccess/source/core/api/CIndexes.cxx87
-rw-r--r--dbaccess/source/core/api/CIndexes.hxx47
-rw-r--r--dbaccess/source/core/api/CRowSetColumn.cxx92
-rw-r--r--dbaccess/source/core/api/CRowSetColumn.hxx49
-rw-r--r--dbaccess/source/core/api/CRowSetDataColumn.cxx236
-rw-r--r--dbaccess/source/core/api/CRowSetDataColumn.hxx99
-rw-r--r--dbaccess/source/core/api/CacheSet.cxx580
-rw-r--r--dbaccess/source/core/api/CacheSet.hxx172
-rw-r--r--dbaccess/source/core/api/FilteredContainer.cxx459
-rw-r--r--dbaccess/source/core/api/HelperCollections.cxx106
-rw-r--r--dbaccess/source/core/api/HelperCollections.hxx106
-rw-r--r--dbaccess/source/core/api/KeySet.cxx1463
-rw-r--r--dbaccess/source/core/api/KeySet.hxx216
-rw-r--r--dbaccess/source/core/api/OptimisticSet.cxx586
-rw-r--r--dbaccess/source/core/api/OptimisticSet.hxx76
-rw-r--r--dbaccess/source/core/api/PrivateRow.cxx133
-rw-r--r--dbaccess/source/core/api/PrivateRow.hxx58
-rw-r--r--dbaccess/source/core/api/RowSet.cxx2965
-rw-r--r--dbaccess/source/core/api/RowSet.hxx527
-rw-r--r--dbaccess/source/core/api/RowSetBase.cxx1438
-rw-r--r--dbaccess/source/core/api/RowSetBase.hxx402
-rw-r--r--dbaccess/source/core/api/RowSetCache.cxx1713
-rw-r--r--dbaccess/source/core/api/RowSetCache.hxx190
-rw-r--r--dbaccess/source/core/api/RowSetCacheIterator.cxx91
-rw-r--r--dbaccess/source/core/api/RowSetCacheIterator.hxx72
-rw-r--r--dbaccess/source/core/api/RowSetRow.hxx52
-rw-r--r--dbaccess/source/core/api/SingleSelectQueryComposer.cxx1922
-rw-r--r--dbaccess/source/core/api/StaticSet.cxx280
-rw-r--r--dbaccess/source/core/api/StaticSet.hxx75
-rw-r--r--dbaccess/source/core/api/TableDeco.cxx634
-rw-r--r--dbaccess/source/core/api/View.cxx120
-rw-r--r--dbaccess/source/core/api/WrappedResultSet.cxx184
-rw-r--r--dbaccess/source/core/api/WrappedResultSet.hxx60
-rw-r--r--dbaccess/source/core/api/callablestatement.cxx250
-rw-r--r--dbaccess/source/core/api/column.cxx411
-rw-r--r--dbaccess/source/core/api/columnsettings.cxx150
-rw-r--r--dbaccess/source/core/api/datacolumn.cxx396
-rw-r--r--dbaccess/source/core/api/datacolumn.hxx107
-rw-r--r--dbaccess/source/core/api/datasettings.cxx191
-rw-r--r--dbaccess/source/core/api/definitioncolumn.cxx610
-rw-r--r--dbaccess/source/core/api/preparedstatement.cxx412
-rw-r--r--dbaccess/source/core/api/query.cxx383
-rw-r--r--dbaccess/source/core/api/query.hxx147
-rw-r--r--dbaccess/source/core/api/querycomposer.cxx265
-rw-r--r--dbaccess/source/core/api/querycontainer.cxx430
-rw-r--r--dbaccess/source/core/api/querydescriptor.cxx269
-rw-r--r--dbaccess/source/core/api/querydescriptor.hxx143
-rw-r--r--dbaccess/source/core/api/resultcolumn.cxx296
-rw-r--r--dbaccess/source/core/api/resultcolumn.hxx87
-rw-r--r--dbaccess/source/core/api/resultset.cxx994
-rw-r--r--dbaccess/source/core/api/resultset.hxx221
-rw-r--r--dbaccess/source/core/api/statement.cxx591
-rw-r--r--dbaccess/source/core/api/table.cxx352
-rw-r--r--dbaccess/source/core/api/tablecontainer.cxx456
-rw-r--r--dbaccess/source/core/api/viewcontainer.cxx254
-rw-r--r--dbaccess/source/core/dataaccess/ComponentDefinition.cxx285
-rw-r--r--dbaccess/source/core/dataaccess/ComponentDefinition.hxx159
-rw-r--r--dbaccess/source/core/dataaccess/ContentHelper.cxx615
-rw-r--r--dbaccess/source/core/dataaccess/ModelImpl.cxx1432
-rw-r--r--dbaccess/source/core/dataaccess/SharedConnection.cxx154
-rw-r--r--dbaccess/source/core/dataaccess/SharedConnection.hxx118
-rw-r--r--dbaccess/source/core/dataaccess/bookmarkcontainer.cxx301
-rw-r--r--dbaccess/source/core/dataaccess/commandcontainer.cxx100
-rw-r--r--dbaccess/source/core/dataaccess/commandcontainer.hxx72
-rw-r--r--dbaccess/source/core/dataaccess/commanddefinition.cxx153
-rw-r--r--dbaccess/source/core/dataaccess/commanddefinition.hxx125
-rw-r--r--dbaccess/source/core/dataaccess/connection.cxx808
-rw-r--r--dbaccess/source/core/dataaccess/connection.hxx229
-rw-r--r--dbaccess/source/core/dataaccess/dataaccessdescriptor.cxx229
-rw-r--r--dbaccess/source/core/dataaccess/databasecontext.cxx753
-rw-r--r--dbaccess/source/core/dataaccess/databasedocument.cxx2211
-rw-r--r--dbaccess/source/core/dataaccess/databasedocument.hxx753
-rw-r--r--dbaccess/source/core/dataaccess/databaseregistrations.cxx369
-rw-r--r--dbaccess/source/core/dataaccess/databaseregistrations.hxx32
-rw-r--r--dbaccess/source/core/dataaccess/datasource.cxx1437
-rw-r--r--dbaccess/source/core/dataaccess/datasource.hxx220
-rw-r--r--dbaccess/source/core/dataaccess/definitioncontainer.cxx679
-rw-r--r--dbaccess/source/core/dataaccess/documentcontainer.cxx770
-rw-r--r--dbaccess/source/core/dataaccess/documentcontainer.hxx137
-rw-r--r--dbaccess/source/core/dataaccess/documentdefinition.cxx2102
-rw-r--r--dbaccess/source/core/dataaccess/documentdefinition.hxx356
-rw-r--r--dbaccess/source/core/dataaccess/documenteventexecutor.cxx199
-rw-r--r--dbaccess/source/core/dataaccess/documenteventexecutor.hxx59
-rw-r--r--dbaccess/source/core/dataaccess/documenteventnotifier.cxx290
-rw-r--r--dbaccess/source/core/dataaccess/documenteventnotifier.hxx128
-rw-r--r--dbaccess/source/core/dataaccess/documentevents.cxx216
-rw-r--r--dbaccess/source/core/dataaccess/intercept.cxx363
-rw-r--r--dbaccess/source/core/dataaccess/intercept.hxx113
-rw-r--r--dbaccess/source/core/dataaccess/myucp_datasupplier.cxx330
-rw-r--r--dbaccess/source/core/dataaccess/myucp_datasupplier.hxx59
-rw-r--r--dbaccess/source/core/dataaccess/myucp_resultset.cxx74
-rw-r--r--dbaccess/source/core/dataaccess/myucp_resultset.hxx49
-rw-r--r--dbaccess/source/core/inc/ContainerMediator.hxx79
-rw-r--r--dbaccess/source/core/inc/ContentHelper.hxx183
-rw-r--r--dbaccess/source/core/inc/DatabaseDataProvider.hxx262
-rw-r--r--dbaccess/source/core/inc/FilteredContainer.hxx136
-rw-r--r--dbaccess/source/core/inc/ModelImpl.hxx542
-rw-r--r--dbaccess/source/core/inc/PropertyForward.hxx69
-rw-r--r--dbaccess/source/core/inc/RefreshListener.hxx42
-rw-r--r--dbaccess/source/core/inc/SingleSelectQueryComposer.hxx263
-rw-r--r--dbaccess/source/core/inc/TableDeco.hxx164
-rw-r--r--dbaccess/source/core/inc/View.hxx71
-rw-r--r--dbaccess/source/core/inc/bookmarkcontainer.hxx148
-rw-r--r--dbaccess/source/core/inc/callablestatement.hxx80
-rw-r--r--dbaccess/source/core/inc/column.hxx217
-rw-r--r--dbaccess/source/core/inc/columnsettings.hxx88
-rw-r--r--dbaccess/source/core/inc/commandbase.hxx50
-rw-r--r--dbaccess/source/core/inc/composertools.hxx121
-rw-r--r--dbaccess/source/core/inc/containerapprove.hxx57
-rw-r--r--dbaccess/source/core/inc/databasecontext.hxx180
-rw-r--r--dbaccess/source/core/inc/datasettings.hxx77
-rw-r--r--dbaccess/source/core/inc/definitioncolumn.hxx291
-rw-r--r--dbaccess/source/core/inc/definitioncontainer.hxx323
-rw-r--r--dbaccess/source/core/inc/documentevents.hxx75
-rw-r--r--dbaccess/source/core/inc/migrwarndlg.hxx24
-rw-r--r--dbaccess/source/core/inc/object.hxx30
-rw-r--r--dbaccess/source/core/inc/objectnameapproval.hxx75
-rw-r--r--dbaccess/source/core/inc/preparedstatement.hxx105
-rw-r--r--dbaccess/source/core/inc/querycomposer.hxx91
-rw-r--r--dbaccess/source/core/inc/querycontainer.hxx165
-rw-r--r--dbaccess/source/core/inc/recovery/dbdocrecovery.hxx71
-rw-r--r--dbaccess/source/core/inc/sdbcoretools.hxx55
-rw-r--r--dbaccess/source/core/inc/statement.hxx179
-rw-r--r--dbaccess/source/core/inc/table.hxx140
-rw-r--r--dbaccess/source/core/inc/tablecontainer.hxx96
-rw-r--r--dbaccess/source/core/inc/veto.hxx55
-rw-r--r--dbaccess/source/core/inc/viewcontainer.hxx94
-rw-r--r--dbaccess/source/core/misc/ContainerMediator.cxx231
-rw-r--r--dbaccess/source/core/misc/DatabaseDataProvider.cxx1066
-rw-r--r--dbaccess/source/core/misc/PropertyForward.cxx146
-rw-r--r--dbaccess/source/core/misc/apitools.cxx114
-rw-r--r--dbaccess/source/core/misc/dsntypes.cxx565
-rw-r--r--dbaccess/source/core/misc/migrwarndlg.cxx22
-rw-r--r--dbaccess/source/core/misc/objectnameapproval.cxx74
-rw-r--r--dbaccess/source/core/misc/sdbcoretools.cxx142
-rw-r--r--dbaccess/source/core/misc/veto.cxx49
-rw-r--r--dbaccess/source/core/recovery/dbdocrecovery.cxx347
-rw-r--r--dbaccess/source/core/recovery/settingsimport.cxx216
-rw-r--r--dbaccess/source/core/recovery/settingsimport.hxx163
-rw-r--r--dbaccess/source/core/recovery/storagestream.cxx55
-rw-r--r--dbaccess/source/core/recovery/storagestream.hxx51
-rw-r--r--dbaccess/source/core/recovery/storagetextstream.cxx71
-rw-r--r--dbaccess/source/core/recovery/storagetextstream.hxx52
-rw-r--r--dbaccess/source/core/recovery/storagexmlstream.cxx151
-rw-r--r--dbaccess/source/core/recovery/storagexmlstream.hxx88
-rw-r--r--dbaccess/source/core/recovery/subcomponentloader.cxx124
-rw-r--r--dbaccess/source/core/recovery/subcomponentloader.hxx71
-rw-r--r--dbaccess/source/core/recovery/subcomponentrecovery.cxx628
-rw-r--r--dbaccess/source/core/recovery/subcomponentrecovery.hxx114
-rw-r--r--dbaccess/source/core/recovery/subcomponents.hxx61
-rw-r--r--dbaccess/source/core/resource/core_resource.cxx41
-rw-r--r--dbaccess/source/filter/hsqldb/alterparser.cxx56
-rw-r--r--dbaccess/source/filter/hsqldb/alterparser.hxx52
-rw-r--r--dbaccess/source/filter/hsqldb/columndef.cxx44
-rw-r--r--dbaccess/source/filter/hsqldb/columndef.hxx47
-rw-r--r--dbaccess/source/filter/hsqldb/createparser.cxx298
-rw-r--r--dbaccess/source/filter/hsqldb/createparser.hxx68
-rw-r--r--dbaccess/source/filter/hsqldb/fbalterparser.cxx53
-rw-r--r--dbaccess/source/filter/hsqldb/fbalterparser.hxx30
-rw-r--r--dbaccess/source/filter/hsqldb/fbcreateparser.cxx218
-rw-r--r--dbaccess/source/filter/hsqldb/fbcreateparser.hxx37
-rw-r--r--dbaccess/source/filter/hsqldb/hsqlbinarynode.cxx58
-rw-r--r--dbaccess/source/filter/hsqldb/hsqlbinarynode.hxx63
-rw-r--r--dbaccess/source/filter/hsqldb/hsqlimport.cxx388
-rw-r--r--dbaccess/source/filter/hsqldb/hsqlimport.hxx60
-rw-r--r--dbaccess/source/filter/hsqldb/parseschema.cxx204
-rw-r--r--dbaccess/source/filter/hsqldb/parseschema.hxx84
-rw-r--r--dbaccess/source/filter/hsqldb/rowinputbinary.cxx399
-rw-r--r--dbaccess/source/filter/hsqldb/rowinputbinary.hxx52
-rw-r--r--dbaccess/source/filter/hsqldb/utils.cxx141
-rw-r--r--dbaccess/source/filter/hsqldb/utils.hxx27
-rw-r--r--dbaccess/source/filter/xml/dbaxml.component46
-rw-r--r--dbaccess/source/filter/xml/dbloader2.cxx535
-rw-r--r--dbaccess/source/filter/xml/xmlAutoStyle.cxx82
-rw-r--r--dbaccess/source/filter/xml/xmlAutoStyle.hxx45
-rw-r--r--dbaccess/source/filter/xml/xmlColumn.cxx162
-rw-r--r--dbaccess/source/filter/xml/xmlColumn.hxx53
-rw-r--r--dbaccess/source/filter/xml/xmlComponent.cxx99
-rw-r--r--dbaccess/source/filter/xml/xmlComponent.hxx40
-rw-r--r--dbaccess/source/filter/xml/xmlConnectionData.cxx93
-rw-r--r--dbaccess/source/filter/xml/xmlConnectionData.hxx41
-rw-r--r--dbaccess/source/filter/xml/xmlConnectionResource.cxx88
-rw-r--r--dbaccess/source/filter/xml/xmlConnectionResource.hxx36
-rw-r--r--dbaccess/source/filter/xml/xmlDataSource.cxx251
-rw-r--r--dbaccess/source/filter/xml/xmlDataSource.hxx47
-rw-r--r--dbaccess/source/filter/xml/xmlDataSourceInfo.cxx119
-rw-r--r--dbaccess/source/filter/xml/xmlDataSourceInfo.hxx37
-rw-r--r--dbaccess/source/filter/xml/xmlDataSourceSetting.cxx215
-rw-r--r--dbaccess/source/filter/xml/xmlDataSourceSetting.hxx60
-rw-r--r--dbaccess/source/filter/xml/xmlDataSourceSettings.cxx66
-rw-r--r--dbaccess/source/filter/xml/xmlDataSourceSettings.hxx39
-rw-r--r--dbaccess/source/filter/xml/xmlDatabase.cxx135
-rw-r--r--dbaccess/source/filter/xml/xmlDatabase.hxx41
-rw-r--r--dbaccess/source/filter/xml/xmlDatabaseDescription.cxx79
-rw-r--r--dbaccess/source/filter/xml/xmlDatabaseDescription.hxx41
-rw-r--r--dbaccess/source/filter/xml/xmlDocuments.cxx99
-rw-r--r--dbaccess/source/filter/xml/xmlDocuments.hxx56
-rw-r--r--dbaccess/source/filter/xml/xmlEnums.hxx23
-rw-r--r--dbaccess/source/filter/xml/xmlExport.cxx1342
-rw-r--r--dbaccess/source/filter/xml/xmlExport.hxx176
-rw-r--r--dbaccess/source/filter/xml/xmlFileBasedDatabase.cxx113
-rw-r--r--dbaccess/source/filter/xml/xmlFileBasedDatabase.hxx36
-rw-r--r--dbaccess/source/filter/xml/xmlHelper.cxx157
-rw-r--r--dbaccess/source/filter/xml/xmlHelper.hxx57
-rw-r--r--dbaccess/source/filter/xml/xmlHierarchyCollection.cxx131
-rw-r--r--dbaccess/source/filter/xml/xmlHierarchyCollection.hxx55
-rw-r--r--dbaccess/source/filter/xml/xmlLogin.cxx111
-rw-r--r--dbaccess/source/filter/xml/xmlLogin.hxx37
-rw-r--r--dbaccess/source/filter/xml/xmlQuery.cxx117
-rw-r--r--dbaccess/source/filter/xml/xmlQuery.hxx46
-rw-r--r--dbaccess/source/filter/xml/xmlServerDatabase.cxx136
-rw-r--r--dbaccess/source/filter/xml/xmlServerDatabase.hxx36
-rw-r--r--dbaccess/source/filter/xml/xmlStyleImport.cxx263
-rw-r--r--dbaccess/source/filter/xml/xmlStyleImport.hxx98
-rw-r--r--dbaccess/source/filter/xml/xmlTable.cxx226
-rw-r--r--dbaccess/source/filter/xml/xmlTable.hxx67
-rw-r--r--dbaccess/source/filter/xml/xmlTableFilterList.cxx95
-rw-r--r--dbaccess/source/filter/xml/xmlTableFilterList.hxx64
-rw-r--r--dbaccess/source/filter/xml/xmlTableFilterPattern.cxx59
-rw-r--r--dbaccess/source/filter/xml/xmlTableFilterPattern.hxx44
-rw-r--r--dbaccess/source/filter/xml/xmlfilter.cxx617
-rw-r--r--dbaccess/source/filter/xml/xmlfilter.hxx121
-rw-r--r--dbaccess/source/inc/OAuthenticationContinuation.hxx67
-rw-r--r--dbaccess/source/inc/apitools.hxx52
-rw-r--r--dbaccess/source/inc/dsntypes.hxx218
-rw-r--r--dbaccess/source/inc/stringconstants.hxx171
-rw-r--r--dbaccess/source/sdbtools/connection/connectiontools.cxx132
-rw-r--r--dbaccess/source/sdbtools/connection/datasourcemetadata.cxx51
-rw-r--r--dbaccess/source/sdbtools/connection/datasourcemetadata.hxx69
-rw-r--r--dbaccess/source/sdbtools/connection/objectnames.cxx420
-rw-r--r--dbaccess/source/sdbtools/connection/objectnames.hxx74
-rw-r--r--dbaccess/source/sdbtools/connection/tablename.cxx232
-rw-r--r--dbaccess/source/sdbtools/connection/tablename.hxx84
-rw-r--r--dbaccess/source/sdbtools/inc/connectiondependent.hxx135
-rw-r--r--dbaccess/source/sdbtools/inc/connectiontools.hxx77
-rw-r--r--dbaccess/source/ui/app/AppController.cxx2834
-rw-r--r--dbaccess/source/ui/app/AppController.hxx540
-rw-r--r--dbaccess/source/ui/app/AppControllerDnD.cxx869
-rw-r--r--dbaccess/source/ui/app/AppControllerGen.cxx736
-rw-r--r--dbaccess/source/ui/app/AppDetailPageHelper.cxx1221
-rw-r--r--dbaccess/source/ui/app/AppDetailPageHelper.hxx349
-rw-r--r--dbaccess/source/ui/app/AppDetailView.cxx510
-rw-r--r--dbaccess/source/ui/app/AppDetailView.hxx318
-rw-r--r--dbaccess/source/ui/app/AppIconControl.cxx238
-rw-r--r--dbaccess/source/ui/app/AppIconControl.hxx67
-rw-r--r--dbaccess/source/ui/app/AppSwapWindow.cxx133
-rw-r--r--dbaccess/source/ui/app/AppSwapWindow.hxx88
-rw-r--r--dbaccess/source/ui/app/AppTitleWindow.cxx65
-rw-r--r--dbaccess/source/ui/app/AppTitleWindow.hxx67
-rw-r--r--dbaccess/source/ui/app/AppView.cxx473
-rw-r--r--dbaccess/source/ui/app/AppView.hxx302
-rw-r--r--dbaccess/source/ui/app/ChildWindow.cxx25
-rw-r--r--dbaccess/source/ui/app/DocumentInfoPreview.cxx164
-rw-r--r--dbaccess/source/ui/app/DocumentInfoPreview.hxx59
-rw-r--r--dbaccess/source/ui/app/subcomponentmanager.cxx551
-rw-r--r--dbaccess/source/ui/app/subcomponentmanager.hxx120
-rw-r--r--dbaccess/source/ui/app/templwin.cxx38
-rw-r--r--dbaccess/source/ui/app/templwin.hxx28
-rw-r--r--dbaccess/source/ui/app/window_layout.txt49
-rw-r--r--dbaccess/source/ui/browser/AsynchronousLink.cxx81
-rw-r--r--dbaccess/source/ui/browser/brwctrlr.cxx2616
-rw-r--r--dbaccess/source/ui/browser/brwview.cxx333
-rw-r--r--dbaccess/source/ui/browser/dataview.cxx154
-rw-r--r--dbaccess/source/ui/browser/dbexchange.cxx251
-rw-r--r--dbaccess/source/ui/browser/dbloader.cxx269
-rw-r--r--dbaccess/source/ui/browser/dbtreemodel.cxx33
-rw-r--r--dbaccess/source/ui/browser/dbtreemodel.hxx57
-rw-r--r--dbaccess/source/ui/browser/dsEntriesNoExp.cxx154
-rw-r--r--dbaccess/source/ui/browser/dsbrowserDnD.cxx258
-rw-r--r--dbaccess/source/ui/browser/exsrcbrw.cxx413
-rw-r--r--dbaccess/source/ui/browser/formadapter.cxx1877
-rw-r--r--dbaccess/source/ui/browser/genericcontroller.cxx1217
-rw-r--r--dbaccess/source/ui/browser/sbagrid.cxx1364
-rw-r--r--dbaccess/source/ui/browser/sbamultiplex.cxx528
-rw-r--r--dbaccess/source/ui/browser/unodatbr.cxx3819
-rw-r--r--dbaccess/source/ui/control/ColumnControlWindow.cxx182
-rw-r--r--dbaccess/source/ui/control/FieldControls.cxx60
-rw-r--r--dbaccess/source/ui/control/FieldDescControl.cxx1384
-rw-r--r--dbaccess/source/ui/control/RelationControl.cxx695
-rw-r--r--dbaccess/source/ui/control/SqlNameEdit.cxx85
-rw-r--r--dbaccess/source/ui/control/TableGrantCtrl.cxx476
-rw-r--r--dbaccess/source/ui/control/charsetlistbox.cxx69
-rw-r--r--dbaccess/source/ui/control/curledit.cxx89
-rw-r--r--dbaccess/source/ui/control/dbtreelistbox.cxx512
-rw-r--r--dbaccess/source/ui/control/opendoccontrols.cxx194
-rw-r--r--dbaccess/source/ui/control/sqledit.cxx515
-rw-r--r--dbaccess/source/ui/control/tabletree.cxx707
-rw-r--r--dbaccess/source/ui/control/undosqledit.cxx34
-rw-r--r--dbaccess/source/ui/dlg/CollectionView.cxx316
-rw-r--r--dbaccess/source/ui/dlg/ConnectionHelper.cxx720
-rw-r--r--dbaccess/source/ui/dlg/ConnectionHelper.hxx103
-rw-r--r--dbaccess/source/ui/dlg/ConnectionPage.cxx284
-rw-r--r--dbaccess/source/ui/dlg/ConnectionPage.hxx72
-rw-r--r--dbaccess/source/ui/dlg/ConnectionPageSetup.cxx153
-rw-r--r--dbaccess/source/ui/dlg/ConnectionPageSetup.hxx63
-rw-r--r--dbaccess/source/ui/dlg/DBSetupConnectionPages.cxx786
-rw-r--r--dbaccess/source/ui/dlg/DBSetupConnectionPages.hxx270
-rw-r--r--dbaccess/source/ui/dlg/DbAdminImpl.cxx1074
-rw-r--r--dbaccess/source/ui/dlg/DbAdminImpl.hxx167
-rw-r--r--dbaccess/source/ui/dlg/DriverSettings.hxx78
-rw-r--r--dbaccess/source/ui/dlg/QueryPropertiesDialog.cxx60
-rw-r--r--dbaccess/source/ui/dlg/RelationDlg.cxx215
-rw-r--r--dbaccess/source/ui/dlg/TablesSingleDlg.cxx105
-rw-r--r--dbaccess/source/ui/dlg/TextConnectionHelper.cxx392
-rw-r--r--dbaccess/source/ui/dlg/TextConnectionHelper.hxx89
-rw-r--r--dbaccess/source/ui/dlg/UserAdmin.cxx316
-rw-r--r--dbaccess/source/ui/dlg/UserAdmin.hxx74
-rw-r--r--dbaccess/source/ui/dlg/UserAdminDlg.cxx162
-rw-r--r--dbaccess/source/ui/dlg/admincontrols.cxx201
-rw-r--r--dbaccess/source/ui/dlg/admincontrols.hxx65
-rw-r--r--dbaccess/source/ui/dlg/adminpages.cxx278
-rw-r--r--dbaccess/source/ui/dlg/adminpages.hxx233
-rw-r--r--dbaccess/source/ui/dlg/adodatalinks.cxx141
-rw-r--r--dbaccess/source/ui/dlg/adodatalinks.hxx26
-rw-r--r--dbaccess/source/ui/dlg/adtabdlg.cxx467
-rw-r--r--dbaccess/source/ui/dlg/advancedsettings.cxx472
-rw-r--r--dbaccess/source/ui/dlg/advancedsettings.hxx116
-rw-r--r--dbaccess/source/ui/dlg/dbadmin.cxx433
-rw-r--r--dbaccess/source/ui/dlg/dbfindex.cxx430
-rw-r--r--dbaccess/source/ui/dlg/dbfindex.hxx110
-rw-r--r--dbaccess/source/ui/dlg/dbwiz.cxx336
-rw-r--r--dbaccess/source/ui/dlg/dbwizsetup.cxx994
-rw-r--r--dbaccess/source/ui/dlg/detailpages.cxx717
-rw-r--r--dbaccess/source/ui/dlg/detailpages.hxx253
-rw-r--r--dbaccess/source/ui/dlg/directsql.cxx430
-rw-r--r--dbaccess/source/ui/dlg/dlgattr.cxx60
-rw-r--r--dbaccess/source/ui/dlg/dlgsave.cxx351
-rw-r--r--dbaccess/source/ui/dlg/dlgsize.cxx83
-rw-r--r--dbaccess/source/ui/dlg/dsnItem.hxx48
-rw-r--r--dbaccess/source/ui/dlg/dsselect.cxx133
-rw-r--r--dbaccess/source/ui/dlg/dsselect.hxx61
-rw-r--r--dbaccess/source/ui/dlg/finteraction.cxx59
-rw-r--r--dbaccess/source/ui/dlg/finteraction.hxx54
-rw-r--r--dbaccess/source/ui/dlg/generalpage.cxx700
-rw-r--r--dbaccess/source/ui/dlg/generalpage.hxx189
-rw-r--r--dbaccess/source/ui/dlg/indexdialog.cxx707
-rw-r--r--dbaccess/source/ui/dlg/indexfieldscontrol.cxx447
-rw-r--r--dbaccess/source/ui/dlg/odbcconfig.cxx325
-rw-r--r--dbaccess/source/ui/dlg/odbcconfig.hxx106
-rw-r--r--dbaccess/source/ui/dlg/optionalboolitem.cxx44
-rw-r--r--dbaccess/source/ui/dlg/optionalboolitem.hxx51
-rw-r--r--dbaccess/source/ui/dlg/paramdialog.cxx334
-rw-r--r--dbaccess/source/ui/dlg/queryfilter.cxx748
-rw-r--r--dbaccess/source/ui/dlg/queryorder.cxx218
-rw-r--r--dbaccess/source/ui/dlg/sqlmessage.cxx604
-rw-r--r--dbaccess/source/ui/dlg/tablespage.cxx488
-rw-r--r--dbaccess/source/ui/dlg/tablespage.hxx81
-rw-r--r--dbaccess/source/ui/dlg/textconnectionsettings.cxx69
-rw-r--r--dbaccess/source/ui/inc/AppElementType.hxx53
-rw-r--r--dbaccess/source/ui/inc/ChildWindow.hxx38
-rw-r--r--dbaccess/source/ui/inc/CollectionView.hxx65
-rw-r--r--dbaccess/source/ui/inc/ColumnControlWindow.hxx82
-rw-r--r--dbaccess/source/ui/inc/ConnectionLine.hxx71
-rw-r--r--dbaccess/source/ui/inc/ConnectionLineAccess.hxx91
-rw-r--r--dbaccess/source/ui/inc/ConnectionLineData.hxx80
-rw-r--r--dbaccess/source/ui/inc/DExport.hxx162
-rw-r--r--dbaccess/source/ui/inc/FieldControls.hxx120
-rw-r--r--dbaccess/source/ui/inc/FieldDescControl.hxx201
-rw-r--r--dbaccess/source/ui/inc/FieldDescriptions.hxx111
-rw-r--r--dbaccess/source/ui/inc/GeneralUndo.hxx40
-rw-r--r--dbaccess/source/ui/inc/HtmlReader.hxx68
-rw-r--r--dbaccess/source/ui/inc/IClipBoardTest.hxx40
-rw-r--r--dbaccess/source/ui/inc/IItemSetHelper.hxx72
-rw-r--r--dbaccess/source/ui/inc/IUpdateHelper.hxx44
-rw-r--r--dbaccess/source/ui/inc/JAccess.hxx70
-rw-r--r--dbaccess/source/ui/inc/JoinController.hxx154
-rw-r--r--dbaccess/source/ui/inc/JoinDesignView.hxx68
-rw-r--r--dbaccess/source/ui/inc/JoinExchange.hxx62
-rw-r--r--dbaccess/source/ui/inc/JoinTableView.hxx325
-rw-r--r--dbaccess/source/ui/inc/QEnumTypes.hxx79
-rw-r--r--dbaccess/source/ui/inc/QueryDesignView.hxx154
-rw-r--r--dbaccess/source/ui/inc/QueryPropertiesDialog.hxx45
-rw-r--r--dbaccess/source/ui/inc/QueryTableView.hxx116
-rw-r--r--dbaccess/source/ui/inc/QueryTextView.hxx69
-rw-r--r--dbaccess/source/ui/inc/QueryViewSwitch.hxx94
-rw-r--r--dbaccess/source/ui/inc/RTableConnectionData.hxx79
-rw-r--r--dbaccess/source/ui/inc/RelControliFace.hxx40
-rw-r--r--dbaccess/source/ui/inc/RelationControl.hxx91
-rw-r--r--dbaccess/source/ui/inc/RelationController.hxx79
-rw-r--r--dbaccess/source/ui/inc/RelationDesignView.hxx45
-rw-r--r--dbaccess/source/ui/inc/RelationDlg.hxx74
-rw-r--r--dbaccess/source/ui/inc/RelationTableView.hxx74
-rw-r--r--dbaccess/source/ui/inc/RtfReader.hxx59
-rw-r--r--dbaccess/source/ui/inc/SqlNameEdit.hxx121
-rw-r--r--dbaccess/source/ui/inc/TableConnection.hxx98
-rw-r--r--dbaccess/source/ui/inc/TableConnectionData.hxx101
-rw-r--r--dbaccess/source/ui/inc/TableController.hxx129
-rw-r--r--dbaccess/source/ui/inc/TableCopyHelper.hxx188
-rw-r--r--dbaccess/source/ui/inc/TableDesignControl.hxx78
-rw-r--r--dbaccess/source/ui/inc/TableDesignHelpBar.hxx59
-rw-r--r--dbaccess/source/ui/inc/TableDesignView.hxx112
-rw-r--r--dbaccess/source/ui/inc/TableFieldDescription.hxx150
-rw-r--r--dbaccess/source/ui/inc/TableGrantCtrl.hxx104
-rw-r--r--dbaccess/source/ui/inc/TableRow.hxx76
-rw-r--r--dbaccess/source/ui/inc/TableRowExchange.hxx40
-rw-r--r--dbaccess/source/ui/inc/TableWindow.hxx183
-rw-r--r--dbaccess/source/ui/inc/TableWindowAccess.hxx94
-rw-r--r--dbaccess/source/ui/inc/TableWindowData.hxx95
-rw-r--r--dbaccess/source/ui/inc/TableWindowListBox.hxx121
-rw-r--r--dbaccess/source/ui/inc/TableWindowTitle.hxx44
-rw-r--r--dbaccess/source/ui/inc/TablesSingleDlg.hxx71
-rw-r--r--dbaccess/source/ui/inc/TokenWriter.hxx206
-rw-r--r--dbaccess/source/ui/inc/TypeInfo.hxx121
-rw-r--r--dbaccess/source/ui/inc/UITools.hxx396
-rw-r--r--dbaccess/source/ui/inc/UserAdminDlg.hxx76
-rw-r--r--dbaccess/source/ui/inc/WCPage.hxx78
-rw-r--r--dbaccess/source/ui/inc/WColumnSelect.hxx82
-rw-r--r--dbaccess/source/ui/inc/WCopyTable.hxx413
-rw-r--r--dbaccess/source/ui/inc/WExtendPages.hxx69
-rw-r--r--dbaccess/source/ui/inc/WNameMatch.hxx63
-rw-r--r--dbaccess/source/ui/inc/WTabPage.hxx46
-rw-r--r--dbaccess/source/ui/inc/WTypeSelect.hxx139
-rw-r--r--dbaccess/source/ui/inc/adtabdlg.hxx98
-rw-r--r--dbaccess/source/ui/inc/advancedsettingsdlg.hxx70
-rw-r--r--dbaccess/source/ui/inc/asyncmodaldialog.hxx47
-rw-r--r--dbaccess/source/ui/inc/browserids.hxx98
-rw-r--r--dbaccess/source/ui/inc/brwctrlr.hxx332
-rw-r--r--dbaccess/source/ui/inc/brwview.hxx96
-rw-r--r--dbaccess/source/ui/inc/callbacks.hxx123
-rw-r--r--dbaccess/source/ui/inc/charsetlistbox.hxx48
-rw-r--r--dbaccess/source/ui/inc/charsets.hxx105
-rw-r--r--dbaccess/source/ui/inc/commontypes.hxx39
-rw-r--r--dbaccess/source/ui/inc/curledit.hxx102
-rw-r--r--dbaccess/source/ui/inc/databaseobjectview.hxx230
-rw-r--r--dbaccess/source/ui/inc/datasourceconnector.hxx76
-rw-r--r--dbaccess/source/ui/inc/dbadmin.hxx114
-rw-r--r--dbaccess/source/ui/inc/dbexchange.hxx83
-rw-r--r--dbaccess/source/ui/inc/dbtreelistbox.hxx164
-rw-r--r--dbaccess/source/ui/inc/dbu_dlg.hxx24
-rw-r--r--dbaccess/source/ui/inc/dbwiz.hxx101
-rw-r--r--dbaccess/source/ui/inc/dbwizsetup.hxx170
-rw-r--r--dbaccess/source/ui/inc/defaultobjectnamecheck.hxx120
-rw-r--r--dbaccess/source/ui/inc/directsql.hxx113
-rw-r--r--dbaccess/source/ui/inc/dlgattr.hxx41
-rw-r--r--dbaccess/source/ui/inc/dlgsave.hxx81
-rw-r--r--dbaccess/source/ui/inc/dlgsize.hxx44
-rw-r--r--dbaccess/source/ui/inc/dsitems.hxx95
-rw-r--r--dbaccess/source/ui/inc/dsmeta.hxx125
-rw-r--r--dbaccess/source/ui/inc/exsrcbrw.hxx96
-rw-r--r--dbaccess/source/ui/inc/formadapter.hxx436
-rw-r--r--dbaccess/source/ui/inc/imageprovider.hxx105
-rw-r--r--dbaccess/source/ui/inc/indexcollection.hxx94
-rw-r--r--dbaccess/source/ui/inc/indexdialog.hxx103
-rw-r--r--dbaccess/source/ui/inc/indexes.hxx81
-rw-r--r--dbaccess/source/ui/inc/indexfieldscontrol.hxx91
-rw-r--r--dbaccess/source/ui/inc/linkeddocuments.hxx108
-rw-r--r--dbaccess/source/ui/inc/objectnamecheck.hxx57
-rw-r--r--dbaccess/source/ui/inc/opendoccontrols.hxx78
-rw-r--r--dbaccess/source/ui/inc/paramdialog.hxx103
-rw-r--r--dbaccess/source/ui/inc/propertystorage.hxx54
-rw-r--r--dbaccess/source/ui/inc/querycontainerwindow.hxx104
-rw-r--r--dbaccess/source/ui/inc/querycontroller.hxx217
-rw-r--r--dbaccess/source/ui/inc/queryfilter.hxx109
-rw-r--r--dbaccess/source/ui/inc/queryorder.hxx81
-rw-r--r--dbaccess/source/ui/inc/sbagrid.hrc37
-rw-r--r--dbaccess/source/ui/inc/sbagrid.hxx293
-rw-r--r--dbaccess/source/ui/inc/sbamultiplex.hxx308
-rw-r--r--dbaccess/source/ui/inc/singledoccontroller.hxx78
-rw-r--r--dbaccess/source/ui/inc/sqledit.hxx99
-rw-r--r--dbaccess/source/ui/inc/sqlmessage.hxx145
-rw-r--r--dbaccess/source/ui/inc/stringlistitem.hxx48
-rw-r--r--dbaccess/source/ui/inc/tabletree.hxx155
-rw-r--r--dbaccess/source/ui/inc/textconnectionsettings.hxx59
-rw-r--r--dbaccess/source/ui/inc/undosqledit.hxx45
-rw-r--r--dbaccess/source/ui/inc/unoadmin.hxx59
-rw-r--r--dbaccess/source/ui/inc/unodatbr.hxx447
-rw-r--r--dbaccess/source/ui/inc/unosqlmessage.hxx68
-rw-r--r--dbaccess/source/ui/misc/DExport.cxx840
-rw-r--r--dbaccess/source/ui/misc/HtmlReader.cxx481
-rw-r--r--dbaccess/source/ui/misc/RowSetDrop.cxx247
-rw-r--r--dbaccess/source/ui/misc/RtfReader.cxx309
-rw-r--r--dbaccess/source/ui/misc/TableCopyHelper.cxx306
-rw-r--r--dbaccess/source/ui/misc/TokenWriter.cxx965
-rw-r--r--dbaccess/source/ui/misc/UITools.cxx1370
-rw-r--r--dbaccess/source/ui/misc/UpdateHelperImpl.hxx74
-rw-r--r--dbaccess/source/ui/misc/WCPage.cxx325
-rw-r--r--dbaccess/source/ui/misc/WColumnSelect.cxx403
-rw-r--r--dbaccess/source/ui/misc/WCopyTable.cxx1554
-rw-r--r--dbaccess/source/ui/misc/WExtendPages.cxx62
-rw-r--r--dbaccess/source/ui/misc/WNameMatch.cxx330
-rw-r--r--dbaccess/source/ui/misc/WTypeSelect.cxx417
-rw-r--r--dbaccess/source/ui/misc/asyncmodaldialog.cxx91
-rw-r--r--dbaccess/source/ui/misc/charsets.cxx130
-rw-r--r--dbaccess/source/ui/misc/controllerframe.cxx390
-rw-r--r--dbaccess/source/ui/misc/databaseobjectview.cxx280
-rw-r--r--dbaccess/source/ui/misc/datasourceconnector.cxx202
-rw-r--r--dbaccess/source/ui/misc/dbaundomanager.cxx324
-rw-r--r--dbaccess/source/ui/misc/dbsubcomponentcontroller.cxx606
-rw-r--r--dbaccess/source/ui/misc/defaultobjectnamecheck.cxx160
-rw-r--r--dbaccess/source/ui/misc/dsmeta.cxx182
-rw-r--r--dbaccess/source/ui/misc/imageprovider.cxx202
-rw-r--r--dbaccess/source/ui/misc/indexcollection.cxx328
-rw-r--r--dbaccess/source/ui/misc/linkeddocuments.cxx354
-rw-r--r--dbaccess/source/ui/misc/propertystorage.cxx106
-rw-r--r--dbaccess/source/ui/misc/singledoccontroller.cxx184
-rw-r--r--dbaccess/source/ui/misc/stringlistitem.cxx62
-rw-r--r--dbaccess/source/ui/querydesign/ConnectionLine.cxx356
-rw-r--r--dbaccess/source/ui/querydesign/ConnectionLineAccess.cxx187
-rw-r--r--dbaccess/source/ui/querydesign/ConnectionLineData.cxx76
-rw-r--r--dbaccess/source/ui/querydesign/JAccess.cxx91
-rw-r--r--dbaccess/source/ui/querydesign/JoinController.cxx406
-rw-r--r--dbaccess/source/ui/querydesign/JoinDesignView.cxx100
-rw-r--r--dbaccess/source/ui/querydesign/JoinExchange.cxx114
-rw-r--r--dbaccess/source/ui/querydesign/JoinTableView.cxx1568
-rw-r--r--dbaccess/source/ui/querydesign/QTableConnection.cxx73
-rw-r--r--dbaccess/source/ui/querydesign/QTableConnection.hxx46
-rw-r--r--dbaccess/source/ui/querydesign/QTableConnectionData.cxx112
-rw-r--r--dbaccess/source/ui/querydesign/QTableConnectionData.hxx67
-rw-r--r--dbaccess/source/ui/querydesign/QTableWindow.cxx175
-rw-r--r--dbaccess/source/ui/querydesign/QTableWindow.hxx76
-rw-r--r--dbaccess/source/ui/querydesign/QTableWindowData.cxx34
-rw-r--r--dbaccess/source/ui/querydesign/QTableWindowData.hxx38
-rw-r--r--dbaccess/source/ui/querydesign/QueryAddTabConnUndoAction.hxx49
-rw-r--r--dbaccess/source/ui/querydesign/QueryDesignFieldUndoAct.hxx138
-rw-r--r--dbaccess/source/ui/querydesign/QueryDesignUndoAction.hxx39
-rw-r--r--dbaccess/source/ui/querydesign/QueryDesignView.cxx3441
-rw-r--r--dbaccess/source/ui/querydesign/QueryMoveTabWinUndoAct.cxx40
-rw-r--r--dbaccess/source/ui/querydesign/QueryMoveTabWinUndoAct.hxx54
-rw-r--r--dbaccess/source/ui/querydesign/QuerySizeTabWinUndoAct.hxx70
-rw-r--r--dbaccess/source/ui/querydesign/QueryTabConnUndoAction.cxx117
-rw-r--r--dbaccess/source/ui/querydesign/QueryTabConnUndoAction.hxx50
-rw-r--r--dbaccess/source/ui/querydesign/QueryTabWinShowUndoAct.hxx51
-rw-r--r--dbaccess/source/ui/querydesign/QueryTabWinUndoAct.cxx112
-rw-r--r--dbaccess/source/ui/querydesign/QueryTabWinUndoAct.hxx61
-rw-r--r--dbaccess/source/ui/querydesign/QueryTableView.cxx889
-rw-r--r--dbaccess/source/ui/querydesign/QueryTextView.cxx177
-rw-r--r--dbaccess/source/ui/querydesign/QueryViewSwitch.cxx292
-rw-r--r--dbaccess/source/ui/querydesign/SelectionBrowseBox.cxx2720
-rw-r--r--dbaccess/source/ui/querydesign/SelectionBrowseBox.hxx324
-rw-r--r--dbaccess/source/ui/querydesign/TableConnection.cxx190
-rw-r--r--dbaccess/source/ui/querydesign/TableConnectionData.cxx147
-rw-r--r--dbaccess/source/ui/querydesign/TableFieldDescription.cxx196
-rw-r--r--dbaccess/source/ui/querydesign/TableFieldInfo.cxx30
-rw-r--r--dbaccess/source/ui/querydesign/TableFieldInfo.hxx43
-rw-r--r--dbaccess/source/ui/querydesign/TableWindow.cxx716
-rw-r--r--dbaccess/source/ui/querydesign/TableWindowAccess.cxx250
-rw-r--r--dbaccess/source/ui/querydesign/TableWindowData.cxx135
-rw-r--r--dbaccess/source/ui/querydesign/TableWindowListBox.cxx292
-rw-r--r--dbaccess/source/ui/querydesign/TableWindowTitle.cxx97
-rw-r--r--dbaccess/source/ui/querydesign/class.jpgbin0 -> 224242 bytes
-rw-r--r--dbaccess/source/ui/querydesign/limitboxcontroller.cxx322
-rw-r--r--dbaccess/source/ui/querydesign/limitboxcontroller.hxx65
-rw-r--r--dbaccess/source/ui/querydesign/querycontainerwindow.cxx222
-rw-r--r--dbaccess/source/ui/querydesign/querycontroller.cxx1790
-rw-r--r--dbaccess/source/ui/querydesign/querydlg.cxx313
-rw-r--r--dbaccess/source/ui/querydesign/querydlg.hxx77
-rw-r--r--dbaccess/source/ui/relationdesign/RTableConnection.cxx117
-rw-r--r--dbaccess/source/ui/relationdesign/RTableConnection.hxx40
-rw-r--r--dbaccess/source/ui/relationdesign/RTableConnectionData.cxx398
-rw-r--r--dbaccess/source/ui/relationdesign/RTableWindow.hxx40
-rw-r--r--dbaccess/source/ui/relationdesign/RelationController.cxx548
-rw-r--r--dbaccess/source/ui/relationdesign/RelationDesignView.cxx74
-rw-r--r--dbaccess/source/ui/relationdesign/RelationTableView.cxx410
-rw-r--r--dbaccess/source/ui/tabledesign/FieldDescriptions.cxx639
-rw-r--r--dbaccess/source/ui/tabledesign/TEditControl.cxx1679
-rw-r--r--dbaccess/source/ui/tabledesign/TEditControl.hxx204
-rw-r--r--dbaccess/source/ui/tabledesign/TableController.cxx1495
-rw-r--r--dbaccess/source/ui/tabledesign/TableDesignControl.cxx172
-rw-r--r--dbaccess/source/ui/tabledesign/TableDesignHelpBar.cxx62
-rw-r--r--dbaccess/source/ui/tabledesign/TableDesignView.cxx260
-rw-r--r--dbaccess/source/ui/tabledesign/TableFieldControl.cxx154
-rw-r--r--dbaccess/source/ui/tabledesign/TableFieldControl.hxx66
-rw-r--r--dbaccess/source/ui/tabledesign/TableFieldDescWin.cxx140
-rw-r--r--dbaccess/source/ui/tabledesign/TableFieldDescWin.hxx91
-rw-r--r--dbaccess/source/ui/tabledesign/TableRow.cxx183
-rw-r--r--dbaccess/source/ui/tabledesign/TableRowExchange.cxx67
-rw-r--r--dbaccess/source/ui/tabledesign/TableUndo.cxx352
-rw-r--r--dbaccess/source/ui/tabledesign/TableUndo.hxx136
-rw-r--r--dbaccess/source/ui/uno/AdvancedSettingsDlg.cxx117
-rw-r--r--dbaccess/source/ui/uno/ColumnControl.cxx146
-rw-r--r--dbaccess/source/ui/uno/ColumnControl.hxx46
-rw-r--r--dbaccess/source/ui/uno/ColumnModel.cxx180
-rw-r--r--dbaccess/source/ui/uno/ColumnModel.hxx97
-rw-r--r--dbaccess/source/ui/uno/ColumnPeer.cxx148
-rw-r--r--dbaccess/source/ui/uno/ColumnPeer.hxx47
-rw-r--r--dbaccess/source/ui/uno/DBTypeWizDlg.cxx85
-rw-r--r--dbaccess/source/ui/uno/DBTypeWizDlg.hxx56
-rw-r--r--dbaccess/source/ui/uno/DBTypeWizDlgSetup.cxx104
-rw-r--r--dbaccess/source/ui/uno/DBTypeWizDlgSetup.hxx59
-rw-r--r--dbaccess/source/ui/uno/TableFilterDlg.cxx85
-rw-r--r--dbaccess/source/ui/uno/TableFilterDlg.hxx57
-rw-r--r--dbaccess/source/ui/uno/UserSettingsDlg.cxx85
-rw-r--r--dbaccess/source/ui/uno/UserSettingsDlg.hxx57
-rw-r--r--dbaccess/source/ui/uno/admindlg.cxx92
-rw-r--r--dbaccess/source/ui/uno/admindlg.hxx56
-rw-r--r--dbaccess/source/ui/uno/composerdialogs.cxx270
-rw-r--r--dbaccess/source/ui/uno/composerdialogs.hxx123
-rw-r--r--dbaccess/source/ui/uno/copytablewizard.cxx1579
-rw-r--r--dbaccess/source/ui/uno/dbinteraction.cxx387
-rw-r--r--dbaccess/source/ui/uno/dbinteraction.hxx168
-rw-r--r--dbaccess/source/ui/uno/textconnectionsettings_uno.cxx268
-rw-r--r--dbaccess/source/ui/uno/unoDirectSql.cxx149
-rw-r--r--dbaccess/source/ui/uno/unoDirectSql.hxx61
-rw-r--r--dbaccess/source/ui/uno/unoadmin.cxx71
-rw-r--r--dbaccess/source/ui/uno/unosqlmessage.cxx144
-rw-r--r--dbaccess/uiconfig/dbapp/menubar/menubar.xml164
-rw-r--r--dbaccess/uiconfig/dbapp/popupmenu/edit.xml35
-rw-r--r--dbaccess/uiconfig/dbapp/popupmenu/new.xml22
-rw-r--r--dbaccess/uiconfig/dbapp/popupmenu/preview.xml14
-rw-r--r--dbaccess/uiconfig/dbapp/statusbar/statusbar.xml25
-rw-r--r--dbaccess/uiconfig/dbapp/toolbar/formobjectbar.xml31
-rw-r--r--dbaccess/uiconfig/dbapp/toolbar/queryobjectbar.xml32
-rw-r--r--dbaccess/uiconfig/dbapp/toolbar/reportobjectbar.xml32
-rw-r--r--dbaccess/uiconfig/dbapp/toolbar/tableobjectbar.xml31
-rw-r--r--dbaccess/uiconfig/dbapp/toolbar/toolbar.xml36
-rw-r--r--dbaccess/uiconfig/dbbrowser/menubar/compat.xml1
-rw-r--r--dbaccess/uiconfig/dbbrowser/menubar/preserve.txt1
-rw-r--r--dbaccess/uiconfig/dbbrowser/popupmenu/explorer.xml17
-rw-r--r--dbaccess/uiconfig/dbbrowser/popupmenu/refreshdata.xml13
-rw-r--r--dbaccess/uiconfig/dbbrowser/toolbar/toolbar.xml50
-rw-r--r--dbaccess/uiconfig/dbquery/menubar/menubar.xml119
-rw-r--r--dbaccess/uiconfig/dbquery/toolbar/designobjectbar.xml29
-rw-r--r--dbaccess/uiconfig/dbquery/toolbar/sqlobjectbar.xml22
-rw-r--r--dbaccess/uiconfig/dbquery/toolbar/toolbar.xml38
-rw-r--r--dbaccess/uiconfig/dbrelation/menubar/menubar.xml103
-rw-r--r--dbaccess/uiconfig/dbrelation/toolbar/toolbar.xml31
-rw-r--r--dbaccess/uiconfig/dbtable/menubar/menubar.xml103
-rw-r--r--dbaccess/uiconfig/dbtable/toolbar/toolbar.xml35
-rw-r--r--dbaccess/uiconfig/dbtdata/menubar/menubar.xml128
-rw-r--r--dbaccess/uiconfig/dbtdata/popupmenu/refreshdata.xml13
-rw-r--r--dbaccess/uiconfig/dbtdata/toolbar/toolbar.xml45
-rw-r--r--dbaccess/uiconfig/ui/admindialog.ui162
-rw-r--r--dbaccess/uiconfig/ui/advancedsettingsdialog.ui210
-rw-r--r--dbaccess/uiconfig/ui/appborderwindow.ui71
-rw-r--r--dbaccess/uiconfig/ui/appdetailwindow.ui55
-rw-r--r--dbaccess/uiconfig/ui/applycolpage.ui243
-rw-r--r--dbaccess/uiconfig/ui/appswapwindow.ui58
-rw-r--r--dbaccess/uiconfig/ui/authentificationpage.ui123
-rw-r--r--dbaccess/uiconfig/ui/autocharsetpage.ui74
-rw-r--r--dbaccess/uiconfig/ui/choosedatasourcedialog.ui181
-rw-r--r--dbaccess/uiconfig/ui/colcontrolbox.ui15
-rw-r--r--dbaccess/uiconfig/ui/collectionviewdialog.ui267
-rw-r--r--dbaccess/uiconfig/ui/colwidthdialog.ui172
-rw-r--r--dbaccess/uiconfig/ui/connectionpage.ui299
-rw-r--r--dbaccess/uiconfig/ui/copytablepage.ui232
-rw-r--r--dbaccess/uiconfig/ui/dbaseindexdialog.ui393
-rw-r--r--dbaccess/uiconfig/ui/dbasepage.ui157
-rw-r--r--dbaccess/uiconfig/ui/dbtreelist.ui104
-rw-r--r--dbaccess/uiconfig/ui/dbwizconnectionpage.ui137
-rw-r--r--dbaccess/uiconfig/ui/dbwizmysqlintropage.ui142
-rw-r--r--dbaccess/uiconfig/ui/dbwizmysqlnativepage.ui84
-rw-r--r--dbaccess/uiconfig/ui/dbwizspreadsheetpage.ui169
-rw-r--r--dbaccess/uiconfig/ui/dbwiztextpage.ui171
-rw-r--r--dbaccess/uiconfig/ui/deleteallrowsdialog.ui81
-rw-r--r--dbaccess/uiconfig/ui/designsavemodifieddialog.ui82
-rw-r--r--dbaccess/uiconfig/ui/detailwindow.ui178
-rw-r--r--dbaccess/uiconfig/ui/directsqldialog.ui335
-rw-r--r--dbaccess/uiconfig/ui/emptypage.ui17
-rw-r--r--dbaccess/uiconfig/ui/fielddescpage.ui429
-rw-r--r--dbaccess/uiconfig/ui/fielddescpanel.ui87
-rw-r--r--dbaccess/uiconfig/ui/fielddialog.ui235
-rw-r--r--dbaccess/uiconfig/ui/finalpagewizard.ui171
-rw-r--r--dbaccess/uiconfig/ui/generalpagedialog.ui86
-rw-r--r--dbaccess/uiconfig/ui/generalpagewizard.ui277
-rw-r--r--dbaccess/uiconfig/ui/generalspecialjdbcdetailspage.ui244
-rw-r--r--dbaccess/uiconfig/ui/generatedvaluespage.ui146
-rw-r--r--dbaccess/uiconfig/ui/indexdesigndialog.ui342
-rw-r--r--dbaccess/uiconfig/ui/jdbcconnectionpage.ui206
-rw-r--r--dbaccess/uiconfig/ui/joindialog.ui312
-rw-r--r--dbaccess/uiconfig/ui/jointablemenu.ui17
-rw-r--r--dbaccess/uiconfig/ui/joinviewmenu.ui25
-rw-r--r--dbaccess/uiconfig/ui/keymenu.ui17
-rw-r--r--dbaccess/uiconfig/ui/ldapconnectionpage.ui189
-rw-r--r--dbaccess/uiconfig/ui/ldappage.ui158
-rw-r--r--dbaccess/uiconfig/ui/limitbox.ui31
-rw-r--r--dbaccess/uiconfig/ui/migrwarndlg.ui81
-rw-r--r--dbaccess/uiconfig/ui/mysqlnativepage.ui197
-rw-r--r--dbaccess/uiconfig/ui/mysqlnativesettings.ui262
-rw-r--r--dbaccess/uiconfig/ui/namematchingpage.ui305
-rw-r--r--dbaccess/uiconfig/ui/odbcpage.ui165
-rw-r--r--dbaccess/uiconfig/ui/parametersdialog.ui232
-rw-r--r--dbaccess/uiconfig/ui/password.ui208
-rw-r--r--dbaccess/uiconfig/ui/querycolmenu.ui31
-rw-r--r--dbaccess/uiconfig/ui/queryfilterdialog.ui388
-rw-r--r--dbaccess/uiconfig/ui/queryfuncmenu.ui53
-rw-r--r--dbaccess/uiconfig/ui/querypropertiesdialog.ui207
-rw-r--r--dbaccess/uiconfig/ui/queryview.ui41
-rw-r--r--dbaccess/uiconfig/ui/relationdialog.ui431
-rw-r--r--dbaccess/uiconfig/ui/rowheightdialog.ui172
-rw-r--r--dbaccess/uiconfig/ui/savedialog.ui208
-rw-r--r--dbaccess/uiconfig/ui/saveindexdialog.ui82
-rw-r--r--dbaccess/uiconfig/ui/savemodifieddialog.ui82
-rw-r--r--dbaccess/uiconfig/ui/sortdialog.ui270
-rw-r--r--dbaccess/uiconfig/ui/specialjdbcconnectionpage.ui234
-rw-r--r--dbaccess/uiconfig/ui/specialsettingspage.ui414
-rw-r--r--dbaccess/uiconfig/ui/sqlexception.ui180
-rw-r--r--dbaccess/uiconfig/ui/tableborderwindow.ui72
-rw-r--r--dbaccess/uiconfig/ui/tabledesignrowmenu.ui63
-rw-r--r--dbaccess/uiconfig/ui/tabledesignsavemodifieddialog.ui82
-rw-r--r--dbaccess/uiconfig/ui/tablelistbox.ui71
-rw-r--r--dbaccess/uiconfig/ui/tablesfilterdialog.ui90
-rw-r--r--dbaccess/uiconfig/ui/tablesfilterpage.ui125
-rw-r--r--dbaccess/uiconfig/ui/tablesjoindialog.ui271
-rw-r--r--dbaccess/uiconfig/ui/tabletitle.ui39
-rw-r--r--dbaccess/uiconfig/ui/taskwindow.ui174
-rw-r--r--dbaccess/uiconfig/ui/textconnectionsettings.ui105
-rw-r--r--dbaccess/uiconfig/ui/textpage.ui385
-rw-r--r--dbaccess/uiconfig/ui/titlewindow.ui90
-rw-r--r--dbaccess/uiconfig/ui/typeselectpage.ui208
-rw-r--r--dbaccess/uiconfig/ui/useradmindialog.ui161
-rw-r--r--dbaccess/uiconfig/ui/useradminpage.ui183
-rw-r--r--dbaccess/uiconfig/ui/userdetailspage.ui225
-rw-r--r--dbaccess/util/dba.component62
-rw-r--r--dbaccess/util/dbu.component130
-rw-r--r--dbaccess/util/sdbt.component26
-rw-r--r--dbaccess/win32/source/odbcconfig/odbcconfig.cxx111
812 files changed, 184886 insertions, 0 deletions
diff --git a/dbaccess/AllLangMoTarget_dba.mk b/dbaccess/AllLangMoTarget_dba.mk
new file mode 100644
index 000000000..5c57ae6a8
--- /dev/null
+++ b/dbaccess/AllLangMoTarget_dba.mk
@@ -0,0 +1,13 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+$(eval $(call gb_AllLangMoTarget_AllLangMoTarget,dba))
+
+$(eval $(call gb_AllLangMoTarget_set_polocation,dba,dbaccess))
+
+# vim: set noet sw=4 ts=4:
diff --git a/dbaccess/CppunitTest_dbaccess_RowSetClones.mk b/dbaccess/CppunitTest_dbaccess_RowSetClones.mk
new file mode 100644
index 000000000..1b67411fb
--- /dev/null
+++ b/dbaccess/CppunitTest_dbaccess_RowSetClones.mk
@@ -0,0 +1,117 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+$(eval $(call gb_CppunitTest_CppunitTest,dbaccess_RowSetClones))
+
+$(eval $(call gb_CppunitTest_add_exception_objects,dbaccess_RowSetClones, \
+ dbaccess/qa/extras/rowsetclones \
+))
+
+$(eval $(call gb_CppunitTest_use_externals,dbaccess_RowSetClones,\
+ boost_headers \
+))
+
+$(eval $(call gb_CppunitTest_use_libraries,dbaccess_RowSetClones, \
+ basegfx \
+ comphelper \
+ cppu \
+ cppuhelper \
+ dba \
+ dbu \
+ sdbt \
+ drawinglayer \
+ editeng \
+ for \
+ forui \
+ i18nlangtag \
+ msfilter \
+ oox \
+ sal \
+ salhelper \
+ sax \
+ sb \
+ sfx \
+ sot \
+ svl \
+ svt \
+ svx \
+ svxcore \
+ test \
+ subsequenttest \
+ tl \
+ tk \
+ ucbhelper \
+ unotest \
+ utl \
+ $(call gb_Helper_optional,SCRIPTING, \
+ vbahelper) \
+ vcl \
+ xo \
+))
+
+$(eval $(call gb_CppunitTest_use_jars,dbaccess_RowSetClones, \
+ sdbc_hsqldb \
+))
+
+$(eval $(call gb_CppunitTest_use_api,dbaccess_RowSetClones,\
+ offapi \
+ oovbaapi \
+ udkapi \
+))
+
+$(eval $(call gb_CppunitTest_use_ure,dbaccess_RowSetClones))
+$(eval $(call gb_CppunitTest_use_vcl,dbaccess_RowSetClones))
+
+$(eval $(call gb_CppunitTest_use_components,dbaccess_RowSetClones,\
+ basic/util/sb \
+ comphelper/util/comphelp \
+ configmgr/source/configmgr \
+ connectivity/source/drivers/hsqldb/hsqldb \
+ $(if $(ENABLE_FIREBIRD_SDBC),connectivity/source/drivers/firebird/firebird_sdbc) \
+ connectivity/source/drivers/jdbc/jdbc \
+ connectivity/source/manager/sdbc2 \
+ dbaccess/util/dba \
+ dbaccess/util/dbu \
+ dbaccess/util/sdbt \
+ dbaccess/source/filter/xml/dbaxml \
+ filter/source/config/cache/filterconfig1 \
+ forms/util/frm \
+ framework/util/fwk \
+ i18npool/util/i18npool \
+ linguistic/source/lng \
+ oox/util/oox \
+ package/source/xstor/xstor \
+ package/util/package2 \
+ sax/source/expatwrap/expwrap \
+ scripting/source/basprov/basprov \
+ scripting/util/scriptframe \
+ sfx2/util/sfx \
+ sot/util/sot \
+ svl/source/fsstor/fsstorage \
+ svl/util/svl \
+ toolkit/util/tk \
+ ucb/source/core/ucb1 \
+ ucb/source/ucp/file/ucpfile1 \
+ ucb/source/ucp/tdoc/ucptdoc1 \
+ unotools/util/utl \
+ unoxml/source/rdf/unordf \
+ unoxml/source/service/unoxml \
+ uui/util/uui \
+ xmloff/util/xo \
+))
+
+$(eval $(call gb_CppunitTest_use_configuration,dbaccess_RowSetClones))
+
+$(call gb_CppunitTest_get_target,dbaccess_RowSetClones) : $(WORKDIR)/CppunitTest/RowSetClones.odb
+$(WORKDIR)/CppunitTest/RowSetClones.odb : $(SRCDIR)/dbaccess/qa/extras/testdocuments/RowSetClones.odb
+ mkdir -p $(dir $@)
+ cp -P -f "$<" "$@"
+.PHONY: $(WORKDIR)/CppunitTest/RowSetClones.odb
+
+# vim: set noet sw=4 ts=4:
diff --git a/dbaccess/CppunitTest_dbaccess_dialog_save.mk b/dbaccess/CppunitTest_dbaccess_dialog_save.mk
new file mode 100644
index 000000000..81adbc733
--- /dev/null
+++ b/dbaccess/CppunitTest_dbaccess_dialog_save.mk
@@ -0,0 +1,109 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+$(eval $(call gb_CppunitTest_CppunitTest,dbaccess_dialog_save))
+
+$(eval $(call gb_CppunitTest_add_exception_objects,dbaccess_dialog_save, \
+ dbaccess/qa/extras/dialog-save \
+))
+
+$(eval $(call gb_CppunitTest_use_externals,dbaccess_dialog_save,\
+ boost_headers \
+))
+
+$(eval $(call gb_CppunitTest_use_libraries,dbaccess_dialog_save, \
+ basegfx \
+ comphelper \
+ cppu \
+ cppuhelper \
+ dba \
+ dbu \
+ sdbt \
+ drawinglayer \
+ editeng \
+ for \
+ forui \
+ i18nlangtag \
+ msfilter \
+ oox \
+ sal \
+ salhelper \
+ sax \
+ sb \
+ sfx \
+ sot \
+ svl \
+ svt \
+ svx \
+ svxcore \
+ test \
+ subsequenttest \
+ tl \
+ tk \
+ ucbhelper \
+ unotest \
+ utl \
+ $(call gb_Helper_optional,SCRIPTING, \
+ vbahelper) \
+ vcl \
+ xo \
+))
+
+$(eval $(call gb_CppunitTest_use_api,dbaccess_dialog_save,\
+ offapi \
+ oovbaapi \
+ udkapi \
+))
+
+$(eval $(call gb_CppunitTest_use_ure,dbaccess_dialog_save))
+$(eval $(call gb_CppunitTest_use_vcl,dbaccess_dialog_save))
+
+$(eval $(call gb_CppunitTest_use_components,dbaccess_dialog_save,\
+ basic/util/sb \
+ comphelper/util/comphelp \
+ configmgr/source/configmgr \
+ dbaccess/util/dba \
+ dbaccess/util/dbu \
+ dbaccess/util/sdbt \
+ dbaccess/source/filter/xml/dbaxml \
+ filter/source/config/cache/filterconfig1 \
+ forms/util/frm \
+ framework/util/fwk \
+ i18npool/util/i18npool \
+ linguistic/source/lng \
+ oox/util/oox \
+ package/source/xstor/xstor \
+ package/util/package2 \
+ sax/source/expatwrap/expwrap \
+ scripting/source/basprov/basprov \
+ scripting/util/scriptframe \
+ sfx2/util/sfx \
+ sot/util/sot \
+ svl/source/fsstor/fsstorage \
+ svl/util/svl \
+ toolkit/util/tk \
+ ucb/source/core/ucb1 \
+ ucb/source/ucp/file/ucpfile1 \
+ ucb/source/ucp/tdoc/ucptdoc1 \
+ unotools/util/utl \
+ unoxml/source/rdf/unordf \
+ unoxml/source/service/unoxml \
+ uui/util/uui \
+ xmloff/util/xo \
+))
+
+$(eval $(call gb_CppunitTest_use_configuration,dbaccess_dialog_save))
+
+$(call gb_CppunitTest_get_target,dbaccess_dialog_save) : $(WORKDIR)/CppunitTest/testDialogSave.odb
+$(WORKDIR)/CppunitTest/testDialogSave.odb : $(SRCDIR)/dbaccess/qa/extras/testdocuments/testDialogSave.odb
+ mkdir -p $(dir $@)
+ cp -P -f "$<" "$@"
+.PHONY: $(WORKDIR)/CppunitTest/testDialogSave.odb
+
+# vim: set noet sw=4 ts=4:
diff --git a/dbaccess/CppunitTest_dbaccess_dialogs_test.mk b/dbaccess/CppunitTest_dbaccess_dialogs_test.mk
new file mode 100644
index 000000000..3ed9a0649
--- /dev/null
+++ b/dbaccess/CppunitTest_dbaccess_dialogs_test.mk
@@ -0,0 +1,69 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#*************************************************************************
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+#*************************************************************************
+
+$(eval $(call gb_CppunitTest_CppunitScreenShot,dbaccess_dialogs_test))
+
+$(eval $(call gb_CppunitTest_add_exception_objects,dbaccess_dialogs_test, \
+ dbaccess/qa/unit/dbaccess-dialogs-test \
+))
+
+$(eval $(call gb_CppunitTest_use_sdk_api,dbaccess_dialogs_test))
+
+$(eval $(call gb_CppunitTest_set_include,dbaccess_dialogs_test,\
+ -I$(SRCDIR)/dbaccess/source/inc \
+ -I$(SRCDIR)/dbaccess/inc \
+ $$(INCLUDE) \
+))
+
+$(eval $(call gb_CppunitTest_use_libraries,dbaccess_dialogs_test, \
+ basegfx \
+ comphelper \
+ cppu \
+ cppuhelper \
+ drawinglayer \
+ editeng \
+ i18nlangtag \
+ i18nutil \
+ msfilter \
+ oox \
+ sal \
+ salhelper \
+ sax \
+ sfx \
+ sot \
+ svl \
+ svt \
+ test \
+ tl \
+ tk \
+ ucbhelper \
+ unotest \
+ utl \
+ vcl \
+ xo \
+))
+
+$(eval $(call gb_CppunitTest_use_external,dbaccess_dialogs_test,boost_headers))
+
+$(eval $(call gb_CppunitTest_use_sdk_api,dbaccess_dialogs_test))
+
+$(eval $(call gb_CppunitTest_use_ure,dbaccess_dialogs_test))
+$(eval $(call gb_CppunitTest_use_vcl_non_headless_with_windows,dbaccess_dialogs_test))
+
+$(eval $(call gb_CppunitTest_use_rdb,dbaccess_dialogs_test,services))
+
+$(eval $(call gb_CppunitTest_use_configuration,dbaccess_dialogs_test))
+
+$(eval $(call gb_CppunitTest_use_uiconfigs,dbaccess_dialogs_test,\
+ dbaccess \
+))
+
+# vim: set noet sw=4 ts=4:
diff --git a/dbaccess/CppunitTest_dbaccess_embeddeddb_performancetest.mk b/dbaccess/CppunitTest_dbaccess_embeddeddb_performancetest.mk
new file mode 100644
index 000000000..6a9225693
--- /dev/null
+++ b/dbaccess/CppunitTest_dbaccess_embeddeddb_performancetest.mk
@@ -0,0 +1,73 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+$(eval $(call gb_CppunitTest_CppunitTest,dbaccess_embeddeddb_performancetest))
+
+$(eval $(call gb_CppunitTest_use_external,dbaccess_embeddeddb_performancetest,boost_headers))
+
+$(eval $(call gb_CppunitTest_add_exception_objects,dbaccess_embeddeddb_performancetest, \
+ dbaccess/qa/unit/embeddeddb_performancetest \
+))
+
+$(eval $(call gb_CppunitTest_use_libraries,dbaccess_embeddeddb_performancetest, \
+ comphelper \
+ cppu \
+ cppuhelper \
+ dbaxml \
+ dbtools \
+ firebird_sdbc \
+ sal \
+ subsequenttest \
+ utl \
+ test \
+ tk \
+ tl \
+ unotest \
+ xo \
+))
+
+$(eval $(call gb_CppunitTest_use_api,dbaccess_embeddeddb_performancetest,\
+ offapi \
+ oovbaapi \
+ udkapi \
+))
+
+$(eval $(call gb_CppunitTest_use_ure,dbaccess_embeddeddb_performancetest))
+$(eval $(call gb_CppunitTest_use_vcl,dbaccess_embeddeddb_performancetest))
+
+$(eval $(call gb_CppunitTest_use_components,dbaccess_embeddeddb_performancetest,\
+ basic/util/sb \
+ comphelper/util/comphelp \
+ configmgr/source/configmgr \
+ connectivity/source/cpool/dbpool2 \
+ connectivity/source/drivers/firebird/firebird_sdbc \
+ connectivity/source/manager/sdbc2 \
+ dbaccess/util/dba \
+ dbaccess/source/filter/xml/dbaxml \
+ dbaccess/util/dbu \
+ filter/source/config/cache/filterconfig1 \
+ framework/util/fwk \
+ i18npool/util/i18npool \
+ linguistic/source/lng \
+ package/source/xstor/xstor \
+ package/util/package2 \
+ sax/source/expatwrap/expwrap \
+ sfx2/util/sfx \
+ svl/source/fsstor/fsstorage \
+ svl/util/svl \
+ toolkit/util/tk \
+ ucb/source/core/ucb1 \
+ ucb/source/ucp/file/ucpfile1 \
+ unotools/util/utl \
+ xmloff/util/xo \
+))
+
+$(eval $(call gb_CppunitTest_use_configuration,dbaccess_embeddeddb_performancetest))
+
+# vim: set noet sw=4 ts=4:
diff --git a/dbaccess/CppunitTest_dbaccess_empty_stdlib_save.mk b/dbaccess/CppunitTest_dbaccess_empty_stdlib_save.mk
new file mode 100644
index 000000000..3a4b44479
--- /dev/null
+++ b/dbaccess/CppunitTest_dbaccess_empty_stdlib_save.mk
@@ -0,0 +1,109 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+$(eval $(call gb_CppunitTest_CppunitTest,dbaccess_empty_stdlib_save))
+
+$(eval $(call gb_CppunitTest_add_exception_objects,dbaccess_empty_stdlib_save, \
+ dbaccess/qa/extras/empty-stdlib-save \
+))
+
+$(eval $(call gb_CppunitTest_use_externals,dbaccess_empty_stdlib_save,\
+ boost_headers \
+))
+
+$(eval $(call gb_CppunitTest_use_libraries,dbaccess_empty_stdlib_save, \
+ basegfx \
+ comphelper \
+ cppu \
+ cppuhelper \
+ dba \
+ dbu \
+ sdbt \
+ drawinglayer \
+ editeng \
+ for \
+ forui \
+ i18nlangtag \
+ msfilter \
+ oox \
+ sal \
+ salhelper \
+ sax \
+ sb \
+ sfx \
+ sot \
+ svl \
+ svt \
+ svx \
+ svxcore \
+ test \
+ subsequenttest \
+ tl \
+ tk \
+ ucbhelper \
+ unotest \
+ utl \
+ $(call gb_Helper_optional,SCRIPTING, \
+ vbahelper) \
+ vcl \
+ xo \
+))
+
+$(eval $(call gb_CppunitTest_use_api,dbaccess_empty_stdlib_save,\
+ offapi \
+ oovbaapi \
+ udkapi \
+))
+
+$(eval $(call gb_CppunitTest_use_ure,dbaccess_empty_stdlib_save))
+$(eval $(call gb_CppunitTest_use_vcl,dbaccess_empty_stdlib_save))
+
+$(eval $(call gb_CppunitTest_use_components,dbaccess_empty_stdlib_save,\
+ basic/util/sb \
+ comphelper/util/comphelp \
+ configmgr/source/configmgr \
+ dbaccess/util/dba \
+ dbaccess/util/dbu \
+ dbaccess/util/sdbt \
+ dbaccess/source/filter/xml/dbaxml \
+ filter/source/config/cache/filterconfig1 \
+ forms/util/frm \
+ framework/util/fwk \
+ i18npool/util/i18npool \
+ linguistic/source/lng \
+ oox/util/oox \
+ package/source/xstor/xstor \
+ package/util/package2 \
+ sax/source/expatwrap/expwrap \
+ scripting/source/basprov/basprov \
+ scripting/util/scriptframe \
+ sfx2/util/sfx \
+ sot/util/sot \
+ svl/source/fsstor/fsstorage \
+ svl/util/svl \
+ toolkit/util/tk \
+ ucb/source/core/ucb1 \
+ ucb/source/ucp/file/ucpfile1 \
+ ucb/source/ucp/tdoc/ucptdoc1 \
+ unotools/util/utl \
+ unoxml/source/rdf/unordf \
+ unoxml/source/service/unoxml \
+ uui/util/uui \
+ xmloff/util/xo \
+))
+
+$(eval $(call gb_CppunitTest_use_configuration,dbaccess_empty_stdlib_save))
+
+$(call gb_CppunitTest_get_target,dbaccess_empty_stdlib_save) : $(WORKDIR)/CppunitTest/testEmptyStdlibSave.odb
+$(WORKDIR)/CppunitTest/testEmptyStdlibSave.odb : $(SRCDIR)/dbaccess/qa/extras/testdocuments/testDialogSave.odb
+ mkdir -p $(dir $@)
+ cp -P -f "$<" "$@"
+.PHONY: $(WORKDIR)/CppunitTest/testEmptyStdlibSave.odb
+
+# vim: set noet sw=4 ts=4:
diff --git a/dbaccess/CppunitTest_dbaccess_firebird_test.mk b/dbaccess/CppunitTest_dbaccess_firebird_test.mk
new file mode 100644
index 000000000..506552099
--- /dev/null
+++ b/dbaccess/CppunitTest_dbaccess_firebird_test.mk
@@ -0,0 +1,70 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+$(eval $(call gb_CppunitTest_CppunitTest,dbaccess_firebird_test))
+
+$(eval $(call gb_CppunitTest_use_external,dbaccess_firebird_test,boost_headers))
+
+$(eval $(call gb_CppunitTest_add_exception_objects,dbaccess_firebird_test, \
+ dbaccess/qa/unit/firebird \
+))
+
+$(eval $(call gb_CppunitTest_use_libraries,dbaccess_firebird_test, \
+ comphelper \
+ cppu \
+ dbaxml \
+ firebird_sdbc \
+ sal \
+ subsequenttest \
+ svt \
+ test \
+ unotest \
+ utl \
+ xo \
+))
+
+$(eval $(call gb_CppunitTest_use_api,dbaccess_firebird_test,\
+ offapi \
+ oovbaapi \
+ udkapi \
+))
+
+$(eval $(call gb_CppunitTest_use_ure,dbaccess_firebird_test))
+$(eval $(call gb_CppunitTest_use_vcl,dbaccess_firebird_test))
+
+$(eval $(call gb_CppunitTest_use_components,dbaccess_firebird_test,\
+ basic/util/sb \
+ comphelper/util/comphelp \
+ configmgr/source/configmgr \
+ connectivity/source/drivers/firebird/firebird_sdbc \
+ connectivity/source/manager/sdbc2 \
+ dbaccess/util/dba \
+ dbaccess/source/filter/xml/dbaxml \
+ dbaccess/util/dbu \
+ filter/source/config/cache/filterconfig1 \
+ framework/util/fwk \
+ i18npool/util/i18npool \
+ linguistic/source/lng \
+ package/source/xstor/xstor \
+ package/util/package2 \
+ sax/source/expatwrap/expwrap \
+ sfx2/util/sfx \
+ svl/source/fsstor/fsstorage \
+ svl/util/svl \
+ toolkit/util/tk \
+ ucb/source/core/ucb1 \
+ ucb/source/ucp/file/ucpfile1 \
+ unotools/util/utl \
+ uui/util/uui \
+ xmloff/util/xo \
+))
+
+$(eval $(call gb_CppunitTest_use_configuration,dbaccess_firebird_test))
+
+# vim: set noet sw=4 ts=4:
diff --git a/dbaccess/CppunitTest_dbaccess_hsqlbinary_import.mk b/dbaccess/CppunitTest_dbaccess_hsqlbinary_import.mk
new file mode 100644
index 000000000..23ec9e1e4
--- /dev/null
+++ b/dbaccess/CppunitTest_dbaccess_hsqlbinary_import.mk
@@ -0,0 +1,114 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+$(eval $(call gb_CppunitTest_CppunitTest,dbaccess_hsql_binary_import))
+
+$(eval $(call gb_CppunitTest_add_exception_objects,dbaccess_hsql_binary_import, \
+ dbaccess/qa/unit/hsql_binary_import \
+))
+
+$(eval $(call gb_CppunitTest_use_external,dbaccess_hsql_binary_import,boost_headers))
+
+$(eval $(call gb_CppunitTest_use_libraries,dbaccess_hsql_binary_import, \
+ basegfx \
+ comphelper \
+ cppu \
+ cppuhelper \
+ dba \
+ dbahsql \
+ dbu \
+ sdbt \
+ drawinglayer \
+ editeng \
+ for \
+ forui \
+ i18nlangtag \
+ msfilter \
+ oox \
+ sal \
+ salhelper \
+ sax \
+ sb \
+ sfx \
+ sot \
+ svl \
+ svt \
+ svx \
+ svxcore \
+ test \
+ subsequenttest \
+ tl \
+ tk \
+ ucbhelper \
+ unotest \
+ utl \
+ $(call gb_Helper_optional,SCRIPTING, \
+ vbahelper) \
+ vcl \
+ xo \
+))
+
+$(eval $(call gb_CppunitTest_use_ure,dbaccess_hsql_binary_import))
+$(eval $(call gb_CppunitTest_use_vcl,dbaccess_hsql_binary_import))
+
+$(eval $(call gb_CppunitTest_set_include,dbaccess_hsql_binary_import,\
+ -I$(SRCDIR)/dbaccess/source/filter/hsqldb \
+ $$(INCLUDE) \
+))
+
+$(eval $(call gb_CppunitTest_use_custom_headers,dbaccess_hsql_binary_import,\
+ officecfg/registry \
+))
+
+$(eval $(call gb_CppunitTest_use_api,dbaccess_hsql_binary_import,\
+ offapi \
+ oovbaapi \
+ udkapi \
+))
+
+$(eval $(call gb_CppunitTest_use_components,dbaccess_hsql_binary_import,\
+ basic/util/sb \
+ comphelper/util/comphelp \
+ configmgr/source/configmgr \
+ connectivity/source/drivers/hsqldb/hsqldb \
+ $(if $(ENABLE_FIREBIRD_SDBC),connectivity/source/drivers/firebird/firebird_sdbc) \
+ connectivity/source/manager/sdbc2 \
+ dbaccess/util/dba \
+ dbaccess/util/dbu \
+ dbaccess/util/sdbt \
+ dbaccess/source/filter/xml/dbaxml \
+ filter/source/config/cache/filterconfig1 \
+ forms/util/frm \
+ framework/util/fwk \
+ i18npool/util/i18npool \
+ linguistic/source/lng \
+ oox/util/oox \
+ package/source/xstor/xstor \
+ package/util/package2 \
+ sax/source/expatwrap/expwrap \
+ scripting/source/basprov/basprov \
+ scripting/util/scriptframe \
+ sfx2/util/sfx \
+ sot/util/sot \
+ svl/source/fsstor/fsstorage \
+ svl/util/svl \
+ toolkit/util/tk \
+ ucb/source/core/ucb1 \
+ ucb/source/ucp/file/ucpfile1 \
+ ucb/source/ucp/tdoc/ucptdoc1 \
+ unotools/util/utl \
+ unoxml/source/rdf/unordf \
+ unoxml/source/service/unoxml \
+ uui/util/uui \
+ xmloff/util/xo \
+))
+
+$(eval $(call gb_CppunitTest_use_configuration,dbaccess_hsql_binary_import))
+
+# vim: set noet sw=4 ts=4:
diff --git a/dbaccess/CppunitTest_dbaccess_hsqldb_test.mk b/dbaccess/CppunitTest_dbaccess_hsqldb_test.mk
new file mode 100644
index 000000000..3cad59f2a
--- /dev/null
+++ b/dbaccess/CppunitTest_dbaccess_hsqldb_test.mk
@@ -0,0 +1,84 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+$(eval $(call gb_CppunitTest_CppunitTest,dbaccess_hsqldb_test))
+
+$(eval $(call gb_CppunitTest_use_external,dbaccess_hsqldb_test,boost_headers))
+
+$(eval $(call gb_CppunitTest_add_exception_objects,dbaccess_hsqldb_test, \
+ dbaccess/qa/unit/hsqldb \
+))
+
+$(eval $(call gb_CppunitTest_use_libraries,dbaccess_hsqldb_test, \
+ affine_uno_uno \
+ comphelper \
+ cppu \
+ cppuhelper \
+ dbaxml \
+ dbtools \
+ jvmfwk \
+ sal \
+ subsequenttest \
+ utl \
+ test \
+ tk \
+ unotest \
+ xo \
+))
+
+$(eval $(call gb_CppunitTest_use_jars,dbaccess_hsqldb_test, \
+ sdbc_hsqldb \
+))
+
+$(eval $(call gb_CppunitTest_use_api,dbaccess_hsqldb_test,\
+ offapi \
+ oovbaapi \
+ udkapi \
+))
+
+$(eval $(call gb_CppunitTest_use_ure,dbaccess_hsqldb_test))
+$(eval $(call gb_CppunitTest_use_vcl,dbaccess_hsqldb_test))
+
+$(eval $(call gb_CppunitTest_use_components,dbaccess_hsqldb_test,\
+ basic/util/sb \
+ comphelper/util/comphelp \
+ configmgr/source/configmgr \
+ connectivity/source/cpool/dbpool2 \
+ connectivity/source/drivers/hsqldb/hsqldb \
+ $(if $(ENABLE_FIREBIRD_SDBC),connectivity/source/drivers/firebird/firebird_sdbc) \
+ connectivity/source/drivers/jdbc/jdbc \
+ connectivity/source/manager/sdbc2 \
+ dbaccess/util/dba \
+ dbaccess/source/filter/xml/dbaxml \
+ dbaccess/util/dbu \
+ filter/source/config/cache/filterconfig1 \
+ framework/util/fwk \
+ i18npool/util/i18npool \
+ linguistic/source/lng \
+ package/source/xstor/xstor \
+ package/util/package2 \
+ sax/source/expatwrap/expwrap \
+ sfx2/util/sfx \
+ svl/source/fsstor/fsstorage \
+ svl/util/svl \
+ toolkit/util/tk \
+ ucb/source/core/ucb1 \
+ ucb/source/ucp/file/ucpfile1 \
+ unotools/util/utl \
+ uui/util/uui \
+ xmloff/util/xo \
+))
+
+$(eval $(call gb_CppunitTest_use_configuration,dbaccess_hsqldb_test))
+
+$(eval $(call gb_CppunitTest_use_uiconfigs,dbaccess_hsqldb_test, \
+ dbaccess \
+))
+
+# vim: set noet sw=4 ts=4:
diff --git a/dbaccess/CppunitTest_dbaccess_hsqlschema_import.mk b/dbaccess/CppunitTest_dbaccess_hsqlschema_import.mk
new file mode 100644
index 000000000..7e131c810
--- /dev/null
+++ b/dbaccess/CppunitTest_dbaccess_hsqlschema_import.mk
@@ -0,0 +1,102 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+$(eval $(call gb_CppunitTest_CppunitTest,dbaccess_hsql_schema_import))
+
+$(eval $(call gb_CppunitTest_add_exception_objects,dbaccess_hsql_schema_import, \
+ dbaccess/qa/extras/hsql_schema_import \
+))
+
+$(eval $(call gb_CppunitTest_use_libraries,dbaccess_hsql_schema_import, \
+ basegfx \
+ comphelper \
+ cppu \
+ cppuhelper \
+ dba \
+ dbahsql \
+ dbu \
+ sdbt \
+ drawinglayer \
+ editeng \
+ for \
+ forui \
+ i18nlangtag \
+ msfilter \
+ oox \
+ sal \
+ salhelper \
+ sax \
+ sb \
+ sfx \
+ sot \
+ svl \
+ svt \
+ svx \
+ svxcore \
+ test \
+ subsequenttest \
+ tl \
+ tk \
+ ucbhelper \
+ unotest \
+ utl \
+ $(call gb_Helper_optional,SCRIPTING, \
+ vbahelper) \
+ vcl \
+ xo \
+))
+
+$(eval $(call gb_CppunitTest_set_include,dbaccess_hsql_schema_import,\
+ -I$(SRCDIR)/dbaccess/source/filter/hsqldb \
+ $$(INCLUDE) \
+))
+
+$(eval $(call gb_CppunitTest_use_api,dbaccess_hsql_schema_import,\
+ offapi \
+ oovbaapi \
+ udkapi \
+))
+
+$(eval $(call gb_CppunitTest_use_components,dbaccess_hsql_schema_import,\
+ basic/util/sb \
+ comphelper/util/comphelp \
+ configmgr/source/configmgr \
+ dbaccess/util/dba \
+ dbaccess/util/dbu \
+ dbaccess/util/sdbt \
+ dbaccess/source/filter/xml/dbaxml \
+ filter/source/config/cache/filterconfig1 \
+ forms/util/frm \
+ framework/util/fwk \
+ i18npool/util/i18npool \
+ linguistic/source/lng \
+ oox/util/oox \
+ package/source/xstor/xstor \
+ package/util/package2 \
+ sax/source/expatwrap/expwrap \
+ scripting/source/basprov/basprov \
+ scripting/util/scriptframe \
+ sfx2/util/sfx \
+ sot/util/sot \
+ svl/source/fsstor/fsstorage \
+ svl/util/svl \
+ toolkit/util/tk \
+ ucb/source/core/ucb1 \
+ ucb/source/ucp/file/ucpfile1 \
+ ucb/source/ucp/tdoc/ucptdoc1 \
+ unotools/util/utl \
+ unoxml/source/rdf/unordf \
+ unoxml/source/service/unoxml \
+ uui/util/uui \
+ xmloff/util/xo \
+))
+
+$(eval $(call gb_CppunitTest_use_configuration,dbaccess_hsql_schema_import))
+
+# vim: set noet sw=4 ts=4:
diff --git a/dbaccess/CppunitTest_dbaccess_macros_test.mk b/dbaccess/CppunitTest_dbaccess_macros_test.mk
new file mode 100644
index 000000000..248a5520c
--- /dev/null
+++ b/dbaccess/CppunitTest_dbaccess_macros_test.mk
@@ -0,0 +1,102 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+$(eval $(call gb_CppunitTest_CppunitTest,dbaccess_macros_test))
+
+$(eval $(call gb_CppunitTest_add_exception_objects,dbaccess_macros_test, \
+ dbaccess/qa/extras/macros-test \
+))
+
+$(eval $(call gb_CppunitTest_use_externals,dbaccess_macros_test,\
+ boost_headers \
+))
+
+$(eval $(call gb_CppunitTest_use_libraries,dbaccess_macros_test, \
+ basegfx \
+ comphelper \
+ cppu \
+ cppuhelper \
+ dba \
+ dbu \
+ sdbt \
+ drawinglayer \
+ editeng \
+ for \
+ forui \
+ i18nlangtag \
+ msfilter \
+ oox \
+ sal \
+ salhelper \
+ sax \
+ sb \
+ sfx \
+ sot \
+ svl \
+ svt \
+ svx \
+ svxcore \
+ test \
+ subsequenttest \
+ tl \
+ tk \
+ ucbhelper \
+ unotest \
+ utl \
+ $(call gb_Helper_optional,SCRIPTING, \
+ vbahelper) \
+ vcl \
+ xo \
+))
+
+$(eval $(call gb_CppunitTest_use_api,dbaccess_macros_test,\
+ offapi \
+ oovbaapi \
+ udkapi \
+))
+
+$(eval $(call gb_CppunitTest_use_ure,dbaccess_macros_test))
+$(eval $(call gb_CppunitTest_use_vcl,dbaccess_macros_test))
+
+$(eval $(call gb_CppunitTest_use_components,dbaccess_macros_test,\
+ basic/util/sb \
+ comphelper/util/comphelp \
+ configmgr/source/configmgr \
+ dbaccess/util/dba \
+ dbaccess/util/dbu \
+ dbaccess/util/sdbt \
+ dbaccess/source/filter/xml/dbaxml \
+ filter/source/config/cache/filterconfig1 \
+ forms/util/frm \
+ framework/util/fwk \
+ i18npool/util/i18npool \
+ oox/util/oox \
+ package/source/xstor/xstor \
+ package/util/package2 \
+ sax/source/expatwrap/expwrap \
+ scripting/source/basprov/basprov \
+ scripting/util/scriptframe \
+ sfx2/util/sfx \
+ sot/util/sot \
+ svl/source/fsstor/fsstorage \
+ svl/util/svl \
+ toolkit/util/tk \
+ ucb/source/core/ucb1 \
+ ucb/source/ucp/file/ucpfile1 \
+ ucb/source/ucp/tdoc/ucptdoc1 \
+ unotools/util/utl \
+ unoxml/source/rdf/unordf \
+ unoxml/source/service/unoxml \
+ uui/util/uui \
+ xmloff/util/xo \
+))
+
+$(eval $(call gb_CppunitTest_use_configuration,dbaccess_macros_test))
+
+# vim: set noet sw=4 ts=4:
diff --git a/dbaccess/CppunitTest_dbaccess_nolib_save.mk b/dbaccess/CppunitTest_dbaccess_nolib_save.mk
new file mode 100644
index 000000000..088dc92c4
--- /dev/null
+++ b/dbaccess/CppunitTest_dbaccess_nolib_save.mk
@@ -0,0 +1,109 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+$(eval $(call gb_CppunitTest_CppunitTest,dbaccess_nolib_save))
+
+$(eval $(call gb_CppunitTest_add_exception_objects,dbaccess_nolib_save, \
+ dbaccess/qa/extras/nolib-save \
+))
+
+$(eval $(call gb_CppunitTest_use_externals,dbaccess_nolib_save,\
+ boost_headers \
+))
+
+$(eval $(call gb_CppunitTest_use_libraries,dbaccess_nolib_save, \
+ basegfx \
+ comphelper \
+ cppu \
+ cppuhelper \
+ dba \
+ dbu \
+ sdbt \
+ drawinglayer \
+ editeng \
+ for \
+ forui \
+ i18nlangtag \
+ msfilter \
+ oox \
+ sal \
+ salhelper \
+ sax \
+ sb \
+ sfx \
+ sot \
+ svl \
+ svt \
+ svx \
+ svxcore \
+ test \
+ subsequenttest \
+ tl \
+ tk \
+ ucbhelper \
+ unotest \
+ utl \
+ $(call gb_Helper_optional,SCRIPTING, \
+ vbahelper) \
+ vcl \
+ xo \
+))
+
+$(eval $(call gb_CppunitTest_use_api,dbaccess_nolib_save,\
+ offapi \
+ oovbaapi \
+ udkapi \
+))
+
+$(eval $(call gb_CppunitTest_use_ure,dbaccess_nolib_save))
+$(eval $(call gb_CppunitTest_use_vcl,dbaccess_nolib_save))
+
+$(eval $(call gb_CppunitTest_use_components,dbaccess_nolib_save,\
+ basic/util/sb \
+ comphelper/util/comphelp \
+ configmgr/source/configmgr \
+ dbaccess/util/dba \
+ dbaccess/util/dbu \
+ dbaccess/util/sdbt \
+ dbaccess/source/filter/xml/dbaxml \
+ filter/source/config/cache/filterconfig1 \
+ forms/util/frm \
+ framework/util/fwk \
+ i18npool/util/i18npool \
+ linguistic/source/lng \
+ oox/util/oox \
+ package/source/xstor/xstor \
+ package/util/package2 \
+ sax/source/expatwrap/expwrap \
+ scripting/source/basprov/basprov \
+ scripting/util/scriptframe \
+ sfx2/util/sfx \
+ sot/util/sot \
+ svl/source/fsstor/fsstorage \
+ svl/util/svl \
+ toolkit/util/tk \
+ ucb/source/core/ucb1 \
+ ucb/source/ucp/file/ucpfile1 \
+ ucb/source/ucp/tdoc/ucptdoc1 \
+ unotools/util/utl \
+ unoxml/source/rdf/unordf \
+ unoxml/source/service/unoxml \
+ uui/util/uui \
+ xmloff/util/xo \
+))
+
+$(eval $(call gb_CppunitTest_use_configuration,dbaccess_nolib_save))
+
+$(call gb_CppunitTest_get_target,dbaccess_nolib_save) : $(WORKDIR)/CppunitTest/testNolibSave.odb
+$(WORKDIR)/CppunitTest/testNolibSave.odb : $(SRCDIR)/dbaccess/qa/extras/testdocuments/testDialogSave.odb
+ mkdir -p $(dir $@)
+ cp -P -f "$<" "$@"
+.PHONY: $(WORKDIR)/CppunitTest/testNolibSave.odb
+
+# vim: set noet sw=4 ts=4:
diff --git a/dbaccess/CppunitTest_dbaccess_tdf119625.mk b/dbaccess/CppunitTest_dbaccess_tdf119625.mk
new file mode 100644
index 000000000..b96ea797f
--- /dev/null
+++ b/dbaccess/CppunitTest_dbaccess_tdf119625.mk
@@ -0,0 +1,114 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+$(eval $(call gb_CppunitTest_CppunitTest,dbaccess_tdf119625))
+
+$(eval $(call gb_CppunitTest_add_exception_objects,dbaccess_tdf119625, \
+ dbaccess/qa/unit/tdf119625 \
+))
+
+$(eval $(call gb_CppunitTest_use_external,dbaccess_tdf119625,boost_headers))
+
+$(eval $(call gb_CppunitTest_use_libraries,dbaccess_tdf119625, \
+ basegfx \
+ comphelper \
+ cppu \
+ cppuhelper \
+ dba \
+ dbahsql \
+ dbu \
+ sdbt \
+ drawinglayer \
+ editeng \
+ for \
+ forui \
+ i18nlangtag \
+ msfilter \
+ oox \
+ sal \
+ salhelper \
+ sax \
+ sb \
+ sfx \
+ sot \
+ svl \
+ svt \
+ svx \
+ svxcore \
+ test \
+ subsequenttest \
+ tl \
+ tk \
+ ucbhelper \
+ unotest \
+ utl \
+ $(call gb_Helper_optional,SCRIPTING, \
+ vbahelper) \
+ vcl \
+ xo \
+))
+
+$(eval $(call gb_CppunitTest_use_ure,dbaccess_tdf119625))
+$(eval $(call gb_CppunitTest_use_vcl,dbaccess_tdf119625))
+
+$(eval $(call gb_CppunitTest_set_include,dbaccess_tdf119625,\
+ -I$(SRCDIR)/dbaccess/source/filter/hsqldb \
+ $$(INCLUDE) \
+))
+
+$(eval $(call gb_CppunitTest_use_custom_headers,dbaccess_tdf119625,\
+ officecfg/registry \
+))
+
+$(eval $(call gb_CppunitTest_use_api,dbaccess_tdf119625,\
+ offapi \
+ oovbaapi \
+ udkapi \
+))
+
+$(eval $(call gb_CppunitTest_use_components,dbaccess_tdf119625,\
+ basic/util/sb \
+ comphelper/util/comphelp \
+ configmgr/source/configmgr \
+ connectivity/source/drivers/hsqldb/hsqldb \
+ connectivity/source/drivers/firebird/firebird_sdbc \
+ connectivity/source/manager/sdbc2 \
+ dbaccess/util/dba \
+ dbaccess/util/dbu \
+ dbaccess/util/sdbt \
+ dbaccess/source/filter/xml/dbaxml \
+ filter/source/config/cache/filterconfig1 \
+ forms/util/frm \
+ framework/util/fwk \
+ i18npool/util/i18npool \
+ linguistic/source/lng \
+ oox/util/oox \
+ package/source/xstor/xstor \
+ package/util/package2 \
+ sax/source/expatwrap/expwrap \
+ scripting/source/basprov/basprov \
+ scripting/util/scriptframe \
+ sfx2/util/sfx \
+ sot/util/sot \
+ svl/source/fsstor/fsstorage \
+ svl/util/svl \
+ toolkit/util/tk \
+ ucb/source/core/ucb1 \
+ ucb/source/ucp/file/ucpfile1 \
+ ucb/source/ucp/tdoc/ucptdoc1 \
+ unotools/util/utl \
+ unoxml/source/rdf/unordf \
+ unoxml/source/service/unoxml \
+ uui/util/uui \
+ xmloff/util/xo \
+))
+
+$(eval $(call gb_CppunitTest_use_configuration,dbaccess_tdf119625))
+
+# vim: set noet sw=4 ts=4:
diff --git a/dbaccess/CppunitTest_dbaccess_tdf126268.mk b/dbaccess/CppunitTest_dbaccess_tdf126268.mk
new file mode 100644
index 000000000..b3e97206b
--- /dev/null
+++ b/dbaccess/CppunitTest_dbaccess_tdf126268.mk
@@ -0,0 +1,114 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+$(eval $(call gb_CppunitTest_CppunitTest,dbaccess_tdf126268))
+
+$(eval $(call gb_CppunitTest_add_exception_objects,dbaccess_tdf126268, \
+ dbaccess/qa/unit/tdf126268 \
+))
+
+$(eval $(call gb_CppunitTest_use_external,dbaccess_tdf126268,boost_headers))
+
+$(eval $(call gb_CppunitTest_use_libraries,dbaccess_tdf126268, \
+ basegfx \
+ comphelper \
+ cppu \
+ cppuhelper \
+ dba \
+ dbahsql \
+ dbu \
+ sdbt \
+ drawinglayer \
+ editeng \
+ for \
+ forui \
+ i18nlangtag \
+ msfilter \
+ oox \
+ sal \
+ salhelper \
+ sax \
+ sb \
+ sfx \
+ sot \
+ svl \
+ svt \
+ svx \
+ svxcore \
+ test \
+ subsequenttest \
+ tl \
+ tk \
+ ucbhelper \
+ unotest \
+ utl \
+ $(call gb_Helper_optional,SCRIPTING, \
+ vbahelper) \
+ vcl \
+ xo \
+))
+
+$(eval $(call gb_CppunitTest_use_ure,dbaccess_tdf126268))
+$(eval $(call gb_CppunitTest_use_vcl,dbaccess_tdf126268))
+
+$(eval $(call gb_CppunitTest_set_include,dbaccess_tdf126268,\
+ -I$(SRCDIR)/dbaccess/source/filter/hsqldb \
+ $$(INCLUDE) \
+))
+
+$(eval $(call gb_CppunitTest_use_custom_headers,dbaccess_tdf126268,\
+ officecfg/registry \
+))
+
+$(eval $(call gb_CppunitTest_use_api,dbaccess_tdf126268,\
+ offapi \
+ oovbaapi \
+ udkapi \
+))
+
+$(eval $(call gb_CppunitTest_use_components,dbaccess_tdf126268,\
+ basic/util/sb \
+ comphelper/util/comphelp \
+ configmgr/source/configmgr \
+ connectivity/source/drivers/hsqldb/hsqldb \
+ connectivity/source/drivers/firebird/firebird_sdbc \
+ connectivity/source/manager/sdbc2 \
+ dbaccess/util/dba \
+ dbaccess/util/dbu \
+ dbaccess/util/sdbt \
+ dbaccess/source/filter/xml/dbaxml \
+ filter/source/config/cache/filterconfig1 \
+ forms/util/frm \
+ framework/util/fwk \
+ i18npool/util/i18npool \
+ linguistic/source/lng \
+ oox/util/oox \
+ package/source/xstor/xstor \
+ package/util/package2 \
+ sax/source/expatwrap/expwrap \
+ scripting/source/basprov/basprov \
+ scripting/util/scriptframe \
+ sfx2/util/sfx \
+ sot/util/sot \
+ svl/source/fsstor/fsstorage \
+ svl/util/svl \
+ toolkit/util/tk \
+ ucb/source/core/ucb1 \
+ ucb/source/ucp/file/ucpfile1 \
+ ucb/source/ucp/tdoc/ucptdoc1 \
+ unotools/util/utl \
+ unoxml/source/rdf/unordf \
+ unoxml/source/service/unoxml \
+ uui/util/uui \
+ xmloff/util/xo \
+))
+
+$(eval $(call gb_CppunitTest_use_configuration,dbaccess_tdf126268))
+
+# vim: set noet sw=4 ts=4:
diff --git a/dbaccess/Executable_odbcconfig.mk b/dbaccess/Executable_odbcconfig.mk
new file mode 100644
index 000000000..862c77b3b
--- /dev/null
+++ b/dbaccess/Executable_odbcconfig.mk
@@ -0,0 +1,31 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+$(eval $(call gb_Executable_Executable,odbcconfig))
+
+$(eval $(call gb_Executable_set_targettype_gui,odbcconfig,YES))
+
+$(eval $(call gb_Executable_use_libraries,odbcconfig,\
+ comphelper \
+))
+
+$(eval $(call gb_Executable_use_system_win32_libs,odbcconfig,\
+ legacy_stdio_definitions \
+ odbccp32 \
+))
+
+$(eval $(call gb_Library_use_sdk_api,odbcconfig))
+
+$(eval $(call gb_Executable_add_exception_objects,odbcconfig,\
+ dbaccess/win32/source/odbcconfig/odbcconfig \
+))
+
+$(eval $(call gb_Executable_add_default_nativeres,odbcconfig))
+
+# vim: set noet sw=4 ts=4:
diff --git a/dbaccess/IwyuFilter_dbaccess.yaml b/dbaccess/IwyuFilter_dbaccess.yaml
new file mode 100644
index 000000000..7d0e1f9c0
--- /dev/null
+++ b/dbaccess/IwyuFilter_dbaccess.yaml
@@ -0,0 +1,162 @@
+---
+assumeFilename: dbaccess/source/ui/querydesign/QueryDesignView.cxx
+excludelist:
+ dbaccess/source/inc/dbu_reghelper.hxx:
+ # Needed for registrationhelper.hxx
+ - com/sun/star/lang/XSingleServiceFactory.hpp
+ - com/sun/star/lang/XMultiServiceFactory.hpp
+ - rtl/ustring.hxx
+ - cppuhelper/factory.hxx
+ dbaccess/source/inc/flt_reghelper.hxx:
+ # Needed for registrationhelper.hxx
+ - com/sun/star/lang/XSingleServiceFactory.hpp
+ - com/sun/star/lang/XMultiServiceFactory.hpp
+ - rtl/ustring.hxx
+ - cppuhelper/factory.hxx
+ dbaccess/inc/strings.hrc:
+ # Needed for TranslateId macro to work
+ - unotools/resmgr.hxx
+ dbaccess/source/filter/xml/xmlExport.hxx:
+ # Needed for implicit dtor
+ - xmloff/txtprmap.hxx
+ dbaccess/source/ui/dlg/odbcconfig.hxx:
+ # Needed on WIN32
+ - tools/link.hxx
+ dbaccess/source/ui/querydesign/QueryTabConnUndoAction.hxx:
+ # Needed for direct member access
+ - JoinTableView.hxx
+ dbaccess/source/core/api/CacheSet.cxx:
+ # Actually used
+ - com/sun/star/io/XInputStream.hpp
+ dbaccess/source/core/api/KeySet.cxx:
+ # Actually used
+ - com/sun/star/sdbc/XDatabaseMetaData.hpp
+ - com/sun/star/sdbc/XPreparedStatement.hpp
+ - com/sun/star/io/XInputStream.hpp
+ dbaccess/source/core/api/TableDeco.cxx:
+ # Actually used
+ - com/sun/star/sdbc/XConnection.hpp
+ dbaccess/source/core/api/query.cxx:
+ # Actually used
+ - com/sun/star/sdbc/XConnection.hpp
+ dbaccess/source/core/api/querycontainer.cxx:
+ # Actually used
+ - com/sun/star/sdbc/XConnection.hpp
+ dbaccess/source/core/dataaccess/databasedocument.cxx:
+ # Actually used
+ - com/sun/star/script/XStorageBasedLibraryContainer.hpp
+ - com/sun/star/io/XOutputStream.hpp
+ dbaccess/source/core/dataaccess/documentevents.cxx:
+ # Actually used
+ - com/sun/star/beans/PropertyValue.hpp
+ dbaccess/source/core/misc/DatabaseDataProvider.cxx:
+ # Needed for UnoType macro to work
+ - com/sun/star/task/XInteractionHandler.hpp
+ dbaccess/source/filter/hsqldb/parseschema.cxx:
+ # Actually used
+ - com/sun/star/embed/XStorage.hpp
+ dbaccess/source/filter/hsqldb/hsqlimport.cxx:
+ # Actually used
+ - com/sun/star/embed/XStorage.hpp
+ - com/sun/star/sdbc/XConnection.hpp
+ dbaccess/source/filter/hsqldb/rowinputbinary.cxx:
+ # Needed boost wrapper header
+ - boost/date_time/posix_time/posix_time.hpp
+ dbaccess/source/filter/xml/xmlDatabase.cxx:
+ # Needed for template
+ - com/sun/star/frame/XModel.hpp
+ dbaccess/source/filter/xml/xmlExport.cxx:
+ # Needed for template
+ - com/sun/star/frame/XModel.hpp
+ dbaccess/source/shared/flt_reghelper.cxx:
+ # Needed for weird included cxx file
+ - comphelper/sequence.hxx
+ dbaccess/source/shared/dbu_reghelper.cxx:
+ # Needed for weird included cxx file
+ - comphelper/sequence.hxx
+ dbaccess/source/ui/app/AppDetailPageHelper.cxx:
+ # Actually used
+ - com/sun/star/sdbc/XConnection.hpp
+ dbaccess/source/ui/app/DocumentInfoPreview.cxx:
+ # Needed for direct member access
+ - com/sun/star/document/XDocumentProperties.hpp
+ dbaccess/source/ui/browser/brwview.cxx:
+ # Needed for direct member access
+ - com/sun/star/awt/XControlContainer.hpp
+ dbaccess/source/ui/browser/genericcontroller.cxx:
+ # Actually used
+ - com/sun/star/sdbc/XDataSource.hpp
+ - com/sun/star/ui/XSidebarProvider.hpp
+ dbaccess/source/ui/browser/sbagrid.cxx:
+ # Actually used
+ - com/sun/star/form/XForm.hpp
+ dbaccess/source/ui/control/TableGrantCtrl.cxx:
+ # Actually used
+ - com/sun/star/sdbcx/XTablesSupplier.hpp
+ dbaccess/source/ui/control/RelationControl.cxx:
+ # Actually used
+ - com/sun/star/awt/XWindow.hpp
+ dbaccess/source/ui/control/sqledit.cxx:
+ # Needed for template
+ - com/sun/star/container/XHierarchicalNameAccess.hpp
+ dbaccess/source/ui/dlg/ConnectionHelper.cxx:
+ # Actually used
+ - com/sun/star/awt/XSystemDependentWindowPeer.hpp
+ - com/sun/star/lang/SystemDependent.hpp
+ dbaccess/source/ui/dlg/DbAdminImpl.cxx:
+ # Actually used
+ - com/sun/star/sdbc/XDriver.hpp
+ dbaccess/source/ui/dlg/UserAdmin.cxx:
+ # Needed for template
+ - com/sun/star/sdbc/XDriver.hpp
+ dbaccess/source/ui/dlg/dbfindex.cxx:
+ # Keep for osl_getThreadTextEncoding
+ - osl/thread.hxx
+ dbaccess/source/ui/dlg/odbcconfig.cxx:
+ # Needed for HAVE_ODBC_ADMINISTRATION on WIN32
+ - config_folders.h
+ - rtl/bootstrap.hxx
+ - osl/process.h
+ - osl/thread.hxx
+ - vcl/svapp.hxx
+ # Needed for platform-specific odbc headers
+ - connectivity/odbc.hxx
+ dbaccess/source/ui/dlg/queryfilter.cxx:
+ # Actually used
+ - com/sun/star/sdb/XSingleSelectQueryComposer.hpp
+ - com/sun/star/container/XNameAccess.hpp
+ - com/sun/star/sdbc/XConnection.hpp
+ dbaccess/source/ui/misc/DExport.cxx:
+ # Actually used
+ - com/sun/star/awt/FontDescriptor.hpp
+ - com/sun/star/uno/XComponentContext.hpp
+ dbaccess/source/ui/misc/UITools.cxx:
+ # Actually used
+ - com/sun/star/container/XHierarchicalNameContainer.hpp
+ dbaccess/source/ui/misc/indexcollection.cxx:
+ # Actually used
+ - com/sun/star/beans/XPropertySet.hpp
+ dbaccess/source/ui/querydesign/QTableWindow.cxx:
+ # Actually used
+ - com/sun/star/beans/XPropertySet.hpp
+ dbaccess/source/ui/querydesign/JoinTableView.cxx:
+ # Actually used
+ - com/sun/star/accessibility/XAccessible.hpp
+ dbaccess/source/ui/querydesign/TableWindow.cxx:
+ # Actually used
+ - com/sun/star/container/XNameAccess.hpp
+ dbaccess/source/ui/querydesign/limitboxcontroller.cxx:
+ # Actually used
+ - com/sun/star/beans/PropertyValue.hpp
+ dbaccess/source/ui/querydesign/SelectionBrowseBox.cxx:
+ # Actually used
+ - com/sun/star/sdbc/XDatabaseMetaData.hpp
+ dbaccess/source/ui/tabledesign/TableFieldControl.cxx:
+ # Actually used
+ - com/sun/star/sdbc/XDatabaseMetaData.hpp
+ dbaccess/source/ui/uno/composerdialogs.cxx:
+ # Actually used
+ - com/sun/star/awt/XWindow.hpp
+ dbaccess/source/ui/uno/unoDirectSql.cxx:
+ # Actually used
+ - com/sun/star/connection/XConnection.hpp
diff --git a/dbaccess/JunitTest_dbaccess_complex.mk b/dbaccess/JunitTest_dbaccess_complex.mk
new file mode 100644
index 000000000..ba333cbf3
--- /dev/null
+++ b/dbaccess/JunitTest_dbaccess_complex.mk
@@ -0,0 +1,51 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+$(eval $(call gb_JunitTest_JunitTest,dbaccess_complex))
+
+$(eval $(call gb_JunitTest_use_unoapi_jars,dbaccess_complex))
+
+$(eval $(call gb_JunitTest_use_jars,dbaccess_complex,\
+ ConnectivityTools \
+ juh \
+))
+
+$(eval $(call gb_JunitTest_set_defs,dbaccess_complex,\
+ $$(DEFS) \
+ -Dorg.openoffice.test.arg.tdoc=$(SRCDIR)/dbaccess/qa/dbaccess \
+))
+
+$(eval $(call gb_JunitTest_add_classes,dbaccess_complex,\
+ complex.dbaccess.Beamer \
+ complex.dbaccess.PropertyBag \
+ complex.dbaccess.RowSet \
+))
+
+$(eval $(call gb_JunitTest_add_sourcefiles,dbaccess_complex,\
+ dbaccess/qa/complex/dbaccess/ApplicationController \
+ dbaccess/qa/complex/dbaccess/Beamer \
+ dbaccess/qa/complex/dbaccess/CRMBasedTestCase \
+ dbaccess/qa/complex/dbaccess/CopyTableInterActionHandler \
+ dbaccess/qa/complex/dbaccess/CopyTableWizard \
+ dbaccess/qa/complex/dbaccess/DataSource \
+ dbaccess/qa/complex/dbaccess/DatabaseApplication \
+ dbaccess/qa/complex/dbaccess/DatabaseDocument \
+ dbaccess/qa/complex/dbaccess/FileHelper \
+ dbaccess/qa/complex/dbaccess/Parser \
+ dbaccess/qa/complex/dbaccess/PropertyBag \
+ dbaccess/qa/complex/dbaccess/Query \
+ dbaccess/qa/complex/dbaccess/QueryInQuery \
+ dbaccess/qa/complex/dbaccess/RowSet \
+ dbaccess/qa/complex/dbaccess/RowSetEventListener \
+ dbaccess/qa/complex/dbaccess/SingleSelectQueryComposer \
+ dbaccess/qa/complex/dbaccess/TestCase \
+ dbaccess/qa/complex/dbaccess/UISettings \
+))
+
+# vim: set noet sw=4 ts=4:
diff --git a/dbaccess/JunitTest_dbaccess_unoapi.mk b/dbaccess/JunitTest_dbaccess_unoapi.mk
new file mode 100644
index 000000000..814cbbcdc
--- /dev/null
+++ b/dbaccess/JunitTest_dbaccess_unoapi.mk
@@ -0,0 +1,14 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+$(eval $(call gb_JunitTest_JunitTest,dbaccess_unoapi))
+
+$(eval $(call gb_JunitTest_set_unoapi_test_defaults,dbaccess_unoapi))
+
+# vim: set noet sw=4 ts=4:
diff --git a/dbaccess/Library_dba.mk b/dbaccess/Library_dba.mk
new file mode 100644
index 000000000..2021bb22a
--- /dev/null
+++ b/dbaccess/Library_dba.mk
@@ -0,0 +1,138 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+$(eval $(call gb_Library_Library,dba))
+
+$(eval $(call gb_Library_set_include,dba,\
+ $$(INCLUDE) \
+ -I$(SRCDIR)/dbaccess/inc \
+ -I$(SRCDIR)/dbaccess/source/inc \
+ -I$(SRCDIR)/dbaccess/source/core/inc \
+ -I$(SRCDIR)/dbaccess/source/filter/hsqldb \
+ -I$(WORKDIR)/YaccTarget/connectivity/source/parse \
+))
+
+$(eval $(call gb_Library_set_precompiled_header,dba,dbaccess/inc/pch/precompiled_dba))
+
+$(eval $(call gb_Library_use_custom_headers,dba,\
+ officecfg/registry \
+))
+
+$(eval $(call gb_Library_add_defs,dba,\
+ -DOOO_DLLIMPLEMENTATION_DBA \
+))
+
+$(eval $(call gb_Library_use_external,dba,boost_headers))
+
+$(eval $(call gb_Library_use_sdk_api,dba))
+
+$(eval $(call gb_Library_use_libraries,dba,\
+ comphelper \
+ cppu \
+ cppuhelper \
+ dbahsql \
+ dbtools \
+ fwk \
+ i18nlangtag \
+ sal \
+ salhelper \
+ sax \
+ sb \
+ sfx \
+ svl \
+ svt \
+ svxcore \
+ tl \
+ ucbhelper \
+ utl \
+ vcl \
+ xo \
+))
+
+$(eval $(call gb_Library_set_componentfile,dba,dbaccess/util/dba,services))
+
+$(eval $(call gb_Library_add_exception_objects,dba,\
+ dbaccess/source/core/api/BookmarkSet \
+ dbaccess/source/core/api/CacheSet \
+ dbaccess/source/core/api/callablestatement \
+ dbaccess/source/core/api/CIndexes \
+ dbaccess/source/core/api/column \
+ dbaccess/source/core/api/columnsettings \
+ dbaccess/source/core/api/CRowSetColumn \
+ dbaccess/source/core/api/CRowSetDataColumn \
+ dbaccess/source/core/api/datacolumn \
+ dbaccess/source/core/api/datasettings \
+ dbaccess/source/core/api/definitioncolumn \
+ dbaccess/source/core/api/FilteredContainer \
+ dbaccess/source/core/api/HelperCollections \
+ dbaccess/source/core/api/KeySet \
+ dbaccess/source/core/api/OptimisticSet \
+ dbaccess/source/core/api/preparedstatement \
+ dbaccess/source/core/api/PrivateRow \
+ dbaccess/source/core/api/query \
+ dbaccess/source/core/api/querycomposer \
+ dbaccess/source/core/api/querycontainer \
+ dbaccess/source/core/api/querydescriptor \
+ dbaccess/source/core/api/resultcolumn \
+ dbaccess/source/core/api/resultset \
+ dbaccess/source/core/api/RowSet \
+ dbaccess/source/core/api/RowSetBase \
+ dbaccess/source/core/api/RowSetCache \
+ dbaccess/source/core/api/RowSetCacheIterator \
+ dbaccess/source/core/api/SingleSelectQueryComposer \
+ dbaccess/source/core/api/statement \
+ dbaccess/source/core/api/StaticSet \
+ dbaccess/source/core/api/table \
+ dbaccess/source/core/api/tablecontainer \
+ dbaccess/source/core/api/TableDeco \
+ dbaccess/source/core/api/View \
+ dbaccess/source/core/api/viewcontainer \
+ dbaccess/source/core/api/WrappedResultSet \
+ dbaccess/source/core/dataaccess/bookmarkcontainer \
+ dbaccess/source/core/dataaccess/commandcontainer \
+ dbaccess/source/core/dataaccess/commanddefinition \
+ dbaccess/source/core/dataaccess/ComponentDefinition \
+ dbaccess/source/core/dataaccess/connection \
+ dbaccess/source/core/dataaccess/ContentHelper \
+ dbaccess/source/core/dataaccess/dataaccessdescriptor \
+ dbaccess/source/core/dataaccess/databasecontext \
+ dbaccess/source/core/dataaccess/databasedocument \
+ dbaccess/source/core/dataaccess/databaseregistrations \
+ dbaccess/source/core/dataaccess/datasource \
+ dbaccess/source/core/dataaccess/definitioncontainer \
+ dbaccess/source/core/dataaccess/documentcontainer \
+ dbaccess/source/core/dataaccess/documentdefinition \
+ dbaccess/source/core/dataaccess/documenteventexecutor \
+ dbaccess/source/core/dataaccess/documenteventnotifier \
+ dbaccess/source/core/dataaccess/documentevents \
+ dbaccess/source/core/dataaccess/intercept \
+ dbaccess/source/core/dataaccess/ModelImpl \
+ dbaccess/source/core/dataaccess/myucp_datasupplier \
+ dbaccess/source/core/dataaccess/myucp_resultset \
+ dbaccess/source/core/dataaccess/SharedConnection \
+ dbaccess/source/core/misc/apitools \
+ dbaccess/source/core/misc/ContainerMediator \
+ dbaccess/source/core/misc/DatabaseDataProvider \
+ dbaccess/source/core/misc/dsntypes \
+ dbaccess/source/core/misc/objectnameapproval \
+ dbaccess/source/core/misc/migrwarndlg \
+ dbaccess/source/core/misc/PropertyForward \
+ dbaccess/source/core/misc/sdbcoretools \
+ dbaccess/source/core/misc/veto \
+ dbaccess/source/core/recovery/dbdocrecovery \
+ dbaccess/source/core/recovery/settingsimport \
+ dbaccess/source/core/recovery/storagestream \
+ dbaccess/source/core/recovery/storagetextstream \
+ dbaccess/source/core/recovery/storagexmlstream \
+ dbaccess/source/core/recovery/subcomponentloader \
+ dbaccess/source/core/recovery/subcomponentrecovery \
+ dbaccess/source/core/resource/core_resource \
+))
+
+# vim: set noet sw=4 ts=4:
diff --git a/dbaccess/Library_dbahsql.mk b/dbaccess/Library_dbahsql.mk
new file mode 100644
index 000000000..7929e9bd6
--- /dev/null
+++ b/dbaccess/Library_dbahsql.mk
@@ -0,0 +1,51 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+$(eval $(call gb_Library_Library,dbahsql))
+
+$(eval $(call gb_Library_set_include,dbahsql,\
+ $$(INCLUDE) \
+ -I$(WORKDIR)/YaccTarget/connectivity/source/parse \
+))
+
+$(eval $(call gb_Library_use_externals,dbahsql,\
+ boost_headers \
+ boost_date_time \
+))
+
+$(eval $(call gb_Library_set_precompiled_header,dbahsql,dbaccess/inc/pch/precompiled_dbahsql))
+
+$(eval $(call gb_Library_use_sdk_api,dbahsql))
+
+$(eval $(call gb_Library_use_libraries,dbahsql,\
+ comphelper \
+ cppu \
+ cppuhelper \
+ sal \
+ salhelper \
+ dbtools \
+ ucbhelper \
+ utl \
+ tl \
+))
+
+$(eval $(call gb_Library_add_exception_objects,dbahsql,\
+ dbaccess/source/filter/hsqldb/hsqlimport \
+ dbaccess/source/filter/hsqldb/parseschema \
+ dbaccess/source/filter/hsqldb/alterparser \
+ dbaccess/source/filter/hsqldb/createparser \
+ dbaccess/source/filter/hsqldb/columndef \
+ dbaccess/source/filter/hsqldb/fbalterparser \
+ dbaccess/source/filter/hsqldb/fbcreateparser \
+ dbaccess/source/filter/hsqldb/rowinputbinary \
+ dbaccess/source/filter/hsqldb/hsqlbinarynode \
+ dbaccess/source/filter/hsqldb/utils \
+))
+
+# vim: set noet sw=4 ts=4:
diff --git a/dbaccess/Library_dbaxml.mk b/dbaccess/Library_dbaxml.mk
new file mode 100644
index 000000000..502c4058d
--- /dev/null
+++ b/dbaccess/Library_dbaxml.mk
@@ -0,0 +1,72 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+$(eval $(call gb_Library_Library,dbaxml))
+
+$(eval $(call gb_Library_set_include,dbaxml,\
+ $$(INCLUDE) \
+ -I$(SRCDIR)/dbaccess/inc \
+ -I$(SRCDIR)/dbaccess/source/inc \
+))
+
+$(eval $(call gb_Library_use_external,dbaxml,boost_headers))
+
+$(eval $(call gb_Library_set_precompiled_header,dbaxml,dbaccess/inc/pch/precompiled_dbaxml))
+
+$(eval $(call gb_Library_use_sdk_api,dbaxml))
+
+$(eval $(call gb_Library_use_libraries,dbaxml,\
+ comphelper \
+ cppu \
+ cppuhelper \
+ dba \
+ dbtools \
+ sal \
+ salhelper \
+ sax \
+ sfx \
+ svl \
+ tk \
+ tl \
+ utl \
+ vcl \
+ xo \
+))
+
+$(eval $(call gb_Library_set_componentfile,dbaxml,dbaccess/source/filter/xml/dbaxml,services))
+
+$(eval $(call gb_Library_add_exception_objects,dbaxml,\
+ dbaccess/source/filter/xml/dbloader2 \
+ dbaccess/source/filter/xml/xmlAutoStyle \
+ dbaccess/source/filter/xml/xmlColumn \
+ dbaccess/source/filter/xml/xmlComponent \
+ dbaccess/source/filter/xml/xmlConnectionData \
+ dbaccess/source/filter/xml/xmlConnectionResource \
+ dbaccess/source/filter/xml/xmlDatabase \
+ dbaccess/source/filter/xml/xmlDatabaseDescription \
+ dbaccess/source/filter/xml/xmlDataSource \
+ dbaccess/source/filter/xml/xmlDataSourceInfo \
+ dbaccess/source/filter/xml/xmlDataSourceSetting \
+ dbaccess/source/filter/xml/xmlDataSourceSettings \
+ dbaccess/source/filter/xml/xmlDocuments \
+ dbaccess/source/filter/xml/xmlExport \
+ dbaccess/source/filter/xml/xmlFileBasedDatabase \
+ dbaccess/source/filter/xml/xmlfilter \
+ dbaccess/source/filter/xml/xmlHelper \
+ dbaccess/source/filter/xml/xmlHierarchyCollection \
+ dbaccess/source/filter/xml/xmlLogin \
+ dbaccess/source/filter/xml/xmlQuery \
+ dbaccess/source/filter/xml/xmlServerDatabase \
+ dbaccess/source/filter/xml/xmlStyleImport \
+ dbaccess/source/filter/xml/xmlTable \
+ dbaccess/source/filter/xml/xmlTableFilterList \
+ dbaccess/source/filter/xml/xmlTableFilterPattern \
+))
+
+# vim: set noet sw=4 ts=4:
diff --git a/dbaccess/Library_dbu.mk b/dbaccess/Library_dbu.mk
new file mode 100644
index 000000000..1157c6ffa
--- /dev/null
+++ b/dbaccess/Library_dbu.mk
@@ -0,0 +1,252 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+$(eval $(call gb_Library_Library,dbu))
+
+$(eval $(call gb_Library_set_include,dbu,\
+ $$(INCLUDE) \
+ -I$(SRCDIR)/dbaccess/inc \
+ -I$(SRCDIR)/dbaccess/source/inc \
+ -I$(SRCDIR)/dbaccess/source/ui/inc \
+ -I$(WORKDIR)/YaccTarget/connectivity/source/parse \
+))
+
+$(eval $(call gb_Library_set_precompiled_header,dbu,dbaccess/inc/pch/precompiled_dbu))
+
+$(eval $(call gb_Library_use_custom_headers,dbu,\
+ officecfg/registry \
+))
+
+$(eval $(call gb_Library_use_sdk_api,dbu))
+
+$(eval $(call gb_Library_add_defs,dbu,\
+ -DDBACCESS_DLLIMPLEMENTATION \
+))
+
+$(eval $(call gb_Library_use_externals,dbu,\
+ boost_headers \
+ odbc_headers \
+))
+
+$(eval $(call gb_Library_use_libraries,dbu,\
+ comphelper \
+ cppu \
+ cppuhelper \
+ dba \
+ dbtools \
+ editeng \
+ fwk \
+ sal \
+ salhelper \
+ i18nlangtag \
+ sfx \
+ sot \
+ svl \
+ svt \
+ svxcore \
+ svx \
+ tk \
+ tl \
+ ucbhelper \
+ utl \
+ vcl \
+))
+
+ifeq ($(OS),WNT)
+$(eval $(call gb_Library_use_system_win32_libs,dbu,\
+ ole32 \
+ oleaut32 \
+ uuid \
+))
+endif
+
+$(eval $(call gb_Library_set_componentfile,dbu,dbaccess/util/dbu,services))
+
+$(eval $(call gb_Library_add_exception_objects,dbu,\
+ dbaccess/source/ui/app/AppController \
+ dbaccess/source/ui/app/AppControllerDnD \
+ dbaccess/source/ui/app/AppControllerGen \
+ dbaccess/source/ui/app/AppDetailPageHelper \
+ dbaccess/source/ui/app/AppDetailView \
+ dbaccess/source/ui/app/AppIconControl \
+ dbaccess/source/ui/app/AppSwapWindow \
+ dbaccess/source/ui/app/AppTitleWindow \
+ dbaccess/source/ui/app/AppView \
+ dbaccess/source/ui/app/ChildWindow \
+ dbaccess/source/ui/app/DocumentInfoPreview \
+ dbaccess/source/ui/app/subcomponentmanager \
+ dbaccess/source/ui/app/templwin \
+ dbaccess/source/ui/browser/AsynchronousLink \
+ dbaccess/source/ui/browser/brwctrlr \
+ dbaccess/source/ui/browser/brwview \
+ dbaccess/source/ui/browser/dataview \
+ dbaccess/source/ui/browser/dbexchange \
+ dbaccess/source/ui/browser/dbloader \
+ dbaccess/source/ui/browser/dbtreemodel \
+ dbaccess/source/ui/browser/dsbrowserDnD \
+ dbaccess/source/ui/browser/dsEntriesNoExp \
+ dbaccess/source/ui/browser/exsrcbrw \
+ dbaccess/source/ui/browser/formadapter \
+ dbaccess/source/ui/browser/genericcontroller \
+ dbaccess/source/ui/browser/sbagrid \
+ dbaccess/source/ui/browser/sbamultiplex \
+ dbaccess/source/ui/browser/unodatbr \
+ dbaccess/source/ui/control/charsetlistbox \
+ dbaccess/source/ui/control/ColumnControlWindow \
+ dbaccess/source/ui/control/curledit \
+ dbaccess/source/ui/control/dbtreelistbox \
+ dbaccess/source/ui/control/FieldControls \
+ dbaccess/source/ui/control/FieldDescControl \
+ dbaccess/source/ui/control/opendoccontrols \
+ dbaccess/source/ui/control/RelationControl \
+ dbaccess/source/ui/control/sqledit \
+ dbaccess/source/ui/control/SqlNameEdit \
+ dbaccess/source/ui/control/TableGrantCtrl \
+ dbaccess/source/ui/control/tabletree \
+ dbaccess/source/ui/control/undosqledit \
+ dbaccess/source/ui/dlg/admincontrols \
+ dbaccess/source/ui/dlg/adminpages \
+ dbaccess/source/ui/dlg/adtabdlg \
+ dbaccess/source/ui/dlg/advancedsettings \
+ dbaccess/source/ui/dlg/CollectionView \
+ dbaccess/source/ui/dlg/ConnectionHelper \
+ dbaccess/source/ui/dlg/ConnectionPage \
+ dbaccess/source/ui/dlg/ConnectionPageSetup \
+ dbaccess/source/ui/dlg/dbadmin \
+ dbaccess/source/ui/dlg/DbAdminImpl \
+ dbaccess/source/ui/dlg/dbfindex \
+ dbaccess/source/ui/dlg/DBSetupConnectionPages \
+ dbaccess/source/ui/dlg/dbwiz \
+ dbaccess/source/ui/dlg/dbwizsetup \
+ dbaccess/source/ui/dlg/detailpages \
+ dbaccess/source/ui/dlg/directsql \
+ dbaccess/source/ui/dlg/dlgattr \
+ dbaccess/source/ui/dlg/dlgsave \
+ dbaccess/source/ui/dlg/dlgsize \
+ dbaccess/source/ui/dlg/dsselect \
+ dbaccess/source/ui/dlg/finteraction \
+ dbaccess/source/ui/dlg/generalpage \
+ dbaccess/source/ui/dlg/indexdialog \
+ dbaccess/source/ui/dlg/indexfieldscontrol \
+ dbaccess/source/ui/dlg/odbcconfig \
+ dbaccess/source/ui/dlg/optionalboolitem \
+ dbaccess/source/ui/dlg/paramdialog \
+ dbaccess/source/ui/dlg/queryfilter \
+ dbaccess/source/ui/dlg/queryorder \
+ dbaccess/source/ui/dlg/QueryPropertiesDialog \
+ dbaccess/source/ui/dlg/RelationDlg \
+ dbaccess/source/ui/dlg/sqlmessage \
+ dbaccess/source/ui/dlg/tablespage \
+ dbaccess/source/ui/dlg/TablesSingleDlg \
+ dbaccess/source/ui/dlg/TextConnectionHelper \
+ dbaccess/source/ui/dlg/textconnectionsettings \
+ dbaccess/source/ui/dlg/UserAdmin \
+ dbaccess/source/ui/dlg/UserAdminDlg \
+ dbaccess/source/ui/misc/asyncmodaldialog \
+ dbaccess/source/ui/misc/charsets \
+ dbaccess/source/ui/misc/controllerframe \
+ dbaccess/source/ui/misc/databaseobjectview \
+ dbaccess/source/ui/misc/datasourceconnector \
+ dbaccess/source/ui/misc/dbaundomanager \
+ dbaccess/source/ui/misc/dbsubcomponentcontroller \
+ dbaccess/source/ui/misc/defaultobjectnamecheck \
+ dbaccess/source/ui/misc/DExport \
+ dbaccess/source/ui/misc/dsmeta \
+ dbaccess/source/ui/misc/HtmlReader \
+ dbaccess/source/ui/misc/imageprovider \
+ dbaccess/source/ui/misc/indexcollection \
+ dbaccess/source/ui/misc/linkeddocuments \
+ dbaccess/source/ui/misc/propertystorage \
+ dbaccess/source/ui/misc/RowSetDrop \
+ dbaccess/source/ui/misc/RtfReader \
+ dbaccess/source/ui/misc/singledoccontroller \
+ dbaccess/source/ui/misc/stringlistitem \
+ dbaccess/source/ui/misc/TableCopyHelper \
+ dbaccess/source/ui/misc/TokenWriter \
+ dbaccess/source/ui/misc/UITools \
+ dbaccess/source/ui/misc/WColumnSelect \
+ dbaccess/source/ui/misc/WCopyTable \
+ dbaccess/source/ui/misc/WCPage \
+ dbaccess/source/ui/misc/WExtendPages \
+ dbaccess/source/ui/misc/WNameMatch \
+ dbaccess/source/ui/misc/WTypeSelect \
+ dbaccess/source/ui/querydesign/ConnectionLine \
+ dbaccess/source/ui/querydesign/ConnectionLineAccess \
+ dbaccess/source/ui/querydesign/ConnectionLineData \
+ dbaccess/source/ui/querydesign/JAccess \
+ dbaccess/source/ui/querydesign/JoinController \
+ dbaccess/source/ui/querydesign/JoinDesignView \
+ dbaccess/source/ui/querydesign/JoinExchange \
+ dbaccess/source/ui/querydesign/JoinTableView \
+ dbaccess/source/ui/querydesign/limitboxcontroller \
+ dbaccess/source/ui/querydesign/QTableConnection \
+ dbaccess/source/ui/querydesign/QTableConnectionData \
+ dbaccess/source/ui/querydesign/QTableWindow \
+ dbaccess/source/ui/querydesign/QTableWindowData \
+ dbaccess/source/ui/querydesign/querycontainerwindow \
+ dbaccess/source/ui/querydesign/querycontroller \
+ dbaccess/source/ui/querydesign/QueryDesignView \
+ dbaccess/source/ui/querydesign/querydlg \
+ dbaccess/source/ui/querydesign/QueryMoveTabWinUndoAct \
+ dbaccess/source/ui/querydesign/QueryTabConnUndoAction \
+ dbaccess/source/ui/querydesign/QueryTableView \
+ dbaccess/source/ui/querydesign/QueryTabWinUndoAct \
+ dbaccess/source/ui/querydesign/QueryTextView \
+ dbaccess/source/ui/querydesign/QueryViewSwitch \
+ dbaccess/source/ui/querydesign/SelectionBrowseBox \
+ dbaccess/source/ui/querydesign/TableConnection \
+ dbaccess/source/ui/querydesign/TableConnectionData \
+ dbaccess/source/ui/querydesign/TableFieldDescription \
+ dbaccess/source/ui/querydesign/TableFieldInfo \
+ dbaccess/source/ui/querydesign/TableWindow \
+ dbaccess/source/ui/querydesign/TableWindowAccess \
+ dbaccess/source/ui/querydesign/TableWindowData \
+ dbaccess/source/ui/querydesign/TableWindowListBox \
+ dbaccess/source/ui/querydesign/TableWindowTitle \
+ dbaccess/source/ui/relationdesign/RelationController \
+ dbaccess/source/ui/relationdesign/RelationDesignView \
+ dbaccess/source/ui/relationdesign/RelationTableView \
+ dbaccess/source/ui/relationdesign/RTableConnection \
+ dbaccess/source/ui/relationdesign/RTableConnectionData \
+ dbaccess/source/ui/tabledesign/FieldDescriptions \
+ dbaccess/source/ui/tabledesign/TableController \
+ dbaccess/source/ui/tabledesign/TableDesignControl \
+ dbaccess/source/ui/tabledesign/TableDesignHelpBar \
+ dbaccess/source/ui/tabledesign/TableDesignView \
+ dbaccess/source/ui/tabledesign/TableFieldControl \
+ dbaccess/source/ui/tabledesign/TableFieldDescWin \
+ dbaccess/source/ui/tabledesign/TableRow \
+ dbaccess/source/ui/tabledesign/TableRowExchange \
+ dbaccess/source/ui/tabledesign/TableUndo \
+ dbaccess/source/ui/tabledesign/TEditControl \
+ dbaccess/source/ui/uno/admindlg \
+ dbaccess/source/ui/uno/AdvancedSettingsDlg \
+ dbaccess/source/ui/uno/ColumnControl \
+ dbaccess/source/ui/uno/ColumnModel \
+ dbaccess/source/ui/uno/ColumnPeer \
+ dbaccess/source/ui/uno/composerdialogs \
+ dbaccess/source/ui/uno/copytablewizard \
+ dbaccess/source/ui/uno/dbinteraction \
+ dbaccess/source/ui/uno/DBTypeWizDlg \
+ dbaccess/source/ui/uno/DBTypeWizDlgSetup \
+ dbaccess/source/ui/uno/TableFilterDlg \
+ dbaccess/source/ui/uno/textconnectionsettings_uno \
+ dbaccess/source/ui/uno/unoadmin \
+ dbaccess/source/ui/uno/unoDirectSql \
+ dbaccess/source/ui/uno/unosqlmessage \
+ dbaccess/source/ui/uno/UserSettingsDlg \
+))
+
+ifeq ($(OS),WNT)
+$(eval $(call gb_Library_add_exception_objects,dbu,\
+ dbaccess/source/ui/dlg/adodatalinks \
+))
+endif
+
+# vim: set noet sw=4 ts=4:
diff --git a/dbaccess/Library_sdbt.mk b/dbaccess/Library_sdbt.mk
new file mode 100644
index 000000000..c6109b6e6
--- /dev/null
+++ b/dbaccess/Library_sdbt.mk
@@ -0,0 +1,46 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+$(eval $(call gb_Library_Library,sdbt))
+
+$(eval $(call gb_Library_set_include,sdbt,\
+ $$(INCLUDE) \
+ -I$(SRCDIR)/dbaccess/inc/ \
+ -I$(SRCDIR)/dbaccess/source/inc/ \
+ -I$(SRCDIR)/dbaccess/source/sdbtools/inc \
+))
+
+$(eval $(call gb_Library_use_external,sdbt,boost_headers))
+
+$(eval $(call gb_Library_set_precompiled_header,sdbt,dbaccess/inc/pch/precompiled_sdbt))
+
+$(eval $(call gb_Library_use_sdk_api,sdbt))
+
+$(eval $(call gb_Library_use_libraries,sdbt,\
+ comphelper \
+ cppu \
+ cppuhelper \
+ dba \
+ dbtools \
+ sal \
+ salhelper \
+ tl \
+ utl \
+))
+
+$(eval $(call gb_Library_set_componentfile,sdbt,dbaccess/util/sdbt,services))
+
+$(eval $(call gb_Library_add_exception_objects,sdbt,\
+ dbaccess/source/sdbtools/connection/connectiontools \
+ dbaccess/source/sdbtools/connection/datasourcemetadata \
+ dbaccess/source/sdbtools/connection/objectnames \
+ dbaccess/source/sdbtools/connection/tablename \
+))
+
+# vim: set noet sw=4 ts=4:
diff --git a/dbaccess/Makefile b/dbaccess/Makefile
new file mode 100644
index 000000000..0997e6284
--- /dev/null
+++ b/dbaccess/Makefile
@@ -0,0 +1,14 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+module_directory:=$(dir $(realpath $(firstword $(MAKEFILE_LIST))))
+
+include $(module_directory)/../solenv/gbuild/partial_build.mk
+
+# vim: set noet sw=4 ts=4:
diff --git a/dbaccess/Module_dbaccess.mk b/dbaccess/Module_dbaccess.mk
new file mode 100644
index 000000000..436f591c7
--- /dev/null
+++ b/dbaccess/Module_dbaccess.mk
@@ -0,0 +1,99 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+$(eval $(call gb_Module_Module,dbaccess))
+
+$(eval $(call gb_Module_add_targets,dbaccess,\
+ Library_dba \
+ Library_dbahsql \
+))
+
+$(eval $(call gb_Module_add_l10n_targets,dbaccess,\
+ AllLangMoTarget_dba \
+))
+
+ifneq (,$(filter DBCONNECTIVITY,$(BUILD_TYPE)))
+
+$(eval $(call gb_Module_add_targets,dbaccess,\
+ $(if $(filter WNT,$(OS)),Executable_odbcconfig) \
+ Library_dbaxml \
+ Library_dbu \
+ Library_sdbt \
+ UIConfig_dbaccess \
+ UIConfig_dbapp \
+ UIConfig_dbbrowser \
+ UIConfig_dbquery \
+ UIConfig_dbrelation \
+ UIConfig_dbtable \
+ UIConfig_dbtdata \
+))
+
+ifneq ($(OS),iOS)
+ifeq ($(ENABLE_FIREBIRD_SDBC),TRUE)
+$(eval $(call gb_Module_add_check_targets,dbaccess,\
+ $(if $(ENABLE_JAVA),CppunitTest_dbaccess_hsqlbinary_import) \
+ $(if $(ENABLE_JAVA),CppunitTest_dbaccess_tdf119625) \
+ $(if $(ENABLE_JAVA),CppunitTest_dbaccess_tdf126268) \
+))
+
+$(eval $(call gb_Module_add_check_targets,dbaccess,\
+ CppunitTest_dbaccess_firebird_test \
+))
+endif
+
+ifneq ($(filter SCRIPTING,$(BUILD_TYPE)),)
+$(eval $(call gb_Module_add_check_targets,dbaccess,\
+ CppunitTest_dbaccess_dialog_save \
+ CppunitTest_dbaccess_empty_stdlib_save \
+ CppunitTest_dbaccess_nolib_save \
+ CppunitTest_dbaccess_macros_test \
+ CppunitTest_dbaccess_hsqlschema_import \
+))
+endif
+
+# this test fails 50% of the time on the mac jenkins buildbots
+ifeq ($(ENABLE_JAVA),TRUE)
+ifneq ($(OS),MACOSX)
+$(eval $(call gb_Module_add_check_targets,dbaccess,\
+ CppunitTest_dbaccess_hsqldb_test \
+ CppunitTest_dbaccess_RowSetClones \
+))
+endif
+endif
+
+# This runs a suite of performance tests on embedded firebird and HSQLDB.
+# Instructions on running the test can be found in qa/unit/embeddedb_performancetest
+ifeq ($(ENABLE_FIREBIRD_SDBC),TRUE)
+ifeq ($(ENABLE_JAVA),TRUE)
+$(eval $(call gb_Module_add_check_targets,dbaccess,\
+ CppunitTest_dbaccess_embeddeddb_performancetest \
+))
+endif
+endif
+
+$(eval $(call gb_Module_add_subsequentcheck_targets,dbaccess,\
+ JunitTest_dbaccess_complex \
+ JunitTest_dbaccess_unoapi \
+))
+
+ifneq ($(ENABLE_JAVA),)
+$(eval $(call gb_Module_add_subsequentcheck_targets,dbaccess,\
+ PythonTest_dbaccess_python \
+))
+endif
+
+# screenshots
+$(eval $(call gb_Module_add_screenshot_targets,dbaccess,\
+ CppunitTest_dbaccess_dialogs_test \
+))
+
+endif
+endif
+
+# vim: set noet sw=4 ts=4:
diff --git a/dbaccess/PythonTest_dbaccess_python.mk b/dbaccess/PythonTest_dbaccess_python.mk
new file mode 100644
index 000000000..874dac927
--- /dev/null
+++ b/dbaccess/PythonTest_dbaccess_python.mk
@@ -0,0 +1,26 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+$(eval $(call gb_PythonTest_PythonTest,dbaccess_python))
+
+$(eval $(call gb_PythonTest_set_defs,dbaccess_python,\
+ TDOC="$(SRCDIR)/dbaccess/qa/extras/testdocuments" \
+))
+
+$(eval $(call gb_PythonTest_add_modules,dbaccess_python,$(SRCDIR)/dbaccess/qa/python,\
+ fdo84315 \
+))
+
+$(call gb_PythonTest_get_target,dbaccess_python) : $(WORKDIR)/CppunitTest/fdo84315.odb
+$(WORKDIR)/CppunitTest/fdo84315.odb : $(SRCDIR)/dbaccess/qa/extras/testdocuments/fdo84315.odb
+ mkdir -p $(dir $@)
+ cp -P -f "$<" "$@"
+.PHONY: $(WORKDIR)/CppunitTest/fdo84315.odb
+
+# vim: set noet sw=4 ts=4:
diff --git a/dbaccess/README.md b/dbaccess/README.md
new file mode 100644
index 000000000..8bcd4dd25
--- /dev/null
+++ b/dbaccess/README.md
@@ -0,0 +1,5 @@
+# Database Access Tools for LibreOffice Base DB Apps
+
+Database access tools, for `base` database application
+
+Builds on top of drivers in `connectivity`.
diff --git a/dbaccess/UIConfig_dbaccess.mk b/dbaccess/UIConfig_dbaccess.mk
new file mode 100644
index 000000000..c0e6a28f8
--- /dev/null
+++ b/dbaccess/UIConfig_dbaccess.mk
@@ -0,0 +1,96 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+$(eval $(call gb_UIConfig_UIConfig,dbaccess))
+
+$(eval $(call gb_UIConfig_add_uifiles,dbaccess, \
+ dbaccess/uiconfig/ui/admindialog \
+ dbaccess/uiconfig/ui/advancedsettingsdialog \
+ dbaccess/uiconfig/ui/appborderwindow \
+ dbaccess/uiconfig/ui/appdetailwindow \
+ dbaccess/uiconfig/ui/applycolpage \
+ dbaccess/uiconfig/ui/appswapwindow \
+ dbaccess/uiconfig/ui/authentificationpage \
+ dbaccess/uiconfig/ui/autocharsetpage \
+ dbaccess/uiconfig/ui/choosedatasourcedialog \
+ dbaccess/uiconfig/ui/colcontrolbox \
+ dbaccess/uiconfig/ui/collectionviewdialog \
+ dbaccess/uiconfig/ui/colwidthdialog \
+ dbaccess/uiconfig/ui/connectionpage \
+ dbaccess/uiconfig/ui/copytablepage \
+ dbaccess/uiconfig/ui/dbaseindexdialog \
+ dbaccess/uiconfig/ui/dbasepage \
+ dbaccess/uiconfig/ui/dbtreelist \
+ dbaccess/uiconfig/ui/dbwizconnectionpage \
+ dbaccess/uiconfig/ui/dbwizmysqlintropage \
+ dbaccess/uiconfig/ui/dbwizmysqlnativepage \
+ dbaccess/uiconfig/ui/dbwizspreadsheetpage \
+ dbaccess/uiconfig/ui/dbwiztextpage \
+ dbaccess/uiconfig/ui/deleteallrowsdialog \
+ dbaccess/uiconfig/ui/designsavemodifieddialog \
+ dbaccess/uiconfig/ui/detailwindow \
+ dbaccess/uiconfig/ui/directsqldialog \
+ dbaccess/uiconfig/ui/emptypage \
+ dbaccess/uiconfig/ui/fielddialog \
+ dbaccess/uiconfig/ui/fielddescpage \
+ dbaccess/uiconfig/ui/fielddescpanel \
+ dbaccess/uiconfig/ui/finalpagewizard \
+ dbaccess/uiconfig/ui/generalpagedialog \
+ dbaccess/uiconfig/ui/generalpagewizard \
+ dbaccess/uiconfig/ui/generalspecialjdbcdetailspage \
+ dbaccess/uiconfig/ui/generatedvaluespage \
+ dbaccess/uiconfig/ui/indexdesigndialog \
+ dbaccess/uiconfig/ui/jdbcconnectionpage \
+ dbaccess/uiconfig/ui/joindialog \
+ dbaccess/uiconfig/ui/jointablemenu \
+ dbaccess/uiconfig/ui/joinviewmenu \
+ dbaccess/uiconfig/ui/keymenu \
+ dbaccess/uiconfig/ui/ldapconnectionpage \
+ dbaccess/uiconfig/ui/ldappage \
+ dbaccess/uiconfig/ui/limitbox \
+ dbaccess/uiconfig/ui/mysqlnativepage \
+ dbaccess/uiconfig/ui/mysqlnativesettings \
+ dbaccess/uiconfig/ui/namematchingpage \
+ dbaccess/uiconfig/ui/odbcpage \
+ dbaccess/uiconfig/ui/parametersdialog \
+ dbaccess/uiconfig/ui/password \
+ dbaccess/uiconfig/ui/querycolmenu \
+ dbaccess/uiconfig/ui/queryfilterdialog \
+ dbaccess/uiconfig/ui/queryfuncmenu \
+ dbaccess/uiconfig/ui/querypropertiesdialog \
+ dbaccess/uiconfig/ui/queryview \
+ dbaccess/uiconfig/ui/relationdialog \
+ dbaccess/uiconfig/ui/rowheightdialog \
+ dbaccess/uiconfig/ui/saveindexdialog \
+ dbaccess/uiconfig/ui/savedialog \
+ dbaccess/uiconfig/ui/savemodifieddialog \
+ dbaccess/uiconfig/ui/specialjdbcconnectionpage \
+ dbaccess/uiconfig/ui/specialsettingspage \
+ dbaccess/uiconfig/ui/sortdialog \
+ dbaccess/uiconfig/ui/sqlexception \
+ dbaccess/uiconfig/ui/tableborderwindow \
+ dbaccess/uiconfig/ui/tabledesignrowmenu \
+ dbaccess/uiconfig/ui/tabledesignsavemodifieddialog \
+ dbaccess/uiconfig/ui/tablelistbox \
+ dbaccess/uiconfig/ui/tablesfilterdialog \
+ dbaccess/uiconfig/ui/tablesfilterpage \
+ dbaccess/uiconfig/ui/tablesjoindialog \
+ dbaccess/uiconfig/ui/tabletitle \
+ dbaccess/uiconfig/ui/taskwindow \
+ dbaccess/uiconfig/ui/textconnectionsettings \
+ dbaccess/uiconfig/ui/textpage \
+ dbaccess/uiconfig/ui/titlewindow \
+ dbaccess/uiconfig/ui/typeselectpage \
+ dbaccess/uiconfig/ui/useradmindialog \
+ dbaccess/uiconfig/ui/useradminpage \
+ dbaccess/uiconfig/ui/userdetailspage \
+ dbaccess/uiconfig/ui/migrwarndlg \
+))
+
+# vim: set noet sw=4 ts=4:
diff --git a/dbaccess/UIConfig_dbapp.mk b/dbaccess/UIConfig_dbapp.mk
new file mode 100644
index 000000000..d93641d35
--- /dev/null
+++ b/dbaccess/UIConfig_dbapp.mk
@@ -0,0 +1,34 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+$(eval $(call gb_UIConfig_UIConfig,modules/dbapp))
+
+$(eval $(call gb_UIConfig_add_menubarfiles,modules/dbapp,\
+ dbaccess/uiconfig/dbapp/menubar/menubar \
+))
+
+$(eval $(call gb_UIConfig_add_popupmenufiles,modules/dbapp,\
+ dbaccess/uiconfig/dbapp/popupmenu/edit \
+ dbaccess/uiconfig/dbapp/popupmenu/new \
+ dbaccess/uiconfig/dbapp/popupmenu/preview \
+))
+
+$(eval $(call gb_UIConfig_add_statusbarfiles,modules/dbapp,\
+ dbaccess/uiconfig/dbapp/statusbar/statusbar \
+))
+
+$(eval $(call gb_UIConfig_add_toolbarfiles,modules/dbapp,\
+ dbaccess/uiconfig/dbapp/toolbar/formobjectbar \
+ dbaccess/uiconfig/dbapp/toolbar/queryobjectbar \
+ dbaccess/uiconfig/dbapp/toolbar/reportobjectbar \
+ dbaccess/uiconfig/dbapp/toolbar/tableobjectbar \
+ dbaccess/uiconfig/dbapp/toolbar/toolbar \
+))
+
+# vim: set noet sw=4 ts=4:
diff --git a/dbaccess/UIConfig_dbbrowser.mk b/dbaccess/UIConfig_dbbrowser.mk
new file mode 100644
index 000000000..eaab6cc2b
--- /dev/null
+++ b/dbaccess/UIConfig_dbbrowser.mk
@@ -0,0 +1,25 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+$(eval $(call gb_UIConfig_UIConfig,modules/dbbrowser))
+
+$(eval $(call gb_UIConfig_add_menubarfiles,modules/dbbrowser,\
+ dbaccess/uiconfig/dbbrowser/menubar/compat \
+))
+
+$(eval $(call gb_UIConfig_add_popupmenufiles,modules/dbbrowser,\
+ dbaccess/uiconfig/dbbrowser/popupmenu/explorer \
+ dbaccess/uiconfig/dbbrowser/popupmenu/refreshdata \
+))
+
+$(eval $(call gb_UIConfig_add_toolbarfiles,modules/dbbrowser,\
+ dbaccess/uiconfig/dbbrowser/toolbar/toolbar \
+))
+
+# vim: set noet sw=4 ts=4:
diff --git a/dbaccess/UIConfig_dbquery.mk b/dbaccess/UIConfig_dbquery.mk
new file mode 100644
index 000000000..5af309335
--- /dev/null
+++ b/dbaccess/UIConfig_dbquery.mk
@@ -0,0 +1,22 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+$(eval $(call gb_UIConfig_UIConfig,modules/dbquery))
+
+$(eval $(call gb_UIConfig_add_menubarfiles,modules/dbquery,\
+ dbaccess/uiconfig/dbquery/menubar/menubar \
+))
+
+$(eval $(call gb_UIConfig_add_toolbarfiles,modules/dbquery,\
+ dbaccess/uiconfig/dbquery/toolbar/designobjectbar \
+ dbaccess/uiconfig/dbquery/toolbar/sqlobjectbar \
+ dbaccess/uiconfig/dbquery/toolbar/toolbar \
+))
+
+# vim: set noet sw=4 ts=4:
diff --git a/dbaccess/UIConfig_dbrelation.mk b/dbaccess/UIConfig_dbrelation.mk
new file mode 100644
index 000000000..51a3b215c
--- /dev/null
+++ b/dbaccess/UIConfig_dbrelation.mk
@@ -0,0 +1,20 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+$(eval $(call gb_UIConfig_UIConfig,modules/dbrelation))
+
+$(eval $(call gb_UIConfig_add_menubarfiles,modules/dbrelation,\
+ dbaccess/uiconfig/dbrelation/menubar/menubar \
+))
+
+$(eval $(call gb_UIConfig_add_toolbarfiles,modules/dbrelation,\
+ dbaccess/uiconfig/dbrelation/toolbar/toolbar \
+))
+
+# vim: set noet sw=4 ts=4:
diff --git a/dbaccess/UIConfig_dbtable.mk b/dbaccess/UIConfig_dbtable.mk
new file mode 100644
index 000000000..9503cc22b
--- /dev/null
+++ b/dbaccess/UIConfig_dbtable.mk
@@ -0,0 +1,20 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+$(eval $(call gb_UIConfig_UIConfig,modules/dbtable))
+
+$(eval $(call gb_UIConfig_add_menubarfiles,modules/dbtable,\
+ dbaccess/uiconfig/dbtable/menubar/menubar \
+))
+
+$(eval $(call gb_UIConfig_add_toolbarfiles,modules/dbtable,\
+ dbaccess/uiconfig/dbtable/toolbar/toolbar \
+))
+
+# vim: set noet sw=4 ts=4:
diff --git a/dbaccess/UIConfig_dbtdata.mk b/dbaccess/UIConfig_dbtdata.mk
new file mode 100644
index 000000000..2f8cb3f62
--- /dev/null
+++ b/dbaccess/UIConfig_dbtdata.mk
@@ -0,0 +1,24 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+$(eval $(call gb_UIConfig_UIConfig,modules/dbtdata))
+
+$(eval $(call gb_UIConfig_add_menubarfiles,modules/dbtdata,\
+ dbaccess/uiconfig/dbtdata/menubar/menubar \
+))
+
+$(eval $(call gb_UIConfig_add_popupmenufiles,modules/dbtdata,\
+ dbaccess/uiconfig/dbtdata/popupmenu/refreshdata \
+))
+
+$(eval $(call gb_UIConfig_add_toolbarfiles,modules/dbtdata,\
+ dbaccess/uiconfig/dbtdata/toolbar/toolbar \
+))
+
+# vim: set noet sw=4 ts=4:
diff --git a/dbaccess/inc/bitmaps.hlst b/dbaccess/inc/bitmaps.hlst
new file mode 100644
index 000000000..15352b63b
--- /dev/null
+++ b/dbaccess/inc/bitmaps.hlst
@@ -0,0 +1,34 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDED_DBACCESS_INC_BITMAPS_HRC
+#define INCLUDED_DBACCESS_INC_BITMAPS_HRC
+
+inline constexpr OUStringLiteral BMP_FORMFOLDER_TREE_L = u"dbaccess/res/forms_32.png";
+inline constexpr OUStringLiteral BMP_REPORTFOLDER_TREE_L = u"dbaccess/res/reports_32.png";
+inline constexpr OUStringLiteral BMP_QUERYFOLDER_TREE_L = u"dbaccess/res/queries_32.png";
+inline constexpr OUStringLiteral BMP_TABLEFOLDER_TREE_L = u"dbaccess/res/tables_32.png";
+inline constexpr OUStringLiteral DATABASE_TREE_ICON = u"dbaccess/res/db.png";
+inline constexpr OUStringLiteral TABLE_TREE_ICON = u"res/sx03188.png";
+inline constexpr OUStringLiteral TABLEFOLDER_TREE_ICON = u"res/sx03187.png";
+inline constexpr OUStringLiteral VIEW_TREE_ICON = u"res/sx16670.png";
+inline constexpr OUStringLiteral QUERY_TREE_ICON = u"res/sx03202.png";
+inline constexpr OUStringLiteral QUERYFOLDER_TREE_ICON = u"res/sx03201.png";
+inline constexpr OUStringLiteral FORM_TREE_ICON = u"dbaccess/res/form_16.png";
+inline constexpr OUStringLiteral FORMFOLDER_TREE_ICON = u"dbaccess/res/forms_16.png";
+inline constexpr OUStringLiteral REPORT_TREE_ICON = u"dbaccess/res/report_16.png";
+inline constexpr OUStringLiteral REPORTFOLDER_TREE_ICON = u"dbaccess/res/reports_16.png";
+inline constexpr OUStringLiteral BMP_PRIMARY_KEY = u"dbaccess/res/jo01.png";
+inline constexpr OUStringLiteral BMP_PKEYICON = u"dbaccess/res/pkey.png";
+inline constexpr OUStringLiteral BMP_UP = u"dbaccess/res/sortup.png";
+inline constexpr OUStringLiteral BMP_DOWN = u"dbaccess/res/sortdown.png";
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/dbaccess/inc/core_resource.hxx b/dbaccess/inc/core_resource.hxx
new file mode 100644
index 000000000..0f7a6ba3e
--- /dev/null
+++ b/dbaccess/inc/core_resource.hxx
@@ -0,0 +1,68 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <rtl/ustring.hxx>
+#include "dbadllapi.hxx"
+#include <unotools/resmgr.hxx>
+
+#define DBA_RES( id ) ::dbaccess::ResourceManager::loadString( id )
+#define DBA_RES_PARAM( id, ascii, replace ) ::dbaccess::ResourceManager::loadString( id, ascii, replace )
+
+namespace dbaccess
+{
+ // ResourceManager
+ // handling resources within the DBA-Core library
+ class OOO_DLLPUBLIC_DBA ResourceManager
+ {
+ private:
+ // no instantiation allowed
+ ResourceManager() = delete;
+ ~ResourceManager() { }
+
+ public:
+ /** loads the string with the specified resource id
+ */
+ static OUString loadString(TranslateId pResId);
+
+ /** loads a string from the resource file, substituting two placeholders with given strings
+
+ @param pResId
+ the resource ID of the string to load
+ @param _pPlaceholderAscii1
+ the ASCII representation of the first placeholder string
+ @param _rReplace1
+ the string which should substitute the first placeholder
+ @param _pPlaceholderAscii2
+ the ASCII representation of the second placeholder string
+ @param _rReplace2
+ the string which should substitute the second placeholder
+ */
+ static OUString loadString(
+ TranslateId pResId,
+ const char* _pPlaceholderAscii1,
+ std::u16string_view _rReplace1,
+ const char* _pPlaceholderAscii2,
+ std::u16string_view _rReplace2
+ );
+ };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/inc/dbaccess_slotid.hrc b/dbaccess/inc/dbaccess_slotid.hrc
new file mode 100644
index 000000000..768887dc0
--- /dev/null
+++ b/dbaccess/inc/dbaccess_slotid.hrc
@@ -0,0 +1,108 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef INCLUDED_DBACCESS_INC_DBACCESS_SLOTID_HRC
+#define INCLUDED_DBACCESS_INC_DBACCESS_SLOTID_HRC
+
+#include <svl/solar.hrc>
+
+#define SID_INDEXDESIGN ( SID_DBACCESS_START + 0 )
+#define SID_DOCUMENT_DATA_SOURCE ( SID_DBACCESS_START + 1 )
+// free
+#define SID_DB_APP_DISABLE_PREVIEW ( SID_DBACCESS_START + 3 )
+#define SID_DB_APP_DSCONNECTION_TYPE ( SID_DBACCESS_START + 4 )
+#define SID_DB_APP_DSADVANCED_SETTINGS ( SID_DBACCESS_START + 5 )
+// free
+#define SID_DB_APP_VIEW_DOCINFO_PREVIEW ( SID_DBACCESS_START + 7 )
+#define SID_DB_APP_VIEW_DOC_PREVIEW ( SID_DBACCESS_START + 8 )
+#define SID_DB_APP_VIEW_TABLES ( SID_DBACCESS_START + 9 )
+#define SID_DB_APP_VIEW_QUERIES ( SID_DBACCESS_START + 10 )
+#define SID_DB_APP_DSIMPORT ( SID_DBACCESS_START + 11 )
+#define SID_DB_APP_VIEW_FORMS ( SID_DBACCESS_START + 12 )
+#define SID_DB_APP_DSRELDESIGN ( SID_DBACCESS_START + 13 )
+#define SID_DB_APP_DSUSERADMIN ( SID_DBACCESS_START + 14 )
+#define SID_DB_APP_TABLEFILTER ( SID_DBACCESS_START + 15 )
+// free
+#define SID_DB_APP_DSPROPS ( SID_DBACCESS_START + 17 )
+#define SID_DB_APP_DBADMIN ( SID_DBACCESS_START + 18 )
+#define SID_APP_NEW_REPORT_PRE_SEL ( SID_DBACCESS_START + 19 )
+#define SID_DB_APP_CONVERTTOVIEW ( SID_DBACCESS_START + 20 )
+#define SID_DB_APP_REFRESH_TABLES ( SID_DBACCESS_START + 21 )
+#define SID_DB_APP_VIEW_REPORTS ( SID_DBACCESS_START + 22 )
+#define SID_DB_APP_DSEXPORT ( SID_DBACCESS_START + 23 )
+
+#define SID_DB_APP_TABLE_DELETE ( SID_DBACCESS_START + 24 )
+#define SID_DB_APP_TABLE_RENAME ( SID_DBACCESS_START + 25 )
+#define SID_DB_APP_TABLE_EDIT ( SID_DBACCESS_START + 26 )
+#define SID_DB_APP_TABLE_OPEN ( SID_DBACCESS_START + 27 )
+
+#define SID_DB_APP_QUERY_DELETE ( SID_DBACCESS_START + 28 )
+#define SID_DB_APP_QUERY_RENAME ( SID_DBACCESS_START + 29 )
+#define SID_DB_APP_QUERY_EDIT ( SID_DBACCESS_START + 30 )
+#define SID_DB_APP_QUERY_OPEN ( SID_DBACCESS_START + 31 )
+
+#define SID_DB_APP_FORM_DELETE ( SID_DBACCESS_START + 32 )
+#define SID_DB_APP_FORM_RENAME ( SID_DBACCESS_START + 33 )
+#define SID_DB_APP_FORM_EDIT ( SID_DBACCESS_START + 34 )
+#define SID_DB_APP_FORM_OPEN ( SID_DBACCESS_START + 35 )
+
+#define SID_DB_APP_REPORT_DELETE ( SID_DBACCESS_START + 36 )
+#define SID_DB_APP_REPORT_RENAME ( SID_DBACCESS_START + 37 )
+#define SID_DB_APP_REPORT_EDIT ( SID_DBACCESS_START + 38 )
+#define SID_DB_APP_REPORT_OPEN ( SID_DBACCESS_START + 39 )
+
+#define SID_DB_APP_DELETE ( SID_DBACCESS_START + 40 )
+#define SID_DB_APP_RENAME ( SID_DBACCESS_START + 41 )
+#define SID_DB_APP_EDIT ( SID_DBACCESS_START + 42 )
+#define SID_DB_APP_OPEN ( SID_DBACCESS_START + 43 )
+
+#define SID_BROWSER_CLEAR_QUERY ( SID_DBACCESS_START + 44 )
+#define SID_RELATION_ADD_RELATION ( SID_DBACCESS_START + 45 )
+#define SID_QUERY_VIEW_FUNCTIONS ( SID_DBACCESS_START + 46 )
+#define SID_QUERY_VIEW_TABLES ( SID_DBACCESS_START + 47 )
+#define SID_QUERY_VIEW_ALIASES ( SID_DBACCESS_START + 48 )
+#define SID_QUERY_DISTINCT_VALUES ( SID_DBACCESS_START + 49 )
+#define SID_FORM_CREATE_REPWIZ_PRE_SEL ( SID_DBACCESS_START + 50 )
+#define SID_REPORT_CREATE_REPWIZ_PRE_SEL ( SID_DBACCESS_START + 51 )
+#define SID_DB_QUERY_PREVIEW ( SID_DBACCESS_START + 52 )
+#define SID_APP_NEW_FOLDER ( SID_DBACCESS_START + 53 )
+#define SID_APP_NEW_FORM ( SID_DBACCESS_START + 54 )
+#define SID_DB_APP_PASTE_SPECIAL ( SID_DBACCESS_START + 55 )
+#define SID_QUERY_LIMIT ( SID_DBACCESS_START + 56 )
+
+// status information
+#define SID_DB_APP_STATUS_TYPE ( SID_DBACCESS_START + 57 )
+#define SID_DB_APP_STATUS_DBNAME ( SID_DBACCESS_START + 58 )
+#define SID_DB_APP_STATUS_USERNAME ( SID_DBACCESS_START + 59 )
+#define SID_DB_APP_STATUS_HOSTNAME ( SID_DBACCESS_START + 60 )
+
+#define SID_DB_APP_SENDREPORTASMAIL ( SID_DBACCESS_START + 61 )
+#define SID_DB_APP_SENDREPORTTOWRITER ( SID_DBACCESS_START + 62 )
+#define SID_DB_FORM_NEW_PILOT ( SID_DBACCESS_START + 63 )
+#define SID_DB_NEW_VIEW_SQL ( SID_DBACCESS_START + 64 )
+#define SID_APP_NEW_REPORT ( SID_DBACCESS_START + 65 )
+
+#define SID_DB_APP_EDIT_SQL_VIEW ( SID_DBACCESS_START + 66 )
+//FREE
+//FREE
+#define SID_QUERY_PROP_DLG ( SID_DBACCESS_START + 69 )
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/inc/dbadllapi.hxx b/dbaccess/inc/dbadllapi.hxx
new file mode 100644
index 000000000..d742b9a3b
--- /dev/null
+++ b/dbaccess/inc/dbadllapi.hxx
@@ -0,0 +1,32 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <sal/config.h>
+
+#include <sal/types.h>
+
+#if defined OOO_DLLIMPLEMENTATION_DBA
+#define OOO_DLLPUBLIC_DBA SAL_DLLPUBLIC_EXPORT
+#else
+#define OOO_DLLPUBLIC_DBA SAL_DLLPUBLIC_IMPORT
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/inc/helpids.h b/dbaccess/inc/helpids.h
new file mode 100644
index 000000000..86c233f9d
--- /dev/null
+++ b/dbaccess/inc/helpids.h
@@ -0,0 +1,110 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef INCLUDED_DBACCESS_INC_HELPIDS_H
+#define INCLUDED_DBACCESS_INC_HELPIDS_H
+
+#include <rtl/string.hxx>
+
+inline constexpr OStringLiteral HID_DATABROWSE_HEADER = "DBACCESS_HID_DATABROWSE_HEADER";
+inline constexpr OStringLiteral HID_CTL_TABBROWSER = "DBACCESS_HID_CTL_TABBROWSER";
+inline constexpr OStringLiteral HID_CTL_TREEVIEW = "DBACCESS_HID_CTL_TREEVIEW";
+
+inline constexpr OStringLiteral HID_DSADMIN_BROWSECONN = "DBACCESS_HID_DSADMIN_BROWSECONN";
+
+inline constexpr OStringLiteral HID_CTL_QRYSQLEDIT = "DBACCESS_HID_CTL_QRYSQLEDIT";
+
+inline constexpr OStringLiteral HID_CTL_QRYDGNTAB = "DBACCESS_HID_CTL_QRYDGNTAB";
+inline constexpr OStringLiteral HID_CTL_QRYDGNCRIT = "DBACCESS_HID_CTL_QRYDGNCRIT";
+inline constexpr OStringLiteral HID_QRYDGN_ROW_VISIBLE = "DBACCESS_HID_QRYDGN_ROW_VISIBLE";
+inline constexpr OStringLiteral HID_QRYDGN_ROW_TABLE = "DBACCESS_HID_QRYDGN_ROW_TABLE";
+inline constexpr OStringLiteral HID_QRYDGN_ROW_FIELD = "DBACCESS_HID_QRYDGN_ROW_FIELD";
+inline constexpr OStringLiteral HID_QRYDGN_ROW_ORDER = "DBACCESS_HID_QRYDGN_ROW_ORDER";
+inline constexpr OStringLiteral HID_QRYDGN_ROW_FUNCTION = "DBACCESS_HID_QRYDGN_ROW_FUNCTION";
+inline constexpr OStringLiteral HID_QRYDGN_ROW_ALIAS = "DBACCESS_HID_QRYDGN_ROW_ALIAS";
+inline constexpr OStringLiteral HID_QRYDGN_ROW_CRIT = "DBACCESS_HID_QRYDGN_ROW_CRIT";
+
+inline constexpr OStringLiteral HID_TAB_DESIGN_FIELDCONTROL = "DBACCESS_HID_TAB_DESIGN_FIELDCONTROL";
+inline constexpr OStringLiteral HID_TAB_DESIGN_DESCWIN = "DBACCESS_HID_TAB_DESIGN_DESCWIN";
+inline constexpr OStringLiteral HID_TABDESIGN_BACKGROUND = "DBACCESS_HID_TABDESIGN_BACKGROUND";
+inline constexpr OStringLiteral HID_CTL_TABLEEDIT = "DBACCESS_HID_CTL_TABLEEDIT";
+inline constexpr OStringLiteral HID_TABDESIGN_NAMECELL = "DBACCESS_HID_TABDESIGN_NAMECELL";
+inline constexpr OStringLiteral HID_TABDESIGN_TYPECELL = "DBACCESS_HID_TABDESIGN_TYPECELL";
+inline constexpr OStringLiteral HID_TABDESIGN_COMMENTCELL = "DBACCESS_HID_TABDESIGN_COMMENTCELL";
+inline constexpr OStringLiteral HID_TAB_DESIGN_HELP_TEXT_FRAME = "DBACCESS_HID_TAB_DESIGN_HELP_TEXT_FRAME";
+inline constexpr OStringLiteral HID_TAB_ENT_DEFAULT = "DBACCESS_HID_TAB_ENT_DEFAULT";
+inline constexpr OStringLiteral HID_TAB_ENT_FORMAT_SAMPLE = "DBACCESS_HID_TAB_ENT_FORMAT_SAMPLE";
+inline constexpr OStringLiteral HID_TAB_ENT_FORMAT = "DBACCESS_HID_TAB_ENT_FORMAT";
+inline constexpr OStringLiteral HID_TAB_ENT_BOOL_DEFAULT = "DBACCESS_HID_TAB_ENT_BOOL_DEFAULT";
+inline constexpr OStringLiteral HID_TAB_ENT_REQUIRED = "DBACCESS_HID_TAB_ENT_REQUIRED";
+inline constexpr OStringLiteral HID_TAB_ENT_AUTOINCREMENT = "DBACCESS_HID_TAB_ENT_AUTOINCREMENT";
+inline constexpr OStringLiteral HID_TAB_ENT_TEXT_LEN = "DBACCESS_HID_TAB_ENT_TEXT_LEN";
+inline constexpr OStringLiteral HID_TAB_ENT_TYPE = "DBACCESS_HID_TAB_ENT_TYPE";
+inline constexpr OStringLiteral HID_TAB_ENT_COLUMNNAME = "DBACCESS_HID_TAB_ENT_COLUMNNAME";
+inline constexpr OStringLiteral HID_TAB_ENT_NUMTYP = "DBACCESS_HID_TAB_ENT_NUMTYP";
+inline constexpr OStringLiteral HID_TAB_ENT_LEN = "DBACCESS_HID_TAB_ENT_LEN";
+inline constexpr OStringLiteral HID_TAB_ENT_SCALE = "DBACCESS_HID_TAB_ENT_SCALE";
+inline constexpr OStringLiteral HID_CTL_RELATIONTAB = "DBACCESS_HID_CTL_RELATIONTAB";
+inline constexpr OStringLiteral HID_RELATIONDIALOG_LEFTFIELDCELL = "DBACCESS_HID_RELATIONDIALOG_LEFTFIELDCELL";
+inline constexpr OStringLiteral HID_RELATIONDIALOG_RIGHTFIELDCELL = "DBACCESS_HID_RELATIONDIALOG_RIGHTFIELDCELL";
+inline constexpr OStringLiteral HID_CONFIRM_DROP_BUTTON_ALL = "DBACCESS_HID_CONFIRM_DROP_BUTTON_ALL";
+inline constexpr OStringLiteral HID_DSADMIN_LDAP_HOSTNAME = "DBACCESS_HID_DSADMIN_LDAP_HOSTNAME";
+inline constexpr OStringLiteral HID_DSADMIN_MOZILLA_PROFILE_NAME = "DBACCESS_HID_DSADMIN_MOZILLA_PROFILE_NAME";
+inline constexpr OStringLiteral HID_DSADMIN_THUNDERBIRD_PROFILE_NAME = "DBACCESS_HID_DSADMIN_THUNDERBIRD_PROFILE_NAME";
+
+inline constexpr OStringLiteral HID_DLGINDEX_INDEXDETAILS_FIELD = "DBACCESS_HID_DLGINDEX_INDEXDETAILS_FIELD";
+inline constexpr OStringLiteral HID_DLGINDEX_INDEXDETAILS_SORTORDER = "DBACCESS_HID_DLGINDEX_INDEXDETAILS_SORTORDER";
+
+inline constexpr OStringLiteral HID_TAB_AUTOINCREMENTVALUE = "DBACCESS_HID_TAB_AUTOINCREMENTVALUE";
+
+inline constexpr OStringLiteral HID_DSADMIN_DBASE_PATH = "DBACCESS_HID_DSADMIN_DBASE_PATH";
+inline constexpr OStringLiteral HID_DSADMIN_MYSQL_DATABASE = "DBACCESS_HID_DSADMIN_MYSQL_DATABASE";
+inline constexpr OStringLiteral HID_DSADMIN_MYSQL_ODBC_DATASOURCE = "DBACCESS_HID_DSADMIN_MYSQL_ODBC_DATASOURCE";
+inline constexpr OStringLiteral HID_DSADMIN_ODBC_DATASOURCE = "DBACCESS_HID_DSADMIN_ODBC_DATASOURCE";
+inline constexpr OStringLiteral HID_DSADMIN_MSACCESS_MDB_FILE = "DBACCESS_HID_DSADMIN_MSACCESS_MDB_FILE";
+inline constexpr OStringLiteral HID_DSADMIN_FLAT_PATH = "DBACCESS_HID_DSADMIN_FLAT_PATH";
+inline constexpr OStringLiteral HID_DSADMIN_CALC_PATH = "DBACCESS_HID_DSADMIN_CALC_PATH";
+inline constexpr OStringLiteral HID_DSADMIN_WRITER_PATH = "DBACCESS_HID_DSADMIN_WRITER_PATH";
+inline constexpr OStringLiteral HID_DSADMIN_ORACLE_DATABASE = "DBACCESS_HID_DSADMIN_ORACLE_DATABASE";
+
+inline constexpr OStringLiteral HID_APP_TABLE_TREE = "DBACCESS_HID_APP_TABLE_TREE";
+inline constexpr OStringLiteral HID_APP_FORM_TREE = "DBACCESS_HID_APP_FORM_TREE";
+inline constexpr OStringLiteral HID_APP_QUERY_TREE = "DBACCESS_HID_APP_QUERY_TREE";
+inline constexpr OStringLiteral HID_APP_REPORT_TREE = "DBACCESS_HID_APP_REPORT_TREE";
+inline constexpr OStringLiteral HID_APP_CREATION_LIST = "DBACCESS_HID_APP_CREATION_LIST";
+inline constexpr OStringLiteral HID_APP_SWAP_ICONCONTROL = "DBACCESS_HID_APP_SWAP_ICONCONTROL";
+
+
+inline constexpr OStringLiteral HID_APP_HELP_TEXT = "DBACCESS_HID_APP_HELP_TEXT";
+inline constexpr OStringLiteral HID_APP_DESCRIPTION_TEXT = "DBACCESS_HID_APP_DESCRIPTION_TEXT";
+inline constexpr OStringLiteral HID_APP_VIEW_PREVIEW_CB = "DBACCESS_HID_APP_VIEW_PREVIEW_CB";
+inline constexpr OStringLiteral HID_APP_VIEW_PREVIEW_1 = "DBACCESS_HID_APP_VIEW_PREVIEW_1";
+inline constexpr OStringLiteral HID_APP_VIEW_PREVIEW_2 = "DBACCESS_HID_APP_VIEW_PREVIEW_2";
+inline constexpr OStringLiteral HID_TABDESIGN_HELPTEXT = "DBACCESS_HID_TABDESIGN_HELPTEXT";
+inline constexpr OStringLiteral HID_APP_VIEW_PREVIEW_3 = "DBACCESS_HID_APP_VIEW_PREVIEW_3";
+
+
+inline constexpr OStringLiteral HID_DBWIZ_PREVIOUS = "DBACCESS_HID_DBWIZ_PREVIOUS";
+inline constexpr OStringLiteral HID_DBWIZ_NEXT = "DBACCESS_HID_DBWIZ_NEXT";
+inline constexpr OStringLiteral HID_DBWIZ_CANCEL = "DBACCESS_HID_DBWIZ_CANCEL";
+inline constexpr OStringLiteral HID_DBWIZ_FINISH = "DBACCESS_HID_DBWIZ_FINISH";
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/inc/pch/precompiled_dba.cxx b/dbaccess/inc/pch/precompiled_dba.cxx
new file mode 100644
index 000000000..17c8073e5
--- /dev/null
+++ b/dbaccess/inc/pch/precompiled_dba.cxx
@@ -0,0 +1,12 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "precompiled_dba.hxx"
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/inc/pch/precompiled_dba.hxx b/dbaccess/inc/pch/precompiled_dba.hxx
new file mode 100644
index 000000000..516dcef5f
--- /dev/null
+++ b/dbaccess/inc/pch/precompiled_dba.hxx
@@ -0,0 +1,274 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+/*
+ This file has been autogenerated by update_pch.sh. It is possible to edit it
+ manually (such as when an include file has been moved/renamed/removed). All such
+ manual changes will be rewritten by the next run of update_pch.sh (which presumably
+ also fixes all possible problems, so it's usually better to use it).
+
+ Generated on 2021-04-11 19:47:49 using:
+ ./bin/update_pch dbaccess dba --cutoff=6 --exclude:system --include:module --include:local
+
+ If after updating build fails, use the following command to locate conflicting headers:
+ ./bin/update_pch_bisect ./dbaccess/inc/pch/precompiled_dba.hxx "make dbaccess.build" --find-conflicts
+*/
+
+#include <sal/config.h>
+#if PCH_LEVEL >= 1
+#include <algorithm>
+#include <assert.h>
+#include <atomic>
+#include <cassert>
+#include <chrono>
+#include <cmath>
+#include <cstddef>
+#include <cstdlib>
+#include <cstring>
+#include <deque>
+#include <float.h>
+#include <functional>
+#include <initializer_list>
+#include <iomanip>
+#include <limits.h>
+#include <limits>
+#include <map>
+#include <math.h>
+#include <memory>
+#include <new>
+#include <optional>
+#include <ostream>
+#include <stddef.h>
+#include <string.h>
+#include <string>
+#include <string_view>
+#include <type_traits>
+#include <utility>
+#include <vector>
+#include <boost/property_tree/ptree_fwd.hpp>
+#endif // PCH_LEVEL >= 1
+#if PCH_LEVEL >= 2
+#include <osl/diagnose.h>
+#include <osl/doublecheckedlocking.h>
+#include <osl/endian.h>
+#include <osl/file.hxx>
+#include <osl/getglobalmutex.hxx>
+#include <osl/interlck.h>
+#include <osl/mutex.h>
+#include <osl/mutex.hxx>
+#include <osl/process.h>
+#include <osl/thread.h>
+#include <osl/time.h>
+#include <rtl/alloc.h>
+#include <rtl/character.hxx>
+#include <rtl/digest.h>
+#include <rtl/instance.hxx>
+#include <rtl/math.h>
+#include <rtl/math.hxx>
+#include <rtl/ref.hxx>
+#include <rtl/strbuf.h>
+#include <rtl/string.h>
+#include <rtl/string.hxx>
+#include <rtl/stringconcat.hxx>
+#include <rtl/stringutils.hxx>
+#include <rtl/textcvt.h>
+#include <rtl/textenc.h>
+#include <rtl/uri.hxx>
+#include <rtl/ustrbuf.h>
+#include <rtl/ustrbuf.hxx>
+#include <rtl/ustring.h>
+#include <rtl/ustring.hxx>
+#include <sal/backtrace.hxx>
+#include <sal/log.hxx>
+#include <sal/macros.h>
+#include <sal/saldllapi.h>
+#include <sal/types.h>
+#include <sal/typesizes.h>
+#include <vcl/Scanline.hxx>
+#include <vcl/alpha.hxx>
+#include <vcl/bitmap.hxx>
+#include <vcl/bitmap/BitmapTypes.hxx>
+#include <vcl/bitmapex.hxx>
+#include <vcl/checksum.hxx>
+#include <vcl/dllapi.h>
+#include <vcl/mapmod.hxx>
+#include <vcl/region.hxx>
+#include <vcl/scopedbitmapaccess.hxx>
+#include <vcl/vclenum.hxx>
+#include <vcl/vclptr.hxx>
+#endif // PCH_LEVEL >= 2
+#if PCH_LEVEL >= 3
+#include <basegfx/basegfxdllapi.h>
+#include <basegfx/color/bcolor.hxx>
+#include <basegfx/numeric/ftools.hxx>
+#include <basegfx/point/b2dpoint.hxx>
+#include <basegfx/point/b2ipoint.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <basegfx/polygon/b2dpolypolygon.hxx>
+#include <basegfx/range/b2drange.hxx>
+#include <basegfx/range/basicrange.hxx>
+#include <basegfx/tuple/b2dtuple.hxx>
+#include <basegfx/tuple/b2ituple.hxx>
+#include <basegfx/tuple/b3dtuple.hxx>
+#include <basegfx/utils/common.hxx>
+#include <basegfx/vector/b2dvector.hxx>
+#include <basegfx/vector/b2enums.hxx>
+#include <basegfx/vector/b2ivector.hxx>
+#include <basic/basicdllapi.h>
+#include <basic/sbxcore.hxx>
+#include <basic/sbxdef.hxx>
+#include <basic/sbxvar.hxx>
+#include <com/sun/star/beans/Property.hpp>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/beans/PropertyState.hpp>
+#include <com/sun/star/beans/XFastPropertySet.hpp>
+#include <com/sun/star/beans/XMultiPropertySet.hpp>
+#include <com/sun/star/beans/XPropertiesChangeListener.hpp>
+#include <com/sun/star/beans/XPropertiesChangeNotifier.hpp>
+#include <com/sun/star/beans/XPropertyContainer.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/beans/XPropertySetOption.hpp>
+#include <com/sun/star/beans/XPropertyState.hpp>
+#include <com/sun/star/beans/XVetoableChangeListener.hpp>
+#include <com/sun/star/container/XChild.hpp>
+#include <com/sun/star/container/XContainer.hpp>
+#include <com/sun/star/container/XEnumerationAccess.hpp>
+#include <com/sun/star/container/XIndexAccess.hpp>
+#include <com/sun/star/container/XNameAccess.hpp>
+#include <com/sun/star/container/XNamed.hpp>
+#include <com/sun/star/embed/ElementModes.hpp>
+#include <com/sun/star/lang/DisposedException.hpp>
+#include <com/sun/star/lang/EventObject.hpp>
+#include <com/sun/star/lang/Locale.hpp>
+#include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
+#include <com/sun/star/lang/XComponent.hpp>
+#include <com/sun/star/lang/XInitialization.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/lang/XTypeProvider.hpp>
+#include <com/sun/star/lang/XUnoTunnel.hpp>
+#include <com/sun/star/sdb/CommandType.hpp>
+#include <com/sun/star/sdb/XSingleSelectQueryComposer.hpp>
+#include <com/sun/star/sdbc/DataType.hpp>
+#include <com/sun/star/sdbc/SQLException.hpp>
+#include <com/sun/star/sdbc/XColumnLocate.hpp>
+#include <com/sun/star/sdbc/XConnection.hpp>
+#include <com/sun/star/sdbc/XDatabaseMetaData.hpp>
+#include <com/sun/star/sdbc/XResultSetMetaData.hpp>
+#include <com/sun/star/sdbc/XRow.hpp>
+#include <com/sun/star/sdbcx/XAppend.hpp>
+#include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
+#include <com/sun/star/sdbcx/XDataDescriptorFactory.hpp>
+#include <com/sun/star/sdbcx/XDrop.hpp>
+#include <com/sun/star/sdbcx/XRename.hpp>
+#include <com/sun/star/security/DocumentSignatureInformation.hpp>
+#include <com/sun/star/ucb/XCommandProcessor.hpp>
+#include <com/sun/star/ucb/XContent.hpp>
+#include <com/sun/star/uno/Any.h>
+#include <com/sun/star/uno/Any.hxx>
+#include <com/sun/star/uno/Reference.h>
+#include <com/sun/star/uno/Reference.hxx>
+#include <com/sun/star/uno/RuntimeException.hpp>
+#include <com/sun/star/uno/Sequence.h>
+#include <com/sun/star/uno/Sequence.hxx>
+#include <com/sun/star/uno/Type.h>
+#include <com/sun/star/uno/Type.hxx>
+#include <com/sun/star/uno/TypeClass.hdl>
+#include <com/sun/star/uno/XAggregation.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <com/sun/star/uno/XInterface.hpp>
+#include <com/sun/star/uno/XWeak.hpp>
+#include <com/sun/star/uno/genfunc.h>
+#include <com/sun/star/uno/genfunc.hxx>
+#include <com/sun/star/util/Date.hpp>
+#include <com/sun/star/util/XRefreshable.hpp>
+#include <comphelper/IdPropArrayHelper.hxx>
+#include <comphelper/broadcasthelper.hxx>
+#include <comphelper/comphelperdllapi.h>
+#include <comphelper/interfacecontainer2.hxx>
+#include <comphelper/namedvaluecollection.hxx>
+#include <comphelper/propagg.hxx>
+#include <comphelper/proparrhlp.hxx>
+#include <comphelper/property.hxx>
+#include <comphelper/propertycontainer.hxx>
+#include <comphelper/propertycontainerhelper.hxx>
+#include <comphelper/propstate.hxx>
+#include <comphelper/sequence.hxx>
+#include <comphelper/servicehelper.hxx>
+#include <comphelper/stl_types.hxx>
+#include <comphelper/types.hxx>
+#include <comphelper/uno3.hxx>
+#include <connectivity/CommonTools.hxx>
+#include <connectivity/IParseContext.hxx>
+#include <connectivity/dbexception.hxx>
+#include <connectivity/dbtools.hxx>
+#include <connectivity/dbtoolsdllapi.hxx>
+#include <connectivity/sdbcx/VDescriptor.hxx>
+#include <connectivity/sqlerror.hxx>
+#include <cppu/cppudllapi.h>
+#include <cppu/unotype.hxx>
+#include <cppuhelper/basemutex.hxx>
+#include <cppuhelper/compbase.hxx>
+#include <cppuhelper/compbase_ex.hxx>
+#include <cppuhelper/cppuhelperdllapi.h>
+#include <cppuhelper/exc_hlp.hxx>
+#include <cppuhelper/implbase.hxx>
+#include <cppuhelper/implbase1.hxx>
+#include <cppuhelper/implbase10.hxx>
+#include <cppuhelper/implbase_ex.hxx>
+#include <cppuhelper/implbase_ex_post.hxx>
+#include <cppuhelper/implbase_ex_pre.hxx>
+#include <cppuhelper/interfacecontainer.h>
+#include <cppuhelper/propshlp.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <cppuhelper/typeprovider.hxx>
+#include <cppuhelper/weak.hxx>
+#include <cppuhelper/weakagg.hxx>
+#include <cppuhelper/weakref.hxx>
+#include <i18nlangtag/lang.h>
+#include <o3tl/cow_wrapper.hxx>
+#include <o3tl/strong_int.hxx>
+#include <o3tl/typed_flags_set.hxx>
+#include <o3tl/underlyingenumvalue.hxx>
+#include <salhelper/salhelperdllapi.h>
+#include <salhelper/simplereferenceobject.hxx>
+#include <salhelper/singletonref.hxx>
+#include <salhelper/thread.hxx>
+#include <sfx2/dllapi.h>
+#include <svl/hint.hxx>
+#include <svl/lstner.hxx>
+#include <svl/svldllapi.h>
+#include <tools/color.hxx>
+#include <tools/degree.hxx>
+#include <tools/diagnose_ex.h>
+#include <tools/gen.hxx>
+#include <tools/link.hxx>
+#include <tools/long.hxx>
+#include <tools/mapunit.hxx>
+#include <tools/ref.hxx>
+#include <tools/solar.h>
+#include <tools/toolsdllapi.h>
+#include <typelib/typeclass.h>
+#include <typelib/typedescription.h>
+#include <typelib/uik.h>
+#include <uno/any2.h>
+#include <uno/data.h>
+#include <uno/sequence2.h>
+#include <unotools/unotoolsdllapi.h>
+#endif // PCH_LEVEL >= 3
+#if PCH_LEVEL >= 4
+#include <ContainerMediator.hxx>
+#include <apitools.hxx>
+#include <column.hxx>
+#include <core_resource.hxx>
+#include <sdbcoretools.hxx>
+#include <stringconstants.hxx>
+#include <strings.hxx>
+#endif // PCH_LEVEL >= 4
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/inc/pch/precompiled_dbahsql.cxx b/dbaccess/inc/pch/precompiled_dbahsql.cxx
new file mode 100644
index 000000000..b56d7b232
--- /dev/null
+++ b/dbaccess/inc/pch/precompiled_dbahsql.cxx
@@ -0,0 +1,12 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "precompiled_dbahsql.hxx"
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/inc/pch/precompiled_dbahsql.hxx b/dbaccess/inc/pch/precompiled_dbahsql.hxx
new file mode 100644
index 000000000..dbc9bdfeb
--- /dev/null
+++ b/dbaccess/inc/pch/precompiled_dbahsql.hxx
@@ -0,0 +1,56 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+/*
+ This file has been autogenerated by update_pch.sh. It is possible to edit it
+ manually (such as when an include file has been moved/renamed/removed). All such
+ manual changes will be rewritten by the next run of update_pch.sh (which presumably
+ also fixes all possible problems, so it's usually better to use it).
+
+ Generated on 2021-03-08 13:13:00 using:
+ ./bin/update_pch dbaccess dbahsql --cutoff=1 --exclude:system --include:module --include:local
+
+ If after updating build fails, use the following command to locate conflicting headers:
+ ./bin/update_pch_bisect ./dbaccess/inc/pch/precompiled_dbahsql.hxx "make dbaccess.build" --find-conflicts
+*/
+
+#include <sal/config.h>
+#if PCH_LEVEL >= 1
+#include <string_view>
+#include <boost/date_time/posix_time/posix_time.hpp>
+#endif // PCH_LEVEL >= 1
+#if PCH_LEVEL >= 2
+#include <rtl/ustrbuf.hxx>
+#include <sal/log.hxx>
+#include <vcl/weld.hxx>
+#endif // PCH_LEVEL >= 2
+#if PCH_LEVEL >= 3
+#include <com/sun/star/embed/ElementModes.hpp>
+#include <com/sun/star/embed/XStorage.hpp>
+#include <com/sun/star/io/TextInputStream.hpp>
+#include <com/sun/star/io/WrongFormatException.hpp>
+#include <com/sun/star/io/XInputStream.hpp>
+#include <com/sun/star/sdbc/DataType.hpp>
+#include <com/sun/star/sdbc/SQLException.hpp>
+#include <com/sun/star/sdbc/XConnection.hpp>
+#include <com/sun/star/sdbc/XParameters.hpp>
+#include <com/sun/star/util/Date.hpp>
+#include <com/sun/star/util/DateTime.hpp>
+#include <com/sun/star/util/Time.hpp>
+#include <comphelper/processfactory.hxx>
+#include <comphelper/string.hxx>
+#include <connectivity/dbexception.hxx>
+#include <connectivity/dbtools.hxx>
+#include <tools/stream.hxx>
+#include <unotools/ucbstreamhelper.hxx>
+#endif // PCH_LEVEL >= 3
+#if PCH_LEVEL >= 4
+#endif // PCH_LEVEL >= 4
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/inc/pch/precompiled_dbaxml.cxx b/dbaccess/inc/pch/precompiled_dbaxml.cxx
new file mode 100644
index 000000000..3fd8cf9b6
--- /dev/null
+++ b/dbaccess/inc/pch/precompiled_dbaxml.cxx
@@ -0,0 +1,12 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "precompiled_dbaxml.hxx"
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/inc/pch/precompiled_dbaxml.hxx b/dbaccess/inc/pch/precompiled_dbaxml.hxx
new file mode 100644
index 000000000..fc06290f4
--- /dev/null
+++ b/dbaccess/inc/pch/precompiled_dbaxml.hxx
@@ -0,0 +1,107 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+/*
+ This file has been autogenerated by update_pch.sh. It is possible to edit it
+ manually (such as when an include file has been moved/renamed/removed). All such
+ manual changes will be rewritten by the next run of update_pch.sh (which presumably
+ also fixes all possible problems, so it's usually better to use it).
+
+ Generated on 2021-03-08 13:13:03 using:
+ ./bin/update_pch dbaccess dbaxml --cutoff=2 --exclude:system --exclude:module --exclude:local
+
+ If after updating build fails, use the following command to locate conflicting headers:
+ ./bin/update_pch_bisect ./dbaccess/inc/pch/precompiled_dbaxml.hxx "make dbaccess.build" --find-conflicts
+*/
+
+#include <sal/config.h>
+#if PCH_LEVEL >= 1
+#include <cassert>
+#include <cstddef>
+#include <cstring>
+#include <functional>
+#include <limits>
+#include <memory>
+#include <new>
+#include <string_view>
+#include <type_traits>
+#include <utility>
+#include <vector>
+#endif // PCH_LEVEL >= 1
+#if PCH_LEVEL >= 2
+#include <osl/diagnose.h>
+#include <rtl/instance.hxx>
+#include <rtl/ref.hxx>
+#include <rtl/strbuf.hxx>
+#include <rtl/stringconcat.hxx>
+#include <rtl/stringutils.hxx>
+#include <rtl/uri.hxx>
+#include <rtl/ustrbuf.h>
+#include <rtl/ustrbuf.hxx>
+#include <rtl/ustring.hxx>
+#include <sal/log.hxx>
+#include <sal/types.h>
+#include <vcl/dllapi.h>
+#include <vcl/svapp.hxx>
+#endif // PCH_LEVEL >= 2
+#if PCH_LEVEL >= 3
+#include <com/sun/star/awt/TextAlign.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/container/XNameContainer.hpp>
+#include <com/sun/star/embed/ElementModes.hpp>
+#include <com/sun/star/frame/XModel.hpp>
+#include <com/sun/star/io/XInputStream.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/lang/XTypeProvider.hpp>
+#include <com/sun/star/sdb/XFormDocumentsSupplier.hpp>
+#include <com/sun/star/sdb/XOfficeDatabaseDocument.hpp>
+#include <com/sun/star/sdb/XQueryDefinitionsSupplier.hpp>
+#include <com/sun/star/sdb/XReportDocumentsSupplier.hpp>
+#include <com/sun/star/sdbcx/XDataDescriptorFactory.hpp>
+#include <com/sun/star/sdbcx/XTablesSupplier.hpp>
+#include <com/sun/star/uno/Any.h>
+#include <com/sun/star/uno/Reference.h>
+#include <com/sun/star/uno/Reference.hxx>
+#include <com/sun/star/uno/Sequence.h>
+#include <com/sun/star/uno/Sequence.hxx>
+#include <com/sun/star/uno/Type.h>
+#include <com/sun/star/util/XNumberFormatsSupplier.hpp>
+#include <comphelper/comphelperdllapi.h>
+#include <comphelper/namedvaluecollection.hxx>
+#include <comphelper/propertysequence.hxx>
+#include <comphelper/sequence.hxx>
+#include <comphelper/types.hxx>
+#include <connectivity/DriversConfig.hxx>
+#include <connectivity/dbtools.hxx>
+#include <cppuhelper/cppuhelperdllapi.h>
+#include <cppuhelper/implbase.hxx>
+#include <cppuhelper/implbase_ex.hxx>
+#include <cppuhelper/weak.hxx>
+#include <o3tl/typed_flags_set.hxx>
+#include <salhelper/simplereferenceobject.hxx>
+#include <sax/tools/converter.hxx>
+#include <sfx2/docfile.hxx>
+#include <svl/filenotation.hxx>
+#include <tools/diagnose_ex.h>
+#include <unotools/pathoptions.hxx>
+#include <xmloff/ProgressBarHelper.hxx>
+#include <xmloff/dllapi.h>
+#include <xmloff/families.hxx>
+#include <xmloff/maptype.hxx>
+#include <xmloff/namespacemap.hxx>
+#include <xmloff/xmlictxt.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/xmluconv.hxx>
+#endif // PCH_LEVEL >= 3
+#if PCH_LEVEL >= 4
+#endif // PCH_LEVEL >= 4
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/inc/pch/precompiled_dbu.cxx b/dbaccess/inc/pch/precompiled_dbu.cxx
new file mode 100644
index 000000000..dbfa961a5
--- /dev/null
+++ b/dbaccess/inc/pch/precompiled_dbu.cxx
@@ -0,0 +1,12 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "precompiled_dbu.hxx"
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/inc/pch/precompiled_dbu.hxx b/dbaccess/inc/pch/precompiled_dbu.hxx
new file mode 100644
index 000000000..9bfc030bc
--- /dev/null
+++ b/dbaccess/inc/pch/precompiled_dbu.hxx
@@ -0,0 +1,247 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+/*
+ This file has been autogenerated by update_pch.sh. It is possible to edit it
+ manually (such as when an include file has been moved/renamed/removed). All such
+ manual changes will be rewritten by the next run of update_pch.sh (which presumably
+ also fixes all possible problems, so it's usually better to use it).
+
+ Generated on 2021-09-12 11:51:31 using:
+ ./bin/update_pch dbaccess dbu --cutoff=12 --exclude:system --exclude:module --exclude:local
+
+ If after updating build fails, use the following command to locate conflicting headers:
+ ./bin/update_pch_bisect ./dbaccess/inc/pch/precompiled_dbu.hxx "make dbaccess.build" --find-conflicts
+*/
+
+#include <sal/config.h>
+#if PCH_LEVEL >= 1
+#include <algorithm>
+#include <cassert>
+#include <cstddef>
+#include <cstdlib>
+#include <cstring>
+#include <deque>
+#include <functional>
+#include <limits>
+#include <map>
+#include <memory>
+#include <mutex>
+#include <new>
+#include <optional>
+#include <ostream>
+#include <string_view>
+#include <type_traits>
+#include <unordered_map>
+#include <utility>
+#include <vector>
+#include <boost/property_tree/ptree_fwd.hpp>
+#endif // PCH_LEVEL >= 1
+#if PCH_LEVEL >= 2
+#include <osl/diagnose.h>
+#include <osl/endian.h>
+#include <osl/file.hxx>
+#include <osl/interlck.h>
+#include <osl/mutex.h>
+#include <osl/mutex.hxx>
+#include <osl/process.h>
+#include <osl/thread.hxx>
+#include <rtl/bootstrap.hxx>
+#include <rtl/instance.hxx>
+#include <rtl/math.h>
+#include <rtl/ref.hxx>
+#include <rtl/strbuf.hxx>
+#include <rtl/string.hxx>
+#include <rtl/stringconcat.hxx>
+#include <rtl/stringutils.hxx>
+#include <rtl/tencinfo.h>
+#include <rtl/textenc.h>
+#include <rtl/ustrbuf.h>
+#include <rtl/ustrbuf.hxx>
+#include <rtl/ustring.h>
+#include <rtl/ustring.hxx>
+#include <rtl/uuid.h>
+#include <sal/detail/log.h>
+#include <sal/log.hxx>
+#include <sal/types.h>
+#include <vcl/IDialogRenderable.hxx>
+#include <vcl/InterimItemWindow.hxx>
+#include <vcl/Scanline.hxx>
+#include <vcl/alpha.hxx>
+#include <vcl/bitmap.hxx>
+#include <vcl/bitmapex.hxx>
+#include <vcl/cairo.hxx>
+#include <vcl/ctrl.hxx>
+#include <vcl/devicecoordinate.hxx>
+#include <vcl/dllapi.h>
+#include <vcl/event.hxx>
+#include <vcl/font.hxx>
+#include <vcl/gradient.hxx>
+#include <vcl/idle.hxx>
+#include <vcl/keycodes.hxx>
+#include <vcl/mapmod.hxx>
+#include <vcl/metaactiontypes.hxx>
+#include <vcl/outdev.hxx>
+#include <vcl/region.hxx>
+#include <vcl/rendercontext/AddFontSubstituteFlags.hxx>
+#include <vcl/rendercontext/AntialiasingFlags.hxx>
+#include <vcl/rendercontext/DrawGridFlags.hxx>
+#include <vcl/rendercontext/DrawImageFlags.hxx>
+#include <vcl/rendercontext/DrawModeFlags.hxx>
+#include <vcl/rendercontext/DrawTextFlags.hxx>
+#include <vcl/rendercontext/GetDefaultFontFlags.hxx>
+#include <vcl/rendercontext/ImplMapRes.hxx>
+#include <vcl/rendercontext/InvertFlags.hxx>
+#include <vcl/rendercontext/RasterOp.hxx>
+#include <vcl/rendercontext/SalLayoutFlags.hxx>
+#include <vcl/rendercontext/State.hxx>
+#include <vcl/rendercontext/SystemTextColorFlags.hxx>
+#include <vcl/salnativewidgets.hxx>
+#include <vcl/settings.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/timer.hxx>
+#include <vcl/transfer.hxx>
+#include <vcl/uitest/factory.hxx>
+#include <vcl/vclenum.hxx>
+#include <vcl/vclptr.hxx>
+#include <vcl/vclreferencebase.hxx>
+#include <vcl/wall.hxx>
+#include <vcl/weld.hxx>
+#include <vcl/window.hxx>
+#endif // PCH_LEVEL >= 2
+#if PCH_LEVEL >= 3
+#include <basegfx/color/bcolor.hxx>
+#include <basegfx/numeric/ftools.hxx>
+#include <basegfx/polygon/b2dpolypolygon.hxx>
+#include <basegfx/vector/b2enums.hxx>
+#include <com/sun/star/awt/DeviceInfo.hpp>
+#include <com/sun/star/beans/NamedValue.hpp>
+#include <com/sun/star/beans/PropertyValue.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/container/XIndexAccess.hpp>
+#include <com/sun/star/container/XNameAccess.hpp>
+#include <com/sun/star/datatransfer/DataFlavor.hpp>
+#include <com/sun/star/datatransfer/XTransferable2.hpp>
+#include <com/sun/star/datatransfer/clipboard/XClipboard.hpp>
+#include <com/sun/star/datatransfer/clipboard/XClipboardOwner.hpp>
+#include <com/sun/star/datatransfer/dnd/DNDConstants.hpp>
+#include <com/sun/star/datatransfer/dnd/DropTargetDragEvent.hpp>
+#include <com/sun/star/datatransfer/dnd/DropTargetDropEvent.hpp>
+#include <com/sun/star/datatransfer/dnd/XDragGestureListener.hpp>
+#include <com/sun/star/datatransfer/dnd/XDragSourceListener.hpp>
+#include <com/sun/star/datatransfer/dnd/XDropTargetListener.hpp>
+#include <com/sun/star/drawing/LineCap.hpp>
+#include <com/sun/star/embed/Aspects.hpp>
+#include <com/sun/star/frame/FrameAction.hpp>
+#include <com/sun/star/frame/XController2.hpp>
+#include <com/sun/star/frame/XDispatch.hpp>
+#include <com/sun/star/frame/XLayoutManager.hpp>
+#include <com/sun/star/frame/XStatusListener.hpp>
+#include <com/sun/star/frame/XTerminateListener.hpp>
+#include <com/sun/star/frame/XTitle.hpp>
+#include <com/sun/star/frame/XTitleChangeBroadcaster.hpp>
+#include <com/sun/star/lang/EventObject.hpp>
+#include <com/sun/star/lang/Locale.hpp>
+#include <com/sun/star/lang/XInitialization.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/lang/XTypeProvider.hpp>
+#include <com/sun/star/lang/XUnoTunnel.hpp>
+#include <com/sun/star/sdb/CommandType.hpp>
+#include <com/sun/star/sdbc/ColumnSearch.hpp>
+#include <com/sun/star/sdbc/DataType.hpp>
+#include <com/sun/star/sdbc/SQLException.hpp>
+#include <com/sun/star/sdbc/XConnection.hpp>
+#include <com/sun/star/sdbc/XDatabaseMetaData.hpp>
+#include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
+#include <com/sun/star/sdbcx/XTablesSupplier.hpp>
+#include <com/sun/star/task/InteractionHandler.hpp>
+#include <com/sun/star/uno/Any.h>
+#include <com/sun/star/uno/Any.hxx>
+#include <com/sun/star/uno/Reference.h>
+#include <com/sun/star/uno/Reference.hxx>
+#include <com/sun/star/uno/Sequence.h>
+#include <com/sun/star/uno/Sequence.hxx>
+#include <com/sun/star/uno/Type.h>
+#include <com/sun/star/uno/XAggregation.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <com/sun/star/uno/genfunc.hxx>
+#include <com/sun/star/util/URL.hpp>
+#include <com/sun/star/util/XNumberFormatter.hpp>
+#include <comphelper/comphelperdllapi.h>
+#include <comphelper/namedvaluecollection.hxx>
+#include <comphelper/sequence.hxx>
+#include <comphelper/types.hxx>
+#include <comphelper/uno3.hxx>
+#include <connectivity/dbexception.hxx>
+#include <connectivity/dbtools.hxx>
+#include <connectivity/dbtoolsdllapi.hxx>
+#include <cppu/unotype.hxx>
+#include <cppuhelper/compbase.hxx>
+#include <cppuhelper/exc_hlp.hxx>
+#include <cppuhelper/implbase.hxx>
+#include <cppuhelper/implbase_ex.hxx>
+#include <cppuhelper/weak.hxx>
+#include <cppuhelper/weakref.hxx>
+#include <o3tl/typed_flags_set.hxx>
+#include <salhelper/simplereferenceobject.hxx>
+#include <salhelper/singletonref.hxx>
+#include <sfx2/dllapi.h>
+#include <sot/exchange.hxx>
+#include <sot/formats.hxx>
+#include <sot/sotdllapi.h>
+#include <svl/hint.hxx>
+#include <svl/itemset.hxx>
+#include <svl/poolitem.hxx>
+#include <svl/stritem.hxx>
+#include <svl/svldllapi.h>
+#include <svl/typedwhich.hxx>
+#include <svtools/svtdllapi.h>
+#include <svx/svxdllapi.h>
+#include <toolkit/helper/vclunohelper.hxx>
+#include <tools/color.hxx>
+#include <tools/degree.hxx>
+#include <tools/diagnose_ex.h>
+#include <tools/gen.hxx>
+#include <tools/globname.hxx>
+#include <tools/link.hxx>
+#include <tools/long.hxx>
+#include <tools/mapunit.hxx>
+#include <tools/poly.hxx>
+#include <tools/ref.hxx>
+#include <tools/solar.h>
+#include <tools/toolsdllapi.h>
+#include <tools/wintypes.hxx>
+#include <typelib/typedescription.h>
+#include <uno/data.h>
+#include <unotools/eventlisteneradapter.hxx>
+#include <unotools/fontdefs.hxx>
+#include <unotools/resmgr.hxx>
+#include <unotools/sharedunocomponent.hxx>
+#include <unotools/unotoolsdllapi.h>
+#endif // PCH_LEVEL >= 3
+#if PCH_LEVEL >= 4
+#include <FieldDescriptions.hxx>
+#include <IClipBoardTest.hxx>
+#include <QEnumTypes.hxx>
+#include <TableConnectionData.hxx>
+#include <TableWindowData.hxx>
+#include <TypeInfo.hxx>
+#include <UITools.hxx>
+#include <browserids.hxx>
+#include <callbacks.hxx>
+#include <dbaccess/AsynchronousLink.hxx>
+#include <dbaccess/IController.hxx>
+#include <dbaccess/controllerframe.hxx>
+#include <dbaccess/dataview.hxx>
+#include <dbaccess/dbaccessdllapi.h>
+#include <dsitems.hxx>
+#include <sqlmessage.hxx>
+#endif // PCH_LEVEL >= 4
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/inc/pch/precompiled_sdbt.cxx b/dbaccess/inc/pch/precompiled_sdbt.cxx
new file mode 100644
index 000000000..26650079d
--- /dev/null
+++ b/dbaccess/inc/pch/precompiled_sdbt.cxx
@@ -0,0 +1,12 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "precompiled_sdbt.hxx"
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/inc/pch/precompiled_sdbt.hxx b/dbaccess/inc/pch/precompiled_sdbt.hxx
new file mode 100644
index 000000000..f691c1fa5
--- /dev/null
+++ b/dbaccess/inc/pch/precompiled_sdbt.hxx
@@ -0,0 +1,48 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+/*
+ This file has been autogenerated by update_pch.sh. It is possible to edit it
+ manually (such as when an include file has been moved/renamed/removed). All such
+ manual changes will be rewritten by the next run of update_pch.sh (which presumably
+ also fixes all possible problems, so it's usually better to use it).
+
+ Generated on 2021-03-08 13:13:17 using:
+ ./bin/update_pch dbaccess sdbt --cutoff=1 --exclude:system --include:module --exclude:local
+
+ If after updating build fails, use the following command to locate conflicting headers:
+ ./bin/update_pch_bisect ./dbaccess/inc/pch/precompiled_sdbt.hxx "make dbaccess.build" --find-conflicts
+*/
+
+#include <sal/config.h>
+#if PCH_LEVEL >= 1
+#include <memory>
+#endif // PCH_LEVEL >= 1
+#if PCH_LEVEL >= 2
+#include <osl/diagnose.h>
+#endif // PCH_LEVEL >= 2
+#if PCH_LEVEL >= 3
+#include <com/sun/star/sdb/CommandType.hpp>
+#include <com/sun/star/sdb/ErrorCondition.hpp>
+#include <com/sun/star/sdb/XQueriesSupplier.hpp>
+#include <com/sun/star/sdb/tools/CompositionType.hpp>
+#include <com/sun/star/sdbcx/XTablesSupplier.hpp>
+#include <comphelper/namedvaluecollection.hxx>
+#include <connectivity/dbmetadata.hxx>
+#include <connectivity/dbtools.hxx>
+#include <connectivity/sqlerror.hxx>
+#include <connectivity/statementcomposer.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <tools/diagnose_ex.h>
+#endif // PCH_LEVEL >= 3
+#if PCH_LEVEL >= 4
+#include <connectiontools.hxx>
+#endif // PCH_LEVEL >= 4
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/inc/query.hrc b/dbaccess/inc/query.hrc
new file mode 100644
index 000000000..e183f777c
--- /dev/null
+++ b/dbaccess/inc/query.hrc
@@ -0,0 +1,35 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_VCL_INC_PRINTACCESSORYVIEW_HRC
+#define INCLUDED_VCL_INC_PRINTACCESSORYVIEW_HRC
+
+#include <unotools/resmgr.hxx>
+
+#define NC_(Context, String) TranslateId(Context, reinterpret_cast<char const *>(u8##String))
+
+const TranslateId RSC_QUERY_OBJECT_TYPE[] =
+{
+ NC_("RSC_QUERY_OBJECT_TYPE", "The table view"),
+ NC_("RSC_QUERY_OBJECT_TYPE", "The query"),
+ NC_("RSC_QUERY_OBJECT_TYPE", "The SQL statement")
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/inc/strings.hrc b/dbaccess/inc/strings.hrc
new file mode 100644
index 000000000..ea57f4ebd
--- /dev/null
+++ b/dbaccess/inc/strings.hrc
@@ -0,0 +1,455 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef INCLUDED_DBACCESS_SOURCE_CORE_INC_CORE_RESOURCE_HRC
+#define INCLUDED_DBACCESS_SOURCE_CORE_INC_CORE_RESOURCE_HRC
+
+#include <unotools/resmgr.hxx>
+
+#define NC_(Context, String) TranslateId(Context, reinterpret_cast<char const *>(u8##String))
+
+#define RID_STR_CONNECTION_INVALID NC_("RID_STR_CONNECTION_INVALID", "No connection could be established.")
+#define RID_STR_TABLE_IS_FILTERED NC_("RID_STR_TABLE_IS_FILTERED", "The table $name$ already exists. It is not visible because it has been filtered out.")
+#define RID_STR_COULDNOTCONNECT_UNSPECIFIED NC_("RID_STR_COULDNOTCONNECT_UNSPECIFIED", "The connection to the external data source could not be established. An unknown error occurred. The driver is probably defective.")
+#define RID_STR_COULDNOTCONNECT_NODRIVER NC_("RID_STR_COULDNOTCONNECT_NODRIVER", "The connection to the external data source could not be established. No SDBC driver was found for the URL '$name$'.")
+#define RID_STR_COULDNOTLOAD_MANAGER NC_("RID_STR_COULDNOTLOAD_MANAGER", "The connection to the external data source could not be established. The SDBC driver manager could not be loaded.")
+#define RID_STR_FORM NC_("RID_STR_FORM", "Form")
+#define RID_STR_REPORT NC_("RID_STR_REPORT", "Report")
+#define RID_STR_DATASOURCE_NOT_STORED NC_("RID_STR_DATASOURCE_NOT_STORED", "The data source was not saved. Please use the interface XStorable to save the data source.")
+#define RID_STR_ONLY_QUERY NC_("RID_STR_ONLY_QUERY", "The given command is not a SELECT statement.\nOnly queries are allowed.")
+#define RID_STR_NO_VALUE_CHANGED NC_("RID_STR_NO_VALUE_CHANGED", "No values were modified.")
+#define RID_STR_NO_XROWUPDATE NC_("RID_STR_NO_XROWUPDATE", "Values could not be inserted. The XRowUpdate interface is not supported by ResultSet.")
+#define RID_STR_NO_XRESULTSETUPDATE NC_("RID_STR_NO_XRESULTSETUPDATE", "Values could not be inserted. The XResultSetUpdate interface is not supported by ResultSet.")
+#define RID_STR_NO_UPDATE_MISSING_CONDITION NC_("RID_STR_NO_UPDATE_MISSING_CONDITION", "Values could not be modified, due to a missing condition statement.")
+#define RID_STR_NO_COLUMN_ADD NC_("RID_STR_NO_COLUMN_ADD", "The adding of columns is not supported.")
+#define RID_STR_NO_COLUMN_DROP NC_("RID_STR_NO_COLUMN_DROP", "The dropping of columns is not supported.")
+#define RID_STR_NO_CONDITION_FOR_PK NC_("RID_STR_NO_CONDITION_FOR_PK", "The WHERE condition could not be created for the primary key.")
+#define RID_STR_COLUMN_UNKNOWN_PROP NC_("RID_STR_COLUMN_UNKNOWN_PROP", "The column does not support the property '%value'.")
+#define RID_STR_COLUMN_NOT_SEARCHABLE NC_("RID_STR_COLUMN_NOT_SEARCHABLE", "The column is not searchable!")
+#define RID_STR_NOT_SEQUENCE_INT8 NC_("RID_STR_NOT_SEQUENCE_INT8", "The value of the columns is not of the type Sequence<sal_Int8>.")
+#define RID_STR_COLUMN_NOT_VALID NC_("RID_STR_COLUMN_NOT_VALID", "The column is not valid.")
+#define RID_STR_COLUMN_MUST_VISIBLE NC_("RID_STR_COLUMN_MUST_VISIBLE", "The column '%name' must be visible as a column.")
+#define RID_STR_NO_XQUERIESSUPPLIER NC_("RID_STR_NO_XQUERIESSUPPLIER", "The interface XQueriesSupplier is not available.")
+#define RID_STR_NO_ABS_ZERO NC_("RID_STR_NO_ABS_ZERO", "An 'absolute(0)' call is not allowed.")
+#define RID_STR_NO_RELATIVE NC_("RID_STR_NO_RELATIVE", "Relative positioning is not allowed in this state.")
+#define RID_STR_NO_REFRESH_AFTERLAST NC_("RID_STR_NO_REFRESH_AFTERLAST", "A row cannot be refreshed when the ResultSet is positioned after the last row.")
+#define RID_STR_NO_MOVETOINSERTROW_CALLED NC_("RID_STR_NO_MOVETOINSERTROW_CALLED", "A new row cannot be inserted when the ResultSet is not first moved to the insert row.")
+#define RID_STR_NO_UPDATEROW NC_("RID_STR_NO_UPDATEROW", "A row cannot be modified in this state")
+#define RID_STR_NO_DELETEROW NC_("RID_STR_NO_DELETEROW", "A row cannot be deleted in this state.")
+#define RID_STR_NO_TABLE_RENAME NC_("RID_STR_NO_TABLE_RENAME", "The driver does not support table renaming.")
+#define RID_STR_COLUMN_ALTER_BY_NAME NC_("RID_STR_COLUMN_ALTER_BY_NAME", "The driver does not support the modification of column descriptions by changing the name.")
+#define RID_STR_COLUMN_ALTER_BY_INDEX NC_("RID_STR_COLUMN_ALTER_BY_INDEX", "The driver does not support the modification of column descriptions by changing the index.")
+#define RID_STR_FILE_DOES_NOT_EXIST NC_("RID_STR_FILE_DOES_NOT_EXIST", "The file \"$file$\" does not exist.")
+#define RID_STR_TABLE_DOES_NOT_EXIST NC_("RID_STR_TABLE_DOES_NOT_EXIST", "There exists no table named \"$table$\".")
+#define RID_STR_QUERY_DOES_NOT_EXIST NC_("RID_STR_QUERY_DOES_NOT_EXIST", "There exists no query named \"$table$\".")
+#define RID_STR_CONFLICTING_NAMES NC_("RID_STR_CONFLICTING_NAMES", "There are tables in the database whose names conflict with the names of existing queries. To make full use of all queries and tables, make sure they have distinct names.")
+#define RID_STR_COMMAND_LEADING_TO_ERROR NC_("RID_STR_COMMAND_LEADING_TO_ERROR", "The SQL command leading to this error is:\n\n$command$")
+#define RID_STR_STATEMENT_WITHOUT_RESULT_SET NC_("RID_STR_STATEMENT_WITHOUT_RESULT_SET", "The SQL command does not describe a result set.")
+#define RID_STR_NAME_MUST_NOT_BE_EMPTY NC_("RID_STR_NAME_MUST_NOT_BE_EMPTY", "The name must not be empty.")
+#define RID_STR_NO_NULL_OBJECTS_IN_CONTAINER NC_("RID_STR_NO_NULL_OBJECTS_IN_CONTAINER", "The container cannot contain NULL objects.")
+#define RID_STR_NAME_ALREADY_USED NC_("RID_STR_NAME_ALREADY_USED", "There already is an object with the given name.")
+#define RID_STR_OBJECT_CONTAINER_MISMATCH NC_("RID_STR_OBJECT_CONTAINER_MISMATCH", "This object cannot be part of this container.")
+#define RID_STR_OBJECT_ALREADY_CONTAINED NC_("RID_STR_OBJECT_ALREADY_CONTAINED", "The object already is, with a different name, part of the container.")
+#define RID_STR_NAME_NOT_FOUND NC_("RID_STR_NAME_NOT_FOUND", "Unable to find the document '$name$'.")
+#define RID_STR_ERROR_WHILE_SAVING NC_("RID_STR_ERROR_WHILE_SAVING", "Could not save the document to $location$:\n$message$")
+#define RID_NO_SUCH_DATA_SOURCE NC_("RID_NO_SUCH_DATA_SOURCE", "Error accessing data source '$name$':\n$error$")
+#define RID_STR_NO_SUB_FOLDER NC_("RID_STR_NO_SUB_FOLDER", "There exists no folder named \"$folder$\".")
+#define RID_STR_NO_DELETE_BEFORE_AFTER NC_("RID_STR_NO_DELETE_BEFORE_AFTER", "Cannot delete the before-first or after-last row.")
+#define RID_STR_NO_DELETE_INSERT_ROW NC_("RID_STR_NO_DELETE_INSERT_ROW", "Cannot delete the insert-row.")
+#define RID_STR_RESULT_IS_READONLY NC_("RID_STR_RESULT_IS_READONLY", "Result set is read only.")
+#define RID_STR_NO_DELETE_PRIVILEGE NC_("RID_STR_NO_DELETE_PRIVILEGE", "DELETE privilege not available.")
+#define RID_STR_ROW_ALREADY_DELETED NC_("RID_STR_ROW_ALREADY_DELETED", "Current row is already deleted.")
+#define RID_STR_UPDATE_FAILED NC_("RID_STR_UPDATE_FAILED", "Current row could not be updated.")
+#define RID_STR_NO_INSERT_PRIVILEGE NC_("RID_STR_NO_INSERT_PRIVILEGE", "INSERT privilege not available.")
+#define RID_STR_INTERNAL_ERROR NC_("RID_STR_INTERNAL_ERROR", "Internal error: no statement object provided by the database driver.")
+#define RID_STR_EXPRESSION1 NC_("RID_STR_EXPRESSION1", "Expression1")
+#define RID_STR_NO_SQL_COMMAND NC_("RID_STR_NO_SQL_COMMAND", "No SQL command was provided.")
+#define RID_STR_INVALID_INDEX NC_("RID_STR_INVALID_INDEX", "Invalid column index.")
+#define RID_STR_INVALID_CURSOR_STATE NC_("RID_STR_INVALID_CURSOR_STATE", "Invalid cursor state.")
+#define RID_STR_CURSOR_BEFORE_OR_AFTER NC_("RID_STR_CURSOR_BEFORE_OR_AFTER", "The cursor points to before the first or after the last row.")
+#define RID_STR_NO_BOOKMARK_BEFORE_OR_AFTER NC_("RID_STR_NO_BOOKMARK_BEFORE_OR_AFTER", "The rows before the first and after the last row don't have a bookmark.")
+#define RID_STR_NO_BOOKMARK_DELETED NC_("RID_STR_NO_BOOKMARK_DELETED", "The current row is deleted, and thus doesn't have a bookmark.")
+#define RID_STR_CONNECTION_REQUEST NC_("RID_STR_CONNECTION_REQUEST", "A connection for the following URL was requested \"$name$\".")
+#define RID_STR_MISSING_EXTENSION NC_("RID_STR_MISSING_EXTENSION", "The extension is not installed.")
+
+#define STR_QUERY_AND_TABLE_DISTINCT_NAMES NC_("STR_QUERY_AND_TABLE_DISTINCT_NAMES", "You cannot give a table and a query the same name. Please use a name which is not yet used by a query or table.")
+#define STR_BASENAME_TABLE NC_("STR_BASENAME_TABLE", "Table")
+#define STR_BASENAME_QUERY NC_("STR_BASENAME_QUERY", "Query")
+#define STR_CONN_WITHOUT_QUERIES_OR_TABLES NC_("STR_CONN_WITHOUT_QUERIES_OR_TABLES", "The given connection is no valid query and/or tables supplier.")
+#define STR_NO_TABLE_OBJECT NC_("STR_NO_TABLE_OBJECT", "The given object is no table object.")
+#define STR_INVALID_COMPOSITION_TYPE NC_("STR_INVALID_COMPOSITION_TYPE", "Invalid composition type - need a value from com.sun.star.sdb.tools.CompositionType.")
+#define STR_INVALID_COMMAND_TYPE NC_("STR_INVALID_COMMAND_TYPE", "Invalid command type - only TABLE and QUERY from com.sun.star.sdb.CommandType are allowed.")
+
+#define STR_QUERY_UNDO_TABWINSHOW NC_("STR_QUERY_UNDO_TABWINSHOW", "Add Table Window" )
+#define STR_QUERY_UNDO_MOVETABWIN NC_("STR_QUERY_UNDO_MOVETABWIN", "Move table window" )
+#define STR_QUERY_UNDO_INSERTCONNECTION NC_("STR_QUERY_UNDO_INSERTCONNECTION", "Insert Join" )
+#define STR_QUERY_UNDO_REMOVECONNECTION NC_("STR_QUERY_UNDO_REMOVECONNECTION", "Delete Join" )
+#define STR_QUERY_UNDO_SIZETABWIN NC_("STR_QUERY_UNDO_SIZETABWIN", "Resize table window" )
+#define STR_QUERY_UNDO_TABFIELDDELETE NC_("STR_QUERY_UNDO_TABFIELDDELETE", "Delete Column" )
+#define STR_QUERY_UNDO_TABFIELDMOVED NC_("STR_QUERY_UNDO_TABFIELDMOVED", "Move column")
+#define STR_QUERY_UNDO_TABFIELDCREATE NC_("STR_QUERY_UNDO_TABFIELDCREATE", "Add Column" )
+#define RID_STR_FIELD_DOESNT_EXIST NC_("RID_STR_FIELD_DOESNT_EXIST", "Invalid expression, field name '$name$' does not exist.")
+#define STR_QUERY_UNDO_TABWINDELETE NC_("STR_QUERY_UNDO_TABWINDELETE", "Delete Table Window" )
+#define STR_QUERY_UNDO_MODIFY_CELL NC_("STR_QUERY_UNDO_MODIFY_CELL", "Edit Column Description")
+#define STR_QUERY_UNDO_SIZE_COLUMN NC_("STR_QUERY_UNDO_SIZE_COLUMN", "Adjust column width")
+#define STR_QUERY_SORTTEXT NC_("STR_QUERY_SORTTEXT", "(not sorted);ascending;descending" )
+#define STR_QUERY_FUNCTIONS NC_("STR_QUERY_FUNCTIONS", "(no function);Group")
+#define STR_QUERY_NOTABLE NC_("STR_QUERY_NOTABLE", "(no table)")
+#define STR_QRY_ORDERBY_UNRELATED NC_("STR_QRY_ORDERBY_UNRELATED", "The database only supports sorting for visible fields.")
+#define STR_QUERY_HANDLETEXT NC_("STR_QUERY_HANDLETEXT", "Field;Alias;Table;Sort;Visible;Function;Criterion;Or;Or")
+#define STR_QUERY_LIMIT_ALL NC_("STR_QUERY_LIMIT_ALL", "All")
+#define STR_QRY_TOO_MANY_COLUMNS NC_("STR_QRY_TOO_MANY_COLUMNS", "There are too many columns.")
+#define STR_QRY_CRITERIA_ON_ASTERISK NC_("STR_QRY_CRITERIA_ON_ASTERISK", "A condition cannot be applied to field [*]" )
+#define STR_QRY_TOO_LONG_STATEMENT NC_("STR_QRY_TOO_LONG_STATEMENT", "The SQL statement created is too long.")
+#define STR_QRY_TOOCOMPLEX NC_("STR_QRY_TOOCOMPLEX", "Query is too complex" )
+#define STR_QRY_NOSELECT NC_("STR_QRY_NOSELECT", "Nothing has been selected." )
+#define STR_QRY_SYNTAX NC_("STR_QRY_SYNTAX", "SQL syntax error" )
+#define STR_QRY_ORDERBY_ON_ASTERISK NC_("STR_QRY_ORDERBY_ON_ASTERISK", "[*] cannot be used as a sort criterion.")
+#define STR_QRY_TOO_MANY_TABLES NC_("STR_QRY_TOO_MANY_TABLES", "There are too many tables.")
+#define STR_QRY_NATIVE NC_("STR_QRY_NATIVE", "The statement will not be applied when querying in the SQL dialect of the database." )
+#define STR_QRY_ILLEGAL_JOIN NC_("STR_QRY_ILLEGAL_JOIN", "Join could not be processed" )
+#define STR_SVT_SQL_SYNTAX_ERROR NC_("STR_SVT_SQL_SYNTAX_ERROR", "Syntax error in SQL statement" )
+#define STR_QUERYDESIGN_NO_VIEW_SUPPORT NC_("STR_QUERYDESIGN_NO_VIEW_SUPPORT", "This database does not support table views.")
+#define STR_NO_ALTER_VIEW_SUPPORT NC_("STR_NO_ALTER_VIEW_SUPPORT", "This database does not support altering of existing table views.")
+#define STR_QUERYDESIGN_NO_VIEW_ASK NC_("STR_QUERYDESIGN_NO_VIEW_ASK", "Do you want to create a query instead?")
+#define STR_DATASOURCE_DELETED NC_("STR_DATASOURCE_DELETED", "The corresponding data source has been deleted. Therefore, data relevant to that data source cannot be saved.")
+#define STR_QRY_COLUMN_NOT_FOUND NC_("STR_QRY_COLUMN_NOT_FOUND", "The column '$name$' is unknown.")
+#define STR_QRY_JOIN_COLUMN_COMPARE NC_("STR_QRY_JOIN_COLUMN_COMPARE", "Columns can only be compared using '='.")
+#define STR_QRY_LIKE_LEFT_NO_COLUMN NC_("STR_QRY_LIKE_LEFT_NO_COLUMN", "You must use a column name before 'LIKE'.")
+#define STR_QRY_CHECK_CASESENSITIVE NC_("STR_QRY_CHECK_CASESENSITIVE", "The column could not be found. Please note that the database is case-sensitive.")
+// To translators: for $object$, one of the values of the RSC_QUERY_OBJECT_TYPE resource will be inserted.
+#define STR_QUERY_SAVEMODIFIED NC_("STR_QUERY_SAVEMODIFIED", "$object$ has been changed.\nDo you want to save the changes?" )
+// To translators: for $object$, one of the values of the RSC_QUERY_OBJECT_TYPE resource (except \"SQL command\", which doesn't make sense here) will be inserted.
+#define STR_ERROR_PARSING_STATEMENT NC_("STR_ERROR_PARSING_STATEMENT", "$object$ is based on an SQL command which could not be parsed.")
+// To translators: for $object$, one of the values of the RSC_QUERY_OBJECT_TYPE resource (except \"SQL command\", which doesn't make sense here) will be inserted.
+#define STR_INFO_OPENING_IN_SQL_VIEW NC_("STR_INFO_OPENING_IN_SQL_VIEW", "$object$ will be opened in SQL view.")
+#define STR_STATEMENT_WITHOUT_RESULT_SET NC_("STR_STATEMENT_WITHOUT_RESULT_SET", "The query does not create a result set, and thus cannot be part of another query.")
+
+#define RID_STR_COLUMN_FORMAT NC_("RID_STR_COLUMN_FORMAT", "Column ~Format...")
+#define RID_STR_COLUMN_WIDTH NC_("RID_STR_COLUMN_WIDTH", "Column ~Width...")
+#define RID_STR_TABLE_FORMAT NC_("RID_STR_TABLE_FORMAT", "Table Format...")
+#define RID_STR_ROW_HEIGHT NC_("RID_STR_ROW_HEIGHT", "Row Height...")
+#define RID_STR_COPY NC_("RID_STR_COPY", "~Copy")
+#define RID_STR_UNDO_MODIFY_RECORD NC_("RID_STR_UNDO_MODIFY_RECORD", "Undo: Data Input")
+#define RID_STR_SAVE_CURRENT_RECORD NC_("RID_STR_SAVE_CURRENT_RECORD", "Save current record")
+#define STR_QRY_TITLE NC_("STR_QRY_TITLE", "Query #" )
+#define STR_TBL_TITLE NC_("STR_TBL_TITLE", "Table #" )
+#define STR_VIEW_TITLE NC_("STR_VIEW_TITLE", "View #" )
+#define STR_NAME_ALREADY_EXISTS NC_("STR_NAME_ALREADY_EXISTS", "The name \"#\" already exists.")
+#define STR_NO_COLUMNNAME_MATCHING NC_("STR_NO_COLUMNNAME_MATCHING", "No matching column names were found.")
+#define STR_ERROR_OCCURRED_WHILE_COPYING NC_("STR_ERROR_OCCURRED_WHILE_COPYING", "An error occurred. Do you want to continue copying?")
+#define STR_DATASOURCE_GRIDCONTROL_NAME NC_("STR_DATASOURCE_GRIDCONTROL_NAME", "Data source table view")
+#define STR_DATASOURCE_GRIDCONTROL_DESC NC_("STR_DATASOURCE_GRIDCONTROL_DESC", "Shows the selected table or query.")
+
+#define STR_QUERY_UNDO_MODIFYSQLEDIT NC_("STR_QUERY_UNDO_MODIFYSQLEDIT", "Modify SQL statement(s)" )
+
+#define RID_STR_NEW_FORM NC_("RID_STR_NEW_FORM", "Create Form in Design View..." )
+#define RID_STR_NEW_FORM_AUTO NC_("RID_STR_NEW_FORM_AUTO", "Use Wizard to Create Form..." )
+#define RID_STR_NEW_REPORT_AUTO NC_("RID_STR_NEW_REPORT_AUTO", "Use Wizard to Create Report..." )
+#define RID_STR_NEW_REPORT NC_("RID_STR_NEW_REPORT", "Create Report in Design View..." )
+#define RID_STR_NEW_QUERY NC_("RID_STR_NEW_QUERY", "Create Query in Design View..." )
+#define RID_STR_NEW_QUERY_SQL NC_("RID_STR_NEW_QUERY_SQL", "Create Query in SQL View..." )
+#define RID_STR_NEW_QUERY_AUTO NC_("RID_STR_NEW_QUERY_AUTO", "Use Wizard to Create Query..." )
+#define RID_STR_NEW_TABLE NC_("RID_STR_NEW_TABLE", "Create Table in Design View..." )
+#define RID_STR_NEW_TABLE_AUTO NC_("RID_STR_NEW_TABLE_AUTO", "Use Wizard to Create Table..." )
+#define RID_STR_NEW_VIEW NC_("RID_STR_NEW_VIEW", "Create View..." )
+#define RID_STR_FORMS_CONTAINER NC_("RID_STR_FORMS_CONTAINER", "Forms" )
+#define RID_STR_REPORTS_CONTAINER NC_("RID_STR_REPORTS_CONTAINER", "Reports" )
+#define RID_STR_REPORTS_HELP_TEXT_WIZARD NC_("RID_STR_REPORTS_HELP_TEXT_WIZARD", "The wizard will guide you through the steps necessary to create a report." )
+#define RID_STR_FORMS_HELP_TEXT NC_("RID_STR_FORMS_HELP_TEXT", "Create a form by specifying the record source, controls, and control properties." )
+#define RID_STR_REPORT_HELP_TEXT NC_("RID_STR_REPORT_HELP_TEXT", "Create a report by specifying the record source, controls, and control properties." )
+#define RID_STR_FORMS_HELP_TEXT_WIZARD NC_("RID_STR_FORMS_HELP_TEXT_WIZARD", "The wizard will guide you through the steps necessary to create a form." )
+#define RID_STR_QUERIES_HELP_TEXT NC_("RID_STR_QUERIES_HELP_TEXT", "Create a query by specifying the filters, input tables, field names, and properties for sorting or grouping." )
+#define RID_STR_QUERIES_HELP_TEXT_SQL NC_("RID_STR_QUERIES_HELP_TEXT_SQL", "Create a query by entering an SQL statement directly." )
+#define RID_STR_QUERIES_HELP_TEXT_WIZARD NC_("RID_STR_QUERIES_HELP_TEXT_WIZARD", "The wizard will guide you through the steps necessary to create a query." )
+#define RID_STR_TABLES_HELP_TEXT_DESIGN NC_("RID_STR_TABLES_HELP_TEXT_DESIGN", "Create a table by specifying the field names and properties, as well as the data types." )
+#define RID_STR_TABLES_HELP_TEXT_WIZARD NC_("RID_STR_TABLES_HELP_TEXT_WIZARD", "Choose from a selection of business and personal table samples, which you customize to create a table." )
+#define RID_STR_VIEWS_HELP_TEXT_DESIGN NC_("RID_STR_VIEWS_HELP_TEXT_DESIGN", "Create a view by specifying the tables and field names you would like to have visible." )
+#define STR_DATABASE NC_("STR_DATABASE", "Database" )
+#define STR_TASKS NC_("STR_TASKS", "Tasks" )
+#define STR_PREVIEW NC_("STR_PREVIEW", "Preview" )
+#define STR_QUERY_CLOSEDOCUMENTS NC_("STR_QUERY_CLOSEDOCUMENTS", "The connection type has been altered.\n" \
+ "For the changes to take effect, all forms, reports, queries and tables must be closed.\n\n" \
+ "Do you want to close all documents now?")
+#define STR_FRM_LABEL NC_("STR_FRM_LABEL", "F~orm name" )
+#define STR_RPT_LABEL NC_("STR_RPT_LABEL", "~Report name" )
+#define STR_FOLDER_LABEL NC_("STR_FOLDER_LABEL", "F~older name" )
+#define STR_SUB_DOCS_WITH_SCRIPTS NC_("STR_SUB_DOCS_WITH_SCRIPTS", "The document contains forms or reports with embedded macros.")
+#define STR_SUB_DOCS_WITH_SCRIPTS_DETAIL NC_("STR_SUB_DOCS_WITH_SCRIPTS_DETAIL", "Macros should be embedded into the database document itself.\n\n" \
+ "You can continue to use your document as before, however, you are encouraged to migrate " \
+ "your macros. The menu item 'Tools / Migrate Macros ...' will assist you with this.\n\n" \
+ "Note that you won't be able to embed macros into the database document itself until " \
+ "this migration is done. ")
+#define RID_STR_EMBEDDED_DATABASE NC_("RID_STR_EMBEDDED_DATABASE", "Embedded database")
+#define RID_STR_NO_DIFF_CAT NC_("RID_STR_NO_DIFF_CAT", "You cannot select different categories.")
+#define RID_STR_UNSUPPORTED_OBJECT_TYPE NC_("RID_STR_UNSUPPORTED_OBJECT_TYPE", "Unsupported object type found ($type$).")
+#define STR_PAGETITLE_GENERAL NC_("STR_PAGETITLE_GENERAL", "Advanced Properties")
+#define STR_PAGETITLE_ADVANCED NC_("STR_PAGETITLE_ADVANCED", "Additional Settings")
+#define STR_PAGETITLE_CONNECTION NC_("STR_PAGETITLE_CONNECTION", "Connection settings")
+#define STR_TBL_LABEL NC_("STR_TBL_LABEL", "~Table Name")
+#define STR_QRY_LABEL NC_("STR_QRY_LABEL", "~Query name")
+#define STR_TITLE_RENAME NC_("STR_TITLE_RENAME", "Rename to")
+#define STR_TITLE_PASTE_AS NC_("STR_TITLE_PASTE_AS", "Insert as")
+
+#define STR_QUERY_BRW_DELETE_ROWS NC_("STR_QUERY_BRW_DELETE_ROWS", "Do you want to delete the selected data?" )
+#define SBA_BROWSER_SETTING_ORDER NC_("SBA_BROWSER_SETTING_ORDER", "Error setting the sort criteria")
+#define SBA_BROWSER_SETTING_FILTER NC_("SBA_BROWSER_SETTING_FILTER", "Error setting the filter criteria")
+#define RID_STR_CONNECTION_LOST NC_("RID_STR_CONNECTION_LOST", "Connection lost")
+#define RID_STR_QUERIES_CONTAINER NC_("RID_STR_QUERIES_CONTAINER", "Queries")
+#define RID_STR_TABLES_CONTAINER NC_("RID_STR_TABLES_CONTAINER", "Tables")
+#define STR_TITLE_CONFIRM_DELETION NC_("STR_TITLE_CONFIRM_DELETION", "Confirm Deletion" )
+#define STR_QUERY_DELETE_TABLE NC_("STR_QUERY_DELETE_TABLE", "Do you want to delete the table '%1'?" )
+#define STR_QUERY_CONNECTION_LOST NC_("STR_QUERY_CONNECTION_LOST", "The connection to the database has been lost. Do you want to reconnect?" )
+#define STR_OPENTABLES_WARNINGS NC_("STR_OPENTABLES_WARNINGS", "Warnings encountered")
+#define STR_OPENTABLES_WARNINGS_DETAILS NC_("STR_OPENTABLES_WARNINGS_DETAILS", "While retrieving the tables, warnings were reported by the database connection.")
+#define STR_CONNECTING_DATASOURCE NC_("STR_CONNECTING_DATASOURCE", "Connecting to \"$name$\" ...")
+#define STR_LOADING_QUERY NC_("STR_LOADING_QUERY", "Loading query $name$ ...")
+#define STR_LOADING_TABLE NC_("STR_LOADING_TABLE", "Loading table $name$ ...")
+#define STR_NO_TABLE_FORMAT_INSIDE NC_("STR_NO_TABLE_FORMAT_INSIDE", "No table format could be found." )
+#define STR_COULDNOTCONNECT_DATASOURCE NC_("STR_COULDNOTCONNECT_DATASOURCE", "The connection to the data source \"$name$\" could not be established.")
+
+#define STR_TABLEDESIGN_DBFIELDTYPES NC_("STR_TABLEDESIGN_DBFIELDTYPES", "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)")
+#define STR_TABLEDESIGN_UNDO_PRIMKEY NC_("STR_TABLEDESIGN_UNDO_PRIMKEY", "Insert/remove primary key" )
+#define STR_VALUE_YES NC_("STR_VALUE_YES", "Yes" )
+#define STR_VALUE_NO NC_("STR_VALUE_NO", "No" )
+// Note: should somehow fit to the word "value" in other languages as well: value - none...
+#define STR_VALUE_NONE NC_("STR_VALUE_NONE", "<none>")
+#define STR_TAB_FIELD_COLUMN_NAME NC_("STR_TAB_FIELD_COLUMN_NAME", "Field Name" )
+#define STR_TAB_FIELD_COLUMN_DATATYPE NC_("STR_TAB_FIELD_COLUMN_DATATYPE", "Field Type" )
+#define STR_TAB_HELP_TEXT NC_("STR_TAB_HELP_TEXT", "Description" )
+#define STR_COLUMN_DESCRIPTION NC_("STR_COLUMN_DESCRIPTION", "Column Description" )
+#define STR_TAB_PROPERTIES NC_("STR_TAB_PROPERTIES", "Field Properties" )
+#define STR_TABED_UNDO_CELLMODIFIED NC_("STR_TABED_UNDO_CELLMODIFIED", "Modify cell" )
+#define STR_TABED_UNDO_ROWDELETED NC_("STR_TABED_UNDO_ROWDELETED", "Delete row" )
+#define STR_TABED_UNDO_TYPE_CHANGED NC_("STR_TABED_UNDO_TYPE_CHANGED", "Modify field type")
+#define STR_TABED_UNDO_ROWINSERTED NC_("STR_TABED_UNDO_ROWINSERTED", "Insert row" )
+#define STR_TABED_UNDO_NEWROWINSERTED NC_("STR_TABED_UNDO_NEWROWINSERTED", "Insert new row" )
+#define STR_DEFAULT_VALUE NC_("STR_DEFAULT_VALUE", "~Default value" )
+#define STR_HELP_BOOL_DEFAULT NC_("STR_HELP_BOOL_DEFAULT", "Select a value that is to appear in all new records as default.\nIf the field is not to have a default value, select the empty string.")
+#define STR_HELP_DEFAULT_VALUE NC_("STR_HELP_DEFAULT_VALUE", "Enter a default value for this field.\n\nWhen you later enter data in the table, this string will be used in each new record for the field selected. It should, therefore, correspond to the cell format that needs to be entered below." )
+#define STR_HELP_TEXT_LENGTH NC_("STR_HELP_TEXT_LENGTH", "Enter the maximum text length permitted." )
+#define STR_HELP_NUMERIC_TYPE NC_("STR_HELP_NUMERIC_TYPE", "Enter the number format." )
+#define STR_HELP_LENGTH NC_("STR_HELP_LENGTH", "Determine the length data can have in this field.\n\nIf decimal fields, then the maximum length of the number to be entered, if binary fields, then the length of the data block.\nThe value will be corrected accordingly when it exceeds the maximum for this database." )
+#define STR_HELP_SCALE NC_("STR_HELP_SCALE", "Specify the number of decimal places permitted in this field." )
+#define STR_HELP_FORMAT_CODE NC_("STR_HELP_FORMAT_CODE", "This is where you see how the data would be displayed in the current format (use the button on the right to modify the format).")
+#define STR_HELP_FORMAT_BUTTON NC_("STR_HELP_FORMAT_BUTTON", "This is where you determine the output format of the data.")
+#define STR_HELP_AUTOINCREMENT NC_("STR_HELP_AUTOINCREMENT", "Choose if this field should contain AutoIncrement values.\n\nYou can not enter data in fields of this type. An intrinsic value will be assigned to each new record automatically (resulting from the increment of the previous record)." )
+#define STR_TABLEDESIGN_DUPLICATE_NAME NC_("STR_TABLEDESIGN_DUPLICATE_NAME", "The table cannot be saved because column name \"$column$\" was assigned twice.")
+#define STR_TBL_COLUMN_IS_KEYCOLUMN NC_("STR_TBL_COLUMN_IS_KEYCOLUMN", "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?")
+#define STR_TBL_COLUMN_IS_KEYCOLUMN_TITLE NC_("STR_TBL_COLUMN_IS_KEYCOLUMN_TITLE", "Primary Key Affected")
+#define STR_COLUMN_NAME NC_("STR_COLUMN_NAME", "Column")
+#define STR_QRY_CONTINUE NC_("STR_QRY_CONTINUE", "Continue anyway?" )
+#define STR_TABLEDESIGN_CONNECTION_MISSING NC_("STR_TABLEDESIGN_CONNECTION_MISSING", "The table could not be saved due to problems connecting to the database.")
+#define STR_TABLEDESIGN_DATASOURCE_DELETED NC_("STR_TABLEDESIGN_DATASOURCE_DELETED", "The table filter could not be adjusted because the data source has been deleted.")
+#define STR_QUERY_SAVE_TABLE_EDIT_INDEXES NC_("STR_QUERY_SAVE_TABLE_EDIT_INDEXES", "Before you can edit the indexes of a table, you have to save it.\nDo you want to save the changes now?")
+#define STR_TABLEDESIGN_NO_PRIM_KEY_HEAD NC_("STR_TABLEDESIGN_NO_PRIM_KEY_HEAD", "No primary key" )
+#define STR_TABLEDESIGN_NO_PRIM_KEY NC_("STR_TABLEDESIGN_NO_PRIM_KEY", "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?" )
+#define STR_TABLEDESIGN_ALTER_ERROR NC_("STR_TABLEDESIGN_ALTER_ERROR", "The column \"$column$\" could not be changed. Should the column instead be deleted and the new format appended?" )
+#define STR_TABLEDESIGN_SAVE_ERROR NC_("STR_TABLEDESIGN_SAVE_ERROR", "Error while saving the table design")
+#define STR_TABLEDESIGN_COULD_NOT_DROP_COL NC_("STR_TABLEDESIGN_COULD_NOT_DROP_COL", "The column $column$ could not be deleted.")
+#define STR_HELP_AUTOINCREMENT_VALUE NC_("STR_HELP_AUTOINCREMENT_VALUE", "Enter an SQL statement for the auto-increment field.\n\nThis statement will be directly transferred to the database when the table is created.")
+#define STR_NO_TYPE_INFO_AVAILABLE NC_("STR_NO_TYPE_INFO_AVAILABLE", "No type information could be retrieved from the database.\nThe table design mode is not available for this data source.")
+#define STR_CHANGE_COLUMN_NAME NC_("STR_CHANGE_COLUMN_NAME", "change field name")
+#define STR_CHANGE_COLUMN_TYPE NC_("STR_CHANGE_COLUMN_TYPE", "change field type")
+#define STR_CHANGE_COLUMN_DESCRIPTION NC_("STR_CHANGE_COLUMN_DESCRIPTION", "change field description")
+#define STR_CHANGE_COLUMN_ATTRIBUTE NC_("STR_CHANGE_COLUMN_ATTRIBUTE", "change field attribute")
+
+#define STR_ENTER_CONNECTION_PASSWORD NC_("STR_ENTER_CONNECTION_PASSWORD", "A password is needed to connect to the data source \"$name$\".")
+#define STR_ASK_FOR_DIRECTORY_CREATION NC_("STR_ASK_FOR_DIRECTORY_CREATION", "The directory\n\n$path$\n\ndoes not exist. Should it be created?")
+#define STR_COULD_NOT_CREATE_DIRECTORY NC_("STR_COULD_NOT_CREATE_DIRECTORY", "The directory $name$ could not be created.")
+#define STR_ALREADYEXISTOVERWRITE NC_("STR_ALREADYEXISTOVERWRITE", "The file already exists. Overwrite?" )
+#define STR_NEW_FOLDER NC_("STR_NEW_FOLDER", "Folder" )
+
+#define STR_DATABASE_TYPE_CHANGE NC_("STR_DATABASE_TYPE_CHANGE", "Database properties" )
+#define STR_PARENTTITLE_GENERAL NC_("STR_PARENTTITLE_GENERAL", "Data Source Properties: #" )
+#define STR_ERR_USE_CONNECT_TO NC_("STR_ERR_USE_CONNECT_TO", "Please choose 'Connect to an existing database' to connect to an existing database instead.")
+#define STR_COULD_NOT_LOAD_ODBC_LIB NC_("STR_COULD_NOT_LOAD_ODBC_LIB", "Could not load the program library #lib# or it is corrupted. The ODBC data source selection is not available.")
+#define STR_UNSUPPORTED_DATASOURCE_TYPE NC_("STR_UNSUPPORTED_DATASOURCE_TYPE", "This kind of data source is not supported on this platform.\nYou are allowed to change the settings, but you probably will not be able to connect to the database.")
+#define STR_AUTOTEXT_FIELD_SEP_NONE NC_("STR_AUTOTEXT_FIELD_SEP_NONE", "{None}")
+// To translators: EM Dec 2002: 'Space' refers t o what you get when you hit the space bar on your keyboard.
+#define STR_AUTOFIELDSEPARATORLIST NC_("STR_AUTOFIELDSEPARATORLIST", ";\t59\t,\t44\t:\t58\t{Tab}\t9\t{Space}\t32" )
+#define STR_AUTODELIMITER_MISSING NC_("STR_AUTODELIMITER_MISSING", "#1 must be set." )
+#define STR_AUTODELIMITER_MUST_DIFFER NC_("STR_AUTODELIMITER_MUST_DIFFER", "#1 and #2 must be different." )
+#define STR_AUTONO_WILDCARDS NC_("STR_AUTONO_WILDCARDS", "Wildcards such as ?,* are not allowed in #1." )
+
+#define STR_CONNECTION_TEST NC_("STR_CONNECTION_TEST", "Connection Test")
+#define STR_CONNECTION_SUCCESS NC_("STR_CONNECTION_SUCCESS", "The connection was established successfully.")
+#define STR_CONNECTION_NO_SUCCESS NC_("STR_CONNECTION_NO_SUCCESS", "The connection could not be established.")
+#define STR_JDBCDRIVER_SUCCESS NC_("STR_JDBCDRIVER_SUCCESS", "The JDBC driver was loaded successfully.")
+#define STR_JDBCDRIVER_NO_SUCCESS NC_("STR_JDBCDRIVER_NO_SUCCESS", "The JDBC driver could not be loaded.")
+#define STR_MSACCESS_FILTERNAME NC_("STR_MSACCESS_FILTERNAME", "MS Access file")
+#define STR_MSACCESS_2007_FILTERNAME NC_("STR_MSACCESS_2007_FILTERNAME", "MS Access 2007 file")
+#define STR_FIREBIRD_FILTERNAME NC_("STR_FIREBIRD_FILTERNAME", "Firebird Database")
+
+#define STR_RSC_CHARSETS NC_("STR_RSC_CHARSETS", "System")
+#define STR_ERROR_DURING_CREATION NC_("STR_ERROR_DURING_CREATION", "Error during creation")
+#define STR_UNEXPECTED_ERROR NC_("STR_UNEXPECTED_ERROR", "An error occurred. The operation could not be performed.")
+#define STR_COULDNOTOPEN_LINKEDDOC NC_("STR_COULDNOTOPEN_LINKEDDOC", "The document \"$file$\" could not be opened.")
+#define STR_MISSING_TABLES_XDROP NC_("STR_MISSING_TABLES_XDROP", "The table cannot be deleted because the database connection does not support this.")
+#define STR_BUTTON_TEXT_ALL NC_("STR_BUTTON_TEXT_ALL", "~All")
+#define STR_UNDO_COLON NC_("STR_UNDO_COLON", "Undo:")
+#define STR_REDO_COLON NC_("STR_REDO_COLON", "Redo:")
+#define STR_UNKNOWN_TYPE_FOUND NC_("STR_UNKNOWN_TYPE_FOUND", "No corresponding column type could be found for column '#1'." )
+#define STR_FILE_DOES_NOT_EXIST NC_("STR_FILE_DOES_NOT_EXIST", "The file \"$file$\" does not exist.")
+#define STR_WARNINGS_DURING_CONNECT NC_("STR_WARNINGS_DURING_CONNECT", "Warnings were encountered while connecting to the data source. Press \"$buttontext$\" to view them.")
+#define STR_NAMED_OBJECT_ALREADY_EXISTS NC_("STR_NAMED_OBJECT_ALREADY_EXISTS", "The name '$#$' already exists.\nPlease enter another name." )
+// #i96130# use hard coded name
+#define RID_STR_EXTENSION_NOT_PRESENT NC_("RID_STR_EXTENSION_NOT_PRESENT", "The report, \"$file$\", requires the Report Builder feature.")
+
+#define STR_COULDNOTCREATE_DRIVERMANAGER NC_("STR_COULDNOTCREATE_DRIVERMANAGER", "Cannot connect to the SDBC driver manager (#servicename#).")
+#define STR_NOREGISTEREDDRIVER NC_("STR_NOREGISTEREDDRIVER", "A driver is not registered for the URL #connurl#.")
+#define STR_NOTABLEINFO NC_("STR_NOTABLEINFO", "Successfully connected, but information about database tables is not available.")
+#define STR_ALL_TABLES NC_("STR_ALL_TABLES", "All tables")
+#define STR_ALL_VIEWS NC_("STR_ALL_VIEWS", "All views")
+#define STR_ALL_TABLES_AND_VIEWS NC_("STR_ALL_TABLES_AND_VIEWS", "All tables and views")
+
+#define STR_TABLE_PRIV_NAME NC_("STR_TABLE_PRIV_NAME", "Table name")
+#define STR_TABLE_PRIV_INSERT NC_("STR_TABLE_PRIV_INSERT", "Insert data")
+#define STR_TABLE_PRIV_DELETE NC_("STR_TABLE_PRIV_DELETE", "Delete data")
+#define STR_TABLE_PRIV_UPDATE NC_("STR_TABLE_PRIV_UPDATE", "Modify data")
+#define STR_TABLE_PRIV_ALTER NC_("STR_TABLE_PRIV_ALTER", "Alter structure")
+#define STR_TABLE_PRIV_SELECT NC_("STR_TABLE_PRIV_SELECT", "Read data")
+#define STR_TABLE_PRIV_REFERENCE NC_("STR_TABLE_PRIV_REFERENCE", "Modify references")
+#define STR_TABLE_PRIV_DROP NC_("STR_TABLE_PRIV_DROP", "Drop structure")
+
+#define STR_DBASE_PATH_OR_FILE NC_("STR_DBASE_PATH_OR_FILE", "Path to the dBASE files")
+#define STR_FLAT_PATH_OR_FILE NC_("STR_FLAT_PATH_OR_FILE", "Path to the text files")
+#define STR_CALC_PATH_OR_FILE NC_("STR_CALC_PATH_OR_FILE", "Path to the spreadsheet document")
+#define STR_NAME_OF_ODBC_DATASOURCE NC_("STR_NAME_OF_ODBC_DATASOURCE", "Name of the ODBC data source on your system")
+#define STR_WRITER_PATH_OR_FILE NC_("STR_WRITER_PATH_OR_FILE", "Path to the Writer document")
+#define STR_MYSQL_DATABASE_NAME NC_("STR_MYSQL_DATABASE_NAME", "Name of the MySQL/MariaDB database")
+#define STR_ORACLE_DATABASE_NAME NC_("STR_ORACLE_DATABASE_NAME", "Name of the Oracle database")
+#define STR_MSACCESS_MDB_FILE NC_("STR_MSACCESS_MDB_FILE", "Microsoft Access database file")
+#define STR_NO_ADDITIONAL_SETTINGS NC_("STR_NO_ADDITIONAL_SETTINGS", "No more settings are necessary. To verify that the connection is working, click the '%test' button.")
+#define STR_COMMONURL NC_("STR_COMMONURL", "Enter the DBMS/driver-specific connection string here" )
+#define STR_HOSTNAME NC_("STR_HOSTNAME", "~Host name")
+#define STR_MOZILLA_PROFILE_NAME NC_("STR_MOZILLA_PROFILE_NAME", "~Mozilla profile name")
+#define STR_THUNDERBIRD_PROFILE_NAME NC_("STR_THUNDERBIRD_PROFILE_NAME", "~Thunderbird profile name")
+#define STR_ADD_TABLES NC_("STR_ADD_TABLES", "Add Tables")
+#define STR_ADD_TABLE_OR_QUERY NC_("STR_ADD_TABLE_OR_QUERY", "Add Table or Query" )
+
+#define STR_WIZ_COLUMN_SELECT_TITLE NC_("STR_WIZ_COLUMN_SELECT_TITEL", "Apply columns")
+#define STR_WIZ_TYPE_SELECT_TITLE NC_("STR_WIZ_TYPE_SELECT_TITEL", "Type formatting")
+#define STR_WIZ_NAME_ALREADY_DEFINED NC_("STR_WIZ_NAME_ALREADY_DEFINED", "Enter a unique name for the new primary key data field.\nThe following name is already in use:")
+#define STR_WIZ_NAME_MATCHING_TITLE NC_("STR_WIZ_NAME_MATCHING_TITEL", "Assign columns" )
+#define STR_WIZ_PB_PREV NC_("STR_WIZ_PB_PREV", "< ~Back")
+#define STR_WIZ_PB_NEXT NC_("STR_WIZ_PB_NEXT", "~Next>")
+#define STR_WIZ_PB_OK NC_("STR_WIZ_PB_OK", "C~reate")
+#define STR_WIZ_TABLE_COPY NC_("STR_WIZ_TABLE_COPY", "Copy table" )
+#define STR_COPYTABLE_TITLE_COPY NC_("STR_COPYTABLE_TITLE_COPY", "Copy table" )
+#define STR_INVALID_TABLE_NAME NC_("STR_INVALID_TABLE_NAME", "This table name is not valid in the current database.")
+#define STR_SUGGEST_APPEND_TABLE_DATA NC_("STR_SUGGEST_APPEND_TABLE_DATA", "Choose the option 'Append data' on the first page to append data to an existing table.")
+#define STR_INVALID_TABLE_NAME_LENGTH NC_("STR_INVALID_TABLE_NAME_LENGTH", "Please change the table name. It is too long.")
+
+#define STR_DBWIZARDTITLE NC_("STR_DBWIZARDTITLE", "Database Wizard" )
+#define STR_PAGETITLE_INTROPAGE NC_("STR_PAGETITLE_INTROPAGE", "Select database" )
+#define STR_PAGETITLE_DBASE NC_("STR_PAGETITLE_DBASE", "Set up dBASE connection" )
+#define STR_PAGETITLE_TEXT NC_("STR_PAGETITLE_TEXT", "Set up a connection to text files" )
+#define STR_PAGETITLE_MSACCESS NC_("STR_PAGETITLE_MSACCESS", "Set up Microsoft Access connection" )
+#define STR_PAGETITLE_LDAP NC_("STR_PAGETITLE_LDAP", "Set up LDAP connection" )
+#define STR_PAGETITLE_ADO NC_("STR_PAGETITLE_ADO", "Set up ADO connection" )
+#define STR_PAGETITLE_JDBC NC_("STR_PAGETITLE_JDBC", "Set up JDBC connection" )
+#define STR_PAGETITLE_ORACLE NC_("STR_PAGETITLE_ORACLE", "Set up Oracle database connection" )
+#define STR_PAGETITLE_MYSQL NC_("STR_PAGETITLE_MYSQL", "Set up MySQL/MariaDB connection" )
+#define STR_PAGETITLE_ODBC NC_("STR_PAGETITLE_ODBC", "Set up ODBC connection" )
+#define STR_PAGETITLE_DOCUMENT_OR_SPREADSHEET NC_("STR_PAGETITLE_DOCUMENT_OR_SPREADSHEET", "Set up Writer Document or Spreadsheet connection" )
+#define STR_PAGETITLE_AUTHENTIFICATION NC_("STR_PAGETITLE_AUTHENTIFICATION", "Set up user authentication" )
+#define STR_PAGETITLE_MYSQL_NATIVE NC_("STR_PAGETITLE_MYSQL_NATIVE", "Set up MySQL/MariaDB server data")
+#define STR_PAGETITLE_FINAL NC_("STR_PAGETITLE_FINAL", "Save and proceed" )
+#define STR_DATABASEDEFAULTNAME NC_("STR_DATABASEDEFAULTNAME", "New Database" )
+#define STR_MYSQLJDBC_HEADERTEXT NC_("STR_MYSQLJDBC_HEADERTEXT", "Set up connection to a MySQL/MariaDB database using JDBC" )
+#define STR_MYSQLJDBC_HELPTEXT NC_("STR_MYSQLJDBC_HELPTEXT", "Please enter the required information to connect to a MySQL/MariaDB database using JDBC. Note that a JDBC driver class must be installed on your system and registered with %PRODUCTNAME.\nPlease contact your system administrator if you are unsure about the following settings.")
+#define STR_MYSQL_DRIVERCLASSTEXT NC_("STR_MYSQL_DRIVERCLASSTEXT", "MySQL/MariaDB JDBC d~river class:")
+#define STR_MYSQL_DEFAULT NC_("STR_MYSQL_DEFAULT", "Default: 3306")
+#define STR_DBASE_HEADERTEXT NC_("STR_DBASE_HEADERTEXT", "Set up a connection to dBASE files" )
+#define STR_DBASE_HELPTEXT NC_("STR_DBASE_HELPTEXT", "Select the folder where the dBASE files are stored." )
+#define STR_TEXT_HEADERTEXT NC_("STR_TEXT_HEADERTEXT", "Set up a connection to text files" )
+#define STR_TEXT_HELPTEXT NC_("STR_TEXT_HELPTEXT", "Select the folder where the CSV (Comma Separated Values) text files are stored. %PRODUCTNAME Base will open these files in read-only mode." )
+#define STR_TEXT_PATH_OR_FILE NC_("STR_TEXT_PATH_OR_FILE", "Path to text files")
+#define STR_MSACCESS_HEADERTEXT NC_("STR_MSACCESS_HEADERTEXT", "Set up a connection to a Microsoft Access database" )
+#define STR_MSACCESS_HELPTEXT NC_("STR_MSACCESS_HELPTEXT", "Please select the Microsoft Access file you want to access.")
+#define STR_ADO_HEADERTEXT NC_("STR_ADO_HEADERTEXT", "Set up a connection to an ADO database" )
+#define STR_ADO_HELPTEXT NC_("STR_ADO_HELPTEXT", "Please enter the URL of the ADO data source you want to connect to.\nClick 'Browse' to configure provider-specific settings.\nPlease contact your system administrator if you are unsure about the following settings." )
+#define STR_ODBC_HEADERTEXT NC_("STR_ODBC_HEADERTEXT", "Set up a connection to an ODBC database" )
+#define STR_ODBC_HELPTEXT NC_("STR_ODBC_HELPTEXT", "Enter the name of the ODBC database you want to connect to.\nClick 'Browse...' to select an ODBC database that is already registered in %PRODUCTNAME.\nPlease contact your system administrator if you are unsure about the following settings." )
+#define STR_JDBC_HEADERTEXT NC_("STR_JDBC_HEADERTEXT", "Set up a connection to a JDBC database" )
+#define STR_JDBC_HELPTEXT NC_("STR_JDBC_HELPTEXT", "Please enter the required information to connect to a JDBC database.\nPlease contact your system administrator if you are unsure about the following settings." )
+#define STR_ORACLE_HEADERTEXT NC_("STR_ORACLE_HEADERTEXT", "Set up a connection to an Oracle database")
+#define STR_ORACLE_DEFAULT NC_("STR_ORACLE_DEFAULT", "Default: 1521" )
+#define STR_ORACLE_DRIVERCLASSTEXT NC_("STR_ORACLE_DRIVERCLASSTEXT", "Oracle JDBC ~driver class")
+#define STR_ORACLE_HELPTEXT NC_("STR_ORACLE_HELPTEXT", "Please enter the required information to connect to an Oracle database. Note that a JDBC Driver Class must be installed on your system and registered with %PRODUCTNAME.\nPlease contact your system administrator if you are unsure about the following settings." )
+#define STR_SPREADSHEET_HEADERTEXT NC_("STR_SPREADSHEET_HEADERTEXT", "Set up a connection to spreadsheets")
+#define STR_SPREADSHEET_HELPTEXT NC_("STR_SPREADSHEET_HELPTEXT", "Click 'Browse...' to select a %PRODUCTNAME spreadsheet or Microsoft Excel workbook.\n%PRODUCTNAME will open this file in read-only mode." )
+#define STR_SPREADSHEETPATH NC_("STR_SPREADSHEETPATH", "~Location and file name" )
+
+#define STR_COMMAND_EXECUTED_SUCCESSFULLY NC_("STR_COMMAND_EXECUTED_SUCCESSFULLY", "Command successfully executed." )
+#define STR_DIRECTSQL_CONNECTIONLOST NC_("STR_DIRECTSQL_CONNECTIONLOST", "The connection to the database has been lost. This dialog will be closed.")
+
+#define STR_TAB_INDEX_SORTORDER NC_("STR_TAB_INDEX_SORTORDER", "Sort order" )
+#define STR_TAB_INDEX_FIELD NC_("STR_TAB_INDEX_FIELD", "Index field" )
+#define STR_ORDER_ASCENDING NC_("STR_ORDER_ASCENDING", "Ascending" )
+#define STR_ORDER_DESCENDING NC_("STR_ORDER_DESCENDING", "Descending" )
+#define STR_CONFIRM_DROP_INDEX NC_("STR_CONFIRM_DROP_INDEX", "Do you really want to delete the index '$name$'?")
+#define STR_LOGICAL_INDEX_NAME NC_("STR_LOGICAL_INDEX_NAME", "index")
+#define STR_NEED_INDEX_FIELDS NC_("STR_NEED_INDEX_FIELDS", "The index must contain at least one field.")
+#define STR_INDEX_NAME_ALREADY_USED NC_("STR_INDEX_NAME_ALREADY_USED", "There is already another index named \"$name$\".")
+#define STR_INDEXDESIGN_DOUBLE_COLUMN_NAME NC_("STR_INDEXDESIGN_DOUBLE_COLUMN_NAME", "In an index definition, no table column may occur more than once. However, you have entered column \"$name$\" twice.")
+
+#define STR_COULD_NOT_CONVERT_PARAM NC_("STR_COULD_NOT_CONVERT_PARAM", "The entry could not be converted to a valid value for the \"$name$\" parameter")
+
+#define STR_EXCEPTION_STATUS NC_("STR_EXCEPTION_STATUS", "SQL Status")
+#define STR_EXCEPTION_ERRORCODE NC_("STR_EXCEPTION_ERRORCODE", "Error code")
+#define STR_EXPLAN_STRINGCONVERSION_ERROR NC_("STR_EXPLAN_STRINGCONVERSION_ERROR", "A frequent reason for this error is an inappropriate character set setting for the language of your database. Check the setting by choosing Edit - Database - Properties.")
+#define STR_EXCEPTION_ERROR NC_("STR_EXCEPTION_ERROR", "Error")
+#define STR_EXCEPTION_WARNING NC_("STR_EXCEPTION_WARNING", "Warning")
+#define STR_EXCEPTION_INFO NC_("STR_EXCEPTION_INFO", "Information")
+#define STR_EXCEPTION_DETAILS NC_("STR_EXCEPTION_DETAILS", "Details")
+
+#define STR_QUERY_USERADMIN_DELETE_USER NC_("STR_QUERY_USERADMIN_DELETE_USER", "Do you really want to delete the user?")
+#define STR_USERADMIN_NOT_AVAILABLE NC_("STR_USERADMIN_NOT_AVAILABLE", "The database does not support user administration." )
+#define STR_ERROR_PASSWORDS_NOT_IDENTICAL NC_("STR_ERROR_PASSWORDS_NOT_IDENTICAL", "The passwords do not match. Please enter the password again.")
+
+#define STR_JOIN_TYPE_HINT NC_("STR_JOIN_TYPE_HINT", "Please note that some databases may not support this join type.")
+#define STR_QUERY_INNER_JOIN NC_("STR_QUERY_INNER_JOIN", "Includes only records for which the contents of the related fields of both tables are identical.")
+#define STR_QUERY_LEFTRIGHT_JOIN NC_("STR_QUERY_LEFTRIGHT_JOIN", "Contains ALL records from table '%1' but only records from table '%2' where the values in the related fields are matching.")
+#define STR_QUERY_FULL_JOIN NC_("STR_QUERY_FULL_JOIN", "Contains ALL records from '%1' and from '%2'.")
+#define STR_QUERY_CROSS_JOIN NC_("STR_QUERY_CROSS_JOIN", "Contains the Cartesian product of ALL records from '%1' and from '%2'.")
+
+#define STR_CTW_NO_VIEWS_SUPPORT NC_("STR_CTW_NO_VIEWS_SUPPORT", "The destination database does not support views.")
+#define STR_CTW_NO_PRIMARY_KEY_SUPPORT NC_("STR_CTW_NO_PRIMARY_KEY_SUPPORT", "The destination database does not support primary keys.")
+#define STR_CTW_INVALID_DATA_ACCESS_DESCRIPTOR NC_("STR_CTW_INVALID_DATA_ACCESS_DESCRIPTOR", "no data access descriptor found, or no data access descriptor able to provide all necessary information")
+#define STR_CTW_ONLY_TABLES_AND_QUERIES_SUPPORT NC_("STR_CTW_ONLY_TABLES_AND_QUERIES_SUPPORT", "Only tables and queries are supported at the moment.")
+#define STR_CTW_COPY_SOURCE_NEEDS_BOOKMARKS NC_("STR_CTW_COPY_SOURCE_NEEDS_BOOKMARKS", "The copy source's result set must support bookmarks.")
+#define STR_CTW_UNSUPPORTED_COLUMN_TYPE NC_("STR_CTW_UNSUPPORTED_COLUMN_TYPE", "Unsupported source column type ($type$) at column position $pos$.")
+#define STR_CTW_ILLEGAL_PARAMETER_COUNT NC_("STR_CTW_ILLEGAL_PARAMETER_COUNT", "Illegal number of initialization parameters.")
+#define STR_CTW_ERROR_DURING_INITIALIZATION NC_("STR_CTW_ERROR_DURING_INITIALIZATION", "An error occurred during initialization.")
+#define STR_CTW_ERROR_UNSUPPORTED_SETTING NC_("STR_CTW_ERROR_UNSUPPORTED_SETTING", "Unsupported setting in the copy source descriptor: $name$.")
+#define STR_CTW_ERROR_NO_QUERY NC_("STR_CTW_ERROR_NO_QUERY", "To copy a query, your connection must be able to provide queries.")
+#define STR_CTW_ERROR_INVALID_INTERACTIONHANDLER NC_("STR_CTW_ERROR_INVALID_INTERACTIONHANDLER", "The given interaction handler is invalid.")
+
+#define STR_QUERY_REL_EDIT_RELATION NC_("STR_QUERY_REL_EDIT_RELATION", "This relation already exists. Do you want to edit it or create a new one?" )
+#define STR_QUERY_REL_EDIT NC_("STR_QUERY_REL_EDIT", "Edit..." )
+#define STR_QUERY_REL_CREATE NC_("STR_QUERY_REL_CREATE", "Create..." )
+#define STR_RELATIONDESIGN NC_("STR_RELATIONDESIGN", " - %PRODUCTNAME Base: Relation design" )
+#define STR_RELATIONDESIGN_NOT_AVAILABLE NC_("STR_RELATIONDESIGN_NOT_AVAILABLE", "The database does not support relations." )
+#define STR_QUERY_REL_DELETE_WINDOW NC_("STR_QUERY_REL_DELETE_WINDOW", "When you delete this table all corresponding relations will be deleted as well. Continue?")
+#define STR_QUERY_REL_COULD_NOT_CREATE NC_("STR_QUERY_REL_COULD_NOT_CREATE", "The database could not create the relation. Maybe foreign keys for this kind of table aren't supported.\nPlease check your documentation of the database.")
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/inc/strings.hxx b/dbaccess/inc/strings.hxx
new file mode 100644
index 000000000..f4c6cb664
--- /dev/null
+++ b/dbaccess/inc/strings.hxx
@@ -0,0 +1,269 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+#pragma once
+
+#include <rtl/ustring.hxx>
+
+// property names
+
+#define PROPERTY_URL "URL"
+#define PROPERTY_INFO "Info"
+#define PROPERTY_SETTINGS "Settings"
+#define PROPERTY_ISPASSWORDREQUIRED "IsPasswordRequired"
+#define PROPERTY_TABLEFILTER "TableFilter"
+#define PROPERTY_TABLETYPEFILTER "TableTypeFilter"
+#define PROPERTY_NAME "Name"
+#define PROPERTY_SCHEMANAME "SchemaName"
+#define PROPERTY_CATALOGNAME "CatalogName"
+#define PROPERTY_PRIVILEGES "Privileges"
+#define PROPERTY_ESCAPE_PROCESSING "EscapeProcessing"
+#define PROPERTY_COMMAND "Command"
+#define PROPERTY_TYPE "Type"
+#define PROPERTY_TYPENAME "TypeName"
+#define PROPERTY_PRECISION "Precision"
+#define PROPERTY_SCALE "Scale"
+#define PROPERTY_ISNULLABLE "IsNullable"
+#define PROPERTY_ISAUTOINCREMENT "IsAutoIncrement"
+#define PROPERTY_ISROWVERSION "IsRowVersion"
+#define PROPERTY_DESCRIPTION "Description"
+#define PROPERTY_DEFAULTVALUE "DefaultValue"
+#define PROPERTY_NUMBERFORMAT "FormatKey"
+#define PROPERTY_QUERYTIMEOUT "QueryTimeOut"
+#define PROPERTY_MAXFIELDSIZE "MaxFieldSize"
+#define PROPERTY_MAXROWS "MaxRows"
+#define PROPERTY_CURSORNAME "CursorName"
+#define PROPERTY_RESULTSETCONCURRENCY "ResultSetConcurrency"
+#define PROPERTY_RESULTSETTYPE "ResultSetType"
+#define PROPERTY_FETCHDIRECTION "FetchDirection"
+#define PROPERTY_FETCHSIZE "FetchSize"
+#define PROPERTY_USEBOOKMARKS "UseBookmarks"
+#define PROPERTY_ISSEARCHABLE "IsSearchable"
+#define PROPERTY_ISCURRENCY "IsCurrency"
+#define PROPERTY_ISSIGNED "IsSigned"
+#define PROPERTY_DISPLAYSIZE "DisplaySize"
+#define PROPERTY_LABEL "Label"
+#define PROPERTY_ISREADONLY "IsReadOnly"
+#define PROPERTY_ISWRITABLE "IsWritable"
+#define PROPERTY_ISDEFINITELYWRITABLE "IsDefinitelyWritable"
+#define PROPERTY_VALUE "Value"
+#define PROPERTY_TABLENAME "TableName"
+#define PROPERTY_ISCASESENSITIVE "IsCaseSensitive"
+#define PROPERTY_SERVICENAME "ServiceName"
+#define PROPERTY_ISBOOKMARKABLE "IsBookmarkable"
+#define PROPERTY_CANUPDATEINSERTEDROWS "CanUpdateInsertedRows"
+#define PROPERTY_NUMBERFORMATSSUPPLIER "NumberFormatsSupplier"
+#define PROPERTY_DATASOURCENAME "DataSourceName"
+#define PROPERTY_DATABASE_LOCATION "DatabaseLocation"
+#define PROPERTY_CONNECTION_RESOURCE "ConnectionResource"
+#define PROPERTY_CONNECTION_INFO "ConnectionInfo"
+#define PROPERTY_RESULT_SET "ResultSet"
+#define PROPERTY_SELECTION "Selection"
+#define PROPERTY_BOOKMARK_SELECTION "BookmarkSelection"
+#define PROPERTY_COLUMN_NAME "ColumnName"
+#define PROPERTY_COLUMN "Column"
+#define PROPERTY_DATASOURCE "DataSource"
+#define PROPERTY_TRANSACTIONISOLATION "TransactionIsolation"
+#define PROPERTY_TYPEMAP "TypeMap"
+#define PROPERTY_USER "User"
+#define PROPERTY_PASSWORD "Password"
+#define PROPERTY_COMMAND_TYPE "CommandType"
+#define PROPERTY_ACTIVECOMMAND "ActiveCommand"
+#define PROPERTY_ACTIVE_CONNECTION "ActiveConnection"
+#define PROPERTY_FILTER "Filter"
+#define PROPERTY_APPLYFILTER "ApplyFilter"
+#define PROPERTY_ORDER "Order"
+#define PROPERTY_APPLYORDER "ApplyOrder"
+#define PROPERTY_ISMODIFIED "IsModified"
+#define PROPERTY_ISNEW "IsNew"
+#define PROPERTY_ROWCOUNT "RowCount"
+#define PROPERTY_ISROWCOUNTFINAL "IsRowCountFinal"
+#define PROPERTY_WIDTH "Width"
+#define PROPERTY_ROW_HEIGHT "RowHeight"
+#define PROPERTY_AUTOGROW "AutoGrow"
+#define PROPERTY_FORMATKEY "FormatKey"
+#define PROPERTY_ALIGN "Align"
+#define PROPERTY_FONT "FontDescriptor"
+#define PROPERTY_TEXTCOLOR "TextColor"
+#define PROPERTY_BOUNDFIELD "BoundField"
+#define PROPERTY_CONTROLSOURCE "DataField"
+#define PROPERTY_REALNAME "RealName"
+#define PROPERTY_UPDATE_TABLENAME "UpdateTableName"
+#define PROPERTY_UPDATE_SCHEMANAME "UpdateSchemaName"
+#define PROPERTY_UPDATE_CATALOGNAME "UpdateCatalogName"
+#define PROPERTY_RELATIVEPOSITION "RelativePosition"
+#define PROPERTY_CONTROLMODEL "ControlModel"
+#define PROPERTY_RELATEDCOLUMN "RelatedColumn"
+#define PROPERTY_ISUNIQUE "IsUnique"
+#define PROPERTY_ISPRIMARYKEYINDEX "IsPrimaryKeyIndex"
+#define PROPERTY_IGNORERESULT "IgnoreResult"
+#define PROPERTY_UPDATERULE "UpdateRule"
+#define PROPERTY_DELETERULE "DeleteRule"
+#define PROPERTY_REFERENCEDTABLE "ReferencedTable"
+#define PROPERTY_SQLEXCEPTION "SQLException"
+#define PROPERTY_BORDER "Border"
+#define PROPERTY_HELPTEXT "HelpText"
+#define PROPERTY_CONTROLDEFAULT "ControlDefault"
+#define PROPERTY_HIDDEN "Hidden"
+#define PROPERTY_DEFAULTSTATE "DefaultState"
+#define PROPERTY_SUPPRESSVERSIONCL "SuppressVersionColumns"
+#define PROPERTY_SHOW_BROWSER "ShowBrowser"
+#define PROPERTY_ENABLE_BROWSER "EnableBrowser"
+#define PROPERTY_SHOWMENU "ShowMenu"
+#define PROPERTY_LAYOUTINFORMATION "LayoutInformation"
+#define PROPERTY_CURRENTTABLE "CurrentTable"
+#define PROPERTY_TEXTLINECOLOR "TextLineColor"
+#define PROPERTY_TEXTEMPHASIS "FontEmphasisMark"
+#define PROPERTY_TEXTRELIEF "FontRelief"
+#define PROPERTY_DEFAULTTEXT "DefaultText"
+#define PROPERTY_EFFECTIVEDEFAULT "EffectiveDefault"
+#define PROPERTY_AUTOINCREMENTCREATION "AutoIncrementCreation"
+#define PROPERTY_BOOLEANCOMPARISONMODE "BooleanComparisonMode"
+#define PROPERTY_ENABLESQL92CHECK "EnableSQL92Check"
+#define PROPERTY_FONTCHARWIDTH "FontCharWidth"
+#define PROPERTY_FONTCHARSET "FontCharset"
+#define PROPERTY_FONTFAMILY "FontFamily"
+#define PROPERTY_FONTHEIGHT "FontHeight"
+#define PROPERTY_FONTKERNING "FontKerning"
+#define PROPERTY_FONTNAME "FontName"
+#define PROPERTY_FONTORIENTATION "FontOrientation"
+#define PROPERTY_FONTPITCH "FontPitch"
+#define PROPERTY_FONTSLANT "FontSlant"
+#define PROPERTY_FONTSTRIKEOUT "FontStrikeout"
+#define PROPERTY_FONTSTYLENAME "FontStyleName"
+#define PROPERTY_FONTUNDERLINE "FontUnderline"
+#define PROPERTY_FONTWEIGHT "FontWeight"
+#define PROPERTY_FONTWIDTH "FontWidth"
+#define PROPERTY_FONTWORDLINEMODE "FontWordLineMode"
+#define PROPERTY_FONTTYPE "FontType"
+#define PROPERTY_PERSISTENT_NAME "PersistentName"
+#define PROPERTY_EMBEDDEDOBJECT "EmbeddedObject"
+#define PROPERTY_ORIGINAL "Original"
+#define PROPERTY_USECATALOGINSELECT "UseCatalogInSelect"
+#define PROPERTY_USESCHEMAINSELECT "UseSchemaInSelect"
+#define PROPERTY_OUTERJOINESCAPE "EnableOuterJoinEscape"
+#define PROPERTY_AS_TEMPLATE "AsTemplate"
+#define PROPERTY_HAVING_CLAUSE "HavingClause"
+#define PROPERTY_GROUP_BY "GroupBy"
+#define PROPERTY_EDIT_WIDTH "EditWidth"
+#define PROPERTY_SINGLESELECTQUERYCOMPOSER "SingleSelectQueryComposer"
+#define PROPERTY_CHANGE_NOTIFICATION_ENABLED "PropertyChangeNotificationEnabled"
+
+// service names
+
+inline constexpr OUStringLiteral SERVICE_SDBC_RESULTSET = u"com.sun.star.sdbc.ResultSet";
+inline constexpr OUStringLiteral SERVICE_SDBC_ROWSET = u"com.sun.star.sdbc.RowSet";
+inline constexpr OUStringLiteral SERVICE_SDBC_STATEMENT = u"com.sun.star.sdbc.Statement";
+inline constexpr OUStringLiteral SERVICE_SDBC_PREPAREDSTATEMENT
+ = u"com.sun.star.sdbc.PreparedStatement";
+inline constexpr OUStringLiteral SERVICE_SDBC_CALLABLESTATEMENT
+ = u"com.sun.star.sdbc.CallableStatement";
+inline constexpr OUStringLiteral SERVICE_SDBCX_CONTAINER = u"com.sun.star.sdbcx.Container";
+inline constexpr OUStringLiteral SERVICE_SDBCX_TABLE = u"com.sun.star.sdbcx.Table";
+inline constexpr OUStringLiteral SERVICE_SDBCX_RESULTSET = u"com.sun.star.sdbcx.ResultSet";
+inline constexpr OUStringLiteral SERVICE_SDB_CONNECTION = u"com.sun.star.sdb.Connection";
+inline constexpr OUStringLiteral SERVICE_SDBCX_COLUMN = u"com.sun.star.sdbcx.Column";
+inline constexpr OUStringLiteral SERVICE_SDBCX_COLUMNDESCRIPTOR
+ = u"com.sun.star.sdbcx.ColumnDescriptor";
+inline constexpr OUStringLiteral SERVICE_SDB_COLUMNSETTINGS = u"com.sun.star.sdb.ColumnSettings";
+inline constexpr OUStringLiteral SERVICE_SDB_RESULTCOLUMN = u"com.sun.star.sdb.ResultColumn";
+inline constexpr OUStringLiteral SERVICE_SDB_DATACOLUMN = u"com.sun.star.sdb.DataColumn";
+inline constexpr OUStringLiteral SERVICE_SDB_DATASOURCE = u"com.sun.star.sdb.DataSource";
+inline constexpr OUStringLiteral SERVICE_SDB_RESULTSET = u"com.sun.star.sdb.ResultSet";
+inline constexpr OUStringLiteral SERVICE_SDB_ROWSET = u"com.sun.star.sdb.RowSet";
+inline constexpr OUStringLiteral SERVICE_SDB_PREPAREDSTATMENT
+ = u"com.sun.star.sdb.PreparedStatement";
+inline constexpr OUStringLiteral SERVICE_SDB_CALLABLESTATEMENT
+ = u"com.sun.star.sdb.CallableStatement";
+inline constexpr OUStringLiteral SERVICE_SDB_SQLQUERYCOMPOSER
+ = u"com.sun.star.sdb.SQLQueryComposer";
+inline constexpr OUStringLiteral SERVICE_SDB_DATASETTINGS = u"com.sun.star.sdb.DefinitionSettings";
+inline constexpr OUStringLiteral SERVICE_SDB_QUERYDESCRIPTOR = u"com.sun.star.sdb.QueryDescriptor";
+inline constexpr OUStringLiteral SERVICE_SDB_QUERY = u"com.sun.star.sdb.Query";
+inline constexpr OUStringLiteral SERVICE_SDBCX_TABLES = u"com.sun.star.sdbcx.Tables";
+inline constexpr OUStringLiteral SERVICE_SDB_QUERIES = u"com.sun.star.sdb.Queries";
+inline constexpr OUStringLiteral SERVICE_SDB_DOCUMENTDEFINITION
+ = u"com.sun.star.sdb.DocumentDefinition";
+inline constexpr OUStringLiteral SERVICE_NAME_FORM_COLLECTION = u"com.sun.star.sdb.Forms";
+inline constexpr OUStringLiteral SERVICE_NAME_REPORT_COLLECTION = u"com.sun.star.sdb.Reports";
+inline constexpr OUStringLiteral SERVICE_NAME_QUERY_COLLECTION = u"com.sun.star.sdb.Queries";
+inline constexpr OUStringLiteral SERVICE_NAME_SINGLESELECTQUERYCOMPOSER
+ = u"com.sun.star.sdb.SingleSelectQueryComposer";
+inline constexpr OUStringLiteral SERVICE_SDB_APPLICATIONCONTROLLER
+ = u"org.openoffice.comp.dbu.OApplicationController";
+
+// info properties
+inline constexpr OUStringLiteral INFO_JDBCDRIVERCLASS = u"JavaDriverClass";
+inline constexpr OUStringLiteral INFO_TEXTFILEEXTENSION = u"Extension";
+inline constexpr OUStringLiteral INFO_CHARSET = u"CharSet";
+inline constexpr OUStringLiteral INFO_TEXTFILEHEADER = u"HeaderLine";
+inline constexpr OUStringLiteral INFO_FIELDDELIMITER = u"FieldDelimiter";
+inline constexpr OUStringLiteral INFO_TEXTDELIMITER = u"StringDelimiter";
+inline constexpr OUStringLiteral INFO_DECIMALDELIMITER = u"DecimalDelimiter";
+inline constexpr OUStringLiteral INFO_THOUSANDSDELIMITER = u"ThousandDelimiter";
+inline constexpr OUStringLiteral INFO_SHOWDELETEDROWS = u"ShowDeleted";
+inline constexpr OUStringLiteral INFO_ALLOWLONGTABLENAMES = u"NoNameLengthLimit";
+inline constexpr OUStringLiteral INFO_ADDITIONALOPTIONS = u"SystemDriverSettings";
+inline constexpr OUStringLiteral INFO_AUTORETRIEVEVALUE = u"AutoRetrievingStatement";
+inline constexpr OUStringLiteral INFO_AUTORETRIEVEENABLED = u"IsAutoRetrievingEnabled";
+inline constexpr OUStringLiteral INFO_APPEND_TABLE_ALIAS = u"AppendTableAliasName";
+inline constexpr OUStringLiteral INFO_AS_BEFORE_CORRELATION_NAME
+ = u"GenerateASBeforeCorrelationName";
+inline constexpr OUStringLiteral INFO_FORMS_CHECK_REQUIRED_FIELDS = u"FormsCheckRequiredFields";
+inline constexpr OUStringLiteral INFO_PARAMETERNAMESUBST = u"ParameterNameSubstitution";
+inline constexpr OUStringLiteral INFO_IGNOREDRIVER_PRIV = u"IgnoreDriverPrivileges";
+inline constexpr OUStringLiteral INFO_USECATALOG = u"UseCatalog";
+inline constexpr OUStringLiteral INFO_CONN_LDAP_BASEDN = u"BaseDN";
+inline constexpr OUStringLiteral INFO_CONN_LDAP_ROWCOUNT = u"MaxRowCount";
+inline constexpr OUStringLiteral INFO_PREVIEW = u"Preview";
+inline constexpr OUStringLiteral INFO_MEDIATYPE = u"MediaType";
+inline constexpr OUStringLiteral INFO_ESCAPE_DATETIME = u"EscapeDateTime";
+
+// other
+inline constexpr OUStringLiteral INFO_POOLURL = u"PoolURL";
+
+// URLs
+
+inline constexpr OUStringLiteral URL_COMPONENT_QUERYDESIGN = u".component:DB/QueryDesign";
+inline constexpr OUStringLiteral URL_COMPONENT_VIEWDESIGN = u".component:DB/ViewDesign";
+inline constexpr OUStringLiteral URL_COMPONENT_TABLEDESIGN = u".component:DB/TableDesign";
+inline constexpr OUStringLiteral URL_COMPONENT_FORMGRIDVIEW = u".component:DB/FormGridView";
+inline constexpr OUStringLiteral URL_COMPONENT_DATASOURCEBROWSER
+ = u".component:DB/DataSourceBrowser";
+inline constexpr OUStringLiteral URL_COMPONENT_RELATIONDESIGN = u".component:DB/RelationDesign";
+#define URL_COMPONENT_REPORTDESIGN ".component:DB/ReportDesign"
+
+// service names
+
+inline constexpr OUStringLiteral SERVICE_SDB_DIRECTSQLDIALOG
+ = u"org.openoffice.comp.dbu.DirectSqlDialog";
+
+// other DBU relevant strings
+
+#define PROPERTY_QUERYDESIGNVIEW "QueryDesignView"
+#define PROPERTY_GRAPHICAL_DESIGN "GraphicalDesign"
+#define PROPERTY_HELP_URL "HelpURL"
+inline constexpr OUStringLiteral FRAME_NAME_QUERY_PREVIEW = u"QueryPreview";
+inline constexpr OUStringLiteral SERVICE_CONTROLDEFAULT = u"com.sun.star.comp.dbu.OColumnControl";
+
+// other DBU properties
+
+#define PROPERTY_ENABLEOUTERJOIN "EnableOuterJoinEscape"
+#define PROPERTY_TABSTOP "TabStop"
+#define PROPERTY_DEFAULTCONTROL "DefaultControl"
+#define PROPERTY_ENABLED "Enabled"
+#define PROPERTY_MOUSE_WHEEL_BEHAVIOR "MouseWheelBehavior"
+
+inline constexpr OUStringLiteral SQLSTATE_GENERAL = u"01000";
+
+#define PROPERTY_IS_FORM "IsForm"
+#define PROPERTY_PERSISTENT_PATH "PersistentPath"
+
+inline constexpr OUStringLiteral STR_AUTOTEXTSEPARATORLIST = u"\"\t34\t'\t39";
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/dbaccess/inc/templwin.hrc b/dbaccess/inc/templwin.hrc
new file mode 100644
index 000000000..052883d37
--- /dev/null
+++ b/dbaccess/inc/templwin.hrc
@@ -0,0 +1,57 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <utility>
+#include <unotools/resmgr.hxx>
+
+#define NC_(Context, String) TranslateId(Context, reinterpret_cast<char const *>(u8##String))
+
+#define DI_TITLE 1
+#define DI_FROM 2
+#define DI_DATE 3
+#define DI_KEYWORDS 4
+#define DI_DESCRIPTION 5
+#define DI_MIMETYPE 6
+#define DI_MODIFIEDDATE 7
+#define DI_MODIFIEDBY 8
+#define DI_PRINTDATE 9
+#define DI_PRINTBY 10
+#define DI_THEME 11
+#define DI_SIZE 12
+
+const std::pair<TranslateId, int> STRARY_SVT_DOCINFO[] =
+{
+ { NC_("STRARY_SVT_DOCINFO", "Title") , DI_TITLE },
+ { NC_("STRARY_SVT_DOCINFO", "By") , DI_FROM },
+ { NC_("STRARY_SVT_DOCINFO", "Date") , DI_DATE },
+ { NC_("STRARY_SVT_DOCINFO", "Keywords") , DI_KEYWORDS },
+ { NC_("STRARY_SVT_DOCINFO", "Description") , DI_DESCRIPTION },
+ { NC_("STRARY_SVT_DOCINFO", "Type") , DI_MIMETYPE },
+ { NC_("STRARY_SVT_DOCINFO", "Modified on") , DI_MODIFIEDDATE },
+ { NC_("STRARY_SVT_DOCINFO", "Modified by") , DI_MODIFIEDBY },
+ { NC_("STRARY_SVT_DOCINFO", "Printed on") , DI_PRINTDATE },
+ { NC_("STRARY_SVT_DOCINFO", "Printed by") , DI_PRINTBY },
+ { NC_("STRARY_SVT_DOCINFO", "Subject") , DI_THEME },
+ { NC_("STRARY_SVT_DOCINFO", "Size") , DI_SIZE }
+};
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/qa/complex/dbaccess/ApplicationController.java b/dbaccess/qa/complex/dbaccess/ApplicationController.java
new file mode 100644
index 000000000..eafc32dba
--- /dev/null
+++ b/dbaccess/qa/complex/dbaccess/ApplicationController.java
@@ -0,0 +1,159 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+package complex.dbaccess;
+
+import com.sun.star.beans.PropertyValue;
+import com.sun.star.container.XNameAccess;
+import com.sun.star.frame.FrameSearchFlag;
+import com.sun.star.frame.XComponentLoader;
+import com.sun.star.frame.XModel;
+import com.sun.star.frame.XStorable;
+import com.sun.star.lang.XComponent;
+import com.sun.star.sdb.XOfficeDatabaseDocument;
+import com.sun.star.sdb.application.XDatabaseDocumentUI;
+import com.sun.star.sdbcx.XTablesSupplier;
+import com.sun.star.uno.Exception;
+import com.sun.star.uno.UnoRuntime;
+import connectivity.tools.HsqlColumnDescriptor;
+import connectivity.tools.HsqlDatabase;
+import connectivity.tools.HsqlTableDescriptor;
+import java.io.IOException;
+
+
+// ---------- junit imports -----------------
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+
+/** complex test case for Base's application UI
+ */
+public class ApplicationController extends TestCase
+{
+
+ private HsqlDatabase m_database;
+ private XOfficeDatabaseDocument m_databaseDocument;
+ private XDatabaseDocumentUI m_documentUI;
+
+ public String getTestObjectName()
+ {
+ return getClass().getName();
+ }
+
+
+ private void impl_closeDocument()
+ {
+ if (m_database != null)
+ {
+ m_database.close();
+ m_database = null;
+ m_databaseDocument = null;
+ m_documentUI = null;
+ }
+ }
+
+
+ private void impl_switchToDocument(String _documentURL) throws java.lang.Exception
+ {
+ // close previous database document
+ impl_closeDocument();
+
+ // create/load the new database document
+ m_database = (_documentURL == null)
+ ? new HsqlDatabase(getMSF())
+ : new HsqlDatabase(getMSF(), _documentURL);
+ m_databaseDocument = m_database.getDatabaseDocument();
+
+ // load it into a frame
+ final Object object = getMSF().createInstance("com.sun.star.frame.Desktop");
+ final XComponentLoader xComponentLoader = UnoRuntime.queryInterface(XComponentLoader.class, object);
+ final XComponent loadedComponent = xComponentLoader.loadComponentFromURL(m_database.getDocumentURL(), "_blank", FrameSearchFlag.ALL, new PropertyValue[0]);
+
+ assertTrue("too many document instances!",
+ UnoRuntime.areSame(loadedComponent, m_databaseDocument));
+
+ // get the controller, which provides access to various UI operations
+ final XModel docModel = UnoRuntime.queryInterface(XModel.class,
+ loadedComponent);
+ m_documentUI = UnoRuntime.queryInterface(XDatabaseDocumentUI.class,
+ docModel.getCurrentController());
+ }
+
+
+ @Before
+ @Override
+ public void before() throws java.lang.Exception
+ {
+ super.before();
+ impl_switchToDocument(null);
+ }
+
+
+ @After
+ @Override
+ public void after() throws java.lang.Exception
+ {
+ impl_closeDocument();
+ super.after();
+ }
+
+
+ @Test
+ public void checkSaveAs() throws Exception, IOException, java.lang.Exception
+ {
+ // issue 93737 describes the problem that when you save-as a database document, and do changes to it,
+ // then those changes are saved in the old document, actually
+ final String oldDocumentURL = m_database.getDocumentURL();
+
+ final String newDocumentURL = createTempFileURL();
+
+ // store the doc in a new location
+ final XStorable storeDoc = UnoRuntime.queryInterface( XStorable.class, m_databaseDocument );
+ storeDoc.storeAsURL( newDocumentURL, new PropertyValue[] { } );
+
+ // connect
+ m_documentUI.connect();
+ assertTrue("could not connect to " + m_database.getDocumentURL(), m_documentUI.isConnected());
+
+ // create a table in the database
+ m_database.createTable(new HsqlTableDescriptor("abc", new HsqlColumnDescriptor[]
+ {
+ new HsqlColumnDescriptor("a", "VARCHAR(50)"),
+ new HsqlColumnDescriptor("b", "VARCHAR(50)"),
+ new HsqlColumnDescriptor("c", "VARCHAR(50)")
+ }));
+
+ // load the old document, and verify there is *no* table therein
+ impl_switchToDocument(oldDocumentURL);
+ m_documentUI.connect();
+ assertTrue("could not connect to " + m_database.getDocumentURL(), m_documentUI.isConnected());
+ XTablesSupplier suppTables = UnoRuntime.queryInterface( XTablesSupplier.class, m_documentUI.getActiveConnection() );
+ XNameAccess tables = suppTables.getTables();
+ assertTrue("the table was created in the wrong database", !tables.hasByName("abc"));
+
+ // load the new document, and verify there *is* a table therein
+ impl_switchToDocument(newDocumentURL);
+ m_documentUI.connect();
+ assertTrue("could not connect to " + m_database.getDocumentURL(), m_documentUI.isConnected());
+
+ suppTables = UnoRuntime.queryInterface( XTablesSupplier.class, m_documentUI.getActiveConnection() );
+ tables = suppTables.getTables();
+ assertTrue("the newly created table has not been written", tables.hasByName("abc"));
+ }
+}
diff --git a/dbaccess/qa/complex/dbaccess/Beamer.java b/dbaccess/qa/complex/dbaccess/Beamer.java
new file mode 100644
index 000000000..3342c70df
--- /dev/null
+++ b/dbaccess/qa/complex/dbaccess/Beamer.java
@@ -0,0 +1,127 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+package complex.dbaccess;
+
+import com.sun.star.beans.PropertyState;
+import com.sun.star.beans.PropertyValue;
+import com.sun.star.container.XEnumeration;
+import com.sun.star.frame.FrameSearchFlag;
+import com.sun.star.frame.XComponentLoader;
+import com.sun.star.frame.XController;
+import com.sun.star.frame.XDispatch;
+import com.sun.star.frame.XDispatchProvider;
+import com.sun.star.frame.XFrame;
+import com.sun.star.frame.XGlobalEventBroadcaster;
+import com.sun.star.frame.XModel;
+import com.sun.star.frame.theGlobalEventBroadcaster;
+import com.sun.star.lang.XComponent;
+import com.sun.star.sdb.CommandType;
+import com.sun.star.uno.Exception;
+import com.sun.star.uno.UnoRuntime;
+import com.sun.star.util.URL;
+import com.sun.star.util.XURLTransformer;
+import com.sun.star.view.XSelectionSupplier;
+// ---------- junit imports -----------------
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+
+
+/** complex test case for Base's application UI
+ */
+public class Beamer extends TestCase
+{
+
+ private XModel docModel;
+
+ @Before
+ @Override
+ public void before() throws Exception, java.lang.Exception
+ {
+ // load it into a frame
+ final Object object = getMSF().createInstance("com.sun.star.frame.Desktop");
+ final XComponentLoader xComponentLoader = UnoRuntime.queryInterface(XComponentLoader.class, object);
+ final XComponent loadedComponent = xComponentLoader.loadComponentFromURL("private:factory/swriter", "_blank", 0, new PropertyValue[0]);
+ // get the controller, which provides access to various UI operations
+ docModel = UnoRuntime.queryInterface(XModel.class, loadedComponent);
+ }
+
+
+ @After
+ @Override
+ public void after()
+ {
+ }
+
+
+ @Test
+ public void testBeamer() throws Exception, java.lang.Exception
+ {
+ final XController controller = docModel.getCurrentController();
+ final XFrame frame = controller.getFrame();
+ final XDispatchProvider dispatchP = UnoRuntime.queryInterface(XDispatchProvider.class, frame);
+ URL command = new URL();
+ command.Complete = ".uno:ViewDataSourceBrowser";
+
+ Object instance = getMSF().createInstance("com.sun.star.util.URLTransformer");
+ XURLTransformer atrans = UnoRuntime.queryInterface(XURLTransformer.class, instance);
+ com.sun.star.util.URL[] aURLA = new com.sun.star.util.URL[1];
+ aURLA[0] = command;
+ atrans.parseStrict(aURLA);
+ command = aURLA[0];
+
+ final XDispatch dispatch = dispatchP.queryDispatch(command, "_self", FrameSearchFlag.AUTO);
+ assertNotNull(dispatch);
+ dispatch.dispatch(command, new PropertyValue[0]);
+
+ final PropertyValue[] props = new PropertyValue[]
+ {
+ new PropertyValue("DataSourceName", 0, "Bibliography", PropertyState.DIRECT_VALUE),
+ new PropertyValue("CommandType", 0, Integer.valueOf(CommandType.TABLE), PropertyState.DIRECT_VALUE),
+ new PropertyValue("Command", 0, "biblio", PropertyState.DIRECT_VALUE)
+ };
+
+ final XFrame beamer = frame.findFrame("_beamer", 0);
+ assertNotNull(beamer);
+ final XGlobalEventBroadcaster evtBc = theGlobalEventBroadcaster.get(
+ getComponentContext());
+ XEnumeration enumeration = evtBc.createEnumeration();
+ int count = -1;
+ while (enumeration.hasMoreElements())
+ {
+ enumeration.nextElement();
+ ++count;
+ }
+ final XSelectionSupplier selSup = UnoRuntime.queryInterface(XSelectionSupplier.class, beamer.getController());
+ selSup.select(props);
+ final com.sun.star.util.XCloseable close = UnoRuntime.queryInterface(com.sun.star.util.XCloseable.class, frame);
+ close.close(false);
+
+ enumeration = evtBc.createEnumeration();
+ int count2 = 0;
+ while (enumeration.hasMoreElements())
+ {
+ enumeration.nextElement();
+ ++count2;
+ }
+
+ assertTrue("count1 = " + count + " count2 = " + count2, count == count2);
+ }
+}
diff --git a/dbaccess/qa/complex/dbaccess/CRMBasedTestCase.java b/dbaccess/qa/complex/dbaccess/CRMBasedTestCase.java
new file mode 100644
index 000000000..a61ffdfa7
--- /dev/null
+++ b/dbaccess/qa/complex/dbaccess/CRMBasedTestCase.java
@@ -0,0 +1,63 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+package complex.dbaccess;
+
+import com.sun.star.sdb.XSingleSelectQueryComposer;
+import connectivity.tools.CRMDatabase;
+
+// ---------- junit imports -----------------
+import org.junit.After;
+import org.junit.Before;
+
+
+public abstract class CRMBasedTestCase extends TestCase
+{
+ protected CRMDatabase m_database;
+
+ protected void createTestCase() throws Exception
+ {
+ m_database = new CRMDatabase( getMSF(), false );
+ }
+
+
+ @Before
+ @Override
+ public void before() throws Exception
+ {
+ createTestCase();
+ }
+
+
+ @After
+ @Override
+ public void after() throws Exception
+ {
+ if ( m_database != null )
+ {
+ m_database.saveAndClose();
+ }
+ }
+
+
+ /** creates a SingleSelectQueryComposer for our connection
+ */
+ protected final XSingleSelectQueryComposer createQueryComposer() throws com.sun.star.uno.Exception
+ {
+ return m_database.getConnection().createSingleSelectQueryComposer();
+ }
+}
diff --git a/dbaccess/qa/complex/dbaccess/CopyTableInterActionHandler.java b/dbaccess/qa/complex/dbaccess/CopyTableInterActionHandler.java
new file mode 100644
index 000000000..57f4172e3
--- /dev/null
+++ b/dbaccess/qa/complex/dbaccess/CopyTableInterActionHandler.java
@@ -0,0 +1,37 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+package complex.dbaccess;
+
+import com.sun.star.lib.uno.helper.WeakBase;
+import com.sun.star.task.XInteractionHandler;
+import com.sun.star.task.XInteractionRequest;
+
+import static org.junit.Assert.*;
+
+class CopyTableInterActionHandler extends WeakBase
+ implements XInteractionHandler
+{
+ CopyTableInterActionHandler()
+ {
+ }
+
+ public void handle(XInteractionRequest xRequest)
+ {
+ fail( "interaction handler is not expected to be called" );
+ }
+}
diff --git a/dbaccess/qa/complex/dbaccess/CopyTableWizard.java b/dbaccess/qa/complex/dbaccess/CopyTableWizard.java
new file mode 100644
index 000000000..a9254fac3
--- /dev/null
+++ b/dbaccess/qa/complex/dbaccess/CopyTableWizard.java
@@ -0,0 +1,194 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+package complex.dbaccess;
+
+import com.sun.star.accessibility.XAccessible;
+import com.sun.star.accessibility.XAccessibleContext;
+import com.sun.star.awt.XExtendedToolkit;
+import com.sun.star.awt.XWindow;
+import com.sun.star.beans.Optional;
+import com.sun.star.beans.XPropertySet;
+import com.sun.star.container.XNameAccess;
+import com.sun.star.sdb.CommandType;
+import com.sun.star.sdb.application.XCopyTableWizard;
+import com.sun.star.sdb.DataAccessDescriptorFactory;
+import com.sun.star.sdbc.XConnection;
+import com.sun.star.sdbcx.XTablesSupplier;
+import com.sun.star.task.XInteractionHandler;
+import com.sun.star.uno.UnoRuntime;
+import com.sun.star.uno.XComponentContext;
+import connectivity.tools.DbaseDatabase;
+import java.io.IOException;
+import util.UITools;
+
+// ---------- junit imports -----------------
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+
+/** complex test case for Base's application UI
+ */
+public class CopyTableWizard extends CRMBasedTestCase
+{
+
+ private DatabaseApplication source;
+ private DbaseDatabase destinationDB = null;
+ private DatabaseApplication dest;
+
+ @After
+ @Override
+ public void after() throws Exception
+ {
+ dest.store();
+ if ( destinationDB != null )
+ destinationDB.close();
+ destinationDB = null;
+ super.after();
+ }
+
+ @Before
+ @Override
+ public void before() throws Exception
+ {
+ createTestCase();
+ source = new DatabaseApplication(m_database.getDatabase());
+ destinationDB = new DbaseDatabase( getMSF() );
+ dest = new DatabaseApplication( destinationDB );
+ }
+
+
+ private static class CopyThread implements Runnable
+ {
+
+ private final XCopyTableWizard copyWizard;
+
+ private CopyThread(final XCopyTableWizard copyWizard)
+ {
+ this.copyWizard = copyWizard;
+ }
+
+ public void run()
+ {
+ copyWizard.execute();
+ }
+ }
+
+ private XWindow getActiveWindow()
+ {
+ Object toolKit = null;
+ try
+ {
+ toolKit = getMSF().createInstance("com.sun.star.awt.Toolkit");
+ }
+ catch (com.sun.star.uno.Exception e)
+ {
+ return null;
+ }
+
+ XExtendedToolkit tk = UnoRuntime.queryInterface( XExtendedToolkit.class, toolKit );
+ Object atw = tk.getActiveTopWindow();
+ return UnoRuntime.queryInterface( XWindow.class, atw );
+ }
+
+ @Test
+ public void copyTable() throws Exception, IOException, java.lang.Exception
+ {
+ copyTable(source,source);
+ }
+
+ @Test
+ public void copyTableDbase() throws Exception, IOException, java.lang.Exception
+ {
+ copyTable(source,dest);
+ }
+ private void copyTable(final DatabaseApplication sourceDb,final DatabaseApplication destDb) throws Exception, IOException, java.lang.Exception
+ {
+ final XConnection destConnection = destDb.getDocumentUI().getActiveConnection();
+
+ final XConnection sourceConnection = sourceDb.getDocumentUI().getActiveConnection();
+ final XTablesSupplier suppTables = UnoRuntime.queryInterface(XTablesSupplier.class, sourceConnection);
+ final XNameAccess tables = suppTables.getTables();
+
+ final String[] names = tables.getElementNames();
+ for (int i = 0; i < names.length; i++)
+ {
+ copyTable(names[i], sourceConnection, destConnection);
+ }
+ }
+
+ private void copyTable(final String tableName, final XConnection sourceConnection, final XConnection destConnection) throws Exception, java.lang.Exception
+ {
+
+ final XInteractionHandler interAction = new CopyTableInterActionHandler();
+ final XComponentContext context = getComponentContext();
+ final XPropertySet sourceDescriptor = DataAccessDescriptorFactory.get(context).createDataAccessDescriptor();
+ sourceDescriptor.setPropertyValue("CommandType", CommandType.TABLE);
+ sourceDescriptor.setPropertyValue("Command", tableName);
+ sourceDescriptor.setPropertyValue("ActiveConnection", sourceConnection);
+
+ final XPropertySet destDescriptor = DataAccessDescriptorFactory.get(context).createDataAccessDescriptor();
+ destDescriptor.setPropertyValue("ActiveConnection", destConnection);
+
+ final XCopyTableWizard copyWizard = com.sun.star.sdb.application.CopyTableWizard.createWithInteractionHandler(
+ context, sourceDescriptor, destDescriptor, interAction);
+ copyWizard.setOperation((short) 0); // com.sun.star.sdb.application.CopyDefinitionAndData
+ Optional<String> auto = new Optional<String>();
+
+ auto.IsPresent = destConnection.getMetaData().supportsCoreSQLGrammar();
+ if (auto.IsPresent)
+ {
+ auto.Value = "ID_test";
+ }
+ copyWizard.setCreatePrimaryKey(auto);
+ Thread thread = new Thread(new CopyThread(copyWizard));
+ thread.start();
+ util.utils.shortWait();
+
+ try
+ {
+ final XWindow dialog = getActiveWindow();
+ final UITools uiTools = new UITools(dialog);
+ final XAccessible root = uiTools.getRoot();
+ final XAccessibleContext accContext = root.getAccessibleContext();
+ final int count = accContext.getAccessibleChildCount();
+ String buttonName = "Create";
+ final XAccessibleContext childContext = accContext.getAccessibleChild(count - 3).getAccessibleContext();
+ final String name = childContext.getAccessibleName();
+ if (name != null && !"".equals(name))
+ {
+ buttonName = name;
+ }
+ try
+ {
+ uiTools.clickButton(buttonName);
+ }
+ catch (java.lang.Exception exception)
+ {
+ exception.printStackTrace( System.err );
+ }
+ }
+ catch (com.sun.star.lang.IndexOutOfBoundsException indexOutOfBoundsException)
+ {
+ }
+ util.utils.shortWait();
+
+ thread.join();
+ }
+
+}
diff --git a/dbaccess/qa/complex/dbaccess/DataSource.java b/dbaccess/qa/complex/dbaccess/DataSource.java
new file mode 100644
index 000000000..0413a6e07
--- /dev/null
+++ b/dbaccess/qa/complex/dbaccess/DataSource.java
@@ -0,0 +1,68 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+package complex.dbaccess;
+
+import com.sun.star.container.XNameAccess;
+import com.sun.star.uno.UnoRuntime;
+import com.sun.star.uno.XNamingService;
+import connectivity.tools.CRMDatabase;
+import connectivity.tools.HsqlDatabase;
+
+// ---------- junit imports -----------------
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+
+
+public class DataSource extends TestCase
+{
+
+ HsqlDatabase m_database;
+ connectivity.tools.DataSource m_dataSource;
+
+
+ private void createTestCase() throws Exception
+ {
+ if (m_database == null)
+ {
+ final CRMDatabase database = new CRMDatabase( getMSF(), false );
+ m_database = database.getDatabase();
+ m_dataSource = m_database.getDataSource();
+ }
+ }
+
+
+ @Test
+ public void testRegistrationName() throws Exception
+ {
+ createTestCase();
+ // 1. check the existing "Bibliography" data source whether it has the proper name
+ String dataSourceName = "Bibliography";
+ final connectivity.tools.DataSource bibliography = new connectivity.tools.DataSource(getMSF(), dataSourceName);
+ assertEquals("pre-registered database has a wrong name!", dataSourceName, bibliography.getName());
+ // 2. register a newly created data source, and verify it has the proper name
+ dataSourceName = "someDataSource";
+ final XNamingService dataSourceRegistrations = UnoRuntime.queryInterface(
+ XNamingService.class, getMSF().createInstance( "com.sun.star.sdb.DatabaseContext" ) );
+ final XNameAccess existenceCheck = UnoRuntime.queryInterface( XNameAccess.class, dataSourceRegistrations );
+ if ( existenceCheck.hasByName( "someDataSource" ) )
+ dataSourceRegistrations.revokeObject( "someDataSource" );
+ dataSourceRegistrations.registerObject("someDataSource", m_dataSource.getXDataSource());
+ assertEquals("registration name of a newly registered data source is wrong", dataSourceName, m_dataSource.getName());
+ }
+}
diff --git a/dbaccess/qa/complex/dbaccess/DatabaseApplication.java b/dbaccess/qa/complex/dbaccess/DatabaseApplication.java
new file mode 100644
index 000000000..dad7644f8
--- /dev/null
+++ b/dbaccess/qa/complex/dbaccess/DatabaseApplication.java
@@ -0,0 +1,73 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+package complex.dbaccess;
+
+import com.sun.star.beans.PropertyValue;
+import com.sun.star.frame.FrameSearchFlag;
+import com.sun.star.frame.XComponentLoader;
+import com.sun.star.frame.XModel;
+import com.sun.star.frame.XStorable;
+import com.sun.star.lang.XComponent;
+import com.sun.star.sdb.XOfficeDatabaseDocument;
+import com.sun.star.sdb.application.XDatabaseDocumentUI;
+import com.sun.star.uno.Exception;
+import com.sun.star.uno.UnoRuntime;
+import connectivity.tools.DatabaseAccess;
+
+public class DatabaseApplication
+{
+
+ private final XOfficeDatabaseDocument databaseDocument;
+ private final XDatabaseDocumentUI documentUI;
+
+ public DatabaseApplication(final DatabaseAccess _db) throws Exception
+ {
+ databaseDocument = _db.getDatabaseDocument();
+
+ // load it into a frame
+ final Object object = _db.getORB().createInstance("com.sun.star.frame.Desktop");
+ final XComponentLoader xComponentLoader = UnoRuntime.queryInterface(XComponentLoader.class, object);
+ final XComponent loadedComponent = xComponentLoader.loadComponentFromURL(_db.getDocumentURL(), "_blank", FrameSearchFlag.ALL, new PropertyValue[0]);
+
+ // get the controller, which provides access to various UI operations
+ final XModel docModel = UnoRuntime.queryInterface(XModel.class, loadedComponent);
+ documentUI = UnoRuntime.queryInterface(XDatabaseDocumentUI.class, docModel.getCurrentController());
+ documentUI.connect();
+ }
+
+ public XDatabaseDocumentUI getDocumentUI()
+ {
+ return documentUI;
+ }
+
+ public void store()
+ {
+ // store the doc in a new location
+ try
+ {
+ final XStorable storeDoc = UnoRuntime.queryInterface(XStorable.class, databaseDocument);
+ if (storeDoc != null)
+ {
+ storeDoc.store();
+ }
+ }
+ catch (com.sun.star.io.IOException iOException)
+ {
+ }
+ }
+}
diff --git a/dbaccess/qa/complex/dbaccess/DatabaseDocument.java b/dbaccess/qa/complex/dbaccess/DatabaseDocument.java
new file mode 100644
index 000000000..5bd28053b
--- /dev/null
+++ b/dbaccess/qa/complex/dbaccess/DatabaseDocument.java
@@ -0,0 +1,995 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+package complex.dbaccess;
+
+import com.sun.star.configuration.theDefaultProvider;
+import com.sun.star.lang.NotInitializedException;
+import com.sun.star.frame.DoubleInitializationException;
+import com.sun.star.awt.XTopWindow;
+import com.sun.star.beans.PropertyState;
+import com.sun.star.document.DocumentEvent;
+import com.sun.star.lang.XEventListener;
+import com.sun.star.lang.XMultiServiceFactory;
+import com.sun.star.script.XStorageBasedLibraryContainer;
+import com.sun.star.task.XInteractionRequest;
+
+import com.sun.star.uno.Type;
+import com.sun.star.uno.UnoRuntime;
+import com.sun.star.frame.XStorable;
+import com.sun.star.beans.NamedValue;
+import com.sun.star.beans.PropertyValue;
+import com.sun.star.beans.XPropertySet;
+import com.sun.star.container.XNameContainer;
+import com.sun.star.container.XSet;
+import com.sun.star.document.XDocumentEventListener;
+import com.sun.star.document.XEmbeddedScripts;
+import com.sun.star.document.XEventsSupplier;
+import com.sun.star.lang.XComponent;
+import com.sun.star.frame.XComponentLoader;
+import com.sun.star.frame.XDispatch;
+import com.sun.star.frame.XDispatchProvider;
+import com.sun.star.frame.XFrame;
+import com.sun.star.frame.XGlobalEventBroadcaster;
+import com.sun.star.frame.XLoadable;
+import com.sun.star.frame.XModel;
+import com.sun.star.frame.XModel2;
+import com.sun.star.frame.XTitle;
+import com.sun.star.frame.theGlobalEventBroadcaster;
+import com.sun.star.lang.EventObject;
+import com.sun.star.lang.XServiceInfo;
+import com.sun.star.lang.XSingleComponentFactory;
+import com.sun.star.lang.XTypeProvider;
+import com.sun.star.script.provider.XScriptProviderSupplier;
+import com.sun.star.sdb.XDocumentDataSource;
+
+import com.sun.star.sdb.XFormDocumentsSupplier;
+import com.sun.star.sdb.XOfficeDatabaseDocument;
+import com.sun.star.sdb.XReportDocumentsSupplier;
+import com.sun.star.task.DocumentMacroConfirmationRequest;
+import com.sun.star.task.XInteractionApprove;
+import com.sun.star.task.XInteractionContinuation;
+import com.sun.star.task.XInteractionHandler;
+import com.sun.star.uno.XComponentContext;
+import com.sun.star.util.CloseVetoException;
+import com.sun.star.util.URL;
+import com.sun.star.util.XChangesBatch;
+import com.sun.star.util.XCloseable;
+import com.sun.star.util.XModifiable;
+import com.sun.star.util.XURLTransformer;
+import java.io.IOException;
+import java.util.Iterator;
+import java.util.ArrayList;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+// ---------- junit imports -----------------
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+
+public class DatabaseDocument extends TestCase implements com.sun.star.document.XDocumentEventListener
+{
+
+ private static final String _BLANK = "_blank";
+ private XComponent m_callbackFactory = null;
+ private final ArrayList<String> m_documentEvents = new ArrayList<String>();
+ private final ArrayList<String> m_globalEvents = new ArrayList<String>();
+ // for those states, see testDocumentEvents
+ private static short STATE_NOT_STARTED = 0;
+ private static short STATE_LOADING_DOC = 1;
+ private static short STATE_MACRO_EXEC_APPROVED = 2;
+ private static short STATE_ON_LOAD_RECEIVED = 3;
+ private short m_loadDocState = STATE_NOT_STARTED;
+
+
+ /** a helper class which can be used by the Basic scripts in our test documents
+ * to notify us of events in this document
+ */
+ private class CallbackComponent implements XDocumentEventListener, XTypeProvider
+ {
+
+ public void documentEventOccured(DocumentEvent _event)
+ {
+ onDocumentEvent(_event);
+ }
+
+ public void disposing(com.sun.star.lang.EventObject _Event)
+ {
+ // not interested in
+ }
+
+ public Type[] getTypes()
+ {
+ final Class interfaces[] = getClass().getInterfaces();
+ Type types[] = new Type[interfaces.length];
+ for (int i = 0; i < interfaces.length; ++i)
+ {
+ types[i] = new Type(interfaces[i]);
+ }
+ return types;
+ }
+
+ public byte[] getImplementationId()
+ {
+ return new byte[0];
+ }
+ }
+
+
+ private static String getCallbackComponentServiceName()
+ {
+ return "org.openoffice.complex.dbaccess.EventCallback";
+ }
+
+
+ /** a factory for a CallbackComponent
+ */
+ private class CallbackComponentFactory implements XSingleComponentFactory, XServiceInfo, XComponent
+ {
+
+ private final ArrayList<XEventListener> m_eventListeners = new ArrayList<XEventListener>();
+
+ public Object createInstanceWithContext(XComponentContext _context) throws com.sun.star.uno.Exception
+ {
+ return new CallbackComponent();
+ }
+
+ public Object createInstanceWithArgumentsAndContext(Object[] arg0, XComponentContext _context) throws com.sun.star.uno.Exception
+ {
+ return createInstanceWithContext(_context);
+ }
+
+ public String getImplementationName()
+ {
+ return "org.openoffice.complex.dbaccess.CallbackComponent";
+ }
+
+ public boolean supportsService(String _service)
+ {
+ return _service.equals(getCallbackComponentServiceName());
+ }
+
+ public String[] getSupportedServiceNames()
+ {
+ return new String[]
+ {
+ getCallbackComponentServiceName()
+ };
+ }
+
+ public void dispose()
+ {
+ final EventObject event = new EventObject(this);
+
+ final ArrayList<XEventListener> eventListenersCopy = (ArrayList<XEventListener>)m_eventListeners.clone();
+ final Iterator<XEventListener> iter = eventListenersCopy.iterator();
+ while (iter.hasNext())
+ {
+ iter.next().disposing(event);
+ }
+ }
+
+ public void addEventListener(XEventListener _listener)
+ {
+ if (_listener != null)
+ {
+ m_eventListeners.add(_listener);
+ }
+ }
+
+ public void removeEventListener(XEventListener _listener)
+ {
+ m_eventListeners.remove(_listener);
+ }
+ }
+
+
+ private class MacroExecutionApprove implements XInteractionHandler
+ {
+
+ private XInteractionHandler m_defaultHandler = null;
+
+ MacroExecutionApprove(XMultiServiceFactory _factory)
+ {
+ try
+ {
+ m_defaultHandler = UnoRuntime.queryInterface(XInteractionHandler.class, _factory.createInstance("com.sun.star.task.InteractionHandler"));
+ }
+ catch (Exception ex)
+ {
+ Logger.getLogger(DatabaseDocument.class.getName()).log(Level.SEVERE, null, ex);
+ }
+ }
+
+ public void handle(XInteractionRequest _request)
+ {
+ final Object request = _request.getRequest();
+ if (!(request instanceof DocumentMacroConfirmationRequest) && (m_defaultHandler != null))
+ {
+ m_defaultHandler.handle(_request);
+ return;
+ }
+
+ assertEquals("interaction handler called in wrong state", STATE_LOADING_DOC, m_loadDocState);
+
+ // auto-approve
+ final XInteractionContinuation continuations[] = _request.getContinuations();
+ for (int i = 0; i < continuations.length; ++i)
+ {
+ final XInteractionApprove approve = UnoRuntime.queryInterface(XInteractionApprove.class, continuations[i]);
+ if (approve != null)
+ {
+ approve.select();
+ m_loadDocState = STATE_MACRO_EXEC_APPROVED;
+ break;
+ }
+ }
+ }
+ }
+
+
+
+ @Override
+ @Before
+ public void before() throws java.lang.Exception
+ {
+ super.before();
+
+ try
+ {
+ // at our service factory, insert a new factory for our CallbackComponent
+ // this will allow the Basic code in our test documents to call back into this test case
+ // here, by just instantiating this service
+ final XSet globalFactory = UnoRuntime.queryInterface(XSet.class, getMSF());
+ m_callbackFactory = new CallbackComponentFactory();
+ globalFactory.insert(m_callbackFactory);
+
+ // register ourself as listener at the global event broadcaster
+ final XGlobalEventBroadcaster broadcaster
+ = theGlobalEventBroadcaster.get(getComponentContext());
+ broadcaster.addDocumentEventListener(this);
+ }
+ catch (Exception e)
+ {
+ System.out.println("could not create the test case, error message:\n" + e.getMessage());
+ e.printStackTrace(System.err);
+ fail("failed to create the test case");
+ }
+ }
+
+
+ @Override
+ @After
+ public void after() throws java.lang.Exception
+ {
+ try
+ {
+ // dispose our callback factory. This will automatically remove it from our service
+ // factory
+ m_callbackFactory.dispose();
+
+ // revoke ourself as listener at the global event broadcaster
+ final XGlobalEventBroadcaster broadcaster
+ = theGlobalEventBroadcaster.get(getComponentContext());
+ broadcaster.removeDocumentEventListener(this);
+ }
+ catch (Exception e)
+ {
+ System.out.println("could not create the test case, error message:\n" + e.getMessage());
+ e.printStackTrace(System.err);
+ fail("failed to close the test case");
+ }
+
+ super.after();
+ }
+
+
+ private static class UnoMethodDescriptor
+ {
+
+ public Class unoInterfaceClass = null;
+ public String methodName = null;
+
+ UnoMethodDescriptor(Class _class, String _method)
+ {
+ unoInterfaceClass = _class;
+ methodName = _method;
+ }
+ }
+
+
+ private void impl_checkDocumentInitState(Object _document, boolean _isInitialized)
+ {
+ // things you cannot do with an uninitialized document:
+ final UnoMethodDescriptor[] unsupportedMethods = new UnoMethodDescriptor[]
+ {
+ new UnoMethodDescriptor(XStorable.class, "store"),
+ new UnoMethodDescriptor(XFormDocumentsSupplier.class, "getFormDocuments"),
+ new UnoMethodDescriptor(XReportDocumentsSupplier.class, "getReportDocuments"),
+ new UnoMethodDescriptor(XScriptProviderSupplier.class, "getScriptProvider"),
+ new UnoMethodDescriptor(XEventsSupplier.class, "getEvents"),
+ new UnoMethodDescriptor(XTitle.class, "getTitle"),
+ new UnoMethodDescriptor(XModel2.class, "getControllers")
+ // (there's much more than this, but we cannot list all methods here, can we ...)
+ };
+
+ for (int i = 0; i < unsupportedMethods.length; ++i)
+ {
+ assureException( _document, unsupportedMethods[i].unoInterfaceClass,
+ unsupportedMethods[i].methodName, new Object[]{}, _isInitialized ? null : NotInitializedException.class );
+ }
+ }
+
+
+ private XModel impl_createDocument() throws Exception
+ {
+ final XModel databaseDoc = UnoRuntime.queryInterface(XModel.class, getMSF().createInstance("com.sun.star.sdb.OfficeDatabaseDocument"));
+
+ // should not be initialized here - we did neither initNew nor load nor storeAsURL it
+ impl_checkDocumentInitState(databaseDoc, false);
+
+ return databaseDoc;
+ }
+
+
+ private void impl_closeDocument(XModel _databaseDoc) throws CloseVetoException, Exception
+ {
+ final XCloseable closeDoc = UnoRuntime.queryInterface(XCloseable.class, _databaseDoc);
+ closeDoc.close(true);
+ }
+
+
+ private XModel impl_createEmptyEmbeddedHSQLDocument() throws Exception, IOException
+ {
+ final XModel databaseDoc = UnoRuntime.queryInterface(XModel.class, getMSF().createInstance("com.sun.star.sdb.OfficeDatabaseDocument"));
+ final XStorable storeDoc = UnoRuntime.queryInterface(XStorable.class, databaseDoc);
+
+ // verify the document rejects API calls which require it to be initialized
+ impl_checkDocumentInitState(databaseDoc, false);
+
+ // though the document is not initialized, you can ask for the location, the URL, and the args
+ final String location = storeDoc.getLocation();
+ final String url = databaseDoc.getURL();
+ final PropertyValue[] args = databaseDoc.getArgs();
+ // they should be all empty at this time
+ assertEquals("location is expected to be empty here", "", location);
+ assertEquals("URL is expected to be empty here", "", url);
+ assertEquals("Args are expected to be empty here", 0, args.length);
+
+ // and, you should be able to set properties at the data source
+ final XOfficeDatabaseDocument dataSourceAccess = UnoRuntime.queryInterface(XOfficeDatabaseDocument.class, databaseDoc);
+ final XPropertySet dsProperties = UnoRuntime.queryInterface(XPropertySet.class, dataSourceAccess.getDataSource());
+ dsProperties.setPropertyValue("URL", "sdbc:embedded:hsqldb");
+
+ final String documentURL = createTempFileURL();
+ storeDoc.storeAsURL(documentURL, new PropertyValue[0]);
+
+ // now that the document is stored, ...
+ // ... its URL should be correct
+ assertEquals("wrong URL after storing the document", documentURL, databaseDoc.getURL());
+ // ... it should be initialized
+ impl_checkDocumentInitState(databaseDoc, true);
+
+ return databaseDoc;
+ }
+
+
+ @Test
+ public void testLoadable() throws Exception, IOException
+ {
+ XModel databaseDoc = impl_createEmptyEmbeddedHSQLDocument();
+ String documentURL = databaseDoc.getURL();
+
+ // there's three methods how you can initialize a database document:
+
+
+ // 1. XStorable::storeAsURL
+ // (this is for compatibility reasons, to not break existing code)
+ // this test is already made in impl_createEmptyEmbeddedHSQLDocument
+
+
+ // 2. XLoadable::load
+ databaseDoc = UnoRuntime.queryInterface(XModel.class, getMSF().createInstance("com.sun.star.sdb.OfficeDatabaseDocument"));
+ documentURL = copyToTempFile(documentURL);
+ // load the doc, and verify it's initialized then, and has the proper URL
+ XLoadable loadDoc = UnoRuntime.queryInterface(XLoadable.class, databaseDoc);
+ loadDoc.load(new PropertyValue[]
+ {
+ new PropertyValue("URL", 0, documentURL, PropertyState.DIRECT_VALUE)
+ });
+ databaseDoc.attachResource(documentURL, new PropertyValue[0]);
+
+ assertEquals("wrong URL after loading the document", documentURL, databaseDoc.getURL());
+ impl_checkDocumentInitState(databaseDoc, true);
+
+ // and while we are here ... initializing the same document again should not be possible
+ assureException( databaseDoc, XLoadable.class, "initNew", new Object[0],
+ DoubleInitializationException.class );
+ assureException( databaseDoc, XLoadable.class, "load", new Object[] { new PropertyValue[0] },
+ DoubleInitializationException.class );
+
+
+ // 3. XLoadable::initNew
+ impl_closeDocument(databaseDoc);
+ databaseDoc = impl_createDocument();
+ loadDoc = UnoRuntime.queryInterface(XLoadable.class, databaseDoc);
+ loadDoc.initNew();
+ assertEquals("wrong URL after initializing the document", "", databaseDoc.getURL());
+ impl_checkDocumentInitState(databaseDoc, true);
+
+ // same as above - initializing the document a second time must fail
+ assureException( databaseDoc, XLoadable.class, "initNew", new Object[0],
+ DoubleInitializationException.class );
+ assureException( databaseDoc, XLoadable.class, "load", new Object[] { new PropertyValue[0] },
+ DoubleInitializationException.class );
+ }
+
+
+ private PropertyValue[] impl_getMarkerLoadArgs()
+ {
+ return new PropertyValue[]
+ {
+ new PropertyValue( "PickListEntry", 0, false, PropertyState.DIRECT_VALUE ),
+ new PropertyValue( "TestCase_Marker", 0, "Yes", PropertyState.DIRECT_VALUE )
+ };
+ }
+
+
+ private boolean impl_hasMarker( final PropertyValue[] _args )
+ {
+ for ( int i=0; i<_args.length; ++i )
+ {
+ if ( _args[i].Name.equals( "TestCase_Marker" ) && _args[i].Value.equals( "Yes" ) )
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+
+ private PropertyValue[] impl_getDefaultLoadArgs()
+ {
+ return new PropertyValue[]
+ {
+ new PropertyValue("PickListEntry", 0, false, PropertyState.DIRECT_VALUE)
+ };
+ }
+
+
+ private PropertyValue[] impl_getMacroExecLoadArgs()
+ {
+ return new PropertyValue[]
+ {
+ new PropertyValue("PickListEntry", 0, false, PropertyState.DIRECT_VALUE),
+ new PropertyValue("MacroExecutionMode", 0, com.sun.star.document.MacroExecMode.USE_CONFIG, PropertyState.DIRECT_VALUE),
+ new PropertyValue("InteractionHandler", 0, new MacroExecutionApprove(getMSF()), PropertyState.DIRECT_VALUE)
+ };
+ }
+
+
+ private int impl_setMacroSecurityLevel(int _level) throws Exception
+ {
+ final XMultiServiceFactory configProvider = theDefaultProvider.get(
+ getComponentContext());
+
+ final NamedValue[] args = new NamedValue[]
+ {
+ new NamedValue("nodepath", "/org.openoffice.Office.Common/Security/Scripting")
+ };
+
+ final XPropertySet securitySettings = UnoRuntime.queryInterface(XPropertySet.class, configProvider.createInstanceWithArguments("com.sun.star.configuration.ConfigurationUpdateAccess", args));
+ final int oldValue = ((Integer) securitySettings.getPropertyValue("MacroSecurityLevel")).intValue();
+ securitySettings.setPropertyValue("MacroSecurityLevel", Integer.valueOf(_level));
+
+ final XChangesBatch committer = UnoRuntime.queryInterface(XChangesBatch.class, securitySettings);
+ committer.commitChanges();
+
+ return oldValue;
+ }
+
+
+ private XModel impl_loadDocument( final String _documentURL, final PropertyValue[] _loadArgs ) throws Exception
+ {
+ final XComponentLoader loader = UnoRuntime.queryInterface(XComponentLoader.class, getMSF().createInstance("com.sun.star.frame.Desktop"));
+ return UnoRuntime.queryInterface(XModel.class, loader.loadComponentFromURL(_documentURL, _BLANK, 0, _loadArgs));
+ }
+
+
+ private void impl_storeDocument( final XModel _document ) throws Exception
+ {
+ // store the document
+ FileHelper.getOOoCompatibleFileURL( _document.getURL() );
+ final XStorable storeDoc = UnoRuntime.queryInterface(XStorable.class, _document);
+ storeDoc.store();
+
+ }
+
+
+ private XModel impl_createDocWithMacro( final String _libName, final String _moduleName, final String _code ) throws Exception, IOException
+ {
+ // create an empty document
+ XModel databaseDoc = impl_createEmptyEmbeddedHSQLDocument();
+
+ // create Basic library/module therein
+ final XEmbeddedScripts embeddedScripts = UnoRuntime.queryInterface(XEmbeddedScripts.class, databaseDoc);
+ final XStorageBasedLibraryContainer basicLibs = embeddedScripts.getBasicLibraries();
+ final XNameContainer newLib = basicLibs.createLibrary( _libName );
+ newLib.insertByName( _moduleName, _code );
+
+ return databaseDoc;
+ }
+
+
+ /** Tests various aspects of database document "revenants"
+ *
+ * Well, I do not really have a good term for this... The point is, database documents are in real
+ * only *one* aspect of a more complex thing. The second aspect is a data source. Both, in some sense,
+ * just represent different views on the same thing. For a given database, there's at each time at most
+ * one data source, and at most one database document. Both have an independent life time, and are
+ * created when needed.
+ * In particular, a document can be closed (this is what happens when the last UI window displaying
+ * this document is closed), and then dies. Now when the other "view", the data source, still exists,
+ * the underlying document data is not discarded, but kept alive (else the data source would die
+ * just because the document dies, which is not desired). If the document is loaded, again, then
+ * it is re-created, using the data of its previous "incarnation".
+ *
+ * This method here tests some of those aspects of a document which should survive the death of one
+ * instance and re-creation as a revenant.
+ */
+ @Test
+ public void testDocumentRevenants() throws Exception, IOException
+ {
+ // create an empty document
+ XModel databaseDoc = impl_createDocWithMacro( "Lib", "Module",
+ "Sub Hello\n" +
+ " MsgBox \"Hello\"\n" +
+ "End Sub\n"
+ );
+ impl_storeDocument( databaseDoc );
+ final String documentURL = databaseDoc.getURL();
+
+ // at this stage, the marker should not yet be present in the doc's args, else some of the below
+ // tests become meaningless
+ assertTrue( "A newly created doc should not have the test case marker", !impl_hasMarker( databaseDoc.getArgs() ) );
+
+ // obtain the DataSource associated with the document. Keeping this alive
+ // ensures that the "impl data" of the document is kept alive, too, so when closing
+ // and re-opening it, this "impl data" must be re-used.
+ XDocumentDataSource dataSource = UnoRuntime.queryInterface(XDocumentDataSource.class, UnoRuntime.queryInterface(XOfficeDatabaseDocument.class, databaseDoc).getDataSource());
+
+ // close and reload the doc
+ impl_closeDocument(databaseDoc);
+ databaseDoc = impl_loadDocument( documentURL, impl_getMarkerLoadArgs() );
+ // since we just put the marker into the load-call, it should be present at the doc
+ assertTrue( "The test case marker got lost.", impl_hasMarker( databaseDoc.getArgs() ) );
+
+ // The basic library should have survived
+ final XEmbeddedScripts embeddedScripts = UnoRuntime.queryInterface(XEmbeddedScripts.class, databaseDoc);
+ final XStorageBasedLibraryContainer basicLibs = embeddedScripts.getBasicLibraries();
+ assertTrue( "Basic lib did not survive reloading a closed document", basicLibs.hasByName( "Lib" ) );
+ final XNameContainer lib = UnoRuntime.queryInterface(XNameContainer.class, basicLibs.getByName("Lib"));
+ assertTrue( "Basic module did not survive reloading a closed document", lib.hasByName( "Module" ) );
+
+ // now closing the doc, and obtaining it from the data source, should preserve the marker we put into the load
+ // args
+ impl_closeDocument( databaseDoc );
+ databaseDoc = UnoRuntime.queryInterface(XModel.class, dataSource.getDatabaseDocument());
+ assertTrue( "The test case marker did not survive re-retrieval of the doc from the data source.",
+ impl_hasMarker( databaseDoc.getArgs() ) );
+
+ // on the other hand, closing and regularly re-loading the doc *without* the marker should indeed
+ // lose it
+ impl_closeDocument( databaseDoc );
+ databaseDoc = impl_loadDocument( documentURL, impl_getDefaultLoadArgs() );
+ assertTrue( "Reloading the document kept the old args, instead of the newly supplied ones.",
+ !impl_hasMarker( databaseDoc.getArgs() ) );
+
+ // clean up
+ impl_closeDocument( databaseDoc );
+ }
+
+
+ @Test
+ public void testDocumentEvents() throws Exception, IOException
+ {
+ // create an empty document
+ final String libName = "EventHandlers";
+ final String moduleName = "all";
+ final String eventHandlerCode =
+ "Option Explicit\n" +
+ "\n" +
+ "Sub OnLoad\n" +
+ " Dim oCallback as Object\n" +
+ " oCallback = createUnoService( \"" + getCallbackComponentServiceName() + "\" )\n" +
+ "\n" +
+ " ' as long as the Document is not passed to the Basic callbacks, we need to create\n" +
+ " ' one ourself\n" +
+ " Dim oEvent as new com.sun.star.document.DocumentEvent\n" +
+ " oEvent.EventName = \"OnLoad\"\n" +
+ " oEvent.Source = ThisComponent\n" +
+ "\n" +
+ " oCallback.documentEventOccurred( oEvent )\n" +
+ "End Sub\n";
+ XModel databaseDoc = impl_createDocWithMacro( libName, moduleName, eventHandlerCode );
+ final String documentURL = databaseDoc.getURL();
+
+ // bind the macro to the OnLoad event
+ final String macroURI = "vnd.sun.star.script:" + libName + "." + moduleName + ".OnLoad?language=Basic&location=document";
+ final XEventsSupplier eventsSupplier = UnoRuntime.queryInterface(XEventsSupplier.class, databaseDoc);
+ eventsSupplier.getEvents().replaceByName("OnLoad", new PropertyValue[]
+ {
+ new PropertyValue("EventType", 0, "Script", PropertyState.DIRECT_VALUE),
+ new PropertyValue("Script", 0, macroURI, PropertyState.DIRECT_VALUE)
+ });
+
+ // store the document, and close it
+ impl_storeDocument( databaseDoc );
+ impl_closeDocument( databaseDoc );
+
+ // ensure the macro security configuration is "ask the user for document macro execution"
+ final int oldSecurityLevel = impl_setMacroSecurityLevel(1);
+
+ // load it, again
+ m_loadDocState = STATE_LOADING_DOC;
+ // expected order of states is:
+ // STATE_LOADING_DOC - initialized here
+ // STATE_MACRO_EXEC_APPROVED - done in our interaction handler, which auto-approves the execution of macros
+ // STATE_ON_LOAD_RECEIVED - done in our callback for the document events
+ //
+ // In particular, it is important that the interaction handler (which plays the role of the user confirmation
+ // here) is called before the OnLoad notification is received - since the latter happens from within
+ // a Basic macro which is bound to the OnLoad event of the document.
+
+ final String context = "OnLoad";
+ impl_startObservingEvents(context);
+ databaseDoc = impl_loadDocument( documentURL, impl_getMacroExecLoadArgs() );
+ impl_stopObservingEvents(m_documentEvents, new String[]
+ {
+ "OnLoad"
+ }, context);
+
+ assertEquals("our provided interaction handler was not called", STATE_ON_LOAD_RECEIVED, m_loadDocState);
+
+ // restore macro security level
+ impl_setMacroSecurityLevel(oldSecurityLevel);
+
+ // close the document
+ impl_closeDocument(databaseDoc);
+ }
+
+
+ @Test
+ public void testGlobalEvents() throws Exception, IOException
+ {
+ XModel databaseDoc = impl_createEmptyEmbeddedHSQLDocument();
+ final XStorable storeDoc = UnoRuntime.queryInterface(XStorable.class, databaseDoc);
+
+ String context, newURL;
+
+ // XStorable.store
+ final String oldURL = databaseDoc.getURL();
+ context = "store";
+ impl_startObservingEvents(context);
+ storeDoc.store();
+ assertEquals("store is not expected to change the document URL", databaseDoc.getURL(), oldURL);
+ impl_stopObservingEvents(m_globalEvents, new String[]
+ {
+ "OnSave", "OnSaveDone"
+ }, context);
+
+ // XStorable.storeToURL
+ context = "storeToURL";
+ impl_startObservingEvents(context);
+ storeDoc.storeToURL(createTempFileURL(), new PropertyValue[0]);
+ assertEquals("storetoURL is not expected to change the document URL", databaseDoc.getURL(), oldURL);
+ impl_stopObservingEvents(m_globalEvents, new String[]
+ {
+ "OnSaveTo", "OnSaveToDone"
+ }, context);
+
+ // XStorable.storeAsURL
+ newURL = createTempFileURL();
+ context = "storeAsURL";
+ impl_startObservingEvents(context);
+ storeDoc.storeAsURL(newURL, new PropertyValue[0]);
+ assertEquals("storeAsURL is expected to change the document URL", databaseDoc.getURL(), newURL);
+ impl_stopObservingEvents(m_globalEvents, new String[]
+ {
+ "OnSaveAs", "OnSaveAsDone"
+ }, context);
+
+ // XModifiable.setModified
+ final XModifiable modifyDoc = UnoRuntime.queryInterface(XModifiable.class, databaseDoc);
+ context = "setModified";
+ impl_startObservingEvents(context);
+ modifyDoc.setModified(true);
+ assertEquals("setModified didn't work", modifyDoc.isModified(), true);
+ impl_stopObservingEvents(m_globalEvents, new String[]
+ {
+ "OnModifyChanged"
+ }, context);
+
+ // XStorable.store, with implicit reset of the "Modified" flag
+ context = "store (2)";
+ impl_startObservingEvents(context);
+ storeDoc.store();
+ assertEquals("'store' should implicitly reset the modified flag", modifyDoc.isModified(), false);
+ impl_stopObservingEvents(m_globalEvents, new String[]
+ {
+ "OnSave", "OnSaveDone", "OnModifyChanged"
+ }, context);
+
+ // XComponentLoader.loadComponentFromURL
+ newURL = copyToTempFile(databaseDoc.getURL());
+ final XComponentLoader loader = UnoRuntime.queryInterface(XComponentLoader.class, getMSF().createInstance("com.sun.star.frame.Desktop"));
+ context = "loadComponentFromURL";
+ impl_startObservingEvents(context);
+ databaseDoc = UnoRuntime.queryInterface(XModel.class, loader.loadComponentFromURL(newURL, _BLANK, 0, impl_getDefaultLoadArgs()));
+ impl_stopObservingEvents(m_globalEvents,
+ new String[]
+ {
+ "OnLoadFinished", "OnViewCreated", "OnFocus", "OnLoad"
+ }, context);
+
+ // closing a document by API
+ final XCloseable closeDoc = UnoRuntime.queryInterface(XCloseable.class, databaseDoc);
+ context = "close (API)";
+ impl_startObservingEvents(context);
+ closeDoc.close(true);
+ impl_stopObservingEvents(m_globalEvents,
+ new String[]
+ {
+ "OnPrepareUnload", "OnViewClosed", "OnUnload"
+ }, context);
+
+ // closing a document via UI
+ context = "close (UI)";
+ impl_startObservingEvents("prepare for '" + context + "'");
+ databaseDoc = UnoRuntime.queryInterface(XModel.class, loader.loadComponentFromURL(newURL, _BLANK, 0, impl_getDefaultLoadArgs()));
+ impl_waitForEvent(m_globalEvents, "OnLoad", 5000);
+ // wait for all events to arrive - OnLoad should be the last one
+
+ final XDispatchProvider dispatchProvider = UnoRuntime.queryInterface(XDispatchProvider.class, databaseDoc.getCurrentController().getFrame());
+ final URL url = impl_getURL(".uno:CloseDoc");
+ final XDispatch dispatcher = dispatchProvider.queryDispatch(url, "", 0);
+ impl_startObservingEvents(context);
+ dispatcher.dispatch(url, new PropertyValue[0]);
+ impl_stopObservingEvents(m_globalEvents,
+ new String[]
+ {
+ "OnPrepareViewClosing", "OnViewClosed", "OnPrepareUnload", "OnUnload"
+ }, context);
+
+ // creating a new document
+ databaseDoc = impl_createDocument();
+ final XLoadable loadDoc = UnoRuntime.queryInterface(XLoadable.class, databaseDoc);
+ context = "initNew";
+ impl_startObservingEvents(context);
+ loadDoc.initNew();
+ impl_stopObservingEvents(m_globalEvents, new String[]
+ {
+ "OnCreate"
+ }, context);
+
+ impl_startObservingEvents(context + " (cleanup)");
+ impl_closeDocument(databaseDoc);
+ impl_waitForEvent(m_globalEvents, "OnUnload", 5000);
+
+ // focus changes
+ context = "activation";
+ // for this, load a database document ...
+ impl_startObservingEvents("prepare for '" + context + "'");
+ databaseDoc = UnoRuntime.queryInterface(XModel.class, loader.loadComponentFromURL(newURL, _BLANK, 0, impl_getDefaultLoadArgs()));
+ final int previousOnLoadEventPos = impl_waitForEvent(m_globalEvents, "OnLoad", 5000);
+ // ... and another document ...
+ final String otherURL = copyToTempFile(databaseDoc.getURL());
+ final XModel otherDoc = UnoRuntime.queryInterface(XModel.class, loader.loadComponentFromURL(otherURL, _BLANK, 0, impl_getDefaultLoadArgs()));
+ impl_raise(otherDoc);
+ impl_waitForEvent(m_globalEvents, "OnLoad", 5000, previousOnLoadEventPos + 1);
+
+ // ... and switch between the two
+ impl_startObservingEvents(context);
+ impl_raise(databaseDoc);
+ impl_stopObservingEvents(m_globalEvents, new String[]
+ {
+ "OnUnfocus", "OnFocus"
+ }, context);
+
+ // cleanup
+ impl_startObservingEvents("cleanup after '" + context + "'");
+ impl_closeDocument(databaseDoc);
+ impl_closeDocument(otherDoc);
+ }
+
+
+ private URL impl_getURL(String _completeURL) throws Exception
+ {
+ final URL[] url =
+ {
+ new URL()
+ };
+ url[0].Complete = _completeURL;
+ final XURLTransformer urlTransformer = UnoRuntime.queryInterface(XURLTransformer.class, getMSF().createInstance("com.sun.star.util.URLTransformer"));
+ urlTransformer.parseStrict(url);
+ return url[0];
+ }
+
+
+ private void impl_raise(XModel _document)
+ {
+ final XFrame frame = _document.getCurrentController().getFrame();
+ final XTopWindow topWindow = UnoRuntime.queryInterface(XTopWindow.class, frame.getContainerWindow());
+ topWindow.toFront();
+ }
+
+
+ private void impl_startObservingEvents(String _context)
+ {
+ System.out.println(" " + _context + " {");
+ synchronized (m_documentEvents)
+ {
+ m_documentEvents.clear();
+ }
+ synchronized (m_globalEvents)
+ {
+ m_globalEvents.clear();
+ }
+ }
+
+
+ private void impl_stopObservingEvents(ArrayList<String> _actualEvents, String[] _expectedEvents, String _context)
+ {
+ try
+ {
+ synchronized (_actualEvents)
+ {
+ int actualEventCount = _actualEvents.size();
+ while (actualEventCount < _expectedEvents.length)
+ {
+ // well, it's possible not all events already arrived, yet - finally, some of them
+ // are notified asynchronously
+ // So, wait a few seconds.
+ try
+ {
+ _actualEvents.wait(20000);
+ }
+ catch (InterruptedException ex)
+ {
+ }
+
+ if (actualEventCount == _actualEvents.size())
+ // the above wait was left because of the timeout, *not* because an event
+ // arrived. Okay, we won't wait any longer, this is a failure.
+ {
+ break;
+ }
+ actualEventCount = _actualEvents.size();
+ }
+
+ assertEquals("wrong event count for '" + _context + "'",
+ _expectedEvents.length, _actualEvents.size());
+
+ for (int i = 0; i < _expectedEvents.length; ++i)
+ {
+ assertEquals("wrong event at position " + (i + 1) + " for '" + _context + "'",
+ _expectedEvents[i], _actualEvents.get(i));
+ }
+ }
+ }
+ finally
+ {
+ System.out.println(" }");
+ }
+ }
+
+
+ private int impl_waitForEvent(ArrayList<String> _eventQueue, String _expectedEvent, int _maxMilliseconds)
+ {
+ return impl_waitForEvent(_eventQueue, _expectedEvent, _maxMilliseconds, 0);
+ }
+
+
+ private int impl_waitForEvent(ArrayList<String> _eventQueue, String _expectedEvent, int _maxMilliseconds, int _firstQueueElementToCheck)
+ {
+ synchronized (_eventQueue)
+ {
+ int waitedMilliseconds = 0;
+
+ while (waitedMilliseconds < _maxMilliseconds)
+ {
+ for (int i = _firstQueueElementToCheck; i < _eventQueue.size(); ++i)
+ {
+ if (_expectedEvent.equals(_eventQueue.get(i)))
+ // found the event in the queue
+ {
+ return i;
+ }
+ }
+
+ // wait a little, perhaps the event will still arrive
+ try
+ {
+ _eventQueue.wait(500);
+ waitedMilliseconds += 500;
+ }
+ catch (InterruptedException e)
+ {
+ }
+ }
+ }
+
+ fail("expected event '" + _expectedEvent + "' did not arrive after " + _maxMilliseconds + " milliseconds");
+ return -1;
+ }
+
+
+ private void onDocumentEvent(DocumentEvent _Event)
+ {
+ if ("OnTitleChanged".equals(_Event.EventName))
+ // OnTitleChanged events are notified too often. This is known, and accepted.
+ // (the deeper reason is that it's difficult to determine, in the DatabaseDocument implementation,
+ // when the title actually changed. In particular, when we do a saveAsURL, and then ask for a
+ // title *before* the TitleHelper got the document's OnSaveAsDone event, then the wrong (old)
+ // title is obtained.
+ {
+ return;
+ }
+
+ if ((_Event.EventName.equals("OnLoad")) && (m_loadDocState != STATE_NOT_STARTED))
+ {
+ assertEquals("OnLoad event must come *after* invocation of the interaction handler / user!",
+ m_loadDocState, STATE_MACRO_EXEC_APPROVED);
+ m_loadDocState = STATE_ON_LOAD_RECEIVED;
+ }
+
+ synchronized (m_documentEvents)
+ {
+ m_documentEvents.add(_Event.EventName);
+ m_documentEvents.notifyAll();
+ }
+
+ System.out.println(" document event: " + _Event.EventName);
+ }
+
+
+ public void documentEventOccured(DocumentEvent _Event)
+ {
+ if ("OnTitleChanged".equals(_Event.EventName))
+ // ignore. See onDocumentEvent for a justification
+ {
+ return;
+ }
+
+ synchronized (m_globalEvents)
+ {
+ m_globalEvents.add(_Event.EventName);
+ m_globalEvents.notifyAll();
+ }
+
+ System.out.println(" global event: " + _Event.EventName);
+ }
+
+
+ public void disposing(EventObject _Event)
+ {
+ // not interested in
+ }
+}
diff --git a/dbaccess/qa/complex/dbaccess/FileHelper.java b/dbaccess/qa/complex/dbaccess/FileHelper.java
new file mode 100644
index 000000000..cae67af00
--- /dev/null
+++ b/dbaccess/qa/complex/dbaccess/FileHelper.java
@@ -0,0 +1,35 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+package complex.dbaccess;
+
+public class FileHelper
+{
+ private FileHelper(){}
+ public static String getOOoCompatibleFileURL( String _javaFileURL )
+ {
+ String returnURL = _javaFileURL;
+ if ( ( returnURL.indexOf( "file:/" ) == 0 ) && ( returnURL.indexOf( "file:///" ) == -1 ) )
+ {
+ // for some reason, the URLs here in Java start with "file:/" only, instead of "file:///"
+ // Some of the office code doesn't like this ...
+ returnURL = "file:///" + returnURL.substring( 6 );
+ }
+ return returnURL;
+ }
+}
diff --git a/dbaccess/qa/complex/dbaccess/Parser.java b/dbaccess/qa/complex/dbaccess/Parser.java
new file mode 100644
index 000000000..8025e1d37
--- /dev/null
+++ b/dbaccess/qa/complex/dbaccess/Parser.java
@@ -0,0 +1,183 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+package complex.dbaccess;
+
+import com.sun.star.beans.XPropertySet;
+import com.sun.star.container.XIndexAccess;
+import com.sun.star.sdb.XParametersSupplier;
+import com.sun.star.sdb.XSingleSelectQueryComposer;
+import com.sun.star.sdbc.DataType;
+import com.sun.star.sdbc.SQLException;
+import com.sun.star.uno.UnoRuntime;
+
+
+// ---------- junit imports -----------------
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+
+public class Parser extends CRMBasedTestCase
+{
+
+ @Override
+ protected void createTestCase() throws Exception
+ {
+ super.createTestCase();
+ m_database.getDatabase().getDataSource().createQuery( "query products", "SELECT * FROM \"products\"" );
+ }
+
+
+ @Test
+ public void checkWhere() throws Exception
+ {
+ final XSingleSelectQueryComposer composer = createQueryComposer();
+ final String SELECT = "SELECT \"products\".\"Name\" FROM \"products\" WHERE ";
+ final String[] queries = new String[]
+ {
+ "\"ID\" in ( 1,2,3,4)"
+ ,"not ( \"ID\" in ( 1,2,3,4))"
+ ,"(1 = 1) is true"
+ ,"(1 = 1) is not false"
+ ,"(1 = 1) is not null"
+ ,"not ( (1 = 1) is not null)"
+ ,"'a' like 'a%'"
+ ,"not ( 'a' like 'a%')"
+ ,"'a' not like 'a%'"
+ ,"1 between 0 and 2"
+ ,"not ( 1 between 0 and 2 )"
+ ,"1 not between 3 and 4"
+ ,"1 not between ( select \"ID\" from \"categories\") and ( select \"ID\" from \"categories\")"
+ ,"1 = 1"
+ ,"0 < 1"
+ ,"not(0 < 1)"
+ ,"1 > 0"
+ ,"not(1 > 0)"
+ ,"1 <> 0"
+ ,"(1 <> 0 and 'a' = 'a' and 'c' = 'd') or (1 = 1 and 2 = 2 and 3 = 4)"
+ ,"not ( 1 <> 0 )"
+ ,"\"CategoryID\" in ( select \"ID\" from \"categories\")"
+ ,"not (\"CategoryID\" in ( select \"ID\" from \"categories\"))"
+ ,"\"CategoryID\" not in ( select \"ID\" from \"categories\")"
+ };
+ for (int i = 0; i < queries.length; i++)
+ {
+ composer.setQuery( SELECT + queries[i]);
+ }
+ }
+
+ /** verifies that aliases for inner queries work as expected
+ */
+ @Test
+ public void checkJoinSyntax() throws Exception
+ {
+ final XSingleSelectQueryComposer composer = createQueryComposer();
+
+ // feed the composer with some statements. If any of those cannot be parsed, the composer
+ // will throw an exception - which is a regression then
+ composer.setQuery(
+ "SELECT \"categories\".\"Name\", " +
+ "\"products\".\"Name\" " +
+ "FROM \"products\" RIGHT OUTER JOIN \"categories\" AS \"categories\" ON \"products\".\"CategoryID\" = \"categories\".\"ID\"" );
+
+ composer.setQuery(
+ "SELECT \"categories\".\"Name\", " +
+ "\"products\".\"Name\" " +
+ "FROM \"products\" LEFT OUTER JOIN \"categories\" AS \"categories\" ON \"products\".\"CategoryID\" = \"categories\".\"ID\"" );
+
+ composer.setQuery(
+ "SELECT \"categories\".\"Name\", " +
+ "\"products\".\"Name\" " +
+ "FROM \"products\" CROSS JOIN \"categories\" AS \"categories\"" );
+
+ composer.setQuery(
+ "SELECT \"categories\".\"Name\", " +
+ "\"products\".\"Name\" " +
+ "FROM \"products\" INNER JOIN \"categories\" AS \"categories\" ON \"products\".\"CategoryID\" = \"categories\".\"ID\"" );
+
+ // just to be sure the composer *really* parses upon setting the query: feed it with
+ // an unparseable statement
+ boolean caughtExpected = false;
+ try
+ {
+ composer.setQuery( "NONSENSE" );
+ }
+ catch( SQLException e )
+ {
+ caughtExpected = true;
+ }
+ assertTrue( "pre-condition not met: parser should except on unparseable statements, else the complete" +
+ "test is bogus!", caughtExpected );
+ }
+
+
+ private void impl_checkParameters( final String _statement, final String[] _expectedParameterNames, final int[] _expectedParameterTypes,final String _context ) throws Exception
+ {
+ final XSingleSelectQueryComposer composer = createQueryComposer();
+ composer.setQuery( _statement );
+
+ assertEquals( "checkParameterTypes: internal error", _expectedParameterNames.length, _expectedParameterTypes.length );
+
+ final XParametersSupplier paramSupp = UnoRuntime.queryInterface(XParametersSupplier.class, composer);
+ final XIndexAccess parameters = paramSupp.getParameters();
+
+ assertEquals( "(ctx: " + _context + ") unexpected parameter count", _expectedParameterNames.length, parameters.getCount() );
+ for ( int i=0; i<parameters.getCount(); ++i )
+ {
+ final XPropertySet parameter = UnoRuntime.queryInterface(XPropertySet.class, parameters.getByIndex(i));
+
+ final String name = (String)parameter.getPropertyValue( "Name" );
+ assertEquals( "(ctx: " + _context + ") unexpected parameter name for parameter number " + ( i + 1 ), _expectedParameterNames[i], name );
+
+ final int type = ((Integer)parameter.getPropertyValue( "Type" )).intValue();
+ assertEquals( "(ctx: " + _context + ") unexpected data type for parameter number " + ( i + 1 ), _expectedParameterTypes[i], type );
+ }
+ }
+
+
+ /** verifies that the parser properly recognizes the types of parameters
+ */
+ @Test
+ public void checkParameterTypes() throws Exception
+ {
+ impl_checkParameters(
+ "SELECT * FROM \"all orders\" " +
+ "WHERE ( \"Order Date\" >= :order_date ) " +
+ " AND ( ( \"Customer Name\" LIKE :customer ) " +
+ " OR ( \"Product Name\" LIKE ? ) " +
+ " )",
+ new String[] { "order_date", "customer", "Product Name" },
+ new int[] { DataType.DATE, DataType.VARCHAR, DataType.VARCHAR },
+ ">= && LIKE"
+ );
+
+ impl_checkParameters(
+ "SELECT * FROM \"categories\" " +
+ "WHERE \"ID\" BETWEEN :id_lo AND :id_hi",
+ new String[] { "id_lo", "id_hi" },
+ new int[] { DataType.INTEGER, DataType.INTEGER },
+ "BETWEEN"
+ );
+
+ impl_checkParameters(
+ "SELECT CONCAT( :prefix, CONCAT( \"Name\", :suffix ) ) FROM \"customers\"",
+ new String[] { "prefix", "suffix" },
+ new int[] { DataType.VARCHAR, DataType.VARCHAR },
+ "CONCAT"
+ );
+ }
+}
diff --git a/dbaccess/qa/complex/dbaccess/PropertyBag.java b/dbaccess/qa/complex/dbaccess/PropertyBag.java
new file mode 100644
index 000000000..6807569ec
--- /dev/null
+++ b/dbaccess/qa/complex/dbaccess/PropertyBag.java
@@ -0,0 +1,302 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+package complex.dbaccess;
+
+import com.sun.star.beans.NamedValue;
+import com.sun.star.beans.PropertyState;
+import com.sun.star.beans.PropertyValue;
+import com.sun.star.beans.PropertyAttribute;
+import com.sun.star.beans.XPropertyAccess;
+import com.sun.star.beans.XPropertySet;
+import com.sun.star.beans.XPropertyContainer;
+import com.sun.star.uno.UnoRuntime;
+import com.sun.star.lang.XMultiServiceFactory;
+
+// ---------- junit imports -----------------
+import org.junit.Before;
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+
+public class PropertyBag extends TestCase
+{
+ private static final String VALUE = "Value";
+ private XPropertyContainer m_bag;
+ private XPropertySet m_set;
+ private XPropertyAccess m_access;
+ private XMultiServiceFactory m_orb = null;
+
+ public String getTestObjectName()
+ {
+ return "PropertyBag";
+ }
+
+ @Before
+ @Override
+ public void before()
+ {
+ m_orb = getMSF();
+ }
+
+ @Test
+ public void checkBasics() throws Exception
+ {
+ createEmptyBag();
+ System.out.println("testing the basics");
+
+ // check whether empty property names are rejected
+ boolean caughtExpected = false;
+ try
+ {
+ m_bag.addProperty( "", PropertyAttribute.BOUND, Integer.valueOf( 3 ) );
+ }
+ catch(com.sun.star.lang.IllegalArgumentException e) { caughtExpected = true; }
+ catch(com.sun.star.uno.Exception e) { }
+ if ( !caughtExpected )
+ {
+ fail("empty property names are not rejected by XPropertyContainer::addProperty");
+ }
+
+ // check whether duplicate insertions are rejected
+ caughtExpected = false;
+ try
+ {
+ m_bag.addProperty( VALUE, PropertyAttribute.BOUND, "" );
+ m_bag.addProperty( VALUE, PropertyAttribute.BOUND, "" );
+ }
+ catch(com.sun.star.beans.PropertyExistException e) { caughtExpected = true; }
+ catch(com.sun.star.uno.Exception e) { }
+ if ( !caughtExpected )
+ {
+ fail("insertion of duplicate property names is not rejected");
+ }
+
+ // try removing the property we just added - this should fail, as it does not have
+ // the REMOVABLE attribute
+ caughtExpected = false;
+ try
+ {
+ m_bag.removeProperty( VALUE);
+ }
+ catch(com.sun.star.beans.NotRemoveableException e) { caughtExpected = true; }
+ catch(com.sun.star.uno.Exception e) { }
+ if ( !caughtExpected )
+ {
+ fail("removing non-removable properties is expected to fail - but it didn't");
+ }
+
+ // try removing a non-existent property
+ caughtExpected = false;
+ try
+ {
+ m_bag.removeProperty( "NonExistent" );
+ }
+ catch(com.sun.star.beans.UnknownPropertyException e) { caughtExpected = true; }
+ catch(com.sun.star.uno.Exception e) { }
+ if ( !caughtExpected )
+ {
+ fail("removing non-existent properties is expected to fail - but it didn't");
+ }
+
+ // try writing and reading a value for the one property we have so far
+ final String testValue = "someArbitraryValue";
+ m_set.setPropertyValue( VALUE , testValue);
+ final String currentValue = (String)m_set.getPropertyValue( VALUE);
+ if ( !currentValue.equals( testValue ) )
+ {
+ fail("set property is not remembered");
+ }
+
+ // try setting an illegal value for the property
+ caughtExpected = false;
+ try
+ {
+ m_set.setPropertyValue( VALUE, Integer.valueOf( 3 ) );
+ }
+ catch(com.sun.star.lang.IllegalArgumentException e) { caughtExpected = true; }
+ catch(com.sun.star.uno.Exception e) { }
+ if ( !caughtExpected )
+ {
+ fail("the bag does not respect the property type we declared for the property");
+ }
+ }
+
+ @Test
+ public void checkSequenceAccess() throws com.sun.star.uno.Exception
+ {
+ System.out.println( "checking PropertySetAccess via sequences" );
+ createStandardBag( false );
+
+
+ // XPropertyAccess.setPropertyValues
+ final PropertyValue expectedValues[] =
+ {
+ new PropertyValue( "BoolValue", -1, Boolean.FALSE, PropertyState.DIRECT_VALUE ),
+ new PropertyValue( "StringValue", -1, "some text", PropertyState.DIRECT_VALUE ),
+ new PropertyValue( "IntegerValue", -1, Integer.valueOf( 3 ), PropertyState.DIRECT_VALUE ),
+ new PropertyValue( "InterfaceValue", -1, m_bag, PropertyState.DIRECT_VALUE )
+ };
+ m_access.setPropertyValues( expectedValues );
+
+ for ( int i=0; i<expectedValues.length; ++i )
+ {
+ final Object value = m_set.getPropertyValue( expectedValues[i].Name );
+ if ( !value.equals( expectedValues[i].Value ) )
+ {
+ System.out.println( "property name : " + expectedValues[i].Name );
+ System.out.println( "expected value: " + expectedValues[i].Value.toString() );
+ System.out.println( "current value : " + value.toString() );
+ fail( "retrieving a previously set property (" + expectedValues[i].Value.getClass().toString() + ") failed" );
+ }
+ }
+
+
+ // XPropertyAccess.getPropertyValues
+ final PropertyValue currentValues[] = m_access.getPropertyValues();
+ for ( int i=0; i<currentValues.length; ++i )
+ {
+ final String name = currentValues[i].Name;
+ final Object value = currentValues[i].Value;
+ for ( int j=0; j<expectedValues.length; ++j )
+ {
+ if ( expectedValues[j].Name.equals( name ) )
+ {
+ if ( !expectedValues[j].Value.equals( value ) )
+ {
+ System.out.println( "property name : " + expectedValues[j].Name );
+ System.out.println( "expected value: " + expectedValues[j].Value.toString() );
+ System.out.println( "current value : " + value.toString() );
+ fail( "getPropertyValues failed for property '" + name + "' failed" );
+ }
+ break;
+ }
+ }
+
+ if ( !m_set.getPropertyValue( name ).equals( value ) )
+ {
+ fail("XPropertyAccess::getPropertyValues() and XPropertyset::getPropertyValue results are inconsistent");
+ }
+ }
+ }
+
+ @Test
+ public void checkDynamicSet()
+ {
+ System.out.println( "checking proper dynamic of the set" );
+ createStandardBag( false );
+
+ final PropertyValue props[] =
+ {
+ new PropertyValue( "BoolValue", -1, Boolean.FALSE, PropertyState.DIRECT_VALUE),
+ new PropertyValue( "StringValue", -1, "test", PropertyState.DIRECT_VALUE ),
+ new PropertyValue( "SomeOtherStringValue", -1, "string value", PropertyState.DIRECT_VALUE )
+ };
+
+ // try setting some property values which are not existent
+ boolean caughtExpected = false;
+ try
+ {
+ m_access.setPropertyValues( props );
+ }
+ catch( com.sun.star.beans.UnknownPropertyException e ) { caughtExpected = true; }
+ catch( com.sun.star.uno.Exception e ) { }
+ if ( !caughtExpected )
+ {
+ fail("the set shouldn't accept unknown property values, if not explicitly told to do so");
+ }
+
+ // re-create the bag, this time allow it to implicitly add properties
+ createStandardBag( true );
+ boolean success = false;
+ try { m_access.setPropertyValues( props ); success = true; }
+ catch( com.sun.star.uno.Exception e ) { }
+ if ( !success )
+ {
+ fail("property bag failed to implicitly add unknown properties");
+ }
+
+ // see whether this property was really added, and not just ignored
+ final PropertyValue newlyAdded = props[ props.length - 1 ];
+ try
+ {
+ if ( !m_set.getPropertyValue( newlyAdded.Name ).equals( newlyAdded.Value ) )
+ {
+ fail("the new property was not really added, or not added with the proper value");
+ }
+ }
+ catch( com.sun.star.uno.Exception e ) { }
+ }
+
+ private void createEmptyBag()
+ {
+ try
+ {
+ m_bag = null;
+ final String serviceName = "com.sun.star.beans.PropertyBag";
+ m_bag = UnoRuntime.queryInterface(XPropertyContainer.class, m_orb.createInstance(serviceName));
+ if ( m_bag == null )
+ {
+ fail("could not create a " + serviceName + " instance");
+ }
+ m_set = UnoRuntime.queryInterface(XPropertySet.class, m_bag);
+ m_access = UnoRuntime.queryInterface(XPropertyAccess.class, m_bag);
+ }
+ catch( com.sun.star.uno.Exception e )
+ {
+ }
+ }
+
+ private void createStandardBag( boolean allowLazyAdding )
+ {
+ try
+ {
+ m_bag = null;
+
+ final Object initArgs[] = { new NamedValue( "AutomaticAddition", Boolean.valueOf( allowLazyAdding ) ) };
+
+ final String serviceName = "com.sun.star.beans.PropertyBag";
+ m_bag = UnoRuntime.queryInterface(XPropertyContainer.class, m_orb.createInstanceWithArguments(serviceName, initArgs));
+ if ( m_bag == null )
+ {
+ fail("could not create a " + serviceName + " instance");
+ }
+ m_set = UnoRuntime.queryInterface(XPropertySet.class, m_bag);
+ m_access = UnoRuntime.queryInterface(XPropertyAccess.class, m_bag);
+
+ final Object properties[][] =
+ {
+ { "BoolValue", Boolean.TRUE },
+ { "StringValue", "" },
+ { "IntegerValue", Integer.valueOf( 3 ) },
+ { "InterfaceValue", m_bag }
+ };
+ for ( int i=0; i<properties.length; ++i )
+ {
+ m_bag.addProperty(
+ (String)properties[i][0],
+ PropertyAttribute.MAYBEVOID,
+ properties[i][1]
+ );
+ }
+ }
+ catch( com.sun.star.uno.Exception e )
+ {
+ }
+ }
+}
diff --git a/dbaccess/qa/complex/dbaccess/Query.java b/dbaccess/qa/complex/dbaccess/Query.java
new file mode 100644
index 000000000..8881bb3ed
--- /dev/null
+++ b/dbaccess/qa/complex/dbaccess/Query.java
@@ -0,0 +1,107 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+package complex.dbaccess;
+
+import com.sun.star.beans.XPropertySet;
+import com.sun.star.container.XIndexAccess;
+import com.sun.star.container.XNameAccess;
+import com.sun.star.container.XNamed;
+import com.sun.star.sdb.XQueriesSupplier;
+import com.sun.star.sdbcx.XColumnsSupplier;
+import com.sun.star.uno.UnoRuntime;
+import connectivity.tools.CRMDatabase;
+
+// ---------- junit imports -----------------
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+
+public class Query extends TestCase
+{
+
+ connectivity.tools.HsqlDatabase m_database;
+
+
+ private void createTestCase()
+ {
+ try
+ {
+ if (m_database == null)
+ {
+ final CRMDatabase database = new CRMDatabase(getMSF(), false);
+ m_database = database.getDatabase();
+ }
+ }
+ catch (Exception e)
+ {
+ System.out.println("could not create the test case, error message:\n" + e.getMessage());
+ e.printStackTrace(System.err);
+ fail("failed to created the test case");
+ }
+ }
+
+
+ @Test
+ public void testQueryColumns()
+ {
+ createTestCase();
+
+ try
+ {
+ final XQueriesSupplier suppQueries = UnoRuntime.queryInterface(
+ XQueriesSupplier.class, m_database.defaultConnection().getXConnection() );
+ final XNameAccess queries = suppQueries.getQueries();
+
+ final String[] queryNames = new String[] { "parseable", "parseable native", "unparseable" };
+ final String[][] expectedColumnNames = new String[][] {
+ new String[] { "ID", "Name", "Address", "City", "Postal","Comment" },
+ new String[] { "TABLE_CATALOG", "TABLE_SCHEMA", "TABLE_NAME", "VIEW_DEFINITION", "CHECK_OPTION", "IS_UPDATABLE", "VALID" },
+ new String[] { "ID_VARCHAR" }
+ };
+
+ for ( int i = 0; i < queryNames.length; ++i )
+ {
+ if (queries.hasByName(queryNames[i]))
+ {
+ final XPropertySet query = UnoRuntime.queryInterface(
+ XPropertySet.class, queries.getByName( queryNames[i] ) );
+
+ final XColumnsSupplier suppCols = UnoRuntime.queryInterface(
+ XColumnsSupplier.class, query);
+ final XIndexAccess columns = UnoRuntime.queryInterface(
+ XIndexAccess.class, suppCols.getColumns());
+
+ // check whether the columns supplied by the query match what we expected
+ assertTrue( "invalid column count (found " + columns.getCount() + ", expected: " + expectedColumnNames[i].length + ") for query \"" + queryNames[i] + "\"",
+ columns.getCount() == expectedColumnNames[i].length );
+ for ( int col = 0; col < columns.getCount(); ++col )
+ {
+ final XNamed columnName = UnoRuntime.queryInterface(
+ XNamed.class, columns.getByIndex(col) );
+ assertTrue( "column no. " + col + " of query \"" + queryNames[i] + "\" not matching",
+ columnName.getName().equals( expectedColumnNames[i][col] ) );
+ }
+ }
+ }
+ }
+ catch ( Exception e )
+ {
+ fail( "caught an unexpected exception: " + e.getMessage() );
+ }
+ }
+}
diff --git a/dbaccess/qa/complex/dbaccess/QueryInQuery.java b/dbaccess/qa/complex/dbaccess/QueryInQuery.java
new file mode 100644
index 000000000..4e6a9d0ff
--- /dev/null
+++ b/dbaccess/qa/complex/dbaccess/QueryInQuery.java
@@ -0,0 +1,177 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+package complex.dbaccess;
+
+import com.sun.star.container.ElementExistException;
+import com.sun.star.lang.IllegalArgumentException;
+import com.sun.star.lang.WrappedTargetException;
+import com.sun.star.sdb.CommandType;
+import com.sun.star.sdbc.SQLException;
+import connectivity.tools.HsqlColumnDescriptor;
+import connectivity.tools.HsqlTableDescriptor;
+import connectivity.tools.RowSet;
+import com.sun.star.sdbc.XStatement;
+import com.sun.star.sdbc.XResultSet;
+
+// ---------- junit imports -----------------
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+
+public class QueryInQuery extends CRMBasedTestCase
+{
+ private static final String QUERY_PRODUCTS = "query products";
+
+
+ @Override
+ protected void createTestCase()
+ {
+ try
+ {
+ super.createTestCase();
+ m_database.getDatabase().getDataSource().createQuery( QUERY_PRODUCTS,"SELECT * FROM \"products\"");
+ }
+ catch ( Exception e )
+ {
+ e.printStackTrace( System.err );
+ fail( "caught an exception (" + e.getMessage() + ") while creating the test case" );
+ }
+ }
+
+
+ private void verifyEqualRowSetContent( int _outerCommandType, String _outerCommand, int _innerCommandType, String _innerCommand ) throws SQLException
+ {
+ final RowSet outerRowSet = m_database.getDatabase().createRowSet( _outerCommandType, _outerCommand );
+ outerRowSet.execute();
+
+ final RowSet innerRowSet = m_database.getDatabase().createRowSet( _innerCommandType, _innerCommand );
+ innerRowSet.execute();
+
+ outerRowSet.last();
+ innerRowSet.last();
+ assertTrue( "wrong record counts", outerRowSet.getRow() == innerRowSet.getRow() );
+
+ outerRowSet.beforeFirst();
+ innerRowSet.beforeFirst();
+ assertTrue( "wrong column counts", outerRowSet.getColumnCount() == innerRowSet.getColumnCount() );
+
+ while ( outerRowSet.next() && innerRowSet.next() )
+ {
+ for ( int i=1; i <= outerRowSet.getColumnCount(); ++i )
+ {
+ assertTrue( "content of column " + i + " of row " + outerRowSet.getRow() + " not identical",
+ innerRowSet.getString(i).equals( outerRowSet.getString(i) ) );
+ }
+ }
+ }
+
+
+ /** executes a SQL statement simply selecting all columns from a query
+ */
+ @Test
+ public void executeSimpleSelect() throws SQLException
+ {
+ verifyEqualRowSetContent(
+ CommandType.COMMAND, "SELECT * FROM \"query products\"",
+ CommandType.QUERY,QUERY_PRODUCTS);
+ }
+
+
+ /** verifies that aliases for inner queries work as expected
+ */
+ @Test
+ public void executeAliasedSelect() throws SQLException
+ {
+ verifyEqualRowSetContent(
+ CommandType.COMMAND, "SELECT \"PROD\".\"ID\" FROM \"query products\" AS \"PROD\"",
+ CommandType.COMMAND, "SELECT \"ID\" FROM \"products\"" );
+ verifyEqualRowSetContent(
+ CommandType.COMMAND, "SELECT \"PROD\".* FROM \"query products\" AS \"PROD\"",
+ CommandType.QUERY,QUERY_PRODUCTS);
+ }
+
+
+ /** verifies that aliases for inner queries work as expected
+ */
+ @Test
+ public void checkNameCollisions()
+ {
+ // create a query with a name which is used by a table
+ boolean caughtExpected = false;
+ try
+ {
+ m_database.getDatabase().getDataSource().createQuery( "products", "SELECT * FROM \"products\"" );
+ }
+ catch ( WrappedTargetException e ) { caughtExpected = true; }
+ catch ( IllegalArgumentException e ) {}
+ catch ( ElementExistException e ) { caughtExpected = true; }
+ assertTrue( "creating queries with the name of an existing table should not be possible",
+ caughtExpected );
+
+ // create a table with a name which is used by a query
+ final HsqlTableDescriptor table = new HsqlTableDescriptor( QUERY_PRODUCTS,
+ new HsqlColumnDescriptor[] {
+ new HsqlColumnDescriptor( "ID", "INTEGER" ),
+ new HsqlColumnDescriptor( "Name", "VARCHAR(50)" ) } );
+
+ caughtExpected = false;
+ try
+ {
+ m_database.getDatabase().createTableInSDBCX( table );
+ }
+ catch ( SQLException e ) { caughtExpected = true; }
+ catch ( ElementExistException ex ) { }
+ assertTrue( "creating tables with the name of an existing query should not be possible",
+ caughtExpected );
+ }
+
+
+ @Test
+ public void checkCyclicReferences() throws ElementExistException, WrappedTargetException, IllegalArgumentException
+ {
+ // some queries which create a cycle in the sub query tree
+ m_database.getDatabase().getDataSource().createQuery( "orders level 1", "SELECT * FROM \"orders level 0\"" );
+ m_database.getDatabase().getDataSource().createQuery( "orders level 2", "SELECT * FROM \"orders level 1\"" );
+ m_database.getDatabase().getDataSource().createQuery( "orders level 3", "SELECT * FROM \"orders level 2\"" );
+ m_database.getDatabase().getDataSource().createQuery( "orders level 0", "SELECT * FROM \"orders level 3\"" );
+
+ final RowSet rowSet = m_database.getDatabase().createRowSet( CommandType.QUERY, "orders level 0" );
+
+ boolean caughtExpected = false;
+ try { rowSet.execute(); }
+ catch ( SQLException e ) { caughtExpected = ( e.ErrorCode == -com.sun.star.sdb.ErrorCondition.PARSER_CYCLIC_SUB_QUERIES ); }
+
+ assertTrue( "executing a query with cyclic nested sub queries should fail!", caughtExpected );
+ }
+
+
+ @Test
+ public void checkStatementQiQSupport()
+ {
+ try
+ {
+ final XStatement statement = m_database.getConnection().createStatement();
+ final XResultSet resultSet = statement.executeQuery( "SELECT * FROM \"query products\"" );
+ assertTrue( "Result Set is null", resultSet != null );
+ }
+ catch( SQLException e )
+ {
+ fail( "SDB level statements do not allow for queries in queries" );
+ }
+ }
+}
diff --git a/dbaccess/qa/complex/dbaccess/RowSet.java b/dbaccess/qa/complex/dbaccess/RowSet.java
new file mode 100644
index 000000000..4c5fcc6da
--- /dev/null
+++ b/dbaccess/qa/complex/dbaccess/RowSet.java
@@ -0,0 +1,942 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+package complex.dbaccess;
+
+import com.sun.star.beans.UnknownPropertyException;
+import com.sun.star.beans.XPropertySet;
+import com.sun.star.container.XIndexAccess;
+import com.sun.star.lang.WrappedTargetException;
+import com.sun.star.lang.XComponent;
+import com.sun.star.sdb.CommandType;
+import com.sun.star.sdb.XParametersSupplier;
+import com.sun.star.sdb.XResultSetAccess;
+import com.sun.star.sdb.XRowSetApproveBroadcaster;
+import com.sun.star.sdbc.SQLException;
+import com.sun.star.sdbc.XParameters;
+import com.sun.star.sdbc.XPreparedStatement;
+import com.sun.star.sdbc.XResultSet;
+import com.sun.star.sdbc.XResultSetUpdate;
+import com.sun.star.sdbc.XRow;
+import com.sun.star.sdbc.XRowSet;
+import com.sun.star.sdbc.XRowUpdate;
+import com.sun.star.sdbcx.XColumnsSupplier;
+import com.sun.star.sdbcx.XDeleteRows;
+import com.sun.star.sdbcx.XRowLocate;
+import com.sun.star.uno.UnoRuntime;
+
+import connectivity.tools.CRMDatabase;
+import connectivity.tools.DataSource;
+import connectivity.tools.HsqlDatabase;
+import connectivity.tools.sdb.Connection;
+import java.lang.reflect.Method;
+import java.util.Random;
+
+// ---------- junit imports -----------------
+import org.junit.After;
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+
+public class RowSet extends TestCase
+{
+
+ static final int MAX_TABLE_ROWS = 100;
+ static final int MAX_FETCH_ROWS = 10;
+ private static final String NEXT = "next";
+ private static final String TEST21 = "Test21";
+ HsqlDatabase m_database;
+ DataSource m_dataSource;
+ XRowSet m_rowSet;
+ XResultSet m_resultSet;
+ XResultSetUpdate m_resultSetUpdate;
+ XRow m_row;
+ XRowLocate m_rowLocate;
+ XPropertySet m_rowSetProperties;
+ XParametersSupplier m_paramsSupplier;
+
+ private final Object failedResultSetMovementStressGuard = new Object();
+ private String failedResultSetMovementStressMessages = "";
+
+ private class ResultSetMovementStress implements Runnable
+ {
+
+ private final XResultSet m_resultSet;
+ private final XRow m_row;
+ private final int m_id;
+
+ private ResultSetMovementStress(XResultSet _resultSet, int _id) throws java.lang.Exception
+ {
+ m_resultSet = _resultSet;
+ m_row = UnoRuntime.queryInterface( XRow.class, m_resultSet );
+ m_id = _id;
+ }
+
+ public void run()
+ {
+ int i=-1;
+ try
+ {
+ m_resultSet.beforeFirst();
+ for (i = 0; m_resultSet.next(); ++i)
+ {
+ int pos = m_resultSet.getRow();
+ testPosition(m_resultSet, m_row, i + 1, "clone move(" + m_id + ")");
+ int pos2 = m_resultSet.getRow();
+ assertTrue("ResultSetMovementStress wrong position: " + i + " Pos1: " + pos + " Pos2: " + pos2, pos == pos2);
+ }
+ }
+ catch (Exception e)
+ {
+ synchronized (failedResultSetMovementStressGuard) {
+ failedResultSetMovementStressMessages
+ += "ResultSetMovementStress(" + m_id + ") failed at i="
+ + i + ": " + e + "\n";
+ }
+ }
+ }
+ }
+
+ private void createTestCase(boolean _defaultRowSet) throws Exception
+ {
+ if (m_database == null)
+ {
+ final CRMDatabase database = new CRMDatabase( getMSF(), false );
+ m_database = database.getDatabase();
+ m_dataSource = m_database.getDataSource();
+ }
+
+ createStructure();
+
+ if (_defaultRowSet)
+ {
+ createRowSet("TEST1", CommandType.TABLE, true, true);
+ }
+ }
+
+ @After public final void closeAndDeleteDatabase() {
+ if (m_database != null) {
+ m_database.closeAndDelete();
+ }
+ }
+
+ /** creates a com.sun.star.sdb.RowSet to use during the test
+ * @param command
+ * the command to use for the RowSet
+ * @param commandType
+ * the command type to use for the RowSet
+ * @param execute
+ * determines whether the RowSet should be executed
+ */
+ private void createRowSet(String command, int commandType, boolean execute) throws com.sun.star.uno.Exception
+ {
+ createRowSet(command, commandType, execute, false);
+ }
+
+
+ /** creates a com.sun.star.sdb.RowSet to use during the test
+ * @param command
+ * the command to use for the RowSet
+ * @param commandType
+ * the command type to use for the RowSet
+ * @param execute
+ * determines whether the RowSet should be executed
+ * @param limitFetchSize
+ * determines whether the fetch size of the RowSet should be limited to MAX_FETCH_ROWS
+ */
+ private void createRowSet(String command, int commandType, boolean execute, boolean limitFetchSize) throws com.sun.star.uno.Exception
+ {
+ m_rowSet = UnoRuntime.queryInterface( XRowSet.class, getMSF().createInstance( "com.sun.star.sdb.RowSet" ) );
+ final XPropertySet rowSetProperties = UnoRuntime.queryInterface( XPropertySet.class, m_rowSet );
+ rowSetProperties.setPropertyValue("Command", command);
+ rowSetProperties.setPropertyValue("CommandType", Integer.valueOf(commandType));
+ rowSetProperties.setPropertyValue("ActiveConnection", m_database.defaultConnection().getXConnection());
+ if (limitFetchSize)
+ {
+ rowSetProperties.setPropertyValue("FetchSize", Integer.valueOf(MAX_FETCH_ROWS));
+ }
+
+ m_resultSet = UnoRuntime.queryInterface( XResultSet.class, m_rowSet );
+ m_resultSetUpdate = UnoRuntime.queryInterface( XResultSetUpdate.class, m_rowSet );
+ m_row = UnoRuntime.queryInterface( XRow.class, m_rowSet );
+ m_rowLocate = UnoRuntime.queryInterface( XRowLocate.class, m_resultSet );
+ m_rowSetProperties = UnoRuntime.queryInterface( XPropertySet.class, m_rowSet );
+ m_paramsSupplier = UnoRuntime.queryInterface( XParametersSupplier.class, m_rowSet );
+
+ if (execute)
+ {
+ m_rowSet.execute();
+ }
+ }
+
+
+ @Test
+ public void testRowSet() throws java.lang.Exception
+ {
+
+ System.out.println("testing testRowSet");
+ createTestCase(true);
+
+ // sequential positioning
+ m_resultSet.beforeFirst();
+ testSequentialPositining(m_resultSet, m_row);
+
+ // absolute positioning
+ testAbsolutePositioning(m_resultSet, m_row);
+
+ // position during modify
+ testModifyPosition(m_resultSet, m_row);
+
+ // 3rd test
+ test3(createClone(), m_resultSet);
+ // 4th test
+ test4(m_resultSet);
+
+ // concurrent (multi threaded) access to the row set and its clones
+ testConcurrentAccess(m_resultSet);
+ }
+
+
+ XResultSet createClone() throws SQLException
+ {
+ final XResultSetAccess rowAcc = UnoRuntime.queryInterface( XResultSetAccess.class, m_rowSet );
+ return rowAcc.createResultSet();
+ }
+
+
+ void createStructure() throws SQLException
+ {
+ m_database.executeSQL("DROP TABLE \"TEST1\" IF EXISTS");
+ m_database.executeSQL("CREATE TABLE \"TEST1\" (\"ID\" integer not null primary key, \"col2\" varchar(50) )");
+
+ final Connection connection = m_database.defaultConnection();
+ final XPreparedStatement prep = connection.prepareStatement("INSERT INTO \"TEST1\" values (?,?)");
+ final XParameters para = UnoRuntime.queryInterface( XParameters.class, prep );
+ for (int i = 1; i <= MAX_TABLE_ROWS; ++i)
+ {
+ para.setInt(1, i);
+ para.setString(2, "Test" + i);
+ prep.executeUpdate();
+ }
+
+ connection.refreshTables();
+ }
+
+
+ void testPosition(XResultSet resultSet, XRow row, int expectedValue, String location) throws SQLException
+ {
+ final int val = row.getInt(1);
+ final int pos = resultSet.getRow();
+ assertTrue(location + ": value/position do not match: " + pos + " (pos) != " + val + " (val)", val == pos);
+ assertTrue(location + ": value/position are not as expected: " + val + " (val) != " + expectedValue + " (expected)", val == expectedValue);
+ }
+
+
+ void testSequentialPositining(XResultSet _resultSet, XRow _row) throws com.sun.star.uno.Exception
+ {
+ // 1st test
+ int i = 1;
+ while (_resultSet.next())
+ {
+ testPosition(_resultSet, _row, i, "testSequentialPositining");
+ ++i;
+ }
+ }
+
+
+ void testAbsolutePositioning(XResultSet _resultSet, XRow _row) throws com.sun.star.uno.Exception
+ {
+ for (int i = 1; i <= MAX_FETCH_ROWS; ++i)
+ {
+ final int calcPos = (MAX_TABLE_ROWS % i) + 1;
+ assertTrue("testAbsolutePositioning failed", _resultSet.absolute(calcPos));
+ testPosition(_resultSet, _row, calcPos, "testAbsolutePositioning");
+ }
+ }
+
+
+ void testModifyPosition(XResultSet _resultSet, XRow _row) throws com.sun.star.uno.Exception
+ {
+ final int testPos = 3;
+ assertTrue("testModifyPosition wants at least " + (testPos+1) + " rows", MAX_FETCH_ROWS >= testPos+1);
+ assertTrue("testModifyPosition failed on moving to row " + testPos, _resultSet.absolute(testPos));
+ UnoRuntime.queryInterface( XRowUpdate.class, _row ).updateString(2, TEST21);
+ testPosition(_resultSet, _row, testPos, "testModifyPosition");
+ UnoRuntime.queryInterface( XResultSetUpdate.class, _resultSet ).cancelRowUpdates();
+ }
+
+
+ void test3(XResultSet clone, XResultSet _resultSet) throws com.sun.star.uno.Exception
+ {
+ final XRow _row = UnoRuntime.queryInterface( XRow.class, _resultSet );
+ final XRow cloneRow = UnoRuntime.queryInterface( XRow.class, clone );
+ for (int i = 1; i <= MAX_FETCH_ROWS; ++i)
+ {
+ final int calcPos = (MAX_TABLE_ROWS % i) + 1;
+ if (clone.absolute(calcPos))
+ {
+ testPosition(clone, cloneRow, calcPos, "test3");
+ testAbsolutePositioning(_resultSet, _row);
+ testAbsolutePositioning(clone, cloneRow);
+ }
+ }
+ }
+
+
+ void test4(XResultSet _resultSet) throws com.sun.star.uno.Exception
+ {
+ final XRow _row = UnoRuntime.queryInterface( XRow.class, _resultSet );
+ _resultSet.beforeFirst();
+
+ for (int i = 1; i <= MAX_TABLE_ROWS; ++i)
+ {
+ _resultSet.next();
+ final XResultSet clone = createClone();
+ final XRow cloneRow = UnoRuntime.queryInterface( XRow.class, clone );
+ final int calcPos = MAX_TABLE_ROWS - 1;
+ if (calcPos != 0 && clone.absolute(calcPos))
+ {
+ testPosition(clone, cloneRow, calcPos, "test4: clone");
+ testPosition(_resultSet, _row, i, "test4: rowset");
+ }
+ }
+ }
+
+
+ void testConcurrentAccess(XResultSet _resultSet) throws Exception
+ {
+ System.out.println("testing Thread");
+
+ _resultSet.beforeFirst();
+
+ final int numberOfThreads = 10;
+
+ final Thread threads[] = new Thread[numberOfThreads];
+ for (int i = 0; i < numberOfThreads; ++i)
+ {
+ threads[i] = new Thread(new ResultSetMovementStress(createClone(), i));
+ System.out.println("starting thread " + (i + 1) + " of " + (numberOfThreads));
+ threads[i].start();
+ }
+
+ for (int i = 0; i < numberOfThreads; ++i)
+ {
+ threads[i].join();
+ }
+ synchronized (failedResultSetMovementStressGuard) {
+ assertEquals("", failedResultSetMovementStressMessages);
+ }
+ }
+
+
+ @Test
+ public void testRowSetEvents() throws java.lang.Exception
+ {
+ System.out.println("testing RowSet Events");
+ createTestCase(true);
+
+ // first we create our RowSet object
+ final RowSetEventListener pRow = new RowSetEventListener();
+
+ final XColumnsSupplier colSup = UnoRuntime.queryInterface( XColumnsSupplier.class, m_rowSet );
+ final XPropertySet col = UnoRuntime.queryInterface( XPropertySet.class, colSup.getColumns().getByName( "ID" ) );
+ col.addPropertyChangeListener("Value", pRow);
+ m_rowSetProperties.addPropertyChangeListener("IsModified", pRow);
+ m_rowSetProperties.addPropertyChangeListener("IsNew", pRow);
+ m_rowSetProperties.addPropertyChangeListener("IsRowCountFinal", pRow);
+ m_rowSetProperties.addPropertyChangeListener("RowCount", pRow);
+
+ final XRowSetApproveBroadcaster xApBroad = UnoRuntime.queryInterface( XRowSetApproveBroadcaster.class, m_resultSet );
+ xApBroad.addRowSetApproveListener(pRow);
+ m_rowSet.addRowSetListener(pRow);
+
+ // do some movements to check if we got all notifications
+ final Class cResSet = Class.forName("com.sun.star.sdbc.XResultSet");
+ final boolean moves[] = new boolean[9];
+ for (int i = 0; i < moves.length; ++i)
+ {
+ moves[i] = false;
+ }
+ moves[RowSetEventListener.APPROVE_CURSOR_MOVE] = true;
+ moves[RowSetEventListener.COLUMN_VALUE] = true;
+ moves[RowSetEventListener.CURSOR_MOVED] = true;
+ moves[RowSetEventListener.IS_ROW_COUNT_FINAL] = true;
+ moves[RowSetEventListener.ROW_COUNT] = true;
+
+ testCursorMove(m_resultSet, cResSet.getMethod("afterLast", (Class[]) null), pRow, moves, null);
+
+ moves[RowSetEventListener.IS_ROW_COUNT_FINAL] = false;
+ moves[RowSetEventListener.ROW_COUNT] = false;
+ testCursorMove(m_resultSet, cResSet.getMethod(NEXT, (Class[]) null), pRow, moves, null);
+ testCursorMove(m_resultSet, cResSet.getMethod(NEXT, (Class[]) null), pRow, moves, null);
+ testCursorMove(m_resultSet, cResSet.getMethod(NEXT, (Class[]) null), pRow, moves, null);
+ testCursorMove(m_resultSet, cResSet.getMethod("last", (Class[]) null), pRow, moves, null);
+ testCursorMove(m_resultSet, cResSet.getMethod(NEXT, (Class[]) null), pRow, moves, null);
+ testCursorMove(m_resultSet, cResSet.getMethod("first", (Class[]) null), pRow, moves, null);
+ testCursorMove(m_resultSet, cResSet.getMethod("previous", (Class[]) null), pRow, moves, null);
+ testCursorMove(m_resultSet, cResSet.getMethod(NEXT, (Class[]) null), pRow, moves, null);
+ moves[RowSetEventListener.IS_MODIFIED] = true;
+ final XRowUpdate updRow = UnoRuntime.queryInterface( XRowUpdate.class, m_resultSet );
+ updRow.updateString(2, TEST21);
+ testCursorMove(m_resultSet, cResSet.getMethod(NEXT, (Class[]) null), pRow, moves, null);
+
+ moves[RowSetEventListener.IS_MODIFIED] = false;
+ updRow.updateString(2, m_row.getString(2));
+ testCursorMove(m_resultSet, cResSet.getMethod(NEXT, (Class[]) null), pRow, moves, null);
+
+ moves[RowSetEventListener.IS_MODIFIED] = false;
+ final Class cupd = Class.forName("com.sun.star.sdbc.XResultSetUpdate");
+ final XResultSetUpdate upd = UnoRuntime.queryInterface( XResultSetUpdate.class, m_resultSet );
+ testCursorMove(upd, cupd.getMethod("moveToInsertRow", (Class[]) null), pRow, moves, null);
+
+ updRow.updateInt(1, MAX_TABLE_ROWS + 2);
+ updRow.updateString(2, "HHHH");
+ moves[RowSetEventListener.APPROVE_CURSOR_MOVE] = false;
+ moves[RowSetEventListener.CURSOR_MOVED] = false;
+ moves[RowSetEventListener.IS_MODIFIED] = true;
+ moves[RowSetEventListener.IS_NEW] = true;
+ moves[RowSetEventListener.ROW_COUNT] = true;
+ moves[RowSetEventListener.APPROVE_ROW_CHANGE] = true;
+ moves[RowSetEventListener.ROW_CHANGED] = true;
+ testCursorMove(upd, cupd.getMethod("insertRow", (Class[]) null), pRow, moves, null);
+
+ moves[RowSetEventListener.IS_NEW] = false;
+ moves[RowSetEventListener.ROW_COUNT] = false;
+ m_resultSet.first();
+ updRow.updateInt(1, MAX_TABLE_ROWS + 3);
+ updRow.updateString(2, "__");
+ testCursorMove(upd, cupd.getMethod("updateRow", (Class[]) null), pRow, moves, null);
+
+ moves[RowSetEventListener.IS_NEW] = true;
+ moves[RowSetEventListener.ROW_COUNT] = true;
+ m_resultSet.first();
+ testCursorMove(upd, cupd.getMethod("deleteRow", (Class[]) null), pRow, moves, null);
+
+ moves[RowSetEventListener.IS_NEW] = false;
+ moves[RowSetEventListener.COLUMN_VALUE] = true;
+ moves[RowSetEventListener.ROW_COUNT] = false;
+ m_resultSet.first();
+ updRow.updateString(2, TEST21);
+ testCursorMove(m_resultSet, cResSet.getMethod("refreshRow", (Class[]) null), pRow, moves, null);
+
+ m_resultSet.first();
+ updRow.updateString(2, TEST21);
+ testCursorMove(upd, cupd.getMethod("cancelRowUpdates", (Class[]) null), pRow, moves, null);
+
+ for (int i = 0; i < moves.length; ++i)
+ {
+ moves[i] = false;
+ }
+ moves[RowSetEventListener.APPROVE_CURSOR_MOVE] = true;
+ moves[RowSetEventListener.COLUMN_VALUE] = true;
+ moves[RowSetEventListener.CURSOR_MOVED] = true;
+
+ final Class cloc = Class.forName("com.sun.star.sdbcx.XRowLocate");
+ m_resultSet.first();
+ final Object bookmark = m_rowLocate.getBookmark();
+ m_resultSet.next();
+ final Object temp[] = new Object[1];
+ temp[0] = bookmark;
+ Class ctemp[] = new Class[1];
+ ctemp[0] = Object.class;
+ testCursorMove(m_rowLocate, cloc.getMethod("moveToBookmark", ctemp), pRow, moves, temp);
+
+ final Object temp2[] = new Object[2];
+ temp2[0] = bookmark;
+ temp2[1] = Integer.valueOf(1);
+ final Class ctemp2[] = new Class[2];
+ ctemp2[0] = Object.class;
+ ctemp2[1] = int.class;
+ testCursorMove(m_rowLocate, cloc.getMethod("moveRelativeToBookmark", ctemp2), pRow, moves, temp2);
+
+ for (int i = 0; i < moves.length; ++i)
+ {
+ moves[i] = false;
+ }
+ moves[RowSetEventListener.APPROVE_ROW_CHANGE] = true;
+ moves[RowSetEventListener.ROW_CHANGED] = true;
+ moves[RowSetEventListener.ROW_COUNT] = true;
+ final Class cdelRows = Class.forName("com.sun.star.sdbcx.XDeleteRows");
+ ctemp[0] = Object[].class;
+ final XDeleteRows delRows = UnoRuntime.queryInterface( XDeleteRows.class, m_resultSet );
+ final Object bookmarks[] = new Object[5];
+ m_resultSet.first();
+ for (int i = 0; i < bookmarks.length; ++i)
+ {
+ m_resultSet.next();
+ bookmarks[i] = m_rowLocate.getBookmark();
+ }
+
+ temp[0] = bookmarks;
+ testCursorMove(delRows, cdelRows.getMethod("deleteRows", ctemp), pRow, moves, temp);
+
+ // now destroy the RowSet
+ final XComponent xComp = UnoRuntime.queryInterface( XComponent.class, m_resultSet );
+ xComp.dispose();
+ }
+
+
+ private void testCursorMove(Object res, Method _method, RowSetEventListener _evt, boolean _must[], Object args[]) throws java.lang.Exception
+ {
+ _evt.clearCalling();
+ _method.invoke(res, args);
+
+ System.out.println("testing events for " + _method.getName());
+ final int calling[] = _evt.getCalling();
+ int pos = 1;
+ assertTrue("Callings are not in the correct order for APPROVE_CURSOR_MOVE ",
+ (!_must[RowSetEventListener.APPROVE_CURSOR_MOVE] || calling[RowSetEventListener.APPROVE_CURSOR_MOVE] == -1) || calling[RowSetEventListener.APPROVE_CURSOR_MOVE] == pos++);
+ assertTrue("Callings are not in the correct order for APPROVE_ROW_CHANGE",
+ (!_must[RowSetEventListener.APPROVE_ROW_CHANGE] || calling[RowSetEventListener.APPROVE_ROW_CHANGE] == -1) || calling[RowSetEventListener.APPROVE_ROW_CHANGE] == pos++);
+ assertTrue("Callings are not in the correct order for COLUMN_VALUE",
+ (!_must[RowSetEventListener.COLUMN_VALUE] || calling[RowSetEventListener.COLUMN_VALUE] == -1) || calling[RowSetEventListener.COLUMN_VALUE] == pos++);
+ assertTrue("Callings are not in the correct order for CURSOR_MOVED",
+ (!_must[RowSetEventListener.CURSOR_MOVED] || calling[RowSetEventListener.CURSOR_MOVED] == -1) || calling[RowSetEventListener.CURSOR_MOVED] == pos++);
+ assertTrue("Callings are not in the correct order for ROW_CHANGED",
+ (!_must[RowSetEventListener.ROW_CHANGED] || calling[RowSetEventListener.ROW_CHANGED] == -1) || calling[RowSetEventListener.ROW_CHANGED] == pos++);
+ assertTrue("Callings are not in the correct order for IS_MODIFIED",
+ (!_must[RowSetEventListener.IS_MODIFIED] || calling[RowSetEventListener.IS_MODIFIED] == -1) || calling[RowSetEventListener.IS_MODIFIED] == pos++);
+ assertTrue("Callings are not in the correct order for IS_NEW",
+ (!_must[RowSetEventListener.IS_NEW] || calling[RowSetEventListener.IS_NEW] == -1) || calling[RowSetEventListener.IS_NEW] == pos++);
+ assertTrue("Callings are not in the correct order for ROW_COUNT",
+ (!_must[RowSetEventListener.ROW_COUNT] || calling[RowSetEventListener.ROW_COUNT] == -1) || calling[RowSetEventListener.ROW_COUNT] == pos++);
+ assertTrue("Callings are not in the correct order for IS_ROW_COUNT_FINAL",
+ (!_must[RowSetEventListener.IS_ROW_COUNT_FINAL] || calling[RowSetEventListener.IS_ROW_COUNT_FINAL] == -1) || calling[RowSetEventListener.IS_ROW_COUNT_FINAL] == pos);
+
+ _evt.clearCalling();
+ }
+
+
+ /** returns the current row count of the RowSet
+ */
+ private int currentRowCount() throws UnknownPropertyException, WrappedTargetException
+ {
+ final Integer rowCount = (Integer) m_rowSetProperties.getPropertyValue("RowCount");
+ return rowCount.intValue();
+ }
+
+
+ /** positions the row set at an arbitrary position between 2 and (current row count - 1)
+ */
+ private int positionRandom() throws SQLException, UnknownPropertyException, WrappedTargetException
+ {
+ // note: obviously this should subtract 2 but actually subtract 3
+ // because if we have just deleted the current row then
+ // ORowSetBase::impl_getRowCount() will lie and currentRowCount()
+ // returns 1 more than the actual number of rows and then
+ // positionRandom() followed by deleteRow() deletes *last* row
+ final int position = (new Random()).nextInt(currentRowCount() - 3) + 2;
+ assertTrue("sub task failed: could not position to row no. " + (Integer.valueOf(position)).toString(),
+ m_resultSet.absolute(position));
+ return m_resultSet.getRow();
+ }
+
+
+ /** moves the result set to a random record between 2 and (current row count - 1), and deletes this record
+ *
+ * After returning from this method, the row set is still positioned at the deleted record
+ * @return
+ * the number/position of the record which has been deleted
+ */
+ private int deleteRandom() throws SQLException, UnknownPropertyException, WrappedTargetException
+ {
+ // check if the current position and the row count in the result set is changed by a deletion (it should not)
+ final int positionBefore = positionRandom();
+ final int rowCountBefore = currentRowCount();
+
+ m_resultSetUpdate.deleteRow();
+
+ final int positionAfter = m_resultSet.getRow();
+ final int rowCountAfter = currentRowCount();
+ assertTrue("position changed during |deleteRow| (it should not)", positionAfter == positionBefore);
+ assertTrue("row count changed with a |deleteRow| (it should not)", rowCountBefore == rowCountAfter);
+ assertTrue("RowSet does not report the current row as deleted after |deleteRow|", m_resultSet.rowDeleted());
+
+ return positionBefore;
+ }
+
+
+ @Test
+ public void testDeleteBehavior() throws Exception
+ {
+ createTestCase(true);
+
+ // ensure that all records are known
+ m_resultSet.last();
+ final int initialRowCount = currentRowCount();
+
+ // delete a random row
+ int deletedRow = deleteRandom();
+
+
+ // asking for the bookmark of a deleted row should fail
+ boolean caughtException = false;
+ try
+ {
+ m_rowLocate.getBookmark();
+ }
+ catch (SQLException e)
+ {
+ caughtException = true;
+ }
+ assertTrue("asking for the bookmark of a deleted row should throw an exception", caughtException);
+
+
+ // isXXX methods should return |false| on a deleted row
+ assertTrue("one of the isFoo failed after |deleteRow|", !m_resultSet.isBeforeFirst() && !m_resultSet.isAfterLast() && !m_resultSet.isFirst() && !m_resultSet.isLast());
+ // note that we can assume that isFirst / isLast also return |false|, since deleteRandom did
+ // not position on the first or last record, but inbetween
+
+
+ // check if moving away from this row in either direction yields the expected results
+ assertTrue("|previous| after |deleteRow| failed", m_resultSet.previous());
+ final int positionPrevious = m_resultSet.getRow();
+ assertTrue("position after |previous| after |deleteRow| is not as expected", positionPrevious == deletedRow - 1);
+
+ deletedRow = deleteRandom();
+ assertTrue("|next| after |deleteRow| failed", m_resultSet.next());
+ final int positionAfter = m_resultSet.getRow();
+ assertTrue("position after |next| after |deleteRow| is not as expected", positionAfter == deletedRow);
+ // since the deleted record "vanishes" as soon as the cursor is moved away from it, the absolute position does
+ // not change with a |next| call here
+
+
+ // check if the deleted rows really vanished after moving away from them
+ assertTrue("row count did not change as expected after two deletions", initialRowCount - 2 == currentRowCount());
+
+
+ // check if the deleted row vanishes after moving to the insertion row
+ final int rowCountBefore = currentRowCount();
+ final int deletedPos = deleteRandom();
+ m_resultSetUpdate.moveToInsertRow();
+ assertTrue("moving to the insertion row immediately after |deleteRow| does not adjust the row count", rowCountBefore == currentRowCount() + 1);
+
+ m_resultSetUpdate.moveToCurrentRow();
+ assertTrue("|moveToCurrentRow| after |deleteRow| + |moveToInsertRow| results in unexpected position",
+ (m_resultSet.getRow() == deletedPos) && !m_resultSet.rowDeleted());
+
+ // the same, but this time with deleting the first row (which is not covered by deleteRandom)
+ m_resultSet.last();
+ m_resultSetUpdate.deleteRow();
+ m_resultSetUpdate.moveToInsertRow();
+ m_resultSetUpdate.moveToCurrentRow();
+ assertTrue("|last| + |deleteRow| + |moveToInsertRow| + |moveToCurrentRow| results in wrong state", m_resultSet.isAfterLast());
+
+
+ // check if deleting a deleted row fails as expected
+ deleteRandom();
+ caughtException = false;
+ try
+ {
+ m_resultSetUpdate.deleteRow();
+ }
+ catch (SQLException e)
+ {
+ caughtException = true;
+ }
+ assertTrue("deleting a deleted row succeeded - it shouldn't", caughtException);
+
+
+ // check if deleteRows fails if it contains the bookmark of a previously-deleted row
+ m_resultSet.first();
+ final Object firstBookmark = m_rowLocate.getBookmark();
+ positionRandom();
+ final Object deleteBookmark = m_rowLocate.getBookmark();
+ m_resultSetUpdate.deleteRow();
+ final XDeleteRows multiDelete = UnoRuntime.queryInterface( XDeleteRows.class, m_resultSet );
+ final int[] deleteSuccess = multiDelete.deleteRows(new Object[]
+ {
+ firstBookmark, deleteBookmark
+ });
+ assertTrue("XDeleteRows::deleteRows with the bookmark of an already-deleted row failed",
+ (deleteSuccess.length == 2) && (deleteSuccess[0] != 0) && (deleteSuccess[1] == 0));
+
+
+ // check if refreshing a deleted row fails as expected
+ deleteRandom();
+ caughtException = false;
+ try
+ {
+ m_resultSet.refreshRow();
+ }
+ catch (SQLException e)
+ {
+ caughtException = true;
+ }
+ assertTrue("refreshing a deleted row succeeded - it shouldn't", caughtException);
+
+
+ // rowUpdated/rowDeleted
+ deleteRandom();
+ assertTrue("rowDeleted and/or rowUpdated are wrong on a deleted row", !m_resultSet.rowUpdated() && !m_resultSet.rowInserted());
+
+
+ // updating values in a deleted row should fail
+ deleteRandom();
+ final XRowUpdate rowUpdated = UnoRuntime.queryInterface( XRowUpdate.class, m_resultSet );
+ caughtException = false;
+ try
+ {
+ rowUpdated.updateString(2, TEST21);
+ }
+ catch (SQLException e)
+ {
+ caughtException = true;
+ }
+ assertTrue("updating values in a deleted row should not succeed", caughtException);
+ }
+
+
+ /** checks whether deletions on the main RowSet properly interfere (or don't interfere) with the movement
+ * on a clone of the RowSet
+ */
+ @Test
+ public void testCloneMovesPlusDeletions() throws Exception
+ {
+ createTestCase(true);
+ // ensure that all records are known
+ m_resultSet.last();
+
+ final XResultSet clone = createClone();
+ final XRowLocate cloneRowLocate = UnoRuntime.queryInterface( XRowLocate.class, clone );
+
+ positionRandom();
+
+
+ // move the clone to the same record as the RowSet, and delete this record
+ cloneRowLocate.moveToBookmark(m_rowLocate.getBookmark());
+ final int clonePosition = clone.getRow();
+ m_resultSetUpdate.deleteRow();
+
+ assertTrue("clone doesn't know that its current row has been deleted via the RowSet", clone.rowDeleted());
+ assertTrue("clone's position changed somehow during deletion", clonePosition == clone.getRow());
+
+
+ // move the row set away from the deleted record. This should still not touch the state of the clone
+ m_resultSet.previous();
+
+ assertTrue("clone doesn't know (anymore) that its current row has been deleted via the RowSet", clone.rowDeleted());
+ assertTrue("clone's position changed somehow during deletion and RowSet-movement", clonePosition == clone.getRow());
+
+
+ // move the clone away from the deleted record
+ clone.next();
+ assertTrue("clone still assumes that its row is deleted - but we already moved it", !clone.rowDeleted());
+
+
+ // check whether deleting the extremes (first / last) work
+ m_resultSet.first();
+ cloneRowLocate.moveToBookmark(m_rowLocate.getBookmark());
+ m_resultSetUpdate.deleteRow();
+ clone.previous();
+ assertTrue("deleting the first record left the clone in a strange state (after |previous|)", clone.isBeforeFirst());
+ clone.next();
+ assertTrue("deleting the first record left the clone in a strange state (after |previous| + |next|)", clone.isFirst());
+
+ m_resultSet.last();
+ cloneRowLocate.moveToBookmark(m_rowLocate.getBookmark());
+ m_resultSetUpdate.deleteRow();
+ clone.next();
+ assertTrue("deleting the last record left the clone in a strange state (after |next|)", clone.isAfterLast());
+ clone.previous();
+ assertTrue("deleting the first record left the clone in a strange state (after |next| + |previous|)", clone.isLast());
+
+
+ // check whether movements of the clone interfere with movements of the RowSet, if the latter is on a deleted row
+ final int positionBefore = positionRandom();
+ m_resultSetUpdate.deleteRow();
+ assertTrue("|deleteRow|, but no |rowDeleted| (this should have been found much earlier!)", m_resultSet.rowDeleted());
+ clone.beforeFirst();
+ while (clone.next()) {}
+ assertTrue("row set forgot that the current row is deleted", m_resultSet.rowDeleted());
+
+ assertTrue("moving to the next record after |deleteRow| and clone moves failed", m_resultSet.next());
+ assertTrue("wrong position after |deleteRow| and clone movement", !m_resultSet.isAfterLast() && !m_resultSet.isBeforeFirst());
+ assertTrue("wrong absolute position after |deleteRow| and clone movement", m_resultSet.getRow() == positionBefore);
+ }
+
+
+ /** checks whether insertions on the main RowSet properly interfere (or don't interfere) with the movement
+ * on a clone of the RowSet
+ */
+ @Test
+ public void testCloneMovesPlusInsertions() throws Exception
+ {
+ createTestCase(true);
+ // ensure that all records are known
+ m_rowSetProperties.setPropertyValue("FetchSize", Integer.valueOf(10));
+
+ final XResultSet clone = createClone();
+ final XRow cloneRow = UnoRuntime.queryInterface( XRow.class, clone );
+
+
+ // first check the basic scenario without the |moveToInsertRow| |moveToCurrentRow|, to ensure that
+ // really those are broken, if at all
+ m_resultSet.last();
+ clone.first();
+ clone.absolute(11);
+ clone.first();
+
+ final int rowValue1 = m_row.getInt(1);
+ final int rowPos = m_resultSet.getRow();
+ final int rowValue2 = m_row.getInt(1);
+ assertTrue("repeated query for the same column value delivers different values (" + rowValue1 + " and " + rowValue2 + ") on row: " + rowPos,
+ rowValue1 == rowValue2);
+
+ testPosition(clone, cloneRow, 1, "mixed clone/rowset move: clone check");
+ testPosition(m_resultSet, m_row, MAX_TABLE_ROWS, "mixed clone/rowset move: rowset check");
+
+
+ // now the complete scenario
+ m_resultSet.last();
+ m_resultSetUpdate.moveToInsertRow();
+ clone.first();
+ clone.absolute(11);
+ clone.first();
+ m_resultSetUpdate.moveToCurrentRow();
+
+ testPosition(clone, cloneRow, 1, "mixed clone/rowset move/insertion: clone check");
+ testPosition(m_resultSet, m_row, 100, "mixed clone/rowset move/insertion: rowset check");
+ }
+
+
+ private void testTableParameters() throws com.sun.star.uno.Exception
+ {
+ // for a row set simply based on a table, there should be not parameters at all
+ createRowSet("products", CommandType.TABLE, false);
+ verifyParameters(new String[]
+ {
+ }, "testTableParameters");
+ }
+
+
+ private void testParametersAfterNormalExecute() throws com.sun.star.uno.Exception
+ {
+ createRowSet("SELECT * FROM \"customers\"", CommandType.COMMAND, true);
+ m_rowSetProperties.setPropertyValue("Command", "SELECT * FROM \"customers\" WHERE \"City\" = :city");
+ final XParameters rowsetParams = UnoRuntime.queryInterface( XParameters.class, m_rowSet );
+ rowsetParams.setString(1, "London");
+ m_rowSet.execute();
+ }
+
+
+ private void verifyParameters(String[] _paramNames, String _context) throws com.sun.star.uno.Exception
+ {
+ final XIndexAccess params = m_paramsSupplier.getParameters();
+ final int expected = _paramNames.length;
+ final int found = params != null ? params.getCount() : 0;
+
+ assertTrue("wrong number of parameters (expected: " + expected + ", found: " + found + ") in " + _context,
+ found == expected);
+
+ if (found == 0)
+ {
+ return;
+ }
+
+ for (int i = 0; i < expected; ++i)
+ {
+ final XPropertySet parameter = UnoRuntime.queryInterface( XPropertySet.class, params.getByIndex( i ) );
+
+ final String expectedName = _paramNames[i];
+ final String foundName = (String) parameter.getPropertyValue("Name");
+ assertTrue("wrong parameter name (expected: " + expectedName + ", found: " + foundName + ") in" + _context,
+ expectedName.equals(foundName));
+ }
+ }
+
+
+ private void testParametrizedQuery() throws com.sun.star.uno.Exception
+ {
+ // for a row set based on a parametrized query, those parameters should be properly
+ // recognized
+ m_dataSource.createQuery("products like", "SELECT * FROM \"products\" WHERE \"Name\" LIKE :product_name");
+ createRowSet("products like", CommandType.QUERY, false);
+ verifyParameters(new String[]
+ {
+ "product_name"
+ }, "testParametrizedQuery");
+ }
+
+
+ private void testParametersInteraction() throws com.sun.star.uno.Exception
+ {
+ createRowSet("products like", CommandType.QUERY, false);
+
+ // let's fill in a parameter value via XParameters, and see whether it is respected by the parameters container
+ final XParameters rowsetParams = UnoRuntime.queryInterface(XParameters.class, m_rowSet);
+ rowsetParams.setString(1, "Apples");
+
+ XIndexAccess params = m_paramsSupplier.getParameters();
+ XPropertySet firstParam = UnoRuntime.queryInterface( XPropertySet.class, params.getByIndex( 0 ) );
+ Object firstParamValue = firstParam.getPropertyValue("Value");
+
+ assertTrue("XParameters and the parameters container do not properly interact",
+ "Apples".equals(firstParamValue));
+
+ // let's see whether this also survives an execute of the row set
+ rowsetParams.setString(1, "Oranges");
+ m_rowSet.execute();
+ {
+ // TODO: the following would not be necessary if the parameters container would *survive*
+ // the execution of the row set. It currently doesn't (though the values it represents do).
+ // It would be nice, but not strictly necessary, if it would.
+ params = m_paramsSupplier.getParameters();
+ firstParam = UnoRuntime.queryInterface( XPropertySet.class, params.getByIndex( 0 ) );
+ }
+ firstParamValue = firstParam.getPropertyValue("Value");
+ assertTrue("XParameters and the parameters container do not properly interact, after the row set has been executed",
+ "Oranges".equals(firstParamValue));
+ }
+
+
+ private void testParametersInFilter() throws com.sun.star.uno.Exception
+ {
+ createRowSet("SELECT * FROM \"customers\"", CommandType.COMMAND, false);
+ m_rowSetProperties.setPropertyValue("Filter", "\"City\" = :city");
+
+ m_rowSetProperties.setPropertyValue("ApplyFilter", Boolean.TRUE);
+ verifyParameters(new String[]
+ {
+ "city"
+ }, "testParametersInFilter");
+
+ m_rowSetProperties.setPropertyValue("ApplyFilter", Boolean.FALSE);
+ verifyParameters(new String[]
+ {
+ }, "testParametersInFilter");
+ }
+
+
+ /** checks the XParametersSupplier functionality of a RowSet
+ */
+ @Test
+ public void testParameters() throws Exception
+ {
+ createTestCase(false);
+ // use an own RowSet instance, not the one which is also used for the other cases
+
+ testTableParameters();
+ testParametrizedQuery();
+ testParametersInFilter();
+
+ testParametersAfterNormalExecute();
+
+ testParametersInteraction();
+ }
+}
+
diff --git a/dbaccess/qa/complex/dbaccess/RowSetEventListener.java b/dbaccess/qa/complex/dbaccess/RowSetEventListener.java
new file mode 100644
index 000000000..991dfb7af
--- /dev/null
+++ b/dbaccess/qa/complex/dbaccess/RowSetEventListener.java
@@ -0,0 +1,102 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+package complex.dbaccess;
+
+import com.sun.star.sdb.XRowSetApproveListener;
+import com.sun.star.sdbc.XRowSetListener;
+import com.sun.star.sdb.RowChangeEvent;
+import com.sun.star.lang.EventObject;
+import com.sun.star.beans.XPropertyChangeListener;
+
+public final class RowSetEventListener implements XRowSetApproveListener,XRowSetListener,XPropertyChangeListener
+{
+ public static final int APPROVE_CURSOR_MOVE = 0;
+ public static final int APPROVE_ROW_CHANGE = 1;
+ public static final int COLUMN_VALUE = 2;
+ public static final int CURSOR_MOVED = 3;
+ public static final int ROW_CHANGED = 4;
+ public static final int IS_MODIFIED = 5;
+ public static final int IS_NEW = 6;
+ public static final int ROW_COUNT = 7;
+ public static final int IS_ROW_COUNT_FINAL = 8;
+
+ private int callPos = 1;
+ private int calling [];
+
+ RowSetEventListener(){
+ calling = new int [9];
+ clearCalling();
+ }
+ public int[] getCalling(){
+ return calling;
+ }
+ public void clearCalling(){
+ for(int i = 0 ; i < calling.length; ++i){
+ calling[i] = -1;
+ }
+ callPos = 1;
+ }
+ // XEventListener
+ public void disposing(com.sun.star.lang.EventObject event)
+ {
+ }
+ // XRowSetApproveBroadcaster
+ public boolean approveCursorMove(EventObject event)
+ {
+ calling[APPROVE_CURSOR_MOVE] = callPos++;
+ return true;
+ }
+ public boolean approveRowChange(RowChangeEvent event)
+ {
+ calling[APPROVE_ROW_CHANGE] = callPos++;
+ return true;
+ }
+ public boolean approveRowSetChange(EventObject event)
+ {
+ return true;
+ }
+
+ // XRowSetListener
+ public void cursorMoved(com.sun.star.lang.EventObject event)
+ {
+ calling[CURSOR_MOVED] = callPos++;
+ }
+ public void rowChanged(com.sun.star.lang.EventObject event)
+ {
+ calling[ROW_CHANGED] = callPos++;
+ }
+ public void rowSetChanged(com.sun.star.lang.EventObject event)
+ {
+ }
+
+ public void propertyChange(com.sun.star.beans.PropertyChangeEvent propertyChangeEvent) {
+ if ( "Value".equals(propertyChangeEvent.PropertyName) ){
+ calling[COLUMN_VALUE] = callPos++;
+ } else if ( "IsModified".equals(propertyChangeEvent.PropertyName) ){
+ calling[IS_MODIFIED] = callPos++;
+ } else if ( "IsNew".equals(propertyChangeEvent.PropertyName) ){
+ calling[IS_NEW] = callPos++;
+ } else if ( "RowCount".equals(propertyChangeEvent.PropertyName) ){
+ calling[ROW_COUNT] = callPos++;
+ } else if ( "IsRowCountFinal".equals(propertyChangeEvent.PropertyName) ){
+ calling[IS_ROW_COUNT_FINAL] = callPos++;
+ }
+ }
+
+}
diff --git a/dbaccess/qa/complex/dbaccess/SingleSelectQueryComposer.java b/dbaccess/qa/complex/dbaccess/SingleSelectQueryComposer.java
new file mode 100644
index 000000000..2d05030b7
--- /dev/null
+++ b/dbaccess/qa/complex/dbaccess/SingleSelectQueryComposer.java
@@ -0,0 +1,351 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+package complex.dbaccess;
+
+import com.sun.star.beans.PropertyState;
+import com.sun.star.sdb.SQLFilterOperator;
+import com.sun.star.beans.PropertyAttribute;
+import com.sun.star.beans.XPropertySet;
+import com.sun.star.beans.XPropertyContainer;
+import com.sun.star.beans.NamedValue;
+import com.sun.star.container.XNameAccess;
+import com.sun.star.sdbcx.XTablesSupplier;
+import com.sun.star.sdb.XParametersSupplier;
+import com.sun.star.beans.PropertyValue;
+import com.sun.star.sdbcx.XColumnsSupplier;
+import com.sun.star.container.XIndexAccess;
+import com.sun.star.sdb.CommandType;
+import com.sun.star.sdb.XSingleSelectQueryComposer;
+import com.sun.star.uno.UnoRuntime;
+import com.sun.star.sdbc.DataType;
+import com.sun.star.sdbc.SQLException;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+
+// ---------- junit imports -----------------
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+
+public class SingleSelectQueryComposer extends CRMBasedTestCase
+{
+
+ private XSingleSelectQueryComposer m_composer = null;
+ private static final String COMPLEXFILTER = "( \"ID\" = 1 AND \"Postal\" = '4' )"
+ + " OR ( \"ID\" = 2 AND \"Postal\" = '5' )"
+ + " OR ( \"ID\" = 3 AND \"Postal\" = '6' AND \"Address\" = '7' )"
+ + " OR ( \"Address\" = '8' )"
+ + " OR ( \"Postal\" = '9' )"
+ + " OR ( NOW( ) = {d '2010-01-01' } )";
+ private static final String INNERPRODUCTSQUERY = "products (inner)";
+
+
+ private void createQueries() throws Exception
+ {
+ m_database.getDatabase().getDataSource().createQuery(INNERPRODUCTSQUERY, "SELECT * FROM \"products\"");
+ }
+
+
+ @Override
+ protected void createTestCase() throws Exception
+ {
+ super.createTestCase();
+
+ createQueries();
+
+ m_composer = createQueryComposer();
+ }
+
+
+ private void checkAttributeAccess(String _attributeName, String _attributeValue)
+ {
+ System.out.println("setting " + _attributeName + " to " + _attributeValue);
+ String realValue = null;
+ try
+ {
+ final Class composerClass = m_composer.getClass();
+ final Method attributeGetter = composerClass.getMethod("get" + _attributeName, new Class[]
+ {
+ });
+ final Method attributeSetter = composerClass.getMethod("set" + _attributeName, new Class[]
+ {
+ String.class
+ });
+
+ attributeSetter.invoke(m_composer, new Object[]
+ {
+ _attributeValue
+ });
+ realValue = (String) attributeGetter.invoke(m_composer, new Object[]
+ {
+ });
+ }
+ catch (NoSuchMethodException e)
+ {
+ }
+ catch (IllegalAccessException e)
+ {
+ }
+ catch (InvocationTargetException e)
+ {
+ }
+ assertTrue("set/get" + _attributeName + " not working as expected (set: " + _attributeValue + ", get: " + (realValue != null ? realValue : "null") + ")",
+ realValue.equals(_attributeValue));
+ System.out.println(" (results in " + m_composer.getQuery() + ")");
+ }
+
+ /** tests setCommand of the composer
+ */
+ @Test
+ public void testSetCommand() throws Exception
+ {
+ System.out.println("testing SingleSelectQueryComposer's setCommand");
+
+ final String table = "SELECT * FROM \"customers\"";
+ m_composer.setCommand("customers", CommandType.TABLE);
+ assertTrue("setCommand/getQuery TABLE inconsistent", m_composer.getQuery().equals(table));
+
+ m_database.getDatabase().getDataSource().createQuery("set command test", "SELECT * FROM \"orders for customer\" \"a\", \"customers\" \"b\" WHERE \"a\".\"Product Name\" = \"b\".\"Name\"");
+ m_composer.setCommand("set command test", CommandType.QUERY);
+ assertTrue("setCommand/getQuery QUERY inconsistent", m_composer.getQuery().equals(m_database.getDatabase().getDataSource().getQueryDefinition("set command test").getCommand()));
+
+ final String sql = "SELECT * FROM \"orders for customer\" WHERE \"Product Name\" = 'test'";
+ m_composer.setCommand(sql, CommandType.COMMAND);
+ assertTrue("setCommand/getQuery COMMAND inconsistent", m_composer.getQuery().equals(sql));
+ }
+
+ /** tests accessing attributes of the composer (order, filter, group by, having)
+ */
+ @Test
+ public void testAttributes() throws Exception
+ {
+ System.out.println("testing SingleSelectQueryComposer's attributes (order, filter, group by, having)");
+
+ System.out.println("check setElementaryQuery");
+
+ final String simpleQuery2 = "SELECT * FROM \"customers\" WHERE \"Name\" = 'oranges'";
+ m_composer.setElementaryQuery(simpleQuery2);
+ assertTrue("setElementaryQuery/getQuery inconsistent", m_composer.getQuery().equals(simpleQuery2));
+
+ System.out.println("check setQuery");
+ final String simpleQuery = "SELECT * FROM \"customers\"";
+ m_composer.setQuery(simpleQuery);
+ assertTrue("set/getQuery inconsistent", m_composer.getQuery().equals(simpleQuery));
+
+ checkAttributeAccess("Filter", "\"Name\" = 'oranges'");
+ checkAttributeAccess("Group", "\"City\"");
+ checkAttributeAccess("Order", "\"Address\"");
+ checkAttributeAccess("HavingClause", "\"ID\" <> 4");
+
+ final XIndexAccess orderColumns = m_composer.getOrderColumns();
+ assertTrue("Order columns doesn't exist: \"Address\"",
+ orderColumns != null && orderColumns.getCount() == 1 && orderColumns.getByIndex(0) != null);
+
+ final XIndexAccess groupColumns = m_composer.getGroupColumns();
+ assertTrue("Group columns doesn't exist: \"City\"",
+ groupColumns != null && groupColumns.getCount() == 1 && groupColumns.getByIndex(0) != null);
+
+ // XColumnsSupplier
+ final XColumnsSupplier xSelectColumns = UnoRuntime.queryInterface(XColumnsSupplier.class, m_composer);
+ assertTrue("no select columns, or wrong number of select columns",
+ xSelectColumns != null && xSelectColumns.getColumns() != null && xSelectColumns.getColumns().getElementNames().length == 6);
+
+ // structured filter
+ m_composer.setQuery("SELECT \"ID\", \"Postal\", \"Address\" FROM \"customers\"");
+ m_composer.setFilter(COMPLEXFILTER);
+ final PropertyValue[][] aStructuredFilter = m_composer.getStructuredFilter();
+ m_composer.setFilter("");
+ m_composer.setStructuredFilter(aStructuredFilter);
+ if (!m_composer.getFilter().equals(COMPLEXFILTER))
+ {
+ System.out.println(COMPLEXFILTER);
+ System.out.println(m_composer.getFilter());
+ }
+ assertTrue("Structured Filter not identical", m_composer.getFilter().equals(COMPLEXFILTER));
+
+ // structured having clause
+ m_composer.setHavingClause(COMPLEXFILTER);
+ final PropertyValue[][] aStructuredHaving = m_composer.getStructuredHavingClause();
+ m_composer.setHavingClause("");
+ m_composer.setStructuredHavingClause(aStructuredHaving);
+ assertTrue("Structured Having Clause not identical", m_composer.getHavingClause().equals(COMPLEXFILTER));
+ }
+
+ /** test various sub query related features ("queries in queries")
+ */
+ @Test
+ public void testSubQueries() throws Exception
+ {
+ m_composer.setQuery("SELECT * from \"" + INNERPRODUCTSQUERY + "\"");
+ final XTablesSupplier suppTables = UnoRuntime.queryInterface(XTablesSupplier.class, m_composer);
+ final XNameAccess tables = suppTables.getTables();
+ assertTrue("a simple SELECT * FROM <query> could not be parsed",
+ tables != null && tables.hasByName(INNERPRODUCTSQUERY));
+
+ final String sInnerCommand = m_database.getDatabase().getDataSource().getQueryDefinition(INNERPRODUCTSQUERY).getCommand();
+ final String sExecutableQuery = m_composer.getQueryWithSubstitution();
+ assertTrue("simple query containing a sub query improperly parsed to SDBC level statement: \n1. " + sExecutableQuery + "\n2. " + "SELECT * FROM ( " + sInnerCommand + " ) AS \"" + INNERPRODUCTSQUERY + "\"",
+ sExecutableQuery.equals("SELECT * FROM ( " + sInnerCommand + " ) AS \"" + INNERPRODUCTSQUERY + "\""));
+ }
+
+ /** tests the XParametersSupplier functionality
+ */
+ @Test
+ public void testParameters() throws Exception
+ {
+ // "orders for customers" is a query with a named parameter (based on another query)
+ m_database.getDatabase().getDataSource().createQuery("orders for customer", "SELECT * FROM \"all orders\" WHERE \"Customer Name\" LIKE :cname");
+ // "orders for customer and product" is query based on "orders for customers", adding an additional,
+ // anonymous parameter
+ m_database.getDatabase().getDataSource().createQuery("orders for customer and product", "SELECT * FROM \"orders for customer\" WHERE \"Product Name\" LIKE ?");
+
+ m_composer.setQuery(m_database.getDatabase().getDataSource().getQueryDefinition("orders for customer and product").getCommand());
+ final XParametersSupplier suppParams = UnoRuntime.queryInterface(XParametersSupplier.class, m_composer);
+ final XIndexAccess parameters = suppParams.getParameters();
+
+ final String expectedParamNames[] =
+
+ {
+ "cname",
+ "Product Name"
+ };
+
+ final int paramCount = parameters.getCount();
+ assertTrue("composer did find wrong number of parameters in the nested queries.",
+ paramCount == expectedParamNames.length);
+
+ for (int i = 0; i < paramCount; ++i)
+ {
+ final XPropertySet parameter = UnoRuntime.queryInterface(XPropertySet.class, parameters.getByIndex(i));
+ final String paramName = (String) parameter.getPropertyValue("Name");
+ assertTrue("wrong parameter name at position " + (i + 1) + " (expected: " + expectedParamNames[i] + ", found: " + paramName + ")",
+ paramName.equals(expectedParamNames[i]));
+
+ }
+ }
+
+ @Test
+ public void testConditionByColumn() throws Exception
+ {
+ m_composer.setQuery("SELECT * FROM \"customers\"");
+
+ final Object initArgs[] =
+
+ {
+ new NamedValue("AutomaticAddition", Boolean.TRUE)
+ };
+ final String serviceName = "com.sun.star.beans.PropertyBag";
+ final XPropertyContainer filter = UnoRuntime.queryInterface(XPropertyContainer.class, getMSF().createInstanceWithArguments(serviceName, initArgs));
+ filter.addProperty("Name", PropertyAttribute.MAYBEVOID, "Comment");
+ filter.addProperty("RealName", PropertyAttribute.MAYBEVOID, "Comment");
+ filter.addProperty("TableName", PropertyAttribute.MAYBEVOID, "customers");
+ filter.addProperty("Value", PropertyAttribute.MAYBEVOID, "Good one.");
+ filter.addProperty("Type", PropertyAttribute.MAYBEVOID, Integer.valueOf(DataType.LONGVARCHAR));
+ final XPropertySet column = UnoRuntime.queryInterface(XPropertySet.class, filter);
+
+ m_composer.appendFilterByColumn(column, true, SQLFilterOperator.LIKE);
+ assertTrue("At least one row should exist", m_database.getConnection().createStatement().executeQuery(m_composer.getQuery()).next());
+ }
+
+ private void impl_testDisjunctiveNormalForm(String _query, PropertyValue[][] _expectedDNF) throws SQLException
+ {
+ m_composer.setQuery(_query);
+
+ final PropertyValue[][] disjunctiveNormalForm = m_composer.getStructuredFilter();
+
+ assertEquals("DNF: wrong number of rows", _expectedDNF.length, disjunctiveNormalForm.length);
+ for (int i = 0; i < _expectedDNF.length; ++i)
+ {
+ assertEquals("DNF: wrong number of columns in row " + i, _expectedDNF[i].length, disjunctiveNormalForm[i].length);
+ for (int j = 0; j < _expectedDNF[i].length; ++j)
+ {
+ assertEquals("DNF: wrong content in column " + j + ", row " + i,
+ _expectedDNF[i][j].Name, disjunctiveNormalForm[i][j].Name);
+ }
+ }
+ }
+
+ /** tests the disjunctive normal form functionality, aka the structured filter,
+ * of the composer
+ */
+ @Test
+ public void testDisjunctiveNormalForm() throws Exception
+ {
+ // a simple case: WHERE clause simply is a combination of predicates knitted with AND
+ String query =
+ "SELECT \"customers\".\"Name\", "
+ + "\"customers\".\"Address\", "
+ + "\"customers\".\"City\", "
+ + "\"customers\".\"Postal\", "
+ + "\"products\".\"Name\" "
+ + "FROM \"orders\", \"customers\", \"orders_details\", \"products\" "
+ + "WHERE ( \"orders\".\"CustomerID\" = \"customers\".\"ID\" "
+ + "AND \"orders_details\".\"OrderID\" = \"orders\".\"ID\" "
+ + "AND \"orders_details\".\"ProductID\" = \"products\".\"ID\" "
+ + ") ";
+
+ impl_testDisjunctiveNormalForm(query, new PropertyValue[][]
+ {
+ new PropertyValue[]
+ {
+ new PropertyValue("CustomerID", SQLFilterOperator.EQUAL, "\"customers\".\"ID\"", PropertyState.DIRECT_VALUE),
+ new PropertyValue("OrderID", SQLFilterOperator.EQUAL, "\"orders\".\"ID\"", PropertyState.DIRECT_VALUE),
+ new PropertyValue("ProductID", SQLFilterOperator.EQUAL, "\"products\".\"ID\"", PropertyState.DIRECT_VALUE)
+ }
+ });
+
+ // somewhat more challenging: One of the conjunction terms is a disjunction itself
+ query =
+ "SELECT \"customers\".\"Name\", "
+ + "\"customers\".\"Address\", "
+ + "\"customers\".\"City\", "
+ + "\"customers\".\"Postal\", "
+ + "\"products\".\"Name\" "
+ + "FROM \"orders\", \"customers\", \"orders_details\", \"products\" "
+ + "WHERE ( \"orders\".\"CustomerID\" = \"customers\".\"ID\" "
+ + "AND \"orders_details\".\"OrderID\" = \"orders\".\"ID\" "
+ + "AND \"orders_details\".\"ProductID\" = \"products\".\"ID\" "
+ + ") "
+ + "AND "
+ + "( \"products\".\"Name\" = 'Apples' "
+ + "OR \"products\".\"ID\" = 2 "
+ + ")";
+
+ impl_testDisjunctiveNormalForm(query, new PropertyValue[][]
+ {
+ new PropertyValue[]
+ {
+ new PropertyValue("CustomerID", SQLFilterOperator.EQUAL, "\"customers\".\"ID\"", PropertyState.DIRECT_VALUE),
+ new PropertyValue("OrderID", SQLFilterOperator.EQUAL, "\"orders\".\"ID\"", PropertyState.DIRECT_VALUE),
+ new PropertyValue("ProductID", SQLFilterOperator.EQUAL, "\"products\".\"ID\"", PropertyState.DIRECT_VALUE),
+ new PropertyValue("Name", SQLFilterOperator.EQUAL, "Apples", PropertyState.DIRECT_VALUE)
+ },
+ new PropertyValue[]
+ {
+ new PropertyValue("CustomerID", SQLFilterOperator.EQUAL, "\"customers\".\"ID\"", PropertyState.DIRECT_VALUE),
+ new PropertyValue("OrderID", SQLFilterOperator.EQUAL, "\"orders\".\"ID\"", PropertyState.DIRECT_VALUE),
+ new PropertyValue("ProductID", SQLFilterOperator.EQUAL, "\"products\".\"ID\"", PropertyState.DIRECT_VALUE),
+ new PropertyValue("ID", SQLFilterOperator.EQUAL, Integer.valueOf(2), PropertyState.DIRECT_VALUE)
+ }
+ });
+
+ }
+}
diff --git a/dbaccess/qa/complex/dbaccess/TestCase.java b/dbaccess/qa/complex/dbaccess/TestCase.java
new file mode 100644
index 000000000..a9768e7b4
--- /dev/null
+++ b/dbaccess/qa/complex/dbaccess/TestCase.java
@@ -0,0 +1,232 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+package complex.dbaccess;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import com.sun.star.beans.PropertyValue;
+import com.sun.star.frame.XComponentLoader;
+import com.sun.star.frame.XModel;
+import com.sun.star.lang.XMultiServiceFactory;
+import com.sun.star.uno.UnoRuntime;
+import com.sun.star.uno.XComponentContext;
+import helper.FileTools;
+import java.io.File;
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+
+// ---------- junit imports -----------------
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.openoffice.test.OfficeConnection;
+import static org.junit.Assert.*;
+
+
+
+public abstract class TestCase
+{
+
+ protected final XComponentContext getComponentContext()
+ {
+ return connection.getComponentContext();
+ }
+
+
+ public void before() throws java.lang.Exception
+ {
+ }
+
+
+ public void after() throws java.lang.Exception
+ {
+ }
+
+
+ /** returns the URL of a temporary file which can be used during the test.
+ *
+ * The file will be deleted when the process exits
+ * @return the URL of a temporary file
+ */
+ protected final String createTempFileURL() throws IOException
+ {
+ final File documentFile = java.io.File.createTempFile( "dbaccess_test", ".odb" ).getAbsoluteFile();
+ if ( documentFile.exists() )
+ {
+ documentFile.delete();
+ }
+ return FileHelper.getOOoCompatibleFileURL( documentFile.toURI().toURL().toString() );
+ }
+
+
+ /**
+ * copies the file given by URL to a temporary file
+ * @return
+ * the URL of the new file
+ */
+ protected final String copyToTempFile( String _sourceURL ) throws IOException
+ {
+ final String targetURL = createTempFileURL();
+ try
+ {
+ FileTools.copyFile( new File( new URI( _sourceURL ) ), new File( new URI( targetURL ) ) );
+ }
+ catch ( URISyntaxException e ) { }
+
+ return FileHelper.getOOoCompatibleFileURL( targetURL );
+ }
+
+
+ protected final XModel loadDocument( final String _docURL ) throws Exception
+ {
+ final XComponentLoader loader = UnoRuntime.queryInterface( XComponentLoader.class,
+ getMSF().createInstance( "com.sun.star.frame.Desktop" ) );
+ return UnoRuntime.queryInterface( XModel.class,
+ loader.loadComponentFromURL( _docURL, "_blank", 0, new PropertyValue[] {} ) );
+ }
+
+
+ /** invokes a given method on a given object, and assures a certain exception is caught
+ * @param _message
+ * is the message to print when the check fails
+ * @param _object
+ * is the object to invoke the method on
+ * @param _methodName
+ * is the name of the method to invoke
+ * @param _methodArgs
+ * are the arguments to pass to the method.
+ * @param _argClasses
+ * are the classes to assume for the arguments of the methods
+ * @param _expectedExceptionClass
+ * is the class of the exception to be caught. If this is null,
+ * it means that <em>no</em> exception must be throw by invoking the method.
+ */
+ private void assureException( final String _message, final Object _object, final String _methodName,
+ final Class[] _argClasses, final Object[] _methodArgs, final Class _expectedExceptionClass )
+ {
+ Class objectClass = _object.getClass();
+
+ boolean noExceptionAllowed = ( _expectedExceptionClass == null );
+
+ boolean caughtExpected = noExceptionAllowed;
+ try
+ {
+ Method method = objectClass.getMethod( _methodName, _argClasses );
+ method.invoke(_object, _methodArgs );
+ }
+ catch ( InvocationTargetException e )
+ {
+ caughtExpected = noExceptionAllowed
+ ? false
+ : ( e.getTargetException().getClass().equals( _expectedExceptionClass ) );
+ }
+ catch( Exception e )
+ {
+ caughtExpected = false;
+ }
+
+ assertTrue( _message, caughtExpected );
+ }
+
+ /** invokes a given method on a given object, and assures a certain exception is caught
+ * @param _message is the message to print when the check fails
+ * @param _object is the object to invoke the method on
+ * @param _methodName is the name of the method to invoke
+ * @param _methodArgs are the arguments to pass to the method. Those implicitly define
+ * the classes of the arguments of the method which is called.
+ * @param _expectedExceptionClass is the class of the exception to be caught. If this is null,
+ * it means that <em>no</em> exception must be throw by invoking the method.
+ */
+ private void assureException( final String _message, final Object _object, final String _methodName,
+ final Object[] _methodArgs, final Class _expectedExceptionClass )
+ {
+ Class[] argClasses = new Class[ _methodArgs.length ];
+ for ( int i=0; i<_methodArgs.length; ++i )
+ argClasses[i] = _methodArgs[i].getClass();
+ assureException( _message, _object, _methodName, argClasses, _methodArgs, _expectedExceptionClass );
+ }
+
+ /** invokes a given method on a given object, and assures a certain exception is caught
+ * @param _object is the object to invoke the method on
+ * @param _methodName is the name of the method to invoke
+ * @param _methodArgs are the arguments to pass to the method. Those implicitly define
+ * the classes of the arguments of the method which is called.
+ * @param _expectedExceptionClass is the class of the exception to be caught. If this is null,
+ * it means that <em>no</em> exception must be throw by invoking the method.
+ */
+ private void assureException( final Object _object, final String _methodName, final Object[] _methodArgs,
+ final Class _expectedExceptionClass )
+ {
+ assureException(
+ "did not catch the expected exception (" +
+ ( ( _expectedExceptionClass == null ) ? "none" : _expectedExceptionClass.getName() ) +
+ ") while calling " + _object.getClass().getName() + "." + _methodName,
+ _object, _methodName, _methodArgs, _expectedExceptionClass );
+ }
+
+ /** invokes a given method on a given object, and assures a certain exception is caught
+ * @param _object is the object to invoke the method on
+ * @param _methodName is the name of the method to invoke
+ * @param _methodArgs are the arguments to pass to the method
+ * @param _argClasses are the classes to assume for the arguments of the methods
+ * @param _expectedExceptionClass is the class of the exception to be caught. If this is null,
+ * it means that <em>no</em> exception must be throw by invoking the method.
+ */
+ protected void assureException( final Object _object, final String _methodName, final Class[] _argClasses,
+ final Object[] _methodArgs, final Class _expectedExceptionClass )
+ {
+ assureException(
+ "did not catch the expected exception (" +
+ ( ( _expectedExceptionClass == null ) ? "none" : _expectedExceptionClass.getName() ) +
+ ") while calling " + _object.getClass().getName() + "." + _methodName,
+ _object, _methodName, _argClasses, _methodArgs, _expectedExceptionClass );
+ }
+
+
+ @SuppressWarnings("unchecked")
+ protected void assureException( Object _object, Class _unoInterfaceClass, String _methodName, Object[] _methodArgs,
+ Class _expectedExceptionClass )
+ {
+ assureException( UnoRuntime.queryInterface( _unoInterfaceClass, _object ), _methodName,
+ _methodArgs, _expectedExceptionClass );
+ }
+
+
+ protected final XMultiServiceFactory getMSF()
+ {
+ return UnoRuntime.queryInterface(XMultiServiceFactory.class, connection.getComponentContext().getServiceManager());
+ }
+
+
+ // setup and close connections
+ @BeforeClass
+ public static void setUpConnection() throws Exception
+ {
+ connection.setUp();
+ }
+
+
+ @AfterClass
+ public static void tearDownConnection() throws InterruptedException, com.sun.star.uno.Exception
+ {
+ connection.tearDown();
+ }
+
+ private static final OfficeConnection connection = new OfficeConnection();
+
+}
diff --git a/dbaccess/qa/complex/dbaccess/UISettings.java b/dbaccess/qa/complex/dbaccess/UISettings.java
new file mode 100644
index 000000000..273d6b7a7
--- /dev/null
+++ b/dbaccess/qa/complex/dbaccess/UISettings.java
@@ -0,0 +1,132 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+package complex.dbaccess;
+
+import com.sun.star.awt.FontSlant;
+import com.sun.star.awt.TextAlign;
+import com.sun.star.beans.XPropertySet;
+import com.sun.star.container.XNameAccess;
+import com.sun.star.form.runtime.XFormController;
+import com.sun.star.frame.XController;
+import com.sun.star.sdb.application.DatabaseObject;
+import com.sun.star.uno.UnoRuntime;
+import com.sun.star.util.XCloseable;
+import connectivity.tools.CRMDatabase;
+
+// ---------- junit imports -----------------
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+
+public class UISettings extends TestCase
+{
+
+ /** verifies that aliases for inner queries work as expected
+ */
+ @Test
+ public void checkTableFormattingPersistence() throws java.lang.Exception
+ {
+ // create, load, and connect a DB doc
+ CRMDatabase database = new CRMDatabase( getMSF(), true );
+
+ // display a table
+ XFormController tableViewController = UnoRuntime.queryInterface( XFormController.class,
+ database.loadSubComponent( DatabaseObject.TABLE, "customers" ) );
+ XPropertySet tableControlModel = UnoRuntime.queryInterface( XPropertySet.class,
+ tableViewController.getCurrentControl().getModel() );
+
+ // change the table's formatting
+ tableControlModel.setPropertyValue( "FontName", "Andale Sans UI" );
+ tableControlModel.setPropertyValue( "FontHeight", Float.valueOf( 20 ) );
+ tableControlModel.setPropertyValue( "FontSlant", FontSlant.ITALIC );
+
+ String docURL = database.getDatabase().getModel().getURL();
+
+ // save close the database document
+ database.saveAndClose();
+
+ // load a copy of the document
+ // normally, it should be sufficient to load the same doc. However, there might be objects in the Java VM
+ // which are not yet freed, and which effectively hold the document alive. More precise: The document (|doc|)
+ // is certainly disposed, but other objects might hold a reference to one of the many other components
+ // around the database document, the data source, the connection, etc. As long as those objects are
+ // not cleaned up, the "database model impl" - the structure holding all document data - will
+ // stay alive, and subsequent requests to load the doc will just reuse it, without really loading it.
+ docURL = copyToTempFile( docURL );
+ loadDocument( docURL );
+ database = new CRMDatabase( getMSF(), docURL );
+
+ // display the table, again
+ tableViewController = UnoRuntime.queryInterface( XFormController.class,
+ database.loadSubComponent( DatabaseObject.TABLE, "customers" ) );
+ tableControlModel = UnoRuntime.queryInterface( XPropertySet.class,
+ tableViewController.getCurrentControl().getModel() );
+
+ // verify the properties
+ assertEquals( "wrong font name", "Andale Sans UI", tableControlModel.getPropertyValue( "FontName" ) );
+ assertEquals( "wrong font height", 20, ((Float)tableControlModel.getPropertyValue( "FontHeight" )).floatValue(), 0 );
+ assertEquals( "wrong font slant", FontSlant.ITALIC, tableControlModel.getPropertyValue( "FontSlant" ) );
+
+ // close the doc
+ database.saveAndClose();
+ }
+
+ /**
+ * checks whether query columns use the settings of the underlying table column, if they do not (yet) have own
+ * settings
+ */
+ @Test
+ public void checkTransparentQueryColumnSettings() throws java.lang.Exception
+ {
+ // create, load, and connect a DB doc
+ CRMDatabase database = new CRMDatabase( getMSF(), true );
+
+ // display a table
+ XController tableView = database.loadSubComponent( DatabaseObject.TABLE, "customers" );
+ XFormController tableViewController = UnoRuntime.queryInterface( XFormController.class,
+ tableView );
+ XNameAccess tableControlModel = UnoRuntime.queryInterface( XNameAccess.class,
+ tableViewController.getCurrentControl().getModel() );
+
+ // change the formatting of a table column
+ XPropertySet idColumn = UnoRuntime.queryInterface( XPropertySet.class, tableControlModel.getByName( "ID" ) );
+ assertTrue( "precondition not met: column already centered",
+ ((Short)idColumn.getPropertyValue( "Align" )).shortValue() != TextAlign.CENTER );
+ idColumn.setPropertyValue( "Align", TextAlign.CENTER );
+
+ // close the table data view
+ XCloseable closeSubComponent = UnoRuntime.queryInterface( XCloseable.class, tableView.getFrame() );
+ closeSubComponent.close( true );
+
+ // create a query based on that column
+ database.getDatabase().getDataSource().createQuery( "q_customers", "SELECT * FROM \"customers\"" );
+
+ // load this query, and verify the table column settings was propagated to the query column
+ XFormController queryViewController = UnoRuntime.queryInterface( XFormController.class,
+ database.loadSubComponent( DatabaseObject.QUERY, "q_customers" ) );
+ tableControlModel = UnoRuntime.queryInterface( XNameAccess.class,
+ queryViewController.getCurrentControl().getModel() );
+ idColumn = UnoRuntime.queryInterface( XPropertySet.class, tableControlModel.getByName( "ID" ) );
+
+ assertTrue( "table column alignment was not propagated to the query column",
+ ((Short)idColumn.getPropertyValue( "Align" )).shortValue() == TextAlign.CENTER );
+
+ // save close the database document
+ database.saveAndClose();
+ }
+}
diff --git a/dbaccess/qa/complex/dbaccess/makefile.mk b/dbaccess/qa/complex/dbaccess/makefile.mk
new file mode 100644
index 000000000..862a0ffc9
--- /dev/null
+++ b/dbaccess/qa/complex/dbaccess/makefile.mk
@@ -0,0 +1,93 @@
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This file incorporates work covered by the following license notice:
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed
+# with this work for additional information regarding copyright
+# ownership. The ASF licenses this file to you under the Apache
+# License, Version 2.0 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.apache.org/licenses/LICENSE-2.0 .
+#
+
+.IF "$(OOO_JUNIT_JAR)" == ""
+nothing .PHONY:
+ @echo -----------------------------------------------------
+ @echo - JUnit not available, not building anything
+ @echo -----------------------------------------------------
+.ELSE
+
+PRJ = ../../..
+PRJNAME = dbaccess
+TARGET = qa_complex_dbaccess
+PACKAGE = complex/dbaccess
+
+# --- Settings -----------------------------------------------------
+.INCLUDE: settings.mk
+
+#----- compile .java files -----------------------------------------
+
+JARFILES = OOoRunner.jar ridl.jar test.jar juh.jar unoil.jar ConnectivityTools.jar
+EXTRAJARFILES = $(OOO_JUNIT_JAR)
+
+#----- create a jar from compiled files ----------------------------
+
+JARTARGET = $(TARGET).jar
+
+#----- Java files --------------------------------------------------
+
+# here store only Files which contain a @Test
+JAVATESTFILES = \
+ ApplicationController.java \
+ Beamer.java \
+ DataSource.java \
+ DatabaseDocument.java \
+ Parser.java \
+ PropertyBag.java \
+ Query.java \
+ QueryInQuery.java \
+ RowSet.java \
+ SingleSelectQueryComposer.java \
+ UISettings.java \
+ CopyTableWizard.java \
+
+# put here all other files
+JAVAFILES = $(JAVATESTFILES) \
+ CRMBasedTestCase.java \
+ CopyTableInterActionHandler.java \
+ DatabaseApplication.java \
+ FileHelper.java \
+ RowSetEventListener.java \
+ TestCase.java \
+
+
+# Sample how to debug
+# JAVAIFLAGS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,address=9003,suspend=y
+
+# --- Targets ------------------------------------------------------
+
+.INCLUDE: target.mk
+
+ALL : ALLTAR
+
+# --- subsequent tests ---------------------------------------------
+
+.IF "$(OOO_SUBSEQUENT_TESTS)" != ""
+
+.INCLUDE: installationtest.mk
+
+ALLTAR : javatest
+
+ # Sample how to debug
+ # JAVAIFLAGS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,address=9003,suspend=y
+
+.END # "$(OOO_SUBSEQUENT_TESTS)" == ""
+
+.END # ELSE "$(OOO_JUNIT_JAR)" != ""
+
diff --git a/dbaccess/qa/extras/dialog-save.cxx b/dbaccess/qa/extras/dialog-save.cxx
new file mode 100644
index 000000000..212127d48
--- /dev/null
+++ b/dbaccess/qa/extras/dialog-save.cxx
@@ -0,0 +1,102 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <sal/config.h>
+#include <test/unoapi_test.hxx>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/lang/XComponent.hpp>
+#include <com/sun/star/frame/XStorable.hpp>
+#include <com/sun/star/document/XEmbeddedScripts.hpp>
+#include <com/sun/star/script/XStorageBasedLibraryContainer.hpp>
+#include <com/sun/star/script/XLibraryContainer.hpp>
+#include <com/sun/star/util/XModifiable.hpp>
+#include <com/sun/star/util/XCloseable.hpp>
+#include <com/sun/star/container/XHierarchicalNameAccess.hpp>
+
+#include <vcl/svapp.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+
+
+class DialogSaveTest : public UnoApiTest
+{
+public:
+ DialogSaveTest();
+
+ void test();
+
+ CPPUNIT_TEST_SUITE(DialogSaveTest);
+// Should we disable this test on MOX and WNT?
+// #if !defined(MACOSX) && !defined(_WIN32)
+ CPPUNIT_TEST(test);
+// #endif
+ CPPUNIT_TEST_SUITE_END();
+
+};
+
+
+DialogSaveTest::DialogSaveTest()
+ : UnoApiTest("/dbaccess/qa/extras/testdocuments")
+{
+}
+
+void DialogSaveTest::test()
+{
+ const OUString aFileName(m_directories.getURLFromWorkdir(u"CppunitTest/testDialogSave.odb"));
+ {
+ uno::Reference< lang::XComponent > xComponent = loadFromDesktop(aFileName);
+ uno::Reference< frame::XStorable > xDocStorable(xComponent, UNO_QUERY_THROW);
+ uno::Reference< document::XEmbeddedScripts > xDocScr(xComponent, UNO_QUERY_THROW);
+ uno::Reference< script::XStorageBasedLibraryContainer > xStorBasLib(xDocScr->getBasicLibraries());
+ CPPUNIT_ASSERT(xStorBasLib.is());
+ uno::Reference< script::XLibraryContainer > xBasLib(xStorBasLib, UNO_QUERY_THROW);
+ uno::Reference< script::XStorageBasedLibraryContainer > xStorDlgLib(xDocScr->getDialogLibraries());
+ CPPUNIT_ASSERT(xStorDlgLib.is());
+ uno::Reference< script::XLibraryContainer > xDlgLib(xStorDlgLib, UNO_QUERY_THROW);
+ static const OUStringLiteral sStandard(u"Standard");
+ xBasLib->loadLibrary(sStandard);
+ CPPUNIT_ASSERT(xBasLib->isLibraryLoaded(sStandard));
+ // the whole point of this test is to test the "save" operation
+ // when the Basic library is loaded, but not the Dialog library
+ CPPUNIT_ASSERT(!xDlgLib->isLibraryLoaded(sStandard));
+
+ // make some change to enable a save
+ // uno::Reference< document::XDocumentPropertiesSupplier > xDocPropSuppl(xComponent, UNO_QUERY_THROW);
+ // uno::Reference< document::XDocumentPropertiesSupplier > xDocProps(xDocPropSuppl->getDocumentProperties());
+ // CPPUNIT_ASSERT(xDocProps.is());
+ // xDocProps.setTitle(xDocProps.getTitle() + " suffix");
+ uno::Reference< util::XModifiable > xDocMod(xComponent, UNO_QUERY_THROW);
+ xDocMod->setModified(true);
+
+ // now save; the code path to exercise in this test is the "store to same location"
+ // do *not* change to store(As|To|URL)!
+ xDocStorable->store();
+
+ // close
+ uno::Reference< util::XCloseable > xDocCloseable(xComponent, UNO_QUERY_THROW);
+ xDocCloseable->close(false);
+
+ // All our uno::References are (should?) be invalid now -> let them go out of scope
+ }
+ {
+ uno::Sequence<uno::Any> args{ uno::Any(aFileName) };
+ Reference<container::XHierarchicalNameAccess> xHNA(getMultiServiceFactory()->createInstanceWithArguments("com.sun.star.packages.Package", args), UNO_QUERY_THROW);
+ Reference< beans::XPropertySet > xPS(xHNA->getByHierarchicalName("Dialogs/Standard/Dialog1.xml"), UNO_QUERY_THROW);
+ sal_Int64 nSize = 0;
+ CPPUNIT_ASSERT(xPS->getPropertyValue("Size") >>= nSize);
+ CPPUNIT_ASSERT(nSize != 0);
+ }
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(DialogSaveTest);
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/qa/extras/empty-stdlib-save.cxx b/dbaccess/qa/extras/empty-stdlib-save.cxx
new file mode 100644
index 000000000..440fc19d4
--- /dev/null
+++ b/dbaccess/qa/extras/empty-stdlib-save.cxx
@@ -0,0 +1,114 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <sal/config.h>
+#include <test/unoapi_test.hxx>
+#include <com/sun/star/lang/XComponent.hpp>
+#include <com/sun/star/frame/XStorable.hpp>
+#include <com/sun/star/document/XEmbeddedScripts.hpp>
+#include <com/sun/star/script/XStorageBasedLibraryContainer.hpp>
+#include <com/sun/star/script/XLibraryContainer.hpp>
+#include <com/sun/star/util/XCloseable.hpp>
+#include <com/sun/star/container/XHierarchicalNameAccess.hpp>
+
+#include <vcl/svapp.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+
+
+class DialogSaveTest : public UnoApiTest
+{
+public:
+ DialogSaveTest();
+
+ void test();
+
+ CPPUNIT_TEST_SUITE(DialogSaveTest);
+// Should we disable this test on MOX and WNT?
+// #if !defined(MACOSX) && !defined(_WIN32)
+ CPPUNIT_TEST(test);
+// #endif
+ CPPUNIT_TEST_SUITE_END();
+
+};
+
+
+DialogSaveTest::DialogSaveTest()
+ : UnoApiTest("/dbaccess/qa/extras/testdocuments")
+{
+}
+
+void DialogSaveTest::test()
+{
+ const OUString aFileName(m_directories.getURLFromWorkdir(u"CppunitTest/testEmptyStdlibSave.odb"));
+ {
+ uno::Reference< lang::XComponent > xComponent = loadFromDesktop(aFileName);
+ uno::Reference< frame::XStorable > xDocStorable(xComponent, UNO_QUERY_THROW);
+ uno::Reference< document::XEmbeddedScripts > xDocScr(xComponent, UNO_QUERY_THROW);
+ uno::Reference< script::XStorageBasedLibraryContainer > xStorBasLib(xDocScr->getBasicLibraries());
+ CPPUNIT_ASSERT(xStorBasLib.is());
+ uno::Reference< script::XLibraryContainer > xBasLib(xStorBasLib, UNO_QUERY_THROW);
+ uno::Reference< script::XStorageBasedLibraryContainer > xStorDlgLib(xDocScr->getDialogLibraries());
+ CPPUNIT_ASSERT(xStorDlgLib.is());
+ uno::Reference< script::XLibraryContainer > xDlgLib(xStorDlgLib, UNO_QUERY_THROW);
+ static const OUStringLiteral sStandard(u"Standard");
+ xBasLib->loadLibrary(sStandard);
+ xDlgLib->loadLibrary(sStandard);
+ CPPUNIT_ASSERT(xBasLib->isLibraryLoaded(sStandard));
+ CPPUNIT_ASSERT(xDlgLib->isLibraryLoaded(sStandard));
+
+ Any a;
+ uno::Reference< container::XNameContainer > xI;
+
+ a = xBasLib->getByName(sStandard);
+ a >>= xI;
+ CPPUNIT_ASSERT(xI.is());
+ xI->removeByName("Raralix");
+
+ a = xDlgLib->getByName(sStandard);
+ a >>= xI;
+ CPPUNIT_ASSERT(xI.is());
+ xI->removeByName("Dialog1");
+
+ // uno::Reference< util::XModifiable > xDlgMod(xDlgLib, UNO_QUERY_THROW);
+ // xDlgMod->setModified(sal_True);
+
+ // uno::Reference< util::XModifiable > xScrMod(xDocScr, UNO_QUERY_THROW);
+ // xScrMod->setModified(sal_True);
+
+ // uno::Reference< util::XModifiable > xDocMod(xComponent, UNO_QUERY_THROW);
+ // std::cerr << "** Modified: " << static_cast<bool>(xDocMod->isModified()) << std::endl;
+ // xDocMod->setModified(sal_True);
+ // std::cerr << "** Modified: " << static_cast<bool>(xDocMod->isModified()) << std::endl;
+ // CPPUNIT_ASSERT(xDocMod->isModified());
+
+ // now save; the code path to exercise in this test is the "store to same location"
+ // do *not* change to store(As|To|URL)!
+ xDocStorable->store();
+
+ // close
+ uno::Reference< util::XCloseable > xDocCloseable(xComponent, UNO_QUERY_THROW);
+ xDocCloseable->close(false);
+
+ // All our uno::References are (should?) be invalid now -> let them go out of scope
+ }
+ {
+ uno::Sequence<uno::Any> args{ uno::Any(aFileName) };
+ Reference<container::XHierarchicalNameAccess> xHNA(getMultiServiceFactory()->createInstanceWithArguments("com.sun.star.packages.Package", args), UNO_QUERY_THROW);
+ CPPUNIT_ASSERT(!xHNA->hasByHierarchicalName("Basic/Standard"));
+ CPPUNIT_ASSERT(!xHNA->hasByHierarchicalName("Dialogs/Standard"));
+ }
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(DialogSaveTest);
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/qa/extras/hsql_schema_import.cxx b/dbaccess/qa/extras/hsql_schema_import.cxx
new file mode 100644
index 000000000..f5f34d38b
--- /dev/null
+++ b/dbaccess/qa/extras/hsql_schema_import.cxx
@@ -0,0 +1,210 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <fbcreateparser.hxx>
+#include <columndef.hxx>
+#include <cppunit/plugin/TestPlugIn.h>
+#include <com/sun/star/sdbc/DataType.hpp>
+#include <cppunit/TestFixture.h>
+#include <cppunit/extensions/HelperMacros.h>
+
+using namespace dbahsql;
+
+namespace
+{
+constexpr std::size_t operator"" _z(unsigned long long n) { return n; }
+
+const ColumnDefinition* lcl_findByType(const std::vector<ColumnDefinition>& columns,
+ sal_Int32 nType)
+{
+ for (const auto& column : columns)
+ {
+ if (column.getDataType() == nType)
+ return &column;
+ }
+ return nullptr;
+}
+}
+
+class HsqlSchemaImportTest : public CppUnit::TestFixture
+{
+public:
+ void testIntegerPrimaryKeyNotNull();
+ void testVarcharWithParam();
+ void testVarcharWithoutParam();
+ void testNumericWithTwoParam();
+ void testIntegerAutoincremental();
+ void testTimestampWithParam();
+ void testDefaultValueNow();
+ void testEvilNullColumnName();
+ // TODO testForeign, testDecomposer
+
+ CPPUNIT_TEST_SUITE(HsqlSchemaImportTest);
+
+ CPPUNIT_TEST(testIntegerPrimaryKeyNotNull);
+ CPPUNIT_TEST(testVarcharWithParam);
+ CPPUNIT_TEST(testVarcharWithoutParam);
+ CPPUNIT_TEST(testNumericWithTwoParam);
+ CPPUNIT_TEST(testIntegerAutoincremental);
+ CPPUNIT_TEST(testTimestampWithParam);
+ CPPUNIT_TEST(testDefaultValueNow);
+ CPPUNIT_TEST(testEvilNullColumnName);
+
+ CPPUNIT_TEST_SUITE_END();
+};
+
+void HsqlSchemaImportTest::testIntegerPrimaryKeyNotNull()
+{
+ FbCreateStmtParser aCreateParser;
+ aCreateParser.parse(u"CREATE CACHED TABLE \"myTable\"(\"id\" INTEGER NOT NULL PRIMARY KEY)");
+
+ CPPUNIT_ASSERT_EQUAL(OUString{ "\"myTable\"" }, aCreateParser.getTableName());
+ const auto& columns = aCreateParser.getColumnDef();
+ CPPUNIT_ASSERT_EQUAL(1_z, columns.size());
+ const auto& column = columns.at(0);
+ CPPUNIT_ASSERT_EQUAL(OUString{ "\"id\"" }, column.getName());
+ CPPUNIT_ASSERT_EQUAL(css::sdbc::DataType::INTEGER, column.getDataType());
+ CPPUNIT_ASSERT(column.isPrimaryKey());
+ CPPUNIT_ASSERT(!column.isNullable());
+ CPPUNIT_ASSERT(!column.isAutoIncremental());
+}
+
+void HsqlSchemaImportTest::testVarcharWithParam()
+{
+ FbCreateStmtParser aCreateParser;
+ aCreateParser.parse(
+ u"CREATE CACHED TABLE \"myTable\"(\"id\" INTEGER NOT NULL PRIMARY KEY, \"myText\" "
+ "VARCHAR(50))");
+
+ const auto& columns = aCreateParser.getColumnDef();
+ CPPUNIT_ASSERT_EQUAL(2_z, columns.size());
+ const ColumnDefinition* colVarchar = lcl_findByType(columns, css::sdbc::DataType::VARCHAR);
+ CPPUNIT_ASSERT(colVarchar != nullptr);
+ const auto& params = colVarchar->getParams();
+ CPPUNIT_ASSERT_EQUAL(1_z, params.size());
+ constexpr sal_Int32 nParamExpected = 50;
+ CPPUNIT_ASSERT_EQUAL(nParamExpected, params.at(0)); // VARCHAR(50)
+}
+
+/**
+ * Special case:
+ * HSQLDB might define a column VARCHAR without parameter. With Firebird
+ * dialect, this is forbidden, so a default parameter has to be appended:
+ **/
+void HsqlSchemaImportTest::testVarcharWithoutParam()
+{
+ FbCreateStmtParser aCreateParser;
+ aCreateParser.parse(
+ u"CREATE CACHED TABLE \"myTable\"(\"id\" INTEGER NOT NULL PRIMARY KEY, \"myText\" "
+ "VARCHAR)");
+
+ const auto& columns = aCreateParser.getColumnDef();
+ CPPUNIT_ASSERT_EQUAL(2_z, columns.size());
+ const ColumnDefinition* colVarchar = lcl_findByType(columns, css::sdbc::DataType::VARCHAR);
+ CPPUNIT_ASSERT(colVarchar != nullptr);
+ const auto& params = colVarchar->getParams();
+ CPPUNIT_ASSERT_EQUAL(1_z, params.size()); // parameter generated
+}
+
+void HsqlSchemaImportTest::testNumericWithTwoParam()
+{
+ FbCreateStmtParser aCreateParser;
+ aCreateParser.parse(
+ u"CREATE CACHED TABLE \"myTable\"(\"id\" INTEGER NOT NULL PRIMARY KEY, \"Betrag\" "
+ "NUMERIC(8,2))");
+
+ const auto& columns = aCreateParser.getColumnDef();
+ CPPUNIT_ASSERT_EQUAL(2_z, columns.size());
+
+ const ColumnDefinition* colNumeric = lcl_findByType(columns, css::sdbc::DataType::NUMERIC);
+ CPPUNIT_ASSERT(colNumeric != nullptr);
+ const auto& params = colNumeric->getParams();
+ CPPUNIT_ASSERT_EQUAL(2_z, params.size());
+
+ constexpr sal_Int32 nPrecision = 8;
+ constexpr sal_Int32 nScale = 2;
+ CPPUNIT_ASSERT_EQUAL(nPrecision, params.at(0));
+ CPPUNIT_ASSERT_EQUAL(nScale, params.at(1));
+}
+
+void HsqlSchemaImportTest::testIntegerAutoincremental()
+{
+ FbCreateStmtParser aCreateParser;
+ aCreateParser.parse(
+ u"CREATE CACHED TABLE \"myTable\"(\"id\" INTEGER NOT NULL PRIMARY KEY GENERATED "
+ "BY DEFAULT AS IDENTITY(START WITH 0), \"myText\" VARCHAR(50))");
+
+ const auto& columns = aCreateParser.getColumnDef();
+ const auto column = columns.at(0);
+ CPPUNIT_ASSERT_EQUAL(css::sdbc::DataType::INTEGER, column.getDataType());
+ CPPUNIT_ASSERT(column.isAutoIncremental());
+ CPPUNIT_ASSERT(column.isPrimaryKey());
+ CPPUNIT_ASSERT(!column.isNullable());
+}
+
+/**
+ * Special case:
+ * Hsqldb might use one parameter for defining column with type TIMESTAMP.
+ * With Firebird this is illegal.
+ */
+void HsqlSchemaImportTest::testTimestampWithParam()
+{
+ FbCreateStmtParser aCreateParser;
+ aCreateParser.parse(
+ u"CREATE CACHED TABLE \"myTable\"(\"id\" INTEGER NOT NULL PRIMARY KEY, \"myText\" "
+ "TIMESTAMP(0))");
+
+ const auto& columns = aCreateParser.getColumnDef();
+ const ColumnDefinition* colTimeStamp = lcl_findByType(columns, css::sdbc::DataType::TIMESTAMP);
+
+ CPPUNIT_ASSERT(colTimeStamp != nullptr);
+
+ // instead of asserting parameter size, look at the deparsed string,
+ // because it's Firebird specific
+ OUString fbSql = aCreateParser.compose();
+ CPPUNIT_ASSERT(fbSql.indexOf("0") < 0); //does not contain
+}
+
+/**
+ * Special case:
+ * HSQLDB uses keyword NOW without quotes. Firebird uses single quotes 'NOW'
+ */
+void HsqlSchemaImportTest::testDefaultValueNow()
+{
+ FbCreateStmtParser aCreateParser;
+ aCreateParser.parse(
+ u"CREATE CACHED TABLE \"myTable\"(\"id\" INTEGER NOT NULL PRIMARY KEY, \"myDate\" "
+ "TIMESTAMP DEFAULT NOW)");
+
+ const auto& columns = aCreateParser.getColumnDef();
+ const ColumnDefinition* colTimeStamp = lcl_findByType(columns, css::sdbc::DataType::TIMESTAMP);
+
+ CPPUNIT_ASSERT(colTimeStamp != nullptr);
+ CPPUNIT_ASSERT_EQUAL(OUString{ "NOW" }, colTimeStamp->getDefault()); // parsed NOW
+ OUString fbSql = aCreateParser.compose();
+ CPPUNIT_ASSERT(fbSql.indexOf("\'NOW\'") > 0); // composed 'NOW'
+}
+
+void HsqlSchemaImportTest::testEvilNullColumnName()
+{
+ FbCreateStmtParser aCreateParser;
+ aCreateParser.parse(u"CREATE CACHED TABLE \"myTable\"(\"id\" INTEGER NOT NULL PRIMARY KEY, "
+ "\"myEvilNOT NULLName\" "
+ "VARCHAR(20))");
+
+ const auto& columns = aCreateParser.getColumnDef();
+ CPPUNIT_ASSERT_EQUAL(2_z, columns.size());
+ const ColumnDefinition* colVarchar = lcl_findByType(columns, css::sdbc::DataType::VARCHAR);
+ CPPUNIT_ASSERT(colVarchar != nullptr);
+ CPPUNIT_ASSERT(colVarchar->isNullable());
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(HsqlSchemaImportTest);
+
+CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/dbaccess/qa/extras/macros-test.cxx b/dbaccess/qa/extras/macros-test.cxx
new file mode 100644
index 000000000..dee5919c3
--- /dev/null
+++ b/dbaccess/qa/extras/macros-test.cxx
@@ -0,0 +1,51 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <sal/config.h>
+#include <test/unoapi_test.hxx>
+#include <com/sun/star/util/XCloseable.hpp>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+
+#if !defined(MACOSX) && !defined(_WIN32)
+
+class DBAccessTest : public UnoApiTest
+{
+public:
+ DBAccessTest();
+
+ void test();
+
+ CPPUNIT_TEST_SUITE(DBAccessTest);
+ CPPUNIT_TEST(test);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+DBAccessTest::DBAccessTest()
+ : UnoApiTest("/dbaccess/qa/extras/testdocuments")
+{
+}
+
+void DBAccessTest::test()
+{
+ OUString aFileName;
+ createFileURL(u"testdb.odb", aFileName);
+ uno::Reference<lang::XComponent> xComponent = loadFromDesktop(aFileName);
+ uno::Reference<util::XCloseable> xDocCloseable(xComponent, UNO_QUERY_THROW);
+ xDocCloseable->close(false);
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(DBAccessTest);
+
+#endif
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/qa/extras/nolib-save.cxx b/dbaccess/qa/extras/nolib-save.cxx
new file mode 100644
index 000000000..59fee844f
--- /dev/null
+++ b/dbaccess/qa/extras/nolib-save.cxx
@@ -0,0 +1,104 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <sal/config.h>
+#include <test/unoapi_test.hxx>
+#include <com/sun/star/lang/XComponent.hpp>
+#include <com/sun/star/frame/XStorable.hpp>
+#include <com/sun/star/document/XEmbeddedScripts.hpp>
+#include <com/sun/star/script/XStorageBasedLibraryContainer.hpp>
+#include <com/sun/star/script/XLibraryContainer.hpp>
+#include <com/sun/star/util/XCloseable.hpp>
+#include <com/sun/star/container/XHierarchicalNameAccess.hpp>
+
+#include <vcl/svapp.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+
+
+class DialogSaveTest : public UnoApiTest
+{
+public:
+ DialogSaveTest();
+
+ void test();
+
+ CPPUNIT_TEST_SUITE(DialogSaveTest);
+// Should we disable this test on MOX and WNT?
+// #if !defined(MACOSX) && !defined(_WIN32)
+ CPPUNIT_TEST(test);
+// #endif
+ CPPUNIT_TEST_SUITE_END();
+
+};
+
+
+DialogSaveTest::DialogSaveTest()
+ : UnoApiTest("/dbaccess/qa/extras/testdocuments")
+{
+}
+
+void DialogSaveTest::test()
+{
+ const OUString aFileName(m_directories.getURLFromWorkdir(u"CppunitTest/testNolibSave.odb"));
+ {
+ uno::Reference< lang::XComponent > xComponent = loadFromDesktop(aFileName);
+ uno::Reference< frame::XStorable > xDocStorable(xComponent, UNO_QUERY_THROW);
+ uno::Reference< document::XEmbeddedScripts > xDocScr(xComponent, UNO_QUERY_THROW);
+ uno::Reference< script::XStorageBasedLibraryContainer > xStorBasLib(xDocScr->getBasicLibraries());
+ CPPUNIT_ASSERT(xStorBasLib.is());
+ uno::Reference< script::XLibraryContainer > xBasLib(xStorBasLib, UNO_QUERY_THROW);
+ uno::Reference< script::XStorageBasedLibraryContainer > xStorDlgLib(xDocScr->getDialogLibraries());
+ CPPUNIT_ASSERT(xStorDlgLib.is());
+ uno::Reference< script::XLibraryContainer > xDlgLib(xStorDlgLib, UNO_QUERY_THROW);
+ static const OUStringLiteral sStandard(u"Standard");
+ xBasLib->loadLibrary(sStandard);
+ xDlgLib->loadLibrary(sStandard);
+ CPPUNIT_ASSERT(xBasLib->isLibraryLoaded(sStandard));
+ CPPUNIT_ASSERT(xDlgLib->isLibraryLoaded(sStandard));
+
+ xBasLib->removeLibrary(sStandard);
+ xDlgLib->removeLibrary(sStandard);
+
+ // uno::Reference< util::XModifiable > xDlgMod(xDlgLib, UNO_QUERY_THROW);
+ // xDlgMod->setModified(sal_True);
+
+ // uno::Reference< util::XModifiable > xScrMod(xDocScr, UNO_QUERY_THROW);
+ // xScrMod->setModified(sal_True);
+
+ // uno::Reference< util::XModifiable > xDocMod(xComponent, UNO_QUERY_THROW);
+ // std::cerr << "** Modified: " << static_cast<bool>(xDocMod->isModified()) << std::endl;
+ // xDocMod->setModified(sal_True);
+ // std::cerr << "** Modified: " << static_cast<bool>(xDocMod->isModified()) << std::endl;
+ // CPPUNIT_ASSERT(xDocMod->isModified());
+
+ // now save; the code path to exercise in this test is the "store to same location"
+ // do *not* change to store(As|To|URL)!
+ xDocStorable->store();
+
+ // close
+ uno::Reference< util::XCloseable > xDocCloseable(xComponent, UNO_QUERY_THROW);
+ xDocCloseable->close(false);
+
+ // All our uno::References are (should?) be invalid now -> let them go out of scope
+ }
+ {
+ uno::Sequence<uno::Any> args{ uno::Any(aFileName) };
+ Reference<container::XHierarchicalNameAccess> xHNA(getMultiServiceFactory()->createInstanceWithArguments("com.sun.star.packages.Package", args), UNO_QUERY_THROW);
+ CPPUNIT_ASSERT(!xHNA->hasByHierarchicalName("Basic/Standard"));
+ CPPUNIT_ASSERT(!xHNA->hasByHierarchicalName("Dialogs/Standard"));
+ }
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(DialogSaveTest);
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/qa/extras/rowsetclones.cxx b/dbaccess/qa/extras/rowsetclones.cxx
new file mode 100644
index 000000000..d83d160ca
--- /dev/null
+++ b/dbaccess/qa/extras/rowsetclones.cxx
@@ -0,0 +1,133 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <sal/config.h>
+#include <test/unoapi_test.hxx>
+#include <com/sun/star/sdb/XOfficeDatabaseDocument.hpp>
+#include <com/sun/star/lang/XComponent.hpp>
+#include <com/sun/star/sdb/CommandType.hpp>
+#include <com/sun/star/sdbc/XConnection.hpp>
+#include <com/sun/star/sdbc/XResultSet.hpp>
+#include <com/sun/star/sdbc/XRow.hpp>
+#include <com/sun/star/sdbcx/XRowLocate.hpp>
+#include <com/sun/star/sdbc/XRowSet.hpp>
+#include <com/sun/star/sdb/XResultSetAccess.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::sdb;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::sdbcx;
+
+class RowSetClones : public UnoApiTest
+{
+public:
+ RowSetClones();
+
+ void test();
+
+ CPPUNIT_TEST_SUITE(RowSetClones);
+ CPPUNIT_TEST(test);
+ CPPUNIT_TEST_SUITE_END();
+
+};
+
+
+RowSetClones::RowSetClones()
+ : UnoApiTest("")
+{
+}
+
+void RowSetClones::test()
+{
+ const OUString sFilePath(m_directories.getURLFromWorkdir(u"CppunitTest/RowSetClones.odb"));
+
+ uno::Reference< lang::XComponent > xComponent (loadFromDesktop(sFilePath));
+ uno::Reference< XOfficeDatabaseDocument > xDocument(xComponent, UNO_QUERY_THROW);
+
+ uno::Reference< XDataSource > xDataSource = xDocument->getDataSource();
+ CPPUNIT_ASSERT(xDataSource.is());
+
+ uno::Reference< XConnection > xConnection = xDataSource->getConnection("","");
+ CPPUNIT_ASSERT(xConnection.is());
+
+ uno::Reference< XRowSet > xRowSet (getMultiServiceFactory()->createInstance("com.sun.star.sdb.RowSet" ), UNO_QUERY);
+ CPPUNIT_ASSERT(xRowSet.is());
+ uno::Reference< XPropertySet > rowSetProperties ( xRowSet, UNO_QUERY );
+ CPPUNIT_ASSERT(rowSetProperties.is());
+ rowSetProperties->setPropertyValue("Command", Any(OUString("SELECT * FROM Assets ORDER BY AssetID")));
+ rowSetProperties->setPropertyValue("CommandType", Any(CommandType::COMMAND));
+ rowSetProperties->setPropertyValue("ActiveConnection", Any(xConnection));
+
+ xRowSet->execute();
+ uno::Reference< XResultSet > xResultSet = xRowSet;
+ CPPUNIT_ASSERT(xResultSet.is());
+ // always starts at BeforeFirst position
+ CPPUNIT_ASSERT(xResultSet->isBeforeFirst());
+ CPPUNIT_ASSERT(xResultSet->next());
+ CPPUNIT_ASSERT(xResultSet->isFirst());
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(1), xResultSet->getRow());
+
+ uno::Reference< XRow > xRow(xResultSet, UNO_QUERY);
+ CPPUNIT_ASSERT(xRow.is());
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(1), xRow->getInt(1));
+
+ uno::Reference< XResultSetAccess > xResultSetAccess(xResultSet, UNO_QUERY);
+ CPPUNIT_ASSERT(xResultSetAccess.is());
+ uno::Reference< XResultSet > xResultSetClone = xResultSetAccess->createResultSet();
+ CPPUNIT_ASSERT(xResultSetClone.is());
+
+ uno::Reference< XRow > xRowClone(xResultSetClone, UNO_QUERY);
+ CPPUNIT_ASSERT(xRowClone.is());
+
+ // the clone starts at same position as what it is cloned from,
+ // and does not move its source.
+ CPPUNIT_ASSERT(xResultSetClone->isFirst());
+ CPPUNIT_ASSERT(xResultSet->isFirst());
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(1), xResultSet->getRow());
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(1), xResultSetClone->getRow());
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(1), xRow->getInt(1));
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(1), xRowClone->getInt(1));
+
+ // if we move the source, the clone does not move
+ CPPUNIT_ASSERT(xResultSet->next());
+ CPPUNIT_ASSERT(xResultSetClone->isFirst());
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(2), xResultSet->getRow());
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(1), xResultSetClone->getRow());
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(2), xRow->getInt(1));
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(1), xRowClone->getInt(1));
+
+ CPPUNIT_ASSERT(xResultSet->last());
+ CPPUNIT_ASSERT(xResultSet->isLast());
+ CPPUNIT_ASSERT(xResultSetClone->isFirst());
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(1), xRowClone->getInt(1));
+
+ // and the other way round
+ CPPUNIT_ASSERT(xResultSet->first());
+ CPPUNIT_ASSERT(xResultSetClone->next());
+ CPPUNIT_ASSERT(xResultSet->isFirst());
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(2), xResultSetClone->getRow());
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(2), xRowClone->getInt(1));
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(1), xRow->getInt(1));
+
+ CPPUNIT_ASSERT(xResultSetClone->last());
+ CPPUNIT_ASSERT(xResultSetClone->isLast());
+ CPPUNIT_ASSERT(xResultSet->isFirst());
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(1), xRow->getInt(1));
+
+ closeDocument(uno::Reference<lang::XComponent>(xDocument, uno::UNO_QUERY));
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(RowSetClones);
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/qa/extras/testdocuments/RowSetClones.odb b/dbaccess/qa/extras/testdocuments/RowSetClones.odb
new file mode 100644
index 000000000..91ed328ac
--- /dev/null
+++ b/dbaccess/qa/extras/testdocuments/RowSetClones.odb
Binary files differ
diff --git a/dbaccess/qa/extras/testdocuments/fdo84315.odb b/dbaccess/qa/extras/testdocuments/fdo84315.odb
new file mode 100644
index 000000000..0513ff587
--- /dev/null
+++ b/dbaccess/qa/extras/testdocuments/fdo84315.odb
Binary files differ
diff --git a/dbaccess/qa/extras/testdocuments/testDialogSave.odb b/dbaccess/qa/extras/testdocuments/testDialogSave.odb
new file mode 100644
index 000000000..d72531253
--- /dev/null
+++ b/dbaccess/qa/extras/testdocuments/testDialogSave.odb
Binary files differ
diff --git a/dbaccess/qa/extras/testdocuments/testdb.odb b/dbaccess/qa/extras/testdocuments/testdb.odb
new file mode 100644
index 000000000..038e998e6
--- /dev/null
+++ b/dbaccess/qa/extras/testdocuments/testdb.odb
Binary files differ
diff --git a/dbaccess/qa/python/fdo84315.py b/dbaccess/qa/python/fdo84315.py
new file mode 100644
index 000000000..f58b16f51
--- /dev/null
+++ b/dbaccess/qa/python/fdo84315.py
@@ -0,0 +1,76 @@
+#! /usr/bin/env python
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+import os
+import unittest
+from collections import deque
+import unohelper
+from org.libreoffice.unotest import UnoInProcess
+
+class Fdo84315(unittest.TestCase):
+
+ @classmethod
+ def setUpClass(cls):
+ cls._uno = UnoInProcess()
+ cls._uno.setUp()
+ workdir = os.environ[ "WORKDIR_FOR_BUILD" ]
+ cls._xDoc = cls._uno.openDocFromAbsolutePath(workdir + "/CppunitTest/fdo84315.odb")
+
+ @classmethod
+ def tearDownClass(cls):
+ cls._uno.tearDown()
+
+ def __test_Query(self, column_name, expected_type, xResultset):
+ self.assertTrue(xResultset)
+ xMeta = xResultset.MetaData
+ self.assertEqual(xMeta.ColumnCount, 1)
+ self.assertEqual(xResultset.findColumn(column_name), 1)
+ self.assertEqual(xMeta.getColumnName(1), column_name)
+ self.assertEqual(xMeta.getColumnType(1), expected_type)
+ return xMeta
+
+ def __test_ResultSetInteger(self, xResultset, expected_values):
+ while xResultset.next():
+ self.assertEqual(xResultset.getInt(1), expected_values.popleft())
+ self.assertEqual(len(expected_values), 0)
+
+ def __test_ResultSetString(self, xResultset, expected_values):
+ while xResultset.next():
+ self.assertEqual(xResultset.getString(1), expected_values.popleft())
+ self.assertEqual(len(expected_values), 0)
+
+ def test_fdo84315(self):
+ xDoc = self.__class__._xDoc
+ xDataSource = xDoc.DataSource
+ xCon = xDataSource.getConnection('','')
+ xStatement = xCon.createStatement()
+
+ NUMERIC = 2
+ VAR_CHAR = 12
+ INTEGER = 4
+
+ xResultset = xStatement.executeQuery('SELECT "count" FROM "test_table"')
+ expected_values = deque([42, 4711])
+ xMeta = self.__test_Query('count', NUMERIC, xResultset)
+ self.__test_ResultSetInteger(xResultset, expected_values)
+
+ xResultset = xStatement.executeQuery('SELECT "name" FROM "test_table"')
+ expected_values = deque(['foo', 'bar'])
+ xMeta = self.__test_Query('name', VAR_CHAR, xResultset)
+ self.__test_ResultSetString(xResultset, expected_values)
+
+ xResultset = xStatement.executeQuery('SELECT "id" FROM "test_table"')
+ expected_values = deque([0, 1])
+ xMeta = self.__test_Query('id', INTEGER, xResultset)
+ self.__test_ResultSetInteger(xResultset, expected_values)
+
+ xCon.dispose()
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/dbaccess/qa/unit/data/dbaccess-dialogs-test.txt b/dbaccess/qa/unit/data/dbaccess-dialogs-test.txt
new file mode 100644
index 000000000..3d0270889
--- /dev/null
+++ b/dbaccess/qa/unit/data/dbaccess-dialogs-test.txt
@@ -0,0 +1,111 @@
+# -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+# This file contains all dialogs that the unit tests in the module
+# will work on if it is in script mode. It will read one-by-one,
+# try to open it and create a screenshot that will be saved in
+# workdir/screenshots using the pattern of the ui-file name.
+#
+# Syntax:
+# - empty lines are allowed
+# - lines starting with '#' are treated as comment
+# - all other lines should contain a *.ui filename in the same
+# notation as in the dialog constructors (see code)
+
+#
+# The 'known' dialogs which have a hard-coded representation
+# in registerKnownDialogsByID/createDialogByID
+#
+
+# No known dialogs in dbaccess for now
+
+#
+# Dialogs without a hard-coded representation. These will
+# be visualized using a fallback based on weld::Builder
+#
+
+# currently deactivated, leads to problems and the test to not work
+# This is typically a hint that these should be hard-coded in the
+# test case since they need some document and model data to work
+# dbaccess/ui/joindialog.ui <- not calling ORelationControl::lateInit for
+# DlgQryJoin::m_xTableControl member OTableListBoxControl::m_pRC_Tables leaves its
+# BrowseBox::mvCols empty, causing "implicit conversion from type 'int' of value -1 (32-bit,
+# signed) to type 'sal_uInt16' (aka 'unsigned short') changed the value to 65535 (16-bit,
+# unsigned)" when calling
+# GetColumnId( static_cast<sal_uInt16>(mvCols.size()) - 1 );
+# in BrowseBox::AutoSizeLastColumn (svtools/source/brwbox/brwbox1.cxx) with Clang
+# -fsanitize=implicit-signed-integer-truncation
+# dbaccess/ui/relationdialog.ui <- not calling ORelationControl::lateInit for
+# ORelationDialog::m_xTableControl member OTableListBoxControl::m_pRC_Tables leaves its
+# BrowseBox::mvCols empty, causing "implicit conversion from type 'int' of value -1 (32-bit,
+# signed) to type 'sal_uInt16' (aka 'unsigned short') changed the value to 65535 (16-bit,
+# unsigned)" when calling
+# GetColumnId( static_cast<sal_uInt16>(mvCols.size()) - 1 );
+# in BrowseBox::AutoSizeLastColumn (svtools/source/brwbox/brwbox1.cxx) with Clang
+# -fsanitize=implicit-signed-integer-truncation
+
+dbaccess/ui/advancedsettingsdialog.ui
+dbaccess/ui/admindialog.ui
+dbaccess/ui/fielddialog.ui
+dbaccess/ui/useradmindialog.ui
+dbaccess/ui/mysqlnativesettings.ui
+dbaccess/ui/textpage.ui
+dbaccess/ui/applycolpage.ui
+dbaccess/ui/copytablepage.ui
+dbaccess/ui/namematchingpage.ui
+dbaccess/ui/typeselectpage.ui
+dbaccess/ui/specialsettingspage.ui
+dbaccess/ui/generatedvaluespage.ui
+dbaccess/ui/ldapconnectionpage.ui
+dbaccess/ui/dbwizmysqlintropage.ui
+dbaccess/ui/dbwizmysqlnativepage.ui
+dbaccess/ui/specialjdbcconnectionpage.ui
+dbaccess/ui/authentificationpage.ui
+dbaccess/ui/finalpagewizard.ui
+dbaccess/ui/tablesfilterpage.ui
+dbaccess/ui/useradminpage.ui
+dbaccess/ui/connectionpage.ui
+dbaccess/ui/dbwizconnectionpage.ui
+dbaccess/ui/dbwiztextpage.ui
+dbaccess/ui/jdbcconnectionpage.ui
+dbaccess/ui/dbwizspreadsheetpage.ui
+dbaccess/ui/dbasepage.ui
+dbaccess/ui/autocharsetpage.ui
+dbaccess/ui/odbcpage.ui
+dbaccess/ui/userdetailspage.ui
+dbaccess/ui/autocharsetpage.ui
+dbaccess/ui/generalspecialjdbcdetailspage.ui
+dbaccess/ui/mysqlnativepage.ui
+dbaccess/ui/ldappage.ui
+dbaccess/ui/emptypage.ui
+dbaccess/ui/generalpagedialog.ui
+dbaccess/ui/generalpagewizard.ui
+dbaccess/ui/collectionviewdialog.ui
+dbaccess/ui/dbaseindexdialog.ui
+dbaccess/ui/directsqldialog.ui
+dbaccess/ui/savedialog.ui
+dbaccess/ui/savedialog.ui
+dbaccess/ui/rowheightdialog.ui
+dbaccess/ui/colwidthdialog.ui
+dbaccess/ui/choosedatasourcedialog.ui
+dbaccess/ui/indexdesigndialog.ui
+dbaccess/ui/parametersdialog.ui
+dbaccess/ui/queryfilterdialog.ui
+dbaccess/ui/sortdialog.ui
+dbaccess/ui/querypropertiesdialog.ui
+dbaccess/ui/sqlexception.ui
+dbaccess/ui/textconnectionsettings.ui
+dbaccess/ui/password.ui
+dbaccess/ui/tablesfilterdialog.ui
+dbaccess/ui/tablesjoindialog.ui
+dbaccess/ui/savemodifieddialog.ui
+dbaccess/ui/saveindexdialog.ui
+dbaccess/ui/designsavemodifieddialog.ui
+dbaccess/ui/tabledesignsavemodifieddialog.ui
+dbaccess/ui/deleteallrowsdialog.ui
diff --git a/dbaccess/qa/unit/data/firebird_empty.odb b/dbaccess/qa/unit/data/firebird_empty.odb
new file mode 100644
index 000000000..9aabfd47b
--- /dev/null
+++ b/dbaccess/qa/unit/data/firebird_empty.odb
Binary files differ
diff --git a/dbaccess/qa/unit/data/firebird_integer_ods12.odb b/dbaccess/qa/unit/data/firebird_integer_ods12.odb
new file mode 100644
index 000000000..642b038dd
--- /dev/null
+++ b/dbaccess/qa/unit/data/firebird_integer_ods12.odb
Binary files differ
diff --git a/dbaccess/qa/unit/data/hsqldb_empty.odb b/dbaccess/qa/unit/data/hsqldb_empty.odb
new file mode 100644
index 000000000..087c26113
--- /dev/null
+++ b/dbaccess/qa/unit/data/hsqldb_empty.odb
Binary files differ
diff --git a/dbaccess/qa/unit/data/hsqldb_migration_test.odb b/dbaccess/qa/unit/data/hsqldb_migration_test.odb
new file mode 100644
index 000000000..99b6b5d9a
--- /dev/null
+++ b/dbaccess/qa/unit/data/hsqldb_migration_test.odb
Binary files differ
diff --git a/dbaccess/qa/unit/data/tdf119625.odb b/dbaccess/qa/unit/data/tdf119625.odb
new file mode 100644
index 000000000..e7bd69d60
--- /dev/null
+++ b/dbaccess/qa/unit/data/tdf119625.odb
Binary files differ
diff --git a/dbaccess/qa/unit/data/tdf126268.odb b/dbaccess/qa/unit/data/tdf126268.odb
new file mode 100644
index 000000000..434a4238b
--- /dev/null
+++ b/dbaccess/qa/unit/data/tdf126268.odb
Binary files differ
diff --git a/dbaccess/qa/unit/data/tdf132924.odb b/dbaccess/qa/unit/data/tdf132924.odb
new file mode 100644
index 000000000..8cee7bcba
--- /dev/null
+++ b/dbaccess/qa/unit/data/tdf132924.odb
Binary files differ
diff --git a/dbaccess/qa/unit/dbaccess-dialogs-test.cxx b/dbaccess/qa/unit/dbaccess-dialogs-test.cxx
new file mode 100644
index 000000000..0551b3118
--- /dev/null
+++ b/dbaccess/qa/unit/dbaccess-dialogs-test.cxx
@@ -0,0 +1,61 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <sal/config.h>
+#include <test/screenshot_test.hxx>
+#include <vcl/abstdlg.hxx>
+
+using namespace ::com::sun::star;
+
+/// Test opening a dialog in dbaccess
+class DbaccessDialogsTest : public ScreenshotTest
+{
+private:
+ /// helper method to populate KnownDialogs, called in setUp(). Needs to be
+ /// written and has to add entries to KnownDialogs
+ virtual void registerKnownDialogsByID(mapType& rKnownDialogs) override;
+
+ /// dialog creation for known dialogs by ID. Has to be implemented for
+ /// each registered known dialog
+ virtual VclPtr<VclAbstractDialog> createDialogByID(sal_uInt32 nID) override;
+
+public:
+ DbaccessDialogsTest();
+
+ // try to open a dialog
+ void openAnyDialog();
+
+ CPPUNIT_TEST_SUITE(DbaccessDialogsTest);
+ CPPUNIT_TEST(openAnyDialog);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+DbaccessDialogsTest::DbaccessDialogsTest() {}
+
+void DbaccessDialogsTest::registerKnownDialogsByID(mapType& /*rKnownDialogs*/)
+{
+ // fill map of known dialogs
+}
+
+VclPtr<VclAbstractDialog> DbaccessDialogsTest::createDialogByID(sal_uInt32 /*nID*/)
+{
+ return nullptr;
+}
+
+void DbaccessDialogsTest::openAnyDialog()
+{
+ /// process input file containing the UXMLDescriptions of the dialogs to dump
+ processDialogBatchFile(u"dbaccess/qa/unit/data/dbaccess-dialogs-test.txt");
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(DbaccessDialogsTest);
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/qa/unit/dbtest_base.cxx b/dbaccess/qa/unit/dbtest_base.cxx
new file mode 100644
index 000000000..b5a3bd31c
--- /dev/null
+++ b/dbaccess/qa/unit/dbtest_base.cxx
@@ -0,0 +1,86 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <sal/config.h>
+
+#include <string_view>
+
+#include <cppunit/TestAssert.h>
+
+#include <test/unoapi_test.hxx>
+#include <unotools/tempfile.hxx>
+#include <com/sun/star/sdb/XOfficeDatabaseDocument.hpp>
+#include <com/sun/star/sdbc/XConnection.hpp>
+#include <com/sun/star/sdbc/XDataSource.hpp>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::sdb;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::uno;
+
+class DBTestBase
+ : public UnoApiTest
+{
+public:
+ DBTestBase() : UnoApiTest("dbaccess/qa/unit/data") {};
+
+ utl::TempFile createTempCopy(std::u16string_view pathname);
+
+ uno::Reference< XOfficeDatabaseDocument >
+ getDocumentForFileName(std::u16string_view sFileName);
+
+ uno::Reference<XOfficeDatabaseDocument> getDocumentForUrl(OUString const & url);
+
+ uno::Reference< XConnection >
+ getConnectionForDocument(
+ uno::Reference< XOfficeDatabaseDocument > const & xDocument);
+};
+
+utl::TempFile DBTestBase::createTempCopy(std::u16string_view pathname) {
+ OUString url;
+ createFileURL(pathname, url);
+ utl::TempFile tmp;
+ tmp.EnableKillingFile();
+ auto const e = osl::File::copy(url, tmp.GetURL());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(
+ (OString(
+ "<" + OUStringToOString(url, RTL_TEXTENCODING_UTF8) + "> -> <"
+ + OUStringToOString(tmp.GetURL(), RTL_TEXTENCODING_UTF8) + ">")
+ .getStr()),
+ osl::FileBase::E_None, e);
+ return tmp;
+}
+
+uno::Reference< XOfficeDatabaseDocument >
+ DBTestBase::getDocumentForFileName(std::u16string_view sFileName)
+{
+ OUString sFilePath;
+ createFileURL(sFileName, sFilePath);
+ return getDocumentForUrl(sFilePath);
+}
+
+uno::Reference<XOfficeDatabaseDocument> DBTestBase::getDocumentForUrl(OUString const & url) {
+ uno::Reference< lang::XComponent > xComponent (loadFromDesktop(url));
+ uno::Reference< XOfficeDatabaseDocument > xDocument(xComponent, UNO_QUERY_THROW);
+ return xDocument;
+}
+
+uno::Reference< XConnection > DBTestBase::getConnectionForDocument(
+ uno::Reference< XOfficeDatabaseDocument > const & xDocument)
+{
+ uno::Reference< XDataSource > xDataSource = xDocument->getDataSource();
+ CPPUNIT_ASSERT(xDataSource.is());
+
+ uno::Reference< XConnection > xConnection = xDataSource->getConnection("","");
+ CPPUNIT_ASSERT(xConnection.is());
+
+ return xConnection;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/qa/unit/embeddeddb_performancetest.cxx b/dbaccess/qa/unit/embeddeddb_performancetest.cxx
new file mode 100644
index 000000000..17eaa52ae
--- /dev/null
+++ b/dbaccess/qa/unit/embeddeddb_performancetest.cxx
@@ -0,0 +1,358 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "dbtest_base.cxx"
+
+#include <memory>
+#include <osl/process.h>
+#include <osl/time.h>
+#include <rtl/ustrbuf.hxx>
+#include <tools/stream.hxx>
+#include <unotools/tempfile.hxx>
+
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/frame/XStorable.hpp>
+#include <com/sun/star/sdb/XOfficeDatabaseDocument.hpp>
+#include <com/sun/star/sdbc/XConnection.hpp>
+#include <com/sun/star/sdbc/XParameters.hpp>
+#include <com/sun/star/sdbc/XPreparedStatement.hpp>
+#include <com/sun/star/sdbc/XResultSet.hpp>
+#include <com/sun/star/sdbc/XRow.hpp>
+#include <com/sun/star/sdbc/XStatement.hpp>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::frame;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::sdb;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::uno;
+
+static void normaliseTimeValue(TimeValue* pVal)
+{
+ pVal->Seconds += pVal->Nanosec / 1000000000;
+ pVal->Nanosec %= 1000000000;
+}
+
+static void getTimeDifference(const TimeValue* pTimeStart,
+ const TimeValue* pTimeEnd,
+ TimeValue* pTimeDifference)
+{
+ // We add 1 second to the nanoseconds to ensure that we get a positive number
+ // We have to normalise anyway so this doesn't cause any harm.
+ // (Seconds/Nanosec are both unsigned)
+ pTimeDifference->Seconds = pTimeEnd->Seconds - pTimeStart->Seconds - 1;
+ pTimeDifference->Nanosec = 1000000000 + pTimeEnd->Nanosec - pTimeStart->Nanosec;
+ normaliseTimeValue(pTimeDifference);
+}
+
+static OUString getPrintableTimeValue(const TimeValue* pTimeValue)
+{
+ return OUString::number(
+ (sal_uInt64(pTimeValue->Seconds) * SAL_CONST_UINT64(1000000000)
+ + sal_uInt64(pTimeValue->Nanosec))/ 1000000
+ );
+}
+
+/*
+ * The recommended way to run this test is:
+ * 'SAL_LOG="" DBA_PERFTEST=YES make CppunitTest_dbaccess_embeddeddb_performancetest'
+ * This blocks the unnecessary exception output and show only the performance data.
+ *
+ * You also need to create the file dbaccess/qa/unit/data/wordlist, this list cannot
+ * contain any unescaped apostrophes (since the words are used directly to assemble
+ * sql statement), apostrophes are escaped using a double apostrophe, i.e. ''.
+ * one easy way of generating a list is using:
+ * 'for WORD in $(aspell dump master); do echo ${WORD//\'/\'\'}; done > dbaccess/qa/unit/data/wordlist'
+ *
+ * Note that wordlist cannot have more than 220580 lines, this is due to a hard
+ * limit in our hsqldb version.
+ *
+ * Also note that this unit test "fails" when doing performance testing, this is
+ * since by default unit test output is hidden, and thus there is no way of
+ * reading the results.
+ */
+class EmbeddedDBPerformanceTest
+ : public DBTestBase
+{
+private:
+ static constexpr OUStringLiteral our_sEnableTestEnvVar = u"DBA_PERFTEST";
+
+
+ // We store the results and print them at the end due to the amount of warning
+ // noise present which otherwise obscures the results.
+ OUStringBuffer m_aOutputBuffer;
+
+ void printTimes(const TimeValue* pTime1, const TimeValue* pTime2, const TimeValue* pTime3);
+
+ void doPerformanceTestOnODB(const OUString& rDriverURL,
+ std::u16string_view rDBName,
+ const bool bUsePreparedStatement);
+
+ void setupTestTable(uno::Reference< XConnection > const & xConnection);
+
+ SvFileStream *getWordListStream();
+
+ // Individual Tests
+ void performPreparedStatementInsertTest(
+ uno::Reference< XConnection > const & xConnection,
+ std::u16string_view rDBName);
+ void performStatementInsertTest(
+ uno::Reference< XConnection > const & xConnection,
+ std::u16string_view rDBName);
+ void performReadTest(
+ uno::Reference< XConnection > const & xConnection,
+ std::u16string_view rDBName);
+
+ // Perform all tests on a given DB.
+ void testFirebird();
+ void testHSQLDB();
+
+public:
+ void testPerformance();
+
+ CPPUNIT_TEST_SUITE(EmbeddedDBPerformanceTest);
+ CPPUNIT_TEST(testPerformance);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+SvFileStream* EmbeddedDBPerformanceTest::getWordListStream()
+{
+ OUString wlPath;
+ createFileURL(u"wordlist", wlPath);
+ return new SvFileStream(wlPath, StreamMode::READ);
+}
+
+void EmbeddedDBPerformanceTest::printTimes(
+ const TimeValue* pTime1,
+ const TimeValue* pTime2,
+ const TimeValue* pTime3)
+{
+ m_aOutputBuffer.append(
+ getPrintableTimeValue(pTime1) + "\t" +
+ getPrintableTimeValue(pTime2) + "\t" +
+ getPrintableTimeValue(pTime3) + "\t"
+ "\n");
+}
+
+// TODO: we probably should create a document from scratch instead?
+
+void EmbeddedDBPerformanceTest::testPerformance()
+{
+ OUString sEnabled;
+ osl_getEnvironment(OUString(our_sEnableTestEnvVar).pData, &sEnabled.pData);
+
+ if (sEnabled.isEmpty())
+ return;
+
+ m_aOutputBuffer.append("---------------------\n");
+ testFirebird();
+ m_aOutputBuffer.append("---------------------\n");
+ testHSQLDB();
+ m_aOutputBuffer.append("---------------------\n");
+
+ fprintf(stdout, "Performance Test Results:\n");
+ fprintf(stdout, "%s",
+ OUStringToOString(m_aOutputBuffer.makeStringAndClear(),
+ RTL_TEXTENCODING_UTF8)
+ .getStr()
+ );
+
+ // We want the results printed, but unit test output is only printed on failure
+ // Hence we deliberately fail the test.
+ CPPUNIT_ASSERT(false);
+}
+
+void EmbeddedDBPerformanceTest::testFirebird()
+{
+
+ m_aOutputBuffer.append("Standard Insert\n");
+ doPerformanceTestOnODB("sdbc:embedded:firebird", u"Firebird", false);
+ m_aOutputBuffer.append("PreparedStatement Insert\n");
+ doPerformanceTestOnODB("sdbc:embedded:firebird", u"Firebird", true);
+}
+
+void EmbeddedDBPerformanceTest::testHSQLDB()
+{
+ m_aOutputBuffer.append("Standard Insert\n");
+ doPerformanceTestOnODB("sdbc:embedded:hsqldb", u"HSQLDB", false);
+ m_aOutputBuffer.append("PreparedStatement Insert\n");
+ doPerformanceTestOnODB("sdbc:embedded:hsqldb", u"HSQLDB", true);
+}
+
+/**
+ * Use an existing .odb to do performance tests on. The database cannot have
+ * a table of the name PFTESTTABLE.
+ */
+void EmbeddedDBPerformanceTest::doPerformanceTestOnODB(
+ const OUString& rDriverURL,
+ std::u16string_view rDBName,
+ const bool bUsePreparedStatement)
+{
+ ::utl::TempFile aFile;
+ aFile.EnableKillingFile();
+
+ {
+ uno::Reference< XOfficeDatabaseDocument > xDocument(
+ m_xSFactory->createInstance("com.sun.star.sdb.OfficeDatabaseDocument"),
+ UNO_QUERY_THROW);
+ uno::Reference< XStorable > xStorable(xDocument, UNO_QUERY_THROW);
+
+ uno::Reference< XDataSource > xDataSource = xDocument->getDataSource();
+ uno::Reference< XPropertySet > xPropertySet(xDataSource, UNO_QUERY_THROW);
+ xPropertySet->setPropertyValue("URL", Any(rDriverURL));
+
+ xStorable->storeAsURL(aFile.GetURL(), uno::Sequence< beans::PropertyValue >());
+ }
+
+ uno::Reference< XOfficeDatabaseDocument > xDocument(
+ loadFromDesktop(aFile.GetURL()), UNO_QUERY_THROW);
+
+ uno::Reference< XConnection > xConnection =
+ getConnectionForDocument(xDocument);
+
+ setupTestTable(xConnection);
+
+ if (bUsePreparedStatement)
+ performPreparedStatementInsertTest(xConnection, rDBName);
+ else
+ performStatementInsertTest(xConnection, rDBName);
+
+ performReadTest(xConnection, rDBName);
+}
+
+void EmbeddedDBPerformanceTest::setupTestTable(
+ uno::Reference< XConnection > const & xConnection)
+{
+ uno::Reference< XStatement > xStatement = xConnection->createStatement();
+
+ // Although not strictly necessary we use quoted identifiers to reflect
+ // the fact that Base always uses quoted identifiers.
+ xStatement->execute(
+ "CREATE TABLE \"PFTESTTABLE\" ( \"ID\" INTEGER NOT NULL PRIMARY KEY "
+ ", \"STRINGCOLUMNA\" VARCHAR (50) "
+ ")");
+
+ xConnection->commit();
+}
+
+void EmbeddedDBPerformanceTest::performPreparedStatementInsertTest(
+ uno::Reference< XConnection > const & xConnection,
+ std::u16string_view rDBName)
+{
+ uno::Reference< XPreparedStatement > xPreparedStatement =
+ xConnection->prepareStatement(
+ "INSERT INTO \"PFTESTTABLE\" ( \"ID\", "
+ "\"STRINGCOLUMNA\" "
+ ") VALUES ( ?, ? )"
+ );
+
+ uno::Reference< XParameters > xParameters(xPreparedStatement, UNO_QUERY_THROW);
+
+ std::unique_ptr< SvFileStream > pFile(getWordListStream());
+
+ OUString aWord;
+ sal_Int32 aID = 0;
+
+ TimeValue aStart, aMiddle, aEnd;
+ osl_getSystemTime(&aStart);
+
+ while (pFile->ReadByteStringLine(aWord, RTL_TEXTENCODING_UTF8))
+ {
+ xParameters->setInt(1, aID++);
+ xParameters->setString(2, aWord);
+ xPreparedStatement->execute();
+ }
+ osl_getSystemTime(&aMiddle);
+ xConnection->commit();
+ osl_getSystemTime(&aEnd);
+
+
+ TimeValue aTimeInsert, aTimeCommit, aTimeTotal;
+ getTimeDifference(&aStart, &aMiddle, &aTimeInsert);
+ getTimeDifference(&aMiddle, &aEnd, &aTimeCommit);
+ getTimeDifference(&aStart, &aEnd, &aTimeTotal);
+ m_aOutputBuffer.append(OUString::Concat("Insert: ") + rDBName + "\n");
+ printTimes(&aTimeInsert, &aTimeCommit, &aTimeTotal);
+
+ pFile->Close();
+}
+
+void EmbeddedDBPerformanceTest::performStatementInsertTest(
+ uno::Reference< XConnection > const & xConnection,
+ std::u16string_view rDBName)
+{
+ uno::Reference< XStatement > xStatement =
+ xConnection->createStatement();
+
+ std::unique_ptr< SvFileStream > pFile(getWordListStream());
+
+ OUString aWord;
+ sal_Int32 aID = 0;
+
+ TimeValue aStart, aMiddle, aEnd;
+ osl_getSystemTime(&aStart);
+
+ while (pFile->ReadByteStringLine(aWord, RTL_TEXTENCODING_UTF8))
+ {
+ xStatement->execute(
+ "INSERT INTO \"PFTESTTABLE\" ( \"ID\", "
+ "\"STRINGCOLUMNA\" "
+ ") VALUES ( "
+ + OUString::number(aID++) + ", '" + aWord + "' )"
+ );
+ }
+ osl_getSystemTime(&aMiddle);
+ xConnection->commit();
+ osl_getSystemTime(&aEnd);
+
+ TimeValue aTimeInsert, aTimeCommit, aTimeTotal;
+ getTimeDifference(&aStart, &aMiddle, &aTimeInsert);
+ getTimeDifference(&aMiddle, &aEnd, &aTimeCommit);
+ getTimeDifference(&aStart, &aEnd, &aTimeTotal);
+ m_aOutputBuffer.append(OUString::Concat("Insert: ") + rDBName + "\n");
+ printTimes(&aTimeInsert, &aTimeCommit, &aTimeTotal);
+
+ pFile->Close();
+}
+
+void EmbeddedDBPerformanceTest::performReadTest(
+ uno::Reference< XConnection > const & xConnection,
+ std::u16string_view rDBName)
+{
+ uno::Reference< XStatement > xStatement = xConnection->createStatement();
+
+ TimeValue aStart, aMiddle, aEnd;
+ osl_getSystemTime(&aStart);
+
+ uno::Reference< XResultSet > xResults = xStatement->executeQuery("SELECT * FROM PFTESTTABLE");
+
+ osl_getSystemTime(&aMiddle);
+
+ uno::Reference< XRow > xRow(xResults, UNO_QUERY_THROW);
+
+ while (xResults->next())
+ {
+ xRow->getString(2);
+ }
+ osl_getSystemTime(&aEnd);
+
+ TimeValue aTimeSelect, aTimeIterate, aTimeTotal;
+ getTimeDifference(&aStart, &aMiddle, &aTimeSelect);
+ getTimeDifference(&aMiddle, &aEnd, &aTimeIterate);
+ getTimeDifference(&aStart, &aEnd, &aTimeTotal);
+ m_aOutputBuffer.append(OUString::Concat("Read from: ") + rDBName + "\n");
+ printTimes(&aTimeSelect, &aTimeIterate, &aTimeTotal);
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(EmbeddedDBPerformanceTest);
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/qa/unit/firebird.cxx b/dbaccess/qa/unit/firebird.cxx
new file mode 100644
index 000000000..7a8143810
--- /dev/null
+++ b/dbaccess/qa/unit/firebird.cxx
@@ -0,0 +1,125 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "dbtest_base.cxx"
+
+#include <com/sun/star/sdb/XOfficeDatabaseDocument.hpp>
+#include <com/sun/star/sdbc/XColumnLocate.hpp>
+#include <com/sun/star/sdbc/XConnection.hpp>
+#include <com/sun/star/sdbc/XResultSet.hpp>
+#include <com/sun/star/sdbc/XRow.hpp>
+#include <com/sun/star/sdbc/XStatement.hpp>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::sdb;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::uno;
+
+class FirebirdTest
+ : public DBTestBase
+{
+public:
+ void testEmptyDBConnection();
+ void testIntegerDatabase();
+ void testTdf132924();
+
+ CPPUNIT_TEST_SUITE(FirebirdTest);
+ CPPUNIT_TEST(testEmptyDBConnection);
+ CPPUNIT_TEST(testIntegerDatabase);
+ CPPUNIT_TEST(testTdf132924);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+/**
+ * Test the loading of an "empty" file, i.e. the embedded database has not yet
+ * been initialised (as occurs when a new .odb is created and opened by base).
+ */
+void FirebirdTest::testEmptyDBConnection()
+{
+ auto const tmp = createTempCopy(u"firebird_empty.odb");
+ uno::Reference< XOfficeDatabaseDocument > xDocument =
+ getDocumentForUrl(tmp.GetURL());
+
+ getConnectionForDocument(xDocument);
+
+ closeDocument(uno::Reference<lang::XComponent>(xDocument, uno::UNO_QUERY));
+}
+
+/**
+ * Test reading of integers from a known .odb to verify that the data
+ * can still be read on all systems.
+ */
+void FirebirdTest::testIntegerDatabase()
+{
+ uno::Reference< XOfficeDatabaseDocument > xDocument =
+ getDocumentForFileName(u"firebird_integer_ods12.odb");
+
+ uno::Reference< XConnection > xConnection =
+ getConnectionForDocument(xDocument);
+
+ uno::Reference< XStatement > xStatement = xConnection->createStatement();
+ CPPUNIT_ASSERT(xStatement.is());
+
+ uno::Reference< XResultSet > xResultSet = xStatement->executeQuery(
+ "SELECT * FROM TESTTABLE");
+ CPPUNIT_ASSERT(xResultSet.is());
+ CPPUNIT_ASSERT(xResultSet->next());
+
+ uno::Reference< XRow > xRow(xResultSet, UNO_QUERY);
+ CPPUNIT_ASSERT(xRow.is());
+ uno::Reference< XColumnLocate > xColumnLocate(xRow, UNO_QUERY);
+ CPPUNIT_ASSERT(xColumnLocate.is());
+
+ CPPUNIT_ASSERT_EQUAL(sal_Int16(-30000),
+ xRow->getShort(xColumnLocate->findColumn("_SMALLINT")));
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(-2100000000),
+ xRow->getInt(xColumnLocate->findColumn("_INT")));
+ CPPUNIT_ASSERT_EQUAL(SAL_CONST_INT64(-9000000000000000000),
+ xRow->getLong(xColumnLocate->findColumn("_BIGINT")));
+ CPPUNIT_ASSERT_EQUAL(OUString("5"),
+ xRow->getString(xColumnLocate->findColumn("_CHAR")));
+ CPPUNIT_ASSERT_EQUAL(OUString("5"),
+ xRow->getString(xColumnLocate->findColumn("_VARCHAR")));
+
+ CPPUNIT_ASSERT(!xResultSet->next()); // Should only be one row
+
+ closeDocument(uno::Reference<lang::XComponent>(xDocument, uno::UNO_QUERY));
+}
+
+void FirebirdTest::testTdf132924()
+{
+ uno::Reference<XOfficeDatabaseDocument> xDocument = getDocumentForFileName(u"tdf132924.odb");
+ uno::Reference<XConnection> xConnection = getConnectionForDocument(xDocument);
+
+ uno::Reference<XStatement> xStatement = xConnection->createStatement();
+ CPPUNIT_ASSERT(xStatement.is());
+
+ uno::Reference<XResultSet> xResultSet = xStatement->executeQuery("SELECT * FROM AliasTest");
+ CPPUNIT_ASSERT(xResultSet.is());
+ CPPUNIT_ASSERT(xResultSet->next());
+
+ uno::Reference<XRow> xRow(xResultSet, UNO_QUERY);
+ CPPUNIT_ASSERT(xRow.is());
+ uno::Reference<XColumnLocate> xColumnLocate(xRow, UNO_QUERY);
+ CPPUNIT_ASSERT(xColumnLocate.is());
+
+ // Without the fix in place, this test would have failed with:
+ // - Expected: 1
+ // - Actual : The column name 'TestId' is not valid
+ CPPUNIT_ASSERT_EQUAL(sal_Int16(1), xRow->getShort(xColumnLocate->findColumn("TestId")));
+ CPPUNIT_ASSERT_EQUAL(OUString("TestName"), xRow->getString(xColumnLocate->findColumn("TestName")));
+
+ closeDocument(uno::Reference<lang::XComponent>(xDocument, uno::UNO_QUERY));
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(FirebirdTest);
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/qa/unit/hsql_binary_import.cxx b/dbaccess/qa/unit/hsql_binary_import.cxx
new file mode 100644
index 000000000..4eac0cdc4
--- /dev/null
+++ b/dbaccess/qa/unit/hsql_binary_import.cxx
@@ -0,0 +1,101 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "dbtest_base.cxx"
+
+#include <osl/process.h>
+#include <cppunit/plugin/TestPlugIn.h>
+#include <com/sun/star/sdbc/XRow.hpp>
+#include <cppunit/extensions/HelperMacros.h>
+#include <officecfg/Office/Common.hxx>
+
+class HsqlBinaryImportTest : public DBTestBase
+{
+public:
+ void testBinaryImport();
+
+ virtual void setUp() override;
+
+ CPPUNIT_TEST_SUITE(HsqlBinaryImportTest);
+
+ CPPUNIT_TEST(testBinaryImport);
+
+ CPPUNIT_TEST_SUITE_END();
+};
+
+void HsqlBinaryImportTest::setUp()
+{
+ DBTestBase::setUp();
+ osl_setEnvironment(OUString{ "DBACCESS_HSQL_MIGRATION" }.pData, OUString{ "1" }.pData);
+}
+
+void HsqlBinaryImportTest::testBinaryImport()
+{
+ bool oldValue = officecfg::Office::Common::Misc::ExperimentalMode::get();
+ {
+ std::shared_ptr<comphelper::ConfigurationChanges> xChanges(
+ comphelper::ConfigurationChanges::create());
+ officecfg::Office::Common::Misc::ExperimentalMode::set(true, xChanges);
+ xChanges->commit();
+ }
+
+ // the migration requires the file to be writable
+ utl::TempFile const temp(createTempCopy(u"hsqldb_migration_test.odb"));
+ uno::Reference<XOfficeDatabaseDocument> const xDocument = getDocumentForUrl(temp.GetURL());
+
+ uno::Reference<XConnection> xConnection = getConnectionForDocument(xDocument);
+ // at this point migration is already done
+
+ uno::Reference<XStatement> statement = xConnection->createStatement();
+
+ uno::Reference<XResultSet> xRes
+ = statement->executeQuery("SELECT \"ID\", \"Power_value\", \"Power_name\", \"Retired\", "
+ "\"Birth_date\" FROM \"TestTable\" ORDER BY \"ID\"");
+ uno::Reference<XRow> xRow(xRes, UNO_QUERY_THROW);
+
+ // assert first row
+ CPPUNIT_ASSERT(xRes->next());
+ constexpr sal_Int16 idExpected = 1;
+ CPPUNIT_ASSERT_EQUAL(idExpected, xRow->getShort(1));
+ CPPUNIT_ASSERT_EQUAL(OUString{ "45.32" }, xRow->getString(2)); // numeric
+ CPPUNIT_ASSERT_EQUAL(OUString{ "laser eye" }, xRow->getString(3)); // varchar
+ CPPUNIT_ASSERT(xRow->getBoolean(4)); // boolean
+
+ css::util::Date date = xRow->getDate(5);
+
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16{ 15 }, date.Day);
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16{ 1 }, date.Month);
+ CPPUNIT_ASSERT_EQUAL(sal_Int16{ 1996 }, date.Year);
+
+ // assert second row
+ CPPUNIT_ASSERT(xRes->next());
+ constexpr sal_Int16 secondIdExpected = 2;
+ CPPUNIT_ASSERT_EQUAL(secondIdExpected, xRow->getShort(1)); // ID
+ CPPUNIT_ASSERT_EQUAL(OUString{ "54.12" }, xRow->getString(2)); // numeric
+ CPPUNIT_ASSERT_EQUAL(OUString{ "telekinesis" }, xRow->getString(3)); // varchar
+ CPPUNIT_ASSERT(!xRow->getBoolean(4)); // boolean
+
+ date = xRow->getDate(5);
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16{ 26 }, date.Day);
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16{ 2 }, date.Month);
+ CPPUNIT_ASSERT_EQUAL(sal_Int16{ 1998 }, date.Year);
+
+ closeDocument(uno::Reference<lang::XComponent>(xDocument, uno::UNO_QUERY));
+ if (!oldValue)
+ {
+ std::shared_ptr<comphelper::ConfigurationChanges> xChanges(
+ comphelper::ConfigurationChanges::create());
+ officecfg::Office::Common::Misc::ExperimentalMode::set(false, xChanges);
+ xChanges->commit();
+ }
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(HsqlBinaryImportTest);
+
+CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/dbaccess/qa/unit/hsqldb.cxx b/dbaccess/qa/unit/hsqldb.cxx
new file mode 100644
index 000000000..5ee011af2
--- /dev/null
+++ b/dbaccess/qa/unit/hsqldb.cxx
@@ -0,0 +1,47 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "dbtest_base.cxx"
+
+#include <com/sun/star/sdb/XOfficeDatabaseDocument.hpp>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::sdb;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::uno;
+
+class HSQLDBTest : public DBTestBase
+{
+public:
+ void testEmptyDBConnection();
+
+ CPPUNIT_TEST_SUITE(HSQLDBTest);
+ CPPUNIT_TEST(testEmptyDBConnection);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+/**
+ * Test the loading of an "empty" file, i.e. the embedded database has not yet
+ * been initialised (as occurs when a new .odb is created and opened by base).
+ */
+void HSQLDBTest::testEmptyDBConnection()
+{
+ auto const file = createTempCopy(u"hsqldb_empty.odb");
+ uno::Reference<XOfficeDatabaseDocument> xDocument = getDocumentForUrl(file.GetURL());
+
+ getConnectionForDocument(xDocument);
+
+ css::uno::Reference<css::lang::XComponent>(xDocument, css::uno::UNO_QUERY_THROW)->dispose();
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(HSQLDBTest);
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/qa/unit/tdf119625.cxx b/dbaccess/qa/unit/tdf119625.cxx
new file mode 100644
index 000000000..22fb58493
--- /dev/null
+++ b/dbaccess/qa/unit/tdf119625.cxx
@@ -0,0 +1,121 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "dbtest_base.cxx"
+
+#include <osl/process.h>
+#include <cppunit/plugin/TestPlugIn.h>
+#include <com/sun/star/sdbc/XRow.hpp>
+#include <cppunit/extensions/HelperMacros.h>
+#include <com/sun/star/util/Time.hpp>
+#include <officecfg/Office/Common.hxx>
+
+class Tdf119625Test : public DBTestBase
+{
+public:
+ void testTime();
+
+ virtual void setUp() override;
+
+ CPPUNIT_TEST_SUITE(Tdf119625Test);
+
+ CPPUNIT_TEST(testTime);
+
+ CPPUNIT_TEST_SUITE_END();
+};
+
+void Tdf119625Test::setUp()
+{
+ DBTestBase::setUp();
+ osl_setEnvironment(OUString{ "DBACCESS_HSQL_MIGRATION" }.pData, OUString{ "1" }.pData);
+}
+
+namespace
+{
+struct expect_t
+{
+ sal_Int16 id;
+ sal_Int16 h, m, s;
+};
+}
+
+/* The values here assume that our results are in UTC. However,
+ tdf#119675 "Firebird: Migration: User dialog to set treatment of
+ datetime and time values during migration" is going to change the
+ final result of migration. If that change is implemented below
+ the level we are testing, this test will have to allow for or set
+ the destination timezone.
+ */
+const expect_t expect[] = { { 0, 15, 10, 10 }, { 1, 23, 30, 30 }, { 2, 5, 0, 0 }, { 3, 4, 30, 0 },
+ { 4, 3, 15, 10 }, { 5, 5, 0, 0 }, { 6, 3, 22, 22 } };
+
+void Tdf119625Test::testTime()
+{
+ bool oldValue = officecfg::Office::Common::Misc::ExperimentalMode::get();
+ {
+ std::shared_ptr<comphelper::ConfigurationChanges> xChanges(
+ comphelper::ConfigurationChanges::create());
+ officecfg::Office::Common::Misc::ExperimentalMode::set(true, xChanges);
+ xChanges->commit();
+ }
+
+ // the migration requires the file to be writable
+ utl::TempFile const temp(createTempCopy(u"tdf119625.odb"));
+ uno::Reference<XOfficeDatabaseDocument> const xDocument = getDocumentForUrl(temp.GetURL());
+
+ uno::Reference<XConnection> xConnection = getConnectionForDocument(xDocument);
+ // at this point migration is already done
+ /* In the presence of tdf#119625, terminal already has messages
+
+ *value exceeds the range for a valid time
+ caused by
+ 'isc_dsql_execute'
+
+ warn:dbaccess:22435:22435:dbaccess/source/filter/hsqldb/hsqlimport.cxx:373: Error during migration
+
+ In this case, we do not expect anything good from the following
+ code, but I (tje, 2018-09-04) do not know how to detect this
+ situation. In particular, the migration has been observed to
+ create the destination table (but truncated after the first
+ row), and xConnection.is() returns true.
+ */
+
+ // select basically everything from the .odb
+ uno::Reference<XStatement> statement = xConnection->createStatement();
+
+ uno::Reference<XResultSet> xRes = statement->executeQuery(" SELECT id, tst_dt, tst_d, tst_t "
+ " FROM tst_data "
+ "ORDER BY id");
+ uno::Reference<XRow> xRow(xRes, UNO_QUERY_THROW);
+
+ // check result
+ for (auto& e : expect)
+ {
+ CPPUNIT_ASSERT(xRes->next());
+ CPPUNIT_ASSERT_EQUAL(xRow->getShort(1), e.id);
+ auto time_got = xRow->getTime(4);
+ auto time_expected = com::sun::star::util::Time(0, e.s, e.m, e.h, false);
+ auto equal_times = time_got == time_expected;
+ CPPUNIT_ASSERT(equal_times);
+ }
+ CPPUNIT_ASSERT(!xRes->next());
+
+ closeDocument(uno::Reference<lang::XComponent>(xDocument, uno::UNO_QUERY));
+ if (!oldValue)
+ {
+ std::shared_ptr<comphelper::ConfigurationChanges> xChanges(
+ comphelper::ConfigurationChanges::create());
+ officecfg::Office::Common::Misc::ExperimentalMode::set(false, xChanges);
+ xChanges->commit();
+ }
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(Tdf119625Test);
+
+CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/dbaccess/qa/unit/tdf126268.cxx b/dbaccess/qa/unit/tdf126268.cxx
new file mode 100644
index 000000000..a4ed9dc3b
--- /dev/null
+++ b/dbaccess/qa/unit/tdf126268.cxx
@@ -0,0 +1,97 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "dbtest_base.cxx"
+
+#include <osl/process.h>
+#include <cppunit/plugin/TestPlugIn.h>
+#include <com/sun/star/sdbc/XRow.hpp>
+#include <cppunit/extensions/HelperMacros.h>
+#include <officecfg/Office/Common.hxx>
+
+class Tdf126268Test : public DBTestBase
+{
+public:
+ void testNumbers();
+
+ virtual void setUp() override;
+
+ CPPUNIT_TEST_SUITE(Tdf126268Test);
+
+ CPPUNIT_TEST(testNumbers);
+
+ CPPUNIT_TEST_SUITE_END();
+};
+
+void Tdf126268Test::setUp()
+{
+ DBTestBase::setUp();
+ osl_setEnvironment(OUString{ "DBACCESS_HSQL_MIGRATION" }.pData, OUString{ "1" }.pData);
+}
+
+namespace
+{
+struct expect_t
+{
+ sal_Int16 id;
+ OUString number;
+};
+}
+
+const expect_t expect[] = {
+ { 1, "0.00" }, { 2, "25.00" }, { 3, "26.00" }, { 4, "30.4" }, { 5, "45.8" },
+ { 6, "-25.00" }, { 7, "-26.00" }, { 8, "-30.4" }, { 9, "-45.8" },
+};
+
+void Tdf126268Test::testNumbers()
+{
+ bool oldValue = officecfg::Office::Common::Misc::ExperimentalMode::get();
+ {
+ std::shared_ptr<comphelper::ConfigurationChanges> xChanges(
+ comphelper::ConfigurationChanges::create());
+ officecfg::Office::Common::Misc::ExperimentalMode::set(true, xChanges);
+ xChanges->commit();
+ }
+
+ // the migration requires the file to be writable
+ utl::TempFile const temp(createTempCopy(u"tdf126268.odb"));
+ uno::Reference<XOfficeDatabaseDocument> const xDocument = getDocumentForUrl(temp.GetURL());
+
+ uno::Reference<XConnection> xConnection = getConnectionForDocument(xDocument);
+
+ // select basically everything from the .odb
+ uno::Reference<XStatement> statement = xConnection->createStatement();
+
+ uno::Reference<XResultSet> xRes
+ = statement->executeQuery("SELECT ID, Column1, Column2 FROM tableTest ORDER BY ID");
+ uno::Reference<XRow> xRow(xRes, UNO_QUERY_THROW);
+
+ // check result
+ for (auto& e : expect)
+ {
+ CPPUNIT_ASSERT(xRes->next());
+ CPPUNIT_ASSERT_EQUAL(e.id, xRow->getShort(1));
+ CPPUNIT_ASSERT_EQUAL(e.number, xRow->getString(2)); //decimal
+ CPPUNIT_ASSERT_EQUAL(e.number, xRow->getString(3)); //numeric
+ }
+ CPPUNIT_ASSERT(!xRes->next());
+
+ closeDocument(uno::Reference<lang::XComponent>(xDocument, uno::UNO_QUERY));
+ if (!oldValue)
+ {
+ std::shared_ptr<comphelper::ConfigurationChanges> xChanges(
+ comphelper::ConfigurationChanges::create());
+ officecfg::Office::Common::Misc::ExperimentalMode::set(false, xChanges);
+ xChanges->commit();
+ }
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(Tdf126268Test);
+
+CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/dbaccess/qa/unoapi/dbaccess.props b/dbaccess/qa/unoapi/dbaccess.props
new file mode 100644
index 000000000..afad9f038
--- /dev/null
+++ b/dbaccess/qa/unoapi/dbaccess.props
@@ -0,0 +1,24 @@
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This file incorporates work covered by the following license notice:
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed
+# with this work for additional information regarding copyright
+# ownership. The ASF licenses this file to you under the Apache
+# License, Version 2.0 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.apache.org/licenses/LICENSE-2.0 .
+#
+
+#properties needed for dbbaccess
+
+jdbc.url=mysql://unoapi:3306/testDB
+jdbc.user=unoapi
+jdbc.password=unoapi
+mysql.url=sdbc:mysql:jdbc:unoapi:3306/TestDB
diff --git a/dbaccess/qa/unoapi/dbaccess.sce b/dbaccess/qa/unoapi/dbaccess.sce
new file mode 100644
index 000000000..13fa966ab
--- /dev/null
+++ b/dbaccess/qa/unoapi/dbaccess.sce
@@ -0,0 +1,32 @@
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This file incorporates work covered by the following license notice:
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed
+# with this work for additional information regarding copyright
+# ownership. The ASF licenses this file to you under the Apache
+# License, Version 2.0 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.apache.org/licenses/LICENSE-2.0 .
+#
+#i84113 -o dbaccess.ConnectionLineAccessibility
+-o dbaccess.DBContentLoader
+#i84114 -o dbaccess.JoinViewAccessibility
+-o dbaccess.OCommandDefinition
+-o dbaccess.ODatabaseContext
+-o dbaccess.ODatabaseSource
+-o dbaccess.ODatasourceAdministrationDialog
+#i98007 -o dbaccess.ODatasourceBrowser
+-o dbaccess.OInteractionHandler
+#i84116 -o dbaccess.OQueryDesign
+-o dbaccess.ORowSet
+-o dbaccess.OSQLMessageDialog
+-o dbaccess.OSingleSelectQueryComposer
+#i95611 -o dbaccess.SbaXGridControl
+#i84128 -o dbaccess.TableWindowAccessibility
diff --git a/dbaccess/qa/unoapi/knownissues.xcl b/dbaccess/qa/unoapi/knownissues.xcl
new file mode 100644
index 000000000..8c635d097
--- /dev/null
+++ b/dbaccess/qa/unoapi/knownissues.xcl
@@ -0,0 +1,80 @@
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This file incorporates work covered by the following license notice:
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed
+# with this work for additional information regarding copyright
+# ownership. The ASF licenses this file to you under the Apache
+# License, Version 2.0 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.apache.org/licenses/LICENSE-2.0 .
+#
+
+### 114044 ###
+dbaccess.ORowSet::com::sun::star::sdbc::XWarningsSupplier
+
+### i38209 ###
+dbaccess.ODatasourceAdministrationDialog::com::sun::star::sdb::DatasourceAdministrationDialog
+
+### i55579 ###
+dbaccess.OQueryDesign::com::sun::star::frame::XController
+
+### i84113 ###
+dbaccess.ConnectionLineAccessibility
+# -> disabled in dbaccess.sce
+
+### i84114 ###
+dbaccess.JoinViewAccessibility
+# -> disabled in dbaccess.sce
+
+### i84116 ###
+dbaccess.OQueryDesign
+# -> disabled in dbaccess.sce
+
+### i84125 ###
+dbaccess.SbaXGridControl::com::sun::star::view::XSelectionSupplier
+
+### i84127 ###
+dbaccess.SbaXGridControl::com::sun::star::awt::XWindow
+
+### i86990 ###
+dbaccess.ODatabaseSource::com::sun::star::beans::XPropertySet
+dbaccess.OCommandDefinition::com::sun::star::beans::XPropertySet
+
+### i84128 ###
+dbaccess.TableWindowAccessibility
+# -> disabled in dbaccess.sce
+
+### i87247 ###
+dbaccess.DBContentLoader::com::sun::star::frame::XFrameLoader
+
+### i88646 ###
+dbaccess.ODatabaseContext::com::sun::star::uno::XNamingService
+
+### i90358 ###
+dbaccess.SbaXGridControl::com::sun::star::awt::XView
+
+### i90359 ###
+dbaccess.ODatabaseSource::com::sun::star::sdb::DataSource
+
+### i95611 ###
+dbaccess.SbaXGridControl
+# -> disabled in dbaccess.sce
+
+### i95691 ###
+dbaccess.ORowSet::com::sun::star::sdbc::XRowUpdate
+dbaccess.ORowSet::com::sun::star::sdbc::XRow
+
+## i97860 ###
+dbaccess.ORowSet::com::sun::star::sdbcx::XDeleteRows
+dbaccess.ORowSet::com::sun::star::sdbc::XResultSetUpdate
+
+### i98007 ###
+dbaccess.ODatasourceBrowser
+# -> disabled in dbaccess.sce \ No newline at end of file
diff --git a/dbaccess/qa/unoapi/testdocuments/TestDB/testDB.dbf b/dbaccess/qa/unoapi/testdocuments/TestDB/testDB.dbf
new file mode 100644
index 000000000..c3af1e143
--- /dev/null
+++ b/dbaccess/qa/unoapi/testdocuments/TestDB/testDB.dbf
Binary files differ
diff --git a/dbaccess/qa/unoapi/testdocuments/TestDB/testDB.dbt b/dbaccess/qa/unoapi/testdocuments/TestDB/testDB.dbt
new file mode 100644
index 000000000..41cb9d24c
--- /dev/null
+++ b/dbaccess/qa/unoapi/testdocuments/TestDB/testDB.dbt
Binary files differ
diff --git a/dbaccess/source/core/api/BookmarkSet.cxx b/dbaccess/source/core/api/BookmarkSet.cxx
new file mode 100644
index 000000000..75dfc24f5
--- /dev/null
+++ b/dbaccess/source/core/api/BookmarkSet.cxx
@@ -0,0 +1,204 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "BookmarkSet.hxx"
+#include <core_resource.hxx>
+#include <strings.hrc>
+#include <com/sun/star/sdbc/XResultSetUpdate.hpp>
+#include <connectivity/dbexception.hxx>
+
+using namespace dbaccess;
+using namespace ::connectivity;
+using namespace ::dbtools;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::sdbcx;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::lang;
+using namespace ::osl;
+
+void OBookmarkSet::construct(const Reference< XResultSet>& _xDriverSet,const OUString& i_sRowSetFilter)
+{
+ OCacheSet::construct(_xDriverSet,i_sRowSetFilter);
+ m_xRowLocate.set(_xDriverSet,UNO_QUERY);
+}
+
+void OBookmarkSet::reset(const Reference< XResultSet>& _xDriverSet)
+{
+ construct(_xDriverSet, m_sRowSetFilter);
+}
+
+Any OBookmarkSet::getBookmark()
+{
+ return m_xRowLocate->getBookmark();
+}
+
+bool OBookmarkSet::moveToBookmark( const Any& bookmark )
+{
+ return m_xRowLocate->moveToBookmark(bookmark);
+}
+
+sal_Int32 OBookmarkSet::compareBookmarks( const Any& _first, const Any& _second )
+{
+ return m_xRowLocate->compareBookmarks(_first,_second);
+}
+
+bool OBookmarkSet::hasOrderedBookmarks( )
+{
+ return m_xRowLocate->hasOrderedBookmarks();
+}
+
+sal_Int32 OBookmarkSet::hashBookmark( const Any& bookmark )
+{
+ return m_xRowLocate->hashBookmark(bookmark);
+}
+
+void OBookmarkSet::insertRow( const ORowSetRow& _rInsertRow,const connectivity::OSQLTable& /*_xTable*/ )
+{
+ Reference<XRowUpdate> xUpdRow(m_xRowLocate,UNO_QUERY);
+ if(!xUpdRow.is())
+ ::dbtools::throwSQLException( DBA_RES( RID_STR_NO_XROWUPDATE ), StandardSQLState::GENERAL_ERROR, *this );
+
+ Reference<XResultSetUpdate> xUpd(m_xRowLocate,UNO_QUERY);
+ if(xUpd.is())
+ {
+ xUpd->moveToInsertRow();
+ sal_Int32 i = 1;
+ connectivity::ORowVector< ORowSetValue > ::Vector::iterator aEnd = _rInsertRow->end();
+ for(connectivity::ORowVector< ORowSetValue > ::Vector::iterator aIter = _rInsertRow->begin()+1;aIter != aEnd;++aIter,++i)
+ {
+ aIter->setSigned(m_aSignedFlags[i-1]);
+ updateColumn(i,xUpdRow,*aIter);
+ }
+ xUpd->insertRow();
+ (*_rInsertRow->begin()) = m_xRowLocate->getBookmark();
+ }
+ else
+ ::dbtools::throwSQLException( DBA_RES( RID_STR_NO_XRESULTSETUPDATE ), StandardSQLState::GENERAL_ERROR, *this );
+}
+
+void OBookmarkSet::updateRow(const ORowSetRow& _rInsertRow ,const ORowSetRow& _rOriginalRow,const connectivity::OSQLTable& /*_xTable*/ )
+{
+ Reference<XRowUpdate> xUpdRow(m_xRowLocate,UNO_QUERY);
+ if(!xUpdRow.is())
+ ::dbtools::throwSQLException( DBA_RES( RID_STR_NO_XROWUPDATE ), StandardSQLState::GENERAL_ERROR, *this );
+
+ sal_Int32 i = 1;
+ connectivity::ORowVector< ORowSetValue > ::Vector::const_iterator aOrgIter = _rOriginalRow->begin()+1;
+ connectivity::ORowVector< ORowSetValue > ::Vector::iterator aEnd = _rInsertRow->end();
+ for(connectivity::ORowVector< ORowSetValue > ::Vector::iterator aIter = _rInsertRow->begin()+1;aIter != aEnd;++aIter,++i,++aOrgIter)
+ {
+ aIter->setSigned(aOrgIter->isSigned());
+ updateColumn(i,xUpdRow,*aIter);
+ }
+
+
+ Reference<XResultSetUpdate> xUpd(m_xRowLocate,UNO_QUERY);
+ if(xUpd.is())
+ xUpd->updateRow();
+ else
+ ::dbtools::throwSQLException( DBA_RES( RID_STR_NO_XRESULTSETUPDATE ), StandardSQLState::GENERAL_ERROR, *this );
+}
+
+void OBookmarkSet::deleteRow(const ORowSetRow& /*_rDeleteRow*/ ,const connectivity::OSQLTable& /*_xTable*/ )
+{
+ Reference<XResultSetUpdate> xUpd(m_xRowLocate,UNO_QUERY);
+
+ xUpd->deleteRow();
+}
+
+void OBookmarkSet::updateColumn(sal_Int32 nPos, const Reference< XRowUpdate >& _xParameter, const ORowSetValue& _rValue)
+{
+ if(!(_rValue.isBound() && _rValue.isModified()))
+ return;
+
+ if(_rValue.isNull())
+ _xParameter->updateNull(nPos);
+ else
+ {
+
+ switch(_rValue.getTypeKind())
+ {
+ case DataType::DECIMAL:
+ case DataType::NUMERIC:
+ _xParameter->updateNumericObject(nPos,_rValue.makeAny(),m_xSetMetaData->getScale(nPos));
+ break;
+ case DataType::CHAR:
+ case DataType::VARCHAR:
+ _xParameter->updateString(nPos,_rValue.getString());
+ break;
+ case DataType::BIGINT:
+ if ( _rValue.isSigned() )
+ _xParameter->updateLong(nPos,_rValue.getLong());
+ else
+ _xParameter->updateString(nPos,_rValue.getString());
+ break;
+ case DataType::BIT:
+ case DataType::BOOLEAN:
+ _xParameter->updateBoolean(nPos,_rValue.getBool());
+ break;
+ case DataType::TINYINT:
+ if ( _rValue.isSigned() )
+ _xParameter->updateByte(nPos,_rValue.getInt8());
+ else
+ _xParameter->updateShort(nPos,_rValue.getInt16());
+ break;
+ case DataType::SMALLINT:
+ if ( _rValue.isSigned() )
+ _xParameter->updateShort(nPos,_rValue.getInt16());
+ else
+ _xParameter->updateInt(nPos,_rValue.getInt32());
+ break;
+ case DataType::INTEGER:
+ if ( _rValue.isSigned() )
+ _xParameter->updateInt(nPos,_rValue.getInt32());
+ else
+ _xParameter->updateLong(nPos,_rValue.getLong());
+ break;
+ case DataType::FLOAT:
+ _xParameter->updateFloat(nPos,_rValue.getFloat());
+ break;
+ case DataType::DOUBLE:
+ case DataType::REAL:
+ _xParameter->updateDouble(nPos,_rValue.getDouble());
+ break;
+ case DataType::DATE:
+ _xParameter->updateDate(nPos,_rValue.getDate());
+ break;
+ case DataType::TIME:
+ _xParameter->updateTime(nPos,_rValue.getTime());
+ break;
+ case DataType::TIMESTAMP:
+ _xParameter->updateTimestamp(nPos,_rValue.getDateTime());
+ break;
+ case DataType::BINARY:
+ case DataType::VARBINARY:
+ case DataType::LONGVARBINARY:
+ _xParameter->updateBytes(nPos,_rValue.getSequence());
+ break;
+ case DataType::BLOB:
+ case DataType::CLOB:
+ _xParameter->updateObject(nPos,_rValue.getAny());
+ break;
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/api/BookmarkSet.hxx b/dbaccess/source/core/api/BookmarkSet.hxx
new file mode 100644
index 000000000..9863a80ec
--- /dev/null
+++ b/dbaccess/source/core/api/BookmarkSet.hxx
@@ -0,0 +1,57 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include "CacheSet.hxx"
+#include <com/sun/star/sdbcx/XRowLocate.hpp>
+#include <com/sun/star/sdbc/XRowUpdate.hpp>
+
+namespace dbaccess
+{
+ // this set is used when we have a bookmarkable set from the driver
+ class OBookmarkSet : public OCacheSet
+ {
+ css::uno::Reference< css::sdbcx::XRowLocate> m_xRowLocate;
+
+ void updateColumn(sal_Int32 nPos, const css::uno::Reference< css::sdbc::XRowUpdate >& _xParameter, const connectivity::ORowSetValue& _rValue);
+ public:
+ explicit OBookmarkSet(sal_Int32 i_nMaxRows) : OCacheSet(i_nMaxRows)
+ {}
+ virtual ~OBookmarkSet() override
+ {
+ m_xRowLocate = nullptr;
+ }
+
+ virtual void construct(const css::uno::Reference< css::sdbc::XResultSet>& _xDriverSet,const OUString& i_sRowSetFilter) override;
+ virtual void reset(const css::uno::Reference< css::sdbc::XResultSet>& _xDriverSet) override;
+ // css::sdbcx::XRowLocate
+ virtual css::uno::Any getBookmark() override;
+ virtual bool moveToBookmark( const css::uno::Any& bookmark ) override;
+ virtual sal_Int32 compareBookmarks( const css::uno::Any& first, const css::uno::Any& second ) override;
+ virtual bool hasOrderedBookmarks( ) override;
+ virtual sal_Int32 hashBookmark( const css::uno::Any& bookmark ) override;
+ // css::sdbc::XResultSetUpdate
+ virtual void insertRow( const ORowSetRow& _rInsertRow,const connectivity::OSQLTable& _xTable ) override;
+ virtual void updateRow(const ORowSetRow& _rInsertRow,const ORowSetRow& _rOriginalRow,const connectivity::OSQLTable& _xTable ) override;
+ virtual void deleteRow(const ORowSetRow& _rInsertRow,const connectivity::OSQLTable& _xTable ) override;
+ };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/api/CIndexes.cxx b/dbaccess/source/core/api/CIndexes.cxx
new file mode 100644
index 000000000..409d87728
--- /dev/null
+++ b/dbaccess/source/core/api/CIndexes.cxx
@@ -0,0 +1,87 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "CIndexes.hxx"
+
+
+using namespace connectivity;
+using namespace connectivity::sdbcx;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::sdbcx;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::lang;
+using namespace dbaccess;
+using namespace cppu;
+
+
+ObjectType OIndexes::createObject(const OUString& _rName)
+{
+ ObjectType xRet;
+ if ( m_xIndexes.is() && m_xIndexes->hasByName(_rName) )
+ xRet.set(m_xIndexes->getByName(_rName),UNO_QUERY);
+ else
+ xRet = OIndexesHelper::createObject(_rName);
+
+ return xRet;
+}
+
+Reference< XPropertySet > OIndexes::createDescriptor()
+{
+ Reference<XDataDescriptorFactory> xData( m_xIndexes,UNO_QUERY);
+ if(xData.is())
+ return xData->createDataDescriptor();
+ else
+ return OIndexesHelper::createDescriptor();
+}
+
+// XAppend
+ObjectType OIndexes::appendObject( const OUString& _rForName, const Reference< XPropertySet >& descriptor )
+{
+ Reference<XAppend> xData( m_xIndexes,UNO_QUERY);
+ if ( !xData.is() )
+ return OIndexesHelper::appendObject( _rForName, descriptor );
+
+ xData->appendByDescriptor(descriptor);
+ return createObject( _rForName );
+}
+
+// XDrop
+void OIndexes::dropObject(sal_Int32 _nPos, const OUString& _sElementName)
+{
+ if ( m_xIndexes.is() )
+ {
+ Reference<XDrop> xData( m_xIndexes,UNO_QUERY);
+ if ( xData.is() )
+ xData->dropByName(_sElementName);
+ }
+ else
+ OIndexesHelper::dropObject(_nPos,_sElementName);
+}
+
+void OIndexes::disposing()
+{
+ if ( m_xIndexes.is() )
+ clear_NoDispose();
+ else
+ OIndexesHelper::disposing();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/api/CIndexes.hxx b/dbaccess/source/core/api/CIndexes.hxx
new file mode 100644
index 000000000..f20da6cbe
--- /dev/null
+++ b/dbaccess/source/core/api/CIndexes.hxx
@@ -0,0 +1,47 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <connectivity/TIndexes.hxx>
+
+namespace dbaccess
+{
+ class OIndexes : public connectivity::OIndexesHelper
+ {
+ css::uno::Reference< css::container::XNameAccess > m_xIndexes;
+ protected:
+ virtual connectivity::sdbcx::ObjectType createObject(const OUString& _rName) override;
+ virtual css::uno::Reference< css::beans::XPropertySet > createDescriptor() override;
+ virtual connectivity::sdbcx::ObjectType appendObject( const OUString& _rForName, const css::uno::Reference< css::beans::XPropertySet >& descriptor ) override;
+ virtual void dropObject(sal_Int32 _nPos, const OUString& _sElementName) override;
+ public:
+ OIndexes(connectivity::OTableHelper* _pTable,
+ ::osl::Mutex& _rMutex,
+ const std::vector< OUString> &_rVector,
+ const css::uno::Reference< css::container::XNameAccess >& _rxIndexes
+ ) : connectivity::OIndexesHelper(_pTable,_rMutex,_rVector)
+ ,m_xIndexes(_rxIndexes)
+ {}
+
+ virtual void disposing() override;
+ };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/api/CRowSetColumn.cxx b/dbaccess/source/core/api/CRowSetColumn.cxx
new file mode 100644
index 000000000..98435b7c4
--- /dev/null
+++ b/dbaccess/source/core/api/CRowSetColumn.cxx
@@ -0,0 +1,92 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#include <stringconstants.hxx>
+#include <strings.hxx>
+#include "CRowSetColumn.hxx"
+
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::sdb;
+using namespace ::com::sun::star::beans;
+
+namespace dbaccess
+{
+
+ORowSetColumn::ORowSetColumn( const Reference < XResultSetMetaData >& _xMetaData,
+ const Reference < XRow >& _xRow, sal_Int32 _nPos,
+ const Reference< XDatabaseMetaData >& _rxDBMeta,
+ const OUString& _rDescription,
+ const OUString& i_sLabel,
+ const std::function<const ::connectivity::ORowSetValue& (sal_Int32)> &_getValue )
+ :ORowSetDataColumn( _xMetaData, _xRow, nullptr, _nPos, _rxDBMeta, _rDescription, i_sLabel, _getValue )
+{
+}
+
+::cppu::IPropertyArrayHelper* ORowSetColumn::createArrayHelper( ) const
+{
+ css::uno::Sequence< css::beans::Property> aDescriptor
+ {
+ { PROPERTY_CATALOGNAME, PROPERTY_ID_CATALOGNAME, cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::READONLY },
+ { PROPERTY_DISPLAYSIZE, PROPERTY_ID_DISPLAYSIZE, cppu::UnoType<sal_Int32>::get(), css::beans::PropertyAttribute::READONLY },
+ { PROPERTY_ISAUTOINCREMENT, PROPERTY_ID_ISAUTOINCREMENT, cppu::UnoType<bool>::get(), css::beans::PropertyAttribute::READONLY },
+ { PROPERTY_ISCASESENSITIVE, PROPERTY_ID_ISCASESENSITIVE, cppu::UnoType<bool>::get(), css::beans::PropertyAttribute::READONLY },
+ { PROPERTY_ISCURRENCY, PROPERTY_ID_ISCURRENCY, cppu::UnoType<bool>::get(), css::beans::PropertyAttribute::READONLY },
+ { PROPERTY_ISDEFINITELYWRITABLE, PROPERTY_ID_ISDEFINITELYWRITABLE, cppu::UnoType<bool>::get(), css::beans::PropertyAttribute::READONLY },
+ { PROPERTY_ISNULLABLE, PROPERTY_ID_ISNULLABLE, cppu::UnoType<sal_Int32>::get(), css::beans::PropertyAttribute::READONLY },
+ { PROPERTY_ISREADONLY, PROPERTY_ID_ISREADONLY, cppu::UnoType<bool>::get(), css::beans::PropertyAttribute::BOUND },
+ { PROPERTY_ISROWVERSION, PROPERTY_ID_ISROWVERSION, cppu::UnoType<bool>::get(), css::beans::PropertyAttribute::READONLY },
+ { PROPERTY_ISSEARCHABLE, PROPERTY_ID_ISSEARCHABLE, cppu::UnoType<bool>::get(), css::beans::PropertyAttribute::READONLY },
+ { PROPERTY_ISSIGNED, PROPERTY_ID_ISSIGNED, cppu::UnoType<bool>::get(), css::beans::PropertyAttribute::READONLY },
+ { PROPERTY_ISWRITABLE, PROPERTY_ID_ISWRITABLE, cppu::UnoType<bool>::get(), css::beans::PropertyAttribute::READONLY },
+ { PROPERTY_LABEL, PROPERTY_ID_LABEL, cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::READONLY },
+ { PROPERTY_PRECISION, PROPERTY_ID_PRECISION, cppu::UnoType<sal_Int32>::get(), css::beans::PropertyAttribute::READONLY },
+ { PROPERTY_SCALE, PROPERTY_ID_SCALE, cppu::UnoType<sal_Int32>::get(), css::beans::PropertyAttribute::READONLY },
+ { PROPERTY_SCHEMANAME, PROPERTY_ID_SCHEMANAME, cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::READONLY },
+ { PROPERTY_SERVICENAME, PROPERTY_ID_SERVICENAME, cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::READONLY },
+ { PROPERTY_TABLENAME, PROPERTY_ID_TABLENAME, cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::READONLY },
+ { PROPERTY_TYPE, PROPERTY_ID_TYPE, cppu::UnoType<sal_Int32>::get(), css::beans::PropertyAttribute::READONLY },
+ { PROPERTY_TYPENAME, PROPERTY_ID_TYPENAME, cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::READONLY },
+ { PROPERTY_VALUE, PROPERTY_ID_VALUE, cppu::UnoType<Any>::get(), css::beans::PropertyAttribute::READONLY | css::beans::PropertyAttribute::BOUND}
+ };
+
+ Sequence< Property > aRegisteredProperties;
+ describeProperties( aRegisteredProperties );
+
+ return new ::cppu::OPropertyArrayHelper( ::comphelper::concatSequences( aDescriptor, aRegisteredProperties ), false );
+}
+
+::cppu::IPropertyArrayHelper& ORowSetColumn::getInfoHelper()
+{
+ return *static_cast< ::comphelper::OPropertyArrayUsageHelper< ORowSetColumn >* >(this)->getArrayHelper();
+}
+
+void SAL_CALL ORowSetColumn::setFastPropertyValue_NoBroadcast(sal_Int32 nHandle,const Any& rValue )
+{
+ OSL_ENSURE( nHandle != PROPERTY_ID_VALUE, "ORowSetColumn::setFastPropertyValue_NoBroadcast: hmm? This property is marked as READONLY!" );
+ if ( nHandle != PROPERTY_ID_VALUE )
+ ORowSetDataColumn::setFastPropertyValue_NoBroadcast( nHandle, rValue );
+}
+
+} // namespace dbaccess
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/api/CRowSetColumn.hxx b/dbaccess/source/core/api/CRowSetColumn.hxx
new file mode 100644
index 000000000..bc0ae7eed
--- /dev/null
+++ b/dbaccess/source/core/api/CRowSetColumn.hxx
@@ -0,0 +1,49 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "RowSetRow.hxx"
+#include <connectivity/CommonTools.hxx>
+#include <comphelper/proparrhlp.hxx>
+#include "CRowSetDataColumn.hxx"
+
+namespace dbaccess
+{
+ class ORowSetColumn;
+ class ORowSetColumn :public ORowSetDataColumn
+ ,public ::comphelper::OPropertyArrayUsageHelper< ORowSetColumn >
+
+ {
+ public:
+ ORowSetColumn( const css::uno::Reference < css::sdbc::XResultSetMetaData >& _xMetaData,
+ const css::uno::Reference < css::sdbc::XRow >& _xRow,
+ sal_Int32 _nPos,
+ const css::uno::Reference< css::sdbc::XDatabaseMetaData >& _rxDBMeta,
+ const OUString& _rDescription,
+ const OUString& i_sLabel,
+ const std::function<const ::connectivity::ORowSetValue& (sal_Int32)> &_getValue);
+
+ virtual ::cppu::IPropertyArrayHelper* createArrayHelper( ) const override;
+ virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper() override;
+ virtual void SAL_CALL setFastPropertyValue_NoBroadcast( sal_Int32 nHandle,const css::uno::Any& rValue ) override;
+ };
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/api/CRowSetDataColumn.cxx b/dbaccess/source/core/api/CRowSetDataColumn.cxx
new file mode 100644
index 000000000..0dce91848
--- /dev/null
+++ b/dbaccess/source/core/api/CRowSetDataColumn.cxx
@@ -0,0 +1,236 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#include "CRowSetDataColumn.hxx"
+#include <stringconstants.hxx>
+#include <strings.hxx>
+#include <cppuhelper/exc_hlp.hxx>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
+#include <com/sun/star/sdbc/SQLException.hpp>
+
+using namespace dbaccess;
+using namespace comphelper;
+using namespace connectivity;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::util;
+using namespace cppu;
+using namespace osl;
+
+
+ORowSetDataColumn::ORowSetDataColumn( const Reference < XResultSetMetaData >& _xMetaData,
+ const Reference < XRow >& _xRow,
+ const Reference < XRowUpdate >& _xRowUpdate,
+ sal_Int32 _nPos,
+ const Reference< XDatabaseMetaData >& _rxDBMeta,
+ const OUString& _rDescription,
+ const OUString& i_sLabel,
+ const std::function<const ORowSetValue& (sal_Int32)> &_getValue)
+ :ODataColumn(_xMetaData,_xRow,_xRowUpdate,_nPos,_rxDBMeta)
+ ,m_pGetValue(_getValue)
+ ,m_sLabel(i_sLabel)
+ ,m_aDescription(_rDescription)
+{
+ OColumnSettings::registerProperties( *this );
+ registerProperty( PROPERTY_DESCRIPTION, PROPERTY_ID_DESCRIPTION, PropertyAttribute::READONLY, &m_aDescription, cppu::UnoType<decltype(m_aDescription)>::get() );
+}
+
+ORowSetDataColumn::~ORowSetDataColumn()
+{
+}
+
+// comphelper::OPropertyArrayUsageHelper
+::cppu::IPropertyArrayHelper* ORowSetDataColumn::createArrayHelper( ) const
+{
+ css::uno::Sequence< css::beans::Property> aDescriptor
+ {
+ { PROPERTY_CATALOGNAME, PROPERTY_ID_CATALOGNAME, cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::READONLY },
+ { PROPERTY_DISPLAYSIZE, PROPERTY_ID_DISPLAYSIZE, cppu::UnoType<sal_Int32>::get(), css::beans::PropertyAttribute::READONLY },
+ { PROPERTY_ISAUTOINCREMENT, PROPERTY_ID_ISAUTOINCREMENT, cppu::UnoType<bool>::get(), css::beans::PropertyAttribute::READONLY },
+ { PROPERTY_ISCASESENSITIVE, PROPERTY_ID_ISCASESENSITIVE, cppu::UnoType<bool>::get(), css::beans::PropertyAttribute::READONLY },
+ { PROPERTY_ISCURRENCY, PROPERTY_ID_ISCURRENCY, cppu::UnoType<bool>::get(), css::beans::PropertyAttribute::READONLY },
+ { PROPERTY_ISDEFINITELYWRITABLE, PROPERTY_ID_ISDEFINITELYWRITABLE, cppu::UnoType<bool>::get(), css::beans::PropertyAttribute::READONLY },
+ { PROPERTY_ISNULLABLE, PROPERTY_ID_ISNULLABLE, cppu::UnoType<sal_Int32>::get(), css::beans::PropertyAttribute::READONLY },
+ { PROPERTY_ISREADONLY, PROPERTY_ID_ISREADONLY, cppu::UnoType<bool>::get(), css::beans::PropertyAttribute::BOUND },
+ { PROPERTY_ISROWVERSION, PROPERTY_ID_ISROWVERSION, cppu::UnoType<bool>::get(), css::beans::PropertyAttribute::READONLY },
+ { PROPERTY_ISSEARCHABLE, PROPERTY_ID_ISSEARCHABLE, cppu::UnoType<bool>::get(), css::beans::PropertyAttribute::READONLY },
+ { PROPERTY_ISSIGNED, PROPERTY_ID_ISSIGNED, cppu::UnoType<bool>::get(), css::beans::PropertyAttribute::READONLY },
+ { PROPERTY_ISWRITABLE, PROPERTY_ID_ISWRITABLE, cppu::UnoType<bool>::get(), css::beans::PropertyAttribute::READONLY },
+ { PROPERTY_LABEL, PROPERTY_ID_LABEL, cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::READONLY },
+ { PROPERTY_PRECISION, PROPERTY_ID_PRECISION, cppu::UnoType<sal_Int32>::get(), css::beans::PropertyAttribute::READONLY },
+ { PROPERTY_SCALE, PROPERTY_ID_SCALE, cppu::UnoType<sal_Int32>::get(), css::beans::PropertyAttribute::READONLY },
+ { PROPERTY_SCHEMANAME, PROPERTY_ID_SCHEMANAME, cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::READONLY },
+ { PROPERTY_SERVICENAME, PROPERTY_ID_SERVICENAME, cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::READONLY },
+ { PROPERTY_TABLENAME, PROPERTY_ID_TABLENAME, cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::READONLY },
+ { PROPERTY_TYPE, PROPERTY_ID_TYPE, cppu::UnoType<sal_Int32>::get(), css::beans::PropertyAttribute::READONLY },
+ { PROPERTY_TYPENAME, PROPERTY_ID_TYPENAME, cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::READONLY },
+ { PROPERTY_VALUE, PROPERTY_ID_VALUE, cppu::UnoType<Any>::get(), css::beans::PropertyAttribute::BOUND }
+ };
+
+ Sequence< Property > aRegisteredProperties;
+ describeProperties( aRegisteredProperties );
+
+ return new ::cppu::OPropertyArrayHelper( ::comphelper::concatSequences( aDescriptor, aRegisteredProperties ), false );
+}
+
+// cppu::OPropertySetHelper
+::cppu::IPropertyArrayHelper& ORowSetDataColumn::getInfoHelper()
+{
+ return *static_cast< ::comphelper::OPropertyArrayUsageHelper< ORowSetDataColumn >* >(this)->getArrayHelper();
+}
+
+void SAL_CALL ORowSetDataColumn::getFastPropertyValue( Any& rValue, sal_Int32 nHandle ) const
+{
+ if ( PROPERTY_ID_VALUE == nHandle )
+ {
+ try
+ {
+ rValue = m_pGetValue(m_nPos).makeAny();
+ }
+ catch(const SQLException &e)
+ {
+ css::uno::Any anyEx = cppu::getCaughtException();
+ throw WrappedTargetRuntimeException("Could not retrieve column value: " + e.Message,
+ *const_cast<ORowSetDataColumn*>(this),
+ anyEx);
+ }
+ }
+ else if ( PROPERTY_ID_LABEL == nHandle && !m_sLabel.isEmpty() )
+ rValue <<= m_sLabel;
+ else
+ ODataColumn::getFastPropertyValue( rValue, nHandle );
+}
+
+void SAL_CALL ORowSetDataColumn::setFastPropertyValue_NoBroadcast(sal_Int32 nHandle,const Any& rValue )
+{
+ switch( nHandle )
+ {
+ case PROPERTY_ID_VALUE:
+ updateObject(rValue);
+ break;
+ case PROPERTY_ID_ISREADONLY:
+ {
+ bool bVal = false;
+ rValue >>= bVal;
+ m_isReadOnly = bVal;
+ }
+ break;
+ default:
+ ODataColumn::setFastPropertyValue_NoBroadcast( nHandle,rValue );
+ break;
+ }
+}
+
+sal_Bool SAL_CALL ORowSetDataColumn::convertFastPropertyValue( Any & rConvertedValue,
+ Any & rOldValue,
+ sal_Int32 nHandle,
+ const Any& rValue )
+{
+ bool bModified = false;
+ switch( nHandle )
+ {
+ case PROPERTY_ID_VALUE:
+ {
+ rConvertedValue = rValue;
+ getFastPropertyValue(rOldValue, PROPERTY_ID_VALUE);
+ bModified = rConvertedValue != rOldValue;
+ }
+ break;
+ case PROPERTY_ID_ISREADONLY:
+ {
+ rConvertedValue = rValue;
+ getFastPropertyValue(rOldValue, PROPERTY_ID_ISREADONLY);
+ bModified = rConvertedValue != rOldValue;
+ }
+ break;
+ default:
+ bModified = ODataColumn::convertFastPropertyValue(rConvertedValue, rOldValue, nHandle, rValue);
+ break;
+ }
+
+ return bModified;
+}
+
+Sequence< sal_Int8 > ORowSetDataColumn::getImplementationId()
+{
+ return css::uno::Sequence<sal_Int8>();
+}
+
+void ORowSetDataColumn::fireValueChange(const ORowSetValue& _rOldValue)
+{
+ const ORowSetValue &value(m_pGetValue(m_nPos));
+ if ( value != _rOldValue)
+ {
+ sal_Int32 nHandle(PROPERTY_ID_VALUE);
+ m_aOldValue = _rOldValue.makeAny();
+ Any aNew = value.makeAny();
+
+ fire(&nHandle, &aNew, &m_aOldValue, 1, false );
+ }
+}
+
+ORowSetDataColumns::ORowSetDataColumns(
+ bool _bCase,
+ const ::rtl::Reference< ::connectivity::OSQLColumns>& _rColumns,
+ ::cppu::OWeakObject& _rParent,
+ ::osl::Mutex& _rMutex,
+ const std::vector< OUString> &_rVector
+ ) : connectivity::sdbcx::OCollection(_rParent,_bCase,_rMutex,_rVector)
+ ,m_aColumns(_rColumns)
+{
+}
+
+ORowSetDataColumns::~ORowSetDataColumns()
+{
+}
+
+sdbcx::ObjectType ORowSetDataColumns::createObject(const OUString& _rName)
+{
+ connectivity::sdbcx::ObjectType xNamed;
+
+ ::comphelper::UStringMixEqual aCase(isCaseSensitive());
+ ::connectivity::OSQLColumns::Vector::const_iterator first = ::connectivity::find(m_aColumns->begin(),m_aColumns->end(),_rName,aCase);
+ if(first != m_aColumns->end())
+ xNamed = *first;
+
+ return xNamed;
+}
+
+void ORowSetDataColumns::disposing()
+{
+ ORowSetDataColumns_BASE::disposing();
+ m_aColumns = nullptr;
+}
+
+void ORowSetDataColumns::assign(const ::rtl::Reference< ::connectivity::OSQLColumns>& _rColumns,const std::vector< OUString> &_rVector)
+{
+ m_aColumns = _rColumns;
+ reFill(_rVector);
+}
+
+void ORowSetDataColumns::impl_refresh()
+{
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/api/CRowSetDataColumn.hxx b/dbaccess/source/core/api/CRowSetDataColumn.hxx
new file mode 100644
index 000000000..f0efcbf8d
--- /dev/null
+++ b/dbaccess/source/core/api/CRowSetDataColumn.hxx
@@ -0,0 +1,99 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "datacolumn.hxx"
+#include "RowSetRow.hxx"
+#include <columnsettings.hxx>
+
+#include <connectivity/CommonTools.hxx>
+#include <comphelper/proparrhlp.hxx>
+
+#include <functional>
+
+namespace dbaccess
+{
+ class ORowSetDataColumn;
+ typedef ::comphelper::OPropertyArrayUsageHelper<ORowSetDataColumn> ORowSetDataColumn_PROP;
+
+ class ORowSetDataColumn : public ODataColumn,
+ public OColumnSettings,
+ public ORowSetDataColumn_PROP
+ {
+ protected:
+ const std::function<const ::connectivity::ORowSetValue& (sal_Int32)> m_pGetValue;
+ css::uno::Any m_aOldValue;
+ OUString m_sLabel;
+ OUString m_aDescription; // description
+
+ virtual ~ORowSetDataColumn() override;
+ public:
+ ORowSetDataColumn(const css::uno::Reference < css::sdbc::XResultSetMetaData >& _xMetaData,
+ const css::uno::Reference < css::sdbc::XRow >& _xRow,
+ const css::uno::Reference < css::sdbc::XRowUpdate >& _xRowUpdate,
+ sal_Int32 _nPos,
+ const css::uno::Reference< css::sdbc::XDatabaseMetaData >& _rxDBMeta,
+ const OUString& _rDescription,
+ const OUString& i_sLabel,
+ const std::function<const ::connectivity::ORowSetValue& (sal_Int32)> &_getValue);
+
+
+ // css::lang::XTypeProvider
+ virtual css::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId() override;
+ // comphelper::OPropertyArrayUsageHelper
+ virtual ::cppu::IPropertyArrayHelper* createArrayHelper( ) const override;
+
+ // cppu::OPropertySetHelper
+ virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper() override;
+
+ virtual sal_Bool SAL_CALL convertFastPropertyValue( css::uno::Any & rConvertedValue,
+ css::uno::Any & rOldValue,
+ sal_Int32 nHandle,
+ const css::uno::Any& rValue ) override;
+ virtual void SAL_CALL getFastPropertyValue( css::uno::Any& rValue, sal_Int32 nHandle ) const override;
+ virtual void SAL_CALL setFastPropertyValue_NoBroadcast(sal_Int32 nHandle,const css::uno::Any& rValue ) override;
+
+ void fireValueChange(const ::connectivity::ORowSetValue& _rOldValue);
+ protected:
+ using ODataColumn::getFastPropertyValue;
+ };
+
+ typedef connectivity::sdbcx::OCollection ORowSetDataColumns_BASE;
+ class ORowSetDataColumns : public ORowSetDataColumns_BASE
+ {
+ ::rtl::Reference< ::connectivity::OSQLColumns> m_aColumns;
+ protected:
+ virtual connectivity::sdbcx::ObjectType createObject(const OUString& _rName) override;
+ virtual void impl_refresh() override;
+ public:
+ ORowSetDataColumns(
+ bool _bCase,
+ const ::rtl::Reference< ::connectivity::OSQLColumns>& _rColumns,
+ ::cppu::OWeakObject& _rParent,
+ ::osl::Mutex& _rMutex,
+ const std::vector< OUString> &_rVector
+ );
+ virtual ~ORowSetDataColumns() override;
+ // only the name is identical to ::cppu::OComponentHelper
+ virtual void disposing() override;
+ void assign(const ::rtl::Reference< ::connectivity::OSQLColumns>& _rColumns,const std::vector< OUString> &_rVector);
+ };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/api/CacheSet.cxx b/dbaccess/source/core/api/CacheSet.cxx
new file mode 100644
index 000000000..9774877e6
--- /dev/null
+++ b/dbaccess/source/core/api/CacheSet.cxx
@@ -0,0 +1,580 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "CacheSet.hxx"
+#include <core_resource.hxx>
+#include <strings.hrc>
+#include <strings.hxx>
+#include <com/sun/star/container/XIndexAccess.hpp>
+#include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/sdbc/XDatabaseMetaData.hpp>
+#include <com/sun/star/sdbc/XPreparedStatement.hpp>
+#include <com/sun/star/sdbc/ColumnValue.hpp>
+#include <com/sun/star/sdbc/XParameters.hpp>
+#include <com/sun/star/sdbcx/XIndexesSupplier.hpp>
+
+#include <connectivity/dbtools.hxx>
+#include <com/sun/star/io/XInputStream.hpp>
+#include <comphelper/types.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <sal/log.hxx>
+#include <osl/diagnose.h>
+#include <tools/diagnose_ex.h>
+
+using namespace comphelper;
+
+using namespace dbaccess;
+using namespace dbtools;
+using namespace connectivity;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::sdbcx;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::io;
+using namespace ::osl;
+
+
+OCacheSet::OCacheSet(sal_Int32 i_nMaxRows)
+ :m_nMaxRows(i_nMaxRows)
+ ,m_bInserted(false)
+ ,m_bUpdated(false)
+ ,m_bDeleted(false)
+{
+
+}
+
+OUString OCacheSet::getIdentifierQuoteString() const
+{
+ OUString sQuote;
+ if ( m_xConnection.is() )
+ if (auto xMeta = m_xConnection->getMetaData())
+ sQuote = xMeta->getIdentifierQuoteString();
+ return sQuote;
+}
+
+void OCacheSet::construct( const Reference< XResultSet>& _xDriverSet,const OUString &i_sRowSetFilter)
+{
+ OSL_ENSURE(_xDriverSet.is(),"Invalid resultSet");
+
+ m_sRowSetFilter = i_sRowSetFilter;
+
+ if(!_xDriverSet.is())
+ return;
+
+ m_xDriverSet = _xDriverSet;
+ m_xDriverRow.set(_xDriverSet,UNO_QUERY);
+ m_xSetMetaData = Reference<XResultSetMetaDataSupplier>(_xDriverSet,UNO_QUERY_THROW)->getMetaData();
+ if ( m_xSetMetaData.is() )
+ {
+ const sal_Int32 nCount = m_xSetMetaData->getColumnCount();
+ m_aNullable.resize(nCount);
+ m_aSignedFlags.resize(nCount);
+ m_aColumnTypes.resize(nCount);
+ auto pNullableIter = m_aNullable.begin();
+ auto pSignedIter = m_aSignedFlags.begin();
+ auto pColumnIter = m_aColumnTypes.begin();
+ for (sal_Int32 i=1; i <= nCount; ++i,++pSignedIter,++pColumnIter,++pNullableIter)
+ {
+ *pNullableIter = m_xSetMetaData->isNullable(i) != ColumnValue::NO_NULLS;
+ *pSignedIter = m_xSetMetaData->isSigned(i);
+ *pColumnIter = m_xSetMetaData->getColumnType(i);
+ }
+ }
+ Reference< XStatement> xStmt(m_xDriverSet->getStatement(),UNO_QUERY);
+ if(xStmt.is())
+ m_xConnection = xStmt->getConnection();
+ else
+ {
+ Reference< XPreparedStatement> xPrepStmt(m_xDriverSet->getStatement(),UNO_QUERY);
+ if ( xPrepStmt.is() )
+ m_xConnection = xPrepStmt->getConnection();
+ }
+}
+
+OCacheSet::~OCacheSet()
+{
+ try
+ {
+ m_xDriverSet = nullptr;
+ m_xDriverRow = nullptr;
+ m_xSetMetaData = nullptr;
+ m_xConnection = nullptr;
+ }
+ catch(Exception&)
+ {
+ TOOLS_WARN_EXCEPTION("dbaccess", "");
+ }
+ catch(...)
+ {
+ SAL_WARN("dbaccess", "Unknown Exception occurred");
+ }
+
+}
+
+void OCacheSet::fillTableName(const Reference<XPropertySet>& _xTable)
+{
+ OSL_ENSURE(_xTable.is(),"OCacheSet::fillTableName: PropertySet is empty!");
+ if(m_aComposedTableName.isEmpty() && _xTable.is() )
+ {
+ Reference<XDatabaseMetaData> xMeta(m_xConnection->getMetaData());
+ m_aComposedTableName = composeTableName(xMeta
+ ,comphelper::getString(_xTable->getPropertyValue(PROPERTY_CATALOGNAME))
+ ,comphelper::getString(_xTable->getPropertyValue(PROPERTY_SCHEMANAME))
+ ,comphelper::getString(_xTable->getPropertyValue(PROPERTY_NAME))
+ ,true
+ ,::dbtools::EComposeRule::InDataManipulation);
+ }
+}
+
+void OCacheSet::insertRow( const ORowSetRow& _rInsertRow,const connectivity::OSQLTable& _xTable )
+{
+ Reference<XPropertySet> xSet(_xTable,UNO_QUERY);
+ fillTableName(xSet);
+
+ OUStringBuffer aSql("INSERT INTO " + m_aComposedTableName + " ( ");
+
+ // set values and column names
+ OUStringBuffer aValues(" VALUES ( ");
+ OUString aQuote = getIdentifierQuoteString();
+ sal_Int32 i = 1;
+ ORowVector< ORowSetValue >::Vector::const_iterator aIter = _rInsertRow->begin()+1;
+ connectivity::ORowVector< ORowSetValue > ::Vector::iterator aEnd = _rInsertRow->end();
+ for(; aIter != aEnd;++aIter)
+ {
+ aSql.append(::dbtools::quoteName( aQuote,m_xSetMetaData->getColumnName(i++)) + ",");
+ aValues.append("?,");
+ }
+
+ aSql[aSql.getLength() - 1] = ')';
+ aValues[aValues.getLength() - 1] = ')';
+
+ aSql.append(aValues);
+ // now create end execute the prepared statement
+ {
+ Reference< XPreparedStatement > xPrep(m_xConnection->prepareStatement(aSql.makeStringAndClear()));
+ Reference< XParameters > xParameter(xPrep,UNO_QUERY);
+ i = 1;
+ for(aIter = _rInsertRow->begin()+1; aIter != aEnd;++aIter,++i)
+ {
+ if(aIter->isNull())
+ xParameter->setNull(i,aIter->getTypeKind());
+ else
+ setParameter(i,xParameter,*aIter,m_xSetMetaData->getColumnType(i),m_xSetMetaData->getScale(i));
+ }
+
+ m_bInserted = xPrep->executeUpdate() > 0;
+ }
+
+ // TODO set the bookmark in the insert row
+}
+
+void OCacheSet::fillParameters( const ORowSetRow& _rRow
+ ,const connectivity::OSQLTable& _xTable
+ ,OUStringBuffer& _sCondition
+ ,OUStringBuffer& _sParameter
+ ,std::vector< sal_Int32>& _rOrgValues)
+{
+ // use keys and indexes for exact positioning
+ // first the keys
+ Reference<XPropertySet> xSet(_xTable,UNO_QUERY);
+ const Reference<XNameAccess> xPrimaryKeyColumns = getPrimaryKeyColumns_throw(xSet);
+ // second the indexes
+ Reference<XIndexesSupplier> xIndexSup(_xTable,UNO_QUERY);
+ Reference<XIndexAccess> xIndexes;
+ if(xIndexSup.is())
+ xIndexes.set(xIndexSup->getIndexes(),UNO_QUERY);
+
+ Reference<XPropertySet> xIndexColsSup;
+ std::vector< Reference<XNameAccess> > aAllIndexColumns;
+ if(xIndexes.is())
+ {
+ for(sal_Int32 j=0;j<xIndexes->getCount();++j)
+ {
+ xIndexColsSup.set(xIndexes->getByIndex(j),UNO_QUERY);
+ if( xIndexColsSup.is()
+ && comphelper::getBOOL(xIndexColsSup->getPropertyValue(PROPERTY_ISUNIQUE))
+ && !comphelper::getBOOL(xIndexColsSup->getPropertyValue(PROPERTY_ISPRIMARYKEYINDEX))
+ )
+ aAllIndexColumns.push_back(Reference<XColumnsSupplier>(xIndexColsSup,UNO_QUERY_THROW)->getColumns());
+ }
+ }
+
+ OUString aColumnName;
+
+ static const char aAnd[] = " AND ";
+
+ OUString aQuote = getIdentifierQuoteString();
+
+ sal_Int32 nCheckCount = 1; // index for the original values
+ sal_Int32 i = 1;
+
+ OUString sIsNull(" IS NULL");
+ OUString sParam(" = ?");
+ ORowVector< ORowSetValue >::Vector::const_iterator aIter = _rRow->begin()+1;
+ ORowVector< ORowSetValue >::Vector::const_iterator aEnd = _rRow->end();
+ for(; aIter != aEnd;++aIter,++nCheckCount,++i)
+ {
+ aColumnName = m_xSetMetaData->getColumnName(i);
+ if(xPrimaryKeyColumns.is() && xPrimaryKeyColumns->hasByName(aColumnName))
+ {
+ _sCondition.append(::dbtools::quoteName( aQuote,aColumnName));
+ if(aIter->isNull())
+ _sCondition.append(sIsNull);
+ else
+ _sCondition.append(sParam);
+ _sCondition.append(aAnd);
+ _rOrgValues.push_back(nCheckCount);
+
+ }
+ for (auto const& indexColumn : aAllIndexColumns)
+ {
+ if(indexColumn->hasByName(aColumnName))
+ {
+ _sCondition.append(::dbtools::quoteName( aQuote,aColumnName));
+ if(aIter->isNull())
+ _sCondition.append(sIsNull);
+ else
+ _sCondition.append(sParam);
+ _sCondition.append(aAnd);
+ _rOrgValues.push_back(nCheckCount);
+ break;
+ }
+ }
+ if(aIter->isModified())
+ {
+ _sParameter.append(::dbtools::quoteName( aQuote,aColumnName) + "?,");
+ }
+ }
+}
+
+void OCacheSet::updateRow(const ORowSetRow& _rInsertRow ,const ORowSetRow& _rOriginalRow,const connectivity::OSQLTable& _xTable )
+{
+ Reference<XPropertySet> xSet(_xTable,UNO_QUERY);
+ fillTableName(xSet);
+
+ OUStringBuffer aSql("UPDATE " + m_aComposedTableName + " SET ");
+ // list all columns that should be set
+
+ OUStringBuffer aCondition;
+ std::vector< sal_Int32> aOrgValues;
+ fillParameters(_rInsertRow,_xTable,aCondition,aSql,aOrgValues);
+ aSql[aSql.getLength() - 1] = ' ';
+ if ( !aCondition.isEmpty() )
+ {
+ aCondition.setLength(aCondition.getLength()-5);
+
+ aSql.append(" WHERE " + aCondition);
+ }
+ else
+ ::dbtools::throwSQLException(
+ DBA_RES( RID_STR_NO_UPDATE_MISSING_CONDITION ), StandardSQLState::GENERAL_ERROR, *this );
+
+ // now create end execute the prepared statement
+ Reference< XPreparedStatement > xPrep(m_xConnection->prepareStatement(aSql.makeStringAndClear()));
+ Reference< XParameters > xParameter(xPrep,UNO_QUERY);
+ sal_Int32 i = 1;
+ connectivity::ORowVector< ORowSetValue > ::Vector::iterator aEnd = _rInsertRow->end();
+ for(ORowVector< ORowSetValue >::Vector::const_iterator aIter = _rInsertRow->begin()+1; aIter != aEnd;++aIter)
+ {
+ if(aIter->isModified())
+ {
+ setParameter(i,xParameter,*aIter,m_xSetMetaData->getColumnType(i),m_xSetMetaData->getScale(i));
+ ++i;
+ }
+ }
+ for (auto const& orgValue : aOrgValues)
+ {
+ setParameter(i,xParameter,(*_rOriginalRow)[orgValue],m_xSetMetaData->getColumnType(i),m_xSetMetaData->getScale(i));
+ ++i;
+ }
+
+ m_bUpdated = xPrep->executeUpdate() > 0;
+}
+
+void OCacheSet::deleteRow(const ORowSetRow& _rDeleteRow ,const connectivity::OSQLTable& _xTable )
+{
+ Reference<XPropertySet> xSet(_xTable,UNO_QUERY);
+ fillTableName(xSet);
+
+ OUStringBuffer aSql("DELETE FROM " + m_aComposedTableName + " WHERE ");
+
+ // use keys and indexes for exact positioning
+ Reference<XIndexesSupplier> xIndexSup(_xTable,UNO_QUERY);
+ Reference<XIndexAccess> xIndexes;
+ if(xIndexSup.is())
+ xIndexes.set(xIndexSup->getIndexes(),UNO_QUERY);
+
+ // Reference<XColumnsSupplier>
+ Reference<XPropertySet> xIndexColsSup;
+ std::vector< Reference<XNameAccess> > aAllIndexColumns;
+ if(xIndexes.is())
+ {
+ for(sal_Int32 j=0;j<xIndexes->getCount();++j)
+ {
+ xIndexColsSup.set(xIndexes->getByIndex(j),UNO_QUERY);
+ if( xIndexColsSup.is()
+ && comphelper::getBOOL(xIndexColsSup->getPropertyValue(PROPERTY_ISUNIQUE))
+ && !comphelper::getBOOL(xIndexColsSup->getPropertyValue(PROPERTY_ISPRIMARYKEYINDEX))
+ )
+ aAllIndexColumns.push_back(Reference<XColumnsSupplier>(xIndexColsSup,UNO_QUERY_THROW)->getColumns());
+ }
+ }
+
+ OUStringBuffer aColumnName;
+ std::vector< sal_Int32> aOrgValues;
+ fillParameters(_rDeleteRow,_xTable,aSql,aColumnName,aOrgValues);
+
+ aSql.setLength(aSql.getLength()-5);
+
+ // now create and execute the prepared statement
+ Reference< XPreparedStatement > xPrep(m_xConnection->prepareStatement(aSql.makeStringAndClear()));
+ Reference< XParameters > xParameter(xPrep,UNO_QUERY);
+ sal_Int32 i = 1;
+ for (auto const& orgValue : aOrgValues)
+ {
+ setParameter(i,xParameter,(*_rDeleteRow)[orgValue],m_xSetMetaData->getColumnType(i),m_xSetMetaData->getScale(i));
+ ++i;
+ }
+
+ m_bDeleted = xPrep->executeUpdate() > 0;
+}
+
+void OCacheSet::setParameter(sal_Int32 nPos
+ ,const Reference< XParameters >& _xParameter
+ ,const ORowSetValue& _rValue
+ ,sal_Int32 _nType
+ ,sal_Int32 _nScale)
+{
+ sal_Int32 nType = ( _nType != DataType::OTHER ) ? _nType : _rValue.getTypeKind();
+ ::dbtools::setObjectWithInfo(_xParameter,nPos,_rValue,nType,_nScale);
+}
+
+void OCacheSet::fillValueRow(ORowSetRow& _rRow,sal_Int32 _nPosition)
+{
+ Any aBookmark = getBookmark();
+ if(!aBookmark.hasValue())
+ aBookmark <<= _nPosition;
+
+ connectivity::ORowVector< ORowSetValue >::Vector::iterator aIter = _rRow->begin();
+ connectivity::ORowVector< ORowSetValue >::Vector::iterator aEnd = _rRow->end();
+ (*aIter) = aBookmark;
+ ++aIter;
+ for(sal_Int32 i=1;aIter != aEnd;++aIter,++i)
+ {
+ aIter->setSigned(m_aSignedFlags[i-1]);
+ aIter->fill(i, m_aColumnTypes[i-1], this);
+ }
+}
+
+sal_Bool SAL_CALL OCacheSet::wasNull( )
+{
+ return m_xDriverRow->wasNull();
+}
+
+OUString SAL_CALL OCacheSet::getString( sal_Int32 columnIndex )
+{
+ return m_xDriverRow->getString(columnIndex);
+}
+
+sal_Bool SAL_CALL OCacheSet::getBoolean( sal_Int32 columnIndex )
+{
+ return m_xDriverRow->getBoolean(columnIndex);
+}
+
+sal_Int8 SAL_CALL OCacheSet::getByte( sal_Int32 columnIndex )
+{
+ return m_xDriverRow->getByte(columnIndex);
+}
+
+sal_Int16 SAL_CALL OCacheSet::getShort( sal_Int32 columnIndex )
+{
+ return m_xDriverRow->getShort(columnIndex);
+}
+
+sal_Int32 SAL_CALL OCacheSet::getInt( sal_Int32 columnIndex )
+{
+ return m_xDriverRow->getInt(columnIndex);
+}
+
+sal_Int64 SAL_CALL OCacheSet::getLong( sal_Int32 columnIndex )
+{
+ return m_xDriverRow->getLong(columnIndex);
+}
+
+float SAL_CALL OCacheSet::getFloat( sal_Int32 columnIndex )
+{
+ return m_xDriverRow->getFloat(columnIndex);
+}
+
+double SAL_CALL OCacheSet::getDouble( sal_Int32 columnIndex )
+{
+ return m_xDriverRow->getDouble(columnIndex);
+}
+
+Sequence< sal_Int8 > SAL_CALL OCacheSet::getBytes( sal_Int32 columnIndex )
+{
+ return m_xDriverRow->getBytes(columnIndex);
+}
+
+css::util::Date SAL_CALL OCacheSet::getDate( sal_Int32 columnIndex )
+{
+ return m_xDriverRow->getDate(columnIndex);
+}
+
+css::util::Time SAL_CALL OCacheSet::getTime( sal_Int32 columnIndex )
+{
+ return m_xDriverRow->getTime(columnIndex);
+}
+
+css::util::DateTime SAL_CALL OCacheSet::getTimestamp( sal_Int32 columnIndex )
+{
+ return m_xDriverRow->getTimestamp(columnIndex);
+}
+
+Reference< css::io::XInputStream > SAL_CALL OCacheSet::getBinaryStream( sal_Int32 columnIndex )
+{
+ return m_xDriverRow->getBinaryStream(columnIndex);
+}
+
+Reference< css::io::XInputStream > SAL_CALL OCacheSet::getCharacterStream( sal_Int32 columnIndex )
+{
+ return m_xDriverRow->getCharacterStream(columnIndex);
+}
+
+Any SAL_CALL OCacheSet::getObject( sal_Int32 columnIndex, const Reference< css::container::XNameAccess >& typeMap )
+{
+ return m_xDriverRow->getObject(columnIndex,typeMap);
+}
+
+Reference< XRef > SAL_CALL OCacheSet::getRef( sal_Int32 columnIndex )
+{
+ return m_xDriverRow->getRef(columnIndex);
+}
+
+Reference< XBlob > SAL_CALL OCacheSet::getBlob( sal_Int32 columnIndex )
+{
+ return m_xDriverRow->getBlob(columnIndex);
+}
+
+Reference< XClob > SAL_CALL OCacheSet::getClob( sal_Int32 columnIndex )
+{
+ return m_xDriverRow->getClob(columnIndex);
+}
+
+Reference< XArray > SAL_CALL OCacheSet::getArray( sal_Int32 columnIndex )
+{
+ return m_xDriverRow->getArray(columnIndex);
+}
+
+// XResultSet
+bool OCacheSet::next()
+{
+ m_bInserted = m_bUpdated = m_bDeleted = false;
+ return m_xDriverSet->next();
+}
+
+void OCacheSet::beforeFirst( )
+{
+ m_bInserted = m_bUpdated = m_bDeleted = false;
+ m_xDriverSet->beforeFirst();
+}
+
+void OCacheSet::afterLast( )
+{
+ m_bInserted = m_bUpdated = m_bDeleted = false;
+ m_xDriverSet->afterLast();
+}
+
+bool OCacheSet::first()
+{
+ m_bInserted = m_bUpdated = m_bDeleted = false;
+ return m_xDriverSet->first();
+}
+
+bool OCacheSet::last()
+{
+ m_bInserted = m_bUpdated = m_bDeleted = false;
+ return m_xDriverSet->last();
+}
+
+sal_Int32 OCacheSet::getRow( )
+{
+ return m_xDriverSet->getRow();
+}
+
+bool OCacheSet::absolute( sal_Int32 row )
+{
+ m_bInserted = m_bUpdated = m_bDeleted = false;
+ return m_xDriverSet->absolute(row);
+}
+
+bool OCacheSet::previous( )
+{
+ m_bInserted = m_bUpdated = m_bDeleted = false;
+ return m_xDriverSet->previous();
+}
+
+void OCacheSet::refreshRow( )
+{
+ m_xDriverSet->refreshRow();
+}
+
+bool OCacheSet::rowUpdated( )
+{
+ return m_xDriverSet->rowUpdated();
+}
+
+bool OCacheSet::rowInserted( )
+{
+ return m_xDriverSet->rowInserted();
+}
+
+bool OCacheSet::rowDeleted( )
+{
+ return m_xDriverSet->rowDeleted();
+}
+
+bool OCacheSet::isResultSetChanged() const
+{
+ return false;
+}
+
+void OCacheSet::mergeColumnValues(sal_Int32 i_nColumnIndex,ORowSetValueVector::Vector& /*io_aInsertRow*/,ORowSetValueVector::Vector& /*io_aRow*/,std::vector<sal_Int32>& o_aChangedColumns)
+{
+ o_aChangedColumns.push_back(i_nColumnIndex);
+}
+
+bool OCacheSet::columnValuesUpdated(ORowSetValueVector::Vector& /*io_aCachedRow*/,const ORowSetValueVector::Vector& /*io_aRow*/)
+{
+ return false;
+}
+
+bool OCacheSet::updateColumnValues(const ORowSetValueVector::Vector& /*io_aCachedRow*/,ORowSetValueVector::Vector& /*io_aRow*/,const std::vector<sal_Int32>& /*i_aChangedColumns*/)
+{
+ return true;
+}
+
+void OCacheSet::fillMissingValues(ORowSetValueVector::Vector& /*io_aRow*/) const
+{
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/api/CacheSet.hxx b/dbaccess/source/core/api/CacheSet.hxx
new file mode 100644
index 000000000..1006b9662
--- /dev/null
+++ b/dbaccess/source/core/api/CacheSet.hxx
@@ -0,0 +1,172 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <com/sun/star/sdbc/XRow.hpp>
+#include <com/sun/star/sdbc/XResultSetMetaData.hpp>
+#include <com/sun/star/sdbc/XResultSet.hpp>
+#include <com/sun/star/sdbc/XConnection.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include "RowSetRow.hxx"
+#include <cppuhelper/implbase.hxx>
+
+#include <vector>
+
+namespace com::sun::star::sdbc{ class XParameters; }
+
+namespace dbaccess
+{
+ class OCacheSet : public ::cppu::WeakImplHelper< css::sdbc::XRow>
+ {
+ protected:
+ css::uno::Reference< css::sdbc::XResultSet> m_xDriverSet;
+ css::uno::Reference< css::sdbc::XRow> m_xDriverRow;
+ css::uno::Reference< css::sdbc::XResultSetMetaData> m_xSetMetaData;
+ css::uno::Reference< css::sdbc::XConnection> m_xConnection;
+
+ std::vector<bool> m_aNullable;
+ std::vector<bool> m_aSignedFlags;
+ std::vector<sal_Int32> m_aColumnTypes;
+ OUString m_aComposedTableName;
+ sal_Int32 m_nMaxRows;
+ bool m_bInserted;
+ bool m_bUpdated;
+ bool m_bDeleted;
+ OUString m_sRowSetFilter;
+
+ explicit OCacheSet(sal_Int32 i_nMaxRows);
+ virtual ~OCacheSet() override;
+
+ static void setParameter(sal_Int32 nPos
+ ,const css::uno::Reference< css::sdbc::XParameters >& _xParameter
+ ,const connectivity::ORowSetValue& _rValue
+ ,sal_Int32 _nType
+ ,sal_Int32 _nScale
+ );
+ void fillParameters( const ORowSetRow& _rRow
+ ,const connectivity::OSQLTable& _xTable
+ ,OUStringBuffer& _sCondition
+ ,OUStringBuffer& _sParameter
+ ,std::vector< sal_Int32>& _rOrgValues);
+ /// @throws css::sdbc::SQLException
+ /// @throws css::uno::RuntimeException
+ void fillTableName(const css::uno::Reference< css::beans::XPropertySet>& _xTable);
+
+ OUString getIdentifierQuoteString() const;
+ public:
+
+ // late constructor
+ virtual void construct(const css::uno::Reference< css::sdbc::XResultSet>& _xDriverSet,const OUString& i_sRowSetFilter);
+ virtual void fillValueRow(ORowSetRow& _rRow,sal_Int32 _nPosition);
+
+ // css::sdbc::XRow
+ virtual sal_Bool SAL_CALL wasNull( ) override;
+ virtual OUString SAL_CALL getString( sal_Int32 columnIndex ) override;
+ virtual sal_Bool SAL_CALL getBoolean( sal_Int32 columnIndex ) override;
+ virtual sal_Int8 SAL_CALL getByte( sal_Int32 columnIndex ) override;
+ virtual sal_Int16 SAL_CALL getShort( sal_Int32 columnIndex ) override;
+ virtual sal_Int32 SAL_CALL getInt( sal_Int32 columnIndex ) override;
+ virtual sal_Int64 SAL_CALL getLong( sal_Int32 columnIndex ) override;
+ virtual float SAL_CALL getFloat( sal_Int32 columnIndex ) override;
+ virtual double SAL_CALL getDouble( sal_Int32 columnIndex ) override;
+ virtual css::uno::Sequence< sal_Int8 > SAL_CALL getBytes( sal_Int32 columnIndex ) override;
+ virtual css::util::Date SAL_CALL getDate( sal_Int32 columnIndex ) override;
+ virtual css::util::Time SAL_CALL getTime( sal_Int32 columnIndex ) override;
+ virtual css::util::DateTime SAL_CALL getTimestamp( sal_Int32 columnIndex ) override;
+ virtual css::uno::Reference< css::io::XInputStream > SAL_CALL getBinaryStream( sal_Int32 columnIndex ) override;
+ virtual css::uno::Reference< css::io::XInputStream > SAL_CALL getCharacterStream( sal_Int32 columnIndex ) override;
+ virtual css::uno::Any SAL_CALL getObject( sal_Int32 columnIndex, const css::uno::Reference< css::container::XNameAccess >& typeMap ) override;
+ virtual css::uno::Reference< css::sdbc::XRef > SAL_CALL getRef( sal_Int32 columnIndex ) override;
+ virtual css::uno::Reference< css::sdbc::XBlob > SAL_CALL getBlob( sal_Int32 columnIndex ) override;
+ virtual css::uno::Reference< css::sdbc::XClob > SAL_CALL getClob( sal_Int32 columnIndex ) override;
+ virtual css::uno::Reference< css::sdbc::XArray > SAL_CALL getArray( sal_Int32 columnIndex ) override;
+ // css::sdbc::XResultSet
+ /// @throws css::sdbc::SQLException
+ /// @throws css::uno::RuntimeException
+ virtual bool next();
+ /// @throws css::sdbc::SQLException
+ /// @throws css::uno::RuntimeException
+ virtual void beforeFirst( );
+ /// @throws css::sdbc::SQLException
+ /// @throws css::uno::RuntimeException
+ virtual void afterLast( );
+ /// @throws css::sdbc::SQLException
+ /// @throws css::uno::RuntimeException
+ virtual bool first();
+ /// @throws css::sdbc::SQLException
+ /// @throws css::uno::RuntimeException
+ virtual bool last();
+ /// @throws css::sdbc::SQLException
+ /// @throws css::uno::RuntimeException
+ virtual sal_Int32 getRow( );
+ /// @throws css::sdbc::SQLException
+ /// @throws css::uno::RuntimeException
+ virtual bool absolute( sal_Int32 row );
+ /// @throws css::sdbc::SQLException
+ /// @throws css::uno::RuntimeException
+ virtual bool previous( );
+ /// @throws css::sdbc::SQLException
+ /// @throws css::uno::RuntimeException
+ virtual void refreshRow( );
+ /// @throws css::sdbc::SQLException
+ /// @throws css::uno::RuntimeException
+ virtual bool rowUpdated( );
+ /// @throws css::sdbc::SQLException
+ /// @throws css::uno::RuntimeException
+ virtual bool rowInserted( );
+ /// @throws css::sdbc::SQLException
+ /// @throws css::uno::RuntimeException
+ virtual bool rowDeleted( );
+ // css::sdbcx::XRowLocate
+ /// @throws css::sdbc::SQLException
+ /// @throws css::uno::RuntimeException
+ virtual css::uno::Any getBookmark() = 0;
+ /// @throws css::sdbc::SQLException
+ /// @throws css::uno::RuntimeException
+ virtual bool moveToBookmark( const css::uno::Any& bookmark ) = 0;
+ /// @throws css::sdbc::SQLException
+ /// @throws css::uno::RuntimeException
+ virtual sal_Int32 compareBookmarks( const css::uno::Any& first, const css::uno::Any& second ) = 0;
+ /// @throws css::sdbc::SQLException
+ /// @throws css::uno::RuntimeException
+ virtual bool hasOrderedBookmarks( ) = 0;
+ /// @throws css::sdbc::SQLException
+ /// @throws css::uno::RuntimeException
+ virtual sal_Int32 hashBookmark( const css::uno::Any& bookmark ) = 0;
+ // css::sdbc::XResultSetUpdate
+ /// @throws css::sdbc::SQLException
+ /// @throws css::uno::RuntimeException
+ virtual void insertRow( const ORowSetRow& _rInsertRow,const connectivity::OSQLTable& _xTable );
+ /// @throws css::sdbc::SQLException
+ /// @throws css::uno::RuntimeException
+ virtual void updateRow( const ORowSetRow& _rInsertRow,const ORowSetRow& _rOriginalRow,const connectivity::OSQLTable& _xTable );
+ /// @throws css::sdbc::SQLException
+ /// @throws css::uno::RuntimeException
+ virtual void deleteRow( const ORowSetRow& _rDeleteRow,const connectivity::OSQLTable& _xTable ) = 0;
+
+ virtual bool isResultSetChanged() const;
+ virtual void reset(const css::uno::Reference< css::sdbc::XResultSet>& _xDriverSet) = 0;
+ virtual void mergeColumnValues(sal_Int32 i_nColumnIndex,ORowSetValueVector::Vector& io_aInsertRow,ORowSetValueVector::Vector& io_aRow,std::vector<sal_Int32>& o_aChangedColumns);
+ virtual bool columnValuesUpdated(ORowSetValueVector::Vector& o_aCachedRow,const ORowSetValueVector::Vector& i_aRow);
+ virtual bool updateColumnValues(const ORowSetValueVector::Vector& io_aCachedRow,ORowSetValueVector::Vector& io_aRow,const std::vector<sal_Int32>& i_aChangedColumns);
+ virtual void fillMissingValues(ORowSetValueVector::Vector& io_aRow) const;
+ };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/api/FilteredContainer.cxx b/dbaccess/source/core/api/FilteredContainer.cxx
new file mode 100644
index 000000000..a5cf0b156
--- /dev/null
+++ b/dbaccess/source/core/api/FilteredContainer.cxx
@@ -0,0 +1,459 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <strings.hxx>
+#include <FilteredContainer.hxx>
+#include <RefreshListener.hxx>
+#include <sdbcoretools.hxx>
+#include <com/sun/star/sdbc/SQLException.hpp>
+#include <com/sun/star/sdbc/XRow.hpp>
+#include <comphelper/types.hxx>
+#include <connectivity/dbtools.hxx>
+#include <tools/wldcrd.hxx>
+#include <tools/diagnose_ex.h>
+#include <optional>
+#include <sal/log.hxx>
+
+namespace dbaccess
+{
+ using namespace dbtools;
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::lang;
+ using namespace ::com::sun::star::beans;
+ using namespace ::com::sun::star::sdbc;
+ using namespace ::com::sun::star::sdb;
+ using namespace ::com::sun::star::sdbcx;
+ using namespace ::com::sun::star::util;
+ using namespace ::com::sun::star::container;
+ using namespace ::osl;
+ using namespace ::comphelper;
+ using namespace ::cppu;
+ using namespace ::connectivity::sdbcx;
+
+/** creates a vector of WildCards and reduce the _rTableFilter of the length of WildCards
+*/
+static sal_Int32 createWildCardVector(Sequence< OUString >& _rTableFilter, std::vector< WildCard >& _rOut)
+{
+ // for wildcard search : remove all table filters which are a wildcard expression and build a WildCard
+ // for them
+ OUString* pTableFilters = _rTableFilter.getArray();
+ OUString* pEnd = pTableFilters + _rTableFilter.getLength();
+ sal_Int32 nShiftPos = 0;
+ for (sal_Int32 i=0; pEnd != pTableFilters; ++pTableFilters,++i)
+ {
+ if (pTableFilters->indexOf('%') != -1)
+ {
+ _rOut.emplace_back(pTableFilters->replace('%', '*'));
+ }
+ else
+ {
+ if (nShiftPos != i)
+ {
+ _rTableFilter.getArray()[nShiftPos] = _rTableFilter.getArray()[i];
+ }
+ ++nShiftPos;
+ }
+ }
+ // now aTableFilter contains nShiftPos non-wc-strings and aWCSearch all wc-strings
+ _rTableFilter.realloc(nShiftPos);
+ return nShiftPos;
+}
+
+ static bool lcl_isElementAllowed( const OUString& _rName,
+ const Sequence< OUString >& _rTableFilter,
+ const std::vector< WildCard >& _rWCSearch )
+ {
+ sal_Int32 nTableFilterLen = _rTableFilter.getLength();
+
+ const OUString* tableFilter = _rTableFilter.getConstArray();
+ const OUString* tableFilterEnd = _rTableFilter.getConstArray() + nTableFilterLen;
+ bool bFilterMatch = std::find( tableFilter, tableFilterEnd, _rName ) != tableFilterEnd;
+ // the table is allowed to "pass" if we had no filters at all or any of the non-wildcard filters matches
+ if (!bFilterMatch && !_rWCSearch.empty())
+ { // or if one of the wildcard expression matches
+ for (auto const& elem : _rWCSearch)
+ {
+ bFilterMatch = elem.Matches( _rName );
+ if (bFilterMatch)
+ break;
+ }
+ }
+
+ return bFilterMatch;
+ }
+
+ typedef ::std::optional< OUString > OptionalString;
+
+ namespace {
+
+ struct TableInfo
+ {
+ OptionalString sComposedName;
+ OptionalString sType;
+ OptionalString sCatalog;
+ OptionalString sSchema;
+ OptionalString sName;
+
+ explicit TableInfo( const OUString& _composedName )
+ : sComposedName( _composedName )
+ {
+ }
+
+ TableInfo( const OUString& _catalog, const OUString& _schema, const OUString& _name,
+ const OUString& _type )
+ :sType( _type )
+ ,sCatalog( _catalog )
+ ,sSchema( _schema )
+ ,sName( _name )
+ {
+ }
+ };
+
+ }
+
+ typedef std::vector< TableInfo > TableInfos;
+
+ static void lcl_ensureComposedName( TableInfo& _io_tableInfo, const Reference< XDatabaseMetaData >& _metaData )
+ {
+ if ( !_metaData.is() )
+ throw RuntimeException("lcl_ensureComposedName: _metaData cannot be null!");
+
+ if ( !_io_tableInfo.sComposedName )
+ {
+ OSL_ENSURE( !!_io_tableInfo.sCatalog && !!_io_tableInfo.sSchema && !!_io_tableInfo.sName, "lcl_ensureComposedName: How should I composed the name from nothing!?" );
+
+ _io_tableInfo.sComposedName = OptionalString(
+ composeTableName( _metaData, *_io_tableInfo.sCatalog, *_io_tableInfo.sSchema, *_io_tableInfo.sName,
+ false, ::dbtools::EComposeRule::InDataManipulation )
+ );
+ }
+ }
+
+ static void lcl_ensureType( TableInfo& _io_tableInfo, const Reference< XDatabaseMetaData >& _metaData, const Reference< XNameAccess >& _masterContainer )
+ {
+ if ( !!_io_tableInfo.sType )
+ return;
+
+ lcl_ensureComposedName( _io_tableInfo, _metaData );
+
+ if ( !_masterContainer.is() )
+ throw RuntimeException("lcl_ensureType: _masterContainer cannot be null!");
+
+ OUString sTypeName;
+ try
+ {
+ Reference< XPropertySet > xTable( _masterContainer->getByName( *_io_tableInfo.sComposedName ), UNO_QUERY_THROW );
+ OSL_VERIFY( xTable->getPropertyValue( PROPERTY_TYPE ) >>= sTypeName );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ _io_tableInfo.sType = OptionalString( sTypeName );
+ }
+
+ static ::std::vector< OUString> lcl_filter( TableInfos&& _unfilteredTables,
+ const Sequence< OUString >& _tableFilter, const Sequence< OUString >& _tableTypeFilter,
+ const Reference< XDatabaseMetaData >& _metaData, const Reference< XNameAccess >& _masterContainer )
+ {
+ TableInfos aFilteredTables;
+
+ // first, filter for the table names
+ sal_Int32 nTableFilterCount = _tableFilter.getLength();
+ bool dontFilterTableNames = ( ( nTableFilterCount == 1 ) && _tableFilter[0] == "%" );
+ if( dontFilterTableNames )
+ {
+ aFilteredTables = std::move(_unfilteredTables);
+ }
+ else
+ {
+ // for wildcard search : remove all table filters which are a wildcard expression and build a WildCard
+ // for them
+ std::vector< WildCard > aWildCardTableFilter;
+ Sequence< OUString > aNonWildCardTableFilter = _tableFilter;
+ nTableFilterCount = createWildCardVector( aNonWildCardTableFilter, aWildCardTableFilter );
+
+ TableInfos aUnfilteredTables( std::move(_unfilteredTables) );
+ aUnfilteredTables.reserve( nTableFilterCount + ( aWildCardTableFilter.size() * 10 ) );
+
+ for (auto & unfilteredTable : aUnfilteredTables)
+ {
+ lcl_ensureComposedName(unfilteredTable, _metaData);
+
+ if ( lcl_isElementAllowed( *unfilteredTable.sComposedName, aNonWildCardTableFilter, aWildCardTableFilter ) )
+ aFilteredTables.push_back(unfilteredTable);
+ }
+ }
+
+ // second, filter for the table types
+ sal_Int32 nTableTypeFilterCount = _tableTypeFilter.getLength();
+ bool dontFilterTableTypes = ( ( nTableTypeFilterCount == 1 ) && _tableTypeFilter[0] == "%" );
+ dontFilterTableTypes = dontFilterTableTypes || ( nTableTypeFilterCount == 0 );
+ // (for TableTypeFilter, unlike TableFilter, "empty" means "do not filter at all")
+ if ( !dontFilterTableTypes )
+ {
+ TableInfos aUnfilteredTables;
+ aUnfilteredTables.swap( aFilteredTables );
+
+ const OUString* pTableTypeFilterBegin = _tableTypeFilter.getConstArray();
+ const OUString* pTableTypeFilterEnd = pTableTypeFilterBegin + _tableTypeFilter.getLength();
+
+ for (auto & unfilteredTable : aUnfilteredTables)
+ {
+ // ensure that we know the table type
+ lcl_ensureType( unfilteredTable, _metaData, _masterContainer );
+
+ if ( std::find( pTableTypeFilterBegin, pTableTypeFilterEnd, *unfilteredTable.sType ) != pTableTypeFilterEnd )
+ aFilteredTables.push_back(unfilteredTable);
+ }
+ }
+
+ ::std::vector< OUString> aReturn;
+ for (auto & filteredTable : aFilteredTables)
+ {
+ lcl_ensureComposedName(filteredTable, _metaData);
+ aReturn.push_back(*filteredTable.sComposedName);
+ }
+ return aReturn;
+ }
+
+ // OViewContainer
+ OFilteredContainer::OFilteredContainer(::cppu::OWeakObject& _rParent,
+ ::osl::Mutex& _rMutex,
+ const Reference< XConnection >& _xCon,
+ bool _bCase,
+ IRefreshListener* _pRefreshListener,
+ std::atomic<std::size_t>& _nInAppend)
+ :OCollection(_rParent,_bCase,_rMutex,std::vector< OUString>())
+ ,m_bConstructed(false)
+ ,m_pRefreshListener(_pRefreshListener)
+ ,m_nInAppend(_nInAppend)
+ ,m_xConnection(_xCon)
+ {
+ }
+
+ void OFilteredContainer::construct(const Reference< XNameAccess >& _rxMasterContainer,
+ const Sequence< OUString >& _rTableFilter,
+ const Sequence< OUString >& _rTableTypeFilter)
+ {
+ try
+ {
+ Reference<XConnection> xCon = m_xConnection;
+ if ( xCon.is() )
+ m_xMetaData = xCon->getMetaData();
+ }
+ catch(SQLException&)
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+
+ m_xMasterContainer = _rxMasterContainer;
+
+ if ( m_xMasterContainer.is() )
+ {
+ addMasterContainerListener();
+
+ TableInfos aUnfilteredTables;
+
+ Sequence< OUString > aNames = m_xMasterContainer->getElementNames();
+ const OUString* name = aNames.getConstArray();
+ const OUString* nameEnd = name + aNames.getLength();
+ for ( ; name != nameEnd; ++name )
+ aUnfilteredTables.emplace_back( *name );
+
+ reFill( lcl_filter( std::move(aUnfilteredTables),
+ _rTableFilter, _rTableTypeFilter, m_xMetaData, m_xMasterContainer ) );
+
+ m_bConstructed = true;
+ }
+ else
+ {
+ construct( _rTableFilter, _rTableTypeFilter );
+ }
+ }
+
+ void OFilteredContainer::construct(const Sequence< OUString >& _rTableFilter, const Sequence< OUString >& _rTableTypeFilter)
+ {
+ // build sorted versions of the filter sequences, so the visibility decision is faster
+ Sequence< OUString > aTableFilter(_rTableFilter);
+
+ // for wildcard search : remove all table filters which are a wildcard expression and build a WildCard
+ // for them
+ std::vector< WildCard > aWCSearch;
+ createWildCardVector(aTableFilter,aWCSearch);
+
+ try
+ {
+ Reference< XConnection > xCon( m_xConnection, UNO_SET_THROW );
+ m_xMetaData.set( xCon->getMetaData(), UNO_SET_THROW );
+
+ // create a table filter suitable for the XDatabaseMetaData::getTables call,
+ // taking into account both the externally-provided table type filter, and any
+ // table type restriction which is inherent to the container
+ Sequence< OUString > aTableTypeFilter;
+ OUString sInherentTableTypeRestriction( getTableTypeRestriction() );
+ if ( !sInherentTableTypeRestriction.isEmpty() )
+ {
+ if ( _rTableTypeFilter.hasElements() )
+ {
+ const OUString* tableType = _rTableTypeFilter.getConstArray();
+ const OUString* tableTypeEnd = tableType + _rTableTypeFilter.getLength();
+ for ( ; tableType != tableTypeEnd; ++tableType )
+ {
+ if ( *tableType == sInherentTableTypeRestriction )
+ break;
+ }
+ if ( tableType == tableTypeEnd )
+ { // the only table type which can be part of this container is not allowed
+ // by the externally provided table type filter.
+ m_bConstructed = true;
+ return;
+ }
+ }
+ aTableTypeFilter = { sInherentTableTypeRestriction };
+ }
+ else
+ {
+ // no container-inherent restriction for the table types
+ if ( !_rTableTypeFilter.hasElements() )
+ { // no externally-provided table type filter => use the default filter
+ getAllTableTypeFilter( aTableTypeFilter );
+ }
+ else
+ {
+ aTableTypeFilter = _rTableTypeFilter;
+ }
+ }
+
+ static constexpr OUStringLiteral sAll = u"%";
+ Reference< XResultSet > xTables = m_xMetaData->getTables( Any(), sAll, sAll, aTableTypeFilter );
+ Reference< XRow > xCurrentRow( xTables, UNO_QUERY_THROW );
+
+ TableInfos aUnfilteredTables;
+
+ OUString sCatalog, sSchema, sName, sType;
+ while ( xTables->next() )
+ {
+ sCatalog = xCurrentRow->getString(1);
+ sSchema = xCurrentRow->getString(2);
+ sName = xCurrentRow->getString(3);
+ sType = xCurrentRow->getString(4);
+
+ aUnfilteredTables.emplace_back( sCatalog, sSchema, sName, sType );
+ }
+
+ reFill( lcl_filter( std::move(aUnfilteredTables),
+ _rTableFilter, aTableTypeFilter, m_xMetaData, nullptr ) );
+
+ disposeComponent( xTables );
+ }
+ catch (const Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ disposing();
+ return;
+ }
+
+ m_bConstructed = true;
+ }
+
+ void OFilteredContainer::disposing()
+ {
+ OCollection::disposing();
+
+ if ( m_xMasterContainer.is() )
+ removeMasterContainerListener();
+
+ m_xMasterContainer = nullptr;
+ m_xMetaData = nullptr;
+ m_pRefreshListener = nullptr;
+ m_bConstructed = false;
+ }
+
+ void OFilteredContainer::impl_refresh()
+ {
+ if ( m_pRefreshListener )
+ {
+ m_bConstructed = false;
+ Reference<XRefreshable> xRefresh(m_xMasterContainer,UNO_QUERY);
+ if ( xRefresh.is() )
+ xRefresh->refresh();
+ m_pRefreshListener->refresh(this);
+ }
+ }
+
+ OUString OFilteredContainer::getNameForObject(const ObjectType& _xObject)
+ {
+ OSL_ENSURE( _xObject.is(), "OFilteredContainer::getNameForObject: Object is NULL!" );
+ return ::dbtools::composeTableName( m_xMetaData, _xObject, ::dbtools::EComposeRule::InDataManipulation, false );
+ }
+
+ // multiple to obtain all tables from XDatabaseMetaData::getTables, via passing a particular
+ // table type filter:
+ // adhere to the standard, which requests to pass a NULL table type filter, if
+ // you want to retrieve all tables
+ #define FILTER_MODE_STANDARD 0
+ // only pass %, which is not allowed by the standard, but understood by some drivers
+ #define FILTER_MODE_WILDCARD 1
+ // only pass TABLE and VIEW
+ #define FILTER_MODE_FIXED 2
+ // do the thing which showed to be the safest way, understood by nearly all
+ // drivers, even the ones which do not understand the standard
+ #define FILTER_MODE_MIX_ALL 3
+
+ void OFilteredContainer::getAllTableTypeFilter( Sequence< OUString >& /* [out] */ _rFilter ) const
+ {
+ sal_Int32 nFilterMode = FILTER_MODE_MIX_ALL;
+ // for compatibility reasons, this is the default: we used this way before we
+ // introduced the TableTypeFilterMode setting
+
+ // obtain the data source we belong to, and the TableTypeFilterMode setting
+ Any aFilterModeSetting;
+ if ( getDataSourceSetting( getDataSource( Reference< XInterface >(m_rParent) ), "TableTypeFilterMode", aFilterModeSetting ) )
+ {
+ OSL_VERIFY( aFilterModeSetting >>= nFilterMode );
+ }
+
+ static const OUStringLiteral sAll( u"%" );
+ static const OUStringLiteral sView( u"VIEW" );
+ static const OUStringLiteral sTable( u"TABLE" );
+
+ switch ( nFilterMode )
+ {
+ default:
+ SAL_WARN("dbaccess", "OTableContainer::getAllTableTypeFilter: unknown TableTypeFilterMode!" );
+ [[fallthrough]];
+ case FILTER_MODE_MIX_ALL:
+ _rFilter = { sView, sTable, sAll };
+ break;
+ case FILTER_MODE_FIXED:
+ _rFilter = { sView, sTable };
+ break;
+ case FILTER_MODE_WILDCARD:
+ _rFilter = { sAll };
+ break;
+ case FILTER_MODE_STANDARD:
+ _rFilter.realloc( 0 );
+ break;
+ }
+ }
+
+} // namespace
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/api/HelperCollections.cxx b/dbaccess/source/core/api/HelperCollections.cxx
new file mode 100644
index 000000000..dfc18badc
--- /dev/null
+++ b/dbaccess/source/core/api/HelperCollections.cxx
@@ -0,0 +1,106 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "HelperCollections.hxx"
+
+#include <strings.hxx>
+
+#include <osl/diagnose.h>
+
+namespace dbaccess
+{
+ using namespace dbtools;
+ using namespace comphelper;
+ using namespace connectivity;
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::beans;
+ using namespace ::com::sun::star::sdbc;
+ using namespace ::com::sun::star::sdb;
+ using namespace ::com::sun::star::sdbcx;
+ using namespace ::com::sun::star::container;
+ using namespace ::com::sun::star::lang;
+ using namespace ::com::sun::star::script;
+ using namespace ::cppu;
+ using namespace ::osl;
+
+ OPrivateColumns::OPrivateColumns(const ::rtl::Reference< ::connectivity::OSQLColumns>& _rColumns,
+ bool _bCase,
+ ::cppu::OWeakObject& _rParent,
+ ::osl::Mutex& _rMutex,
+ const std::vector< OUString> &_rVector,
+ bool _bUseAsIndex
+ ) : sdbcx::OCollection(_rParent,_bCase,_rMutex,_rVector,_bUseAsIndex)
+ ,m_aColumns(_rColumns)
+ {
+ }
+
+ std::unique_ptr<OPrivateColumns> OPrivateColumns::createWithIntrinsicNames( const ::rtl::Reference< ::connectivity::OSQLColumns >& _rColumns,
+ bool _bCase, ::cppu::OWeakObject& _rParent, ::osl::Mutex& _rMutex )
+ {
+ std::vector< OUString > aNames; aNames.reserve( _rColumns->size() );
+
+ OUString sColumName;
+ for (auto const& column : *_rColumns)
+ {
+ Reference< XPropertySet > xColumn(column, UNO_SET_THROW);
+ xColumn->getPropertyValue( PROPERTY_NAME ) >>= sColumName;
+ aNames.push_back( sColumName );
+ }
+ return std::unique_ptr<OPrivateColumns>(new OPrivateColumns( _rColumns, _bCase, _rParent, _rMutex, aNames, false ));
+ }
+
+ void OPrivateColumns::disposing()
+ {
+ m_aColumns = nullptr;
+ clear_NoDispose();
+ // we're not owner of the objects we're holding, instead the object we got in our ctor is
+ // So we're not allowed to dispose our elements.
+ OPrivateColumns_Base::disposing();
+ }
+
+ connectivity::sdbcx::ObjectType OPrivateColumns::createObject(const OUString& _rName)
+ {
+ if ( m_aColumns.is() )
+ {
+ ::connectivity::OSQLColumns::Vector::const_iterator aIter = find(m_aColumns->begin(),m_aColumns->end(),_rName,isCaseSensitive());
+ if(aIter == m_aColumns->end())
+ aIter = findRealName(m_aColumns->begin(),m_aColumns->end(),_rName,isCaseSensitive());
+
+ if(aIter != m_aColumns->end())
+ return connectivity::sdbcx::ObjectType(*aIter,UNO_QUERY);
+
+ OSL_FAIL("Column not found in collection!");
+ }
+ return nullptr;
+ }
+
+ connectivity::sdbcx::ObjectType OPrivateTables::createObject(const OUString& _rName)
+ {
+ if ( !m_aTables.empty() )
+ {
+ OSQLTables::iterator aIter = m_aTables.find(_rName);
+ OSL_ENSURE(aIter != m_aTables.end(),"Table not found!");
+ OSL_ENSURE(aIter->second.is(),"Table is null!");
+ return connectivity::sdbcx::ObjectType(m_aTables.find(_rName)->second,UNO_QUERY);
+ }
+ return nullptr;
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/api/HelperCollections.hxx b/dbaccess/source/core/api/HelperCollections.hxx
new file mode 100644
index 000000000..ed89fc643
--- /dev/null
+++ b/dbaccess/source/core/api/HelperCollections.hxx
@@ -0,0 +1,106 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <connectivity/sdbcx/VCollection.hxx>
+#include <connectivity/dbconversion.hxx>
+#include <rtl/ref.hxx>
+
+namespace dbaccess
+{
+ using namespace dbtools;
+ using namespace comphelper;
+ using namespace connectivity;
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::beans;
+ using namespace ::com::sun::star::sdbc;
+ using namespace ::com::sun::star::sdb;
+ using namespace ::com::sun::star::sdbcx;
+ using namespace ::com::sun::star::container;
+ using namespace ::com::sun::star::lang;
+ using namespace ::com::sun::star::script;
+ using namespace ::cppu;
+ using namespace ::osl;
+
+ typedef connectivity::sdbcx::OCollection OPrivateColumns_Base;
+ class OPrivateColumns : public OPrivateColumns_Base
+ {
+ ::rtl::Reference< ::connectivity::OSQLColumns> m_aColumns;
+ protected:
+ virtual connectivity::sdbcx::ObjectType createObject(const OUString& _rName) override;
+ virtual void impl_refresh() override {}
+ virtual Reference< XPropertySet > createDescriptor() override
+ {
+ return nullptr;
+ }
+ public:
+ OPrivateColumns(const ::rtl::Reference< ::connectivity::OSQLColumns>& _rColumns,
+ bool _bCase,
+ ::cppu::OWeakObject& _rParent,
+ ::osl::Mutex& _rMutex,
+ const std::vector< OUString> &_rVector,
+ bool _bUseAsIndex = false
+ );
+
+ /** creates a columns instance as above, but taking the names from the columns itself
+ */
+ static std::unique_ptr<OPrivateColumns> createWithIntrinsicNames(
+ const ::rtl::Reference< ::connectivity::OSQLColumns >& _rColumns,
+ bool _bCase,
+ ::cppu::OWeakObject& _rParent,
+ ::osl::Mutex& _rMutex
+ );
+
+ virtual void disposing() override;
+ };
+ typedef connectivity::sdbcx::OCollection OPrivateTables_BASE;
+
+ // OPrivateTables
+ class OPrivateTables : public OPrivateTables_BASE
+ {
+ OSQLTables m_aTables;
+ protected:
+ virtual connectivity::sdbcx::ObjectType createObject(const OUString& _rName) override;
+ virtual void impl_refresh() override {}
+ virtual Reference< XPropertySet > createDescriptor() override
+ {
+ return nullptr;
+ }
+ public:
+ OPrivateTables( const OSQLTables& _rTables,
+ bool _bCase,
+ ::cppu::OWeakObject& _rParent,
+ ::osl::Mutex& _rMutex,
+ std::vector< OUString> && _rVector
+ ) : sdbcx::OCollection(_rParent,_bCase,_rMutex,_rVector)
+ ,m_aTables(std::move(_rTables))
+ {
+ }
+ virtual void disposing() override
+ {
+ clear_NoDispose();
+ // we're not owner of the objects we're holding, instead the object we got in our ctor is
+ // So we're not allowed to dispose our elements.
+ m_aTables.clear();
+ OPrivateTables_BASE::disposing();
+ }
+ };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/api/KeySet.cxx b/dbaccess/source/core/api/KeySet.cxx
new file mode 100644
index 000000000..338d4d7f8
--- /dev/null
+++ b/dbaccess/source/core/api/KeySet.cxx
@@ -0,0 +1,1463 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <memory>
+#include <string_view>
+
+#include "KeySet.hxx"
+#include <sal/log.hxx>
+#include <core_resource.hxx>
+#include <strings.hrc>
+#include <strings.hxx>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/sdb/XParametersSupplier.hpp>
+#include <com/sun/star/sdbc/XDatabaseMetaData.hpp>
+#include <com/sun/star/sdbc/ColumnValue.hpp>
+#include <com/sun/star/sdbc/SQLException.hpp>
+#include <com/sun/star/sdbc/XPreparedStatement.hpp>
+#include <com/sun/star/sdbc/XParameters.hpp>
+#include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp>
+#include <com/sun/star/sdbc/XGeneratedResultSet.hpp>
+#include <com/sun/star/container/XIndexAccess.hpp>
+#include <com/sun/star/sdbcx/CompareBookmark.hpp>
+#include <com/sun/star/sdb/XSingleSelectQueryComposer.hpp>
+#include <com/sun/star/sdbcx/XIndexesSupplier.hpp>
+#include <comphelper/types.hxx>
+#include <connectivity/dbtools.hxx>
+#include <connectivity/dbexception.hxx>
+#include <algorithm>
+#include <com/sun/star/io/XInputStream.hpp>
+#include <com/sun/star/sdbcx/XTablesSupplier.hpp>
+#include <composertools.hxx>
+#include "PrivateRow.hxx"
+
+using namespace dbaccess;
+using namespace ::connectivity;
+using namespace ::dbtools;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::sdb;
+using namespace ::com::sun::star::sdbcx;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::util;
+using namespace ::com::sun::star::io;
+using namespace ::com::sun::star;
+using namespace ::cppu;
+using namespace ::osl;
+using std::vector;
+
+namespace
+{
+ void lcl_fillIndexColumns(const Reference<XIndexAccess>& _xIndexes, std::vector< Reference<XNameAccess> >& _rAllIndexColumns)
+ {
+ if ( !_xIndexes.is() )
+ return;
+
+ Reference<XPropertySet> xIndexColsSup;
+ sal_Int32 nCount = _xIndexes->getCount();
+ for(sal_Int32 j = 0 ; j < nCount ; ++j)
+ {
+ xIndexColsSup.set(_xIndexes->getByIndex(j),UNO_QUERY);
+ if( xIndexColsSup.is()
+ && comphelper::getBOOL(xIndexColsSup->getPropertyValue(PROPERTY_ISUNIQUE))
+ && !comphelper::getBOOL(xIndexColsSup->getPropertyValue(PROPERTY_ISPRIMARYKEYINDEX))
+ )
+ _rAllIndexColumns.push_back(Reference<XColumnsSupplier>(xIndexColsSup,UNO_QUERY_THROW)->getColumns());
+ }
+ }
+
+ template < typename T > void tryDispose( Reference<T> &r )
+ {
+ try
+ {
+ ::comphelper::disposeComponent(r);
+ }
+ catch(const Exception&)
+ {
+ r = nullptr;
+ }
+ catch(...)
+ {
+ SAL_WARN("dbaccess", "Unknown Exception occurred");
+ }
+ }
+}
+
+
+OKeySet::OKeySet(const connectivity::OSQLTable& _xTable,
+ const OUString& _rUpdateTableName, // this can be the alias or the full qualified name
+ const Reference< XSingleSelectQueryAnalyzer >& _xComposer,
+ const ORowSetValueVector& _aParameterValueForCache,
+ sal_Int32 i_nMaxRows,
+ sal_Int32& o_nRowCount)
+ :OCacheSet(i_nMaxRows)
+ ,m_aParameterValueForCache(new ORowSetValueVector(_aParameterValueForCache))
+ ,m_xTable(_xTable)
+ ,m_xComposer(_xComposer)
+ ,m_sUpdateTableName(_rUpdateTableName)
+ ,m_rRowCount(o_nRowCount)
+ ,m_bRowCountFinal(false)
+{
+}
+
+OKeySet::~OKeySet()
+{
+ tryDispose(m_xSet);
+ // m_xStatement is necessarily one of those
+ for (auto & statement : m_vStatements)
+ {
+ tryDispose(statement.second);
+ }
+
+ m_xComposer = nullptr;
+
+}
+
+void OKeySet::initColumns()
+{
+ Reference<XDatabaseMetaData> xMeta = m_xConnection->getMetaData();
+ bool bCase = xMeta.is() && xMeta->supportsMixedCaseQuotedIdentifiers();
+ m_pKeyColumnNames.reset( new SelectColumnsMetaData(bCase) );
+ m_pColumnNames.reset( new SelectColumnsMetaData(bCase) );
+ m_pParameterNames.reset( new SelectColumnsMetaData(bCase) );
+ m_pForeignColumnNames.reset( new SelectColumnsMetaData(bCase) );
+}
+
+void OKeySet::findTableColumnsMatching_throw( const Any& i_aTable,
+ const OUString& i_rUpdateTableName,
+ const Reference<XDatabaseMetaData>& i_xMeta,
+ const Reference<XNameAccess>& i_xQueryColumns,
+ std::unique_ptr<SelectColumnsMetaData> const & o_pKeyColumnNames)
+{
+ // first ask the database itself for the best columns which can be used
+ Sequence< OUString> aBestColumnNames;
+ Reference<XNameAccess> xKeyColumns = getPrimaryKeyColumns_throw(i_aTable);
+ if ( xKeyColumns.is() )
+ aBestColumnNames = xKeyColumns->getElementNames();
+
+ const Reference<XColumnsSupplier> xTblColSup(i_aTable,UNO_QUERY_THROW);
+ const Reference<XNameAccess> xTblColumns = xTblColSup->getColumns();
+ // locate parameter in select columns
+ Reference<XParametersSupplier> xParaSup(m_xComposer,UNO_QUERY);
+ Reference<XIndexAccess> xQueryParameters = xParaSup->getParameters();
+ const sal_Int32 nParaCount = xQueryParameters->getCount();
+ Sequence< OUString> aParameterColumns(nParaCount);
+ auto aParameterColumnsRange = asNonConstRange(aParameterColumns);
+ for(sal_Int32 i = 0; i< nParaCount;++i)
+ {
+ Reference<XPropertySet> xPara(xQueryParameters->getByIndex(i),UNO_QUERY_THROW);
+ xPara->getPropertyValue(PROPERTY_REALNAME) >>= aParameterColumnsRange[i];
+ }
+
+ OUString sUpdateTableName( i_rUpdateTableName );
+ if ( sUpdateTableName.isEmpty() )
+ {
+ SAL_WARN("dbaccess", "OKeySet::findTableColumnsMatching_throw: This is a fallback only - it won't work when the table has an alias name." );
+ // If i_aTable originates from a query composer, and is a table which appears with an alias in the SELECT statement,
+ // then the below code will not produce correct results.
+ // For instance, imagine a "SELECT alias.col FROM table AS alias". Now i_aTable would be the table named
+ // "table", so our sUpdateTableName would be "table" as well - not the information about the "alias" is
+ // already lost here.
+ // now getColumnPositions would traverse the columns, and check which of them belong to the table denoted
+ // by sUpdateTableName. Since the latter is "table", but the columns only know that they belong to a table
+ // named "alias", there will be no matching - so getColumnPositions wouldn't find anything.
+
+ OUString sCatalog, sSchema, sTable;
+ Reference<XPropertySet> xTableProp( i_aTable, UNO_QUERY_THROW );
+ xTableProp->getPropertyValue( PROPERTY_CATALOGNAME )>>= sCatalog;
+ xTableProp->getPropertyValue( PROPERTY_SCHEMANAME ) >>= sSchema;
+ xTableProp->getPropertyValue( PROPERTY_NAME ) >>= sTable;
+ sUpdateTableName = dbtools::composeTableName( i_xMeta, sCatalog, sSchema, sTable, false, ::dbtools::EComposeRule::InDataManipulation );
+ }
+
+ ::dbaccess::getColumnPositions(i_xQueryColumns,aBestColumnNames,sUpdateTableName,(*o_pKeyColumnNames),true);
+ ::dbaccess::getColumnPositions(i_xQueryColumns,xTblColumns->getElementNames(),sUpdateTableName,(*m_pColumnNames),true);
+ ::dbaccess::getColumnPositions(i_xQueryColumns,aParameterColumns,sUpdateTableName,(*m_pParameterNames),true);
+
+ if ( o_pKeyColumnNames->empty() )
+ {
+ ::dbtools::throwGenericSQLException("Could not find any key column.", *this );
+ }
+
+ for (auto const& keyColumn : *o_pKeyColumnNames)
+ {
+ if ( !xTblColumns->hasByName( keyColumn.second.sRealName ) )
+ continue;
+
+ Reference<XPropertySet> xProp( xTblColumns->getByName( keyColumn.second.sRealName ), UNO_QUERY );
+ bool bAuto = false;
+ if ( ( xProp->getPropertyValue( PROPERTY_ISAUTOINCREMENT ) >>= bAuto ) && bAuto )
+ m_aAutoColumns.push_back( keyColumn.first );
+ }
+}
+
+namespace
+{
+ void appendOneKeyColumnClause( std::u16string_view tblName, const OUString &colName, const connectivity::ORowSetValue &_rValue, OUStringBuffer &o_buf )
+ {
+ OUString fullName;
+ if (tblName.empty())
+ fullName = colName;
+ else
+ fullName = OUString::Concat(tblName) + "." + colName;
+ if ( _rValue.isNull() )
+ {
+ o_buf.append(fullName + " IS NULL ");
+ }
+ else
+ {
+ o_buf.append(fullName + " = ? ");
+ }
+ }
+}
+
+void OKeySet::setOneKeyColumnParameter( sal_Int32 &nPos, const Reference< XParameters > &_xParameter, const connectivity::ORowSetValue &_rValue, sal_Int32 _nType, sal_Int32 _nScale )
+{
+ if ( _rValue.isNull() )
+ {
+ // Nothing to do, appendOneKeyColumnClause took care of it,
+ // the "IS NULL" is hardcoded in the query
+ }
+ else
+ {
+ setParameter( nPos++, _xParameter, _rValue, _nType, _nScale );
+ }
+}
+
+OUStringBuffer OKeySet::createKeyFilter()
+{
+ connectivity::ORowVector< ORowSetValue >::Vector::const_iterator aIter = m_aKeyIter->second.first->begin();
+
+ static const char aAnd[] = " AND ";
+ const OUString aQuote = getIdentifierQuoteString();
+ OUStringBuffer aFilter;
+ // create the where clause
+ Reference<XDatabaseMetaData> xMeta = m_xConnection->getMetaData();
+ for (auto const& keyColumnName : *m_pKeyColumnNames)
+ {
+ if ( ! aFilter.isEmpty() )
+ aFilter.append(aAnd);
+ appendOneKeyColumnClause(::dbtools::quoteTableName(xMeta, keyColumnName.second.sTableName, ::dbtools::EComposeRule::InDataManipulation),
+ ::dbtools::quoteName(aQuote, keyColumnName.second.sRealName),
+ *aIter++,
+ aFilter);
+ }
+ for (auto const& foreignColumnName : * m_pForeignColumnNames)
+ {
+ if ( ! aFilter.isEmpty() )
+ aFilter.append(aAnd);
+ appendOneKeyColumnClause(::dbtools::quoteTableName(xMeta, foreignColumnName.second.sTableName, ::dbtools::EComposeRule::InDataManipulation),
+ ::dbtools::quoteName(aQuote, foreignColumnName.second.sRealName),
+ *aIter++,
+ aFilter);
+ }
+ return aFilter;
+}
+
+void OKeySet::construct(const Reference< XResultSet>& _xDriverSet, const OUString& i_sRowSetFilter)
+{
+ OCacheSet::construct(_xDriverSet,i_sRowSetFilter);
+
+ initColumns();
+
+ Reference<XDatabaseMetaData> xMeta = m_xConnection->getMetaData();
+ Reference<XColumnsSupplier> xQueryColSup(m_xComposer, UNO_QUERY);
+ const Reference<XNameAccess> xQueryColumns = xQueryColSup->getColumns();
+ findTableColumnsMatching_throw( Any(m_xTable), m_sUpdateTableName, xMeta, xQueryColumns, m_pKeyColumnNames );
+
+ Reference< XSingleSelectQueryComposer> xSourceComposer(m_xComposer,UNO_QUERY);
+ Reference< XMultiServiceFactory > xFactory(m_xConnection, UNO_QUERY_THROW);
+ Reference<XSingleSelectQueryComposer> xAnalyzer(xFactory->createInstance(SERVICE_NAME_SINGLESELECTQUERYCOMPOSER),UNO_QUERY);
+ xAnalyzer->setElementaryQuery(xSourceComposer->getElementaryQuery());
+ Reference<XTablesSupplier> xTabSup(xAnalyzer,uno::UNO_QUERY);
+ Reference<XNameAccess> xSelectTables = xTabSup->getTables();
+ const Sequence< OUString> aSeq = xSelectTables->getElementNames();
+ if ( aSeq.getLength() > 1 ) // special handling for join
+ {
+ const OUString* pIter = aSeq.getConstArray();
+ const OUString* const pEnd = pIter + aSeq.getLength();
+ for(;pIter != pEnd;++pIter)
+ {
+ if ( *pIter != m_sUpdateTableName )
+ {
+ connectivity::OSQLTable xSelColSup(xSelectTables->getByName(*pIter),uno::UNO_QUERY);
+ Reference<XPropertySet> xProp(xSelColSup,uno::UNO_QUERY);
+ OUString sSelectTableName = ::dbtools::composeTableName( xMeta, xProp, ::dbtools::EComposeRule::InDataManipulation, false );
+
+ ::dbaccess::getColumnPositions(xQueryColumns, xSelColSup->getColumns()->getElementNames(), sSelectTableName, (*m_pForeignColumnNames), true);
+
+ // LEM: there used to be a break here; however, I see no reason to stop
+ // at first non-updateTable, so I removed it. (think of multiple joins...)
+ }
+ }
+ }
+
+ // the first row is empty because it's now easier for us to distinguish when we are beforefirst or first
+ // without extra variable to be set
+ OKeySetValue keySetValue(nullptr,std::pair<sal_Int32,Reference<XRow> >(0,Reference<XRow>()));
+ m_aKeyMap.emplace(0, keySetValue);
+ m_aKeyIter = m_aKeyMap.begin();
+}
+
+void OKeySet::reset(const Reference< XResultSet>& _xDriverSet)
+{
+ OCacheSet::construct(_xDriverSet, m_sRowSetFilter);
+ m_bRowCountFinal = false;
+ m_aKeyMap.clear();
+ OKeySetValue keySetValue(nullptr,std::pair<sal_Int32,Reference<XRow> >(0,Reference<XRow>()));
+ m_aKeyMap.emplace(0,keySetValue);
+ m_aKeyIter = m_aKeyMap.begin();
+}
+
+void OKeySet::ensureStatement( )
+{
+ // do we already have a statement for the current combination of NULLness
+ // of key & foreign columns?
+ std::vector<bool> FilterColumnsNULL;
+ FilterColumnsNULL.reserve(m_aKeyIter->second.first->size());
+ for (auto const& elem : *m_aKeyIter->second.first)
+ FilterColumnsNULL.push_back(elem.isNull());
+ vStatements_t::const_iterator pNewStatement(m_vStatements.find(FilterColumnsNULL));
+ if(pNewStatement == m_vStatements.end())
+ {
+ // no: make a new one
+ makeNewStatement();
+ std::pair< vStatements_t::const_iterator, bool > insert_result
+ (m_vStatements.emplace( FilterColumnsNULL, m_xStatement));
+ (void) insert_result; // WaE: unused variable
+ assert(insert_result.second);
+ }
+ else
+ // yes: use it
+ m_xStatement = pNewStatement->second;
+}
+
+void OKeySet::makeNewStatement()
+{
+ Reference< XSingleSelectQueryComposer> xSourceComposer(m_xComposer,UNO_QUERY);
+ Reference< XMultiServiceFactory > xFactory(m_xConnection, UNO_QUERY_THROW);
+ Reference<XSingleSelectQueryComposer> xAnalyzer(xFactory->createInstance(SERVICE_NAME_SINGLESELECTQUERYCOMPOSER),UNO_QUERY);
+ xAnalyzer->setElementaryQuery(xSourceComposer->getElementaryQuery());
+
+ OUStringBuffer aFilter(createKeyFilter());
+ executeStatement(aFilter, xAnalyzer);
+}
+
+void OKeySet::executeStatement(OUStringBuffer& io_aFilter, Reference<XSingleSelectQueryComposer>& io_xAnalyzer)
+{
+ bool bFilterSet = !m_sRowSetFilter.isEmpty();
+ if ( bFilterSet )
+ {
+ FilterCreator aFilterCreator;
+ aFilterCreator.append( m_sRowSetFilter );
+ aFilterCreator.append( io_aFilter.makeStringAndClear() );
+ io_aFilter = aFilterCreator.getComposedAndClear();
+ }
+ io_xAnalyzer->setFilter(io_aFilter.makeStringAndClear());
+ if ( bFilterSet )
+ {
+ Sequence< Sequence< PropertyValue > > aFilter2 = io_xAnalyzer->getStructuredFilter();
+ const Sequence< PropertyValue >* pOr = aFilter2.getConstArray();
+ const Sequence< PropertyValue >* pOrEnd = pOr + aFilter2.getLength();
+ for(;pOr != pOrEnd;++pOr)
+ {
+ const PropertyValue* pAnd = pOr->getConstArray();
+ const PropertyValue* pAndEnd = pAnd + pOr->getLength();
+ for(;pAnd != pAndEnd;++pAnd)
+ {
+ OUString sValue;
+ if ( !(pAnd->Value >>= sValue) || !( sValue == "?" || sValue.startsWith( ":" ) ) )
+ { // we have a criteria which has to be taken into account for updates
+ m_aFilterColumns.push_back(pAnd->Name);
+ }
+ }
+ }
+ }
+ m_xStatement = m_xConnection->prepareStatement(io_xAnalyzer->getQueryWithSubstitution());
+ ::comphelper::disposeComponent(io_xAnalyzer);
+}
+
+void OKeySet::invalidateRow()
+{
+ m_xRow = nullptr;
+ ::comphelper::disposeComponent(m_xSet);
+}
+
+Any OKeySet::getBookmark()
+{
+ OSL_ENSURE(m_aKeyIter != m_aKeyMap.end() && m_aKeyIter != m_aKeyMap.begin(),
+ "getBookmark is only possible when we stand on a valid row!");
+ return Any(m_aKeyIter->first);
+}
+
+bool OKeySet::moveToBookmark( const Any& bookmark )
+{
+ m_bInserted = m_bUpdated = m_bDeleted = false;
+ m_aKeyIter = m_aKeyMap.find(::comphelper::getINT32(bookmark));
+ invalidateRow();
+ return m_aKeyIter != m_aKeyMap.end();
+}
+
+sal_Int32 OKeySet::compareBookmarks( const Any& _first, const Any& _second )
+{
+ sal_Int32 nFirst = 0, nSecond = 0;
+ _first >>= nFirst;
+ _second >>= nSecond;
+
+ return (nFirst != nSecond) ? CompareBookmark::NOT_EQUAL : CompareBookmark::EQUAL;
+}
+
+bool OKeySet::hasOrderedBookmarks( )
+{
+ return true;
+}
+
+sal_Int32 OKeySet::hashBookmark( const Any& bookmark )
+{
+ return ::comphelper::getINT32(bookmark);
+}
+
+
+void OKeySet::updateRow(const ORowSetRow& _rInsertRow ,const ORowSetRow& _rOriginalRow,const connectivity::OSQLTable& _xTable )
+{
+ Reference<XPropertySet> xSet(_xTable,UNO_QUERY);
+ fillTableName(xSet);
+
+ OUStringBuffer aSql = "UPDATE " + m_aComposedTableName + " SET ";
+ // list all columns that should be set
+ constexpr OUStringLiteral aPara(u" = ?,");
+ OUString aQuote = getIdentifierQuoteString();
+ constexpr OUStringLiteral aAnd(u" AND ");
+ OUString sIsNull(" IS NULL");
+ OUString sParam(" = ?");
+
+ // use keys and indexes for exact positioning
+ Reference<XIndexesSupplier> xIndexSup(_xTable,UNO_QUERY);
+ Reference<XIndexAccess> xIndexes;
+ if ( xIndexSup.is() )
+ xIndexes.set(xIndexSup->getIndexes(),UNO_QUERY);
+
+ std::vector< Reference<XNameAccess> > aAllIndexColumns;
+ lcl_fillIndexColumns(xIndexes,aAllIndexColumns);
+
+ OUStringBuffer sKeyCondition,sIndexCondition;
+ std::vector<sal_Int32> aIndexColumnPositions;
+
+ const sal_Int32 nOldLength = aSql.getLength();
+ // here we build the condition part for the update statement
+ for (auto const& columnName : *m_pColumnNames)
+ {
+ if ( m_pKeyColumnNames->find(columnName.first) != m_pKeyColumnNames->end() )
+ {
+ sKeyCondition.append(::dbtools::quoteName( aQuote,columnName.second.sRealName));
+ if((*_rOriginalRow)[columnName.second.nPosition].isNull())
+ sKeyCondition.append(sIsNull);
+ else
+ sKeyCondition.append(sParam);
+ sKeyCondition.append(aAnd);
+ }
+ else
+ {
+ for (auto const& indexColumn : aAllIndexColumns)
+ {
+ if(indexColumn->hasByName(columnName.first))
+ {
+ sIndexCondition.append(::dbtools::quoteName( aQuote,columnName.second.sRealName));
+ if((*_rOriginalRow)[columnName.second.nPosition].isNull())
+ sIndexCondition.append(sIsNull);
+ else
+ {
+ sIndexCondition.append(sParam);
+ aIndexColumnPositions.push_back(columnName.second.nPosition);
+ }
+ sIndexCondition.append(aAnd);
+ break;
+ }
+ }
+ }
+ if((*_rInsertRow)[columnName.second.nPosition].isModified())
+ {
+ aSql.append(::dbtools::quoteName( aQuote,columnName.second.sRealName) + aPara);
+ }
+ }
+
+ if( aSql.getLength() != nOldLength )
+ {
+ aSql.setLength(aSql.getLength()-1);
+ }
+ else
+ ::dbtools::throwSQLException( DBA_RES( RID_STR_NO_VALUE_CHANGED ), StandardSQLState::GENERAL_ERROR, m_xConnection );
+
+ if(!sKeyCondition.isEmpty() || !sIndexCondition.isEmpty())
+ {
+ aSql.append(" WHERE ");
+ if(!sKeyCondition.isEmpty() && !sIndexCondition.isEmpty())
+ {
+ aSql.append(sKeyCondition + sIndexCondition);
+ }
+ else if(!sKeyCondition.isEmpty())
+ {
+ aSql.append(sKeyCondition);
+ }
+ else if(!sIndexCondition.isEmpty())
+ {
+ aSql.append(sIndexCondition);
+ }
+ aSql.setLength(aSql.getLength()-5); // remove the last AND
+ }
+ else
+ ::dbtools::throwSQLException( DBA_RES( RID_STR_NO_CONDITION_FOR_PK ), StandardSQLState::GENERAL_ERROR, m_xConnection );
+
+ // now create end execute the prepared statement
+ executeUpdate(_rInsertRow ,_rOriginalRow,aSql.makeStringAndClear(),u"",aIndexColumnPositions);
+}
+
+void OKeySet::executeUpdate(const ORowSetRow& _rInsertRow ,const ORowSetRow& _rOriginalRow,const OUString& i_sSQL,std::u16string_view i_sTableName,const std::vector<sal_Int32>& _aIndexColumnPositions)
+{
+ // now create end execute the prepared statement
+ Reference< XPreparedStatement > xPrep(m_xConnection->prepareStatement(i_sSQL));
+ Reference< XParameters > xParameter(xPrep,UNO_QUERY);
+
+ bool bRefetch = true;
+ Reference<XRow> xRow;
+ sal_Int32 i = 1;
+ // first the set values
+ for (auto const& columnName : *m_pColumnNames)
+ {
+ if ( i_sTableName.empty() || columnName.second.sTableName == i_sTableName )
+ {
+ sal_Int32 nPos = columnName.second.nPosition;
+ if((*_rInsertRow)[nPos].isModified())
+ {
+ if ( bRefetch )
+ {
+ bRefetch = std::find(m_aFilterColumns.begin(),m_aFilterColumns.end(),columnName.second.sRealName) == m_aFilterColumns.end();
+ }
+ impl_convertValue_throw(_rInsertRow,columnName.second);
+ (*_rInsertRow)[nPos].setSigned((*_rOriginalRow)[nPos].isSigned());
+ setParameter(i++,xParameter,(*_rInsertRow)[nPos],columnName.second.nType,columnName.second.nScale);
+ }
+ }
+ }
+ // and then the values of the where condition
+ for (auto const& keyColumnName : *m_pKeyColumnNames)
+ {
+ if ( i_sTableName.empty() || keyColumnName.second.sTableName == i_sTableName )
+ {
+ setParameter(i++,xParameter,(*_rOriginalRow)[keyColumnName.second.nPosition],keyColumnName.second.nType,keyColumnName.second.nScale);
+ }
+ }
+ if ( !_aIndexColumnPositions.empty() )
+ {
+ // now we have to set the index values
+ auto aIter = m_pColumnNames->begin();
+ for (auto const& indexColumnPosition : _aIndexColumnPositions)
+ {
+ setParameter(i++,xParameter,(*_rOriginalRow)[indexColumnPosition],(*_rOriginalRow)[indexColumnPosition].getTypeKind(),aIter->second.nScale);
+ ++aIter;
+ }
+ }
+ const sal_Int32 nRowsUpdated = xPrep->executeUpdate();
+ m_bUpdated = nRowsUpdated > 0;
+ if(m_bUpdated)
+ {
+ const sal_Int32 nBookmark = ::comphelper::getINT32((*_rInsertRow)[0].getAny());
+ m_aKeyIter = m_aKeyMap.find(nBookmark);
+ m_aKeyIter->second.second.first = 2;
+ m_aKeyIter->second.second.second = xRow;
+ copyRowValue(_rInsertRow,m_aKeyIter->second.first,nBookmark);
+ tryRefetch(_rInsertRow,bRefetch);
+ }
+}
+
+void OKeySet::insertRow( const ORowSetRow& _rInsertRow,const connectivity::OSQLTable& _xTable )
+{
+ Reference<XPropertySet> xSet(_xTable,UNO_QUERY);
+ fillTableName(xSet);
+
+ OUStringBuffer aSql( "INSERT INTO " + m_aComposedTableName + " ( ");
+
+ // set values and column names
+ OUStringBuffer aValues(" VALUES ( ");
+ OUString aQuote = getIdentifierQuoteString();
+
+ bool bRefetch = true;
+ bool bModified = false;
+ for (auto const& columnName : *m_pColumnNames)
+ {
+ if((*_rInsertRow)[columnName.second.nPosition].isModified())
+ {
+ if ( bRefetch )
+ {
+ bRefetch = std::find(m_aFilterColumns.begin(),m_aFilterColumns.end(),columnName.second.sRealName) == m_aFilterColumns.end();
+ }
+ aSql.append(::dbtools::quoteName( aQuote,columnName.second.sRealName) + ",");
+ aValues.append("?,");
+ bModified = true;
+ }
+ }
+ if ( !bModified )
+ ::dbtools::throwSQLException( DBA_RES( RID_STR_NO_VALUE_CHANGED ), StandardSQLState::GENERAL_ERROR, m_xConnection );
+
+ aSql[aSql.getLength() - 1] = ')';
+ aValues[aValues.getLength() - 1] = ')';
+ aSql.append(aValues);
+ // now create,fill and execute the prepared statement
+ executeInsert(_rInsertRow,aSql.makeStringAndClear(),u"",bRefetch);
+}
+
+void OKeySet::executeInsert( const ORowSetRow& _rInsertRow,const OUString& i_sSQL,std::u16string_view i_sTableName,bool bRefetch )
+{
+ // now create,fill and execute the prepared statement
+ Reference< XPreparedStatement > xPrep(m_xConnection->prepareStatement(i_sSQL));
+ Reference< XParameters > xParameter(xPrep,UNO_QUERY);
+
+ sal_Int32 i = 1;
+ for (auto const& columnName : *m_pColumnNames)
+ {
+ if ( i_sTableName.empty() || columnName.second.sTableName == i_sTableName )
+ {
+ const sal_Int32 nPos = columnName.second.nPosition;
+ if((*_rInsertRow)[nPos].isModified())
+ {
+ if((*_rInsertRow)[nPos].isNull())
+ xParameter->setNull(i++,(*_rInsertRow)[nPos].getTypeKind());
+ else
+ {
+ impl_convertValue_throw(_rInsertRow,columnName.second);
+ (*_rInsertRow)[nPos].setSigned(m_aSignedFlags[nPos-1]);
+ setParameter(i++,xParameter,(*_rInsertRow)[nPos],columnName.second.nType,columnName.second.nScale);
+ }
+ }
+ }
+ }
+
+ m_bInserted = xPrep->executeUpdate() > 0;
+ bool bAutoValuesFetched = false;
+ if ( m_bInserted )
+ {
+ // first insert the default values into the insertrow
+ for (auto const& columnName : *m_pColumnNames)
+ {
+ if ( !(*_rInsertRow)[columnName.second.nPosition].isModified() )
+ {
+ if(columnName.second.bNullable && columnName.second.sDefaultValue.isEmpty())
+ {
+ (*_rInsertRow)[columnName.second.nPosition].setTypeKind(columnName.second.nType);
+ (*_rInsertRow)[columnName.second.nPosition].setNull();
+ }
+ else
+ {
+ (*_rInsertRow)[columnName.second.nPosition] = columnName.second.sDefaultValue;
+ (*_rInsertRow)[columnName.second.nPosition].setTypeKind(columnName.second.nType);
+ }
+ }
+ }
+ try
+ {
+ Reference< XGeneratedResultSet > xGRes(xPrep, UNO_QUERY);
+ if ( xGRes.is() )
+ {
+ Reference< XResultSet > xRes = xGRes->getGeneratedValues();
+ Reference< XRow > xRow(xRes,UNO_QUERY);
+ if ( xRow.is() && xRes->next() )
+ {
+ Reference< XResultSetMetaDataSupplier > xMdSup(xRes,UNO_QUERY);
+ Reference< XResultSetMetaData > xMd = xMdSup->getMetaData();
+ sal_Int32 nColumnCount = xMd->getColumnCount();
+ std::vector< OUString >::const_iterator aAutoIter = m_aAutoColumns.begin();
+ std::vector< OUString >::const_iterator aAutoEnd = m_aAutoColumns.end();
+ for (sal_Int32 j = 1;aAutoIter != aAutoEnd && j <= nColumnCount; ++aAutoIter,++j)
+ {
+ SelectColumnsMetaData::const_iterator aFind = m_pKeyColumnNames->find(*aAutoIter);
+ if ( aFind != m_pKeyColumnNames->end() )
+ (*_rInsertRow)[aFind->second.nPosition].fill(j, aFind->second.nType, xRow);
+ }
+ bAutoValuesFetched = true;
+ }
+ }
+ }
+ catch(const Exception&)
+ {
+ SAL_WARN("dbaccess", "Could not execute GeneratedKeys() stmt");
+ }
+ }
+
+ ::comphelper::disposeComponent(xPrep);
+
+ if ( i_sTableName.empty() && !bAutoValuesFetched && m_bInserted )
+ {
+ // first check if all key column values were set
+ const OUString sQuote = getIdentifierQuoteString();
+ OUStringBuffer sMaxStmt;
+ auto aEnd = m_pKeyColumnNames->end();
+ for (auto const& autoColumn : m_aAutoColumns)
+ {
+ // we will only fetch values which are keycolumns
+ SelectColumnsMetaData::const_iterator aFind = m_pKeyColumnNames->find(autoColumn);
+ if ( aFind != aEnd )
+ {
+ sMaxStmt.append(" MAX(" + ::dbtools::quoteName( sQuote,aFind->second.sRealName) + "),");
+ }
+ }
+
+ if(!sMaxStmt.isEmpty())
+ {
+ sMaxStmt[sMaxStmt.getLength()-1] = ' ';
+ OUString sStmt = "SELECT " + sMaxStmt + "FROM ";
+ OUString sCatalog,sSchema,sTable;
+ ::dbtools::qualifiedNameComponents(m_xConnection->getMetaData(),m_sUpdateTableName,sCatalog,sSchema,sTable,::dbtools::EComposeRule::InDataManipulation);
+ sStmt += ::dbtools::composeTableNameForSelect( m_xConnection, sCatalog, sSchema, sTable );
+ try
+ {
+ // now fetch the autoincrement values
+ Reference<XStatement> xStatement = m_xConnection->createStatement();
+ Reference<XResultSet> xRes = xStatement->executeQuery(sStmt);
+ Reference<XRow> xRow(xRes,UNO_QUERY);
+ if(xRow.is() && xRes->next())
+ {
+ sal_Int32 j=1;
+ for (auto const& autoColumn : m_aAutoColumns)
+ {
+ // we will only fetch values which are keycolumns
+ SelectColumnsMetaData::const_iterator aFind = m_pKeyColumnNames->find(autoColumn);
+ if ( aFind != aEnd )
+ (*_rInsertRow)[aFind->second.nPosition].fill(j++, aFind->second.nType, xRow);
+ }
+ }
+ ::comphelper::disposeComponent(xStatement);
+ }
+ catch(SQLException&)
+ {
+ SAL_WARN("dbaccess", "Could not fetch with MAX() ");
+ }
+ }
+ }
+ if ( m_bInserted )
+ {
+ OKeySetMatrix::const_iterator aKeyIter = m_aKeyMap.end();
+ --aKeyIter;
+ ORowSetRow aKeyRow = new connectivity::ORowVector< ORowSetValue >(m_pKeyColumnNames->size());
+ copyRowValue(_rInsertRow,aKeyRow,aKeyIter->first + 1);
+
+ m_aKeyIter = m_aKeyMap.emplace( aKeyIter->first + 1, OKeySetValue(aKeyRow,std::pair<sal_Int32,Reference<XRow> >(1,Reference<XRow>())) ).first;
+ // now we set the bookmark for this row
+ (*_rInsertRow)[0] = Any(static_cast<sal_Int32>(m_aKeyIter->first));
+ tryRefetch(_rInsertRow,bRefetch);
+ }
+}
+
+void OKeySet::tryRefetch(const ORowSetRow& _rInsertRow,bool bRefetch)
+{
+ if ( bRefetch )
+ {
+ try
+ {
+ bRefetch = doTryRefetch_throw();
+ }
+ catch(const Exception&)
+ {
+ bRefetch = false;
+ }
+ }
+ if ( !bRefetch )
+ {
+ m_aKeyIter->second.second.second = new OPrivateRow(std::vector(*_rInsertRow));
+ }
+}
+
+void OKeySet::copyRowValue(const ORowSetRow& _rInsertRow, ORowSetRow const & _rKeyRow, sal_Int32 i_nBookmark)
+{
+ connectivity::ORowVector< ORowSetValue >::Vector::iterator aIter = _rKeyRow->begin();
+
+ // check the if the parameter values have been changed
+ OSL_ENSURE((m_aParameterValueForCache->size()-1) == m_pParameterNames->size(),"OKeySet::copyRowValue: Parameter values and names differ!");
+ connectivity::ORowVector< ORowSetValue >::Vector::const_iterator aParaValuesIter = m_aParameterValueForCache->begin() +1;
+
+ bool bChanged = false;
+ sal_Int32 i = 1;
+ for (auto const& parameterName : *m_pParameterNames)
+ {
+ ORowSetValue aValue(*aParaValuesIter);
+ aValue.setSigned(m_aSignedFlags[parameterName.second.nPosition-1]);
+ if ( (*_rInsertRow)[parameterName.second.nPosition] != aValue )
+ {
+ rtl::Reference aCopy(
+ new ORowSetValueVector(*m_aParameterValueForCache));
+ (*aCopy)[i] = (*_rInsertRow)[parameterName.second.nPosition];
+ m_aUpdatedParameter[i_nBookmark] = aCopy;
+ bChanged = true;
+ }
+ ++aParaValuesIter;
+ ++i;
+ }
+ if ( !bChanged )
+ {
+ m_aUpdatedParameter.erase(i_nBookmark);
+ }
+
+ // update the key values
+ for (auto const& keyColumnName : *m_pKeyColumnNames)
+ {
+ impl_convertValue_throw(_rInsertRow,keyColumnName.second);
+ *aIter = (*_rInsertRow)[keyColumnName.second.nPosition];
+ aIter->setTypeKind(keyColumnName.second.nType);
+ ++aIter;
+ }
+}
+
+void OKeySet::deleteRow(const ORowSetRow& _rDeleteRow,const connectivity::OSQLTable& _xTable )
+{
+ Reference<XPropertySet> xSet(_xTable,UNO_QUERY);
+ fillTableName(xSet);
+
+ OUStringBuffer aSql("DELETE FROM " + m_aComposedTableName + " WHERE ");
+
+ // list all columns that should be set
+ OUString aQuote = getIdentifierQuoteString();
+ static const char aAnd[] = " AND ";
+
+ // use keys and indexes for exact positioning
+ Reference<XIndexesSupplier> xIndexSup(_xTable,UNO_QUERY);
+ Reference<XIndexAccess> xIndexes;
+ if ( xIndexSup.is() )
+ xIndexes.set(xIndexSup->getIndexes(),UNO_QUERY);
+
+ // Reference<XColumnsSupplier>
+ std::vector< Reference<XNameAccess> > aAllIndexColumns;
+ lcl_fillIndexColumns(xIndexes,aAllIndexColumns);
+
+ OUStringBuffer sIndexCondition;
+ std::vector<sal_Int32> aIndexColumnPositions;
+
+ for (auto const& columnName : *m_pColumnNames)
+ {
+ if ( m_pKeyColumnNames->find(columnName.first) != m_pKeyColumnNames->end() )
+ {
+ aSql.append(::dbtools::quoteName( aQuote,columnName.second.sRealName));
+ if((*_rDeleteRow)[columnName.second.nPosition].isNull())
+ {
+ SAL_WARN("dbaccess", "can a primary key be null");
+ aSql.append(" IS NULL");
+ }
+ else
+ aSql.append(" = ?");
+ aSql.append(aAnd);
+ }
+ else
+ {
+ for (auto const& indexColumn : aAllIndexColumns)
+ {
+ if(indexColumn->hasByName(columnName.first))
+ {
+ sIndexCondition.append(::dbtools::quoteName( aQuote,columnName.second.sRealName));
+ if((*_rDeleteRow)[columnName.second.nPosition].isNull())
+ sIndexCondition.append(" IS NULL");
+ else
+ {
+ sIndexCondition.append(" = ?");
+ aIndexColumnPositions.push_back(columnName.second.nPosition);
+ }
+ sIndexCondition.append(aAnd);
+
+ break;
+ }
+ }
+ }
+ }
+ aSql.append(sIndexCondition);
+ aSql.setLength(aSql.getLength()-5);
+
+ // now create end execute the prepared statement
+ Reference< XPreparedStatement > xPrep(m_xConnection->prepareStatement(aSql.makeStringAndClear()));
+ Reference< XParameters > xParameter(xPrep,UNO_QUERY);
+
+ sal_Int32 i = 1;
+ for (auto const& keyColumnName : *m_pKeyColumnNames)
+ {
+ setParameter(i++,xParameter,(*_rDeleteRow)[keyColumnName.second.nPosition],keyColumnName.second.nType,keyColumnName.second.nScale);
+ }
+
+ // now we have to set the index values
+ auto aIter = m_pColumnNames->begin();
+ for (auto const& indexColumnPosition : aIndexColumnPositions)
+ {
+ setParameter(i++,xParameter,(*_rDeleteRow)[indexColumnPosition],(*_rDeleteRow)[indexColumnPosition].getTypeKind(),aIter->second.nScale);
+ ++aIter;
+ }
+
+ m_bDeleted = xPrep->executeUpdate() > 0;
+
+ if(m_bDeleted)
+ {
+ sal_Int32 nBookmark = ::comphelper::getINT32((*_rDeleteRow)[0].getAny());
+ if(m_aKeyIter == m_aKeyMap.find(nBookmark) && m_aKeyIter != m_aKeyMap.end())
+ ++m_aKeyIter;
+ m_aKeyMap.erase(nBookmark);
+ m_bDeleted = true;
+ }
+}
+
+bool OKeySet::next()
+{
+ m_bInserted = m_bUpdated = m_bDeleted = false;
+
+ if(isAfterLast())
+ return false;
+ ++m_aKeyIter;
+ if(!m_bRowCountFinal && m_aKeyIter == m_aKeyMap.end())
+ {
+ // not yet all records fetched, but we reached the end of those we fetched
+ // try to fetch one more row
+ if (fetchRow())
+ {
+ OSL_ENSURE(!isAfterLast(), "fetchRow succeeded, but isAfterLast()");
+ return true;
+ }
+ else
+ {
+ // nope, we arrived at end of data
+ m_aKeyIter = m_aKeyMap.end();
+ OSL_ENSURE(isAfterLast(), "fetchRow failed, but not end of data");
+ }
+ }
+
+ invalidateRow();
+ return !isAfterLast();
+}
+
+bool OKeySet::isBeforeFirst( )
+{
+ return m_aKeyIter == m_aKeyMap.begin();
+}
+
+bool OKeySet::isAfterLast( )
+{
+ return m_bRowCountFinal && m_aKeyIter == m_aKeyMap.end();
+}
+
+void OKeySet::beforeFirst( )
+{
+ m_bInserted = m_bUpdated = m_bDeleted = false;
+ m_aKeyIter = m_aKeyMap.begin();
+ invalidateRow();
+}
+
+void OKeySet::afterLast( )
+{
+ m_bInserted = m_bUpdated = m_bDeleted = false;
+ fillAllRows();
+ m_aKeyIter = m_aKeyMap.end();
+ invalidateRow();
+}
+
+bool OKeySet::first()
+{
+ m_bInserted = m_bUpdated = m_bDeleted = false;
+ m_aKeyIter = m_aKeyMap.begin();
+ ++m_aKeyIter;
+ if(m_aKeyIter == m_aKeyMap.end())
+ {
+ if (!fetchRow())
+ {
+ m_aKeyIter = m_aKeyMap.end();
+ return false;
+ }
+ }
+ else
+ invalidateRow();
+ return m_aKeyIter != m_aKeyMap.end() && m_aKeyIter != m_aKeyMap.begin();
+}
+
+bool OKeySet::last( )
+{
+ m_bInserted = m_bUpdated = m_bDeleted = false;
+ bool bFetchedRow = fillAllRows();
+
+ m_aKeyIter = m_aKeyMap.end();
+ --m_aKeyIter;
+ if ( !bFetchedRow )
+ {
+ invalidateRow();
+ }
+ return m_aKeyIter != m_aKeyMap.end() && m_aKeyIter != m_aKeyMap.begin();
+}
+
+sal_Int32 OKeySet::getRow( )
+{
+ OSL_ENSURE(!isAfterLast(),"getRow is not allowed when afterlast record!");
+ OSL_ENSURE(!isBeforeFirst(),"getRow is not allowed when beforefirst record!");
+
+ return std::distance(m_aKeyMap.begin(),m_aKeyIter);
+}
+
+bool OKeySet::absolute( sal_Int32 row )
+{
+ m_bInserted = m_bUpdated = m_bDeleted = false;
+ OSL_ENSURE(row,"absolute(0) isn't allowed!");
+ bool bFetchedRow = false;
+ if(row < 0)
+ {
+ if(!m_bRowCountFinal)
+ bFetchedRow = fillAllRows();
+
+ row = std::min(std::abs(row), static_cast<sal_Int32>(std::distance(m_aKeyMap.begin(), m_aKeyIter)));
+ m_aKeyIter = std::prev(m_aKeyIter, row);
+ }
+ else
+ {
+ if(row >= static_cast<sal_Int32>(m_aKeyMap.size()))
+ {
+ // we don't have this row
+ if(!m_bRowCountFinal)
+ {
+ // but there may still be rows to fetch.
+ bool bNext = true;
+ for(sal_Int32 i=m_aKeyMap.size()-1;i < row && bNext;++i)
+ bNext = fetchRow();
+ // it is guaranteed that the above loop has executed at least once,
+ // that is fetchRow called at least once.
+ if ( bNext )
+ {
+ bFetchedRow = true;
+ }
+ else
+ {
+ // reached end of data before desired row
+ m_aKeyIter = m_aKeyMap.end();
+ return false;
+ }
+ }
+ else
+ {
+ // no more rows to fetch -> fail
+ m_aKeyIter = m_aKeyMap.end();
+ return false;
+ }
+ }
+ else
+ {
+ m_aKeyIter = std::next(m_aKeyMap.begin(), row);
+ }
+ }
+ if ( !bFetchedRow )
+ {
+ invalidateRow();
+ }
+
+ return m_aKeyIter != m_aKeyMap.end() && m_aKeyIter != m_aKeyMap.begin();
+}
+
+bool OKeySet::previous()
+{
+ m_bInserted = m_bUpdated = m_bDeleted = false;
+ if(m_aKeyIter != m_aKeyMap.begin())
+ {
+ --m_aKeyIter;
+ invalidateRow();
+ }
+ return m_aKeyIter != m_aKeyMap.begin();
+}
+
+bool OKeySet::doTryRefetch_throw()
+{
+ ensureStatement( );
+ // we just reassign the base members
+ Reference< XParameters > xParameter(m_xStatement,UNO_QUERY);
+ OSL_ENSURE(xParameter.is(),"No Parameter interface!");
+ xParameter->clearParameters();
+
+ sal_Int32 nPos=1;
+ connectivity::ORowVector< ORowSetValue >::Vector::const_iterator aParaIter;
+ connectivity::ORowVector< ORowSetValue >::Vector::const_iterator aParaEnd;
+ OUpdatedParameter::const_iterator aUpdateFind = m_aUpdatedParameter.find(m_aKeyIter->first);
+ if ( aUpdateFind == m_aUpdatedParameter.end() )
+ {
+ aParaIter = m_aParameterValueForCache->begin();
+ aParaEnd = m_aParameterValueForCache->end();
+ }
+ else
+ {
+ aParaIter = aUpdateFind->second->begin();
+ aParaEnd = aUpdateFind->second->end();
+ }
+
+ for(++aParaIter;aParaIter != aParaEnd;++aParaIter,++nPos)
+ {
+ ::dbtools::setObjectWithInfo( xParameter, nPos, aParaIter->makeAny(), aParaIter->getTypeKind() );
+ }
+
+ // now set the primary key column values
+ connectivity::ORowVector< ORowSetValue >::Vector::const_iterator aIter = m_aKeyIter->second.first->begin();
+ for (auto const& keyColumnName : *m_pKeyColumnNames)
+ setOneKeyColumnParameter(nPos,xParameter,*aIter++,keyColumnName.second.nType,keyColumnName.second.nScale);
+ for (auto const& foreignColumnName : *m_pForeignColumnNames)
+ setOneKeyColumnParameter(nPos,xParameter,*aIter++,foreignColumnName.second.nType,foreignColumnName.second.nScale);
+
+ m_xSet = m_xStatement->executeQuery();
+ OSL_ENSURE(m_xSet.is(),"No resultset from statement!");
+ return m_xSet->next();
+}
+
+void OKeySet::refreshRow()
+{
+ invalidateRow();
+
+ if(isBeforeFirst() || isAfterLast())
+ return;
+
+ if ( m_aKeyIter->second.second.second.is() )
+ {
+ m_xRow = m_aKeyIter->second.second.second;
+ return;
+ }
+
+ bool bOK = doTryRefetch_throw();
+ if ( !bOK )
+ {
+ // This row has disappeared; remove it.
+ OKeySetMatrix::const_iterator aTemp = m_aKeyIter;
+ // use *next* row
+ ++m_aKeyIter;
+ m_aKeyMap.erase(aTemp);
+
+ // adjust RowCount for the row we have removed
+ if (m_rRowCount > 0)
+ --m_rRowCount;
+ else
+ SAL_WARN("dbaccess", "m_rRowCount got out of sync: non-empty m_aKeyMap, but m_rRowCount <= 0");
+
+ if (m_aKeyIter == m_aKeyMap.end())
+ {
+ ::comphelper::disposeComponent(m_xSet);
+ if (!isAfterLast())
+ {
+ // it was the last fetched row,
+ // but there may be another one to fetch
+ if (!fetchRow())
+ {
+ // nope, that really was the last
+ m_aKeyIter = m_aKeyMap.end();
+ OSL_ENSURE(isAfterLast(), "fetchRow() failed but not isAfterLast()!");
+ }
+ }
+ // Now, either fetchRow has set m_xRow or isAfterLast()
+ }
+ else
+ {
+ refreshRow();
+ }
+ }
+ else
+ {
+ m_xRow.set(m_xSet,UNO_QUERY);
+ OSL_ENSURE(m_xRow.is(),"No row from statement!");
+ }
+}
+
+bool OKeySet::fetchRow()
+{
+ // fetch the next row and append on the keyset
+ bool bRet = false;
+ if ( !m_bRowCountFinal && (!m_nMaxRows || sal_Int32(m_aKeyMap.size()) < m_nMaxRows) )
+ bRet = m_xDriverSet->next();
+ if ( bRet )
+ {
+ ORowSetRow aKeyRow = new connectivity::ORowVector< ORowSetValue >((*m_pKeyColumnNames).size() + m_pForeignColumnNames->size());
+
+ ::comphelper::disposeComponent(m_xSet);
+ m_xRow.set(m_xDriverRow, UNO_SET_THROW);
+
+ connectivity::ORowVector< ORowSetValue >::Vector::iterator aIter = aKeyRow->begin();
+ // copy key columns
+ for (auto const& keyColumnName : *m_pKeyColumnNames)
+ {
+ const SelectColumnDescription& rColDesc = keyColumnName.second;
+ aIter->fill(rColDesc.nPosition, rColDesc.nType, m_xRow);
+ ++aIter;
+ }
+ // copy missing columns from other tables
+ for (auto const& foreignColumnName : *m_pForeignColumnNames)
+ {
+ const SelectColumnDescription& rColDesc = foreignColumnName.second;
+ aIter->fill(rColDesc.nPosition, rColDesc.nType, m_xRow);
+ ++aIter;
+ }
+ m_aKeyIter = m_aKeyMap.emplace( m_aKeyMap.rbegin()->first+1,OKeySetValue(aKeyRow,std::pair<sal_Int32,Reference<XRow> >(0,Reference<XRow>())) ).first;
+ }
+ else
+ m_bRowCountFinal = true;
+ return bRet;
+}
+
+bool OKeySet::fillAllRows()
+{
+ if(m_bRowCountFinal)
+ {
+ return false;
+ }
+ else
+ {
+ while(fetchRow())
+ ;
+ return true;
+ }
+}
+
+// XRow
+sal_Bool SAL_CALL OKeySet::wasNull( )
+{
+ if ( ! m_xRow.is() )
+ throwGenericSQLException("Must call getFOO() for some FOO before wasNull()", *this);
+
+ OSL_ENSURE(m_xRow.is(),"m_xRow is null! I've thrown, but function execution continued?");
+ return m_xRow->wasNull();
+}
+
+inline void OKeySet::ensureRowForData( )
+{
+ if (! m_xRow.is() )
+ refreshRow();
+ if (! m_xRow.is() )
+ throwSQLException("Failed to refetch row", "02000", *this, -2);
+
+ OSL_ENSURE(m_xRow.is(),"m_xRow is null! I've called throwSQLException but execution continued?");
+}
+
+OUString SAL_CALL OKeySet::getString( sal_Int32 columnIndex )
+{
+ ensureRowForData();
+ return m_xRow->getString(columnIndex);
+}
+
+sal_Bool SAL_CALL OKeySet::getBoolean( sal_Int32 columnIndex )
+{
+ ensureRowForData();
+ return m_xRow->getBoolean(columnIndex);
+}
+
+sal_Int8 SAL_CALL OKeySet::getByte( sal_Int32 columnIndex )
+{
+ ensureRowForData();
+ return m_xRow->getByte(columnIndex);
+}
+
+sal_Int16 SAL_CALL OKeySet::getShort( sal_Int32 columnIndex )
+{
+ ensureRowForData();
+ return m_xRow->getShort(columnIndex);
+}
+
+sal_Int32 SAL_CALL OKeySet::getInt( sal_Int32 columnIndex )
+{
+ ensureRowForData();
+ return m_xRow->getInt(columnIndex);
+}
+
+sal_Int64 SAL_CALL OKeySet::getLong( sal_Int32 columnIndex )
+{
+ ensureRowForData();
+ return m_xRow->getLong(columnIndex);
+}
+
+float SAL_CALL OKeySet::getFloat( sal_Int32 columnIndex )
+{
+ ensureRowForData();
+ return m_xRow->getFloat(columnIndex);
+}
+
+double SAL_CALL OKeySet::getDouble( sal_Int32 columnIndex )
+{
+ ensureRowForData();
+ return m_xRow->getDouble(columnIndex);
+}
+
+Sequence< sal_Int8 > SAL_CALL OKeySet::getBytes( sal_Int32 columnIndex )
+{
+ ensureRowForData();
+ return m_xRow->getBytes(columnIndex);
+}
+
+css::util::Date SAL_CALL OKeySet::getDate( sal_Int32 columnIndex )
+{
+ ensureRowForData();
+ return m_xRow->getDate(columnIndex);
+}
+
+css::util::Time SAL_CALL OKeySet::getTime( sal_Int32 columnIndex )
+{
+ ensureRowForData();
+ return m_xRow->getTime(columnIndex);
+}
+
+css::util::DateTime SAL_CALL OKeySet::getTimestamp( sal_Int32 columnIndex )
+{
+ ensureRowForData();
+ return m_xRow->getTimestamp(columnIndex);
+}
+
+Reference< css::io::XInputStream > SAL_CALL OKeySet::getBinaryStream( sal_Int32 columnIndex )
+{
+ ensureRowForData();
+ return m_xRow->getBinaryStream(columnIndex);
+}
+
+Reference< css::io::XInputStream > SAL_CALL OKeySet::getCharacterStream( sal_Int32 columnIndex )
+{
+ ensureRowForData();
+ return m_xRow->getCharacterStream(columnIndex);
+}
+
+Any SAL_CALL OKeySet::getObject( sal_Int32 columnIndex, const Reference< css::container::XNameAccess >& typeMap )
+{
+ ensureRowForData();
+ return m_xRow->getObject(columnIndex,typeMap);
+}
+
+Reference< XRef > SAL_CALL OKeySet::getRef( sal_Int32 columnIndex )
+{
+ ensureRowForData();
+ return m_xRow->getRef(columnIndex);
+}
+
+Reference< XBlob > SAL_CALL OKeySet::getBlob( sal_Int32 columnIndex )
+{
+ ensureRowForData();
+ return m_xRow->getBlob(columnIndex);
+}
+
+Reference< XClob > SAL_CALL OKeySet::getClob( sal_Int32 columnIndex )
+{
+ ensureRowForData();
+ return m_xRow->getClob(columnIndex);
+}
+
+Reference< XArray > SAL_CALL OKeySet::getArray( sal_Int32 columnIndex )
+{
+ ensureRowForData();
+ return m_xRow->getArray(columnIndex);
+}
+
+bool OKeySet::rowUpdated( )
+{
+ return m_aKeyIter != m_aKeyMap.begin() && m_aKeyIter != m_aKeyMap.end() && m_aKeyIter->second.second.first == 2;
+}
+
+bool OKeySet::rowInserted( )
+{
+ return m_aKeyIter != m_aKeyMap.begin() && m_aKeyIter != m_aKeyMap.end() && m_aKeyIter->second.second.first == 1;
+}
+
+bool OKeySet::rowDeleted( )
+{
+ bool bDeleted = m_bDeleted;
+ m_bDeleted = false;
+ return bDeleted;
+}
+
+namespace dbaccess
+{
+
+void getColumnPositions(const Reference<XNameAccess>& _rxQueryColumns,
+ const css::uno::Sequence< OUString >& _aColumnNames,
+ std::u16string_view _rsUpdateTableName,
+ SelectColumnsMetaData& o_rColumnNames,
+ bool i_bAppendTableName)
+ {
+ // get the real name of the columns
+ Sequence< OUString> aSelNames(_rxQueryColumns->getElementNames());
+ const OUString* pSelIter = aSelNames.getConstArray();
+ const OUString* pSelEnd = pSelIter + aSelNames.getLength();
+
+ const OUString* pTblColumnIter = _aColumnNames.getConstArray();
+ const OUString* pTblColumnEnd = pTblColumnIter + _aColumnNames.getLength();
+
+ ::comphelper::UStringMixEqual bCase(o_rColumnNames.key_comp().isCaseSensitive());
+
+ for(sal_Int32 nPos = 1;pSelIter != pSelEnd;++pSelIter,++nPos)
+ {
+ Reference<XPropertySet> xQueryColumnProp(_rxQueryColumns->getByName(*pSelIter),UNO_QUERY_THROW);
+ OUString sRealName,sTableName;
+ OSL_ENSURE(xQueryColumnProp->getPropertySetInfo()->hasPropertyByName(PROPERTY_REALNAME),"Property REALNAME not available!");
+ OSL_ENSURE(xQueryColumnProp->getPropertySetInfo()->hasPropertyByName(PROPERTY_TABLENAME),"Property TABLENAME not available!");
+ xQueryColumnProp->getPropertyValue(PROPERTY_REALNAME) >>= sRealName;
+ xQueryColumnProp->getPropertyValue(PROPERTY_TABLENAME) >>= sTableName;
+
+ for(;pTblColumnIter != pTblColumnEnd;++pTblColumnIter)
+ {
+ if(bCase(sRealName,*pTblColumnIter) && bCase(_rsUpdateTableName,sTableName) && o_rColumnNames.find(*pTblColumnIter) == o_rColumnNames.end())
+ {
+ sal_Int32 nType = 0;
+ xQueryColumnProp->getPropertyValue(PROPERTY_TYPE) >>= nType;
+ sal_Int32 nScale = 0;
+ xQueryColumnProp->getPropertyValue(PROPERTY_SCALE) >>= nScale;
+ OUString sColumnDefault;
+ if ( xQueryColumnProp->getPropertySetInfo()->hasPropertyByName(PROPERTY_DEFAULTVALUE) )
+ xQueryColumnProp->getPropertyValue(PROPERTY_DEFAULTVALUE) >>= sColumnDefault;
+
+ sal_Int32 nNullable = ColumnValue::NULLABLE_UNKNOWN;
+ OSL_VERIFY( xQueryColumnProp->getPropertyValue( PROPERTY_ISNULLABLE ) >>= nNullable );
+
+ SelectColumnDescription aColDesc( nPos, nType, nScale, nNullable != sdbc::ColumnValue::NO_NULLS, sColumnDefault );
+ OUString sName;
+ if ( i_bAppendTableName )
+ {
+ sName = sTableName + "." + sRealName;
+ aColDesc.sRealName = sRealName;
+ aColDesc.sTableName = sTableName;
+ }
+ else
+ {
+ sName = sRealName;
+ }
+ o_rColumnNames[sName] = aColDesc;
+
+ break;
+ }
+ }
+ pTblColumnIter = _aColumnNames.getConstArray();
+ }
+ }
+}
+
+void OKeySet::impl_convertValue_throw(const ORowSetRow& _rInsertRow,const SelectColumnDescription& i_aMetaData)
+{
+ ORowSetValue& aValue((*_rInsertRow)[i_aMetaData.nPosition]);
+ switch(i_aMetaData.nType)
+ {
+ case DataType::DECIMAL:
+ case DataType::NUMERIC:
+ {
+ OUString sValue = aValue.getString();
+ sal_Int32 nIndex = sValue.indexOf('.');
+ if ( nIndex != -1 )
+ {
+ aValue = sValue.copy(0,std::min(sValue.getLength(),nIndex + (i_aMetaData.nScale > 0 ? i_aMetaData.nScale + 1 : 0)));
+ }
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/api/KeySet.hxx b/dbaccess/source/core/api/KeySet.hxx
new file mode 100644
index 000000000..57889c774
--- /dev/null
+++ b/dbaccess/source/core/api/KeySet.hxx
@@ -0,0 +1,216 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include "CacheSet.hxx"
+
+#include <memory>
+#include <map>
+#include <vector>
+
+#include <com/sun/star/sdb/XSingleSelectQueryAnalyzer.hpp>
+#include <com/sun/star/sdb/XSingleSelectQueryComposer.hpp>
+#include <comphelper/stl_types.hxx>
+
+namespace dbaccess
+{
+ struct SelectColumnDescription
+ {
+ OUString sRealName; // may be empty
+ OUString sTableName; // may be empty
+ OUString sDefaultValue;
+ sal_Int32 nPosition;
+ sal_Int32 nType;
+ sal_Int32 nScale;
+ bool bNullable;
+
+ SelectColumnDescription()
+ :nPosition( 0 )
+ ,nType( 0 )
+ ,nScale( 0 )
+ ,bNullable(false)
+ {
+ }
+
+ SelectColumnDescription( sal_Int32 _nPosition, sal_Int32 _nType, sal_Int32 _nScale,bool _bNullable, const OUString& _rDefaultValue )
+ :sDefaultValue( _rDefaultValue )
+ ,nPosition( _nPosition )
+ ,nType( _nType )
+ ,nScale( _nScale )
+ ,bNullable(_bNullable)
+ {
+ }
+ };
+ typedef std::map< OUString, SelectColumnDescription, ::comphelper::UStringMixLess > SelectColumnsMetaData;
+
+ // the elements of _rxQueryColumns must have the properties PROPERTY_REALNAME and PROPERTY_TABLENAME
+ void getColumnPositions(const css::uno::Reference< css::container::XNameAccess >& _rxQueryColumns,
+ const css::uno::Sequence< OUString >& _rColumnNames,
+ std::u16string_view _rsUpdateTableName,
+ SelectColumnsMetaData& o_rColumnNames /* out */,
+ bool i_bAppendTableName = false);
+
+ typedef std::pair<ORowSetRow,std::pair<sal_Int32,css::uno::Reference< css::sdbc::XRow> > > OKeySetValue;
+ typedef std::map<sal_Int32,OKeySetValue > OKeySetMatrix;
+ typedef std::map<sal_Int32, rtl::Reference<ORowSetValueVector> > OUpdatedParameter;
+ // is used when the source supports keys
+ class OKeySet : public OCacheSet
+ {
+ protected:
+ OKeySetMatrix m_aKeyMap;
+ OKeySetMatrix::iterator m_aKeyIter;
+
+ std::vector< OUString > m_aAutoColumns; // contains all columns which are autoincrement ones
+
+ OUpdatedParameter m_aUpdatedParameter; // contains all parameter which have been updated and are needed for refetching
+ rtl::Reference<ORowSetValueVector> m_aParameterValueForCache;
+ std::unique_ptr<SelectColumnsMetaData> m_pKeyColumnNames; // contains all key column names
+ std::unique_ptr<SelectColumnsMetaData> m_pColumnNames; // contains all column names
+ std::unique_ptr<SelectColumnsMetaData> m_pParameterNames; // contains all parameter names
+ std::unique_ptr<SelectColumnsMetaData> m_pForeignColumnNames; // contains all column names of the rest
+ connectivity::OSQLTable m_xTable; // reference to our table
+ // we need a different SQL (statement) for each different combination
+ // of NULLness of key & foreign columns;
+ // each subclause is either "colName = ?" or "colName IS NULL"
+ // (we avoid the standard "colName IS NOT DISTINCT FROM ?" because it is not widely supported)
+ typedef std::map< std::vector<bool>,
+ css::uno::Reference< css::sdbc::XPreparedStatement > >
+ vStatements_t;
+ vStatements_t m_vStatements;
+ css::uno::Reference< css::sdbc::XPreparedStatement> m_xStatement;
+ css::uno::Reference< css::sdbc::XResultSet> m_xSet;
+ css::uno::Reference< css::sdbc::XRow> m_xRow;
+ css::uno::Reference< css::sdb::XSingleSelectQueryAnalyzer > m_xComposer;
+ const OUString m_sUpdateTableName;
+ std::vector< OUString > m_aFilterColumns;
+ sal_Int32& m_rRowCount;
+
+ bool m_bRowCountFinal;
+
+ /** copies the values from the insert row into the key row
+ *
+ * \param _rInsertRow the row which was inserted
+ * \param _rKeyRow The current key row of the row set.
+ + \param i_nBookmark The bookmark is used to update the parameter
+ */
+ void copyRowValue(const ORowSetRow& _rInsertRow, ORowSetRow const & _rKeyRow, sal_Int32 i_nBookmark);
+
+ // returns true if it did any work
+ bool fillAllRows();
+ bool fetchRow();
+ void invalidateRow();
+
+ static void impl_convertValue_throw(const ORowSetRow& _rInsertRow,const SelectColumnDescription& i_aMetaData);
+ void initColumns();
+ void findTableColumnsMatching_throw( const css::uno::Any& i_aTable,
+ const OUString& i_rUpdateTableName,
+ const css::uno::Reference< css::sdbc::XDatabaseMetaData>& i_xMeta,
+ const css::uno::Reference< css::container::XNameAccess>& i_xQueryColumns,
+ std::unique_ptr<SelectColumnsMetaData> const & o_pKeyColumnNames);
+ void ensureStatement( );
+ virtual void makeNewStatement( );
+ static void setOneKeyColumnParameter( sal_Int32 &nPos,
+ const css::uno::Reference< css::sdbc::XParameters > &_xParameter,
+ const connectivity::ORowSetValue &_rValue,
+ sal_Int32 _nType,
+ sal_Int32 _nScale );
+ OUStringBuffer createKeyFilter( );
+ /// @throws css::sdbc::SQLException
+ /// @throws css::uno::RuntimeException
+ bool doTryRefetch_throw();
+ void tryRefetch(const ORowSetRow& _rInsertRow,bool bRefetch);
+ void executeUpdate(const ORowSetRow& _rInsertRow, const ORowSetRow& _rOriginalRow, const OUString& i_sSQL, std::u16string_view i_sTableName,const std::vector<sal_Int32>& _aIndexColumnPositions = std::vector<sal_Int32>());
+ void executeInsert( const ORowSetRow& _rInsertRow, const OUString& i_sSQL, std::u16string_view i_sTableName, bool bRefetch = false);
+ void executeStatement(OUStringBuffer& io_aFilter, css::uno::Reference< css::sdb::XSingleSelectQueryComposer>& io_xAnalyzer);
+
+ virtual ~OKeySet() override;
+ public:
+ OKeySet(const connectivity::OSQLTable& _xTable,
+ const OUString& _rUpdateTableName,
+ const css::uno::Reference< css::sdb::XSingleSelectQueryAnalyzer >& _xComposer,
+ const ORowSetValueVector& _aParameterValueForCache,
+ sal_Int32 i_nMaxRows,
+ sal_Int32& o_nRowCount);
+
+ // late ctor which can throw exceptions
+ virtual void construct(const css::uno::Reference< css::sdbc::XResultSet>& _xDriverSet,const OUString& i_sRowSetFilter) override;
+ virtual void reset(const css::uno::Reference< css::sdbc::XResultSet>& _xDriverSet) override;
+
+ // css::sdbc::XRow
+ virtual sal_Bool SAL_CALL wasNull( ) override;
+ virtual OUString SAL_CALL getString( sal_Int32 columnIndex ) override;
+ virtual sal_Bool SAL_CALL getBoolean( sal_Int32 columnIndex ) override;
+ virtual sal_Int8 SAL_CALL getByte( sal_Int32 columnIndex ) override;
+ virtual sal_Int16 SAL_CALL getShort( sal_Int32 columnIndex ) override;
+ virtual sal_Int32 SAL_CALL getInt( sal_Int32 columnIndex ) override;
+ virtual sal_Int64 SAL_CALL getLong( sal_Int32 columnIndex ) override;
+ virtual float SAL_CALL getFloat( sal_Int32 columnIndex ) override;
+ virtual double SAL_CALL getDouble( sal_Int32 columnIndex ) override;
+ virtual css::uno::Sequence< sal_Int8 > SAL_CALL getBytes( sal_Int32 columnIndex ) override;
+ virtual css::util::Date SAL_CALL getDate( sal_Int32 columnIndex ) override;
+ virtual css::util::Time SAL_CALL getTime( sal_Int32 columnIndex ) override;
+ virtual css::util::DateTime SAL_CALL getTimestamp( sal_Int32 columnIndex ) override;
+ virtual css::uno::Reference< css::io::XInputStream > SAL_CALL getBinaryStream( sal_Int32 columnIndex ) override;
+ virtual css::uno::Reference< css::io::XInputStream > SAL_CALL getCharacterStream( sal_Int32 columnIndex ) override;
+ virtual css::uno::Any SAL_CALL getObject( sal_Int32 columnIndex, const css::uno::Reference< css::container::XNameAccess >& typeMap ) override;
+ virtual css::uno::Reference< css::sdbc::XRef > SAL_CALL getRef( sal_Int32 columnIndex ) override;
+ virtual css::uno::Reference< css::sdbc::XBlob > SAL_CALL getBlob( sal_Int32 columnIndex ) override;
+ virtual css::uno::Reference< css::sdbc::XClob > SAL_CALL getClob( sal_Int32 columnIndex ) override;
+ virtual css::uno::Reference< css::sdbc::XArray > SAL_CALL getArray( sal_Int32 columnIndex ) override;
+
+
+ virtual bool rowUpdated( ) override;
+ virtual bool rowInserted( ) override;
+ virtual bool rowDeleted( ) override;
+ bool isBeforeFirst( );
+ bool isAfterLast( );
+
+ // css::sdbc::XResultSet
+ virtual bool next() override;
+ virtual void beforeFirst( ) override;
+ virtual void afterLast( ) override;
+ virtual bool first() override;
+ virtual bool last( ) override;
+ virtual sal_Int32 getRow( ) override;
+ virtual bool absolute( sal_Int32 row ) override;
+ virtual bool previous( ) override;
+ /// @throws css::sdbc::SQLException
+ /// @throws css::uno::RuntimeException
+ void ensureRowForData( );
+ virtual void refreshRow( ) override;
+ // css::sdbcx::XRowLocate
+ virtual css::uno::Any getBookmark() override;
+
+ virtual bool moveToBookmark( const css::uno::Any& bookmark ) override;
+
+ virtual sal_Int32 compareBookmarks( const css::uno::Any& first, const css::uno::Any& second ) override;
+
+ virtual bool hasOrderedBookmarks( ) override;
+
+ virtual sal_Int32 hashBookmark( const css::uno::Any& bookmark ) override;
+
+ // css::sdbc::XResultSetUpdate
+ virtual void updateRow(const ORowSetRow& _rInsertRow,const ORowSetRow& _rOriginalRow,const connectivity::OSQLTable& _xTable ) override;
+ virtual void deleteRow(const ORowSetRow& _rInsertRow,const connectivity::OSQLTable& _xTable ) override;
+ virtual void insertRow( const ORowSetRow& _rInsertRow,const connectivity::OSQLTable& _xTable ) override;
+ };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/api/OptimisticSet.cxx b/dbaccess/source/core/api/OptimisticSet.cxx
new file mode 100644
index 000000000..d1d70955f
--- /dev/null
+++ b/dbaccess/source/core/api/OptimisticSet.cxx
@@ -0,0 +1,586 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#include <memory>
+#include "OptimisticSet.hxx"
+#include <core_resource.hxx>
+#include <strings.hrc>
+#include <strings.hxx>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/sdbc/XDatabaseMetaData.hpp>
+#include <com/sun/star/sdbc/XPreparedStatement.hpp>
+#include <com/sun/star/sdbc/XParameters.hpp>
+#include <com/sun/star/sdb/XSingleSelectQueryComposer.hpp>
+#include <comphelper/types.hxx>
+#include <connectivity/dbtools.hxx>
+#include <connectivity/dbexception.hxx>
+#include <map>
+#include <algorithm>
+#include <com/sun/star/sdbcx/XTablesSupplier.hpp>
+#include <composertools.hxx>
+
+using namespace dbaccess;
+using namespace ::connectivity;
+using namespace ::dbtools;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::sdb;
+using namespace ::com::sun::star::sdbcx;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::util;
+using namespace ::com::sun::star::io;
+using namespace ::com::sun::star;
+using namespace ::cppu;
+using namespace ::osl;
+
+typedef std::map<OUString, OUStringBuffer> TSQLStatements;
+namespace
+{
+ void lcl_fillKeyCondition(const OUString& i_sTableName,std::u16string_view i_sQuotedColumnName,const ORowSetValue& i_aValue,TSQLStatements& io_aKeyConditions)
+ {
+ OUStringBuffer& rKeyCondition = io_aKeyConditions[i_sTableName];
+ if ( !rKeyCondition.isEmpty() )
+ rKeyCondition.append(" AND ");
+ rKeyCondition.append(i_sQuotedColumnName);
+ if ( i_aValue.isNull() )
+ rKeyCondition.append(" IS NULL");
+ else
+ rKeyCondition.append(" = ?");
+ }
+}
+
+
+OptimisticSet::OptimisticSet(const Reference<XComponentContext>& _rContext,
+ const Reference< XConnection>& i_xConnection,
+ const Reference< XSingleSelectQueryAnalyzer >& _xComposer,
+ const ORowSetValueVector& _aParameterValueForCache,
+ sal_Int32 i_nMaxRows,
+ sal_Int32& o_nRowCount)
+ :OKeySet(nullptr,OUString(),_xComposer,_aParameterValueForCache,i_nMaxRows,o_nRowCount)
+ ,m_aSqlParser( _rContext )
+ ,m_aSqlIterator( i_xConnection, Reference<XTablesSupplier>(_xComposer,UNO_QUERY_THROW)->getTables(), m_aSqlParser )
+ ,m_bResultSetChanged(false)
+{
+}
+
+OptimisticSet::~OptimisticSet()
+{
+}
+
+void OptimisticSet::construct(const Reference< XResultSet>& _xDriverSet,const OUString& i_sRowSetFilter)
+{
+ OCacheSet::construct(_xDriverSet,i_sRowSetFilter);
+
+ initColumns();
+ m_sRowSetFilter = i_sRowSetFilter;
+
+ Reference<XDatabaseMetaData> xMeta = m_xConnection->getMetaData();
+ bool bCase = xMeta.is() && xMeta->supportsMixedCaseQuotedIdentifiers();
+ Reference<XColumnsSupplier> xQueryColSup(m_xComposer,UNO_QUERY);
+ const Reference<XNameAccess> xQueryColumns = xQueryColSup->getColumns();
+ const Reference<XTablesSupplier> xTabSup(m_xComposer,UNO_QUERY);
+ const Reference<XNameAccess> xTables = xTabSup->getTables();
+ const Sequence< OUString> aTableNames = xTables->getElementNames();
+ const OUString* pTableNameIter = aTableNames.getConstArray();
+ const OUString* pTableNameEnd = pTableNameIter + aTableNames.getLength();
+ for( ; pTableNameIter != pTableNameEnd ; ++pTableNameIter)
+ {
+ std::unique_ptr<SelectColumnsMetaData> pKeyColumNames(new SelectColumnsMetaData(bCase));
+ findTableColumnsMatching_throw(xTables->getByName(*pTableNameIter),*pTableNameIter,xMeta,xQueryColumns,pKeyColumNames);
+ m_pKeyColumnNames->insert(pKeyColumNames->begin(),pKeyColumNames->end());
+ }
+
+ // the first row is empty because it's now easier for us to distinguish when we are beforefirst or first
+ // without extra variable to be set
+ OKeySetValue keySetValue(nullptr,std::pair<sal_Int32,Reference<XRow> >(0,Reference<XRow>()));
+ m_aKeyMap.emplace(0,keySetValue);
+ m_aKeyIter = m_aKeyMap.begin();
+
+ Reference< XSingleSelectQueryComposer> xSourceComposer(m_xComposer,UNO_QUERY);
+ Reference< XMultiServiceFactory > xFactory(m_xConnection, UNO_QUERY_THROW);
+ Reference<XSingleSelectQueryComposer> xAnalyzer(xFactory->createInstance(SERVICE_NAME_SINGLESELECTQUERYCOMPOSER),UNO_QUERY);
+ OUString sQuery = xSourceComposer->getQuery();
+ xAnalyzer->setElementaryQuery(xSourceComposer->getElementaryQuery());
+ // check for joins
+ OUString aErrorMsg;
+ std::unique_ptr<OSQLParseNode> pStatementNode( m_aSqlParser.parseTree( aErrorMsg, sQuery ) );
+ m_aSqlIterator.setParseTree( pStatementNode.get() );
+ m_aSqlIterator.traverseAll();
+ fillJoinedColumns_throw(m_aSqlIterator.getJoinConditions());
+
+}
+
+void OptimisticSet::makeNewStatement( )
+{
+ OUStringBuffer aFilter = createKeyFilter();
+
+ Reference< XSingleSelectQueryComposer> xSourceComposer(m_xComposer,UNO_QUERY);
+ Reference< XMultiServiceFactory > xFactory(m_xConnection, UNO_QUERY_THROW);
+ Reference<XSingleSelectQueryComposer> xAnalyzer(xFactory->createInstance(SERVICE_NAME_SINGLESELECTQUERYCOMPOSER),UNO_QUERY);
+ xAnalyzer->setElementaryQuery(xSourceComposer->getElementaryQuery());
+
+ const OUString sComposerFilter = m_xComposer->getFilter();
+ if ( !m_sRowSetFilter.isEmpty() || !sComposerFilter.isEmpty() )
+ {
+ FilterCreator aFilterCreator;
+ if ( !sComposerFilter.isEmpty() && sComposerFilter != m_sRowSetFilter )
+ aFilterCreator.append( sComposerFilter );
+ aFilterCreator.append( m_sRowSetFilter );
+ aFilterCreator.append( aFilter.makeStringAndClear() );
+ aFilter = aFilterCreator.getComposedAndClear();
+ }
+ xAnalyzer->setFilter(aFilter.makeStringAndClear());
+ m_xStatement = m_xConnection->prepareStatement(xAnalyzer->getQueryWithSubstitution());
+ ::comphelper::disposeComponent(xAnalyzer);
+}
+
+void OptimisticSet::updateRow(const ORowSetRow& _rInsertRow ,const ORowSetRow& _rOriginalRow,const connectivity::OSQLTable& /*_xTable*/ )
+{
+ if ( m_aJoinedKeyColumns.empty() )
+ throw SQLException();
+ // list all columns that should be set
+ OUString aQuote = getIdentifierQuoteString();
+
+ std::map< OUString,bool > aResultSetChanged;
+ TSQLStatements aKeyConditions;
+ TSQLStatements aSql;
+
+ // here we build the condition part for the update statement
+ for (auto const& columnName : *m_pColumnNames)
+ {
+ aResultSetChanged.try_emplace(columnName.second.sTableName, false);
+ const OUString sQuotedColumnName = ::dbtools::quoteName( aQuote,columnName.second.sRealName);
+ if ( m_pKeyColumnNames->find(columnName.first) != m_pKeyColumnNames->end() )
+ {
+ aResultSetChanged[columnName.second.sTableName] = m_aJoinedKeyColumns.find(columnName.second.nPosition) != m_aJoinedKeyColumns.end();
+ lcl_fillKeyCondition(columnName.second.sTableName,sQuotedColumnName,(*_rOriginalRow)[columnName.second.nPosition],aKeyConditions);
+ }
+ if((*_rInsertRow)[columnName.second.nPosition].isModified())
+ {
+ if ( m_aJoinedKeyColumns.find(columnName.second.nPosition) != m_aJoinedKeyColumns.end() )
+ throw SQLException();
+
+ std::map<sal_Int32,sal_Int32>::const_iterator aJoinIter = m_aJoinedColumns.find(columnName.second.nPosition);
+ if ( aJoinIter != m_aJoinedColumns.end() )
+ {
+ (*_rInsertRow)[aJoinIter->second] = (*_rInsertRow)[columnName.second.nPosition];
+ }
+ OUStringBuffer& rPart = aSql[columnName.second.sTableName];
+ if ( !rPart.isEmpty() )
+ rPart.append(", ");
+ rPart.append(sQuotedColumnName + " = ?");
+ }
+ }
+
+ if( aSql.empty() )
+ ::dbtools::throwSQLException( DBA_RES( RID_STR_NO_VALUE_CHANGED ), StandardSQLState::GENERAL_ERROR, m_xConnection );
+
+ if( aKeyConditions.empty() )
+ ::dbtools::throwSQLException( DBA_RES( RID_STR_NO_CONDITION_FOR_PK ), StandardSQLState::GENERAL_ERROR, m_xConnection );
+
+ Reference<XDatabaseMetaData> xMetaData = m_xConnection->getMetaData();
+
+ for (auto const& elem : aSql)
+ {
+ if ( !elem.second.isEmpty() )
+ {
+ m_bResultSetChanged = m_bResultSetChanged || aResultSetChanged[elem.first];
+ OUString sCatalog,sSchema,sTable;
+ ::dbtools::qualifiedNameComponents(xMetaData,elem.first,sCatalog,sSchema,sTable,::dbtools::EComposeRule::InDataManipulation);
+ OUStringBuffer sSql("UPDATE " + ::dbtools::composeTableNameForSelect( m_xConnection, sCatalog, sSchema, sTable ) +
+ " SET " + elem.second);
+ OUStringBuffer& rCondition = aKeyConditions[elem.first];
+ if ( !rCondition.isEmpty() )
+ sSql.append(" WHERE " + rCondition );
+
+ executeUpdate(_rInsertRow ,_rOriginalRow,sSql.makeStringAndClear(),elem.first);
+ }
+ }
+}
+
+void OptimisticSet::insertRow( const ORowSetRow& _rInsertRow,const connectivity::OSQLTable& /*_xTable*/ )
+{
+ TSQLStatements aSql;
+ TSQLStatements aParameter;
+ TSQLStatements aKeyConditions;
+ std::map< OUString,bool > aResultSetChanged;
+ OUString aQuote = getIdentifierQuoteString();
+
+ // here we build the condition part for the update statement
+ for (auto const& columnName : *m_pColumnNames)
+ {
+ aResultSetChanged.try_emplace(columnName.second.sTableName, false);
+
+ const OUString sQuotedColumnName = ::dbtools::quoteName( aQuote,columnName.second.sRealName);
+ if ( (*_rInsertRow)[columnName.second.nPosition].isModified() )
+ {
+ if ( m_aJoinedKeyColumns.find(columnName.second.nPosition) != m_aJoinedKeyColumns.end() )
+ {
+ lcl_fillKeyCondition(columnName.second.sTableName,sQuotedColumnName,(*_rInsertRow)[columnName.second.nPosition],aKeyConditions);
+ aResultSetChanged[columnName.second.sTableName] = true;
+ }
+ std::map<sal_Int32,sal_Int32>::const_iterator aJoinIter = m_aJoinedColumns.find(columnName.second.nPosition);
+ if ( aJoinIter != m_aJoinedColumns.end() )
+ {
+ (*_rInsertRow)[aJoinIter->second] = (*_rInsertRow)[columnName.second.nPosition];
+ }
+ OUStringBuffer& rPart = aSql[columnName.second.sTableName];
+ if ( !rPart.isEmpty() )
+ rPart.append(", ");
+ rPart.append(sQuotedColumnName);
+ OUStringBuffer& rParam = aParameter[columnName.second.sTableName];
+ if ( !rParam.isEmpty() )
+ rParam.append(", ");
+ rParam.append("?");
+ }
+ }
+ if ( aParameter.empty() )
+ ::dbtools::throwSQLException( DBA_RES( RID_STR_NO_VALUE_CHANGED ), StandardSQLState::GENERAL_ERROR, m_xConnection );
+
+ Reference<XDatabaseMetaData> xMetaData = m_xConnection->getMetaData();
+ for (auto const& elem : aSql)
+ {
+ if ( !elem.second.isEmpty() )
+ {
+ m_bResultSetChanged = m_bResultSetChanged || aResultSetChanged[elem.first];
+ OUString sCatalog,sSchema,sTable;
+ ::dbtools::qualifiedNameComponents(xMetaData,elem.first,sCatalog,sSchema,sTable,::dbtools::EComposeRule::InDataManipulation);
+ OUString sComposedTableName = ::dbtools::composeTableNameForSelect( m_xConnection, sCatalog, sSchema, sTable );
+ OUString sSql("INSERT INTO " + sComposedTableName + " ( " + elem.second +
+ ") VALUES ( " + aParameter[elem.first] + " )");
+
+ OUStringBuffer& rCondition = aKeyConditions[elem.first];
+ if ( !rCondition.isEmpty() )
+ {
+ OUString sQuery("SELECT " + elem.second + " FROM " + sComposedTableName +
+ " WHERE " + rCondition);
+
+ try
+ {
+ Reference< XPreparedStatement > xPrep(m_xConnection->prepareStatement(sQuery));
+ Reference< XParameters > xParameter(xPrep,UNO_QUERY);
+ // and then the values of the where condition
+ sal_Int32 i = 1;
+ for (auto const& keyColumnName : *m_pKeyColumnNames)
+ {
+ if ( keyColumnName.second.sTableName == elem.first )
+ {
+ setParameter(i++,xParameter,(*_rInsertRow)[keyColumnName.second.nPosition],keyColumnName.second.nType,keyColumnName.second.nScale);
+ }
+ }
+ Reference<XResultSet> xRes = xPrep->executeQuery();
+ Reference<XRow> xRow(xRes,UNO_QUERY);
+ if ( xRow.is() && xRes->next() )
+ {
+ m_bResultSetChanged = true;
+ continue;
+ }
+ }
+ catch(const SQLException&)
+ {
+ }
+ }
+
+ executeInsert(_rInsertRow,sSql,elem.first);
+ }
+ }
+}
+
+void OptimisticSet::deleteRow(const ORowSetRow& _rDeleteRow,const connectivity::OSQLTable& /*_xTable*/ )
+{
+ OUString aQuote = getIdentifierQuoteString();
+ TSQLStatements aKeyConditions;
+
+ // here we build the condition part for the update statement
+ for (auto const& columnName : *m_pColumnNames)
+ {
+ if ( m_aJoinedKeyColumns.find(columnName.second.nPosition) == m_aJoinedKeyColumns.end() && m_pKeyColumnNames->find(columnName.first) != m_pKeyColumnNames->end() )
+ {
+ // only delete rows which aren't the key in the join
+ const OUString sQuotedColumnName = ::dbtools::quoteName( aQuote,columnName.second.sRealName);
+ lcl_fillKeyCondition(columnName.second.sTableName,sQuotedColumnName,(*_rDeleteRow)[columnName.second.nPosition],aKeyConditions);
+ }
+ }
+ Reference<XDatabaseMetaData> xMetaData = m_xConnection->getMetaData();
+ for (auto & keyCondition : aKeyConditions)
+ {
+ OUStringBuffer& rCondition = keyCondition.second;
+ if ( !rCondition.isEmpty() )
+ {
+ OUString sCatalog,sSchema,sTable;
+ ::dbtools::qualifiedNameComponents(xMetaData,keyCondition.first,sCatalog,sSchema,sTable,::dbtools::EComposeRule::InDataManipulation);
+ OUString sSql("DELETE FROM " + ::dbtools::composeTableNameForSelect( m_xConnection, sCatalog, sSchema, sTable ) +
+ " WHERE " + rCondition );
+ executeDelete(_rDeleteRow, sSql, keyCondition.first);
+ }
+ }
+}
+
+void OptimisticSet::executeDelete(const ORowSetRow& _rDeleteRow,const OUString& i_sSQL,std::u16string_view i_sTableName)
+{
+ // now create and execute the prepared statement
+ Reference< XPreparedStatement > xPrep(m_xConnection->prepareStatement(i_sSQL));
+ Reference< XParameters > xParameter(xPrep,UNO_QUERY);
+
+ sal_Int32 i = 1;
+ for (auto const& keyColumnName : *m_pKeyColumnNames)
+ {
+ if ( keyColumnName.second.sTableName == i_sTableName )
+ setParameter(i++,xParameter,(*_rDeleteRow)[keyColumnName.second.nPosition],keyColumnName.second.nType,keyColumnName.second.nScale);
+ }
+ m_bDeleted = xPrep->executeUpdate() > 0;
+
+ if(m_bDeleted)
+ {
+ sal_Int32 nBookmark = ::comphelper::getINT32((*_rDeleteRow)[0].getAny());
+ if(m_aKeyIter == m_aKeyMap.find(nBookmark) && m_aKeyIter != m_aKeyMap.end())
+ ++m_aKeyIter;
+ m_aKeyMap.erase(nBookmark);
+ m_bDeleted = true;
+ }
+}
+
+void OptimisticSet::fillJoinedColumns_throw(const std::vector< TNodePair >& i_aJoinColumns)
+{
+ for (auto const& joinColumn : i_aJoinColumns)
+ {
+ OUString sColumnName,sTableName;
+ m_aSqlIterator.getColumnRange(joinColumn.first,sColumnName,sTableName);
+ OUString sLeft(sTableName + "." + sColumnName);
+ m_aSqlIterator.getColumnRange(joinColumn.second,sColumnName,sTableName);
+ OUString sRight(sTableName + "." + sColumnName);
+ fillJoinedColumns_throw(sLeft, sRight);
+ }
+}
+
+void OptimisticSet::fillJoinedColumns_throw(const OUString& i_sLeftColumn,const OUString& i_sRightColumn)
+{
+ sal_Int32 nLeft = 0,nRight = 0;
+ SelectColumnsMetaData::const_iterator aLeftIter = m_pKeyColumnNames->find(i_sLeftColumn);
+ SelectColumnsMetaData::const_iterator aRightIter = m_pKeyColumnNames->find(i_sRightColumn);
+
+ bool bLeftKey = aLeftIter != m_pKeyColumnNames->end();
+ if ( bLeftKey )
+ {
+ nLeft = aLeftIter->second.nPosition;
+ }
+ else
+ {
+ aLeftIter = m_pColumnNames->find(i_sLeftColumn);
+ if ( aLeftIter != m_pColumnNames->end() )
+ nLeft = aLeftIter->second.nPosition;
+ }
+
+ bool bRightKey = aRightIter != m_pKeyColumnNames->end();
+ if ( bRightKey )
+ {
+ nRight = aRightIter->second.nPosition;
+ }
+ else
+ {
+ aRightIter = m_pColumnNames->find(i_sRightColumn);
+ if ( aRightIter != m_pColumnNames->end() )
+ nRight = aRightIter->second.nPosition;
+ }
+
+ if (bLeftKey)
+ m_aJoinedKeyColumns[nLeft] = nRight;
+ else
+ m_aJoinedColumns[nLeft] = nRight;
+ if (bRightKey)
+ m_aJoinedKeyColumns[nRight] = nLeft;
+ else
+ m_aJoinedColumns[nRight] = nLeft;
+}
+
+bool OptimisticSet::isResultSetChanged() const
+{
+ bool bOld = m_bResultSetChanged;
+ m_bResultSetChanged = false;
+ return bOld;
+}
+
+void OptimisticSet::mergeColumnValues(sal_Int32 i_nColumnIndex,ORowSetValueVector::Vector& io_aInsertRow,ORowSetValueVector::Vector& io_aRow,std::vector<sal_Int32>& o_aChangedColumns)
+{
+ o_aChangedColumns.push_back(i_nColumnIndex);
+ std::map<sal_Int32,sal_Int32>::const_iterator aJoinIter = m_aJoinedColumns.find(i_nColumnIndex);
+ if ( aJoinIter != m_aJoinedColumns.end() )
+ {
+ io_aRow[aJoinIter->second] = io_aRow[i_nColumnIndex];
+ io_aInsertRow[aJoinIter->second] = io_aInsertRow[i_nColumnIndex];
+ io_aRow[aJoinIter->second].setModified(true);
+ o_aChangedColumns.push_back(aJoinIter->second);
+ }
+}
+
+bool OptimisticSet::updateColumnValues(const ORowSetValueVector::Vector& io_aCachedRow,ORowSetValueVector::Vector& io_aRow,const std::vector<sal_Int32>& i_aChangedColumns)
+{
+ bool bRet = false;
+ for( const auto& aColIdx : i_aChangedColumns )
+ {
+ SelectColumnsMetaData::const_iterator aFind = std::find_if(
+ m_pKeyColumnNames->begin(),m_pKeyColumnNames->end(),
+ [&aColIdx]( const SelectColumnsMetaData::value_type& aType )
+ { return aType.second.nPosition == aColIdx; } );
+ if ( aFind != m_pKeyColumnNames->end() )
+ {
+ const OUString sTableName = aFind->second.sTableName;
+ aFind = std::find_if( m_pKeyColumnNames->begin(),m_pKeyColumnNames->end(),
+ [&sTableName]
+ ( const SelectColumnsMetaData::value_type& rCurr )
+ { return rCurr.second.sTableName == sTableName; } );
+ while( aFind != m_pKeyColumnNames->end() )
+ {
+ io_aRow[aFind->second.nPosition].setSigned(io_aCachedRow[aFind->second.nPosition].isSigned());
+ if ( io_aCachedRow[aFind->second.nPosition] != io_aRow[aFind->second.nPosition] )
+ break;
+ ++aFind;
+ }
+ if ( aFind == m_pKeyColumnNames->end() )
+ {
+ bRet = true;
+ for( const auto& aCol : *m_pColumnNames )
+ {
+ if ( aCol.second.sTableName == sTableName )
+ {
+ io_aRow[aCol.second.nPosition] = io_aCachedRow[aCol.second.nPosition];
+ io_aRow[aCol.second.nPosition].setModified(true);
+ }
+ }
+ }
+ }
+ }
+ return bRet;
+}
+
+bool OptimisticSet::columnValuesUpdated(ORowSetValueVector::Vector& o_aCachedRow,const ORowSetValueVector::Vector& i_aRow)
+{
+ bool bRet = false;
+ for( const auto& aCol : *m_pColumnNames )
+ {
+ sal_Int32 nPos = aCol.second.nPosition;
+ SelectColumnsMetaData::const_iterator aFind = std::find_if(
+ m_pKeyColumnNames->begin(),m_pKeyColumnNames->end(),
+ [&nPos] ( const SelectColumnsMetaData::value_type& aType )
+ { return aType.second.nPosition == nPos; } );
+ if ( aFind != m_pKeyColumnNames->end() )
+ {
+ const OUString sTableName = aFind->second.sTableName;
+ aFind = std::find_if( m_pKeyColumnNames->begin(),m_pKeyColumnNames->end(),
+ [&sTableName]
+ ( const SelectColumnsMetaData::value_type& rCurr )
+ { return rCurr.second.sTableName == sTableName; } );
+ while( aFind != m_pKeyColumnNames->end() )
+ {
+ o_aCachedRow[aFind->second.nPosition].setSigned(i_aRow[aFind->second.nPosition].isSigned());
+ if ( o_aCachedRow[aFind->second.nPosition] != i_aRow[aFind->second.nPosition] )
+ break;
+ ++aFind;
+ }
+ if ( aFind == m_pKeyColumnNames->end() )
+ {
+ bRet = true;
+ for( const auto& aCol2 : *m_pColumnNames )
+ {
+ if ( aCol2.second.sTableName == sTableName )
+ {
+ o_aCachedRow[aCol2.second.nPosition] = i_aRow[aCol2.second.nPosition];
+ o_aCachedRow[aCol2.second.nPosition].setModified(true);
+ }
+ }
+ fillMissingValues(o_aCachedRow);
+ }
+ }
+ }
+ return bRet;
+}
+
+void OptimisticSet::fillMissingValues(ORowSetValueVector::Vector& io_aRow) const
+{
+ TSQLStatements aSql;
+ TSQLStatements aKeyConditions;
+ OUString aQuote = getIdentifierQuoteString();
+ // here we build the condition part for the update statement
+ for (auto const& columnName : *m_pColumnNames)
+ {
+ const OUString sQuotedColumnName = ::dbtools::quoteName( aQuote,columnName.second.sRealName);
+ if ( m_aJoinedKeyColumns.find(columnName.second.nPosition) != m_aJoinedKeyColumns.end() )
+ {
+ lcl_fillKeyCondition(columnName.second.sTableName,sQuotedColumnName,io_aRow[columnName.second.nPosition],aKeyConditions);
+ }
+ OUStringBuffer& rPart = aSql[columnName.second.sTableName];
+ if ( !rPart.isEmpty() )
+ rPart.append(", ");
+ rPart.append(sQuotedColumnName);
+ }
+ Reference<XDatabaseMetaData> xMetaData = m_xConnection->getMetaData();
+ for (auto const& elem : aSql)
+ {
+ if ( !elem.second.isEmpty() )
+ {
+ OUStringBuffer& rCondition = aKeyConditions[elem.first];
+ if ( !rCondition.isEmpty() )
+ {
+ OUString sCatalog,sSchema,sTable;
+ ::dbtools::qualifiedNameComponents(xMetaData,elem.first,sCatalog,sSchema,sTable,::dbtools::EComposeRule::InDataManipulation);
+ OUString sComposedTableName = ::dbtools::composeTableNameForSelect( m_xConnection, sCatalog, sSchema, sTable );
+ OUString sQuery("SELECT " + elem.second + " FROM " + sComposedTableName + " WHERE " + rCondition);
+ rCondition.setLength(0);
+
+ try
+ {
+ Reference< XPreparedStatement > xPrep(m_xConnection->prepareStatement(sQuery));
+ Reference< XParameters > xParameter(xPrep,UNO_QUERY);
+ // and then the values of the where condition
+ sal_Int32 i = 1;
+ for (auto const& keyColumn : *m_pKeyColumnNames)
+ {
+ if ( keyColumn.second.sTableName == elem.first )
+ {
+ setParameter(i++,xParameter,io_aRow[keyColumn.second.nPosition],keyColumn.second.nType,keyColumn.second.nScale);
+ }
+ }
+ Reference<XResultSet> xRes = xPrep->executeQuery();
+ Reference<XRow> xRow(xRes,UNO_QUERY);
+ if ( xRow.is() && xRes->next() )
+ {
+ i = 1;
+ for (auto const& columnName : *m_pColumnNames)
+ {
+ if ( columnName.second.sTableName == elem.first )
+ {
+ io_aRow[columnName.second.nPosition].fill(i++, columnName.second.nType, xRow);
+ io_aRow[columnName.second.nPosition].setModified(true);
+ }
+ }
+ }
+ }
+ catch(const SQLException&)
+ {
+ }
+ }
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/api/OptimisticSet.hxx b/dbaccess/source/core/api/OptimisticSet.hxx
new file mode 100644
index 000000000..bf5e3a803
--- /dev/null
+++ b/dbaccess/source/core/api/OptimisticSet.hxx
@@ -0,0 +1,76 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include "KeySet.hxx"
+
+#include <connectivity/sqlparse.hxx>
+#include <connectivity/sqliterator.hxx>
+
+#include <com/sun/star/sdb/XSingleSelectQueryAnalyzer.hpp>
+
+namespace dbaccess
+{
+ // is used when the source supports keys
+ class OptimisticSet : public OKeySet
+ {
+ ::connectivity::OSQLParser m_aSqlParser;
+ ::connectivity::OSQLParseTreeIterator m_aSqlIterator;
+
+ std::map<sal_Int32,sal_Int32> m_aJoinedColumns;
+ std::map<sal_Int32,sal_Int32> m_aJoinedKeyColumns;
+
+ mutable bool m_bResultSetChanged;
+
+ void executeDelete(const ORowSetRow& _rDeleteRow,const OUString& i_sSQL,std::u16string_view i_sTableName);
+ void fillJoinedColumns_throw(const std::vector< ::connectivity::TNodePair>& i_aJoinColumns);
+ void fillJoinedColumns_throw(const OUString& i_sLeftColumn,const OUString& i_sRightColumn);
+ protected:
+ virtual void makeNewStatement( ) override;
+ virtual ~OptimisticSet() override;
+ public:
+ OptimisticSet(const css::uno::Reference< css::uno::XComponentContext>& _rContext,
+ const css::uno::Reference< css::sdbc::XConnection>& i_xConnection,
+ const css::uno::Reference< css::sdb::XSingleSelectQueryAnalyzer >& _xComposer,
+ const ORowSetValueVector& _aParameterValueForCache,
+ sal_Int32 i_nMaxRows,
+ sal_Int32& o_nRowCount);
+
+ // late ctor which can throw exceptions
+ virtual void construct(const css::uno::Reference< css::sdbc::XResultSet>& _xDriverSet,const OUString& i_sRowSetFilter) override;
+
+ // css::sdbc::XResultSetUpdate
+ virtual void updateRow(const ORowSetRow& _rInsertRow,const ORowSetRow& _rOriginalRow,const connectivity::OSQLTable& _xTable ) override;
+ virtual void deleteRow(const ORowSetRow& _rInsertRow,const connectivity::OSQLTable& _xTable ) override;
+ virtual void insertRow( const ORowSetRow& _rInsertRow,const connectivity::OSQLTable& _xTable ) override;
+
+ // CacheSet
+ virtual bool isResultSetChanged() const override;
+ virtual void mergeColumnValues(sal_Int32 i_nColumnIndex,ORowSetValueVector::Vector& io_aInsertRow,ORowSetValueVector::Vector& io_aRow,std::vector<sal_Int32>& o_aChangedColumns) override;
+ virtual bool columnValuesUpdated(ORowSetValueVector::Vector& o_aCachedRow,const ORowSetValueVector::Vector& i_aRow) override;
+ virtual bool updateColumnValues(const ORowSetValueVector::Vector& io_aCachedRow,ORowSetValueVector::Vector& io_aRow,const std::vector<sal_Int32>& i_aChangedColumns) override;
+ virtual void fillMissingValues(ORowSetValueVector::Vector& io_aRow) const override;
+
+ bool isReadOnly() const { return m_aJoinedKeyColumns.empty(); }
+ const std::map<sal_Int32,sal_Int32>& getJoinedKeyColumns() const { return m_aJoinedKeyColumns; }
+ };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/api/PrivateRow.cxx b/dbaccess/source/core/api/PrivateRow.cxx
new file mode 100644
index 000000000..9bf270960
--- /dev/null
+++ b/dbaccess/source/core/api/PrivateRow.cxx
@@ -0,0 +1,133 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "PrivateRow.hxx"
+
+using namespace dbaccess;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::sdb;
+using namespace ::com::sun::star::sdbcx;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::util;
+using namespace ::com::sun::star;
+
+sal_Bool SAL_CALL OPrivateRow::wasNull( )
+ {
+ return m_aRow[m_nPos].isNull();
+ }
+ OUString SAL_CALL OPrivateRow::getString( ::sal_Int32 columnIndex )
+ {
+ m_nPos = columnIndex;
+ return m_aRow[m_nPos].getString();
+ }
+ sal_Bool SAL_CALL OPrivateRow::getBoolean( ::sal_Int32 columnIndex )
+ {
+ m_nPos = columnIndex;
+ return m_aRow[m_nPos].getBool();
+ }
+ ::sal_Int8 SAL_CALL OPrivateRow::getByte( ::sal_Int32 columnIndex )
+ {
+ m_nPos = columnIndex;
+ return m_aRow[m_nPos].getInt8();
+ }
+ ::sal_Int16 SAL_CALL OPrivateRow::getShort( ::sal_Int32 columnIndex )
+ {
+ m_nPos = columnIndex;
+ return m_aRow[m_nPos].getInt16();
+ }
+ ::sal_Int32 SAL_CALL OPrivateRow::getInt( ::sal_Int32 columnIndex )
+ {
+ m_nPos = columnIndex;
+ return m_aRow[m_nPos].getInt32();
+ }
+ ::sal_Int64 SAL_CALL OPrivateRow::getLong( ::sal_Int32 columnIndex )
+ {
+ m_nPos = columnIndex;
+ return m_aRow[m_nPos].getLong();
+ }
+ float SAL_CALL OPrivateRow::getFloat( ::sal_Int32 columnIndex )
+ {
+ m_nPos = columnIndex;
+ return m_aRow[m_nPos].getFloat();
+ }
+ double SAL_CALL OPrivateRow::getDouble( ::sal_Int32 columnIndex )
+ {
+ m_nPos = columnIndex;
+ return m_aRow[m_nPos].getDouble();
+ }
+ Sequence< ::sal_Int8 > SAL_CALL OPrivateRow::getBytes( ::sal_Int32 columnIndex )
+ {
+ m_nPos = columnIndex;
+ return m_aRow[m_nPos].getSequence();
+ }
+ css::util::Date SAL_CALL OPrivateRow::getDate( ::sal_Int32 columnIndex )
+ {
+ m_nPos = columnIndex;
+ return m_aRow[m_nPos].getDate();
+ }
+ css::util::Time SAL_CALL OPrivateRow::getTime( ::sal_Int32 columnIndex )
+ {
+ m_nPos = columnIndex;
+ return m_aRow[m_nPos].getTime();
+ }
+ css::util::DateTime SAL_CALL OPrivateRow::getTimestamp( ::sal_Int32 columnIndex )
+ {
+ m_nPos = columnIndex;
+ return m_aRow[m_nPos].getDateTime();
+ }
+ Reference< css::io::XInputStream > SAL_CALL OPrivateRow::getBinaryStream( ::sal_Int32 columnIndex )
+ {
+ m_nPos = columnIndex;
+ return Reference< css::io::XInputStream >(m_aRow[m_nPos].makeAny(),UNO_QUERY);
+ }
+ Reference< css::io::XInputStream > SAL_CALL OPrivateRow::getCharacterStream( ::sal_Int32 columnIndex )
+ {
+ m_nPos = columnIndex;
+ return Reference< css::io::XInputStream >(m_aRow[m_nPos].makeAny(),UNO_QUERY);
+ }
+ Any SAL_CALL OPrivateRow::getObject( ::sal_Int32 columnIndex, const Reference< css::container::XNameAccess >& )
+ {
+ m_nPos = columnIndex;
+ return m_aRow[m_nPos].makeAny();
+ }
+ Reference< XRef > SAL_CALL OPrivateRow::getRef( ::sal_Int32 columnIndex )
+ {
+ m_nPos = columnIndex;
+ return Reference< XRef >(m_aRow[m_nPos].makeAny(),UNO_QUERY);
+ }
+ Reference< XBlob > SAL_CALL OPrivateRow::getBlob( ::sal_Int32 columnIndex )
+ {
+ m_nPos = columnIndex;
+ return Reference< XBlob >(m_aRow[m_nPos].makeAny(),UNO_QUERY);
+ }
+ Reference< XClob > SAL_CALL OPrivateRow::getClob( ::sal_Int32 columnIndex )
+ {
+ m_nPos = columnIndex;
+ return Reference< XClob >(m_aRow[m_nPos].makeAny(),UNO_QUERY);
+ }
+ Reference< XArray > SAL_CALL OPrivateRow::getArray( ::sal_Int32 columnIndex )
+ {
+ m_nPos = columnIndex;
+ return Reference< XArray >(m_aRow[m_nPos].makeAny(),UNO_QUERY);
+ }
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/api/PrivateRow.hxx b/dbaccess/source/core/api/PrivateRow.hxx
new file mode 100644
index 000000000..c5ce74f15
--- /dev/null
+++ b/dbaccess/source/core/api/PrivateRow.hxx
@@ -0,0 +1,58 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <cppuhelper/implbase.hxx>
+#include <com/sun/star/sdbc/XRow.hpp>
+#include "RowSetRow.hxx"
+
+namespace dbaccess
+{
+ class OPrivateRow : public ::cppu::WeakImplHelper< css::sdbc::XRow>
+ {
+ ORowSetValueVector::Vector m_aRow;
+ sal_Int32 m_nPos;
+ public:
+ explicit OPrivateRow(ORowSetValueVector::Vector&& i_aRow) : m_aRow(std::move(i_aRow)),m_nPos(0)
+ {
+ }
+ virtual sal_Bool SAL_CALL wasNull( ) override;
+ virtual OUString SAL_CALL getString( ::sal_Int32 columnIndex ) override;
+ virtual sal_Bool SAL_CALL getBoolean( ::sal_Int32 columnIndex ) override;
+ virtual ::sal_Int8 SAL_CALL getByte( ::sal_Int32 columnIndex ) override;
+ virtual ::sal_Int16 SAL_CALL getShort( ::sal_Int32 columnIndex ) override;
+ virtual ::sal_Int32 SAL_CALL getInt( ::sal_Int32 columnIndex ) override;
+ virtual ::sal_Int64 SAL_CALL getLong( ::sal_Int32 columnIndex ) override;
+ virtual float SAL_CALL getFloat( ::sal_Int32 columnIndex ) override;
+ virtual double SAL_CALL getDouble( ::sal_Int32 columnIndex ) override;
+ virtual css::uno::Sequence< ::sal_Int8 > SAL_CALL getBytes( ::sal_Int32 columnIndex ) override;
+ virtual css::util::Date SAL_CALL getDate( ::sal_Int32 columnIndex ) override;
+ virtual css::util::Time SAL_CALL getTime( ::sal_Int32 columnIndex ) override;
+ virtual css::util::DateTime SAL_CALL getTimestamp( ::sal_Int32 columnIndex ) override;
+ virtual css::uno::Reference< css::io::XInputStream > SAL_CALL getBinaryStream( ::sal_Int32 columnIndex ) override;
+ virtual css::uno::Reference< css::io::XInputStream > SAL_CALL getCharacterStream( ::sal_Int32 columnIndex ) override;
+ virtual css::uno::Any SAL_CALL getObject( ::sal_Int32 columnIndex, const css::uno::Reference< css::container::XNameAccess >& typeMap ) override;
+ virtual css::uno::Reference< css::sdbc::XRef > SAL_CALL getRef( ::sal_Int32 columnIndex ) override;
+ virtual css::uno::Reference< css::sdbc::XBlob > SAL_CALL getBlob( ::sal_Int32 columnIndex ) override;
+ virtual css::uno::Reference< css::sdbc::XClob > SAL_CALL getClob( ::sal_Int32 columnIndex ) override;
+ virtual css::uno::Reference< css::sdbc::XArray > SAL_CALL getArray( ::sal_Int32 columnIndex ) override;
+ };
+} // dbaccess
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/api/RowSet.cxx b/dbaccess/source/core/api/RowSet.cxx
new file mode 100644
index 000000000..28c392995
--- /dev/null
+++ b/dbaccess/source/core/api/RowSet.cxx
@@ -0,0 +1,2965 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+#include <sal/log.hxx>
+
+#include <map>
+#include <utility>
+
+#include "RowSet.hxx"
+#include <stringconstants.hxx>
+#include <sdbcoretools.hxx>
+#include <SingleSelectQueryComposer.hxx>
+#include "CRowSetColumn.hxx"
+#include "CRowSetDataColumn.hxx"
+#include "RowSetCache.hxx"
+#include <strings.hrc>
+#include <strings.hxx>
+#include <core_resource.hxx>
+#include <tablecontainer.hxx>
+
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/lang/DisposedException.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/sdb/CommandType.hpp>
+#include <com/sun/star/sdb/DatabaseContext.hpp>
+#include <com/sun/star/sdb/ErrorCondition.hpp>
+#include <com/sun/star/sdb/RowChangeAction.hpp>
+#include <com/sun/star/sdb/RowSetVetoException.hpp>
+#include <com/sun/star/sdb/XCompletedConnection.hpp>
+#include <com/sun/star/sdb/XParametersSupplier.hpp>
+#include <com/sun/star/sdb/XQueriesSupplier.hpp>
+#include <com/sun/star/sdbc/FetchDirection.hpp>
+#include <com/sun/star/sdbc/ResultSetConcurrency.hpp>
+#include <com/sun/star/sdbc/ResultSetType.hpp>
+#include <com/sun/star/sdbc/XDataSource.hpp>
+#include <com/sun/star/sdbcx/Privilege.hpp>
+#include <com/sun/star/util/XNumberFormatsSupplier.hpp>
+
+#include <comphelper/extract.hxx>
+#include <comphelper/seqstream.hxx>
+#include <comphelper/sequence.hxx>
+#include <comphelper/servicehelper.hxx>
+#include <comphelper/types.hxx>
+#include <comphelper/uno3.hxx>
+#include <connectivity/BlobHelper.hxx>
+#include <connectivity/dbconversion.hxx>
+#include <connectivity/dbexception.hxx>
+#include <connectivity/dbtools.hxx>
+#include <cppuhelper/exc_hlp.hxx>
+#include <cppuhelper/interfacecontainer.h>
+#include <cppuhelper/supportsservice.hxx>
+#include <cppuhelper/typeprovider.hxx>
+#include <i18nlangtag/languagetag.hxx>
+#include <o3tl/safeint.hxx>
+#include <unotools/syslocale.hxx>
+#include <tools/diagnose_ex.h>
+
+using namespace utl;
+using namespace dbaccess;
+using namespace connectivity;
+using namespace comphelper;
+using namespace dbtools;
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::sdb;
+using namespace ::com::sun::star::sdbcx;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::task;
+using namespace ::com::sun::star::util;
+using namespace ::cppu;
+using namespace ::osl;
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+com_sun_star_comp_dba_ORowSet_get_implementation(css::uno::XComponentContext* context,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new ORowSet(context));
+}
+
+namespace dbaccess
+{
+ORowSet::ORowSet( const Reference< css::uno::XComponentContext >& _rxContext )
+ :ORowSet_BASE1(m_aMutex)
+ ,ORowSetBase( _rxContext, ORowSet_BASE1::rBHelper, &m_aMutex )
+ ,m_aPrematureParamValues(new ORowSetValueVector)
+ ,m_aParameterValueForCache(new ORowSetValueVector)
+ ,m_aRowsetListeners(*m_pMutex)
+ ,m_aApproveListeners(*m_pMutex)
+ ,m_aRowsChangeListener(*m_pMutex)
+ ,m_sErrorString(ResourceManager::loadString(RID_STR_COMMAND_LEADING_TO_ERROR))
+ ,m_nFetchDirection(FetchDirection::FORWARD)
+ ,m_nFetchSize(50)
+ ,m_nMaxFieldSize(0)
+ ,m_nMaxRows(0)
+ ,m_nQueryTimeOut(0)
+ ,m_nCommandType(CommandType::COMMAND)
+ ,m_nTransactionIsolation(0)
+ ,m_nPrivileges(0)
+ ,m_nLastKnownRowCount(0)
+ ,m_nInAppend(0)
+ ,m_bInsertingRow(false)
+ ,m_bLastKnownRowCountFinal(false)
+ ,m_bUseEscapeProcessing(true)
+ ,m_bApplyFilter(false)
+ ,m_bCommandFacetsDirty( true )
+ ,m_bParametersDirty( true )
+ ,m_bModified(false)
+ ,m_bRebuildConnOnExecute(false)
+ ,m_bIsBookmarkable(true)
+ ,m_bNew(false)
+ ,m_bCanUpdateInsertedRows(true)
+ ,m_bOwnConnection(false)
+ ,m_bPropChangeNotifyEnabled(true)
+{
+ m_nResultSetType = ResultSetType::SCROLL_SENSITIVE;
+ m_nResultSetConcurrency = ResultSetConcurrency::UPDATABLE;
+ m_pMySelf = this;
+ m_aActiveConnection <<= m_xActiveConnection;
+
+ sal_Int32 const nRBT = PropertyAttribute::READONLY | PropertyAttribute::BOUND | PropertyAttribute::TRANSIENT;
+ sal_Int32 const nRT = PropertyAttribute::READONLY | PropertyAttribute::TRANSIENT;
+ sal_Int32 const nBT = PropertyAttribute::BOUND | PropertyAttribute::TRANSIENT;
+
+ m_aPrematureParamValues->resize( 0 );
+
+ // sdb.RowSet Properties
+ registerMayBeVoidProperty(PROPERTY_ACTIVE_CONNECTION,PROPERTY_ID_ACTIVE_CONNECTION, PropertyAttribute::MAYBEVOID|PropertyAttribute::TRANSIENT|PropertyAttribute::BOUND, &m_aActiveConnection, cppu::UnoType<XConnection>::get());
+ registerProperty(PROPERTY_DATASOURCENAME, PROPERTY_ID_DATASOURCENAME, PropertyAttribute::BOUND, &m_aDataSourceName, ::cppu::UnoType<OUString>::get());
+ registerProperty(PROPERTY_COMMAND, PROPERTY_ID_COMMAND, PropertyAttribute::BOUND, &m_aCommand, ::cppu::UnoType<OUString>::get());
+ registerProperty(PROPERTY_COMMAND_TYPE, PROPERTY_ID_COMMAND_TYPE, PropertyAttribute::BOUND, &m_nCommandType, ::cppu::UnoType<sal_Int32>::get());
+ registerProperty(PROPERTY_ACTIVECOMMAND, PROPERTY_ID_ACTIVECOMMAND, nRBT, &m_aActiveCommand, ::cppu::UnoType<OUString>::get());
+ registerProperty(PROPERTY_IGNORERESULT, PROPERTY_ID_IGNORERESULT, PropertyAttribute::BOUND, &m_bIgnoreResult, cppu::UnoType<bool>::get());
+ registerProperty(PROPERTY_FILTER, PROPERTY_ID_FILTER, PropertyAttribute::BOUND, &m_aFilter, ::cppu::UnoType<OUString>::get());
+ registerProperty(PROPERTY_HAVING_CLAUSE, PROPERTY_ID_HAVING_CLAUSE, PropertyAttribute::BOUND, &m_aHavingClause, ::cppu::UnoType<OUString>::get());
+ registerProperty(PROPERTY_GROUP_BY, PROPERTY_ID_GROUP_BY, PropertyAttribute::BOUND, &m_aGroupBy, ::cppu::UnoType<OUString>::get());
+ registerProperty(PROPERTY_APPLYFILTER, PROPERTY_ID_APPLYFILTER, PropertyAttribute::BOUND, &m_bApplyFilter, cppu::UnoType<bool>::get());
+ registerProperty(PROPERTY_ORDER, PROPERTY_ID_ORDER, PropertyAttribute::BOUND, &m_aOrder, ::cppu::UnoType<OUString>::get());
+ registerProperty(PROPERTY_PRIVILEGES, PROPERTY_ID_PRIVILEGES, nRT, &m_nPrivileges, ::cppu::UnoType<sal_Int32>::get());
+ registerProperty(PROPERTY_ISMODIFIED, PROPERTY_ID_ISMODIFIED, nBT, &m_bModified, cppu::UnoType<bool>::get());
+ registerProperty(PROPERTY_ISNEW, PROPERTY_ID_ISNEW, nRBT, &m_bNew, cppu::UnoType<bool>::get());
+ registerProperty(PROPERTY_SINGLESELECTQUERYCOMPOSER,PROPERTY_ID_SINGLESELECTQUERYCOMPOSER, nRT, &m_xComposer, cppu::UnoType<XSingleSelectQueryComposer>::get());
+
+ // sdbcx.ResultSet Properties
+ registerProperty(PROPERTY_ISBOOKMARKABLE, PROPERTY_ID_ISBOOKMARKABLE, nRT, &m_bIsBookmarkable, cppu::UnoType<bool>::get());
+ registerProperty(PROPERTY_CANUPDATEINSERTEDROWS,PROPERTY_ID_CANUPDATEINSERTEDROWS, nRT, &m_bCanUpdateInsertedRows, cppu::UnoType<bool>::get());
+ // sdbc.ResultSet Properties
+ registerProperty(PROPERTY_RESULTSETCONCURRENCY, PROPERTY_ID_RESULTSETCONCURRENCY, PropertyAttribute::TRANSIENT, &m_nResultSetConcurrency,::cppu::UnoType<sal_Int32>::get());
+ registerProperty(PROPERTY_RESULTSETTYPE, PROPERTY_ID_RESULTSETTYPE, PropertyAttribute::TRANSIENT, &m_nResultSetType, ::cppu::UnoType<sal_Int32>::get());
+ registerProperty(PROPERTY_FETCHDIRECTION, PROPERTY_ID_FETCHDIRECTION, PropertyAttribute::TRANSIENT, &m_nFetchDirection, ::cppu::UnoType<sal_Int32>::get());
+ registerProperty(PROPERTY_FETCHSIZE, PROPERTY_ID_FETCHSIZE, PropertyAttribute::TRANSIENT, &m_nFetchSize, ::cppu::UnoType<sal_Int32>::get());
+
+ // sdbc.RowSet Properties
+ registerProperty(PROPERTY_URL, PROPERTY_ID_URL, 0, &m_aURL, ::cppu::UnoType<OUString>::get());
+ registerProperty(PROPERTY_TRANSACTIONISOLATION, PROPERTY_ID_TRANSACTIONISOLATION, PropertyAttribute::TRANSIENT, &m_nTransactionIsolation,::cppu::UnoType<sal_Int32>::get());
+ registerMayBeVoidProperty(PROPERTY_TYPEMAP, PROPERTY_ID_TYPEMAP, PropertyAttribute::MAYBEVOID|PropertyAttribute::TRANSIENT, &m_aTypeMap, cppu::UnoType<XNameAccess>::get());
+ registerProperty(PROPERTY_ESCAPE_PROCESSING,PROPERTY_ID_ESCAPE_PROCESSING, PropertyAttribute::BOUND, &m_bUseEscapeProcessing,cppu::UnoType<bool>::get() );
+ registerProperty(PROPERTY_QUERYTIMEOUT, PROPERTY_ID_QUERYTIMEOUT, PropertyAttribute::TRANSIENT, &m_nQueryTimeOut, ::cppu::UnoType<sal_Int32>::get());
+ registerProperty(PROPERTY_MAXFIELDSIZE, PROPERTY_ID_MAXFIELDSIZE, PropertyAttribute::TRANSIENT, &m_nMaxFieldSize, ::cppu::UnoType<sal_Int32>::get());
+ registerProperty(PROPERTY_MAXROWS, PROPERTY_ID_MAXROWS, 0, &m_nMaxRows, ::cppu::UnoType<sal_Int32>::get() );
+ registerProperty(PROPERTY_USER, PROPERTY_ID_USER, PropertyAttribute::TRANSIENT, &m_aUser, ::cppu::UnoType<OUString>::get());
+ registerProperty(PROPERTY_PASSWORD, PROPERTY_ID_PASSWORD, PropertyAttribute::TRANSIENT, &m_aPassword, ::cppu::UnoType<OUString>::get());
+
+ registerProperty(PROPERTY_UPDATE_CATALOGNAME, PROPERTY_ID_UPDATE_CATALOGNAME, PropertyAttribute::BOUND, &m_aUpdateCatalogName, ::cppu::UnoType<OUString>::get());
+ registerProperty(PROPERTY_UPDATE_SCHEMANAME, PROPERTY_ID_UPDATE_SCHEMANAME, PropertyAttribute::BOUND, &m_aUpdateSchemaName, ::cppu::UnoType<OUString>::get());
+ registerProperty(PROPERTY_UPDATE_TABLENAME, PROPERTY_ID_UPDATE_TABLENAME, PropertyAttribute::BOUND, &m_aUpdateTableName, ::cppu::UnoType<OUString>::get());
+
+ // ???
+ registerProperty(PROPERTY_CHANGE_NOTIFICATION_ENABLED, PROPERTY_ID_PROPCHANGE_NOTIFY, PropertyAttribute::BOUND, &m_bPropChangeNotifyEnabled, cppu::UnoType<bool>::get());
+}
+
+ORowSet::~ORowSet()
+{
+ if ( !m_rBHelper.bDisposed && !m_rBHelper.bInDispose )
+ {
+ SAL_WARN("dbaccess", "Please check who doesn't dispose this component!");
+ osl_atomic_increment( &m_refCount );
+ dispose();
+ }
+}
+
+void ORowSet::getPropertyDefaultByHandle( sal_Int32 _nHandle, Any& _rDefault ) const
+{
+ switch( _nHandle )
+ {
+ case PROPERTY_ID_COMMAND_TYPE:
+ _rDefault <<= CommandType::COMMAND;
+ break;
+ case PROPERTY_ID_IGNORERESULT:
+ _rDefault <<= false;
+ break;
+ case PROPERTY_ID_APPLYFILTER:
+ _rDefault <<= false;
+ break;
+ case PROPERTY_ID_ISMODIFIED:
+ _rDefault <<= false;
+ break;
+ case PROPERTY_ID_ISBOOKMARKABLE:
+ _rDefault <<= true;
+ break;
+ case PROPERTY_ID_CANUPDATEINSERTEDROWS:
+ _rDefault <<= true;
+ break;
+ case PROPERTY_ID_RESULTSETTYPE:
+ _rDefault <<= ResultSetType::SCROLL_INSENSITIVE;
+ break;
+ case PROPERTY_ID_RESULTSETCONCURRENCY:
+ _rDefault <<= ResultSetConcurrency::UPDATABLE;
+ break;
+ case PROPERTY_ID_FETCHDIRECTION:
+ _rDefault <<= FetchDirection::FORWARD;
+ break;
+ case PROPERTY_ID_FETCHSIZE:
+ _rDefault <<= static_cast<sal_Int32>(1);
+ break;
+ case PROPERTY_ID_ESCAPE_PROCESSING:
+ _rDefault <<= true;
+ break;
+ case PROPERTY_ID_MAXROWS:
+ _rDefault <<= sal_Int32( 0 );
+ break;
+ case PROPERTY_ID_FILTER:
+ case PROPERTY_ID_HAVING_CLAUSE:
+ case PROPERTY_ID_GROUP_BY:
+ case PROPERTY_ID_ORDER:
+ case PROPERTY_ID_UPDATE_CATALOGNAME:
+ case PROPERTY_ID_UPDATE_SCHEMANAME:
+ case PROPERTY_ID_UPDATE_TABLENAME:
+ _rDefault <<= OUString();
+ break;
+ }
+}
+
+void SAL_CALL ORowSet::setFastPropertyValue_NoBroadcast(sal_Int32 nHandle,const Any& rValue)
+{
+ switch(nHandle)
+ {
+ case PROPERTY_ID_ISMODIFIED:
+ m_bModified = cppu::any2bool(rValue);
+ break;
+ case PROPERTY_ID_FETCHDIRECTION:
+ if( m_nResultSetType == ResultSetType::FORWARD_ONLY)
+ throw Exception("resultsettype is FORWARD_ONLY", nullptr);
+ [[fallthrough]];
+ default:
+ OPropertyStateContainer::setFastPropertyValue_NoBroadcast(nHandle,rValue);
+ }
+
+ if ( ( nHandle == PROPERTY_ID_ACTIVE_CONNECTION )
+ || ( nHandle == PROPERTY_ID_DATASOURCENAME )
+ || ( nHandle == PROPERTY_ID_COMMAND )
+ || ( nHandle == PROPERTY_ID_COMMAND_TYPE )
+ || ( nHandle == PROPERTY_ID_IGNORERESULT )
+ || ( nHandle == PROPERTY_ID_FILTER )
+ || ( nHandle == PROPERTY_ID_HAVING_CLAUSE )
+ || ( nHandle == PROPERTY_ID_GROUP_BY )
+ || ( nHandle == PROPERTY_ID_APPLYFILTER )
+ || ( nHandle == PROPERTY_ID_ORDER )
+ || ( nHandle == PROPERTY_ID_URL )
+ || ( nHandle == PROPERTY_ID_USER )
+ )
+ {
+ m_bCommandFacetsDirty = true;
+ }
+
+
+ switch(nHandle)
+ {
+ case PROPERTY_ID_ACTIVE_CONNECTION:
+ // the new connection
+ {
+ assert(m_aActiveConnection == rValue);
+ Reference< XConnection > xNewConnection(m_aActiveConnection,UNO_QUERY);
+ setActiveConnection(xNewConnection, false);
+ }
+
+ m_bOwnConnection = false;
+ m_bRebuildConnOnExecute = false;
+ break;
+
+ case PROPERTY_ID_DATASOURCENAME:
+ if(!m_xStatement.is())
+ {
+ Reference< XConnection > xNewConn;
+ Any aNewConn;
+ aNewConn <<= xNewConn;
+ setFastPropertyValue(PROPERTY_ID_ACTIVE_CONNECTION, aNewConn);
+ }
+ else
+ m_bRebuildConnOnExecute = true;
+ break;
+ case PROPERTY_ID_FETCHSIZE:
+ if(m_pCache)
+ {
+ m_pCache->setFetchSize(m_nFetchSize);
+ fireRowcount();
+ }
+ break;
+ case PROPERTY_ID_URL:
+ // is the connection-to-be-built determined by the url (which is the case if m_aDataSourceName is empty) ?
+ if (m_aDataSourceName.isEmpty())
+ {
+ // are we active at the moment ?
+ if (m_xStatement.is())
+ // yes -> the next execute needs to rebuild our connection because of this new property
+ m_bRebuildConnOnExecute = true;
+ else
+ { // no -> drop our active connection (if we have one) as it doesn't correspond to this new property value anymore
+ Reference< XConnection > xNewConn;
+ Any aNewConn;
+ aNewConn <<= xNewConn;
+ setFastPropertyValue(PROPERTY_ID_ACTIVE_CONNECTION, aNewConn);
+ }
+ }
+ m_bOwnConnection = true;
+ break;
+ case PROPERTY_ID_TYPEMAP:
+ m_xTypeMap.set(m_aTypeMap, css::uno::UNO_QUERY);
+ break;
+ case PROPERTY_ID_PROPCHANGE_NOTIFY:
+ m_bPropChangeNotifyEnabled = ::cppu::any2bool(rValue);
+ break;
+ default:
+ break;
+ }
+}
+
+void SAL_CALL ORowSet::getFastPropertyValue(Any& rValue,sal_Int32 nHandle) const
+{
+ if(m_pCache)
+ {
+ switch(nHandle)
+ {
+ case PROPERTY_ID_ISMODIFIED:
+ rValue <<= m_bModified;
+ break;
+ case PROPERTY_ID_ISNEW:
+ rValue <<= m_bNew;
+ break;
+ case PROPERTY_ID_PRIVILEGES:
+ rValue <<= m_pCache->m_nPrivileges;
+ break;
+ case PROPERTY_ID_ACTIVE_CONNECTION:
+ rValue <<= m_xActiveConnection;
+ break;
+ case PROPERTY_ID_TYPEMAP:
+ rValue <<= m_xTypeMap;
+ break;
+ default:
+ ORowSetBase::getFastPropertyValue(rValue,nHandle);
+ }
+ }
+ else
+ {
+ switch(nHandle)
+ {
+ case PROPERTY_ID_ACTIVE_CONNECTION:
+ rValue <<= m_xActiveConnection;
+ break;
+ case PROPERTY_ID_TYPEMAP:
+ rValue <<= m_xTypeMap;
+ break;
+ case PROPERTY_ID_PROPCHANGE_NOTIFY:
+ rValue <<= m_bPropChangeNotifyEnabled;
+ break;
+ default:
+ ORowSetBase::getFastPropertyValue(rValue,nHandle);
+ }
+ }
+}
+
+// css::XTypeProvider
+Sequence< Type > SAL_CALL ORowSet::getTypes()
+{
+ OTypeCollection aTypes(cppu::UnoType<XPropertySet>::get(),
+ cppu::UnoType<XFastPropertySet>::get(),
+ cppu::UnoType<XMultiPropertySet>::get(),
+ ::comphelper::concatSequences(ORowSet_BASE1::getTypes(),ORowSetBase::getTypes()));
+ return aTypes.getTypes();
+}
+
+Sequence< sal_Int8 > SAL_CALL ORowSet::getImplementationId()
+{
+ return css::uno::Sequence<sal_Int8>();
+}
+
+// css::XInterface
+Any SAL_CALL ORowSet::queryInterface( const Type & rType )
+{
+ return ORowSet_BASE1::queryInterface( rType);
+}
+
+void SAL_CALL ORowSet::acquire() noexcept
+{
+ ORowSet_BASE1::acquire();
+}
+
+void SAL_CALL ORowSet::release() noexcept
+{
+ ORowSet_BASE1::release();
+}
+
+// css::XUnoTunnel
+sal_Int64 SAL_CALL ORowSet::getSomething( const Sequence< sal_Int8 >& rId )
+{
+ return comphelper::getSomethingImpl(rId, this);
+}
+
+const Sequence< sal_Int8 > & ORowSet::getUnoTunnelId()
+{
+ static const comphelper::UnoIdInit s_Id;
+ return s_Id.getSeq();
+}
+
+// css::XAggregation
+Any SAL_CALL ORowSet::queryAggregation( const Type& rType )
+{
+ Any aRet(ORowSetBase::queryInterface(rType));
+ if (!aRet.hasValue())
+ aRet = ORowSet_BASE1::queryAggregation(rType);
+ return aRet;
+}
+
+// css::XServiceInfo
+OUString SAL_CALL ORowSet::getImplementationName()
+{
+ return "com.sun.star.comp.dba.ORowSet";
+}
+
+sal_Bool SAL_CALL ORowSet::supportsService( const OUString& _rServiceName )
+{
+ return cppu::supportsService(this, _rServiceName);
+}
+
+Sequence< OUString > SAL_CALL ORowSet::getSupportedServiceNames()
+{
+ return { SERVICE_SDBC_RESULTSET, SERVICE_SDBC_ROWSET, SERVICE_SDBCX_RESULTSET,
+ SERVICE_SDB_RESULTSET, SERVICE_SDB_ROWSET };
+}
+
+// OComponentHelper
+void SAL_CALL ORowSet::disposing()
+{
+ OPropertyStateContainer::disposing();
+
+ MutexGuard aGuard(m_aMutex);
+ EventObject aDisposeEvent;
+ aDisposeEvent.Source = static_cast< XComponent* >(this);
+ m_aRowsetListeners.disposeAndClear( aDisposeEvent );
+ m_aApproveListeners.disposeAndClear( aDisposeEvent );
+ m_aRowsChangeListener.disposeAndClear( aDisposeEvent );
+
+ freeResources( true );
+
+ // remove myself as dispose listener
+ Reference< XComponent > xComponent(m_xActiveConnection, UNO_QUERY);
+ if (xComponent.is())
+ {
+ Reference<XEventListener> xEvt;
+ query_aggregation(this,xEvt);
+ xComponent->removeEventListener(xEvt);
+ }
+
+ m_aActiveConnection = Any(); // the any contains a reference too
+ if(m_bOwnConnection)
+ ::comphelper::disposeComponent(m_xActiveConnection);
+ m_xActiveConnection = nullptr;
+
+
+ ORowSetBase::disposing();
+}
+
+void ORowSet::freeResources( bool _bComplete )
+{
+ MutexGuard aGuard(m_aMutex);
+
+ // free all clones
+ for (auto const& clone : m_aClones)
+ {
+ Reference< XComponent > xComp(clone.get(), UNO_QUERY);
+ if (xComp.is())
+ xComp->dispose();
+ }
+ m_aClones.clear();
+
+ doCancelModification();
+
+ m_aBookmark = Any();
+ m_bBeforeFirst = true;
+ m_bAfterLast = false;
+ m_bNew = false;
+ m_bModified = false;
+ m_bIsInsertRow = false;
+ m_bLastKnownRowCountFinal = false;
+ m_nLastKnownRowCount = 0;
+
+ if ( !_bComplete )
+ return;
+
+ // the columns must be disposed before the querycomposer is disposed because
+ // their owner can be the composer
+ TDataColumns().swap(m_aDataColumns);// clear and resize capacity
+ std::vector<bool>().swap(m_aReadOnlyDataColumns);
+
+ m_xColumns = nullptr;
+ if ( m_pColumns )
+ m_pColumns->disposing();
+ // dispose the composer to avoid that everybody knows that the querycomposer is eol
+ try { ::comphelper::disposeComponent( m_xComposer ); }
+ catch(Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ m_xComposer = nullptr;
+ }
+
+ // let our warnings container forget the reference to the (possibly disposed) old result set
+ m_aWarnings.setExternalWarnings( nullptr );
+
+ m_pCache.reset();
+
+ impl_resetTables_nothrow();
+
+ m_xStatement = nullptr;
+ m_xTypeMap = nullptr;
+
+ if ( m_aOldRow.is() )
+ m_aOldRow->clearRow();
+
+ impl_disposeParametersContainer_nothrow();
+
+ m_bCommandFacetsDirty = true;
+}
+
+void ORowSet::setActiveConnection( Reference< XConnection > const & _rxNewConn, bool _bFireEvent )
+{
+ if (_rxNewConn.get() == m_xActiveConnection.get())
+ // nothing to do
+ return;
+
+ // remove the event listener for the old connection
+ Reference< XComponent > xComponent(m_xActiveConnection, UNO_QUERY);
+ if (xComponent.is())
+ {
+ Reference<XEventListener> xListener;
+ query_aggregation(this, xListener);
+ xComponent->removeEventListener(xListener);
+ }
+
+ // if we owned the connection, remember it for later disposing
+ if(m_bOwnConnection)
+ m_xOldConnection = m_xActiveConnection;
+
+ // for firing the PropertyChangeEvent
+ sal_Int32 nHandle = PROPERTY_ID_ACTIVE_CONNECTION;
+ Any aOldConnection; aOldConnection <<= m_xActiveConnection;
+ Any aNewConnection; aNewConnection <<= _rxNewConn;
+
+ // set the new connection
+ m_xActiveConnection = _rxNewConn;
+ if (m_xActiveConnection.is())
+ m_aActiveConnection <<= m_xActiveConnection;
+ else
+ m_aActiveConnection.clear();
+
+ // fire the event
+ if (_bFireEvent)
+ fire(&nHandle, &aNewConnection, &aOldConnection, 1, false);
+
+ // register as event listener for the new connection
+ xComponent.set(m_xActiveConnection,UNO_QUERY);
+ if (xComponent.is())
+ {
+ Reference<XEventListener> xListener;
+ query_aggregation(this, xListener);
+ xComponent->addEventListener(xListener);
+ }
+}
+
+// css::XEventListener
+void SAL_CALL ORowSet::disposing( const css::lang::EventObject& Source )
+{
+ // close rowset because the connection is going to be deleted (someone told me :-)
+ Reference<XConnection> xCon(Source.Source,UNO_QUERY);
+ if(m_xActiveConnection == xCon)
+ {
+ close();
+ {
+ MutexGuard aGuard( m_aMutex );
+ Reference< XConnection > xXConnection;
+ setActiveConnection( xXConnection );
+ }
+ }
+}
+
+// XCloseable
+void SAL_CALL ORowSet::close( )
+{
+ {
+ MutexGuard aGuard( m_aMutex );
+ ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper.bDisposed);
+ }
+ // additionals things to set
+ freeResources( true );
+}
+
+// comphelper::OPropertyArrayUsageHelper
+::cppu::IPropertyArrayHelper* ORowSet::createArrayHelper( ) const
+{
+ Sequence< Property > aProps;
+ describeProperties(aProps);
+ return new ::cppu::OPropertyArrayHelper(aProps);
+}
+
+// cppu::OPropertySetHelper
+::cppu::IPropertyArrayHelper& SAL_CALL ORowSet::getInfoHelper()
+{
+ return *::comphelper::OPropertyArrayUsageHelper<ORowSet>::getArrayHelper();
+}
+
+void ORowSet::updateValue(sal_Int32 columnIndex,const ORowSetValue& x)
+{
+ ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper.bDisposed);
+
+ ::osl::MutexGuard aGuard( *m_pMutex );
+ checkUpdateConditions(columnIndex);
+ checkUpdateIterator();
+
+ ORowSetValueVector::Vector& rRow = **m_aCurrentRow;
+ ORowSetNotifier aNotify(this, std::vector(rRow));
+ m_pCache->updateValue(columnIndex,x,rRow,aNotify.getChangedColumns());
+ m_bModified = m_bModified || !aNotify.getChangedColumns().empty();
+ aNotify.firePropertyChange();
+}
+
+// XRowUpdate
+void SAL_CALL ORowSet::updateNull( sal_Int32 columnIndex )
+{
+ ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper.bDisposed);
+
+ ::osl::MutexGuard aGuard( *m_pMutex );
+ checkUpdateConditions(columnIndex);
+ checkUpdateIterator();
+
+ ORowSetValueVector::Vector& rRow = **m_aCurrentRow;
+ ORowSetNotifier aNotify(this, std::vector(rRow));
+ m_pCache->updateNull(columnIndex,rRow,aNotify.getChangedColumns());
+ m_bModified = m_bModified || !aNotify.getChangedColumns().empty();
+ aNotify.firePropertyChange();
+}
+
+void SAL_CALL ORowSet::updateBoolean( sal_Int32 columnIndex, sal_Bool x )
+{
+ updateValue(columnIndex, static_cast<bool>(x));
+}
+
+void SAL_CALL ORowSet::updateByte( sal_Int32 columnIndex, sal_Int8 x )
+{
+ updateValue(columnIndex,x);
+}
+
+void SAL_CALL ORowSet::updateShort( sal_Int32 columnIndex, sal_Int16 x )
+{
+ updateValue(columnIndex,x);
+}
+
+void SAL_CALL ORowSet::updateInt( sal_Int32 columnIndex, sal_Int32 x )
+{
+ updateValue(columnIndex,x);
+}
+
+void SAL_CALL ORowSet::updateLong( sal_Int32 columnIndex, sal_Int64 x )
+{
+ updateValue(columnIndex,x);
+}
+
+void SAL_CALL ORowSet::updateFloat( sal_Int32 columnIndex, float x )
+{
+ updateValue(columnIndex,x);
+}
+
+void SAL_CALL ORowSet::updateDouble( sal_Int32 columnIndex, double x )
+{
+ updateValue(columnIndex,x);
+}
+
+void SAL_CALL ORowSet::updateString( sal_Int32 columnIndex, const OUString& x )
+{
+ updateValue(columnIndex,x);
+}
+
+void SAL_CALL ORowSet::updateBytes( sal_Int32 columnIndex, const Sequence< sal_Int8 >& x )
+{
+ updateValue(columnIndex,x);
+}
+
+void SAL_CALL ORowSet::updateDate( sal_Int32 columnIndex, const css::util::Date& x )
+{
+ updateValue(columnIndex,x);
+}
+
+void SAL_CALL ORowSet::updateTime( sal_Int32 columnIndex, const css::util::Time& x )
+{
+ updateValue(columnIndex,x);
+}
+
+void SAL_CALL ORowSet::updateTimestamp( sal_Int32 columnIndex, const css::util::DateTime& x )
+{
+ updateValue(columnIndex,x);
+}
+
+void SAL_CALL ORowSet::updateBinaryStream( sal_Int32 columnIndex, const Reference< css::io::XInputStream >& x, sal_Int32 length )
+{
+ ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper.bDisposed);
+ ::osl::MutexGuard aGuard( *m_pMutex );
+ checkUpdateConditions(columnIndex);
+ checkUpdateIterator();
+
+ {
+ Sequence<sal_Int8> aSeq;
+ if(x.is())
+ x->readBytes(aSeq,length);
+ updateValue(columnIndex,aSeq);
+ }
+}
+
+void SAL_CALL ORowSet::updateCharacterStream( sal_Int32 columnIndex, const Reference< css::io::XInputStream >& x, sal_Int32 length )
+{
+ ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper.bDisposed);
+ ::osl::MutexGuard aGuard( *m_pMutex );
+ checkUpdateConditions(columnIndex);
+ checkUpdateIterator();
+ ORowSetValueVector::Vector& rRow = **m_aCurrentRow;
+ ORowSetNotifier aNotify(this, std::vector(rRow));
+ m_pCache->updateCharacterStream(columnIndex,x,length,rRow,aNotify.getChangedColumns());
+ m_bModified = m_bModified || !aNotify.getChangedColumns().empty();
+ aNotify.firePropertyChange();
+}
+
+void SAL_CALL ORowSet::updateObject( sal_Int32 columnIndex, const Any& x )
+{
+ ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper.bDisposed);
+ ::osl::MutexGuard aGuard( *m_pMutex );
+ checkUpdateConditions(columnIndex);
+ checkUpdateIterator();
+
+ Any aNewValue = x;
+
+ if ( m_pColumns )
+ {
+ Reference<XPropertySet> xColumn(m_pColumns->getByIndex(columnIndex-1),UNO_QUERY);
+ sal_Int32 nColType = 0;
+ xColumn->getPropertyValue(PROPERTY_TYPE) >>= nColType;
+ switch( nColType )
+ {
+ case DataType::DATE:
+ case DataType::TIME:
+ case DataType::TIMESTAMP:
+ {
+ double nValue = 0;
+ if ( x >>= nValue )
+ {
+ if ( DataType::TIMESTAMP == nColType )
+ aNewValue <<= dbtools::DBTypeConversion::toDateTime( nValue );
+ else if ( DataType::DATE == nColType )
+ aNewValue <<= dbtools::DBTypeConversion::toDate( nValue );
+ else
+ aNewValue <<= dbtools::DBTypeConversion::toTime( nValue );
+ }
+ break;
+ }
+ }
+ }
+
+ if (!::dbtools::implUpdateObject(this, columnIndex, aNewValue))
+ { // there is no other updateXXX call which can handle the value in x
+ ORowSetValueVector::Vector& rRow = **m_aCurrentRow;
+ ORowSetNotifier aNotify(this, std::vector(rRow));
+ m_pCache->updateObject(columnIndex,aNewValue,rRow,aNotify.getChangedColumns());
+ m_bModified = m_bModified || !aNotify.getChangedColumns().empty();
+ aNotify.firePropertyChange();
+ }
+}
+
+void SAL_CALL ORowSet::updateNumericObject( sal_Int32 columnIndex, const Any& x, sal_Int32 /*scale*/ )
+{
+ ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper.bDisposed);
+ ::osl::MutexGuard aGuard( *m_pMutex );
+ checkUpdateConditions(columnIndex);
+ checkUpdateIterator();
+ ORowSetValueVector::Vector& rRow = **m_aCurrentRow;
+ ORowSetNotifier aNotify(this, std::vector(rRow));
+ m_pCache->updateNumericObject(columnIndex,x,rRow,aNotify.getChangedColumns());
+ m_bModified = m_bModified || !aNotify.getChangedColumns().empty();
+ aNotify.firePropertyChange();
+}
+
+namespace
+{
+ class ProtectFlag
+ {
+ bool& m_rInsertingRow;
+ public:
+ explicit ProtectFlag(bool& rInsertingRow)
+ : m_rInsertingRow(rInsertingRow)
+ {
+ if (m_rInsertingRow)
+ {
+ throw std::runtime_error("recursion in insertRow");
+ }
+ m_rInsertingRow = true;
+ }
+ ~ProtectFlag()
+ {
+ m_rInsertingRow = false;
+ }
+ };
+}
+
+// XResultSetUpdate
+void SAL_CALL ORowSet::insertRow()
+{
+ ProtectFlag aFlagControl(m_bInsertingRow);
+
+ ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper.bDisposed);
+ // insertRow is not allowed when
+ // standing not on the insert row nor
+ // when the row isn't modified
+ // or the concurrency is read only
+ ::osl::ResettableMutexGuard aGuard( *m_pMutex );
+
+ if(!m_pCache || !m_bNew || !m_bModified || m_nResultSetConcurrency == ResultSetConcurrency::READ_ONLY)
+ throwFunctionSequenceException(*this);
+
+ // remember old value for fire
+ bool bOld = m_bNew;
+
+ ORowSetRow aOldValues;
+ if ( !m_aCurrentRow.isNull() )
+ aOldValues = new ORowSetValueVector( *(*m_aCurrentRow));
+ Sequence<Any> aChangedBookmarks;
+ RowsChangeEvent aEvt(*this,RowChangeAction::INSERT,1,aChangedBookmarks);
+ notifyAllListenersRowBeforeChange(aGuard,aEvt);
+
+ std::vector< Any > aBookmarks;
+ bool bInserted = m_pCache->insertRow(aBookmarks);
+
+ // make sure that our row is set to the new inserted row before clearing the insert flags in the cache
+ m_pCache->resetInsertRow(bInserted);
+
+ // notification order
+ // - column values
+ setCurrentRow( false, true, aOldValues, aGuard ); // we don't move here
+
+ // read-only flag restored
+ impl_restoreDataColumnsWriteable_throw();
+
+ // - rowChanged
+ notifyAllListenersRowChanged(aGuard,aEvt);
+
+ if ( !aBookmarks.empty() )
+ {
+ RowsChangeEvent aUpEvt(*this,RowChangeAction::UPDATE,aBookmarks.size(),comphelper::containerToSequence(aBookmarks));
+ notifyAllListenersRowChanged(aGuard,aUpEvt);
+ }
+
+ // - IsModified
+ if(!m_bModified)
+ fireProperty(PROPERTY_ID_ISMODIFIED,false,true);
+ OSL_ENSURE( !m_bModified, "ORowSet::insertRow: just updated, but _still_ modified?" );
+
+ // - IsNew
+ if(m_bNew != bOld)
+ fireProperty(PROPERTY_ID_ISNEW,m_bNew,bOld);
+
+ // - RowCount/IsRowCountFinal
+ fireRowcount();
+}
+
+void SAL_CALL ORowSet::updateRow( )
+{
+ ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper.bDisposed);
+ // not allowed when standing on insert row
+ ::osl::ResettableMutexGuard aGuard( *m_pMutex );
+ if ( !m_pCache || m_nResultSetConcurrency == ResultSetConcurrency::READ_ONLY || m_bNew || ((m_pCache->m_nPrivileges & Privilege::UPDATE ) != Privilege::UPDATE) )
+ throwFunctionSequenceException(*this);
+
+
+ if(!m_bModified)
+ return;
+
+ ORowSetRow aOldValues;
+ if ( !m_aCurrentRow.isNull() )
+ aOldValues = new ORowSetValueVector( *(*m_aCurrentRow) );
+
+ Sequence<Any> aChangedBookmarks;
+ RowsChangeEvent aEvt(*this,RowChangeAction::UPDATE,1,aChangedBookmarks);
+ notifyAllListenersRowBeforeChange(aGuard,aEvt);
+
+ std::vector< Any > aBookmarks;
+ m_pCache->updateRow(m_aCurrentRow.operator ->(),aBookmarks);
+ if ( !aBookmarks.empty() )
+ aEvt.Bookmarks = comphelper::containerToSequence(aBookmarks);
+ aEvt.Rows += aBookmarks.size();
+ m_aBookmark = m_pCache->getBookmark();
+ m_aCurrentRow = m_pCache->m_aMatrixIter;
+ m_bIsInsertRow = false;
+ if ( m_pCache->m_aMatrixIter != m_pCache->getEnd() && (*m_pCache->m_aMatrixIter).is() )
+ {
+ if ( m_pCache->isResultSetChanged() )
+ {
+ impl_rebuild_throw(aGuard);
+ }
+ else
+ {
+ m_aOldRow->setRow(new ORowSetValueVector(*(*m_aCurrentRow)));
+
+ // notification order
+ // - column values
+ ORowSetBase::firePropertyChange(aOldValues);
+ }
+ // - rowChanged
+ notifyAllListenersRowChanged(aGuard,aEvt);
+
+ // - IsModified
+ if(!m_bModified)
+ fireProperty(PROPERTY_ID_ISMODIFIED,false,true);
+ OSL_ENSURE( !m_bModified, "ORowSet::updateRow: just updated, but _still_ modified?" );
+
+ // - RowCount/IsRowCountFinal
+ fireRowcount();
+ }
+ else if ( !m_bAfterLast ) // the update went wrong
+ {
+ ::dbtools::throwSQLException( DBA_RES( RID_STR_UPDATE_FAILED ), StandardSQLState::INVALID_CURSOR_POSITION, *this );
+ }
+}
+
+void SAL_CALL ORowSet::deleteRow( )
+{
+ ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper.bDisposed);
+
+ ::osl::ResettableMutexGuard aGuard( *m_pMutex );
+ checkCache();
+
+ if ( m_bBeforeFirst || m_bAfterLast )
+ ::dbtools::throwSQLException( DBA_RES( RID_STR_NO_DELETE_BEFORE_AFTER ), StandardSQLState::INVALID_CURSOR_POSITION, *this );
+ if ( m_bNew )
+ ::dbtools::throwSQLException( DBA_RES( RID_STR_NO_DELETE_INSERT_ROW ), StandardSQLState::INVALID_CURSOR_POSITION, *this );
+ if ( m_nResultSetConcurrency == ResultSetConcurrency::READ_ONLY )
+ ::dbtools::throwSQLException( DBA_RES( RID_STR_RESULT_IS_READONLY ), StandardSQLState::FUNCTION_SEQUENCE_ERROR, *this );
+ if ( ( m_pCache->m_nPrivileges & Privilege::DELETE ) != Privilege::DELETE )
+ ::dbtools::throwSQLException( DBA_RES( RID_STR_NO_DELETE_PRIVILEGE ), StandardSQLState::FUNCTION_SEQUENCE_ERROR, *this );
+ if ( rowDeleted() )
+ ::dbtools::throwSQLException( DBA_RES( RID_STR_ROW_ALREADY_DELETED ), StandardSQLState::FUNCTION_SEQUENCE_ERROR, *this );
+
+ // this call position the cache indirect
+ Any aBookmarkToDelete( m_aBookmark );
+ positionCache( MOVE_NONE );
+ sal_Int32 nDeletePosition = m_pCache->getRow();
+
+ notifyRowSetAndClonesRowDelete( aBookmarkToDelete );
+
+ ORowSetRow aOldValues;
+ if ( m_pCache->m_aMatrixIter != m_pCache->getEnd() && m_pCache->m_aMatrixIter->is() )
+ aOldValues = new ORowSetValueVector( *(*(m_pCache->m_aMatrixIter)) );
+
+ Sequence<Any> aChangedBookmarks;
+ RowsChangeEvent aEvt(*this,RowChangeAction::DELETE,1,aChangedBookmarks);
+ notifyAllListenersRowBeforeChange(aGuard,aEvt);
+
+ m_pCache->deleteRow();
+ notifyRowSetAndClonesRowDeleted( aBookmarkToDelete, nDeletePosition );
+
+ ORowSetNotifier aNotifier( this );
+ // this will call cancelRowModification on the cache if necessary
+
+ // notification order
+ // - rowChanged
+ notifyAllListenersRowChanged(aGuard,aEvt);
+
+ // - IsModified
+ // - IsNew
+ aNotifier.fire( );
+
+ // - RowCount/IsRowCountFinal
+ fireRowcount();
+}
+
+void ORowSet::implCancelRowUpdates( bool _bNotifyModified )
+{
+ ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper.bDisposed);
+
+ ::osl::MutexGuard aGuard( *m_pMutex );
+ if ( m_bBeforeFirst || m_bAfterLast || rowDeleted() )
+ return; // nothing to do so return
+
+ checkCache();
+ // cancelRowUpdates is not allowed when:
+ // - standing on the insert row
+ // - the concurrency is read only
+ // - the current row is deleted
+ if ( m_bNew || m_nResultSetConcurrency == ResultSetConcurrency::READ_ONLY )
+ throwFunctionSequenceException(*this);
+
+ positionCache( MOVE_NONE );
+
+ ORowSetRow aOldValues;
+ if ( !m_bModified && _bNotifyModified && !m_aCurrentRow.isNull() )
+ aOldValues = new ORowSetValueVector( *(*m_aCurrentRow) );
+
+ m_pCache->cancelRowUpdates();
+
+ m_aBookmark = m_pCache->getBookmark();
+ m_aCurrentRow = m_pCache->m_aMatrixIter;
+ m_bIsInsertRow = false;
+
+ // notification order
+ // IsModified
+ if( !m_bModified && _bNotifyModified )
+ {
+ // - column values
+ ORowSetBase::firePropertyChange(aOldValues);
+ fireProperty(PROPERTY_ID_ISMODIFIED,false,true);
+ }
+}
+
+void SAL_CALL ORowSet::cancelRowUpdates( )
+{
+ implCancelRowUpdates( true );
+}
+
+void SAL_CALL ORowSet::addRowSetListener( const Reference< XRowSetListener >& listener )
+{
+ ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper.bDisposed);
+
+ ::osl::MutexGuard aGuard( m_aColumnsMutex );
+ if(listener.is())
+ m_aRowsetListeners.addInterface(listener);
+}
+
+void SAL_CALL ORowSet::removeRowSetListener( const Reference< XRowSetListener >& listener )
+{
+ ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper.bDisposed);
+
+ ::osl::MutexGuard aGuard( m_aColumnsMutex );
+ if(listener.is())
+ m_aRowsetListeners.removeInterface(listener);
+}
+
+void ORowSet::notifyAllListeners(::osl::ResettableMutexGuard& _rGuard)
+{
+ EventObject aEvt(*m_pMySelf);
+ _rGuard.clear();
+ m_aRowsetListeners.notifyEach( &XRowSetListener::rowSetChanged, aEvt );
+ _rGuard.reset();
+}
+
+void ORowSet::notifyAllListenersCursorMoved(::osl::ResettableMutexGuard& _rGuard)
+{
+ EventObject aEvt(*m_pMySelf);
+ _rGuard.clear();
+ m_aRowsetListeners.notifyEach( &XRowSetListener::cursorMoved, aEvt );
+ _rGuard.reset();
+}
+
+void ORowSet::notifyAllListenersRowChanged(::osl::ResettableMutexGuard& _rGuard, const RowsChangeEvent& aEvt)
+{
+ _rGuard.clear();
+ m_aRowsetListeners.notifyEach( &XRowSetListener::rowChanged, static_cast<EventObject>(aEvt) );
+ m_aRowsChangeListener.notifyEach( &XRowsChangeListener::rowsChanged, aEvt );
+ _rGuard.reset();
+}
+
+bool ORowSet::notifyAllListenersCursorBeforeMove(::osl::ResettableMutexGuard& _rGuard)
+{
+ EventObject aEvt(*m_pMySelf);
+ std::vector< Reference< css::sdb::XRowSetApproveListener > > aListenerSeq = m_aApproveListeners.getElements();
+ _rGuard.clear();
+ bool bCheck = std::all_of(aListenerSeq.rbegin(), aListenerSeq.rend(),
+ [&aEvt](Reference<css::sdb::XRowSetApproveListener>& rxItem) {
+ try
+ {
+ return static_cast<bool>(rxItem->approveCursorMove(aEvt));
+ }
+ catch( RuntimeException& )
+ {
+ return true;
+ }
+ });
+ _rGuard.reset();
+ return bCheck;
+}
+
+void ORowSet::notifyAllListenersRowBeforeChange(::osl::ResettableMutexGuard& _rGuard,const RowChangeEvent &aEvt)
+{
+ std::vector< Reference< css::sdb::XRowSetApproveListener > > aListenerSeq = m_aApproveListeners.getElements();
+ _rGuard.clear();
+ bool bCheck = std::all_of(aListenerSeq.rbegin(), aListenerSeq.rend(),
+ [&aEvt](Reference<css::sdb::XRowSetApproveListener>& rxItem) {
+ try
+ {
+ return static_cast<bool>(rxItem->approveRowChange(aEvt));
+ }
+ catch( RuntimeException& )
+ {
+ return true;
+ }
+ });
+ _rGuard.reset();
+
+ if ( !bCheck )
+ m_aErrors.raiseTypedException( sdb::ErrorCondition::ROW_SET_OPERATION_VETOED, *this, ::cppu::UnoType< RowSetVetoException >::get() );
+}
+
+void ORowSet::fireRowcount()
+{
+ sal_Int32 nCurrentRowCount( impl_getRowCount() );
+ bool bCurrentRowCountFinal( m_pCache->m_bRowCountFinal );
+
+ if ( m_nLastKnownRowCount != nCurrentRowCount )
+ {
+ sal_Int32 nHandle = PROPERTY_ID_ROWCOUNT;
+ Any aNew,aOld;
+ aNew <<= nCurrentRowCount; aOld <<= m_nLastKnownRowCount;
+ fire(&nHandle,&aNew,&aOld,1,false);
+ m_nLastKnownRowCount = nCurrentRowCount;
+ }
+ if ( !m_bLastKnownRowCountFinal && ( m_bLastKnownRowCountFinal != bCurrentRowCountFinal ) )
+ {
+ sal_Int32 nHandle = PROPERTY_ID_ISROWCOUNTFINAL;
+ Any aNew,aOld;
+ aNew <<= bCurrentRowCountFinal;
+ aOld <<= m_bLastKnownRowCountFinal;
+ fire(&nHandle,&aNew,&aOld,1,false);
+ m_bLastKnownRowCountFinal = bCurrentRowCountFinal;
+ }
+}
+
+void SAL_CALL ORowSet::moveToInsertRow( )
+{
+ ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper.bDisposed);
+
+ ::osl::ResettableMutexGuard aGuard( *m_pMutex );
+ checkPositioningAllowed();
+ if ( ( m_pCache->m_nPrivileges & Privilege::INSERT ) != Privilege::INSERT )
+ ::dbtools::throwSQLException( DBA_RES( RID_STR_NO_INSERT_PRIVILEGE ), StandardSQLState::GENERAL_ERROR, *this );
+
+ if ( !notifyAllListenersCursorBeforeMove( aGuard ) )
+ return;
+
+ // remember old value for fire
+ ORowSetRow aOldValues;
+ if ( rowDeleted() )
+ {
+ positionCache( MOVE_FORWARD );
+ m_pCache->next();
+ setCurrentRow( true, false, aOldValues, aGuard);
+ }
+ else
+ positionCache( MOVE_NONE );
+
+ // check before because the resultset could be empty
+ if ( !m_bBeforeFirst
+ && !m_bAfterLast
+ && m_pCache->m_aMatrixIter != m_pCache->getEnd()
+ && m_pCache->m_aMatrixIter->is()
+ )
+ aOldValues = new ORowSetValueVector( *(*(m_pCache->m_aMatrixIter)) );
+
+ const bool bNewState = m_bNew;
+ const bool bModState = m_bModified;
+
+ m_pCache->moveToInsertRow();
+ m_aCurrentRow = m_pCache->m_aInsertRow;
+ m_bIsInsertRow = true;
+
+ // set read-only flag to false
+ impl_setDataColumnsWriteable_throw();
+
+ // notification order
+ // - column values
+ ORowSetBase::firePropertyChange(aOldValues);
+
+ // - cursorMoved
+ notifyAllListenersCursorMoved(aGuard);
+
+ // - IsModified
+ if ( bModState != m_bModified )
+ fireProperty( PROPERTY_ID_ISMODIFIED, m_bModified, bModState );
+
+ // - IsNew
+ if ( bNewState != m_bNew )
+ fireProperty( PROPERTY_ID_ISNEW, m_bNew, bNewState );
+
+ // - RowCount/IsRowCountFinal
+ fireRowcount();
+}
+
+void ORowSet::impl_setDataColumnsWriteable_throw()
+{
+ impl_restoreDataColumnsWriteable_throw();
+ m_aReadOnlyDataColumns.resize(m_aDataColumns.size(),false);
+ std::vector<bool, std::allocator<bool> >::iterator aReadIter = m_aReadOnlyDataColumns.begin();
+ for (auto const& dataColumn : m_aDataColumns)
+ {
+ bool bReadOnly = false;
+ dataColumn->getPropertyValue(PROPERTY_ISREADONLY) >>= bReadOnly;
+ *aReadIter = bReadOnly;
+
+ dataColumn->setPropertyValue(PROPERTY_ISREADONLY,Any(false));
+ ++aReadIter;
+ }
+}
+
+void ORowSet::impl_restoreDataColumnsWriteable_throw()
+{
+ assert(m_aDataColumns.size() == m_aReadOnlyDataColumns.size() || m_aReadOnlyDataColumns.size() == 0 );
+ TDataColumns::const_iterator aIter = m_aDataColumns.begin();
+ for (bool readOnlyDataColumn : m_aReadOnlyDataColumns)
+ {
+ (*aIter)->setPropertyValue(PROPERTY_ISREADONLY, Any(readOnlyDataColumn) );
+ ++aIter;
+ }
+ m_aReadOnlyDataColumns.clear();
+}
+
+void SAL_CALL ORowSet::moveToCurrentRow( )
+{
+ ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper.bDisposed);
+
+ ::osl::ResettableMutexGuard aGuard( *m_pMutex );
+ checkPositioningAllowed();
+
+ if ( !m_pCache->m_bNew && !m_bModified )
+ // nothing to do if we're not on the insertion row, and not modified otherwise
+ return;
+
+ if ( rowDeleted() )
+ // this would perhaps even justify a RuntimeException...
+ // if the current row is deleted, then no write access to this row should be possible. So,
+ // m_bModified should be true. Also, as soon as somebody calls moveToInsertRow,
+ // our current row should not be deleted anymore. So, we should not have survived the above
+ // check "if ( !m_pCache->m_bNew && !m_bModified )"
+ ::dbtools::throwSQLException( DBA_RES( RID_STR_ROW_ALREADY_DELETED ), StandardSQLState::FUNCTION_SEQUENCE_ERROR, *this );
+
+ if ( !notifyAllListenersCursorBeforeMove( aGuard ) )
+ return;
+
+ positionCache( MOVE_NONE_REFRESH );
+
+ ORowSetNotifier aNotifier( this );
+
+ // notification order
+ // - cursorMoved
+ notifyAllListenersCursorMoved(aGuard);
+
+ // - IsModified
+ // - IsNew
+ aNotifier.fire();
+}
+
+// XRow
+sal_Bool SAL_CALL ORowSet::wasNull( )
+{
+ ::osl::MutexGuard aGuard( *m_pMutex );
+ checkCache();
+
+ return ( m_pCache && isInsertRow() ) ? (**m_pCache->m_aInsertRow)[m_nLastColumnIndex].isNull() : ORowSetBase::wasNull();
+}
+
+const ORowSetValue& ORowSet::getInsertValue(sal_Int32 columnIndex)
+{
+ checkCache();
+
+ if ( m_pCache && isInsertRow() )
+ {
+ m_nLastColumnIndex = columnIndex;
+ return (**m_pCache->m_aInsertRow)[m_nLastColumnIndex];
+ }
+ return getValue(columnIndex);
+}
+
+OUString SAL_CALL ORowSet::getString( sal_Int32 columnIndex )
+{
+ ::osl::MutexGuard aGuard( *m_pMutex );
+ return getInsertValue(columnIndex).getString();
+}
+
+sal_Bool SAL_CALL ORowSet::getBoolean( sal_Int32 columnIndex )
+{
+ ::osl::MutexGuard aGuard( *m_pMutex );
+ return getInsertValue(columnIndex).getBool();
+}
+
+sal_Int8 SAL_CALL ORowSet::getByte( sal_Int32 columnIndex )
+{
+ ::osl::MutexGuard aGuard( *m_pMutex );
+ return getInsertValue(columnIndex).getInt8();
+}
+
+sal_Int16 SAL_CALL ORowSet::getShort( sal_Int32 columnIndex )
+{
+ ::osl::MutexGuard aGuard( *m_pMutex );
+ return getInsertValue(columnIndex).getInt16();
+}
+
+sal_Int32 SAL_CALL ORowSet::getInt( sal_Int32 columnIndex )
+{
+ ::osl::MutexGuard aGuard( *m_pMutex );
+ return getInsertValue(columnIndex).getInt32();
+}
+
+sal_Int64 SAL_CALL ORowSet::getLong( sal_Int32 columnIndex )
+{
+ ::osl::MutexGuard aGuard( *m_pMutex );
+ return getInsertValue(columnIndex).getLong();
+}
+
+float SAL_CALL ORowSet::getFloat( sal_Int32 columnIndex )
+{
+ ::osl::MutexGuard aGuard( *m_pMutex );
+ return getInsertValue(columnIndex).getFloat();
+}
+
+double SAL_CALL ORowSet::getDouble( sal_Int32 columnIndex )
+{
+ ::osl::MutexGuard aGuard( *m_pMutex );
+ return getInsertValue(columnIndex).getDouble();
+}
+
+Sequence< sal_Int8 > SAL_CALL ORowSet::getBytes( sal_Int32 columnIndex )
+{
+ ::osl::MutexGuard aGuard( *m_pMutex );
+ return getInsertValue(columnIndex).getSequence();
+}
+
+css::util::Date SAL_CALL ORowSet::getDate( sal_Int32 columnIndex )
+{
+ ::osl::MutexGuard aGuard( *m_pMutex );
+ return getInsertValue(columnIndex).getDate();
+}
+
+css::util::Time SAL_CALL ORowSet::getTime( sal_Int32 columnIndex )
+{
+ ::osl::MutexGuard aGuard( *m_pMutex );
+ return getInsertValue(columnIndex).getTime();
+}
+
+css::util::DateTime SAL_CALL ORowSet::getTimestamp( sal_Int32 columnIndex )
+{
+ ::osl::MutexGuard aGuard( *m_pMutex );
+ return getInsertValue(columnIndex).getDateTime();
+}
+
+Reference< css::io::XInputStream > SAL_CALL ORowSet::getBinaryStream( sal_Int32 columnIndex )
+{
+ ::osl::MutexGuard aGuard( *m_pMutex );
+ if ( m_pCache && isInsertRow() )
+ {
+ checkCache();
+ m_nLastColumnIndex = columnIndex;
+ return new ::comphelper::SequenceInputStream((**m_pCache->m_aInsertRow)[m_nLastColumnIndex].getSequence());
+ }
+
+ return ORowSetBase::getBinaryStream(columnIndex);
+}
+
+Reference< css::io::XInputStream > SAL_CALL ORowSet::getCharacterStream( sal_Int32 columnIndex )
+{
+ ::osl::MutexGuard aGuard( *m_pMutex );
+ if(m_pCache && isInsertRow() )
+ {
+ checkCache();
+ m_nLastColumnIndex = columnIndex;
+ return new ::comphelper::SequenceInputStream((**m_pCache->m_aInsertRow)[m_nLastColumnIndex].getSequence());
+ }
+
+ return ORowSetBase::getCharacterStream(columnIndex);
+}
+
+Any SAL_CALL ORowSet::getObject( sal_Int32 columnIndex, const Reference< XNameAccess >& /*typeMap*/ )
+{
+ ::osl::MutexGuard aGuard( *m_pMutex );
+ return getInsertValue(columnIndex).makeAny();
+}
+
+Reference< XRef > SAL_CALL ORowSet::getRef( sal_Int32 /*columnIndex*/ )
+{
+ return Reference< XRef >();
+}
+
+Reference< XBlob > SAL_CALL ORowSet::getBlob( sal_Int32 columnIndex )
+{
+ if ( m_pCache && isInsertRow() )
+ {
+ checkCache();
+ m_nLastColumnIndex = columnIndex;
+ return new ::connectivity::BlobHelper((**m_pCache->m_aInsertRow)[m_nLastColumnIndex].getSequence());
+ }
+ return ORowSetBase::getBlob(columnIndex);
+}
+
+Reference< XClob > SAL_CALL ORowSet::getClob( sal_Int32 columnIndex )
+{
+ return Reference< XClob >(getInsertValue(columnIndex).makeAny(),UNO_QUERY);
+}
+
+Reference< XArray > SAL_CALL ORowSet::getArray( sal_Int32 /*columnIndex*/ )
+{
+ return Reference< XArray >();
+}
+
+void SAL_CALL ORowSet::executeWithCompletion( const Reference< XInteractionHandler >& _rxHandler )
+{
+ if (!_rxHandler.is())
+ execute();
+
+ ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper.bDisposed);
+
+ // tell everybody that we will change the result set
+ approveExecution();
+
+ ResettableMutexGuard aGuard( m_aMutex );
+
+ try
+ {
+ freeResources( m_bCommandFacetsDirty );
+
+ // calc the connection to be used
+ if (m_xActiveConnection.is() && m_bRebuildConnOnExecute)
+ {
+ // there was a setProperty(ActiveConnection), but a setProperty(DataSource) _after_ that, too
+ Reference< XConnection > xXConnection;
+ setActiveConnection( xXConnection );
+ }
+ calcConnection( _rxHandler );
+ m_bRebuildConnOnExecute = false;
+
+ Reference< XSingleSelectQueryComposer > xComposer = getCurrentSettingsComposer( this, m_aContext, nullptr );
+ Reference<XParametersSupplier> xParameters(xComposer, UNO_QUERY);
+
+ Reference<XIndexAccess> xParamsAsIndicies = xParameters.is() ? xParameters->getParameters() : Reference<XIndexAccess>();
+ const sal_Int32 nParamCount = xParamsAsIndicies.is() ? xParamsAsIndicies->getCount() : 0;
+ if ( m_aParametersSet.size() < o3tl::make_unsigned(nParamCount) )
+ m_aParametersSet.resize( nParamCount ,false);
+
+ ::dbtools::askForParameters( xComposer, this, m_xActiveConnection, _rxHandler,m_aParametersSet );
+ }
+ // ensure that only the allowed exceptions leave this block
+ catch(SQLException&)
+ {
+ throw;
+ }
+ catch(RuntimeException&)
+ {
+ throw;
+ }
+ catch(Exception const &)
+ {
+ TOOLS_WARN_EXCEPTION("dbaccess", "ORowSet::executeWithCompletion: caught an unexpected exception type while filling in the parameters");
+ }
+
+ // we're done with the parameters, now for the real execution
+
+ // do the real execute
+ execute_NoApprove_NoNewConn(aGuard);
+}
+
+Reference< XIndexAccess > SAL_CALL ORowSet::getParameters( )
+{
+ ::osl::MutexGuard aGuard( *m_pMutex );
+ ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper.bDisposed);
+
+ if ( m_bCommandFacetsDirty )
+ // need to rebuild the parameters, since some property which contributes to the
+ // complete command, and thus the parameters, changed
+ impl_disposeParametersContainer_nothrow();
+
+ if ( !m_pParameters && !m_aCommand.isEmpty() )
+ {
+ try
+ {
+ OUString sNotInterestedIn;
+ impl_initComposer_throw( sNotInterestedIn );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+
+ // our caller could change our parameters at any time
+ m_bParametersDirty = true;
+
+ return m_pParameters;
+}
+
+void ORowSet::approveExecution()
+{
+ ::osl::MutexGuard aGuard( m_aColumnsMutex );
+ EventObject aEvt(*this);
+
+ OInterfaceIteratorHelper3 aApproveIter( m_aApproveListeners );
+ while ( aApproveIter.hasMoreElements() )
+ {
+ Reference< XRowSetApproveListener > xListener( aApproveIter.next() );
+ try
+ {
+ if ( !xListener->approveRowSetChange( aEvt ) )
+ throw RowSetVetoException();
+ }
+ catch ( const DisposedException& e )
+ {
+ if ( e.Context == xListener )
+ aApproveIter.remove();
+ }
+ catch ( const RuntimeException& ) { throw; }
+ catch ( const RowSetVetoException& ) { throw; }
+ catch ( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+}
+
+// XRowSet
+void SAL_CALL ORowSet::execute( )
+{
+ ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper.bDisposed);
+
+ // tell everybody that we will change the result set
+ approveExecution();
+
+ ResettableMutexGuard aGuard( m_aMutex );
+ freeResources( m_bCommandFacetsDirty );
+
+ // calc the connection to be used
+ if (m_xActiveConnection.is() && m_bRebuildConnOnExecute) {
+ // there was a setProperty(ActiveConnection), but a setProperty(DataSource) _after_ that, too
+ Reference< XConnection> xXConnection;
+ setActiveConnection( xXConnection );
+ }
+
+ calcConnection(nullptr);
+ m_bRebuildConnOnExecute = false;
+
+ // do the real execute
+ execute_NoApprove_NoNewConn(aGuard);
+}
+
+void ORowSet::setStatementResultSetType( const Reference< XPropertySet >& _rxStatement, sal_Int32 _nDesiredResultSetType, sal_Int32 _nDesiredResultSetConcurrency )
+{
+ OSL_ENSURE( _rxStatement.is(), "ORowSet::setStatementResultSetType: invalid statement - this will crash!" );
+
+ sal_Int32 nResultSetType( _nDesiredResultSetType );
+ sal_Int32 nResultSetConcurrency( _nDesiredResultSetConcurrency );
+
+ // there *might* be a data source setting which tells use to be more defensive with those settings
+ // #i15113#
+ bool bRespectDriverRST = false;
+ Any aSetting;
+ if ( getDataSourceSetting( ::dbaccess::getDataSource( m_xActiveConnection ), "RespectDriverResultSetType", aSetting ) )
+ {
+ OSL_VERIFY( aSetting >>= bRespectDriverRST );
+ }
+
+ if ( bRespectDriverRST )
+ {
+ // try type/concurrency settings with decreasing usefulness, and rely on what the connection claims
+ // to support
+ Reference< XDatabaseMetaData > xMeta( m_xActiveConnection->getMetaData() );
+
+ sal_Int32 nCharacteristics[5][2] =
+ { { ResultSetType::SCROLL_SENSITIVE, ResultSetConcurrency::UPDATABLE },
+ { ResultSetType::SCROLL_INSENSITIVE, ResultSetConcurrency::UPDATABLE },
+ { ResultSetType::SCROLL_SENSITIVE, ResultSetConcurrency::READ_ONLY },
+ { ResultSetType::SCROLL_INSENSITIVE, ResultSetConcurrency::READ_ONLY },
+ { ResultSetType::FORWARD_ONLY, ResultSetConcurrency::READ_ONLY }
+ };
+ sal_Int32 i=0;
+ if ( m_xActiveConnection->getMetaData()->isReadOnly() )
+ i = 2; // if the database is read-only we only should use read-only concurrency
+
+ for ( ; i<5; ++i )
+ {
+ nResultSetType = nCharacteristics[i][0];
+ nResultSetConcurrency = nCharacteristics[i][1];
+
+ // don't try type/concurrency pairs which are more featured than what our caller requested
+ if ( nResultSetType > _nDesiredResultSetType )
+ continue;
+ if ( nResultSetConcurrency > _nDesiredResultSetConcurrency )
+ continue;
+
+ if ( xMeta.is() && xMeta->supportsResultSetConcurrency( nResultSetType, nResultSetConcurrency ) )
+ break;
+ }
+ }
+
+ _rxStatement->setPropertyValue( PROPERTY_RESULTSETTYPE, Any( nResultSetType ) );
+ _rxStatement->setPropertyValue( PROPERTY_RESULTSETCONCURRENCY, Any( nResultSetConcurrency ) );
+}
+
+void ORowSet::impl_ensureStatement_throw()
+{
+ OUString sCommandToExecute;
+ if(m_bCommandFacetsDirty)
+ {
+ impl_initComposer_throw( sCommandToExecute );
+ }
+ else
+ {
+ sCommandToExecute = m_bUseEscapeProcessing ? m_xComposer->getQueryWithSubstitution() : m_aActiveCommand;
+ }
+
+ try
+ {
+ m_xStatement = m_xActiveConnection->prepareStatement( sCommandToExecute );
+ if ( !m_xStatement.is() )
+ {
+ ::dbtools::throwSQLException( DBA_RES( RID_STR_INTERNAL_ERROR ), StandardSQLState::GENERAL_ERROR, *this );
+ }
+
+ Reference< XPropertySet > xStatementProps( m_xStatement, UNO_QUERY_THROW );
+ // set the result set type and concurrency
+ try
+ {
+ xStatementProps->setPropertyValue( PROPERTY_USEBOOKMARKS, Any( true ) );
+ xStatementProps->setPropertyValue( PROPERTY_MAXROWS, Any( m_nMaxRows ) );
+
+ setStatementResultSetType( xStatementProps, m_nResultSetType, m_nResultSetConcurrency );
+ }
+ catch ( const Exception& )
+ {
+ // this exception doesn't matter here because when we catch an exception
+ // then the driver doesn't support this feature
+ }
+ }
+ catch (SQLException& rException)
+ {
+ css::sdbc::SQLException* pLastExceptionInChain = SQLExceptionInfo::getLastException(&rException);
+ assert(pLastExceptionInChain && "will at least be &rException");
+
+ // append information about what we were actually going to execute
+ OUString sInfo(m_sErrorString.replaceFirst("$command$", sCommandToExecute));
+ css::uno::Any aAppend = SQLExceptionInfo::createException(SQLExceptionInfo::TYPE::SQLContext, sInfo, OUString(), 0);
+ pLastExceptionInChain->NextException = aAppend;
+
+ // propagate
+ throw;
+ }
+}
+
+Reference< XResultSet > ORowSet::impl_prepareAndExecute_throw()
+{
+ impl_ensureStatement_throw();
+
+ m_aParameterValueForCache->resize(1);
+ Reference< XParameters > xParam( m_xStatement, UNO_QUERY_THROW );
+ size_t nParamCount( m_pParameters.is() ? m_pParameters->size() : m_aPrematureParamValues->size() );
+ for ( size_t i=1; i<=nParamCount; ++i )
+ {
+ ORowSetValue& rParamValue( getParameterStorage( static_cast<sal_Int32>(i) ) );
+ ::dbtools::setObjectWithInfo( xParam, i, rParamValue.makeAny(), rParamValue.getTypeKind() );
+ m_aParameterValueForCache->push_back(rParamValue);
+ }
+ m_bParametersDirty = false;
+
+ Reference< XResultSet > xResultSet(m_xStatement->executeQuery());
+
+ OUString aComposedUpdateTableName;
+ if ( !m_aUpdateTableName.isEmpty() )
+ aComposedUpdateTableName = composeTableName( m_xActiveConnection->getMetaData(), m_aUpdateCatalogName, m_aUpdateSchemaName, m_aUpdateTableName, false, ::dbtools::EComposeRule::InDataManipulation );
+
+ SAL_INFO("dbaccess", "ORowSet::impl_prepareAndExecute_throw: creating cache" );
+ m_pCache =
+ std::make_shared<ORowSetCache>(xResultSet, m_xComposer.get(), m_aContext, aComposedUpdateTableName,
+ m_bModified, m_bNew, *m_aParameterValueForCache, m_aFilter, m_nMaxRows);
+ if ( m_nResultSetConcurrency == ResultSetConcurrency::READ_ONLY )
+ {
+ m_nPrivileges = Privilege::SELECT;
+ m_pCache->m_nPrivileges = Privilege::SELECT;
+ }
+ m_pCache->setFetchSize(m_nFetchSize);
+ m_aCurrentRow = m_pCache->createIterator(this);
+ m_bIsInsertRow = false;
+ m_aOldRow = m_pCache->registerOldRow();
+
+ return xResultSet;
+}
+
+void ORowSet::impl_initializeColumnSettings_nothrow( const Reference< XPropertySet >& _rxTemplateColumn, const Reference< XPropertySet >& _rxRowSetColumn )
+{
+ OSL_ENSURE( _rxTemplateColumn.is() && _rxRowSetColumn.is(),
+ "ORowSet::impl_initializeColumnSettings_nothrow: this will crash!" );
+
+ bool bHaveAnyColumnSetting = false;
+ try
+ {
+ Reference< XPropertySetInfo > xInfo( _rxTemplateColumn->getPropertySetInfo(), UNO_SET_THROW );
+
+ // a number of properties is plain copied
+ const OUString aPropertyNames[] = {
+ OUString(PROPERTY_ALIGN), OUString(PROPERTY_RELATIVEPOSITION), OUString(PROPERTY_WIDTH), OUString(PROPERTY_HIDDEN), OUString(PROPERTY_CONTROLMODEL),
+ OUString(PROPERTY_HELPTEXT), OUString(PROPERTY_CONTROLDEFAULT)
+ };
+ for (const auto & aPropertyName : aPropertyNames)
+ {
+ if ( xInfo->hasPropertyByName( aPropertyName ) )
+ {
+ _rxRowSetColumn->setPropertyValue( aPropertyName, _rxTemplateColumn->getPropertyValue( aPropertyName ) );
+ bHaveAnyColumnSetting = true;
+ }
+ }
+
+ // the format key is slightly more complex
+ sal_Int32 nFormatKey = 0;
+ if( xInfo->hasPropertyByName( PROPERTY_NUMBERFORMAT ) )
+ {
+ _rxTemplateColumn->getPropertyValue( PROPERTY_NUMBERFORMAT ) >>= nFormatKey;
+ bHaveAnyColumnSetting = true;
+ }
+ if ( !nFormatKey && m_xNumberFormatTypes.is() )
+ nFormatKey = ::dbtools::getDefaultNumberFormat( _rxTemplateColumn, m_xNumberFormatTypes, SvtSysLocale().GetLanguageTag().getLocale() );
+ _rxRowSetColumn->setPropertyValue( PROPERTY_NUMBERFORMAT, Any( nFormatKey ) );
+ }
+ catch(Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ return;
+ }
+
+ if ( bHaveAnyColumnSetting )
+ return;
+
+ // the template column could not provide *any* setting. Okay, probably it's a parser column, which
+ // does not offer those. However, perhaps the template column refers to a table column, which we
+ // can use as new template column
+ try
+ {
+ Reference< XPropertySetInfo > xInfo( _rxTemplateColumn->getPropertySetInfo(), UNO_SET_THROW );
+ if ( !xInfo->hasPropertyByName( PROPERTY_TABLENAME ) )
+ // no chance
+ return;
+
+ OUString sTableName;
+ OSL_VERIFY( _rxTemplateColumn->getPropertyValue( PROPERTY_TABLENAME ) >>= sTableName );
+
+ Reference< XNameAccess > xTables( impl_getTables_throw(), UNO_SET_THROW );
+ if ( !xTables->hasByName( sTableName ) )
+ // no chance
+ return;
+
+ Reference< XColumnsSupplier > xTableColSup( xTables->getByName( sTableName ), UNO_QUERY_THROW );
+ Reference< XNameAccess > xTableCols( xTableColSup->getColumns(), UNO_SET_THROW );
+
+ OUString sTableColumnName;
+
+ // get the "Name" or (preferred) "RealName" property of the column
+ OUString sNamePropertyName( PROPERTY_NAME );
+ if ( xInfo->hasPropertyByName( PROPERTY_REALNAME ) )
+ sNamePropertyName = PROPERTY_REALNAME;
+ OSL_VERIFY( _rxTemplateColumn->getPropertyValue( sNamePropertyName ) >>= sTableColumnName );
+
+ if ( !xTableCols->hasByName( sTableColumnName ) )
+ return;
+
+ Reference< XPropertySet > xTableColumn( xTableCols->getByName( sTableColumnName ), UNO_QUERY_THROW );
+ impl_initializeColumnSettings_nothrow( xTableColumn, _rxRowSetColumn );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+}
+
+void ORowSet::execute_NoApprove_NoNewConn(ResettableMutexGuard& _rClearForNotification)
+{
+ // now we can dispose our old connection
+ ::comphelper::disposeComponent(m_xOldConnection);
+ m_xOldConnection = nullptr;
+
+ // do we need a new statement
+ if ( m_bCommandFacetsDirty )
+ {
+ m_xStatement = nullptr;
+ m_xComposer = nullptr;
+
+ Reference< XResultSet > xResultSet( impl_prepareAndExecute_throw() );
+
+ // let our warnings container forget the reference to the (possibly disposed) old result set
+ m_aWarnings.setExternalWarnings( nullptr );
+ // clear all current warnings
+ m_aWarnings.clearWarnings();
+ // let the warnings container know about the new "external warnings"
+ m_aWarnings.setExternalWarnings( Reference< XWarningsSupplier >( xResultSet, UNO_QUERY ) );
+
+ // get the locale
+ Locale aLocale = SvtSysLocale().GetLanguageTag().getLocale();
+
+ // get the numberformatTypes
+ OSL_ENSURE(m_xActiveConnection.is(),"No ActiveConnection");
+ Reference< XNumberFormatsSupplier> xNumberFormat = ::dbtools::getNumberFormats(m_xActiveConnection);
+ if ( xNumberFormat.is() )
+ m_xNumberFormatTypes.set(xNumberFormat->getNumberFormats(),UNO_QUERY);
+
+ ::rtl::Reference< ::connectivity::OSQLColumns> aColumns = new ::connectivity::OSQLColumns();
+ std::vector< OUString> aNames;
+ OUString aDescription;
+
+ const std::map<sal_Int32,sal_Int32>& rKeyColumns = m_pCache->getKeyColumns();
+ if(!m_xColumns.is())
+ {
+ SAL_INFO("dbaccess", "ORowSet::execute_NoApprove_NoNewConn::creating columns" );
+ // use the meta data
+ Reference<XResultSetMetaDataSupplier> xMetaSup(m_xStatement,UNO_QUERY);
+ try
+ {
+ Reference<XResultSetMetaData> xMetaData = xMetaSup->getMetaData();
+ if ( xMetaData.is() )
+ {
+ sal_Int32 nCount = xMetaData->getColumnCount();
+ m_aDataColumns.reserve(nCount+1);
+ aColumns->reserve(nCount+1);
+ std::map< OUString, int > aColumnMap;
+ for (sal_Int32 i = 0 ; i < nCount; ++i)
+ {
+ // retrieve the name of the column
+ OUString sName = xMetaData->getColumnName(i + 1);
+ // check for duplicate entries
+ if(aColumnMap.find(sName) != aColumnMap.end())
+ {
+ OUString sAlias(sName);
+ sal_Int32 searchIndex=1;
+ while(aColumnMap.find(sAlias) != aColumnMap.end())
+ {
+ sAlias = sName + OUString::number(searchIndex++);
+ }
+ sName = sAlias;
+ }
+ rtl::Reference<ORowSetDataColumn> pColumn = new ORowSetDataColumn( getMetaData(),
+ this,
+ this,
+ i+1,
+ m_xActiveConnection->getMetaData(),
+ aDescription,
+ OUString(),
+ [this] (sal_Int32 const column) -> ORowSetValue const& {
+ return this->getInsertValue(column);
+ });
+ aColumnMap.insert(std::make_pair(sName,0));
+ aColumns->emplace_back(pColumn);
+ pColumn->setName(sName);
+ aNames.push_back(sName);
+ m_aDataColumns.push_back(pColumn.get());
+
+ pColumn->setFastPropertyValue_NoBroadcast(PROPERTY_ID_ISREADONLY,Any(rKeyColumns.find(i+1) != rKeyColumns.end()));
+
+ try
+ {
+ sal_Int32 nFormatKey = 0;
+ if(m_xNumberFormatTypes.is())
+ nFormatKey = ::dbtools::getDefaultNumberFormat(pColumn,m_xNumberFormatTypes,aLocale);
+
+
+ pColumn->setFastPropertyValue_NoBroadcast(PROPERTY_ID_NUMBERFORMAT,Any(nFormatKey));
+ pColumn->setFastPropertyValue_NoBroadcast(PROPERTY_ID_RELATIVEPOSITION,Any(sal_Int32(i+1)));
+ pColumn->setFastPropertyValue_NoBroadcast(PROPERTY_ID_WIDTH,Any(sal_Int32(227)));
+ pColumn->setFastPropertyValue_NoBroadcast(PROPERTY_ID_ALIGN,Any(sal_Int32(0)));
+ pColumn->setFastPropertyValue_NoBroadcast(PROPERTY_ID_HIDDEN, css::uno::Any(false));
+ }
+ catch(Exception&)
+ {
+ }
+ }
+ }
+ }
+ catch (SQLException&)
+ {
+ }
+ }
+ else
+ {
+ // create the rowset columns
+ Reference< XResultSetMetaData > xMeta( getMetaData(), UNO_SET_THROW );
+ sal_Int32 nCount = xMeta->getColumnCount();
+ m_aDataColumns.reserve(nCount+1);
+ aColumns->reserve(nCount+1);
+ std::set< Reference< XPropertySet > > aAllColumns;
+
+ for(sal_Int32 i=1; i <= nCount ;++i)
+ {
+ OUString sName = xMeta->getColumnName(i);
+ OUString sColumnLabel = xMeta->getColumnLabel(i);
+
+ // retrieve the column number |i|
+ Reference<XPropertySet> xColumn;
+ {
+ bool bReFetchName = false;
+ if (m_xColumns->hasByName(sColumnLabel))
+ m_xColumns->getByName(sColumnLabel) >>= xColumn;
+ if (!xColumn.is() && m_xColumns->hasByName(sName))
+ m_xColumns->getByName(sName) >>= xColumn;
+
+ // check if column already in the list we need another
+ if ( aAllColumns.find( xColumn ) != aAllColumns.end() )
+ {
+ xColumn = nullptr;
+ bReFetchName = true;
+ sColumnLabel.clear();
+ }
+ if(!xColumn.is())
+ {
+ // no column found so we could look at the position i
+ Reference<XIndexAccess> xIndexAccess(m_xColumns,UNO_QUERY);
+ if(xIndexAccess.is() && i <= xIndexAccess->getCount())
+ {
+ xIndexAccess->getByIndex(i-1) >>= xColumn;
+ }
+ else
+ {
+ Sequence< OUString> aSeq = m_xColumns->getElementNames();
+ if( i <= aSeq.getLength())
+ {
+ m_xColumns->getByName(aSeq.getConstArray()[i-1]) >>= xColumn;
+ }
+ }
+ }
+ if(bReFetchName && xColumn.is())
+ xColumn->getPropertyValue(PROPERTY_NAME) >>= sName;
+ aAllColumns.insert( xColumn );
+ }
+
+ // create a RowSetDataColumn
+ {
+ Reference<XPropertySetInfo> xInfo = xColumn.is() ? xColumn->getPropertySetInfo() : Reference<XPropertySetInfo>();
+ if(xInfo.is() && xInfo->hasPropertyByName(PROPERTY_DESCRIPTION))
+ aDescription = comphelper::getString(xColumn->getPropertyValue(PROPERTY_DESCRIPTION));
+
+ OUString sParseLabel;
+ if ( xColumn.is() )
+ {
+ xColumn->getPropertyValue(PROPERTY_LABEL) >>= sParseLabel;
+ }
+ rtl::Reference<ORowSetDataColumn> pColumn = new ORowSetDataColumn( getMetaData(),
+ this,
+ this,
+ i,
+ m_xActiveConnection->getMetaData(),
+ aDescription,
+ sParseLabel,
+ [this] (sal_Int32 const column) -> ORowSetValue const& {
+ return this->getInsertValue(column);
+ });
+ aColumns->emplace_back(pColumn);
+
+ pColumn->setFastPropertyValue_NoBroadcast(PROPERTY_ID_ISREADONLY,Any(rKeyColumns.find(i) != rKeyColumns.end()));
+
+ if(sColumnLabel.isEmpty())
+ {
+ if(xColumn.is())
+ xColumn->getPropertyValue(PROPERTY_NAME) >>= sColumnLabel;
+ else
+ sColumnLabel = DBA_RES( RID_STR_EXPRESSION1 );
+ }
+ pColumn->setName(sColumnLabel);
+ aNames.push_back(sColumnLabel);
+ m_aDataColumns.push_back(pColumn.get());
+
+ if ( xColumn.is() )
+ impl_initializeColumnSettings_nothrow( xColumn, pColumn );
+ }
+ }
+ }
+ // now create the columns we need
+ if(m_pColumns)
+ m_pColumns->assign(aColumns,aNames);
+ else
+ {
+ Reference<XDatabaseMetaData> xMeta = m_xActiveConnection->getMetaData();
+ m_pColumns.reset( new ORowSetDataColumns(xMeta.is() && xMeta->supportsMixedCaseQuotedIdentifiers(),
+ aColumns,*this,m_aColumnsMutex,aNames) );
+ }
+ }
+ else // !m_bCommandFacetsDirty
+ {
+ Reference< XResultSet > xResultSet;
+ if(m_bParametersDirty)
+ {
+ xResultSet = impl_prepareAndExecute_throw();
+ }
+ else
+ {
+ xResultSet = m_xStatement->executeQuery();
+ m_pCache->reset(xResultSet);
+ }
+ // let our warnings container forget the reference to the (possibly disposed) old result set
+ m_aWarnings.setExternalWarnings( nullptr );
+ // clear all current warnings
+ m_aWarnings.clearWarnings();
+ // let the warnings container know about the new "external warnings"
+ m_aWarnings.setExternalWarnings( Reference< XWarningsSupplier >( xResultSet, UNO_QUERY ) );
+ }
+ checkCache();
+ // notify the rowset listeners
+ notifyAllListeners(_rClearForNotification);
+}
+
+// XRowSetApproveBroadcaster
+void SAL_CALL ORowSet::addRowSetApproveListener( const Reference< XRowSetApproveListener >& listener )
+{
+ ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper.bDisposed);
+
+ ::osl::MutexGuard aGuard( m_aColumnsMutex );
+
+ m_aApproveListeners.addInterface(listener);
+}
+
+void SAL_CALL ORowSet::removeRowSetApproveListener( const Reference< XRowSetApproveListener >& listener )
+{
+ ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper.bDisposed);
+
+ ::osl::MutexGuard aGuard( m_aColumnsMutex );
+
+ m_aApproveListeners.removeInterface(listener);
+}
+
+// XRowsChangeBroadcaster
+void SAL_CALL ORowSet::addRowsChangeListener( const Reference< XRowsChangeListener >& listener )
+{
+ ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper.bDisposed);
+
+ ::osl::MutexGuard aGuard( m_aColumnsMutex );
+
+ m_aRowsChangeListener.addInterface(listener);
+}
+
+void SAL_CALL ORowSet::removeRowsChangeListener( const Reference< XRowsChangeListener >& listener )
+{
+ ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper.bDisposed);
+
+ ::osl::MutexGuard aGuard( m_aColumnsMutex );
+
+ m_aRowsChangeListener.removeInterface(listener);
+}
+
+// XResultSetAccess
+Reference< XResultSet > SAL_CALL ORowSet::createResultSet( )
+{
+ ::osl::MutexGuard aGuard( m_aColumnsMutex );
+
+ if(m_xStatement.is())
+ {
+ rtl::Reference<ORowSetClone> pClone = new ORowSetClone( m_aContext, *this, m_pMutex );
+ m_aClones.emplace_back(css::uno::Reference< css::uno::XWeak >(pClone));
+ return pClone;
+ }
+ return Reference< XResultSet >();
+}
+
+// css::util::XCancellable
+void SAL_CALL ORowSet::cancel( )
+{
+ ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper.bDisposed);
+}
+
+// css::sdbcx::XDeleteRows
+Sequence< sal_Int32 > SAL_CALL ORowSet::deleteRows( const Sequence< Any >& rows )
+{
+ ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper.bDisposed);
+
+ if(!m_pCache || m_nResultSetConcurrency == ResultSetConcurrency::READ_ONLY)
+ throwFunctionSequenceException(*this);
+
+ ::osl::ResettableMutexGuard aGuard( *m_pMutex );
+
+ Sequence<Any> aChangedBookmarks;
+ RowsChangeEvent aEvt(*this,RowChangeAction::DELETE,rows.getLength(),aChangedBookmarks);
+ // notify the rowset listeners
+ notifyAllListenersRowBeforeChange(aGuard,aEvt);
+
+ Sequence< sal_Int32 > aResults( rows.getLength() );
+ const Any* row = rows.getConstArray();
+ const Any* rowEnd = rows.getConstArray() + rows.getLength();
+ sal_Int32* result = aResults.getArray();
+ for ( ; row != rowEnd; ++row, ++result )
+ {
+ *result = 0;
+ if ( !m_pCache->moveToBookmark( *row ) )
+ continue;
+ sal_Int32 nDeletePosition = m_pCache->getRow();
+
+ // first notify the clones so that they can save their position
+ notifyRowSetAndClonesRowDelete( *row );
+
+ // now delete the row
+ if ( !m_pCache->deleteRow() )
+ continue;
+ *result = 1;
+ // now notify that we have deleted
+ notifyRowSetAndClonesRowDeleted( *row, nDeletePosition );
+ }
+ aEvt.Rows = aResults.getLength();
+
+ // we have to check if we stand on the insert row and if so we have to reset it
+ ORowSetNotifier aNotifier( this );
+ // this will call cancelRowModification on the cache if necessary
+ // notification order
+ // - rowChanged
+ notifyAllListenersRowChanged(aGuard,aEvt);
+
+ // - IsModified
+ // - IsNew
+ aNotifier.fire();
+
+ // - RowCount/IsRowCountFinal
+ fireRowcount();
+
+ return aResults;
+}
+
+void ORowSet::notifyRowSetAndClonesRowDelete( const Any& _rBookmark )
+{
+ // notify ourself
+ onDeleteRow( _rBookmark );
+ // notify the clones
+ for (auto const& elem : m_aClones)
+ {
+ auto pClone = comphelper::getFromUnoTunnel<ORowSetClone>(elem.get());
+ if(pClone)
+ pClone->onDeleteRow( _rBookmark );
+ }
+}
+
+void ORowSet::notifyRowSetAndClonesRowDeleted( const Any& _rBookmark, sal_Int32 _nPos )
+{
+ // notify ourself
+ onDeletedRow( _rBookmark, _nPos );
+ // notify the clones
+ for (auto const& clone : m_aClones)
+ {
+ auto pClone = comphelper::getFromUnoTunnel<ORowSetClone>(clone.get());
+ if(pClone)
+ pClone->onDeletedRow( _rBookmark, _nPos );
+ }
+}
+
+Reference< XConnection > ORowSet::calcConnection(const Reference< XInteractionHandler >& _rxHandler)
+{
+ MutexGuard aGuard(m_aMutex);
+ if (!m_xActiveConnection.is())
+ {
+ Reference< XConnection > xNewConn;
+ if ( !m_aDataSourceName.isEmpty() )
+ {
+ Reference< XDatabaseContext > xDatabaseContext( DatabaseContext::create(m_aContext) );
+ try
+ {
+ Reference< XDataSource > xDataSource( xDatabaseContext->getByName( m_aDataSourceName ), UNO_QUERY_THROW );
+
+ // try connecting with the interaction handler
+ Reference< XCompletedConnection > xComplConn( xDataSource, UNO_QUERY );
+ if ( _rxHandler.is() && xComplConn.is() )
+ {
+ xNewConn = xComplConn->connectWithCompletion( _rxHandler );
+ }
+ else
+ {
+ xNewConn = xDataSource->getConnection( m_aUser, m_aPassword );
+ }
+ }
+ catch ( const SQLException& )
+ {
+ throw;
+ }
+ catch ( const Exception& )
+ {
+ Any aError = ::cppu::getCaughtException();
+ OUString sMessage = ResourceManager::loadString( RID_NO_SUCH_DATA_SOURCE,
+ "$name$", m_aDataSourceName, "$error$", extractExceptionMessage( m_aContext, aError ) );
+ ::dbtools::throwGenericSQLException( sMessage, *this, aError );
+ }
+ }
+ setActiveConnection(xNewConn);
+ m_bOwnConnection = true;
+ }
+ return m_xActiveConnection;
+}
+
+Reference< XNameAccess > ORowSet::impl_getTables_throw()
+{
+ Reference< XNameAccess > xTables;
+
+ Reference< XTablesSupplier > xTablesAccess( m_xActiveConnection, UNO_QUERY );
+ if ( xTablesAccess.is() )
+ {
+ xTables.set( xTablesAccess->getTables(), UNO_SET_THROW );
+ }
+ else if ( m_xTables )
+ {
+ xTables = m_xTables.get();
+ }
+ else
+ {
+ if ( !m_xActiveConnection.is() )
+ throw SQLException(DBA_RES(RID_STR_CONNECTION_INVALID),*this,SQLSTATE_GENERAL,1000,Any() );
+
+ bool bCase = true;
+ try
+ {
+ Reference<XDatabaseMetaData> xMeta = m_xActiveConnection->getMetaData();
+ bCase = xMeta.is() && xMeta->supportsMixedCaseQuotedIdentifiers();
+ }
+ catch(SQLException&)
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+
+ m_xTables.reset(new OTableContainer(*this,m_aMutex,m_xActiveConnection,bCase,nullptr,nullptr,m_nInAppend));
+ xTables = m_xTables.get();
+ Sequence<OUString> aTableFilter { "%" };
+ m_xTables->construct(aTableFilter,Sequence< OUString>());
+ }
+
+ return xTables;
+}
+
+void ORowSet::impl_resetTables_nothrow()
+{
+ if ( !m_xTables )
+ return;
+
+ try
+ {
+ m_xTables->dispose();
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+
+ m_xTables.reset();
+}
+
+void ORowSet::impl_initComposer_throw( OUString& _out_rCommandToExecute )
+{
+ bool bUseEscapeProcessing = impl_buildActiveCommand_throw( );
+ _out_rCommandToExecute = m_aActiveCommand;
+ if ( !bUseEscapeProcessing )
+ return;
+
+ if (m_bCommandFacetsDirty)
+ m_xComposer = nullptr;
+
+ Reference< XMultiServiceFactory > xFactory( m_xActiveConnection, UNO_QUERY );
+ if ( !m_xComposer.is() && xFactory.is() )
+ {
+ try
+ {
+ m_xComposer.set( xFactory->createInstance( SERVICE_NAME_SINGLESELECTQUERYCOMPOSER ), UNO_QUERY_THROW );
+ }
+ catch (const Exception& ) { m_xComposer = nullptr; }
+ }
+ if ( !m_xComposer.is() )
+ m_xComposer = new OSingleSelectQueryComposer( impl_getTables_throw(), m_xActiveConnection, m_aContext );
+
+ m_xComposer->setCommand( m_aCommand,m_nCommandType );
+ m_aActiveCommand = m_xComposer->getQuery();
+
+ m_xComposer->setFilter( m_bApplyFilter ? m_aFilter : OUString() );
+ m_xComposer->setHavingClause( m_bApplyFilter ? m_aHavingClause : OUString() );
+
+ if ( m_bIgnoreResult )
+ { // append a "0=1" filter
+ // don't simply overwrite an existent filter, this would lead to problems if this existent
+ // filter contains parameters (since a keyset may add parameters itself)
+ m_xComposer->setElementaryQuery( m_xComposer->getQuery( ) );
+ m_xComposer->setFilter( "0 = 1" );
+ }
+
+ m_xComposer->setOrder( m_aOrder );
+ m_xComposer->setGroup( m_aGroupBy );
+
+ if ( !m_xColumns.is() )
+ {
+ Reference< XColumnsSupplier > xCols( m_xComposer, UNO_QUERY_THROW );
+ m_xColumns = xCols->getColumns();
+ }
+
+ impl_initParametersContainer_nothrow();
+
+ _out_rCommandToExecute = m_xComposer->getQueryWithSubstitution();
+
+ m_bCommandFacetsDirty = false;
+}
+
+bool ORowSet::impl_buildActiveCommand_throw()
+{
+ // create the sql command
+ // from a table name or get the command out of a query (not a view)
+ // the last use the command as it is
+ bool bDoEscapeProcessing = m_bUseEscapeProcessing;
+
+ m_aActiveCommand.clear();
+ OUString sCommand;
+
+ if ( m_aCommand.isEmpty() )
+ return bDoEscapeProcessing;
+
+ switch (m_nCommandType)
+ {
+ case CommandType::TABLE:
+ {
+ impl_resetTables_nothrow();
+ if ( bDoEscapeProcessing )
+ {
+ Reference< XNameAccess > xTables( impl_getTables_throw() );
+ if ( xTables->hasByName(m_aCommand) )
+ {
+ }
+ else
+ {
+ OUString sMessage( DBA_RES( RID_STR_TABLE_DOES_NOT_EXIST ) );
+ throwGenericSQLException(sMessage.replaceAll( "$table$", m_aCommand ),*this);
+ }
+ }
+ else
+ {
+ sCommand = "SELECT * FROM ";
+ OUString sCatalog, sSchema, sTable;
+ ::dbtools::qualifiedNameComponents( m_xActiveConnection->getMetaData(), m_aCommand, sCatalog, sSchema, sTable, ::dbtools::EComposeRule::InDataManipulation );
+ sCommand += ::dbtools::composeTableNameForSelect( m_xActiveConnection, sCatalog, sSchema, sTable );
+ }
+ }
+ break;
+
+ case CommandType::QUERY:
+ {
+ Reference< XQueriesSupplier > xQueriesAccess(m_xActiveConnection, UNO_QUERY);
+ if (!xQueriesAccess.is())
+ throw SQLException(DBA_RES(RID_STR_NO_XQUERIESSUPPLIER),*this,OUString(),0,Any());
+ Reference< css::container::XNameAccess > xQueries(xQueriesAccess->getQueries());
+ if (xQueries->hasByName(m_aCommand))
+ {
+ Reference< XPropertySet > xQuery(xQueries->getByName(m_aCommand),UNO_QUERY);
+ OSL_ENSURE(xQuery.is(),"ORowSet::impl_buildActiveCommand_throw: Query is NULL!");
+ if ( xQuery.is() )
+ {
+ xQuery->getPropertyValue(PROPERTY_COMMAND) >>= sCommand;
+ xQuery->getPropertyValue(PROPERTY_ESCAPE_PROCESSING) >>= bDoEscapeProcessing;
+ if ( bDoEscapeProcessing != m_bUseEscapeProcessing )
+ {
+ bool bOldValue = m_bUseEscapeProcessing;
+ m_bUseEscapeProcessing = bDoEscapeProcessing;
+ fireProperty(PROPERTY_ID_ESCAPE_PROCESSING,bOldValue,bDoEscapeProcessing);
+ }
+
+ OUString aCatalog,aSchema,aTable;
+ xQuery->getPropertyValue(PROPERTY_UPDATE_CATALOGNAME) >>= aCatalog;
+ xQuery->getPropertyValue(PROPERTY_UPDATE_SCHEMANAME) >>= aSchema;
+ xQuery->getPropertyValue(PROPERTY_UPDATE_TABLENAME) >>= aTable;
+ if(!aTable.isEmpty())
+ m_aUpdateTableName = composeTableName( m_xActiveConnection->getMetaData(), aCatalog, aSchema, aTable, false, ::dbtools::EComposeRule::InDataManipulation );
+ }
+ }
+ else
+ {
+ OUString sMessage( DBA_RES( RID_STR_QUERY_DOES_NOT_EXIST ) );
+ throwGenericSQLException(sMessage.replaceAll( "$table$", m_aCommand ),*this);
+ }
+ }
+ break;
+
+ default:
+ sCommand = m_aCommand;
+ break;
+ }
+
+ m_aActiveCommand = sCommand;
+
+ if ( m_aActiveCommand.isEmpty() && !bDoEscapeProcessing )
+ ::dbtools::throwSQLException( DBA_RES( RID_STR_NO_SQL_COMMAND ), StandardSQLState::FUNCTION_SEQUENCE_ERROR, *this );
+
+ return bDoEscapeProcessing;
+}
+
+void ORowSet::impl_initParametersContainer_nothrow()
+{
+ OSL_PRECOND( !m_pParameters.is(), "ORowSet::impl_initParametersContainer_nothrow: already initialized the parameters!" );
+
+ m_pParameters = new param::ParameterWrapperContainer( m_xComposer );
+ // copy the premature parameters into the final ones
+ size_t nParamCount( std::min( m_pParameters->size(), m_aPrematureParamValues->size() ) );
+ for ( size_t i=0; i<nParamCount; ++i )
+ {
+ (*m_pParameters)[i] = (*m_aPrematureParamValues)[i];
+ }
+}
+
+void ORowSet::impl_disposeParametersContainer_nothrow()
+{
+ if ( !m_pParameters.is() )
+ return;
+
+ // copy the actual values to our "premature" ones, to preserve them for later use
+ size_t nParamCount( m_pParameters->size() );
+ m_aPrematureParamValues->resize( nParamCount );
+ for ( size_t i=0; i<nParamCount; ++i )
+ {
+ (*m_aPrematureParamValues)[i] = (*m_pParameters)[i];
+ }
+
+ m_pParameters->dispose();
+ m_pParameters = nullptr;
+}
+
+ORowSetValue& ORowSet::getParameterStorage(sal_Int32 parameterIndex)
+{
+ ::connectivity::checkDisposed( ORowSet_BASE1::rBHelper.bDisposed );
+ if ( parameterIndex < 1 )
+ throwInvalidIndexException( *this );
+
+ if ( m_aParametersSet.size() < o3tl::make_unsigned(parameterIndex) )
+ m_aParametersSet.resize( parameterIndex ,false);
+ m_aParametersSet[parameterIndex - 1] = true;
+
+ if ( m_pParameters.is() )
+ {
+ if ( m_bCommandFacetsDirty )
+ // need to rebuild the parameters, since some property which contributes to the
+ // complete command, and thus the parameters, changed
+ impl_disposeParametersContainer_nothrow();
+ if ( m_pParameters.is() )
+ {
+ if ( o3tl::make_unsigned(parameterIndex) > m_pParameters->size() )
+ throwInvalidIndexException( *this );
+ return (*m_pParameters)[ parameterIndex - 1 ];
+ }
+ }
+
+ if ( m_aPrematureParamValues->size() < o3tl::make_unsigned(parameterIndex) )
+ m_aPrematureParamValues->resize( parameterIndex );
+ return (*m_aPrematureParamValues)[ parameterIndex - 1 ];
+}
+
+// XParameters
+void SAL_CALL ORowSet::setNull( sal_Int32 parameterIndex, sal_Int32 /*sqlType*/ )
+{
+ ::osl::MutexGuard aGuard( m_aColumnsMutex );
+
+ getParameterStorage( parameterIndex ).setNull();
+ m_bParametersDirty = true;
+}
+
+void SAL_CALL ORowSet::setObjectNull( sal_Int32 parameterIndex, sal_Int32 sqlType, const OUString& /*typeName*/ )
+{
+ setNull( parameterIndex, sqlType );
+}
+
+void ORowSet::setParameter(sal_Int32 parameterIndex, const ORowSetValue& x)
+{
+ ::osl::MutexGuard aGuard( m_aColumnsMutex );
+
+ getParameterStorage( parameterIndex ) = x;
+ m_bParametersDirty = true;
+}
+
+void SAL_CALL ORowSet::setBoolean( sal_Int32 parameterIndex, sal_Bool x )
+{
+ setParameter(parameterIndex, static_cast<bool>(x));
+}
+
+void SAL_CALL ORowSet::setByte( sal_Int32 parameterIndex, sal_Int8 x )
+{
+ setParameter(parameterIndex,x);
+}
+
+void SAL_CALL ORowSet::setShort( sal_Int32 parameterIndex, sal_Int16 x )
+{
+ setParameter(parameterIndex,x);
+}
+
+void SAL_CALL ORowSet::setInt( sal_Int32 parameterIndex, sal_Int32 x )
+{
+ setParameter(parameterIndex,x);
+}
+
+void SAL_CALL ORowSet::setLong( sal_Int32 parameterIndex, sal_Int64 x )
+{
+ setParameter(parameterIndex,x);
+}
+
+void SAL_CALL ORowSet::setFloat( sal_Int32 parameterIndex, float x )
+{
+ setParameter(parameterIndex,x);
+}
+
+void SAL_CALL ORowSet::setDouble( sal_Int32 parameterIndex, double x )
+{
+ setParameter(parameterIndex,x);
+}
+
+void SAL_CALL ORowSet::setString( sal_Int32 parameterIndex, const OUString& x )
+{
+ setParameter(parameterIndex,x);
+}
+
+void SAL_CALL ORowSet::setBytes( sal_Int32 parameterIndex, const Sequence< sal_Int8 >& x )
+{
+ setParameter(parameterIndex,x);
+}
+
+void SAL_CALL ORowSet::setDate( sal_Int32 parameterIndex, const css::util::Date& x )
+{
+ setParameter(parameterIndex,x);
+}
+
+void SAL_CALL ORowSet::setTime( sal_Int32 parameterIndex, const css::util::Time& x )
+{
+ setParameter(parameterIndex,x);
+}
+
+void SAL_CALL ORowSet::setTimestamp( sal_Int32 parameterIndex, const css::util::DateTime& x )
+{
+ setParameter(parameterIndex,x);
+}
+
+void SAL_CALL ORowSet::setBinaryStream( sal_Int32 parameterIndex, const Reference< css::io::XInputStream >& x, sal_Int32 length )
+{
+ ::osl::MutexGuard aGuard( m_aColumnsMutex );
+ ORowSetValue& rParamValue( getParameterStorage( parameterIndex ) );
+
+ try
+ {
+ Sequence <sal_Int8> aData;
+ x->readBytes(aData, length);
+ rParamValue = aData;
+ m_bParametersDirty = true;
+ x->closeInput();
+ }
+ catch( Exception const & )
+ {
+ css::uno::Any anyEx = cppu::getCaughtException();
+ throw SQLException("ORowSet::setBinaryStream", *this, "S1000", 0,anyEx);
+ }
+}
+
+void SAL_CALL ORowSet::setCharacterStream( sal_Int32 parameterIndex, const Reference< css::io::XInputStream >& x, sal_Int32 length )
+{
+ ::osl::MutexGuard aGuard( m_aColumnsMutex );
+ ORowSetValue& rParamValue( getParameterStorage( parameterIndex ) );
+ try
+ {
+ Sequence <sal_Int8> aData;
+ OUString aDataStr;
+ // the data is given as character data and the length defines the character length
+ sal_Int32 nSize = x->readBytes(aData, length * sizeof(sal_Unicode));
+ if (nSize / sizeof(sal_Unicode))
+ aDataStr = OUString(reinterpret_cast<sal_Unicode const *>(aData.getConstArray()), nSize / sizeof(sal_Unicode));
+ m_bParametersDirty = true;
+ rParamValue = aDataStr;
+ rParamValue.setTypeKind( DataType::LONGVARCHAR );
+ x->closeInput();
+ }
+ catch( Exception const & )
+ {
+ css::uno::Any anyEx = cppu::getCaughtException();
+ throw SQLException("ORowSet::setCharacterStream", *this, "S1000", 0, anyEx);
+ }
+}
+
+void SAL_CALL ORowSet::setObject( sal_Int32 parameterIndex, const Any& x )
+{
+ if ( !::dbtools::implSetObject( this, parameterIndex, x ) )
+ { // there is no other setXXX call which can handle the value in x
+ throw SQLException();
+ }
+ m_bParametersDirty = true;
+}
+
+void SAL_CALL ORowSet::setObjectWithInfo( sal_Int32 parameterIndex, const Any& x, sal_Int32 targetSqlType, sal_Int32 /*scale*/ )
+{
+ ::osl::MutexGuard aGuard( m_aColumnsMutex );
+ ORowSetValue& rParamValue( getParameterStorage( parameterIndex ) );
+ setObject( parameterIndex, x );
+ rParamValue.setTypeKind( targetSqlType );
+}
+
+void SAL_CALL ORowSet::setRef( sal_Int32 /*parameterIndex*/, const Reference< XRef >& /*x*/ )
+{
+ ::dbtools::throwFeatureNotImplementedSQLException( "XParameters::setRef", *this );
+}
+
+void SAL_CALL ORowSet::setBlob( sal_Int32 /*parameterIndex*/, const Reference< XBlob >& /*x*/ )
+{
+ ::dbtools::throwFeatureNotImplementedSQLException( "XParameters::setBlob", *this );
+}
+
+void SAL_CALL ORowSet::setClob( sal_Int32 /*parameterIndex*/, const Reference< XClob >& /*x*/ )
+{
+ ::dbtools::throwFeatureNotImplementedSQLException( "XParameters::setClob", *this );
+}
+
+void SAL_CALL ORowSet::setArray( sal_Int32 /*parameterIndex*/, const Reference< XArray >& /*x*/ )
+{
+ ::dbtools::throwFeatureNotImplementedSQLException( "XParameters::setArray", *this );
+}
+
+void SAL_CALL ORowSet::clearParameters( )
+{
+ ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper.bDisposed);
+
+ ::osl::MutexGuard aGuard( m_aColumnsMutex );
+
+ size_t nParamCount( m_pParameters.is() ? m_pParameters->size() : m_aPrematureParamValues->size() );
+ for ( size_t i=1; i<=nParamCount; ++i )
+ getParameterStorage( static_cast<sal_Int32>(i) ).setNull();
+ m_aParametersSet.clear();
+}
+
+Any SAL_CALL ORowSet::getWarnings( )
+{
+ return m_aWarnings.getWarnings();
+}
+
+void SAL_CALL ORowSet::clearWarnings( )
+{
+ m_aWarnings.clearWarnings();
+}
+
+void ORowSet::doCancelModification( )
+{
+ if ( isModification() )
+ {
+ // read-only flag restored
+ impl_restoreDataColumnsWriteable_throw();
+ m_pCache->cancelRowModification();
+ }
+ m_bModified = false;
+ m_bIsInsertRow = false;
+}
+
+bool ORowSet::isModification( )
+{
+ return isNew();
+}
+
+bool ORowSet::isModified( )
+{
+ return m_bModified;
+}
+
+bool ORowSet::isNew( )
+{
+ return m_bNew;
+}
+
+bool ORowSet::isPropertyChangeNotificationEnabled() const
+{
+ return m_bPropChangeNotifyEnabled;
+}
+
+void ORowSet::checkUpdateIterator()
+{
+ if(!m_bIsInsertRow)
+ {
+ m_pCache->setUpdateIterator(m_aCurrentRow);
+ m_aCurrentRow = m_pCache->m_aInsertRow;
+ m_bIsInsertRow = true;
+ }
+}
+
+void ORowSet::checkUpdateConditions(sal_Int32 columnIndex)
+{
+ checkCache();
+ if ( m_nResultSetConcurrency == ResultSetConcurrency::READ_ONLY)
+ ::dbtools::throwSQLException( DBA_RES( RID_STR_RESULT_IS_READONLY ), StandardSQLState::GENERAL_ERROR, *this );
+
+ if ( rowDeleted() )
+ ::dbtools::throwSQLException( DBA_RES( RID_STR_ROW_ALREADY_DELETED ), StandardSQLState::INVALID_CURSOR_POSITION, *this );
+
+ if ( m_aCurrentRow.isNull() )
+ ::dbtools::throwSQLException( DBA_RES( RID_STR_INVALID_CURSOR_STATE ), StandardSQLState::INVALID_CURSOR_STATE, *this );
+
+ if ( columnIndex <= 0 || (*m_aCurrentRow)->size() <= o3tl::make_unsigned(columnIndex) )
+ ::dbtools::throwSQLException( DBA_RES( RID_STR_INVALID_INDEX ), StandardSQLState::INVALID_DESCRIPTOR_INDEX, *this );
+}
+
+void SAL_CALL ORowSet::refreshRow( )
+{
+
+ ORowSetNotifier aNotifier( this );
+ // this will call cancelRowModification on the cache if necessary
+
+ // notification order:
+ if ( m_bModified && m_pCache )
+ implCancelRowUpdates( false ); // do _not_ notify the IsModify - will do this ourself below
+
+ // - column values
+ ORowSetBase::refreshRow();
+
+ // - IsModified
+ // - IsNew
+ aNotifier.fire( );
+}
+
+void ORowSet::impl_rebuild_throw(::osl::ResettableMutexGuard& _rGuard)
+{
+ Reference< XResultSet > xResultSet(m_xStatement->executeQuery());
+ m_pCache->reset(xResultSet);
+ m_aWarnings.setExternalWarnings( Reference< XWarningsSupplier >( xResultSet, UNO_QUERY ) );
+ notifyAllListeners(_rGuard);
+}
+
+// ***********************************************************
+// ORowSetClone
+// ***********************************************************
+
+ORowSetClone::ORowSetClone( const Reference<XComponentContext>& _rContext, ORowSet& rParent, ::osl::Mutex* _pMutex )
+ :OSubComponent(m_aMutex, rParent)
+ ,ORowSetBase( _rContext, OComponentHelper::rBHelper, _pMutex )
+ ,m_pParent(&rParent)
+ ,m_nFetchDirection(rParent.m_nFetchDirection)
+ ,m_nFetchSize(rParent.m_nFetchSize)
+ ,m_bIsBookmarkable(true)
+{
+
+ m_nResultSetType = rParent.m_nResultSetType;
+ m_nResultSetConcurrency = ResultSetConcurrency::READ_ONLY;
+ m_pMySelf = this;
+ m_bClone = true;
+ m_bBeforeFirst = rParent.m_bBeforeFirst;
+ m_bAfterLast = rParent.m_bAfterLast;
+ m_pCache = rParent.m_pCache;
+ m_aBookmark = rParent.m_aBookmark;
+ m_aCurrentRow = m_pCache->createIterator(this);
+ m_xNumberFormatTypes = rParent.m_xNumberFormatTypes;
+
+ m_aOldRow = m_pCache->registerOldRow();
+
+ ::rtl::Reference< ::connectivity::OSQLColumns> aColumns = new ::connectivity::OSQLColumns();
+ std::vector< OUString> aNames;
+
+ OUString aDescription;
+ Locale aLocale = SvtSysLocale().GetLanguageTag().getLocale();
+
+ if ( rParent.m_pColumns )
+ {
+ Sequence< OUString> aSeq = rParent.m_pColumns->getElementNames();
+ const OUString* pIter = aSeq.getConstArray();
+ const OUString* pEnd = pIter + aSeq.getLength();
+ aColumns->reserve(aSeq.getLength()+1);
+ for(sal_Int32 i=1;pIter != pEnd ;++pIter,++i)
+ {
+ Reference<XPropertySet> xColumn;
+ rParent.m_pColumns->getByName(*pIter) >>= xColumn;
+ if(xColumn->getPropertySetInfo()->hasPropertyByName(PROPERTY_DESCRIPTION))
+ aDescription = comphelper::getString(xColumn->getPropertyValue(PROPERTY_DESCRIPTION));
+
+ OUString sParseLabel;
+ xColumn->getPropertyValue(PROPERTY_LABEL) >>= sParseLabel;
+ rtl::Reference<ORowSetColumn> pColumn = new ORowSetColumn( rParent.getMetaData(),
+ this,
+ i,
+ rParent.m_xActiveConnection->getMetaData(),
+ aDescription,
+ sParseLabel,
+ [this] (sal_Int32 const column) -> ORowSetValue const& {
+ return this->getValue(column);
+ });
+ aColumns->emplace_back(pColumn);
+ pColumn->setName(*pIter);
+ aNames.push_back(*pIter);
+ m_aDataColumns.push_back(pColumn.get());
+
+ pColumn->setFastPropertyValue_NoBroadcast(PROPERTY_ID_ALIGN,xColumn->getPropertyValue(PROPERTY_ALIGN));
+ sal_Int32 nFormatKey = 0;
+ xColumn->getPropertyValue(PROPERTY_NUMBERFORMAT) >>= nFormatKey;
+ if(!nFormatKey && xColumn.is() && m_xNumberFormatTypes.is())
+ nFormatKey = ::dbtools::getDefaultNumberFormat(xColumn,m_xNumberFormatTypes,aLocale);
+ pColumn->setFastPropertyValue_NoBroadcast(PROPERTY_ID_NUMBERFORMAT,Any(nFormatKey));
+ pColumn->setFastPropertyValue_NoBroadcast(PROPERTY_ID_RELATIVEPOSITION,xColumn->getPropertyValue(PROPERTY_RELATIVEPOSITION));
+ pColumn->setFastPropertyValue_NoBroadcast(PROPERTY_ID_WIDTH,xColumn->getPropertyValue(PROPERTY_WIDTH));
+ pColumn->setFastPropertyValue_NoBroadcast(PROPERTY_ID_HIDDEN,xColumn->getPropertyValue(PROPERTY_HIDDEN));
+ pColumn->setFastPropertyValue_NoBroadcast(PROPERTY_ID_CONTROLMODEL,xColumn->getPropertyValue(PROPERTY_CONTROLMODEL));
+ pColumn->setFastPropertyValue_NoBroadcast(PROPERTY_ID_HELPTEXT,xColumn->getPropertyValue(PROPERTY_HELPTEXT));
+ pColumn->setFastPropertyValue_NoBroadcast(PROPERTY_ID_CONTROLDEFAULT,xColumn->getPropertyValue(PROPERTY_CONTROLDEFAULT));
+
+ }
+ }
+ Reference<XDatabaseMetaData> xMeta = rParent.m_xActiveConnection->getMetaData();
+ m_pColumns.reset( new ORowSetDataColumns(xMeta.is() && xMeta->supportsMixedCaseQuotedIdentifiers(),
+ aColumns,*this,m_aMutex,aNames) );
+
+ sal_Int32 const nRT = PropertyAttribute::READONLY | PropertyAttribute::TRANSIENT;
+
+ // sdb.RowSet Properties
+ registerMayBeVoidProperty(PROPERTY_ACTIVE_CONNECTION,PROPERTY_ID_ACTIVE_CONNECTION, PropertyAttribute::MAYBEVOID|PropertyAttribute::READONLY, &rParent.m_aActiveConnection, cppu::UnoType<XConnection>::get());
+ registerProperty(PROPERTY_RESULTSETCONCURRENCY, PROPERTY_ID_RESULTSETCONCURRENCY, PropertyAttribute::READONLY, &m_nResultSetConcurrency,::cppu::UnoType<sal_Int32>::get());
+ registerProperty(PROPERTY_RESULTSETTYPE, PROPERTY_ID_RESULTSETTYPE, PropertyAttribute::READONLY, &m_nResultSetType, ::cppu::UnoType<sal_Int32>::get());
+ registerProperty(PROPERTY_FETCHDIRECTION, PROPERTY_ID_FETCHDIRECTION, PropertyAttribute::TRANSIENT, &m_nFetchDirection, ::cppu::UnoType<sal_Int32>::get());
+ registerProperty(PROPERTY_FETCHSIZE, PROPERTY_ID_FETCHSIZE, PropertyAttribute::TRANSIENT, &m_nFetchSize, ::cppu::UnoType<sal_Int32>::get());
+ registerProperty(PROPERTY_ISBOOKMARKABLE, PROPERTY_ID_ISBOOKMARKABLE, nRT, &m_bIsBookmarkable, cppu::UnoType<bool>::get());
+}
+
+ORowSetClone::~ORowSetClone()
+{
+}
+
+// css::XTypeProvider
+Sequence< Type > ORowSetClone::getTypes()
+{
+ return ::comphelper::concatSequences(OSubComponent::getTypes(),ORowSetBase::getTypes());
+}
+
+// css::XInterface
+Any ORowSetClone::queryInterface( const Type & rType )
+{
+ Any aRet = ORowSetBase::queryInterface(rType);
+ if(!aRet.hasValue())
+ aRet = OSubComponent::queryInterface(rType);
+ return aRet;
+}
+
+void ORowSetClone::acquire() noexcept
+{
+ OSubComponent::acquire();
+}
+
+void ORowSetClone::release() noexcept
+{
+ OSubComponent::release();
+}
+
+// XServiceInfo
+OUString ORowSetClone::getImplementationName( )
+{
+ return "com.sun.star.sdb.ORowSetClone";
+}
+
+sal_Bool ORowSetClone::supportsService( const OUString& _rServiceName )
+{
+ return cppu::supportsService(this, _rServiceName);
+}
+
+Sequence< OUString > ORowSetClone::getSupportedServiceNames( )
+{
+ return { SERVICE_SDBC_RESULTSET, SERVICE_SDB_RESULTSET };
+}
+
+// OComponentHelper
+void ORowSetClone::disposing()
+{
+ MutexGuard aGuard( m_aMutex );
+ ORowSetBase::disposing();
+
+ m_pParent = nullptr;
+ m_pMutex = &m_aMutex; // this must be done here because someone could hold a ref to us and try to do something
+ OSubComponent::disposing();
+}
+
+// XCloseable
+void ORowSetClone::close()
+{
+ {
+ MutexGuard aGuard( m_aMutex );
+ if (OComponentHelper::rBHelper.bDisposed)
+ throw DisposedException();
+ }
+ dispose();
+}
+
+// comphelper::OPropertyArrayUsageHelper
+::cppu::IPropertyArrayHelper* ORowSetClone::createArrayHelper( ) const
+{
+ Sequence< Property > aProps;
+ describeProperties(aProps);
+ return new ::cppu::OPropertyArrayHelper(aProps);
+}
+
+// cppu::OPropertySetHelper
+::cppu::IPropertyArrayHelper& SAL_CALL ORowSetClone::getInfoHelper()
+{
+ return *::comphelper::OPropertyArrayUsageHelper<ORowSetClone>::getArrayHelper();
+}
+
+const Sequence< sal_Int8 > & ORowSetClone::getUnoTunnelId()
+{
+ static const comphelper::UnoIdInit implId;
+ return implId.getSeq();
+}
+
+// css::XUnoTunnel
+sal_Int64 SAL_CALL ORowSetClone::getSomething( const Sequence< sal_Int8 >& rId )
+{
+ return comphelper::getSomethingImpl(rId, this);
+}
+
+void SAL_CALL ORowSetClone::setFastPropertyValue_NoBroadcast(sal_Int32 nHandle,const Any& rValue)
+{
+ if ( nHandle == PROPERTY_ID_FETCHSIZE )
+ {
+ if ( m_pParent )
+ m_pParent->setFastPropertyValue_NoBroadcast( nHandle, rValue );
+ }
+
+ OPropertyStateContainer::setFastPropertyValue_NoBroadcast(nHandle,rValue);
+}
+
+void ORowSetClone::doCancelModification( )
+{
+}
+
+bool ORowSetClone::isModification( )
+{
+ return false;
+}
+
+bool ORowSetClone::isModified( )
+{
+ return false;
+}
+
+bool ORowSetClone::isNew( )
+{
+ return false;
+}
+
+void SAL_CALL ORowSetClone::execute( )
+{
+ throwFunctionNotSupportedSQLException( "RowSetClone::XRowSet::execute", *this );
+}
+
+void SAL_CALL ORowSetClone::addRowSetListener( const Reference< XRowSetListener >& )
+{
+ throwFunctionNotSupportedRuntimeException( "RowSetClone::XRowSet", *this );
+}
+
+void SAL_CALL ORowSetClone::removeRowSetListener( const Reference< XRowSetListener >& )
+{
+ throwFunctionNotSupportedRuntimeException( "RowSetClone::XRowSet", *this );
+}
+
+} // dbaccess
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/api/RowSet.hxx b/dbaccess/source/core/api/RowSet.hxx
new file mode 100644
index 000000000..afe49a923
--- /dev/null
+++ b/dbaccess/source/core/api/RowSet.hxx
@@ -0,0 +1,527 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <sal/config.h>
+
+#include <atomic>
+#include <cstddef>
+
+#include <apitools.hxx>
+#include "RowSetBase.hxx"
+
+#include <com/sun/star/sdbc/XPreparedStatement.hpp>
+#include <com/sun/star/sdbc/XConnection.hpp>
+#include <com/sun/star/sdb/XSingleSelectQueryComposer.hpp>
+#include <com/sun/star/sdb/XResultSetAccess.hpp>
+#include <com/sun/star/sdbc/XRowSetListener.hpp>
+#include <com/sun/star/sdbc/XRowUpdate.hpp>
+#include <com/sun/star/sdbc/XResultSetUpdate.hpp>
+#include <com/sun/star/sdbc/XParameters.hpp>
+#include <com/sun/star/sdb/XRowSetApproveBroadcaster.hpp>
+#include <com/sun/star/util/XCancellable.hpp>
+#include <com/sun/star/sdbcx/XDeleteRows.hpp>
+#include <com/sun/star/sdb/XCompletedExecution.hpp>
+#include <com/sun/star/sdb/XParametersSupplier.hpp>
+#include <com/sun/star/sdb/XRowsChangeBroadcaster.hpp>
+
+#include <cppuhelper/compbase12.hxx>
+#include <cppuhelper/basemutex.hxx>
+#include <comphelper/interfacecontainer3.hxx>
+#include <connectivity/paramwrapper.hxx>
+#include <connectivity/FValue.hxx>
+#include <connectivity/warningscontainer.hxx>
+
+namespace dbaccess
+{
+ typedef ::cppu::WeakAggComponentImplHelper12 < css::sdb::XResultSetAccess
+ , css::sdb::XRowSetApproveBroadcaster
+ , css::sdb::XRowsChangeBroadcaster
+ , css::sdbcx::XDeleteRows
+ , css::sdbc::XParameters
+ , css::lang::XEventListener
+ , css::sdbc::XResultSetUpdate
+ , css::sdbc::XRowUpdate
+ , css::util::XCancellable
+ , css::sdb::XCompletedExecution
+ , css::sdb::XParametersSupplier
+ , css::sdbc::XWarningsSupplier
+ > ORowSet_BASE1;
+
+ class OTableContainer;
+ class ORowSet final : public cppu::BaseMutex
+ , public ORowSet_BASE1
+ , public ORowSetBase
+ , public ::comphelper::OPropertyArrayUsageHelper<ORowSet>
+ {
+ friend class ORowSetClone;
+
+ css::uno::Reference< css::sdbc::XConnection > m_xOldConnection;
+ css::uno::Reference< css::sdbc::XConnection > m_xActiveConnection;
+ css::uno::Any m_aActiveConnection;
+ css::uno::Reference< css::container::XNameAccess > m_xTypeMap;
+ css::uno::Any m_aTypeMap;
+ css::uno::Reference< css::sdbc::XPreparedStatement > m_xStatement;
+ css::uno::Reference< css::sdb::XSingleSelectQueryComposer > m_xComposer;
+ css::uno::Reference< css::container::XNameAccess > m_xColumns; // the columns from a table or query
+
+ connectivity::OWeakRefArray m_aClones;
+ /** our parameters as XPropertySet instances and ORowSetValue instances
+ */
+ ::dbtools::param::ParametersContainerRef m_pParameters;
+ /** our parameters values, used when we do not yet have a parameters container
+ (since we have not been executed, yet)
+ */
+ rtl::Reference<ORowSetValueVector> m_aPrematureParamValues;
+ rtl::Reference<ORowSetValueVector> m_aParameterValueForCache;
+ std::vector<bool> m_aParametersSet;
+ std::vector<bool> m_aReadOnlyDataColumns;
+
+ ::comphelper::OInterfaceContainerHelper3<css::sdbc::XRowSetListener> m_aRowsetListeners;
+ ::comphelper::OInterfaceContainerHelper3<css::sdb::XRowSetApproveListener> m_aApproveListeners;
+ ::comphelper::OInterfaceContainerHelper3<css::sdb::XRowsChangeListener> m_aRowsChangeListener;
+
+ ::dbtools::WarningsContainer m_aWarnings;
+
+ // no Reference! see OCollection::acquire
+ std::unique_ptr<OTableContainer> m_xTables;
+
+ OUString m_aCommand;
+ OUString m_aDataSourceName;
+ OUString m_aURL;
+ OUString m_aUser;
+ OUString m_aPassword;
+ OUString m_aFilter;
+ OUString m_aHavingClause;
+ OUString m_aGroupBy;
+ OUString m_aOrder;
+ OUString m_aActiveCommand;
+ OUString m_aUpdateCatalogName; // is set by a query
+ OUString m_aUpdateSchemaName; // is set by a query
+ OUString m_aUpdateTableName; // is set by a query
+ OUString m_sErrorString;
+
+ sal_Int32 m_nFetchDirection;
+ sal_Int32 m_nFetchSize;
+ sal_Int32 m_nMaxFieldSize;
+ sal_Int32 m_nMaxRows;
+ sal_Int32 m_nQueryTimeOut;
+ sal_Int32 m_nCommandType;
+ sal_Int32 m_nTransactionIsolation;
+ sal_Int32 m_nPrivileges;
+ sal_Int32 m_nLastKnownRowCount;
+ std::atomic<std::size_t> m_nInAppend;
+ bool m_bInsertingRow;
+ bool m_bLastKnownRowCountFinal;
+ bool m_bUseEscapeProcessing ;
+ bool m_bApplyFilter ;
+ bool m_bCommandFacetsDirty; // any of the facets which define the active command is dirty
+ bool m_bParametersDirty; // parameters changed since execute
+ bool m_bModified ;
+ bool m_bRebuildConnOnExecute ;
+ bool m_bIsBookmarkable ;
+ bool m_bNew ;
+ bool m_bCanUpdateInsertedRows;
+ bool m_bOwnConnection;
+ bool m_bPropChangeNotifyEnabled;
+
+ /** builds m_aActiveCommand from our settings
+
+ @return
+ whether we should use escape processing before executing the actual command. This is determined
+ from our own EscapeProcessing property, and possibly overruled by the respective property
+ of a query we're based on.
+ */
+ bool impl_buildActiveCommand_throw();
+
+ /** initializes our query composer, and everything which has to do with it
+
+ If we don't use escape processing, then we don't have a composer, and everything
+ related to it. Nonetheless, _out_rCommandToExecute and the return value are properly
+ initialized.
+
+ @param _out_rCommandToExecute
+ The command which is to be executed, according to the current settings -
+ it is built from our active command plus our current filter/order criterions.
+
+ @precond
+ m_xActiveConnection points to a valid SDB-level connection
+
+ @throws css::sdb::SQLException
+ if a database-related error occurred
+
+ @throws css::uno::RuntimeException
+ if any of the components involved throws a css::uno::RuntimeException
+ */
+ void impl_initComposer_throw( OUString& _out_rCommandToExecute );
+
+ /** returns the table container of our active connection
+
+ If our connection is able to provide a tables container, this one is returned.
+ Else, if m_pTables is not <NULL/>, this one will returned.
+ Else, m_pTables will be constructed and returned.
+
+ @precond m_xActiveConnection is not <NULL/>
+ @throws css::sdbc::SQLException
+ if retrieving or constructing the tables container goes wrong
+
+ @see impl_resetTables_nothrow
+ */
+ css::uno::Reference< css::container::XNameAccess >
+ impl_getTables_throw();
+
+ /** cleans up m_pTables, and resets it to <NULL/>
+ */
+ void impl_resetTables_nothrow();
+
+ /** prepares and executes our command
+ */
+ css::uno::Reference< css::sdbc::XResultSet >
+ impl_prepareAndExecute_throw();
+ void impl_ensureStatement_throw();
+
+ /// @throws css::sdbc::SQLException
+ /// @throws css::uno::RuntimeException
+ css::uno::Reference< css::sdbc::XConnection > calcConnection(const css::uno::Reference< css::task::XInteractionHandler >& _rxHandler);
+ // free clones and ParseTree. Plus, if _bComplete is <TRUE/>, *all* other associated resources
+ void freeResources( bool _bComplete );
+
+ /// informs the clones (and ourself) that we are going to delete a record with a given bookmark
+ void notifyRowSetAndClonesRowDelete( const css::uno::Any& _rBookmark );
+
+ /// inform the clones (and ourself) that we have deleted a record with a given bookmark
+ void notifyRowSetAndClonesRowDeleted( const css::uno::Any& _rBookmark, sal_Int32 _nPos );
+
+ void checkUpdateIterator();
+ const connectivity::ORowSetValue& getInsertValue(sal_Int32 columnIndex);
+ void setParameter(sal_Int32 parameterIndex, const connectivity::ORowSetValue& x);
+ // resizes the parameter vector if necessary
+ ::connectivity::ORowSetValue& getParameterStorage( sal_Int32 parameterIndex );
+
+ void updateValue(sal_Int32 columnIndex,const connectivity::ORowSetValue& x);
+ void checkUpdateConditions(sal_Int32 columnIndex);
+ void impl_rebuild_throw(::osl::ResettableMutexGuard& _rGuard);
+ // set all data columns to writeable
+ void impl_setDataColumnsWriteable_throw();
+ // restore the old state of the data column read-only state
+ void impl_restoreDataColumnsWriteable_throw();
+
+ virtual void SAL_CALL setFastPropertyValue_NoBroadcast(sal_Int32 nHandle,const css::uno::Any& rValue) override;
+ virtual void SAL_CALL getFastPropertyValue(css::uno::Any& rValue,sal_Int32 nHandle) const override;
+ virtual void getPropertyDefaultByHandle( sal_Int32 _nHandle, css::uno::Any& _rDefault ) const override;
+
+ virtual void fireRowcount() override;
+ void notifyAllListenersRowBeforeChange(::osl::ResettableMutexGuard& _rGuard,const css::sdb::RowChangeEvent &rEvt);
+ void notifyAllListenersRowChanged(::osl::ResettableMutexGuard& _rGuard,const css::sdb::RowsChangeEvent& rEvt);
+ virtual bool notifyAllListenersCursorBeforeMove(::osl::ResettableMutexGuard& _rGuard) override;
+ virtual void notifyAllListenersCursorMoved(::osl::ResettableMutexGuard& _rGuard) override;
+ // notify all that rowset changed
+ void notifyAllListeners(::osl::ResettableMutexGuard& _rGuard);
+
+ virtual void doCancelModification( ) override;
+ virtual bool isModification( ) override;
+ virtual bool isModified( ) override;
+ virtual bool isNew( ) override;
+ virtual bool isPropertyChangeNotificationEnabled() const override;
+
+ virtual ~ORowSet() override;
+
+ public:
+ explicit ORowSet(const css::uno::Reference<css::uno::XComponentContext>&);
+
+ // css::lang::XTypeProvider
+ virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes() override;
+ virtual css::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId() override;
+
+ // css::uno::XInterface
+ virtual css::uno::Any SAL_CALL queryInterface( const css::uno::Type & rType ) override;
+ virtual void SAL_CALL acquire() noexcept override;
+ virtual void SAL_CALL release() noexcept override;
+
+ // css::lang::XUnoTunnel
+ virtual sal_Int64 SAL_CALL getSomething( const css::uno::Sequence< sal_Int8 >& aIdentifier ) override;
+ static const css::uno::Sequence< sal_Int8 > & getUnoTunnelId();
+
+ // css::uno::XAggregation
+ virtual css::uno::Any SAL_CALL queryAggregation( const css::uno::Type& aType ) override;
+
+ // css::lang::XServiceInfo
+ virtual OUString SAL_CALL getImplementationName( ) override;
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override;
+
+ // OComponentHelper
+ virtual void SAL_CALL disposing() override;
+
+ // css::lang::XEventListener
+ virtual void SAL_CALL disposing( const css::lang::EventObject& Source ) override;
+
+ // css::sdbc::XCloseable
+ virtual void SAL_CALL close( ) override;
+
+ // comphelper::OPropertyArrayUsageHelper
+ virtual ::cppu::IPropertyArrayHelper* createArrayHelper( ) const override;
+
+ // cppu::OPropertySetHelper
+ virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper() override;
+
+ // css::sdbc::XResultSet
+ virtual void SAL_CALL refreshRow( ) override;
+
+ // XCompletedExecution
+ virtual void SAL_CALL executeWithCompletion( const css::uno::Reference< css::task::XInteractionHandler >& handler ) override;
+
+ // XParametersSupplier
+ virtual css::uno::Reference< css::container::XIndexAccess > SAL_CALL getParameters( ) override;
+
+ // css::sdbc::XRow
+ virtual sal_Bool SAL_CALL wasNull( ) override;
+ virtual OUString SAL_CALL getString( sal_Int32 columnIndex ) override;
+ virtual sal_Bool SAL_CALL getBoolean( sal_Int32 columnIndex ) override;
+ virtual sal_Int8 SAL_CALL getByte( sal_Int32 columnIndex ) override;
+ virtual sal_Int16 SAL_CALL getShort( sal_Int32 columnIndex ) override;
+ virtual sal_Int32 SAL_CALL getInt( sal_Int32 columnIndex ) override;
+ virtual sal_Int64 SAL_CALL getLong( sal_Int32 columnIndex ) override;
+ virtual float SAL_CALL getFloat( sal_Int32 columnIndex ) override;
+ virtual double SAL_CALL getDouble( sal_Int32 columnIndex ) override;
+ virtual css::uno::Sequence< sal_Int8 > SAL_CALL getBytes( sal_Int32 columnIndex ) override;
+ virtual css::util::Date SAL_CALL getDate( sal_Int32 columnIndex ) override;
+ virtual css::util::Time SAL_CALL getTime( sal_Int32 columnIndex ) override;
+ virtual css::util::DateTime SAL_CALL getTimestamp( sal_Int32 columnIndex ) override;
+ virtual css::uno::Reference< css::io::XInputStream > SAL_CALL getBinaryStream( sal_Int32 columnIndex ) override;
+ virtual css::uno::Reference< css::io::XInputStream > SAL_CALL getCharacterStream( sal_Int32 columnIndex ) override;
+ virtual css::uno::Any SAL_CALL getObject( sal_Int32 columnIndex, const css::uno::Reference< css::container::XNameAccess >& typeMap ) override;
+ virtual css::uno::Reference< css::sdbc::XRef > SAL_CALL getRef( sal_Int32 columnIndex ) override;
+ virtual css::uno::Reference< css::sdbc::XBlob > SAL_CALL getBlob( sal_Int32 columnIndex ) override;
+ virtual css::uno::Reference< css::sdbc::XClob > SAL_CALL getClob( sal_Int32 columnIndex ) override;
+ virtual css::uno::Reference< css::sdbc::XArray > SAL_CALL getArray( sal_Int32 columnIndex ) override;
+
+ // css::sdbc::XRowUpdate
+ virtual void SAL_CALL updateNull( sal_Int32 columnIndex ) override;
+ virtual void SAL_CALL updateBoolean( sal_Int32 columnIndex, sal_Bool x ) override;
+ virtual void SAL_CALL updateByte( sal_Int32 columnIndex, sal_Int8 x ) override;
+ virtual void SAL_CALL updateShort( sal_Int32 columnIndex, sal_Int16 x ) override;
+ virtual void SAL_CALL updateInt( sal_Int32 columnIndex, sal_Int32 x ) override;
+ virtual void SAL_CALL updateLong( sal_Int32 columnIndex, sal_Int64 x ) override;
+ virtual void SAL_CALL updateFloat( sal_Int32 columnIndex, float x ) override;
+ virtual void SAL_CALL updateDouble( sal_Int32 columnIndex, double x ) override;
+ virtual void SAL_CALL updateString( sal_Int32 columnIndex, const OUString& x ) override;
+ virtual void SAL_CALL updateBytes( sal_Int32 columnIndex, const css::uno::Sequence< sal_Int8 >& x ) override;
+ virtual void SAL_CALL updateDate( sal_Int32 columnIndex, const css::util::Date& x ) override;
+ virtual void SAL_CALL updateTime( sal_Int32 columnIndex, const css::util::Time& x ) override;
+ virtual void SAL_CALL updateTimestamp( sal_Int32 columnIndex, const css::util::DateTime& x ) override;
+ virtual void SAL_CALL updateBinaryStream( sal_Int32 columnIndex, const css::uno::Reference< css::io::XInputStream >& x, sal_Int32 length ) override;
+ virtual void SAL_CALL updateCharacterStream( sal_Int32 columnIndex, const css::uno::Reference< css::io::XInputStream >& x, sal_Int32 length ) override;
+ virtual void SAL_CALL updateObject( sal_Int32 columnIndex, const css::uno::Any& x ) override;
+ virtual void SAL_CALL updateNumericObject( sal_Int32 columnIndex, const css::uno::Any& x, sal_Int32 scale ) override;
+
+ // css::sdbc::XResultSetUpdate
+ virtual void SAL_CALL insertRow( ) override;
+ virtual void SAL_CALL updateRow( ) override;
+ virtual void SAL_CALL deleteRow( ) override;
+ virtual void SAL_CALL cancelRowUpdates( ) override;
+ virtual void SAL_CALL moveToInsertRow( ) override;
+ virtual void SAL_CALL moveToCurrentRow( ) override;
+
+ // css::sdbc::XRowSet
+ virtual void SAL_CALL execute( ) override;
+ virtual void SAL_CALL addRowSetListener( const css::uno::Reference< css::sdbc::XRowSetListener >& listener ) override;
+ virtual void SAL_CALL removeRowSetListener( const css::uno::Reference< css::sdbc::XRowSetListener >& listener ) override;
+
+ // css::sdb::XRowSetApproveBroadcaster
+ virtual void SAL_CALL addRowSetApproveListener( const css::uno::Reference< css::sdb::XRowSetApproveListener >& listener ) override;
+ virtual void SAL_CALL removeRowSetApproveListener( const css::uno::Reference< css::sdb::XRowSetApproveListener >& listener ) override;
+
+ // css::sdb::XRowsChangeBroadcaster
+ virtual void SAL_CALL addRowsChangeListener( const css::uno::Reference< css::sdb::XRowsChangeListener >& listener ) override;
+ virtual void SAL_CALL removeRowsChangeListener( const css::uno::Reference< css::sdb::XRowsChangeListener >& listener ) override;
+
+ // css::sdb::XResultSetAccess
+ virtual css::uno::Reference< css::sdbc::XResultSet > SAL_CALL createResultSet( ) override;
+
+ // css::util::XCancellable
+ virtual void SAL_CALL cancel( ) override;
+
+ // css::sdbcx::XDeleteRows
+ virtual css::uno::Sequence< sal_Int32 > SAL_CALL deleteRows( const css::uno::Sequence< css::uno::Any >& rows ) override;
+
+ // XParameters
+ virtual void SAL_CALL setNull( sal_Int32 parameterIndex, sal_Int32 sqlType ) override;
+ virtual void SAL_CALL setObjectNull( sal_Int32 parameterIndex, sal_Int32 sqlType, const OUString& typeName ) override;
+ virtual void SAL_CALL setBoolean( sal_Int32 parameterIndex, sal_Bool x ) override;
+ virtual void SAL_CALL setByte( sal_Int32 parameterIndex, sal_Int8 x ) override;
+ virtual void SAL_CALL setShort( sal_Int32 parameterIndex, sal_Int16 x ) override;
+ virtual void SAL_CALL setInt( sal_Int32 parameterIndex, sal_Int32 x ) override;
+ virtual void SAL_CALL setLong( sal_Int32 parameterIndex, sal_Int64 x ) override;
+ virtual void SAL_CALL setFloat( sal_Int32 parameterIndex, float x ) override;
+ virtual void SAL_CALL setDouble( sal_Int32 parameterIndex, double x ) override;
+ virtual void SAL_CALL setString( sal_Int32 parameterIndex, const OUString& x ) override;
+ virtual void SAL_CALL setBytes( sal_Int32 parameterIndex, const css::uno::Sequence< sal_Int8 >& x ) override;
+ virtual void SAL_CALL setDate( sal_Int32 parameterIndex, const css::util::Date& x ) override;
+ virtual void SAL_CALL setTime( sal_Int32 parameterIndex, const css::util::Time& x ) override;
+ virtual void SAL_CALL setTimestamp( sal_Int32 parameterIndex, const css::util::DateTime& x ) override;
+ virtual void SAL_CALL setBinaryStream( sal_Int32 parameterIndex, const css::uno::Reference< css::io::XInputStream >& x, sal_Int32 length ) override;
+ virtual void SAL_CALL setCharacterStream( sal_Int32 parameterIndex, const css::uno::Reference< css::io::XInputStream >& x, sal_Int32 length ) override;
+ virtual void SAL_CALL setObject( sal_Int32 parameterIndex, const css::uno::Any& x ) override;
+ virtual void SAL_CALL setObjectWithInfo( sal_Int32 parameterIndex, const css::uno::Any& x, sal_Int32 targetSqlType, sal_Int32 scale ) override;
+ virtual void SAL_CALL setRef( sal_Int32 parameterIndex, const css::uno::Reference< css::sdbc::XRef >& x ) override;
+ virtual void SAL_CALL setBlob( sal_Int32 parameterIndex, const css::uno::Reference< css::sdbc::XBlob >& x ) override;
+ virtual void SAL_CALL setClob( sal_Int32 parameterIndex, const css::uno::Reference< css::sdbc::XClob >& x ) override;
+ virtual void SAL_CALL setArray( sal_Int32 parameterIndex, const css::uno::Reference< css::sdbc::XArray >& x ) override;
+ virtual void SAL_CALL clearParameters( ) override;
+
+ // XWarningsSupplier
+ virtual css::uno::Any SAL_CALL getWarnings( ) override;
+ virtual void SAL_CALL clearWarnings( ) override;
+
+ /** implement the <method>execute</method>, without calling the approve listeners and without building a new
+ connection
+ @param _rClearForNotification mutex to clear before doing the final notifications
+ */
+ void execute_NoApprove_NoNewConn(::osl::ResettableMutexGuard& _rClearForNotification);
+
+ /** call the RowSetApproveListeners<p/>
+ @throws css::sdb::RowSetVetoException if one of the listeners vetoed
+ @throws css::uno::RuntimeException
+ */
+ void approveExecution();
+
+ /// set m_xActiveConnection, fire a PropertyChangeEvent if necessary, do the event listener handling etc
+ void setActiveConnection( css::uno::Reference< css::sdbc::XConnection > const & _rxNewConn, bool _bFireEvent = true );
+
+ void implCancelRowUpdates( bool _bNotifyModified );
+
+ /** sets the given result set type/concurrency at the given statement, while respecting
+ possibly related data source settings
+ */
+ void setStatementResultSetType(
+ const css::uno::Reference< css::beans::XPropertySet >& _rxStatement,
+ sal_Int32 _nDesiredResultSetType,
+ sal_Int32 _nDesiredResultSetConcurrency
+ );
+
+ /** initializes a given RowSet column with the ColumnSettings (width, format, hidden, etc.) from a
+ template column.
+
+ If the template column supports any of the known column settings, they're plain copied. If not,
+ the template column is examined for a TableName and Name property, and the table column described
+ by those is used to find and copy the column settings.
+ */
+ void impl_initializeColumnSettings_nothrow(
+ const css::uno::Reference< css::beans::XPropertySet >& _rxTemplateColumn,
+ const css::uno::Reference< css::beans::XPropertySet >& _rxRowSetColumn
+ );
+
+ /** initializes our parameters container (m_pParameters) according to the parameter columns as
+ obtained from our composer
+ */
+ void impl_initParametersContainer_nothrow();
+ /** disposes our parameters container
+ */
+ void impl_disposeParametersContainer_nothrow();
+
+ using ORowSetBase::getFastPropertyValue;
+ using ORowSetBase::firePropertyChange;
+ using ORowSetBase::doCancelModification;
+ using ORowSetBase::isModification;
+ using ORowSetBase::isModified;
+ using ORowSetBase::isNew;
+ };
+
+
+ // ORowSetClone
+
+ class ORowSetClone : public cppu::BaseMutex
+ ,public OSubComponent
+ ,public ORowSetBase
+ ,public ::comphelper::OPropertyArrayUsageHelper < ORowSetClone >
+ {
+ ORowSet* m_pParent;
+ sal_Int32 m_nFetchDirection;
+ sal_Int32 m_nFetchSize;
+ bool m_bIsBookmarkable;
+
+ protected:
+ // the clone can not insert anything
+ virtual void doCancelModification( ) override;
+ virtual bool isModification( ) override;
+ virtual bool isModified( ) override;
+ virtual bool isNew( ) override;
+
+ virtual void SAL_CALL setFastPropertyValue_NoBroadcast(sal_Int32 nHandle,const css::uno::Any& rValue) override;
+ public:
+ ORowSetClone( const css::uno::Reference<css::uno::XComponentContext>& _rContext, ORowSet& rParent, ::osl::Mutex* _pMutex );
+ virtual ~ORowSetClone() override;
+
+ // css::lang::XTypeProvider
+ virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes() override;
+ virtual css::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId() override
+ {
+ return css::uno::Sequence<sal_Int8>();
+ }
+
+ // css::uno::XInterface
+ virtual css::uno::Any SAL_CALL queryInterface( const css::uno::Type & rType ) override;
+ virtual void SAL_CALL acquire() noexcept override;
+ virtual void SAL_CALL release() noexcept override;
+
+ // css::lang::XServiceInfo
+ virtual OUString SAL_CALL getImplementationName( ) override;
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override;
+
+ // css::lang::XUnoTunnel
+ virtual sal_Int64 SAL_CALL getSomething( const css::uno::Sequence< sal_Int8 >& aIdentifier ) override;
+ static const css::uno::Sequence< sal_Int8 > & getUnoTunnelId();
+
+ // OComponentHelper
+ virtual void SAL_CALL disposing() override;
+
+ // css::sdbc::XCloseable
+ virtual void SAL_CALL close( ) override;
+
+ // css::beans::XPropertySet
+ virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo( ) override
+ {
+ return ::cppu::OPropertySetHelper::createPropertySetInfo(getInfoHelper());
+ }
+
+ // css::sdbc::XRowSet
+ virtual void SAL_CALL execute( ) override;
+ virtual void SAL_CALL addRowSetListener( const css::uno::Reference< css::sdbc::XRowSetListener >& listener ) override;
+ virtual void SAL_CALL removeRowSetListener( const css::uno::Reference< css::sdbc::XRowSetListener >& listener ) override;
+
+ // comphelper::OPropertyArrayUsageHelper
+ virtual ::cppu::IPropertyArrayHelper* createArrayHelper( ) const override;
+
+ // cppu::OPropertySetHelper
+ virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper() override;
+
+ protected:
+ using ORowSetBase::doCancelModification;
+ using ORowSetBase::isModification;
+ using ORowSetBase::isModified;
+ using ORowSetBase::isNew;
+ using ORowSetBase::rowDeleted;
+ };
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/api/RowSetBase.cxx b/dbaccess/source/core/api/RowSetBase.cxx
new file mode 100644
index 000000000..46e612271
--- /dev/null
+++ b/dbaccess/source/core/api/RowSetBase.cxx
@@ -0,0 +1,1438 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "RowSetBase.hxx"
+#include "CRowSetDataColumn.hxx"
+#include <connectivity/sdbcx/VCollection.hxx>
+#include "RowSetCache.hxx"
+#include <stringconstants.hxx>
+#include <sal/log.hxx>
+#include <core_resource.hxx>
+#include <strings.hrc>
+#include <strings.hxx>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/sdbcx/CompareBookmark.hpp>
+#include <com/sun/star/sdbc/ResultSetConcurrency.hpp>
+#include <com/sun/star/sdbc/ResultSetType.hpp>
+#include <comphelper/sequence.hxx>
+#include <comphelper/seqstream.hxx>
+#include <connectivity/dbexception.hxx>
+#include <o3tl/safeint.hxx>
+#include <tools/diagnose_ex.h>
+
+using namespace dbaccess;
+using namespace connectivity;
+using namespace connectivity::sdbcx;
+using namespace comphelper;
+using namespace dbtools;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::sdb;
+using namespace ::com::sun::star::sdbcx;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::util;
+using namespace ::cppu;
+using namespace ::osl;
+
+namespace dbaccess
+{
+
+// OEmptyCollection
+class OEmptyCollection : public sdbcx::OCollection
+{
+protected:
+ virtual void impl_refresh() override;
+ virtual connectivity::sdbcx::ObjectType createObject(const OUString& _rName) override;
+public:
+ OEmptyCollection(::cppu::OWeakObject& _rParent,::osl::Mutex& _rMutex) : OCollection(_rParent, true, _rMutex, std::vector< OUString>()){}
+};
+
+void OEmptyCollection::impl_refresh()
+{
+}
+
+connectivity::sdbcx::ObjectType OEmptyCollection::createObject(const OUString& /*_rName*/)
+{
+ return connectivity::sdbcx::ObjectType();
+}
+
+// ORowSetBase
+
+ORowSetBase::ORowSetBase( const Reference<XComponentContext>& _rContext, ::cppu::OBroadcastHelper& _rBHelper, ::osl::Mutex* _pMutex )
+ :OPropertyStateContainer(_rBHelper)
+ ,m_pMutex(_pMutex)
+ ,m_pMySelf(nullptr)
+ ,m_rBHelper(_rBHelper)
+ ,m_aContext( _rContext )
+ ,m_nLastColumnIndex(-1)
+ ,m_nDeletedPosition(-1)
+ ,m_nResultSetType( ResultSetType::FORWARD_ONLY )
+ ,m_nResultSetConcurrency( ResultSetConcurrency::READ_ONLY )
+ ,m_bClone(false)
+ ,m_bIgnoreResult(false)
+ ,m_bBeforeFirst(true) // changed from sal_False
+ ,m_bAfterLast(false)
+ ,m_bIsInsertRow(false)
+{
+ sal_Int32 nRBT = PropertyAttribute::READONLY | PropertyAttribute::BOUND | PropertyAttribute::TRANSIENT;
+
+ registerPropertyNoMember( PROPERTY_ROWCOUNT, PROPERTY_ID_ROWCOUNT, nRBT, cppu::UnoType<sal_Int32>::get(), css::uno::Any(sal_Int32(0)) );
+ registerPropertyNoMember( PROPERTY_ISROWCOUNTFINAL, PROPERTY_ID_ISROWCOUNTFINAL, nRBT, cppu::UnoType<bool>::get(), css::uno::Any(false) );
+}
+
+ORowSetBase::~ORowSetBase()
+{
+ if(m_pColumns)
+ {
+ TDataColumns().swap(m_aDataColumns);
+ m_pColumns->acquire();
+ m_pColumns->disposing();
+ }
+}
+
+// css::lang::XTypeProvider
+Sequence< Type > ORowSetBase::getTypes()
+{
+ return ::comphelper::concatSequences(ORowSetBase_BASE::getTypes(),OPropertyStateContainer::getTypes());
+}
+
+// css::uno::XInterface
+Any ORowSetBase::queryInterface( const Type & rType )
+{
+ Any aRet = ORowSetBase_BASE::queryInterface(rType);
+ if(!aRet.hasValue())
+ aRet = OPropertyStateContainer::queryInterface(rType);
+ return aRet;
+}
+
+void SAL_CALL ORowSetBase::getFastPropertyValue(Any& rValue,sal_Int32 nHandle) const
+{
+ if(m_pCache)
+ {
+ switch(nHandle)
+ {
+ case PROPERTY_ID_ROWCOUNT:
+ rValue <<= impl_getRowCount();
+ break;
+ case PROPERTY_ID_ISROWCOUNTFINAL:
+ rValue <<= m_pCache->m_bRowCountFinal;
+ break;
+ default:
+ OPropertyStateContainer::getFastPropertyValue(rValue,nHandle);
+ }
+ }
+ else
+ OPropertyStateContainer::getFastPropertyValue(rValue,nHandle);
+}
+
+// OComponentHelper
+void SAL_CALL ORowSetBase::disposing()
+{
+ MutexGuard aGuard(*m_pMutex);
+
+ if ( m_pColumns )
+ {
+ TDataColumns().swap(m_aDataColumns);
+ m_pColumns->disposing();
+ }
+ if ( m_pCache )
+ {
+ m_pCache->deregisterOldRow(m_aOldRow);
+ m_pCache->deleteIterator(this);
+ }
+ m_pCache = nullptr;
+}
+
+// comphelper::OPropertyArrayUsageHelper
+::cppu::IPropertyArrayHelper* ORowSetBase::createArrayHelper( ) const
+{
+ Sequence< Property > aProps;
+ describeProperties(aProps);
+ return new ::cppu::OPropertyArrayHelper(aProps);
+}
+
+// cppu::OPropertySetHelper
+::cppu::IPropertyArrayHelper& SAL_CALL ORowSetBase::getInfoHelper()
+{
+ return *getArrayHelper();
+}
+
+// XRow
+sal_Bool SAL_CALL ORowSetBase::wasNull( )
+{
+ ::osl::MutexGuard aGuard( *m_pMutex );
+ checkCache();
+ return !((m_nLastColumnIndex != -1) && !m_aCurrentRow.isNull() && m_aCurrentRow != m_pCache->getEnd() && m_aCurrentRow->is())
+ || (**m_aCurrentRow)[m_nLastColumnIndex].isNull();
+}
+
+const ORowSetValue& ORowSetBase::getValue(sal_Int32 columnIndex)
+{
+ checkCache();
+ return impl_getValue(columnIndex);
+}
+
+const ORowSetValue& ORowSetBase::impl_getValue(sal_Int32 columnIndex)
+{
+ if ( m_bBeforeFirst || m_bAfterLast )
+ {
+ SAL_WARN("dbaccess", "ORowSetBase::getValue: Illegal call here (we're before first or after last)!");
+ ::dbtools::throwSQLException( DBA_RES( RID_STR_CURSOR_BEFORE_OR_AFTER ), StandardSQLState::INVALID_CURSOR_POSITION, *m_pMySelf );
+ }
+
+ if ( impl_rowDeleted() )
+ {
+ return m_aEmptyValue;
+ }
+
+ bool bValidCurrentRow = ( !m_aCurrentRow.isNull() && m_aCurrentRow != m_pCache->getEnd() && m_aCurrentRow->is() );
+ if ( !bValidCurrentRow )
+ {
+ // currentrow is null when the clone moves the window
+ positionCache( MOVE_NONE );
+ m_aCurrentRow = m_pCache->m_aMatrixIter;
+ m_bIsInsertRow = false;
+ OSL_ENSURE(!m_aCurrentRow.isNull(),"ORowSetBase::getValue: we don't stand on a valid row! Row is null.");
+
+ bValidCurrentRow = ( !m_aCurrentRow.isNull() && m_aCurrentRow != m_pCache->getEnd() && m_aCurrentRow->is() );
+ }
+
+ if ( bValidCurrentRow )
+ {
+#if OSL_DEBUG_LEVEL > 0
+ ORowSetMatrix::const_iterator aCacheEnd;
+ ORowSetMatrix::iterator aCurrentRow;
+ aCacheEnd = m_pCache->getEnd();
+ aCurrentRow = m_aCurrentRow;
+ ORowSetCacheMap::const_iterator aCacheIter = m_aCurrentRow.getIter();
+ ORowSetCacheIterator_Helper aHelper = aCacheIter->second;
+ ORowSetMatrix::const_iterator k = aHelper.aIterator;
+ for (; k != m_pCache->getEnd(); ++k)
+ {
+ ORowSetValueVector* pTemp = k->get();
+ OSL_ENSURE( pTemp != reinterpret_cast<void*>(0xfeeefeee),"HALT!" );
+ }
+ OSL_ENSURE(!m_aCurrentRow.isNull() && m_aCurrentRow < m_pCache->getEnd() && aCacheIter != m_pCache->m_aCacheIterators.end(),"Invalid iterator set for currentrow!");
+#endif
+ ORowSetRow rRow = *m_aCurrentRow;
+ bool bValidPosition = rRow.is() && o3tl::make_unsigned(columnIndex) < rRow->size();
+ if (!bValidPosition)
+ {
+ SAL_WARN("dbaccess", "ORowSetBase::getValue: Invalid size of vector!");
+ ::dbtools::throwSQLException( DBA_RES( RID_STR_CURSOR_BEFORE_OR_AFTER ), StandardSQLState::INVALID_CURSOR_POSITION, *m_pMySelf );
+ }
+ m_nLastColumnIndex = columnIndex;
+ return (*rRow)[m_nLastColumnIndex];
+ }
+
+ // we should normally never reach this
+ return m_aEmptyValue;
+}
+
+OUString SAL_CALL ORowSetBase::getString( sal_Int32 columnIndex )
+{
+ ::osl::MutexGuard aGuard( *m_pMutex );
+ return getValue(columnIndex).getString();
+}
+
+sal_Bool SAL_CALL ORowSetBase::getBoolean( sal_Int32 columnIndex )
+{
+ ::osl::MutexGuard aGuard( *m_pMutex );
+ return getValue(columnIndex).getBool();
+}
+
+sal_Int8 SAL_CALL ORowSetBase::getByte( sal_Int32 columnIndex )
+{
+ ::osl::MutexGuard aGuard( *m_pMutex );
+ return getValue(columnIndex).getInt8();
+}
+
+sal_Int16 SAL_CALL ORowSetBase::getShort( sal_Int32 columnIndex )
+{
+ ::osl::MutexGuard aGuard( *m_pMutex );
+ return getValue(columnIndex).getInt16();
+}
+
+sal_Int32 SAL_CALL ORowSetBase::getInt( sal_Int32 columnIndex )
+{
+ ::osl::MutexGuard aGuard( *m_pMutex );
+ return getValue(columnIndex).getInt32();
+}
+
+sal_Int64 SAL_CALL ORowSetBase::getLong( sal_Int32 columnIndex )
+{
+ ::osl::MutexGuard aGuard( *m_pMutex );
+ return getValue(columnIndex).getLong();
+}
+
+float SAL_CALL ORowSetBase::getFloat( sal_Int32 columnIndex )
+{
+ ::osl::MutexGuard aGuard( *m_pMutex );
+ return getValue(columnIndex).getFloat();
+}
+
+double SAL_CALL ORowSetBase::getDouble( sal_Int32 columnIndex )
+{
+ ::osl::MutexGuard aGuard( *m_pMutex );
+ return getValue(columnIndex).getDouble();
+}
+
+Sequence< sal_Int8 > SAL_CALL ORowSetBase::getBytes( sal_Int32 columnIndex )
+{
+ ::osl::MutexGuard aGuard( *m_pMutex );
+ return getValue(columnIndex).getSequence();
+}
+
+css::util::Date SAL_CALL ORowSetBase::getDate( sal_Int32 columnIndex )
+{
+ ::osl::MutexGuard aGuard( *m_pMutex );
+ return getValue(columnIndex).getDate();
+}
+
+css::util::Time SAL_CALL ORowSetBase::getTime( sal_Int32 columnIndex )
+{
+ ::osl::MutexGuard aGuard( *m_pMutex );
+ return getValue(columnIndex).getTime();
+}
+
+css::util::DateTime SAL_CALL ORowSetBase::getTimestamp( sal_Int32 columnIndex )
+{
+ ::osl::MutexGuard aGuard( *m_pMutex );
+ return getValue(columnIndex).getDateTime();
+}
+
+Reference< css::io::XInputStream > SAL_CALL ORowSetBase::getBinaryStream( sal_Int32 columnIndex )
+{
+ ::osl::MutexGuard aGuard( *m_pMutex );
+ checkCache();
+
+ if ( m_bBeforeFirst || m_bAfterLast )
+ {
+ SAL_WARN("dbaccess", "ORowSetBase::getBinaryStream: Illegal call here (we're before first or after last)!");
+ ::dbtools::throwSQLException( DBA_RES( RID_STR_CURSOR_BEFORE_OR_AFTER ), StandardSQLState::INVALID_CURSOR_POSITION, *m_pMySelf );
+ }
+
+ if ( impl_rowDeleted() )
+ {
+ return nullptr;
+ }
+
+ bool bValidCurrentRow = ( !m_aCurrentRow.isNull() && m_aCurrentRow != m_pCache->getEnd() && m_aCurrentRow->is() );
+ if ( !bValidCurrentRow )
+ {
+ positionCache( MOVE_NONE );
+ m_aCurrentRow = m_pCache->m_aMatrixIter;
+ m_bIsInsertRow = false;
+ OSL_ENSURE(!m_aCurrentRow.isNull(),"ORowSetBase::getBinaryStream: we don't stand on a valid row! Row is null.");
+
+ bValidCurrentRow = ( !m_aCurrentRow.isNull() && m_aCurrentRow != m_pCache->getEnd() && m_aCurrentRow->is() );
+ }
+
+ if ( bValidCurrentRow )
+ {
+ m_nLastColumnIndex = columnIndex;
+ return new ::comphelper::SequenceInputStream((**m_aCurrentRow)[m_nLastColumnIndex].getSequence());
+ }
+
+ // we should normally never reach this
+ return Reference< css::io::XInputStream >();
+}
+
+Reference< css::io::XInputStream > SAL_CALL ORowSetBase::getCharacterStream( sal_Int32 columnIndex )
+{
+ return getBinaryStream(columnIndex);
+}
+
+Any SAL_CALL ORowSetBase::getObject( sal_Int32 columnIndex, const Reference< XNameAccess >& /*typeMap*/ )
+{
+ ::osl::MutexGuard aGuard( *m_pMutex );
+ checkCache();
+
+ return getValue(columnIndex).makeAny();
+}
+
+Reference< XRef > SAL_CALL ORowSetBase::getRef( sal_Int32 /*columnIndex*/ )
+{
+ ::dbtools::throwFeatureNotImplementedSQLException( "XRow::getRef", *m_pMySelf );
+ return nullptr;
+}
+
+Reference< XBlob > SAL_CALL ORowSetBase::getBlob( sal_Int32 columnIndex )
+{
+ return Reference< XBlob >(getValue(columnIndex).makeAny(),UNO_QUERY);
+}
+
+Reference< XClob > SAL_CALL ORowSetBase::getClob( sal_Int32 columnIndex )
+{
+ return Reference< XClob >(getValue(columnIndex).makeAny(),UNO_QUERY);
+}
+
+Reference< XArray > SAL_CALL ORowSetBase::getArray( sal_Int32 /*columnIndex*/ )
+{
+ ::dbtools::throwFeatureNotImplementedSQLException( "XRow::getArray", *m_pMySelf );
+ return nullptr;
+}
+
+// css::sdbcx::XRowLocate
+Any SAL_CALL ORowSetBase::getBookmark( )
+{
+ SAL_INFO("dbaccess", "ORowSetBase::getBookmark() Clone = " << m_bClone);
+ ::connectivity::checkDisposed(m_rBHelper.bDisposed);
+ ::osl::MutexGuard aGuard( *m_pMutex );
+ checkCache();
+
+ if ( m_bBeforeFirst || m_bAfterLast )
+ ::dbtools::throwSQLException( DBA_RES( RID_STR_NO_BOOKMARK_BEFORE_OR_AFTER ), StandardSQLState::INVALID_CURSOR_POSITION, *m_pMySelf );
+
+ if ( impl_rowDeleted() )
+ ::dbtools::throwSQLException( DBA_RES( RID_STR_NO_BOOKMARK_DELETED ), StandardSQLState::INVALID_CURSOR_POSITION, *m_pMySelf );
+
+ OSL_ENSURE( m_aBookmark.hasValue(), "ORowSetBase::getBookmark: bookmark has no value!" );
+ return m_aBookmark;
+}
+
+sal_Bool SAL_CALL ORowSetBase::moveToBookmark( const Any& bookmark )
+{
+ SAL_INFO("dbaccess", "ORowSetBase::moveToBookmark(Any) Clone = " << m_bClone);
+ OSL_ENSURE(bookmark.hasValue(),"ORowSetBase::moveToBookmark bookmark has no value!");
+ ::osl::ResettableMutexGuard aGuard( *m_pMutex );
+
+ if(!bookmark.hasValue() || m_nResultSetType == ResultSetType::FORWARD_ONLY)
+ {
+ if(bookmark.hasValue())
+ SAL_WARN("dbaccess", "MoveToBookmark is not possible when we are only forward");
+ else
+ SAL_WARN("dbaccess", "Bookmark is not valid");
+ throwFunctionSequenceException(*m_pMySelf);
+ }
+
+ checkCache();
+
+ bool bRet( notifyAllListenersCursorBeforeMove( aGuard ) );
+ if ( bRet )
+ {
+ // check if we are inserting a row
+ bool bWasNew = m_pCache->m_bNew || impl_rowDeleted();
+
+ ORowSetNotifier aNotifier( this );
+ // this will call cancelRowModification on the cache if necessary
+
+ ORowSetRow aOldValues = getOldRow(bWasNew);
+
+ bRet = m_pCache->moveToBookmark(bookmark);
+ doCancelModification( );
+ if(bRet)
+ {
+ // notification order
+ // - column values
+ // - cursorMoved
+ setCurrentRow( true, true, aOldValues, aGuard );
+ }
+ else
+ {
+ movementFailed();
+ }
+
+ // - IsModified
+ // - IsNew
+ aNotifier.fire( );
+ }
+ SAL_INFO("dbaccess", "ORowSetBase::moveToBookmark(Any) = " << bRet << " Clone = " << m_bClone);
+ return bRet;
+}
+
+sal_Bool SAL_CALL ORowSetBase::moveRelativeToBookmark( const Any& bookmark, sal_Int32 rows )
+{
+ SAL_INFO("dbaccess", "ORowSetBase::moveRelativeToBookmark(Any," << rows << ") Clone = " << m_bClone);
+ ::connectivity::checkDisposed(m_rBHelper.bDisposed);
+
+ ::osl::ResettableMutexGuard aGuard( *m_pMutex );
+
+ checkPositioningAllowed();
+
+ bool bRet( notifyAllListenersCursorBeforeMove( aGuard ) );
+ if ( bRet )
+ {
+ // check if we are inserting a row
+ bool bWasNew = m_pCache->m_bNew || rowDeleted();
+
+ ORowSetNotifier aNotifier( this );
+ // this will call cancelRowModification on the cache if necessary
+
+ ORowSetRow aOldValues = getOldRow(bWasNew);
+
+ bRet = m_pCache->moveRelativeToBookmark(bookmark,rows);
+ doCancelModification( );
+ if(bRet)
+ {
+ // notification order
+ // - column values
+ // - cursorMoved
+ setCurrentRow( true, true, aOldValues, aGuard );
+ }
+ else
+ movementFailed();
+
+ // - IsModified
+ // - IsNew
+ aNotifier.fire( );
+
+ // RowCount/IsRowCountFinal
+ fireRowcount();
+ }
+ SAL_INFO("dbaccess", "ORowSetBase::moveRelativeToBookmark(Any," << rows << ") = " << bRet << " Clone = " << m_bClone);
+ return bRet;
+}
+
+sal_Int32 SAL_CALL ORowSetBase::compareBookmarks( const Any& _first, const Any& _second )
+{
+ ::osl::MutexGuard aGuard( *m_pMutex );
+ checkCache();
+ return m_pCache->compareBookmarks(_first,_second);
+}
+
+sal_Bool SAL_CALL ORowSetBase::hasOrderedBookmarks( )
+{
+ ::osl::MutexGuard aGuard( *m_pMutex );
+ checkCache();
+ return m_pCache->hasOrderedBookmarks();
+}
+
+sal_Int32 SAL_CALL ORowSetBase::hashBookmark( const Any& bookmark )
+{
+ ::osl::MutexGuard aGuard( *m_pMutex );
+ checkCache();
+ return m_pCache->hashBookmark(bookmark);
+}
+
+// XResultSetMetaDataSupplier
+Reference< XResultSetMetaData > SAL_CALL ORowSetBase::getMetaData( )
+{
+ ::connectivity::checkDisposed(m_rBHelper.bDisposed);
+
+ Reference< XResultSetMetaData > xMeta;
+ if(m_pCache)
+ xMeta = m_pCache->getMetaData();
+
+ return xMeta;
+}
+
+// XColumnLocate
+sal_Int32 SAL_CALL ORowSetBase::findColumn( const OUString& columnName )
+{
+ ::connectivity::checkDisposed(m_rBHelper.bDisposed);
+
+ ::osl::MutexGuard aGuard( m_aColumnsMutex );
+ // it is possible to save some time here when we remember the names - position relation in a map
+ return m_pColumns ? m_pColumns->findColumn(columnName) : sal_Int32(0);
+}
+
+// css::sdbcx::XColumnsSupplier
+Reference< XNameAccess > SAL_CALL ORowSetBase::getColumns( )
+{
+ ::connectivity::checkDisposed(m_rBHelper.bDisposed);
+
+ ::osl::MutexGuard aGuard( m_aColumnsMutex );
+ if(!m_pColumns)
+ {
+ if (!m_pEmptyCollection)
+ m_pEmptyCollection.reset( new OEmptyCollection(*m_pMySelf,m_aColumnsMutex) );
+ return m_pEmptyCollection.get();
+ }
+
+ return m_pColumns.get();
+}
+
+// XResultSet
+sal_Bool SAL_CALL ORowSetBase::next( )
+{
+ SAL_INFO("dbaccess", "ORowSetBase::next() Clone = " << m_bClone);
+ ::osl::ResettableMutexGuard aGuard( *m_pMutex );
+ checkCache();
+
+ bool bRet( notifyAllListenersCursorBeforeMove( aGuard ) );
+ if ( bRet )
+ {
+ // check if we are inserting a row
+ bool bWasNew = m_pCache->m_bNew || impl_rowDeleted();
+
+ ORowSetNotifier aNotifier( this );
+ // this will call cancelRowModification on the cache if necessary
+
+ ORowSetRow aOldValues = getOldRow(bWasNew);
+
+ positionCache( MOVE_FORWARD );
+ bool bAfterLast = m_pCache->isAfterLast();
+ bRet = m_pCache->next();
+ doCancelModification( );
+
+ // if we were afterLast before next() then we still are,
+ // i.e. bAfterLast implies m_pCache->isAfterLast()
+ if (bAfterLast)
+ assert(m_pCache->isAfterLast());
+ // so the only way bAfterLast != m_pCache->isAfterLast()
+ // would be that we just arrived there,
+ if (bAfterLast != m_pCache->isAfterLast())
+ {
+ assert(!bAfterLast);
+ assert(m_pCache->isAfterLast());
+ }
+ // in which case we *did* move the cursor
+ if ( bRet || bAfterLast != m_pCache->isAfterLast() )
+ {
+ // notification order
+ // - column values
+ // - cursorMoved
+ setCurrentRow( true, true, aOldValues, aGuard );
+ OSL_ENSURE(!m_bBeforeFirst,"BeforeFirst is true. I don't know why?");
+ }
+ else
+ {
+ // moved after the last row
+ movementFailed();
+ OSL_ENSURE(m_bAfterLast,"AfterLast is false. I don't know why?");
+ }
+
+ // - IsModified
+ // - IsNew
+ aNotifier.fire();
+
+ // - RowCount/IsRowCountFinal
+ fireRowcount();
+ }
+ SAL_INFO("dbaccess", "ORowSetBase::next() = " << bRet << " Clone = " << m_bClone);
+ return bRet;
+}
+
+sal_Bool SAL_CALL ORowSetBase::isBeforeFirst( )
+{
+ ::connectivity::checkDisposed(m_rBHelper.bDisposed);
+ ::osl::MutexGuard aGuard( *m_pMutex );
+ checkCache();
+
+ SAL_INFO("dbaccess", "ORowSetBase::isBeforeFirst() = " << m_bBeforeFirst << " Clone = " << m_bClone);
+
+ return m_bBeforeFirst;
+}
+
+sal_Bool SAL_CALL ORowSetBase::isAfterLast( )
+{
+ ::connectivity::checkDisposed(m_rBHelper.bDisposed);
+ ::osl::MutexGuard aGuard( *m_pMutex );
+ checkCache();
+ SAL_INFO("dbaccess", "ORowSetBase::isAfterLast() = " << m_bAfterLast << " Clone = " << m_bClone);
+
+ return m_bAfterLast;
+}
+
+bool ORowSetBase::isOnFirst()
+{
+ return isFirst();
+}
+
+sal_Bool SAL_CALL ORowSetBase::isFirst( )
+{
+ SAL_INFO("dbaccess", "ORowSetBase::isFirst() Clone = " << m_bClone);
+
+ ::connectivity::checkDisposed(m_rBHelper.bDisposed);
+ ::osl::MutexGuard aGuard( *m_pMutex );
+ checkCache();
+
+ if ( m_bBeforeFirst || m_bAfterLast )
+ return false;
+
+ if ( impl_rowDeleted() )
+ return ( m_nDeletedPosition == 1 );
+
+ positionCache( MOVE_NONE );
+ bool bIsFirst = m_pCache->isFirst();
+
+ SAL_INFO("dbaccess", "ORowSetBase::isFirst() = " << bIsFirst << " Clone = " << m_bClone);
+ return bIsFirst;
+}
+
+bool ORowSetBase::isOnLast()
+{
+ return isLast();
+}
+
+sal_Bool SAL_CALL ORowSetBase::isLast( )
+{
+ SAL_INFO("dbaccess", "ORowSetBase::isLast() Clone = " << m_bClone);
+ ::connectivity::checkDisposed(m_rBHelper.bDisposed);
+ ::osl::MutexGuard aGuard( *m_pMutex );
+ checkCache();
+
+ if ( m_bBeforeFirst || m_bAfterLast )
+ return false;
+
+ if ( impl_rowDeleted() )
+ {
+ if ( !m_pCache->m_bRowCountFinal )
+ return false;
+ else
+ return ( m_nDeletedPosition == impl_getRowCount() );
+ }
+
+ positionCache( MOVE_NONE );
+ bool bIsLast = m_pCache->isLast();
+
+ SAL_INFO("dbaccess", "ORowSetBase::isLast() = " << bIsLast << " Clone = " << m_bClone);
+ return bIsLast;
+}
+
+void SAL_CALL ORowSetBase::beforeFirst( )
+{
+ SAL_INFO("dbaccess", "ORowSetBase::beforeFirst() Clone = " << m_bClone);
+ ::connectivity::checkDisposed(m_rBHelper.bDisposed);
+ ::osl::ResettableMutexGuard aGuard( *m_pMutex );
+
+ checkPositioningAllowed();
+
+ // check if we are inserting a row
+ bool bWasNew = m_pCache->m_bNew || impl_rowDeleted();
+
+ if((bWasNew || !m_bBeforeFirst) && notifyAllListenersCursorBeforeMove(aGuard) )
+ {
+ ORowSetNotifier aNotifier( this );
+ // this will call cancelRowModification on the cache if necessary
+
+ if ( !m_bBeforeFirst )
+ {
+ ORowSetRow aOldValues = getOldRow(bWasNew);
+ m_pCache->beforeFirst();
+ doCancelModification( );
+
+ // notification order
+ // - column values
+ // - cursorMoved
+ setCurrentRow( true, true, aOldValues, aGuard );
+
+ // - IsModified
+ // - Isnew
+ aNotifier.fire();
+
+ // - RowCount/IsRowCountFinal
+ fireRowcount();
+ }
+
+ // to be done _after_ the notifications!
+ m_aOldRow->clearRow();
+ }
+ SAL_INFO("dbaccess", "ORowSetBase::beforeFirst() Clone = " << m_bClone);
+}
+
+void SAL_CALL ORowSetBase::afterLast( )
+{
+ SAL_INFO("dbaccess", "ORowSetBase::afterLast() Clone = " << m_bClone);
+ ::connectivity::checkDisposed(m_rBHelper.bDisposed);
+
+ ::osl::ResettableMutexGuard aGuard( *m_pMutex );
+ checkPositioningAllowed();
+
+ bool bWasNew = m_pCache->m_bNew || impl_rowDeleted();
+
+ if((bWasNew || !m_bAfterLast) && notifyAllListenersCursorBeforeMove(aGuard) )
+ {
+ // check if we are inserting a row
+ ORowSetNotifier aNotifier( this );
+ // this will call cancelRowModification on the cache if necessary
+
+ if(!m_bAfterLast)
+ {
+ ORowSetRow aOldValues = getOldRow(bWasNew);
+
+ m_pCache->afterLast();
+ doCancelModification( );
+
+ // notification order
+ // - column values
+ // - cursorMoved
+ setCurrentRow( true, true, aOldValues, aGuard );
+
+ // - IsModified
+ // - Isnew
+ aNotifier.fire();
+
+ // - RowCount/IsRowCountFinal
+ fireRowcount();
+ }
+ }
+ SAL_INFO("dbaccess", "ORowSetBase::afterLast() Clone = " << m_bClone);
+}
+
+bool SAL_CALL ORowSetBase::move(std::function<bool(ORowSetBase *)> const & _aCheckFunctor,
+ std::function<bool(ORowSetCache *)> const & _aMovementFunctor)
+{
+ SAL_INFO("dbaccess", "ORowSetBase::move() Clone = " << m_bClone);
+ ::connectivity::checkDisposed(m_rBHelper.bDisposed);
+ ::osl::ResettableMutexGuard aGuard( *m_pMutex );
+ checkPositioningAllowed();
+
+ bool bRet( notifyAllListenersCursorBeforeMove( aGuard ) );
+ if( bRet )
+ {
+ // check if we are inserting a row
+ bool bWasNew = m_pCache->m_bNew || rowDeleted();
+
+ ORowSetNotifier aNotifier( this );
+ // this will call cancelRowModification on the cache if necessary
+
+ ORowSetRow aOldValues = getOldRow(bWasNew);
+
+ bool bMoved = ( bWasNew || !_aCheckFunctor(this) );
+
+ bRet = _aMovementFunctor(m_pCache.get());
+ doCancelModification( );
+
+ if ( bRet )
+ {
+ // notification order
+ // - column values
+ // - cursorMoved
+ setCurrentRow( bMoved, true, aOldValues, aGuard );
+ }
+ else
+ { // first goes wrong so there is no row
+ movementFailed();
+ }
+
+ // - IsModified
+ // - IsNew
+ aNotifier.fire();
+
+ // - RowCount/IsRowCountFinal
+ fireRowcount();
+ }
+ SAL_INFO("dbaccess", "ORowSetBase::move() = " << bRet << " Clone = " << m_bClone);
+ return bRet;
+}
+
+sal_Bool SAL_CALL ORowSetBase::first( )
+{
+ SAL_INFO("dbaccess", "ORowSetBase::first() Clone = " << m_bClone);
+ auto ioF_tmp = std::mem_fn(&ORowSetBase::isOnFirst);
+ auto F_tmp = std::mem_fn(&ORowSetCache::first);
+ return move(ioF_tmp,F_tmp);
+}
+
+sal_Bool SAL_CALL ORowSetBase::last( )
+{
+ SAL_INFO("dbaccess", "ORowSetBase::last() Clone = " << m_bClone);
+ auto ioL_tmp = std::mem_fn(&ORowSetBase::isOnLast);
+ auto L_tmp = std::mem_fn(&ORowSetCache::last);
+ return move(ioL_tmp,L_tmp);
+}
+
+sal_Int32 SAL_CALL ORowSetBase::getRow( )
+{
+ SAL_INFO("dbaccess", "ORowSetBase::getRow() Clone = " << m_bClone);
+ ::osl::MutexGuard aGuard( *m_pMutex );
+
+ checkCache();
+ return impl_getRow();
+}
+
+sal_Int32 ORowSetBase::impl_getRow()
+{
+ sal_Int32 nPos = 0;
+ if ( m_bBeforeFirst )
+ nPos = 0;
+ else if ( m_bAfterLast )
+ nPos = impl_getRowCount() + 1;
+ else if ( impl_rowDeleted() )
+ nPos = m_nDeletedPosition;
+ else if ( !m_bClone && m_pCache->m_bNew )
+ nPos = 0;
+ else
+ {
+ positionCache( MOVE_NONE );
+ nPos = m_pCache->getRow();
+ }
+ SAL_INFO("dbaccess", "ORowSetBase::impl_getRow() = " << nPos << " Clone = " << m_bClone);
+ return nPos;
+}
+
+sal_Bool SAL_CALL ORowSetBase::absolute( sal_Int32 row )
+{
+ SAL_INFO("dbaccess", "ORowSetBase::absolute(" << row << ") Clone = " << m_bClone);
+ ::connectivity::checkDisposed(m_rBHelper.bDisposed);
+ ::osl::ResettableMutexGuard aGuard( *m_pMutex );
+ checkPositioningAllowed();
+
+ bool bRet = ( row > 0 )
+ && notifyAllListenersCursorBeforeMove( aGuard );
+ if ( bRet )
+ {
+ // check if we are inserting a row
+ bool bWasNew = m_pCache->m_bNew || rowDeleted();
+
+ ORowSetNotifier aNotifier( this );
+ // this will call cancelRowModification on the cache if necessary
+
+ ORowSetRow aOldValues = getOldRow(bWasNew);
+
+ bRet = m_pCache->absolute(row);
+ doCancelModification( );
+
+ if(bRet)
+ {
+ // notification order
+ // - column values
+ // - cursorMoved
+ setCurrentRow( true, true, aOldValues, aGuard );
+ }
+ else
+ { // absolute movement goes wrong we stand left or right side of the rows
+ movementFailed();
+ }
+
+ // - IsModified
+ // - IsNew
+ aNotifier.fire();
+
+ // - RowCount/IsRowCountFinal
+ fireRowcount();
+ }
+ SAL_INFO("dbaccess", "ORowSetBase::absolute(" << row << ") = " << bRet << " Clone = " << m_bClone);
+ return bRet;
+}
+
+sal_Bool SAL_CALL ORowSetBase::relative( sal_Int32 rows )
+{
+ SAL_INFO("dbaccess", "ORowSetBase::relative(" << rows << ") Clone = " << m_bClone);
+ ::connectivity::checkDisposed(m_rBHelper.bDisposed);
+
+ ::osl::ResettableMutexGuard aGuard( *m_pMutex );
+
+ if(!rows)
+ return true; // in this case do nothing
+
+ checkPositioningAllowed();
+
+ bool bRet =
+ ( ( !m_bAfterLast || rows <= 0 )
+ && ( !m_bBeforeFirst || rows >= 0 )
+ && notifyAllListenersCursorBeforeMove( aGuard )
+ );
+
+ if ( bRet )
+ {
+ // check if we are inserting a row
+ bool bWasNew = m_pCache->m_bNew || rowDeleted();
+
+ ORowSetNotifier aNotifier( this );
+ // this will call cancelRowModification on the cache if necessary
+
+ ORowSetRow aOldValues = getOldRow(bWasNew);
+
+ positionCache( rows > 0 ? MOVE_FORWARD : MOVE_BACKWARD );
+ bRet = m_pCache->relative(rows);
+ doCancelModification( );
+
+ if(bRet)
+ {
+ // notification order
+ // - column values
+ // - cursorMoved
+ setCurrentRow( true, true, aOldValues, aGuard );
+ }
+ else
+ {
+ movementFailed();
+ }
+
+ // - IsModified
+ // - IsNew
+ aNotifier.fire();
+
+ // - RowCount/IsRowCountFinal
+ fireRowcount();
+ }
+ SAL_INFO("dbaccess", "ORowSetBase::relative(" << rows << ") = " << bRet << " Clone = " << m_bClone);
+ return bRet;
+}
+
+sal_Bool SAL_CALL ORowSetBase::previous( )
+{
+ SAL_INFO("dbaccess", "ORowSetBase::previous() Clone = " << m_bClone);
+ ::connectivity::checkDisposed(m_rBHelper.bDisposed);
+ ::osl::ResettableMutexGuard aGuard( *m_pMutex );
+
+ checkPositioningAllowed();
+
+ bool bRet = !m_bBeforeFirst
+ && notifyAllListenersCursorBeforeMove(aGuard);
+
+ if ( bRet )
+ {
+ // check if we are inserting a row
+ bool bWasNew = m_pCache->m_bNew || rowDeleted();
+
+ ORowSetNotifier aNotifier( this );
+ // this will call cancelRowModification on the cache if necessary
+
+ ORowSetRow aOldValues = getOldRow(bWasNew);
+
+ positionCache( MOVE_BACKWARD );
+ bRet = m_pCache->previous();
+ doCancelModification( );
+
+ // if m_bBeforeFirst is false and bRet is false then we stood on the first row
+ if(!m_bBeforeFirst || bRet)
+ {
+ // notification order
+ // - column values
+ // - cursorMoved
+ setCurrentRow( true, true, aOldValues, aGuard );
+ }
+ else
+ {
+ SAL_WARN("dbaccess", "ORowSetBase::previous: inconsistency!" );
+ // we should never reach this place, as we should not get into this whole branch if m_bBeforeFirst
+ // was |true| from the beginning
+ movementFailed();
+ }
+
+ // - IsModified
+ // - IsNew
+ aNotifier.fire();
+
+ // - RowCount/IsRowCountFinal
+ fireRowcount();
+ }
+ SAL_INFO("dbaccess", "ORowSetBase::previous() = " << bRet << " Clone = " << m_bClone);
+ return bRet;
+}
+
+void ORowSetBase::setCurrentRow( bool _bMoved, bool _bDoNotify, const ORowSetRow& _rOldValues, ::osl::ResettableMutexGuard& _rGuard )
+{
+ SAL_INFO("dbaccess", "ORowSetBase::setCurrentRow() Clone = " << m_bClone);
+ m_bBeforeFirst = m_pCache->isBeforeFirst();
+ m_bAfterLast = m_pCache->isAfterLast();
+
+ if(!(m_bBeforeFirst || m_bAfterLast))
+ {
+ m_aBookmark = m_pCache->getBookmark();
+ OSL_ENSURE(m_aBookmark.hasValue(),"Bookmark has no value!");
+ m_aCurrentRow = m_pCache->m_aMatrixIter;
+ m_bIsInsertRow = false;
+ OSL_ENSURE(!m_aCurrentRow.isNull(),"CurrentRow is null!");
+ OSL_ENSURE(!m_aCurrentRow.isNull() && m_aCurrentRow != m_pCache->getEnd(),"Position of matrix iterator isn't valid!");
+ OSL_ENSURE(m_aCurrentRow->is(),"Currentrow isn't valid");
+ OSL_ENSURE(m_aBookmark.hasValue(),"Bookmark has no value!");
+
+ m_aCurrentRow = m_pCache->m_aMatrixIter;
+ m_bIsInsertRow = false;
+ OSL_ENSURE(!m_aCurrentRow.isNull(),"CurrentRow is nul after positionCache!");
+#if OSL_DEBUG_LEVEL > 0
+ ORowSetRow rRow = *m_aCurrentRow;
+ OSL_ENSURE(rRow.is() ,"Invalid size of vector!");
+#endif
+
+ // notification order
+ // - column values
+ if ( _bDoNotify )
+ firePropertyChange(_rOldValues);
+
+ }
+ else
+ {
+ m_aOldRow->clearRow();
+ m_aCurrentRow = m_pCache->getEnd();
+ m_aBookmark = Any();
+ }
+
+ // TODO: can this be done before the notifications?
+ if(!(m_bBeforeFirst || m_bAfterLast) && !m_aCurrentRow.isNull() && m_aCurrentRow->is() && m_aCurrentRow != m_pCache->getEnd())
+ m_aOldRow->setRow(new ORowSetValueVector( *(*m_aCurrentRow) ));
+
+ if ( _bMoved && _bDoNotify )
+ // - cursorMoved
+ notifyAllListenersCursorMoved( _rGuard );
+
+ SAL_INFO("dbaccess", "ORowSetBase::setCurrentRow() Clone = " << m_bClone);
+}
+
+void ORowSetBase::checkPositioningAllowed()
+{
+ if(!m_pCache || m_nResultSetType == ResultSetType::FORWARD_ONLY)
+ throwFunctionSequenceException(*m_pMySelf);
+}
+
+Reference< XInterface > ORowSetBase::getStatement()
+{
+ return nullptr;
+}
+
+void SAL_CALL ORowSetBase::refreshRow( )
+{
+ ::connectivity::checkDisposed(m_rBHelper.bDisposed);
+ ::osl::MutexGuard aGuard( *m_pMutex );
+ checkCache();
+ if ( impl_rowDeleted() )
+ throwSQLException( "The current row is deleted", StandardSQLState::INVALID_CURSOR_STATE, Reference< XRowSet >( this ) );
+
+ if(!(m_bBeforeFirst || m_bAfterLast))
+ {
+ bool bWasNew = m_pCache->m_bNew || impl_rowDeleted();
+ ORowSetRow aOldValues = getOldRow(bWasNew);
+ positionCache( MOVE_NONE );
+ m_pCache->refreshRow();
+ firePropertyChange(aOldValues);
+ }
+}
+
+sal_Bool SAL_CALL ORowSetBase::rowUpdated( )
+{
+ ::osl::MutexGuard aGuard( *m_pMutex );
+ checkCache();
+
+ if ( impl_rowDeleted() )
+ return false;
+
+ return m_pCache->rowUpdated();
+}
+
+sal_Bool SAL_CALL ORowSetBase::rowInserted( )
+{
+ ::osl::MutexGuard aGuard( *m_pMutex );
+
+ checkCache();
+
+ if ( impl_rowDeleted() )
+ return false;
+
+ return m_pCache->rowInserted();
+}
+
+sal_Bool SAL_CALL ORowSetBase::rowDeleted( )
+{
+ ::osl::MutexGuard aGuard( *m_pMutex );
+ checkCache();
+ return impl_rowDeleted();
+}
+
+bool ORowSetBase::impl_rowDeleted( )
+{
+ return !m_aBookmark.hasValue() && !m_bBeforeFirst && !m_bAfterLast;
+}
+
+// XWarningsSupplier
+Any SAL_CALL ORowSetBase::getWarnings( )
+{
+ ::osl::MutexGuard aGuard( *m_pMutex );
+
+ if ( m_pCache )
+ {
+ Reference< XWarningsSupplier > xWarnings( m_pCache->m_xSet.get(), UNO_QUERY );
+ if ( xWarnings.is() )
+ return xWarnings->getWarnings();
+ }
+
+ return Any();
+}
+
+void SAL_CALL ORowSetBase::clearWarnings( )
+{
+ ::osl::MutexGuard aGuard( *m_pMutex );
+
+ if ( m_pCache )
+ {
+ Reference< XWarningsSupplier > xWarnings( m_pCache->m_xSet.get(), UNO_QUERY );
+ if ( xWarnings.is() )
+ xWarnings->clearWarnings();
+ }
+}
+
+void ORowSetBase::firePropertyChange(const ORowSetRow& _rOldRow)
+{
+ if (!isPropertyChangeNotificationEnabled())
+ return;
+
+ SAL_INFO("dbaccess", "ORowSetBase::firePropertyChange" );
+ SAL_INFO("dbaccess", "ORowSetBase::firePropertyChange() Clone = " << m_bClone);
+ OSL_ENSURE(m_pColumns,"Columns can not be NULL here!");
+ sal_Int32 i=0;
+ for (auto const& dataColumn : m_aDataColumns)
+ {
+ try
+ {
+ dataColumn->fireValueChange(_rOldRow.is() ? (*_rOldRow)[i+1] : ::connectivity::ORowSetValue());
+ }
+ catch (const Exception&)
+ {
+ TOOLS_WARN_EXCEPTION("dbaccess", "firePropertyChange: Exception on column " << i);
+ }
+ ++i;
+ }
+ SAL_INFO("dbaccess", "ORowSetBase::firePropertyChange() Clone = " << m_bClone);
+}
+
+void ORowSetBase::firePropertyChange(sal_Int32 _nPos,const ::connectivity::ORowSetValue& _rOldValue)
+{
+ OSL_ENSURE(_nPos < static_cast<sal_Int32>(m_aDataColumns.size()),"nPos is invalid!");
+ m_aDataColumns[_nPos]->fireValueChange(_rOldValue);
+}
+
+void ORowSetBase::fireRowcount()
+{
+}
+
+bool ORowSetBase::notifyAllListenersCursorBeforeMove(::osl::ResettableMutexGuard& /*_rGuard*/)
+{
+ return true;
+}
+
+void ORowSetBase::notifyAllListenersCursorMoved(::osl::ResettableMutexGuard& /*_rGuard*/)
+{
+}
+
+bool ORowSetBase::isPropertyChangeNotificationEnabled() const
+{
+ return true;
+}
+
+void ORowSetBase::fireProperty( sal_Int32 _nProperty, bool _bNew, bool _bOld )
+{
+ Any aNew( _bNew );
+ Any aOld( _bOld );
+ fire( &_nProperty, &aNew, &aOld, 1, false );
+}
+
+void ORowSetBase::positionCache( CursorMoveDirection _ePrepareForDirection )
+{
+ SAL_INFO("dbaccess", "ORowSetBase::positionCache() Clone = " << m_bClone);
+
+ bool bSuccess = false;
+ if ( m_aBookmark.hasValue() )
+ {
+ if (_ePrepareForDirection == MOVE_NONE_REFRESH ||
+ (m_pCache->isAfterLast() != bool(isAfterLast())) || ( m_pCache->isBeforeFirst() != bool(isBeforeFirst()) ) ||
+ m_pCache->compareBookmarks( m_aBookmark, m_pCache->getBookmark() ) != CompareBookmark::EQUAL )
+ bSuccess = m_pCache->moveToBookmark( m_aBookmark );
+ else
+ bSuccess = true;
+ }
+ else
+ {
+ if ( m_bBeforeFirst )
+ {
+ m_pCache->beforeFirst();
+ bSuccess = true;
+ }
+ else if ( m_bAfterLast )
+ {
+ m_pCache->afterLast();
+ bSuccess = true;
+ }
+ else
+ {
+ OSL_ENSURE( m_nDeletedPosition >= 1, "ORowSetBase::positionCache: no bookmark, and no valid 'deleted position'!" );
+ switch ( _ePrepareForDirection )
+ {
+ case MOVE_FORWARD:
+ if ( m_nDeletedPosition > 1 )
+ bSuccess = m_pCache->absolute( m_nDeletedPosition - 1 );
+ else
+ {
+ m_pCache->beforeFirst();
+ bSuccess = true;
+ }
+ break;
+
+ case MOVE_BACKWARD:
+ if ( m_pCache->m_bRowCountFinal && ( m_nDeletedPosition == impl_getRowCount() ) )
+ {
+ m_pCache->afterLast();
+ bSuccess = true;
+ }
+ else
+ bSuccess = m_pCache->absolute( m_nDeletedPosition );
+ break;
+
+ case MOVE_NONE:
+ case MOVE_NONE_REFRESH:
+ bSuccess = false; // will be asserted below
+ break;
+ }
+ }
+ }
+ OSL_ENSURE( bSuccess, "ORowSetBase::positionCache: failed!" );
+
+ SAL_INFO("dbaccess", "ORowSetBase::positionCache() Clone = " << m_bClone);
+}
+
+void ORowSetBase::checkCache()
+{
+ ::connectivity::checkDisposed(m_rBHelper.bDisposed);
+ if(!m_pCache)
+ throwFunctionSequenceException(*m_pMySelf);
+}
+
+void ORowSetBase::movementFailed()
+{
+ SAL_INFO("dbaccess", "ORowSetBase::movementFailed() Clone = " << m_bClone);
+ m_aOldRow->clearRow();
+ m_aCurrentRow = m_pCache->getEnd();
+ m_bBeforeFirst = m_pCache->isBeforeFirst();
+ m_bAfterLast = m_pCache->isAfterLast();
+ m_aBookmark = Any();
+ OSL_ENSURE(m_bBeforeFirst || m_bAfterLast,"BeforeFirst or AfterLast is wrong!");
+ SAL_INFO("dbaccess", "ORowSetBase::movementFailed() Clone = " << m_bClone);
+}
+
+ORowSetRow ORowSetBase::getOldRow(bool _bWasNew)
+{
+ OSL_ENSURE(m_aOldRow.is(),"RowSetRowHElper isn't valid!");
+ ORowSetRow aOldValues;
+ if ( !_bWasNew && m_aOldRow->getRow().is() )
+ aOldValues = new ORowSetValueVector( *(m_aOldRow->getRow())); // remember the old values
+ return aOldValues;
+}
+
+void ORowSetBase::getPropertyDefaultByHandle( sal_Int32 /*_nHandle*/, Any& _rDefault ) const
+{
+ _rDefault.clear();
+}
+
+void ORowSetBase::onDeleteRow( const Any& _rBookmark )
+{
+ if ( rowDeleted() )
+ // not interested in
+ return;
+
+ ::osl::MutexGuard aGuard( *m_pMutex );
+ //OSL_ENSURE( m_aBookmark.hasValue(), "ORowSetBase::onDeleteRow: Bookmark isn't valid!" );
+ if ( compareBookmarks( _rBookmark, m_aBookmark ) == CompareBookmark::EQUAL )
+ {
+ positionCache( MOVE_NONE );
+ m_nDeletedPosition = m_pCache->getRow();
+ }
+}
+
+void ORowSetBase::onDeletedRow( const Any& _rBookmark, sal_Int32 _nPos )
+{
+ if ( rowDeleted() )
+ {
+ // if we're a clone, and on a deleted row, and the main RowSet deleted another
+ // row (only the main RowSet can, clones can't), which is *before* our
+ // deleted position, then we have to adjust this position
+ if ( m_bClone && ( _nPos < m_nDeletedPosition ) )
+ --m_nDeletedPosition;
+ return;
+ }
+
+ ::osl::MutexGuard aGuard( *m_pMutex );
+ if ( compareBookmarks( _rBookmark, m_aBookmark ) == CompareBookmark::EQUAL )
+ {
+ m_aOldRow->clearRow();
+ m_aCurrentRow = m_pCache->getEnd();
+ m_aBookmark = Any();
+ }
+}
+
+sal_Int32 ORowSetBase::impl_getRowCount() const
+{
+ sal_Int32 nRowCount( m_pCache->m_nRowCount );
+ if ( const_cast< ORowSetBase* >( this )->rowDeleted() && !m_pCache->m_bNew )
+ ++nRowCount;
+ return nRowCount;
+}
+
+struct ORowSetNotifierImpl
+{
+ std::vector<sal_Int32> aChangedColumns;
+ ORowSetValueVector::Vector aRow;
+};
+
+
+ORowSetNotifier::ORowSetNotifier( ORowSetBase* _pRowSet )
+ :m_pRowSet( _pRowSet )
+ ,m_bWasNew( false )
+ ,m_bWasModified( false )
+{
+
+ OSL_ENSURE( m_pRowSet, "ORowSetNotifier::ORowSetNotifier: invalid row set. This will crash." );
+
+ // remember the "inserted" and "modified" state for later firing
+ m_bWasNew = m_pRowSet->isNew( ORowSetBase::GrantNotifierAccess() );
+ m_bWasModified = m_pRowSet->isModified( ORowSetBase::GrantNotifierAccess() );
+
+ // if the row set is on the insert row, then we need to cancel this
+ if ( m_pRowSet->isModification( ORowSetBase::GrantNotifierAccess() ) )
+ m_pRowSet->doCancelModification( ORowSetBase::GrantNotifierAccess() );
+}
+
+ORowSetNotifier::ORowSetNotifier( ORowSetBase* _pRowSet, ORowSetValueVector::Vector&& i_aRow )
+ :m_pImpl(new ORowSetNotifierImpl)
+ ,m_pRowSet( _pRowSet )
+ ,m_bWasNew( false )
+ ,m_bWasModified( false )
+{
+
+ OSL_ENSURE( m_pRowSet, "ORowSetNotifier::ORowSetNotifier: invalid row set. This will crash." );
+ m_pImpl->aRow = std::move(i_aRow); // yes, create a copy to store the old values
+}
+
+ORowSetNotifier::~ORowSetNotifier( )
+{
+}
+
+void ORowSetNotifier::fire()
+{
+ // we're not interested in firing changes FALSE->TRUE, only TRUE->FALSE.
+ // (the former would be quite pathological, e.g. after a failed movement)
+
+ if ( m_bWasModified
+ && ( m_bWasModified != m_pRowSet->isModified( ORowSetBase::GrantNotifierAccess() ) )
+ )
+ m_pRowSet->fireProperty( PROPERTY_ID_ISMODIFIED, false, true, ORowSetBase::GrantNotifierAccess() );
+
+ if ( m_bWasNew
+ && ( m_bWasNew != m_pRowSet->isNew( ORowSetBase::GrantNotifierAccess() ) )
+ )
+ m_pRowSet->fireProperty( PROPERTY_ID_ISNEW, false, true, ORowSetBase::GrantNotifierAccess() );
+}
+
+std::vector<sal_Int32>& ORowSetNotifier::getChangedColumns() const
+{
+ OSL_ENSURE(m_pImpl, "Illegal CTor call, use the other one!");
+ return m_pImpl->aChangedColumns;
+}
+
+void ORowSetNotifier::firePropertyChange()
+{
+ OSL_ENSURE(m_pImpl, "Illegal CTor call, use the other one!");
+ if (m_pImpl)
+ {
+ for (auto const& changedColumn : m_pImpl->aChangedColumns)
+ {
+ m_pRowSet->firePropertyChange(changedColumn-1 ,m_pImpl->aRow[changedColumn-1], ORowSetBase::GrantNotifierAccess());
+ }
+ if ( !m_pImpl->aChangedColumns.empty() )
+ m_pRowSet->fireProperty(PROPERTY_ID_ISMODIFIED,true,false, ORowSetBase::GrantNotifierAccess());
+ }
+}
+
+} // namespace dbaccess
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/api/RowSetBase.hxx b/dbaccess/source/core/api/RowSetBase.hxx
new file mode 100644
index 000000000..f5443a2af
--- /dev/null
+++ b/dbaccess/source/core/api/RowSetBase.hxx
@@ -0,0 +1,402 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <memory>
+#include <cppuhelper/implbase10.hxx>
+#include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
+#include <com/sun/star/sdbc/XRow.hpp>
+#include <com/sun/star/sdbc/XColumnLocate.hpp>
+#include <com/sun/star/sdbc/XCloseable.hpp>
+#include <com/sun/star/sdbcx/XRowLocate.hpp>
+#include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp>
+#include <com/sun/star/sdbc/XWarningsSupplier.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/lang/XUnoTunnel.hpp>
+#include <cppuhelper/interfacecontainer.h>
+#include <connectivity/sqlerror.hxx>
+#include <connectivity/CommonTools.hxx>
+#include <comphelper/propertystatecontainer.hxx>
+#include <comphelper/proparrhlp.hxx>
+#include <com/sun/star/sdbc/XRowSet.hpp>
+#include <com/sun/star/util/XNumberFormatTypes.hpp>
+#include <com/sun/star/container/XNameAccess.hpp>
+#include "RowSetRow.hxx"
+#include "RowSetCacheIterator.hxx"
+
+#include <functional>
+
+namespace com::sun::star {
+ namespace sdb { struct RowChangeEvent; }
+ namespace lang { struct Locale; }
+}
+
+namespace dbaccess
+{
+ class OEmptyCollection;
+
+ typedef ::cppu::ImplHelper10< css::sdbcx::XRowLocate,
+ css::sdbc::XRow,
+ css::sdbc::XResultSetMetaDataSupplier,
+ css::sdbc::XWarningsSupplier,
+ css::sdbc::XColumnLocate,
+ css::sdbcx::XColumnsSupplier,
+ css::lang::XServiceInfo,
+ css::sdbc::XRowSet,
+ css::sdbc::XCloseable,
+ css::lang::XUnoTunnel> ORowSetBase_BASE;
+
+ class ORowSetCache;
+ class ORowSetDataColumns;
+ class ORowSetCacheIterator;
+ class ORowSetDataColumn;
+ class ORowSetBase : public ORowSetBase_BASE,
+ public ::comphelper::OPropertyStateContainer,
+ public ::comphelper::OPropertyArrayUsageHelper<ORowSetBase> // this class hold the static property info
+ {
+ protected:
+ typedef std::vector<ORowSetDataColumn*> TDataColumns;
+ ::osl::Mutex* m_pMutex; // this is the mutex from the rowset itself
+ ::osl::Mutex // we need an extra mutex for columns to prevent deadlock when setting new values
+ // for a row
+ m_aColumnsMutex;
+
+ css::uno::Any m_aBookmark;
+ ORowSetCacheIterator m_aCurrentRow; // contains the actual fetched row
+ TORowSetOldRowHelperRef m_aOldRow;
+ TDataColumns m_aDataColumns; // holds the columns as m_pColumns but know the implementation class
+ connectivity::ORowSetValue m_aEmptyValue; // only for error case
+
+ ::cppu::OWeakObject* m_pMySelf; // set by derived classes
+ std::shared_ptr<ORowSetCache> m_pCache; // the cache is used by the rowset and his clone (shared)
+ std::unique_ptr<ORowSetDataColumns> m_pColumns; // represent the select columns
+ ::cppu::OBroadcastHelper& m_rBHelper; // must be set from the derived classes
+ // is used when the formatkey for database types is set
+ css::uno::Reference< css::util::XNumberFormatTypes> m_xNumberFormatTypes;
+ std::unique_ptr<OEmptyCollection> m_pEmptyCollection;
+
+ css::uno::Reference< css::uno::XComponentContext> m_aContext;
+ ::connectivity::SQLError m_aErrors;
+
+ sal_Int32 m_nLastColumnIndex; // the last column ask for, used for wasNull()
+ sal_Int32 m_nDeletedPosition; // is set only when a row was deleted
+ sal_Int32 m_nResultSetType; // fetch property
+ sal_Int32 m_nResultSetConcurrency;
+ bool m_bClone; // I'm clone or not
+ bool m_bIgnoreResult ;
+ bool m_bBeforeFirst : 1;
+ bool m_bAfterLast : 1;
+ bool m_bIsInsertRow : 1;
+
+ protected:
+ ORowSetBase(
+ const css::uno::Reference<css::uno::XComponentContext>& _rContext,
+ ::cppu::OBroadcastHelper& _rBHelper,
+ ::osl::Mutex* _pMutex
+ );
+
+ // fire a notification for all that are listening on column::VALUE property
+ void firePropertyChange(const ORowSetRow& _rOldRow);
+ // fire a change for one column
+ // _nPos starts at zero
+ void firePropertyChange(sal_Int32 _nPos,const ::connectivity::ORowSetValue& _rNewValue);
+
+ // fire if rowcount changed
+ virtual void fireRowcount();
+ // notify row changed
+ virtual bool notifyAllListenersCursorBeforeMove(::osl::ResettableMutexGuard& _rGuard);
+ // notify cursor moved
+ virtual void notifyAllListenersCursorMoved(::osl::ResettableMutexGuard& _rGuard);
+
+ // cancel the insertion, if necessary (means if we're on the insert row)
+ virtual void doCancelModification( ) = 0;
+ // return <TRUE/> if and only if we're using the insert row (means: we're updating _or_ inserting)
+ virtual bool isModification( ) = 0;
+ // return <TRUE/> if and only if the current row is modified
+ // TODO: isn't this the same as isModification?
+ virtual bool isModified( ) = 0;
+ // return <TRUE/> if and only if the current row is the insert row
+ virtual bool isNew( ) = 0;
+ // return <TRUE/> if the property change notification should be fired
+ // upon property change.
+ virtual bool isPropertyChangeNotificationEnabled() const;
+ // notify the change of a boolean property
+ void fireProperty( sal_Int32 _nProperty, bool _bNew, bool _bOld );
+
+ // OPropertyStateContainer
+ virtual void getPropertyDefaultByHandle( sal_Int32 _nHandle, css::uno::Any& _rDefault ) const override;
+ virtual void SAL_CALL getFastPropertyValue(css::uno::Any& rValue,sal_Int32 nHandle) const override;
+
+ enum CursorMoveDirection
+ {
+ /// denotes a cursor move forward
+ MOVE_FORWARD,
+ /// denotes a cursor move backwards
+ MOVE_BACKWARD,
+ /// denotes no cursor move at all, but move cache to current row (if it is not there already)
+ MOVE_NONE,
+ /// denotes no cursor move at all, but force the cache to move to current row (and refresh the row)
+ MOVE_NONE_REFRESH
+ };
+ /** positions the cache in preparation of a cursor move
+
+ Normally, the cache is simply moved to our bookmark (m_aBookmark). If however the current
+ row is deleted, then the cache is properly positioned for a following cursor movement in the
+ given direction.
+
+ @param _ePrepareForDirection
+ the direction into which the cursor should be moved after the call. If we're currently not on
+ a deleted row, this parameter is ignored, since in this case the cache is simply moved to
+ m_aBookmark.</br>
+ If, however, we're currently on a deleted row, this is used to properly position the cache
+ using <member>m_nDeletedPosition</member>.<br/>
+ In this case, MOVE_NONE(_REFRESH) is not supported. This is because the deleted row
+ (to which the RowSet currently points to) is not present in the cache. So, you cannot move the
+ cache to this row.
+ */
+ void positionCache( CursorMoveDirection _ePrepareForDirection );
+
+ // returns a value of a column of the current row
+ const connectivity::ORowSetValue& getValue(sal_Int32 columnIndex);
+ // the cache has to be checked before calling this method
+ const connectivity::ORowSetValue& impl_getValue(sal_Int32 columnIndex);
+ // sets the current and the bookmark
+ void setCurrentRow( bool _bMoved, bool _bDoNotify, const ORowSetRow& _rOldValues, ::osl::ResettableMutexGuard& _rGuard);
+ /// @throws css::sdbc::SQLException
+ /// @throws css::uno::RuntimeException
+ void checkPositioningAllowed();
+ // checks if the cache is null
+ void checkCache();
+ // sets the bookmark to Any()
+ // m_aCurrentRow to end of matrix
+ // m_aOldRow to NULL
+ void movementFailed();
+
+ ORowSetRow getOldRow(bool _bWasNew);
+ /** move the cache the position defined by the member functor
+ @param _aCheckFunctor
+ Return <TRUE/> when we already stand on the row we want to.
+ @param _aMovementFunctor
+ The method used to move.
+ @return
+ <TRUE/> if movement was successful.
+ */
+ bool SAL_CALL move( std::function<bool(ORowSetBase *)> const & _aCheckFunctor,
+ std::function<bool(ORowSetCache *)> const & _aMovementFunctor);
+
+ /** same meaning as isFirst. Only need by mem_fun
+ @return
+ <TRUE/> if so.
+ */
+ bool isOnFirst();
+ /** same meaning as isLast. Only need by mem_fun
+ @return
+ <TRUE/> if so.
+ */
+ bool isOnLast();
+
+ /** returns the current row count
+
+ This function takes into account that we might actually be positioned on a
+ deleted row, so that m_pCache->m_nRowCount does not really reflect the actual
+ count.
+
+ @precond
+ Our mutex is locked.
+ */
+ sal_Int32 impl_getRowCount() const;
+
+ // the checkCache has to be called before calling this methods
+ sal_Int32 impl_getRow();
+ bool impl_rowDeleted();
+
+ public:
+ virtual ~ORowSetBase() override;
+
+ // OComponentHelper
+ virtual void SAL_CALL disposing();
+
+ // css::beans::XPropertySet
+ virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo( ) override
+ {
+ return ::cppu::OPropertySetHelper::createPropertySetInfo(getInfoHelper());
+ }
+
+ // comphelper::OPropertyArrayUsageHelper
+ virtual ::cppu::IPropertyArrayHelper* createArrayHelper( ) const override;
+
+ // cppu::OPropertySetHelper
+ virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper() override;
+
+ // css::lang::XTypeProvider
+ virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes() override;
+
+ // css::uno::XInterface
+ virtual css::uno::Any SAL_CALL queryInterface( const css::uno::Type & rType ) override;
+
+ // css::sdbc::XWarningsSupplier
+ virtual css::uno::Any SAL_CALL getWarnings( ) override;
+ virtual void SAL_CALL clearWarnings( ) override;
+
+ // css::sdbc::XResultSetMetaDataSupplier
+ virtual css::uno::Reference< css::sdbc::XResultSetMetaData > SAL_CALL getMetaData( ) override;
+
+ // css::sdbc::XColumnLocate
+ virtual sal_Int32 SAL_CALL findColumn( const OUString& columnName ) override;
+
+ // css::sdbcx::XColumnsSupplier
+ virtual css::uno::Reference< css::container::XNameAccess > SAL_CALL getColumns( ) override;
+
+ // css::sdbc::XRow
+ virtual sal_Bool SAL_CALL wasNull( ) override;
+ virtual OUString SAL_CALL getString( sal_Int32 columnIndex ) override;
+ virtual sal_Bool SAL_CALL getBoolean( sal_Int32 columnIndex ) override;
+ virtual sal_Int8 SAL_CALL getByte( sal_Int32 columnIndex ) override;
+ virtual sal_Int16 SAL_CALL getShort( sal_Int32 columnIndex ) override;
+ virtual sal_Int32 SAL_CALL getInt( sal_Int32 columnIndex ) override;
+ virtual sal_Int64 SAL_CALL getLong( sal_Int32 columnIndex ) override;
+ virtual float SAL_CALL getFloat( sal_Int32 columnIndex ) override;
+ virtual double SAL_CALL getDouble( sal_Int32 columnIndex ) override;
+ virtual css::uno::Sequence< sal_Int8 > SAL_CALL getBytes( sal_Int32 columnIndex ) override;
+ virtual css::util::Date SAL_CALL getDate( sal_Int32 columnIndex ) override;
+ virtual css::util::Time SAL_CALL getTime( sal_Int32 columnIndex ) override;
+ virtual css::util::DateTime SAL_CALL getTimestamp( sal_Int32 columnIndex ) override;
+ virtual css::uno::Reference< css::io::XInputStream > SAL_CALL getBinaryStream( sal_Int32 columnIndex ) override;
+ virtual css::uno::Reference< css::io::XInputStream > SAL_CALL getCharacterStream( sal_Int32 columnIndex ) override;
+ virtual css::uno::Any SAL_CALL getObject( sal_Int32 columnIndex, const css::uno::Reference< css::container::XNameAccess >& typeMap ) override;
+ virtual css::uno::Reference< css::sdbc::XRef > SAL_CALL getRef( sal_Int32 columnIndex ) override;
+ virtual css::uno::Reference< css::sdbc::XBlob > SAL_CALL getBlob( sal_Int32 columnIndex ) override;
+ virtual css::uno::Reference< css::sdbc::XClob > SAL_CALL getClob( sal_Int32 columnIndex ) override;
+ virtual css::uno::Reference< css::sdbc::XArray > SAL_CALL getArray( sal_Int32 columnIndex ) override;
+
+ // css::sdbcx::XRowLocate
+ virtual css::uno::Any SAL_CALL getBookmark( ) override;
+ virtual sal_Bool SAL_CALL moveToBookmark( const css::uno::Any& bookmark ) override;
+ virtual sal_Bool SAL_CALL moveRelativeToBookmark( const css::uno::Any& bookmark, sal_Int32 rows ) override;
+ virtual sal_Int32 SAL_CALL compareBookmarks( const css::uno::Any& first, const css::uno::Any& second ) override;
+ virtual sal_Bool SAL_CALL hasOrderedBookmarks( ) override;
+ virtual sal_Int32 SAL_CALL hashBookmark( const css::uno::Any& bookmark ) override;
+
+ // css::sdbc::XResultSet
+ virtual sal_Bool SAL_CALL next( ) override;
+ virtual sal_Bool SAL_CALL isBeforeFirst( ) override;
+ virtual sal_Bool SAL_CALL isAfterLast( ) override;
+ virtual sal_Bool SAL_CALL isFirst( ) override;
+ virtual sal_Bool SAL_CALL isLast( ) override;
+ virtual void SAL_CALL beforeFirst( ) override;
+ virtual void SAL_CALL afterLast( ) override;
+ virtual sal_Bool SAL_CALL first( ) override;
+ virtual sal_Bool SAL_CALL last( ) override;
+ virtual sal_Int32 SAL_CALL getRow( ) override;
+ virtual sal_Bool SAL_CALL absolute( sal_Int32 row ) override;
+ virtual sal_Bool SAL_CALL relative( sal_Int32 rows ) override;
+ virtual sal_Bool SAL_CALL previous( ) override;
+ virtual void SAL_CALL refreshRow( ) override;
+ virtual sal_Bool SAL_CALL rowUpdated( ) override;
+ virtual sal_Bool SAL_CALL rowInserted( ) override;
+ virtual sal_Bool SAL_CALL rowDeleted( ) override;
+ virtual css::uno::Reference< css::uno::XInterface > SAL_CALL getStatement( ) override;
+
+ // css::sdbc::XRowSet
+ virtual void SAL_CALL execute( ) override = 0;
+ virtual void SAL_CALL addRowSetListener( const css::uno::Reference< css::sdbc::XRowSetListener >& listener ) override = 0;
+ virtual void SAL_CALL removeRowSetListener( const css::uno::Reference< css::sdbc::XRowSetListener >& listener ) override = 0;
+
+ // is called when the rowset is going to delete this bookmark _rBookmark
+ void onDeleteRow( const css::uno::Any& _rBookmark );
+ // is called when the rowset has deleted this bookmark _rBookmark
+ void onDeletedRow( const css::uno::Any& _rBookmark, sal_Int32 _nPos );
+
+ // granular access control
+ struct GrantNotifierAccess { friend class ORowSetNotifier; private: GrantNotifierAccess () { } };
+
+ // cancel the insertion, if necessary (means if we're on the insert row)
+ void doCancelModification( const GrantNotifierAccess& ) { doCancelModification(); }
+ bool isModification( const GrantNotifierAccess& ) { return isModification(); }
+ bool isModified( const GrantNotifierAccess& ) { return isModified(); }
+ bool isNew( const GrantNotifierAccess& ) { return isNew(); }
+ bool isInsertRow() const { return m_bIsInsertRow; } // isNew() || isModified(); }
+ void fireProperty( sal_Int32 _nProperty, bool _bNew, bool _bOld, const GrantNotifierAccess& )
+ {
+ fireProperty( _nProperty, _bNew, _bOld );
+ }
+ void firePropertyChange(sal_Int32 _nPos,const ::connectivity::ORowSetValue& _rNewValue, const GrantNotifierAccess& )
+ {
+ firePropertyChange(_nPos,_rNewValue);
+ }
+ using ::comphelper::OPropertyStateContainer::getFastPropertyValue;
+ };
+
+ /** eases the handling of the doCancelModification and notifyCancelInsert methods
+
+ <p>The class can only be used on the stack, within a method of ORowSetBase (or derivees)</p>
+ */
+ struct ORowSetNotifierImpl;
+ class ORowSetNotifier
+ {
+ private:
+ std::unique_ptr<ORowSetNotifierImpl> m_pImpl;
+ ORowSetBase* m_pRowSet;
+ // not acquired! This is not necessary because this class here is to be used on the stack within
+ // a method of ORowSetBase (or derivees)
+ bool m_bWasNew;
+ bool m_bWasModified;
+
+ public:
+ /** constructs the object, and cancels the insertion
+
+ @see ORowSetBase::doCancelModification
+ */
+ explicit ORowSetNotifier( ORowSetBase* m_pRowSet );
+
+ /** use this one to construct a vector for change value notification
+ */
+ ORowSetNotifier( ORowSetBase* m_pRowSet, ORowSetValueVector::Vector&& i_aRow );
+
+ // destructs the object. <member>fire</member> has to be called before.
+ ~ORowSetNotifier( );
+
+ /** notifies the insertion
+
+ <p>This has <em>not</em> been put into the destructor by intention!<br/>
+
+ The destructor is called during stack unwinding in case of an exception, so if we would do
+ listener notification there, this would have the potential of another exception during stack
+ unwinding, which would terminate the application.</p>
+
+ @see ORowSetBase::notifyCancelInsert
+ */
+ void fire();
+
+ /** notifies value change events and notifies IsModified
+ @param i_aChangedColumns the index of the changed value columns
+ @param i_aRow the old values
+ @see ORowSetBase::notifyCancelInsert
+ */
+ void firePropertyChange();
+
+ /** use this one to store the inde of the changed column values
+ */
+ std::vector<sal_Int32>& getChangedColumns() const;
+
+ };
+
+} // end of namespace
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/api/RowSetCache.cxx b/dbaccess/source/core/api/RowSetCache.cxx
new file mode 100644
index 000000000..8a23d6624
--- /dev/null
+++ b/dbaccess/source/core/api/RowSetCache.cxx
@@ -0,0 +1,1713 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <memory>
+#include "BookmarkSet.hxx"
+#include "KeySet.hxx"
+#include "OptimisticSet.hxx"
+#include "RowSetBase.hxx"
+#include "RowSetCache.hxx"
+#include "StaticSet.hxx"
+#include "WrappedResultSet.hxx"
+#include <core_resource.hxx>
+#include <strings.hrc>
+#include <strings.hxx>
+
+#include <com/sun/star/sdbc/ColumnValue.hpp>
+#include <com/sun/star/sdbc/ResultSetConcurrency.hpp>
+#include <com/sun/star/sdbc/ResultSetType.hpp>
+#include <com/sun/star/sdbcx/CompareBookmark.hpp>
+#include <com/sun/star/sdbcx/Privilege.hpp>
+#include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
+#include <com/sun/star/sdbcx/XTablesSupplier.hpp>
+
+#include <comphelper/extract.hxx>
+#include <comphelper/types.hxx>
+#include <connectivity/dbexception.hxx>
+#include <connectivity/dbtools.hxx>
+#include <connectivity/sqliterator.hxx>
+#include <connectivity/sqlnode.hxx>
+#include <connectivity/sqlparse.hxx>
+#include <sqlbison.hxx>
+#include <tools/diagnose_ex.h>
+#include <o3tl/safeint.hxx>
+#include <osl/diagnose.h>
+
+#include <algorithm>
+
+using namespace dbaccess;
+using namespace dbtools;
+using namespace connectivity;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::sdb;
+using namespace ::com::sun::star::sdbcx;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::lang;
+using namespace ::cppu;
+using namespace ::osl;
+
+// This class calls m_pCacheSet->FOO_checked(..., sal_False)
+// (where FOO is absolute, last, previous)
+// when it does not immediately care about the values in the row's columns.
+// As a corollary, m_pCacheSet may be left in an inconsistent state,
+// and all ->fillFOO calls (and ->getFOO) may fail or give wrong results,
+// until m_pCacheSet is moved (or refreshed) again.
+// So always make sure m_pCacheSet is moved or refreshed before accessing column values.
+
+
+ORowSetCache::ORowSetCache(const Reference< XResultSet >& _xRs,
+ const Reference< XSingleSelectQueryAnalyzer >& _xAnalyzer,
+ const Reference<XComponentContext>& _rContext,
+ const OUString& _rUpdateTableName,
+ bool& _bModified,
+ bool& _bNew,
+ const ORowSetValueVector& _aParameterValueForCache,
+ const OUString& i_sRowSetFilter,
+ sal_Int32 i_nMaxRows)
+ :m_xSet(_xRs)
+ ,m_xMetaData(Reference< XResultSetMetaDataSupplier >(_xRs,UNO_QUERY_THROW)->getMetaData())
+ ,m_aContext( _rContext )
+ ,m_nFetchSize(0)
+ ,m_nRowCount(0)
+ ,m_nPrivileges( Privilege::SELECT )
+ ,m_nPosition(0)
+ ,m_nStartPos(0)
+ ,m_nEndPos(0)
+ ,m_bRowCountFinal(false)
+ ,m_bBeforeFirst(true)
+ ,m_bAfterLast( false )
+ ,m_bModified(_bModified)
+ ,m_bNew(_bNew)
+{
+
+ // first try if the result can be used to do inserts and updates
+ Reference< XPropertySet> xProp(_xRs,UNO_QUERY);
+ Reference< XPropertySetInfo > xPropInfo = xProp->getPropertySetInfo();
+ bool bBookmarkable = false;
+ try
+ {
+ Reference< XResultSetUpdate> xUp(_xRs,UNO_QUERY_THROW);
+ bBookmarkable = xPropInfo->hasPropertyByName(PROPERTY_ISBOOKMARKABLE) &&
+ any2bool(xProp->getPropertyValue(PROPERTY_ISBOOKMARKABLE)) && Reference< XRowLocate >(_xRs, UNO_QUERY).is();
+ if ( bBookmarkable )
+ {
+ xUp->moveToInsertRow();
+ xUp->cancelRowUpdates();
+ _xRs->beforeFirst();
+ m_nPrivileges = Privilege::SELECT|Privilege::DELETE|Privilege::INSERT|Privilege::UPDATE;
+ m_xCacheSet = new WrappedResultSet(i_nMaxRows);
+ m_xCacheSet->construct(_xRs,i_sRowSetFilter);
+ return;
+ }
+ }
+ catch(const Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess.core");
+ }
+ try
+ {
+ if ( xPropInfo->hasPropertyByName(PROPERTY_RESULTSETTYPE) &&
+ ::comphelper::getINT32(xProp->getPropertyValue(PROPERTY_RESULTSETTYPE)) != ResultSetType::FORWARD_ONLY)
+ _xRs->beforeFirst();
+ }
+ catch(const SQLException&)
+ {
+ TOOLS_WARN_EXCEPTION("dbaccess.core", "ORowSetCache");
+ }
+
+ // check if all keys of the updateable table are fetched
+ bool bAllKeysFound = false;
+ sal_Int32 nTablesCount = 0;
+
+ bool bNeedKeySet = !bBookmarkable || (xPropInfo->hasPropertyByName(PROPERTY_RESULTSETCONCURRENCY) &&
+ ::comphelper::getINT32(xProp->getPropertyValue(PROPERTY_RESULTSETCONCURRENCY)) == ResultSetConcurrency::READ_ONLY);
+
+ OUString aUpdateTableName = _rUpdateTableName;
+ Reference< XConnection> xConnection;
+ // first we need a connection
+ Reference< XStatement> xStmt(_xRs->getStatement(),UNO_QUERY);
+ if(xStmt.is())
+ xConnection = xStmt->getConnection();
+ else
+ {
+ Reference< XPreparedStatement> xPrepStmt(_xRs->getStatement(),UNO_QUERY);
+ xConnection = xPrepStmt->getConnection();
+ }
+ OSL_ENSURE(xConnection.is(),"No connection!");
+ if(_xAnalyzer.is())
+ {
+ try
+ {
+ Reference<XTablesSupplier> xTabSup(_xAnalyzer,UNO_QUERY);
+ OSL_ENSURE(xTabSup.is(),"ORowSet::execute composer isn't a tablesupplier!");
+ Reference<XNameAccess> xTables = xTabSup->getTables();
+ Sequence< OUString> aTableNames = xTables->getElementNames();
+ if ( aTableNames.getLength() > 1 && _rUpdateTableName.isEmpty() && bNeedKeySet )
+ {// here we have a join or union and nobody told us which table to update, so we update them all
+ m_nPrivileges = Privilege::SELECT|Privilege::DELETE|Privilege::INSERT|Privilege::UPDATE;
+ rtl::Reference<OptimisticSet> pCursor = new OptimisticSet(m_aContext,xConnection,_xAnalyzer,_aParameterValueForCache,i_nMaxRows,m_nRowCount);
+ m_xCacheSet = pCursor;
+ try
+ {
+ m_xCacheSet->construct(_xRs,i_sRowSetFilter);
+ if ( pCursor->isReadOnly() )
+ m_nPrivileges = Privilege::SELECT;
+ m_aKeyColumns = pCursor->getJoinedKeyColumns();
+ return;
+ }
+ catch (const Exception&)
+ {
+ TOOLS_WARN_EXCEPTION("dbaccess.core", "ORowSetCache");
+ }
+ m_xCacheSet.clear();
+ }
+ else
+ {
+ if(!_rUpdateTableName.isEmpty() && xTables->hasByName(_rUpdateTableName))
+ xTables->getByName(_rUpdateTableName) >>= m_aUpdateTable;
+ else if(xTables->getElementNames().hasElements())
+ {
+ aUpdateTableName = xTables->getElementNames()[0];
+ xTables->getByName(aUpdateTableName) >>= m_aUpdateTable;
+ }
+ Reference<XIndexAccess> xIndexAccess(xTables,UNO_QUERY);
+ if(xIndexAccess.is())
+ nTablesCount = xIndexAccess->getCount();
+ else
+ nTablesCount = xTables->getElementNames().getLength();
+
+ if(m_aUpdateTable.is() && nTablesCount < 3) // for we can't handle more than 2 tables in our keyset
+ {
+ Reference<XPropertySet> xSet(m_aUpdateTable,UNO_QUERY);
+ const Reference<XNameAccess> xPrimaryKeyColumns = dbtools::getPrimaryKeyColumns_throw(xSet);
+ if ( xPrimaryKeyColumns.is() )
+ {
+ Reference<XColumnsSupplier> xColSup(_xAnalyzer,UNO_QUERY);
+ if ( xColSup.is() )
+ {
+ Reference<XNameAccess> xSelColumns = xColSup->getColumns();
+ Reference<XDatabaseMetaData> xMeta = xConnection->getMetaData();
+ SelectColumnsMetaData aColumnNames(xMeta.is() && xMeta->supportsMixedCaseQuotedIdentifiers());
+ ::dbaccess::getColumnPositions(xSelColumns,xPrimaryKeyColumns->getElementNames(),aUpdateTableName,aColumnNames);
+ bAllKeysFound = !aColumnNames.empty() && aColumnNames.size() == o3tl::make_unsigned(xPrimaryKeyColumns->getElementNames().getLength());
+ }
+ }
+ }
+ }
+ }
+ catch (Exception const&)
+ {
+ TOOLS_WARN_EXCEPTION("dbaccess.core", "ORowSetCache");
+ }
+ }
+
+ // first check if resultset is bookmarkable
+ if(!bNeedKeySet)
+ {
+ try
+ {
+ m_xCacheSet = new OBookmarkSet(i_nMaxRows);
+ m_xCacheSet->construct(_xRs,i_sRowSetFilter);
+
+ // check privileges
+ m_nPrivileges = Privilege::SELECT;
+ if(Reference<XResultSetUpdate>(_xRs,UNO_QUERY).is()) // this interface is optional so we have to check it
+ {
+ Reference<XPropertySet> xTable(m_aUpdateTable,UNO_QUERY);
+ if(xTable.is() && xTable->getPropertySetInfo()->hasPropertyByName(PROPERTY_PRIVILEGES))
+ {
+ m_nPrivileges = 0;
+ xTable->getPropertyValue(PROPERTY_PRIVILEGES) >>= m_nPrivileges;
+ if(!m_nPrivileges)
+ m_nPrivileges = Privilege::SELECT;
+ }
+ }
+ }
+ catch (const SQLException&)
+ {
+ TOOLS_WARN_EXCEPTION("dbaccess.core", "ORowSetCache");
+ bNeedKeySet = true;
+ }
+
+ }
+ if(bNeedKeySet)
+ {
+ // need to check if we could handle this select clause
+ bAllKeysFound = bAllKeysFound && (nTablesCount == 1 || checkJoin(xConnection,_xAnalyzer,aUpdateTableName));
+
+ if(!bAllKeysFound )
+ {
+ if ( bBookmarkable )
+ {
+ // here I know that we have a read only bookmarkable cursor
+ _xRs->beforeFirst();
+ m_nPrivileges = Privilege::SELECT;
+ m_xCacheSet = new WrappedResultSet(i_nMaxRows);
+ m_xCacheSet->construct(_xRs,i_sRowSetFilter);
+ return;
+ }
+ m_xCacheSet = new OStaticSet(i_nMaxRows);
+ m_xCacheSet->construct(_xRs,i_sRowSetFilter);
+ m_nPrivileges = Privilege::SELECT;
+ }
+ else
+ {
+ Reference<XDatabaseMetaData> xMeta = xConnection->getMetaData();
+ SelectColumnsMetaData aColumnNames(xMeta.is() && xMeta->supportsMixedCaseQuotedIdentifiers());
+ Reference<XColumnsSupplier> xColSup(_xAnalyzer,UNO_QUERY);
+ Reference<XNameAccess> xSelColumns = xColSup->getColumns();
+ Reference<XNameAccess> xColumns = m_aUpdateTable->getColumns();
+ ::dbaccess::getColumnPositions(xSelColumns,xColumns->getElementNames(),aUpdateTableName,aColumnNames);
+
+ // check privileges
+ m_nPrivileges = Privilege::SELECT;
+ bool bNoInsert = false;
+
+ Sequence< OUString> aNames(xColumns->getElementNames());
+ const OUString* pIter = aNames.getConstArray();
+ const OUString* pEnd = pIter + aNames.getLength();
+ for(;pIter != pEnd;++pIter)
+ {
+ Reference<XPropertySet> xColumn(xColumns->getByName(*pIter),UNO_QUERY);
+ OSL_ENSURE(xColumn.is(),"Column in table is null!");
+ if(xColumn.is())
+ {
+ sal_Int32 nNullable = 0;
+ xColumn->getPropertyValue(PROPERTY_ISNULLABLE) >>= nNullable;
+ if(nNullable == ColumnValue::NO_NULLS && aColumnNames.find(*pIter) == aColumnNames.end())
+ { // we found a column where null is not allowed so we can't insert new values
+ bNoInsert = true;
+ break; // one column is enough
+ }
+ }
+ }
+
+ rtl::Reference<OKeySet> pKeySet = new OKeySet(m_aUpdateTable, aUpdateTableName ,_xAnalyzer,_aParameterValueForCache,i_nMaxRows,m_nRowCount);
+ try
+ {
+ m_xCacheSet = pKeySet;
+ pKeySet->construct(_xRs,i_sRowSetFilter);
+
+ if(Reference<XResultSetUpdate>(_xRs,UNO_QUERY).is()) // this interface is optional so we have to check it
+ {
+ Reference<XPropertySet> xTable(m_aUpdateTable,UNO_QUERY);
+ if(xTable.is() && xTable->getPropertySetInfo()->hasPropertyByName(PROPERTY_PRIVILEGES))
+ {
+ m_nPrivileges = 0;
+ xTable->getPropertyValue(PROPERTY_PRIVILEGES) >>= m_nPrivileges;
+ if(!m_nPrivileges)
+ m_nPrivileges = Privilege::SELECT;
+ }
+ }
+ if(bNoInsert)
+ m_nPrivileges |= ~Privilege::INSERT; // remove the insert privilege
+ }
+ catch (const SQLException&)
+ {
+ TOOLS_WARN_EXCEPTION("dbaccess.core", "ORowSetCache");
+ // we couldn't create a keyset here so we have to create a static cache
+ m_xCacheSet = new OStaticSet(i_nMaxRows);
+ m_xCacheSet->construct(_xRs,i_sRowSetFilter);
+ m_nPrivileges = Privilege::SELECT;
+ }
+ }
+
+ }
+ // last check
+ if(!bAllKeysFound && xProp->getPropertySetInfo()->hasPropertyByName(PROPERTY_RESULTSETCONCURRENCY) &&
+ ::comphelper::getINT32(xProp->getPropertyValue(PROPERTY_RESULTSETCONCURRENCY)) == ResultSetConcurrency::READ_ONLY)
+ m_nPrivileges = Privilege::SELECT;
+}
+
+ORowSetCache::~ORowSetCache()
+{
+ m_xCacheSet.clear();
+ if(m_pMatrix)
+ {
+ m_pMatrix->clear();
+ m_pMatrix.reset();
+ }
+
+ if(m_pInsertMatrix)
+ {
+ m_pInsertMatrix->clear();
+ m_pInsertMatrix.reset();
+ }
+ m_xSet = WeakReference< XResultSet>();
+ m_xMetaData = nullptr;
+ m_aUpdateTable = nullptr;
+}
+
+void ORowSetCache::setFetchSize(sal_Int32 _nSize)
+{
+ if(_nSize == m_nFetchSize)
+ return;
+
+ m_nFetchSize = _nSize;
+ if(!m_pMatrix)
+ {
+ m_pMatrix.reset( new ORowSetMatrix(_nSize) );
+ m_aMatrixIter = m_pMatrix->end();
+ m_aMatrixEnd = m_pMatrix->end();
+
+ m_pInsertMatrix.reset( new ORowSetMatrix(1) ); // a little bit overkill but ??? :-)
+ m_aInsertRow = m_pInsertMatrix->end();
+ }
+ else
+ {
+ // now correct the iterator in our iterator vector
+ std::vector<sal_Int32> aPositions;
+ std::map<sal_Int32,bool> aCacheIterToChange;
+ // first get the positions where they stand now
+ for(const auto& [rIndex, rHelper] : m_aCacheIterators)
+ {
+ aCacheIterToChange[rIndex] = false;
+ if ( !rHelper.pRowSet->isInsertRow()
+ /*&& rHelper.aIterator != m_pMatrix->end()*/ && !m_bModified )
+ {
+ ptrdiff_t nDist = rHelper.aIterator - m_pMatrix->begin();
+ aPositions.push_back(nDist);
+ aCacheIterToChange[rIndex] = true;
+ }
+ }
+ sal_Int32 nKeyPos = m_aMatrixIter - m_pMatrix->begin();
+ m_pMatrix->resize(_nSize);
+
+ if ( nKeyPos < _nSize )
+ m_aMatrixIter = m_pMatrix->begin() + nKeyPos;
+ else
+ m_aMatrixIter = m_pMatrix->end();
+ m_aMatrixEnd = m_pMatrix->end();
+
+ // now adjust their positions because a resize invalidates all iterators
+ std::vector<sal_Int32>::const_iterator aIter = aPositions.begin();
+ ORowSetCacheMap::iterator aCacheIter = m_aCacheIterators.begin();
+ for(const auto& rPosChange : aCacheIterToChange)
+ {
+ if ( rPosChange.second )
+ {
+ OSL_ENSURE((*aIter >= static_cast<ORowSetMatrix::difference_type>(0)) && (*aIter < static_cast<sal_Int32>(m_pMatrix->size())),"Position is invalid!");
+ if ( *aIter < _nSize )
+ aCacheIter->second.aIterator = m_pMatrix->begin() + *aIter++;
+ else
+ aCacheIter->second.aIterator = m_pMatrix->end();
+ }
+ ++aCacheIter;
+ }
+ }
+ if(!m_nPosition)
+ {
+ sal_Int32 nNewSt = 0;
+ fillMatrix(nNewSt,_nSize);
+ OSL_ENSURE(nNewSt == 0, "fillMatrix set new start to unexpected value");
+ m_nStartPos = 0;
+ m_nEndPos = _nSize;
+ }
+ else if (m_nStartPos < m_nPosition && m_nPosition <= m_nEndPos)
+ {
+ sal_Int32 nNewSt = -1;
+ _nSize += m_nStartPos;
+ fillMatrix(nNewSt, _nSize);
+ if (nNewSt >= 0)
+ {
+ m_nStartPos = nNewSt;
+ m_nEndPos = _nSize;
+ m_aMatrixIter = calcPosition();
+ }
+ else
+ {
+ m_nEndPos = m_nStartPos + m_nFetchSize;
+ }
+ }
+ else
+ {
+ OSL_FAIL("m_nPosition not between m_nStartPos and m_nEndpos");
+ // try to repair
+ moveWindow();
+ m_aMatrixIter = calcPosition();
+ }
+}
+
+// XResultSetMetaDataSupplier
+
+static Any lcl_getBookmark(ORowSetValue& i_aValue,OCacheSet* i_pCacheSet)
+{
+ switch ( i_aValue.getTypeKind() )
+ {
+ case DataType::TINYINT:
+ case DataType::SMALLINT:
+ case DataType::INTEGER:
+ return Any(i_aValue.getInt32());
+ default:
+ if ( i_pCacheSet && i_aValue.isNull())
+ i_aValue = i_pCacheSet->getBookmark();
+ return i_aValue.getAny();
+ }
+}
+
+// css::sdbcx::XRowLocate
+Any ORowSetCache::getBookmark( )
+{
+ if(m_bAfterLast)
+ throwFunctionSequenceException(m_xSet.get());
+
+ if ( m_aMatrixIter >= m_pMatrix->end() || m_aMatrixIter < m_pMatrix->begin() || !(*m_aMatrixIter).is())
+ {
+ return Any(); // this is allowed here because the rowset knows what it is doing
+ }
+
+ return lcl_getBookmark((**m_aMatrixIter)[0],m_xCacheSet.get());
+}
+
+bool ORowSetCache::moveToBookmark( const Any& bookmark )
+{
+ if ( m_xCacheSet->moveToBookmark(bookmark) )
+ {
+ m_bBeforeFirst = false;
+ m_nPosition = m_xCacheSet->getRow();
+
+ checkPositionFlags();
+
+ if(!m_bAfterLast)
+ {
+ moveWindow();
+ checkPositionFlags();
+ if ( !m_bAfterLast )
+ {
+ m_aMatrixIter = calcPosition();
+ OSL_ENSURE(m_aMatrixIter->is(),"Iterator after moveToBookmark not valid");
+ }
+ else
+ m_aMatrixIter = m_pMatrix->end();
+ }
+ else
+ m_aMatrixIter = m_pMatrix->end();
+ }
+ else
+ return false;
+
+ return m_aMatrixIter != m_pMatrix->end() && (*m_aMatrixIter).is();
+}
+
+bool ORowSetCache::moveRelativeToBookmark( const Any& bookmark, sal_Int32 rows )
+{
+ bool bRet( moveToBookmark( bookmark ) );
+ if ( bRet )
+ {
+ m_nPosition = m_xCacheSet->getRow() + rows;
+ absolute(m_nPosition);
+
+ bRet = m_aMatrixIter != m_pMatrix->end() && (*m_aMatrixIter).is();
+ }
+
+ return bRet;
+}
+
+sal_Int32 ORowSetCache::compareBookmarks( const Any& _first, const Any& _second )
+{
+ return (!_first.hasValue() || !_second.hasValue()) ? CompareBookmark::NOT_COMPARABLE : m_xCacheSet->compareBookmarks(_first,_second);
+}
+
+bool ORowSetCache::hasOrderedBookmarks( )
+{
+ return m_xCacheSet->hasOrderedBookmarks();
+}
+
+sal_Int32 ORowSetCache::hashBookmark( const Any& bookmark )
+{
+ return m_xCacheSet->hashBookmark(bookmark);
+}
+
+// XRowUpdate
+void ORowSetCache::updateNull(sal_Int32 columnIndex,ORowSetValueVector::Vector& io_aRow
+ ,std::vector<sal_Int32>& o_ChangedColumns
+ )
+{
+ checkUpdateConditions(columnIndex);
+
+ ORowSetValueVector::Vector& rInsert = **m_aInsertRow;
+ if ( !rInsert[columnIndex].isNull() )
+ {
+ rInsert[columnIndex].setBound(true);
+ rInsert[columnIndex].setNull();
+ rInsert[columnIndex].setModified(true);
+ io_aRow[columnIndex].setNull();
+
+ m_xCacheSet->mergeColumnValues(columnIndex,rInsert,io_aRow,o_ChangedColumns);
+ impl_updateRowFromCache_throw(io_aRow,o_ChangedColumns);
+ }
+}
+
+void ORowSetCache::updateValue(sal_Int32 columnIndex,const ORowSetValue& x
+ ,ORowSetValueVector::Vector& io_aRow
+ ,std::vector<sal_Int32>& o_ChangedColumns
+ )
+{
+ checkUpdateConditions(columnIndex);
+
+ ORowSetValueVector::Vector& rInsert = **m_aInsertRow;
+ if ( rInsert[columnIndex] != x )
+ {
+ rInsert[columnIndex].setBound(true);
+ rInsert[columnIndex] = x;
+ rInsert[columnIndex].setModified(true);
+ io_aRow[columnIndex] = rInsert[columnIndex];
+
+ m_xCacheSet->mergeColumnValues(columnIndex,rInsert,io_aRow,o_ChangedColumns);
+ impl_updateRowFromCache_throw(io_aRow,o_ChangedColumns);
+ }
+}
+
+void ORowSetCache::updateCharacterStream( sal_Int32 columnIndex, const Reference< css::io::XInputStream >& x
+ , sal_Int32 length,ORowSetValueVector::Vector& io_aRow
+ ,std::vector<sal_Int32>& o_ChangedColumns
+ )
+{
+ checkUpdateConditions(columnIndex);
+
+ Sequence<sal_Int8> aSeq;
+ if(x.is())
+ x->readBytes(aSeq,length);
+
+ ORowSetValueVector::Vector& rInsert = **m_aInsertRow;
+ rInsert[columnIndex].setBound(true);
+ rInsert[columnIndex] = aSeq;
+ rInsert[columnIndex].setModified(true);
+ io_aRow[columnIndex] = Any(x);
+
+ m_xCacheSet->mergeColumnValues(columnIndex,rInsert,io_aRow,o_ChangedColumns);
+ impl_updateRowFromCache_throw(io_aRow,o_ChangedColumns);
+}
+
+void ORowSetCache::updateObject( sal_Int32 columnIndex, const Any& x
+ ,ORowSetValueVector::Vector& io_aRow
+ ,std::vector<sal_Int32>& o_ChangedColumns
+ )
+{
+ checkUpdateConditions(columnIndex);
+
+ ORowSetValueVector::Vector& rInsert = **m_aInsertRow;
+ ORowSetValue aTemp;
+ aTemp.fill(x);
+ if ( rInsert[columnIndex] != aTemp )
+ {
+ rInsert[columnIndex].setBound(true);
+ rInsert[columnIndex] = aTemp;
+ rInsert[columnIndex].setModified(true);
+ io_aRow[columnIndex] = rInsert[columnIndex];
+
+ m_xCacheSet->mergeColumnValues(columnIndex,rInsert,io_aRow,o_ChangedColumns);
+ impl_updateRowFromCache_throw(io_aRow,o_ChangedColumns);
+ }
+}
+
+void ORowSetCache::updateNumericObject( sal_Int32 columnIndex, const Any& x
+ ,ORowSetValueVector::Vector& io_aRow
+ ,std::vector<sal_Int32>& o_ChangedColumns
+ )
+{
+ checkUpdateConditions(columnIndex);
+
+ ORowSetValueVector::Vector& rInsert = **m_aInsertRow;
+ ORowSetValue aTemp;
+ aTemp.fill(x);
+ if ( rInsert[columnIndex] != aTemp )
+ {
+ rInsert[columnIndex].setBound(true);
+ rInsert[columnIndex] = aTemp;
+ rInsert[columnIndex].setModified(true);
+ io_aRow[columnIndex] = rInsert[columnIndex];
+
+ m_xCacheSet->mergeColumnValues(columnIndex,rInsert,io_aRow,o_ChangedColumns);
+ impl_updateRowFromCache_throw(io_aRow,o_ChangedColumns);
+ }
+}
+
+// XResultSet
+bool ORowSetCache::next( )
+{
+ if(!isAfterLast())
+ {
+ m_bBeforeFirst = false;
+ ++m_nPosition;
+
+ // after we increment the position we have to check if we are already after the last row
+ checkPositionFlags();
+ if(!m_bAfterLast)
+ {
+ moveWindow();
+
+ OSL_ENSURE(((m_nPosition - m_nStartPos) - 1) < static_cast<sal_Int32>(m_pMatrix->size()),"Position is behind end()!");
+ m_aMatrixIter = calcPosition();
+ checkPositionFlags();
+ }
+ }
+
+ return !m_bAfterLast;
+}
+
+
+bool ORowSetCache::isFirst( ) const
+{
+ return m_nPosition == 1; // ask resultset for
+}
+
+bool ORowSetCache::isLast( ) const
+{
+ return m_nPosition == m_nRowCount;
+}
+
+void ORowSetCache::beforeFirst( )
+{
+ if(!m_bBeforeFirst)
+ {
+ m_bAfterLast = false;
+ m_nPosition = 0;
+ m_bBeforeFirst = true;
+ m_xCacheSet->beforeFirst();
+ moveWindow();
+ m_aMatrixIter = m_pMatrix->end();
+ }
+}
+
+void ORowSetCache::afterLast( )
+{
+ if(m_bAfterLast)
+ return;
+
+ m_bBeforeFirst = false;
+ m_bAfterLast = true;
+
+ if(!m_bRowCountFinal)
+ {
+ m_xCacheSet->last();
+ m_bRowCountFinal = true;
+ m_nRowCount = m_xCacheSet->getRow();// + 1 removed
+ }
+ m_xCacheSet->afterLast();
+
+ m_nPosition = 0;
+ m_aMatrixIter = m_pMatrix->end();
+}
+
+bool ORowSetCache::fillMatrix(sal_Int32& _nNewStartPos, sal_Int32 &_nNewEndPos)
+{
+ OSL_ENSURE((_nNewStartPos != _nNewEndPos) || (_nNewStartPos == 0 && _nNewEndPos == 0 && m_nRowCount == 0),
+ "ORowSetCache::fillMatrix: StartPos and EndPos can not be equal (unless the recordset is empty)!");
+ // If _nNewStartPos >= 0, then fill the whole window with new data
+ // Else if _nNewStartPos == -1, then fill only segment [m_nEndPos, _nNewEndPos)
+ // Else, undefined (invalid argument)
+ OSL_ENSURE( _nNewStartPos >= -1, "ORowSetCache::fillMatrix: invalid _nNewStartPos" );
+
+ ORowSetMatrix::iterator aIter;
+ sal_Int32 i;
+ bool bCheck;
+ sal_Int32 requestedStartPos;
+ if ( _nNewStartPos == -1 )
+ {
+ aIter = m_pMatrix->begin() + (m_nEndPos - m_nStartPos);
+ i = m_nEndPos + 1;
+ requestedStartPos = m_nStartPos;
+ }
+ else
+ {
+ aIter = m_pMatrix->begin();
+ i = _nNewStartPos + 1;
+ requestedStartPos = _nNewStartPos;
+ }
+ bCheck = m_xCacheSet->absolute(i);
+
+
+ for(; i <= _nNewEndPos; ++i,++aIter)
+ {
+ if(bCheck)
+ {
+ if(!aIter->is())
+ *aIter = new ORowSetValueVector(m_xMetaData->getColumnCount());
+ m_xCacheSet->fillValueRow(*aIter,i);
+ }
+ else
+ { // there are no more rows found so we can fetch some before start
+
+ if(!m_bRowCountFinal)
+ {
+ if(m_xCacheSet->previous()) // because we stand after the last row
+ m_nRowCount = m_xCacheSet->getRow(); // here we have the row count
+ if(!m_nRowCount)
+ m_nRowCount = i-1; // it can be that getRow return zero
+ m_bRowCountFinal = true;
+ }
+ const ORowSetMatrix::iterator aEnd = aIter;
+ ORowSetMatrix::const_iterator aRealEnd = m_pMatrix->end();
+ sal_Int32 nPos;
+ if (m_nRowCount >= m_nFetchSize)
+ {
+ nPos = m_nRowCount - m_nFetchSize;
+ }
+ else
+ {
+ nPos = 0;
+ }
+ _nNewStartPos = nPos;
+ _nNewEndPos = m_nRowCount;
+ ++nPos;
+ bCheck = m_xCacheSet->absolute(nPos);
+
+ for(;bCheck && nPos <= requestedStartPos && aIter != aRealEnd; ++aIter, ++nPos)
+ {
+ if(!aIter->is())
+ *aIter = new ORowSetValueVector(m_xMetaData->getColumnCount());
+ m_xCacheSet->fillValueRow(*aIter, nPos);
+ bCheck = m_xCacheSet->next();
+ }
+ if(aIter != aEnd)
+ std::rotate(m_pMatrix->begin(),aEnd,aIter);
+ break;
+ }
+ bCheck = m_xCacheSet->next();
+ }
+ // we have to read one row forward to ensure that we know when we are on last row
+ // but only when we don't know it already
+ if(!m_bRowCountFinal)
+ {
+ if(!m_xCacheSet->next())
+ {
+ if(m_xCacheSet->previous()) // because we stand after the last row
+ m_nRowCount = m_xCacheSet->getRow(); // here we have the row count
+ m_bRowCountFinal = true;
+ }
+ else
+ m_nRowCount = std::max(i,m_nRowCount);
+
+ }
+ return bCheck;
+}
+
+// If m_nPosition is out of the current window,
+// move it and update m_nStartPos and m_nEndPos
+// Caller is responsible for updating m_aMatrixIter
+void ORowSetCache::moveWindow()
+{
+ OSL_ENSURE(m_nStartPos >= 0,"ORowSetCache::moveWindow: m_nStartPos is less than 0!");
+ OSL_ENSURE(m_nEndPos >= m_nStartPos,"ORowSetCache::moveWindow: m_nStartPos not smaller than m_nEndPos");
+ OSL_ENSURE(m_nEndPos-m_nStartPos <= m_nFetchSize,"ORowSetCache::moveWindow: m_nStartPos and m_nEndPos too far apart");
+
+ if ( m_nStartPos < m_nPosition && m_nPosition <= m_nEndPos )
+ {
+ // just move inside the window
+ OSL_ENSURE((m_nPosition - m_nStartPos) <= static_cast<sal_Int32>(m_pMatrix->size()),"Position is behind end()!");
+ // make double plus sure that we have fetched that row
+ m_aMatrixIter = calcPosition();
+ OSL_ENSURE(m_aMatrixIter != m_pMatrix->end(), "New m_aMatrixIter is at end(), but should not.");
+ if(!m_aMatrixIter->is())
+ {
+ bool bOk( m_xCacheSet->absolute( m_nPosition ) );
+ if ( bOk )
+ {
+ *m_aMatrixIter = new ORowSetValueVector(m_xMetaData->getColumnCount());
+ m_xCacheSet->fillValueRow(*m_aMatrixIter,m_nPosition);
+ // we have to read one row forward to ensure that we know when we are on last row
+ // but only when we don't know it already
+ if ( !m_bRowCountFinal )
+ {
+ bOk = m_xCacheSet->absolute( m_nPosition + 1 );
+ if ( bOk )
+ m_nRowCount = std::max(sal_Int32(m_nPosition+1),m_nRowCount);
+ }
+ }
+ if(!bOk && !m_bRowCountFinal)
+ {
+ // because we stand after the last row
+ m_nRowCount = m_xCacheSet->previous() ? m_xCacheSet->getRow() : 0;
+ m_bRowCountFinal = true;
+ }
+ }
+ return;
+ }
+
+ sal_Int32 nDiff = (m_nFetchSize - 1) / 2;
+ sal_Int32 nNewStartPos = (m_nPosition - nDiff) - 1; //m_nPosition is 1-based, but m_nStartPos is 0-based
+ sal_Int32 nNewEndPos = nNewStartPos + m_nFetchSize;
+
+ if ( nNewStartPos < 0 )
+ {
+ // The computed new window crashes through the floor (begins before first row);
+ // nNew*Pos has to be shifted by -nNewStartPos
+ nNewEndPos -= nNewStartPos;
+ nNewStartPos = 0;
+ }
+
+ if ( nNewStartPos < m_nStartPos )
+ { // need to fill data *before* m_nStartPos
+ if ( nNewEndPos > m_nStartPos )
+ { // The two regions are overlapping.
+ // We'll first rotate the contents of m_pMatrix so that the overlap area
+ // is positioned right; in the old window it is at the beginning,
+ // it has to go to the end.
+ // then we fill in the rows between new and old start pos.
+
+ bool bCheck;
+ bCheck = m_xCacheSet->absolute(nNewStartPos + 1);
+
+ // m_nEndPos < nNewEndPos when window not filled (e.g. there are fewer rows in total than window size)
+ m_nEndPos = std::min(nNewEndPos, m_nEndPos);
+ const sal_Int32 nOverlapSize = m_nEndPos - m_nStartPos;
+ const sal_Int32 nStartPosOffset = m_nStartPos - nNewStartPos; // by how much m_nStartPos moves
+ m_nStartPos = nNewStartPos;
+ OSL_ENSURE( o3tl::make_unsigned(nOverlapSize) <= m_pMatrix->size(), "new window end is after end of cache matrix!" );
+ // the first position in m_pMatrix whose data we don't keep;
+ // content will be moved to m_pMatrix.begin()
+ ORowSetMatrix::iterator aEnd (m_pMatrix->begin() + nOverlapSize);
+ // the first unused position after we are done; it == m_pMatrix.end() if and only if the window is full
+ ORowSetMatrix::iterator aNewEnd (aEnd + nStartPosOffset);
+ // *m_pMatrix now looks like:
+ // [0; nOverlapSize) i.e. [begin(); aEnd): data kept
+ // [nOverlapSize; nOverlapSize + nStartPosOffset) i.e. [aEnd, aNewEnd): new data of positions < old m_nStartPos
+ // [nOverlapSize + nStartPosOffset; size()) i.e. [aNewEnd, end()): unused
+ // Note that nOverlapSize + nStartPosOffset == m_nEndPos - m_nStartPos (new values)
+ // When we are finished:
+ // [0; nStartPosOffset) i.e. [begin(); aEnd): new data of positions < old m_nStartPos
+ // [nStartPosOffset; nOverlapSize + nStartPosOffset) i.e. [aEnd, aNewEnd): kept
+ // [nOverlapSize + nStartPosOffset; size()) i.e. [aNewEnd, end()): unused
+
+ if ( bCheck )
+ {
+ {
+ ORowSetMatrix::iterator aIter(aEnd);
+ sal_Int32 nPos = m_nStartPos + 1;
+ fill(aIter, aNewEnd, nPos, bCheck);
+ }
+
+ std::rotate(m_pMatrix->begin(), aEnd, aNewEnd);
+ if (!m_bModified)
+ {
+ // now correct the iterator in our iterator vector
+ // rotateCacheIterator(aEnd-m_pMatrix->begin()); //can't be used because they decrement and here we need to increment
+ for(auto& rCacheIter : m_aCacheIterators)
+ {
+ if ( !rCacheIter.second.pRowSet->isInsertRow()
+ && rCacheIter.second.aIterator != m_pMatrix->end() )
+ {
+ const ptrdiff_t nDist = rCacheIter.second.aIterator - m_pMatrix->begin();
+ if ( nDist >= nOverlapSize )
+ {
+ // That's from outside the overlap area; invalidate iterator.
+ rCacheIter.second.aIterator = m_pMatrix->end();
+ }
+ else
+ {
+ // Inside overlap area: move to correct position
+ OSL_ENSURE(((nDist + nStartPosOffset) >= static_cast<ORowSetMatrix::difference_type>(0)) &&
+ ((nDist + nStartPosOffset) < static_cast<sal_Int32>(m_pMatrix->size())),"Position is invalid!");
+ rCacheIter.second.aIterator += nStartPosOffset;
+ OSL_ENSURE(rCacheIter.second.aIterator >= m_pMatrix->begin()
+ && rCacheIter.second.aIterator < m_pMatrix->end(),"Iterator out of area!");
+ }
+ }
+ }
+ }
+ }
+ else
+ { // normally this should never happen
+ OSL_FAIL("What the hell is happen here!");
+ return;
+ }
+ }
+ else
+ {// no rows can be reused so fill again
+ reFillMatrix(nNewStartPos,nNewEndPos);
+ }
+ }
+
+ OSL_ENSURE(nNewStartPos >= m_nStartPos, "ORowSetCache::moveWindow internal error: new start pos before current start pos");
+ if ( m_nEndPos < nNewEndPos )
+ { // need to fill data *after* m_nEndPos
+ if( nNewStartPos < m_nEndPos )
+ { // The two regions are overlapping.
+ const sal_Int32 nRowsInCache = m_nEndPos - m_nStartPos;
+ if ( nRowsInCache < m_nFetchSize )
+ {
+ // There is some unused space in *m_pMatrix; fill it
+ OSL_ENSURE((nRowsInCache >= static_cast<ORowSetMatrix::difference_type>(0)) && (o3tl::make_unsigned(nRowsInCache) < m_pMatrix->size()),"Position is invalid!");
+ sal_Int32 nPos = m_nEndPos + 1;
+ bool bCheck = m_xCacheSet->absolute(nPos);
+ ORowSetMatrix::iterator aIter = m_pMatrix->begin() + nRowsInCache;
+ const sal_Int32 nRowsToFetch = std::min(nNewEndPos-m_nEndPos, m_nFetchSize-nRowsInCache);
+ const ORowSetMatrix::const_iterator aEnd = aIter + nRowsToFetch;
+ bCheck = fill(aIter, aEnd, nPos, bCheck);
+ m_nEndPos = nPos - 1;
+ OSL_ENSURE( (!bCheck && m_nEndPos <= nNewEndPos ) ||
+ ( bCheck && m_nEndPos == nNewEndPos ),
+ "ORowSetCache::moveWindow opportunistic fetch-after-current-end went badly");
+ }
+
+ // A priori, the rows from begin() [inclusive] to (begin() + nNewStartPos - m_nStartPos) [exclusive]
+ // have to be refilled with new to-be-fetched rows.
+ // The rows behind this can be reused
+ ORowSetMatrix::iterator aIter = m_pMatrix->begin();
+ const sal_Int32 nNewStartPosInMatrix = nNewStartPos - m_nStartPos;
+ OSL_ENSURE((nNewStartPosInMatrix >= static_cast<ORowSetMatrix::difference_type>(0)) && (o3tl::make_unsigned(nNewStartPosInMatrix) < m_pMatrix->size()),"Position is invalid!");
+ // first position we reuse
+ const ORowSetMatrix::const_iterator aEnd = m_pMatrix->begin() + nNewStartPosInMatrix;
+ // End of used portion of the matrix. Is < m_pMatrix->end() if less data than window size
+ ORowSetMatrix::iterator aDataEnd = m_pMatrix->begin() + (m_nEndPos - m_nStartPos);
+
+ sal_Int32 nPos = m_nEndPos + 1;
+ bool bCheck = m_xCacheSet->absolute(nPos);
+ bCheck = fill(aIter, aEnd, nPos, bCheck); // refill the region we don't need anymore
+ //aIter and nPos are now the position *after* last filled in one!
+
+ // bind end to front
+ if(bCheck)
+ {
+ OSL_ENSURE(aIter == aEnd, "fill() said went till end, but did not.");
+ // rotate the end to the front
+ std::rotate(m_pMatrix->begin(), aIter, aDataEnd);
+ // now correct the iterator in our iterator vector
+ rotateCacheIterator( nNewStartPosInMatrix );
+ m_nStartPos = nNewStartPos;
+ m_nEndPos = nNewEndPos;
+ // now I can say how many rows we have
+ // we have to read one row forward to ensure that we know when we are on last row
+ // but only when we don't know it already
+ bool bOk = true;
+ if(!m_bRowCountFinal)
+ bOk = m_xCacheSet->next();
+ if(!bOk)
+ {
+ m_xCacheSet->previous(); // because we stand after the last row
+ m_nRowCount = nPos; // here we have the row count
+ OSL_ENSURE(nPos == m_xCacheSet->getRow(),"nPos is not valid!");
+ m_bRowCountFinal = true;
+ }
+ else if(!m_bRowCountFinal)
+ m_nRowCount = std::max(nPos+1, m_nRowCount); //+1 because we successfully moved to row after nPos
+ else
+ OSL_ENSURE(m_nRowCount >= nPos, "Final m_nRowCount is smaller than row I moved to!");
+ }
+ else
+ { // the end was reached before or at end() so we can set the start before or at nNewStartPos
+ // and possibly keep more of m_pMatrix than planned.
+ const ORowSetMatrix::const_iterator::difference_type nFetchedRows = aIter - m_pMatrix->begin();
+ // *m_pMatrix now looks like:
+ // [0; nFetchedRows) i.e. [begin(); aIter): newly fetched data for positions m_nEndPos to m_nEndPos+nFetchedRows
+ // [nFetchedRows; ???) i.e. [aIter; aDataEnd]: data to be kept for positions m_nStartPos+nFetchedRows to ???
+
+ nPos -= 1;
+ m_nStartPos += nFetchedRows;
+ m_nEndPos = nPos;
+ std::rotate(m_pMatrix->begin(), aIter, aDataEnd);
+ // now correct the iterator in our iterator vector
+ rotateCacheIterator( nFetchedRows );
+
+ if ( !m_bRowCountFinal )
+ {
+ m_xCacheSet->previous(); // because we stand after the last row
+ m_nRowCount = std::max(m_nRowCount, nPos); // here we have the row count
+ OSL_ENSURE(nPos == m_xCacheSet->getRow(),"nPos isn't valid!");
+ m_bRowCountFinal = true;
+ }
+
+ }
+ // here we need only to check if the beginning row is valid. If not we have to fetch it.
+ if(!m_pMatrix->begin()->is())
+ {
+ aIter = m_pMatrix->begin();
+
+ nPos = m_nStartPos + 1;
+ bCheck = m_xCacheSet->absolute(nPos);
+ for(; !aIter->is() && bCheck;++aIter, ++nPos)
+ {
+ OSL_ENSURE(aIter != m_pMatrix->end(),"Invalid iterator");
+
+ *aIter = new ORowSetValueVector(m_xMetaData->getColumnCount());
+ m_xCacheSet->fillValueRow(*aIter, nPos);
+
+ bCheck = m_xCacheSet->next();
+ }
+ }
+ }
+ else // no rows can be reused so fill again
+ reFillMatrix(nNewStartPos,nNewEndPos);
+ }
+
+ if(!m_bRowCountFinal)
+ m_nRowCount = std::max(m_nPosition,m_nRowCount);
+ OSL_ENSURE(m_nStartPos >= 0,"ORowSetCache::moveWindow: m_nStartPos is less than 0!");
+ OSL_ENSURE(m_nEndPos > m_nStartPos,"ORowSetCache::moveWindow: m_nStartPos not smaller than m_nEndPos");
+ OSL_ENSURE(m_nEndPos-m_nStartPos <= m_nFetchSize,"ORowSetCache::moveWindow: m_nStartPos and m_nEndPos too far apart");
+}
+
+bool ORowSetCache::first( )
+{
+ // First move to the first row.
+ // Then check if the cache window is at the beginning.
+ // If not, then position the window and fill it with data.
+ // We move the window smartly, i.e. we clear only the rows that are out of range
+ bool bRet = m_xCacheSet->first();
+ if(bRet)
+ {
+ m_bBeforeFirst = m_bAfterLast = false;
+ m_nPosition = 1;
+ moveWindow();
+ m_aMatrixIter = m_pMatrix->begin();
+ }
+ else
+ {
+ m_bRowCountFinal = m_bBeforeFirst = m_bAfterLast = true;
+ m_nRowCount = m_nPosition = 0;
+
+ OSL_ENSURE(m_bBeforeFirst || m_bNew,"ORowSetCache::first return false and BeforeFirst isn't true");
+ m_aMatrixIter = m_pMatrix->end();
+ }
+ return bRet;
+}
+
+bool ORowSetCache::last( )
+{
+ bool bRet = m_xCacheSet->last();
+ if(bRet)
+ {
+ m_bBeforeFirst = m_bAfterLast = false;
+ if(!m_bRowCountFinal)
+ {
+ m_bRowCountFinal = true;
+ m_nRowCount = m_xCacheSet->getRow(); // not + 1
+ }
+ m_nPosition = m_xCacheSet->getRow();
+ moveWindow();
+ // we have to repositioning because moveWindow can modify the cache
+ m_xCacheSet->last();
+ OSL_ENSURE(((m_nPosition - m_nStartPos) - 1) < static_cast<sal_Int32>(m_pMatrix->size()),"Position is behind end()!");
+ m_aMatrixIter = calcPosition();
+ }
+ else
+ {
+ m_bRowCountFinal = m_bBeforeFirst = m_bAfterLast = true;
+ m_nRowCount = m_nPosition = 0;
+ OSL_ENSURE(m_bBeforeFirst,"ORowSetCache::last return false and BeforeFirst isn't true");
+ m_aMatrixIter = m_pMatrix->end();
+ }
+#if OSL_DEBUG_LEVEL > 0
+ if(bRet)
+ {
+ assert((*m_aMatrixIter).is() && "ORowSetCache::last: Row not valid!");
+ }
+#endif
+
+ return bRet;
+}
+
+sal_Int32 ORowSetCache::getRow( ) const
+{
+ return (isBeforeFirst() || isAfterLast()) ? 0 : m_nPosition;
+}
+
+bool ORowSetCache::absolute( sal_Int32 row )
+{
+ if(!row )
+ throw SQLException(DBA_RES(RID_STR_NO_ABS_ZERO),nullptr,SQLSTATE_GENERAL,1000,Any() );
+
+ if(row < 0)
+ {
+ // here we have to scroll from the last row to backward so we have to go to last row and
+ // and to the previous
+ if(m_bRowCountFinal || last())
+ {
+ m_nPosition = m_nRowCount + row + 1; // + row because row is negative and +1 because row==-1 means last row
+ if(m_nPosition < 1)
+ {
+ m_bBeforeFirst = true;
+ m_bAfterLast = false;
+ m_aMatrixIter = m_pMatrix->end();
+ }
+ else
+ {
+ m_bBeforeFirst = false;
+ m_bAfterLast = m_nPosition > m_nRowCount;
+ moveWindow();
+ OSL_ENSURE(((m_nPosition - m_nStartPos) - 1) < static_cast<sal_Int32>(m_pMatrix->size()),"Position is behind end()!");
+ m_aMatrixIter = calcPosition();
+ }
+ }
+ else
+ m_aMatrixIter = m_pMatrix->end();
+ }
+ else
+ {
+ m_nPosition = row;
+ // the position flags
+ m_bBeforeFirst = false;
+ checkPositionFlags();
+
+ if(!m_bAfterLast)
+ {
+ moveWindow();
+ checkPositionFlags();
+ if(!m_bAfterLast)
+ m_aMatrixIter = calcPosition();
+ else
+ m_aMatrixIter = m_pMatrix->end();
+ }
+ else
+ m_aMatrixIter = m_pMatrix->end();
+ }
+
+ return !(m_bAfterLast || m_bBeforeFirst);
+}
+
+bool ORowSetCache::relative( sal_Int32 rows )
+{
+ bool bErg = true;
+ if(rows)
+ {
+ sal_Int32 nNewPosition = m_nPosition + rows;
+
+ if ( m_bBeforeFirst && rows > 0 )
+ nNewPosition = rows;
+ else if ( m_bRowCountFinal && m_bAfterLast && rows < 0 )
+ nNewPosition = m_nRowCount + 1 + rows;
+ else
+ if ( m_bBeforeFirst || ( m_bRowCountFinal && m_bAfterLast ) )
+ throw SQLException( DBA_RES( RID_STR_NO_RELATIVE ), nullptr, SQLSTATE_GENERAL, 1000, Any() );
+ if ( nNewPosition )
+ {
+ bErg = absolute( nNewPosition );
+ bErg = bErg && !isAfterLast() && !isBeforeFirst();
+ }
+ else
+ {
+ m_bBeforeFirst = true;
+ bErg = false;
+ }
+ }
+ return bErg;
+}
+
+bool ORowSetCache::previous( )
+{
+ bool bRet = false;
+ if(!isBeforeFirst())
+ {
+ if(m_bAfterLast) // we stand after the last row so one before is the last row
+ bRet = last();
+ else
+ {
+ m_bAfterLast = false;
+ --m_nPosition;
+ moveWindow();
+ OSL_ENSURE(((m_nPosition - m_nStartPos) - 1) < static_cast<sal_Int32>(m_pMatrix->size()),"Position is behind end()!");
+
+ checkPositionFlags();
+
+ if(!m_nPosition)
+ {
+ m_bBeforeFirst = true;
+ m_aMatrixIter = m_pMatrix->end();
+ }
+ else
+ {
+ m_aMatrixIter = calcPosition();
+ bRet = (*m_aMatrixIter).is();
+ }
+ }
+ }
+ return bRet;
+}
+
+void ORowSetCache::refreshRow( )
+{
+ if(isAfterLast())
+ throw SQLException(DBA_RES(RID_STR_NO_REFRESH_AFTERLAST),nullptr,SQLSTATE_GENERAL,1000,Any() );
+ OSL_ENSURE(m_aMatrixIter != m_pMatrix->end(),"refreshRow() called for invalid row!");
+ m_xCacheSet->refreshRow();
+ m_xCacheSet->fillValueRow(*m_aMatrixIter,m_nPosition);
+ if ( m_bNew )
+ {
+ cancelRowModification();
+ }
+}
+
+bool ORowSetCache::rowUpdated( )
+{
+ return m_xCacheSet->rowUpdated();
+}
+
+bool ORowSetCache::rowInserted( )
+{
+ return m_xCacheSet->rowInserted();
+}
+
+// XResultSetUpdate
+bool ORowSetCache::insertRow(std::vector< Any >& o_aBookmarks)
+{
+ if ( !m_bNew || !m_aInsertRow->is() )
+ throw SQLException(DBA_RES(RID_STR_NO_MOVETOINSERTROW_CALLED),nullptr,SQLSTATE_GENERAL,1000,Any() );
+
+ m_xCacheSet->insertRow(*m_aInsertRow,m_aUpdateTable);
+
+ bool bRet( rowInserted() );
+ if ( bRet )
+ {
+ ++m_nRowCount;
+ Any aBookmark = (**m_aInsertRow)[0].makeAny();
+ m_bAfterLast = m_bBeforeFirst = false;
+ if(aBookmark.hasValue())
+ {
+ moveToBookmark(aBookmark);
+ // update the cached values
+ ORowSetValueVector::Vector& rCurrentRow = **m_aMatrixIter;
+ ORowSetMatrix::const_iterator aIter = m_pMatrix->begin();
+ for(;aIter != m_pMatrix->end();++aIter)
+ {
+ if ( m_aMatrixIter != aIter && aIter->is() && m_xCacheSet->columnValuesUpdated(**aIter,rCurrentRow) )
+ {
+ o_aBookmarks.push_back(lcl_getBookmark((**aIter)[0], m_xCacheSet.get()));
+ }
+ }
+ }
+ else
+ {
+ OSL_FAIL("There must be a bookmark after the row was inserted!");
+ }
+ }
+ return bRet;
+}
+
+void ORowSetCache::resetInsertRow(bool _bClearInsertRow)
+{
+ if ( _bClearInsertRow )
+ clearInsertRow();
+ m_bNew = false;
+ m_bModified = false;
+}
+
+void ORowSetCache::cancelRowModification()
+{
+ // clear the insertrow references -> implies that the current row of the rowset changes as well
+ for(auto& rCacheIter : m_aCacheIterators)
+ {
+ if ( rCacheIter.second.pRowSet->isInsertRow() && rCacheIter.second.aIterator == m_aInsertRow )
+ rCacheIter.second.aIterator = m_pMatrix->end();
+ }
+ resetInsertRow(false);
+}
+
+void ORowSetCache::updateRow( ORowSetMatrix::iterator const & _rUpdateRow, std::vector< Any >& o_aBookmarks )
+{
+ if(isAfterLast() || isBeforeFirst())
+ throw SQLException(DBA_RES(RID_STR_NO_UPDATEROW),nullptr,SQLSTATE_GENERAL,1000,Any() );
+
+ Any aBookmark = (**_rUpdateRow)[0].makeAny();
+ OSL_ENSURE(aBookmark.hasValue(),"Bookmark must have a value!");
+ // here we don't have to reposition our CacheSet, when we try to update a row,
+ // the row was already fetched
+ moveToBookmark(aBookmark);
+ m_xCacheSet->updateRow(*_rUpdateRow,*m_aMatrixIter,m_aUpdateTable);
+ // refetch the whole row
+ (*m_aMatrixIter) = nullptr;
+
+ if ( moveToBookmark(aBookmark) )
+ {
+ // update the cached values
+ ORowSetValueVector::Vector& rCurrentRow = **m_aMatrixIter;
+ ORowSetMatrix::const_iterator aIter = m_pMatrix->begin();
+ for(;aIter != m_pMatrix->end();++aIter)
+ {
+ if ( m_aMatrixIter != aIter && aIter->is() && m_xCacheSet->columnValuesUpdated(**aIter,rCurrentRow) )
+ {
+ o_aBookmarks.push_back(lcl_getBookmark((**aIter)[0], m_xCacheSet.get()));
+ }
+ }
+ }
+
+ m_bModified = false;
+}
+
+bool ORowSetCache::deleteRow( )
+{
+ if(isAfterLast() || isBeforeFirst())
+ throw SQLException(DBA_RES(RID_STR_NO_DELETEROW),nullptr,SQLSTATE_GENERAL,1000,Any() );
+
+ m_xCacheSet->deleteRow(*m_aMatrixIter,m_aUpdateTable);
+ if ( !m_xCacheSet->rowDeleted() )
+ return false;
+
+ --m_nRowCount;
+ OSL_ENSURE(((m_nPosition - m_nStartPos) - 1) < static_cast<sal_Int32>(m_pMatrix->size()),"Position is behind end()!");
+ ORowSetMatrix::iterator aPos = calcPosition();
+ (*aPos) = nullptr;
+
+ ORowSetMatrix::const_iterator aEnd = m_pMatrix->end();
+ for(++aPos;aPos != aEnd && aPos->is();++aPos)
+ {
+ *(aPos-1) = *aPos;
+ (*aPos) = nullptr;
+ }
+ m_aMatrixIter = m_pMatrix->end();
+
+ --m_nPosition;
+ return true;
+}
+
+void ORowSetCache::cancelRowUpdates( )
+{
+ m_bNew = m_bModified = false;
+ if(!m_nPosition)
+ {
+ OSL_FAIL("cancelRowUpdates:Invalid positions pos == 0");
+ ::dbtools::throwFunctionSequenceException(nullptr);
+ }
+
+ if(m_xCacheSet->absolute(m_nPosition))
+ m_xCacheSet->fillValueRow(*m_aMatrixIter,m_nPosition);
+ else
+ {
+ OSL_FAIL("cancelRowUpdates couldn't position right with absolute");
+ ::dbtools::throwFunctionSequenceException(nullptr);
+ }
+}
+
+void ORowSetCache::moveToInsertRow( )
+{
+ m_bNew = true;
+ m_bAfterLast = false;
+
+ m_aInsertRow = m_pInsertMatrix->begin();
+ if(!m_aInsertRow->is())
+ *m_aInsertRow = new ORowSetValueVector(m_xMetaData->getColumnCount());
+
+ // we don't unbound the bookmark column
+ ORowSetValueVector::Vector::iterator aIter = (*m_aInsertRow)->begin()+1;
+ ORowSetValueVector::Vector::const_iterator aEnd = (*m_aInsertRow)->end();
+ for(sal_Int32 i = 1;aIter != aEnd;++aIter,++i)
+ {
+ aIter->setBound(false);
+ aIter->setModified(false);
+ aIter->setNull();
+ aIter->setTypeKind(m_xMetaData->getColumnType(i));
+ }
+}
+
+ORowSetCacheIterator ORowSetCache::createIterator(ORowSetBase* _pRowSet)
+{
+ ORowSetCacheIterator_Helper aHelper;
+ aHelper.aIterator = m_pMatrix->end();
+ aHelper.pRowSet = _pRowSet;
+ return ORowSetCacheIterator(m_aCacheIterators.insert(m_aCacheIterators.begin(),ORowSetCacheMap::value_type(m_aCacheIterators.size()+1,aHelper)),this,_pRowSet);
+}
+
+void ORowSetCache::deleteIterator(const ORowSetBase* _pRowSet)
+{
+ ORowSetCacheMap::const_iterator aCacheIter = m_aCacheIterators.begin();
+ for(;aCacheIter != m_aCacheIterators.end();)
+ {
+ if ( aCacheIter->second.pRowSet == _pRowSet )
+ {
+ aCacheIter = m_aCacheIterators.erase(aCacheIter);
+ }
+ else
+ ++aCacheIter;
+ }
+}
+
+void ORowSetCache::rotateCacheIterator(ORowSetMatrix::difference_type _nDist)
+{
+ if (m_bModified)
+ return;
+
+ if(!_nDist)
+ return;
+
+ // now correct the iterator in our iterator vector
+ for(auto& rCacheIter : m_aCacheIterators)
+ {
+ if ( !rCacheIter.second.pRowSet->isInsertRow()
+ && rCacheIter.second.aIterator != m_pMatrix->end())
+ {
+ ptrdiff_t nDist = rCacheIter.second.aIterator - m_pMatrix->begin();
+ if(nDist < _nDist)
+ {
+ rCacheIter.second.aIterator = m_pMatrix->end();
+ }
+ else
+ {
+ OSL_ENSURE((rCacheIter.second.aIterator - m_pMatrix->begin()) >= _nDist,"Invalid Dist value!");
+ rCacheIter.second.aIterator -= _nDist;
+ OSL_ENSURE(rCacheIter.second.aIterator >= m_pMatrix->begin()
+ && rCacheIter.second.aIterator < m_pMatrix->end(),"Iterator out of area!");
+ }
+ }
+ }
+}
+
+void ORowSetCache::rotateAllCacheIterators()
+{
+ if (m_bModified)
+ return;
+
+ // now correct the iterator in our iterator vector
+ for (auto& rCacheIter : m_aCacheIterators)
+ {
+ if (!rCacheIter.second.pRowSet->isInsertRow())
+ {
+ rCacheIter.second.aIterator = m_pMatrix->end();
+ }
+ }
+}
+
+void ORowSetCache::setUpdateIterator(const ORowSetMatrix::iterator& _rOriginalRow)
+{
+ m_aInsertRow = m_pInsertMatrix->begin();
+ if(!m_aInsertRow->is())
+ *m_aInsertRow = new ORowSetValueVector(m_xMetaData->getColumnCount());
+
+ (*(*m_aInsertRow)) = *(*_rOriginalRow);
+ // we don't unbound the bookmark column
+ for(auto& rItem : **m_aInsertRow)
+ rItem.setModified(false);
+}
+
+void ORowSetCache::checkPositionFlags()
+{
+ if(m_bRowCountFinal)
+ {
+ m_bAfterLast = m_nPosition > m_nRowCount;
+ if(m_bAfterLast)
+ m_nPosition = 0;//m_nRowCount;
+ }
+}
+
+void ORowSetCache::checkUpdateConditions(sal_Int32 columnIndex)
+{
+ if(m_bAfterLast || columnIndex >= static_cast<sal_Int32>((*m_aInsertRow)->size()))
+ throwFunctionSequenceException(m_xSet.get());
+}
+
+bool ORowSetCache::checkInnerJoin(const ::connectivity::OSQLParseNode *pNode,const Reference< XConnection>& _xConnection,const OUString& _sUpdateTableName)
+{
+ bool bOk = false;
+ if (pNode->count() == 3 && // expression in parentheses
+ SQL_ISPUNCTUATION(pNode->getChild(0),"(") &&
+ SQL_ISPUNCTUATION(pNode->getChild(2),")"))
+ {
+ bOk = checkInnerJoin(pNode->getChild(1),_xConnection,_sUpdateTableName);
+ }
+ else if ((SQL_ISRULE(pNode,search_condition) || SQL_ISRULE(pNode,boolean_term)) && // AND/OR link
+ pNode->count() == 3)
+ {
+ // only allow an AND link
+ if ( SQL_ISTOKEN(pNode->getChild(1),AND) )
+ bOk = checkInnerJoin(pNode->getChild(0),_xConnection,_sUpdateTableName)
+ && checkInnerJoin(pNode->getChild(2),_xConnection,_sUpdateTableName);
+ }
+ else if (SQL_ISRULE(pNode,comparison_predicate))
+ {
+ // only the comparison of columns is allowed
+ OSL_ENSURE(pNode->count() == 3,"checkInnerJoin: Error in Parse Tree");
+ if (!(SQL_ISRULE(pNode->getChild(0),column_ref) &&
+ SQL_ISRULE(pNode->getChild(2),column_ref) &&
+ pNode->getChild(1)->getNodeType() == SQLNodeType::Equal))
+ {
+ bOk = false;
+ }
+ else
+ {
+ OUString sColumnName,sTableRange;
+ OSQLParseTreeIterator::getColumnRange( pNode->getChild(0), _xConnection, sColumnName, sTableRange );
+ bOk = sTableRange == _sUpdateTableName;
+ if ( !bOk )
+ {
+ OSQLParseTreeIterator::getColumnRange( pNode->getChild(2), _xConnection, sColumnName, sTableRange );
+ bOk = sTableRange == _sUpdateTableName;
+ }
+ }
+ }
+ return bOk;
+}
+
+bool ORowSetCache::checkJoin(const Reference< XConnection>& _xConnection,
+ const Reference< XSingleSelectQueryAnalyzer >& _xAnalyzer,
+ const OUString& _sUpdateTableName )
+{
+ bool bOk = false;
+ OUString sSql = _xAnalyzer->getQuery();
+ OUString sErrorMsg;
+ ::connectivity::OSQLParser aSqlParser( m_aContext );
+ std::unique_ptr< ::connectivity::OSQLParseNode> pSqlParseNode( aSqlParser.parseTree(sErrorMsg,sSql));
+ if ( pSqlParseNode && SQL_ISRULE(pSqlParseNode, select_statement) )
+ {
+ OSQLParseNode* pTableRefCommalist = pSqlParseNode->getByRule(::connectivity::OSQLParseNode::table_ref_commalist);
+ OSL_ENSURE(pTableRefCommalist,"NO tables why!?");
+ if(pTableRefCommalist && pTableRefCommalist->count() == 1)
+ {
+ // we found only one element so it must some kind of join here
+ OSQLParseNode* pJoin = pTableRefCommalist->getByRule(::connectivity::OSQLParseNode::qualified_join);
+ if(pJoin)
+ { // we are only interested in qualified joins like RIGHT or LEFT
+ OSQLParseNode* pJoinType = pJoin->getChild(1);
+ OSQLParseNode* pOuterType = nullptr;
+ if(SQL_ISRULE(pJoinType,join_type) && pJoinType->count() == 2)
+ pOuterType = pJoinType->getChild(0);
+ else if(SQL_ISRULE(pJoinType,outer_join_type))
+ pOuterType = pJoinType;
+
+ bool bCheck = false;
+ bool bLeftSide = false;
+ if(pOuterType)
+ { // found outer join
+ bLeftSide = SQL_ISTOKEN(pOuterType->getChild(0),LEFT);
+ bCheck = bLeftSide || SQL_ISTOKEN(pOuterType->getChild(0),RIGHT);
+ }
+
+ if(bCheck)
+ { // here we know that we have to check on which side our table resides
+ const OSQLParseNode* pTableRef;
+ if(bLeftSide)
+ pTableRef = pJoin->getChild(0);
+ else
+ pTableRef = pJoin->getChild(3);
+ OSL_ENSURE(SQL_ISRULE(pTableRef,table_ref),"Must be a tableref here!");
+
+ OUString sTableRange = OSQLParseNode::getTableRange(pTableRef);
+ if(sTableRange.isEmpty())
+ pTableRef->getChild(0)->parseNodeToStr( sTableRange, _xConnection, nullptr, false, false );
+ bOk = sTableRange == _sUpdateTableName;
+ }
+ }
+ }
+ else
+ {
+ OSQLParseNode* pWhereOpt = pSqlParseNode->getChild(3)->getChild(1);
+ if ( pWhereOpt && !pWhereOpt->isLeaf() )
+ bOk = checkInnerJoin(pWhereOpt->getChild(1),_xConnection,_sUpdateTableName);
+ }
+ }
+ return bOk;
+}
+
+void ORowSetCache::clearInsertRow()
+{
+ // we don't unbound the bookmark column
+ if ( m_aInsertRow != m_pInsertMatrix->end() && m_aInsertRow->is() )
+ {
+ ORowSetValueVector::Vector::iterator aIter = (*m_aInsertRow)->begin()+1;
+ ORowSetValueVector::Vector::const_iterator aEnd = (*m_aInsertRow)->end();
+ for(;aIter != aEnd;++aIter)
+ {
+ aIter->setBound(false);
+ aIter->setModified(false);
+ aIter->setNull();
+ }
+ }
+}
+
+ORowSetMatrix::iterator ORowSetCache::calcPosition() const
+{
+ sal_Int32 nValue = (m_nPosition - m_nStartPos) - 1;
+ OSL_ENSURE((nValue >= static_cast<ORowSetMatrix::difference_type>(0)) && (o3tl::make_unsigned(nValue) < m_pMatrix->size()),"Position is invalid!");
+ return ( nValue < 0 || o3tl::make_unsigned(nValue) >= m_pMatrix->size() ) ? m_pMatrix->end() : (m_pMatrix->begin() + nValue);
+}
+
+TORowSetOldRowHelperRef ORowSetCache::registerOldRow()
+{
+ TORowSetOldRowHelperRef pRef = new ORowSetOldRowHelper(ORowSetRow());
+ m_aOldRows.push_back(pRef);
+ return pRef;
+}
+
+void ORowSetCache::deregisterOldRow(const TORowSetOldRowHelperRef& _rRow)
+{
+ TOldRowSetRows::iterator aOldRowIter = std::find_if(m_aOldRows.begin(), m_aOldRows.end(),
+ [&_rRow](const TORowSetOldRowHelperRef& rxOldRow) { return rxOldRow.get() == _rRow.get(); });
+ if (aOldRowIter != m_aOldRows.end())
+ m_aOldRows.erase(aOldRowIter);
+}
+
+bool ORowSetCache::reFillMatrix(sal_Int32 _nNewStartPos, sal_Int32 _nNewEndPos)
+{
+ for (const auto& rxOldRow : m_aOldRows)
+ {
+ if ( rxOldRow.is() && rxOldRow->getRow().is() )
+ rxOldRow->setRow(new ORowSetValueVector( *(rxOldRow->getRow()) ) );
+ }
+ sal_Int32 nNewSt = _nNewStartPos;
+ bool bRet = fillMatrix(nNewSt,_nNewEndPos);
+ m_nStartPos = nNewSt;
+ m_nEndPos = _nNewEndPos;
+ rotateAllCacheIterators(); // invalidate every iterator
+ return bRet;
+}
+
+bool ORowSetCache::fill(ORowSetMatrix::iterator& _aIter, const ORowSetMatrix::const_iterator& _aEnd, sal_Int32& _nPos, bool _bCheck)
+{
+ const sal_Int32 nColumnCount = m_xMetaData->getColumnCount();
+ for (; _bCheck && _aIter != _aEnd; ++_aIter, ++_nPos)
+ {
+ if ( !_aIter->is() )
+ *_aIter = new ORowSetValueVector(nColumnCount);
+ else
+ {
+ for (const auto& rxOldRow : m_aOldRows)
+ {
+ if ( rxOldRow->getRow() == *_aIter )
+ *_aIter = new ORowSetValueVector(nColumnCount);
+ }
+ }
+ m_xCacheSet->fillValueRow(*_aIter, _nPos);
+ _bCheck = m_xCacheSet->next();
+ }
+ return _bCheck;
+}
+
+bool ORowSetCache::isResultSetChanged() const
+{
+ return m_xCacheSet->isResultSetChanged();
+}
+
+void ORowSetCache::reset(const Reference< XResultSet>& _xDriverSet)
+{
+ m_xSet = _xDriverSet;
+ m_xMetaData.set(Reference< XResultSetMetaDataSupplier >(_xDriverSet,UNO_QUERY_THROW)->getMetaData());
+ m_xCacheSet->reset(_xDriverSet);
+
+ m_bRowCountFinal = false;
+ m_nRowCount = 0;
+ reFillMatrix(m_nStartPos,m_nEndPos);
+}
+
+void ORowSetCache::impl_updateRowFromCache_throw(ORowSetValueVector::Vector& io_aRow
+ ,std::vector<sal_Int32> const & o_ChangedColumns)
+{
+ if ( o_ChangedColumns.size() > 1 )
+ {
+ for (auto const& elem : *m_pMatrix)
+ {
+ if ( elem.is() && m_xCacheSet->updateColumnValues(*elem,io_aRow,o_ChangedColumns))
+ {
+ return;
+ }
+ }
+ m_xCacheSet->fillMissingValues(io_aRow);
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/api/RowSetCache.hxx b/dbaccess/source/core/api/RowSetCache.hxx
new file mode 100644
index 000000000..01ed6394d
--- /dev/null
+++ b/dbaccess/source/core/api/RowSetCache.hxx
@@ -0,0 +1,190 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <connectivity/CommonTools.hxx>
+#include <com/sun/star/io/XInputStream.hpp>
+#include <com/sun/star/sdbc/XConnection.hpp>
+#include <com/sun/star/sdb/XSingleSelectQueryAnalyzer.hpp>
+#include <com/sun/star/sdbc/XResultSetMetaData.hpp>
+#include "RowSetRow.hxx"
+#include "RowSetCacheIterator.hxx"
+
+namespace connectivity
+{
+ class OSQLParseNode;
+}
+namespace dbaccess
+{
+ class OCacheSet;
+
+ class ORowSetCache
+ {
+ friend class ORowSetBase;
+ friend class ORowSet;
+ friend class ORowSetClone;
+ friend class ORowSetCacheIterator;
+
+ typedef std::vector< TORowSetOldRowHelperRef > TOldRowSetRows;
+
+ std::map<sal_Int32,sal_Int32> m_aKeyColumns;
+ //the set can be static, bookmarkable or keyset
+ css::uno::WeakReference< css::sdbc::XResultSet> m_xSet;
+ css::uno::Reference< css::sdbc::XResultSetMetaData > m_xMetaData; // must be before m_aInsertRow
+ css::uno::Reference< css::uno::XComponentContext> m_aContext;
+
+ rtl::Reference<OCacheSet> m_xCacheSet; // is a bookmarkable, keyset or static resultset
+
+ std::unique_ptr<ORowSetMatrix> m_pMatrix; // represent the table struct
+ ORowSetMatrix::iterator m_aMatrixIter; // represent a row of the table
+ ORowSetMatrix::iterator m_aMatrixEnd; // present the row behind the last row of the table
+ ORowSetCacheMap m_aCacheIterators;
+ TOldRowSetRows m_aOldRows;
+
+ std::unique_ptr<ORowSetMatrix> m_pInsertMatrix; // represent the rows which should be inserted normally this is only one
+ ORowSetMatrix::iterator m_aInsertRow; // represent an insert row
+
+ connectivity::OSQLTable m_aUpdateTable; // used for updates/deletes and inserts
+
+ sal_Int32 m_nFetchSize;
+ sal_Int32 m_nRowCount;
+ sal_Int32 m_nPrivileges;
+ sal_Int32 m_nPosition; // 0 means before first (i.e. 1-based)
+
+ sal_Int32 m_nStartPos; // start pos of the window zero based (inclusive)
+ sal_Int32 m_nEndPos; // end pos of the window zero based (exclusive)
+
+ bool m_bRowCountFinal ;
+ bool m_bBeforeFirst ;
+ bool m_bAfterLast ;
+ bool& m_bModified ; // points to the rowset member m_bModified
+ bool& m_bNew ; // points to the rowset member m_bNew
+
+ bool fill(ORowSetMatrix::iterator& _aIter, const ORowSetMatrix::const_iterator& _aEnd, sal_Int32& _nPos, bool _bCheck);
+ bool reFillMatrix(sal_Int32 _nNewStartPos,sal_Int32 nNewEndPos);
+ bool fillMatrix(sal_Int32 &_nNewStartPos,sal_Int32 &_nNewEndPos);
+ void moveWindow();
+
+ void rotateCacheIterator(ORowSetMatrix::difference_type _nDist);
+ void rotateAllCacheIterators();
+ void updateValue(sal_Int32 columnIndex
+ ,const connectivity::ORowSetValue& x
+ ,ORowSetValueVector::Vector& io_aRow
+ ,std::vector<sal_Int32>& o_ChangedColumns
+ );
+
+ void impl_updateRowFromCache_throw(ORowSetValueVector::Vector& io_aRow
+ ,std::vector<sal_Int32> const & o_ChangedColumns
+ );
+ // checks and set the flags isAfterLast isLast and position when afterlast is true
+ void checkPositionFlags();
+ void checkUpdateConditions(sal_Int32 columnIndex);
+ bool checkJoin( const css::uno::Reference< css::sdbc::XConnection>& _xConnection,
+ const css::uno::Reference< css::sdb::XSingleSelectQueryAnalyzer >& _xComposer,
+ const OUString& _sUpdateTableName);
+ bool checkInnerJoin(const ::connectivity::OSQLParseNode *pNode
+ ,const css::uno::Reference< css::sdbc::XConnection>& _xConnection
+ ,const OUString& _sUpdateTableName);
+
+ // clears the insert row
+ void clearInsertRow();
+ ORowSetMatrix::iterator calcPosition() const;
+
+ protected:
+ const ORowSetMatrix::iterator& getEnd() const { return m_aMatrixEnd;}
+ // is called when after a moveToInsertRow a movement (next, etc) was called
+ void cancelRowModification();
+ public:
+ ORowSetCache(const css::uno::Reference< css::sdbc::XResultSet >& _xRs,
+ const css::uno::Reference< css::sdb::XSingleSelectQueryAnalyzer >& _xAnalyzer,
+ const css::uno::Reference< css::uno::XComponentContext >& _rContext,
+ const OUString& _rUpdateTableName,
+ bool& _bModified,
+ bool& _bNew,
+ const ORowSetValueVector& _aParameterValueForCache,
+ const OUString& i_sRowSetFilter,
+ sal_Int32 i_nMaxRows);
+ ~ORowSetCache();
+
+
+ // called from the rowset when an updateXXX was called for the first time
+ void setUpdateIterator(const ORowSetMatrix::iterator& _rOriginalRow);
+ ORowSetCacheIterator createIterator(ORowSetBase* _pRowSet);
+ void deleteIterator(const ORowSetBase* _pRowSet);
+ // sets the size of the matrix
+ void setFetchSize(sal_Int32 _nSize);
+
+ TORowSetOldRowHelperRef registerOldRow();
+ void deregisterOldRow(const TORowSetOldRowHelperRef& _rRow);
+
+ // css::sdbc::XResultSetMetaDataSupplier
+ const css::uno::Reference< css::sdbc::XResultSetMetaData >& getMetaData( ) const { return m_xMetaData;}
+
+ // css::sdbcx::XRowLocate
+ css::uno::Any getBookmark( );
+ bool moveToBookmark( const css::uno::Any& bookmark );
+ bool moveRelativeToBookmark( const css::uno::Any& bookmark, sal_Int32 rows );
+ sal_Int32 compareBookmarks( const css::uno::Any& first, const css::uno::Any& second );
+ bool hasOrderedBookmarks( );
+ sal_Int32 hashBookmark( const css::uno::Any& bookmark );
+
+ // css::sdbc::XRowUpdate
+ void updateCharacterStream( sal_Int32 columnIndex, const css::uno::Reference< css::io::XInputStream >& x, sal_Int32 length,ORowSetValueVector::Vector& io_aRow,std::vector<sal_Int32>& o_ChangedColumns
+ );
+ void updateObject( sal_Int32 columnIndex, const css::uno::Any& x,ORowSetValueVector::Vector& io_aRow ,std::vector<sal_Int32>& o_ChangedColumns);
+ void updateNumericObject( sal_Int32 columnIndex, const css::uno::Any& x, ORowSetValueVector::Vector& io_aRow ,std::vector<sal_Int32>& o_ChangedColumns);
+ void updateNull(sal_Int32 columnIndex
+ ,ORowSetValueVector::Vector& io_aRow
+ ,std::vector<sal_Int32>& o_ChangedColumns
+ );
+
+ // css::sdbc::XResultSet
+ bool next( );
+ bool isBeforeFirst( ) const { return m_bBeforeFirst;}
+ bool isAfterLast( ) const { return m_bAfterLast;}
+ bool isFirst( ) const;
+ bool isLast( ) const;
+ void beforeFirst( );
+ void afterLast( );
+ bool first( );
+ bool last( );
+ sal_Int32 getRow( ) const;
+ bool absolute( sal_Int32 row );
+ bool relative( sal_Int32 rows );
+ bool previous( );
+ void refreshRow( );
+ bool rowUpdated( );
+ bool rowInserted( );
+
+ // css::sdbc::XResultSetUpdate
+ bool insertRow(std::vector< css::uno::Any >& o_aBookmarks);
+ void resetInsertRow(bool _bClearInsertRow);
+
+ void updateRow( ORowSetMatrix::iterator const & _rUpdateRow, std::vector< css::uno::Any >& o_aBookmarks );
+ bool deleteRow();
+ void cancelRowUpdates( );
+ void moveToInsertRow( );
+
+ const std::map<sal_Int32,sal_Int32>& getKeyColumns() const { return m_aKeyColumns; }
+ bool isResultSetChanged() const;
+ void reset(const css::uno::Reference< css::sdbc::XResultSet>& _xDriverSet);
+ };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/api/RowSetCacheIterator.cxx b/dbaccess/source/core/api/RowSetCacheIterator.cxx
new file mode 100644
index 000000000..7df7bae6b
--- /dev/null
+++ b/dbaccess/source/core/api/RowSetCacheIterator.cxx
@@ -0,0 +1,91 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "RowSetCacheIterator.hxx"
+#include "RowSetCache.hxx"
+#include "RowSetBase.hxx"
+
+using namespace dbaccess;
+
+ORowSetCacheIterator::ORowSetCacheIterator(const ORowSetCacheIterator& _rRH)
+: m_aIter(_rRH.m_aIter)
+, m_pCache(_rRH.m_pCache)
+,m_pRowSet(_rRH.m_pRowSet)
+{
+}
+
+ORowSetCacheIterator::operator ORowSetMatrix::iterator const &()
+{
+ return m_aIter->second.aIterator;
+}
+
+ORowSetCacheIterator& ORowSetCacheIterator::operator =(const ORowSetCacheIterator& _rRH)
+{
+ if(this == &_rRH)
+ return *this;
+
+ m_pCache = _rRH.m_pCache;
+ m_aIter = _rRH.m_aIter;
+ m_pRowSet = _rRH.m_pRowSet;
+
+ return *this;
+}
+
+ORowSetCacheIterator& ORowSetCacheIterator::operator =(const ORowSetMatrix::iterator& _rIter)
+{
+ m_aIter->second.aIterator = _rIter;
+ return *this;
+}
+
+ORowSetRow& ORowSetCacheIterator::operator *()
+{
+ return *m_aIter->second.aIterator;
+}
+
+ORowSetMatrix::iterator& ORowSetCacheIterator::operator ->()
+{
+ return m_aIter->second.aIterator;
+}
+
+bool ORowSetCacheIterator::operator <(const ORowSetMatrix::iterator& _rRH) const
+{
+ return m_aIter->second.aIterator < _rRH;
+}
+
+bool ORowSetCacheIterator::operator !=(const ORowSetMatrix::iterator& _rRH) const
+{
+ return m_aIter->second.aIterator != _rRH;
+}
+
+bool ORowSetCacheIterator::isNull() const
+{
+ bool bRet = !m_pCache || !m_pRowSet || m_aIter == m_pCache->m_aCacheIterators.end();
+ if ( !bRet )
+ {
+ bRet = ( m_pRowSet->isInsertRow()
+ ?
+ m_aIter->second.aIterator == m_pCache->m_pInsertMatrix->end()
+ :
+ m_aIter->second.aIterator == m_pCache->m_pMatrix->end()
+ );
+ }
+ return bRet;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/api/RowSetCacheIterator.hxx b/dbaccess/source/core/api/RowSetCacheIterator.hxx
new file mode 100644
index 000000000..9c7a9afd4
--- /dev/null
+++ b/dbaccess/source/core/api/RowSetCacheIterator.hxx
@@ -0,0 +1,72 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <sal/config.h>
+
+#include <map>
+
+#include "RowSetRow.hxx"
+
+namespace dbaccess
+{
+ class ORowSetBase;
+ struct ORowSetCacheIterator_Helper
+ {
+ ORowSetMatrix::iterator aIterator;
+ ORowSetBase* pRowSet;
+ };
+
+ typedef std::map<sal_Int32, ORowSetCacheIterator_Helper> ORowSetCacheMap;
+
+ class ORowSetCache;
+ class ORowSetCacheIterator final
+ {
+ friend class ORowSetCache;
+ ORowSetCacheMap::iterator m_aIter;
+ ORowSetCache* m_pCache;
+ ORowSetBase* m_pRowSet;
+
+ ORowSetCacheIterator(const ORowSetCacheMap::iterator& _rIter,ORowSetCache* _pCache,ORowSetBase* _pRowSet)
+ : m_aIter(_rIter)
+ ,m_pCache(_pCache)
+ ,m_pRowSet(_pRowSet)
+ {
+ }
+ public:
+ ORowSetCacheIterator() :m_aIter(),m_pCache(nullptr),m_pRowSet(nullptr){}
+ ORowSetCacheIterator(const ORowSetCacheIterator& _rRH);
+ ORowSetCacheIterator& operator =(const ORowSetCacheIterator&);
+
+ bool isNull() const;
+ ORowSetCacheIterator& operator =(const ORowSetMatrix::iterator&);
+ operator ORowSetMatrix::iterator const &();
+
+ ORowSetRow& operator *();
+
+ ORowSetMatrix::iterator& operator ->();
+
+ bool operator <(const ORowSetMatrix::iterator& _rRH) const;
+ bool operator !=(const ORowSetMatrix::iterator& _rRH) const;
+
+ const ORowSetCacheMap::iterator& getIter() const { return m_aIter; }
+ };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/api/RowSetRow.hxx b/dbaccess/source/core/api/RowSetRow.hxx
new file mode 100644
index 000000000..7f24267b7
--- /dev/null
+++ b/dbaccess/source/core/api/RowSetRow.hxx
@@ -0,0 +1,52 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <rtl/ref.hxx>
+#include <connectivity/CommonTools.hxx>
+#include <connectivity/FValue.hxx>
+#include <salhelper/simplereferenceobject.hxx>
+
+namespace dbaccess
+{
+ typedef connectivity::ORowVector< connectivity::ORowSetValue > ORowSetValueVector;
+ typedef ::rtl::Reference< ORowSetValueVector > ORowSetRow;
+ typedef std::vector< ORowSetRow > ORowSetMatrix;
+
+ class ORowSetOldRowHelper : public salhelper::SimpleReferenceObject
+ {
+ ORowSetRow m_aRow;
+
+ ORowSetOldRowHelper& operator=(const ORowSetOldRowHelper& _rRH) = delete;
+ ORowSetOldRowHelper(const ORowSetOldRowHelper& _rRh) = delete;
+ public:
+ explicit ORowSetOldRowHelper(const ORowSetRow& _rRow)
+ : m_aRow(_rRow)
+ {}
+
+ const ORowSetRow& getRow() const { return m_aRow; }
+ void clearRow() { m_aRow = nullptr; }
+ void setRow(const ORowSetRow& _rRow) { m_aRow = _rRow; }
+ };
+
+ typedef ::rtl::Reference< ORowSetOldRowHelper > TORowSetOldRowHelperRef;
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/api/SingleSelectQueryComposer.cxx b/dbaccess/source/core/api/SingleSelectQueryComposer.cxx
new file mode 100644
index 000000000..3c6906893
--- /dev/null
+++ b/dbaccess/source/core/api/SingleSelectQueryComposer.cxx
@@ -0,0 +1,1922 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <string.h>
+#include <sal/log.hxx>
+#include <composertools.hxx>
+#include <strings.hrc>
+#include <strings.hxx>
+#include <core_resource.hxx>
+#include <stringconstants.hxx>
+#include "HelperCollections.hxx"
+#include <SingleSelectQueryComposer.hxx>
+#include <sqlbison.hxx>
+#include <sdbcoretools.hxx>
+
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/i18n/LocaleData.hpp>
+#include <com/sun/star/script/Converter.hpp>
+#include <com/sun/star/sdb/BooleanComparisonMode.hpp>
+#include <com/sun/star/sdb/SQLFilterOperator.hpp>
+#include <com/sun/star/sdb/XQueriesSupplier.hpp>
+#include <com/sun/star/sdb/CommandType.hpp>
+#include <com/sun/star/sdbc/ColumnSearch.hpp>
+#include <com/sun/star/sdbc/DataType.hpp>
+#include <com/sun/star/sdbc/XConnection.hpp>
+#include <com/sun/star/sdbc/XResultSetMetaData.hpp>
+#include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp>
+#include <com/sun/star/sdbc/XParameters.hpp>
+#include <com/sun/star/util/NumberFormatter.hpp>
+
+#include <comphelper/types.hxx>
+#include <cppuhelper/exc_hlp.hxx>
+#include <connectivity/dbtools.hxx>
+#include <connectivity/PColumn.hxx>
+#include <connectivity/predicateinput.hxx>
+#include <tools/diagnose_ex.h>
+#include <osl/diagnose.h>
+#include <unotools/sharedunocomponent.hxx>
+
+#include <memory>
+#include <string_view>
+
+using namespace ::dbaccess;
+using namespace ::dbtools;
+using namespace ::comphelper;
+using namespace ::connectivity;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::sdb;
+using namespace ::com::sun::star::sdbcx;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::i18n;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::script;
+using namespace ::com::sun::star::util;
+using namespace ::cppu;
+using namespace ::osl;
+using namespace ::utl;
+
+namespace dbaccess {
+namespace BooleanComparisonMode = ::com::sun::star::sdb::BooleanComparisonMode;
+}
+
+constexpr OUStringLiteral STR_SELECT = u"SELECT ";
+constexpr OUStringLiteral STR_FROM = u" FROM ";
+constexpr OUStringLiteral STR_WHERE = u" WHERE ";
+constexpr OUStringLiteral STR_GROUP_BY = u" GROUP BY ";
+constexpr OUStringLiteral STR_HAVING = u" HAVING ";
+constexpr OUStringLiteral STR_ORDER_BY = u" ORDER BY ";
+constexpr OUStringLiteral STR_AND = u" AND ";
+constexpr OUStringLiteral STR_OR = u" OR ";
+constexpr OUStringLiteral STR_LIKE = u" LIKE ";
+constexpr OUStringLiteral L_BRACKET = u"(";
+constexpr OUStringLiteral R_BRACKET = u")";
+constexpr OUStringLiteral COMMA = u",";
+
+namespace
+{
+ /** parses the given statement, using the given parser, returns a parse node representing
+ the statement
+
+ If the statement cannot be parsed, an error is thrown.
+ */
+ std::unique_ptr<OSQLParseNode> parseStatement_throwError( OSQLParser& _rParser, const OUString& _rStatement, const Reference< XInterface >& _rxContext )
+ {
+ OUString aErrorMsg;
+ std::unique_ptr<OSQLParseNode> pNewSqlParseNode = _rParser.parseTree( aErrorMsg, _rStatement );
+ if ( !pNewSqlParseNode )
+ {
+ OUString sSQLStateGeneralError( getStandardSQLState( StandardSQLState::GENERAL_ERROR ) );
+ SQLException aError2( aErrorMsg, _rxContext, sSQLStateGeneralError, 1000, Any() );
+ SQLException aError1( _rStatement, _rxContext, sSQLStateGeneralError, 1000, Any( aError2 ) );
+ throw SQLException(_rParser.getContext().getErrorMessage(OParseContext::ErrorCode::General),_rxContext,sSQLStateGeneralError,1000,Any(aError1));
+ }
+ return pNewSqlParseNode;
+ }
+
+ /** checks whether the given parse node describes a valid single select statement, throws
+ an error if not
+ */
+ void checkForSingleSelect_throwError( const OSQLParseNode* pStatementNode, OSQLParseTreeIterator& _rIterator,
+ const Reference< XInterface >& _rxContext, const OUString& _rOriginatingCommand )
+ {
+ const OSQLParseNode* pOldNode = _rIterator.getParseTree();
+
+ // determine the statement type
+ _rIterator.setParseTree( pStatementNode );
+ _rIterator.traverseAll();
+ bool bIsSingleSelect = ( _rIterator.getStatementType() == OSQLStatementType::Select );
+
+ // throw the error, if necessary
+ if ( !bIsSingleSelect || SQL_ISRULE( pStatementNode, union_statement ) ) // #i4229# OJ
+ {
+ // restore the old node before throwing the exception
+ _rIterator.setParseTree( pOldNode );
+ // and now really ...
+ SQLException aError1( _rOriginatingCommand, _rxContext, getStandardSQLState( StandardSQLState::GENERAL_ERROR ), 1000, Any() );
+ throw SQLException( DBA_RES( RID_STR_ONLY_QUERY ), _rxContext,
+ getStandardSQLState( StandardSQLState::GENERAL_ERROR ), 1000, Any( aError1 ) );
+ }
+
+ delete pOldNode;
+ }
+
+ /** combines parseStatement_throwError and checkForSingleSelect_throwError
+ */
+ void parseAndCheck_throwError( OSQLParser& _rParser, const OUString& _rStatement,
+ OSQLParseTreeIterator& _rIterator, const Reference< XInterface >& _rxContext )
+ {
+ std::unique_ptr<OSQLParseNode> pNode = parseStatement_throwError( _rParser, _rStatement, _rxContext );
+ checkForSingleSelect_throwError( pNode.release(), _rIterator, _rxContext, _rStatement );
+ }
+
+ /** transforms a parse node describing a complete statement into a pure select
+ statement, without any filter/order/groupby/having clauses
+ */
+ OUString getPureSelectStatement( const OSQLParseNode* _pRootNode, const Reference< XConnection >& _rxConnection )
+ {
+ OUString sSQL = STR_SELECT;
+ _pRootNode->getChild(1)->parseNodeToStr( sSQL, _rxConnection );
+ _pRootNode->getChild(2)->parseNodeToStr( sSQL, _rxConnection );
+ sSQL += STR_FROM;
+ _pRootNode->getChild(3)->getChild(0)->getChild(1)->parseNodeToStr( sSQL, _rxConnection );
+ return sSQL;
+ }
+
+ /** resets an SQL iterator, including deletion of the parse tree, and dispose
+ */
+ void resetIterator( OSQLParseTreeIterator& _rIterator )
+ {
+ const OSQLParseNode* pSqlParseNode = _rIterator.getParseTree();
+ _rIterator.setParseTree(nullptr);
+ delete pSqlParseNode;
+ _rIterator.dispose();
+ }
+ void lcl_addFilterCriteria_throw(sal_Int32 i_nFilterOperator,std::u16string_view i_sValue,OUStringBuffer& o_sRet)
+ {
+ switch( i_nFilterOperator )
+ {
+ case SQLFilterOperator::EQUAL:
+ o_sRet.append(OUString::Concat(" = ") + i_sValue);
+ break;
+ case SQLFilterOperator::NOT_EQUAL:
+ o_sRet.append(OUString::Concat(" <> ") + i_sValue);
+ break;
+ case SQLFilterOperator::LESS:
+ o_sRet.append(OUString::Concat(" < ") + i_sValue);
+ break;
+ case SQLFilterOperator::GREATER:
+ o_sRet.append(OUString::Concat(" > ") + i_sValue);
+ break;
+ case SQLFilterOperator::LESS_EQUAL:
+ o_sRet.append(OUString::Concat(" <= ") + i_sValue);
+ break;
+ case SQLFilterOperator::GREATER_EQUAL:
+ o_sRet.append(OUString::Concat(" >= ") + i_sValue);
+ break;
+ case SQLFilterOperator::LIKE:
+ o_sRet.append(OUString::Concat(" LIKE ") + i_sValue);
+ break;
+ case SQLFilterOperator::NOT_LIKE:
+ o_sRet.append(OUString::Concat(" NOT LIKE ") + i_sValue);
+ break;
+ case SQLFilterOperator::SQLNULL:
+ o_sRet.append(" IS NULL");
+ break;
+ case SQLFilterOperator::NOT_SQLNULL:
+ o_sRet.append(" IS NOT NULL");
+ break;
+ default:
+ throw SQLException();
+ }
+ }
+
+}
+
+
+OSingleSelectQueryComposer::OSingleSelectQueryComposer(const Reference< XNameAccess>& _rxTables,
+ const Reference< XConnection>& _xConnection,
+ const Reference<XComponentContext>& _rContext )
+ :OSubComponent(m_aMutex,_xConnection)
+ ,OPropertyContainer(m_aBHelper)
+ ,m_aSqlParser( _rContext, &m_aParseContext )
+ ,m_aSqlIterator( _xConnection, _rxTables, m_aSqlParser )
+ ,m_aAdditiveIterator( _xConnection, _rxTables, m_aSqlParser )
+ ,m_aElementaryParts( size_t(SQLPartCount) )
+ ,m_xConnection(_xConnection)
+ ,m_xMetaData(_xConnection->getMetaData())
+ ,m_xConnectionTables( _rxTables )
+ ,m_aContext( _rContext )
+ ,m_nBoolCompareMode( BooleanComparisonMode::EQUAL_INTEGER )
+ ,m_nCommandType(CommandType::COMMAND)
+{
+ if ( !m_aContext.is() || !m_xConnection.is() || !m_xConnectionTables.is() )
+ throw IllegalArgumentException();
+
+ registerProperty(PROPERTY_ORIGINAL,PROPERTY_ID_ORIGINAL,PropertyAttribute::BOUND|PropertyAttribute::READONLY,&m_sOriginal,cppu::UnoType<decltype(m_sOriginal)>::get());
+
+ m_aCurrentColumns.resize(4);
+
+ m_aLocale = m_aParseContext.getPreferredLocale();
+ m_xNumberFormatsSupplier = dbtools::getNumberFormats( m_xConnection, true, m_aContext );
+ Reference< XLocaleData4 > xLocaleData( LocaleData::create(m_aContext) );
+ LocaleDataItem aData = xLocaleData->getLocaleItem(m_aLocale);
+ m_sDecimalSep = aData.decimalSeparator;
+ OSL_ENSURE(m_sDecimalSep.getLength() == 1,"OSingleSelectQueryComposer::OSingleSelectQueryComposer decimal separator is not 1 length");
+ try
+ {
+ Any aValue;
+ Reference<XInterface> xDs = dbaccess::getDataSource(_xConnection);
+ if ( dbtools::getDataSourceSetting(xDs,static_cast <OUString> (PROPERTY_BOOLEANCOMPARISONMODE),aValue) )
+ {
+ OSL_VERIFY( aValue >>= m_nBoolCompareMode );
+ }
+ Reference< XQueriesSupplier > xQueriesAccess(m_xConnection, UNO_QUERY);
+ if (xQueriesAccess.is())
+ m_xConnectionQueries = xQueriesAccess->getQueries();
+ }
+ catch(Exception&)
+ {
+ }
+}
+
+OSingleSelectQueryComposer::~OSingleSelectQueryComposer()
+{
+}
+
+// OComponentHelper
+void SAL_CALL OSingleSelectQueryComposer::disposing()
+{
+ OSubComponent::disposing();
+
+ MutexGuard aGuard(m_aMutex);
+
+ resetIterator( m_aSqlIterator );
+ resetIterator( m_aAdditiveIterator );
+
+ m_xConnectionTables = nullptr;
+ m_xConnection = nullptr;
+
+ clearCurrentCollections();
+}
+
+IMPLEMENT_FORWARD_XINTERFACE3(OSingleSelectQueryComposer,OSubComponent,OSingleSelectQueryComposer_BASE,OPropertyContainer)
+OUString SAL_CALL OSingleSelectQueryComposer::getImplementationName()
+ {
+ return "org.openoffice.comp.dba.OSingleSelectQueryComposer";
+ }
+sal_Bool SAL_CALL OSingleSelectQueryComposer::supportsService(const OUString& _rServiceName)
+ {
+ const css::uno::Sequence< OUString > aSupported(getSupportedServiceNames());
+ for (const OUString& s : aSupported)
+ if (s == _rServiceName)
+ return true;
+
+ return false;
+ }
+css::uno::Sequence< OUString > SAL_CALL OSingleSelectQueryComposer::getSupportedServiceNames()
+{
+ return { SERVICE_NAME_SINGLESELECTQUERYCOMPOSER };
+}
+
+css::uno::Sequence<sal_Int8> OSingleSelectQueryComposer::getImplementationId()
+{
+ return css::uno::Sequence<sal_Int8>();
+}
+
+css::uno::Sequence< css::uno::Type > OSingleSelectQueryComposer::getTypes()
+{
+ return ::comphelper::concatSequences(
+ OSubComponent::getTypes( ),
+ OSingleSelectQueryComposer_BASE::getTypes( ),
+ OPropertyContainer::getTypes( )
+ );
+}
+
+css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL OSingleSelectQueryComposer::getPropertySetInfo()
+{
+ Reference< XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) );
+ return xInfo;
+}
+::cppu::IPropertyArrayHelper& OSingleSelectQueryComposer::getInfoHelper()
+{
+ return *OSingleSelectQueryComposer::getArrayHelper();
+}
+::cppu::IPropertyArrayHelper* OSingleSelectQueryComposer::createArrayHelper( ) const
+{
+ css::uno::Sequence< css::beans::Property > aProps;
+ describeProperties(aProps);
+ return new ::cppu::OPropertyArrayHelper(aProps);
+}
+
+
+// XSingleSelectQueryAnalyzer
+OUString SAL_CALL OSingleSelectQueryComposer::getQuery( )
+{
+ ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ TGetParseNode F_tmp(&OSQLParseTreeIterator::getParseTree);
+ return getStatementPart(F_tmp,m_aSqlIterator);
+}
+
+void SAL_CALL OSingleSelectQueryComposer::setQuery( const OUString& command )
+{
+ ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
+
+ ::osl::MutexGuard aGuard( m_aMutex );
+ m_nCommandType = CommandType::COMMAND;
+ // first clear the tables and columns
+ clearCurrentCollections();
+ // now set the new one
+ setQuery_Impl(command);
+ m_sOriginal = command;
+
+ // reset the additive iterator to the same statement
+ parseAndCheck_throwError( m_aSqlParser, m_sOriginal, m_aAdditiveIterator, *this );
+
+ // we have no "elementary" parts anymore (means filter/groupby/having/order clauses)
+ for ( SQLPart eLoopParts = Where; eLoopParts != SQLPartCount; incSQLPart( eLoopParts ) )
+ m_aElementaryParts[ eLoopParts ].clear();
+}
+
+void SAL_CALL OSingleSelectQueryComposer::setCommand( const OUString& Command,sal_Int32 _nCommandType )
+{
+ OUStringBuffer sSQL;
+ switch(_nCommandType)
+ {
+ case CommandType::COMMAND:
+ setElementaryQuery(Command);
+ return;
+ case CommandType::TABLE:
+ if ( m_xConnectionTables->hasByName(Command) )
+ {
+ sSQL.append("SELECT * FROM ");
+ Reference< XPropertySet > xTable;
+ try
+ {
+ m_xConnectionTables->getByName( Command ) >>= xTable;
+ }
+ catch(const WrappedTargetException& e)
+ {
+ SQLException e2;
+ if ( e.TargetException >>= e2 )
+ throw e2;
+ }
+ catch(Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+
+ sSQL.append(dbtools::composeTableNameForSelect(m_xConnection,xTable));
+ }
+ else
+ {
+ OUString sMessage( DBA_RES( RID_STR_TABLE_DOES_NOT_EXIST ) );
+ throwGenericSQLException(sMessage.replaceAll( "$table$", Command ),*this);
+ }
+ break;
+ case CommandType::QUERY:
+ if ( m_xConnectionQueries->hasByName(Command) )
+ {
+
+ Reference<XPropertySet> xQuery(m_xConnectionQueries->getByName(Command),UNO_QUERY);
+ OUString sCommand;
+ xQuery->getPropertyValue(PROPERTY_COMMAND) >>= sCommand;
+ sSQL.append(sCommand);
+ }
+ else
+ {
+ OUString sMessage( DBA_RES( RID_STR_QUERY_DOES_NOT_EXIST ) );
+ throwGenericSQLException(sMessage.replaceAll( "$table$", Command ),*this);
+ }
+
+ break;
+ default:
+ break;
+ }
+ ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
+
+ ::osl::MutexGuard aGuard( m_aMutex );
+ m_nCommandType = _nCommandType;
+ m_sCommand = Command;
+ // first clear the tables and columns
+ clearCurrentCollections();
+ // now set the new one
+ OUString sCommand = sSQL.makeStringAndClear();
+ setElementaryQuery(sCommand);
+ m_sOriginal = sCommand;
+}
+
+void OSingleSelectQueryComposer::setQuery_Impl( const OUString& command )
+{
+ // parse this
+ parseAndCheck_throwError( m_aSqlParser, command, m_aSqlIterator, *this );
+
+ // strip it from all clauses, to have the pure SELECT statement
+ m_aPureSelectSQL = getPureSelectStatement( m_aSqlIterator.getParseTree(), m_xConnection );
+
+ // update tables
+ getTables();
+}
+
+Sequence< Sequence< PropertyValue > > SAL_CALL OSingleSelectQueryComposer::getStructuredHavingClause( )
+{
+ TGetParseNode F_tmp(&OSQLParseTreeIterator::getSimpleHavingTree);
+ return getStructuredCondition(F_tmp);
+}
+
+Sequence< Sequence< PropertyValue > > SAL_CALL OSingleSelectQueryComposer::getStructuredFilter( )
+{
+ TGetParseNode F_tmp(&OSQLParseTreeIterator::getSimpleWhereTree);
+ return getStructuredCondition(F_tmp);
+}
+
+void SAL_CALL OSingleSelectQueryComposer::appendHavingClauseByColumn( const Reference< XPropertySet >& column, sal_Bool andCriteria,sal_Int32 filterOperator )
+{
+ auto F_tmp = std::mem_fn(&OSingleSelectQueryComposer::implSetHavingClause);
+ setConditionByColumn(column,andCriteria,F_tmp,filterOperator);
+}
+
+void SAL_CALL OSingleSelectQueryComposer::appendFilterByColumn( const Reference< XPropertySet >& column, sal_Bool andCriteria,sal_Int32 filterOperator )
+{
+ auto F_tmp = std::mem_fn(&OSingleSelectQueryComposer::implSetFilter);
+ setConditionByColumn(column,andCriteria,F_tmp,filterOperator);
+}
+
+OUString OSingleSelectQueryComposer::impl_getColumnRealName_throw(const Reference< XPropertySet >& column, bool bGroupBy)
+{
+ ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
+
+ getColumns();
+ if ( !column.is()
+ || !m_aCurrentColumns[SelectColumns]
+ || !column->getPropertySetInfo()->hasPropertyByName(PROPERTY_NAME)
+ )
+ {
+ OUString sError(DBA_RES(RID_STR_COLUMN_UNKNOWN_PROP));
+ SQLException aErr(sError.replaceAll("%value", PROPERTY_NAME),*this,SQLSTATE_GENERAL,1000,Any() );
+ throw SQLException(DBA_RES(RID_STR_COLUMN_NOT_VALID),*this,SQLSTATE_GENERAL,1000,Any(aErr) );
+ }
+
+ OUString aName, aNewName;
+ column->getPropertyValue(PROPERTY_NAME) >>= aName;
+
+ if ( bGroupBy &&
+ !m_xMetaData->supportsGroupByUnrelated() &&
+ m_aCurrentColumns[SelectColumns] &&
+ !m_aCurrentColumns[SelectColumns]->hasByName(aName) )
+ {
+ OUString sError(DBA_RES(RID_STR_COLUMN_MUST_VISIBLE));
+ throw SQLException(sError.replaceAll("%name", aName),*this,SQLSTATE_GENERAL,1000,Any() );
+ }
+
+ OUString aQuote = m_xMetaData->getIdentifierQuoteString();
+ if ( m_aCurrentColumns[SelectColumns]->hasByName(aName) )
+ {
+ Reference<XPropertySet> xColumn;
+ m_aCurrentColumns[SelectColumns]->getByName(aName) >>= xColumn;
+ OSL_ENSURE(xColumn->getPropertySetInfo()->hasPropertyByName(PROPERTY_REALNAME),"Property REALNAME not available!");
+ OSL_ENSURE(xColumn->getPropertySetInfo()->hasPropertyByName(PROPERTY_TABLENAME),"Property TABLENAME not available!");
+ OSL_ENSURE(xColumn->getPropertySetInfo()->hasPropertyByName("Function"),"Property FUNCTION not available!");
+
+ OUString sRealName, sTableName;
+ xColumn->getPropertyValue(PROPERTY_REALNAME) >>= sRealName;
+ xColumn->getPropertyValue(PROPERTY_TABLENAME) >>= sTableName;
+ bool bFunction = false;
+ xColumn->getPropertyValue("Function") >>= bFunction;
+ if ( sRealName == aName )
+ {
+ if ( bFunction )
+ aNewName = aName;
+ else
+ {
+ if(sTableName.indexOf('.') != -1)
+ {
+ OUString aCatlog,aSchema,aTable;
+ ::dbtools::qualifiedNameComponents(m_xMetaData,sTableName,aCatlog,aSchema,aTable,::dbtools::EComposeRule::InDataManipulation);
+ sTableName = ::dbtools::composeTableName( m_xMetaData, aCatlog, aSchema, aTable, true, ::dbtools::EComposeRule::InDataManipulation );
+ }
+ else if (!sTableName.isEmpty())
+ sTableName = ::dbtools::quoteName(aQuote,sTableName);
+
+ if(sTableName.isEmpty())
+ aNewName = ::dbtools::quoteName(aQuote,sRealName);
+ else
+ aNewName = sTableName + "." + ::dbtools::quoteName(aQuote,sRealName);
+ }
+ }
+ else
+ aNewName = ::dbtools::quoteName(aQuote,aName);
+ }
+ else
+ aNewName = getTableAlias(column) + ::dbtools::quoteName(aQuote,aName);
+ return aNewName;
+}
+
+OUString OSingleSelectQueryComposer::impl_getColumnNameOrderBy_throw(const Reference< XPropertySet >& column)
+{
+ ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
+
+ getColumns();
+ if ( !column.is()
+ || !m_aCurrentColumns[SelectColumns]
+ || !column->getPropertySetInfo()->hasPropertyByName(PROPERTY_NAME)
+ )
+ {
+ OUString sError(DBA_RES(RID_STR_COLUMN_UNKNOWN_PROP));
+ SQLException aErr(sError.replaceAll("%value", PROPERTY_NAME),*this,SQLSTATE_GENERAL,1000,Any() );
+ throw SQLException(DBA_RES(RID_STR_COLUMN_NOT_VALID),*this,SQLSTATE_GENERAL,1000,Any(aErr) );
+ }
+
+ OUString aName;
+ column->getPropertyValue(PROPERTY_NAME) >>= aName;
+
+ const OUString aQuote = m_xMetaData->getIdentifierQuoteString();
+
+ if ( m_aCurrentColumns[SelectColumns] &&
+ m_aCurrentColumns[SelectColumns]->hasByName(aName) )
+ {
+ // It is a column from the SELECT list, use it as such.
+ return ::dbtools::quoteName(aQuote,aName);
+ }
+
+ // Nope, it is an unrelated column.
+ // Is that supported?
+ if ( !m_xMetaData->supportsOrderByUnrelated() )
+ {
+ OUString sError(DBA_RES(RID_STR_COLUMN_MUST_VISIBLE));
+ throw SQLException(sError.replaceAll("%name", aName),*this,SQLSTATE_GENERAL,1000,Any() );
+ }
+
+ // We need to refer to it by its "real" name, that is by schemaName.tableName.columnNameInTable
+ return impl_getColumnRealName_throw(column, false);
+}
+
+void SAL_CALL OSingleSelectQueryComposer::appendOrderByColumn( const Reference< XPropertySet >& column, sal_Bool ascending )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ OUString sColumnName( impl_getColumnNameOrderBy_throw(column) );
+ OUString sOrder = getOrder();
+ if ( !(sOrder.isEmpty() || sColumnName.isEmpty()) )
+ sOrder += COMMA;
+ sOrder += sColumnName;
+ if ( !(ascending || sColumnName.isEmpty()) )
+ sOrder += " DESC ";
+
+ setOrder(sOrder);
+}
+
+void SAL_CALL OSingleSelectQueryComposer::appendGroupByColumn( const Reference< XPropertySet >& column)
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ OUString sColumnName( impl_getColumnRealName_throw(column, true) );
+ OrderCreator aComposer;
+ aComposer.append( getGroup() );
+ aComposer.append( sColumnName );
+ setGroup( aComposer.getComposedAndClear() );
+}
+
+OUString OSingleSelectQueryComposer::composeStatementFromParts( const std::vector< OUString >& _rParts )
+{
+ OSL_ENSURE( _rParts.size() == size_t(SQLPartCount), "OSingleSelectQueryComposer::composeStatementFromParts: invalid parts array!" );
+
+ OUStringBuffer aSql( m_aPureSelectSQL );
+ for ( SQLPart eLoopParts = Where; eLoopParts != SQLPartCount; incSQLPart( eLoopParts ) )
+ if ( !_rParts[ eLoopParts ].isEmpty() )
+ {
+ aSql.append( getKeyword( eLoopParts ) );
+ aSql.append( _rParts[ eLoopParts ] );
+ }
+
+ return aSql.makeStringAndClear();
+}
+
+OUString SAL_CALL OSingleSelectQueryComposer::getElementaryQuery()
+{
+ return composeStatementFromParts( m_aElementaryParts );
+}
+
+void SAL_CALL OSingleSelectQueryComposer::setElementaryQuery( const OUString& _rElementary )
+{
+ ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ // remember the 4 current "additive" clauses
+ std::vector< OUString > aAdditiveClauses( SQLPartCount );
+ for ( SQLPart eLoopParts = Where; eLoopParts != SQLPartCount; incSQLPart( eLoopParts ) )
+ aAdditiveClauses[ eLoopParts ] = getSQLPart( eLoopParts, m_aAdditiveIterator, false );
+
+ // clear the tables and columns
+ clearCurrentCollections();
+ // set and parse the new query
+ setQuery_Impl( _rElementary );
+
+ // get the 4 elementary parts of the statement
+ for ( SQLPart eLoopParts = Where; eLoopParts != SQLPartCount; incSQLPart( eLoopParts ) )
+ m_aElementaryParts[ eLoopParts ] = getSQLPart( eLoopParts, m_aSqlIterator, false );
+
+ // reset the AdditiveIterator: m_aPureSelectSQL may have changed
+ try
+ {
+ parseAndCheck_throwError( m_aSqlParser, composeStatementFromParts( aAdditiveClauses ), m_aAdditiveIterator, *this );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ SAL_WARN("dbaccess", "OSingleSelectQueryComposer::setElementaryQuery: there should be no error anymore for the additive statement!" );
+ // every part of the additive statement should have passed other tests already, and should not
+ // be able to cause any errors ... me thinks
+ }
+}
+
+namespace
+{
+ OUString getComposedClause( const OUString& _rElementaryClause, const OUString& _rAdditionalClause,
+ TokenComposer& _rComposer, std::u16string_view _rKeyword )
+ {
+ _rComposer.clear();
+ _rComposer.append( _rElementaryClause );
+ _rComposer.append( _rAdditionalClause );
+ OUString sComposed = _rComposer.getComposedAndClear();
+ if ( !sComposed.isEmpty() )
+ sComposed = _rKeyword + sComposed;
+ return sComposed;
+ }
+}
+
+void OSingleSelectQueryComposer::setSingleAdditiveClause( SQLPart _ePart, const OUString& _rClause )
+{
+ ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ // if nothing is changed, do nothing
+ if ( getSQLPart( _ePart, m_aAdditiveIterator, false ) == _rClause )
+ return;
+
+ // collect the 4 single parts as they're currently set
+ std::vector< OUString > aClauses;
+ aClauses.reserve( size_t(SQLPartCount) );
+ for ( SQLPart eLoopParts = Where; eLoopParts != SQLPartCount; incSQLPart( eLoopParts ) )
+ aClauses.push_back( getSQLPart( eLoopParts, m_aSqlIterator, true ) );
+
+ // overwrite the one part in question here
+ std::unique_ptr< TokenComposer > pComposer;
+ if ( ( _ePart == Where ) || ( _ePart == Having ) )
+ pComposer.reset( new FilterCreator );
+ else
+ pComposer.reset( new OrderCreator );
+ aClauses[ _ePart ] = getComposedClause( m_aElementaryParts[ _ePart ], _rClause,
+ *pComposer, getKeyword( _ePart ) );
+
+ // construct the complete statement
+ OUStringBuffer aSql(m_aPureSelectSQL);
+ for ( SQLPart eLoopParts = Where; eLoopParts != SQLPartCount; incSQLPart( eLoopParts ) )
+ aSql.append(aClauses[ eLoopParts ]);
+
+ // set the query
+ setQuery_Impl(aSql.makeStringAndClear());
+
+ // clear column collections which (might) have changed
+ clearColumns( ParameterColumns );
+ if ( _ePart == Order )
+ clearColumns( OrderColumns );
+ else if ( _ePart == Group )
+ clearColumns( GroupByColumns );
+
+ // also, since the "additive filter" change, we need to rebuild our "additive" statement
+ aSql = m_aPureSelectSQL;
+ // again, first get all the old additive parts
+ for ( SQLPart eLoopParts = Where; eLoopParts != SQLPartCount; incSQLPart( eLoopParts ) )
+ aClauses[ eLoopParts ] = getSQLPart( eLoopParts, m_aAdditiveIterator, true );
+ // then overwrite the one in question
+ aClauses[ _ePart ] = getComposedClause( OUString(), _rClause, *pComposer, getKeyword( _ePart ) );
+ // and parse it, so that m_aAdditiveIterator is up to date
+ for ( SQLPart eLoopParts = Where; eLoopParts != SQLPartCount; incSQLPart( eLoopParts ) )
+ aSql.append(aClauses[ eLoopParts ]);
+ try
+ {
+ parseAndCheck_throwError( m_aSqlParser, aSql.makeStringAndClear(), m_aAdditiveIterator, *this );
+ }
+ catch( const Exception& )
+ {
+ SAL_WARN("dbaccess", "OSingleSelectQueryComposer::setSingleAdditiveClause: there should be no error anymore for the additive statement!" );
+ // every part of the additive statement should have passed other tests already, and should not
+ // be able to cause any errors ... me thinks
+ }
+}
+
+void SAL_CALL OSingleSelectQueryComposer::setFilter( const OUString& filter )
+{
+ setSingleAdditiveClause( Where, filter );
+}
+
+void SAL_CALL OSingleSelectQueryComposer::setOrder( const OUString& order )
+{
+ setSingleAdditiveClause( Order, order );
+}
+
+void SAL_CALL OSingleSelectQueryComposer::setGroup( const OUString& group )
+{
+ setSingleAdditiveClause( Group, group );
+}
+
+void SAL_CALL OSingleSelectQueryComposer::setHavingClause( const OUString& filter )
+{
+ setSingleAdditiveClause( Having, filter );
+}
+
+// XTablesSupplier
+Reference< XNameAccess > SAL_CALL OSingleSelectQueryComposer::getTables( )
+{
+ ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
+
+ ::osl::MutexGuard aGuard( m_aMutex );
+ if ( !m_pTables )
+ {
+ const OSQLTables& aTables = m_aSqlIterator.getTables();
+ std::vector< OUString> aNames;
+ for (auto const& elem : aTables)
+ aNames.push_back(elem.first);
+
+ m_pTables.reset( new OPrivateTables(aTables,m_xMetaData->supportsMixedCaseQuotedIdentifiers(),*this,m_aMutex,std::move(aNames)) );
+ }
+
+ return m_pTables.get();
+}
+
+// XColumnsSupplier
+Reference< XNameAccess > SAL_CALL OSingleSelectQueryComposer::getColumns( )
+{
+ ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
+ ::osl::MutexGuard aGuard( m_aMutex );
+ if ( !!m_aCurrentColumns[SelectColumns] )
+ return m_aCurrentColumns[SelectColumns].get();
+
+ std::vector< OUString> aNames;
+ ::rtl::Reference< OSQLColumns> aSelectColumns;
+ bool bCase = true;
+ Reference< XNameAccess> xQueryColumns;
+ if ( m_nCommandType == CommandType::QUERY )
+ {
+ Reference<XColumnsSupplier> xSup(m_xConnectionQueries->getByName(m_sCommand),UNO_QUERY);
+ if(xSup.is())
+ xQueryColumns = xSup->getColumns();
+ }
+
+ do {
+
+ try
+ {
+ SharedUNOComponent< XStatement, DisposableComponent > xStatement;
+ SharedUNOComponent< XPreparedStatement, DisposableComponent > xPreparedStatement;
+
+ bCase = m_xMetaData->supportsMixedCaseQuotedIdentifiers();
+ aSelectColumns = m_aSqlIterator.getSelectColumns();
+
+ OUStringBuffer aSQL( m_aPureSelectSQL + STR_WHERE + " ( 0 = 1 )");
+
+ // preserve the original WHERE clause
+ // #i102234#
+ OUString sOriginalWhereClause = getSQLPart( Where, m_aSqlIterator, false );
+ if ( !sOriginalWhereClause.isEmpty() )
+ {
+ aSQL.append( " AND ( " + sOriginalWhereClause + " ) " );
+ }
+
+ OUString sGroupBy = getSQLPart( Group, m_aSqlIterator, true );
+ if ( !sGroupBy.isEmpty() )
+ aSQL.append( sGroupBy );
+
+ OUString sSQL( aSQL.makeStringAndClear() );
+ // normalize the statement so that it doesn't contain any application-level features anymore
+ OUString sError;
+ const std::unique_ptr< OSQLParseNode > pStatementTree( m_aSqlParser.parseTree( sError, sSQL ) );
+ OSL_ENSURE(pStatementTree, "OSingleSelectQueryComposer::getColumns: could not parse the "
+ "column retrieval statement!");
+ if (pStatementTree)
+ if ( !pStatementTree->parseNodeToExecutableStatement( sSQL, m_xConnection, m_aSqlParser, nullptr ) )
+ break;
+
+ Reference< XResultSetMetaData > xResultSetMeta;
+ Reference< XResultSetMetaDataSupplier > xResMetaDataSup;
+ try
+ {
+ xPreparedStatement.set( m_xConnection->prepareStatement( sSQL ), UNO_QUERY_THROW );
+ xResMetaDataSup.set( xPreparedStatement, UNO_QUERY_THROW );
+ xResultSetMeta.set( xResMetaDataSup->getMetaData(), UNO_SET_THROW );
+ }
+ catch( const Exception& ) { }
+
+ if ( !xResultSetMeta.is() && xPreparedStatement.is() )
+ {
+ try
+ {
+ //@see issue http://qa.openoffice.org/issues/show_bug.cgi?id=110111
+ // access returns a different order of column names when executing select * from
+ // and asking the columns from the metadata.
+ Reference< XParameters > xParameters( xPreparedStatement, UNO_QUERY_THROW );
+ Reference< XIndexAccess > xPara = getParameters();
+ for(sal_Int32 i = 1;i <= xPara->getCount();++i)
+ xParameters->setNull(i,DataType::VARCHAR);
+ xResMetaDataSup.set(xPreparedStatement->executeQuery(), UNO_QUERY_THROW );
+ xResultSetMeta.set( xResMetaDataSup->getMetaData(), UNO_SET_THROW );
+ }
+ catch( const Exception& ) { }
+ }
+
+ if ( !xResultSetMeta.is() )
+ {
+ xStatement.reset( Reference< XStatement >( m_xConnection->createStatement(), UNO_SET_THROW ) );
+ Reference< XPropertySet > xStatementProps( xStatement, UNO_QUERY_THROW );
+ try { xStatementProps->setPropertyValue( PROPERTY_ESCAPE_PROCESSING, Any( false ) ); }
+ catch ( const Exception& ) { DBG_UNHANDLED_EXCEPTION("dbaccess"); }
+ xResMetaDataSup.set( xStatement->executeQuery( sSQL ), UNO_QUERY_THROW );
+ xResultSetMeta.set( xResMetaDataSup->getMetaData(), UNO_SET_THROW );
+
+ if (xResultSetMeta.is())
+ {
+ SAL_WARN("dbaccess", "OSingleSelectQueryComposer::getColumns failed to get xResultSetMeta from executed PreparedStatement, but got it from 'no escape processing' statement. SQL command:\n\t" << sSQL );
+ }
+ }
+
+ if ( aSelectColumns->empty() )
+ {
+ // This is a valid case. If we can syntactically parse the query, but not semantically
+ // (e.g. because it is based on a table we do not know), then there will be no SelectColumns
+ aSelectColumns = ::connectivity::parse::OParseColumn::createColumnsForResultSet( xResultSetMeta, m_xMetaData ,xQueryColumns);
+ break;
+ }
+
+ const ::comphelper::UStringMixEqual aCaseCompare( bCase );
+ std::set< size_t > aUsedSelectColumns;
+ ::connectivity::parse::OParseColumn::StringMap aColumnNames;
+
+ sal_Int32 nCount = xResultSetMeta->getColumnCount();
+ OSL_ENSURE( static_cast<size_t>(nCount) == aSelectColumns->size(), "OSingleSelectQueryComposer::getColumns: inconsistent column counts, this might result in wrong columns!" );
+ for(sal_Int32 i=1;i<=nCount;++i)
+ {
+ OUString sColumnName = xResultSetMeta->getColumnName(i);
+ OUString sColumnLabel;
+ if ( xQueryColumns.is() && xQueryColumns->hasByName(sColumnName) )
+ {
+ Reference<XPropertySet> xQueryColumn(xQueryColumns->getByName(sColumnName),UNO_QUERY_THROW);
+ xQueryColumn->getPropertyValue(PROPERTY_LABEL) >>= sColumnLabel;
+ }
+ else
+ sColumnLabel = xResultSetMeta->getColumnLabel(i);
+ bool bFound = false;
+ OSQLColumns::Vector::const_iterator aFind = ::connectivity::find(aSelectColumns->begin(),aSelectColumns->end(),sColumnLabel,aCaseCompare);
+ size_t nFoundSelectColumnPos = aFind - aSelectColumns->begin();
+ if ( aFind != aSelectColumns->end() )
+ {
+ if ( aUsedSelectColumns.find( nFoundSelectColumnPos ) != aUsedSelectColumns.end() )
+ { // we found a column name which exists twice
+ // so we start after the first found
+ do
+ {
+ aFind = ::connectivity::findRealName(++aFind,aSelectColumns->end(),sColumnName,aCaseCompare);
+ nFoundSelectColumnPos = aFind - aSelectColumns->begin();
+ }
+ while ( ( aUsedSelectColumns.find( nFoundSelectColumnPos ) != aUsedSelectColumns.end() )
+ && ( aFind != aSelectColumns->end() )
+ );
+ }
+ if ( aFind != aSelectColumns->end() )
+ {
+ (*aFind)->getPropertyValue(PROPERTY_NAME) >>= sColumnName;
+ aUsedSelectColumns.insert( nFoundSelectColumnPos );
+ aNames.push_back(sColumnName);
+ bFound = true;
+ }
+ }
+
+ if ( bFound )
+ continue;
+
+ OSQLColumns::Vector::const_iterator aRealFind = ::connectivity::findRealName(
+ aSelectColumns->begin(), aSelectColumns->end(), sColumnName, aCaseCompare );
+
+ if ( i > static_cast< sal_Int32>( aSelectColumns->size() ) )
+ {
+ aSelectColumns->emplace_back(::connectivity::parse::OParseColumn::createColumnForResultSet( xResultSetMeta, m_xMetaData, i ,aColumnNames)
+ );
+ OSL_ENSURE( aSelectColumns->size() == static_cast<size_t>(i), "OSingleSelectQueryComposer::getColumns: inconsistency!" );
+ }
+ else if ( aRealFind == aSelectColumns->end() )
+ {
+ // we can now only look if we found it under the realname property
+ // here we have to make the assumption that the position is correct
+ OSQLColumns::Vector::const_iterator aFind2 = aSelectColumns->begin() + i-1;
+ Reference<XPropertySet> xProp = *aFind2;
+ if ( !xProp.is() || !xProp->getPropertySetInfo()->hasPropertyByName( PROPERTY_REALNAME ) )
+ continue;
+
+ rtl::Reference<::connectivity::parse::OParseColumn> pColumn = new ::connectivity::parse::OParseColumn(xProp,bCase);
+ pColumn->setFunction(::comphelper::getBOOL(xProp->getPropertyValue("Function")));
+ pColumn->setAggregateFunction(::comphelper::getBOOL(xProp->getPropertyValue("AggregateFunction")));
+
+ OUString sRealName;
+ xProp->getPropertyValue(PROPERTY_REALNAME) >>= sRealName;
+ if ( sColumnName.isEmpty() )
+ xProp->getPropertyValue(PROPERTY_NAME) >>= sColumnName;
+
+ sal_Int32 j = 0;
+ while ( std::any_of(aNames.begin(),aNames.end(),
+ [&aCaseCompare, &sColumnName](const OUString& lhs)
+ { return aCaseCompare(lhs, sColumnName); } ) )
+ {
+ sColumnName += OUString::number(++j);
+ }
+
+ pColumn->setName(sColumnName);
+ pColumn->setRealName(sRealName);
+ pColumn->setTableName(::comphelper::getString(xProp->getPropertyValue(PROPERTY_TABLENAME)));
+
+ (*aSelectColumns)[i-1] = pColumn;
+ }
+ else
+ continue;
+
+ aUsedSelectColumns.insert( static_cast<size_t>(i - 1) );
+ aNames.push_back( sColumnName );
+ }
+ }
+ catch(const Exception&)
+ {
+ }
+
+ } while ( false );
+
+ bool bMissingSomeColumnLabels = !aNames.empty() && aNames.size() != aSelectColumns->size();
+ SAL_WARN_IF(bMissingSomeColumnLabels, "dbaccess", "We have column labels for *some* columns but not all");
+ //^^this happens in the evolution address book where we have real column names of e.g.
+ //first_name, second_name and city. On parsing via
+ //OSQLParseTreeIterator::appendColumns it creates some labels using those real names
+ //but the evo address book gives them proper labels of First Name, Second Name and City
+ //the munge means that here we have e.g. just "City" as a label because it matches
+
+ //This is all a horrible mess
+ if (bMissingSomeColumnLabels)
+ aNames.clear();
+
+ if ( aNames.empty() )
+ m_aCurrentColumns[ SelectColumns ] = OPrivateColumns::createWithIntrinsicNames( aSelectColumns, bCase, *this, m_aMutex );
+ else
+ m_aCurrentColumns[ SelectColumns ].reset( new OPrivateColumns( aSelectColumns, bCase, *this, m_aMutex, aNames ) );
+
+ return m_aCurrentColumns[SelectColumns].get();
+}
+
+bool OSingleSelectQueryComposer::setORCriteria(OSQLParseNode const * pCondition, OSQLParseTreeIterator& _rIterator,
+ std::vector< std::vector < PropertyValue > >& rFilters, const Reference< css::util::XNumberFormatter > & xFormatter) const
+{
+ // Round brackets around the expression
+ if (pCondition->count() == 3 &&
+ SQL_ISPUNCTUATION(pCondition->getChild(0),"(") &&
+ SQL_ISPUNCTUATION(pCondition->getChild(2),")"))
+ {
+ return setORCriteria(pCondition->getChild(1), _rIterator, rFilters, xFormatter);
+ }
+ // OR logic expression
+ // a searchcondition can only look like this: search_condition SQL_TOKEN_OR boolean_term
+ else if (SQL_ISRULE(pCondition,search_condition))
+ {
+ bool bResult = true;
+ for (int i = 0; bResult && i < 3; i+=2)
+ {
+ // Is the first element a OR logic expression again?
+ // Then descend recursively ...
+ if (SQL_ISRULE(pCondition->getChild(i),search_condition))
+ bResult = setORCriteria(pCondition->getChild(i), _rIterator, rFilters, xFormatter);
+ else
+ {
+ rFilters.emplace_back();
+ bResult = setANDCriteria(pCondition->getChild(i), _rIterator, rFilters[rFilters.size() - 1], xFormatter);
+ }
+ }
+ return bResult;
+ }
+ else
+ {
+ rFilters.emplace_back();
+ return setANDCriteria(pCondition, _rIterator, rFilters[rFilters.size() - 1], xFormatter);
+ }
+}
+
+bool OSingleSelectQueryComposer::setANDCriteria( OSQLParseNode const * pCondition,
+ OSQLParseTreeIterator& _rIterator, std::vector < PropertyValue >& rFilter, const Reference< XNumberFormatter > & xFormatter) const
+{
+ // Round brackets
+ if (SQL_ISRULE(pCondition,boolean_primary))
+ {
+ // this should not occur
+ SAL_WARN("dbaccess","boolean_primary in And-Criteria");
+ return false;
+ }
+ // The first element is an AND logical expression again
+ else if ( SQL_ISRULE(pCondition,boolean_term) && pCondition->count() == 3 )
+ {
+ return setANDCriteria(pCondition->getChild(0), _rIterator, rFilter, xFormatter) &&
+ setANDCriteria(pCondition->getChild(2), _rIterator, rFilter, xFormatter);
+ }
+ else if (SQL_ISRULE(pCondition, comparison_predicate))
+ {
+ return setComparisonPredicate(pCondition,_rIterator,rFilter,xFormatter);
+ }
+ else if (SQL_ISRULE(pCondition,like_predicate))
+ {
+ return setLikePredicate(pCondition,_rIterator,rFilter,xFormatter);
+ }
+ else if (SQL_ISRULE(pCondition,test_for_null) ||
+ SQL_ISRULE(pCondition,in_predicate) ||
+ SQL_ISRULE(pCondition,all_or_any_predicate) ||
+ SQL_ISRULE(pCondition,between_predicate))
+ {
+ if (SQL_ISRULE(pCondition->getChild(0), column_ref))
+ {
+ PropertyValue aItem;
+ OUString aValue;
+ OUString aColumnName;
+
+ pCondition->parseNodeToStr( aValue, m_xConnection );
+ pCondition->getChild(0)->parseNodeToStr( aColumnName, m_xConnection );
+
+ // don't display the column name
+ aValue = aValue.copy(aColumnName.getLength());
+ aValue = aValue.trim();
+
+ aItem.Name = getColumnName(pCondition->getChild(0),_rIterator);
+ aItem.Value <<= aValue;
+ aItem.Handle = 0; // just to know that this is not one the known ones
+ if ( SQL_ISRULE(pCondition,like_predicate) )
+ {
+ if ( SQL_ISTOKEN(pCondition->getChild(1)->getChild(0),NOT) )
+ aItem.Handle = SQLFilterOperator::NOT_LIKE;
+ else
+ aItem.Handle = SQLFilterOperator::LIKE;
+ }
+ else if (SQL_ISRULE(pCondition,test_for_null))
+ {
+ if (SQL_ISTOKEN(pCondition->getChild(1)->getChild(1),NOT) )
+ aItem.Handle = SQLFilterOperator::NOT_SQLNULL;
+ else
+ aItem.Handle = SQLFilterOperator::SQLNULL;
+ }
+ else if (SQL_ISRULE(pCondition,in_predicate))
+ {
+ SAL_WARN("dbaccess", "OSingleSelectQueryComposer::setANDCriteria: in_predicate not implemented!" );
+ }
+ else if (SQL_ISRULE(pCondition,all_or_any_predicate))
+ {
+ SAL_WARN("dbaccess", "OSingleSelectQueryComposer::setANDCriteria: all_or_any_predicate not implemented!" );
+ }
+ else if (SQL_ISRULE(pCondition,between_predicate))
+ {
+ SAL_WARN("dbaccess", "OSingleSelectQueryComposer::setANDCriteria: between_predicate not implemented!" );
+ }
+
+ rFilter.push_back(aItem);
+ }
+ else
+ return false;
+ }
+ else if (SQL_ISRULE(pCondition,existence_test) ||
+ SQL_ISRULE(pCondition,unique_test))
+ {
+ // this couldn't be handled here, too complex
+ // as we need a field name
+ return false;
+ }
+ else
+ return false;
+
+ return true;
+}
+
+sal_Int32 OSingleSelectQueryComposer::getPredicateType(OSQLParseNode const * _pPredicate)
+{
+ sal_Int32 nPredicate = SQLFilterOperator::EQUAL;
+ switch (_pPredicate->getNodeType())
+ {
+ case SQLNodeType::Equal:
+ nPredicate = SQLFilterOperator::EQUAL;
+ break;
+ case SQLNodeType::NotEqual:
+ nPredicate = SQLFilterOperator::NOT_EQUAL;
+ break;
+ case SQLNodeType::Less:
+ nPredicate = SQLFilterOperator::LESS;
+ break;
+ case SQLNodeType::LessEq:
+ nPredicate = SQLFilterOperator::LESS_EQUAL;
+ break;
+ case SQLNodeType::Great:
+ nPredicate = SQLFilterOperator::GREATER;
+ break;
+ case SQLNodeType::GreatEq:
+ nPredicate = SQLFilterOperator::GREATER_EQUAL;
+ break;
+ default:
+ SAL_WARN("dbaccess","Wrong NodeType!");
+ }
+ return nPredicate;
+}
+
+bool OSingleSelectQueryComposer::setLikePredicate(OSQLParseNode const * pCondition, OSQLParseTreeIterator const & _rIterator,
+ std::vector < PropertyValue >& rFilter, const Reference< css::util::XNumberFormatter > & xFormatter) const
+{
+ OSL_ENSURE(SQL_ISRULE(pCondition, like_predicate),"setLikePredicate: pCondition is not a LikePredicate");
+
+ assert(pCondition->count() == 2);
+ OSQLParseNode const *pRowValue = pCondition->getChild(0);
+ OSQLParseNode const *pPart2 = pCondition->getChild(1);
+
+ PropertyValue aItem;
+ if ( SQL_ISTOKEN(pPart2->getChild(0),NOT) )
+ aItem.Handle = SQLFilterOperator::NOT_LIKE;
+ else
+ aItem.Handle = SQLFilterOperator::LIKE;
+
+ if (SQL_ISRULE(pRowValue, column_ref))
+ {
+ OUString aValue;
+
+ // skip (optional "NOT") and "LIKE"
+ for (size_t i=2; i < pPart2->count(); i++)
+ {
+ pPart2->getChild(i)->parseNodeToPredicateStr(
+ aValue, m_xConnection, xFormatter, m_aLocale, m_sDecimalSep );
+ }
+
+ aItem.Name = getColumnName(pRowValue,_rIterator);
+ aItem.Value <<= aValue;
+ rFilter.push_back(aItem);
+ }
+ else if (SQL_ISRULE(pRowValue, set_fct_spec ) ||
+ SQL_ISRULE(pRowValue, general_set_fct))
+ {
+ OUString aValue;
+ OUString aColumnName;
+
+ pPart2->getChild(2)->parseNodeToPredicateStr(aValue, m_xConnection, xFormatter, m_aLocale, m_sDecimalSep );
+ pPart2->getChild(3)->parseNodeToPredicateStr(aValue, m_xConnection, xFormatter, m_aLocale, m_sDecimalSep );
+ pRowValue->parseNodeToPredicateStr( aColumnName, m_xConnection, xFormatter, m_aLocale, m_sDecimalSep );
+
+ aItem.Name = getColumnName(pRowValue,_rIterator);
+ aItem.Value <<= aValue;
+ rFilter.push_back(aItem);
+ }
+ else // Can only be an expression
+ {
+ OUString aName, aValue;
+
+ OSQLParseNode const *pValue = pPart2->getChild(2);
+
+ // Field names
+ for (size_t i=0;i< pRowValue->count();i++)
+ pRowValue->getChild(i)->parseNodeToPredicateStr( aName, m_xConnection, xFormatter, m_aLocale, m_sDecimalSep );
+
+ // Criterion
+ for(size_t i=0;i< pValue->count();i++)
+ pValue->getChild(i)->parseNodeToPredicateStr(aValue, m_xConnection, xFormatter, m_aLocale, m_sDecimalSep );
+ pPart2->getChild(3)->parseNodeToPredicateStr(aValue, m_xConnection, xFormatter, m_aLocale, m_sDecimalSep );
+
+ aItem.Name = aName;
+ aItem.Value <<= aValue;
+ rFilter.push_back(aItem);
+ }
+ return true;
+}
+
+bool OSingleSelectQueryComposer::setComparisonPredicate(OSQLParseNode const * pCondition, OSQLParseTreeIterator const & _rIterator,
+ std::vector < PropertyValue >& rFilter, const Reference< css::util::XNumberFormatter > & xFormatter) const
+{
+ OSL_ENSURE(SQL_ISRULE(pCondition, comparison_predicate),"setComparisonPredicate: pCondition is not a ComparisonPredicate");
+ if (SQL_ISRULE(pCondition->getChild(0), column_ref) ||
+ SQL_ISRULE(pCondition->getChild(pCondition->count()-1), column_ref))
+ {
+ PropertyValue aItem;
+ OUString aValue;
+ sal_uInt32 nPos;
+ if (SQL_ISRULE(pCondition->getChild(0), column_ref))
+ {
+ nPos = 0;
+ size_t i=1;
+
+ aItem.Handle = getPredicateType(pCondition->getChild(i));
+
+ // go forward - don't display the operator
+ for (i++;i < pCondition->count();i++)
+ pCondition->getChild(i)->parseNodeToPredicateStr(
+ aValue, m_xConnection, xFormatter, m_aLocale, m_sDecimalSep );
+ }
+ else if (SQL_ISRULE(pCondition->getChild(pCondition->count()-1), column_ref))
+ {
+ nPos = pCondition->count()-1;
+
+ sal_Int32 i = pCondition->count() - 2;
+ switch (pCondition->getChild(i)->getNodeType())
+ {
+ case SQLNodeType::Equal:
+ aItem.Handle = SQLFilterOperator::EQUAL;
+ break;
+ case SQLNodeType::NotEqual:
+ aItem.Handle = SQLFilterOperator::NOT_EQUAL;
+ break;
+ case SQLNodeType::Less:
+ // take the opposite as we change the order
+ aItem.Handle = SQLFilterOperator::GREATER_EQUAL;
+ break;
+ case SQLNodeType::LessEq:
+ // take the opposite as we change the order
+ aItem.Handle = SQLFilterOperator::GREATER;
+ break;
+ case SQLNodeType::Great:
+ // take the opposite as we change the order
+ aItem.Handle = SQLFilterOperator::LESS_EQUAL;
+ break;
+ case SQLNodeType::GreatEq:
+ // take the opposite as we change the order
+ aItem.Handle = SQLFilterOperator::LESS;
+ break;
+ default:
+ break;
+ }
+
+ // go backward - don't display the operator
+ for (i--; i >= 0; i--)
+ pCondition->getChild(i)->parseNodeToPredicateStr(
+ aValue, m_xConnection, xFormatter, m_aLocale, m_sDecimalSep );
+ }
+ else
+ return false;
+
+ aItem.Name = getColumnName(pCondition->getChild(nPos),_rIterator);
+ aItem.Value <<= aValue;
+ rFilter.push_back(aItem);
+ }
+ else if (SQL_ISRULE(pCondition->getChild(0), set_fct_spec ) ||
+ SQL_ISRULE(pCondition->getChild(0), general_set_fct))
+ {
+ PropertyValue aItem;
+ OUString aValue;
+ OUString aColumnName;
+
+ pCondition->getChild(2)->parseNodeToPredicateStr(aValue, m_xConnection, xFormatter, m_aLocale, m_sDecimalSep );
+ pCondition->getChild(0)->parseNodeToPredicateStr( aColumnName, m_xConnection, xFormatter, m_aLocale, m_sDecimalSep );
+
+ aItem.Name = getColumnName(pCondition->getChild(0),_rIterator);
+ aItem.Value <<= aValue;
+ aItem.Handle = getPredicateType(pCondition->getChild(1));
+ rFilter.push_back(aItem);
+ }
+ else // Can only be an expression
+ {
+ PropertyValue aItem;
+ OUString aName, aValue;
+
+ OSQLParseNode *pLhs = pCondition->getChild(0);
+ OSQLParseNode *pRhs = pCondition->getChild(2);
+
+ // Field names
+ for (size_t i=0;i< pLhs->count();i++)
+ pLhs->getChild(i)->parseNodeToPredicateStr( aName, m_xConnection, xFormatter, m_aLocale, m_sDecimalSep );
+
+ // Criterion
+ aItem.Handle = getPredicateType(pCondition->getChild(1));
+ for(size_t i=0;i< pRhs->count();i++)
+ pRhs->getChild(i)->parseNodeToPredicateStr(aValue, m_xConnection, xFormatter, m_aLocale, m_sDecimalSep );
+
+ aItem.Name = aName;
+ aItem.Value <<= aValue;
+ rFilter.push_back(aItem);
+ }
+ return true;
+}
+
+// Functions for analysing SQL
+OUString OSingleSelectQueryComposer::getColumnName( ::connectivity::OSQLParseNode const * pColumnRef, OSQLParseTreeIterator const & _rIterator )
+{
+ OUString aTableRange, aColumnName;
+ _rIterator.getColumnRange(pColumnRef,aColumnName,aTableRange);
+ return aColumnName;
+}
+
+OUString SAL_CALL OSingleSelectQueryComposer::getFilter( )
+{
+ ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
+ ::osl::MutexGuard aGuard( m_aMutex );
+ return getSQLPart(Where,m_aAdditiveIterator,false);
+}
+
+OUString SAL_CALL OSingleSelectQueryComposer::getOrder( )
+{
+ ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
+ ::osl::MutexGuard aGuard( m_aMutex );
+ return getSQLPart(Order,m_aAdditiveIterator,false);
+}
+
+OUString SAL_CALL OSingleSelectQueryComposer::getGroup( )
+{
+ ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
+ ::osl::MutexGuard aGuard( m_aMutex );
+ return getSQLPart(Group,m_aAdditiveIterator,false);
+}
+
+OUString OSingleSelectQueryComposer::getHavingClause()
+{
+ ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
+ ::osl::MutexGuard aGuard( m_aMutex );
+ return getSQLPart(Having,m_aAdditiveIterator,false);
+}
+
+OUString OSingleSelectQueryComposer::getTableAlias(const Reference< XPropertySet >& column) const
+{
+ OUString sReturn;
+ if(m_pTables && m_pTables->getCount() > 1)
+ {
+ OUString aCatalog,aSchema,aTable,aColumnName;
+ if(column->getPropertySetInfo()->hasPropertyByName(PROPERTY_CATALOGNAME))
+ column->getPropertyValue(PROPERTY_CATALOGNAME) >>= aCatalog;
+ if(column->getPropertySetInfo()->hasPropertyByName(PROPERTY_SCHEMANAME))
+ column->getPropertyValue(PROPERTY_SCHEMANAME) >>= aSchema;
+ if(column->getPropertySetInfo()->hasPropertyByName(PROPERTY_TABLENAME))
+ column->getPropertyValue(PROPERTY_TABLENAME) >>= aTable;
+ column->getPropertyValue(PROPERTY_NAME) >>= aColumnName;
+
+ Sequence< OUString> aNames(m_pTables->getElementNames());
+ const OUString* pBegin = aNames.getConstArray();
+ const OUString* const pEnd = pBegin + aNames.getLength();
+
+ if(aTable.isEmpty())
+ { // we haven't found a table name, now we must search every table for this column
+ for(;pBegin != pEnd;++pBegin)
+ {
+ Reference<XColumnsSupplier> xColumnsSupp;
+ m_pTables->getByName(*pBegin) >>= xColumnsSupp;
+
+ if(xColumnsSupp.is() && xColumnsSupp->getColumns()->hasByName(aColumnName))
+ {
+ aTable = *pBegin;
+ break;
+ }
+ }
+ }
+ else
+ {
+ OUString aComposedName = ::dbtools::composeTableName( m_xMetaData, aCatalog, aSchema, aTable, false, ::dbtools::EComposeRule::InDataManipulation );
+
+ // Is this the right case for the table name?
+ // Else, look for it with different case, if applicable.
+
+ if(!m_pTables->hasByName(aComposedName))
+ {
+ ::comphelper::UStringMixLess aTmp(m_aAdditiveIterator.getTables().key_comp());
+ ::comphelper::UStringMixEqual aComp(aTmp.isCaseSensitive());
+ for(;pBegin != pEnd;++pBegin)
+ {
+ Reference<XPropertySet> xTableProp;
+ m_pTables->getByName(*pBegin) >>= xTableProp;
+ OSL_ENSURE(xTableProp.is(),"Table isn't a propertyset!");
+ if(xTableProp.is())
+ {
+ OUString aCatalog2,aSchema2,aTable2;
+ xTableProp->getPropertyValue(PROPERTY_CATALOGNAME) >>= aCatalog2;
+ xTableProp->getPropertyValue(PROPERTY_SCHEMANAME) >>= aSchema2;
+ xTableProp->getPropertyValue(PROPERTY_NAME) >>= aTable2;
+ if(aComp(aCatalog,aCatalog2) && aComp(aSchema,aSchema2) && aComp(aTable,aTable2))
+ {
+ aCatalog = aCatalog2;
+ aSchema = aSchema2;
+ aTable = aTable2;
+ break;
+ }
+ }
+ }
+ }
+ }
+ if(pBegin != pEnd)
+ {
+ sReturn = ::dbtools::composeTableName( m_xMetaData, aCatalog, aSchema, aTable, true, ::dbtools::EComposeRule::InDataManipulation ) + ".";
+ }
+ }
+ return sReturn;
+}
+
+Reference< XIndexAccess > SAL_CALL OSingleSelectQueryComposer::getParameters( )
+{
+ // now set the Parameters
+ if ( !m_aCurrentColumns[ParameterColumns] )
+ {
+ ::rtl::Reference< OSQLColumns> aCols = m_aSqlIterator.getParameters();
+ std::vector< OUString> aNames;
+ for (auto const& elem : *aCols)
+ aNames.push_back(getString(elem->getPropertyValue(PROPERTY_NAME)));
+ m_aCurrentColumns[ParameterColumns].reset( new OPrivateColumns(aCols,m_xMetaData->supportsMixedCaseQuotedIdentifiers(),*this,m_aMutex,aNames,true) );
+ }
+
+ return m_aCurrentColumns[ParameterColumns].get();
+}
+
+void OSingleSelectQueryComposer::clearColumns( const EColumnType _eType )
+{
+ OPrivateColumns* pColumns = m_aCurrentColumns[ _eType ].get();
+ if ( pColumns != nullptr )
+ {
+ pColumns->disposing();
+ m_aColumnsCollection.push_back( std::move(m_aCurrentColumns[ _eType ]) );
+ }
+}
+
+void OSingleSelectQueryComposer::clearCurrentCollections()
+{
+ for (auto & currentColumn : m_aCurrentColumns)
+ {
+ if (currentColumn)
+ {
+ currentColumn->disposing();
+ m_aColumnsCollection.push_back(std::move(currentColumn));
+ }
+ }
+
+ if(m_pTables)
+ {
+ m_pTables->disposing();
+ m_aTablesCollection.push_back(std::move(m_pTables));
+ }
+}
+
+Reference< XIndexAccess > OSingleSelectQueryComposer::setCurrentColumns( EColumnType _eType,
+ const ::rtl::Reference< OSQLColumns >& _rCols )
+{
+ ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
+
+ ::osl::MutexGuard aGuard( m_aMutex );
+ // now set the group columns
+ if ( !m_aCurrentColumns[_eType] )
+ {
+ std::vector< OUString> aNames;
+ for (auto const& elem : *_rCols)
+ aNames.push_back(getString(elem->getPropertyValue(PROPERTY_NAME)));
+ m_aCurrentColumns[_eType].reset( new OPrivateColumns(_rCols,m_xMetaData->supportsMixedCaseQuotedIdentifiers(),*this,m_aMutex,aNames,true) );
+ }
+
+ return m_aCurrentColumns[_eType].get();
+}
+
+Reference< XIndexAccess > SAL_CALL OSingleSelectQueryComposer::getGroupColumns( )
+{
+ return setCurrentColumns( GroupByColumns, m_aAdditiveIterator.getGroupColumns() );
+}
+
+Reference< XIndexAccess > SAL_CALL OSingleSelectQueryComposer::getOrderColumns( )
+{
+ return setCurrentColumns( OrderColumns, m_aAdditiveIterator.getOrderColumns() );
+}
+
+OUString SAL_CALL OSingleSelectQueryComposer::getQueryWithSubstitution( )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
+
+ OUString sSqlStatement( getQuery() );
+
+ const OSQLParseNode* pStatementNode = m_aSqlIterator.getParseTree();
+ if ( pStatementNode )
+ {
+ SQLException aError;
+ if ( !pStatementNode->parseNodeToExecutableStatement( sSqlStatement, m_xConnection, m_aSqlParser, &aError ) )
+ throw aError;
+ }
+
+ return sSqlStatement;
+}
+
+OUString OSingleSelectQueryComposer::getStatementPart( TGetParseNode const & _aGetFunctor, OSQLParseTreeIterator& _rIterator )
+{
+ OUString sResult;
+
+ const OSQLParseNode* pNode = _aGetFunctor( &_rIterator );
+ if ( pNode )
+ pNode->parseNodeToStr( sResult, m_xConnection );
+
+ return sResult;
+}
+
+namespace
+{
+ OUString lcl_getDecomposedColumnName(const OUString& rComposedName, const OUString& rQuoteString)
+ {
+ const sal_Int32 nQuoteLength = rQuoteString.getLength();
+ OUString sName = rComposedName.trim();
+ OUString sColumnName;
+ sal_Int32 nPos, nRPos = 0;
+
+ for (;;)
+ {
+ nPos = sName.indexOf( rQuoteString, nRPos );
+ if ( nPos >= 0 )
+ {
+ nRPos = sName.indexOf( rQuoteString, nPos + nQuoteLength );
+ if ( nRPos > nPos )
+ {
+ if ( nRPos + nQuoteLength < sName.getLength() )
+ {
+ nRPos += nQuoteLength; // -1 + 1 skip dot
+ }
+ else
+ {
+ sColumnName = sName.copy( nPos + nQuoteLength, nRPos - nPos - nQuoteLength );
+ break;
+ }
+ }
+ else
+ break;
+ }
+ else
+ break;
+ }
+ return sColumnName.isEmpty() ? rComposedName : sColumnName;
+ }
+
+ OUString lcl_getCondition(const Sequence< Sequence< PropertyValue > >& filter,
+ const OPredicateInputController& i_aPredicateInputController,
+ const Reference< XNameAccess >& i_xSelectColumns,
+ const OUString& rQuoteString)
+ {
+ OUStringBuffer sRet;
+ const Sequence< PropertyValue >* pOrIter = filter.getConstArray();
+ const Sequence< PropertyValue >* pOrEnd = pOrIter + filter.getLength();
+ while ( pOrIter != pOrEnd )
+ {
+ if ( pOrIter->hasElements() )
+ {
+ sRet.append(L_BRACKET);
+ const PropertyValue* pAndIter = pOrIter->getConstArray();
+ const PropertyValue* pAndEnd = pAndIter + pOrIter->getLength();
+ while ( pAndIter != pAndEnd )
+ {
+ sRet.append(pAndIter->Name);
+ OUString sValue;
+ pAndIter->Value >>= sValue;
+ const OUString sColumnName = lcl_getDecomposedColumnName( pAndIter->Name, rQuoteString );
+ if ( i_xSelectColumns.is() && i_xSelectColumns->hasByName(sColumnName) )
+ {
+ Reference<XPropertySet> xColumn(i_xSelectColumns->getByName(sColumnName),UNO_QUERY);
+ sValue = i_aPredicateInputController.getPredicateValueStr(sValue,xColumn);
+ }
+ else
+ {
+ sValue = i_aPredicateInputController.getPredicateValueStr(pAndIter->Name,sValue);
+ }
+ lcl_addFilterCriteria_throw(pAndIter->Handle,sValue,sRet);
+ ++pAndIter;
+ if ( pAndIter != pAndEnd )
+ sRet.append(STR_AND);
+ }
+ sRet.append(R_BRACKET);
+ }
+ ++pOrIter;
+ if ( pOrIter != pOrEnd && !sRet.isEmpty() )
+ sRet.append(STR_OR);
+ }
+ return sRet.makeStringAndClear();
+ }
+}
+
+void SAL_CALL OSingleSelectQueryComposer::setStructuredFilter( const Sequence< Sequence< PropertyValue > >& filter )
+{
+ OPredicateInputController aPredicateInput(m_aContext, m_xConnection, &m_aParseContext);
+ setFilter(lcl_getCondition(filter, aPredicateInput, getColumns(), m_xMetaData->getIdentifierQuoteString()));
+}
+
+void SAL_CALL OSingleSelectQueryComposer::setStructuredHavingClause( const Sequence< Sequence< PropertyValue > >& filter )
+{
+ OPredicateInputController aPredicateInput(m_aContext, m_xConnection);
+ setHavingClause(lcl_getCondition(filter, aPredicateInput, getColumns(), m_xMetaData->getIdentifierQuoteString()));
+}
+
+void OSingleSelectQueryComposer::setConditionByColumn( const Reference< XPropertySet >& column, bool andCriteria, std::function<bool(OSingleSelectQueryComposer *, const OUString&)> const & _aSetFunctor, sal_Int32 filterOperator)
+{
+ try
+ {
+ ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
+
+ if ( !column.is()
+ || !column->getPropertySetInfo()->hasPropertyByName(PROPERTY_VALUE)
+ || !column->getPropertySetInfo()->hasPropertyByName(PROPERTY_NAME)
+ || !column->getPropertySetInfo()->hasPropertyByName(PROPERTY_TYPE))
+ throw SQLException(DBA_RES(RID_STR_COLUMN_NOT_VALID),*this,SQLSTATE_GENERAL,1000,Any() );
+
+ sal_Int32 nType = 0;
+ column->getPropertyValue(PROPERTY_TYPE) >>= nType;
+ sal_Int32 nSearchable = dbtools::getSearchColumnFlag(m_xConnection,nType);
+ if(nSearchable == ColumnSearch::NONE)
+ throw SQLException(DBA_RES(RID_STR_COLUMN_NOT_SEARCHABLE),*this,SQLSTATE_GENERAL,1000,Any() );
+
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ OUString aName;
+ column->getPropertyValue(PROPERTY_NAME) >>= aName;
+
+ const Any aValue = column->getPropertyValue(PROPERTY_VALUE);
+
+ OUStringBuffer aSQL;
+ const OUString aQuote = m_xMetaData->getIdentifierQuoteString();
+ getColumns();
+
+ // TODO: if this is called for HAVING, check that the column is a GROUP BY column
+ // or that it is an aggregate function
+
+ if ( m_aCurrentColumns[SelectColumns] && m_aCurrentColumns[SelectColumns]->hasByName(aName) )
+ {
+ Reference<XPropertySet> xColumn;
+ m_aCurrentColumns[SelectColumns]->getByName(aName) >>= xColumn;
+ OSL_ENSURE(xColumn->getPropertySetInfo()->hasPropertyByName(PROPERTY_REALNAME),"Property REALNAME not available!");
+ OSL_ENSURE(xColumn->getPropertySetInfo()->hasPropertyByName(PROPERTY_TABLENAME),"Property TABLENAME not available!");
+ OSL_ENSURE(xColumn->getPropertySetInfo()->hasPropertyByName("AggregateFunction"),"Property AggregateFunction not available!");
+
+ OUString sRealName,sTableName;
+ xColumn->getPropertyValue(PROPERTY_REALNAME) >>= sRealName;
+ xColumn->getPropertyValue(PROPERTY_TABLENAME) >>= sTableName;
+ if(sTableName.indexOf('.') != -1)
+ {
+ OUString aCatlog,aSchema,aTable;
+ ::dbtools::qualifiedNameComponents(m_xMetaData,sTableName,aCatlog,aSchema,aTable,::dbtools::EComposeRule::InDataManipulation);
+ sTableName = ::dbtools::composeTableName( m_xMetaData, aCatlog, aSchema, aTable, true, ::dbtools::EComposeRule::InDataManipulation );
+ }
+ else
+ sTableName = ::dbtools::quoteName(aQuote,sTableName);
+
+ if ( !::comphelper::getBOOL(xColumn->getPropertyValue("Function")) )
+ {
+ aSQL = sTableName + "." + ::dbtools::quoteName( aQuote, sRealName );
+ }
+ else
+ aSQL = sRealName;
+ }
+ else
+ {
+ aSQL = getTableAlias( column ) + ::dbtools::quoteName( aQuote, aName );
+ }
+
+ if ( aValue.hasValue() )
+ {
+ if( !m_xTypeConverter.is() )
+ m_xTypeConverter.set( Converter::create(m_aContext) );
+ OSL_ENSURE(m_xTypeConverter.is(),"NO typeconverter!");
+
+ if ( nType != DataType::BOOLEAN && DataType::BIT != nType )
+ {
+ lcl_addFilterCriteria_throw(filterOperator,u"",aSQL);
+ }
+
+ switch(nType)
+ {
+ case DataType::VARCHAR:
+ case DataType::CHAR:
+ case DataType::LONGVARCHAR:
+ aSQL.append( DBTypeConversion::toSQLString( nType, aValue, m_xTypeConverter ) );
+ break;
+ case DataType::CLOB:
+ {
+ Reference< XClob > xClob(aValue,UNO_QUERY);
+ if ( xClob.is() )
+ {
+ const ::sal_Int64 nLength = xClob->length();
+ if ( sal_Int64(nLength + aSQL.getLength() + STR_LIKE.getLength() ) < sal_Int64(SAL_MAX_INT32) )
+ {
+ aSQL.append("'" + xClob->getSubString(1,static_cast<sal_Int32>(nLength)) + "'");
+ }
+ }
+ else
+ {
+ aSQL.append( DBTypeConversion::toSQLString( nType, aValue, m_xTypeConverter ) );
+ }
+ }
+ break;
+ case DataType::VARBINARY:
+ case DataType::BINARY:
+ case DataType::LONGVARBINARY:
+ {
+ Sequence<sal_Int8> aSeq;
+ if(!(aValue >>= aSeq))
+ throw SQLException(DBA_RES(RID_STR_NOT_SEQUENCE_INT8),*this,SQLSTATE_GENERAL,1000,Any() );
+ if(nSearchable == ColumnSearch::CHAR)
+ {
+ aSQL.append( "\'" );
+ }
+ aSQL.append( "0x" );
+ const sal_Int8* pBegin = aSeq.getConstArray();
+ const sal_Int8* pEnd = pBegin + aSeq.getLength();
+ for(;pBegin != pEnd;++pBegin)
+ {
+ aSQL.append( static_cast<sal_Int32>(*pBegin), 16 );
+ }
+ if(nSearchable == ColumnSearch::CHAR)
+ aSQL.append( "\'" );
+ }
+ break;
+ case DataType::BIT:
+ case DataType::BOOLEAN:
+ {
+ bool bValue = false;
+ m_xTypeConverter->convertToSimpleType(aValue, TypeClass_BOOLEAN) >>= bValue;
+
+ OUString sColumnExp = aSQL.makeStringAndClear();
+ getBooleanComparisonPredicate( sColumnExp, bValue, m_nBoolCompareMode, aSQL );
+ }
+ break;
+ default:
+ aSQL.append( DBTypeConversion::toSQLString( nType, aValue, m_xTypeConverter ) );
+ break;
+ }
+ }
+ else
+ {
+ sal_Int32 nFilterOp = filterOperator;
+ if ( filterOperator != SQLFilterOperator::SQLNULL && filterOperator != SQLFilterOperator::NOT_SQLNULL )
+ nFilterOp = SQLFilterOperator::SQLNULL;
+ lcl_addFilterCriteria_throw(nFilterOp,u"",aSQL);
+ }
+
+ // Attach filter
+ // Construct SELECT without WHERE and ORDER BY
+ OUString sFilter = getFilter();
+
+ if ( !sFilter.isEmpty() && !aSQL.isEmpty() )
+ {
+ sFilter = L_BRACKET + sFilter + R_BRACKET +
+ (andCriteria ? std::u16string_view(STR_AND) : std::u16string_view(STR_OR));
+ }
+ sFilter += aSQL;
+
+ // add the filter and the sort order
+ _aSetFunctor(this,sFilter);
+ }
+ catch (css::lang::WrappedTargetException & e)
+ {
+ if (e.TargetException.isExtractableTo(
+ cppu::UnoType<css::sdbc::SQLException>::get()))
+ {
+ cppu::throwException(e.TargetException);
+ }
+ else
+ {
+ throw;
+ }
+ }
+}
+
+Sequence< Sequence< PropertyValue > > OSingleSelectQueryComposer::getStructuredCondition( TGetParseNode const & _aGetFunctor )
+{
+ ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
+
+ MutexGuard aGuard(m_aMutex);
+
+ Sequence< Sequence< PropertyValue > > aFilterSeq;
+ OUString sFilter = getStatementPart( _aGetFunctor, m_aAdditiveIterator );
+
+
+ if ( !sFilter.isEmpty() )
+ {
+ OUString aSql(m_aPureSelectSQL + STR_WHERE + sFilter);
+ // build a temporary parse node
+ const OSQLParseNode* pTempNode = m_aAdditiveIterator.getParseTree();
+
+ OUString aErrorMsg;
+ std::unique_ptr<OSQLParseNode> pSqlParseNode( m_aSqlParser.parseTree(aErrorMsg,aSql));
+ if (pSqlParseNode)
+ {
+ m_aAdditiveIterator.setParseTree(pSqlParseNode.get());
+ // normalize the filter
+ OSQLParseNode* pWhereNode = const_cast<OSQLParseNode*>(m_aAdditiveIterator.getWhereTree());
+
+ OSQLParseNode* pCondition = pWhereNode->getChild(1);
+ #if OSL_DEBUG_LEVEL > 0
+ OUString sCondition;
+ pCondition->parseNodeToStr( sCondition, m_xConnection );
+ #endif
+ OSQLParseNode::negateSearchCondition(pCondition);
+
+ pCondition = pWhereNode->getChild(1);
+ #if OSL_DEBUG_LEVEL > 0
+ sCondition.clear();
+ pCondition->parseNodeToStr( sCondition, m_xConnection );
+ #endif
+ OSQLParseNode::disjunctiveNormalForm(pCondition);
+
+ pCondition = pWhereNode->getChild(1);
+ #if OSL_DEBUG_LEVEL > 0
+ sCondition.clear();
+ pCondition->parseNodeToStr( sCondition, m_xConnection );
+ #endif
+ OSQLParseNode::absorptions(pCondition);
+
+ pCondition = pWhereNode->getChild(1);
+ #if OSL_DEBUG_LEVEL > 0
+ sCondition.clear();
+ pCondition->parseNodeToStr( sCondition, m_xConnection );
+ #endif
+ if ( pCondition )
+ {
+ std::vector< std::vector < PropertyValue > > aFilters;
+ Reference< XNumberFormatter > xFormatter( NumberFormatter::create(m_aContext), UNO_QUERY_THROW );
+ xFormatter->attachNumberFormatsSupplier( m_xNumberFormatsSupplier );
+
+ if (setORCriteria(pCondition, m_aAdditiveIterator, aFilters, xFormatter))
+ {
+ aFilterSeq.realloc(aFilters.size());
+ Sequence<PropertyValue>* pFilters = aFilterSeq.getArray();
+ for (auto const& filter : aFilters)
+ {
+ pFilters->realloc(filter.size());
+ PropertyValue* pFilter = pFilters->getArray();
+ for (auto const& elem : filter)
+ {
+ *pFilter = elem;
+ ++pFilter;
+ }
+ ++pFilters;
+ }
+ }
+ }
+ // restore
+ m_aAdditiveIterator.setParseTree(pTempNode);
+ }
+ }
+ return aFilterSeq;
+}
+
+OUString OSingleSelectQueryComposer::getKeyword( SQLPart _ePart )
+{
+ OUString sKeyword;
+ switch(_ePart)
+ {
+ default:
+ SAL_WARN("dbaccess", "OSingleSelectQueryComposer::getKeyWord: Invalid enum value!" );
+ [[fallthrough]]; // fallback to WHERE
+ case Where:
+ sKeyword = STR_WHERE;
+ break;
+ case Group:
+ sKeyword = STR_GROUP_BY;
+ break;
+ case Having:
+ sKeyword = STR_HAVING;
+ break;
+ case Order:
+ sKeyword = STR_ORDER_BY;
+ break;
+ }
+ return sKeyword;
+}
+
+OUString OSingleSelectQueryComposer::getSQLPart( SQLPart _ePart, OSQLParseTreeIterator& _rIterator, bool _bWithKeyword )
+{
+ TGetParseNode F_tmp(&OSQLParseTreeIterator::getSimpleWhereTree);
+ OUString sKeyword( getKeyword( _ePart ) );
+ switch(_ePart)
+ {
+ case Where:
+ F_tmp = TGetParseNode(&OSQLParseTreeIterator::getSimpleWhereTree);
+ break;
+ case Group:
+ F_tmp = TGetParseNode (&OSQLParseTreeIterator::getSimpleGroupByTree);
+ break;
+ case Having:
+ F_tmp = TGetParseNode(&OSQLParseTreeIterator::getSimpleHavingTree);
+ break;
+ case Order:
+ F_tmp = TGetParseNode(&OSQLParseTreeIterator::getSimpleOrderTree);
+ break;
+ default:
+ SAL_WARN("dbaccess","Invalid enum value!");
+ }
+
+ OUString sRet = getStatementPart( F_tmp, _rIterator );
+ if ( _bWithKeyword && !sRet.isEmpty() )
+ sRet = sKeyword + sRet;
+ return sRet;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/api/StaticSet.cxx b/dbaccess/source/core/api/StaticSet.cxx
new file mode 100644
index 000000000..97226b466
--- /dev/null
+++ b/dbaccess/source/core/api/StaticSet.cxx
@@ -0,0 +1,280 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#include "StaticSet.hxx"
+#include <com/sun/star/sdbcx/CompareBookmark.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <connectivity/CommonTools.hxx>
+#include <comphelper/types.hxx>
+#include <o3tl/safeint.hxx>
+#include <osl/diagnose.h>
+
+using namespace dbaccess;
+using namespace connectivity;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::sdbcx;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::lang;
+using namespace ::osl;
+
+void OStaticSet::fillValueRow(ORowSetRow& _rRow,sal_Int32 /*_nPosition*/)
+{
+ _rRow = *m_aSetIter;
+}
+
+// css::sdbcx::XRowLocate
+Any OStaticSet::getBookmark()
+{
+ return Any(getRow());
+}
+
+bool OStaticSet::moveToBookmark( const Any& bookmark )
+{
+ m_bInserted = m_bUpdated = m_bDeleted = false;
+ return absolute(::comphelper::getINT32(bookmark));
+}
+
+sal_Int32 OStaticSet::compareBookmarks( const Any& _first, const Any& _second )
+{
+ sal_Int32 nFirst = 0, nSecond = 0;
+ _first >>= nFirst;
+ _second >>= nSecond;
+ return (nFirst < nSecond) ? CompareBookmark::LESS : ((nFirst > nSecond) ? CompareBookmark::GREATER : CompareBookmark::EQUAL);
+}
+
+bool OStaticSet::hasOrderedBookmarks( )
+{
+ return true;
+}
+
+sal_Int32 OStaticSet::hashBookmark( const Any& bookmark )
+{
+ return ::comphelper::getINT32(bookmark);
+}
+
+bool OStaticSet::fetchRow()
+{
+ bool bRet = false;
+ if ( !m_bEnd && (!m_nMaxRows || sal_Int32(m_aSet.size()) < m_nMaxRows) )
+ bRet = m_xDriverSet->next();
+ if ( bRet )
+ {
+ m_aSet.push_back(new connectivity::ORowVector< connectivity::ORowSetValue >(m_xSetMetaData->getColumnCount()));
+ m_aSetIter = m_aSet.end() - 1;
+ (**m_aSetIter)[0] = getRow();
+ OCacheSet::fillValueRow(*m_aSetIter,(**m_aSetIter)[0].getInt32());
+ }
+ else
+ m_bEnd = true;
+ return bRet;
+}
+
+void OStaticSet::fillAllRows()
+{
+ if(m_bEnd)
+ return;
+
+ sal_Int32 nColumnCount = m_xSetMetaData->getColumnCount();
+ while(m_xDriverSet->next())
+ {
+ ORowSetRow pRow = new connectivity::ORowVector< connectivity::ORowSetValue >(nColumnCount);
+ m_aSet.push_back(pRow);
+ m_aSetIter = m_aSet.end() - 1;
+ (*pRow)[0] = getRow();
+ OCacheSet::fillValueRow(pRow,(*pRow)[0].getInt32());
+ }
+ m_bEnd = true;
+}
+
+// XResultSet
+bool OStaticSet::next()
+{
+ m_bInserted = m_bUpdated = m_bDeleted = false;
+
+ if(isAfterLast())
+ return false;
+ if(!m_bEnd) // not yet all records fetched
+ {
+ ++m_aSetIter;
+ if(m_aSetIter == m_aSet.end() && !fetchRow())
+ m_aSetIter = m_aSet.end();
+ }
+ else if(!isAfterLast())
+ ++m_aSetIter;
+ return !isAfterLast();
+}
+
+bool OStaticSet::isBeforeFirst( )
+{
+ return m_aSetIter == m_aSet.begin();
+}
+
+bool OStaticSet::isAfterLast( )
+{
+ return m_aSetIter == m_aSet.end() && m_bEnd;
+}
+
+void OStaticSet::beforeFirst( )
+{
+ m_bInserted = m_bUpdated = m_bDeleted = false;
+ m_aSetIter = m_aSet.begin();
+}
+
+void OStaticSet::afterLast( )
+{
+ m_bInserted = m_bUpdated = m_bDeleted = false;
+ fillAllRows();
+ m_aSetIter = m_aSet.end();
+}
+
+bool OStaticSet::first()
+{
+ m_bInserted = m_bUpdated = m_bDeleted = false;
+ m_aSetIter = m_aSet.begin()+1;
+ if(m_aSetIter == m_aSet.end() && !fetchRow())
+ m_aSetIter = m_aSet.end();
+
+ return m_aSetIter != m_aSet.end();
+}
+
+bool OStaticSet::last()
+{
+ m_bInserted = m_bUpdated = m_bDeleted = false;
+ fillAllRows();
+ m_aSetIter = m_aSet.end()-1;
+
+ return !isBeforeFirst() && !isAfterLast();
+}
+
+sal_Int32 OStaticSet::getRow( )
+{
+ OSL_ENSURE(!isAfterLast(),"getRow is not allowed when afterlast record!");
+ OSL_ENSURE(!isBeforeFirst(),"getRow is not allowed when beforefirst record!");
+
+ sal_Int32 nPos = m_aSet.size() - (m_aSet.end() - m_aSetIter);
+ OSL_ENSURE(nPos > 0,"RowPos is < 0");
+ return nPos;
+}
+
+bool OStaticSet::absolute( sal_Int32 row )
+{
+ m_bInserted = m_bUpdated = m_bDeleted = false;
+ OSL_ENSURE(row,"OStaticSet::absolute: INVALID row number!");
+ // if row greater 0 than count from end - row means last
+ if(row < 0)
+ {
+ if(!m_bEnd)
+ fillAllRows();
+
+ sal_Int32 nRow = getRow();
+ nRow += row;
+ if(nRow <= static_cast<sal_Int32>(m_aSet.size()))
+ m_aSetIter = m_aSet.begin() + nRow;
+ else
+ m_aSetIter = m_aSet.begin();
+ }
+ else if(row > 0)
+ {
+ if(o3tl::make_unsigned(row) >= m_aSet.size())
+ {
+ if(!m_bEnd)
+ {
+ bool bNext = true;
+ for(sal_Int32 i=m_aSet.size()-1;i < row && bNext;++i)
+ bNext = fetchRow();
+ }
+
+ if(o3tl::make_unsigned(row) > m_aSet.size())
+ m_aSetIter = m_aSet.end(); // check again
+ else
+ m_aSetIter = m_aSet.begin() + row;
+ }
+ else
+ m_aSetIter = m_aSet.begin() + row;
+ }
+
+ return m_aSetIter != m_aSet.end() && m_aSetIter != m_aSet.begin();
+}
+
+bool OStaticSet::previous( )
+{
+ m_bInserted = m_bUpdated = m_bDeleted = false;
+
+ if(m_aSetIter != m_aSet.begin())
+ --m_aSetIter;
+
+ return m_aSetIter != m_aSet.begin();
+}
+
+void OStaticSet::refreshRow( )
+{
+}
+
+bool OStaticSet::rowUpdated( )
+{
+ return m_bUpdated;
+}
+
+bool OStaticSet::rowInserted( )
+{
+ return m_bInserted;
+}
+
+bool OStaticSet::rowDeleted( )
+{
+ return m_bDeleted;
+}
+
+void OStaticSet::insertRow( const ORowSetRow& _rInsertRow,const connectivity::OSQLTable& _xTable )
+{
+ OCacheSet::insertRow( _rInsertRow,_xTable);
+ if(m_bInserted)
+ {
+ m_aSet.push_back(new ORowVector< ORowSetValue >(*_rInsertRow)); // we don't know where the new row is so we append it to the current rows
+ m_aSetIter = m_aSet.end() - 1;
+ (**m_aSetIter)[0] = (*_rInsertRow)[0] = getBookmark();
+ m_bEnd = false;
+ }
+}
+
+void OStaticSet::deleteRow(const ORowSetRow& _rDeleteRow ,const connectivity::OSQLTable& _xTable )
+{
+ OCacheSet::deleteRow(_rDeleteRow,_xTable);
+ if(m_bDeleted)
+ {
+ ORowSetMatrix::iterator aPos = m_aSet.begin()+(*_rDeleteRow)[0].getInt32();
+ if(aPos == (m_aSet.end()-1))
+ m_aSetIter = m_aSet.end();
+ m_aSet.erase(aPos);
+ }
+}
+
+void OStaticSet::reset(const Reference< XResultSet> &_xDriverSet)
+{
+ OCacheSet::construct(_xDriverSet, m_sRowSetFilter);
+ ORowSetMatrix().swap(m_aSet);
+ m_aSetIter = m_aSet.end();
+ m_bEnd = false;
+ m_aSet.emplace_back(nullptr); // this is the beforefirst record
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/api/StaticSet.hxx b/dbaccess/source/core/api/StaticSet.hxx
new file mode 100644
index 000000000..9f765996b
--- /dev/null
+++ b/dbaccess/source/core/api/StaticSet.hxx
@@ -0,0 +1,75 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include "CacheSet.hxx"
+
+namespace dbaccess
+{
+ // is used when nothing is supported by the driver
+ // we use a snapshot
+ class OStaticSet : public OCacheSet
+ {
+ ORowSetMatrix m_aSet;
+ ORowSetMatrix::iterator m_aSetIter;
+ bool m_bEnd;
+ bool fetchRow();
+ void fillAllRows();
+ public:
+ explicit OStaticSet(sal_Int32 i_nMaxRows) : OCacheSet(i_nMaxRows)
+ , m_aSetIter(m_aSet.end())
+ , m_bEnd(false)
+ {
+ m_aSet.push_back(nullptr); // this is the beforefirst record
+ }
+
+ virtual void reset(const css::uno::Reference< css::sdbc::XResultSet>& _xDriverSet) override;
+
+ virtual void fillValueRow(ORowSetRow& _rRow,sal_Int32 _nPosition) override;
+ // css::sdbcx::XRowLocate
+ virtual css::uno::Any getBookmark() override;
+ virtual bool moveToBookmark( const css::uno::Any& bookmark ) override;
+ virtual sal_Int32 compareBookmarks( const css::uno::Any& first, const css::uno::Any& second ) override;
+ virtual bool hasOrderedBookmarks( ) override;
+ virtual sal_Int32 hashBookmark( const css::uno::Any& bookmark ) override;
+
+ bool isBeforeFirst( );
+ bool isAfterLast( );
+
+ // css::sdbc::XResultSet
+ virtual bool next() override;
+ virtual void beforeFirst( ) override;
+ virtual void afterLast( ) override;
+ virtual bool first() override;
+ virtual bool last() override;
+ virtual sal_Int32 getRow( ) override;
+ virtual bool absolute( sal_Int32 row ) override;
+ virtual bool previous( ) override;
+ virtual void refreshRow( ) override;
+ virtual bool rowUpdated( ) override;
+ virtual bool rowInserted( ) override;
+ virtual bool rowDeleted( ) override;
+ // css::sdbc::XResultSetUpdate
+ virtual void insertRow( const ORowSetRow& _rInsertRow,const connectivity::OSQLTable& _xTable ) override;
+ virtual void deleteRow(const ORowSetRow& _rInsertRow,const connectivity::OSQLTable& _xTable ) override;
+ };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/api/TableDeco.cxx b/dbaccess/source/core/api/TableDeco.cxx
new file mode 100644
index 000000000..92821750f
--- /dev/null
+++ b/dbaccess/source/core/api/TableDeco.cxx
@@ -0,0 +1,634 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <TableDeco.hxx>
+#include <definitioncolumn.hxx>
+#include <stringconstants.hxx>
+#include <strings.hxx>
+#include <core_resource.hxx>
+#include <strings.hrc>
+#include <osl/diagnose.h>
+#include <sal/log.hxx>
+
+#include <comphelper/property.hxx>
+#include <comphelper/servicehelper.hxx>
+#include <com/sun/star/sdbc/SQLException.hpp>
+#include <com/sun/star/sdbc/XConnection.hpp>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <connectivity/dbtools.hxx>
+#include <connectivity/dbexception.hxx>
+#include <ContainerMediator.hxx>
+
+using namespace dbaccess;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::util;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::sdbcx;
+using namespace ::com::sun::star::container;
+using namespace ::osl;
+using namespace ::comphelper;
+using namespace ::dbtools;
+using namespace ::cppu;
+
+// ODBTableDecorator
+
+ODBTableDecorator::ODBTableDecorator( const Reference< XConnection >& _rxConnection, const Reference< XColumnsSupplier >& _rxNewTable,
+ const Reference< XNumberFormatsSupplier >& _rxNumberFormats, const Reference< XNameAccess >& _xColumnDefinitions )
+ :OTableDescriptor_BASE(m_aMutex)
+ ,ODataSettings(OTableDescriptor_BASE::rBHelper)
+ ,m_xTable(_rxNewTable)
+ ,m_xColumnDefinitions(_xColumnDefinitions)
+ ,m_xConnection( _rxConnection )
+ ,m_xMetaData( _rxConnection.is() ? _rxConnection->getMetaData() : Reference< XDatabaseMetaData >() )
+ ,m_xNumberFormats( _rxNumberFormats )
+ ,m_nPrivileges(-1)
+{
+ ODataSettings::registerPropertiesFor(this);
+}
+
+ODBTableDecorator::~ODBTableDecorator()
+{
+}
+
+Sequence< sal_Int8 > ODBTableDecorator::getImplementationId()
+{
+ return css::uno::Sequence<sal_Int8>();
+}
+
+// OComponentHelper
+void SAL_CALL ODBTableDecorator::disposing()
+{
+ OPropertySetHelper::disposing();
+ OTableDescriptor_BASE::disposing();
+
+ MutexGuard aGuard(m_aMutex);
+ m_xTable = nullptr;
+ m_xMetaData = nullptr;
+ m_xColumnDefinitions = nullptr;
+ m_xNumberFormats = nullptr;
+ if ( m_pColumns )
+ m_pColumns->disposing();
+ m_xColumnMediator = nullptr;
+}
+
+sal_Bool SAL_CALL ODBTableDecorator::convertFastPropertyValue(
+ Any & rConvertedValue,
+ Any & rOldValue,
+ sal_Int32 nHandle,
+ const Any& rValue )
+{
+ bool bRet = true;
+ switch(nHandle)
+ {
+ case PROPERTY_ID_PRIVILEGES:
+ case PROPERTY_ID_FILTER:
+ case PROPERTY_ID_ORDER:
+ case PROPERTY_ID_APPLYFILTER:
+ case PROPERTY_ID_FONT:
+ case PROPERTY_ID_ROW_HEIGHT:
+ case PROPERTY_ID_AUTOGROW:
+ case PROPERTY_ID_TEXTCOLOR:
+ case PROPERTY_ID_TEXTLINECOLOR:
+ case PROPERTY_ID_TEXTEMPHASIS:
+ case PROPERTY_ID_TEXTRELIEF:
+ case PROPERTY_ID_FONTCHARWIDTH:
+ case PROPERTY_ID_FONTCHARSET:
+ case PROPERTY_ID_FONTFAMILY:
+ case PROPERTY_ID_FONTHEIGHT:
+ case PROPERTY_ID_FONTKERNING:
+ case PROPERTY_ID_FONTNAME:
+ case PROPERTY_ID_FONTORIENTATION:
+ case PROPERTY_ID_FONTPITCH:
+ case PROPERTY_ID_FONTSLANT:
+ case PROPERTY_ID_FONTSTRIKEOUT:
+ case PROPERTY_ID_FONTSTYLENAME:
+ case PROPERTY_ID_FONTUNDERLINE:
+ case PROPERTY_ID_FONTWEIGHT:
+ case PROPERTY_ID_FONTWIDTH:
+ case PROPERTY_ID_FONTWORDLINEMODE:
+ case PROPERTY_ID_FONTTYPE:
+ bRet = ODataSettings::convertFastPropertyValue(rConvertedValue, rOldValue,nHandle,rValue);
+ break;
+
+ default:
+ {
+ Any aValue;
+ getFastPropertyValue(aValue,nHandle);
+ bRet = ::comphelper::tryPropertyValue(rConvertedValue,rOldValue,rValue,aValue,::cppu::UnoType<OUString>::get());
+ }
+ break; // we assume that it works
+ }
+ return bRet;
+}
+
+void ODBTableDecorator::setFastPropertyValue_NoBroadcast(sal_Int32 _nHandle, const Any& _rValue)
+{
+ switch(_nHandle)
+ {
+ case PROPERTY_ID_PRIVILEGES:
+ SAL_WARN("dbaccess", "Property is readonly!");
+ [[fallthrough]];
+ case PROPERTY_ID_FILTER:
+ case PROPERTY_ID_ORDER:
+ case PROPERTY_ID_APPLYFILTER:
+ case PROPERTY_ID_FONT:
+ case PROPERTY_ID_ROW_HEIGHT:
+ case PROPERTY_ID_AUTOGROW:
+ case PROPERTY_ID_TEXTCOLOR:
+ case PROPERTY_ID_TEXTLINECOLOR:
+ case PROPERTY_ID_TEXTEMPHASIS:
+ case PROPERTY_ID_TEXTRELIEF:
+ case PROPERTY_ID_FONTCHARWIDTH:
+ case PROPERTY_ID_FONTCHARSET:
+ case PROPERTY_ID_FONTFAMILY:
+ case PROPERTY_ID_FONTHEIGHT:
+ case PROPERTY_ID_FONTKERNING:
+ case PROPERTY_ID_FONTNAME:
+ case PROPERTY_ID_FONTORIENTATION:
+ case PROPERTY_ID_FONTPITCH:
+ case PROPERTY_ID_FONTSLANT:
+ case PROPERTY_ID_FONTSTRIKEOUT:
+ case PROPERTY_ID_FONTSTYLENAME:
+ case PROPERTY_ID_FONTUNDERLINE:
+ case PROPERTY_ID_FONTWEIGHT:
+ case PROPERTY_ID_FONTWIDTH:
+ case PROPERTY_ID_FONTWORDLINEMODE:
+ case PROPERTY_ID_FONTTYPE:
+
+ ODataSettings::setFastPropertyValue_NoBroadcast(_nHandle, _rValue);
+ break;
+ case PROPERTY_ID_CATALOGNAME:
+ {
+ Reference<XPropertySet> xProp(m_xTable,UNO_QUERY);
+ xProp->setPropertyValue(PROPERTY_CATALOGNAME,_rValue);
+ }
+ break;
+ case PROPERTY_ID_SCHEMANAME:
+ {
+ Reference<XPropertySet> xProp(m_xTable,UNO_QUERY);
+ xProp->setPropertyValue(PROPERTY_SCHEMANAME,_rValue);
+ }
+ break;
+ case PROPERTY_ID_NAME:
+ {
+ Reference<XPropertySet> xProp(m_xTable,UNO_QUERY);
+ xProp->setPropertyValue(PROPERTY_NAME,_rValue);
+ }
+ break;
+ case PROPERTY_ID_DESCRIPTION:
+ {
+ Reference<XPropertySet> xProp(m_xTable,UNO_QUERY);
+ xProp->setPropertyValue(PROPERTY_DESCRIPTION,_rValue);
+ }
+ break;
+ case PROPERTY_ID_TYPE:
+ {
+ Reference<XPropertySet> xProp(m_xTable,UNO_QUERY);
+ xProp->setPropertyValue(PROPERTY_TYPE,_rValue);
+ }
+ break;
+ }
+}
+
+void ODBTableDecorator::getFastPropertyValue(Any& _rValue, sal_Int32 _nHandle) const
+{
+
+ switch(_nHandle)
+ {
+ case PROPERTY_ID_PRIVILEGES:
+ {
+ if ( -1 == m_nPrivileges )
+ fillPrivileges();
+ Reference<XPropertySet> xProp(m_xTable,UNO_QUERY);
+ Reference<XPropertySetInfo> xInfo = xProp->getPropertySetInfo();
+ if ( xInfo->hasPropertyByName(PROPERTY_PRIVILEGES) )
+ {
+ _rValue <<= m_nPrivileges;
+ break;
+ }
+ }
+ [[fallthrough]];
+
+ case PROPERTY_ID_FILTER:
+ case PROPERTY_ID_ORDER:
+ case PROPERTY_ID_APPLYFILTER:
+ case PROPERTY_ID_FONT:
+ case PROPERTY_ID_ROW_HEIGHT:
+ case PROPERTY_ID_AUTOGROW:
+ case PROPERTY_ID_TEXTCOLOR:
+ case PROPERTY_ID_TEXTLINECOLOR:
+ case PROPERTY_ID_TEXTEMPHASIS:
+ case PROPERTY_ID_TEXTRELIEF:
+ case PROPERTY_ID_FONTCHARWIDTH:
+ case PROPERTY_ID_FONTCHARSET:
+ case PROPERTY_ID_FONTFAMILY:
+ case PROPERTY_ID_FONTHEIGHT:
+ case PROPERTY_ID_FONTKERNING:
+ case PROPERTY_ID_FONTNAME:
+ case PROPERTY_ID_FONTORIENTATION:
+ case PROPERTY_ID_FONTPITCH:
+ case PROPERTY_ID_FONTSLANT:
+ case PROPERTY_ID_FONTSTRIKEOUT:
+ case PROPERTY_ID_FONTSTYLENAME:
+ case PROPERTY_ID_FONTUNDERLINE:
+ case PROPERTY_ID_FONTWEIGHT:
+ case PROPERTY_ID_FONTWIDTH:
+ case PROPERTY_ID_FONTWORDLINEMODE:
+ case PROPERTY_ID_FONTTYPE:
+ ODataSettings::getFastPropertyValue(_rValue, _nHandle);
+ break;
+ case PROPERTY_ID_CATALOGNAME:
+ {
+ Reference<XPropertySet> xProp(m_xTable,UNO_QUERY);
+ _rValue = xProp->getPropertyValue(PROPERTY_CATALOGNAME);
+ }
+ break;
+ case PROPERTY_ID_SCHEMANAME:
+ {
+ Reference<XPropertySet> xProp(m_xTable,UNO_QUERY);
+ _rValue = xProp->getPropertyValue(PROPERTY_SCHEMANAME);
+ }
+ break;
+ case PROPERTY_ID_NAME:
+ {
+ Reference<XPropertySet> xProp(m_xTable,UNO_QUERY);
+ _rValue = xProp->getPropertyValue(PROPERTY_NAME);
+ }
+ break;
+ case PROPERTY_ID_DESCRIPTION:
+ {
+ Reference<XPropertySet> xProp(m_xTable,UNO_QUERY);
+ _rValue = xProp->getPropertyValue(PROPERTY_DESCRIPTION);
+ }
+ break;
+ case PROPERTY_ID_TYPE:
+ {
+ Reference<XPropertySet> xProp(m_xTable,UNO_QUERY);
+ _rValue = xProp->getPropertyValue(PROPERTY_TYPE);
+ }
+ break;
+ default:
+ SAL_WARN("dbaccess", "Invalid Handle for table");
+ }
+}
+
+void ODBTableDecorator::construct()
+{
+ bool bNotFound = true;
+ Reference<XPropertySet> xProp(m_xTable,UNO_QUERY);
+ if ( xProp.is() )
+ {
+ Reference<XPropertySetInfo> xInfo = xProp->getPropertySetInfo();
+ bNotFound = !xInfo->hasPropertyByName(PROPERTY_PRIVILEGES);
+ }
+ if ( bNotFound )
+ registerProperty(PROPERTY_PRIVILEGES, PROPERTY_ID_PRIVILEGES, PropertyAttribute::BOUND | PropertyAttribute::READONLY,
+ &m_nPrivileges, ::cppu::UnoType<sal_Int32>::get());
+}
+
+::cppu::IPropertyArrayHelper* ODBTableDecorator::createArrayHelper(sal_Int32 /*_nId*/) const
+{
+ Reference<XPropertySet> xProp(m_xTable,UNO_QUERY);
+ Reference<XPropertySetInfo> xInfo = xProp->getPropertySetInfo();
+
+ Sequence< Property > aTableProps = xInfo->getProperties();
+ for (Property & prop : asNonConstRange(aTableProps))
+ {
+ if (prop.Name == PROPERTY_CATALOGNAME)
+ prop.Handle = PROPERTY_ID_CATALOGNAME;
+ else if (prop.Name == PROPERTY_SCHEMANAME)
+ prop.Handle = PROPERTY_ID_SCHEMANAME;
+ else if (prop.Name == PROPERTY_NAME)
+ prop.Handle = PROPERTY_ID_NAME;
+ else if (prop.Name == PROPERTY_DESCRIPTION)
+ prop.Handle = PROPERTY_ID_DESCRIPTION;
+ else if (prop.Name == PROPERTY_TYPE)
+ prop.Handle = PROPERTY_ID_TYPE;
+ else if (prop.Name == PROPERTY_PRIVILEGES)
+ prop.Handle = PROPERTY_ID_PRIVILEGES;
+ }
+
+ describeProperties(aTableProps);
+
+ return new ::cppu::OPropertyArrayHelper(aTableProps);
+}
+
+::cppu::IPropertyArrayHelper & SAL_CALL ODBTableDecorator::getInfoHelper()
+{
+ Reference<XPropertySet> xProp(m_xTable,UNO_QUERY);
+
+ Reference<XPropertySetInfo> xInfo = xProp->getPropertySetInfo();
+ bool bIsDescriptor = (xInfo->getPropertyByName(PROPERTY_NAME).Attributes & PropertyAttribute::READONLY) == 0;
+
+ return *ODBTableDecorator_PROP::getArrayHelper( bIsDescriptor ? 0 : 1 );
+
+ // TODO: this is a HACK, and prone to errors
+ // The OIdPropertyArrayUsageHelper is intended for classes where there exists a known, limited
+ // number of different property set infos (distinguished by the ID), all implemented by this very
+ // same class.
+ // However, in this case here we have an unknown, potentially unlimited number of different
+ // property set infos: Depending on the table for which we act as decorator, different property
+ // sets might exist.
+}
+
+// XServiceInfo
+OUString SAL_CALL ODBTableDecorator::getImplementationName()
+ {
+ return "com.sun.star.sdb.dbaccess.ODBTableDecorator";
+ }
+sal_Bool SAL_CALL ODBTableDecorator::supportsService(const OUString& _rServiceName)
+ {
+ const css::uno::Sequence< OUString > aSupported(getSupportedServiceNames());
+ for (const OUString& s : aSupported)
+ if (s == _rServiceName)
+ return true;
+
+ return false;
+ }
+css::uno::Sequence< OUString > SAL_CALL ODBTableDecorator::getSupportedServiceNames()
+{
+ return { SERVICE_SDBCX_TABLE };
+}
+
+
+Any SAL_CALL ODBTableDecorator::queryInterface( const Type & rType )
+{
+ Any aRet;
+ if(m_xTable.is())
+ {
+ aRet = m_xTable->queryInterface(rType);
+ if(aRet.hasValue())
+ { // now we know that our table supports this type so we return ourself
+ aRet = OTableDescriptor_BASE::queryInterface(rType);
+ if(!aRet.hasValue())
+ aRet = ODataSettings::queryInterface(rType);
+ }
+ }
+
+ return aRet;
+}
+
+Sequence< Type > SAL_CALL ODBTableDecorator::getTypes( )
+{
+ Reference<XTypeProvider> xTypes(m_xTable,UNO_QUERY);
+ OSL_ENSURE(xTypes.is(),"Table must be a TypeProvider!");
+ return xTypes->getTypes();
+}
+
+// XRename,
+void SAL_CALL ODBTableDecorator::rename( const OUString& _rNewName )
+{
+ ::osl::MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OTableDescriptor_BASE::rBHelper.bDisposed);
+ Reference<XRename> xRename(m_xTable,UNO_QUERY);
+ if(!xRename.is())
+ throw SQLException(DBA_RES(RID_STR_NO_TABLE_RENAME),*this,SQLSTATE_GENERAL,1000,Any() );
+ // not supported
+ xRename->rename(_rNewName);
+}
+
+// XAlterTable,
+void SAL_CALL ODBTableDecorator::alterColumnByName( const OUString& _rName, const Reference< XPropertySet >& _rxDescriptor )
+{
+ ::osl::MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OTableDescriptor_BASE::rBHelper.bDisposed);
+ Reference<XAlterTable> xAlter(m_xTable,UNO_QUERY);
+ if(!xAlter.is())
+ throw SQLException(DBA_RES(RID_STR_COLUMN_ALTER_BY_NAME),*this,SQLSTATE_GENERAL,1000,Any() );
+ xAlter->alterColumnByName(_rName,_rxDescriptor);
+ if(m_pColumns)
+ m_pColumns->refresh();
+}
+
+void SAL_CALL ODBTableDecorator::alterColumnByIndex( sal_Int32 _nIndex, const Reference< XPropertySet >& _rxDescriptor )
+{
+ ::osl::MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OTableDescriptor_BASE::rBHelper.bDisposed);
+ Reference<XAlterTable> xAlter(m_xTable,UNO_QUERY);
+ if(!xAlter.is())
+ throw SQLException(DBA_RES(RID_STR_COLUMN_ALTER_BY_INDEX),*this,SQLSTATE_GENERAL,1000,Any() );
+ // not supported
+ xAlter->alterColumnByIndex(_nIndex,_rxDescriptor);
+ if(m_pColumns)
+ m_pColumns->refresh();
+}
+
+Reference< XNameAccess> ODBTableDecorator::getIndexes()
+{
+ ::osl::MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OTableDescriptor_BASE::rBHelper.bDisposed);
+ return Reference< XIndexesSupplier>(m_xTable,UNO_QUERY_THROW)->getIndexes();
+}
+
+Reference< XIndexAccess> ODBTableDecorator::getKeys()
+{
+ ::osl::MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OTableDescriptor_BASE::rBHelper.bDisposed);
+ return Reference< XKeysSupplier>(m_xTable,UNO_QUERY_THROW)->getKeys();
+}
+
+Reference< XNameAccess> ODBTableDecorator::getColumns()
+{
+ ::osl::MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OTableDescriptor_BASE::rBHelper.bDisposed);
+
+ if(!m_pColumns)
+ refreshColumns();
+
+ return m_pColumns.get();
+}
+
+OUString SAL_CALL ODBTableDecorator::getName()
+{
+ ::osl::MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OTableDescriptor_BASE::rBHelper.bDisposed);
+ Reference<XNamed> xName(m_xTable,UNO_QUERY);
+ OSL_ENSURE(xName.is(),"Table should support the XNamed interface");
+ return xName->getName();
+}
+
+sal_Int64 SAL_CALL ODBTableDecorator::getSomething( const Sequence< sal_Int8 >& rId )
+{
+ if (comphelper::isUnoTunnelId<ODBTableDecorator>(rId))
+ return comphelper::getSomething_cast(this);
+
+ sal_Int64 nRet = 0;
+ Reference<XUnoTunnel> xTunnel(m_xTable,UNO_QUERY);
+ if(xTunnel.is())
+ nRet = xTunnel->getSomething(rId);
+ return nRet;
+}
+
+const Sequence< sal_Int8 > & ODBTableDecorator::getUnoTunnelId()
+{
+ static const comphelper::UnoIdInit implId;
+ return implId.getSeq();
+}
+
+void ODBTableDecorator::fillPrivileges() const
+{
+ // somebody is asking for the privileges and we do not know them, yet
+ m_nPrivileges = 0;
+ try
+ {
+ Reference<XPropertySet> xProp(m_xTable,UNO_QUERY);
+ if ( xProp.is() )
+ {
+ if ( xProp->getPropertySetInfo()->hasPropertyByName(PROPERTY_PRIVILEGES) )
+ {
+ xProp->getPropertyValue(PROPERTY_PRIVILEGES) >>= m_nPrivileges;
+ }
+ if ( m_nPrivileges == 0 ) // second chance
+ {
+ OUString sCatalog,sSchema,sName;
+ xProp->getPropertyValue(PROPERTY_CATALOGNAME) >>= sCatalog;
+ xProp->getPropertyValue(PROPERTY_SCHEMANAME) >>= sSchema;
+ xProp->getPropertyValue(PROPERTY_NAME) >>= sName;
+ m_nPrivileges = ::dbtools::getTablePrivileges(m_xMetaData, sCatalog,sSchema, sName);
+ }
+ }
+ }
+ catch(const SQLException&)
+ {
+ SAL_WARN("dbaccess", "ODBTableDecorator::ODBTableDecorator : could not collect the privileges !");
+ }
+}
+
+Reference< XPropertySet > SAL_CALL ODBTableDecorator::createDataDescriptor( )
+{
+ ::osl::MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OTableDescriptor_BASE::rBHelper.bDisposed);
+
+ Reference< XDataDescriptorFactory > xFactory( m_xTable, UNO_QUERY );
+ OSL_ENSURE( xFactory.is(), "ODBTableDecorator::createDataDescriptor: invalid table!" );
+ Reference< XColumnsSupplier > xColsSupp;
+ if ( xFactory.is() )
+ xColsSupp.set(xFactory->createDataDescriptor(), css::uno::UNO_QUERY);
+
+ return new ODBTableDecorator(
+ m_xConnection,
+ xColsSupp,
+ m_xNumberFormats,
+ nullptr
+ );
+}
+
+Reference< css::beans::XPropertySetInfo > SAL_CALL ODBTableDecorator::getPropertySetInfo( )
+{
+ return ::cppu::OPropertySetHelper::createPropertySetInfo(getInfoHelper());
+}
+
+void ODBTableDecorator::refreshColumns()
+{
+ ::osl::MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OTableDescriptor_BASE::rBHelper.bDisposed);
+
+ std::vector< OUString> aVector;
+
+ Reference<XNameAccess> xNames;
+ if(m_xTable.is())
+ {
+ xNames = m_xTable->getColumns();
+ if(xNames.is())
+ {
+ const Sequence< OUString> aNames = xNames->getElementNames();
+ aVector.insert(aVector.end(), aNames.begin(), aNames.end());
+ }
+ }
+ if(!m_pColumns)
+ {
+ OColumns* pCol = new OColumns(*this,m_aMutex,xNames,m_xMetaData.is() && m_xMetaData->supportsMixedCaseQuotedIdentifiers(),aVector,
+ this,this,
+ m_xMetaData.is() && m_xMetaData->supportsAlterTableWithAddColumn(),
+ m_xMetaData.is() && m_xMetaData->supportsAlterTableWithDropColumn());
+
+ pCol->setParent(*this);
+ rtl::Reference<OContainerMediator> pMediator = new OContainerMediator( pCol, m_xColumnDefinitions );
+ m_xColumnMediator = pMediator;
+ pCol->setMediator( pMediator.get() );
+ m_pColumns.reset(pCol);
+ }
+ else
+ m_pColumns->reFill(aVector);
+}
+
+rtl::Reference<OColumn> ODBTableDecorator::createColumn(const OUString& _rName) const
+{
+ rtl::Reference<OColumn> pReturn;
+
+ Reference<XNameAccess> xNames;
+ if ( m_xTable.is() )
+ {
+ xNames = m_xTable->getColumns();
+
+ if ( xNames.is() && xNames->hasByName(_rName) )
+ {
+ Reference<XPropertySet> xProp(xNames->getByName(_rName),UNO_QUERY);
+
+ Reference<XPropertySet> xColumnDefinition;
+ if ( m_xColumnDefinitions.is() && m_xColumnDefinitions->hasByName(_rName))
+ xColumnDefinition.set(m_xColumnDefinitions->getByName(_rName),UNO_QUERY);
+
+ pReturn = new OTableColumnWrapper( xProp, xColumnDefinition, false );
+ }
+ }
+ return pReturn;
+}
+
+void ODBTableDecorator::columnAppended( const Reference< XPropertySet >& /*_rxSourceDescriptor*/ )
+{
+ // not interested in
+}
+
+void ODBTableDecorator::columnDropped(const OUString& _sName)
+{
+ Reference<XDrop> xDrop(m_xColumnDefinitions,UNO_QUERY);
+ if ( xDrop.is() && m_xColumnDefinitions->hasByName(_sName) )
+ xDrop->dropByName(_sName);
+}
+
+Reference< XPropertySet > ODBTableDecorator::createColumnDescriptor()
+{
+ Reference<XDataDescriptorFactory> xNames;
+ if(m_xTable.is())
+ xNames.set(m_xTable->getColumns(),UNO_QUERY);
+ Reference< XPropertySet > xRet;
+ if ( xNames.is() )
+ xRet = new OTableColumnDescriptorWrapper( xNames->createDataDescriptor(), false, true );
+ return xRet;
+}
+
+void SAL_CALL ODBTableDecorator::acquire() noexcept
+{
+ OTableDescriptor_BASE::acquire();
+}
+
+void SAL_CALL ODBTableDecorator::release() noexcept
+{
+ OTableDescriptor_BASE::release();
+}
+
+void SAL_CALL ODBTableDecorator::setName( const OUString& /*aName*/ )
+{
+ throwFunctionNotSupportedRuntimeException( "XNamed::setName", *this );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/api/View.cxx b/dbaccess/source/core/api/View.cxx
new file mode 100644
index 000000000..c52c4885c
--- /dev/null
+++ b/dbaccess/source/core/api/View.cxx
@@ -0,0 +1,120 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <View.hxx>
+#include <strings.hxx>
+
+#include <connectivity/dbtools.hxx>
+
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+
+#include <tools/diagnose_ex.h>
+
+namespace dbaccess
+{
+
+ using namespace ::com::sun::star::uno;
+ using ::com::sun::star::sdbc::XConnection;
+ using ::com::sun::star::lang::XMultiServiceFactory;
+
+ static OUString lcl_getServiceNameForSetting(const Reference< css::sdbc::XConnection >& _xConnection,const OUString& i_sSetting)
+ {
+ OUString sSupportService;
+ Any aValue;
+ if ( dbtools::getDataSourceSetting(_xConnection,i_sSetting,aValue) )
+ {
+ aValue >>= sSupportService;
+ }
+ return sSupportService;
+ }
+ // View
+ View::View( const Reference< XConnection >& _rxConnection, bool _bCaseSensitive,
+ const OUString& _rCatalogName,const OUString& _rSchemaName, const OUString& _rName )
+ :View_Base( _bCaseSensitive, _rName, _rxConnection->getMetaData(), OUString(), _rSchemaName, _rCatalogName )
+ {
+ m_nCommandHandle = getProperty(PROPERTY_COMMAND).Handle;
+ try
+ {
+ Reference<XMultiServiceFactory> xFac(_rxConnection,UNO_QUERY_THROW);
+ m_xViewAccess.set(xFac->createInstance(lcl_getServiceNameForSetting(_rxConnection,"ViewAccessServiceName")),UNO_QUERY);
+ }
+ catch(const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+
+ View::~View()
+ {
+ }
+
+ IMPLEMENT_FORWARD_REFCOUNT( View, View_Base )
+ IMPLEMENT_GET_IMPLEMENTATION_ID( View )
+
+ Any SAL_CALL View::queryInterface( const Type & _rType )
+ {
+ if(_rType == cppu::UnoType<XAlterView>::get()&& !m_xViewAccess.is() )
+ return Any();
+ Any aReturn = View_Base::queryInterface( _rType );
+ if ( !aReturn.hasValue() )
+ aReturn = View_IBASE::queryInterface( _rType );
+ return aReturn;
+ }
+
+ Sequence< Type > SAL_CALL View::getTypes( )
+ {
+ Type aAlterType = cppu::UnoType<XAlterView>::get();
+
+ Sequence< Type > aTypes( ::comphelper::concatSequences(View_Base::getTypes(),View_IBASE::getTypes()) );
+ std::vector<Type> aOwnTypes;
+ aOwnTypes.reserve(aTypes.getLength());
+
+ const Type* pIter = aTypes.getConstArray();
+ const Type* pEnd = pIter + aTypes.getLength();
+ for(;pIter != pEnd ;++pIter)
+ {
+ if( *pIter != aAlterType || m_xViewAccess.is() )
+ aOwnTypes.push_back(*pIter);
+ }
+
+ return Sequence< Type >(aOwnTypes.data(), aOwnTypes.size());
+ }
+
+ void SAL_CALL View::alterCommand( const OUString& _rNewCommand )
+ {
+ OSL_ENSURE(m_xViewAccess.is(),"Illegal call to AlterView!");
+ m_xViewAccess->alterCommand(this,_rNewCommand);
+ }
+
+ void SAL_CALL View::getFastPropertyValue( Any& _rValue, sal_Int32 _nHandle ) const
+ {
+ if ( _nHandle == m_nCommandHandle && m_xViewAccess.is() )
+ {
+ // retrieve the very current command, don't rely on the base classes cached value
+ // (which we initialized empty, anyway)
+ _rValue <<= m_xViewAccess->getCommand(const_cast<View*>(this));
+ return;
+ }
+
+ View_Base::getFastPropertyValue( _rValue, _nHandle );
+ }
+
+} // namespace dbaccess
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/api/WrappedResultSet.cxx b/dbaccess/source/core/api/WrappedResultSet.cxx
new file mode 100644
index 000000000..09d70826b
--- /dev/null
+++ b/dbaccess/source/core/api/WrappedResultSet.cxx
@@ -0,0 +1,184 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "WrappedResultSet.hxx"
+#include <com/sun/star/sdbc/XResultSetUpdate.hpp>
+
+using namespace dbaccess;
+using namespace ::connectivity;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::sdbcx;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::lang;
+using namespace ::osl;
+
+void WrappedResultSet::construct(const Reference< XResultSet>& _xDriverSet,const OUString& i_sRowSetFilter)
+{
+ OCacheSet::construct(_xDriverSet,i_sRowSetFilter);
+ m_xUpd.set(_xDriverSet,UNO_QUERY_THROW);
+ m_xRowLocate.set(_xDriverSet,UNO_QUERY_THROW);
+ m_xUpdRow.set(_xDriverSet,UNO_QUERY_THROW);
+}
+
+void WrappedResultSet::reset(const Reference< XResultSet>& _xDriverSet)
+{
+ construct(_xDriverSet, m_sRowSetFilter);
+}
+
+Any WrappedResultSet::getBookmark()
+{
+ if ( m_xRowLocate.is() )
+ {
+ return m_xRowLocate->getBookmark( );
+ }
+ return Any(m_xDriverSet->getRow());
+}
+
+bool WrappedResultSet::moveToBookmark( const Any& bookmark )
+{
+ return m_xRowLocate->moveToBookmark( bookmark );
+}
+
+sal_Int32 WrappedResultSet::compareBookmarks( const Any& _first, const Any& _second )
+{
+ return m_xRowLocate->compareBookmarks( _first,_second );
+}
+
+bool WrappedResultSet::hasOrderedBookmarks( )
+{
+ return m_xRowLocate->hasOrderedBookmarks();
+}
+
+sal_Int32 WrappedResultSet::hashBookmark( const Any& bookmark )
+{
+ return m_xRowLocate->hashBookmark(bookmark);
+}
+
+void WrappedResultSet::insertRow( const ORowSetRow& _rInsertRow,const connectivity::OSQLTable& /*_xTable*/ )
+{
+ m_xUpd->moveToInsertRow();
+ sal_Int32 i = 1;
+ connectivity::ORowVector< ORowSetValue > ::Vector::const_iterator aEnd = _rInsertRow->end();
+ for(connectivity::ORowVector< ORowSetValue > ::Vector::iterator aIter = _rInsertRow->begin()+1;aIter != aEnd;++aIter,++i)
+ {
+ aIter->setSigned(m_aSignedFlags[i-1]);
+ updateColumn(i,m_xUpdRow,*aIter);
+ }
+ m_xUpd->insertRow();
+ (*_rInsertRow->begin()) = getBookmark();
+}
+
+void WrappedResultSet::updateRow(const ORowSetRow& _rInsertRow ,const ORowSetRow& _rOriginalRow,const connectivity::OSQLTable& /*_xTable*/ )
+{
+ sal_Int32 i = 1;
+ connectivity::ORowVector< ORowSetValue > ::Vector::const_iterator aOrgIter = _rOriginalRow->begin()+1;
+ connectivity::ORowVector< ORowSetValue > ::Vector::iterator aEnd = _rInsertRow->end();
+ for(connectivity::ORowVector< ORowSetValue > ::Vector::iterator aIter = _rInsertRow->begin()+1;aIter != aEnd;++aIter,++i,++aOrgIter)
+ {
+ aIter->setSigned(aOrgIter->isSigned());
+ updateColumn(i,m_xUpdRow,*aIter);
+ }
+ m_xUpd->updateRow();
+}
+
+void WrappedResultSet::deleteRow(const ORowSetRow& /*_rDeleteRow*/ ,const connectivity::OSQLTable& /*_xTable*/ )
+{
+ m_xUpd->deleteRow();
+}
+
+void WrappedResultSet::updateColumn(sal_Int32 nPos, const Reference< XRowUpdate >& _xParameter, const ORowSetValue& _rValue)
+{
+ if(!(_rValue.isBound() && _rValue.isModified()))
+ return;
+
+ if(_rValue.isNull())
+ _xParameter->updateNull(nPos);
+ else
+ {
+
+ switch(_rValue.getTypeKind())
+ {
+ case DataType::DECIMAL:
+ case DataType::NUMERIC:
+ _xParameter->updateNumericObject(nPos,_rValue.makeAny(),m_xSetMetaData->getScale(nPos));
+ break;
+ case DataType::CHAR:
+ case DataType::VARCHAR:
+ _xParameter->updateString(nPos,_rValue.getString());
+ break;
+ case DataType::BIGINT:
+ if ( _rValue.isSigned() )
+ _xParameter->updateLong(nPos,_rValue.getLong());
+ else
+ _xParameter->updateString(nPos,_rValue.getString());
+ break;
+ case DataType::BIT:
+ case DataType::BOOLEAN:
+ _xParameter->updateBoolean(nPos,_rValue.getBool());
+ break;
+ case DataType::TINYINT:
+ if ( _rValue.isSigned() )
+ _xParameter->updateByte(nPos,_rValue.getInt8());
+ else
+ _xParameter->updateShort(nPos,_rValue.getInt16());
+ break;
+ case DataType::SMALLINT:
+ if ( _rValue.isSigned() )
+ _xParameter->updateShort(nPos,_rValue.getInt16());
+ else
+ _xParameter->updateInt(nPos,_rValue.getInt32());
+ break;
+ case DataType::INTEGER:
+ if ( _rValue.isSigned() )
+ _xParameter->updateInt(nPos,_rValue.getInt32());
+ else
+ _xParameter->updateLong(nPos,_rValue.getLong());
+ break;
+ case DataType::FLOAT:
+ _xParameter->updateFloat(nPos,_rValue.getFloat());
+ break;
+ case DataType::DOUBLE:
+ case DataType::REAL:
+ _xParameter->updateDouble(nPos,_rValue.getDouble());
+ break;
+ case DataType::DATE:
+ _xParameter->updateDate(nPos,_rValue.getDate());
+ break;
+ case DataType::TIME:
+ _xParameter->updateTime(nPos,_rValue.getTime());
+ break;
+ case DataType::TIMESTAMP:
+ _xParameter->updateTimestamp(nPos,_rValue.getDateTime());
+ break;
+ case DataType::BINARY:
+ case DataType::VARBINARY:
+ case DataType::LONGVARBINARY:
+ _xParameter->updateBytes(nPos,_rValue.getSequence());
+ break;
+ case DataType::BLOB:
+ case DataType::CLOB:
+ _xParameter->updateObject(nPos,_rValue.getAny());
+ break;
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/api/WrappedResultSet.hxx b/dbaccess/source/core/api/WrappedResultSet.hxx
new file mode 100644
index 000000000..58b2d7041
--- /dev/null
+++ b/dbaccess/source/core/api/WrappedResultSet.hxx
@@ -0,0 +1,60 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include "CacheSet.hxx"
+#include <com/sun/star/sdbcx/XRowLocate.hpp>
+#include <com/sun/star/sdbc/XRowUpdate.hpp>
+#include <com/sun/star/sdbc/XResultSetUpdate.hpp>
+
+namespace dbaccess
+{
+ // this set is used when we have a bookmarkable set from the driver
+ class WrappedResultSet : public OCacheSet
+ {
+ css::uno::Reference< css::sdbcx::XRowLocate> m_xRowLocate;
+ css::uno::Reference< css::sdbc::XResultSetUpdate> m_xUpd;
+ css::uno::Reference< css::sdbc::XRowUpdate> m_xUpdRow;
+
+ void updateColumn(sal_Int32 nPos, const css::uno::Reference< css::sdbc::XRowUpdate >& _xParameter, const connectivity::ORowSetValue& _rValue);
+ public:
+ explicit WrappedResultSet(sal_Int32 i_nMaxRows) : OCacheSet(i_nMaxRows)
+ {}
+ virtual ~WrappedResultSet() override
+ {
+ m_xRowLocate = nullptr;
+ }
+
+ virtual void construct(const css::uno::Reference< css::sdbc::XResultSet>& _xDriverSet,const OUString& i_sRowSetFilter) override;
+ virtual void reset(const css::uno::Reference< css::sdbc::XResultSet>& _xDriverSet) override;
+ // css::sdbcx::XRowLocate
+ virtual css::uno::Any getBookmark() override;
+ virtual bool moveToBookmark( const css::uno::Any& bookmark ) override;
+ virtual sal_Int32 compareBookmarks( const css::uno::Any& first, const css::uno::Any& second ) override;
+ virtual bool hasOrderedBookmarks( ) override;
+ virtual sal_Int32 hashBookmark( const css::uno::Any& bookmark ) override;
+ // css::sdbc::XResultSetUpdate
+ virtual void insertRow( const ORowSetRow& _rInsertRow,const connectivity::OSQLTable& _xTable ) override;
+ virtual void updateRow(const ORowSetRow& _rInsertRow,const ORowSetRow& _rOriginalRow,const connectivity::OSQLTable& _xTable ) override;
+ virtual void deleteRow(const ORowSetRow& _rInsertRow,const connectivity::OSQLTable& _xTable ) override;
+ };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/api/callablestatement.cxx b/dbaccess/source/core/api/callablestatement.cxx
new file mode 100644
index 000000000..8f864fbe0
--- /dev/null
+++ b/dbaccess/source/core/api/callablestatement.cxx
@@ -0,0 +1,250 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <callablestatement.hxx>
+#include <cppuhelper/typeprovider.hxx>
+#include <cppuhelper/queryinterface.hxx>
+#include <strings.hxx>
+
+using namespace dbaccess;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::sdbcx;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::cppu;
+using namespace ::osl;
+
+// css::lang::XTypeProvider
+Sequence< Type > OCallableStatement::getTypes()
+{
+ OTypeCollection aTypes(cppu::UnoType<XRow>::get(),
+ cppu::UnoType<XOutParameters>::get(),
+ OPreparedStatement::getTypes() );
+
+ return aTypes.getTypes();
+}
+
+Sequence< sal_Int8 > OCallableStatement::getImplementationId()
+{
+ return css::uno::Sequence<sal_Int8>();
+}
+
+// css::uno::XInterface
+Any OCallableStatement::queryInterface( const Type & rType )
+{
+ Any aIface = OPreparedStatement::queryInterface( rType );
+ if (!aIface.hasValue())
+ aIface = ::cppu::queryInterface(
+ rType,
+ static_cast< XRow * >( this ),
+ static_cast< XOutParameters * >( this ));
+ return aIface;
+}
+
+void OCallableStatement::acquire() noexcept
+{
+ OPreparedStatement::acquire();
+}
+
+void OCallableStatement::release() noexcept
+{
+ OPreparedStatement::release();
+}
+
+// XServiceInfo
+OUString OCallableStatement::getImplementationName( )
+{
+ return "com.sun.star.sdb.OCallableStatement";
+}
+
+Sequence< OUString > OCallableStatement::getSupportedServiceNames( )
+{
+ return { SERVICE_SDBC_CALLABLESTATEMENT, SERVICE_SDB_CALLABLESTATEMENT };
+}
+
+// XOutParameters
+void SAL_CALL OCallableStatement::registerOutParameter( sal_Int32 parameterIndex, sal_Int32 sqlType, const OUString& typeName )
+{
+ MutexGuard aGuard(m_aMutex);
+
+ ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed);
+
+ Reference< XOutParameters >(m_xAggregateAsSet, UNO_QUERY_THROW)->registerOutParameter( parameterIndex, sqlType, typeName );
+}
+
+void SAL_CALL OCallableStatement::registerNumericOutParameter( sal_Int32 parameterIndex, sal_Int32 sqlType, sal_Int32 scale )
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed);
+
+ Reference< XOutParameters >(m_xAggregateAsSet, UNO_QUERY_THROW)->registerNumericOutParameter( parameterIndex, sqlType, scale );
+}
+
+// XRow
+sal_Bool SAL_CALL OCallableStatement::wasNull( )
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed);
+
+ return Reference< XRow >(m_xAggregateAsSet, UNO_QUERY_THROW)->wasNull();
+}
+
+OUString SAL_CALL OCallableStatement::getString( sal_Int32 columnIndex )
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed);
+
+ return Reference< XRow >(m_xAggregateAsSet, UNO_QUERY_THROW)->getString( columnIndex );
+}
+
+sal_Bool SAL_CALL OCallableStatement::getBoolean( sal_Int32 columnIndex )
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed);
+
+ return Reference< XRow >(m_xAggregateAsSet, UNO_QUERY_THROW)->getBoolean( columnIndex );
+}
+
+sal_Int8 SAL_CALL OCallableStatement::getByte( sal_Int32 columnIndex )
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed);
+
+ return Reference< XRow >(m_xAggregateAsSet, UNO_QUERY_THROW)->getByte( columnIndex );
+}
+
+sal_Int16 SAL_CALL OCallableStatement::getShort( sal_Int32 columnIndex )
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed);
+ return Reference< XRow >(m_xAggregateAsSet, UNO_QUERY_THROW)->getShort( columnIndex );
+}
+
+sal_Int32 SAL_CALL OCallableStatement::getInt( sal_Int32 columnIndex )
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed);
+ return Reference< XRow >(m_xAggregateAsSet, UNO_QUERY_THROW)->getInt( columnIndex );
+}
+
+sal_Int64 SAL_CALL OCallableStatement::getLong( sal_Int32 columnIndex )
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed);
+ return Reference< XRow >(m_xAggregateAsSet, UNO_QUERY_THROW)->getLong( columnIndex );
+}
+
+float SAL_CALL OCallableStatement::getFloat( sal_Int32 columnIndex )
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed);
+ return Reference< XRow >(m_xAggregateAsSet, UNO_QUERY_THROW)->getFloat( columnIndex );
+}
+
+double SAL_CALL OCallableStatement::getDouble( sal_Int32 columnIndex )
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed);
+ return Reference< XRow >(m_xAggregateAsSet, UNO_QUERY_THROW)->getDouble( columnIndex );
+}
+
+Sequence< sal_Int8 > SAL_CALL OCallableStatement::getBytes( sal_Int32 columnIndex )
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed);
+ return Reference< XRow >(m_xAggregateAsSet, UNO_QUERY_THROW)->getBytes( columnIndex );
+}
+
+css::util::Date SAL_CALL OCallableStatement::getDate( sal_Int32 columnIndex )
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed);
+ return Reference< XRow >(m_xAggregateAsSet, UNO_QUERY_THROW)->getDate( columnIndex );
+}
+
+css::util::Time SAL_CALL OCallableStatement::getTime( sal_Int32 columnIndex )
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed);
+ return Reference< XRow >(m_xAggregateAsSet, UNO_QUERY_THROW)->getTime( columnIndex );
+}
+
+css::util::DateTime SAL_CALL OCallableStatement::getTimestamp( sal_Int32 columnIndex )
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed);
+
+ return Reference< XRow >(m_xAggregateAsSet, UNO_QUERY_THROW)->getTimestamp( columnIndex );
+}
+
+Reference< css::io::XInputStream > SAL_CALL OCallableStatement::getBinaryStream( sal_Int32 columnIndex )
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed);
+
+ return Reference< XRow >(m_xAggregateAsSet, UNO_QUERY_THROW)->getBinaryStream( columnIndex );
+}
+
+Reference< css::io::XInputStream > SAL_CALL OCallableStatement::getCharacterStream( sal_Int32 columnIndex )
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed);
+
+ return Reference< XRow >(m_xAggregateAsSet, UNO_QUERY_THROW)->getCharacterStream( columnIndex );
+}
+
+Any SAL_CALL OCallableStatement::getObject( sal_Int32 columnIndex, const Reference< css::container::XNameAccess >& typeMap )
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed);
+
+ return Reference< XRow >(m_xAggregateAsSet, UNO_QUERY_THROW)->getObject( columnIndex, typeMap );
+}
+
+Reference< XRef > SAL_CALL OCallableStatement::getRef( sal_Int32 columnIndex )
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed);
+ return Reference< XRow >(m_xAggregateAsSet, UNO_QUERY_THROW)->getRef( columnIndex );
+}
+
+Reference< XBlob > SAL_CALL OCallableStatement::getBlob( sal_Int32 columnIndex )
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed);
+ return Reference< XRow >(m_xAggregateAsSet, UNO_QUERY_THROW)->getBlob( columnIndex );
+}
+
+Reference< XClob > SAL_CALL OCallableStatement::getClob( sal_Int32 columnIndex )
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed);
+ return Reference< XRow >(m_xAggregateAsSet, UNO_QUERY_THROW)->getClob( columnIndex );
+}
+
+Reference< XArray > SAL_CALL OCallableStatement::getArray( sal_Int32 columnIndex )
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed);
+ return Reference< XRow >(m_xAggregateAsSet, UNO_QUERY_THROW)->getArray( columnIndex );
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/api/column.cxx b/dbaccess/source/core/api/column.cxx
new file mode 100644
index 000000000..5bc70affb
--- /dev/null
+++ b/dbaccess/source/core/api/column.cxx
@@ -0,0 +1,411 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <ContainerMediator.hxx>
+#include <column.hxx>
+#include <strings.hrc>
+#include <strings.hxx>
+#include <core_resource.hxx>
+#include <stringconstants.hxx>
+#include <sdbcoretools.hxx>
+
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/sdb/tools/XTableAlteration.hpp>
+
+#include <comphelper/sequence.hxx>
+#include <comphelper/types.hxx>
+#include <comphelper/uno3.hxx>
+#include <connectivity/TTableHelper.hxx>
+#include <connectivity/dbexception.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <osl/diagnose.h>
+
+using namespace dbaccess;
+using namespace connectivity;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::sdbcx;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::awt;
+using namespace ::com::sun::star::io;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::util;
+using namespace ::osl;
+using namespace ::comphelper;
+using namespace ::cppu;
+
+
+// OColumn
+OColumn::OColumn( const bool _bNameIsReadOnly )
+ :OColumnBase( m_aMutex )
+ ,::comphelper::OPropertyContainer( OColumnBase::rBHelper )
+{
+
+ registerProperty( PROPERTY_NAME, PROPERTY_ID_NAME, _bNameIsReadOnly ? PropertyAttribute::READONLY : 0,
+ &m_sName, cppu::UnoType<decltype(m_sName)>::get() );
+}
+
+OColumn::~OColumn()
+{
+}
+
+// css::lang::XTypeProvider
+Sequence< Type > OColumn::getTypes()
+{
+ return ::comphelper::concatSequences(
+ OColumnBase::getTypes(),
+ getBaseTypes()
+ );
+}
+
+// css::uno::XInterface
+IMPLEMENT_FORWARD_XINTERFACE2( OColumn, OColumnBase, ::comphelper::OPropertyContainer )
+
+// css::lang::XServiceInfo
+OUString OColumn::getImplementationName( )
+{
+ return "com.sun.star.sdb.OColumn";
+}
+
+sal_Bool OColumn::supportsService( const OUString& _rServiceName )
+{
+ return cppu::supportsService(this, _rServiceName);
+}
+
+Sequence< OUString > OColumn::getSupportedServiceNames( )
+{
+ return { SERVICE_SDBCX_COLUMN };
+}
+
+// OComponentHelper
+void OColumn::disposing()
+{
+ OPropertyContainer::disposing();
+}
+
+// css::beans::XPropertySet
+Reference< XPropertySetInfo > OColumn::getPropertySetInfo()
+{
+ return createPropertySetInfo( getInfoHelper() ) ;
+}
+
+OUString SAL_CALL OColumn::getName( )
+{
+ return m_sName;
+}
+
+void SAL_CALL OColumn::setName( const OUString& _rName )
+{
+ m_sName = _rName;
+}
+
+void OColumn::registerProperty( const OUString& _rName, sal_Int32 _nHandle, sal_Int32 _nAttributes, void* _pPointerToMember, const Type& _rMemberType )
+{
+ ::comphelper::OPropertyContainer::registerProperty( _rName, _nHandle, _nAttributes, _pPointerToMember, _rMemberType );
+}
+
+void OColumn::registerMayBeVoidProperty( const OUString& _rName, sal_Int32 _nHandle, sal_Int32 _nAttributes, Any* _pPointerToMember, const Type& _rExpectedType )
+{
+ ::comphelper::OPropertyContainer::registerMayBeVoidProperty( _rName, _nHandle, _nAttributes, _pPointerToMember, _rExpectedType );
+}
+
+// OColumns
+
+OColumns::OColumns(::cppu::OWeakObject& _rParent,
+ ::osl::Mutex& _rMutex,
+ bool _bCaseSensitive,const std::vector< OUString> &_rVector,
+ IColumnFactory* _pColFactory,
+ ::connectivity::sdbcx::IRefreshableColumns* _pRefresh,
+ bool _bAddColumn,
+ bool _bDropColumn,
+ bool _bUseHardRef)
+ : OColumns_BASE(_rParent,_bCaseSensitive,_rMutex,_rVector,_bUseHardRef)
+ ,m_pMediator(nullptr)
+ ,m_pColFactoryImpl(_pColFactory)
+ ,m_pRefreshColumns(_pRefresh)
+ ,m_bInitialized(false)
+ ,m_bAddColumn(_bAddColumn)
+ ,m_bDropColumn(_bDropColumn)
+{
+}
+
+OColumns::OColumns(::cppu::OWeakObject& _rParent, ::osl::Mutex& _rMutex,
+ const css::uno::Reference< css::container::XNameAccess >& _rxDrvColumns,
+ bool _bCaseSensitive,const std::vector< OUString> &_rVector,
+ IColumnFactory* _pColFactory,
+ ::connectivity::sdbcx::IRefreshableColumns* _pRefresh,
+ bool _bAddColumn,
+ bool _bDropColumn,
+ bool _bUseHardRef)
+ : OColumns_BASE(_rParent,_bCaseSensitive,_rMutex,_rVector,_bUseHardRef)
+ ,m_pMediator(nullptr)
+ ,m_xDrvColumns(_rxDrvColumns)
+ ,m_pColFactoryImpl(_pColFactory)
+ ,m_pRefreshColumns(_pRefresh)
+ ,m_bInitialized(false)
+ ,m_bAddColumn(_bAddColumn)
+ ,m_bDropColumn(_bDropColumn)
+{
+}
+
+OColumns::~OColumns()
+{
+}
+
+// XServiceInfo
+OUString OColumns::getImplementationName( )
+{
+ return "com.sun.star.sdb.OColumns";
+}
+
+sal_Bool OColumns::supportsService( const OUString& _rServiceName )
+{
+ return cppu::supportsService(this, _rServiceName);
+}
+
+Sequence< OUString > OColumns::getSupportedServiceNames( )
+{
+ return { SERVICE_SDBCX_CONTAINER };
+}
+
+void OColumns::append( const OUString& _rName, OColumn* _pColumn )
+{
+ MutexGuard aGuard(m_rMutex);
+
+ OSL_ENSURE( _pColumn, "OColumns::append: invalid column!" );
+ OSL_ENSURE( !m_pElements->exists( _rName ),"OColumns::append: Column already exists");
+
+ _pColumn->m_sName = _rName;
+
+ // now really insert the column
+ insertElement( _rName, _pColumn );
+}
+
+void OColumns::clearColumns()
+{
+ MutexGuard aGuard(m_rMutex);
+ disposing();
+}
+
+void OColumns::disposing()
+{
+ MutexGuard aGuard(m_rMutex);
+ m_xDrvColumns = nullptr;
+ m_pMediator = nullptr;
+ m_pColFactoryImpl = nullptr;
+ OColumns_BASE::disposing();
+}
+
+void OColumns::impl_refresh()
+{
+ if (m_pRefreshColumns)
+ m_pRefreshColumns->refreshColumns();
+}
+
+connectivity::sdbcx::ObjectType OColumns::createObject(const OUString& _rName)
+{
+ OSL_ENSURE(m_pColFactoryImpl, "OColumns::createObject: no column factory!");
+
+ connectivity::sdbcx::ObjectType xRet;
+ if ( m_pColFactoryImpl )
+ {
+ xRet = m_pColFactoryImpl->createColumn(_rName);
+ Reference<XChild> xChild(xRet,UNO_QUERY);
+ if ( xChild.is() )
+ xChild->setParent(static_cast<XChild*>(static_cast<TXChild*>(this)));
+ }
+
+ Reference<XPropertySet> xDest(xRet,UNO_QUERY);
+ if ( m_pMediator && xDest.is() )
+ m_pMediator->notifyElementCreated(_rName,xDest);
+
+ return xRet;
+}
+
+Reference< XPropertySet > OColumns::createDescriptor()
+{
+ if ( m_pColFactoryImpl )
+ {
+ Reference<XPropertySet> xRet = m_pColFactoryImpl->createColumnDescriptor();
+ Reference<XChild> xChild(xRet,UNO_QUERY);
+ if ( xChild.is() )
+ xChild->setParent(static_cast<XChild*>(static_cast<TXChild*>(this)));
+ return xRet;
+ }
+ else
+ return Reference< XPropertySet >();
+}
+
+Any SAL_CALL OColumns::queryInterface( const Type & rType )
+{
+ Any aRet;
+ if(m_xDrvColumns.is())
+ {
+ aRet = m_xDrvColumns->queryInterface(rType);
+ if ( aRet.hasValue() )
+ aRet = OColumns_BASE::queryInterface( rType);
+ if ( !aRet.hasValue() )
+ aRet = TXChild::queryInterface( rType);
+ return aRet;
+ }
+ else if(!m_pTable || !m_pTable->isNew())
+ {
+ if(!m_bAddColumn && rType == cppu::UnoType<XAppend>::get())
+ return Any();
+ if(!m_bDropColumn && rType == cppu::UnoType<XDrop>::get())
+ return Any();
+ }
+
+ aRet = OColumns_BASE::queryInterface( rType);
+ if ( !aRet.hasValue() )
+ aRet = TXChild::queryInterface( rType);
+ return aRet;
+}
+
+Sequence< Type > SAL_CALL OColumns::getTypes( )
+{
+ bool bAppendFound = false,bDropFound = false;
+
+ sal_Int32 nSize = 0;
+ Type aAppendType = cppu::UnoType<XAppend>::get();
+ Type aDropType = cppu::UnoType<XDrop>::get();
+ if(m_xDrvColumns.is())
+ {
+ Reference<XTypeProvider> xTypes(m_xDrvColumns,UNO_QUERY);
+ Sequence< Type > aTypes(xTypes->getTypes());
+
+ const Type* pBegin = aTypes.getConstArray();
+ const Type* pEnd = pBegin + aTypes.getLength();
+ for (;pBegin != pEnd ; ++pBegin)
+ {
+ if(aAppendType == *pBegin)
+ bAppendFound = true;
+ else if(aDropType == *pBegin)
+ bDropFound = true;
+ }
+ nSize = (bDropFound ? (bAppendFound ? 0 : 1) : (bAppendFound ? 1 : 2));
+ }
+ else
+ {
+ if (m_pTable && m_pTable->isNew())
+ nSize = 0;
+ else if (m_bDropColumn)
+ nSize = m_bAddColumn ? 0 : 1;
+ else
+ nSize = m_bAddColumn ? 1 : 2;
+ bDropFound = (m_pTable && m_pTable->isNew()) || m_bDropColumn;
+ bAppendFound = (m_pTable && m_pTable->isNew()) || m_bAddColumn;
+ }
+ Sequence< Type > aTypes(::comphelper::concatSequences(OColumns_BASE::getTypes(),TXChild::getTypes()));
+ Sequence< Type > aRet(aTypes.getLength() - nSize);
+
+ const Type* pBegin = aTypes.getConstArray();
+ const Type* pEnd = pBegin + aTypes.getLength();
+ for(sal_Int32 i=0;pBegin != pEnd ;++pBegin)
+ {
+ if(*pBegin != aAppendType && *pBegin != aDropType)
+ aRet.getArray()[i++] = *pBegin;
+ else if(bDropFound && *pBegin == aDropType)
+ aRet.getArray()[i++] = *pBegin;
+ else if(bAppendFound && *pBegin == aAppendType)
+ aRet.getArray()[i++] = *pBegin;
+ }
+ return aRet;
+}
+
+// XAppend
+sdbcx::ObjectType OColumns::appendObject( const OUString& _rForName, const Reference< XPropertySet >& descriptor )
+{
+ sdbcx::ObjectType xReturn;
+
+ Reference< XAppend > xAppend( m_xDrvColumns, UNO_QUERY );
+ if ( xAppend.is() )
+ {
+ xAppend->appendByDescriptor(descriptor);
+ xReturn = createObject( _rForName );
+ }
+ else if ( m_pTable && !m_pTable->isNew() )
+ {
+ if ( m_bAddColumn )
+ {
+ Reference< css::sdb::tools::XTableAlteration> xAlterService = m_pTable->getAlterService();
+ if ( xAlterService.is() )
+ {
+ xAlterService->addColumn(m_pTable,descriptor);
+ xReturn = createObject( _rForName );
+ }
+ else
+ xReturn = OColumns_BASE::appendObject( _rForName, descriptor );
+ }
+ else
+ ::dbtools::throwGenericSQLException( DBA_RES( RID_STR_NO_COLUMN_ADD ), static_cast<XChild*>(static_cast<TXChild*>(this)) );
+ }
+ else
+ xReturn = cloneDescriptor( descriptor );
+
+ if ( m_pColFactoryImpl )
+ m_pColFactoryImpl->columnAppended( descriptor );
+
+ ::dbaccess::notifyDataSourceModified(m_xParent);
+
+ return xReturn;
+}
+
+// XDrop
+void OColumns::dropObject(sal_Int32 _nPos, const OUString& _sElementName)
+{
+ Reference< XDrop > xDrop( m_xDrvColumns, UNO_QUERY );
+ if ( xDrop.is() )
+ {
+ xDrop->dropByName( _sElementName );
+ }
+ else if ( m_pTable && !m_pTable->isNew() )
+ {
+ if ( m_bDropColumn )
+ {
+ Reference< css::sdb::tools::XTableAlteration> xAlterService = m_pTable->getAlterService();
+ if ( xAlterService.is() )
+ xAlterService->dropColumn(m_pTable,_sElementName);
+ else
+ OColumns_BASE::dropObject(_nPos,_sElementName);
+ }
+ else
+ ::dbtools::throwGenericSQLException( DBA_RES( RID_STR_NO_COLUMN_DROP ), static_cast<XChild*>(static_cast<TXChild*>(this)) );
+ }
+
+ if ( m_pColFactoryImpl )
+ m_pColFactoryImpl->columnDropped(_sElementName);
+
+ ::dbaccess::notifyDataSourceModified(m_xParent);
+}
+
+Reference< XInterface > SAL_CALL OColumns::getParent( )
+{
+ ::osl::MutexGuard aGuard(m_rMutex);
+ return m_xParent;
+}
+
+void SAL_CALL OColumns::setParent( const Reference< XInterface >& _xParent )
+{
+ ::osl::MutexGuard aGuard(m_rMutex);
+ m_xParent = _xParent;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/api/columnsettings.cxx b/dbaccess/source/core/api/columnsettings.cxx
new file mode 100644
index 000000000..3f62a5a69
--- /dev/null
+++ b/dbaccess/source/core/api/columnsettings.cxx
@@ -0,0 +1,150 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <columnsettings.hxx>
+#include <stringconstants.hxx>
+#include <strings.hxx>
+
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+
+#include <comphelper/property.hxx>
+#include <tools/diagnose_ex.h>
+
+namespace dbaccess
+{
+
+ using ::com::sun::star::uno::Reference;
+ using ::com::sun::star::uno::UNO_QUERY;
+ using ::com::sun::star::uno::UNO_SET_THROW;
+ using ::com::sun::star::uno::Exception;
+ using ::com::sun::star::uno::Any;
+ using ::com::sun::star::uno::Type;
+ using ::com::sun::star::beans::XPropertySet;
+ using ::com::sun::star::beans::XPropertySetInfo;
+
+ namespace PropertyAttribute = ::com::sun::star::beans::PropertyAttribute;
+
+ // OColumnSettings
+
+ OColumnSettings::OColumnSettings()
+ :m_bHidden(false)
+ {
+ }
+
+ OColumnSettings::~OColumnSettings()
+ {
+ }
+
+ void OColumnSettings::registerProperties( IPropertyContainer& _rPropertyContainer )
+ {
+ const sal_Int32 nBoundAttr = PropertyAttribute::BOUND;
+ const sal_Int32 nMayBeVoidAttr = PropertyAttribute::MAYBEVOID | nBoundAttr;
+
+ const Type& rSalInt32Type = ::cppu::UnoType<sal_Int32>::get();
+ const Type& rStringType = ::cppu::UnoType<OUString>::get();
+
+ _rPropertyContainer.registerMayBeVoidProperty( PROPERTY_ALIGN, PROPERTY_ID_ALIGN, nMayBeVoidAttr, &m_aAlignment, rSalInt32Type );
+ _rPropertyContainer.registerMayBeVoidProperty( PROPERTY_NUMBERFORMAT, PROPERTY_ID_NUMBERFORMAT, nMayBeVoidAttr, &m_aFormatKey, rSalInt32Type );
+ _rPropertyContainer.registerMayBeVoidProperty( PROPERTY_RELATIVEPOSITION, PROPERTY_ID_RELATIVEPOSITION, nMayBeVoidAttr, &m_aRelativePosition, rSalInt32Type );
+ _rPropertyContainer.registerMayBeVoidProperty( PROPERTY_WIDTH, PROPERTY_ID_WIDTH, nMayBeVoidAttr, &m_aWidth, rSalInt32Type );
+ _rPropertyContainer.registerMayBeVoidProperty( PROPERTY_HELPTEXT, PROPERTY_ID_HELPTEXT, nMayBeVoidAttr, &m_aHelpText, rStringType );
+ _rPropertyContainer.registerMayBeVoidProperty( PROPERTY_CONTROLDEFAULT, PROPERTY_ID_CONTROLDEFAULT, nMayBeVoidAttr, &m_aControlDefault, rStringType );
+ _rPropertyContainer.registerProperty( PROPERTY_CONTROLMODEL, PROPERTY_ID_CONTROLMODEL, nBoundAttr, &m_xControlModel, cppu::UnoType<decltype(m_xControlModel)>::get() );
+ _rPropertyContainer.registerProperty( PROPERTY_HIDDEN, PROPERTY_ID_HIDDEN, nBoundAttr, &m_bHidden, cppu::UnoType<decltype(m_bHidden)>::get() );
+ }
+
+ bool OColumnSettings::isColumnSettingProperty( const sal_Int32 _nPropertyHandle )
+ {
+ return ( _nPropertyHandle == PROPERTY_ID_ALIGN )
+ || ( _nPropertyHandle == PROPERTY_ID_NUMBERFORMAT )
+ || ( _nPropertyHandle == PROPERTY_ID_RELATIVEPOSITION )
+ || ( _nPropertyHandle == PROPERTY_ID_WIDTH )
+ || ( _nPropertyHandle == PROPERTY_ID_HELPTEXT )
+ || ( _nPropertyHandle == PROPERTY_ID_CONTROLDEFAULT )
+ || ( _nPropertyHandle == PROPERTY_ID_CONTROLMODEL )
+ || ( _nPropertyHandle == PROPERTY_ID_HIDDEN );
+ }
+
+ bool OColumnSettings::isDefaulted( const sal_Int32 _nPropertyHandle, const Any& _rPropertyValue )
+ {
+ switch ( _nPropertyHandle )
+ {
+ case PROPERTY_ID_ALIGN:
+ case PROPERTY_ID_NUMBERFORMAT:
+ case PROPERTY_ID_RELATIVEPOSITION:
+ case PROPERTY_ID_WIDTH:
+ case PROPERTY_ID_HELPTEXT:
+ case PROPERTY_ID_CONTROLDEFAULT:
+ return !_rPropertyValue.hasValue();
+
+ case PROPERTY_ID_CONTROLMODEL:
+ return !Reference< XPropertySet >( _rPropertyValue, UNO_QUERY ).is();
+
+ case PROPERTY_ID_HIDDEN:
+ {
+ bool bHidden = false;
+ OSL_VERIFY( _rPropertyValue >>= bHidden );
+ return !bHidden;
+ }
+ }
+ OSL_FAIL( "OColumnSettings::isDefaulted: illegal property handle!" );
+ return false;
+ }
+
+ bool OColumnSettings::hasDefaultSettings( const Reference< XPropertySet >& _rxColumn )
+ {
+ ENSURE_OR_THROW( _rxColumn.is(), "illegal column" );
+ try
+ {
+ Reference< XPropertySetInfo > xPSI( _rxColumn->getPropertySetInfo(), UNO_SET_THROW );
+
+ struct PropertyDescriptor
+ {
+ OUString sName;
+ sal_Int32 nHandle;
+ };
+ const PropertyDescriptor aProps[] =
+ {
+ { OUString(PROPERTY_ALIGN), PROPERTY_ID_ALIGN },
+ { OUString(PROPERTY_NUMBERFORMAT), PROPERTY_ID_NUMBERFORMAT },
+ { OUString(PROPERTY_RELATIVEPOSITION), PROPERTY_ID_RELATIVEPOSITION },
+ { OUString(PROPERTY_WIDTH), PROPERTY_ID_WIDTH },
+ { OUString(PROPERTY_HELPTEXT), PROPERTY_ID_HELPTEXT },
+ { OUString(PROPERTY_CONTROLDEFAULT), PROPERTY_ID_CONTROLDEFAULT },
+ { OUString(PROPERTY_CONTROLMODEL), PROPERTY_ID_CONTROLMODEL },
+ { OUString(PROPERTY_HIDDEN), PROPERTY_ID_HIDDEN }
+ };
+
+ for (const auto & aProp : aProps)
+ {
+ if ( xPSI->hasPropertyByName( aProp.sName ) )
+ if ( !isDefaulted( aProp.nHandle, _rxColumn->getPropertyValue( aProp.sName ) ) )
+ return false;
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ return true;
+ }
+
+} // namespace dbaccess
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/api/datacolumn.cxx b/dbaccess/source/core/api/datacolumn.cxx
new file mode 100644
index 000000000..c597a4064
--- /dev/null
+++ b/dbaccess/source/core/api/datacolumn.cxx
@@ -0,0 +1,396 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "datacolumn.hxx"
+#include <cppuhelper/queryinterface.hxx>
+#include <cppuhelper/typeprovider.hxx>
+#include <strings.hxx>
+
+using namespace dbaccess;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::sdb;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::container;
+using namespace ::osl;
+using namespace ::comphelper;
+using namespace ::cppu;
+
+
+ODataColumn::ODataColumn(
+ const Reference < XResultSetMetaData >& _xMetaData,
+ const Reference < XRow >& _xRow,
+ const Reference < XRowUpdate >& _xRowUpdate,
+ sal_Int32 _nPos,
+ const Reference< XDatabaseMetaData >& _rxDBMeta)
+ :OResultColumn(_xMetaData, _nPos, _rxDBMeta)
+ ,m_xRow(_xRow)
+ ,m_xRowUpdate(_xRowUpdate)
+{
+}
+
+ODataColumn::~ODataColumn()
+{
+}
+
+// css::lang::XTypeProvider
+Sequence< Type > ODataColumn::getTypes()
+{
+ OTypeCollection aTypes(cppu::UnoType<XColumn>::get(),
+ cppu::UnoType<XColumnUpdate>::get(),
+ OColumn::getTypes());
+ return aTypes.getTypes();
+}
+
+Sequence< sal_Int8 > ODataColumn::getImplementationId()
+{
+ return css::uno::Sequence<sal_Int8>();
+}
+
+Any SAL_CALL ODataColumn::queryInterface( const Type & _rType )
+{
+ Any aReturn = OResultColumn::queryInterface(_rType);
+ if (!aReturn.hasValue())
+ aReturn = ::cppu::queryInterface(_rType,
+ static_cast< XColumn* >(this),
+ static_cast< XColumnUpdate* >(this)
+ );
+ return aReturn;
+}
+
+// XServiceInfo
+OUString ODataColumn::getImplementationName( )
+{
+ return "com.sun.star.sdb.ODataColumn";
+}
+
+Sequence< OUString > ODataColumn::getSupportedServiceNames( )
+{
+ return { SERVICE_SDBCX_COLUMN, SERVICE_SDB_RESULTCOLUMN, SERVICE_SDB_DATACOLUMN };
+}
+
+// OComponentHelper
+void ODataColumn::disposing()
+{
+ OResultColumn::disposing();
+
+ m_xRow = nullptr;
+ m_xRowUpdate = nullptr;
+}
+
+// css::sdb::XColumn
+sal_Bool ODataColumn::wasNull()
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(!m_xRow.is());
+
+ return m_xRow->wasNull();
+}
+
+OUString ODataColumn::getString()
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(!m_xRow.is());
+
+ return m_xRow->getString(m_nPos);
+}
+
+sal_Bool ODataColumn::getBoolean()
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(!m_xRow.is());
+
+ return m_xRow->getBoolean(m_nPos);
+}
+
+sal_Int8 ODataColumn::getByte()
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(!m_xRow.is());
+
+ return m_xRow->getByte(m_nPos);
+}
+
+sal_Int16 ODataColumn::getShort()
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(!m_xRow.is());
+
+ return m_xRow->getShort(m_nPos);
+}
+
+sal_Int32 ODataColumn::getInt()
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(!m_xRow.is());
+
+ return m_xRow->getInt(m_nPos);
+}
+
+sal_Int64 ODataColumn::getLong()
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(!m_xRow.is());
+
+ return m_xRow->getLong(m_nPos);
+}
+
+float ODataColumn::getFloat()
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(!m_xRow.is());
+
+ return m_xRow->getFloat(m_nPos);
+}
+
+double ODataColumn::getDouble()
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(!m_xRow.is());
+
+ return m_xRow->getDouble(m_nPos);
+}
+
+Sequence< sal_Int8 > ODataColumn::getBytes()
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(!m_xRow.is());
+
+ return m_xRow->getBytes(m_nPos);
+}
+
+css::util::Date ODataColumn::getDate()
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(!m_xRow.is());
+
+ return m_xRow->getDate(m_nPos);
+}
+
+css::util::Time ODataColumn::getTime()
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(!m_xRow.is());
+
+ return m_xRow->getTime(m_nPos);
+}
+
+css::util::DateTime ODataColumn::getTimestamp()
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(!m_xRow.is());
+
+ return m_xRow->getTimestamp(m_nPos);
+}
+
+Reference< css::io::XInputStream > ODataColumn::getBinaryStream()
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(!m_xRow.is());
+
+ return m_xRow->getBinaryStream(m_nPos);
+}
+
+Reference< css::io::XInputStream > ODataColumn::getCharacterStream()
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(!m_xRow.is());
+
+ return m_xRow->getCharacterStream(m_nPos);
+}
+
+Any ODataColumn::getObject(const Reference< css::container::XNameAccess > & typeMap)
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(!m_xRow.is());
+
+ return m_xRow->getObject(m_nPos, typeMap);
+}
+
+Reference< XRef > ODataColumn::getRef()
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(!m_xRow.is());
+
+ return m_xRow->getRef(m_nPos);
+}
+
+Reference< XBlob > ODataColumn::getBlob()
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(!m_xRow.is());
+
+ return m_xRow->getBlob(m_nPos);
+}
+
+Reference< XClob > ODataColumn::getClob()
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(!m_xRow.is());
+
+ return m_xRow->getClob(m_nPos);
+}
+
+Reference< XArray > ODataColumn::getArray()
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(!m_xRow.is());
+
+ return m_xRow->getArray(m_nPos);
+}
+
+// css::sdb::XColumnUpdate
+void ODataColumn::updateNull()
+{
+ MutexGuard aGuard( m_aMutex );
+ ::connectivity::checkDisposed(!m_xRowUpdate.is());
+
+ m_xRowUpdate->updateNull(m_nPos);
+}
+
+void ODataColumn::updateBoolean(sal_Bool x)
+{
+ MutexGuard aGuard( m_aMutex );
+ ::connectivity::checkDisposed(!m_xRowUpdate.is());
+
+ m_xRowUpdate->updateBoolean(m_nPos, x);
+}
+
+void ODataColumn::updateByte(sal_Int8 x)
+{
+ MutexGuard aGuard( m_aMutex );
+ ::connectivity::checkDisposed(!m_xRowUpdate.is());
+
+ m_xRowUpdate->updateByte(m_nPos, x);
+}
+
+void ODataColumn::updateShort(sal_Int16 x)
+{
+ MutexGuard aGuard( m_aMutex );
+ ::connectivity::checkDisposed(!m_xRowUpdate.is());
+
+ m_xRowUpdate->updateShort(m_nPos, x);
+}
+
+void ODataColumn::updateInt(sal_Int32 x)
+{
+ MutexGuard aGuard( m_aMutex );
+ ::connectivity::checkDisposed(!m_xRowUpdate.is());
+
+ m_xRowUpdate->updateInt(m_nPos, x);
+}
+
+void ODataColumn::updateLong(sal_Int64 x)
+{
+ MutexGuard aGuard( m_aMutex );
+ ::connectivity::checkDisposed(!m_xRowUpdate.is());
+
+ m_xRowUpdate->updateLong(m_nPos, x);
+}
+
+void ODataColumn::updateFloat(float x)
+{
+ MutexGuard aGuard( m_aMutex );
+ ::connectivity::checkDisposed(!m_xRowUpdate.is());
+
+ m_xRowUpdate->updateFloat(m_nPos, x);
+}
+
+void ODataColumn::updateDouble(double x)
+{
+ MutexGuard aGuard( m_aMutex );
+ ::connectivity::checkDisposed(!m_xRowUpdate.is());
+
+ m_xRowUpdate->updateDouble(m_nPos, x);
+}
+
+void ODataColumn::updateString(const OUString& x)
+{
+ MutexGuard aGuard( m_aMutex );
+ ::connectivity::checkDisposed(!m_xRowUpdate.is());
+
+ m_xRowUpdate->updateString(m_nPos, x);
+}
+
+void ODataColumn::updateBytes(const Sequence< sal_Int8 >& x)
+{
+ MutexGuard aGuard( m_aMutex );
+ ::connectivity::checkDisposed(!m_xRowUpdate.is());
+
+ m_xRowUpdate->updateBytes(m_nPos, x);
+}
+
+void ODataColumn::updateDate(const css::util::Date& x)
+{
+ MutexGuard aGuard( m_aMutex );
+ ::connectivity::checkDisposed(!m_xRowUpdate.is());
+
+ m_xRowUpdate->updateDate(m_nPos, x);
+}
+
+void ODataColumn::updateTime(const css::util::Time& x)
+{
+ MutexGuard aGuard( m_aMutex );
+ ::connectivity::checkDisposed(!m_xRowUpdate.is());
+
+ m_xRowUpdate->updateTime(m_nPos, x);
+}
+
+void ODataColumn::updateTimestamp(const css::util::DateTime& x)
+{
+ MutexGuard aGuard( m_aMutex );
+ ::connectivity::checkDisposed(!m_xRowUpdate.is());
+
+ m_xRowUpdate->updateTimestamp(m_nPos, x);
+}
+
+void ODataColumn::updateCharacterStream(const Reference< css::io::XInputStream > & x, sal_Int32 length)
+{
+ MutexGuard aGuard( m_aMutex );
+ ::connectivity::checkDisposed(!m_xRowUpdate.is());
+
+ m_xRowUpdate->updateCharacterStream(m_nPos, x, length);
+}
+
+void ODataColumn::updateBinaryStream(const Reference< css::io::XInputStream > & x, sal_Int32 length)
+{
+ MutexGuard aGuard( m_aMutex );
+ ::connectivity::checkDisposed(!m_xRowUpdate.is());
+
+ m_xRowUpdate->updateBinaryStream(m_nPos, x, length);
+}
+
+void ODataColumn::updateNumericObject(const Any& x, sal_Int32 scale)
+{
+ MutexGuard aGuard( m_aMutex );
+ ::connectivity::checkDisposed(!m_xRowUpdate.is());
+
+ m_xRowUpdate->updateNumericObject(m_nPos, x, scale);
+}
+
+void ODataColumn::updateObject(const Any& x)
+{
+ MutexGuard aGuard( m_aMutex );
+ ::connectivity::checkDisposed(!m_xRowUpdate.is());
+
+ m_xRowUpdate->updateObject(m_nPos, x);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/api/datacolumn.hxx b/dbaccess/source/core/api/datacolumn.hxx
new file mode 100644
index 000000000..46512d945
--- /dev/null
+++ b/dbaccess/source/core/api/datacolumn.hxx
@@ -0,0 +1,107 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <com/sun/star/sdbc/XRowUpdate.hpp>
+#include <com/sun/star/sdbc/XRow.hpp>
+#include <com/sun/star/sdbc/XResultSetMetaData.hpp>
+#include <com/sun/star/sdb/XColumn.hpp>
+#include <com/sun/star/sdb/XColumnUpdate.hpp>
+#include "resultcolumn.hxx"
+namespace dbaccess
+{
+
+ // ODataColumn
+
+ class ODataColumn : public OResultColumn,
+ public css::sdb::XColumn,
+ public css::sdb::XColumnUpdate
+ {
+ css::uno::Reference < css::sdbc::XRow > m_xRow;
+ css::uno::Reference < css::sdbc::XRowUpdate > m_xRowUpdate;
+ protected:
+ virtual ~ODataColumn() override;
+ public:
+ ODataColumn (const css::uno::Reference < css::sdbc::XResultSetMetaData >& _xMetaData,
+ const css::uno::Reference < css::sdbc::XRow >& _xRow,
+ const css::uno::Reference < css::sdbc::XRowUpdate >& _xRowUpdate,
+ sal_Int32 _nPos,
+ const css::uno::Reference< css::sdbc::XDatabaseMetaData >& _rxDBMeta);
+
+ // css::lang::XTypeProvider
+ virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes() override;
+ virtual css::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId() override;
+
+ // css::uno::XInterface
+ virtual css::uno::Any SAL_CALL queryInterface( const css::uno::Type & rType ) override;
+ virtual void SAL_CALL acquire() noexcept override { OResultColumn::acquire(); }
+ virtual void SAL_CALL release() noexcept override { OResultColumn::release(); }
+
+ // css::lang::XServiceInfo
+ virtual OUString SAL_CALL getImplementationName( ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override;
+
+ // cppu::OComponentHelper
+ virtual void SAL_CALL disposing() override;
+
+ // css::sdb::XColumn
+ virtual sal_Bool SAL_CALL wasNull( ) override;
+ virtual OUString SAL_CALL getString( ) override;
+ virtual sal_Bool SAL_CALL getBoolean( ) override;
+ virtual sal_Int8 SAL_CALL getByte( ) override;
+ virtual sal_Int16 SAL_CALL getShort( ) override;
+ virtual sal_Int32 SAL_CALL getInt( ) override;
+ virtual sal_Int64 SAL_CALL getLong( ) override;
+ virtual float SAL_CALL getFloat( ) override;
+ virtual double SAL_CALL getDouble( ) override;
+ virtual css::uno::Sequence< sal_Int8 > SAL_CALL getBytes( ) override;
+ virtual css::util::Date SAL_CALL getDate( ) override;
+ virtual css::util::Time SAL_CALL getTime( ) override;
+ virtual css::util::DateTime SAL_CALL getTimestamp( ) override;
+ virtual css::uno::Reference< css::io::XInputStream > SAL_CALL getBinaryStream( ) override;
+ virtual css::uno::Reference< css::io::XInputStream > SAL_CALL getCharacterStream( ) override;
+ virtual css::uno::Any SAL_CALL getObject( const css::uno::Reference< css::container::XNameAccess >& typeMap ) override;
+ virtual css::uno::Reference< css::sdbc::XRef > SAL_CALL getRef( ) override;
+ virtual css::uno::Reference< css::sdbc::XBlob > SAL_CALL getBlob( ) override;
+ virtual css::uno::Reference< css::sdbc::XClob > SAL_CALL getClob( ) override;
+ virtual css::uno::Reference< css::sdbc::XArray > SAL_CALL getArray( ) override;
+
+ // css::sdb::XColumnUpdate
+ virtual void SAL_CALL updateNull( ) override;
+ virtual void SAL_CALL updateBoolean( sal_Bool x ) override;
+ virtual void SAL_CALL updateByte( sal_Int8 x ) override;
+ virtual void SAL_CALL updateShort( sal_Int16 x ) override;
+ virtual void SAL_CALL updateInt( sal_Int32 x ) override;
+ virtual void SAL_CALL updateLong( sal_Int64 x ) override;
+ virtual void SAL_CALL updateFloat( float x ) override;
+ virtual void SAL_CALL updateDouble( double x ) override;
+ virtual void SAL_CALL updateString( const OUString& x ) override;
+ virtual void SAL_CALL updateBytes( const css::uno::Sequence< sal_Int8 >& x ) override;
+ virtual void SAL_CALL updateDate( const css::util::Date& x ) override;
+ virtual void SAL_CALL updateTime( const css::util::Time& x ) override;
+ virtual void SAL_CALL updateTimestamp( const css::util::DateTime& x ) override;
+ virtual void SAL_CALL updateBinaryStream( const css::uno::Reference< css::io::XInputStream >& x, sal_Int32 length ) override;
+ virtual void SAL_CALL updateCharacterStream( const css::uno::Reference< css::io::XInputStream >& x, sal_Int32 length ) override;
+ virtual void SAL_CALL updateObject( const css::uno::Any& x ) override;
+ virtual void SAL_CALL updateNumericObject( const css::uno::Any& x, sal_Int32 scale ) override;
+ };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/api/datasettings.cxx b/dbaccess/source/core/api/datasettings.cxx
new file mode 100644
index 000000000..e845f1135
--- /dev/null
+++ b/dbaccess/source/core/api/datasettings.cxx
@@ -0,0 +1,191 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <datasettings.hxx>
+#include <stringconstants.hxx>
+#include <strings.hxx>
+#include <comphelper/types.hxx>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/awt/FontEmphasisMark.hpp>
+#include <com/sun/star/awt/FontRelief.hpp>
+
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::awt;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::beans;
+using namespace ::comphelper;
+using namespace ::cppu;
+
+namespace dbaccess
+{
+// ODataSettings
+void ODataSettings::registerPropertiesFor(ODataSettings_Base* _pItem)
+{
+ if ( m_bQuery )
+ {
+ registerProperty(PROPERTY_HAVING_CLAUSE, PROPERTY_ID_HAVING_CLAUSE, PropertyAttribute::BOUND,
+ &_pItem->m_sHavingClause, cppu::UnoType<decltype(_pItem->m_sHavingClause)>::get());
+
+ registerProperty(PROPERTY_GROUP_BY, PROPERTY_ID_GROUP_BY, PropertyAttribute::BOUND,
+ &_pItem->m_sGroupBy, cppu::UnoType<decltype(_pItem->m_sGroupBy)>::get());
+ }
+
+ registerProperty(PROPERTY_FILTER, PROPERTY_ID_FILTER, PropertyAttribute::BOUND,
+ &_pItem->m_sFilter, cppu::UnoType<decltype(_pItem->m_sFilter)>::get());
+
+ registerProperty(PROPERTY_ORDER, PROPERTY_ID_ORDER, PropertyAttribute::BOUND,
+ &_pItem->m_sOrder, cppu::UnoType<decltype(_pItem->m_sOrder)>::get());
+
+ registerProperty(PROPERTY_APPLYFILTER, PROPERTY_ID_APPLYFILTER, PropertyAttribute::BOUND,
+ &_pItem->m_bApplyFilter, cppu::UnoType<bool>::get());
+
+ registerProperty(PROPERTY_FONT, PROPERTY_ID_FONT, PropertyAttribute::BOUND,
+ &_pItem->m_aFont, cppu::UnoType<decltype(_pItem->m_aFont)>::get());
+
+ registerMayBeVoidProperty(PROPERTY_ROW_HEIGHT, PROPERTY_ID_ROW_HEIGHT, PropertyAttribute::BOUND | PropertyAttribute::MAYBEVOID,
+ &_pItem->m_aRowHeight, ::cppu::UnoType<sal_Int32>::get());
+
+ registerProperty(PROPERTY_AUTOGROW, PROPERTY_ID_AUTOGROW, PropertyAttribute::BOUND,
+ &_pItem->m_bAutoGrow, cppu::UnoType<bool>::get());
+
+ registerMayBeVoidProperty(PROPERTY_TEXTCOLOR, PROPERTY_ID_TEXTCOLOR, PropertyAttribute::BOUND | PropertyAttribute::MAYBEVOID,
+ &_pItem->m_aTextColor, ::cppu::UnoType<sal_Int32>::get());
+
+ registerMayBeVoidProperty(PROPERTY_TEXTLINECOLOR, PROPERTY_ID_TEXTLINECOLOR, PropertyAttribute::BOUND | PropertyAttribute::MAYBEVOID,
+ &_pItem->m_aTextLineColor, ::cppu::UnoType<sal_Int32>::get());
+
+ registerProperty(PROPERTY_TEXTEMPHASIS, PROPERTY_ID_TEXTEMPHASIS, PropertyAttribute::BOUND,
+ &_pItem->m_nFontEmphasis, cppu::UnoType<decltype(_pItem->m_nFontEmphasis)>::get());
+
+ registerProperty(PROPERTY_TEXTRELIEF, PROPERTY_ID_TEXTRELIEF, PropertyAttribute::BOUND,&_pItem->m_nFontRelief, cppu::UnoType<decltype(_pItem->m_nFontRelief)>::get());
+
+ registerProperty(PROPERTY_FONTNAME, PROPERTY_ID_FONTNAME, PropertyAttribute::BOUND,&_pItem->m_aFont.Name, cppu::UnoType<decltype(_pItem->m_aFont.Name)>::get());
+ registerProperty(PROPERTY_FONTHEIGHT, PROPERTY_ID_FONTHEIGHT, PropertyAttribute::BOUND,&_pItem->m_aFont.Height, cppu::UnoType<decltype(_pItem->m_aFont.Height)>::get());
+ registerProperty(PROPERTY_FONTWIDTH, PROPERTY_ID_FONTWIDTH, PropertyAttribute::BOUND,&_pItem->m_aFont.Width, cppu::UnoType<decltype(_pItem->m_aFont.Width)>::get());
+ registerProperty(PROPERTY_FONTSTYLENAME, PROPERTY_ID_FONTSTYLENAME, PropertyAttribute::BOUND,&_pItem->m_aFont.StyleName, cppu::UnoType<decltype(_pItem->m_aFont.StyleName)>::get());
+ registerProperty(PROPERTY_FONTFAMILY, PROPERTY_ID_FONTFAMILY, PropertyAttribute::BOUND,&_pItem->m_aFont.Family, cppu::UnoType<decltype(_pItem->m_aFont.Family)>::get());
+ registerProperty(PROPERTY_FONTCHARSET, PROPERTY_ID_FONTCHARSET, PropertyAttribute::BOUND,&_pItem->m_aFont.CharSet, cppu::UnoType<decltype(_pItem->m_aFont.CharSet)>::get());
+ registerProperty(PROPERTY_FONTPITCH, PROPERTY_ID_FONTPITCH, PropertyAttribute::BOUND,&_pItem->m_aFont.Pitch, cppu::UnoType<decltype(_pItem->m_aFont.Pitch)>::get());
+ registerProperty(PROPERTY_FONTCHARWIDTH, PROPERTY_ID_FONTCHARWIDTH, PropertyAttribute::BOUND,&_pItem->m_aFont.CharacterWidth, cppu::UnoType<decltype(_pItem->m_aFont.CharacterWidth)>::get());
+ registerProperty(PROPERTY_FONTWEIGHT, PROPERTY_ID_FONTWEIGHT, PropertyAttribute::BOUND,&_pItem->m_aFont.Weight, cppu::UnoType<decltype(_pItem->m_aFont.Weight)>::get());
+ registerProperty(PROPERTY_FONTSLANT, PROPERTY_ID_FONTSLANT, PropertyAttribute::BOUND,&_pItem->m_aFont.Slant, cppu::UnoType<decltype(_pItem->m_aFont.Slant)>::get());
+ registerProperty(PROPERTY_FONTUNDERLINE, PROPERTY_ID_FONTUNDERLINE, PropertyAttribute::BOUND,&_pItem->m_aFont.Underline, cppu::UnoType<decltype(_pItem->m_aFont.Underline)>::get());
+ registerProperty(PROPERTY_FONTSTRIKEOUT, PROPERTY_ID_FONTSTRIKEOUT, PropertyAttribute::BOUND,&_pItem->m_aFont.Strikeout, cppu::UnoType<decltype(_pItem->m_aFont.Strikeout)>::get());
+ registerProperty(PROPERTY_FONTORIENTATION, PROPERTY_ID_FONTORIENTATION, PropertyAttribute::BOUND,&_pItem->m_aFont.Orientation, cppu::UnoType<decltype(_pItem->m_aFont.Orientation)>::get());
+ registerProperty(PROPERTY_FONTKERNING, PROPERTY_ID_FONTKERNING, PropertyAttribute::BOUND,&_pItem->m_aFont.Kerning, cppu::UnoType<decltype(_pItem->m_aFont.Kerning)>::get());
+ registerProperty(PROPERTY_FONTWORDLINEMODE, PROPERTY_ID_FONTWORDLINEMODE,PropertyAttribute::BOUND,&_pItem->m_aFont.WordLineMode, cppu::UnoType<decltype(_pItem->m_aFont.WordLineMode)>::get());
+ registerProperty(PROPERTY_FONTTYPE, PROPERTY_ID_FONTTYPE, PropertyAttribute::BOUND,&_pItem->m_aFont.Type, cppu::UnoType<decltype(_pItem->m_aFont.Type)>::get());
+}
+
+ODataSettings::ODataSettings(OBroadcastHelper& _rBHelper,bool _bQuery)
+ :OPropertyStateContainer(_rBHelper)
+ ,m_bQuery(_bQuery)
+{
+}
+
+ODataSettings_Base::ODataSettings_Base()
+ :m_bApplyFilter(false)
+ ,m_bAutoGrow(false)
+ ,m_aFont(::comphelper::getDefaultFont())
+ ,m_nFontEmphasis(css::awt::FontEmphasisMark::NONE)
+ ,m_nFontRelief(css::awt::FontRelief::NONE)
+{
+}
+
+ODataSettings_Base::~ODataSettings_Base()
+{
+}
+
+void ODataSettings::getPropertyDefaultByHandle( sal_Int32 _nHandle, Any& _rDefault ) const
+{
+ static css::awt::FontDescriptor aFD = ::comphelper::getDefaultFont();
+ switch( _nHandle )
+ {
+ case PROPERTY_ID_HAVING_CLAUSE:
+ case PROPERTY_ID_GROUP_BY:
+ case PROPERTY_ID_FILTER:
+ case PROPERTY_ID_ORDER:
+ _rDefault <<= OUString();
+ break;
+ case PROPERTY_ID_FONT:
+ _rDefault <<= ::comphelper::getDefaultFont();
+ break;
+ case PROPERTY_ID_APPLYFILTER:
+ _rDefault <<= false;
+ break;
+ case PROPERTY_ID_TEXTRELIEF:
+ _rDefault <<= css::awt::FontRelief::NONE;
+ break;
+ case PROPERTY_ID_TEXTEMPHASIS:
+ _rDefault <<= css::awt::FontEmphasisMark::NONE;
+ break;
+ case PROPERTY_ID_FONTNAME:
+ _rDefault <<= aFD.Name;
+ break;
+ case PROPERTY_ID_FONTHEIGHT:
+ _rDefault <<= aFD.Height;
+ break;
+ case PROPERTY_ID_FONTWIDTH:
+ _rDefault <<= aFD.Width;
+ break;
+ case PROPERTY_ID_FONTSTYLENAME:
+ _rDefault <<= aFD.StyleName;
+ break;
+ case PROPERTY_ID_FONTFAMILY:
+ _rDefault <<= aFD.Family;
+ break;
+ case PROPERTY_ID_FONTCHARSET:
+ _rDefault <<= aFD.CharSet;
+ break;
+ case PROPERTY_ID_FONTPITCH:
+ _rDefault <<= aFD.Pitch;
+ break;
+ case PROPERTY_ID_FONTCHARWIDTH:
+ _rDefault <<= aFD.CharacterWidth;
+ break;
+ case PROPERTY_ID_FONTWEIGHT:
+ _rDefault <<= aFD.Weight;
+ break;
+ case PROPERTY_ID_FONTSLANT:
+ _rDefault <<= aFD.Slant;
+ break;
+ case PROPERTY_ID_FONTUNDERLINE:
+ _rDefault <<= aFD.Underline;
+ break;
+ case PROPERTY_ID_FONTSTRIKEOUT:
+ _rDefault <<= aFD.Strikeout;
+ break;
+ case PROPERTY_ID_FONTORIENTATION:
+ _rDefault <<= aFD.Orientation;
+ break;
+ case PROPERTY_ID_FONTKERNING:
+ _rDefault <<= aFD.Kerning;
+ break;
+ case PROPERTY_ID_FONTWORDLINEMODE:
+ _rDefault <<= aFD.WordLineMode;
+ break;
+ case PROPERTY_ID_FONTTYPE:
+ _rDefault <<= aFD.Type;
+ break;
+ }
+}
+
+} // namespace dbaccess
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/api/definitioncolumn.cxx b/dbaccess/source/core/api/definitioncolumn.cxx
new file mode 100644
index 000000000..3f9542180
--- /dev/null
+++ b/dbaccess/source/core/api/definitioncolumn.cxx
@@ -0,0 +1,610 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <bitset>
+
+#include <stringconstants.hxx>
+#include <strings.hxx>
+#include <definitioncolumn.hxx>
+#include <sdbcoretools.hxx>
+
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/sdbcx/XTablesSupplier.hpp>
+
+#include <comphelper/property.hxx>
+#include <connectivity/dbtools.hxx>
+#include <sal/log.hxx>
+#include <tools/diagnose_ex.h>
+
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::sdbcx;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::container;
+using namespace ::cppu;
+using namespace ::comphelper;
+using namespace ::osl;
+using namespace dbaccess;
+
+namespace
+{
+ const sal_Int32 HAS_DESCRIPTION = 0x00000001;
+ const sal_Int32 HAS_DEFAULTVALUE = 0x00000002;
+ const sal_Int32 HAS_ROWVERSION = 0x00000004;
+ const sal_Int32 HAS_AUTOINCREMENT_CREATION = 0x00000008;
+ const sal_Int32 HAS_CATALOGNAME = 0x00000010;
+ const sal_Int32 HAS_SCHEMANAME = 0x00000020;
+ const sal_Int32 HAS_TABLENAME = 0x00000040;
+}
+
+// OTableColumnDescriptor
+IMPLEMENT_FORWARD_XINTERFACE2(OTableColumnDescriptor,OColumn,TXChild)
+
+void OTableColumnDescriptor::impl_registerProperties()
+{
+ sal_Int32 nDefaultAttr = m_bActAsDescriptor ? 0 : PropertyAttribute::READONLY;
+
+ registerProperty( PROPERTY_TYPENAME, PROPERTY_ID_TYPENAME, nDefaultAttr, &m_aTypeName, cppu::UnoType<decltype(m_aTypeName)>::get() );
+ registerProperty( PROPERTY_DESCRIPTION, PROPERTY_ID_DESCRIPTION, nDefaultAttr, &m_aDescription, cppu::UnoType<decltype(m_aDescription)>::get() );
+ registerProperty( PROPERTY_DEFAULTVALUE, PROPERTY_ID_DEFAULTVALUE, nDefaultAttr, &m_aDefaultValue, cppu::UnoType<decltype(m_aDefaultValue)>::get() );
+
+ if ( m_bActAsDescriptor )
+ registerProperty( PROPERTY_AUTOINCREMENTCREATION, PROPERTY_ID_AUTOINCREMENTCREATION, nDefaultAttr, &m_aAutoIncrementValue, cppu::UnoType<decltype(m_aAutoIncrementValue)>::get() );
+
+ registerProperty( PROPERTY_TYPE, PROPERTY_ID_TYPE, nDefaultAttr, &m_nType, cppu::UnoType<decltype(m_nType)>::get() );
+ registerProperty( PROPERTY_PRECISION, PROPERTY_ID_PRECISION, nDefaultAttr, &m_nPrecision, cppu::UnoType<decltype(m_nPrecision)>::get() );
+ registerProperty( PROPERTY_SCALE, PROPERTY_ID_SCALE, nDefaultAttr, &m_nScale, cppu::UnoType<decltype(m_nScale)>::get() );
+ registerProperty( PROPERTY_ISNULLABLE, PROPERTY_ID_ISNULLABLE, nDefaultAttr, &m_nIsNullable, cppu::UnoType<decltype(m_nIsNullable)>::get() );
+ registerProperty( PROPERTY_ISAUTOINCREMENT, PROPERTY_ID_ISAUTOINCREMENT, nDefaultAttr, &m_bAutoIncrement, cppu::UnoType<decltype(m_bAutoIncrement)>::get() );
+ registerProperty( PROPERTY_ISROWVERSION, PROPERTY_ID_ISROWVERSION, nDefaultAttr, &m_bRowVersion, cppu::UnoType<decltype(m_bRowVersion)>::get() );
+ registerProperty( PROPERTY_ISCURRENCY, PROPERTY_ID_ISCURRENCY, nDefaultAttr, &m_bCurrency, cppu::UnoType<decltype(m_bCurrency)>::get() );
+
+ OColumnSettings::registerProperties( *this );
+}
+
+IMPLEMENT_GET_IMPLEMENTATION_ID( OTableColumnDescriptor )
+
+// css::lang::XServiceInfo
+OUString OTableColumnDescriptor::getImplementationName( )
+{
+ return "com.sun.star.sdb.OTableColumnDescriptor";
+}
+
+Sequence< OUString > OTableColumnDescriptor::getSupportedServiceNames( )
+{
+ return { m_bActAsDescriptor? OUString(SERVICE_SDBCX_COLUMNDESCRIPTOR) : OUString(SERVICE_SDBCX_COLUMN),
+ SERVICE_SDB_COLUMNSETTINGS };
+}
+
+// comphelper::OPropertyArrayUsageHelper
+::cppu::IPropertyArrayHelper* OTableColumnDescriptor::createArrayHelper( ) const
+{
+ Sequence< Property > aProps;
+ describeProperties( aProps );
+ return new ::cppu::OPropertyArrayHelper( aProps );
+}
+
+// cppu::OPropertySetHelper
+::cppu::IPropertyArrayHelper& OTableColumnDescriptor::getInfoHelper()
+{
+ return *static_cast< ::comphelper::OPropertyArrayUsageHelper< OTableColumnDescriptor >* >(this)->getArrayHelper();
+}
+
+void OTableColumnDescriptor::setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const Any& rValue )
+{
+ OColumn::setFastPropertyValue_NoBroadcast( nHandle, rValue );
+ ::dbaccess::notifyDataSourceModified( m_xParent );
+}
+
+Reference< XInterface > SAL_CALL OTableColumnDescriptor::getParent( )
+{
+ ::osl::MutexGuard aGuard(m_aMutex);
+ return m_xParent;
+}
+
+void SAL_CALL OTableColumnDescriptor::setParent( const Reference< XInterface >& _xParent )
+{
+ ::osl::MutexGuard aGuard(m_aMutex);
+ m_xParent = _xParent;
+}
+
+// OTableColumn
+
+OTableColumn::OTableColumn( const OUString& _rName )
+ :OTableColumnDescriptor( false /* do not act as descriptor */ )
+{
+ m_sName = _rName;
+}
+
+OTableColumn::~OTableColumn()
+{
+}
+
+IMPLEMENT_GET_IMPLEMENTATION_ID( OTableColumn )
+
+OUString OTableColumn::getImplementationName( )
+{
+ return "com.sun.star.sdb.OTableColumn";
+}
+
+::cppu::IPropertyArrayHelper& SAL_CALL OTableColumn::getInfoHelper()
+{
+ return *OTableColumn_PBase::getArrayHelper();
+}
+
+::cppu::IPropertyArrayHelper* OTableColumn::createArrayHelper( ) const
+{
+ return OTableColumnDescriptor::createArrayHelper();
+}
+
+// OQueryColumn
+
+OQueryColumn::OQueryColumn( const Reference< XPropertySet >& _rxParserColumn, const Reference< XConnection >& _rxConnection, const OUString &i_sLabel )
+ :OTableColumnDescriptor( false /* do not act as descriptor */ )
+ ,m_sLabel(i_sLabel)
+{
+ const sal_Int32 nPropAttr = PropertyAttribute::READONLY;
+ registerProperty( PROPERTY_CATALOGNAME, PROPERTY_ID_CATALOGNAME, nPropAttr, &m_sCatalogName, cppu::UnoType<decltype(m_sCatalogName)>::get() );
+ registerProperty( PROPERTY_SCHEMANAME, PROPERTY_ID_SCHEMANAME, nPropAttr, &m_sSchemaName, cppu::UnoType<decltype(m_sSchemaName)>::get() );
+ registerProperty( PROPERTY_TABLENAME, PROPERTY_ID_TABLENAME, nPropAttr, &m_sTableName, cppu::UnoType<decltype(m_sTableName)>::get() );
+ registerProperty( PROPERTY_REALNAME, PROPERTY_ID_REALNAME, nPropAttr, &m_sRealName, cppu::UnoType<decltype(m_sRealName)>::get() );
+ registerProperty( PROPERTY_LABEL, PROPERTY_ID_LABEL, nPropAttr, &m_sLabel, cppu::UnoType<decltype(m_sLabel)>::get() );
+
+
+ if( ! (_rxParserColumn->getPropertyValue( PROPERTY_TYPENAME ) >>= m_aTypeName) )
+ SAL_WARN("dbaccess.core", "OQueryColumn: unable to get property " PROPERTY_TYPENAME);
+
+ if( ! (_rxParserColumn->getPropertyValue( PROPERTY_ISNULLABLE ) >>= m_nIsNullable) )
+ SAL_WARN("dbaccess.core", "OQueryColumn: unable to get property " PROPERTY_ISNULLABLE);
+
+ if( ! (_rxParserColumn->getPropertyValue( PROPERTY_PRECISION ) >>= m_nPrecision) )
+ SAL_WARN("dbaccess.core", "OQueryColumn: unable to get property " PROPERTY_PRECISION);
+
+ if( ! (_rxParserColumn->getPropertyValue( PROPERTY_SCALE ) >>= m_nScale) )
+ SAL_WARN("dbaccess.core", "OQueryColumn: unable to get property " PROPERTY_SCALE);
+
+ if( ! (_rxParserColumn->getPropertyValue( PROPERTY_TYPE ) >>= m_nType) )
+ SAL_WARN("dbaccess.core", "OQueryColumn: unable to get property " PROPERTY_TYPE);
+
+ if( ! (_rxParserColumn->getPropertyValue( PROPERTY_ISAUTOINCREMENT ) >>= m_bAutoIncrement) )
+ SAL_WARN("dbaccess.core", "OQueryColumn: unable to get property " PROPERTY_ISAUTOINCREMENT);
+
+ if( ! (_rxParserColumn->getPropertyValue( PROPERTY_ISCURRENCY ) >>= m_bCurrency) )
+ SAL_WARN("dbaccess.core", "OQueryColumn: unable to get property " PROPERTY_ISCURRENCY);
+
+ if( ! (_rxParserColumn->getPropertyValue( PROPERTY_NAME ) >>= m_sName) )
+ SAL_WARN("dbaccess.core", "OQueryColumn: unable to get property " PROPERTY_NAME);
+
+ m_bRowVersion = false;
+
+ Reference< XPropertySetInfo > xPSI( _rxParserColumn->getPropertySetInfo(), UNO_SET_THROW );
+ if ( xPSI->hasPropertyByName( PROPERTY_DEFAULTVALUE ) )
+ if( ! (_rxParserColumn->getPropertyValue( PROPERTY_DEFAULTVALUE ) >>= m_aDefaultValue) )
+ SAL_WARN("dbaccess.core", "OQueryColumn: unable to get property " PROPERTY_DEFAULTVALUE);
+
+ // copy some optional properties from the parser column
+ struct PropertyDescriptor
+ {
+ OUString sName;
+ sal_Int32 nHandle;
+ };
+ const PropertyDescriptor aProps[] =
+ {
+ { OUString(PROPERTY_CATALOGNAME), PROPERTY_ID_CATALOGNAME },
+ { OUString(PROPERTY_SCHEMANAME), PROPERTY_ID_SCHEMANAME },
+ { OUString(PROPERTY_TABLENAME), PROPERTY_ID_TABLENAME },
+ { OUString(PROPERTY_REALNAME), PROPERTY_ID_REALNAME }
+ };
+ for (const auto & aProp : aProps)
+ {
+ if ( xPSI->hasPropertyByName( aProp.sName ) )
+ setFastPropertyValue_NoBroadcast( aProp.nHandle, _rxParserColumn->getPropertyValue( aProp.sName ) );
+ }
+
+ // determine the table column we're based on
+ osl_atomic_increment( &m_refCount );
+ {
+ m_xOriginalTableColumn = impl_determineOriginalTableColumn( _rxConnection );
+ }
+ osl_atomic_decrement( &m_refCount );
+}
+
+OQueryColumn::~OQueryColumn()
+{
+}
+
+Reference< XPropertySet > OQueryColumn::impl_determineOriginalTableColumn( const Reference< XConnection >& _rxConnection )
+{
+ OSL_PRECOND( _rxConnection.is(), "OQueryColumn::impl_determineOriginalTableColumn: illegal connection!" );
+ if ( !_rxConnection.is() )
+ return nullptr;
+
+ Reference< XPropertySet > xOriginalTableColumn;
+ try
+ {
+ // determine the composed table name, plus the column name, as indicated by the
+ // respective properties
+ OUString sCatalog, sSchema, sTable;
+ if( ! (getPropertyValue( PROPERTY_CATALOGNAME ) >>= sCatalog) )
+ SAL_WARN("dbaccess.core", "impl_determineOriginalTableColumn: unable to get property " PROPERTY_CATALOGNAME);
+ if( ! (getPropertyValue( PROPERTY_SCHEMANAME ) >>= sSchema) )
+ SAL_WARN("dbaccess.core", "impl_determineOriginalTableColumn: unable to get property " PROPERTY_SCHEMANAME);
+ if( ! (getPropertyValue( PROPERTY_TABLENAME ) >>= sTable) )
+ SAL_WARN("dbaccess.core", "impl_determineOriginalTableColumn: unable to get property " PROPERTY_TABLENAME);
+ if ( sCatalog.isEmpty() && sSchema.isEmpty() && sTable.isEmpty() )
+ return nullptr;
+
+ OUString sComposedTableName = ::dbtools::composeTableName(
+ _rxConnection->getMetaData(), sCatalog, sSchema, sTable, false, ::dbtools::EComposeRule::Complete );
+
+ // retrieve the table in question
+ Reference< XTablesSupplier > xSuppTables( _rxConnection, UNO_QUERY_THROW );
+ Reference< XNameAccess > xTables( xSuppTables->getTables(), UNO_SET_THROW );
+ if ( !xTables->hasByName( sComposedTableName ) )
+ return nullptr;
+
+ Reference< XColumnsSupplier > xSuppCols( xTables->getByName( sComposedTableName ), UNO_QUERY_THROW );
+ Reference< XNameAccess > xColumns( xSuppCols->getColumns(), UNO_SET_THROW );
+
+ OUString sColumn;
+ if( ! (getPropertyValue( PROPERTY_REALNAME ) >>= sColumn) )
+ SAL_WARN("dbaccess.core", "impl_determineOriginalTableColumn: unable to get property " PROPERTY_REALNAME);
+ if ( !xColumns->hasByName( sColumn ) )
+ return nullptr;
+
+ xOriginalTableColumn.set( xColumns->getByName( sColumn ), UNO_QUERY );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ return xOriginalTableColumn;
+}
+
+IMPLEMENT_GET_IMPLEMENTATION_ID( OQueryColumn )
+
+OUString SAL_CALL OQueryColumn::getImplementationName( )
+{
+ return "org.openoffice.comp.dbaccess.OQueryColumn";
+}
+
+::cppu::IPropertyArrayHelper& SAL_CALL OQueryColumn::getInfoHelper()
+{
+ return *OQueryColumn_PBase::getArrayHelper();
+}
+
+::cppu::IPropertyArrayHelper* OQueryColumn::createArrayHelper() const
+{
+ return OTableColumnDescriptor::createArrayHelper();
+}
+
+void SAL_CALL OQueryColumn::getFastPropertyValue( Any& _rValue, sal_Int32 _nHandle ) const
+{
+ OTableColumnDescriptor::getFastPropertyValue( _rValue, _nHandle );
+
+ // special treatment for column settings:
+ if ( !OColumnSettings::isColumnSettingProperty( _nHandle ) )
+ return;
+
+ // If the setting has its default value, then try to obtain the value from the table column which
+ // this query column is based on
+ if ( !OColumnSettings::isDefaulted( _nHandle, _rValue ) )
+ return;
+
+ if ( !m_xOriginalTableColumn.is() )
+ return;
+
+ try
+ {
+ // determine original property name
+ OUString sPropName;
+ sal_Int16 nAttributes( 0 );
+ const_cast< OQueryColumn* >( this )->getInfoHelper().fillPropertyMembersByHandle( &sPropName, &nAttributes, _nHandle );
+ OSL_ENSURE( !sPropName.isEmpty(), "OColumnWrapper::impl_getPropertyNameFromHandle: property not found!" );
+
+ _rValue = m_xOriginalTableColumn->getPropertyValue( sPropName );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+}
+
+// OColumnWrapper
+
+OColumnWrapper::OColumnWrapper( const Reference< XPropertySet > & rCol, const bool _bNameIsReadOnly )
+ :OColumn( _bNameIsReadOnly )
+ ,m_xAggregate(rCol)
+ ,m_nColTypeID(-1)
+{
+ // which type of aggregate property do we have?
+ // we distinguish the properties by the containment of optional properties
+ m_nColTypeID = 0;
+ if ( !m_xAggregate.is() )
+ return;
+
+ Reference <XPropertySetInfo > xInfo(m_xAggregate->getPropertySetInfo());
+ m_nColTypeID |= xInfo->hasPropertyByName(PROPERTY_DESCRIPTION) ? HAS_DESCRIPTION : 0;
+ m_nColTypeID |= xInfo->hasPropertyByName(PROPERTY_DEFAULTVALUE) ? HAS_DEFAULTVALUE : 0;
+ m_nColTypeID |= xInfo->hasPropertyByName(PROPERTY_ISROWVERSION) ? HAS_ROWVERSION : 0;
+ m_nColTypeID |= xInfo->hasPropertyByName(PROPERTY_AUTOINCREMENTCREATION) ? HAS_AUTOINCREMENT_CREATION : 0;
+ m_nColTypeID |= xInfo->hasPropertyByName(PROPERTY_CATALOGNAME) ? HAS_CATALOGNAME : 0;
+ m_nColTypeID |= xInfo->hasPropertyByName(PROPERTY_SCHEMANAME) ? HAS_SCHEMANAME : 0;
+ m_nColTypeID |= xInfo->hasPropertyByName(PROPERTY_TABLENAME) ? HAS_TABLENAME : 0;
+
+ m_xAggregate->getPropertyValue(PROPERTY_NAME) >>= m_sName;
+}
+
+OColumnWrapper::~OColumnWrapper()
+{
+}
+
+OUString OColumnWrapper::impl_getPropertyNameFromHandle( const sal_Int32 _nHandle ) const
+{
+ OUString sPropName;
+ sal_Int16 nAttributes( 0 );
+ const_cast< OColumnWrapper* >( this )->getInfoHelper().fillPropertyMembersByHandle( &sPropName, &nAttributes, _nHandle );
+ OSL_ENSURE( !sPropName.isEmpty(), "OColumnWrapper::impl_getPropertyNameFromHandle: property not found!" );
+ return sPropName;
+}
+
+void OColumnWrapper::getFastPropertyValue( Any& rValue, sal_Int32 nHandle ) const
+{
+ // derived classes are free to either use the OPropertyContainer(Helper) mechanisms for properties,
+ // or to declare additional properties which are to be forwarded to the wrapped object. So we need
+ // to distinguish those cases.
+ if ( OColumn::isRegisteredProperty( nHandle ) )
+ {
+ OColumn::getFastPropertyValue( rValue, nHandle );
+ }
+ else
+ {
+ rValue = m_xAggregate->getPropertyValue( impl_getPropertyNameFromHandle( nHandle ) );
+ }
+}
+
+sal_Bool OColumnWrapper::convertFastPropertyValue( Any & rConvertedValue, Any & rOldValue, sal_Int32 nHandle,
+ const Any& rValue )
+{
+ bool bModified( false );
+ if ( OColumn::isRegisteredProperty( nHandle ) )
+ {
+ bModified = OColumn::convertFastPropertyValue( rConvertedValue, rOldValue, nHandle, rValue );
+ }
+ else
+ {
+ getFastPropertyValue( rOldValue, nHandle );
+ if ( rOldValue != rValue )
+ {
+ rConvertedValue = rValue;
+ bModified = true;
+ }
+ }
+ return bModified;
+}
+
+void OColumnWrapper::setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const Any& rValue )
+{
+ if ( OColumn::isRegisteredProperty( nHandle ) )
+ {
+ OColumn::setFastPropertyValue_NoBroadcast( nHandle, rValue );
+ }
+ else
+ {
+ m_xAggregate->setPropertyValue( impl_getPropertyNameFromHandle( nHandle ), rValue );
+ }
+}
+
+// OTableColumnDescriptorWrapper
+OTableColumnDescriptorWrapper::OTableColumnDescriptorWrapper( const Reference< XPropertySet >& _rCol, const bool _bPureWrap, const bool _bIsDescriptor )
+ :OColumnWrapper( _rCol, !_bIsDescriptor )
+ ,m_bPureWrap( _bPureWrap )
+ ,m_bIsDescriptor( _bIsDescriptor )
+{
+ // let the ColumnSettings register its properties
+ OColumnSettings::registerProperties( *this );
+}
+
+// css::lang::XTypeProvider
+IMPLEMENT_GET_IMPLEMENTATION_ID( OTableColumnDescriptorWrapper )
+
+// css::lang::XServiceInfo
+OUString OTableColumnDescriptorWrapper::getImplementationName( )
+{
+ return "com.sun.star.sdb.OTableColumnDescriptorWrapper";
+}
+
+Sequence< OUString > OTableColumnDescriptorWrapper::getSupportedServiceNames( )
+{
+ return { SERVICE_SDBCX_COLUMNDESCRIPTOR, SERVICE_SDB_COLUMNSETTINGS };
+}
+
+// comphelper::OPropertyArrayUsageHelper
+::cppu::IPropertyArrayHelper* OTableColumnDescriptorWrapper::createArrayHelper( sal_Int32 nId ) const
+{
+ const sal_Int32 nHaveAlways = 7;
+
+ // Which optional properties are contained?
+ const sal_Int32 nHaveOptionally (std::bitset<7>(nId).count());
+
+ css::uno::Sequence< css::beans::Property> aDescriptor(nHaveAlways + nHaveOptionally);
+ css::beans::Property* pDesc = aDescriptor.getArray();
+ sal_Int32 nPos = 0;
+
+ pDesc[nPos++] = css::beans::Property(PROPERTY_ISAUTOINCREMENT, PROPERTY_ID_ISAUTOINCREMENT, cppu::UnoType<bool>::get(), 0);
+ pDesc[nPos++] = css::beans::Property(PROPERTY_ISCURRENCY, PROPERTY_ID_ISCURRENCY, cppu::UnoType<bool>::get(), 0);
+ pDesc[nPos++] = css::beans::Property(PROPERTY_ISNULLABLE, PROPERTY_ID_ISNULLABLE, cppu::UnoType<sal_Int32>::get(), 0);
+ pDesc[nPos++] = css::beans::Property(PROPERTY_PRECISION, PROPERTY_ID_PRECISION, cppu::UnoType<sal_Int32>::get(), 0);
+ pDesc[nPos++] = css::beans::Property(PROPERTY_SCALE, PROPERTY_ID_SCALE, cppu::UnoType<sal_Int32>::get(), 0);
+ pDesc[nPos++] = css::beans::Property(PROPERTY_TYPE, PROPERTY_ID_TYPE, cppu::UnoType<sal_Int32>::get(), 0);
+ pDesc[nPos++] = css::beans::Property(PROPERTY_TYPENAME, PROPERTY_ID_TYPENAME, cppu::UnoType<OUString >::get(), 0);
+
+ if ( nId & HAS_AUTOINCREMENT_CREATION )
+ {
+ pDesc[nPos++] = css::beans::Property(PROPERTY_AUTOINCREMENTCREATION, PROPERTY_ID_AUTOINCREMENTCREATION, cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::MAYBEVOID );
+ }
+ if ( nId & HAS_DEFAULTVALUE )
+ {
+ pDesc[nPos++] = css::beans::Property(PROPERTY_DEFAULTVALUE, PROPERTY_ID_DEFAULTVALUE, cppu::UnoType<OUString >::get(), 0);
+ }
+ if ( nId & HAS_DESCRIPTION )
+ {
+ pDesc[nPos++] = css::beans::Property(PROPERTY_DESCRIPTION, PROPERTY_ID_DESCRIPTION, cppu::UnoType<OUString >::get(), 0);
+ }
+ if ( nId & HAS_ROWVERSION )
+ {
+ pDesc[nPos++] = css::beans::Property(PROPERTY_ISROWVERSION, PROPERTY_ID_ISROWVERSION, cppu::UnoType<bool>::get(), 0);
+ }
+ if ( nId & HAS_CATALOGNAME )
+ {
+ pDesc[nPos++] = css::beans::Property(PROPERTY_CATALOGNAME, PROPERTY_ID_CATALOGNAME, cppu::UnoType<OUString >::get(), 0);
+ }
+ if ( nId & HAS_SCHEMANAME )
+ {
+ pDesc[nPos++] = css::beans::Property(PROPERTY_SCHEMANAME, PROPERTY_ID_SCHEMANAME, cppu::UnoType<OUString >::get(), 0);
+ }
+ if ( nId & HAS_TABLENAME )
+ {
+ pDesc[nPos++] = css::beans::Property(PROPERTY_TABLENAME, PROPERTY_ID_TABLENAME, cppu::UnoType<OUString >::get(), 0);
+ }
+
+ OSL_ENSURE(nPos == aDescriptor.getLength(), "forgot to adjust the count ?");
+
+ if ( !m_bIsDescriptor )
+ {
+ for ( auto & prop : asNonConstRange(aDescriptor) )
+ {
+ prop.Attributes |= PropertyAttribute::READONLY;
+ }
+ }
+
+ // finally also describe the properties which are maintained by our base class, in particular the OPropertyContainerHelper
+ Sequence< Property > aBaseProperties;
+ describeProperties( aBaseProperties );
+
+ Sequence< Property > aAllProperties( ::comphelper::concatSequences( aDescriptor, aBaseProperties ) );
+ return new ::cppu::OPropertyArrayHelper( aAllProperties, false );
+}
+
+// cppu::OPropertySetHelper
+::cppu::IPropertyArrayHelper& OTableColumnDescriptorWrapper::getInfoHelper()
+{
+ return *static_cast< OIdPropertyArrayUsageHelper< OTableColumnDescriptorWrapper >* >(this)->getArrayHelper(m_nColTypeID);
+}
+
+void OTableColumnDescriptorWrapper::getFastPropertyValue( Any& rValue, sal_Int32 nHandle ) const
+{
+ if ( m_bPureWrap )
+ {
+ rValue = m_xAggregate->getPropertyValue( impl_getPropertyNameFromHandle( nHandle ) );
+ }
+ else
+ {
+ OColumnWrapper::getFastPropertyValue( rValue, nHandle );
+ }
+}
+
+sal_Bool OTableColumnDescriptorWrapper::convertFastPropertyValue( Any & rConvertedValue, Any & rOldValue, sal_Int32 nHandle, const Any& rValue )
+{
+ bool bModified(false);
+ if ( m_bPureWrap )
+ {
+ // do not delegate to OColumnWrapper: It would, for the properties which were registered with registerProperty,
+ // ask the OPropertyContainer base class, which is not what we want here.
+ // TODO: the whole "m_bPureWrap"-thingie is strange. We should have a dedicated class doing this wrapping,
+ // not a class which normally serves other purposes, and only sometimes does a "pure wrap". It makes the
+ // code unnecessarily hard to maintain, and error prone.
+ rOldValue = m_xAggregate->getPropertyValue( impl_getPropertyNameFromHandle( nHandle ) );
+ if ( rOldValue != rValue )
+ {
+ rConvertedValue = rValue;
+ bModified = true;
+ }
+ }
+ else
+ {
+ bModified = OColumnWrapper::convertFastPropertyValue( rConvertedValue, rOldValue, nHandle, rValue );
+ }
+ return bModified;
+}
+
+void OTableColumnDescriptorWrapper::setFastPropertyValue_NoBroadcast(
+ sal_Int32 nHandle,
+ const Any& rValue
+ )
+{
+ if ( m_bPureWrap )
+ {
+ m_xAggregate->setPropertyValue( impl_getPropertyNameFromHandle( nHandle ), rValue );
+ }
+ else
+ {
+ OColumnWrapper::setFastPropertyValue_NoBroadcast( nHandle, rValue );
+ }
+}
+
+// OTableColumnWrapper
+OTableColumnWrapper::OTableColumnWrapper( const Reference< XPropertySet >& rCol, const Reference< XPropertySet >& _xColDefinition,
+ const bool _bPureWrap )
+ :OTableColumnDescriptorWrapper( rCol, _bPureWrap, false )
+{
+ osl_atomic_increment( &m_refCount );
+ if ( _xColDefinition.is() )
+ {
+ try
+ {
+ ::comphelper::copyProperties( _xColDefinition, this );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+ osl_atomic_decrement( &m_refCount );
+}
+
+OTableColumnWrapper::~OTableColumnWrapper()
+{
+}
+
+IMPLEMENT_GET_IMPLEMENTATION_ID( OTableColumnWrapper )
+
+OUString OTableColumnWrapper::getImplementationName( )
+{
+ return "com.sun.star.sdb.OTableColumnWrapper";
+}
+
+Sequence< OUString > OTableColumnWrapper::getSupportedServiceNames( )
+{
+ return { SERVICE_SDBCX_COLUMN, SERVICE_SDB_COLUMNSETTINGS };
+}
+
+::cppu::IPropertyArrayHelper& OTableColumnWrapper::getInfoHelper()
+{
+ return *static_cast< OIdPropertyArrayUsageHelper< OTableColumnWrapper >* >(this)->getArrayHelper(m_nColTypeID);
+}
+
+// comphelper::OPropertyArrayUsageHelper
+::cppu::IPropertyArrayHelper* OTableColumnWrapper::createArrayHelper( sal_Int32 nId ) const
+{
+ return OTableColumnDescriptorWrapper::createArrayHelper( nId );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/api/preparedstatement.cxx b/dbaccess/source/core/api/preparedstatement.cxx
new file mode 100644
index 000000000..02dd32379
--- /dev/null
+++ b/dbaccess/source/core/api/preparedstatement.cxx
@@ -0,0 +1,412 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#include <com/sun/star/lang/DisposedException.hpp>
+#include <com/sun/star/sdbc/XConnection.hpp>
+#include <com/sun/star/sdbc/XDatabaseMetaData.hpp>
+#include <com/sun/star/sdbc/SQLException.hpp>
+
+#include <connectivity/dbtools.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <cppuhelper/queryinterface.hxx>
+#include <cppuhelper/typeprovider.hxx>
+#include <preparedstatement.hxx>
+#include <strings.hxx>
+#include "resultcolumn.hxx"
+#include "resultset.hxx"
+#include <tools/diagnose_ex.h>
+
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::sdbcx;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::cppu;
+using namespace ::osl;
+using namespace dbaccess;
+
+
+OPreparedStatement::OPreparedStatement(const Reference< XConnection > & _xConn,
+ const Reference< XInterface > & _xStatement)
+ :OStatementBase(_xConn, _xStatement)
+{
+ m_xAggregateAsParameters.set( m_xAggregateAsSet, UNO_QUERY_THROW );
+
+ Reference<XDatabaseMetaData> xMeta = _xConn->getMetaData();
+ m_pColumns.reset( new OColumns(*this, m_aMutex, xMeta.is() && xMeta->supportsMixedCaseQuotedIdentifiers(),std::vector< OUString>(), nullptr,nullptr) );
+}
+
+OPreparedStatement::~OPreparedStatement()
+{
+ m_pColumns->acquire();
+ m_pColumns->disposing();
+}
+
+// css::lang::XTypeProvider
+Sequence< Type > OPreparedStatement::getTypes()
+{
+ OTypeCollection aTypes(cppu::UnoType<XServiceInfo>::get(),
+ cppu::UnoType<XPreparedStatement>::get(),
+ cppu::UnoType<XParameters>::get(),
+ cppu::UnoType<XResultSetMetaDataSupplier>::get(),
+ cppu::UnoType<XColumnsSupplier>::get(),
+ OStatementBase::getTypes() );
+
+ return aTypes.getTypes();
+}
+
+Sequence< sal_Int8 > OPreparedStatement::getImplementationId()
+{
+ return css::uno::Sequence<sal_Int8>();
+}
+
+// css::uno::XInterface
+Any OPreparedStatement::queryInterface( const Type & rType )
+{
+ Any aIface = OStatementBase::queryInterface( rType );
+ if (!aIface.hasValue())
+ aIface = ::cppu::queryInterface(
+ rType,
+ static_cast< XServiceInfo * >( this ),
+ static_cast< XParameters * >( this ),
+ static_cast< XColumnsSupplier * >( this ),
+ static_cast< XResultSetMetaDataSupplier * >( this ),
+ static_cast< XPreparedBatchExecution * >( this ),
+ static_cast< XMultipleResults * >( this ),
+ static_cast< XPreparedStatement * >( this ));
+ return aIface;
+}
+
+void OPreparedStatement::acquire() noexcept
+{
+ OStatementBase::acquire();
+}
+
+void OPreparedStatement::release() noexcept
+{
+ OStatementBase::release();
+}
+
+// XServiceInfo
+OUString OPreparedStatement::getImplementationName( )
+{
+ return "com.sun.star.sdb.OPreparedStatement";
+}
+
+sal_Bool OPreparedStatement::supportsService( const OUString& _rServiceName )
+{
+ return cppu::supportsService(this, _rServiceName);
+}
+
+Sequence< OUString > OPreparedStatement::getSupportedServiceNames( )
+{
+ return { SERVICE_SDBC_PREPAREDSTATEMENT, SERVICE_SDB_PREPAREDSTATMENT };
+}
+
+// OComponentHelper
+void OPreparedStatement::disposing()
+{
+ {
+ MutexGuard aGuard(m_aMutex);
+ m_pColumns->disposing();
+ m_xAggregateAsParameters = nullptr;
+ }
+ OStatementBase::disposing();
+}
+
+// css::sdbcx::XColumnsSupplier
+Reference< css::container::XNameAccess > OPreparedStatement::getColumns()
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed);
+
+ // do we have to populate the columns
+ if (!m_pColumns->isInitialized())
+ {
+ try
+ {
+ Reference< XResultSetMetaDataSupplier > xSuppMeta( m_xAggregateAsSet, UNO_QUERY_THROW );
+ Reference< XResultSetMetaData > xMetaData( xSuppMeta->getMetaData(), UNO_SET_THROW );
+
+ Reference< XConnection > xConn( getConnection(), UNO_SET_THROW );
+ Reference< XDatabaseMetaData > xDBMeta( xConn->getMetaData(), UNO_SET_THROW );
+
+ for (sal_Int32 i = 0, nCount = xMetaData->getColumnCount(); i < nCount; ++i)
+ {
+ // retrieve the name of the column
+ OUString aName = xMetaData->getColumnName(i + 1);
+ rtl::Reference<OResultColumn> pColumn = new OResultColumn(xMetaData, i + 1, xDBMeta);
+ // don't silently assume that the name is unique - preparedStatement implementations
+ // are allowed to return duplicate names, but we are required to have
+ // unique column names
+ if ( m_pColumns->hasByName( aName ) )
+ aName = ::dbtools::createUniqueName( m_pColumns.get(), aName );
+
+ m_pColumns->append(aName, pColumn.get());
+ }
+ }
+ catch (const SQLException& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ m_pColumns->setInitialized();
+ }
+ return m_pColumns.get();
+}
+
+// XResultSetMetaDataSupplier
+Reference< XResultSetMetaData > OPreparedStatement::getMetaData()
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed);
+ return Reference< XResultSetMetaDataSupplier >( m_xAggregateAsSet, UNO_QUERY_THROW )->getMetaData();
+}
+
+// XPreparedStatement
+Reference< XResultSet > OPreparedStatement::executeQuery()
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed);
+
+ disposeResultSet();
+
+ Reference< XResultSet > xResultSet;
+ Reference< XResultSet > xDrvResultSet = Reference< XPreparedStatement >( m_xAggregateAsSet, UNO_QUERY_THROW )->executeQuery();
+ if (xDrvResultSet.is())
+ {
+ xResultSet = new OResultSet(xDrvResultSet, *this, m_pColumns->isCaseSensitive());
+
+ // keep the resultset weak
+ m_aResultSet = xResultSet;
+ }
+ return xResultSet;
+}
+
+sal_Int32 OPreparedStatement::executeUpdate()
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed);
+
+ disposeResultSet();
+
+ return Reference< XPreparedStatement >( m_xAggregateAsSet, UNO_QUERY_THROW )->executeUpdate();
+}
+
+sal_Bool OPreparedStatement::execute()
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed);
+
+ disposeResultSet();
+
+ return Reference< XPreparedStatement >( m_xAggregateAsSet, UNO_QUERY_THROW )->execute();
+}
+
+Reference< XConnection > OPreparedStatement::getConnection()
+{
+ return Reference< XConnection > (m_xParent, UNO_QUERY);
+}
+
+// XParameters
+void SAL_CALL OPreparedStatement::setNull( sal_Int32 parameterIndex, sal_Int32 sqlType )
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed);
+
+ m_xAggregateAsParameters->setNull(parameterIndex, sqlType);
+}
+
+void SAL_CALL OPreparedStatement::setObjectNull( sal_Int32 parameterIndex, sal_Int32 sqlType, const OUString& typeName )
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed);
+
+ m_xAggregateAsParameters->setObjectNull(parameterIndex, sqlType, typeName);
+}
+
+void SAL_CALL OPreparedStatement::setBoolean( sal_Int32 parameterIndex, sal_Bool x )
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed);
+
+ m_xAggregateAsParameters->setBoolean(parameterIndex, x);
+}
+
+void SAL_CALL OPreparedStatement::setByte( sal_Int32 parameterIndex, sal_Int8 x )
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed);
+
+ m_xAggregateAsParameters->setByte(parameterIndex, x);
+}
+
+void SAL_CALL OPreparedStatement::setShort( sal_Int32 parameterIndex, sal_Int16 x )
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed);
+
+ m_xAggregateAsParameters->setShort(parameterIndex, x);
+}
+
+void SAL_CALL OPreparedStatement::setInt( sal_Int32 parameterIndex, sal_Int32 x )
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed);
+
+ m_xAggregateAsParameters->setInt(parameterIndex, x);
+}
+
+void SAL_CALL OPreparedStatement::setLong( sal_Int32 parameterIndex, sal_Int64 x )
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed);
+
+ m_xAggregateAsParameters->setLong(parameterIndex, x);
+}
+
+void SAL_CALL OPreparedStatement::setFloat( sal_Int32 parameterIndex, float x )
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed);
+
+ m_xAggregateAsParameters->setFloat(parameterIndex, x);
+}
+
+void SAL_CALL OPreparedStatement::setDouble( sal_Int32 parameterIndex, double x )
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed);
+
+ m_xAggregateAsParameters->setDouble(parameterIndex, x);
+}
+
+void SAL_CALL OPreparedStatement::setString( sal_Int32 parameterIndex, const OUString& x )
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed);
+
+ m_xAggregateAsParameters->setString(parameterIndex, x);
+}
+
+void SAL_CALL OPreparedStatement::setBytes( sal_Int32 parameterIndex, const Sequence< sal_Int8 >& x )
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed);
+
+ m_xAggregateAsParameters->setBytes(parameterIndex, x);
+}
+
+void SAL_CALL OPreparedStatement::setDate( sal_Int32 parameterIndex, const css::util::Date& x )
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed);
+
+ m_xAggregateAsParameters->setDate(parameterIndex, x);
+}
+
+void SAL_CALL OPreparedStatement::setTime( sal_Int32 parameterIndex, const css::util::Time& x )
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed);
+
+ m_xAggregateAsParameters->setTime(parameterIndex, x);
+}
+
+void SAL_CALL OPreparedStatement::setTimestamp( sal_Int32 parameterIndex, const css::util::DateTime& x )
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed);
+
+ m_xAggregateAsParameters->setTimestamp(parameterIndex, x);
+}
+
+void SAL_CALL OPreparedStatement::setBinaryStream( sal_Int32 parameterIndex, const Reference< css::io::XInputStream >& x, sal_Int32 length )
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed);
+
+ m_xAggregateAsParameters->setBinaryStream(parameterIndex, x, length);
+}
+
+void SAL_CALL OPreparedStatement::setCharacterStream( sal_Int32 parameterIndex, const Reference< css::io::XInputStream >& x, sal_Int32 length )
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed);
+
+ m_xAggregateAsParameters->setCharacterStream(parameterIndex, x, length);
+}
+
+void SAL_CALL OPreparedStatement::setObject( sal_Int32 parameterIndex, const Any& x )
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed);
+
+ m_xAggregateAsParameters->setObject(parameterIndex, x);
+}
+
+void SAL_CALL OPreparedStatement::setObjectWithInfo( sal_Int32 parameterIndex, const Any& x, sal_Int32 targetSqlType, sal_Int32 scale )
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed);
+
+ m_xAggregateAsParameters->setObjectWithInfo(parameterIndex, x, targetSqlType, scale);
+}
+
+void SAL_CALL OPreparedStatement::setRef( sal_Int32 parameterIndex, const Reference< XRef >& x )
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed);
+
+ m_xAggregateAsParameters->setRef(parameterIndex, x);
+}
+
+void SAL_CALL OPreparedStatement::setBlob( sal_Int32 parameterIndex, const Reference< XBlob >& x )
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed);
+
+ m_xAggregateAsParameters->setBlob(parameterIndex, x);
+}
+
+void SAL_CALL OPreparedStatement::setClob( sal_Int32 parameterIndex, const Reference< XClob >& x )
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed);
+
+ m_xAggregateAsParameters->setClob(parameterIndex, x);
+}
+
+void SAL_CALL OPreparedStatement::setArray( sal_Int32 parameterIndex, const Reference< XArray >& x )
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed);
+
+ m_xAggregateAsParameters->setArray(parameterIndex, x);
+}
+
+void SAL_CALL OPreparedStatement::clearParameters( )
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed);
+
+ m_xAggregateAsParameters->clearParameters();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/api/query.cxx b/dbaccess/source/core/api/query.cxx
new file mode 100644
index 000000000..33ceca9ce
--- /dev/null
+++ b/dbaccess/source/core/api/query.cxx
@@ -0,0 +1,383 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "query.hxx"
+#include <stringconstants.hxx>
+#include <connectivity/dbexception.hxx>
+#include <connectivity/PColumn.hxx>
+#include <connectivity/warningscontainer.hxx>
+#include "HelperCollections.hxx"
+#include <core_resource.hxx>
+#include <strings.hrc>
+#include <strings.hxx>
+
+#include <tools/diagnose_ex.h>
+#include <osl/diagnose.h>
+
+#include <com/sun/star/sdbc/XConnection.hpp>
+#include <com/sun/star/sdb/XSingleSelectQueryComposer.hpp>
+#include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp>
+#include <com/sun/star/sdb/SQLContext.hpp>
+
+#include <comphelper/property.hxx>
+#include <unotools/sharedunocomponent.hxx>
+#include <definitioncolumn.hxx>
+
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <ContainerMediator.hxx>
+
+using namespace dbaccess;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::sdbcx;
+using namespace ::com::sun::star::sdb;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::util;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::container;
+using namespace ::comphelper;
+using namespace ::osl;
+using namespace ::cppu;
+using namespace ::utl;
+
+namespace dbaccess
+{
+
+// OQuery
+
+OQuery::OQuery( const Reference< XPropertySet >& _rxCommandDefinition
+ ,const Reference< XConnection >& _rxConn
+ ,const Reference< XComponentContext >& _xORB)
+ :OContentHelper(_xORB,nullptr,std::make_shared<OContentHelper_Impl>())
+ ,OQueryDescriptor_Base(m_aMutex,*this)
+ ,ODataSettings(OContentHelper::rBHelper,true)
+ ,m_xCommandDefinition(_rxCommandDefinition)
+ ,m_xConnection(_rxConn)
+ ,m_pWarnings( nullptr )
+ ,m_eDoingCurrently(AggregateAction::NONE)
+{
+ registerProperties();
+ ODataSettings::registerPropertiesFor(this);
+
+ osl_atomic_increment(&m_refCount);
+ OSL_ENSURE(m_xCommandDefinition.is(), "OQuery::OQuery : invalid CommandDefinition object !");
+ if ( m_xCommandDefinition.is() )
+ {
+ try
+ {
+ ::comphelper::copyProperties(_rxCommandDefinition,this);
+ }
+ catch(Exception&)
+ {
+ TOOLS_WARN_EXCEPTION("dbaccess", "OQueryDescriptor_Base::OQueryDescriptor_Base");
+ }
+
+ m_xCommandDefinition->addPropertyChangeListener(OUString(), this);
+ // m_xCommandDefinition->addPropertyChangeListener(PROPERTY_NAME, this);
+ m_xCommandPropInfo = m_xCommandDefinition->getPropertySetInfo();
+ }
+ OSL_ENSURE(m_xConnection.is(), "OQuery::OQuery : invalid connection !");
+ osl_atomic_decrement(&m_refCount);
+}
+
+OQuery::~OQuery()
+{
+}
+
+css::uno::Sequence<sal_Int8> OQuery::getImplementationId()
+{
+ return css::uno::Sequence<sal_Int8>();
+}
+
+css::uno::Sequence< css::uno::Type > OQuery::getTypes()
+{
+ return ::comphelper::concatSequences(
+ OQueryDescriptor_Base::getTypes( ),
+ ODataSettings::getTypes( ),
+ OContentHelper::getTypes( )
+ );
+}
+
+IMPLEMENT_FORWARD_XINTERFACE3( OQuery,OContentHelper,OQueryDescriptor_Base,ODataSettings)
+
+void OQuery::rebuildColumns()
+{
+ OSL_PRECOND( getColumnCount() == 0, "OQuery::rebuildColumns: column container should be empty!" );
+ // the base class' definition of rebuildColumns promised that clearColumns is called before rebuildColumns
+
+ try
+ {
+ m_pColumnMediator = nullptr;
+
+ Reference<XColumnsSupplier> xColSup(m_xCommandDefinition,UNO_QUERY);
+ Reference< XNameAccess > xColumnDefinitions;
+ if ( xColSup.is() )
+ {
+ xColumnDefinitions = xColSup->getColumns();
+ if ( xColumnDefinitions.is() )
+ m_pColumnMediator = new OContainerMediator( m_pColumns.get(), xColumnDefinitions );
+ }
+
+ // fill the columns with columns from the statement
+ Reference< XMultiServiceFactory > xFactory( m_xConnection, UNO_QUERY_THROW );
+ SharedUNOComponent< XSingleSelectQueryComposer, DisposableComponent > xComposer(
+ Reference< XSingleSelectQueryComposer >( xFactory->createInstance( SERVICE_NAME_SINGLESELECTQUERYCOMPOSER ), UNO_QUERY_THROW ) );
+
+ Reference< XNameAccess > xColumns;
+ Reference< XIndexAccess > xColumnsIndexed;
+ try
+ {
+ xComposer->setQuery( m_sCommand );
+ Reference< XColumnsSupplier > xCols( xComposer, UNO_QUERY_THROW );
+ xColumns.set( xCols->getColumns(), UNO_SET_THROW );
+ xColumnsIndexed.set( xColumns, UNO_QUERY_THROW );
+ }
+ catch( const SQLException& ) { }
+
+ SharedUNOComponent< XPreparedStatement, DisposableComponent > xPreparedStatement;
+ if ( !xColumns.is() || ( xColumnsIndexed->getCount() == 0 ) )
+ { // the QueryComposer could not parse it. Try a lean version.
+ xPreparedStatement.set( m_xConnection->prepareStatement( m_sCommand ), UNO_QUERY_THROW );
+ Reference< XResultSetMetaDataSupplier > xResMetaDataSup( xPreparedStatement, UNO_QUERY_THROW );
+ Reference< XResultSetMetaData > xResultSetMeta( xResMetaDataSup->getMetaData() );
+ if ( !xResultSetMeta.is() )
+ {
+ OUString sError( DBA_RES( RID_STR_STATEMENT_WITHOUT_RESULT_SET ) );
+ ::dbtools::throwSQLException( sError, StandardSQLState::GENERAL_ERROR, *this );
+ }
+
+ Reference< XDatabaseMetaData > xDBMeta( m_xConnection->getMetaData(), UNO_SET_THROW );
+ ::rtl::Reference< OSQLColumns > aParseColumns(
+ ::connectivity::parse::OParseColumn::createColumnsForResultSet( xResultSetMeta, xDBMeta,xColumnDefinitions ) );
+ xColumns = OPrivateColumns::createWithIntrinsicNames(
+ aParseColumns, xDBMeta->supportsMixedCaseQuotedIdentifiers(), *this, m_aMutex ).release();
+ if ( !xColumns.is() )
+ throw RuntimeException();
+ }
+
+ const Sequence<OUString> aColNames = xColumns->getElementNames();
+ for ( const OUString& rName : aColNames )
+ {
+ Reference<XPropertySet> xSource(xColumns->getByName( rName ),UNO_QUERY);
+ OUString sLabel = rName;
+ if ( xColumnDefinitions.is() && xColumnDefinitions->hasByName(rName) )
+ {
+ Reference<XPropertySet> xCommandColumn(xColumnDefinitions->getByName( rName ),UNO_QUERY);
+ xCommandColumn->getPropertyValue(PROPERTY_LABEL) >>= sLabel;
+ }
+ rtl::Reference<OQueryColumn> pColumn = new OQueryColumn( xSource, m_xConnection, sLabel);
+ pColumn->setParent( *this );
+
+ implAppendColumn( rName, pColumn.get() );
+ Reference< XPropertySet > xDest( *pColumn, UNO_QUERY_THROW );
+ if ( m_pColumnMediator.is() )
+ m_pColumnMediator->notifyElementCreated( rName, xDest );
+ }
+ }
+ catch( const SQLContext& e )
+ {
+ if ( m_pWarnings )
+ m_pWarnings->appendWarning( e );
+ }
+ catch( const SQLWarning& e )
+ {
+ if ( m_pWarnings )
+ m_pWarnings->appendWarning( e );
+ }
+ catch( const SQLException& e )
+ {
+ if ( m_pWarnings )
+ m_pWarnings->appendWarning( e );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+}
+
+// XServiceInfo
+OUString SAL_CALL OQuery::getImplementationName()
+ {
+ return "com.sun.star.sdb.dbaccess.OQuery";
+ }
+sal_Bool SAL_CALL OQuery::supportsService(const OUString& _rServiceName)
+ {
+ const css::uno::Sequence< OUString > aSupported(getSupportedServiceNames());
+ for (const OUString& s : aSupported)
+ if (s == _rServiceName)
+ return true;
+
+ return false;
+ }
+css::uno::Sequence< OUString > SAL_CALL OQuery::getSupportedServiceNames( )
+{
+ return { SERVICE_SDB_DATASETTINGS, SERVICE_SDB_QUERY, "com.sun.star.sdb.QueryDefinition" };
+}
+
+// css::beans::XPropertyChangeListener
+void SAL_CALL OQuery::propertyChange( const PropertyChangeEvent& _rSource )
+{
+ sal_Int32 nOwnHandle = -1;
+ {
+ MutexGuard aGuard(m_aMutex);
+
+ OSL_ENSURE(_rSource.Source.get() == Reference< XInterface >(m_xCommandDefinition, UNO_QUERY).get(),
+ "OQuery::propertyChange : where did this call come from ?");
+
+ if (m_eDoingCurrently == AggregateAction::SettingProperties)
+ // we're setting the property ourself, so we will do the necessary notifications later
+ return;
+
+ // forward this to our own member holding a copy of the property value
+ if (getArrayHelper()->hasPropertyByName(_rSource.PropertyName))
+ {
+ Property aOwnProp = getArrayHelper()->getPropertyByName(_rSource.PropertyName);
+ nOwnHandle = aOwnProp.Handle;
+ ODataSettings::setFastPropertyValue_NoBroadcast(nOwnHandle, _rSource.NewValue);
+ // don't use our own setFastPropertyValue_NoBroadcast, this would forward it to the CommandSettings,
+ // again
+ // and don't use the "real" setPropertyValue, this is too expensive and not sure to succeed
+ }
+ else
+ {
+ OSL_FAIL("OQuery::propertyChange : my CommandDefinition has more properties than I do !");
+ }
+ }
+
+ fire(&nOwnHandle, &_rSource.NewValue, &_rSource.OldValue, 1, false);
+}
+
+void SAL_CALL OQuery::disposing( const EventObject& _rSource )
+{
+ MutexGuard aGuard(m_aMutex);
+
+ OSL_ENSURE(_rSource.Source.get() == Reference< XInterface >(m_xCommandDefinition, UNO_QUERY).get(),
+ "OQuery::disposing : where did this call come from ?");
+
+ m_xCommandDefinition->removePropertyChangeListener(OUString(), this);
+ m_xCommandDefinition = nullptr;
+}
+
+// XDataDescriptorFactory
+Reference< XPropertySet > SAL_CALL OQuery::createDataDescriptor( )
+{
+ return new OQueryDescriptor(*this);
+}
+
+// pseudo-XComponent
+void SAL_CALL OQuery::disposing()
+{
+ MutexGuard aGuard(m_aMutex);
+ if (m_xCommandDefinition.is())
+ {
+ m_xCommandDefinition->removePropertyChangeListener(OUString(), this);
+ m_xCommandDefinition = nullptr;
+ }
+ disposeColumns();
+
+ m_pWarnings = nullptr;
+}
+
+void OQuery::setFastPropertyValue_NoBroadcast( sal_Int32 _nHandle, const Any& _rValue )
+{
+ ODataSettings::setFastPropertyValue_NoBroadcast(_nHandle, _rValue);
+ OUString sAggPropName;
+ sal_Int16 nAttr = 0;
+ if (getInfoHelper().fillPropertyMembersByHandle(&sAggPropName,&nAttr,_nHandle) &&
+ m_xCommandPropInfo.is() &&
+ m_xCommandPropInfo->hasPropertyByName(sAggPropName))
+ { // the base class holds the property values itself, but we have to forward this to our CommandDefinition
+
+ m_eDoingCurrently = AggregateAction::SettingProperties;
+ OAutoActionReset aAutoReset(*this);
+ m_xCommandDefinition->setPropertyValue(sAggPropName, _rValue);
+
+ if ( PROPERTY_ID_COMMAND == _nHandle )
+ // the columns are out of date if we are based on a new statement...
+ setColumnsOutOfDate();
+ }
+}
+
+Reference< XPropertySetInfo > SAL_CALL OQuery::getPropertySetInfo( )
+{
+ return createPropertySetInfo( getInfoHelper() ) ;
+}
+
+::cppu::IPropertyArrayHelper& OQuery::getInfoHelper()
+{
+ return *getArrayHelper();
+}
+
+::cppu::IPropertyArrayHelper* OQuery::createArrayHelper( ) const
+{
+ Sequence< Property > aProps;
+ // our own props
+ describeProperties(aProps);
+ return new ::cppu::OPropertyArrayHelper(aProps);
+}
+
+rtl::Reference<OColumn> OQuery::createColumn(const OUString& /*_rName*/) const
+{
+ return nullptr;
+}
+
+void SAL_CALL OQuery::rename( const OUString& newName )
+{
+ MutexGuard aGuard(m_aMutex);
+ Reference<XRename> xRename(m_xCommandDefinition,UNO_QUERY);
+ OSL_ENSURE(xRename.is(),"No XRename interface!");
+ if(xRename.is())
+ xRename->rename(newName);
+}
+
+void OQuery::registerProperties()
+{
+ // the properties which OCommandBase supplies (it has no own registration, as it's not derived from
+ // an OPropertyStateContainer)
+ registerProperty(PROPERTY_NAME, PROPERTY_ID_NAME, PropertyAttribute::BOUND|PropertyAttribute::CONSTRAINED,
+ &m_sElementName, cppu::UnoType<decltype(m_sElementName)>::get());
+
+ registerProperty(PROPERTY_COMMAND, PROPERTY_ID_COMMAND, PropertyAttribute::BOUND,
+ &m_sCommand, cppu::UnoType<decltype(m_sCommand)>::get());
+
+ registerProperty(PROPERTY_ESCAPE_PROCESSING, PROPERTY_ID_ESCAPE_PROCESSING, PropertyAttribute::BOUND,
+ &m_bEscapeProcessing, cppu::UnoType<bool>::get());
+
+ registerProperty(PROPERTY_UPDATE_TABLENAME, PROPERTY_ID_UPDATE_TABLENAME, PropertyAttribute::BOUND,
+ &m_sUpdateTableName, cppu::UnoType<decltype(m_sUpdateTableName)>::get());
+
+ registerProperty(PROPERTY_UPDATE_SCHEMANAME, PROPERTY_ID_UPDATE_SCHEMANAME, PropertyAttribute::BOUND,
+ &m_sUpdateSchemaName, cppu::UnoType<decltype(m_sUpdateSchemaName)>::get());
+
+ registerProperty(PROPERTY_UPDATE_CATALOGNAME, PROPERTY_ID_UPDATE_CATALOGNAME, PropertyAttribute::BOUND,
+ &m_sUpdateCatalogName, cppu::UnoType<decltype(m_sUpdateCatalogName)>::get());
+
+ registerProperty(PROPERTY_LAYOUTINFORMATION, PROPERTY_ID_LAYOUTINFORMATION, PropertyAttribute::BOUND,
+ &m_aLayoutInformation, cppu::UnoType<decltype(m_aLayoutInformation)>::get());
+}
+
+OUString OQuery::determineContentType() const
+{
+ return "application/vnd.org.openoffice.DatabaseQuery";
+}
+
+} // namespace dbaccess
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/api/query.hxx b/dbaccess/source/core/api/query.hxx
new file mode 100644
index 000000000..fefcb94b4
--- /dev/null
+++ b/dbaccess/source/core/api/query.hxx
@@ -0,0 +1,147 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include "querydescriptor.hxx"
+#include <cppuhelper/implbase3.hxx>
+#include <rtl/ref.hxx>
+#include <com/sun/star/sdbcx/XDataDescriptorFactory.hpp>
+#include <com/sun/star/beans/XPropertyChangeListener.hpp>
+#include <com/sun/star/sdbc/XConnection.hpp>
+#include <com/sun/star/sdbcx/XRename.hpp>
+#include <ContentHelper.hxx>
+
+#include <map>
+
+namespace dbtools
+{
+ class WarningsContainer;
+}
+
+namespace dbaccess
+{
+
+// OQuery - an object implementing the sdb.Query service
+typedef ::cppu::ImplHelper3 < css::sdbcx::XDataDescriptorFactory,
+ css::beans::XPropertyChangeListener,
+ css::sdbcx::XRename
+ > OQuery_Base;
+class OQuery;
+class OColumn;
+typedef ::comphelper::OPropertyArrayUsageHelper< OQuery > OQuery_ArrayHelperBase;
+
+class OQuery :public OContentHelper
+ ,public OQueryDescriptor_Base
+ ,public OQuery_Base
+ ,public OQuery_ArrayHelperBase
+ ,public ODataSettings
+{
+ friend struct TRelease;
+
+protected:
+ css::uno::Reference< css::beans::XPropertySet > m_xCommandDefinition;
+ css::uno::Reference< css::sdbc::XConnection > m_xConnection;
+ css::uno::Reference< css::beans::XPropertySetInfo > m_xCommandPropInfo;
+ ::rtl::Reference< OContainerMediator > m_pColumnMediator;
+ ::dbtools::WarningsContainer* m_pWarnings;
+
+ // possible actions on our "aggregate"
+ enum class AggregateAction { NONE, SettingProperties };
+ AggregateAction m_eDoingCurrently;
+
+ /** a class which automatically resets m_eDoingCurrently in its destructor
+ */
+ class OAutoActionReset; // just for the following friend declaration
+ friend class OAutoActionReset;
+ class OAutoActionReset
+ {
+ OQuery& m_rActor;
+ public:
+ explicit OAutoActionReset(OQuery& _rActor) : m_rActor(_rActor) { }
+ ~OAutoActionReset() { m_rActor.m_eDoingCurrently = AggregateAction::NONE; }
+ };
+
+protected:
+ virtual ~OQuery() override;
+
+// OPropertyArrayUsageHelper
+ virtual ::cppu::IPropertyArrayHelper* createArrayHelper( ) const override;
+ using OQuery_ArrayHelperBase::getArrayHelper;
+
+public:
+ OQuery(
+ const css::uno::Reference< css::beans::XPropertySet >& _rxCommandDefinition,
+ const css::uno::Reference< css::sdbc::XConnection >& _rxConn,
+ const css::uno::Reference< css::uno::XComponentContext >& _xORB
+ );
+
+ virtual css::uno::Sequence<css::uno::Type> SAL_CALL getTypes() override;
+ virtual css::uno::Sequence<sal_Int8> SAL_CALL getImplementationId() override;
+
+// css::uno::XInterface
+ DECLARE_XINTERFACE( )
+
+// css::beans::XPropertySet
+ virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo( ) override;
+
+// OPropertySetHelper
+ virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper() override;
+
+// css::lang::XServiceInfo
+ DECLARE_SERVICE_INFO();
+
+// css::sdbcx::XDataDescriptorFactory
+ virtual css::uno::Reference< css::beans::XPropertySet > SAL_CALL createDataDescriptor( ) override;
+
+// css::beans::XPropertyChangeListener
+ virtual void SAL_CALL propertyChange( const css::beans::PropertyChangeEvent& evt ) override;
+
+// css::lang::XEventListener
+ virtual void SAL_CALL disposing( const css::lang::EventObject& _rSource ) override;
+
+// OPropertySetHelper
+ virtual void SAL_CALL setFastPropertyValue_NoBroadcast(
+ sal_Int32 nHandle,
+ const css::uno::Any& rValue ) override;
+
+public:
+ // the caller is responsible for the lifetime!
+ void setWarningsContainer( ::dbtools::WarningsContainer* _pWarnings ) { m_pWarnings = _pWarnings; }
+
+ // XRename
+ virtual void SAL_CALL rename( const OUString& newName ) override;
+
+protected:
+ virtual void SAL_CALL disposing() override;
+
+ virtual rtl::Reference<OColumn> createColumn(const OUString& _rName) const override;
+
+ virtual void rebuildColumns( ) override;
+
+ // OContentHelper overridables
+ virtual OUString determineContentType() const override;
+
+private:
+ void registerProperties();
+};
+
+} // namespace dbaccess
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/api/querycomposer.cxx b/dbaccess/source/core/api/querycomposer.cxx
new file mode 100644
index 000000000..8bab87187
--- /dev/null
+++ b/dbaccess/source/core/api/querycomposer.cxx
@@ -0,0 +1,265 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <com/sun/star/lang/DisposedException.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/sdbc/ColumnSearch.hpp>
+#include <com/sun/star/sdbc/XConnection.hpp>
+#include <comphelper/sequence.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <unotools/configmgr.hxx>
+#include <comphelper/types.hxx>
+#include <com/sun/star/sdb/SQLFilterOperator.hpp>
+#include <querycomposer.hxx>
+#include <strings.hxx>
+#include <composertools.hxx>
+#include <algorithm>
+
+using namespace dbaccess;
+using namespace comphelper;
+using namespace connectivity;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::sdb;
+using namespace ::com::sun::star::sdbcx;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::lang;
+using namespace ::cppu;
+using namespace ::osl;
+using namespace ::utl;
+
+
+OQueryComposer::OQueryComposer(const Reference< XConnection>& _xConnection)
+ : OSubComponent(m_aMutex,_xConnection)
+{
+ OSL_ENSURE(_xConnection.is()," Connection can't be null!");
+
+ Reference<XMultiServiceFactory> xFac( _xConnection, UNO_QUERY_THROW );
+ m_xComposer.set( xFac->createInstance( SERVICE_NAME_SINGLESELECTQUERYCOMPOSER ), UNO_QUERY_THROW );
+ m_xComposerHelper.set( xFac->createInstance( SERVICE_NAME_SINGLESELECTQUERYCOMPOSER ), UNO_QUERY_THROW );
+}
+
+OQueryComposer::~OQueryComposer()
+{
+}
+
+void SAL_CALL OQueryComposer::disposing()
+{
+ ::comphelper::disposeComponent(m_xComposerHelper);
+ ::comphelper::disposeComponent(m_xComposer);
+}
+
+// css::lang::XTypeProvider
+Sequence< Type > SAL_CALL OQueryComposer::getTypes()
+{
+ return ::comphelper::concatSequences(OSubComponent::getTypes(),OQueryComposer_BASE::getTypes());
+}
+
+Sequence< sal_Int8 > SAL_CALL OQueryComposer::getImplementationId()
+{
+ return css::uno::Sequence<sal_Int8>();
+}
+
+Any SAL_CALL OQueryComposer::queryInterface( const Type & rType )
+{
+ Any aRet = OSubComponent::queryInterface(rType);
+ if(!aRet.hasValue())
+ aRet = OQueryComposer_BASE::queryInterface(rType);
+ return aRet;
+}
+
+// XServiceInfo
+OUString OQueryComposer::getImplementationName( )
+{
+ return "com.sun.star.sdb.dbaccess.OQueryComposer";
+}
+
+sal_Bool OQueryComposer::supportsService( const OUString& _rServiceName )
+{
+ return cppu::supportsService(this, _rServiceName);
+}
+
+Sequence< OUString > OQueryComposer::getSupportedServiceNames( )
+{
+ return { SERVICE_SDB_SQLQUERYCOMPOSER };
+}
+
+// XSQLQueryComposer
+OUString SAL_CALL OQueryComposer::getQuery( )
+{
+ ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
+
+ ::osl::MutexGuard aGuard( m_aMutex );
+ Reference<XPropertySet> xProp(m_xComposer,UNO_QUERY);
+ OUString sQuery;
+ if ( xProp.is() )
+ xProp->getPropertyValue(PROPERTY_ORIGINAL) >>= sQuery;
+ return sQuery;
+}
+
+void SAL_CALL OQueryComposer::setQuery( const OUString& command )
+{
+ ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
+
+ ::osl::MutexGuard aGuard( m_aMutex );
+ m_aFilters.clear();
+ m_xComposer->setQuery(command);
+ m_sOrgFilter = m_xComposer->getFilter();
+ m_sOrgOrder = m_xComposer->getOrder();
+}
+
+OUString SAL_CALL OQueryComposer::getComposedQuery( )
+{
+ ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
+
+ MutexGuard aGuard(m_aMutex);
+
+ return m_xComposer->getQuery();
+}
+
+OUString SAL_CALL OQueryComposer::getFilter( )
+{
+ ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
+ MutexGuard aGuard(m_aMutex);
+ FilterCreator aFilterCreator;
+ aFilterCreator = std::for_each(m_aFilters.begin(),m_aFilters.end(),aFilterCreator);
+ return aFilterCreator.getComposedAndClear();
+}
+
+Sequence< Sequence< PropertyValue > > SAL_CALL OQueryComposer::getStructuredFilter( )
+{
+ ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
+
+ MutexGuard aGuard(m_aMutex);
+ return m_xComposer->getStructuredFilter();
+}
+
+OUString SAL_CALL OQueryComposer::getOrder( )
+{
+ ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
+
+ ::osl::MutexGuard aGuard( m_aMutex );
+ OrderCreator aOrderCreator;
+ aOrderCreator = std::for_each(m_aOrders.begin(),m_aOrders.end(),aOrderCreator);
+ return aOrderCreator.getComposedAndClear();
+}
+
+void SAL_CALL OQueryComposer::appendFilterByColumn( const Reference< XPropertySet >& column )
+{
+ ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ m_xComposerHelper->setQuery(getQuery());
+ m_xComposerHelper->setFilter(OUString());
+ m_xComposerHelper->appendFilterByColumn(column, true, SQLFilterOperator::EQUAL);
+
+ FilterCreator aFilterCreator;
+ aFilterCreator.append(getFilter());
+ aFilterCreator.append(m_xComposerHelper->getFilter());
+
+ setFilter( aFilterCreator.getComposedAndClear() );
+}
+
+void SAL_CALL OQueryComposer::appendOrderByColumn( const Reference< XPropertySet >& column, sal_Bool ascending )
+{
+ ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ m_xComposerHelper->setQuery(getQuery());
+ m_xComposerHelper->setOrder(OUString());
+ m_xComposerHelper->appendOrderByColumn(column,ascending);
+
+ OrderCreator aOrderCreator;
+ aOrderCreator.append(getOrder());
+ aOrderCreator.append(m_xComposerHelper->getOrder());
+
+ setOrder(aOrderCreator.getComposedAndClear());
+}
+
+void SAL_CALL OQueryComposer::setFilter( const OUString& filter )
+{
+ ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
+
+ ::osl::MutexGuard aGuard( m_aMutex );
+ FilterCreator aFilterCreator;
+ aFilterCreator.append(m_sOrgFilter);
+ aFilterCreator.append(filter);
+
+ m_aFilters.clear();
+ if ( !filter.isEmpty() )
+ m_aFilters.push_back(filter);
+
+ m_xComposer->setFilter( aFilterCreator.getComposedAndClear() );
+}
+
+void SAL_CALL OQueryComposer::setOrder( const OUString& order )
+{
+ ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
+
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ OrderCreator aOrderCreator;
+ aOrderCreator.append(m_sOrgOrder);
+ aOrderCreator.append(order);
+
+ m_aOrders.clear();
+ if ( !order.isEmpty() )
+ m_aOrders.push_back(order);
+
+ m_xComposer->setOrder(aOrderCreator.getComposedAndClear());
+}
+
+// XTablesSupplier
+Reference< XNameAccess > SAL_CALL OQueryComposer::getTables( )
+{
+ ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
+
+ ::osl::MutexGuard aGuard( m_aMutex );
+ return Reference<XTablesSupplier>(m_xComposer,UNO_QUERY_THROW)->getTables();
+}
+
+// XColumnsSupplier
+Reference< XNameAccess > SAL_CALL OQueryComposer::getColumns( )
+{
+ ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
+
+ ::osl::MutexGuard aGuard( m_aMutex );
+ return Reference<XColumnsSupplier>(m_xComposer,UNO_QUERY_THROW)->getColumns();
+}
+
+Reference< XIndexAccess > SAL_CALL OQueryComposer::getParameters( )
+{
+ ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
+
+ ::osl::MutexGuard aGuard( m_aMutex );
+ return Reference<XParametersSupplier>(m_xComposer,UNO_QUERY_THROW)->getParameters();
+}
+
+void SAL_CALL OQueryComposer::acquire() noexcept
+{
+ OSubComponent::acquire();
+}
+
+void SAL_CALL OQueryComposer::release() noexcept
+{
+ OSubComponent::release();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/api/querycontainer.cxx b/dbaccess/source/core/api/querycontainer.cxx
new file mode 100644
index 000000000..583cab373
--- /dev/null
+++ b/dbaccess/source/core/api/querycontainer.cxx
@@ -0,0 +1,430 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <querycontainer.hxx>
+#include "query.hxx"
+#include <strings.hxx>
+#include <objectnameapproval.hxx>
+#include <veto.hxx>
+
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/container/XContainer.hpp>
+#include <com/sun/star/container/XContainerApproveBroadcaster.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
+#include <com/sun/star/sdbc/XConnection.hpp>
+#include <com/sun/star/sdb/QueryDefinition.hpp>
+
+#include <osl/diagnose.h>
+#include <comphelper/uno3.hxx>
+#include <comphelper/property.hxx>
+#include <comphelper/types.hxx>
+#include <cppuhelper/exc_hlp.hxx>
+
+using namespace dbtools;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::ucb;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::sdb;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::sdbcx;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::util;
+using namespace ::osl;
+using namespace ::comphelper;
+using namespace ::cppu;
+
+namespace dbaccess
+{
+
+// OQueryContainer
+
+OQueryContainer::OQueryContainer(
+ const Reference< XNameContainer >& _rxCommandDefinitions
+ , const Reference< XConnection >& _rxConn
+ , const Reference< XComponentContext >& _rxORB,
+ ::dbtools::WarningsContainer* _pWarnings)
+ :ODefinitionContainer(_rxORB,nullptr,std::make_shared<ODefinitionContainer_Impl>())
+ ,m_pWarnings( _pWarnings )
+ ,m_xCommandDefinitions(_rxCommandDefinitions)
+ ,m_xConnection(_rxConn)
+ ,m_eDoingCurrently(AggregateAction::NONE)
+{
+}
+
+void OQueryContainer::init()
+{
+ Reference< XContainer > xContainer( m_xCommandDefinitions, UNO_QUERY_THROW );
+ xContainer->addContainerListener( this );
+
+ Reference< XContainerApproveBroadcaster > xContainerApprove( m_xCommandDefinitions, UNO_QUERY_THROW );
+ xContainerApprove->addContainerApproveListener( this );
+
+ // fill my structures
+ ODefinitionContainer_Impl& rDefinitions( getDefinitions() );
+ Sequence< OUString > sDefinitionNames = m_xCommandDefinitions->getElementNames();
+ const OUString* pDefinitionName = sDefinitionNames.getConstArray();
+ const OUString* pEnd = pDefinitionName + sDefinitionNames.getLength();
+ for ( ; pDefinitionName != pEnd; ++pDefinitionName )
+ {
+ rDefinitions.insert( *pDefinitionName, TContentPtr() );
+ m_aDocuments.push_back(m_aDocumentMap.emplace( *pDefinitionName,Documents::mapped_type()).first);
+ }
+
+ setElementApproval( std::make_shared<ObjectNameApproval>( m_xConnection, ObjectNameApproval::TypeQuery ) );
+}
+
+rtl::Reference<OQueryContainer> OQueryContainer::create(
+ const Reference< XNameContainer >& _rxCommandDefinitions
+ , const Reference< XConnection >& _rxConn
+ , const Reference< XComponentContext >& _rxORB,
+ ::dbtools::WarningsContainer* _pWarnings)
+{
+ rtl::Reference c(
+ new OQueryContainer(
+ _rxCommandDefinitions, _rxConn, _rxORB, _pWarnings));
+ c->init();
+ return c;
+}
+
+OQueryContainer::~OQueryContainer()
+{
+ // dispose();
+ // maybe we're already disposed, but this should be uncritical
+}
+
+IMPLEMENT_FORWARD_XINTERFACE2( OQueryContainer,ODefinitionContainer,OQueryContainer_Base)
+
+IMPLEMENT_FORWARD_XTYPEPROVIDER2( OQueryContainer,ODefinitionContainer,OQueryContainer_Base)
+
+void OQueryContainer::disposing()
+{
+ ODefinitionContainer::disposing();
+ MutexGuard aGuard(m_aMutex);
+ if ( !m_xCommandDefinitions.is() )
+ // already disposed
+ return;
+
+ Reference< XContainer > xContainer( m_xCommandDefinitions, UNO_QUERY );
+ xContainer->removeContainerListener( this );
+ Reference< XContainerApproveBroadcaster > xContainerApprove( m_xCommandDefinitions, UNO_QUERY );
+ xContainerApprove->removeContainerApproveListener( this );
+
+ m_xCommandDefinitions = nullptr;
+ m_xConnection = nullptr;
+}
+
+// XServiceInfo
+OUString SAL_CALL OQueryContainer::getImplementationName()
+ {
+ return "com.sun.star.sdb.dbaccess.OQueryContainer";
+ }
+sal_Bool SAL_CALL OQueryContainer::supportsService(const OUString& _rServiceName)
+ {
+ const css::uno::Sequence< OUString > aSupported(getSupportedServiceNames());
+ for (const OUString& s : aSupported)
+ if (s == _rServiceName)
+ return true;
+
+ return false;
+ }
+css::uno::Sequence< OUString > SAL_CALL OQueryContainer::getSupportedServiceNames()
+{
+ return { SERVICE_SDBCX_CONTAINER, SERVICE_SDB_QUERIES };
+}
+
+// XDataDescriptorFactory
+Reference< XPropertySet > SAL_CALL OQueryContainer::createDataDescriptor( )
+{
+ return new OQueryDescriptor();
+}
+
+// XAppend
+void SAL_CALL OQueryContainer::appendByDescriptor( const Reference< XPropertySet >& _rxDesc )
+{
+ ResettableMutexGuard aGuard(m_aMutex);
+ if ( !m_xCommandDefinitions.is() )
+ throw DisposedException( OUString(), *this );
+
+ // first clone this object's CommandDefinition part
+ Reference< css::sdb::XQueryDefinition > xCommandDefinitionPart = css::sdb::QueryDefinition::create(m_aContext);
+
+ ::comphelper::copyProperties( _rxDesc, Reference<XPropertySet>(xCommandDefinitionPart, UNO_QUERY_THROW) );
+ // TODO : the columns part of the descriptor has to be copied
+
+ // create a wrapper for the object (*before* inserting into our command definition container)
+ Reference< XContent > xNewObject( implCreateWrapper( Reference< XContent>( xCommandDefinitionPart, UNO_QUERY_THROW ) ) );
+
+ OUString sNewObjectName;
+ _rxDesc->getPropertyValue(PROPERTY_NAME) >>= sNewObjectName;
+
+ try
+ {
+ notifyByName( aGuard, sNewObjectName, xNewObject, nullptr, E_INSERTED, ApproveListeners );
+ }
+ catch (const WrappedTargetException& e)
+ {
+ disposeComponent( xNewObject );
+ disposeComponent( xCommandDefinitionPart );
+ throw WrappedTargetRuntimeException(e.Message, e.Context, e.TargetException);
+ }
+ catch (const Exception&)
+ {
+ disposeComponent( xNewObject );
+ disposeComponent( xCommandDefinitionPart );
+ throw;
+ }
+
+ // insert the basic object into the definition container
+ {
+ m_eDoingCurrently = AggregateAction::Inserting;
+ OAutoActionReset aAutoReset(*this);
+ m_xCommandDefinitions->insertByName(sNewObjectName, Any(xCommandDefinitionPart));
+ }
+
+ implAppend( sNewObjectName, xNewObject );
+ try
+ {
+ notifyByName( aGuard, sNewObjectName, xNewObject, nullptr, E_INSERTED, ContainerListemers );
+ }
+ catch (const WrappedTargetException& e)
+ {
+ throw WrappedTargetRuntimeException(e.Message, e.Context, e.TargetException);
+ }
+}
+
+// XDrop
+void SAL_CALL OQueryContainer::dropByName( const OUString& _rName )
+{
+ MutexGuard aGuard(m_aMutex);
+ if ( !checkExistence(_rName) )
+ throw NoSuchElementException(_rName,*this);
+
+ if ( !m_xCommandDefinitions.is() )
+ throw DisposedException( OUString(), *this );
+
+ // now simply forward the remove request to the CommandDefinition container, we're a listener for the removal
+ // and thus we do everything necessary in ::elementRemoved
+ m_xCommandDefinitions->removeByName(_rName);
+}
+
+void SAL_CALL OQueryContainer::dropByIndex( sal_Int32 _nIndex )
+{
+ MutexGuard aGuard(m_aMutex);
+ if ((_nIndex<0) || (_nIndex>getCount()))
+ throw IndexOutOfBoundsException();
+
+ if ( !m_xCommandDefinitions.is() )
+ throw DisposedException( OUString(), *this );
+
+ OUString sName;
+ Reference<XPropertySet> xProp(Reference<XIndexAccess>(m_xCommandDefinitions,UNO_QUERY_THROW)->getByIndex(_nIndex),UNO_QUERY);
+ if ( xProp.is() )
+ xProp->getPropertyValue(PROPERTY_NAME) >>= sName;
+
+ dropByName(sName);
+}
+
+void SAL_CALL OQueryContainer::elementInserted( const css::container::ContainerEvent& _rEvent )
+{
+ Reference< XContent > xNewElement;
+ OUString sElementName;
+ _rEvent.Accessor >>= sElementName;
+ {
+ MutexGuard aGuard(m_aMutex);
+ if (AggregateAction::Inserting == m_eDoingCurrently)
+ // nothing to do, we're inserting via an "appendByDescriptor"
+ return;
+
+ OSL_ENSURE(!sElementName.isEmpty(), "OQueryContainer::elementInserted : invalid name !");
+ OSL_ENSURE(m_aDocumentMap.find(sElementName) == m_aDocumentMap.end(), "OQueryContainer::elementInserted : oops... we're inconsistent with our master container !");
+ if (sElementName.isEmpty() || hasByName(sElementName))
+ return;
+
+ // insert an own new element
+ xNewElement = implCreateWrapper(sElementName);
+ }
+ insertByName(sElementName,Any(xNewElement));
+}
+
+void SAL_CALL OQueryContainer::elementRemoved( const css::container::ContainerEvent& _rEvent )
+{
+ OUString sAccessor;
+ _rEvent.Accessor >>= sAccessor;
+ {
+ OSL_ENSURE(!sAccessor.isEmpty(), "OQueryContainer::elementRemoved : invalid name !");
+ OSL_ENSURE(m_aDocumentMap.find(sAccessor) != m_aDocumentMap.end(), "OQueryContainer::elementRemoved : oops... we're inconsistent with our master container !");
+ if ( sAccessor.isEmpty() || !hasByName(sAccessor) )
+ return;
+ }
+ removeByName(sAccessor);
+}
+
+void SAL_CALL OQueryContainer::elementReplaced( const css::container::ContainerEvent& _rEvent )
+{
+ Reference< XContent > xNewElement;
+ OUString sAccessor;
+ _rEvent.Accessor >>= sAccessor;
+
+ {
+ MutexGuard aGuard(m_aMutex);
+ OSL_ENSURE(!sAccessor.isEmpty(), "OQueryContainer::elementReplaced : invalid name !");
+ OSL_ENSURE(m_aDocumentMap.find(sAccessor) != m_aDocumentMap.end(), "OQueryContainer::elementReplaced : oops... we're inconsistent with our master container !");
+ if (sAccessor.isEmpty() || !hasByName(sAccessor))
+ return;
+
+ xNewElement = implCreateWrapper(sAccessor);
+ }
+
+ replaceByName(sAccessor,Any(xNewElement));
+}
+
+Reference< XVeto > SAL_CALL OQueryContainer::approveInsertElement( const ContainerEvent& Event )
+{
+ OUString sName;
+ OSL_VERIFY( Event.Accessor >>= sName );
+ Reference< XContent > xElement( Event.Element, UNO_QUERY_THROW );
+
+ Reference< XVeto > xReturn;
+ try
+ {
+ getElementApproval()->approveElement( sName );
+ }
+ catch( const Exception& )
+ {
+ xReturn = new Veto( ::cppu::getCaughtException() );
+ }
+ return xReturn;
+}
+
+Reference< XVeto > SAL_CALL OQueryContainer::approveReplaceElement( const ContainerEvent& /*Event*/ )
+{
+ return nullptr;
+}
+
+Reference< XVeto > SAL_CALL OQueryContainer::approveRemoveElement( const ContainerEvent& /*Event*/ )
+{
+ return nullptr;
+}
+
+void SAL_CALL OQueryContainer::disposing( const css::lang::EventObject& _rSource )
+{
+ if (_rSource.Source.get() == Reference< XInterface >(m_xCommandDefinitions, UNO_QUERY).get())
+ { // our "master container" (with the command definitions) is being disposed
+ OSL_FAIL("OQueryContainer::disposing : nobody should dispose the CommandDefinition container before disposing my connection !");
+ dispose();
+ }
+ else
+ {
+ Reference< XContent > xSource(_rSource.Source, UNO_QUERY);
+ // it's one of our documents...
+ for (auto const& document : m_aDocumentMap)
+ {
+ if ( xSource == document.second.get() )
+ {
+ m_xCommandDefinitions->removeByName(document.first);
+ break;
+ }
+ }
+ ODefinitionContainer::disposing(_rSource);
+ }
+}
+
+OUString OQueryContainer::determineContentType() const
+{
+ return "application/vnd.org.openoffice.DatabaseQueryContainer";
+}
+
+Reference< XContent > OQueryContainer::implCreateWrapper(const OUString& _rName)
+{
+ Reference< XContent > xObject(m_xCommandDefinitions->getByName(_rName),UNO_QUERY);
+ return implCreateWrapper(xObject);
+}
+
+Reference< XContent > OQueryContainer::implCreateWrapper(const Reference< XContent >& _rxCommandDesc)
+{
+ Reference<XNameContainer> xContainer(_rxCommandDesc,UNO_QUERY);
+ Reference< XContent > xReturn;
+ if ( xContainer .is() )
+ {
+ xReturn = create( xContainer, m_xConnection, m_aContext, m_pWarnings ).
+ get();
+ }
+ else
+ {
+ rtl::Reference<OQuery> pNewObject = new OQuery( Reference< XPropertySet >( _rxCommandDesc, UNO_QUERY ), m_xConnection, m_aContext );
+ xReturn = pNewObject;
+
+ pNewObject->setWarningsContainer( m_pWarnings );
+// pNewObject->getColumns();
+ // Why? This is expensive. If you comment this in 'cause you really need it, be sure to run the
+ // QueryInQuery test in dbaccess/qa/complex/dbaccess ...
+ }
+
+ return xReturn;
+}
+
+Reference< XContent > OQueryContainer::createObject( const OUString& _rName)
+{
+ return implCreateWrapper(_rName);
+}
+
+bool OQueryContainer::checkExistence(const OUString& _rName)
+{
+ bool bRet = false;
+ if ( !m_bInPropertyChange )
+ {
+ bRet = m_xCommandDefinitions->hasByName(_rName);
+ Documents::const_iterator aFind = m_aDocumentMap.find(_rName);
+ if ( !bRet && aFind != m_aDocumentMap.end() )
+ {
+ m_aDocuments.erase( std::find(m_aDocuments.begin(),m_aDocuments.end(),aFind));
+ m_aDocumentMap.erase(aFind);
+ }
+ else if ( bRet && aFind == m_aDocumentMap.end() )
+ {
+ implAppend(_rName,nullptr);
+ }
+ }
+ return bRet;
+}
+
+sal_Bool SAL_CALL OQueryContainer::hasElements( )
+{
+ MutexGuard aGuard(m_aMutex);
+ return m_xCommandDefinitions->hasElements();
+}
+
+sal_Int32 SAL_CALL OQueryContainer::getCount( )
+{
+ MutexGuard aGuard(m_aMutex);
+ return Reference<XIndexAccess>(m_xCommandDefinitions,UNO_QUERY_THROW)->getCount();
+}
+
+Sequence< OUString > SAL_CALL OQueryContainer::getElementNames( )
+{
+ MutexGuard aGuard(m_aMutex);
+
+ return m_xCommandDefinitions->getElementNames();
+}
+
+} // namespace dbaccess
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/api/querydescriptor.cxx b/dbaccess/source/core/api/querydescriptor.cxx
new file mode 100644
index 000000000..0ac6d76e3
--- /dev/null
+++ b/dbaccess/source/core/api/querydescriptor.cxx
@@ -0,0 +1,269 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "querydescriptor.hxx"
+#include <stringconstants.hxx>
+#include <strings.hxx>
+#include <comphelper/servicehelper.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::awt;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::util;
+using namespace ::osl;
+using namespace ::cppu;
+
+namespace dbaccess
+{
+
+// OQueryDescriptor
+
+OQueryDescriptor::OQueryDescriptor()
+ :OQueryDescriptor_Base(m_aMutex,*this)
+ ,ODataSettings(m_aBHelper,true)
+{
+ registerProperties();
+ ODataSettings::registerPropertiesFor(this);
+}
+
+OQueryDescriptor::OQueryDescriptor(const OQueryDescriptor_Base& _rSource)
+ :OQueryDescriptor_Base(_rSource,*this)
+ ,ODataSettings(m_aBHelper,true)
+{
+ registerProperties();
+ ODataSettings::registerPropertiesFor(this);
+}
+
+OQueryDescriptor::~OQueryDescriptor()
+{
+}
+
+css::uno::Sequence<sal_Int8> OQueryDescriptor::getImplementationId()
+{
+ return css::uno::Sequence<sal_Int8>();
+}
+
+css::uno::Sequence< css::uno::Type > OQueryDescriptor::getTypes()
+{
+ return ::comphelper::concatSequences(
+ OQueryDescriptor_Base::getTypes( ),
+ ODataSettings::getTypes( )
+ );
+}
+
+IMPLEMENT_FORWARD_XINTERFACE3( OQueryDescriptor,OWeakObject,OQueryDescriptor_Base,ODataSettings)
+
+void OQueryDescriptor::registerProperties()
+{
+ // the properties which OCommandBase supplies (it has no own registration, as it's not derived from
+ // an OPropertyStateContainer)
+ registerProperty(PROPERTY_NAME, PROPERTY_ID_NAME, PropertyAttribute::BOUND|PropertyAttribute::CONSTRAINED,
+ &m_sElementName, cppu::UnoType<decltype(m_sElementName)>::get());
+
+ registerProperty(PROPERTY_COMMAND, PROPERTY_ID_COMMAND, PropertyAttribute::BOUND,
+ &m_sCommand, cppu::UnoType<decltype(m_sCommand)>::get());
+
+ registerProperty(PROPERTY_ESCAPE_PROCESSING, PROPERTY_ID_ESCAPE_PROCESSING, PropertyAttribute::BOUND,
+ &m_bEscapeProcessing, cppu::UnoType<bool>::get());
+
+ registerProperty(PROPERTY_UPDATE_TABLENAME, PROPERTY_ID_UPDATE_TABLENAME, PropertyAttribute::BOUND,
+ &m_sUpdateTableName, cppu::UnoType<decltype(m_sUpdateTableName)>::get());
+
+ registerProperty(PROPERTY_UPDATE_SCHEMANAME, PROPERTY_ID_UPDATE_SCHEMANAME, PropertyAttribute::BOUND,
+ &m_sUpdateSchemaName, cppu::UnoType<decltype(m_sUpdateSchemaName)>::get());
+
+ registerProperty(PROPERTY_UPDATE_CATALOGNAME, PROPERTY_ID_UPDATE_CATALOGNAME, PropertyAttribute::BOUND,
+ &m_sUpdateCatalogName, cppu::UnoType<decltype(m_sUpdateCatalogName)>::get());
+
+ registerProperty(PROPERTY_LAYOUTINFORMATION, PROPERTY_ID_LAYOUTINFORMATION, PropertyAttribute::BOUND,
+ &m_aLayoutInformation, cppu::UnoType<decltype(m_aLayoutInformation)>::get());
+}
+
+Reference< XPropertySetInfo > SAL_CALL OQueryDescriptor::getPropertySetInfo( )
+{
+ return createPropertySetInfo( getInfoHelper() ) ;
+}
+
+::cppu::IPropertyArrayHelper& OQueryDescriptor::getInfoHelper()
+{
+ return *getArrayHelper();
+}
+
+::cppu::IPropertyArrayHelper* OQueryDescriptor::createArrayHelper( ) const
+{
+ Sequence< Property > aProps;
+ describeProperties(aProps);
+ return new ::cppu::OPropertyArrayHelper(aProps);
+}
+
+
+OQueryDescriptor_Base::OQueryDescriptor_Base(::osl::Mutex& _rMutex,::cppu::OWeakObject& _rMySelf)
+ :m_bColumnsOutOfDate(true)
+ ,m_rMutex(_rMutex)
+{
+ m_pColumns.reset( new OColumns(_rMySelf, m_rMutex, true,std::vector< OUString>(), this,this) );
+}
+
+OQueryDescriptor_Base::OQueryDescriptor_Base(const OQueryDescriptor_Base& _rSource,::cppu::OWeakObject& _rMySelf)
+ :m_bColumnsOutOfDate(true)
+ ,m_rMutex(_rSource.m_rMutex)
+{
+ m_pColumns.reset( new OColumns(_rMySelf, m_rMutex, true,std::vector< OUString>(), this,this) );
+
+ m_sCommand = _rSource.m_sCommand;
+ m_bEscapeProcessing = _rSource.m_bEscapeProcessing;
+ m_sUpdateTableName = _rSource.m_sUpdateTableName;
+ m_sUpdateSchemaName = _rSource.m_sUpdateSchemaName;
+ m_sUpdateCatalogName = _rSource.m_sUpdateCatalogName;
+ m_aLayoutInformation = _rSource.m_aLayoutInformation;
+}
+
+OQueryDescriptor_Base::~OQueryDescriptor_Base()
+{
+ m_pColumns->acquire();
+ m_pColumns->disposing();
+}
+
+sal_Int64 SAL_CALL OQueryDescriptor_Base::getSomething( const Sequence< sal_Int8 >& _rIdentifier )
+{
+ return comphelper::getSomethingImpl(_rIdentifier, this);
+}
+
+const css::uno::Sequence<sal_Int8> & OQueryDescriptor_Base::getUnoTunnelId()
+{
+ static const comphelper::UnoIdInit aId;
+ return aId.getSeq();
+}
+
+css::uno::Sequence<sal_Int8> OQueryDescriptor_Base::getImplementationId()
+{
+ return css::uno::Sequence<sal_Int8>();
+}
+
+void OQueryDescriptor_Base::setColumnsOutOfDate( bool _bOutOfDate )
+{
+ m_bColumnsOutOfDate = _bOutOfDate;
+ if ( !m_bColumnsOutOfDate )
+ m_pColumns->setInitialized();
+}
+
+void OQueryDescriptor_Base::implAppendColumn( const OUString& _rName, OColumn* _pColumn )
+{
+ m_pColumns->append( _rName, _pColumn );
+}
+
+void OQueryDescriptor_Base::clearColumns( )
+{
+ m_pColumns->clearColumns();
+
+ setColumnsOutOfDate();
+}
+
+Reference< XNameAccess > SAL_CALL OQueryDescriptor_Base::getColumns( )
+{
+ MutexGuard aGuard(m_rMutex);
+
+ if ( m_bColumnsOutOfDate )
+ {
+ // clear the current columns
+ clearColumns();
+
+ // do this before rebuildColumns. This prevents recursion, e.g. in the case where we
+ // have queries with cyclic references:
+ // foo := SELECT * FROM bar
+ // bar := SELECT * FROM foo
+ setColumnsOutOfDate( false );
+
+ // rebuild them
+ try
+ {
+ rebuildColumns();
+ }
+ catch ( const Exception& )
+ {
+ setColumnsOutOfDate();
+ throw;
+ }
+ }
+
+ return m_pColumns.get();
+}
+
+OUString SAL_CALL OQueryDescriptor_Base::getImplementationName( )
+{
+ return "com.sun.star.sdb.OQueryDescriptor";
+}
+
+sal_Bool SAL_CALL OQueryDescriptor_Base::supportsService( const OUString& _rServiceName )
+{
+ return cppu::supportsService(this, _rServiceName);
+}
+
+Sequence< OUString > SAL_CALL OQueryDescriptor_Base::getSupportedServiceNames( )
+{
+ return { SERVICE_SDB_DATASETTINGS, SERVICE_SDB_QUERYDESCRIPTOR };
+}
+
+void OQueryDescriptor_Base::disposeColumns()
+{
+ m_pColumns->disposing();
+}
+
+void OQueryDescriptor_Base::columnAppended( const Reference< XPropertySet >& /*_rxSourceDescriptor*/ )
+{
+ // not interested in
+}
+
+void OQueryDescriptor_Base::columnDropped(const OUString& /*_sName*/)
+{
+ // not interested in
+}
+
+Reference< XPropertySet > OQueryDescriptor_Base::createColumnDescriptor()
+{
+ OSL_FAIL( "OQueryDescriptor_Base::createColumnDescriptor: called why?" );
+ return nullptr;
+}
+
+void OQueryDescriptor_Base::rebuildColumns( )
+{
+}
+
+// IRefreshableColumns
+void OQueryDescriptor_Base::refreshColumns()
+{
+ MutexGuard aGuard( m_rMutex );
+
+ clearColumns();
+ rebuildColumns();
+}
+
+rtl::Reference<OColumn> OQueryDescriptor_Base::createColumn( const OUString& /*_rName*/ ) const
+{
+ // creating a column/descriptor for a query/descriptor does not make sense at all
+ return nullptr;
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/api/querydescriptor.hxx b/dbaccess/source/core/api/querydescriptor.hxx
new file mode 100644
index 000000000..e78b035da
--- /dev/null
+++ b/dbaccess/source/core/api/querydescriptor.hxx
@@ -0,0 +1,143 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <cppuhelper/implbase3.hxx>
+#include <comphelper/proparrhlp.hxx>
+#include <osl/mutex.hxx>
+
+#include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/lang/XUnoTunnel.hpp>
+
+#include <apitools.hxx>
+#include <column.hxx>
+#include <datasettings.hxx>
+#include <commandbase.hxx>
+#include <comphelper/broadcasthelper.hxx>
+#include <comphelper/uno3.hxx>
+
+namespace dbaccess
+{
+
+// OQueryDescriptor_Base - a query descriptor (as the name suggests :)
+typedef ::cppu::ImplHelper3<
+ css::sdbcx::XColumnsSupplier,
+ css::lang::XUnoTunnel,
+ css::lang::XServiceInfo > OQueryDescriptor_BASE;
+
+class OQueryDescriptor_Base
+ :public OQueryDescriptor_BASE
+ ,public OCommandBase
+ ,public IColumnFactory
+ ,public ::connectivity::sdbcx::IRefreshableColumns
+{
+private:
+ bool m_bColumnsOutOfDate : 1; // the columns have to be rebuild on the next getColumns ?
+ ::osl::Mutex& m_rMutex;
+
+protected:
+ std::unique_ptr<OColumns> m_pColumns; // our column descriptions
+ OUString m_sElementName;
+ virtual ~OQueryDescriptor_Base();
+
+ void setColumnsOutOfDate( bool _bOutOfDate = true );
+
+ sal_Int32 getColumnCount() const { return m_pColumns ? m_pColumns->getCount() : 0; }
+ void clearColumns( );
+
+ void implAppendColumn( const OUString& _rName, OColumn* _pColumn );
+
+public:
+ OQueryDescriptor_Base(::osl::Mutex& _rMutex,::cppu::OWeakObject& _rMySelf);
+ /** constructs the object with a UNO QueryDescriptor. If you use this ctor, the resulting object
+ won't have any column information (the column container will be empty)
+ */
+ OQueryDescriptor_Base(const OQueryDescriptor_Base& _rSource,::cppu::OWeakObject& _rMySelf);
+
+// css::sdbcx::XColumnsSupplier
+ virtual css::uno::Reference< css::container::XNameAccess > SAL_CALL getColumns( ) override;
+
+// css::lang::XUnoTunnel
+ virtual sal_Int64 SAL_CALL getSomething( const css::uno::Sequence< sal_Int8 >& aIdentifier ) override;
+ virtual css::uno::Sequence<sal_Int8> SAL_CALL getImplementationId( ) override;
+ static const css::uno::Sequence< sal_Int8 > & getUnoTunnelId();
+
+
+// css::lang::XServiceInfo
+ virtual OUString SAL_CALL getImplementationName( ) override;
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override;
+
+protected:
+
+// IColumnFactory
+ virtual rtl::Reference<OColumn> createColumn(const OUString& _rName) const override;
+ virtual css::uno::Reference< css::beans::XPropertySet > createColumnDescriptor() override;
+ virtual void columnAppended( const css::uno::Reference< css::beans::XPropertySet >& _rxSourceDescriptor ) override;
+ virtual void columnDropped(const OUString& _sName) override;
+
+ /** rebuild our columns set
+
+ clearColumns has already been called before, do <em>NOT</em> call it, again
+ */
+ virtual void rebuildColumns( );
+
+ void disposeColumns();
+
+ // IRefreshableColumns overridables
+ virtual void refreshColumns() override;
+};
+
+class OQueryDescriptor : public comphelper::OMutexAndBroadcastHelper
+ ,public ::cppu::OWeakObject
+ ,public OQueryDescriptor_Base
+ ,public ::comphelper::OPropertyArrayUsageHelper< OQueryDescriptor_Base >
+ ,public ODataSettings
+{
+ OQueryDescriptor(const OQueryDescriptor&) = delete;
+ void operator =(const OQueryDescriptor&) = delete;
+ // helper
+ void registerProperties();
+protected:
+ // OPropertyArrayUsageHelper
+ virtual ::cppu::IPropertyArrayHelper* createArrayHelper( ) const override;
+
+ // OPropertySetHelper
+ virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper() override;
+
+ virtual ~OQueryDescriptor() override;
+public:
+ OQueryDescriptor();
+ explicit OQueryDescriptor(const OQueryDescriptor_Base& _rSource);
+
+ virtual css::uno::Sequence<css::uno::Type> SAL_CALL getTypes() override;
+ virtual css::uno::Sequence<sal_Int8> SAL_CALL getImplementationId() override;
+
+// css::uno::XInterface
+ DECLARE_XINTERFACE( )
+
+ // css::beans::XPropertySet
+ virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo( ) override;
+
+};
+} // namespace dbaccess
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/api/resultcolumn.cxx b/dbaccess/source/core/api/resultcolumn.cxx
new file mode 100644
index 000000000..938e7d1d3
--- /dev/null
+++ b/dbaccess/source/core/api/resultcolumn.cxx
@@ -0,0 +1,296 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "resultcolumn.hxx"
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/sdbc/SQLException.hpp>
+#include <com/sun/star/sdbc/DataType.hpp>
+#include <com/sun/star/sdbc/ColumnValue.hpp>
+#include <com/sun/star/sdbc/XRow.hpp>
+#include <tools/diagnose_ex.h>
+#include <stringconstants.hxx>
+#include <strings.hxx>
+
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::container;
+using namespace ::osl;
+using namespace ::comphelper;
+using namespace ::cppu;
+using namespace dbaccess;
+
+
+OResultColumn::OResultColumn( const Reference < XResultSetMetaData >& _xMetaData, sal_Int32 _nPos,
+ const Reference< XDatabaseMetaData >& _rxDBMeta )
+ :OColumn( true )
+ ,m_xMetaData( _xMetaData )
+ ,m_xDBMetaData( _rxDBMeta )
+ ,m_nPos( _nPos )
+{
+}
+
+void OResultColumn::impl_determineIsRowVersion_nothrow()
+{
+ if ( m_aIsRowVersion.hasValue() )
+ return;
+ m_aIsRowVersion <<= false;
+
+ OSL_ENSURE( m_xDBMetaData.is(), "OResultColumn::impl_determineIsRowVersion_nothrow: no DBMetaData!" );
+ if ( !m_xDBMetaData.is() )
+ return;
+
+ try
+ {
+ OUString sCatalog, sSchema, sTable, sColumnName;
+ getPropertyValue( PROPERTY_CATALOGNAME ) >>= sCatalog;
+ getPropertyValue( PROPERTY_SCHEMANAME ) >>= sSchema;
+ getPropertyValue( PROPERTY_TABLENAME ) >>= sTable;
+ getPropertyValue( PROPERTY_NAME ) >>= sColumnName;
+
+ try
+ {
+ Reference< XResultSet > xVersionColumns = m_xDBMetaData->getVersionColumns(
+ Any( sCatalog ), sSchema, sTable );
+ if ( xVersionColumns.is() ) // allowed to be NULL
+ {
+ Reference< XRow > xResultRow( xVersionColumns, UNO_QUERY_THROW );
+ while ( xVersionColumns->next() )
+ {
+ if ( xResultRow->getString( 2 ) == sColumnName )
+ {
+ m_aIsRowVersion <<= true;
+ break;
+ }
+ }
+ }
+ }
+ catch(const SQLException&)
+ {
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+}
+
+OResultColumn::~OResultColumn()
+{
+}
+
+// css::lang::XTypeProvider
+Sequence< sal_Int8 > OResultColumn::getImplementationId()
+{
+ return css::uno::Sequence<sal_Int8>();
+}
+
+// XServiceInfo
+OUString OResultColumn::getImplementationName( )
+{
+ return "com.sun.star.sdb.OResultColumn";
+}
+
+Sequence< OUString > OResultColumn::getSupportedServiceNames( )
+{
+ return { SERVICE_SDBCX_COLUMN, SERVICE_SDB_RESULTCOLUMN };
+}
+
+// OComponentHelper
+void OResultColumn::disposing()
+{
+ OColumn::disposing();
+
+ MutexGuard aGuard(m_aMutex);
+ m_xMetaData = nullptr;
+}
+
+// comphelper::OPropertyArrayUsageHelper
+::cppu::IPropertyArrayHelper* OResultColumn::createArrayHelper( ) const
+{
+ return new ::cppu::OPropertyArrayHelper
+ {
+ {
+ { PROPERTY_CATALOGNAME, PROPERTY_ID_CATALOGNAME, cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::READONLY },
+ { PROPERTY_DISPLAYSIZE, PROPERTY_ID_DISPLAYSIZE, cppu::UnoType<sal_Int32>::get(), css::beans::PropertyAttribute::READONLY },
+ { PROPERTY_ISAUTOINCREMENT, PROPERTY_ID_ISAUTOINCREMENT, cppu::UnoType<bool>::get(), css::beans::PropertyAttribute::READONLY },
+ { PROPERTY_ISCASESENSITIVE, PROPERTY_ID_ISCASESENSITIVE, cppu::UnoType<bool>::get(), css::beans::PropertyAttribute::READONLY },
+ { PROPERTY_ISCURRENCY, PROPERTY_ID_ISCURRENCY, cppu::UnoType<bool>::get(), css::beans::PropertyAttribute::READONLY },
+ { PROPERTY_ISDEFINITELYWRITABLE, PROPERTY_ID_ISDEFINITELYWRITABLE, cppu::UnoType<bool>::get(), css::beans::PropertyAttribute::READONLY },
+ { PROPERTY_ISNULLABLE, PROPERTY_ID_ISNULLABLE, cppu::UnoType<sal_Int32>::get(), css::beans::PropertyAttribute::READONLY },
+ { PROPERTY_ISREADONLY, PROPERTY_ID_ISREADONLY, cppu::UnoType<bool>::get(), css::beans::PropertyAttribute::READONLY },
+ { PROPERTY_ISROWVERSION, PROPERTY_ID_ISROWVERSION, cppu::UnoType<bool>::get(), css::beans::PropertyAttribute::READONLY },
+ { PROPERTY_ISSEARCHABLE, PROPERTY_ID_ISSEARCHABLE, cppu::UnoType<bool>::get(), css::beans::PropertyAttribute::READONLY },
+ { PROPERTY_ISSIGNED, PROPERTY_ID_ISSIGNED, cppu::UnoType<bool>::get(), css::beans::PropertyAttribute::READONLY },
+ { PROPERTY_ISWRITABLE, PROPERTY_ID_ISWRITABLE, cppu::UnoType<bool>::get(), css::beans::PropertyAttribute::READONLY },
+ { PROPERTY_LABEL, PROPERTY_ID_LABEL, cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::READONLY },
+ { PROPERTY_NAME, PROPERTY_ID_NAME, cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::READONLY },
+ { PROPERTY_PRECISION, PROPERTY_ID_PRECISION, cppu::UnoType<sal_Int32>::get(), css::beans::PropertyAttribute::READONLY },
+ { PROPERTY_SCALE, PROPERTY_ID_SCALE, cppu::UnoType<sal_Int32>::get(), css::beans::PropertyAttribute::READONLY },
+ { PROPERTY_SCHEMANAME, PROPERTY_ID_SCHEMANAME, cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::READONLY },
+ { PROPERTY_SERVICENAME, PROPERTY_ID_SERVICENAME, cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::READONLY },
+ { PROPERTY_TABLENAME, PROPERTY_ID_TABLENAME, cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::READONLY },
+ { PROPERTY_TYPE, PROPERTY_ID_TYPE, cppu::UnoType<sal_Int32>::get(), css::beans::PropertyAttribute::READONLY },
+ { PROPERTY_TYPENAME, PROPERTY_ID_TYPENAME, cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::READONLY }
+ }
+ };
+}
+
+// cppu::OPropertySetHelper
+::cppu::IPropertyArrayHelper& OResultColumn::getInfoHelper()
+{
+ return *static_cast< ::comphelper::OPropertyArrayUsageHelper< OResultColumn >* >(this)->getArrayHelper();
+}
+
+namespace
+{
+ template< typename T >
+ void obtain( Any& _out_rValue, ::std::optional< T > & _rCache, const sal_Int32 _nPos, const Reference < XResultSetMetaData >& _rxResultMeta, T (SAL_CALL XResultSetMetaData::*Getter)( sal_Int32 ) )
+ {
+ if ( !_rCache )
+ _rCache = (_rxResultMeta.get()->*Getter)(_nPos);
+ _out_rValue <<= *_rCache;
+ }
+}
+
+void OResultColumn::getFastPropertyValue( Any& rValue, sal_Int32 nHandle ) const
+{
+ try
+ {
+ if ( OColumn::isRegisteredProperty( nHandle ) )
+ {
+ OColumn::getFastPropertyValue( rValue, nHandle );
+ }
+ else
+ {
+ switch (nHandle)
+ {
+ case PROPERTY_ID_ISROWVERSION:
+ const_cast< OResultColumn* >( this )->impl_determineIsRowVersion_nothrow();
+ rValue = m_aIsRowVersion;
+ break;
+ case PROPERTY_ID_TABLENAME:
+ rValue <<= m_xMetaData->getTableName(m_nPos);
+ break;
+ case PROPERTY_ID_SCHEMANAME:
+ rValue <<= m_xMetaData->getSchemaName(m_nPos);
+ break;
+ case PROPERTY_ID_CATALOGNAME:
+ rValue <<= m_xMetaData->getCatalogName(m_nPos);
+ break;
+ case PROPERTY_ID_ISSIGNED:
+ obtain( rValue, m_isSigned, m_nPos, m_xMetaData, &XResultSetMetaData::isSigned );
+ break;
+ case PROPERTY_ID_ISCURRENCY:
+ obtain( rValue, m_isCurrency, m_nPos, m_xMetaData, &XResultSetMetaData::isCurrency );
+ break;
+ case PROPERTY_ID_ISSEARCHABLE:
+ obtain( rValue, m_bSearchable, m_nPos, m_xMetaData, &XResultSetMetaData::isSearchable );
+ break;
+ case PROPERTY_ID_ISCASESENSITIVE:
+ obtain( rValue, m_isCaseSensitive, m_nPos, m_xMetaData, &XResultSetMetaData::isCaseSensitive );
+ break;
+ case PROPERTY_ID_ISREADONLY:
+ obtain( rValue, m_isReadOnly, m_nPos, m_xMetaData, &XResultSetMetaData::isReadOnly );
+ break;
+ case PROPERTY_ID_ISWRITABLE:
+ obtain( rValue, m_isWritable, m_nPos, m_xMetaData, &XResultSetMetaData::isWritable );
+ break;
+ case PROPERTY_ID_ISDEFINITELYWRITABLE:
+ obtain( rValue, m_isDefinitelyWritable, m_nPos, m_xMetaData, &XResultSetMetaData::isDefinitelyWritable );
+ break;
+ case PROPERTY_ID_ISAUTOINCREMENT:
+ obtain( rValue, m_isAutoIncrement, m_nPos, m_xMetaData, &XResultSetMetaData::isAutoIncrement );
+ break;
+ case PROPERTY_ID_SERVICENAME:
+ rValue <<= m_xMetaData->getColumnServiceName(m_nPos);
+ break;
+ case PROPERTY_ID_LABEL:
+ obtain( rValue, m_sColumnLabel, m_nPos, m_xMetaData, &XResultSetMetaData::getColumnLabel );
+ break;
+ case PROPERTY_ID_DISPLAYSIZE:
+ obtain( rValue, m_nColumnDisplaySize, m_nPos, m_xMetaData, &XResultSetMetaData::getColumnDisplaySize );
+ break;
+ case PROPERTY_ID_TYPE:
+ obtain( rValue, m_nColumnType, m_nPos, m_xMetaData, &XResultSetMetaData::getColumnType );
+ break;
+ case PROPERTY_ID_PRECISION:
+ obtain( rValue, m_nPrecision, m_nPos, m_xMetaData, &XResultSetMetaData::getPrecision );
+ break;
+ case PROPERTY_ID_SCALE:
+ obtain( rValue, m_nScale, m_nPos, m_xMetaData, &XResultSetMetaData::getScale );
+ break;
+ case PROPERTY_ID_ISNULLABLE:
+ obtain( rValue, m_isNullable, m_nPos, m_xMetaData, &XResultSetMetaData::isNullable );
+ break;
+ case PROPERTY_ID_TYPENAME:
+ rValue <<= m_xMetaData->getColumnTypeName(m_nPos);
+ break;
+ default:
+ OSL_FAIL( "OResultColumn::getFastPropertyValue: unknown property handle!" );
+ break;
+ }
+ }
+ }
+ catch (SQLException& )
+ {
+ // default handling if we caught an exception
+ switch (nHandle)
+ {
+ case PROPERTY_ID_LABEL:
+ case PROPERTY_ID_TYPENAME:
+ case PROPERTY_ID_SERVICENAME:
+ case PROPERTY_ID_TABLENAME:
+ case PROPERTY_ID_SCHEMANAME:
+ case PROPERTY_ID_CATALOGNAME:
+ // empty string'S
+ rValue <<= OUString();
+ break;
+ case PROPERTY_ID_ISROWVERSION:
+ case PROPERTY_ID_ISAUTOINCREMENT:
+ case PROPERTY_ID_ISWRITABLE:
+ case PROPERTY_ID_ISDEFINITELYWRITABLE:
+ case PROPERTY_ID_ISCASESENSITIVE:
+ case PROPERTY_ID_ISSEARCHABLE:
+ case PROPERTY_ID_ISCURRENCY:
+ case PROPERTY_ID_ISSIGNED:
+ {
+ rValue <<= false;
+ } break;
+ case PROPERTY_ID_ISREADONLY:
+ {
+ rValue <<= true;
+ } break;
+ case PROPERTY_ID_SCALE:
+ case PROPERTY_ID_PRECISION:
+ case PROPERTY_ID_DISPLAYSIZE:
+ rValue <<= sal_Int32(0);
+ break;
+ case PROPERTY_ID_TYPE:
+ rValue <<= sal_Int32(DataType::SQLNULL);
+ break;
+ case PROPERTY_ID_ISNULLABLE:
+ rValue <<= ColumnValue::NULLABLE_UNKNOWN;
+ break;
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/api/resultcolumn.hxx b/dbaccess/source/core/api/resultcolumn.hxx
new file mode 100644
index 000000000..53803bac8
--- /dev/null
+++ b/dbaccess/source/core/api/resultcolumn.hxx
@@ -0,0 +1,87 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <com/sun/star/sdbc/XResultSetMetaData.hpp>
+#include <com/sun/star/sdbc/XDatabaseMetaData.hpp>
+#include <column.hxx>
+#include <optional>
+#include <comphelper/proparrhlp.hxx>
+namespace dbaccess
+{
+
+ // OResultColumn
+
+ class OResultColumn : public OColumn,
+ public ::comphelper::OPropertyArrayUsageHelper < OResultColumn >
+ {
+ protected:
+ css::uno::Reference < css::sdbc::XResultSetMetaData > m_xMetaData;
+ css::uno::Reference< css::sdbc::XDatabaseMetaData > m_xDBMetaData;
+ sal_Int32 m_nPos;
+ css::uno::Any m_aIsRowVersion;
+ mutable ::std::optional< sal_Bool > m_isSigned;
+ mutable ::std::optional< sal_Bool > m_isCurrency;
+ mutable ::std::optional< sal_Bool > m_bSearchable;
+ mutable ::std::optional< sal_Bool > m_isCaseSensitive;
+ mutable ::std::optional< sal_Bool > m_isReadOnly;
+ mutable ::std::optional< sal_Bool > m_isWritable;
+ mutable ::std::optional< sal_Bool > m_isDefinitelyWritable;
+ mutable ::std::optional< sal_Bool > m_isAutoIncrement;
+ mutable ::std::optional< sal_Int32 > m_isNullable;
+ mutable ::std::optional< OUString > m_sColumnLabel;
+ mutable ::std::optional< sal_Int32 > m_nColumnDisplaySize;
+ mutable ::std::optional< sal_Int32 > m_nColumnType;
+ mutable ::std::optional< sal_Int32 > m_nPrecision;
+ mutable ::std::optional< sal_Int32 > m_nScale;
+
+ virtual ~OResultColumn() override;
+ public:
+ OResultColumn(
+ const css::uno::Reference < css::sdbc::XResultSetMetaData >& _xMetaData,
+ sal_Int32 _nPos,
+ const css::uno::Reference< css::sdbc::XDatabaseMetaData >& _rxDBMeta );
+
+ // css::lang::XTypeProvider
+ virtual css::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId() override;
+
+ // css::lang::XServiceInfo
+ virtual OUString SAL_CALL getImplementationName( ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override;
+
+ // cppu::OComponentHelper
+ virtual void SAL_CALL disposing() override;
+
+ // comphelper::OPropertyArrayUsageHelper
+ virtual ::cppu::IPropertyArrayHelper* createArrayHelper( ) const override;
+
+ // cppu::OPropertySetHelper
+ virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper() override;
+ virtual void SAL_CALL getFastPropertyValue( css::uno::Any& rValue, sal_Int32 nHandle ) const override;
+
+ private:
+ void impl_determineIsRowVersion_nothrow();
+
+ protected:
+ using ::cppu::OPropertySetHelper::getFastPropertyValue;
+ };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/api/resultset.cxx b/dbaccess/source/core/api/resultset.cxx
new file mode 100644
index 000000000..2fe6cf355
--- /dev/null
+++ b/dbaccess/source/core/api/resultset.cxx
@@ -0,0 +1,994 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "resultset.hxx"
+#include <sal/log.hxx>
+#include <stringconstants.hxx>
+#include <strings.hxx>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/sdbc/ResultSetType.hpp>
+#include <com/sun/star/sdbc/SQLException.hpp>
+#include <cppuhelper/supportsservice.hxx>
+#include <cppuhelper/queryinterface.hxx>
+#include <cppuhelper/typeprovider.hxx>
+#include <comphelper/types.hxx>
+#include <tools/diagnose_ex.h>
+#include "datacolumn.hxx"
+#include <connectivity/dbexception.hxx>
+#include <connectivity/dbtools.hxx>
+
+
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::sdbcx;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::container;
+using namespace ::cppu;
+using namespace ::osl;
+using namespace dbaccess;
+using namespace dbtools;
+
+
+OResultSet::OResultSet(const css::uno::Reference< css::sdbc::XResultSet >& _xResultSet,
+ const css::uno::Reference< css::uno::XInterface >& _xStatement,
+ bool _bCaseSensitive)
+ :OResultSetBase(m_aMutex)
+ ,OPropertySetHelper(OResultSetBase::rBHelper)
+ ,m_xDelegatorResultSet(_xResultSet)
+ ,m_aWarnings( Reference< XWarningsSupplier >( _xResultSet, UNO_QUERY ) )
+ ,m_nResultSetConcurrency(0)
+ ,m_bIsBookmarkable(false)
+{
+ m_pColumns.reset( new OColumns(*this, m_aMutex, _bCaseSensitive, std::vector< OUString>(), nullptr,nullptr) );
+
+ try
+ {
+ m_aStatement = _xStatement;
+ m_xDelegatorResultSetUpdate.set(m_xDelegatorResultSet, css::uno::UNO_QUERY);
+ m_xDelegatorRow.set(m_xDelegatorResultSet, css::uno::UNO_QUERY);
+ m_xDelegatorRowUpdate.set(m_xDelegatorResultSet, css::uno::UNO_QUERY);
+
+ Reference< XPropertySet > xSet(m_xDelegatorResultSet, UNO_QUERY);
+ sal_Int32 nResultSetType(0);
+ xSet->getPropertyValue(PROPERTY_RESULTSETTYPE) >>= nResultSetType;
+ xSet->getPropertyValue(PROPERTY_RESULTSETCONCURRENCY) >>= m_nResultSetConcurrency;
+
+ // test for Bookmarks
+ if (ResultSetType::FORWARD_ONLY != nResultSetType)
+ {
+ Reference <XPropertySetInfo > xInfo(xSet->getPropertySetInfo());
+ if (xInfo->hasPropertyByName(PROPERTY_ISBOOKMARKABLE))
+ {
+ m_bIsBookmarkable = ::comphelper::getBOOL(xSet->getPropertyValue(PROPERTY_ISBOOKMARKABLE));
+ OSL_ENSURE( !m_bIsBookmarkable || Reference< XRowLocate >(m_xDelegatorResultSet, UNO_QUERY).is(),
+ "OResultSet::OResultSet: aggregate is inconsistent in its bookmarkable attribute!" );
+ m_bIsBookmarkable = m_bIsBookmarkable && Reference< XRowLocate >(m_xDelegatorResultSet, UNO_QUERY).is();
+ }
+ }
+ }
+ catch (const Exception&)
+ {
+ }
+}
+
+OResultSet::~OResultSet()
+{
+ m_pColumns->acquire();
+ m_pColumns->disposing();
+}
+
+// css::lang::XTypeProvider
+Sequence< Type > OResultSet::getTypes()
+{
+ OTypeCollection aTypes(cppu::UnoType<XPropertySet>::get(),
+ OResultSetBase::getTypes());
+
+ return aTypes.getTypes();
+}
+
+Sequence< sal_Int8 > OResultSet::getImplementationId()
+{
+ return css::uno::Sequence<sal_Int8>();
+}
+
+// css::uno::XInterface
+Any OResultSet::queryInterface( const Type & rType )
+{
+ Any aIface = OResultSetBase::queryInterface( rType );
+ if (!aIface.hasValue())
+ aIface = ::cppu::queryInterface(
+ rType,
+ static_cast< XPropertySet * >( this ));
+
+ return aIface;
+}
+
+void OResultSet::acquire() noexcept
+{
+ OResultSetBase::acquire();
+}
+
+void OResultSet::release() noexcept
+{
+ OResultSetBase::release();
+}
+
+
+// OResultSetBase
+void OResultSet::disposing()
+{
+ OPropertySetHelper::disposing();
+
+ MutexGuard aGuard(m_aMutex);
+
+ // free the columns
+ m_pColumns->disposing();
+
+ // close the pending result set
+ Reference< XCloseable > (m_xDelegatorResultSet, UNO_QUERY_THROW)->close();
+
+ m_xDelegatorResultSet = nullptr;
+ m_xDelegatorRow = nullptr;
+ m_xDelegatorRowUpdate = nullptr;
+
+ m_aStatement.clear();
+}
+
+// XCloseable
+void OResultSet::close()
+{
+ {
+ MutexGuard aGuard( m_aMutex );
+ ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed);
+ }
+ dispose();
+}
+
+// XServiceInfo
+OUString OResultSet::getImplementationName( )
+{
+ return "com.sun.star.sdb.OResultSet";
+}
+
+sal_Bool OResultSet::supportsService( const OUString& _rServiceName )
+{
+ return cppu::supportsService(this, _rServiceName);
+}
+
+Sequence< OUString > OResultSet::getSupportedServiceNames( )
+{
+ return { SERVICE_SDBC_RESULTSET, SERVICE_SDB_RESULTSET };
+}
+
+// css::beans::XPropertySet
+Reference< XPropertySetInfo > OResultSet::getPropertySetInfo()
+{
+ return createPropertySetInfo( getInfoHelper() ) ;
+}
+
+// comphelper::OPropertyArrayUsageHelper
+::cppu::IPropertyArrayHelper* OResultSet::createArrayHelper( ) const
+{
+ return new ::cppu::OPropertyArrayHelper
+ {
+ {
+ { PROPERTY_CURSORNAME, PROPERTY_ID_CURSORNAME, cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::READONLY },
+ { PROPERTY_FETCHDIRECTION, PROPERTY_ID_FETCHDIRECTION, cppu::UnoType<sal_Int32>::get(), 0 },
+ { PROPERTY_FETCHSIZE, PROPERTY_ID_FETCHSIZE, cppu::UnoType<sal_Int32>::get(), 0 },
+ { PROPERTY_ISBOOKMARKABLE, PROPERTY_ID_ISBOOKMARKABLE, cppu::UnoType<bool>::get(), css::beans::PropertyAttribute::READONLY },
+ { PROPERTY_RESULTSETCONCURRENCY, PROPERTY_ID_RESULTSETCONCURRENCY, cppu::UnoType<sal_Int32>::get(), css::beans::PropertyAttribute::READONLY },
+ { PROPERTY_RESULTSETTYPE, PROPERTY_ID_RESULTSETTYPE, cppu::UnoType<sal_Int32>::get(), css::beans::PropertyAttribute::READONLY }
+ }
+ };
+}
+
+// cppu::OPropertySetHelper
+::cppu::IPropertyArrayHelper& OResultSet::getInfoHelper()
+{
+ return *getArrayHelper();
+}
+
+sal_Bool OResultSet::convertFastPropertyValue(Any & rConvertedValue, Any & rOldValue, sal_Int32 nHandle, const Any& rValue )
+{
+ // be lazy ...
+ rConvertedValue = rValue;
+ getFastPropertyValue( rOldValue, nHandle );
+ return true;
+}
+
+void OResultSet::setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const Any& rValue )
+{
+ // set it for the driver result set
+ Reference< XPropertySet > xSet(m_xDelegatorResultSet, UNO_QUERY);
+ switch (nHandle)
+ {
+ case PROPERTY_ID_FETCHDIRECTION:
+ xSet->setPropertyValue(PROPERTY_FETCHDIRECTION, rValue);
+ break;
+ case PROPERTY_ID_FETCHSIZE:
+ xSet->setPropertyValue(PROPERTY_FETCHSIZE, rValue);
+ break;
+ default:
+ SAL_WARN("dbaccess", "unknown Property");
+ }
+}
+
+void OResultSet::getFastPropertyValue( Any& rValue, sal_Int32 nHandle ) const
+{
+ switch (nHandle)
+ {
+ case PROPERTY_ID_ISBOOKMARKABLE:
+ {
+ rValue <<= m_bIsBookmarkable;
+ } break;
+ default:
+ {
+ // get the property name
+ OUString aPropName;
+ sal_Int16 nAttributes;
+ const_cast<OResultSet*>(this)->getInfoHelper().
+ fillPropertyMembersByHandle(&aPropName, &nAttributes, nHandle);
+ OSL_ENSURE(!aPropName.isEmpty(), "property not found?");
+
+ // now read the value
+ rValue = Reference< XPropertySet >(m_xDelegatorResultSet, UNO_QUERY_THROW)->getPropertyValue(aPropName);
+ }
+ }
+}
+
+// XWarningsSupplier
+Any OResultSet::getWarnings()
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed);
+ return m_aWarnings.getWarnings();
+}
+
+void OResultSet::clearWarnings()
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed);
+ m_aWarnings.clearWarnings();
+}
+
+// css::sdbc::XResultSetMetaDataSupplier
+Reference< XResultSetMetaData > OResultSet::getMetaData()
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed);
+
+ return Reference< XResultSetMetaDataSupplier >(m_xDelegatorResultSet, UNO_QUERY_THROW)->getMetaData();
+}
+
+// css::sdbc::XColumnLocate
+sal_Int32 OResultSet::findColumn(const OUString& columnName)
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed);
+
+ return Reference< XColumnLocate >(m_xDelegatorResultSet, UNO_QUERY_THROW)->findColumn(columnName);
+}
+
+namespace
+{
+ Reference< XDatabaseMetaData > lcl_getDBMetaDataFromStatement_nothrow( const Reference< XInterface >& _rxStatement )
+ {
+ Reference< XDatabaseMetaData > xDBMetaData;
+ try
+ {
+ Reference< XStatement > xStatement( _rxStatement, UNO_QUERY );
+ Reference< XPreparedStatement > xPreparedStatement( _rxStatement, UNO_QUERY );
+ Reference< XConnection > xConn;
+ if ( xStatement.is() )
+ xConn = xStatement->getConnection();
+ else if ( xPreparedStatement.is() )
+ xConn = xPreparedStatement->getConnection();
+ if ( xConn.is() )
+ xDBMetaData = xConn->getMetaData();
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ return xDBMetaData;
+ }
+}
+
+// css::sdbcx::XColumnsSupplier
+Reference< css::container::XNameAccess > OResultSet::getColumns()
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed);
+
+ // do we have to populate the columns
+ if (!m_pColumns->isInitialized())
+ {
+ // get the metadata
+ Reference< XResultSetMetaData > xMetaData = Reference< XResultSetMetaDataSupplier >(m_xDelegatorResultSet, UNO_QUERY_THROW)->getMetaData();
+
+ sal_Int32 nColCount = 0;
+ // do we have columns
+ try
+ {
+ Reference< XDatabaseMetaData > xDBMetaData( lcl_getDBMetaDataFromStatement_nothrow( getStatement() ) );
+ nColCount = xMetaData->getColumnCount();
+
+ for ( sal_Int32 i = 0; i < nColCount; ++i)
+ {
+ // retrieve the name of the column
+ OUString sName = xMetaData->getColumnName(i + 1);
+ rtl::Reference<ODataColumn> pColumn = new ODataColumn(xMetaData, m_xDelegatorRow, m_xDelegatorRowUpdate, i + 1, xDBMetaData);
+
+ // don't silently assume that the name is unique - result set implementations
+ // are allowed to return duplicate names, but we are required to have
+ // unique column names
+ if ( m_pColumns->hasByName( sName ) )
+ sName = ::dbtools::createUniqueName( m_pColumns.get(), sName );
+
+ m_pColumns->append( sName, pColumn.get() );
+ }
+ }
+ catch ( const SQLException& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ m_pColumns->setInitialized();
+
+ #if OSL_DEBUG_LEVEL > 0
+ // some sanity checks. Especially in case we auto-adjusted the column names above,
+ // this might be reasonable
+ try
+ {
+ const Reference< XNameAccess > xColNames( static_cast< XNameAccess* >( m_pColumns.get() ), UNO_SET_THROW );
+ const Sequence< OUString > aNames( xColNames->getElementNames() );
+ SAL_WARN_IF( aNames.getLength() != nColCount, "dbaccess",
+ "OResultSet::getColumns: invalid column count!" );
+ for ( auto const & name : aNames )
+ {
+ Reference< XPropertySet > xColProps( xColNames->getByName( name ), UNO_QUERY_THROW );
+ OUString sName;
+ OSL_VERIFY( xColProps->getPropertyValue( PROPERTY_NAME ) >>= sName );
+ SAL_WARN_IF( sName != name, "dbaccess", "OResultSet::getColumns: invalid column name!" );
+ }
+
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ #endif
+ }
+ return m_pColumns.get();
+}
+
+// css::sdbc::XRow
+sal_Bool OResultSet::wasNull()
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed);
+
+ return m_xDelegatorRow->wasNull();
+}
+
+OUString OResultSet::getString(sal_Int32 columnIndex)
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed);
+
+ return m_xDelegatorRow->getString(columnIndex);
+}
+
+sal_Bool OResultSet::getBoolean(sal_Int32 columnIndex)
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed);
+
+ return m_xDelegatorRow->getBoolean(columnIndex);
+}
+
+sal_Int8 OResultSet::getByte(sal_Int32 columnIndex)
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed);
+
+ return m_xDelegatorRow->getByte(columnIndex);
+}
+
+sal_Int16 OResultSet::getShort(sal_Int32 columnIndex)
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed);
+
+ return m_xDelegatorRow->getShort(columnIndex);
+}
+
+sal_Int32 OResultSet::getInt(sal_Int32 columnIndex)
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed);
+
+ return m_xDelegatorRow->getInt(columnIndex);
+}
+
+sal_Int64 OResultSet::getLong(sal_Int32 columnIndex)
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed);
+
+ return m_xDelegatorRow->getLong(columnIndex);
+}
+
+float OResultSet::getFloat(sal_Int32 columnIndex)
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed);
+
+ return m_xDelegatorRow->getFloat(columnIndex);
+}
+
+double OResultSet::getDouble(sal_Int32 columnIndex)
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed);
+
+ return m_xDelegatorRow->getDouble(columnIndex);
+}
+
+Sequence< sal_Int8 > OResultSet::getBytes(sal_Int32 columnIndex)
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed);
+
+ return m_xDelegatorRow->getBytes(columnIndex);
+}
+
+css::util::Date OResultSet::getDate(sal_Int32 columnIndex)
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed);
+
+ return m_xDelegatorRow->getDate(columnIndex);
+}
+
+css::util::Time OResultSet::getTime(sal_Int32 columnIndex)
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed);
+
+ return m_xDelegatorRow->getTime(columnIndex);
+}
+
+css::util::DateTime OResultSet::getTimestamp(sal_Int32 columnIndex)
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed);
+
+ return m_xDelegatorRow->getTimestamp(columnIndex);
+}
+
+Reference< css::io::XInputStream > OResultSet::getBinaryStream(sal_Int32 columnIndex)
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed);
+
+ return m_xDelegatorRow->getBinaryStream(columnIndex);
+}
+
+Reference< css::io::XInputStream > OResultSet::getCharacterStream(sal_Int32 columnIndex)
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed);
+
+ return m_xDelegatorRow->getCharacterStream(columnIndex);
+}
+
+Any OResultSet::getObject(sal_Int32 columnIndex, const Reference< css::container::XNameAccess > & typeMap)
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed);
+
+ return m_xDelegatorRow->getObject(columnIndex, typeMap);
+}
+
+Reference< XRef > OResultSet::getRef(sal_Int32 columnIndex)
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed);
+
+ return m_xDelegatorRow->getRef(columnIndex);
+}
+
+Reference< XBlob > OResultSet::getBlob(sal_Int32 columnIndex)
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed);
+
+ return m_xDelegatorRow->getBlob(columnIndex);
+}
+
+Reference< XClob > OResultSet::getClob(sal_Int32 columnIndex)
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed);
+
+ return m_xDelegatorRow->getClob(columnIndex);
+}
+
+Reference< XArray > OResultSet::getArray(sal_Int32 columnIndex)
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed);
+
+ return m_xDelegatorRow->getArray(columnIndex);
+}
+
+// css::sdbc::XRowUpdate
+void OResultSet::updateNull(sal_Int32 columnIndex)
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed);
+
+ checkReadOnly();
+
+ m_xDelegatorRowUpdate->updateNull(columnIndex);
+}
+
+void OResultSet::updateBoolean(sal_Int32 columnIndex, sal_Bool x)
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed);
+
+ checkReadOnly();
+
+ m_xDelegatorRowUpdate->updateBoolean(columnIndex, x);
+}
+
+void OResultSet::updateByte(sal_Int32 columnIndex, sal_Int8 x)
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed);
+
+ checkReadOnly();
+
+ m_xDelegatorRowUpdate->updateByte(columnIndex, x);
+}
+
+void OResultSet::updateShort(sal_Int32 columnIndex, sal_Int16 x)
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed);
+
+ checkReadOnly();
+
+ m_xDelegatorRowUpdate->updateShort(columnIndex, x);
+}
+
+void OResultSet::updateInt(sal_Int32 columnIndex, sal_Int32 x)
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed);
+
+ checkReadOnly();
+
+ m_xDelegatorRowUpdate->updateInt(columnIndex, x);
+}
+
+void OResultSet::updateLong(sal_Int32 columnIndex, sal_Int64 x)
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed);
+
+ checkReadOnly();
+
+ m_xDelegatorRowUpdate->updateLong(columnIndex, x);
+}
+
+void OResultSet::updateFloat(sal_Int32 columnIndex, float x)
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed);
+
+ checkReadOnly();
+
+ m_xDelegatorRowUpdate->updateFloat(columnIndex, x);
+}
+
+void OResultSet::updateDouble(sal_Int32 columnIndex, double x)
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed);
+
+ checkReadOnly();
+
+ m_xDelegatorRowUpdate->updateDouble(columnIndex, x);
+}
+
+void OResultSet::updateString(sal_Int32 columnIndex, const OUString& x)
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed);
+
+ checkReadOnly();
+
+ m_xDelegatorRowUpdate->updateString(columnIndex, x);
+}
+
+void OResultSet::updateBytes(sal_Int32 columnIndex, const Sequence< sal_Int8 >& x)
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed);
+
+ checkReadOnly();
+
+ m_xDelegatorRowUpdate->updateBytes(columnIndex, x);
+}
+
+void OResultSet::updateDate(sal_Int32 columnIndex, const css::util::Date& x)
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed);
+
+ checkReadOnly();
+
+ m_xDelegatorRowUpdate->updateDate(columnIndex, x);
+}
+
+void OResultSet::updateTime(sal_Int32 columnIndex, const css::util::Time& x)
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed);
+
+ checkReadOnly();
+
+ m_xDelegatorRowUpdate->updateTime(columnIndex, x);
+}
+
+void OResultSet::updateTimestamp(sal_Int32 columnIndex, const css::util::DateTime& x)
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed);
+
+ checkReadOnly();
+
+ m_xDelegatorRowUpdate->updateTimestamp(columnIndex, x);
+}
+
+void OResultSet::updateBinaryStream(sal_Int32 columnIndex, const Reference< css::io::XInputStream > & x, sal_Int32 length)
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed);
+
+ checkReadOnly();
+
+ m_xDelegatorRowUpdate->updateBinaryStream(columnIndex, x, length);
+}
+
+void OResultSet::updateCharacterStream(sal_Int32 columnIndex, const Reference< css::io::XInputStream > & x, sal_Int32 length)
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed);
+
+ checkReadOnly();
+
+ m_xDelegatorRowUpdate->updateCharacterStream(columnIndex, x, length);
+}
+
+void OResultSet::updateNumericObject(sal_Int32 columnIndex, const Any& x, sal_Int32 scale)
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed);
+
+ checkReadOnly();
+
+ m_xDelegatorRowUpdate->updateNumericObject(columnIndex, x, scale);
+}
+
+void OResultSet::updateObject(sal_Int32 columnIndex, const Any& x)
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed);
+
+ checkReadOnly();
+
+ m_xDelegatorRowUpdate->updateObject(columnIndex, x);
+}
+
+// css::sdbc::XResultSet
+sal_Bool OResultSet::next()
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed);
+
+ return m_xDelegatorResultSet->next();
+}
+
+sal_Bool OResultSet::isBeforeFirst()
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed);
+
+ return m_xDelegatorResultSet->isBeforeFirst();
+}
+
+sal_Bool OResultSet::isAfterLast()
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed);
+
+ return m_xDelegatorResultSet->isAfterLast();
+}
+
+sal_Bool OResultSet::isFirst()
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed);
+
+ return m_xDelegatorResultSet->isFirst();
+}
+
+sal_Bool OResultSet::isLast()
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed);
+
+ return m_xDelegatorResultSet->isLast();
+}
+
+void OResultSet::beforeFirst()
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed);
+
+ m_xDelegatorResultSet->beforeFirst();
+}
+
+void OResultSet::afterLast()
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed);
+
+ m_xDelegatorResultSet->afterLast();
+}
+
+sal_Bool OResultSet::first()
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed);
+
+ return m_xDelegatorResultSet->first();
+}
+
+sal_Bool OResultSet::last()
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed);
+
+ return m_xDelegatorResultSet->last();
+}
+
+sal_Int32 OResultSet::getRow()
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed);
+
+ return m_xDelegatorResultSet->getRow();
+}
+
+sal_Bool OResultSet::absolute(sal_Int32 row)
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed);
+
+ return m_xDelegatorResultSet->absolute(row);
+}
+
+sal_Bool OResultSet::relative(sal_Int32 rows)
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed);
+
+ return m_xDelegatorResultSet->relative(rows);
+}
+
+sal_Bool OResultSet::previous()
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed);
+
+ return m_xDelegatorResultSet->previous();
+}
+
+void OResultSet::refreshRow()
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed);
+
+ m_xDelegatorResultSet->refreshRow();
+}
+
+sal_Bool OResultSet::rowUpdated()
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed);
+
+ return m_xDelegatorResultSet->rowUpdated();
+}
+
+sal_Bool OResultSet::rowInserted()
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed);
+
+ return m_xDelegatorResultSet->rowInserted();
+}
+
+sal_Bool OResultSet::rowDeleted()
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed);
+
+ return m_xDelegatorResultSet->rowDeleted();
+}
+
+Reference< XInterface > OResultSet::getStatement()
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed);
+
+ return m_aStatement;
+}
+
+// css::sdbcx::XRowLocate
+Any OResultSet::getBookmark()
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed);
+
+ checkBookmarkable();
+
+ return Reference< XRowLocate >(m_xDelegatorResultSet, UNO_QUERY_THROW)->getBookmark();
+}
+
+sal_Bool OResultSet::moveToBookmark(const Any& bookmark)
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed);
+
+ checkBookmarkable();
+
+ return Reference< XRowLocate >(m_xDelegatorResultSet, UNO_QUERY_THROW)->moveToBookmark(bookmark);
+}
+
+sal_Bool OResultSet::moveRelativeToBookmark(const Any& bookmark, sal_Int32 rows)
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed);
+
+ checkBookmarkable();
+
+ return Reference< XRowLocate >(m_xDelegatorResultSet, UNO_QUERY_THROW)->moveRelativeToBookmark(bookmark, rows);
+}
+
+sal_Int32 OResultSet::compareBookmarks(const Any& _first, const Any& _second)
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed);
+
+ checkBookmarkable();
+
+ return Reference< XRowLocate >(m_xDelegatorResultSet, UNO_QUERY_THROW)->compareBookmarks(_first, _second);
+}
+
+sal_Bool OResultSet::hasOrderedBookmarks()
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed);
+
+ checkBookmarkable();
+
+ return Reference< XRowLocate >(m_xDelegatorResultSet, UNO_QUERY_THROW)->hasOrderedBookmarks();
+}
+
+sal_Int32 OResultSet::hashBookmark(const Any& bookmark)
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed);
+
+ checkBookmarkable();
+
+ return Reference< XRowLocate >(m_xDelegatorResultSet, UNO_QUERY_THROW)->hashBookmark(bookmark);
+}
+
+// css::sdbc::XResultSetUpdate
+void OResultSet::insertRow()
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed);
+
+ checkReadOnly();
+
+ m_xDelegatorResultSetUpdate->insertRow();
+}
+
+void OResultSet::updateRow()
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed);
+
+ checkReadOnly();
+
+ m_xDelegatorResultSetUpdate->updateRow();
+}
+
+void OResultSet::deleteRow()
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed);
+
+ checkReadOnly();
+
+ m_xDelegatorResultSetUpdate->deleteRow();
+}
+
+void OResultSet::cancelRowUpdates()
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed);
+
+ checkReadOnly();
+
+ m_xDelegatorResultSetUpdate->cancelRowUpdates();
+}
+
+void OResultSet::moveToInsertRow()
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed);
+
+ checkReadOnly();
+
+ m_xDelegatorResultSetUpdate->moveToInsertRow();
+}
+
+void OResultSet::moveToCurrentRow()
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed);
+
+ checkReadOnly();
+
+ m_xDelegatorResultSetUpdate->moveToCurrentRow();
+}
+
+void OResultSet::checkReadOnly() const
+{
+ if ( ( m_nResultSetConcurrency == ResultSetConcurrency::READ_ONLY )
+ || !m_xDelegatorResultSetUpdate.is()
+ )
+ throwSQLException( "The result set is read-only.", StandardSQLState::GENERAL_ERROR, *const_cast< OResultSet* >( this ) );
+}
+
+void OResultSet::checkBookmarkable() const
+{
+ if ( !m_bIsBookmarkable )
+ throwSQLException( "The result set does not have bookmark support.", StandardSQLState::GENERAL_ERROR, *const_cast< OResultSet* >( this ) );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/api/resultset.hxx b/dbaccess/source/core/api/resultset.hxx
new file mode 100644
index 000000000..b2da0f248
--- /dev/null
+++ b/dbaccess/source/core/api/resultset.hxx
@@ -0,0 +1,221 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <column.hxx>
+#include <connectivity/warningscontainer.hxx>
+
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/sdbc/XStatement.hpp>
+#include <com/sun/star/sdbc/XCloseable.hpp>
+#include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp>
+#include <com/sun/star/sdbc/XWarningsSupplier.hpp>
+#include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
+#include <com/sun/star/sdbc/XResultSet.hpp>
+#include <com/sun/star/sdbc/XRow.hpp>
+#include <com/sun/star/sdbc/XColumnLocate.hpp>
+#include <com/sun/star/sdbcx/XRowLocate.hpp>
+#include <com/sun/star/sdbc/XRowUpdate.hpp>
+#include <com/sun/star/sdbc/XResultSetUpdate.hpp>
+#include <com/sun/star/sdbc/ResultSetConcurrency.hpp>
+
+#include <cppuhelper/propshlp.hxx>
+#include <comphelper/proparrhlp.hxx>
+#include <osl/diagnose.h>
+#include <cppuhelper/compbase.hxx>
+#include <cppuhelper/basemutex.hxx>
+
+namespace dbaccess
+{
+ typedef ::cppu::WeakComponentImplHelper< css::sdbc::XWarningsSupplier,
+ css::sdbc::XResultSet,
+ css::sdbc::XResultSetMetaDataSupplier,
+ css::sdbc::XRow,
+ css::sdbc::XCloseable,
+ css::sdbc::XColumnLocate,
+ css::sdbcx::XRowLocate,
+ css::sdbcx::XColumnsSupplier,
+ css::sdbc::XResultSetUpdate,
+ css::sdbc::XRowUpdate,
+ css::lang::XServiceInfo > OResultSetBase;
+
+ // OResultSet
+
+ class OResultSet final : public cppu::BaseMutex,
+ public OResultSetBase,
+ public ::cppu::OPropertySetHelper,
+ public ::comphelper::OPropertyArrayUsageHelper < OResultSet >
+ {
+ css::uno::Reference< css::uno::XInterface> m_aStatement;
+
+ css::uno::Reference< css::sdbc::XResultSet > m_xDelegatorResultSet;
+ css::uno::Reference< css::sdbc::XResultSetUpdate > m_xDelegatorResultSetUpdate;
+ css::uno::Reference< css::sdbc::XRow > m_xDelegatorRow;
+ css::uno::Reference< css::sdbc::XRowUpdate > m_xDelegatorRowUpdate;
+
+ ::dbtools::WarningsContainer m_aWarnings;
+ std::unique_ptr<OColumns> m_pColumns;
+ sal_Int32 m_nResultSetConcurrency;
+ bool m_bIsBookmarkable : 1;
+
+ public:
+ OResultSet(const css::uno::Reference< css::sdbc::XResultSet >& _xResultSet,
+ const css::uno::Reference< css::uno::XInterface >& _xStatement,
+ bool _bCaseSensitive);
+ virtual ~OResultSet() override;
+
+ // css::lang::XTypeProvider
+ virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes() override;
+ virtual css::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId() override;
+
+ // css::uno::XInterface
+ virtual css::uno::Any SAL_CALL queryInterface( const css::uno::Type & rType ) override;
+ virtual void SAL_CALL acquire() noexcept override;
+ virtual void SAL_CALL release() noexcept override;
+
+ // css::lang::XServiceInfo
+ virtual OUString SAL_CALL getImplementationName( ) override;
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override;
+
+ // ::cppu::OComponentHelper
+ virtual void SAL_CALL disposing() override;
+
+ // css::sdbc::XCloseable
+ virtual void SAL_CALL close( ) override;
+
+ // css::beans::XPropertySet
+ virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo( ) override;
+
+ // comphelper::OPropertyArrayUsageHelper
+ virtual ::cppu::IPropertyArrayHelper* createArrayHelper( ) const override;
+
+ // cppu::OPropertySetHelper
+ virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper() override;
+
+ virtual sal_Bool SAL_CALL convertFastPropertyValue(
+ css::uno::Any & rConvertedValue,
+ css::uno::Any & rOldValue,
+ sal_Int32 nHandle,
+ const css::uno::Any& rValue ) override;
+ virtual void SAL_CALL setFastPropertyValue_NoBroadcast(
+ sal_Int32 nHandle,
+ const css::uno::Any& rValue
+ ) override;
+ virtual void SAL_CALL getFastPropertyValue( css::uno::Any& rValue, sal_Int32 nHandle ) const override;
+
+ // css::sdbc::XWarningsSupplier
+ virtual css::uno::Any SAL_CALL getWarnings( ) override;
+ virtual void SAL_CALL clearWarnings( ) override;
+
+ // css::sdbc::XResultSetMetaDataSupplier
+ virtual css::uno::Reference< css::sdbc::XResultSetMetaData > SAL_CALL getMetaData( ) override;
+
+ // css::sdbc::XColumnLocate
+ virtual sal_Int32 SAL_CALL findColumn( const OUString& columnName ) override;
+
+ // css::sdbcx::XColumnsSupplier
+ virtual css::uno::Reference< css::container::XNameAccess > SAL_CALL getColumns( ) override;
+
+ // css::sdbc::XRow
+ virtual sal_Bool SAL_CALL wasNull( ) override;
+ virtual OUString SAL_CALL getString( sal_Int32 columnIndex ) override;
+ virtual sal_Bool SAL_CALL getBoolean( sal_Int32 columnIndex ) override;
+ virtual sal_Int8 SAL_CALL getByte( sal_Int32 columnIndex ) override;
+ virtual sal_Int16 SAL_CALL getShort( sal_Int32 columnIndex ) override;
+ virtual sal_Int32 SAL_CALL getInt( sal_Int32 columnIndex ) override;
+ virtual sal_Int64 SAL_CALL getLong( sal_Int32 columnIndex ) override;
+ virtual float SAL_CALL getFloat( sal_Int32 columnIndex ) override;
+ virtual double SAL_CALL getDouble( sal_Int32 columnIndex ) override;
+ virtual css::uno::Sequence< sal_Int8 > SAL_CALL getBytes( sal_Int32 columnIndex ) override;
+ virtual css::util::Date SAL_CALL getDate( sal_Int32 columnIndex ) override;
+ virtual css::util::Time SAL_CALL getTime( sal_Int32 columnIndex ) override;
+ virtual css::util::DateTime SAL_CALL getTimestamp( sal_Int32 columnIndex ) override;
+ virtual css::uno::Reference< css::io::XInputStream > SAL_CALL getBinaryStream( sal_Int32 columnIndex ) override;
+ virtual css::uno::Reference< css::io::XInputStream > SAL_CALL getCharacterStream( sal_Int32 columnIndex ) override;
+ virtual css::uno::Any SAL_CALL getObject( sal_Int32 columnIndex, const css::uno::Reference< css::container::XNameAccess >& typeMap ) override;
+ virtual css::uno::Reference< css::sdbc::XRef > SAL_CALL getRef( sal_Int32 columnIndex ) override;
+ virtual css::uno::Reference< css::sdbc::XBlob > SAL_CALL getBlob( sal_Int32 columnIndex ) override;
+ virtual css::uno::Reference< css::sdbc::XClob > SAL_CALL getClob( sal_Int32 columnIndex ) override;
+ virtual css::uno::Reference< css::sdbc::XArray > SAL_CALL getArray( sal_Int32 columnIndex ) override;
+
+ // css::sdbc::XResultSet
+ virtual sal_Bool SAL_CALL next( ) override;
+ virtual sal_Bool SAL_CALL isBeforeFirst( ) override;
+ virtual sal_Bool SAL_CALL isAfterLast( ) override;
+ virtual sal_Bool SAL_CALL isFirst( ) override;
+ virtual sal_Bool SAL_CALL isLast( ) override;
+ virtual void SAL_CALL beforeFirst( ) override;
+ virtual void SAL_CALL afterLast( ) override;
+ virtual sal_Bool SAL_CALL first( ) override;
+ virtual sal_Bool SAL_CALL last( ) override;
+ virtual sal_Int32 SAL_CALL getRow( ) override;
+ virtual sal_Bool SAL_CALL absolute( sal_Int32 row ) override;
+ virtual sal_Bool SAL_CALL relative( sal_Int32 rows ) override;
+ virtual sal_Bool SAL_CALL previous( ) override;
+ virtual void SAL_CALL refreshRow( ) override;
+ virtual sal_Bool SAL_CALL rowUpdated( ) override;
+ virtual sal_Bool SAL_CALL rowInserted( ) override;
+ virtual sal_Bool SAL_CALL rowDeleted( ) override;
+ virtual css::uno::Reference< css::uno::XInterface > SAL_CALL getStatement( ) override;
+
+ // css::sdbcx::XRowLocate
+ virtual css::uno::Any SAL_CALL getBookmark( ) override;
+ virtual sal_Bool SAL_CALL moveToBookmark( const css::uno::Any& bookmark ) override;
+ virtual sal_Bool SAL_CALL moveRelativeToBookmark( const css::uno::Any& bookmark, sal_Int32 rows ) override;
+ virtual sal_Int32 SAL_CALL compareBookmarks( const css::uno::Any& first, const css::uno::Any& second ) override;
+ virtual sal_Bool SAL_CALL hasOrderedBookmarks( ) override;
+ virtual sal_Int32 SAL_CALL hashBookmark( const css::uno::Any& bookmark ) override;
+
+ // css::sdbc::XResultSetUpdate
+ virtual void SAL_CALL insertRow( ) override;
+ virtual void SAL_CALL updateRow( ) override;
+ virtual void SAL_CALL deleteRow( ) override;
+ virtual void SAL_CALL cancelRowUpdates( ) override;
+ virtual void SAL_CALL moveToInsertRow( ) override;
+ virtual void SAL_CALL moveToCurrentRow( ) override;
+
+ // css::sdbc::XRowUpdate
+ virtual void SAL_CALL updateNull( sal_Int32 columnIndex ) override;
+ virtual void SAL_CALL updateBoolean( sal_Int32 columnIndex, sal_Bool x ) override;
+ virtual void SAL_CALL updateByte( sal_Int32 columnIndex, sal_Int8 x ) override;
+ virtual void SAL_CALL updateShort( sal_Int32 columnIndex, sal_Int16 x ) override;
+ virtual void SAL_CALL updateInt( sal_Int32 columnIndex, sal_Int32 x ) override;
+ virtual void SAL_CALL updateLong( sal_Int32 columnIndex, sal_Int64 x ) override;
+ virtual void SAL_CALL updateFloat( sal_Int32 columnIndex, float x ) override;
+ virtual void SAL_CALL updateDouble( sal_Int32 columnIndex, double x ) override;
+ virtual void SAL_CALL updateString( sal_Int32 columnIndex, const OUString& x ) override;
+ virtual void SAL_CALL updateBytes( sal_Int32 columnIndex, const css::uno::Sequence< sal_Int8 >& x ) override;
+ virtual void SAL_CALL updateDate( sal_Int32 columnIndex, const css::util::Date& x ) override;
+ virtual void SAL_CALL updateTime( sal_Int32 columnIndex, const css::util::Time& x ) override;
+ virtual void SAL_CALL updateTimestamp( sal_Int32 columnIndex, const css::util::DateTime& x ) override;
+ virtual void SAL_CALL updateBinaryStream( sal_Int32 columnIndex, const css::uno::Reference< css::io::XInputStream >& x, sal_Int32 length ) override;
+ virtual void SAL_CALL updateCharacterStream( sal_Int32 columnIndex, const css::uno::Reference< css::io::XInputStream >& x, sal_Int32 length ) override;
+ virtual void SAL_CALL updateObject( sal_Int32 columnIndex, const css::uno::Any& x ) override;
+ virtual void SAL_CALL updateNumericObject( sal_Int32 columnIndex, const css::uno::Any& x, sal_Int32 scale ) override;
+
+ private:
+ void checkReadOnly() const;
+ void checkBookmarkable() const;
+
+ using ::cppu::OPropertySetHelper::getFastPropertyValue;
+ };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/api/statement.cxx b/dbaccess/source/core/api/statement.cxx
new file mode 100644
index 000000000..3a67cbaeb
--- /dev/null
+++ b/dbaccess/source/core/api/statement.cxx
@@ -0,0 +1,591 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <statement.hxx>
+#include "resultset.hxx"
+#include <stringconstants.hxx>
+#include <strings.hxx>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/sdbc/XDatabaseMetaData.hpp>
+#include <com/sun/star/sdbc/SQLException.hpp>
+#include <cppuhelper/queryinterface.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <cppuhelper/typeprovider.hxx>
+#include <comphelper/property.hxx>
+#include <comphelper/types.hxx>
+#include <tools/diagnose_ex.h>
+#include <connectivity/dbexception.hxx>
+
+using namespace ::com::sun::star::sdb;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::cppu;
+using namespace ::osl;
+using namespace dbaccess;
+using namespace dbtools;
+
+
+OStatementBase::OStatementBase(const Reference< XConnection > & _xConn,
+ const Reference< XInterface > & _xStatement)
+ :OSubComponent(m_aMutex, _xConn)
+ ,OPropertySetHelper(OComponentHelper::rBHelper)
+ ,m_bUseBookmarks( false )
+ ,m_bEscapeProcessing( true )
+
+{
+ OSL_ENSURE(_xStatement.is() ,"Statement is NULL!");
+ m_xAggregateAsSet.set(_xStatement,UNO_QUERY);
+ m_xAggregateAsCancellable.set(m_xAggregateAsSet, UNO_QUERY);
+}
+
+OStatementBase::~OStatementBase()
+{
+}
+
+// css::lang::XTypeProvider
+Sequence< Type > OStatementBase::getTypes()
+{
+ OTypeCollection aTypes(cppu::UnoType<XPropertySet>::get(),
+ cppu::UnoType<XWarningsSupplier>::get(),
+ cppu::UnoType<XCloseable>::get(),
+ cppu::UnoType<XMultipleResults>::get(),
+ cppu::UnoType<css::util::XCancellable>::get(),
+ OSubComponent::getTypes() );
+ Reference< XGeneratedResultSet > xGRes(m_xAggregateAsSet, UNO_QUERY);
+ if ( xGRes.is() )
+ aTypes = OTypeCollection(cppu::UnoType<XGeneratedResultSet>::get(),aTypes.getTypes());
+ Reference< XPreparedBatchExecution > xPreparedBatchExecution(m_xAggregateAsSet, UNO_QUERY);
+ if ( xPreparedBatchExecution.is() )
+ aTypes = OTypeCollection(cppu::UnoType<XPreparedBatchExecution>::get(),aTypes.getTypes());
+
+ return aTypes.getTypes();
+}
+
+// css::uno::XInterface
+Any OStatementBase::queryInterface( const Type & rType )
+{
+ Any aIface = OSubComponent::queryInterface( rType );
+ if (!aIface.hasValue())
+ {
+ aIface = ::cppu::queryInterface(
+ rType,
+ static_cast< XPropertySet * >( this ),
+ static_cast< XWarningsSupplier * >( this ),
+ static_cast< XCloseable * >( this ),
+ static_cast< XMultipleResults * >( this ),
+ static_cast< css::util::XCancellable * >( this ));
+ if ( !aIface.hasValue() )
+ {
+ Reference< XGeneratedResultSet > xGRes(m_xAggregateAsSet, UNO_QUERY);
+ if ( cppu::UnoType<XGeneratedResultSet>::get()== rType && xGRes.is() )
+ aIface = ::cppu::queryInterface(rType,static_cast< XGeneratedResultSet * >( this ));
+ }
+ if ( !aIface.hasValue() )
+ {
+ Reference< XPreparedBatchExecution > xGRes(m_xAggregateAsSet, UNO_QUERY);
+ if ( cppu::UnoType<XPreparedBatchExecution>::get()== rType && xGRes.is() )
+ aIface = ::cppu::queryInterface(rType,static_cast< XPreparedBatchExecution * >( this ));
+ }
+ }
+ return aIface;
+}
+
+void OStatementBase::acquire() noexcept
+{
+ OSubComponent::acquire();
+}
+
+void OStatementBase::release() noexcept
+{
+ OSubComponent::release();
+}
+
+void OStatementBase::disposeResultSet()
+{
+ // free the cursor if alive
+ Reference< XComponent > xComp(m_aResultSet.get(), UNO_QUERY);
+ if (xComp.is())
+ xComp->dispose();
+ m_aResultSet.clear();
+}
+
+// OComponentHelper
+void OStatementBase::disposing()
+{
+ OPropertySetHelper::disposing();
+
+ MutexGuard aGuard(m_aMutex);
+
+ // free pending results
+ disposeResultSet();
+
+ // free the original statement
+ {
+ MutexGuard aCancelGuard(m_aCancelMutex);
+ m_xAggregateAsCancellable = nullptr;
+ }
+
+ if ( m_xAggregateAsSet.is() )
+ {
+ try
+ {
+ Reference< XCloseable > (m_xAggregateAsSet, UNO_QUERY_THROW)->close();
+ }
+ catch(RuntimeException& )
+ {// don't care for anymore
+ }
+ }
+ m_xAggregateAsSet = nullptr;
+
+ // free the parent at last
+ OSubComponent::disposing();
+}
+
+// XCloseable
+void OStatementBase::close()
+{
+ {
+ MutexGuard aGuard( m_aMutex );
+ ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed);
+ }
+ dispose();
+}
+
+// OPropertySetHelper
+Reference< XPropertySetInfo > OStatementBase::getPropertySetInfo()
+{
+ return createPropertySetInfo( getInfoHelper() ) ;
+}
+
+// comphelper::OPropertyArrayUsageHelper
+::cppu::IPropertyArrayHelper* OStatementBase::createArrayHelper( ) const
+{
+ return new ::cppu::OPropertyArrayHelper
+ {
+ {
+ { PROPERTY_CURSORNAME, PROPERTY_ID_CURSORNAME, cppu::UnoType<OUString>::get(), 0 },
+ { PROPERTY_ESCAPE_PROCESSING, PROPERTY_ID_ESCAPE_PROCESSING, cppu::UnoType<bool>::get(), 0 },
+ { PROPERTY_FETCHDIRECTION, PROPERTY_ID_FETCHDIRECTION, cppu::UnoType<sal_Int32>::get(), 0 },
+ { PROPERTY_FETCHSIZE, PROPERTY_ID_FETCHSIZE, cppu::UnoType<sal_Int32>::get(), 0 },
+ { PROPERTY_MAXFIELDSIZE, PROPERTY_ID_MAXFIELDSIZE, cppu::UnoType<sal_Int32>::get(), 0 },
+ { PROPERTY_MAXROWS, PROPERTY_ID_MAXROWS, cppu::UnoType<sal_Int32>::get(), 0 },
+ { PROPERTY_QUERYTIMEOUT, PROPERTY_ID_QUERYTIMEOUT, cppu::UnoType<sal_Int32>::get(), 0 },
+ { PROPERTY_RESULTSETCONCURRENCY, PROPERTY_ID_RESULTSETCONCURRENCY, cppu::UnoType<sal_Int32>::get(), 0 },
+ { PROPERTY_RESULTSETTYPE, PROPERTY_ID_RESULTSETTYPE, cppu::UnoType<sal_Int32>::get(), 0 },
+ { PROPERTY_USEBOOKMARKS, PROPERTY_ID_USEBOOKMARKS, cppu::UnoType<bool>::get(), 0 }
+ }
+ };
+}
+
+// cppu::OPropertySetHelper
+::cppu::IPropertyArrayHelper& OStatementBase::getInfoHelper()
+{
+ return *getArrayHelper();
+}
+
+sal_Bool OStatementBase::convertFastPropertyValue(Any & rConvertedValue, Any & rOldValue, sal_Int32 nHandle, const Any& rValue )
+{
+ bool bModified(false);
+ switch (nHandle)
+ {
+ case PROPERTY_ID_USEBOOKMARKS:
+ bModified = ::comphelper::tryPropertyValue( rConvertedValue, rOldValue, rValue, m_bUseBookmarks );
+ break;
+
+ case PROPERTY_ID_ESCAPE_PROCESSING:
+ bModified = ::comphelper::tryPropertyValue( rConvertedValue, rOldValue, rValue, m_bEscapeProcessing );
+ break;
+
+ default:
+ if ( m_xAggregateAsSet.is() )
+ {
+ // get the property name
+ OUString sPropName;
+ getInfoHelper().fillPropertyMembersByHandle( &sPropName, nullptr, nHandle );
+
+ // now set the value
+ Any aCurrentValue = m_xAggregateAsSet->getPropertyValue( sPropName );
+ if ( aCurrentValue != rValue )
+ {
+ rOldValue = aCurrentValue;
+ rConvertedValue = rValue;
+ bModified = true;
+ }
+ }
+ break;
+ }
+ return bModified;
+}
+
+void OStatementBase::setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const Any& rValue )
+{
+ switch ( nHandle )
+ {
+ case PROPERTY_ID_USEBOOKMARKS:
+ {
+ m_bUseBookmarks = ::comphelper::getBOOL( rValue );
+ if ( m_xAggregateAsSet.is() && m_xAggregateAsSet->getPropertySetInfo()->hasPropertyByName( PROPERTY_USEBOOKMARKS ) )
+ m_xAggregateAsSet->setPropertyValue( PROPERTY_USEBOOKMARKS, rValue );
+ }
+ break;
+
+ case PROPERTY_ID_ESCAPE_PROCESSING:
+ m_bEscapeProcessing = ::comphelper::getBOOL( rValue );
+ if ( m_xAggregateAsSet.is() )
+ m_xAggregateAsSet->setPropertyValue( PROPERTY_ESCAPE_PROCESSING, rValue );
+ break;
+
+ default:
+ if ( m_xAggregateAsSet.is() )
+ {
+ OUString sPropName;
+ getInfoHelper().fillPropertyMembersByHandle( &sPropName, nullptr, nHandle );
+ m_xAggregateAsSet->setPropertyValue( sPropName, rValue );
+ }
+ break;
+ }
+}
+
+void OStatementBase::getFastPropertyValue( Any& rValue, sal_Int32 nHandle ) const
+{
+ switch (nHandle)
+ {
+ case PROPERTY_ID_USEBOOKMARKS:
+ rValue <<= m_bUseBookmarks;
+ break;
+
+ case PROPERTY_ID_ESCAPE_PROCESSING:
+ // don't rely on our aggregate - if it implements this wrong, and always returns
+ // TRUE here, then we would loop in impl_doEscapeProcessing_nothrow
+ rValue <<= m_bEscapeProcessing;
+ break;
+
+ default:
+ if ( m_xAggregateAsSet.is() )
+ {
+ OUString sPropName;
+ const_cast< OStatementBase* >( this )->getInfoHelper().fillPropertyMembersByHandle( &sPropName, nullptr, nHandle );
+ rValue = m_xAggregateAsSet->getPropertyValue( sPropName );
+ }
+ break;
+ }
+}
+
+// XWarningsSupplier
+Any OStatementBase::getWarnings()
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed);
+
+ return Reference< XWarningsSupplier >(m_xAggregateAsSet, UNO_QUERY_THROW)->getWarnings();
+}
+
+void OStatementBase::clearWarnings()
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed);
+
+ Reference< XWarningsSupplier >(m_xAggregateAsSet, UNO_QUERY_THROW)->clearWarnings();
+}
+
+// css::util::XCancellable
+void OStatementBase::cancel()
+{
+ // no blocking as cancel is typically called from a different thread
+ MutexGuard aCancelGuard(m_aCancelMutex);
+ if (m_xAggregateAsCancellable.is())
+ m_xAggregateAsCancellable->cancel();
+ // else do nothing
+}
+
+// XMultipleResults
+Reference< XResultSet > SAL_CALL OStatementBase::getResultSet( )
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed);
+
+ // first check the meta data
+ Reference<XDatabaseMetaData> xMeta = Reference< XConnection > (m_xParent, UNO_QUERY_THROW)->getMetaData();
+ if (!xMeta.is() || !xMeta->supportsMultipleResultSets())
+ throwFunctionSequenceException(*this);
+
+ return Reference< XMultipleResults >(m_xAggregateAsSet, UNO_QUERY_THROW)->getResultSet();
+}
+
+sal_Int32 SAL_CALL OStatementBase::getUpdateCount( )
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed);
+
+ // first check the meta data
+ Reference<XDatabaseMetaData> xMeta = Reference< XConnection > (m_xParent, UNO_QUERY_THROW)->getMetaData();
+ if (!xMeta.is() || !xMeta->supportsMultipleResultSets())
+ throwFunctionSequenceException(*this);
+
+ return Reference< XMultipleResults >(m_xAggregateAsSet, UNO_QUERY_THROW)->getUpdateCount();
+}
+
+sal_Bool SAL_CALL OStatementBase::getMoreResults( )
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed);
+
+ // first check the meta data
+ Reference<XDatabaseMetaData> xMeta = Reference< XConnection > (m_xParent, UNO_QUERY_THROW)->getMetaData();
+ if (!xMeta.is() || !xMeta->supportsMultipleResultSets())
+ throwFunctionSequenceException(*this);
+
+ // free the previous results
+ disposeResultSet();
+
+ return Reference< XMultipleResults >(m_xAggregateAsSet, UNO_QUERY_THROW)->getMoreResults();
+}
+
+// XPreparedBatchExecution
+void SAL_CALL OStatementBase::addBatch( )
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed);
+
+ // first check the meta data
+ Reference<XDatabaseMetaData> xMeta = Reference< XConnection > (m_xParent, UNO_QUERY_THROW)->getMetaData();
+ if (!xMeta.is() || !xMeta->supportsBatchUpdates())
+ throwFunctionSequenceException(*this);
+
+ Reference< XPreparedBatchExecution >(m_xAggregateAsSet, UNO_QUERY_THROW)->addBatch();
+}
+
+void SAL_CALL OStatementBase::clearBatch( )
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed);
+
+ // first check the meta data
+ Reference<XDatabaseMetaData> xMeta = Reference< XConnection > (m_xParent, UNO_QUERY_THROW)->getMetaData();
+ if (!xMeta.is() || !xMeta->supportsBatchUpdates())
+ throwFunctionSequenceException(*this);
+
+ Reference< XPreparedBatchExecution >(m_xAggregateAsSet, UNO_QUERY_THROW)->clearBatch();
+}
+
+Sequence< sal_Int32 > SAL_CALL OStatementBase::executeBatch( )
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed);
+
+ // first check the meta data
+ Reference<XDatabaseMetaData> xMeta = Reference< XConnection > (m_xParent, UNO_QUERY_THROW)->getMetaData();
+ if (!xMeta.is() || !xMeta->supportsBatchUpdates())
+ throwFunctionSequenceException(*this);
+
+ // free the previous results
+ disposeResultSet();
+
+ return Reference< XPreparedBatchExecution >(m_xAggregateAsSet, UNO_QUERY_THROW)->executeBatch();
+}
+
+Reference< XResultSet > SAL_CALL OStatementBase::getGeneratedValues( )
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed);
+ Reference< XGeneratedResultSet > xGRes(m_xAggregateAsSet, UNO_QUERY);
+
+ if ( xGRes.is() )
+ return xGRes->getGeneratedValues( );
+ return Reference< XResultSet >();
+}
+
+
+// OStatement
+
+OStatement::OStatement( const Reference< XConnection >& _xConn, const Reference< XInterface > & _xStatement )
+ :OStatementBase( _xConn, _xStatement )
+ ,m_bAttemptedComposerCreation( false )
+{
+ m_xAggregateStatement.set( _xStatement, UNO_QUERY_THROW );
+}
+
+IMPLEMENT_FORWARD_XINTERFACE2( OStatement, OStatementBase, OStatement_IFACE );
+IMPLEMENT_FORWARD_XTYPEPROVIDER2( OStatement, OStatementBase, OStatement_IFACE );
+
+// XServiceInfo
+OUString OStatement::getImplementationName( )
+{
+ return "com.sun.star.sdb.OStatement";
+}
+
+sal_Bool OStatement::supportsService( const OUString& _rServiceName )
+{
+ return cppu::supportsService(this, _rServiceName);
+}
+
+Sequence< OUString > OStatement::getSupportedServiceNames( )
+{
+ return { SERVICE_SDBC_STATEMENT };
+}
+
+// XStatement
+Reference< XResultSet > OStatement::executeQuery( const OUString& _rSQL )
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed);
+
+ disposeResultSet();
+ Reference< XResultSet > xResultSet;
+
+ OUString sSQL( impl_doEscapeProcessing_nothrow( _rSQL ) );
+
+ Reference< XResultSet > xInnerResultSet = m_xAggregateStatement->executeQuery( sSQL );
+ Reference< XConnection > xConnection( m_xParent, UNO_QUERY_THROW );
+
+ if ( xInnerResultSet.is() )
+ {
+ Reference< XDatabaseMetaData > xMeta = xConnection->getMetaData();
+ bool bCaseSensitive = xMeta.is() && xMeta->supportsMixedCaseQuotedIdentifiers();
+ xResultSet = new OResultSet( xInnerResultSet, *this, bCaseSensitive );
+
+ // keep the resultset weak
+ m_aResultSet = xResultSet;
+ }
+
+ return xResultSet;
+}
+
+sal_Int32 OStatement::executeUpdate( const OUString& _rSQL )
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed);
+
+ disposeResultSet();
+
+ OUString sSQL( impl_doEscapeProcessing_nothrow( _rSQL ) );
+ return m_xAggregateStatement->executeUpdate( sSQL );
+}
+
+sal_Bool OStatement::execute( const OUString& _rSQL )
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed);
+
+ disposeResultSet();
+
+ OUString sSQL( impl_doEscapeProcessing_nothrow( _rSQL ) );
+ return m_xAggregateStatement->execute( sSQL );
+}
+
+void OStatement::addBatch( const OUString& _rSQL )
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed);
+
+ // first check the meta data
+ Reference<XDatabaseMetaData> xMeta = Reference< XConnection > (m_xParent, UNO_QUERY_THROW)->getMetaData();
+ if (!xMeta.is() || !xMeta->supportsBatchUpdates())
+ throwFunctionSequenceException(*this);
+
+ OUString sSQL( impl_doEscapeProcessing_nothrow( _rSQL ) );
+ Reference< XBatchExecution >(m_xAggregateAsSet, UNO_QUERY_THROW)->addBatch( sSQL );
+}
+
+void OStatement::clearBatch( )
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed);
+ // first check the meta data
+ Reference<XDatabaseMetaData> xMeta = Reference< XConnection > (m_xParent, UNO_QUERY_THROW)->getMetaData();
+ if (!xMeta.is() || !xMeta->supportsBatchUpdates())
+ throwFunctionSequenceException(*this);
+
+ Reference< XBatchExecution >(m_xAggregateAsSet, UNO_QUERY_THROW)->clearBatch();
+}
+
+Sequence< sal_Int32 > OStatement::executeBatch( )
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed);
+ // first check the meta data
+ Reference<XDatabaseMetaData> xMeta = Reference< XConnection > (m_xParent, UNO_QUERY_THROW)->getMetaData();
+ if (!xMeta.is() || !xMeta->supportsBatchUpdates())
+ throwFunctionSequenceException(*this);
+ return Reference< XBatchExecution >(m_xAggregateAsSet, UNO_QUERY_THROW)->executeBatch( );
+}
+
+
+Reference< XConnection > OStatement::getConnection()
+{
+ return Reference< XConnection >( m_xParent, UNO_QUERY );
+}
+
+void SAL_CALL OStatement::disposing()
+{
+ OStatementBase::disposing();
+ m_xComposer.clear();
+ m_xAggregateStatement.clear();
+}
+
+OUString OStatement::impl_doEscapeProcessing_nothrow( const OUString& _rSQL ) const
+{
+ if ( !m_bEscapeProcessing )
+ return _rSQL;
+ try
+ {
+ if ( !impl_ensureComposer_nothrow() )
+ return _rSQL;
+
+ bool bParseable = false;
+ try { m_xComposer->setQuery( _rSQL ); bParseable = true; }
+ catch( const SQLException& ) { }
+
+ if ( !bParseable )
+ // if we cannot parse it, silently accept this. The driver is probably able to cope with it then
+ return _rSQL;
+
+ OUString sLowLevelSQL = m_xComposer->getQueryWithSubstitution();
+ return sLowLevelSQL;
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+
+ return _rSQL;
+}
+
+bool OStatement::impl_ensureComposer_nothrow() const
+{
+ if ( m_bAttemptedComposerCreation )
+ return m_xComposer.is();
+
+ const_cast< OStatement* >( this )->m_bAttemptedComposerCreation = true;
+ try
+ {
+ Reference< XMultiServiceFactory > xFactory( m_xParent, UNO_QUERY_THROW );
+ const_cast< OStatement* >( this )->m_xComposer.set( xFactory->createInstance( SERVICE_NAME_SINGLESELECTQUERYCOMPOSER ), UNO_QUERY_THROW );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+
+ return m_xComposer.is();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/api/table.cxx b/dbaccess/source/core/api/table.cxx
new file mode 100644
index 000000000..f9a1dffb9
--- /dev/null
+++ b/dbaccess/source/core/api/table.cxx
@@ -0,0 +1,352 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <table.hxx>
+#include <definitioncolumn.hxx>
+#include <stringconstants.hxx>
+#include <strings.hxx>
+#include <core_resource.hxx>
+#include <strings.hrc>
+#include "CIndexes.hxx"
+
+#include <osl/diagnose.h>
+#include <comphelper/servicehelper.hxx>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/sdbc/SQLException.hpp>
+#include <com/sun/star/sdb/tools/XTableRename.hpp>
+#include <com/sun/star/sdb/tools/XTableAlteration.hpp>
+
+#include <connectivity/TKeys.hxx>
+#include <connectivity/dbtools.hxx>
+
+#include <ContainerMediator.hxx>
+
+using namespace dbaccess;
+using namespace connectivity;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::util;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::sdbcx;
+using namespace ::com::sun::star::container;
+using namespace ::osl;
+using namespace ::comphelper;
+using namespace ::cppu;
+
+// ODBTable
+
+ODBTable::ODBTable(connectivity::sdbcx::OCollection* _pTables
+ ,const Reference< XConnection >& _rxConn
+ ,const OUString& _rCatalog
+ ,const OUString& _rSchema
+ ,const OUString& _rName
+ ,const OUString& _rType
+ ,const OUString& _rDesc
+ ,const Reference< XNameAccess >& _xColumnDefinitions)
+ :OTable_Base(_pTables,_rxConn,_rxConn->getMetaData().is() && _rxConn->getMetaData()->supportsMixedCaseQuotedIdentifiers(), _rName, _rType, _rDesc, _rSchema, _rCatalog )
+ ,m_xColumnDefinitions(_xColumnDefinitions)
+ ,m_nPrivileges(0)
+{
+ OSL_ENSURE(getMetaData().is(), "ODBTable::ODBTable : invalid conn !");
+ OSL_ENSURE(!_rName.isEmpty(), "ODBTable::ODBTable : name !");
+ // TODO : think about collecting the privileges here, as we can't ensure that in getFastPropertyValue, where
+ // we do this at the moment, the statement needed can be supplied by the connection (for example the SQL-Server
+ // ODBC driver does not allow more than one statement per connection, and in getFastPropertyValue it's more
+ // likely that it's already used up than it's here.)
+}
+
+ODBTable::ODBTable(connectivity::sdbcx::OCollection* _pTables
+ ,const Reference< XConnection >& _rxConn)
+ :OTable_Base(_pTables,_rxConn, _rxConn->getMetaData().is() && _rxConn->getMetaData()->supportsMixedCaseQuotedIdentifiers())
+ ,m_nPrivileges(-1)
+{
+}
+
+ODBTable::~ODBTable()
+{
+}
+
+rtl::Reference<OColumn> ODBTable::createColumn(const OUString& _rName) const
+{
+ Reference<XPropertySet> xProp;
+ if ( m_xDriverColumns.is() && m_xDriverColumns->hasByName(_rName) )
+ {
+ xProp.set(m_xDriverColumns->getByName(_rName),UNO_QUERY);
+ }
+ else
+ {
+ OColumns* pColumns = static_cast<OColumns*>(m_xColumns.get());
+ xProp.set(pColumns->createBaseObject(_rName),UNO_QUERY);
+ }
+
+ Reference<XPropertySet> xColumnDefinition;
+ if ( m_xColumnDefinitions.is() && m_xColumnDefinitions->hasByName(_rName) )
+ xColumnDefinition.set(m_xColumnDefinitions->getByName(_rName),UNO_QUERY);
+ return new OTableColumnWrapper( xProp, xColumnDefinition, false );
+}
+
+void ODBTable::columnAppended( const Reference< XPropertySet >& /*_rxSourceDescriptor*/ )
+{
+ // not interested in
+}
+
+void ODBTable::columnDropped(const OUString& _sName)
+{
+ Reference<XDrop> xDrop(m_xColumnDefinitions,UNO_QUERY);
+ if ( xDrop.is() && m_xColumnDefinitions->hasByName(_sName) )
+ {
+ xDrop->dropByName(_sName);
+ }
+}
+
+Sequence< sal_Int8 > ODBTable::getImplementationId()
+{
+ return css::uno::Sequence<sal_Int8>();
+}
+
+// OComponentHelper
+void SAL_CALL ODBTable::disposing()
+{
+ OPropertySetHelper::disposing();
+ OTable_Base::disposing();
+ m_xColumnDefinitions = nullptr;
+ m_xDriverColumns = nullptr;
+ m_pColumnMediator = nullptr;
+}
+
+void ODBTable::getFastPropertyValue(Any& _rValue, sal_Int32 _nHandle) const
+{
+ if ((PROPERTY_ID_PRIVILEGES == _nHandle) && (-1 == m_nPrivileges))
+ { // somebody is asking for the privileges and we do not know them, yet
+ const_cast<ODBTable*>(this)->m_nPrivileges = ::dbtools::getTablePrivileges(getMetaData(),m_CatalogName,m_SchemaName, m_Name);
+ }
+
+ OTable_Base::getFastPropertyValue(_rValue, _nHandle);
+}
+
+void ODBTable::construct()
+{
+ ::osl::MutexGuard aGuard(m_aMutex);
+
+ // we don't collect the privileges here, this is potentially expensive. Instead we determine them on request.
+ // (see getFastPropertyValue)
+ m_nPrivileges = -1;
+
+ OTable_Base::construct();
+
+ registerProperty(PROPERTY_FILTER, PROPERTY_ID_FILTER, PropertyAttribute::BOUND,
+ &m_sFilter, cppu::UnoType<OUString>::get());
+
+ registerProperty(PROPERTY_ORDER, PROPERTY_ID_ORDER, PropertyAttribute::BOUND,
+ &m_sOrder, cppu::UnoType<OUString>::get());
+
+ registerProperty(PROPERTY_APPLYFILTER, PROPERTY_ID_APPLYFILTER, PropertyAttribute::BOUND,
+ &m_bApplyFilter, cppu::UnoType<bool>::get());
+
+ registerProperty(PROPERTY_FONT, PROPERTY_ID_FONT, PropertyAttribute::BOUND,
+ &m_aFont, cppu::UnoType<css::awt::FontDescriptor>::get());
+
+ registerMayBeVoidProperty(PROPERTY_ROW_HEIGHT, PROPERTY_ID_ROW_HEIGHT, PropertyAttribute::BOUND | PropertyAttribute::MAYBEVOID,
+ &m_aRowHeight, cppu::UnoType<sal_Int32>::get());
+
+ registerProperty(PROPERTY_AUTOGROW, PROPERTY_ID_AUTOGROW, PropertyAttribute::BOUND,
+ &m_bAutoGrow, cppu::UnoType<bool>::get());
+
+ registerMayBeVoidProperty(PROPERTY_TEXTCOLOR, PROPERTY_ID_TEXTCOLOR, PropertyAttribute::BOUND | PropertyAttribute::MAYBEVOID,
+ &m_aTextColor, cppu::UnoType<sal_Int32>::get());
+
+ registerProperty(PROPERTY_PRIVILEGES, PROPERTY_ID_PRIVILEGES, PropertyAttribute::BOUND | PropertyAttribute::READONLY,
+ &m_nPrivileges, cppu::UnoType<sal_Int32>::get());
+
+ registerMayBeVoidProperty(PROPERTY_TEXTLINECOLOR, PROPERTY_ID_TEXTLINECOLOR, PropertyAttribute::BOUND | PropertyAttribute::MAYBEVOID,
+ &m_aTextLineColor, cppu::UnoType<sal_Int32>::get());
+
+ registerProperty(PROPERTY_TEXTEMPHASIS, PROPERTY_ID_TEXTEMPHASIS, PropertyAttribute::BOUND,
+ &m_nFontEmphasis, cppu::UnoType<sal_Int16>::get());
+
+ registerProperty(PROPERTY_TEXTRELIEF, PROPERTY_ID_TEXTRELIEF, PropertyAttribute::BOUND,
+ &m_nFontRelief, cppu::UnoType<sal_Int16>::get());
+
+ registerProperty(PROPERTY_FONTNAME, PROPERTY_ID_FONTNAME, PropertyAttribute::BOUND,&m_aFont.Name, cppu::UnoType<OUString>::get());
+ registerProperty(PROPERTY_FONTHEIGHT, PROPERTY_ID_FONTHEIGHT, PropertyAttribute::BOUND,&m_aFont.Height, cppu::UnoType<sal_Int16>::get());
+ registerProperty(PROPERTY_FONTWIDTH, PROPERTY_ID_FONTWIDTH, PropertyAttribute::BOUND,&m_aFont.Width, cppu::UnoType<sal_Int16>::get());
+ registerProperty(PROPERTY_FONTSTYLENAME, PROPERTY_ID_FONTSTYLENAME, PropertyAttribute::BOUND,&m_aFont.StyleName, cppu::UnoType<OUString>::get());
+ registerProperty(PROPERTY_FONTFAMILY, PROPERTY_ID_FONTFAMILY, PropertyAttribute::BOUND,&m_aFont.Family, cppu::UnoType<sal_Int16>::get());
+ registerProperty(PROPERTY_FONTCHARSET, PROPERTY_ID_FONTCHARSET, PropertyAttribute::BOUND,&m_aFont.CharSet, cppu::UnoType<sal_Int16>::get());
+ registerProperty(PROPERTY_FONTPITCH, PROPERTY_ID_FONTPITCH, PropertyAttribute::BOUND,&m_aFont.Pitch, cppu::UnoType<sal_Int16>::get());
+ registerProperty(PROPERTY_FONTCHARWIDTH, PROPERTY_ID_FONTCHARWIDTH, PropertyAttribute::BOUND,&m_aFont.CharacterWidth, cppu::UnoType<float>::get());
+ registerProperty(PROPERTY_FONTWEIGHT, PROPERTY_ID_FONTWEIGHT, PropertyAttribute::BOUND,&m_aFont.Weight, cppu::UnoType<float>::get());
+ registerProperty(PROPERTY_FONTSLANT, PROPERTY_ID_FONTSLANT, PropertyAttribute::BOUND,&m_aFont.Slant, cppu::UnoType<css::awt::FontSlant>::get());
+ registerProperty(PROPERTY_FONTUNDERLINE, PROPERTY_ID_FONTUNDERLINE, PropertyAttribute::BOUND,&m_aFont.Underline, cppu::UnoType<sal_Int16>::get());
+ registerProperty(PROPERTY_FONTSTRIKEOUT, PROPERTY_ID_FONTSTRIKEOUT, PropertyAttribute::BOUND,&m_aFont.Strikeout, cppu::UnoType<sal_Int16>::get());
+ registerProperty(PROPERTY_FONTORIENTATION, PROPERTY_ID_FONTORIENTATION, PropertyAttribute::BOUND,&m_aFont.Orientation, cppu::UnoType<float>::get());
+ registerProperty(PROPERTY_FONTKERNING, PROPERTY_ID_FONTKERNING, PropertyAttribute::BOUND,&m_aFont.Kerning, cppu::UnoType<sal_Bool>::get());
+ registerProperty(PROPERTY_FONTWORDLINEMODE, PROPERTY_ID_FONTWORDLINEMODE,PropertyAttribute::BOUND,&m_aFont.WordLineMode, cppu::UnoType<sal_Bool>::get());
+ registerProperty(PROPERTY_FONTTYPE, PROPERTY_ID_FONTTYPE, PropertyAttribute::BOUND,&m_aFont.Type, cppu::UnoType<sal_Int16>::get());
+
+ refreshColumns();
+}
+
+::cppu::IPropertyArrayHelper* ODBTable::createArrayHelper( sal_Int32 _nId) const
+{
+ Sequence< Property > aProps;
+ describeProperties(aProps);
+ if(!_nId)
+ {
+ for(Property & prop : asNonConstRange(aProps))
+ {
+ if (prop.Name == PROPERTY_CATALOGNAME)
+ prop.Attributes = PropertyAttribute::READONLY;
+ else if (prop.Name == PROPERTY_SCHEMANAME)
+ prop.Attributes = PropertyAttribute::READONLY;
+ else if (prop.Name == PROPERTY_DESCRIPTION)
+ prop.Attributes = PropertyAttribute::READONLY;
+ else if (prop.Name == PROPERTY_NAME)
+ prop.Attributes = PropertyAttribute::READONLY;
+ }
+ }
+
+ return new ::cppu::OPropertyArrayHelper(aProps);
+}
+
+::cppu::IPropertyArrayHelper & SAL_CALL ODBTable::getInfoHelper()
+{
+ return *ODBTable_PROP::getArrayHelper(isNew() ? 1 : 0);
+}
+
+// XServiceInfo
+OUString SAL_CALL ODBTable::getImplementationName()
+ {
+ return "com.sun.star.sdb.dbaccess.ODBTable";
+ }
+sal_Bool SAL_CALL ODBTable::supportsService(const OUString& _rServiceName)
+ {
+ const css::uno::Sequence< OUString > aSupported(getSupportedServiceNames());
+ for (const OUString& s : aSupported)
+ if (s == _rServiceName)
+ return true;
+
+ return false;
+ }
+css::uno::Sequence< OUString > SAL_CALL ODBTable::getSupportedServiceNames()
+{
+ return { SERVICE_SDBCX_TABLE };
+}
+
+
+Any SAL_CALL ODBTable::queryInterface( const Type & rType )
+{
+ if(rType == cppu::UnoType<XRename>::get()&& !getRenameService().is() )
+ return Any();
+ if(rType == cppu::UnoType<XAlterTable>::get()&& !getAlterService().is() )
+ return Any();
+ return OTable_Base::queryInterface( rType);
+}
+
+Sequence< Type > SAL_CALL ODBTable::getTypes( )
+{
+ Type aRenameType = cppu::UnoType<XRename>::get();
+ Type aAlterType = cppu::UnoType<XAlterTable>::get();
+
+ Sequence< Type > aTypes(OTable_Base::getTypes());
+ std::vector<Type> aOwnTypes;
+ aOwnTypes.reserve(aTypes.getLength());
+
+ const Type* pIter = aTypes.getConstArray();
+ const Type* pEnd = pIter + aTypes.getLength();
+ for(;pIter != pEnd ;++pIter)
+ {
+ if( (*pIter != aRenameType || getRenameService().is()) && (*pIter != aAlterType || getAlterService().is()))
+ aOwnTypes.push_back(*pIter);
+ }
+
+ return Sequence< Type >(aOwnTypes.data(), aOwnTypes.size());
+}
+
+// XRename,
+void SAL_CALL ODBTable::rename( const OUString& _rNewName )
+{
+ ::osl::MutexGuard aGuard(m_aMutex);
+ checkDisposed(connectivity::sdbcx::OTableDescriptor_BASE::rBHelper.bDisposed);
+ if ( !getRenameService().is() )
+ throw SQLException(DBA_RES(RID_STR_NO_TABLE_RENAME),*this,SQLSTATE_GENERAL,1000,Any() );
+
+ Reference<XPropertySet> xTable(this);
+ getRenameService()->rename(xTable,_rNewName);
+ ::connectivity::OTable_TYPEDEF::rename(_rNewName);
+}
+
+// XAlterTable,
+void SAL_CALL ODBTable::alterColumnByName( const OUString& _rName, const Reference< XPropertySet >& _rxDescriptor )
+{
+ ::osl::MutexGuard aGuard(m_aMutex);
+ checkDisposed(connectivity::sdbcx::OTableDescriptor_BASE::rBHelper.bDisposed);
+ if ( !getAlterService().is() )
+ throw SQLException(DBA_RES(RID_STR_NO_TABLE_RENAME),*this,SQLSTATE_GENERAL,1000,Any() );
+
+ if ( !m_xColumns->hasByName(_rName) )
+ throw SQLException(DBA_RES(RID_STR_COLUMN_NOT_VALID),*this,SQLSTATE_GENERAL,1000,Any() );
+
+ Reference<XPropertySet> xTable(this);
+ getAlterService()->alterColumnByName(xTable,_rName,_rxDescriptor);
+ m_xColumns->refresh();
+}
+
+sal_Int64 SAL_CALL ODBTable::getSomething( const Sequence< sal_Int8 >& rId )
+{
+ return comphelper::getSomethingImpl(rId, this,
+ comphelper::FallbackToGetSomethingOf<OTable_Base>{});
+}
+
+const Sequence< sal_Int8 > & ODBTable::getUnoTunnelId()
+{
+ static const comphelper::UnoIdInit s_Id;
+ return s_Id.getSeq();
+}
+
+Reference< XPropertySet > ODBTable::createColumnDescriptor()
+{
+ return new OTableColumnDescriptor( true );
+}
+
+sdbcx::OCollection* ODBTable::createColumns(const ::std::vector< OUString>& _rNames)
+{
+ Reference<XDatabaseMetaData> xMeta = getMetaData();
+ OColumns* pCol = new OColumns(*this, m_aMutex, nullptr, isCaseSensitive(), _rNames, this,this,
+ getAlterService().is() || (xMeta.is() && xMeta->supportsAlterTableWithAddColumn()),
+ getAlterService().is() || (xMeta.is() && xMeta->supportsAlterTableWithDropColumn()));
+ static_cast<OColumnsHelper*>(pCol)->setParent(this);
+ pCol->setParent(*this);
+ m_pColumnMediator = new OContainerMediator( pCol, m_xColumnDefinitions );
+ pCol->setMediator( m_pColumnMediator.get() );
+ return pCol;
+}
+
+sdbcx::OCollection* ODBTable::createKeys(const ::std::vector< OUString>& _rNames)
+{
+ return new connectivity::OKeysHelper(this,m_aMutex,_rNames);
+}
+
+sdbcx::OCollection* ODBTable::createIndexes(const ::std::vector< OUString>& _rNames)
+{
+ return new OIndexes(this,m_aMutex,_rNames,nullptr);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/api/tablecontainer.cxx b/dbaccess/source/core/api/tablecontainer.cxx
new file mode 100644
index 000000000..3971dd154
--- /dev/null
+++ b/dbaccess/source/core/api/tablecontainer.cxx
@@ -0,0 +1,456 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <tablecontainer.hxx>
+#include <table.hxx>
+#include <comphelper/property.hxx>
+#include <comphelper/processfactory.hxx>
+#include <core_resource.hxx>
+#include <strings.hrc>
+#include <strings.hxx>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/beans/PropertyState.hpp>
+#include <com/sun/star/beans/XPropertyState.hpp>
+#include <com/sun/star/sdb/TableDefinition.hpp>
+#include <com/sun/star/sdbc/XConnection.hpp>
+#include <com/sun/star/sdbc/XDatabaseMetaData.hpp>
+#include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
+#include <com/sun/star/sdbc/XRow.hpp>
+#include <com/sun/star/sdbc/SQLException.hpp>
+#include <comphelper/types.hxx>
+#include <connectivity/dbtools.hxx>
+#include <connectivity/dbexception.hxx>
+#include <TableDeco.hxx>
+#include <sdbcoretools.hxx>
+#include <ContainerMediator.hxx>
+#include <objectnameapproval.hxx>
+#include <tools/diagnose_ex.h>
+
+using namespace dbaccess;
+using namespace dbtools;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::sdb;
+using namespace ::com::sun::star::sdbcx;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::util;
+using namespace ::osl;
+using namespace ::comphelper;
+using namespace ::cppu;
+using namespace ::connectivity::sdbcx;
+
+namespace
+{
+ bool lcl_isPropertySetDefaulted(const Sequence< OUString>& _aNames,const Reference<XPropertySet>& _xProp)
+ {
+ Reference<XPropertyState> xState(_xProp,UNO_QUERY);
+ if ( !xState )
+ return false;
+ const OUString* pIter = _aNames.getConstArray();
+ const OUString* pEnd = pIter + _aNames.getLength();
+ for(;pIter != pEnd;++pIter)
+ {
+ try
+ {
+ PropertyState aState = xState->getPropertyState(*pIter);
+ if ( aState != PropertyState_DEFAULT_VALUE )
+ break;
+ }
+ catch(const Exception&)
+ {
+ TOOLS_WARN_EXCEPTION("dbaccess", "" );
+ }
+ }
+ return ( pIter == pEnd );
+ }
+}
+
+// OTableContainer
+
+OTableContainer::OTableContainer(::cppu::OWeakObject& _rParent,
+ ::osl::Mutex& _rMutex,
+ const Reference< XConnection >& _xCon,
+ bool _bCase,
+ const Reference< XNameContainer >& _xTableDefinitions,
+ IRefreshListener* _pRefreshListener,
+ std::atomic<std::size_t>& _nInAppend)
+ :OFilteredContainer(_rParent,_rMutex,_xCon,_bCase,_pRefreshListener,_nInAppend)
+ ,m_xTableDefinitions(_xTableDefinitions)
+{
+}
+
+OTableContainer::~OTableContainer()
+{
+}
+
+void OTableContainer::removeMasterContainerListener()
+{
+ try
+ {
+ Reference<XContainer> xCont( m_xMasterContainer, UNO_QUERY_THROW );
+ xCont->removeContainerListener( this );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+}
+
+OUString OTableContainer::getTableTypeRestriction() const
+{
+ // no restriction at all (other than the ones provided externally)
+ return OUString();
+}
+
+// XServiceInfo
+OUString SAL_CALL OTableContainer::getImplementationName()
+ {
+ return "com.sun.star.sdb.dbaccess.OTableContainer";
+ }
+sal_Bool SAL_CALL OTableContainer::supportsService(const OUString& _rServiceName)
+ {
+ const css::uno::Sequence< OUString > aSupported(getSupportedServiceNames());
+ for (const OUString& s : aSupported)
+ if (s == _rServiceName)
+ return true;
+
+ return false;
+ }
+css::uno::Sequence< OUString > SAL_CALL OTableContainer::getSupportedServiceNames()
+{
+ return { SERVICE_SDBCX_CONTAINER, SERVICE_SDBCX_TABLES };
+}
+
+
+namespace
+{
+void lcl_createDefinitionObject(const OUString& _rName
+ ,const Reference< XNameContainer >& _xTableDefinitions
+ ,Reference<XPropertySet>& _xTableDefinition
+ ,Reference<XNameAccess>& _xColumnDefinitions)
+{
+ if ( !_xTableDefinitions.is() )
+ return;
+
+ if ( _xTableDefinitions->hasByName(_rName) )
+ _xTableDefinition.set(_xTableDefinitions->getByName(_rName),UNO_QUERY);
+ else
+ {
+ // set as folder
+ _xTableDefinition = TableDefinition::createWithName( ::comphelper::getProcessComponentContext(), _rName );
+ _xTableDefinitions->insertByName(_rName,Any(_xTableDefinition));
+ }
+ Reference<XColumnsSupplier> xColumnsSupplier(_xTableDefinition,UNO_QUERY);
+ if ( xColumnsSupplier.is() )
+ _xColumnDefinitions = xColumnsSupplier->getColumns();
+}
+
+}
+
+connectivity::sdbcx::ObjectType OTableContainer::createObject(const OUString& _rName)
+{
+ Reference<XColumnsSupplier > xSup;
+ if(m_xMasterContainer.is() && m_xMasterContainer->hasByName(_rName))
+ xSup.set(m_xMasterContainer->getByName(_rName),UNO_QUERY);
+
+ connectivity::sdbcx::ObjectType xRet;
+ if ( m_xMetaData.is() )
+ {
+ Reference<XPropertySet> xTableDefinition;
+ Reference<XNameAccess> xColumnDefinitions;
+ lcl_createDefinitionObject(_rName,m_xTableDefinitions,xTableDefinition,xColumnDefinitions);
+
+ if ( xSup.is() )
+ {
+ rtl::Reference<ODBTableDecorator> pTable = new ODBTableDecorator( m_xConnection, xSup, ::dbtools::getNumberFormats( m_xConnection ) ,xColumnDefinitions);
+ xRet = pTable;
+ pTable->construct();
+ }
+ else
+ {
+ OUString sCatalog,sSchema,sTable;
+ ::dbtools::qualifiedNameComponents(m_xMetaData,
+ _rName,
+ sCatalog,
+ sSchema,
+ sTable,
+ ::dbtools::EComposeRule::InDataManipulation);
+ Any aCatalog;
+ if(!sCatalog.isEmpty())
+ aCatalog <<= sCatalog;
+ OUString sType,sDescription;
+ Sequence< OUString> aTypeFilter;
+ getAllTableTypeFilter( aTypeFilter );
+
+ Reference< XResultSet > xRes;
+ if ( m_xMetaData.is() )
+ xRes = m_xMetaData->getTables(aCatalog,sSchema,sTable,aTypeFilter);
+ if(xRes.is() && xRes->next())
+ {
+ Reference< XRow > xRow(xRes,UNO_QUERY);
+ if(xRow.is())
+ {
+ sType = xRow->getString(4);
+ sDescription = xRow->getString(5);
+ }
+ }
+ ::comphelper::disposeComponent(xRes);
+ rtl::Reference<ODBTable> pTable = new ODBTable(this
+ ,m_xConnection
+ ,sCatalog
+ ,sSchema
+ ,sTable
+ ,sType
+ ,sDescription
+ ,xColumnDefinitions);
+ xRet = pTable;
+ pTable->construct();
+ }
+ Reference<XPropertySet> xDest(xRet,UNO_QUERY);
+ if ( xTableDefinition.is() )
+ ::comphelper::copyProperties(xTableDefinition,xDest);
+
+ if ( !m_pTableMediator.is() )
+ m_pTableMediator = new OContainerMediator(
+ this, m_xTableDefinitions );
+ if ( m_pTableMediator.is() )
+ m_pTableMediator->notifyElementCreated(_rName,xDest);
+ }
+
+ return xRet;
+}
+
+Reference< XPropertySet > OTableContainer::createDescriptor()
+{
+ Reference< XPropertySet > xRet;
+
+ // first we have to look if the master tables support this
+ // and if so then create a table object as well with the master tables
+ Reference<XColumnsSupplier > xMasterColumnsSup;
+ Reference<XDataDescriptorFactory> xDataFactory(m_xMasterContainer,UNO_QUERY);
+ if ( xDataFactory.is() && m_xMetaData.is() )
+ {
+ xMasterColumnsSup.set( xDataFactory->createDataDescriptor(), UNO_QUERY );
+ rtl::Reference<ODBTableDecorator> pTable = new ODBTableDecorator( m_xConnection, xMasterColumnsSup, ::dbtools::getNumberFormats( m_xConnection ) ,nullptr);
+ xRet = pTable;
+ pTable->construct();
+ }
+ else
+ {
+ rtl::Reference<ODBTable> pTable = new ODBTable(this, m_xConnection);
+ xRet = pTable;
+ pTable->construct();
+ }
+ return xRet;
+}
+
+// XAppend
+ObjectType OTableContainer::appendObject( const OUString& _rForName, const Reference< XPropertySet >& descriptor )
+{
+ // append the new table with a create stmt
+ OUString aName = getString(descriptor->getPropertyValue(PROPERTY_NAME));
+ if(m_xMasterContainer.is() && m_xMasterContainer->hasByName(aName))
+ {
+ OUString sMessage(DBA_RES(RID_STR_TABLE_IS_FILTERED));
+ throw SQLException(sMessage.replaceAll("$name$", aName),static_cast<XTypeProvider*>(static_cast<OFilteredContainer*>(this)),SQLSTATE_GENERAL,1000,Any());
+ }
+
+ Reference< XConnection > xConnection( m_xConnection.get(), UNO_QUERY );
+ PContainerApprove pApprove = std::make_shared<ObjectNameApproval>( xConnection, ObjectNameApproval::TypeTable );
+ pApprove->approveElement( aName );
+
+ {
+ EnsureReset aReset(m_nInAppend);
+ Reference<XAppend> xAppend(m_xMasterContainer,UNO_QUERY);
+ if(xAppend.is())
+ {
+ xAppend->appendByDescriptor(descriptor);
+ }
+ else
+ {
+ OUString aSql = ::dbtools::createSqlCreateTableStatement(descriptor,m_xConnection);
+
+ Reference<XConnection> xCon = m_xConnection;
+ OSL_ENSURE(xCon.is(),"Connection is null!");
+ if ( xCon.is() )
+ {
+ Reference< XStatement > xStmt = xCon->createStatement( );
+ if ( xStmt.is() )
+ xStmt->execute(aSql);
+ ::comphelper::disposeComponent(xStmt);
+ }
+ }
+ }
+
+ Reference<XPropertySet> xTableDefinition;
+ Reference<XNameAccess> xColumnDefinitions;
+ lcl_createDefinitionObject(getNameForObject(descriptor),m_xTableDefinitions,xTableDefinition,xColumnDefinitions);
+ Reference<XColumnsSupplier> xSup(descriptor,UNO_QUERY);
+ Reference<XDataDescriptorFactory> xFac(xColumnDefinitions,UNO_QUERY);
+ Reference<XAppend> xAppend(xColumnDefinitions,UNO_QUERY);
+ bool bModified = false;
+ if ( xSup.is() && xColumnDefinitions.is() && xFac.is() && xAppend.is() )
+ {
+ Reference<XNameAccess> xNames = xSup->getColumns();
+ if ( xNames.is() )
+ {
+ Reference<XPropertySet> xProp = xFac->createDataDescriptor();
+ Sequence< OUString> aSeq = xNames->getElementNames();
+ const OUString* pIter = aSeq.getConstArray();
+ const OUString* pEnd = pIter + aSeq.getLength();
+ for(;pIter != pEnd;++pIter)
+ {
+ if ( !xColumnDefinitions->hasByName(*pIter) )
+ {
+ Reference<XPropertySet> xColumn(xNames->getByName(*pIter),UNO_QUERY);
+ if ( !OColumnSettings::hasDefaultSettings( xColumn ) )
+ {
+ ::comphelper::copyProperties( xColumn, xProp );
+ xAppend->appendByDescriptor( xProp );
+ bModified = true;
+ }
+ }
+ }
+ }
+ }
+ Sequence< OUString> aNames{
+ PROPERTY_FILTER, PROPERTY_ORDER, PROPERTY_APPLYFILTER, PROPERTY_FONT,
+ PROPERTY_ROW_HEIGHT, PROPERTY_TEXTCOLOR, PROPERTY_TEXTLINECOLOR,
+ PROPERTY_TEXTEMPHASIS, PROPERTY_TEXTRELIEF};
+ if ( bModified || !lcl_isPropertySetDefaulted(aNames,xTableDefinition) )
+ ::dbaccess::notifyDataSourceModified(m_xTableDefinitions);
+
+ return createObject( _rForName );
+}
+
+// XDrop
+void OTableContainer::dropObject(sal_Int32 _nPos, const OUString& _sElementName)
+{
+ Reference< XDrop > xDrop(m_xMasterContainer,UNO_QUERY);
+ if(xDrop.is())
+ xDrop->dropByName(_sElementName);
+ else
+ {
+ OUString sComposedName;
+
+ bool bIsView = false;
+ Reference<XPropertySet> xTable(getObject(_nPos),UNO_QUERY);
+ if ( xTable.is() && m_xMetaData.is() )
+ {
+ OUString sSchema,sCatalog,sTable;
+ if (m_xMetaData->supportsCatalogsInTableDefinitions())
+ xTable->getPropertyValue(PROPERTY_CATALOGNAME) >>= sCatalog;
+ if (m_xMetaData->supportsSchemasInTableDefinitions())
+ xTable->getPropertyValue(PROPERTY_SCHEMANAME) >>= sSchema;
+ xTable->getPropertyValue(PROPERTY_NAME) >>= sTable;
+
+ sComposedName = ::dbtools::composeTableName( m_xMetaData, sCatalog, sSchema, sTable, true, ::dbtools::EComposeRule::InTableDefinitions );
+
+ OUString sType;
+ xTable->getPropertyValue(PROPERTY_TYPE) >>= sType;
+ bIsView = sType.equalsIgnoreAsciiCase("VIEW");
+ }
+
+ if(sComposedName.isEmpty())
+ ::dbtools::throwFunctionSequenceException(static_cast<XTypeProvider*>(static_cast<OFilteredContainer*>(this)));
+
+ OUString aSql("DROP ");
+
+ if ( bIsView ) // here we have a view
+ aSql += "VIEW ";
+ else
+ aSql += "TABLE ";
+ aSql += sComposedName;
+ Reference<XConnection> xCon = m_xConnection;
+ OSL_ENSURE(xCon.is(),"Connection is null!");
+ if ( xCon.is() )
+ {
+ Reference< XStatement > xStmt = xCon->createStatement( );
+ if(xStmt.is())
+ xStmt->execute(aSql);
+ ::comphelper::disposeComponent(xStmt);
+ }
+ }
+
+ if ( m_xTableDefinitions.is() && m_xTableDefinitions->hasByName(_sElementName) )
+ {
+ m_xTableDefinitions->removeByName(_sElementName);
+ }
+}
+
+void SAL_CALL OTableContainer::elementInserted( const ContainerEvent& Event )
+{
+ ::osl::MutexGuard aGuard(m_rMutex);
+ OUString sName;
+ Event.Accessor >>= sName;
+ if ( !m_nInAppend && !hasByName(sName) )
+ {
+ if(!m_xMasterContainer.is() || m_xMasterContainer->hasByName(sName))
+ {
+ ObjectType xName = createObject(sName);
+ insertElement(sName,xName);
+ // and notify our listeners
+ ContainerEvent aEvent(static_cast<XContainer*>(this), Any(sName), Any(xName), Any());
+ m_aContainerListeners.notifyEach( &XContainerListener::elementInserted, aEvent );
+ }
+ }
+}
+
+void SAL_CALL OTableContainer::elementRemoved( const ContainerEvent& /*Event*/ )
+{
+}
+
+void SAL_CALL OTableContainer::elementReplaced( const ContainerEvent& Event )
+{
+ // create a new config entry
+ OUString sOldComposedName,sNewComposedName;
+ Event.ReplacedElement >>= sOldComposedName;
+ Event.Accessor >>= sNewComposedName;
+
+ renameObject(sOldComposedName,sNewComposedName);
+}
+
+void OTableContainer::disposing()
+{
+ OFilteredContainer::disposing();
+ // say goodbye to our listeners
+ m_xTableDefinitions = nullptr;
+ m_pTableMediator = nullptr;
+}
+
+void SAL_CALL OTableContainer::disposing( const css::lang::EventObject& /*Source*/ )
+{
+}
+
+void OTableContainer::addMasterContainerListener()
+{
+ try
+ {
+ Reference< XContainer > xCont( m_xMasterContainer, UNO_QUERY_THROW );
+ xCont->addContainerListener( this );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/api/viewcontainer.cxx b/dbaccess/source/core/api/viewcontainer.cxx
new file mode 100644
index 000000000..462a3b1d0
--- /dev/null
+++ b/dbaccess/source/core/api/viewcontainer.cxx
@@ -0,0 +1,254 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <strings.hxx>
+#include <viewcontainer.hxx>
+#include <View.hxx>
+
+#include <comphelper/types.hxx>
+#include <connectivity/dbtools.hxx>
+#include <connectivity/dbexception.hxx>
+
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/sdbc/XConnection.hpp>
+
+using namespace dbaccess;
+using namespace dbtools;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::sdb;
+using namespace ::com::sun::star::sdbcx;
+using namespace ::com::sun::star::util;
+using namespace ::com::sun::star::container;
+using namespace ::osl;
+using namespace ::comphelper;
+using namespace ::cppu;
+using namespace ::connectivity::sdbcx;
+
+// OViewContainer
+
+OViewContainer::OViewContainer(::cppu::OWeakObject& _rParent
+ ,::osl::Mutex& _rMutex
+ ,const Reference< XConnection >& _xCon
+ ,bool _bCase
+ ,IRefreshListener* _pRefreshListener
+ ,std::atomic<std::size_t>& _nInAppend)
+ :OFilteredContainer(_rParent,_rMutex,_xCon,_bCase,_pRefreshListener,_nInAppend)
+ ,m_bInElementRemoved(false)
+{
+}
+
+OViewContainer::~OViewContainer()
+{
+}
+
+// XServiceInfo
+OUString SAL_CALL OViewContainer::getImplementationName()
+ {
+ return "com.sun.star.sdb.dbaccess.OViewContainer";
+ }
+sal_Bool SAL_CALL OViewContainer::supportsService(const OUString& _rServiceName)
+ {
+ const css::uno::Sequence< OUString > aSupported(getSupportedServiceNames());
+ for (const OUString& s : aSupported)
+ if (s == _rServiceName)
+ return true;
+
+ return false;
+ }
+css::uno::Sequence< OUString > SAL_CALL OViewContainer::getSupportedServiceNames()
+{
+ return { SERVICE_SDBCX_CONTAINER, SERVICE_SDBCX_TABLES };
+}
+
+
+ObjectType OViewContainer::createObject(const OUString& _rName)
+{
+ ObjectType xProp;
+ if ( m_xMasterContainer.is() && m_xMasterContainer->hasByName(_rName) )
+ xProp.set(m_xMasterContainer->getByName(_rName),UNO_QUERY);
+
+ if ( !xProp.is() )
+ {
+ OUString sCatalog,sSchema,sTable;
+ ::dbtools::qualifiedNameComponents(m_xMetaData,
+ _rName,
+ sCatalog,
+ sSchema,
+ sTable,
+ ::dbtools::EComposeRule::InDataManipulation);
+ return new View(m_xConnection,
+ isCaseSensitive(),
+ sCatalog,
+ sSchema,
+ sTable
+ );
+ }
+
+ return xProp;
+}
+
+Reference< XPropertySet > OViewContainer::createDescriptor()
+{
+ Reference< XPropertySet > xRet;
+ // first we have to look if the master tables support this
+ // and if so then create a table object as well with the master tables
+ Reference<XDataDescriptorFactory> xDataFactory(m_xMasterContainer,UNO_QUERY);
+ if(xDataFactory.is())
+ xRet = xDataFactory->createDataDescriptor();
+ else
+ xRet = new ::connectivity::sdbcx::OView(isCaseSensitive(),m_xMetaData);
+
+ return xRet;
+}
+
+// XAppend
+ObjectType OViewContainer::appendObject( const OUString& _rForName, const Reference< XPropertySet >& descriptor )
+{
+ // append the new table with a create stmt
+ OUString aName = getString(descriptor->getPropertyValue(PROPERTY_NAME));
+
+ Reference<XAppend> xAppend(m_xMasterContainer,UNO_QUERY);
+ Reference< XPropertySet > xProp = descriptor;
+ if(xAppend.is())
+ {
+ EnsureReset aReset(m_nInAppend);
+
+ xAppend->appendByDescriptor(descriptor);
+ if(m_xMasterContainer->hasByName(aName))
+ xProp.set(m_xMasterContainer->getByName(aName),UNO_QUERY);
+ }
+ else
+ {
+ OUString sComposedName = ::dbtools::composeTableName( m_xMetaData, descriptor, ::dbtools::EComposeRule::InTableDefinitions, true );
+ if(sComposedName.isEmpty())
+ ::dbtools::throwFunctionSequenceException(static_cast<XTypeProvider*>(static_cast<OFilteredContainer*>(this)));
+
+ OUString sCommand;
+ descriptor->getPropertyValue(PROPERTY_COMMAND) >>= sCommand;
+
+ OUString aSQL = "CREATE VIEW " + sComposedName + " AS " + sCommand;
+
+ Reference<XConnection> xCon = m_xConnection;
+ OSL_ENSURE(xCon.is(),"Connection is null!");
+ if ( xCon.is() )
+ {
+ ::utl::SharedUNOComponent< XStatement > xStmt( xCon->createStatement() );
+ if ( xStmt.is() )
+ xStmt->execute( aSQL );
+ }
+ }
+
+ return createObject( _rForName );
+}
+
+// XDrop
+void OViewContainer::dropObject(sal_Int32 _nPos, const OUString& _sElementName)
+{
+ if ( m_bInElementRemoved )
+ return;
+
+ Reference< XDrop > xDrop(m_xMasterContainer,UNO_QUERY);
+ if(xDrop.is())
+ xDrop->dropByName(_sElementName);
+ else
+ {
+ OUString sComposedName;
+
+ Reference<XPropertySet> xTable(getObject(_nPos),UNO_QUERY);
+ if ( xTable.is() )
+ {
+ OUString sCatalog,sSchema,sTable;
+ xTable->getPropertyValue(PROPERTY_CATALOGNAME) >>= sCatalog;
+ xTable->getPropertyValue(PROPERTY_SCHEMANAME) >>= sSchema;
+ xTable->getPropertyValue(PROPERTY_NAME) >>= sTable;
+
+ sComposedName = ::dbtools::composeTableName( m_xMetaData, sCatalog, sSchema, sTable, true, ::dbtools::EComposeRule::InTableDefinitions );
+ }
+
+ if(sComposedName.isEmpty())
+ ::dbtools::throwFunctionSequenceException(static_cast<XTypeProvider*>(static_cast<OFilteredContainer*>(this)));
+
+ OUString aSql = "DROP VIEW " + sComposedName;
+ Reference<XConnection> xCon = m_xConnection;
+ OSL_ENSURE(xCon.is(),"Connection is null!");
+ if ( xCon.is() )
+ {
+ Reference< XStatement > xStmt = xCon->createStatement( );
+ if(xStmt.is())
+ xStmt->execute(aSql);
+ ::comphelper::disposeComponent(xStmt);
+ }
+ }
+}
+
+void SAL_CALL OViewContainer::elementInserted( const ContainerEvent& Event )
+{
+ ::osl::MutexGuard aGuard(m_rMutex);
+ OUString sName;
+ if ( ( Event.Accessor >>= sName )
+ && ( !m_nInAppend )
+ && ( !hasByName( sName ) )
+ )
+ {
+ Reference<XPropertySet> xProp(Event.Element,UNO_QUERY);
+ OUString sType;
+ xProp->getPropertyValue(PROPERTY_TYPE) >>= sType;
+ if ( sType == "VIEW" )
+ insertElement(sName,createObject(sName));
+ }
+}
+
+void SAL_CALL OViewContainer::elementRemoved( const ContainerEvent& Event )
+{
+ ::osl::MutexGuard aGuard(m_rMutex);
+ OUString sName;
+ if ( !((Event.Accessor >>= sName) && hasByName(sName)) )
+ return;
+
+ m_bInElementRemoved = true;
+ try
+ {
+ dropByName(sName);
+ }
+ catch(Exception&)
+ {
+ m_bInElementRemoved = false;
+ throw;
+ }
+ m_bInElementRemoved = false;
+}
+
+void SAL_CALL OViewContainer::disposing( const css::lang::EventObject& /*Source*/ )
+{
+}
+
+void SAL_CALL OViewContainer::elementReplaced( const ContainerEvent& /*Event*/ )
+{
+}
+
+OUString OViewContainer::getTableTypeRestriction() const
+{
+ // no restriction at all (other than the ones provided externally)
+ return "VIEW";
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/dataaccess/ComponentDefinition.cxx b/dbaccess/source/core/dataaccess/ComponentDefinition.cxx
new file mode 100644
index 000000000..a3a645982
--- /dev/null
+++ b/dbaccess/source/core/dataaccess/ComponentDefinition.cxx
@@ -0,0 +1,285 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "ComponentDefinition.hxx"
+#include <stringconstants.hxx>
+#include <strings.hxx>
+
+#include <osl/diagnose.h>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+//#include <cppuhelper/interfacecontainer.hxx>
+#include <comphelper/property.hxx>
+#include <comphelper/propertysequence.hxx>
+#include <definitioncolumn.hxx>
+
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::container;
+using namespace ::cppu;
+
+namespace dbaccess
+{
+
+/// helper class for column property change events which holds the OComponentDefinition weak
+class OColumnPropertyListener:
+ public ::cppu::WeakImplHelper< XPropertyChangeListener >
+{
+ OComponentDefinition* m_pComponent;
+protected:
+ virtual ~OColumnPropertyListener() override {}
+public:
+ explicit OColumnPropertyListener(OComponentDefinition* _pComponent) : m_pComponent(_pComponent){}
+ OColumnPropertyListener(const OColumnPropertyListener&) = delete;
+ const OColumnPropertyListener& operator=(const OColumnPropertyListener&) = delete;
+ // XPropertyChangeListener
+ virtual void SAL_CALL propertyChange( const PropertyChangeEvent& /*_rEvent*/ ) override
+ {
+ if ( m_pComponent )
+ m_pComponent->notifyDataSourceModified();
+ }
+ // XEventListener
+ virtual void SAL_CALL disposing( const EventObject& /*_rSource*/ ) override
+ {
+ }
+ void clear() { m_pComponent = nullptr; }
+};
+
+OComponentDefinition_Impl::OComponentDefinition_Impl()
+{
+}
+
+OComponentDefinition_Impl::~OComponentDefinition_Impl()
+{
+}
+
+// OComponentDefinition
+
+
+void OComponentDefinition::initialize( const Sequence< Any >& aArguments )
+{
+ OUString rName;
+ if( (aArguments.getLength() == 1) && (aArguments[0] >>= rName) )
+ {
+ Sequence<Any> aNewArgs(comphelper::InitAnyPropertySequence(
+ {
+ {PROPERTY_NAME, Any(rName)}
+ }));
+ OContentHelper::initialize(aNewArgs);
+ }
+ else
+ OContentHelper::initialize(aArguments);
+}
+
+void OComponentDefinition::registerProperties()
+{
+ m_xColumnPropertyListener = new OColumnPropertyListener(this);
+ OComponentDefinition_Impl& rDefinition( getDefinition() );
+ ODataSettings::registerPropertiesFor( &rDefinition );
+
+ registerProperty(PROPERTY_NAME, PROPERTY_ID_NAME, PropertyAttribute::BOUND | PropertyAttribute::READONLY|PropertyAttribute::CONSTRAINED,
+ &rDefinition.m_aProps.aTitle, cppu::UnoType<decltype(rDefinition.m_aProps.aTitle)>::get());
+
+ if ( m_bTable )
+ {
+ registerProperty(PROPERTY_SCHEMANAME, PROPERTY_ID_SCHEMANAME, PropertyAttribute::BOUND,
+ &rDefinition.m_sSchemaName, cppu::UnoType<decltype(rDefinition.m_sSchemaName)>::get());
+
+ registerProperty(PROPERTY_CATALOGNAME, PROPERTY_ID_CATALOGNAME, PropertyAttribute::BOUND,
+ &rDefinition.m_sCatalogName, cppu::UnoType<decltype(rDefinition.m_sCatalogName)>::get());
+ }
+}
+
+OComponentDefinition::OComponentDefinition(const Reference< XComponentContext >& _xORB
+ ,const Reference< XInterface >& _xParentContainer
+ ,const TContentPtr& _pImpl
+ ,bool _bTable)
+ :OContentHelper(_xORB,_xParentContainer,_pImpl)
+ ,ODataSettings(OContentHelper::rBHelper,!_bTable)
+ ,m_bTable(_bTable)
+{
+ registerProperties();
+}
+
+OComponentDefinition::~OComponentDefinition()
+{
+}
+
+OComponentDefinition::OComponentDefinition( const Reference< XInterface >& _rxContainer
+ ,const OUString& _rElementName
+ ,const Reference< XComponentContext >& _xORB
+ ,const TContentPtr& _pImpl
+ ,bool _bTable)
+ :OContentHelper(_xORB,_rxContainer,_pImpl)
+ ,ODataSettings(OContentHelper::rBHelper,!_bTable)
+ ,m_bTable(_bTable)
+{
+ registerProperties();
+
+ m_pImpl->m_aProps.aTitle = _rElementName;
+ OSL_ENSURE(!m_pImpl->m_aProps.aTitle.isEmpty(), "OComponentDefinition::OComponentDefinition : invalid name !");
+}
+
+css::uno::Sequence<sal_Int8> OComponentDefinition::getImplementationId()
+{
+ return css::uno::Sequence<sal_Int8>();
+}
+
+css::uno::Sequence< css::uno::Type > OComponentDefinition::getTypes()
+{
+ return ::comphelper::concatSequences(
+ ODataSettings::getTypes( ),
+ OContentHelper::getTypes( ),
+ OComponentDefinition_BASE::getTypes( )
+ );
+}
+IMPLEMENT_FORWARD_XINTERFACE3( OComponentDefinition,OContentHelper,ODataSettings,OComponentDefinition_BASE)
+
+OUString SAL_CALL OComponentDefinition::getImplementationName()
+{
+ return "com.sun.star.comp.dba.OComponentDefinition";
+}
+
+Sequence< OUString > SAL_CALL OComponentDefinition::getSupportedServiceNames()
+{
+ return { "com.sun.star.sdb.TableDefinition", "com.sun.star.ucb.Content" };
+}
+
+void SAL_CALL OComponentDefinition::disposing()
+{
+ OContentHelper::disposing();
+ if (m_pColumns)
+ {
+ m_pColumns->disposing();
+ }
+ m_xColumnPropertyListener->clear();
+ m_xColumnPropertyListener.clear();
+}
+
+IPropertyArrayHelper& OComponentDefinition::getInfoHelper()
+{
+ return *getArrayHelper();
+}
+
+IPropertyArrayHelper* OComponentDefinition::createArrayHelper( ) const
+{
+ Sequence< Property > aProps;
+ describeProperties(aProps);
+ return new OPropertyArrayHelper(aProps);
+}
+
+Reference< XPropertySetInfo > SAL_CALL OComponentDefinition::getPropertySetInfo( )
+{
+ Reference<XPropertySetInfo> xInfo( createPropertySetInfo( getInfoHelper() ) );
+ return xInfo;
+}
+
+OUString OComponentDefinition::determineContentType() const
+{
+ return m_bTable
+ ? OUString( "application/vnd.org.openoffice.DatabaseTable" )
+ : OUString( "application/vnd.org.openoffice.DatabaseCommandDefinition" );
+}
+
+Reference< XNameAccess> OComponentDefinition::getColumns()
+{
+ ::osl::MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(OContentHelper::rBHelper.bDisposed);
+
+ if (!m_pColumns)
+ {
+ std::vector< OUString> aNames;
+
+ const OComponentDefinition_Impl& rDefinition( getDefinition() );
+ aNames.reserve( rDefinition.size() );
+
+ for (auto const& definition : rDefinition)
+ aNames.push_back(definition.first);
+
+ m_pColumns.reset(new OColumns(*this, m_aMutex, true, aNames, this, nullptr, true, false, false));
+ m_pColumns->setParent(*this);
+ }
+ // see OCollection::acquire
+ return m_pColumns.get();
+}
+
+rtl::Reference<OColumn> OComponentDefinition::createColumn(const OUString& _rName) const
+{
+ const OComponentDefinition_Impl& rDefinition( getDefinition() );
+ OComponentDefinition_Impl::const_iterator aFind = rDefinition.find( _rName );
+ if ( aFind != rDefinition.end() )
+ {
+ aFind->second->addPropertyChangeListener(OUString(),m_xColumnPropertyListener);
+ return new OTableColumnWrapper( aFind->second, aFind->second, true );
+ }
+ OSL_FAIL( "OComponentDefinition::createColumn: is this a valid case?" );
+ // This here is the last place creating a OTableColumn, and somehow /me thinks it is not needed ...
+ return new OTableColumn( _rName );
+}
+
+Reference< XPropertySet > OComponentDefinition::createColumnDescriptor()
+{
+ return new OTableColumnDescriptor( true );
+}
+
+void OComponentDefinition::setFastPropertyValue_NoBroadcast(sal_Int32 nHandle,const Any& rValue)
+{
+ ODataSettings::setFastPropertyValue_NoBroadcast(nHandle,rValue);
+ notifyDataSourceModified();
+}
+
+void OComponentDefinition::columnDropped(const OUString& _sName)
+{
+ getDefinition().erase( _sName );
+ notifyDataSourceModified();
+}
+
+void OComponentDefinition::columnAppended( const Reference< XPropertySet >& _rxSourceDescriptor )
+{
+ OUString sName;
+ _rxSourceDescriptor->getPropertyValue( PROPERTY_NAME ) >>= sName;
+
+ Reference<XPropertySet> xColDesc = new OTableColumnDescriptor( true );
+ ::comphelper::copyProperties( _rxSourceDescriptor, xColDesc );
+ getDefinition().insert( sName, xColDesc );
+
+ // formerly, here was a setParent at the xColDesc. The parent used was an adapter (ChildHelper_Impl)
+ // which held another XChild weak, and forwarded all getParent requests to this other XChild.
+ // m_pColumns was used for this. This was nonsense, since m_pColumns dies when our instance dies,
+ // but xColDesc will live longer than this. So effectively, the setParent call was pretty useless.
+ //
+ // The intention for this parenting was that the column descriptor is able to find the data source,
+ // by traveling up the parent hierarchy until there's an XDataSource. This didn't work (which
+ // for instance causes #i65023#). We need another way to properly ensure this.
+
+ notifyDataSourceModified();
+}
+
+} // namespace dbaccess
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+com_sun_star_comp_dba_OComponentDefinition(css::uno::XComponentContext* context,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new dbaccess::OComponentDefinition(
+ context, nullptr, std::make_shared<dbaccess::OComponentDefinition_Impl>()));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/dataaccess/ComponentDefinition.hxx b/dbaccess/source/core/dataaccess/ComponentDefinition.hxx
new file mode 100644
index 000000000..4c10a5354
--- /dev/null
+++ b/dbaccess/source/core/dataaccess/ComponentDefinition.hxx
@@ -0,0 +1,159 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <commandbase.hxx>
+#include <com/sun/star/sdbcx/XRename.hpp>
+#include <cppuhelper/implbase1.hxx>
+#include <comphelper/proparrhlp.hxx>
+#include <rtl/ref.hxx>
+#include <datasettings.hxx>
+#include <com/sun/star/container/XNameAccess.hpp>
+#include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
+#include <com/sun/star/beans/XPropertyChangeListener.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <ContentHelper.hxx>
+#include <apitools.hxx>
+#include <column.hxx>
+
+#include <memory>
+namespace dbaccess
+{
+
+ typedef ::cppu::ImplHelper1< css::sdbcx::XColumnsSupplier > OComponentDefinition_BASE;
+
+ class OComponentDefinition_Impl : public OContentHelper_Impl
+ ,public ODataSettings_Base
+ {
+ public:
+ typedef std::map < OUString
+ , css::uno::Reference< css::beans::XPropertySet >
+ > Columns;
+ typedef Columns::iterator iterator;
+ typedef Columns::const_iterator const_iterator;
+
+ private:
+ Columns m_aColumns;
+
+ public:
+ OUString m_sSchemaName;
+ OUString m_sCatalogName;
+
+ public:
+ OComponentDefinition_Impl();
+ virtual ~OComponentDefinition_Impl() override;
+
+ size_t size() const { return m_aColumns.size(); }
+
+ const_iterator begin() const { return m_aColumns.begin(); }
+ const_iterator end() const { return m_aColumns.end(); }
+
+ const_iterator find( const OUString& _rName ) const { return m_aColumns.find( _rName ); }
+
+ void erase( const OUString& _rName ) { m_aColumns.erase( _rName ); }
+
+ void insert( const OUString& _rName, const css::uno::Reference< css::beans::XPropertySet >& _rxColumn )
+ {
+ OSL_PRECOND( m_aColumns.find( _rName ) == m_aColumns.end(), "OComponentDefinition_Impl::insert: there's already an element with this name!" );
+ m_aColumns.emplace( _rName, _rxColumn );
+ }
+ };
+
+class OColumnPropertyListener;
+// OComponentDefinition - a database "document" which describes a query
+class OComponentDefinition :public OContentHelper
+ ,public ODataSettings
+ ,public IColumnFactory
+ ,public OComponentDefinition_BASE
+ ,public ::comphelper::OPropertyArrayUsageHelper< OComponentDefinition >
+{
+ // no Reference! see OCollection::acquire
+ std::unique_ptr<OColumns> m_pColumns;
+ rtl::Reference<OColumnPropertyListener> m_xColumnPropertyListener;
+ bool m_bTable;
+
+protected:
+ virtual ~OComponentDefinition() override;
+ virtual void SAL_CALL disposing() override;
+
+ const OComponentDefinition_Impl& getDefinition() const { return dynamic_cast< const OComponentDefinition_Impl& >( *m_pImpl ); }
+ OComponentDefinition_Impl& getDefinition() { return dynamic_cast< OComponentDefinition_Impl& >( *m_pImpl ); }
+public:
+ OComponentDefinition(
+ const css::uno::Reference< css::uno::XComponentContext >&,
+ const css::uno::Reference< css::uno::XInterface >& _xParentContainer,
+ const TContentPtr& _pImpl,
+ bool _bTable = true);
+
+ OComponentDefinition(
+ const css::uno::Reference< css::uno::XInterface >& _rxContainer
+ ,const OUString& _rElementName
+ ,const css::uno::Reference< css::uno::XComponentContext >&
+ ,const TContentPtr& _pImpl
+ ,bool _bTable = true
+ );
+
+ virtual css::uno::Sequence<css::uno::Type> SAL_CALL getTypes() override;
+ virtual css::uno::Sequence<sal_Int8> SAL_CALL getImplementationId() override;
+
+// css::uno::XInterface
+ DECLARE_XINTERFACE( )
+
+ // css::lang::XServiceInfo
+ virtual OUString SAL_CALL getImplementationName( ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override;
+
+ // XInitialization
+ virtual void SAL_CALL initialize( css::uno::Sequence< css::uno::Any > const & rArguments) override;
+
+ // css::beans::XPropertySet
+ virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo( ) override;
+
+ // XColumnsSupplier
+ virtual css::uno::Reference< css::container::XNameAccess > SAL_CALL getColumns( ) override;
+
+ // OPropertySetHelper
+ virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper() override;
+
+ // IColumnFactory
+ virtual rtl::Reference<OColumn> createColumn(const OUString& _rName) const override;
+ virtual css::uno::Reference< css::beans::XPropertySet > createColumnDescriptor() override;
+ virtual void columnAppended( const css::uno::Reference< css::beans::XPropertySet >& _rxSourceDescriptor ) override;
+ virtual void columnDropped(const OUString& _sName) override;
+ using OContentHelper::notifyDataSourceModified;
+
+protected:
+// OPropertyArrayUsageHelper
+ virtual ::cppu::IPropertyArrayHelper* createArrayHelper( ) const override;
+
+ virtual void SAL_CALL setFastPropertyValue_NoBroadcast(
+ sal_Int32 nHandle,
+ const css::uno::Any& rValue) override;
+
+ // OContentHelper overridables
+ virtual OUString determineContentType() const override;
+
+private:
+ void registerProperties();
+};
+
+} // namespace dbaccess
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/dataaccess/ContentHelper.cxx b/dbaccess/source/core/dataaccess/ContentHelper.cxx
new file mode 100644
index 000000000..558dd7450
--- /dev/null
+++ b/dbaccess/source/core/dataaccess/ContentHelper.cxx
@@ -0,0 +1,615 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <ContentHelper.hxx>
+#include <rtl/ref.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <ucbhelper/cancelcommandexecution.hxx>
+#include <com/sun/star/ucb/UnsupportedCommandException.hpp>
+#include <com/sun/star/lang/IllegalArgumentException.hpp>
+#include <com/sun/star/lang/IllegalAccessException.hpp>
+#include <com/sun/star/beans/IllegalTypeException.hpp>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/beans/PropertyValue.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/container/ElementExistException.hpp>
+#include <ucbhelper/propertyvalueset.hxx>
+#include <ucbhelper/contentidentifier.hxx>
+#include <comphelper/servicehelper.hxx>
+#include <tools/diagnose_ex.h>
+#include <sdbcoretools.hxx>
+#include <stringconstants.hxx>
+#include <strings.hxx>
+
+#include <map>
+
+namespace dbaccess
+{
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::ucb;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::io;
+using namespace ::com::sun::star::util;
+using namespace ::com::sun::star::embed;
+using namespace ::com::sun::star::container;
+using namespace ::cppu;
+
+OContentHelper_Impl::OContentHelper_Impl()
+ : m_pDataSource(nullptr)
+{
+}
+
+OContentHelper_Impl::~OContentHelper_Impl()
+{
+}
+
+OContentHelper::OContentHelper(const Reference< XComponentContext >& _xORB
+ ,const Reference< XInterface >& _xParentContainer
+ ,const TContentPtr& _pImpl)
+ : OContentHelper_COMPBASE(m_aMutex)
+ ,m_aContentListeners(m_aMutex)
+ ,m_aPropertyChangeListeners(m_aMutex)
+ ,m_xParentContainer( _xParentContainer )
+ ,m_aContext( _xORB )
+ ,m_pImpl(_pImpl)
+ ,m_nCommandId(0)
+{
+}
+
+void SAL_CALL OContentHelper::disposing()
+{
+ ::osl::MutexGuard aGuard(m_aMutex);
+
+ // say goodbye to our listeners
+ EventObject aEvt(*this);
+ m_aContentListeners.disposeAndClear(aEvt);
+
+ m_xParentContainer = nullptr;
+}
+
+OUString SAL_CALL OContentHelper::getImplementationName()
+ {
+ return "com.sun.star.comp.sdb.Content";
+ }
+sal_Bool SAL_CALL OContentHelper::supportsService(const OUString& _rServiceName)
+ {
+ const css::uno::Sequence< OUString > aSupported(getSupportedServiceNames());
+ for (const OUString& s : aSupported)
+ if (s == _rServiceName)
+ return true;
+
+ return false;
+ }
+css::uno::Sequence< OUString > SAL_CALL OContentHelper::getSupportedServiceNames()
+{
+ return { "com.sun.star.ucb.Content" };
+}
+
+
+const css::uno::Sequence<sal_Int8> & OContentHelper::getUnoTunnelId()
+{
+ static const comphelper::UnoIdInit aId;
+ return aId.getSeq();
+}
+
+css::uno::Sequence<sal_Int8> OContentHelper::getImplementationId()
+{
+ return css::uno::Sequence<sal_Int8>();
+}
+
+// XContent
+Reference< XContentIdentifier > SAL_CALL OContentHelper::getIdentifier( )
+{
+ ::osl::MutexGuard aGuard(m_aMutex);
+ OUString aIdentifier( "private:" + impl_getHierarchicalName( true ) );
+ return new ::ucbhelper::ContentIdentifier( aIdentifier );
+}
+
+OUString OContentHelper::impl_getHierarchicalName( bool _includingRootContainer ) const
+{
+ OUStringBuffer aHierarchicalName( m_pImpl->m_aProps.aTitle );
+ Reference< XInterface > xParent = m_xParentContainer;
+ while( xParent.is() )
+ {
+ Reference<XPropertySet> xProp( xParent, UNO_QUERY );
+ Reference< XChild > xChild( xParent, UNO_QUERY );
+ xParent.set( xChild.is() ? xChild->getParent() : Reference< XInterface >(), UNO_QUERY );
+ if ( xProp.is() && xParent.is() )
+ {
+ OUString sName;
+ xProp->getPropertyValue( PROPERTY_NAME ) >>= sName;
+
+ OUString sPrevious = aHierarchicalName.makeStringAndClear();
+ aHierarchicalName.append( sName + "/" + sPrevious );
+ }
+ }
+ OUString sHierarchicalName( aHierarchicalName.makeStringAndClear() );
+ if ( !_includingRootContainer )
+ sHierarchicalName = sHierarchicalName.copy( sHierarchicalName.indexOf( '/' ) + 1 );
+ return sHierarchicalName;
+}
+
+OUString SAL_CALL OContentHelper::getContentType()
+{
+ ::osl::MutexGuard aGuard(m_aMutex);
+
+ if ( !m_pImpl->m_aProps.aContentType )
+ { // content type not yet retrieved
+ m_pImpl->m_aProps.aContentType = determineContentType();
+ }
+
+ return *m_pImpl->m_aProps.aContentType;
+}
+
+void SAL_CALL OContentHelper::addContentEventListener( const Reference< XContentEventListener >& _rxListener )
+{
+ ::osl::MutexGuard aGuard(m_aMutex);
+ if ( _rxListener.is() )
+ m_aContentListeners.addInterface(_rxListener);
+}
+
+void SAL_CALL OContentHelper::removeContentEventListener( const Reference< XContentEventListener >& _rxListener )
+{
+ ::osl::MutexGuard aGuard(m_aMutex);
+ if (_rxListener.is())
+ m_aContentListeners.removeInterface(_rxListener);
+}
+
+// XCommandProcessor
+sal_Int32 SAL_CALL OContentHelper::createCommandIdentifier( )
+{
+ ::osl::MutexGuard aGuard(m_aMutex);
+ // Just increase counter on every call to generate an identifier.
+ return ++m_nCommandId;
+}
+
+Any SAL_CALL OContentHelper::execute( const Command& aCommand, sal_Int32 /*CommandId*/, const Reference< XCommandEnvironment >& Environment )
+{
+ Any aRet;
+ if ( aCommand.Name == "getPropertyValues" )
+ {
+ // getPropertyValues
+
+ Sequence< Property > Properties;
+ if ( !( aCommand.Argument >>= Properties ) )
+ {
+ OSL_FAIL( "Wrong argument type!" );
+ ucbhelper::cancelCommandExecution(
+ Any( IllegalArgumentException(
+ OUString(),
+ static_cast< cppu::OWeakObject * >( this ),
+ -1 ) ),
+ Environment );
+ // Unreachable
+ }
+ aRet <<= getPropertyValues( Properties);
+ }
+ else if ( aCommand.Name == "setPropertyValues" )
+ {
+ // setPropertyValues
+
+ Sequence< PropertyValue > aProperties;
+ if ( !( aCommand.Argument >>= aProperties ) )
+ {
+ OSL_FAIL( "Wrong argument type!" );
+ ucbhelper::cancelCommandExecution(
+ Any( IllegalArgumentException(
+ OUString(),
+ static_cast< cppu::OWeakObject * >( this ),
+ -1 ) ),
+ Environment );
+ // Unreachable
+ }
+
+ if ( !aProperties.hasElements() )
+ {
+ OSL_FAIL( "No properties!" );
+ ucbhelper::cancelCommandExecution(
+ Any( IllegalArgumentException(
+ OUString(),
+ static_cast< cppu::OWeakObject * >( this ),
+ -1 ) ),
+ Environment );
+ // Unreachable
+ }
+
+ aRet <<= setPropertyValues( aProperties );
+ }
+ else if ( aCommand.Name == "getPropertySetInfo" )
+ {
+ // getPropertySetInfo
+
+ Reference<XPropertySet> xProp(*this,UNO_QUERY);
+ if ( xProp.is() )
+ aRet <<= xProp->getPropertySetInfo();
+ // aRet <<= getPropertySetInfo(); // TODO
+ }
+ else
+ {
+ // Unsupported command
+
+ OSL_FAIL( "Content::execute - unsupported command!" );
+
+ ucbhelper::cancelCommandExecution(
+ Any( UnsupportedCommandException(
+ OUString(),
+ static_cast< cppu::OWeakObject * >( this ) ) ),
+ Environment );
+ // Unreachable
+ }
+
+ return aRet;
+}
+
+void SAL_CALL OContentHelper::abort( sal_Int32 /*CommandId*/ )
+{
+}
+
+// XPropertiesChangeNotifier
+void SAL_CALL OContentHelper::addPropertiesChangeListener( const Sequence< OUString >& PropertyNames, const Reference< XPropertiesChangeListener >& Listener )
+{
+ ::osl::MutexGuard aGuard(m_aMutex);
+ sal_Int32 nCount = PropertyNames.getLength();
+ if ( !nCount )
+ {
+ // Note: An empty sequence means a listener for "all" properties.
+ m_aPropertyChangeListeners.addInterface(OUString(), Listener );
+ }
+ else
+ {
+ const OUString* pSeq = PropertyNames.getConstArray();
+
+ for ( sal_Int32 n = 0; n < nCount; ++n )
+ {
+ const OUString& rName = pSeq[ n ];
+ if ( !rName.isEmpty() )
+ m_aPropertyChangeListeners.addInterface(rName, Listener );
+ }
+ }
+}
+
+void SAL_CALL OContentHelper::removePropertiesChangeListener( const Sequence< OUString >& PropertyNames, const Reference< XPropertiesChangeListener >& Listener )
+{
+ ::osl::MutexGuard aGuard(m_aMutex);
+ sal_Int32 nCount = PropertyNames.getLength();
+ if ( !nCount )
+ {
+ // Note: An empty sequence means a listener for "all" properties.
+ m_aPropertyChangeListeners.removeInterface( OUString(), Listener );
+ }
+ else
+ {
+ const OUString* pSeq = PropertyNames.getConstArray();
+
+ for ( sal_Int32 n = 0; n < nCount; ++n )
+ {
+ const OUString& rName = pSeq[ n ];
+ if ( !rName.isEmpty() )
+ m_aPropertyChangeListeners.removeInterface( rName, Listener );
+ }
+ }
+}
+
+// XPropertyContainer
+void SAL_CALL OContentHelper::addProperty( const OUString& /*Name*/, sal_Int16 /*Attributes*/, const Any& /*DefaultValue*/ )
+{
+ OSL_FAIL( "OContentHelper::addProperty: not implemented!" );
+}
+
+void SAL_CALL OContentHelper::removeProperty( const OUString& /*Name*/ )
+{
+ OSL_FAIL( "OContentHelper::removeProperty: not implemented!" );
+}
+
+// XInitialization
+void SAL_CALL OContentHelper::initialize( const Sequence< Any >& _aArguments )
+{
+ const Any* pBegin = _aArguments.getConstArray();
+ const Any* pEnd = pBegin + _aArguments.getLength();
+ PropertyValue aValue;
+ for(;pBegin != pEnd;++pBegin)
+ {
+ *pBegin >>= aValue;
+ if ( aValue.Name == "Parent" )
+ {
+ m_xParentContainer.set(aValue.Value,UNO_QUERY);
+ }
+ else if ( aValue.Name == PROPERTY_NAME )
+ {
+ aValue.Value >>= m_pImpl->m_aProps.aTitle;
+ }
+ else if ( aValue.Name == PROPERTY_PERSISTENT_NAME )
+ {
+ aValue.Value >>= m_pImpl->m_aProps.sPersistentName;
+ }
+ }
+}
+
+Sequence< Any > OContentHelper::setPropertyValues(const Sequence< PropertyValue >& rValues )
+{
+ osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
+
+ Sequence< Any > aRet( rValues.getLength() );
+ auto aRetRange = asNonConstRange(aRet);
+ Sequence< PropertyChangeEvent > aChanges( rValues.getLength() );
+ sal_Int32 nChanged = 0;
+
+ PropertyChangeEvent aEvent;
+ aEvent.Source = static_cast< cppu::OWeakObject * >( this );
+ aEvent.Further = false;
+ aEvent.PropertyHandle = -1;
+
+ const PropertyValue* pValues = rValues.getConstArray();
+ sal_Int32 nCount = rValues.getLength();
+
+ for ( sal_Int32 n = 0; n < nCount; ++n )
+ {
+ const PropertyValue& rValue = pValues[ n ];
+
+ if ( rValue.Name == "ContentType" || rValue.Name == "IsDocument" || rValue.Name == "IsFolder" )
+ {
+ // Read-only property!
+ aRetRange[ n ] <<= IllegalAccessException("Property is read-only!",
+ static_cast< cppu::OWeakObject * >( this ) );
+ }
+ else if ( rValue.Name == "Title" )
+ {
+ OUString aNewValue;
+ if ( rValue.Value >>= aNewValue )
+ {
+ if ( aNewValue != m_pImpl->m_aProps.aTitle )
+ {
+ aEvent.PropertyName = rValue.Name;
+ aEvent.OldValue <<= m_pImpl->m_aProps.aTitle;
+
+ try
+ {
+ impl_rename_throw( aNewValue ,false);
+ OSL_ENSURE( m_pImpl->m_aProps.aTitle == aNewValue, "OContentHelper::setPropertyValues('Title'): rename did not work!" );
+
+ aEvent.NewValue <<= aNewValue;
+ aChanges.getArray()[ nChanged ] = aEvent;
+ nChanged++;
+ }
+ catch( const Exception& )
+ {
+ TOOLS_WARN_EXCEPTION( "dbaccess", "OContentHelper::setPropertyValues('Title'): caught an exception while renaming!" );
+ }
+ }
+ else
+ {
+ // Old value equals new value. No error!
+ }
+ }
+ else
+ {
+ aRetRange[ n ] <<= IllegalTypeException("Property value has wrong type!",
+ static_cast< cppu::OWeakObject * >( this ) );
+ }
+ }
+
+ else
+ {
+ aRetRange[ n ] <<= Exception("No property set for storing the value!",
+ static_cast< cppu::OWeakObject * >( this ) );
+ }
+ }
+
+ if ( nChanged > 0 )
+ {
+ notifyDataSourceModified();
+ aGuard.clear();
+ aChanges.realloc( nChanged );
+ notifyPropertiesChange( aChanges );
+ }
+
+ return aRet;
+}
+
+// static
+Reference< XRow > OContentHelper::getPropertyValues( const Sequence< Property >& rProperties)
+{
+ // Note: Empty sequence means "get values of all supported properties".
+
+ rtl::Reference< ::ucbhelper::PropertyValueSet > xRow = new ::ucbhelper::PropertyValueSet( m_aContext );
+
+ sal_Int32 nCount = rProperties.getLength();
+ if ( nCount )
+ {
+ const Property* pProps = rProperties.getConstArray();
+ for ( sal_Int32 n = 0; n < nCount; ++n )
+ {
+ const Property& rProp = pProps[ n ];
+
+ // Process Core properties.
+
+ if ( rProp.Name == "ContentType" )
+ {
+ xRow->appendString ( rProp, getContentType() );
+ }
+ else if ( rProp.Name == "Title" )
+ {
+ xRow->appendString ( rProp, m_pImpl->m_aProps.aTitle );
+ }
+ else if ( rProp.Name == "IsDocument" )
+ {
+ xRow->appendBoolean( rProp, m_pImpl->m_aProps.bIsDocument );
+ }
+ else if ( rProp.Name == "IsFolder" )
+ {
+ xRow->appendBoolean( rProp, m_pImpl->m_aProps.bIsFolder );
+ }
+ else
+ xRow->appendVoid(rProp);
+ }
+ }
+ else
+ {
+ // Append all Core Properties.
+ xRow->appendString (
+ Property( "ContentType", -1,
+ cppu::UnoType<OUString>::get(),
+ PropertyAttribute::BOUND
+ | PropertyAttribute::READONLY ),
+ getContentType() );
+ xRow->appendString (
+ Property( "Title", -1,
+ cppu::UnoType<OUString>::get(),
+ PropertyAttribute::BOUND ),
+ m_pImpl->m_aProps.aTitle );
+ xRow->appendBoolean(
+ Property( "IsDocument", -1,
+ cppu::UnoType<bool>::get(),
+ PropertyAttribute::BOUND
+ | PropertyAttribute::READONLY ),
+ m_pImpl->m_aProps.bIsDocument );
+ xRow->appendBoolean(
+ Property( "IsFolder", -1,
+ cppu::UnoType<bool>::get(),
+ PropertyAttribute::BOUND
+ | PropertyAttribute::READONLY ),
+ m_pImpl->m_aProps.bIsFolder );
+
+ // @@@ Append other properties supported directly.
+ }
+
+ return xRow;
+}
+
+void OContentHelper::notifyPropertiesChange( const Sequence< PropertyChangeEvent >& evt ) const
+{
+
+ sal_Int32 nCount = evt.getLength();
+ if ( !nCount )
+ return;
+
+ // First, notify listeners interested in changes of every property.
+ comphelper::OInterfaceContainerHelper3<XPropertiesChangeListener>* pAllPropsContainer = m_aPropertyChangeListeners.getContainer( OUString() );
+ if ( pAllPropsContainer )
+ pAllPropsContainer->notifyEach( &XPropertiesChangeListener::propertiesChange, evt );
+
+ typedef std::map< XPropertiesChangeListener*, Sequence< PropertyChangeEvent > > PropertiesEventListenerMap;
+ PropertiesEventListenerMap aListeners;
+
+ const PropertyChangeEvent* propertyChangeEvent = evt.getConstArray();
+
+ for ( sal_Int32 n = 0; n < nCount; ++n, ++propertyChangeEvent )
+ {
+ const PropertyChangeEvent& rEvent = *propertyChangeEvent;
+ const OUString& rName = rEvent.PropertyName;
+
+ comphelper::OInterfaceContainerHelper3<XPropertiesChangeListener>* pPropsContainer = m_aPropertyChangeListeners.getContainer( rName );
+ if ( pPropsContainer )
+ {
+ comphelper::OInterfaceIteratorHelper3 aIter( *pPropsContainer );
+ while ( aIter.hasMoreElements() )
+ {
+ Sequence< PropertyChangeEvent >* propertyEvents;
+
+ XPropertiesChangeListener* pListener = aIter.next().get();
+ PropertiesEventListenerMap::iterator it = aListeners.find( pListener );
+ if ( it == aListeners.end() )
+ {
+ // Not in map - create and insert new entry.
+ auto pair = aListeners.emplace( pListener, Sequence< PropertyChangeEvent >( nCount ));
+ propertyEvents = &pair.first->second;
+ }
+ else
+ propertyEvents = &(*it).second;
+
+ propertyEvents->getArray()[n] = rEvent;
+ }
+ }
+ }
+
+ // Notify listeners.
+ for (auto & rPair : aListeners)
+ {
+ XPropertiesChangeListener* pListener = rPair.first;
+ Sequence< PropertyChangeEvent >& rSeq = rPair.second;
+
+ // Propagate event.
+ pListener->propertiesChange( rSeq );
+ }
+}
+
+// css::lang::XUnoTunnel
+sal_Int64 OContentHelper::getSomething( const Sequence< sal_Int8 > & rId )
+{
+ return comphelper::getSomethingImpl(rId, this);
+}
+
+Reference< XInterface > SAL_CALL OContentHelper::getParent( )
+{
+ ::osl::MutexGuard aGuard(m_aMutex);
+ return m_xParentContainer;
+}
+
+void SAL_CALL OContentHelper::setParent( const Reference< XInterface >& _xParent )
+{
+ ::osl::MutexGuard aGuard(m_aMutex);
+ m_xParentContainer = _xParent;
+}
+
+void OContentHelper::impl_rename_throw(const OUString& _sNewName,bool _bNotify )
+{
+ osl::ClearableGuard< osl::Mutex > aGuard(m_aMutex);
+ if ( _sNewName == m_pImpl->m_aProps.aTitle )
+ return;
+ try
+ {
+ Sequence<PropertyChangeEvent> aChanges{
+ { /* Source */ static_cast<cppu::OWeakObject*>(this),
+ /* PropertyName */ PROPERTY_NAME,
+ /* Further */ false,
+ /* PropertyHandle */ PROPERTY_ID_NAME,
+ /* OldValue */ Any(m_pImpl->m_aProps.aTitle),
+ /* NewValue */ Any(_sNewName) }
+ };
+
+ aGuard.clear();
+
+ m_pImpl->m_aProps.aTitle = _sNewName;
+ if ( _bNotify )
+ notifyPropertiesChange( aChanges );
+ notifyDataSourceModified();
+ }
+ catch(const PropertyVetoException&)
+ {
+ throw ElementExistException(_sNewName,*this);
+ }
+}
+
+void SAL_CALL OContentHelper::rename( const OUString& newName )
+{
+
+ impl_rename_throw(newName);
+
+}
+
+void OContentHelper::notifyDataSourceModified()
+{
+ ::dbaccess::notifyDataSourceModified(m_xParentContainer);
+}
+
+} // namespace dbaccess
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/dataaccess/ModelImpl.cxx b/dbaccess/source/core/dataaccess/ModelImpl.cxx
new file mode 100644
index 000000000..5a4078fcc
--- /dev/null
+++ b/dbaccess/source/core/dataaccess/ModelImpl.cxx
@@ -0,0 +1,1432 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <databasecontext.hxx>
+#include "databasedocument.hxx"
+#include "datasource.hxx"
+#include <definitioncontainer.hxx>
+#include <ModelImpl.hxx>
+#include <sdbcoretools.hxx>
+
+#include <com/sun/star/beans/PropertyBag.hpp>
+#include <com/sun/star/container/XSet.hpp>
+#include <com/sun/star/document/MacroExecMode.hpp>
+#include <com/sun/star/embed/XTransactedObject.hpp>
+#include <com/sun/star/embed/XTransactionBroadcaster.hpp>
+#include <com/sun/star/embed/StorageFactory.hpp>
+#include <com/sun/star/frame/theGlobalEventBroadcaster.hpp>
+#include <com/sun/star/io/IOException.hpp>
+#include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
+#include <com/sun/star/sdb/BooleanComparisonMode.hpp>
+#include <com/sun/star/script/DocumentScriptLibraryContainer.hpp>
+#include <com/sun/star/script/DocumentDialogLibraryContainer.hpp>
+#include <com/sun/star/util/NumberFormatsSupplier.hpp>
+#include <com/sun/star/security/DocumentDigitalSignatures.hpp>
+#include <com/sun/star/security/XDocumentDigitalSignatures.hpp>
+#include <com/sun/star/task/DocumentMacroConfirmationRequest.hpp>
+
+#include <cppuhelper/exc_hlp.hxx>
+#include <cppuhelper/implbase.hxx>
+#include <comphelper/storagehelper.hxx>
+#include <comphelper/types.hxx>
+#include <comphelper/processfactory.hxx>
+#include <sfx2/docfile.hxx>
+#include <sfx2/signaturestate.hxx>
+#include <tools/diagnose_ex.h>
+#include <osl/file.hxx>
+#include <osl/diagnose.h>
+#include <sal/log.hxx>
+#include <tools/urlobj.hxx>
+#include <unotools/configmgr.hxx>
+#include <unotools/tempfile.hxx>
+#include <i18nlangtag/languagetag.hxx>
+
+#include <algorithm>
+
+using namespace css;
+using namespace ::com::sun::star::document;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::sdbcx;
+using namespace ::com::sun::star::sdb;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::embed;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::util;
+using namespace ::com::sun::star::io;
+using namespace ::com::sun::star::ucb;
+using namespace ::com::sun::star::frame;
+using namespace ::com::sun::star::view;
+using namespace ::com::sun::star::task;
+using namespace ::com::sun::star::script;
+using namespace ::cppu;
+using namespace ::osl;
+using namespace ::comphelper;
+
+namespace dbaccess
+{
+
+// DocumentStorageAccess
+class DocumentStorageAccess : public ::cppu::WeakImplHelper< XDocumentSubStorageSupplier
+ , XTransactionListener >
+{
+ typedef std::map< OUString, Reference< XStorage > > NamedStorages;
+
+ ::osl::Mutex m_aMutex;
+ /// all sub storages which we ever gave to the outer world
+ NamedStorages m_aExposedStorages;
+ ODatabaseModelImpl* m_pModelImplementation;
+ bool m_bPropagateCommitToRoot;
+ bool m_bDisposingSubStorages;
+
+public:
+ explicit DocumentStorageAccess( ODatabaseModelImpl& _rModelImplementation )
+ :m_pModelImplementation( &_rModelImplementation )
+ ,m_bPropagateCommitToRoot( true )
+ ,m_bDisposingSubStorages( false )
+ {
+ }
+
+protected:
+ virtual ~DocumentStorageAccess() override
+ {
+ }
+
+public:
+ void dispose();
+
+ // XDocumentSubStorageSupplier
+ virtual Reference< XStorage > SAL_CALL getDocumentSubStorage( const OUString& aStorageName, ::sal_Int32 _nMode ) override;
+ virtual Sequence< OUString > SAL_CALL getDocumentSubStoragesNames( ) override;
+
+ // XTransactionListener
+ virtual void SAL_CALL preCommit( const css::lang::EventObject& aEvent ) override;
+ virtual void SAL_CALL commited( const css::lang::EventObject& aEvent ) override;
+ virtual void SAL_CALL preRevert( const css::lang::EventObject& aEvent ) override;
+ virtual void SAL_CALL reverted( const css::lang::EventObject& aEvent ) override;
+
+ // XEventListener
+ virtual void SAL_CALL disposing( const css::lang::EventObject& Source ) override;
+
+ /// disposes all storages managed by this instance
+ void disposeStorages();
+
+ /// disposes all known sub storages
+ void commitStorages();
+
+ /// commits the dedicated "database" storage
+ bool commitEmbeddedStorage( bool _bPreventRootCommits );
+
+private:
+ /** opens the sub storage with the given name, in the given mode
+ */
+ Reference< XStorage > impl_openSubStorage_nothrow( const OUString& _rStorageName, sal_Int32 _nMode );
+
+ void impl_suspendCommitPropagation()
+ {
+ OSL_ENSURE( m_bPropagateCommitToRoot, "DocumentStorageAccess::impl_suspendCommitPropagation: already suspended" );
+ m_bPropagateCommitToRoot = false;
+ }
+ void impl_resumeCommitPropagation()
+ {
+ OSL_ENSURE( !m_bPropagateCommitToRoot, "DocumentStorageAccess::impl_resumeCommitPropagation: not suspended" );
+ m_bPropagateCommitToRoot = true;
+ }
+
+};
+
+void DocumentStorageAccess::dispose()
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ for (auto const& exposedStorage : m_aExposedStorages)
+ {
+ try
+ {
+ Reference< XTransactionBroadcaster > xBroadcaster(exposedStorage.second, UNO_QUERY);
+ if ( xBroadcaster.is() )
+ xBroadcaster->removeTransactionListener( this );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+
+ m_aExposedStorages.clear();
+
+ m_pModelImplementation = nullptr;
+}
+
+Reference< XStorage > DocumentStorageAccess::impl_openSubStorage_nothrow( const OUString& _rStorageName, sal_Int32 _nDesiredMode )
+{
+ OSL_ENSURE( !_rStorageName.isEmpty(),"ODatabaseModelImpl::impl_openSubStorage_nothrow: Invalid storage name!" );
+
+ Reference< XStorage > xStorage;
+ try
+ {
+ Reference< XStorage > xRootStorage( m_pModelImplementation->getOrCreateRootStorage() );
+ if ( xRootStorage.is() )
+ {
+ sal_Int32 nRealMode = m_pModelImplementation->m_bDocumentReadOnly ? ElementModes::READ : _nDesiredMode;
+ if ( nRealMode == ElementModes::READ )
+ {
+ if ( xRootStorage.is() && !xRootStorage->hasByName( _rStorageName ) )
+ return xStorage;
+ }
+
+ xStorage = xRootStorage->openStorageElement( _rStorageName, nRealMode );
+
+ Reference< XTransactionBroadcaster > xBroad( xStorage, UNO_QUERY );
+ if ( xBroad.is() )
+ xBroad->addTransactionListener( this );
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+
+ return xStorage;
+}
+
+void DocumentStorageAccess::disposeStorages()
+{
+ m_bDisposingSubStorages = true;
+
+ for (auto & exposedStorage : m_aExposedStorages)
+ {
+ try
+ {
+ ::comphelper::disposeComponent( exposedStorage.second );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+ m_aExposedStorages.clear();
+
+ m_bDisposingSubStorages = false;
+}
+
+void DocumentStorageAccess::commitStorages()
+{
+ try
+ {
+ for (auto const& exposedStorage : m_aExposedStorages)
+ {
+ tools::stor::commitStorageIfWriteable( exposedStorage.second );
+ }
+ }
+ catch(const WrappedTargetException&)
+ {
+ // WrappedTargetException not allowed to leave
+ throw IOException();
+ }
+}
+
+bool DocumentStorageAccess::commitEmbeddedStorage( bool _bPreventRootCommits )
+{
+ if ( _bPreventRootCommits )
+ impl_suspendCommitPropagation();
+
+ bool bSuccess = false;
+ try
+ {
+ NamedStorages::const_iterator pos = m_aExposedStorages.find( "database" );
+ if ( pos != m_aExposedStorages.end() )
+ bSuccess = tools::stor::commitStorageIfWriteable( pos->second );
+ }
+ catch( Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+
+ if ( _bPreventRootCommits )
+ impl_resumeCommitPropagation();
+
+ return bSuccess;
+
+}
+
+Reference< XStorage > SAL_CALL DocumentStorageAccess::getDocumentSubStorage( const OUString& aStorageName, ::sal_Int32 _nDesiredMode )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ NamedStorages::const_iterator pos = m_aExposedStorages.find( aStorageName );
+ if ( pos == m_aExposedStorages.end() )
+ {
+ Reference< XStorage > xResult = impl_openSubStorage_nothrow( aStorageName, _nDesiredMode );
+ pos = m_aExposedStorages.emplace( aStorageName, xResult ).first;
+ }
+
+ return pos->second;
+}
+
+Sequence< OUString > SAL_CALL DocumentStorageAccess::getDocumentSubStoragesNames( )
+{
+ Reference< XStorage > xRootStor( m_pModelImplementation->getRootStorage() );
+ if ( !xRootStor.is() )
+ return Sequence< OUString >();
+
+ std::vector< OUString > aNames;
+
+ const Sequence< OUString > aElementNames( xRootStor->getElementNames() );
+ for ( OUString const & name : aElementNames )
+ {
+ if ( xRootStor->isStorageElement( name ) )
+ aNames.push_back( name );
+ }
+ return aNames.empty()
+ ? Sequence< OUString >()
+ : Sequence< OUString >( aNames.data(), aNames.size() );
+}
+
+void SAL_CALL DocumentStorageAccess::preCommit( const css::lang::EventObject& /*aEvent*/ )
+{
+ // not interested in
+}
+
+void SAL_CALL DocumentStorageAccess::commited( const css::lang::EventObject& aEvent )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ if ( m_pModelImplementation )
+ m_pModelImplementation->setModified( true );
+
+ if ( !(m_pModelImplementation && m_bPropagateCommitToRoot) )
+ return;
+
+ Reference< XStorage > xStorage( aEvent.Source, UNO_QUERY );
+
+ // check if this is the dedicated "database" sub storage
+ NamedStorages::const_iterator pos = m_aExposedStorages.find( "database" );
+ if ( ( pos != m_aExposedStorages.end() )
+ && ( pos->second == xStorage )
+ )
+ {
+ // if so, also commit the root storage
+ m_pModelImplementation->commitRootStorage();
+ }
+}
+
+void SAL_CALL DocumentStorageAccess::preRevert( const css::lang::EventObject& /*aEvent*/ )
+{
+ // not interested in
+}
+
+void SAL_CALL DocumentStorageAccess::reverted( const css::lang::EventObject& /*aEvent*/ )
+{
+ // not interested in
+}
+
+void SAL_CALL DocumentStorageAccess::disposing( const css::lang::EventObject& Source )
+{
+ OSL_ENSURE( Reference< XStorage >( Source.Source, UNO_QUERY ).is(), "DocumentStorageAccess::disposing: No storage? What's this?" );
+
+ if ( m_bDisposingSubStorages )
+ return;
+
+ auto find = std::find_if(m_aExposedStorages.begin(), m_aExposedStorages.end(),
+ [&Source](const NamedStorages::value_type& rEntry) { return rEntry.second == Source.Source; });
+ if (find != m_aExposedStorages.end())
+ m_aExposedStorages.erase( find );
+}
+
+// ODatabaseModelImpl
+
+ODatabaseModelImpl::ODatabaseModelImpl( const Reference< XComponentContext >& _rxContext, ODatabaseContext& _rDBContext )
+ :m_aContainer(4)
+ ,m_aMacroMode( *this )
+ ,m_nImposedMacroExecMode( MacroExecMode::NEVER_EXECUTE )
+ ,m_rDBContext( _rDBContext )
+ ,m_refCount(0)
+ ,m_bModificationLock( false )
+ ,m_bDocumentInitialized( false )
+ ,m_nScriptingSignatureState(SignatureState::UNKNOWN)
+ ,m_aContext( _rxContext )
+ ,m_nLoginTimeout(0)
+ ,m_bReadOnly(false)
+ ,m_bPasswordRequired(false)
+ ,m_bSuppressVersionColumns(true)
+ ,m_bModified(false)
+ ,m_bDocumentReadOnly(false)
+ ,m_bMacroCallsSeenWhileLoading(false)
+ ,m_pSharedConnectionManager(nullptr)
+ ,m_nControllerLockCount(0)
+{
+ // some kind of default
+ m_sConnectURL = "jdbc:";
+ m_aTableFilter = { "%" };
+ impl_construct_nothrow();
+}
+
+ODatabaseModelImpl::ODatabaseModelImpl(
+ const OUString& _rRegistrationName,
+ const Reference< XComponentContext >& _rxContext,
+ ODatabaseContext& _rDBContext
+ )
+ :m_aContainer(4)
+ ,m_aMacroMode( *this )
+ ,m_nImposedMacroExecMode( MacroExecMode::NEVER_EXECUTE )
+ ,m_rDBContext( _rDBContext )
+ ,m_refCount(0)
+ ,m_bModificationLock( false )
+ ,m_bDocumentInitialized( false )
+ ,m_nScriptingSignatureState(SignatureState::UNKNOWN)
+ ,m_aContext( _rxContext )
+ ,m_sName(_rRegistrationName)
+ ,m_nLoginTimeout(0)
+ ,m_bReadOnly(false)
+ ,m_bPasswordRequired(false)
+ ,m_bSuppressVersionColumns(true)
+ ,m_bModified(false)
+ ,m_bDocumentReadOnly(false)
+ ,m_bMacroCallsSeenWhileLoading(false)
+ ,m_pSharedConnectionManager(nullptr)
+ ,m_nControllerLockCount(0)
+{
+ impl_construct_nothrow();
+}
+
+ODatabaseModelImpl::~ODatabaseModelImpl()
+{
+}
+
+void ODatabaseModelImpl::impl_construct_nothrow()
+{
+ // create the property bag to hold the settings (also known as "Info" property)
+ try
+ {
+ // the set of property value types in the bag is limited:
+ Sequence< Type > aAllowedTypes({
+ cppu::UnoType<sal_Bool>::get(),
+ cppu::UnoType<double>::get(),
+ cppu::UnoType<OUString>::get(),
+ cppu::UnoType<sal_Int32>::get(),
+ cppu::UnoType<sal_Int16>::get(),
+ cppu::UnoType<Sequence< Any >>::get(),
+ });
+
+ m_xSettings = PropertyBag::createWithTypes( m_aContext, aAllowedTypes, false/*AllowEmptyPropertyName*/, true/*AutomaticAddition*/ );
+
+ // insert the default settings
+ Reference< XPropertyContainer > xContainer( m_xSettings, UNO_QUERY_THROW );
+ Reference< XSet > xSettingsSet( m_xSettings, UNO_QUERY_THROW );
+ const AsciiPropertyValue* pSettings = getDefaultDataSourceSettings();
+ for ( ; pSettings->AsciiName; ++pSettings )
+ {
+ if ( !pSettings->DefaultValue.hasValue() )
+ {
+ Property aProperty(
+ OUString::createFromAscii( pSettings->AsciiName ),
+ -1,
+ pSettings->ValueType,
+ PropertyAttribute::BOUND | PropertyAttribute::MAYBEDEFAULT | PropertyAttribute::MAYBEVOID
+ );
+ xSettingsSet->insert( Any( aProperty ) );
+ }
+ else
+ {
+ xContainer->addProperty(
+ OUString::createFromAscii( pSettings->AsciiName ),
+ PropertyAttribute::BOUND | PropertyAttribute::MAYBEDEFAULT,
+ pSettings->DefaultValue
+ );
+ }
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ m_rDBContext.appendAtTerminateListener(*this);
+}
+
+namespace
+{
+ OUString lcl_getContainerStorageName_throw( ODatabaseModelImpl::ObjectType _eType )
+ {
+ const char* pAsciiName( nullptr );
+ switch ( _eType )
+ {
+ case ODatabaseModelImpl::E_FORM: pAsciiName = "forms"; break;
+ case ODatabaseModelImpl::E_REPORT: pAsciiName = "reports"; break;
+ case ODatabaseModelImpl::E_QUERY: pAsciiName = "queries"; break;
+ case ODatabaseModelImpl::E_TABLE: pAsciiName = "tables"; break;
+ default:
+ throw RuntimeException();
+ }
+ return OUString::createFromAscii( pAsciiName );
+ }
+
+ bool lcl_hasObjectWithMacros_throw( const ODefinitionContainer_Impl& _rObjectDefinitions, const Reference< XStorage >& _rxContainerStorage )
+ {
+ bool bSomeDocHasMacros = false;
+
+ for (auto const& objectDefinition : _rObjectDefinitions)
+ {
+ const TContentPtr& rDefinition( objectDefinition.second );
+ const OUString& rPersistentName( rDefinition->m_aProps.sPersistentName );
+
+ if ( rPersistentName.isEmpty() )
+ { // it's a logical sub folder used to organize the real objects
+ const ODefinitionContainer_Impl& rSubFoldersObjectDefinitions( dynamic_cast< const ODefinitionContainer_Impl& >( *rDefinition ) );
+ bSomeDocHasMacros = lcl_hasObjectWithMacros_throw( rSubFoldersObjectDefinitions, _rxContainerStorage );
+ if (bSomeDocHasMacros)
+ break;
+ continue;
+ }
+
+ bSomeDocHasMacros = ODatabaseModelImpl::objectHasMacros( _rxContainerStorage, rPersistentName );
+ if (bSomeDocHasMacros)
+ break;
+ }
+ return bSomeDocHasMacros;
+ }
+
+ bool lcl_hasObjectsWithMacros_nothrow( ODatabaseModelImpl& _rModel, const ODatabaseModelImpl::ObjectType _eType )
+ {
+ bool bSomeDocHasMacros = false;
+
+ const OContentHelper_Impl& rContainerData( *_rModel.getObjectContainer( _eType ) );
+ const ODefinitionContainer_Impl& rObjectDefinitions = dynamic_cast< const ODefinitionContainer_Impl& >( rContainerData );
+
+ try
+ {
+ Reference< XStorage > xContainerStorage( _rModel.getStorage( _eType ) );
+ // note the READWRITE here: If the storage already existed before, then the OpenMode will
+ // be ignored, anyway.
+ // If the storage did not yet exist, then it will be created. If the database document
+ // is read-only, the OpenMode will be automatically downgraded to READ. Otherwise,
+ // the storage will in fact be created as READWRITE. While this is not strictly necessary
+ // for this particular use case here, it is required since the storage is *cached*, and
+ // later use cases will need the READWRITE mode.
+
+ if ( xContainerStorage.is() )
+ bSomeDocHasMacros = lcl_hasObjectWithMacros_throw( rObjectDefinitions, xContainerStorage );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ // be on the safe side: If we can't reliably determine whether there are macros,
+ // assume there actually are. Better this way, than the other way round.
+ bSomeDocHasMacros = true;
+ }
+
+ return bSomeDocHasMacros;
+ }
+}
+
+bool ODatabaseModelImpl::objectHasMacros( const Reference< XStorage >& _rxContainerStorage, const OUString& _rPersistentName )
+{
+ OSL_PRECOND( _rxContainerStorage.is(), "ODatabaseModelImpl::objectHasMacros: this will crash!" );
+
+ bool bHasMacros = true;
+ try
+ {
+ if ( !_rxContainerStorage->hasByName( _rPersistentName ) )
+ return false;
+
+ Reference< XStorage > xObjectStor( _rxContainerStorage->openStorageElement(
+ _rPersistentName, ElementModes::READ ) );
+
+ bHasMacros = ::sfx2::DocumentMacroMode::storageHasMacros( xObjectStor );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ return bHasMacros;
+}
+
+void ODatabaseModelImpl::reset()
+{
+ m_bReadOnly = false;
+ std::vector<TContentPtr>(4).swap(m_aContainer);
+
+ if ( m_pStorageAccess.is() )
+ {
+ m_pStorageAccess->dispose();
+ m_pStorageAccess.clear();
+ }
+}
+
+void ODatabaseModelImpl::disposing( const css::lang::EventObject& Source )
+{
+ Reference<XConnection> xCon(Source.Source,UNO_QUERY);
+ if ( xCon.is() )
+ {
+ bool bStore = false;
+ for (OWeakConnectionArray::iterator i = m_aConnections.begin(); i != m_aConnections.end(); )
+ {
+ css::uno::Reference< css::sdbc::XConnection > xIterConn ( *i );
+ if ( !xIterConn.is())
+ {
+ i = m_aConnections.erase(i);
+ }
+ else if ( xCon == xIterConn )
+ {
+ *i = css::uno::WeakReference< css::sdbc::XConnection >();
+ bStore = true;
+ break;
+ } else
+ ++i;
+ }
+
+ if ( bStore )
+ commitRootStorage();
+ }
+ else
+ {
+ OSL_FAIL( "ODatabaseModelImpl::disposing: where does this come from?" );
+ }
+}
+
+void ODatabaseModelImpl::clearConnections()
+{
+ OWeakConnectionArray aConnections;
+ aConnections.swap( m_aConnections );
+
+ Reference< XConnection > xConn;
+ for (auto const& connection : aConnections)
+ {
+ xConn = connection;
+ if ( xConn.is() )
+ {
+ try
+ {
+ xConn->close();
+ }
+ catch(const Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+ }
+
+ m_pSharedConnectionManager = nullptr;
+ m_xSharedConnectionManager = nullptr;
+}
+
+void ODatabaseModelImpl::dispose()
+{
+ // dispose the data source and the model
+ try
+ {
+ Reference< XDataSource > xDS( m_xDataSource );
+ ::comphelper::disposeComponent( xDS );
+
+ Reference< XModel > xModel( m_xModel );
+ ::comphelper::disposeComponent( xModel );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ m_xDataSource = WeakReference<XDataSource>();
+ m_xModel = WeakReference< XModel >();
+
+ for (auto const& elem : m_aContainer)
+ {
+ if ( elem )
+ elem->m_pDataSource = nullptr;
+ }
+ m_aContainer.clear();
+
+ clearConnections();
+
+ m_xNumberFormatsSupplier = nullptr;
+
+ try
+ {
+ bool bCouldStore = commitEmbeddedStorage( true );
+ // "true" means that committing the embedded storage should not trigger committing the root
+ // storage. This is because we are going to commit the root storage ourself, anyway
+ disposeStorages();
+ if ( bCouldStore )
+ commitRootStorage();
+
+ impl_switchToStorage_throw( nullptr );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+
+ if ( m_pStorageAccess.is() )
+ {
+ m_pStorageAccess->dispose();
+ m_pStorageAccess.clear();
+ }
+}
+
+const Reference< XNumberFormatsSupplier > & ODatabaseModelImpl::getNumberFormatsSupplier()
+{
+ if (!m_xNumberFormatsSupplier.is())
+ {
+ // the arguments : the work locale of the current user
+ Locale aLocale( LanguageTag::convertToLocale( utl::ConfigManager::getWorkLocale(), false));
+
+ m_xNumberFormatsSupplier.set( NumberFormatsSupplier::createWithLocale( m_aContext, aLocale ) );
+ }
+ return m_xNumberFormatsSupplier;
+}
+
+void ODatabaseModelImpl::setDocFileLocation( const OUString& i_rLoadedFrom )
+{
+ ENSURE_OR_THROW( !i_rLoadedFrom.isEmpty(), "invalid URL" );
+ m_sDocFileLocation = i_rLoadedFrom;
+}
+
+void ODatabaseModelImpl::setResource( const OUString& i_rDocumentURL, const Sequence< PropertyValue >& _rArgs )
+{
+ ENSURE_OR_THROW( !i_rDocumentURL.isEmpty(), "invalid URL" );
+
+ ::comphelper::NamedValueCollection aMediaDescriptor( _rArgs );
+#if OSL_DEBUG_LEVEL > 0
+ if ( aMediaDescriptor.has( "SalvagedFile" ) )
+ {
+ OUString sSalvagedFile( aMediaDescriptor.getOrDefault( "SalvagedFile", OUString() ) );
+ // If SalvagedFile is an empty string, this indicates "the document is being recovered, but i_rDocumentURL already
+ // is the real document URL, not the temporary document location"
+ if ( sSalvagedFile.isEmpty() )
+ sSalvagedFile = i_rDocumentURL;
+
+ OSL_ENSURE( sSalvagedFile == i_rDocumentURL, "ODatabaseModelImpl::setResource: inconsistency!" );
+ // nowadays, setResource should only be called with the logical URL of the document
+ }
+#endif
+
+ m_aMediaDescriptor = stripLoadArguments( aMediaDescriptor );
+
+ impl_switchToLogicalURL( i_rDocumentURL );
+}
+
+::comphelper::NamedValueCollection ODatabaseModelImpl::stripLoadArguments( const ::comphelper::NamedValueCollection& _rArguments )
+{
+ OSL_ENSURE( !_rArguments.has( "Model" ), "ODatabaseModelImpl::stripLoadArguments: this is suspicious (1)!" );
+ OSL_ENSURE( !_rArguments.has( "ViewName" ), "ODatabaseModelImpl::stripLoadArguments: this is suspicious (2)!" );
+
+ ::comphelper::NamedValueCollection aMutableArgs( _rArguments );
+ aMutableArgs.remove( "Model" );
+ aMutableArgs.remove( "ViewName" );
+ return aMutableArgs;
+}
+
+void ODatabaseModelImpl::disposeStorages()
+{
+ getDocumentStorageAccess()->disposeStorages();
+}
+
+Reference< XSingleServiceFactory > ODatabaseModelImpl::createStorageFactory() const
+{
+ return StorageFactory::create( m_aContext );
+}
+
+void ODatabaseModelImpl::commitRootStorage()
+{
+ Reference< XStorage > xStorage( getOrCreateRootStorage() );
+ bool bSuccess = commitStorageIfWriteable_ignoreErrors( xStorage );
+ SAL_WARN_IF(!bSuccess && xStorage.is(), "dbaccess",
+ "ODatabaseModelImpl::commitRootStorage: could not commit the storage!");
+}
+
+Reference< XStorage > const & ODatabaseModelImpl::getOrCreateRootStorage()
+{
+ if ( !m_xDocumentStorage.is() )
+ {
+ Reference< XSingleServiceFactory> xStorageFactory = StorageFactory::create( m_aContext );
+ Any aSource = m_aMediaDescriptor.get( "Stream" );
+ if ( !aSource.hasValue() )
+ aSource = m_aMediaDescriptor.get( "InputStream" );
+ if ( !aSource.hasValue() && !m_sDocFileLocation.isEmpty() )
+ aSource <<= m_sDocFileLocation;
+ // TODO: shouldn't we also check URL?
+
+ OSL_ENSURE( aSource.hasValue(), "ODatabaseModelImpl::getOrCreateRootStorage: no source to create the storage from!" );
+
+ if ( aSource.hasValue() )
+ {
+ Sequence< Any > aStorageCreationArgs{ aSource, Any(ElementModes::READWRITE) };
+
+ Reference< XStorage > xDocumentStorage;
+ OUString sURL;
+ aSource >>= sURL;
+ // Don't try to load a meta-URL as-is.
+ if (!sURL.startsWithIgnoreAsciiCase("vnd.sun.star.pkg:"))
+ {
+ try
+ {
+ xDocumentStorage.set( xStorageFactory->createInstanceWithArguments( aStorageCreationArgs ), UNO_QUERY_THROW );
+ }
+ catch( const Exception& )
+ {
+ m_bDocumentReadOnly = true;
+ aStorageCreationArgs.getArray()[1] <<= ElementModes::READ;
+ try
+ {
+ xDocumentStorage.set( xStorageFactory->createInstanceWithArguments( aStorageCreationArgs ), UNO_QUERY_THROW );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+ }
+
+ impl_switchToStorage_throw( xDocumentStorage );
+ }
+ }
+ return m_xDocumentStorage.getTyped();
+}
+
+DocumentStorageAccess* ODatabaseModelImpl::getDocumentStorageAccess()
+{
+ if ( !m_pStorageAccess.is() )
+ {
+ m_pStorageAccess = new DocumentStorageAccess( *this );
+ }
+ return m_pStorageAccess.get();
+}
+
+void ODatabaseModelImpl::modelIsDisposing( const bool _wasInitialized, ResetModelAccess )
+{
+ m_xModel.clear();
+
+ // Basic libraries and Dialog libraries are a model facet, though held at this impl class.
+ // They automatically dispose themself when the model they belong to is being disposed.
+ // So, to not be tempted to do anything with them, again, we reset them.
+ m_xBasicLibraries.clear();
+ m_xDialogLibraries.clear();
+
+ m_bDocumentInitialized = _wasInitialized;
+}
+
+Reference< XDocumentSubStorageSupplier > ODatabaseModelImpl::getDocumentSubStorageSupplier()
+{
+ return getDocumentStorageAccess();
+}
+
+bool ODatabaseModelImpl::commitEmbeddedStorage( bool _bPreventRootCommits )
+{
+ return getDocumentStorageAccess()->commitEmbeddedStorage( _bPreventRootCommits );
+}
+
+bool ODatabaseModelImpl::commitStorageIfWriteable_ignoreErrors( const Reference< XStorage >& _rxStorage )
+{
+ bool bTryToPreserveScriptSignature = false;
+ utl::TempFile aTempFile;
+ aTempFile.EnableKillingFile();
+ OUString sTmpFileUrl = aTempFile.GetURL();
+ SignatureState aSignatureState = getScriptingSignatureState();
+ OUString sLocation = getDocFileLocation();
+ bool bIsEmbedded = sLocation.startsWith("vnd.sun.star.pkg:") && sLocation.endsWith("/EmbeddedDatabase");
+ if (!bIsEmbedded && !sLocation.isEmpty()
+ && (aSignatureState == SignatureState::OK || aSignatureState == SignatureState::NOTVALIDATED
+ || aSignatureState == SignatureState::INVALID
+ || aSignatureState == SignatureState::UNKNOWN))
+ {
+ bTryToPreserveScriptSignature = true;
+ // We need to first save the file (which removes the macro signature), then add the macro signature again.
+ // For that, we need a temporary copy of the original file.
+ osl::File::RC rc = osl::File::copy(sLocation, sTmpFileUrl);
+ if (rc != osl::FileBase::E_None)
+ throw uno::RuntimeException("Could not create temp file");
+ }
+
+ bool bSuccess = false;
+ try
+ {
+ bSuccess = tools::stor::commitStorageIfWriteable( _rxStorage );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+
+ // Preserve script signature if the script has not changed
+ if (bTryToPreserveScriptSignature)
+ {
+ OUString aODFVersion(comphelper::OStorageHelper::GetODFVersionFromStorage(_rxStorage));
+ uno::Reference<security::XDocumentDigitalSignatures> xDDSigns;
+ try
+ {
+ xDDSigns = security::DocumentDigitalSignatures::createWithVersion(
+ comphelper::getProcessComponentContext(), aODFVersion);
+
+ const OUString aScriptSignName
+ = xDDSigns->getScriptingContentSignatureDefaultStreamName();
+
+ if (!aScriptSignName.isEmpty())
+ {
+ Reference<XStorage> xReadOrig
+ = comphelper::OStorageHelper::GetStorageOfFormatFromURL(
+ ZIP_STORAGE_FORMAT_STRING, sTmpFileUrl, ElementModes::READ);
+ if (!xReadOrig.is())
+ throw uno::RuntimeException("Could not read " + sTmpFileUrl);
+ uno::Reference<embed::XStorage> xMetaInf
+ = xReadOrig->openStorageElement("META-INF", embed::ElementModes::READ);
+
+ uno::Reference<embed::XStorage> xTargetMetaInf
+ = _rxStorage->openStorageElement("META-INF", embed::ElementModes::READWRITE);
+ if (xMetaInf.is() && xTargetMetaInf.is() && xMetaInf->hasByName(aScriptSignName))
+ {
+ xMetaInf->copyElementTo(aScriptSignName, xTargetMetaInf, aScriptSignName);
+
+ uno::Reference<embed::XTransactedObject> xTransact(xTargetMetaInf,
+ uno::UNO_QUERY);
+ if (xTransact.is())
+ xTransact->commit();
+
+ xTargetMetaInf->dispose();
+
+ // now check the copied signature
+ uno::Sequence<security::DocumentSignatureInformation> aInfos
+ = xDDSigns->verifyScriptingContentSignatures(
+ _rxStorage, uno::Reference<io::XInputStream>());
+ SignatureState nState = DocumentSignatures::getSignatureState(aInfos);
+ if (nState == SignatureState::OK || nState == SignatureState::NOTVALIDATED
+ || nState == SignatureState::PARTIAL_OK)
+ {
+ // commit the ZipStorage from target medium
+ xTransact.set(_rxStorage, uno::UNO_QUERY);
+ if (xTransact.is())
+ xTransact->commit();
+ }
+ else
+ {
+ SAL_WARN("dbaccess", "An invalid signature was copied!");
+ }
+ }
+ }
+ }
+ catch (uno::Exception&)
+ {
+ TOOLS_WARN_EXCEPTION("dbaccess", "");
+ }
+ }
+
+ return bSuccess;
+}
+
+void ODatabaseModelImpl::setModified( bool _bModified )
+{
+ if ( isModifyLocked() )
+ return;
+
+ try
+ {
+ Reference< XModifiable > xModi( m_xModel.get(), UNO_QUERY );
+ if ( xModi.is() )
+ xModi->setModified( _bModified );
+ else
+ m_bModified = _bModified;
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+}
+
+Reference<XDataSource> ODatabaseModelImpl::getOrCreateDataSource()
+{
+ Reference<XDataSource> xDs = m_xDataSource;
+ if ( !xDs.is() )
+ {
+ xDs = new ODatabaseSource(this);
+ m_xDataSource = xDs;
+ }
+ return xDs;
+}
+
+Reference< XModel> ODatabaseModelImpl::getModel_noCreate() const
+{
+ return m_xModel;
+}
+
+Reference< XModel > ODatabaseModelImpl::createNewModel_deliverOwnership()
+{
+ Reference< XModel > xModel( m_xModel );
+ OSL_PRECOND( !xModel.is(), "ODatabaseModelImpl::createNewModel_deliverOwnership: not to be called if there already is a model!" );
+ if ( !xModel.is() )
+ {
+ bool bHadModelBefore = m_bDocumentInitialized;
+
+ xModel = ODatabaseDocument::createDatabaseDocument( this, ODatabaseDocument::FactoryAccess() );
+ m_xModel = xModel;
+
+ try
+ {
+ Reference< XGlobalEventBroadcaster > xModelCollection = theGlobalEventBroadcaster::get( m_aContext );
+ xModelCollection->insert( Any( xModel ) );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+
+ if ( bHadModelBefore )
+ {
+ // do an attachResources
+ // In case the document is loaded regularly, this is not necessary, as our loader will do it.
+ // However, in case that the document is implicitly created by asking the data source for the document,
+ // then nobody would call the doc's attachResource. So, we do it here, to ensure it's in a proper
+ // state, fires all events, and so on.
+ // #i105505#
+ xModel->attachResource( xModel->getURL(), m_aMediaDescriptor.getPropertyValues() );
+ }
+ }
+ return xModel;
+}
+
+void ODatabaseModelImpl::acquire()
+{
+ osl_atomic_increment(&m_refCount);
+}
+
+void ODatabaseModelImpl::release()
+{
+ if ( osl_atomic_decrement(&m_refCount) == 0 )
+ {
+ acquire(); // prevent multiple releases
+ m_rDBContext.removeFromTerminateListener(*this);
+ dispose();
+ m_rDBContext.storeTransientProperties(*this);
+ if (!m_sDocumentURL.isEmpty())
+ m_rDBContext.revokeDatabaseDocument(*this);
+ delete this;
+ }
+}
+
+void ODatabaseModelImpl::commitStorages()
+{
+ getDocumentStorageAccess()->commitStorages();
+}
+
+Reference< XStorage > ODatabaseModelImpl::getStorage( const ObjectType _eType )
+{
+ return getDocumentStorageAccess()->getDocumentSubStorage( getObjectContainerStorageName( _eType ),
+ css::embed::ElementModes::READWRITE );
+}
+
+const AsciiPropertyValue* ODatabaseModelImpl::getDefaultDataSourceSettings()
+{
+ static const AsciiPropertyValue aKnownSettings[] =
+ {
+ // known JDBC settings
+ AsciiPropertyValue( "JavaDriverClass", Any( OUString() ) ),
+ AsciiPropertyValue( "JavaDriverClassPath", Any( OUString() ) ),
+ AsciiPropertyValue( "IgnoreCurrency", Any( false ) ),
+ // known settings for file-based drivers
+ AsciiPropertyValue( "Extension", Any( OUString() ) ),
+ AsciiPropertyValue( "CharSet", Any( OUString() ) ),
+ AsciiPropertyValue( "HeaderLine", Any( true ) ),
+ AsciiPropertyValue( "FieldDelimiter", Any( OUString( "," ) ) ),
+ AsciiPropertyValue( "StringDelimiter", Any( OUString( "\"" ) ) ),
+ AsciiPropertyValue( "DecimalDelimiter", Any( OUString( "." ) ) ),
+ AsciiPropertyValue( "ThousandDelimiter", Any( OUString() ) ),
+ AsciiPropertyValue( "ShowDeleted", Any( false ) ),
+ // known ODBC settings
+ AsciiPropertyValue( "SystemDriverSettings", Any( OUString() ) ),
+ AsciiPropertyValue( "UseCatalog", Any( false ) ),
+ AsciiPropertyValue( "TypeInfoSettings", Any( Sequence< Any >()) ),
+ // settings related to auto increment handling
+ AsciiPropertyValue( "AutoIncrementCreation", Any( OUString() ) ),
+ AsciiPropertyValue( "AutoRetrievingStatement", Any( OUString() ) ),
+ AsciiPropertyValue( "IsAutoRetrievingEnabled", Any( false ) ),
+ // known LDAP driver settings
+ AsciiPropertyValue( "HostName", Any( OUString() ) ),
+ AsciiPropertyValue( "PortNumber", Any( sal_Int32(389) ) ),
+ AsciiPropertyValue( "BaseDN", Any( OUString() ) ),
+ AsciiPropertyValue( "MaxRowCount", Any( sal_Int32(100) ) ),
+ // known MySQLNative driver settings
+ AsciiPropertyValue( "LocalSocket", Any( OUString() ) ),
+ AsciiPropertyValue( "NamedPipe", Any( OUString() ) ),
+ // misc known driver settings
+ AsciiPropertyValue( "ParameterNameSubstitution", Any( false ) ),
+ AsciiPropertyValue( "AddIndexAppendix", Any( true ) ),
+ AsciiPropertyValue( "IgnoreDriverPrivileges", Any( true ) ),
+ AsciiPropertyValue( "ImplicitCatalogRestriction", ::cppu::UnoType< OUString >::get() ),
+ AsciiPropertyValue( "ImplicitSchemaRestriction", ::cppu::UnoType< OUString >::get() ),
+ AsciiPropertyValue( "PrimaryKeySupport", ::cppu::UnoType< sal_Bool >::get() ),
+ AsciiPropertyValue( "ShowColumnDescription", Any( false ) ),
+ // known SDB level settings
+ AsciiPropertyValue( "NoNameLengthLimit", Any( false ) ),
+ AsciiPropertyValue( "AppendTableAliasName", Any( false ) ),
+ AsciiPropertyValue( "GenerateASBeforeCorrelationName", Any( false ) ),
+ AsciiPropertyValue( "ColumnAliasInOrderBy", Any( true ) ),
+ AsciiPropertyValue( "EnableSQL92Check", Any( false ) ),
+ AsciiPropertyValue( "BooleanComparisonMode", Any( BooleanComparisonMode::EQUAL_INTEGER ) ),
+ AsciiPropertyValue( "TableTypeFilterMode", Any( sal_Int32(3) ) ),
+ AsciiPropertyValue( "RespectDriverResultSetType", Any( false ) ),
+ AsciiPropertyValue( "UseSchemaInSelect", Any( true ) ),
+ AsciiPropertyValue( "UseCatalogInSelect", Any( true ) ),
+ AsciiPropertyValue( "EnableOuterJoinEscape", Any( true ) ),
+ AsciiPropertyValue( "PreferDosLikeLineEnds", Any( false ) ),
+ AsciiPropertyValue( "FormsCheckRequiredFields", Any( true ) ),
+ AsciiPropertyValue( "EscapeDateTime", Any( true ) ),
+
+ // known services to handle database tasks
+ AsciiPropertyValue( "TableAlterationServiceName", Any( OUString() ) ),
+ AsciiPropertyValue( "TableRenameServiceName", Any( OUString() ) ),
+ AsciiPropertyValue( "ViewAlterationServiceName", Any( OUString() ) ),
+ AsciiPropertyValue( "ViewAccessServiceName", Any( OUString() ) ),
+ AsciiPropertyValue( "CommandDefinitions", Any( OUString() ) ),
+ AsciiPropertyValue( "Forms", Any( OUString() ) ),
+ AsciiPropertyValue( "Reports", Any( OUString() ) ),
+ AsciiPropertyValue( "KeyAlterationServiceName", Any( OUString() ) ),
+ AsciiPropertyValue( "IndexAlterationServiceName", Any( OUString() ) ),
+
+ AsciiPropertyValue()
+ };
+ return aKnownSettings;
+}
+
+TContentPtr& ODatabaseModelImpl::getObjectContainer( ObjectType _eType )
+{
+ OSL_PRECOND( _eType >= E_FORM && _eType <= E_TABLE, "ODatabaseModelImpl::getObjectContainer: illegal index!" );
+ TContentPtr& rContentPtr = m_aContainer[ _eType ];
+
+ if ( !rContentPtr )
+ {
+ rContentPtr = std::make_shared<ODefinitionContainer_Impl>();
+ rContentPtr->m_pDataSource = this;
+ rContentPtr->m_aProps.aTitle = lcl_getContainerStorageName_throw( _eType );
+ }
+ return rContentPtr;
+}
+
+bool ODatabaseModelImpl::adjustMacroMode_AutoReject()
+{
+ return m_aMacroMode.adjustMacroMode( nullptr );
+}
+
+bool ODatabaseModelImpl::checkMacrosOnLoading()
+{
+ Reference< XInteractionHandler > xInteraction;
+ xInteraction = m_aMediaDescriptor.getOrDefault( "InteractionHandler", xInteraction );
+ return m_aMacroMode.checkMacrosOnLoading( xInteraction );
+}
+
+void ODatabaseModelImpl::resetMacroExecutionMode()
+{
+ m_aMacroMode = ::sfx2::DocumentMacroMode( *this );
+}
+
+Reference< XStorageBasedLibraryContainer > ODatabaseModelImpl::getLibraryContainer( bool _bScript )
+{
+ Reference< XStorageBasedLibraryContainer >& rxContainer( _bScript ? m_xBasicLibraries : m_xDialogLibraries );
+ if ( rxContainer.is() )
+ return rxContainer;
+
+ Reference< XStorageBasedDocument > xDocument( getModel_noCreate(), UNO_QUERY_THROW );
+ // this is only to be called if there already exists a document model - in fact, it is
+ // to be called by the document model only
+
+ try
+ {
+ Reference< XStorageBasedLibraryContainer > (*Factory)( const Reference< XComponentContext >&, const Reference< XStorageBasedDocument >&)
+ = _bScript ? &DocumentScriptLibraryContainer::create : &DocumentDialogLibraryContainer::create;
+
+ rxContainer.set(
+ (*Factory)( m_aContext, xDocument ),
+ UNO_SET_THROW
+ );
+ }
+ catch( const RuntimeException& )
+ {
+ throw;
+ }
+ catch( const Exception& )
+ {
+ throw WrappedTargetRuntimeException(
+ OUString(),
+ xDocument,
+ ::cppu::getCaughtException()
+ );
+ }
+ return rxContainer;
+}
+
+void ODatabaseModelImpl::storeLibraryContainersTo( const Reference< XStorage >& _rxToRootStorage )
+{
+ if ( m_xBasicLibraries.is() )
+ m_xBasicLibraries->storeLibrariesToStorage( _rxToRootStorage );
+
+ if ( m_xDialogLibraries.is() )
+ m_xDialogLibraries->storeLibrariesToStorage( _rxToRootStorage );
+}
+
+Reference< XStorage > ODatabaseModelImpl::switchToStorage( const Reference< XStorage >& _rxNewRootStorage )
+{
+ if ( !_rxNewRootStorage.is() )
+ throw IllegalArgumentException();
+
+ return impl_switchToStorage_throw( _rxNewRootStorage );
+}
+
+namespace
+{
+ void lcl_modifyListening( ::sfx2::IModifiableDocument& _rDocument,
+ const Reference< XStorage >& _rxStorage, ::rtl::Reference< ::sfx2::DocumentStorageModifyListener >& _inout_rListener,
+ comphelper::SolarMutex& _rMutex, bool _bListen )
+ {
+ Reference< XModifiable > xModify( _rxStorage, UNO_QUERY );
+ OSL_ENSURE( xModify.is() || !_rxStorage.is(), "lcl_modifyListening: storage can't notify us!" );
+
+ if ( xModify.is() && !_bListen && _inout_rListener.is() )
+ {
+ xModify->removeModifyListener( _inout_rListener );
+ }
+
+ if ( _inout_rListener.is() )
+ {
+ _inout_rListener->dispose();
+ _inout_rListener = nullptr;
+ }
+
+ if ( xModify.is() && _bListen )
+ {
+ _inout_rListener = new ::sfx2::DocumentStorageModifyListener( _rDocument, _rMutex );
+ xModify->addModifyListener( _inout_rListener );
+ }
+ }
+}
+
+namespace
+{
+ void lcl_rebaseScriptStorage_throw( const Reference< XStorageBasedLibraryContainer >& _rxContainer,
+ const Reference< XStorage >& _rxNewRootStorage )
+ {
+ if ( _rxContainer.is() )
+ {
+ if ( _rxNewRootStorage.is() )
+ _rxContainer->setRootStorage( _rxNewRootStorage );
+// else
+ // TODO: what to do here? dispose the container?
+ }
+ }
+}
+
+Reference< XStorage > const & ODatabaseModelImpl::impl_switchToStorage_throw( const Reference< XStorage >& _rxNewRootStorage )
+{
+ // stop listening for modifications at the old storage
+ lcl_modifyListening( *this, m_xDocumentStorage.getTyped(), m_pStorageModifyListener, Application::GetSolarMutex(), false );
+
+ // set new storage
+ m_xDocumentStorage.reset( _rxNewRootStorage, SharedStorage::TakeOwnership );
+
+ // start listening for modifications
+ lcl_modifyListening( *this, m_xDocumentStorage.getTyped(), m_pStorageModifyListener, Application::GetSolarMutex(), true );
+
+ // forward new storage to Basic and Dialog library containers
+ lcl_rebaseScriptStorage_throw( m_xBasicLibraries, m_xDocumentStorage.getTyped() );
+ lcl_rebaseScriptStorage_throw( m_xDialogLibraries, m_xDocumentStorage.getTyped() );
+
+ m_bReadOnly = !tools::stor::storageIsWritable_nothrow( m_xDocumentStorage.getTyped() );
+ // TODO: our data source, if it exists, must broadcast the change of its ReadOnly property
+
+ return m_xDocumentStorage.getTyped();
+}
+
+void ODatabaseModelImpl::impl_switchToLogicalURL( const OUString& i_rDocumentURL )
+{
+ if ( i_rDocumentURL == m_sDocumentURL )
+ return;
+
+ const OUString sOldURL( m_sDocumentURL );
+ // update our name, if necessary
+ if ( ( m_sName == m_sDocumentURL ) // our name is our old URL
+ || ( m_sName.isEmpty() ) // we do not have a name, yet (i.e. are not registered at the database context)
+ )
+ {
+ INetURLObject aURL( i_rDocumentURL );
+ if ( aURL.GetProtocol() != INetProtocol::NotValid )
+ {
+ m_sName = i_rDocumentURL;
+ // TODO: our data source must broadcast the change of the Name property
+ }
+ }
+
+ // remember URL
+ m_sDocumentURL = i_rDocumentURL;
+
+ // update our location, if necessary
+ if ( m_sDocFileLocation.isEmpty() )
+ m_sDocFileLocation = m_sDocumentURL;
+
+ // register at the database context, or change registration
+ if (!sOldURL.isEmpty())
+ m_rDBContext.databaseDocumentURLChange( sOldURL, m_sDocumentURL );
+ else
+ m_rDBContext.registerDatabaseDocument( *this );
+}
+
+OUString ODatabaseModelImpl::getObjectContainerStorageName( const ObjectType _eType )
+{
+ return lcl_getContainerStorageName_throw( _eType );
+}
+
+sal_Int16 ODatabaseModelImpl::getCurrentMacroExecMode() const
+{
+ sal_Int16 nCurrentMode = MacroExecMode::NEVER_EXECUTE;
+ try
+ {
+ nCurrentMode = m_aMediaDescriptor.getOrDefault( "MacroExecutionMode", nCurrentMode );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ return nCurrentMode;
+}
+
+void ODatabaseModelImpl::setCurrentMacroExecMode( sal_uInt16 nMacroMode )
+{
+ m_aMediaDescriptor.put( "MacroExecutionMode", nMacroMode );
+}
+
+OUString ODatabaseModelImpl::getDocumentLocation() const
+{
+ return getURL();
+ // formerly, we returned getDocFileLocation here, which is the location of the file from which we
+ // recovered the "real" document.
+ // However, during CWS autorecovery evolving, we clarified (with MAV/MT) the role of XModel::getURL and
+ // XStorable::getLocation. In this course, we agreed that for a macro security check, the *document URL*
+ // (not the recovery file URL) is to be used: The recovery file lies in the backup folder, and by definition,
+ // this folder is considered to be secure. So, the document URL needs to be used to decide about the security.
+}
+
+ODatabaseModelImpl::EmbeddedMacros ODatabaseModelImpl::determineEmbeddedMacros()
+{
+ if ( !m_aEmbeddedMacros )
+ {
+ if ( ::sfx2::DocumentMacroMode::storageHasMacros( getOrCreateRootStorage() ) )
+ {
+ m_aEmbeddedMacros = eDocumentWideMacros;
+ }
+ else if ( lcl_hasObjectsWithMacros_nothrow( *this, E_FORM )
+ || lcl_hasObjectsWithMacros_nothrow( *this, E_REPORT )
+ )
+ {
+ m_aEmbeddedMacros = eSubDocumentMacros;
+ }
+ else
+ {
+ m_aEmbeddedMacros = eNoMacros;
+ }
+ }
+ return *m_aEmbeddedMacros;
+}
+
+bool ODatabaseModelImpl::documentStorageHasMacros() const
+{
+ const_cast< ODatabaseModelImpl* >( this )->determineEmbeddedMacros();
+ return ( *m_aEmbeddedMacros != eNoMacros );
+}
+
+bool ODatabaseModelImpl::macroCallsSeenWhileLoading() const
+{
+ return m_bMacroCallsSeenWhileLoading;
+}
+
+Reference< XEmbeddedScripts > ODatabaseModelImpl::getEmbeddedDocumentScripts() const
+{
+ return Reference< XEmbeddedScripts >( getModel_noCreate(), UNO_QUERY );
+}
+
+SignatureState ODatabaseModelImpl::getScriptingSignatureState()
+{
+ return m_nScriptingSignatureState;
+}
+
+bool ODatabaseModelImpl::hasTrustedScriptingSignature(bool bAllowUIToAddAuthor)
+{
+ bool bResult = false;
+
+ try
+ {
+ // Don't use m_xDocumentStorage, that somehow has an incomplete storage representation
+ // which leads to signatures not being found
+ Reference<XStorage> xStorage = comphelper::OStorageHelper::GetStorageOfFormatFromURL(
+ ZIP_STORAGE_FORMAT_STRING, m_sDocFileLocation, ElementModes::READ);
+
+ OUString aODFVersion(comphelper::OStorageHelper::GetODFVersionFromStorage(getOrCreateRootStorage()));
+ uno::Reference<security::XDocumentDigitalSignatures> xSigner(
+ security::DocumentDigitalSignatures::createWithVersion(
+ comphelper::getProcessComponentContext(), aODFVersion));
+ const uno::Sequence<security::DocumentSignatureInformation> aInfo
+ = xSigner->verifyScriptingContentSignatures(xStorage,
+ uno::Reference<io::XInputStream>());
+
+ if (!aInfo.hasElements())
+ return false;
+
+ m_nScriptingSignatureState = DocumentSignatures::getSignatureState(aInfo);
+ if (m_nScriptingSignatureState == SignatureState::OK
+ || m_nScriptingSignatureState == SignatureState::NOTVALIDATED)
+ {
+ bResult = std::any_of(aInfo.begin(), aInfo.end(),
+ [&xSigner](const security::DocumentSignatureInformation& rInfo) {
+ return xSigner->isAuthorTrusted(rInfo.Signer);
+ });
+ }
+
+ if (!bResult && bAllowUIToAddAuthor)
+ {
+ Reference<XInteractionHandler> xInteraction;
+ xInteraction = m_aMediaDescriptor.getOrDefault("InteractionHandler", xInteraction);
+ if (xInteraction.is())
+ {
+ task::DocumentMacroConfirmationRequest aRequest;
+ aRequest.DocumentURL = m_sDocFileLocation;
+ aRequest.DocumentStorage = xStorage;
+ aRequest.DocumentSignatureInformation = aInfo;
+ aRequest.DocumentVersion = aODFVersion;
+ aRequest.Classification = task::InteractionClassification_QUERY;
+ bResult = SfxMedium::CallApproveHandler(xInteraction, uno::Any(aRequest), true);
+ }
+ }
+ }
+ catch (uno::Exception&)
+ {
+ }
+
+ return bResult;
+}
+
+void ODatabaseModelImpl::storageIsModified()
+{
+ setModified( true );
+}
+
+ModelDependentComponent::ModelDependentComponent( const ::rtl::Reference< ODatabaseModelImpl >& _model )
+ :m_pImpl( _model )
+{
+}
+
+ModelDependentComponent::~ModelDependentComponent()
+{
+}
+
+} // namespace dbaccess
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/dataaccess/SharedConnection.cxx b/dbaccess/source/core/dataaccess/SharedConnection.cxx
new file mode 100644
index 000000000..31a8e68ba
--- /dev/null
+++ b/dbaccess/source/core/dataaccess/SharedConnection.cxx
@@ -0,0 +1,154 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "SharedConnection.hxx"
+#include <comphelper/uno3.hxx>
+
+namespace dbaccess
+{
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::container;
+using namespace connectivity;
+
+OSharedConnection::OSharedConnection(Reference<XAggregation>& _rxProxyConnection)
+ : OSharedConnection_BASE(m_aMutex)
+{
+ setDelegation(_rxProxyConnection, m_refCount);
+}
+
+OSharedConnection::~OSharedConnection() {}
+
+void SAL_CALL OSharedConnection::disposing()
+{
+ OSharedConnection_BASE::disposing();
+ OConnectionWrapper::disposing();
+}
+
+Reference<XStatement> SAL_CALL OSharedConnection::createStatement()
+{
+ ::osl::MutexGuard aGuard(m_aMutex);
+ checkDisposed(rBHelper.bDisposed);
+
+ return m_xConnection->createStatement();
+}
+
+Reference<XPreparedStatement> SAL_CALL OSharedConnection::prepareStatement(const OUString& sql)
+{
+ ::osl::MutexGuard aGuard(m_aMutex);
+ checkDisposed(rBHelper.bDisposed);
+
+ return m_xConnection->prepareStatement(sql);
+}
+
+Reference<XPreparedStatement> SAL_CALL OSharedConnection::prepareCall(const OUString& sql)
+{
+ ::osl::MutexGuard aGuard(m_aMutex);
+ checkDisposed(rBHelper.bDisposed);
+
+ return m_xConnection->prepareCall(sql);
+}
+
+OUString SAL_CALL OSharedConnection::nativeSQL(const OUString& sql)
+{
+ ::osl::MutexGuard aGuard(m_aMutex);
+ checkDisposed(rBHelper.bDisposed);
+
+ return m_xConnection->nativeSQL(sql);
+}
+
+sal_Bool SAL_CALL OSharedConnection::getAutoCommit()
+{
+ ::osl::MutexGuard aGuard(m_aMutex);
+ checkDisposed(rBHelper.bDisposed);
+
+ return m_xConnection->getAutoCommit();
+}
+
+void SAL_CALL OSharedConnection::commit()
+{
+ ::osl::MutexGuard aGuard(m_aMutex);
+ checkDisposed(rBHelper.bDisposed);
+
+ m_xConnection->commit();
+}
+
+void SAL_CALL OSharedConnection::rollback()
+{
+ ::osl::MutexGuard aGuard(m_aMutex);
+ checkDisposed(rBHelper.bDisposed);
+
+ m_xConnection->rollback();
+}
+
+sal_Bool SAL_CALL OSharedConnection::isClosed()
+{
+ ::osl::MutexGuard aGuard(m_aMutex);
+ if (!m_xConnection.is())
+ return true;
+
+ return m_xConnection->isClosed();
+}
+
+Reference<XDatabaseMetaData> SAL_CALL OSharedConnection::getMetaData()
+{
+ ::osl::MutexGuard aGuard(m_aMutex);
+ checkDisposed(rBHelper.bDisposed);
+
+ return m_xConnection->getMetaData();
+}
+
+sal_Bool SAL_CALL OSharedConnection::isReadOnly()
+{
+ ::osl::MutexGuard aGuard(m_aMutex);
+ checkDisposed(rBHelper.bDisposed);
+
+ return m_xConnection->isReadOnly();
+}
+
+OUString SAL_CALL OSharedConnection::getCatalog()
+{
+ ::osl::MutexGuard aGuard(m_aMutex);
+ checkDisposed(rBHelper.bDisposed);
+
+ return m_xConnection->getCatalog();
+}
+
+sal_Int32 SAL_CALL OSharedConnection::getTransactionIsolation()
+{
+ ::osl::MutexGuard aGuard(m_aMutex);
+ checkDisposed(rBHelper.bDisposed);
+
+ return m_xConnection->getTransactionIsolation();
+}
+
+Reference<css::container::XNameAccess> SAL_CALL OSharedConnection::getTypeMap()
+{
+ ::osl::MutexGuard aGuard(m_aMutex);
+ checkDisposed(rBHelper.bDisposed);
+
+ return m_xConnection->getTypeMap();
+}
+
+IMPLEMENT_GET_IMPLEMENTATION_ID(OSharedConnection)
+
+} // namespace dbaccess
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/dataaccess/SharedConnection.hxx b/dbaccess/source/core/dataaccess/SharedConnection.hxx
new file mode 100644
index 000000000..ea6e961cf
--- /dev/null
+++ b/dbaccess/source/core/dataaccess/SharedConnection.hxx
@@ -0,0 +1,118 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <connectivity/ConnectionWrapper.hxx>
+#include <connectivity/CommonTools.hxx>
+#include <cppuhelper/compbase.hxx>
+#include <cppuhelper/basemutex.hxx>
+#include <com/sun/star/sdbc/SQLException.hpp>
+#include <com/sun/star/sdbc/XConnection.hpp>
+#include <comphelper/sequence.hxx>
+
+namespace dbaccess
+{
+ // OSharedConnection: This class implements a simple forwarding of connection calls.
+ // All methods will be forwarded with exception of the set methods, which are not allowed
+ // to be called on shared connections. Instances of this class will be created when the
+ // datasource is asked for not isolated connection.
+ typedef ::cppu::WeakComponentImplHelper< css::sdbc::XConnection
+ > OSharedConnection_BASE;
+ typedef ::connectivity::OConnectionWrapper OSharedConnection_BASE2;
+
+ class OSharedConnection : public ::cppu::BaseMutex
+ , public OSharedConnection_BASE
+ , public OSharedConnection_BASE2
+ {
+ protected:
+ virtual void SAL_CALL disposing() override;
+ virtual ~OSharedConnection() override;
+ public:
+ explicit OSharedConnection(css::uno::Reference< css::uno::XAggregation >& _rxProxyConnection);
+
+ virtual css::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId( ) override;
+
+ virtual void SAL_CALL acquire() noexcept override { OSharedConnection_BASE::acquire(); }
+ virtual void SAL_CALL release() noexcept override { OSharedConnection_BASE::release(); }
+ virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes( ) override
+ {
+ return ::comphelper::concatSequences(
+ OSharedConnection_BASE::getTypes(),
+ OSharedConnection_BASE2::getTypes()
+ );
+ }
+
+ virtual css::uno::Any SAL_CALL queryInterface( const css::uno::Type& _rType ) override
+ {
+ css::uno::Any aReturn = OSharedConnection_BASE::queryInterface(_rType);
+ if ( !aReturn.hasValue() )
+ aReturn = OSharedConnection_BASE2::queryInterface(_rType);
+ return aReturn;
+ }
+
+ // XCloseable
+ virtual void SAL_CALL close( ) override
+ {
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+ ::connectivity::checkDisposed(rBHelper.bDisposed);
+ }
+ dispose();
+ }
+
+ // XConnection
+ virtual void SAL_CALL setAutoCommit( sal_Bool /*autoCommit*/ ) override
+ {
+ throw css::sdbc::SQLException("This call is not allowed when sharing connections.",*this,"S10000",0,css::uno::Any());
+ }
+ virtual void SAL_CALL setReadOnly( sal_Bool /*readOnly*/ ) override
+ {
+ throw css::sdbc::SQLException("This call is not allowed when sharing connections.",*this,"S10000",0,css::uno::Any());
+ }
+ virtual void SAL_CALL setCatalog( const OUString& /*catalog*/ ) override
+ {
+ throw css::sdbc::SQLException("This call is not allowed when sharing connections.",*this,"S10000",0,css::uno::Any());
+ }
+ virtual void SAL_CALL setTransactionIsolation( sal_Int32 /*level*/ ) override
+ {
+ throw css::sdbc::SQLException("This call is not allowed when sharing connections.",*this,"S10000",0,css::uno::Any());
+ }
+ virtual void SAL_CALL setTypeMap( const css::uno::Reference< css::container::XNameAccess >& /*typeMap*/ ) override
+ {
+ throw css::sdbc::SQLException("This call is not allowed when sharing connections.",*this,"S10000",0,css::uno::Any());
+ }
+ // XConnection
+ virtual css::uno::Reference< css::sdbc::XStatement > SAL_CALL createStatement( ) override;
+ virtual css::uno::Reference< css::sdbc::XPreparedStatement > SAL_CALL prepareStatement( const OUString& sql ) override;
+ virtual css::uno::Reference< css::sdbc::XPreparedStatement > SAL_CALL prepareCall( const OUString& sql ) override;
+ virtual OUString SAL_CALL nativeSQL( const OUString& sql ) override;
+ virtual sal_Bool SAL_CALL getAutoCommit( ) override;
+ virtual void SAL_CALL commit( ) override;
+ virtual void SAL_CALL rollback( ) override;
+ virtual sal_Bool SAL_CALL isClosed( ) override;
+ virtual css::uno::Reference< css::sdbc::XDatabaseMetaData > SAL_CALL getMetaData( ) override;
+ virtual sal_Bool SAL_CALL isReadOnly( ) override;
+ virtual OUString SAL_CALL getCatalog( ) override;
+ virtual sal_Int32 SAL_CALL getTransactionIsolation( ) override;
+ virtual css::uno::Reference< css::container::XNameAccess > SAL_CALL getTypeMap( ) override;
+ };
+
+} // namespace dbaccess
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/dataaccess/bookmarkcontainer.cxx b/dbaccess/source/core/dataaccess/bookmarkcontainer.cxx
new file mode 100644
index 000000000..a03caea57
--- /dev/null
+++ b/dbaccess/source/core/dataaccess/bookmarkcontainer.cxx
@@ -0,0 +1,301 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <bookmarkcontainer.hxx>
+
+#include <o3tl/safeint.hxx>
+#include <osl/diagnose.h>
+#include <comphelper/enumhelper.hxx>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <com/sun/star/lang/NoSupportException.hpp>
+#include <cppuhelper/supportsservice.hxx>
+
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::container;
+using namespace ::osl;
+using namespace ::comphelper;
+using namespace ::cppu;
+
+namespace dbaccess
+{
+
+// OBookmarkContainer
+
+OBookmarkContainer::OBookmarkContainer(OWeakObject& _rParent, Mutex& _rMutex)
+ :m_rParent(_rParent)
+ ,m_aContainerListeners(_rMutex)
+ ,m_rMutex(_rMutex)
+{
+}
+
+
+void SAL_CALL OBookmarkContainer::acquire( ) noexcept
+{
+ m_rParent.acquire();
+}
+
+void SAL_CALL OBookmarkContainer::release( ) noexcept
+{
+ m_rParent.release();
+}
+
+OBookmarkContainer::~OBookmarkContainer()
+{
+}
+
+// XServiceInfo
+OUString SAL_CALL OBookmarkContainer::getImplementationName( )
+{
+ return "com.sun.star.comp.dba.OBookmarkContainer";
+}
+
+sal_Bool SAL_CALL OBookmarkContainer::supportsService( const OUString& _rServiceName )
+{
+ return cppu::supportsService(this, _rServiceName);
+}
+
+Sequence< OUString > SAL_CALL OBookmarkContainer::getSupportedServiceNames( )
+{
+ return { "com.sun.star.sdb.DefinitionContainer" };
+}
+
+// XNameContainer
+void SAL_CALL OBookmarkContainer::insertByName( const OUString& _rName, const Any& aElement )
+{
+ MutexGuard aGuard(m_rMutex);
+
+ if (checkExistence(_rName))
+ throw ElementExistException();
+
+ if (_rName.isEmpty())
+ throw IllegalArgumentException();
+
+ // approve the new object
+ OUString sNewLink;
+ if (!(aElement >>= sNewLink))
+ throw IllegalArgumentException();
+
+ implAppend(_rName, sNewLink);
+
+ // notify the listeners
+ if (m_aContainerListeners.getLength())
+ {
+ ContainerEvent aEvent(*this, Any(_rName), Any(sNewLink), Any());
+ m_aContainerListeners.notifyEach( &XContainerListener::elementInserted, aEvent );
+ }
+}
+
+void SAL_CALL OBookmarkContainer::removeByName( const OUString& _rName )
+{
+ OUString sOldBookmark;
+ {
+ MutexGuard aGuard(m_rMutex);
+
+ // check the arguments
+ if (_rName.isEmpty())
+ throw IllegalArgumentException();
+
+ if (!checkExistence(_rName))
+ throw NoSuchElementException();
+
+ // the old element (for the notifications)
+ sOldBookmark = m_aBookmarks[_rName];
+
+ // do the removal
+ implRemove(_rName);
+ }
+
+ // notify the listeners
+ if (m_aContainerListeners.getLength())
+ {
+ ContainerEvent aEvent(*this, Any(_rName), Any(sOldBookmark), Any());
+ m_aContainerListeners.notifyEach( &XContainerListener::elementRemoved, aEvent );
+ }
+}
+
+// XNameReplace
+void SAL_CALL OBookmarkContainer::replaceByName( const OUString& _rName, const Any& aElement )
+{
+ ClearableMutexGuard aGuard(m_rMutex);
+
+ // check the arguments
+ if (_rName.isEmpty())
+ throw IllegalArgumentException();
+
+ // do we have such an element?
+ if (!checkExistence(_rName))
+ throw NoSuchElementException();
+
+ // approve the new object
+ OUString sNewLink;
+ if (!(aElement >>= sNewLink))
+ throw IllegalArgumentException();
+
+ // the old element (for the notifications)
+ OUString sOldLink = m_aBookmarks[_rName];
+
+ // do the replace
+ implReplace(_rName, sNewLink);
+
+ // notify the listeners
+ aGuard.clear();
+ if (m_aContainerListeners.getLength())
+ {
+ ContainerEvent aEvent(*this, Any(_rName), Any(sNewLink), Any(sOldLink));
+ m_aContainerListeners.notifyEach( &XContainerListener::elementReplaced, aEvent );
+ }
+}
+
+void SAL_CALL OBookmarkContainer::addContainerListener( const Reference< XContainerListener >& _rxListener )
+{
+ MutexGuard aGuard(m_rMutex);
+ if (_rxListener.is())
+ m_aContainerListeners.addInterface(_rxListener);
+}
+
+void SAL_CALL OBookmarkContainer::removeContainerListener( const Reference< XContainerListener >& _rxListener )
+{
+ MutexGuard aGuard(m_rMutex);
+ if (_rxListener.is())
+ m_aContainerListeners.removeInterface(_rxListener);
+}
+
+// XElementAccess
+Type SAL_CALL OBookmarkContainer::getElementType( )
+{
+ return ::cppu::UnoType<OUString>::get();
+}
+
+sal_Bool SAL_CALL OBookmarkContainer::hasElements( )
+{
+ MutexGuard aGuard(m_rMutex);
+ return !m_aBookmarks.empty();
+}
+
+// XEnumerationAccess
+Reference< XEnumeration > SAL_CALL OBookmarkContainer::createEnumeration( )
+{
+ MutexGuard aGuard(m_rMutex);
+ return new ::comphelper::OEnumerationByIndex(static_cast<XIndexAccess*>(this));
+}
+
+// XIndexAccess
+sal_Int32 SAL_CALL OBookmarkContainer::getCount( )
+{
+ MutexGuard aGuard(m_rMutex);
+ return m_aBookmarks.size();
+}
+
+Any SAL_CALL OBookmarkContainer::getByIndex( sal_Int32 _nIndex )
+{
+ MutexGuard aGuard(m_rMutex);
+
+ if ((_nIndex < 0) || (o3tl::make_unsigned(_nIndex) >= m_aBookmarksIndexed.size()))
+ throw IndexOutOfBoundsException();
+
+ return Any(m_aBookmarksIndexed[_nIndex]->second);
+}
+
+Any SAL_CALL OBookmarkContainer::getByName( const OUString& _rName )
+{
+ MutexGuard aGuard(m_rMutex);
+
+ if (!checkExistence(_rName))
+ throw NoSuchElementException();
+
+ return Any(m_aBookmarks[_rName]);
+}
+
+Sequence< OUString > SAL_CALL OBookmarkContainer::getElementNames( )
+{
+ MutexGuard aGuard(m_rMutex);
+
+ Sequence< OUString > aNames(m_aBookmarks.size());
+ OUString* pNames = aNames.getArray();
+
+ for (auto const& bookmarkIndexed : m_aBookmarksIndexed)
+ {
+ *pNames = bookmarkIndexed->first;
+ ++pNames;
+ }
+
+ return aNames;
+}
+
+sal_Bool SAL_CALL OBookmarkContainer::hasByName( const OUString& _rName )
+{
+ MutexGuard aGuard(m_rMutex);
+
+ return checkExistence(_rName);
+}
+
+void OBookmarkContainer::implRemove(const OUString& _rName)
+{
+ MutexGuard aGuard(m_rMutex);
+
+ // look for the name in the index access vector
+ MapString2String::const_iterator aMapPos = m_aBookmarks.end();
+ auto aSearch = std::find_if(m_aBookmarksIndexed.begin(), m_aBookmarksIndexed.end(),
+ [&_rName](const MapString2String::iterator& rIter) { return rIter->first == _rName; });
+ if (aSearch != m_aBookmarksIndexed.end())
+ {
+ aMapPos = *aSearch;
+ m_aBookmarksIndexed.erase(aSearch);
+ }
+
+ if (m_aBookmarks.end() == aMapPos)
+ {
+ OSL_FAIL("OBookmarkContainer::implRemove: inconsistence!");
+ return;
+ }
+
+ // remove the map entries
+ m_aBookmarks.erase(aMapPos);
+}
+
+void OBookmarkContainer::implAppend(const OUString& _rName, const OUString& _rDocumentLocation)
+{
+ MutexGuard aGuard(m_rMutex);
+
+ OSL_ENSURE(m_aBookmarks.find(_rName) == m_aBookmarks.end(),"Bookmark already known!");
+ m_aBookmarksIndexed.push_back(m_aBookmarks.emplace( _rName,_rDocumentLocation).first);
+}
+
+void OBookmarkContainer::implReplace(const OUString& _rName, const OUString& _rNewLink)
+{
+ MutexGuard aGuard(m_rMutex);
+ OSL_ENSURE(checkExistence(_rName), "OBookmarkContainer::implReplace : invalid name !");
+
+ m_aBookmarks[_rName] = _rNewLink;
+}
+
+Reference< XInterface > SAL_CALL OBookmarkContainer::getParent( )
+{
+ return m_rParent;
+}
+
+void SAL_CALL OBookmarkContainer::setParent( const Reference< XInterface >& /*Parent*/ )
+{
+ throw NoSupportException();
+}
+
+} // namespace dbaccess
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/dataaccess/commandcontainer.cxx b/dbaccess/source/core/dataaccess/commandcontainer.cxx
new file mode 100644
index 000000000..8afb81520
--- /dev/null
+++ b/dbaccess/source/core/dataaccess/commandcontainer.cxx
@@ -0,0 +1,100 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "commandcontainer.hxx"
+#include "commanddefinition.hxx"
+
+#include <com/sun/star/sdb/TableDefinition.hpp>
+#include <com/sun/star/sdb/CommandDefinition.hpp>
+
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::ucb;
+using namespace ::osl;
+using namespace ::comphelper;
+using namespace ::cppu;
+
+namespace dbaccess
+{
+
+// OCommandContainer
+
+OCommandContainer::OCommandContainer( const Reference< css::uno::XComponentContext >& _xORB
+ ,const Reference< XInterface >& _xParentContainer
+ ,const TContentPtr& _pImpl
+ ,bool _bTables
+ )
+ :ODefinitionContainer(_xORB,_xParentContainer,_pImpl,!_bTables)
+ ,m_bTables(_bTables)
+{
+}
+
+OCommandContainer::~OCommandContainer()
+{
+}
+
+IMPLEMENT_FORWARD_XINTERFACE2( OCommandContainer,ODefinitionContainer,OCommandContainer_BASE)
+css::uno::Sequence< css::uno::Type > OCommandContainer::getTypes()
+{
+ return ::comphelper::concatSequences(
+ ODefinitionContainer::getTypes( ),
+ OCommandContainer_BASE::getTypes( )
+ );
+}
+
+css::uno::Sequence<sal_Int8> OCommandContainer::getImplementationId()
+{
+ return css::uno::Sequence<sal_Int8>();
+}
+
+Reference< XContent > OCommandContainer::createObject( const OUString& _rName)
+{
+ const ODefinitionContainer_Impl& rDefinitions( getDefinitions() );
+ OSL_ENSURE( rDefinitions.find(_rName) != rDefinitions.end(), "OCommandContainer::createObject: Invalid entry in map!" );
+
+ const TContentPtr& pElementContent( rDefinitions.find( _rName )->second );
+ if ( m_bTables )
+ return new OComponentDefinition( *this, _rName, m_aContext, pElementContent, m_bTables );
+ else
+ return static_cast< css::sdb::XQueryDefinition * > ( new OCommandDefinition( *this, _rName, m_aContext, pElementContent ) );
+}
+
+Reference< XInterface > SAL_CALL OCommandContainer::createInstanceWithArguments(const Sequence< Any >& /*aArguments*/ )
+{
+ return createInstance( );
+}
+
+Reference< XInterface > SAL_CALL OCommandContainer::createInstance( )
+{
+ if(m_bTables)
+ return css::sdb::TableDefinition::createDefault( m_aContext );
+ else
+ return css::sdb::CommandDefinition::create( m_aContext );
+}
+
+OUString OCommandContainer::determineContentType() const
+{
+ return "application/vnd.org.openoffice.DatabaseCommandDefinitionContainer";
+}
+
+} // namespace dbaccess
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/dataaccess/commandcontainer.hxx b/dbaccess/source/core/dataaccess/commandcontainer.hxx
new file mode 100644
index 000000000..3ea36f648
--- /dev/null
+++ b/dbaccess/source/core/dataaccess/commandcontainer.hxx
@@ -0,0 +1,72 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <definitioncontainer.hxx>
+
+#include <com/sun/star/lang/XSingleServiceFactory.hpp>
+
+#include <cppuhelper/implbase1.hxx>
+
+namespace dbaccess
+{
+// OCommandContainer
+
+typedef ::cppu::ImplHelper1 < css::lang::XSingleServiceFactory
+ > OCommandContainer_BASE;
+
+class OCommandContainer : public ODefinitionContainer
+ ,public OCommandContainer_BASE
+{
+ bool m_bTables;
+
+public:
+ /** constructs the container.<BR>
+ */
+ OCommandContainer(
+ const css::uno::Reference< css::uno::XComponentContext >& _xORB
+ ,const css::uno::Reference< css::uno::XInterface >& _xParentContainer
+ ,const TContentPtr& _pImpl
+ ,bool _bTables
+ );
+
+ DECLARE_XINTERFACE( )
+
+ virtual css::uno::Sequence<css::uno::Type> SAL_CALL getTypes() override;
+ virtual css::uno::Sequence<sal_Int8> SAL_CALL getImplementationId() override;
+
+ // XSingleServiceFactory
+ virtual css::uno::Reference< css::uno::XInterface > SAL_CALL createInstance( ) override;
+ virtual css::uno::Reference< css::uno::XInterface > SAL_CALL createInstanceWithArguments( const css::uno::Sequence< css::uno::Any >& aArguments ) override;
+
+protected:
+ virtual ~OCommandContainer() override;
+
+ // ODefinitionContainer
+ virtual css::uno::Reference< css::ucb::XContent > createObject(const OUString& _rName) override;
+
+protected:
+ // OContentHelper overridables
+ virtual OUString determineContentType() const override;
+};
+
+} // namespace dbaccess
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/dataaccess/commanddefinition.cxx b/dbaccess/source/core/dataaccess/commanddefinition.cxx
new file mode 100644
index 000000000..f04c47228
--- /dev/null
+++ b/dbaccess/source/core/dataaccess/commanddefinition.cxx
@@ -0,0 +1,153 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "commanddefinition.hxx"
+#include <stringconstants.hxx>
+#include <strings.hxx>
+
+#include <com/sun/star/container/ElementExistException.hpp>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+
+
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::container;
+
+namespace dbaccess
+{
+
+void OCommandDefinition::registerProperties()
+{
+ OCommandDefinition_Impl& rCommandDefinition = dynamic_cast< OCommandDefinition_Impl& >( *m_pImpl );
+ registerProperty(PROPERTY_COMMAND, PROPERTY_ID_COMMAND, PropertyAttribute::BOUND,
+ &rCommandDefinition.m_sCommand, cppu::UnoType<decltype(rCommandDefinition.m_sCommand)>::get());
+
+ registerProperty(PROPERTY_ESCAPE_PROCESSING, PROPERTY_ID_ESCAPE_PROCESSING, PropertyAttribute::BOUND,
+ &rCommandDefinition.m_bEscapeProcessing, cppu::UnoType<bool>::get());
+
+ registerProperty(PROPERTY_UPDATE_TABLENAME, PROPERTY_ID_UPDATE_TABLENAME, PropertyAttribute::BOUND,
+ &rCommandDefinition.m_sUpdateTableName, cppu::UnoType<decltype(rCommandDefinition.m_sUpdateTableName)>::get());
+
+ registerProperty(PROPERTY_UPDATE_SCHEMANAME, PROPERTY_ID_UPDATE_SCHEMANAME, PropertyAttribute::BOUND,
+ &rCommandDefinition.m_sUpdateSchemaName, cppu::UnoType<decltype(rCommandDefinition.m_sUpdateSchemaName)>::get());
+
+ registerProperty(PROPERTY_UPDATE_CATALOGNAME, PROPERTY_ID_UPDATE_CATALOGNAME, PropertyAttribute::BOUND,
+ &rCommandDefinition.m_sUpdateCatalogName, cppu::UnoType<decltype(rCommandDefinition.m_sUpdateCatalogName)>::get());
+ registerProperty(PROPERTY_LAYOUTINFORMATION, PROPERTY_ID_LAYOUTINFORMATION, PropertyAttribute::BOUND,
+ &rCommandDefinition.m_aLayoutInformation, cppu::UnoType<decltype(rCommandDefinition.m_aLayoutInformation)>::get());
+}
+
+OCommandDefinition::OCommandDefinition(const Reference< XComponentContext >& _xORB
+ ,const Reference< XInterface >& _rxContainer
+ ,const TContentPtr& _pImpl)
+ :OComponentDefinition(_xORB,_rxContainer,_pImpl,false)
+{
+ registerProperties();
+}
+
+OCommandDefinition::~OCommandDefinition()
+{
+}
+
+OCommandDefinition::OCommandDefinition( const Reference< XInterface >& _rxContainer
+ ,const OUString& _rElementName
+ ,const Reference< XComponentContext >& _xORB
+ ,const TContentPtr& _pImpl)
+ :OComponentDefinition(_rxContainer,_rElementName,_xORB,_pImpl,false)
+{
+ registerProperties();
+}
+
+css::uno::Sequence<sal_Int8> OCommandDefinition::getImplementationId()
+{
+ return css::uno::Sequence<sal_Int8>();
+}
+
+css::uno::Sequence< css::uno::Type > OCommandDefinition::getTypes()
+{
+ return ::comphelper::concatSequences(
+ OCommandDefinition_Base::getTypes( ),
+ OComponentDefinition::getTypes( )
+ );
+}
+IMPLEMENT_FORWARD_XINTERFACE2( OCommandDefinition,OComponentDefinition,OCommandDefinition_Base)
+css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL OCommandDefinition::getPropertySetInfo()
+{
+ Reference< XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) );
+ return xInfo;
+}
+::cppu::IPropertyArrayHelper& OCommandDefinition::getInfoHelper()
+{
+ return *OCommandDefinition_PROP::getArrayHelper();
+}
+::cppu::IPropertyArrayHelper* OCommandDefinition::createArrayHelper( ) const
+{
+ css::uno::Sequence< css::beans::Property > aProps;
+ describeProperties(aProps);
+ return new ::cppu::OPropertyArrayHelper(aProps);
+}
+
+
+OUString SAL_CALL OCommandDefinition::getImplementationName()
+{
+ return "com.sun.star.comp.dba.OCommandDefinition";
+}
+
+css::uno::Sequence<OUString> SAL_CALL OCommandDefinition::getSupportedServiceNames()
+{
+ return {
+ "com.sun.star.sdb.QueryDefinition",
+ "com.sun.star.sdb.CommandDefinition",
+ "com.sun.star.ucb.Content"
+ };
+}
+
+void SAL_CALL OCommandDefinition::rename( const OUString& newName )
+{
+ try
+ {
+ sal_Int32 nHandle = PROPERTY_ID_NAME;
+ osl::ClearableGuard< osl::Mutex > aGuard(m_aMutex);
+ Any aOld(m_pImpl->m_aProps.aTitle);
+ aGuard.clear();
+ Any aNew(newName);
+ fire(&nHandle, &aNew, &aOld, 1, true );
+
+ m_pImpl->m_aProps.aTitle = newName;
+ fire(&nHandle, &aNew, &aOld, 1, false );
+ }
+ catch(const PropertyVetoException&)
+ {
+ throw ElementExistException(newName,*this);
+ }
+}
+
+} // namespace dbaccess
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+com_sun_star_comp_dba_OCommandDefinition(css::uno::XComponentContext* context,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new dbaccess::OCommandDefinition(
+ context, nullptr, std::make_shared<dbaccess::OCommandDefinition_Impl>() ));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/dataaccess/commanddefinition.hxx b/dbaccess/source/core/dataaccess/commanddefinition.hxx
new file mode 100644
index 000000000..ed348a889
--- /dev/null
+++ b/dbaccess/source/core/dataaccess/commanddefinition.hxx
@@ -0,0 +1,125 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <commandbase.hxx>
+#include <apitools.hxx>
+#include <com/sun/star/container/XNameAccess.hpp>
+#include <com/sun/star/sdbcx/XRename.hpp>
+#include <com/sun/star/sdb/XQueryDefinition.hpp>
+#include <datasettings.hxx>
+#include <ContentHelper.hxx>
+#include "ComponentDefinition.hxx"
+
+#include <comphelper/proparrhlp.hxx>
+#include <comphelper/uno3.hxx>
+#include <cppuhelper/implbase2.hxx>
+
+namespace dbaccess
+{
+
+// OCommandDefinition - a database "document" which describes a query
+ class OCommandDefinition_Impl : public OComponentDefinition_Impl
+ ,public OCommandBase
+ {
+ public:
+ };
+
+typedef ::cppu::ImplHelper2 < css::sdbcx::XRename,
+ css::sdb::XQueryDefinition
+ > OCommandDefinition_Base;
+class OCommandDefinition;
+typedef ::comphelper::OPropertyArrayUsageHelper< OCommandDefinition >
+ OCommandDefinition_PROP;
+
+class OCommandDefinition : public OComponentDefinition
+ ,public OCommandDefinition_Base
+ ,public OCommandDefinition_PROP
+{
+protected:
+ virtual ~OCommandDefinition() override;
+
+public:
+ OCommandDefinition(const css::uno::Reference< css::uno::XComponentContext >& ,
+ const css::uno::Reference< css::uno::XInterface >& _xParentContainer,
+ const TContentPtr& _pImpl);
+
+ OCommandDefinition(
+ const css::uno::Reference< css::uno::XInterface >& _rxContainer
+ ,const OUString& _rElementName
+ ,const css::uno::Reference< css::uno::XComponentContext >&
+ ,const TContentPtr& _pImpl
+ );
+
+ virtual css::uno::Sequence<css::uno::Type> SAL_CALL getTypes() override;
+ virtual css::uno::Sequence<sal_Int8> SAL_CALL getImplementationId() override;
+
+// css::uno::XInterface
+ DECLARE_XINTERFACE( )
+
+// css::lang::XServiceInfo
+ virtual OUString SAL_CALL getImplementationName( ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override;
+
+ // XRename
+ virtual void SAL_CALL rename( const OUString& newName ) override;
+
+ // overrides to resolve ambiguity
+ virtual void SAL_CALL setPropertyValue(const OUString& p1, const css::uno::Any& p2) override
+ { OComponentDefinition::setPropertyValue(p1, p2); }
+ virtual css::uno::Any SAL_CALL getPropertyValue(const OUString& p1) override
+ { return OComponentDefinition::getPropertyValue(p1); }
+ virtual void SAL_CALL addPropertyChangeListener(const OUString& p1, const css::uno::Reference<css::beans::XPropertyChangeListener>& p2) override
+ { OComponentDefinition::addPropertyChangeListener(p1, p2); }
+ virtual void SAL_CALL removePropertyChangeListener(const OUString& p1, const css::uno::Reference<css::beans::XPropertyChangeListener>& p2) override
+ { OComponentDefinition::removePropertyChangeListener(p1, p2); }
+ virtual void SAL_CALL addVetoableChangeListener(const OUString& p1, const css::uno::Reference<css::beans::XVetoableChangeListener>& p2) override
+ { OComponentDefinition::addVetoableChangeListener(p1, p2); }
+ virtual void SAL_CALL removeVetoableChangeListener(const OUString& p1, const css::uno::Reference<css::beans::XVetoableChangeListener>& p2) override
+ { OComponentDefinition::removeVetoableChangeListener(p1, p2); }
+ virtual css::uno::Reference<css::ucb::XContentIdentifier> SAL_CALL getIdentifier() override
+ { return OComponentDefinition::getIdentifier(); }
+ virtual OUString SAL_CALL getContentType() override
+ { return OComponentDefinition::getContentType(); }
+ virtual void SAL_CALL addContentEventListener(const css::uno::Reference<css::ucb::XContentEventListener>& p1) override
+ { OComponentDefinition::addContentEventListener(p1); }
+ virtual void SAL_CALL removeContentEventListener(const css::uno::Reference<css::ucb::XContentEventListener>& p1) override
+ { OComponentDefinition::removeContentEventListener(p1); }
+ virtual void SAL_CALL dispose() override
+ { OComponentDefinition::dispose(); }
+ virtual void SAL_CALL addEventListener(const css::uno::Reference<css::lang::XEventListener>& p1) override
+ { OComponentDefinition::addEventListener(p1); }
+ virtual void SAL_CALL removeEventListener(const css::uno::Reference<css::lang::XEventListener>& p1) override
+ { OComponentDefinition::removeEventListener(p1); }
+
+ // OPropertySetHelper
+ virtual css::uno::Reference<css::beans::XPropertySetInfo> SAL_CALL getPropertySetInfo() override;
+ virtual cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper() override;
+ virtual cppu::IPropertyArrayHelper* createArrayHelper() const override;
+
+
+private:
+ // helper
+ void registerProperties();
+};
+
+} // namespace dbaccess
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/dataaccess/connection.cxx b/dbaccess/source/core/dataaccess/connection.cxx
new file mode 100644
index 000000000..37cf9e669
--- /dev/null
+++ b/dbaccess/source/core/dataaccess/connection.cxx
@@ -0,0 +1,808 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+
+#include <iterator>
+
+#include "connection.hxx"
+#include "datasource.hxx"
+#include <strings.hrc>
+#include <strings.hxx>
+#include <core_resource.hxx>
+#include <statement.hxx>
+#include <preparedstatement.hxx>
+#include <callablestatement.hxx>
+#include <SingleSelectQueryComposer.hxx>
+#include <querycomposer.hxx>
+
+#include <com/sun/star/lang/NoSupportException.hpp>
+#include <com/sun/star/sdb/CommandType.hpp>
+#include <com/sun/star/sdb/tools/ConnectionTools.hpp>
+#include <com/sun/star/reflection/ProxyFactory.hpp>
+#include <com/sun/star/beans/NamedValue.hpp>
+#include <connectivity/dbtools.hxx>
+#include <connectivity/dbmetadata.hxx>
+#include <tools/diagnose_ex.h>
+#include <osl/diagnose.h>
+#include <comphelper/sequence.hxx>
+#include <comphelper/types.hxx>
+#include <cppuhelper/supportsservice.hxx>
+
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::util;
+using namespace ::com::sun::star::sdb;
+using namespace ::com::sun::star::sdb::application;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::sdbcx;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::reflection;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::graphic;
+using namespace ::osl;
+using namespace ::comphelper;
+using namespace ::cppu;
+using namespace ::dbtools;
+
+using ::com::sun::star::sdb::tools::XTableName;
+using ::com::sun::star::sdb::tools::XObjectNames;
+using ::com::sun::star::sdb::tools::XDataSourceMetaData;
+
+namespace dbaccess
+{
+
+// XServiceInfo
+OUString OConnection::getImplementationName( )
+{
+ return "com.sun.star.comp.dbaccess.Connection";
+}
+
+sal_Bool OConnection::supportsService( const OUString& _rServiceName )
+{
+ return cppu::supportsService(this, _rServiceName);
+}
+
+Sequence< OUString > OConnection::getSupportedServiceNames( )
+{
+ Sequence< OUString > aSupported = OConnectionWrapper::getSupportedServiceNames();
+
+ if ( comphelper::findValue( aSupported, SERVICE_SDB_CONNECTION ) == -1 )
+ {
+ sal_Int32 nLen = aSupported.getLength();
+ aSupported.realloc( nLen + 1 );
+ aSupported.getArray()[ nLen ] = SERVICE_SDB_CONNECTION;
+ }
+
+ return aSupported;
+}
+
+// XCloseable
+void OConnection::close()
+{
+ // being closed is the same as being disposed
+ dispose();
+}
+
+sal_Bool OConnection::isClosed()
+{
+ MutexGuard aGuard(m_aMutex);
+ return !m_xMasterConnection.is();
+}
+
+// XConnection
+Reference< XStatement > OConnection::createStatement()
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed();
+
+ Reference< XStatement > xStatement;
+ Reference< XStatement > xMasterStatement = m_xMasterConnection->createStatement();
+ if ( xMasterStatement.is() )
+ {
+ xStatement = new OStatement(this, xMasterStatement);
+ m_aStatements.emplace_back(xStatement);
+ }
+ return xStatement;
+}
+
+Reference< XPreparedStatement > OConnection::prepareStatement(const OUString& sql)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed();
+
+ // TODO convert the SQL to SQL the driver understands
+ Reference< XPreparedStatement > xStatement;
+ Reference< XPreparedStatement > xMasterStatement = m_xMasterConnection->prepareStatement(sql);
+ if ( xMasterStatement.is() )
+ {
+ xStatement = new OPreparedStatement(this, xMasterStatement);
+ m_aStatements.emplace_back(xStatement);
+ }
+ return xStatement;
+}
+
+Reference< XPreparedStatement > OConnection::prepareCall(const OUString& sql)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed();
+
+ Reference< XPreparedStatement > xStatement;
+ Reference< XPreparedStatement > xMasterStatement = m_xMasterConnection->prepareCall(sql);
+ if ( xMasterStatement.is() )
+ {
+ xStatement = new OCallableStatement(this, xMasterStatement);
+ m_aStatements.emplace_back(xStatement);
+ }
+ return xStatement;
+}
+
+OUString OConnection::nativeSQL(const OUString& sql)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed();
+ return m_xMasterConnection->nativeSQL(sql);
+}
+
+void OConnection::setAutoCommit(sal_Bool autoCommit)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed();
+ m_xMasterConnection->setAutoCommit(autoCommit);
+}
+
+sal_Bool OConnection::getAutoCommit()
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed();
+ return m_xMasterConnection->getAutoCommit();
+}
+
+void OConnection::commit()
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed();
+ m_xMasterConnection->commit();
+}
+
+void OConnection::rollback()
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed();
+ m_xMasterConnection->rollback();
+}
+
+Reference< XDatabaseMetaData > OConnection::getMetaData()
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed();
+ return m_xMasterConnection->getMetaData();
+}
+
+void OConnection::setReadOnly(sal_Bool readOnly)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed();
+ m_xMasterConnection->setReadOnly(readOnly);
+}
+
+sal_Bool OConnection::isReadOnly()
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed();
+ return m_xMasterConnection->isReadOnly();
+}
+
+void OConnection::setCatalog(const OUString& catalog)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed();
+ m_xMasterConnection->setCatalog(catalog);
+}
+
+OUString OConnection::getCatalog()
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed();
+ return m_xMasterConnection->getCatalog();
+}
+
+void OConnection::setTransactionIsolation(sal_Int32 level)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed();
+ m_xMasterConnection->setTransactionIsolation(level);
+}
+
+sal_Int32 OConnection::getTransactionIsolation()
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed();
+ return m_xMasterConnection->getTransactionIsolation();
+}
+
+Reference< XNameAccess > OConnection::getTypeMap()
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed();
+ return m_xMasterConnection->getTypeMap();
+}
+
+void OConnection::setTypeMap(const Reference< XNameAccess > & typeMap)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed();
+ m_xMasterConnection->setTypeMap(typeMap);
+}
+
+// OConnection
+
+OConnection::OConnection(ODatabaseSource& _rDB
+ , Reference< XConnection > const & _rxMaster
+ , const Reference< XComponentContext >& _rxORB)
+ :OSubComponent(m_aMutex, static_cast< OWeakObject* >(&_rDB))
+ // as the queries reroute their refcounting to us, this m_aMutex is okey. If the queries
+ // container would do its own refcounting, it would have to acquire m_pMutex
+ // same for tables
+ ,m_aTableFilter(_rDB.m_pImpl->m_aTableFilter)
+ ,m_aTableTypeFilter(_rDB.m_pImpl->m_aTableTypeFilter)
+ ,m_aContext( _rxORB )
+ ,m_xMasterConnection(_rxMaster)
+ ,m_aWarnings( Reference< XWarningsSupplier >( _rxMaster, UNO_QUERY ) )
+ ,m_nInAppend(0)
+ ,m_bSupportsViews(false)
+ ,m_bSupportsUsers(false)
+ ,m_bSupportsGroups(false)
+{
+ osl_atomic_increment(&m_refCount);
+
+ try
+ {
+ Reference< XProxyFactory > xProxyFactory = ProxyFactory::create( m_aContext );
+ Reference<XAggregation> xAgg = xProxyFactory->createProxy(_rxMaster);
+ setDelegation(xAgg,m_refCount);
+ OSL_ENSURE(m_xConnection.is(), "OConnection::OConnection : invalid master connection !");
+ }
+ catch(const Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+
+ m_xTableUIProvider.set(m_xMasterConnection, css::uno::UNO_QUERY);
+
+ try
+ {
+ m_xQueries = OQueryContainer::create(Reference< XNameContainer >(_rDB.getQueryDefinitions(), UNO_QUERY), this, _rxORB, &m_aWarnings).get();
+
+ bool bCase = true;
+ Reference<XDatabaseMetaData> xMeta;
+ try
+ {
+ xMeta = getMetaData();
+ bCase = xMeta.is() && xMeta->supportsMixedCaseQuotedIdentifiers();
+ }
+ catch(const SQLException&)
+ {
+ }
+ Reference< XNameContainer > xTableDefinitions(_rDB.getTables(),UNO_QUERY);
+ m_pTables.reset( new OTableContainer( *this, m_aMutex, this, bCase, xTableDefinitions, this, m_nInAppend ) );
+
+ // check if we support types
+ if ( xMeta.is() )
+ {
+ Reference<XResultSet> xRes = xMeta->getTableTypes();
+ if(xRes.is())
+ {
+ Reference<XRow> xRow(xRes,UNO_QUERY);
+ while(xRes->next())
+ {
+ OUString sValue = xRow->getString(1);
+ if( !xRow->wasNull() && sValue == "VIEW")
+ {
+ m_bSupportsViews = true;
+ break;
+ }
+ }
+ }
+ // some dbs don't support this type so we should ask if a XViewsSupplier is supported
+ if(!m_bSupportsViews)
+ {
+ Reference< XViewsSupplier > xMaster(getMasterTables(),UNO_QUERY);
+
+ if (xMaster.is() && xMaster->getViews().is())
+ m_bSupportsViews = true;
+ }
+ if(m_bSupportsViews)
+ {
+ m_pViews.reset( new OViewContainer(*this, m_aMutex, this, bCase, this, m_nInAppend) );
+ m_pViews->addContainerListener(m_pTables.get());
+ m_pTables->addContainerListener(m_pViews.get());
+ }
+ m_bSupportsUsers = Reference< XUsersSupplier> (getMasterTables(),UNO_QUERY).is();
+ m_bSupportsGroups = Reference< XGroupsSupplier> (getMasterTables(),UNO_QUERY).is();
+
+ impl_checkTableQueryNames_nothrow();
+ }
+ }
+ catch(const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ osl_atomic_decrement( &m_refCount );
+}
+
+OConnection::~OConnection()
+{
+}
+
+// XWarningsSupplier
+Any SAL_CALL OConnection::getWarnings()
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed();
+ return m_aWarnings.getWarnings();
+}
+
+void SAL_CALL OConnection::clearWarnings( )
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed();
+ m_aWarnings.clearWarnings();
+}
+
+namespace
+{
+ struct CompareTypeByName
+ {
+ bool operator() ( const Type& _rLHS, const Type& _rRHS ) const
+ {
+ return _rLHS.getTypeName() < _rRHS.getTypeName();
+ }
+ };
+ typedef std::set< Type, CompareTypeByName > TypeBag;
+
+ void lcl_copyTypes( TypeBag& _out_rTypes, const Sequence< Type >& _rTypes )
+ {
+ std::copy( _rTypes.begin(), _rTypes.end(),
+ std::insert_iterator< TypeBag >( _out_rTypes, _out_rTypes.begin() ) );
+ }
+}
+
+// css::lang::XTypeProvider
+Sequence< Type > OConnection::getTypes()
+{
+ TypeBag aNormalizedTypes;
+
+ lcl_copyTypes( aNormalizedTypes, OSubComponent::getTypes() );
+ lcl_copyTypes( aNormalizedTypes, OConnection_Base::getTypes() );
+ lcl_copyTypes( aNormalizedTypes, ::connectivity::OConnectionWrapper::getTypes() );
+
+ if ( !m_bSupportsViews )
+ aNormalizedTypes.erase( cppu::UnoType<XViewsSupplier>::get() );
+ if ( !m_bSupportsUsers )
+ aNormalizedTypes.erase( cppu::UnoType<XUsersSupplier>::get() );
+ if ( !m_bSupportsGroups )
+ aNormalizedTypes.erase( cppu::UnoType<XGroupsSupplier>::get() );
+
+ return comphelper::containerToSequence(aNormalizedTypes);
+}
+
+Sequence< sal_Int8 > OConnection::getImplementationId()
+{
+ return css::uno::Sequence<sal_Int8>();
+}
+
+// css::uno::XInterface
+Any OConnection::queryInterface( const Type & rType )
+{
+ if ( !m_bSupportsViews && rType.equals( cppu::UnoType<XViewsSupplier>::get() ) )
+ return Any();
+ else if ( !m_bSupportsUsers && rType.equals( cppu::UnoType<XUsersSupplier>::get() ) )
+ return Any();
+ else if ( !m_bSupportsGroups && rType.equals( cppu::UnoType<XGroupsSupplier>::get() ) )
+ return Any();
+ Any aReturn = OSubComponent::queryInterface( rType );
+ if (!aReturn.hasValue())
+ {
+ aReturn = OConnection_Base::queryInterface( rType );
+ if (!aReturn.hasValue())
+ aReturn = OConnectionWrapper::queryInterface( rType );
+ }
+ return aReturn;
+}
+
+void OConnection::acquire() noexcept
+{
+ // include this one when you want to see who calls it (call graph)
+ OSubComponent::acquire();
+}
+
+void OConnection::release() noexcept
+{
+ // include this one when you want to see who calls it (call graph)
+ OSubComponent::release();
+}
+
+// OSubComponent
+void OConnection::disposing()
+{
+ MutexGuard aGuard(m_aMutex);
+
+ OSubComponent::disposing();
+ OConnectionWrapper::disposing();
+
+ for (auto const& statement : m_aStatements)
+ {
+ Reference<XComponent> xComp(statement.get(),UNO_QUERY);
+ ::comphelper::disposeComponent(xComp);
+ }
+ m_aStatements.clear();
+ m_xMasterTables = nullptr;
+
+ if(m_pTables)
+ m_pTables->dispose();
+ if(m_pViews)
+ m_pViews->dispose();
+
+ ::comphelper::disposeComponent(m_xQueries);
+
+ for (auto const& composer : m_aComposers)
+ {
+ Reference<XComponent> xComp(composer.get(),UNO_QUERY);
+ ::comphelper::disposeComponent(xComp);
+ }
+
+ m_aComposers.clear();
+
+ try
+ {
+ if (m_xMasterConnection.is())
+ m_xMasterConnection->close();
+ }
+ catch(const Exception&)
+ {
+ }
+ m_xMasterConnection = nullptr;
+}
+
+// XChild
+Reference< XInterface > OConnection::getParent()
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed();
+ return m_xParent;
+}
+
+void OConnection::setParent(const Reference< XInterface > & /*Parent*/)
+{
+ throw NoSupportException();
+}
+
+// XSQLQueryComposerFactory
+Reference< XSQLQueryComposer > OConnection::createQueryComposer()
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed();
+
+ // Reference< XNumberFormatsSupplier > xSupplier = pParent->getNumberFormatsSupplier();
+ Reference< XSQLQueryComposer > xComposer( new OQueryComposer( this ) );
+ m_aComposers.emplace_back(xComposer);
+ return xComposer;
+}
+
+void OConnection::impl_fillTableFilter()
+{
+ Reference<XPropertySet> xProp(getParent(),UNO_QUERY);
+ if ( xProp.is() )
+ {
+ xProp->getPropertyValue(PROPERTY_TABLEFILTER) >>= m_aTableFilter;
+ xProp->getPropertyValue(PROPERTY_TABLETYPEFILTER) >>= m_aTableTypeFilter;
+ }
+}
+
+void OConnection::refresh(const Reference< XNameAccess >& _rToBeRefreshed)
+{
+ if ( _rToBeRefreshed == Reference< XNameAccess >(m_pTables.get()) )
+ {
+ if (m_pTables && !m_pTables->isInitialized())
+ {
+ impl_fillTableFilter();
+ // check if our "master connection" can supply tables
+ getMasterTables();
+
+ if (m_xMasterTables.is() && m_xMasterTables->getTables().is())
+ { // yes -> wrap them
+ m_pTables->construct(m_xMasterTables->getTables(),m_aTableFilter, m_aTableTypeFilter);
+ }
+ else
+ { // no -> use an own container
+ m_pTables->construct(m_aTableFilter, m_aTableTypeFilter);
+ }
+ }
+ }
+ else if ( _rToBeRefreshed == Reference< XNameAccess >(m_pViews.get()) )
+ {
+ if (m_pViews && !m_pViews->isInitialized())
+ {
+ impl_fillTableFilter();
+ // check if our "master connection" can supply tables
+ Reference< XViewsSupplier > xMaster(getMasterTables(),UNO_QUERY);
+
+ if (xMaster.is() && xMaster->getViews().is())
+ m_pViews->construct(xMaster->getViews(),m_aTableFilter, m_aTableTypeFilter);
+ else
+ m_pViews->construct(m_aTableFilter, m_aTableTypeFilter);
+ }
+ }
+}
+
+// XTablesSupplier
+Reference< XNameAccess > OConnection::getTables()
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed();
+
+ refresh(m_pTables.get());
+
+ return m_pTables.get();
+}
+
+Reference< XNameAccess > SAL_CALL OConnection::getViews( )
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed();
+
+ refresh(m_pViews.get());
+
+ return m_pViews.get();
+}
+
+// XQueriesSupplier
+Reference< XNameAccess > OConnection::getQueries()
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed();
+
+ return m_xQueries;
+}
+
+// css::sdb::XCommandPreparation
+Reference< XPreparedStatement > SAL_CALL OConnection::prepareCommand( const OUString& command, sal_Int32 commandType )
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed();
+
+ OUString aStatement;
+ switch (commandType)
+ {
+ case CommandType::TABLE:
+ {
+ aStatement = "SELECT * FROM ";
+
+ OUString sCatalog, sSchema, sTable;
+ ::dbtools::qualifiedNameComponents( getMetaData(), command, sCatalog, sSchema, sTable, ::dbtools::EComposeRule::InDataManipulation );
+ aStatement += ::dbtools::composeTableNameForSelect( this, sCatalog, sSchema, sTable );
+ }
+ break;
+ case CommandType::QUERY:
+ if ( m_xQueries->hasByName(command) )
+ {
+ Reference< XPropertySet > xQuery(m_xQueries->getByName(command),UNO_QUERY);
+ xQuery->getPropertyValue(PROPERTY_COMMAND) >>= aStatement;
+ }
+ break;
+ default:
+ aStatement = command;
+ }
+ // TODO EscapeProcessing
+ return prepareStatement(aStatement);
+}
+
+Reference< XInterface > SAL_CALL OConnection::createInstance( const OUString& _sServiceSpecifier )
+{
+ Reference< XServiceInfo > xRet;
+ if ( SERVICE_NAME_SINGLESELECTQUERYCOMPOSER == _sServiceSpecifier || _sServiceSpecifier == "com.sun.star.sdb.SingleSelectQueryAnalyzer" )
+ {
+ xRet = new OSingleSelectQueryComposer( getTables(),this, m_aContext );
+ m_aComposers.emplace_back(xRet);
+ }
+ else
+ {
+ if ( !_sServiceSpecifier.isEmpty() )
+ {
+ TSupportServices::const_iterator aFind = m_aSupportServices.find(_sServiceSpecifier);
+ if ( aFind == m_aSupportServices.end() )
+ {
+ Reference<XConnection> xMy(this);
+ Sequence<Any> aArgs{ Any(NamedValue("ActiveConnection",Any(xMy))) };
+ aFind = m_aSupportServices.emplace(
+ _sServiceSpecifier,
+ m_aContext->getServiceManager()->createInstanceWithArgumentsAndContext(_sServiceSpecifier, aArgs, m_aContext)
+ ).first;
+ }
+ return aFind->second;
+ }
+ }
+ return Reference<XInterface>(xRet, UNO_QUERY);
+}
+
+Reference< XInterface > SAL_CALL OConnection::createInstanceWithArguments( const OUString& _sServiceSpecifier, const Sequence< Any >& /*Arguments*/ )
+{
+ return createInstance(_sServiceSpecifier);
+}
+
+Sequence< OUString > SAL_CALL OConnection::getAvailableServiceNames( )
+{
+ Sequence< OUString > aRet { SERVICE_NAME_SINGLESELECTQUERYCOMPOSER };
+ return aRet;
+}
+
+Reference< XTablesSupplier > const & OConnection::getMasterTables()
+{
+// check if out "master connection" can supply tables
+ if(!m_xMasterTables.is())
+ {
+ try
+ {
+ Reference<XDatabaseMetaData> xMeta = getMetaData();
+ if ( xMeta.is() )
+ m_xMasterTables = ::dbtools::getDataDefinitionByURLAndConnection( xMeta->getURL(), m_xMasterConnection, m_aContext );
+ }
+ catch(const SQLException&)
+ {
+ }
+ }
+ return m_xMasterTables;
+}
+
+// XUsersSupplier
+Reference< XNameAccess > SAL_CALL OConnection::getUsers( )
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed();
+
+ Reference<XUsersSupplier> xUsr(getMasterTables(),UNO_QUERY);
+ return xUsr.is() ? xUsr->getUsers() : Reference< XNameAccess >();
+}
+
+// XGroupsSupplier
+Reference< XNameAccess > SAL_CALL OConnection::getGroups( )
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed();
+ Reference<XGroupsSupplier> xGrp(getMasterTables(),UNO_QUERY);
+ return xGrp.is() ? xGrp->getGroups() : Reference< XNameAccess >();
+}
+
+void OConnection::impl_loadConnectionTools_throw()
+{
+ m_xConnectionTools = css::sdb::tools::ConnectionTools::createWithConnection( m_aContext, this );
+}
+
+Reference< XTableName > SAL_CALL OConnection::createTableName( )
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed();
+ impl_loadConnectionTools_throw();
+
+ return m_xConnectionTools->createTableName();
+}
+
+Reference< XObjectNames > SAL_CALL OConnection::getObjectNames( )
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed();
+ impl_loadConnectionTools_throw();
+
+ return m_xConnectionTools->getObjectNames();
+}
+
+Reference< XDataSourceMetaData > SAL_CALL OConnection::getDataSourceMetaData( )
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed();
+ impl_loadConnectionTools_throw();
+
+ return m_xConnectionTools->getDataSourceMetaData();
+}
+
+Reference< css::container::XNameAccess > SAL_CALL OConnection::getFieldsByCommandDescriptor( ::sal_Int32 commandType, const OUString& command, css::uno::Reference< css::lang::XComponent >& keepFieldsAlive )
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed();
+ impl_loadConnectionTools_throw();
+
+ return m_xConnectionTools->getFieldsByCommandDescriptor(commandType,command,keepFieldsAlive);
+}
+
+Reference< XSingleSelectQueryComposer > SAL_CALL OConnection::getComposer( ::sal_Int32 commandType, const OUString& command )
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed();
+ impl_loadConnectionTools_throw();
+
+ return m_xConnectionTools->getComposer(commandType,command);
+}
+
+void OConnection::impl_checkTableQueryNames_nothrow()
+{
+ DatabaseMetaData aMeta( static_cast< XConnection* >( this ) );
+ if ( !aMeta.supportsSubqueriesInFrom() )
+ // nothing to do
+ return;
+
+ try
+ {
+ Reference< XNameAccess > xTables( getTables() );
+ const Sequence< OUString > aTableNames( xTables->getElementNames() );
+ std::set< OUString > aSortedTableNames( aTableNames.begin(), aTableNames.end() );
+
+ Reference< XNameAccess > xQueries( getQueries() );
+ const Sequence< OUString > aQueryNames( xQueries->getElementNames() );
+
+ for ( auto const & queryName : aQueryNames )
+ {
+ if ( aSortedTableNames.find( queryName ) != aSortedTableNames.end() )
+ {
+ OUString sConflictWarning( DBA_RES( RID_STR_CONFLICTING_NAMES ) );
+ m_aWarnings.appendWarning( sConflictWarning, "01SB0", *this );
+ }
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+}
+
+Reference< XGraphic > SAL_CALL OConnection::getTableIcon( const OUString& TableName, ::sal_Int32 ColorMode )
+{
+ Reference< XGraphic > xReturn;
+
+ // ask our aggregate
+ if ( m_xTableUIProvider.is() )
+ xReturn = m_xTableUIProvider->getTableIcon( TableName, ColorMode );
+
+ // ask ourself
+ // well, we don't have own functionality here ...
+ // In the future, we might decide to delegate the complete handling to this interface.
+ // In this case, we would need to load the icon here.
+
+ return xReturn;
+}
+
+Reference< XInterface > SAL_CALL OConnection::getTableEditor( const Reference< XDatabaseDocumentUI >& DocumentUI, const OUString& TableName )
+{
+ Reference< XInterface > xReturn;
+
+ // ask our aggregate
+ if ( m_xTableUIProvider.is() )
+ xReturn = m_xTableUIProvider->getTableEditor( DocumentUI, TableName );
+
+ // ask ourself
+ // well, we don't have own functionality here ...
+ // In the future, we might decide to delegate the complete handling to this interface.
+ // In this case, we would need to instantiate a css.sdb.TableDesign here.
+
+ return xReturn;
+}
+
+} // namespace dbaccess
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/dataaccess/connection.hxx b/dbaccess/source/core/dataaccess/connection.hxx
new file mode 100644
index 000000000..4ecfa7d70
--- /dev/null
+++ b/dbaccess/source/core/dataaccess/connection.hxx
@@ -0,0 +1,229 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <sal/config.h>
+
+#include <atomic>
+#include <cstddef>
+#include <map>
+
+#include <apitools.hxx>
+#include <querycontainer.hxx>
+#include <tablecontainer.hxx>
+#include <viewcontainer.hxx>
+#include <RefreshListener.hxx>
+
+#include <com/sun/star/container/XChild.hpp>
+#include <com/sun/star/lang/DisposedException.hpp>
+#include <com/sun/star/sdb/XSQLQueryComposerFactory.hpp>
+#include <com/sun/star/sdb/XCommandPreparation.hpp>
+#include <com/sun/star/sdbcx/XTablesSupplier.hpp>
+#include <com/sun/star/sdbcx/XViewsSupplier.hpp>
+#include <com/sun/star/sdbcx/XUsersSupplier.hpp>
+#include <com/sun/star/sdbcx/XGroupsSupplier.hpp>
+#include <com/sun/star/sdb/XQueriesSupplier.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/sdb/tools/XConnectionTools.hpp>
+#include <com/sun/star/sdb/application/XTableUIProvider.hpp>
+#include <com/sun/star/sdbc/XWarningsSupplier.hpp>
+
+#include <cppuhelper/implbase13.hxx>
+#include <connectivity/ConnectionWrapper.hxx>
+#include <connectivity/CommonTools.hxx>
+#include <connectivity/warningscontainer.hxx>
+
+namespace dbaccess
+{
+
+typedef cppu::ImplHelper13 < css::container::XChild
+ , css::sdbcx::XTablesSupplier
+ , css::sdbcx::XViewsSupplier
+ , css::sdbc::XConnection
+ , css::sdbc::XWarningsSupplier
+ , css::sdb::XQueriesSupplier
+ , css::sdb::XSQLQueryComposerFactory
+ , css::sdb::XCommandPreparation
+ , css::lang::XMultiServiceFactory
+ , css::sdbcx::XUsersSupplier
+ , css::sdbcx::XGroupsSupplier
+ , css::sdb::tools::XConnectionTools
+ , css::sdb::application::XTableUIProvider
+ > OConnection_Base;
+
+class ODatabaseSource;
+// OConnection
+class OConnection final :public ::cppu::BaseMutex
+ ,public OSubComponent
+ ,public ::connectivity::OConnectionWrapper
+ ,public OConnection_Base
+ ,public IRefreshListener
+{
+ css::uno::Reference< css::sdbcx::XTablesSupplier >
+ m_xMasterTables; // just to avoid the recreation of the catalog
+ connectivity::OWeakRefArray m_aStatements;
+ css::uno::Reference< css::container::XNameAccess >
+ m_xQueries;
+ connectivity::OWeakRefArray m_aComposers;
+
+ // the filter as set on the parent data link at construction of the connection
+ css::uno::Sequence< OUString > m_aTableFilter;
+ css::uno::Sequence< OUString > m_aTableTypeFilter;
+ css::uno::Reference< css::uno::XComponentContext > m_aContext;
+ css::uno::Reference< css::sdbc::XConnection > m_xMasterConnection;
+ css::uno::Reference< css::sdb::tools::XConnectionTools > m_xConnectionTools;
+ css::uno::Reference< css::sdb::application::XTableUIProvider > m_xTableUIProvider;
+
+ // defines the helper services for example to query the command of a view
+ // @ see com.sun.star.sdb.tools.XViewAccess
+ typedef std::map< OUString, css::uno::Reference< css::uno::XInterface> > TSupportServices;
+ TSupportServices m_aSupportServices;
+
+ std::unique_ptr<OTableContainer> m_pTables;
+ std::unique_ptr<OViewContainer> m_pViews;
+ ::dbtools::WarningsContainer m_aWarnings;
+ std::atomic<std::size_t> m_nInAppend;
+ bool m_bSupportsViews; // true when the getTableTypes return "VIEW" as type
+ bool m_bSupportsUsers;
+ bool m_bSupportsGroups;
+
+ virtual ~OConnection() override;
+public:
+ OConnection(ODatabaseSource& _rDB
+ ,css::uno::Reference< css::sdbc::XConnection > const & _rxMaster
+ ,const css::uno::Reference< css::uno::XComponentContext >& _rxORB);
+
+// css::lang::XTypeProvider
+ virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes() override;
+ virtual css::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId() override;
+
+// css::uno::XInterface
+ virtual css::uno::Any SAL_CALL queryInterface( const css::uno::Type & rType ) override;
+ virtual void SAL_CALL acquire() noexcept override;
+ virtual void SAL_CALL release() noexcept override;
+
+// OComponentHelper
+ virtual void SAL_CALL disposing() override;
+
+// css::container::XChild
+ virtual css::uno::Reference< css::uno::XInterface > SAL_CALL getParent( ) override;
+ virtual void SAL_CALL setParent( const css::uno::Reference< css::uno::XInterface >& Parent ) override;
+
+// css::sdbcx::XTablesSupplier
+ virtual css::uno::Reference< css::container::XNameAccess > SAL_CALL getTables( ) override;
+// css::sdbcx::XViewsSupplier
+ virtual css::uno::Reference< css::container::XNameAccess > SAL_CALL getViews( ) override;
+
+// css::sdb::XQueriesSupplier
+ virtual css::uno::Reference< css::container::XNameAccess > SAL_CALL getQueries( ) override;
+
+// css::sdb::XSQLQueryComposerFactory
+ virtual css::uno::Reference< css::sdb::XSQLQueryComposer > SAL_CALL createQueryComposer( ) override;
+
+// css::sdb::XCommandPreparation
+ virtual css::uno::Reference< css::sdbc::XPreparedStatement > SAL_CALL prepareCommand( const OUString& command, sal_Int32 commandType ) override;
+
+// css::sdbc::XWarningsSupplier
+ virtual css::uno::Any SAL_CALL getWarnings( ) override;
+ virtual void SAL_CALL clearWarnings( ) override;
+
+// css::lang::XServiceInfo
+ virtual OUString SAL_CALL getImplementationName( ) override;
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override;
+
+// XConnection
+ virtual css::uno::Reference< css::sdbc::XStatement > SAL_CALL createStatement( ) override;
+ virtual css::uno::Reference< css::sdbc::XPreparedStatement > SAL_CALL prepareStatement( const OUString& sql ) override;
+ virtual css::uno::Reference< css::sdbc::XPreparedStatement > SAL_CALL prepareCall( const OUString& sql ) override;
+ virtual OUString SAL_CALL nativeSQL( const OUString& sql ) override;
+ virtual void SAL_CALL setAutoCommit( sal_Bool autoCommit ) override;
+ virtual sal_Bool SAL_CALL getAutoCommit( ) override;
+ virtual void SAL_CALL commit( ) override;
+ virtual void SAL_CALL rollback( ) override;
+ virtual sal_Bool SAL_CALL isClosed( ) override;
+ virtual css::uno::Reference< css::sdbc::XDatabaseMetaData > SAL_CALL getMetaData( ) override;
+ virtual void SAL_CALL setReadOnly( sal_Bool readOnly ) override;
+ virtual sal_Bool SAL_CALL isReadOnly( ) override;
+ virtual void SAL_CALL setCatalog( const OUString& catalog ) override;
+ virtual OUString SAL_CALL getCatalog( ) override;
+ virtual void SAL_CALL setTransactionIsolation( sal_Int32 level ) override;
+ virtual sal_Int32 SAL_CALL getTransactionIsolation( ) override;
+ virtual css::uno::Reference< css::container::XNameAccess > SAL_CALL getTypeMap( ) override;
+ virtual void SAL_CALL setTypeMap( const css::uno::Reference< css::container::XNameAccess >& typeMap ) override;
+
+// css::sdbc::XCloseable
+ virtual void SAL_CALL close( ) override;
+
+ // XMultiServiceFactory
+ virtual css::uno::Reference< css::uno::XInterface > SAL_CALL createInstance( const OUString& aServiceSpecifier ) override;
+ virtual css::uno::Reference< css::uno::XInterface > SAL_CALL createInstanceWithArguments( const OUString& ServiceSpecifier, const css::uno::Sequence< css::uno::Any >& Arguments ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getAvailableServiceNames( ) override;
+
+ // XUsersSupplier
+ virtual css::uno::Reference< css::container::XNameAccess > SAL_CALL getUsers( ) override;
+ // XGroupsSupplier
+ virtual css::uno::Reference< css::container::XNameAccess > SAL_CALL getGroups( ) override;
+
+ // XConnectionTools
+ virtual css::uno::Reference< css::sdb::tools::XTableName > SAL_CALL createTableName( ) override;
+ virtual css::uno::Reference< css::sdb::tools::XObjectNames > SAL_CALL getObjectNames( ) override;
+ virtual css::uno::Reference< css::sdb::tools::XDataSourceMetaData > SAL_CALL getDataSourceMetaData( ) override;
+ virtual css::uno::Reference< css::container::XNameAccess > SAL_CALL getFieldsByCommandDescriptor( ::sal_Int32 commandType, const OUString& command, css::uno::Reference< css::lang::XComponent >& keepFieldsAlive ) override;
+ virtual css::uno::Reference< css::sdb::XSingleSelectQueryComposer > SAL_CALL getComposer( ::sal_Int32 commandType, const OUString& command ) override;
+
+ // XTableUIProvider
+ virtual css::uno::Reference< css::graphic::XGraphic > SAL_CALL getTableIcon( const OUString& TableName, ::sal_Int32 ColorMode ) override;
+ virtual css::uno::Reference< css::uno::XInterface > SAL_CALL getTableEditor( const css::uno::Reference< css::sdb::application::XDatabaseDocumentUI >& DocumentUI, const OUString& TableName ) override;
+
+ // IRefreshListener
+ virtual void refresh(const css::uno::Reference< css::container::XNameAccess >& _rToBeRefreshed) override;
+
+private:
+ /// @throws css::lang::DisposedException
+ void checkDisposed()
+ {
+ if ( rBHelper.bDisposed || !m_xConnection.is() )
+ throw css::lang::DisposedException();
+ }
+
+ css::uno::Reference< css::sdbcx::XTablesSupplier > const & getMasterTables();
+
+ /** checks whether or not there are naming conflicts between tables and queries
+ */
+ void impl_checkTableQueryNames_nothrow();
+
+ /** loads the XConnectionTools implementation which we forward the respective functionality to
+
+ @throws css::uno::RuntimeException
+ if the implementation cannot be loaded
+
+ @postcond
+ m_xConnectionTools is nol <NULL/>
+ */
+ void impl_loadConnectionTools_throw();
+
+ /** reads the table filter and table type filter from the datasource
+ */
+ void impl_fillTableFilter();
+};
+
+} // namespace dbaccess
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/dataaccess/dataaccessdescriptor.cxx b/dbaccess/source/core/dataaccess/dataaccessdescriptor.cxx
new file mode 100644
index 000000000..ef5239a67
--- /dev/null
+++ b/dbaccess/source/core/dataaccess/dataaccessdescriptor.cxx
@@ -0,0 +1,229 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <stringconstants.hxx>
+#include <strings.hxx>
+
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/beans/PropertyValue.hpp>
+#include <com/sun/star/sdb/CommandType.hpp>
+#include <com/sun/star/sdbc/XConnection.hpp>
+#include <com/sun/star/sdbc/XResultSet.hpp>
+#include <com/sun/star/sdb/XDataAccessDescriptorFactory.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+
+#include <comphelper/broadcasthelper.hxx>
+#include <comphelper/proparrhlp.hxx>
+#include <comphelper/propertycontainer.hxx>
+#include <comphelper/uno3.hxx>
+#include <cppuhelper/implbase.hxx>
+#include <cppuhelper/supportsservice.hxx>
+
+namespace
+{
+
+ using ::com::sun::star::uno::Reference;
+ using ::com::sun::star::uno::Any;
+ using ::com::sun::star::uno::Sequence;
+ using ::com::sun::star::lang::XServiceInfo;
+ using ::com::sun::star::beans::XPropertySetInfo;
+ using ::com::sun::star::beans::Property;
+ using ::com::sun::star::sdbc::XConnection;
+ using ::com::sun::star::sdbc::XResultSet;
+ using ::com::sun::star::beans::XPropertySet;
+ using ::com::sun::star::beans::PropertyValue;
+
+ namespace PropertyAttribute = ::com::sun::star::beans::PropertyAttribute;
+ namespace CommandType = ::com::sun::star::sdb::CommandType;
+
+ // DataAccessDescriptor
+ typedef ::comphelper::OMutexAndBroadcastHelper DataAccessDescriptor_MutexBase;
+
+ typedef ::cppu::WeakImplHelper< XServiceInfo
+ > DataAccessDescriptor_TypeBase;
+
+ typedef ::comphelper::OPropertyContainer DataAccessDescriptor_PropertyBase;
+
+ class DataAccessDescriptor :public DataAccessDescriptor_MutexBase
+ ,public DataAccessDescriptor_TypeBase
+ ,public DataAccessDescriptor_PropertyBase
+ ,public ::comphelper::OPropertyArrayUsageHelper< DataAccessDescriptor >
+ {
+ public:
+ DataAccessDescriptor();
+
+ // UNO
+ DECLARE_XINTERFACE()
+ DECLARE_XTYPEPROVIDER()
+
+ // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName( ) override;
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+ virtual Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override;
+
+ protected:
+ virtual ~DataAccessDescriptor() override;
+
+ protected:
+ // XPropertySet
+ virtual Reference< XPropertySetInfo > SAL_CALL getPropertySetInfo() override;
+ virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper() override;
+
+ // OPropertyArrayUsageHelper
+ virtual ::cppu::IPropertyArrayHelper* createArrayHelper( ) const override;
+
+ private:
+ // </properties>
+ OUString m_sDataSourceName;
+ OUString m_sDatabaseLocation;
+ OUString m_sConnectionResource;
+ Sequence< PropertyValue > m_aConnectionInfo;
+ Reference< XConnection > m_xActiveConnection;
+ OUString m_sCommand;
+ sal_Int32 m_nCommandType;
+ OUString m_sFilter;
+ OUString m_sOrder;
+ OUString m_sHavingClause;
+ OUString m_sGroupBy;
+ bool m_bEscapeProcessing;
+ Reference< XResultSet > m_xResultSet;
+ Sequence< Any > m_aSelection;
+ bool m_bBookmarkSelection;
+ OUString m_sColumnName;
+ Reference< XPropertySet > m_xColumn;
+ // </properties>
+ };
+
+ DataAccessDescriptor::DataAccessDescriptor()
+ :DataAccessDescriptor_PropertyBase( m_aBHelper )
+ ,m_nCommandType( CommandType::COMMAND )
+ ,m_bEscapeProcessing( true )
+ ,m_bBookmarkSelection( true )
+ {
+ registerProperty(PROPERTY_DATASOURCENAME, PROPERTY_ID_DATASOURCENAME, PropertyAttribute::BOUND, &m_sDataSourceName , cppu::UnoType<decltype(m_sDataSourceName )>::get());
+ registerProperty(PROPERTY_DATABASE_LOCATION, PROPERTY_ID_DATABASE_LOCATION, PropertyAttribute::BOUND, &m_sDatabaseLocation , cppu::UnoType<decltype(m_sDatabaseLocation )>::get());
+ registerProperty(PROPERTY_CONNECTION_RESOURCE, PROPERTY_ID_CONNECTION_RESOURCE, PropertyAttribute::BOUND, &m_sConnectionResource , cppu::UnoType<decltype(m_sConnectionResource )>::get());
+ registerProperty(PROPERTY_CONNECTION_INFO, PROPERTY_ID_CONNECTION_INFO, PropertyAttribute::BOUND, &m_aConnectionInfo , cppu::UnoType<decltype(m_aConnectionInfo )>::get());
+ registerProperty(PROPERTY_ACTIVE_CONNECTION, PROPERTY_ID_ACTIVE_CONNECTION, PropertyAttribute::BOUND, &m_xActiveConnection , cppu::UnoType<decltype(m_xActiveConnection )>::get());
+ registerProperty(PROPERTY_COMMAND, PROPERTY_ID_COMMAND, PropertyAttribute::BOUND, &m_sCommand , cppu::UnoType<decltype(m_sCommand )>::get());
+ registerProperty(PROPERTY_COMMAND_TYPE, PROPERTY_ID_COMMAND_TYPE, PropertyAttribute::BOUND, &m_nCommandType , cppu::UnoType<decltype(m_nCommandType )>::get());
+ registerProperty(PROPERTY_FILTER, PROPERTY_ID_FILTER, PropertyAttribute::BOUND, &m_sFilter , cppu::UnoType<decltype(m_sFilter )>::get());
+ registerProperty(PROPERTY_ORDER, PROPERTY_ID_ORDER, PropertyAttribute::BOUND, &m_sOrder , cppu::UnoType<decltype(m_sOrder )>::get());
+ registerProperty(PROPERTY_HAVING_CLAUSE, PROPERTY_ID_HAVING_CLAUSE, PropertyAttribute::BOUND, &m_sHavingClause , cppu::UnoType<decltype(m_sHavingClause )>::get());
+ registerProperty(PROPERTY_GROUP_BY, PROPERTY_ID_GROUP_BY, PropertyAttribute::BOUND, &m_sGroupBy , cppu::UnoType<decltype(m_sGroupBy )>::get());
+ registerProperty(PROPERTY_ESCAPE_PROCESSING, PROPERTY_ID_ESCAPE_PROCESSING, PropertyAttribute::BOUND, &m_bEscapeProcessing , cppu::UnoType<decltype(m_bEscapeProcessing )>::get());
+ registerProperty(PROPERTY_RESULT_SET, PROPERTY_ID_RESULT_SET, PropertyAttribute::BOUND, &m_xResultSet , cppu::UnoType<decltype(m_xResultSet )>::get());
+ registerProperty(PROPERTY_SELECTION, PROPERTY_ID_SELECTION, PropertyAttribute::BOUND, &m_aSelection , cppu::UnoType<decltype(m_aSelection )>::get());
+ registerProperty(PROPERTY_BOOKMARK_SELECTION, PROPERTY_ID_BOOKMARK_SELECTION, PropertyAttribute::BOUND, &m_bBookmarkSelection , cppu::UnoType<decltype(m_bBookmarkSelection )>::get());
+ registerProperty(PROPERTY_COLUMN_NAME, PROPERTY_ID_COLUMN_NAME, PropertyAttribute::BOUND, &m_sColumnName , cppu::UnoType<decltype(m_sColumnName )>::get());
+ registerProperty(PROPERTY_COLUMN, PROPERTY_ID_COLUMN, PropertyAttribute::BOUND, &m_xColumn , cppu::UnoType<decltype(m_xColumn )>::get());
+ }
+
+ DataAccessDescriptor::~DataAccessDescriptor()
+ {
+ }
+
+ IMPLEMENT_FORWARD_XINTERFACE2( DataAccessDescriptor, DataAccessDescriptor_TypeBase, DataAccessDescriptor_PropertyBase );
+
+ IMPLEMENT_FORWARD_XTYPEPROVIDER2( DataAccessDescriptor, DataAccessDescriptor_TypeBase, DataAccessDescriptor_PropertyBase );
+
+ OUString SAL_CALL DataAccessDescriptor::getImplementationName()
+ {
+ return "com.sun.star.comp.dba.DataAccessDescriptor";
+ }
+
+ sal_Bool SAL_CALL DataAccessDescriptor::supportsService( const OUString& rServiceName )
+ {
+ return cppu::supportsService(this, rServiceName);
+ }
+
+ Sequence< OUString > SAL_CALL DataAccessDescriptor::getSupportedServiceNames( )
+ {
+ return { "com.sun.star.sdb.DataAccessDescriptor" };
+ }
+
+ Reference< XPropertySetInfo > SAL_CALL DataAccessDescriptor::getPropertySetInfo()
+ {
+ Reference< XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) );
+ return xInfo;
+ }
+
+ ::cppu::IPropertyArrayHelper& DataAccessDescriptor::getInfoHelper()
+ {
+ return *getArrayHelper();
+ }
+
+ ::cppu::IPropertyArrayHelper* DataAccessDescriptor::createArrayHelper( ) const
+ {
+ Sequence< Property > aProps;
+ describeProperties( aProps );
+ return new ::cppu::OPropertyArrayHelper( aProps );
+ }
+
+ // DataAccessDescriptorFactory
+ class DataAccessDescriptorFactory: public ::cppu::WeakImplHelper<XServiceInfo, css::sdb::XDataAccessDescriptorFactory>
+ {
+ public:
+ // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName( ) override;
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+ virtual Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override;
+
+ // XDataAccessDescriptorFactory
+ virtual Reference< XPropertySet > SAL_CALL createDataAccessDescriptor( ) override;
+
+ DataAccessDescriptorFactory();
+ };
+
+ DataAccessDescriptorFactory::DataAccessDescriptorFactory()
+ {
+ }
+
+ OUString SAL_CALL DataAccessDescriptorFactory::getImplementationName()
+ {
+ return "com.sun.star.comp.dba.DataAccessDescriptorFactory";
+ }
+
+ sal_Bool SAL_CALL DataAccessDescriptorFactory::supportsService( const OUString& rServiceName )
+ {
+ return cppu::supportsService(this, rServiceName);
+ }
+
+ Sequence< OUString > SAL_CALL DataAccessDescriptorFactory::getSupportedServiceNames()
+ {
+ return { "com.sun.star.sdb.DataAccessDescriptorFactory" };
+ }
+
+ Reference< XPropertySet > SAL_CALL DataAccessDescriptorFactory::createDataAccessDescriptor( )
+ {
+ return new DataAccessDescriptor();
+ }
+
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+com_sun_star_comp_dba_DataAccessDescriptorFactory(
+ css::uno::XComponentContext *,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new DataAccessDescriptorFactory());
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/dataaccess/databasecontext.cxx b/dbaccess/source/core/dataaccess/databasecontext.cxx
new file mode 100644
index 000000000..5afdadb67
--- /dev/null
+++ b/dbaccess/source/core/dataaccess/databasecontext.cxx
@@ -0,0 +1,753 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <config_features.h>
+
+#include <strings.hrc>
+#include <strings.hxx>
+#include <core_resource.hxx>
+#include <databasecontext.hxx>
+#include "databaseregistrations.hxx"
+#include "datasource.hxx"
+
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/document/MacroExecMode.hpp>
+#include <com/sun/star/frame/Desktop.hpp>
+#include <com/sun/star/frame/TerminationVetoException.hpp>
+#include <com/sun/star/frame/XLoadable.hpp>
+#include <com/sun/star/frame/XModel.hpp>
+#include <com/sun/star/frame/XModel2.hpp>
+#include <com/sun/star/frame/XTerminateListener.hpp>
+#include <com/sun/star/lang/DisposedException.hpp>
+#include <com/sun/star/registry/InvalidRegistryException.hpp>
+#include <com/sun/star/sdbc/XDataSource.hpp>
+#include <com/sun/star/task/InteractionClassification.hpp>
+#include <com/sun/star/ucb/InteractiveIOException.hpp>
+#include <com/sun/star/ucb/IOErrorCode.hpp>
+#include <com/sun/star/uri/UriReferenceFactory.hpp>
+#include <com/sun/star/task/InteractionHandler.hpp>
+#include <com/sun/star/util/CloseVetoException.hpp>
+#include <com/sun/star/util/XCloseable.hpp>
+
+#include <basic/basmgr.hxx>
+#include <comphelper/enumhelper.hxx>
+#include <comphelper/namedvaluecollection.hxx>
+#include <comphelper/processfactory.hxx>
+#include <comphelper/servicehelper.hxx>
+#include <cppuhelper/implbase.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <cppuhelper/exc_hlp.hxx>
+#include <cppuhelper/weak.hxx>
+#include <rtl/uri.hxx>
+#include <sal/log.hxx>
+#include <svl/filenotation.hxx>
+#include <tools/diagnose_ex.h>
+#include <tools/urlobj.hxx>
+#include <ucbhelper/content.hxx>
+#include <rtl/ref.hxx>
+#include <unotools/sharedunocomponent.hxx>
+#include <vector>
+
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::sdb;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::document;
+using namespace ::com::sun::star::frame;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::util;
+using namespace ::com::sun::star::registry;
+using namespace ::com::sun::star;
+using namespace ::cppu;
+using namespace ::osl;
+using namespace ::utl;
+
+using ::com::sun::star::task::InteractionClassification_ERROR;
+using ::com::sun::star::ucb::IOErrorCode_NO_FILE;
+using ::com::sun::star::ucb::InteractiveIOException;
+using ::com::sun::star::ucb::IOErrorCode_NOT_EXISTING;
+using ::com::sun::star::ucb::IOErrorCode_NOT_EXISTING_PATH;
+
+namespace dbaccess
+{
+
+ typedef ::cppu::WeakImplHelper< XTerminateListener
+ > DatabaseDocumentLoader_Base;
+ class DatabaseDocumentLoader : public DatabaseDocumentLoader_Base
+ {
+ private:
+ Reference< XDesktop2 > m_xDesktop;
+ std::vector< const ODatabaseModelImpl* > m_aDatabaseDocuments;
+
+ public:
+ explicit DatabaseDocumentLoader( const Reference<XComponentContext> & rxContext);
+
+ void append(const ODatabaseModelImpl& _rModelImpl )
+ {
+ m_aDatabaseDocuments.emplace_back(&_rModelImpl);
+ }
+
+ void remove(const ODatabaseModelImpl& _rModelImpl)
+ {
+ m_aDatabaseDocuments.erase(std::find(m_aDatabaseDocuments.begin(), m_aDatabaseDocuments.end(), &_rModelImpl));
+ }
+
+
+ private:
+ // XTerminateListener
+ virtual void SAL_CALL queryTermination( const lang::EventObject& Event ) override;
+ virtual void SAL_CALL notifyTermination( const lang::EventObject& Event ) override;
+ // XEventListener
+ virtual void SAL_CALL disposing( const css::lang::EventObject& Source ) override;
+ };
+
+ DatabaseDocumentLoader::DatabaseDocumentLoader( const Reference<XComponentContext> & rxContext )
+ {
+ try
+ {
+ m_xDesktop.set( Desktop::create(rxContext) );
+ m_xDesktop->addTerminateListener( this );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+
+ void SAL_CALL DatabaseDocumentLoader::queryTermination( const lang::EventObject& /*Event*/ )
+ {
+ std::vector< const ODatabaseModelImpl* > aCpy(m_aDatabaseDocuments);
+ for( const auto& pCopy : aCpy )
+ {
+ try
+ {
+ const Reference< XModel2 > xMod( pCopy->getModel_noCreate(),
+ UNO_QUERY_THROW );
+ if( !xMod->getControllers()->hasMoreElements() )
+ {
+ Reference< util::XCloseable > xClose( xMod,
+ UNO_QUERY_THROW );
+ xClose->close( false );
+ }
+ }
+ catch( const CloseVetoException& )
+ {
+ throw TerminationVetoException();
+ }
+ }
+ }
+
+ void SAL_CALL DatabaseDocumentLoader::notifyTermination( const lang::EventObject& /*Event*/ )
+ {
+ }
+
+ void SAL_CALL DatabaseDocumentLoader::disposing( const lang::EventObject& /*Source*/ )
+ {
+ }
+
+// ODatabaseContext
+
+ODatabaseContext::ODatabaseContext( const Reference< XComponentContext >& _rxContext )
+ :DatabaseAccessContext_Base(m_aMutex)
+ ,m_aContext( _rxContext )
+ ,m_aContainerListeners(m_aMutex)
+{
+ m_xDatabaseDocumentLoader = new DatabaseDocumentLoader( _rxContext );
+
+#if HAVE_FEATURE_SCRIPTING
+ ::basic::BasicManagerRepository::registerCreationListener( *this );
+#endif
+
+ osl_atomic_increment( &m_refCount );
+ {
+ m_xDBRegistrationAggregate.set( createDataSourceRegistrations( m_aContext ), UNO_SET_THROW );
+ m_xDatabaseRegistrations.set( m_xDBRegistrationAggregate, UNO_QUERY_THROW );
+
+ m_xDBRegistrationAggregate->setDelegator( *this );
+ }
+ osl_atomic_decrement( &m_refCount );
+}
+
+ODatabaseContext::~ODatabaseContext()
+{
+#if HAVE_FEATURE_SCRIPTING
+ ::basic::BasicManagerRepository::revokeCreationListener( *this );
+#endif
+
+ m_xDatabaseDocumentLoader.clear();
+ m_xDBRegistrationAggregate->setDelegator( nullptr );
+ m_xDBRegistrationAggregate.clear();
+ m_xDatabaseRegistrations.clear();
+}
+
+// XServiceInfo
+OUString ODatabaseContext::getImplementationName( )
+{
+ return "com.sun.star.comp.dba.ODatabaseContext";
+}
+
+sal_Bool ODatabaseContext::supportsService( const OUString& _rServiceName )
+{
+ return cppu::supportsService(this, _rServiceName);
+}
+
+Sequence< OUString > ODatabaseContext::getSupportedServiceNames( )
+{
+ return { "com.sun.star.sdb.DatabaseContext" };
+}
+
+Reference< XInterface > ODatabaseContext::impl_createNewDataSource()
+{
+ ::rtl::Reference pImpl( new ODatabaseModelImpl( m_aContext, *this ) );
+ Reference< XDataSource > xDataSource( pImpl->getOrCreateDataSource() );
+
+ return xDataSource;
+}
+
+Reference< XInterface > SAL_CALL ODatabaseContext::createInstance( )
+{
+ // for convenience of the API user, we ensure the document is fully initialized (effectively: XLoadable::initNew
+ // has been called at the DatabaseDocument).
+ return impl_createNewDataSource();
+}
+
+Reference< XInterface > SAL_CALL ODatabaseContext::createInstanceWithArguments( const Sequence< Any >& _rArguments )
+{
+ ::comphelper::NamedValueCollection aArgs( _rArguments );
+ OUString sURL = aArgs.getOrDefault( INFO_POOLURL, OUString() );
+
+ Reference< XInterface > xDataSource;
+ if ( !sURL.isEmpty() )
+ xDataSource = getObject( sURL );
+
+ if ( !xDataSource.is() )
+ xDataSource = impl_createNewDataSource();
+
+ return xDataSource;
+}
+
+// DatabaseAccessContext_Base
+void ODatabaseContext::disposing()
+{
+ // notify our listener
+ css::lang::EventObject aDisposeEvent(static_cast< XContainer* >(this));
+ m_aContainerListeners.disposeAndClear(aDisposeEvent);
+
+ // dispose the data sources
+ // disposing seems to remove elements, so work on copy for valid iterators
+ ObjectCache objCopy;
+ objCopy.swap(m_aDatabaseObjects);
+ for (auto const& elem : objCopy)
+ {
+ rtl::Reference< ODatabaseModelImpl > obj(elem.second);
+ // make sure obj is acquired and does not delete itself from within
+ // dispose()
+ obj->dispose();
+ }
+}
+
+// XNamingService
+Reference< XInterface > ODatabaseContext::getRegisteredObject(const OUString& _rName)
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(DatabaseAccessContext_Base::rBHelper.bDisposed);
+
+ OUString sURL( getDatabaseLocation( _rName ) );
+
+ if ( sURL.isEmpty() )
+ // there is a registration for this name, but no URL
+ throw IllegalArgumentException();
+
+ // check if URL is already loaded
+ Reference< XInterface > xExistent = getObject( sURL );
+ if ( xExistent.is() )
+ return xExistent;
+
+ return loadObjectFromURL( _rName, sURL );
+}
+
+Reference< XInterface > ODatabaseContext::loadObjectFromURL(const OUString& _rName,const OUString& _sURL)
+{
+ INetURLObject aURL( _sURL );
+
+ if ( aURL.GetProtocol() == INetProtocol::NotValid )
+ throw NoSuchElementException( _rName, *this );
+
+ bool bEmbeddedDataSource = aURL.isSchemeEqualTo(INetProtocol::VndSunStarPkg);
+ try
+ {
+ if (!bEmbeddedDataSource)
+ {
+ ::ucbhelper::Content aContent( _sURL, nullptr, comphelper::getProcessComponentContext() );
+ if ( !aContent.isDocument() )
+ throw InteractiveIOException(
+ _sURL, *this, InteractionClassification_ERROR, IOErrorCode_NO_FILE
+ );
+ }
+ }
+ catch ( const InteractiveIOException& e )
+ {
+ if ( ( e.Code == IOErrorCode_NO_FILE )
+ || ( e.Code == IOErrorCode_NOT_EXISTING )
+ || ( e.Code == IOErrorCode_NOT_EXISTING_PATH )
+ )
+ {
+ // #i40463# #i39187#
+ OUString sErrorMessage( DBA_RES( RID_STR_FILE_DOES_NOT_EXIST ) );
+ ::svt::OFileNotation aTransformer( _sURL );
+
+ SQLException aError;
+ aError.Message = sErrorMessage.replaceAll( "$file$", aTransformer.get( ::svt::OFileNotation::N_SYSTEM ) );
+
+ throw WrappedTargetException( _sURL, *this, Any( aError ) );
+ }
+ throw WrappedTargetException( _sURL, *this, ::cppu::getCaughtException() );
+ }
+ catch( const Exception& )
+ {
+ throw WrappedTargetException( _sURL, *this, ::cppu::getCaughtException() );
+ }
+
+ OSL_ENSURE( m_aDatabaseObjects.find( _sURL ) == m_aDatabaseObjects.end(),
+ "ODatabaseContext::loadObjectFromURL: not intended for already-cached objects!" );
+
+ ::rtl::Reference< ODatabaseModelImpl > pModelImpl;
+ {
+ pModelImpl.set( new ODatabaseModelImpl( _rName, m_aContext, *this ) );
+
+ Reference< XModel > xModel( pModelImpl->createNewModel_deliverOwnership(), UNO_SET_THROW );
+ Reference< XLoadable > xLoad( xModel, UNO_QUERY_THROW );
+
+ ::comphelper::NamedValueCollection aArgs;
+ aArgs.put( "URL", _sURL );
+ aArgs.put( "MacroExecutionMode", MacroExecMode::USE_CONFIG );
+ aArgs.put( "InteractionHandler", task::InteractionHandler::createWithParent(m_aContext, nullptr) );
+ if (bEmbeddedDataSource)
+ {
+ // In this case the host contains the real path, and the path is the embedded stream name.
+ auto const uri = css::uri::UriReferenceFactory::create(m_aContext)->parse(_sURL);
+ if (uri.is() && uri->isAbsolute()
+ && uri->hasAuthority() && !uri->hasQuery() && !uri->hasFragment())
+ {
+ auto const auth = uri->getAuthority();
+ auto const decAuth = rtl::Uri::decode(
+ auth, rtl_UriDecodeStrict, RTL_TEXTENCODING_UTF8);
+ if (auth.isEmpty() == decAuth.isEmpty()) {
+ // Decoding of auth to UTF-8 succeeded:
+ OUString sBaseURI = decAuth + uri->getPath();
+ aArgs.put("BaseURI", sBaseURI);
+ } else {
+ SAL_WARN(
+ "dbaccess.core",
+ "<" << _sURL << "> cannot be parse as vnd.sun.star.pkg URL");
+ }
+ } else {
+ SAL_WARN(
+ "dbaccess.core", "<" << _sURL << "> cannot be parse as vnd.sun.star.pkg URL");
+ }
+ }
+
+ Sequence< PropertyValue > aResource( aArgs.getPropertyValues() );
+ xLoad->load( aResource );
+ xModel->attachResource( _sURL, aResource );
+
+ ::utl::CloseableComponent aEnsureClose( xModel );
+ }
+
+ setTransientProperties( _sURL, *pModelImpl );
+
+ return pModelImpl->getOrCreateDataSource();
+}
+
+void ODatabaseContext::appendAtTerminateListener(const ODatabaseModelImpl& _rDataSourceModel)
+{
+ m_xDatabaseDocumentLoader->append(_rDataSourceModel);
+}
+
+void ODatabaseContext::removeFromTerminateListener(const ODatabaseModelImpl& _rDataSourceModel)
+{
+ m_xDatabaseDocumentLoader->remove(_rDataSourceModel);
+}
+
+void ODatabaseContext::setTransientProperties(const OUString& _sURL, ODatabaseModelImpl& _rDataSourceModel )
+{
+ if ( m_aDatasourceProperties.end() == m_aDatasourceProperties.find(_sURL) )
+ return;
+ try
+ {
+ OUString sAuthFailedPassword;
+ Reference< XPropertySet > xDSProps( _rDataSourceModel.getOrCreateDataSource(), UNO_QUERY_THROW );
+ const Sequence< PropertyValue >& rSessionPersistentProps = m_aDatasourceProperties[_sURL];
+ for ( auto const & prop : rSessionPersistentProps )
+ {
+ if ( prop.Name == "AuthFailedPassword" )
+ {
+ OSL_VERIFY( prop.Value >>= sAuthFailedPassword );
+ }
+ else
+ {
+ xDSProps->setPropertyValue( prop.Name, prop.Value );
+ }
+ }
+
+ _rDataSourceModel.m_sFailedPassword = sAuthFailedPassword;
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+}
+
+void ODatabaseContext::registerObject(const OUString& _rName, const Reference< XInterface > & _rxObject)
+{
+ if ( _rName.isEmpty() )
+ throw IllegalArgumentException( OUString(), *this, 1 );
+
+ Reference< XDocumentDataSource > xDocDataSource( _rxObject, UNO_QUERY );
+ Reference< XModel > xModel( xDocDataSource.is() ? xDocDataSource->getDatabaseDocument() : Reference< XOfficeDatabaseDocument >(), UNO_QUERY );
+ if ( !xModel.is() )
+ throw IllegalArgumentException( OUString(), *this, 2 );
+
+ OUString sURL = xModel->getURL();
+ if ( sURL.isEmpty() )
+ throw IllegalArgumentException( DBA_RES( RID_STR_DATASOURCE_NOT_STORED ), *this, 2 );
+
+ { // avoid deadlocks: lock m_aMutex after checking arguments
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(DatabaseAccessContext_Base::rBHelper.bDisposed);
+
+ registerDatabaseLocation( _rName, sURL );
+
+ ODatabaseSource::setName( xDocDataSource, _rName, ODatabaseSource::DBContextAccess() );
+ }
+
+ // notify our container listeners
+ ContainerEvent aEvent(static_cast<XContainer*>(this), Any(_rName), Any(_rxObject), Any());
+ m_aContainerListeners.notifyEach( &XContainerListener::elementInserted, aEvent );
+}
+
+void ODatabaseContext::storeTransientProperties( ODatabaseModelImpl& _rModelImpl)
+{
+ Reference< XPropertySet > xSource( _rModelImpl.getOrCreateDataSource(), UNO_QUERY );
+ ::comphelper::NamedValueCollection aRememberProps;
+
+ try
+ {
+ // get the info about the properties, check which ones are transient and not readonly
+ Reference< XPropertySetInfo > xSetInfo;
+ if (xSource.is())
+ xSetInfo = xSource->getPropertySetInfo();
+ Sequence< Property > aProperties;
+ if (xSetInfo.is())
+ aProperties = xSetInfo->getProperties();
+
+ for ( const Property& rProperty : std::as_const(aProperties) )
+ {
+ if ( ( ( rProperty.Attributes & PropertyAttribute::TRANSIENT) != 0 )
+ && ( ( rProperty.Attributes & PropertyAttribute::READONLY) == 0 )
+ )
+ {
+ // found such a property
+ aRememberProps.put( rProperty.Name, xSource->getPropertyValue( rProperty.Name ) );
+ }
+ }
+ }
+ catch ( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+
+ // additionally, remember the "failed password", which is not available as property
+ // #i86178#
+ aRememberProps.put( "AuthFailedPassword", _rModelImpl.m_sFailedPassword );
+
+ OUString sDocumentURL( _rModelImpl.getURL() );
+ if ( m_aDatabaseObjects.find( sDocumentURL ) != m_aDatabaseObjects.end() )
+ {
+ m_aDatasourceProperties[ sDocumentURL ] = aRememberProps.getPropertyValues();
+ }
+ else if ( m_aDatabaseObjects.find( _rModelImpl.m_sName ) != m_aDatabaseObjects.end() )
+ {
+ OSL_FAIL( "ODatabaseContext::storeTransientProperties: a database document register by name? This shouldn't happen anymore!" );
+ // all the code should have been changed so that registration is by URL only
+ m_aDatasourceProperties[ _rModelImpl.m_sName ] = aRememberProps.getPropertyValues();
+ }
+ else
+ {
+ OSL_ENSURE( sDocumentURL.isEmpty() && _rModelImpl.m_sName.isEmpty() ,
+ "ODatabaseContext::storeTransientProperties: a non-empty data source which I do not know?!" );
+ }
+}
+
+void SAL_CALL ODatabaseContext::addContainerListener( const Reference< XContainerListener >& _rxListener )
+{
+ m_aContainerListeners.addInterface(_rxListener);
+}
+
+void SAL_CALL ODatabaseContext::removeContainerListener( const Reference< XContainerListener >& _rxListener )
+{
+ m_aContainerListeners.removeInterface(_rxListener);
+}
+
+void ODatabaseContext::revokeObject(const OUString& _rName)
+{
+ ClearableMutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(DatabaseAccessContext_Base::rBHelper.bDisposed);
+
+ OUString sURL = getDatabaseLocation( _rName );
+
+ revokeDatabaseLocation( _rName );
+ // will throw if something goes wrong
+
+ if ( m_aDatabaseObjects.find( _rName ) != m_aDatabaseObjects.end() )
+ {
+ m_aDatasourceProperties[ sURL ] = m_aDatasourceProperties[ _rName ];
+ }
+
+ // check if URL is already loaded
+ ObjectCache::const_iterator aExistent = m_aDatabaseObjects.find( sURL );
+ if ( aExistent != m_aDatabaseObjects.end() )
+ m_aDatabaseObjects.erase( aExistent );
+
+ // notify our container listeners
+ ContainerEvent aEvent( *this, Any( _rName ), Any(), Any() );
+ aGuard.clear();
+ m_aContainerListeners.notifyEach( &XContainerListener::elementRemoved, aEvent );
+}
+
+sal_Bool SAL_CALL ODatabaseContext::hasRegisteredDatabase( const OUString& Name )
+{
+ return m_xDatabaseRegistrations->hasRegisteredDatabase( Name );
+}
+
+Sequence< OUString > SAL_CALL ODatabaseContext::getRegistrationNames()
+{
+ return m_xDatabaseRegistrations->getRegistrationNames();
+}
+
+OUString SAL_CALL ODatabaseContext::getDatabaseLocation( const OUString& Name )
+{
+ return m_xDatabaseRegistrations->getDatabaseLocation( Name );
+}
+
+void SAL_CALL ODatabaseContext::registerDatabaseLocation( const OUString& Name, const OUString& Location )
+{
+ m_xDatabaseRegistrations->registerDatabaseLocation( Name, Location );
+}
+
+void SAL_CALL ODatabaseContext::revokeDatabaseLocation( const OUString& Name )
+{
+ m_xDatabaseRegistrations->revokeDatabaseLocation( Name );
+}
+
+void SAL_CALL ODatabaseContext::changeDatabaseLocation( const OUString& Name, const OUString& NewLocation )
+{
+ m_xDatabaseRegistrations->changeDatabaseLocation( Name, NewLocation );
+}
+
+sal_Bool SAL_CALL ODatabaseContext::isDatabaseRegistrationReadOnly( const OUString& Name )
+{
+ return m_xDatabaseRegistrations->isDatabaseRegistrationReadOnly( Name );
+}
+
+void SAL_CALL ODatabaseContext::addDatabaseRegistrationsListener( const Reference< XDatabaseRegistrationsListener >& Listener )
+{
+ m_xDatabaseRegistrations->addDatabaseRegistrationsListener( Listener );
+}
+
+void SAL_CALL ODatabaseContext::removeDatabaseRegistrationsListener( const Reference< XDatabaseRegistrationsListener >& Listener )
+{
+ m_xDatabaseRegistrations->removeDatabaseRegistrationsListener( Listener );
+}
+
+// css::container::XElementAccess
+Type ODatabaseContext::getElementType( )
+{
+ return cppu::UnoType<XDataSource>::get();
+}
+
+sal_Bool ODatabaseContext::hasElements()
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(DatabaseAccessContext_Base::rBHelper.bDisposed);
+
+ return getElementNames().hasElements();
+}
+
+// css::container::XEnumerationAccess
+Reference< css::container::XEnumeration > ODatabaseContext::createEnumeration()
+{
+ MutexGuard aGuard(m_aMutex);
+ return new ::comphelper::OEnumerationByName(static_cast<XNameAccess*>(this));
+}
+
+// css::container::XNameAccess
+Any ODatabaseContext::getByName(const OUString& _rName)
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(DatabaseAccessContext_Base::rBHelper.bDisposed);
+ if ( _rName.isEmpty() )
+ throw NoSuchElementException(_rName, *this);
+
+ try
+ {
+ Reference< XInterface > xExistent = getObject( _rName );
+ if ( xExistent.is() )
+ return Any( xExistent );
+
+ // see whether this is a registered name
+ OUString sURL;
+ if ( hasRegisteredDatabase( _rName ) )
+ {
+ sURL = getDatabaseLocation( _rName );
+ // is the object cached under its URL?
+ xExistent = getObject( sURL );
+ }
+ else
+ // interpret the name as URL
+ sURL = _rName;
+
+ if ( !xExistent.is() )
+ // try to load this as URL
+ xExistent = loadObjectFromURL( _rName, sURL );
+ return Any( xExistent );
+ }
+ catch (const NoSuchElementException&)
+ { // let these exceptions through
+ throw;
+ }
+ catch (const WrappedTargetException&)
+ { // let these exceptions through
+ throw;
+ }
+ catch (const RuntimeException&)
+ { // let these exceptions through
+ throw;
+ }
+ catch (const Exception&)
+ { // exceptions other than the specified ones -> wrap
+ Any aError = ::cppu::getCaughtException();
+ throw WrappedTargetException(_rName, *this, aError );
+ }
+}
+
+Sequence< OUString > ODatabaseContext::getElementNames()
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(DatabaseAccessContext_Base::rBHelper.bDisposed);
+
+ return getRegistrationNames();
+}
+
+sal_Bool ODatabaseContext::hasByName(const OUString& _rName)
+{
+ MutexGuard aGuard(m_aMutex);
+ ::connectivity::checkDisposed(DatabaseAccessContext_Base::rBHelper.bDisposed);
+
+ return hasRegisteredDatabase( _rName );
+}
+
+Reference< XInterface > ODatabaseContext::getObject( const OUString& _rURL )
+{
+ ObjectCache::const_iterator aFind = m_aDatabaseObjects.find( _rURL );
+ Reference< XInterface > xExistent;
+ if ( aFind != m_aDatabaseObjects.end() )
+ xExistent = aFind->second->getOrCreateDataSource();
+ return xExistent;
+}
+
+void ODatabaseContext::registerDatabaseDocument( ODatabaseModelImpl& _rModelImpl )
+{
+ OUString sURL( _rModelImpl.getURL() );
+ SAL_INFO("dbaccess.core", "DatabaseContext: registering " << sURL);
+ if ( m_aDatabaseObjects.find( sURL ) == m_aDatabaseObjects.end() )
+ {
+ m_aDatabaseObjects[ sURL ] = &_rModelImpl;
+ setTransientProperties( sURL, _rModelImpl );
+ }
+ else
+ OSL_FAIL( "ODatabaseContext::registerDatabaseDocument: already have an object registered for this URL!" );
+}
+
+void ODatabaseContext::revokeDatabaseDocument( const ODatabaseModelImpl& _rModelImpl )
+{
+ const OUString& sURL( _rModelImpl.getURL() );
+ SAL_INFO("dbaccess.core", "DatabaseContext: deregistering " << sURL);
+ m_aDatabaseObjects.erase( sURL );
+}
+
+void ODatabaseContext::databaseDocumentURLChange( const OUString& _rOldURL, const OUString& _rNewURL )
+{
+ SAL_INFO("dbaccess.core", "DatabaseContext: changing registrations from " << _rOldURL <<
+ " to " << _rNewURL);
+ ObjectCache::const_iterator oldPos = m_aDatabaseObjects.find( _rOldURL );
+ ENSURE_OR_THROW( oldPos != m_aDatabaseObjects.end(), "illegal old database document URL" );
+ ObjectCache::const_iterator newPos = m_aDatabaseObjects.find( _rNewURL );
+ ENSURE_OR_THROW( newPos == m_aDatabaseObjects.end(), "illegal new database document URL" );
+
+ m_aDatabaseObjects[ _rNewURL ] = oldPos->second;
+ m_aDatabaseObjects.erase( oldPos );
+}
+
+sal_Int64 SAL_CALL ODatabaseContext::getSomething( const Sequence< sal_Int8 >& rId )
+{
+ return comphelper::getSomethingImpl(rId, this);
+}
+
+const Sequence< sal_Int8 > & ODatabaseContext::getUnoTunnelId()
+{
+ static const comphelper::UnoIdInit implId;
+ return implId.getSeq();
+}
+
+void ODatabaseContext::onBasicManagerCreated( const Reference< XModel >& _rxForDocument, BasicManager& _rBasicManager )
+{
+#if !HAVE_FEATURE_SCRIPTING
+ (void) _rxForDocument;
+ (void) _rBasicManager;
+#else
+ // if it's a database document ...
+ Reference< XOfficeDatabaseDocument > xDatabaseDocument( _rxForDocument, UNO_QUERY );
+ // ... or a sub document of a database document ...
+ if ( !xDatabaseDocument.is() )
+ {
+ Reference< XChild > xDocAsChild( _rxForDocument, UNO_QUERY );
+ if ( xDocAsChild.is() )
+ xDatabaseDocument.set( xDocAsChild->getParent(), UNO_QUERY );
+ }
+
+ // ... whose BasicManager has just been created, then add the global DatabaseDocument variable to its scope.
+ if ( xDatabaseDocument.is() )
+ _rBasicManager.SetGlobalUNOConstant( "ThisDatabaseDocument", Any( xDatabaseDocument ) );
+#endif
+}
+
+} // namespace dbaccess
+
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+com_sun_star_comp_dba_ODatabaseContext_get_implementation(
+ css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const& )
+{
+ return cppu::acquire(new dbaccess::ODatabaseContext(context));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/dataaccess/databasedocument.cxx b/dbaccess/source/core/dataaccess/databasedocument.cxx
new file mode 100644
index 000000000..419d02d2d
--- /dev/null
+++ b/dbaccess/source/core/dataaccess/databasedocument.cxx
@@ -0,0 +1,2211 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <core_resource.hxx>
+#include <strings.hrc>
+#include "databasedocument.hxx"
+#include "documenteventexecutor.hxx"
+#include <databasecontext.hxx>
+#include "documentcontainer.hxx"
+#include <sdbcoretools.hxx>
+#include <strings.hxx>
+#include <recovery/dbdocrecovery.hxx>
+
+#include <officecfg/Office/Common.hxx>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/document/XExporter.hpp>
+#include <com/sun/star/document/XFilter.hpp>
+#include <com/sun/star/document/XImporter.hpp>
+#include <com/sun/star/document/XGraphicStorageHandler.hpp>
+#include <com/sun/star/document/GraphicStorageHandler.hpp>
+#include <com/sun/star/frame/Desktop.hpp>
+#include <com/sun/star/frame/ModuleManager.hpp>
+#include <com/sun/star/io/IOException.hpp>
+#include <com/sun/star/io/XSeekable.hpp>
+#include <com/sun/star/io/XOutputStream.hpp>
+#include <com/sun/star/io/XTruncate.hpp>
+#include <com/sun/star/lang/NoSupportException.hpp>
+#include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
+#include <com/sun/star/script/provider/theMasterScriptProviderFactory.hpp>
+#include <com/sun/star/sdb/DatabaseContext.hpp>
+#include <com/sun/star/sdb/application/XDatabaseDocumentUI.hpp>
+#include <com/sun/star/task/XStatusIndicator.hpp>
+#include <com/sun/star/ucb/SimpleFileAccess.hpp>
+#include <com/sun/star/ui/UIConfigurationManager.hpp>
+#include <com/sun/star/util/CloseVetoException.hpp>
+#include <com/sun/star/view/XSelectionSupplier.hpp>
+#include <com/sun/star/xml/sax/XDocumentHandler.hpp>
+#include <com/sun/star/xml/sax/Writer.hpp>
+
+#include <com/sun/star/script/XStorageBasedLibraryContainer.hpp>
+#include <com/sun/star/awt/XControl.hpp>
+#include <com/sun/star/awt/DialogProvider.hpp>
+
+#include <comphelper/documentconstants.hxx>
+#include <comphelper/enumhelper.hxx>
+#include <comphelper/genericpropertyset.hxx>
+#include <comphelper/namedvaluecollection.hxx>
+#include <comphelper/numberedcollection.hxx>
+#include <comphelper/servicehelper.hxx>
+#include <comphelper/storagehelper.hxx>
+#include <comphelper/propertysetinfo.hxx>
+#include <comphelper/types.hxx>
+
+#include <connectivity/dbtools.hxx>
+
+#include <cppuhelper/exc_hlp.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <framework/titlehelper.hxx>
+#include <unotools/saveopt.hxx>
+#include <tools/diagnose_ex.h>
+#include <osl/diagnose.h>
+
+#include <vcl/GraphicObject.hxx>
+#include <tools/urlobj.hxx>
+
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::frame;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::document;
+using namespace ::com::sun::star::io;
+using namespace ::com::sun::star::util;
+using namespace ::com::sun::star::embed;
+using namespace ::com::sun::star::task;
+using namespace ::com::sun::star::view;
+using namespace ::com::sun::star::sdb;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::xml::sax;
+using namespace ::com::sun::star::script;
+using namespace ::com::sun::star::script::provider;
+using namespace ::com::sun::star::ui;
+using namespace ::cppu;
+
+namespace dbaccess
+{
+
+// ViewMonitor
+
+bool ViewMonitor::onControllerConnected( const Reference< XController >& _rxController )
+{
+ bool bFirstControllerEver = !m_bEverHadController;
+ m_bEverHadController = true;
+
+ m_xLastConnectedController = _rxController;
+ m_bLastIsFirstEverController = bFirstControllerEver;
+
+ return bFirstControllerEver;
+}
+
+bool ViewMonitor::onSetCurrentController( const Reference< XController >& _rxController )
+{
+ // we interpret this as "loading the document (including UI) is finished",
+ // if and only if this is the controller which was last connected, and it was the
+ // first controller ever connected
+ bool bLoadFinished = ( _rxController == m_xLastConnectedController ) && m_bLastIsFirstEverController;
+
+ // notify the respective events
+ if ( bLoadFinished )
+ m_rEventNotifier.notifyDocumentEventAsync( m_bIsNewDocument ? "OnNew" : "OnLoad" );
+
+ return bLoadFinished;
+}
+
+
+ODatabaseDocument::ODatabaseDocument(const ::rtl::Reference<ODatabaseModelImpl>& _pImpl )
+ :ModelDependentComponent( _pImpl )
+ ,ODatabaseDocument_OfficeDocument( getMutex() )
+ ,m_aModifyListeners( getMutex() )
+ ,m_aCloseListener( getMutex() )
+ ,m_aStorageListeners( getMutex() )
+ ,m_pEventContainer( new DocumentEvents( *this, getMutex(), _pImpl->getDocumentEvents() ) )
+ ,m_aEventNotifier( *this, getMutex() )
+ ,m_aViewMonitor( m_aEventNotifier )
+ ,m_eInitState( NotInitialized )
+ ,m_bClosing( false )
+ ,m_bAllowDocumentScripting( false )
+ ,m_bHasBeenRecovered( false )
+ ,m_bEmbedded(false)
+{
+ osl_atomic_increment( &m_refCount );
+ {
+ impl_reparent_nothrow( m_xForms );
+ impl_reparent_nothrow( m_xReports );
+ impl_reparent_nothrow( m_pImpl->m_xTableDefinitions );
+ impl_reparent_nothrow( m_pImpl->m_xCommandDefinitions );
+
+ m_pEventExecutor = new DocumentEventExecutor( m_pImpl->m_aContext, this );
+ }
+ osl_atomic_decrement( &m_refCount );
+
+ // if there previously was a document instance for the same Impl which was already initialized,
+ // then consider ourself initialized, too.
+ // #i94840#
+ if ( !m_pImpl->hadInitializedDocument() )
+ return;
+
+ // Note we set our init-state to "Initializing", not "Initialized". We're created from inside the ModelImpl,
+ // which is expected to call attachResource in case there was a previous incarnation of the document,
+ // so we can properly finish our initialization then.
+ impl_setInitializing();
+
+ if ( !m_pImpl->getURL().isEmpty() )
+ {
+ // if the previous incarnation of the DatabaseDocument already had a URL, then creating this incarnation
+ // here is effectively loading the document.
+ // #i105505#
+ m_aViewMonitor.onLoadedDocument();
+ }
+}
+
+ODatabaseDocument::~ODatabaseDocument()
+{
+ if ( !ODatabaseDocument_OfficeDocument::rBHelper.bInDispose && !ODatabaseDocument_OfficeDocument::rBHelper.bDisposed )
+ {
+ acquire();
+ dispose();
+ }
+}
+
+Any SAL_CALL ODatabaseDocument::queryInterface( const Type& _rType )
+{
+ // strip XEmbeddedScripts and XScriptInvocationContext if we have any form/report
+ // which already contains macros. In this case, the database document itself is not
+ // allowed to contain macros, too.
+ if ( !m_bAllowDocumentScripting
+ && ( _rType.equals( cppu::UnoType<XEmbeddedScripts>::get() )
+ || _rType.equals( cppu::UnoType<XScriptInvocationContext>::get() )
+ )
+ )
+ return Any();
+
+ Any aReturn = ODatabaseDocument_OfficeDocument::queryInterface(_rType);
+ if (!aReturn.hasValue())
+ aReturn = ODatabaseDocument_Title::queryInterface(_rType);
+ return aReturn;
+}
+
+void SAL_CALL ODatabaseDocument::acquire( ) noexcept
+{
+ ODatabaseDocument_OfficeDocument::acquire();
+}
+
+void SAL_CALL ODatabaseDocument::release( ) noexcept
+{
+ ODatabaseDocument_OfficeDocument::release();
+}
+
+Sequence< Type > SAL_CALL ODatabaseDocument::getTypes( )
+{
+ Sequence< Type > aTypes = ::comphelper::concatSequences(
+ ODatabaseDocument_OfficeDocument::getTypes(),
+ ODatabaseDocument_Title::getTypes()
+ );
+
+ // strip XEmbeddedScripts and XScriptInvocationContext if we have any form/report
+ // which already contains macros. In this case, the database document itself is not
+ // allowed to contain macros, too.
+ if ( !m_bAllowDocumentScripting )
+ {
+ auto [begin, end] = asNonConstRange(aTypes);
+ auto newEnd = std::remove_if( begin, end,
+ [](const Type& t)
+ { return t == cppu::UnoType<XEmbeddedScripts>::get() ||
+ t == cppu::UnoType<XScriptInvocationContext>::get();} );
+ aTypes.realloc( std::distance(begin, newEnd) );
+ }
+
+ return aTypes;
+}
+
+Sequence< sal_Int8 > SAL_CALL ODatabaseDocument::getImplementationId( )
+{
+ return css::uno::Sequence<sal_Int8>();
+}
+
+// local functions
+namespace
+{
+ Reference< XStatusIndicator > lcl_extractStatusIndicator( const ::comphelper::NamedValueCollection& _rArguments )
+ {
+ Reference< XStatusIndicator > xStatusIndicator;
+ return _rArguments.getOrDefault( "StatusIndicator", xStatusIndicator );
+ }
+
+ void lcl_triggerStatusIndicator_throw( const ::comphelper::NamedValueCollection& _rArguments, DocumentGuard& _rGuard, const bool _bStart )
+ {
+ Reference< XStatusIndicator > xStatusIndicator( lcl_extractStatusIndicator( _rArguments ) );
+ if ( !xStatusIndicator.is() )
+ return;
+
+ _rGuard.clear();
+ try
+ {
+ if ( _bStart )
+ xStatusIndicator->start( OUString(), sal_Int32(1000000) );
+ else
+ xStatusIndicator->end();
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ _rGuard.reset();
+ // note that |reset| can throw a DisposedException
+ }
+
+ void lcl_extractStatusIndicator( const ::comphelper::NamedValueCollection& _rArguments, Sequence< Any >& _rCallArgs )
+ {
+ Reference< XStatusIndicator > xStatusIndicator( lcl_extractStatusIndicator( _rArguments ) );
+ if ( !xStatusIndicator.is() )
+ return;
+
+ sal_Int32 nLength = _rCallArgs.getLength();
+ _rCallArgs.realloc( nLength + 1 );
+ _rCallArgs.getArray()[ nLength ] <<= xStatusIndicator;
+ }
+
+ void lcl_extractAndStartStatusIndicator( const ::comphelper::NamedValueCollection& _rArguments, Reference< XStatusIndicator >& _rxStatusIndicator,
+ Sequence< Any >& _rCallArgs )
+ {
+ _rxStatusIndicator = lcl_extractStatusIndicator( _rArguments );
+ if ( !_rxStatusIndicator.is() )
+ return;
+
+ try
+ {
+ _rxStatusIndicator->start( OUString(), sal_Int32(1000000) );
+
+ sal_Int32 nLength = _rCallArgs.getLength();
+ _rCallArgs.realloc( nLength + 1 );
+ _rCallArgs.getArray()[ nLength ] <<= _rxStatusIndicator;
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+
+ Sequence< PropertyValue > lcl_appendFileNameToDescriptor( const ::comphelper::NamedValueCollection& _rDescriptor, const OUString& _rURL )
+ {
+ ::comphelper::NamedValueCollection aMutableDescriptor( _rDescriptor );
+ if ( !_rURL.isEmpty() )
+ {
+ aMutableDescriptor.put( "FileName", _rURL );
+ aMutableDescriptor.put( "URL", _rURL );
+ }
+ return aMutableDescriptor.getPropertyValues();
+ }
+}
+
+constexpr OUStringLiteral sPictures = u"Pictures";
+
+// base documents seem to have a different behaviour to other documents, the
+// root storage contents at least seem to be re-used over different saves, thus if there is a
+// top level Picture directory it is never cleared.
+// If we delete the 'Pictures' directory then the dialog library storage which does store
+// any embed images will not work properly. ( this is due to the fact it will
+// try to load the dialog which will try and access the embed images, if those images are not cached in
+// memory it will try to read them from the Picture directory which is now gone, so... we have to use this
+// inglorious hack below which basically will
+//
+// a) create a temp storage
+//
+// b) introspect any dialogs for any embed graphics and grab the associate URL(s)
+//
+// c) populate the temp storage with the associated embed images ( will be stored in a 'Pictures' folder )
+//
+// d) delete the 'Picture' element from the root storage
+//
+// e) copy the Pictures element of the temp storage to the root storage
+//
+// this assumes that we don't use the Pictures folder in the root of the base
+// document for anything, I believe this is a valid assumption ( as much as
+// I could check anyway )
+
+/// @throws RuntimeException
+static void lcl_uglyHackToStoreDialogeEmbedImages( const Reference< XStorageBasedLibraryContainer >& xDlgCont, const Reference< XStorage >& xStorage, const Reference< XModel >& rxModel, const Reference<XComponentContext >& rxContext )
+{
+ const Sequence< OUString > sLibraries = xDlgCont->getElementNames();
+ Reference< XStorage > xTmpPic = xStorage->openStorageElement( "tempPictures", ElementModes::READWRITE );
+
+ std::vector<uno::Reference<graphic::XGraphic>> vxGraphicList;
+ for ( OUString const & sLibrary : sLibraries )
+ {
+ xDlgCont->loadLibrary( sLibrary );
+ Reference< XNameContainer > xLib;
+ xDlgCont->getByName( sLibrary ) >>= xLib;
+ if ( xLib.is() )
+ {
+ Sequence< OUString > sDialogs = xLib->getElementNames();
+ sal_Int32 nDialogs( sDialogs.getLength() );
+ for ( sal_Int32 j=0; j < nDialogs; ++j )
+ {
+ Reference < awt::XDialogProvider > xDlgPrv = awt::DialogProvider::createWithModel(rxContext, rxModel);
+ OUString sDialogUrl =
+ "vnd.sun.star.script:" + sLibrary + "." + sDialogs[j] + "?location=document";
+
+ Reference< css::awt::XControl > xDialog( xDlgPrv->createDialog( sDialogUrl ), UNO_QUERY );
+ Reference< XInterface > xModel( xDialog->getModel() );
+ vcl::graphic::SearchForGraphics(xModel, vxGraphicList);
+ }
+ }
+ }
+ // if we have any image urls, make sure we copy the associated images into tempPictures
+ if (!vxGraphicList.empty())
+ {
+ // Export the images to the storage
+ uno::Reference<document::XGraphicStorageHandler> xGraphicStorageHandler;
+ xGraphicStorageHandler.set(GraphicStorageHandler::createWithStorage(rxContext, xTmpPic));
+ if (xGraphicStorageHandler.is())
+ {
+ for (uno::Reference<graphic::XGraphic> const & rxGraphic : vxGraphicList)
+ {
+ xGraphicStorageHandler->saveGraphic(rxGraphic);
+ }
+ }
+ // delete old 'Pictures' storage and copy the contents of tempPictures into xStorage
+ xStorage->removeElement( sPictures );
+ xTmpPic->copyElementTo( sPictures, xStorage, sPictures );
+ }
+ else
+ {
+ // clean up an existing Pictures dir
+ if ( xStorage->isStorageElement( sPictures ) )
+ xStorage->removeElement( sPictures );
+ }
+}
+
+void ODatabaseDocument::impl_setInitialized()
+{
+ m_eInitState = Initialized;
+
+ // start event notifications
+ m_aEventNotifier.onDocumentInitialized();
+}
+
+void ODatabaseDocument::impl_reset_nothrow()
+{
+ try
+ {
+ m_pImpl->clearConnections();
+ m_pImpl->disposeStorages();
+ m_pImpl->resetRootStorage();
+
+ clearObjectContainer( m_xForms );
+ clearObjectContainer( m_xReports );
+ clearObjectContainer( m_pImpl->m_xTableDefinitions );
+ clearObjectContainer( m_pImpl->m_xCommandDefinitions );
+
+ m_eInitState = NotInitialized;
+
+ m_pImpl->reset();
+ }
+ catch(const Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ m_pImpl->m_bDocumentReadOnly = false;
+}
+
+namespace
+{
+ /** property map for import/export info set */
+ comphelper::PropertyMapEntry const aExportInfoMap[] =
+ {
+ { OUString("BaseURI"), 0, ::cppu::UnoType<OUString>::get(), beans::PropertyAttribute::MAYBEVOID, 0 },
+ { OUString("StreamName"), 0, ::cppu::UnoType<OUString>::get(), beans::PropertyAttribute::MAYBEVOID, 0 },
+ { OUString("UsePrettyPrinting"), 0, ::cppu::UnoType<sal_Bool>::get(), beans::PropertyAttribute::MAYBEVOID, 0},
+ { OUString("TargetStorage"), 0, cppu::UnoType<embed::XStorage>::get(), beans::PropertyAttribute::MAYBEVOID, 0},
+ { OUString("StreamRelPath"), 0, cppu::UnoType<OUString>::get(), beans::PropertyAttribute::MAYBEVOID, 0},
+ };
+}
+
+void ODatabaseDocument::impl_import_nolck_throw( const Reference< XComponentContext >& _rContext, const Reference< XInterface >& _rxTargetComponent,
+ const ::comphelper::NamedValueCollection& _rResource )
+{
+ Sequence< Any > aFilterCreationArgs;
+ Reference< XStatusIndicator > xStatusIndicator;
+ lcl_extractAndStartStatusIndicator( _rResource, xStatusIndicator, aFilterCreationArgs );
+
+ uno::Reference< beans::XPropertySet > xInfoSet( comphelper::GenericPropertySet_CreateInstance( new comphelper::PropertySetInfo( aExportInfoMap ) ) );
+ OUString sBaseURI = _rResource.getOrDefault("BaseURI", OUString());
+ if (sBaseURI.isEmpty())
+ sBaseURI = _rResource.getOrDefault("URL",OUString());
+ assert(!sBaseURI.isEmpty()); // needed for relative URLs
+ xInfoSet->setPropertyValue("BaseURI", uno::Any(sBaseURI));
+ xInfoSet->setPropertyValue("StreamName", uno::Any(OUString("content.xml")));
+
+ const sal_Int32 nCount = aFilterCreationArgs.getLength();
+ aFilterCreationArgs.realloc(nCount + 1);
+ aFilterCreationArgs.getArray()[nCount] <<= xInfoSet;
+
+ Reference< XImporter > xImporter(
+ _rContext->getServiceManager()->createInstanceWithArgumentsAndContext("com.sun.star.comp.sdb.DBFilter", aFilterCreationArgs, _rContext),
+ UNO_QUERY_THROW );
+
+ Reference< XComponent > xComponent( _rxTargetComponent, UNO_QUERY_THROW );
+ xImporter->setTargetDocument( xComponent );
+
+ Reference< XFilter > xFilter( xImporter, UNO_QUERY_THROW );
+ Sequence< PropertyValue > aFilterArgs( ODatabaseModelImpl::stripLoadArguments( _rResource ).getPropertyValues() );
+ xFilter->filter( aFilterArgs );
+
+ if ( xStatusIndicator.is() )
+ xStatusIndicator->end();
+}
+
+void SAL_CALL ODatabaseDocument::initNew( )
+{
+ // SYNCHRONIZED ->
+ DocumentGuard aGuard( *this, DocumentGuard::InitMethod );
+
+ impl_reset_nothrow();
+
+ impl_setInitializing();
+
+ // create a temporary storage
+ Reference< XStorage > xTempStor( ::comphelper::OStorageHelper::GetTemporaryStorage( m_pImpl->m_aContext ) );
+
+ // store therein
+ impl_storeToStorage_throw( xTempStor, Sequence< PropertyValue >(), aGuard );
+
+ // let the impl know we're now based on this storage
+ m_pImpl->switchToStorage( xTempStor );
+
+ // for the newly created document, allow document-wide scripting
+ m_bAllowDocumentScripting = true;
+
+ impl_setInitialized();
+
+ m_aEventNotifier.notifyDocumentEventAsync( "OnTitleChanged" );
+
+ impl_setModified_nothrow( false, aGuard );
+ // <- SYNCHRONIZED
+
+ m_aEventNotifier.notifyDocumentEvent( "OnCreate" );
+
+ impl_notifyStorageChange_nolck_nothrow( xTempStor );
+}
+
+void SAL_CALL ODatabaseDocument::load( const Sequence< PropertyValue >& Arguments )
+{
+ // SYNCHRONIZED ->
+ DocumentGuard aGuard( *this, DocumentGuard::InitMethod );
+
+ impl_reset_nothrow();
+
+ ::comphelper::NamedValueCollection aResource( Arguments );
+ if ( aResource.has( "FileName" ) && !aResource.has( "URL" ) )
+ // FileName is the compatibility name for URL, so we might have clients passing
+ // a FileName only. However, some of our code works with the URL only, so ensure
+ // we have one.
+ aResource.put( "URL", aResource.get( "FileName" ) );
+ if ( aResource.has( "URL" ) && !aResource.has( "FileName" ) )
+ // similar ... just in case there is legacy code which expects a FileName only
+ aResource.put( "FileName", aResource.get( "URL" ) );
+
+ // now that somebody (perhaps) told us a macro execution mode, remember it as
+ // ImposedMacroExecMode
+ m_pImpl->setImposedMacroExecMode(
+ aResource.getOrDefault( "MacroExecutionMode", m_pImpl->getImposedMacroExecMode() ) );
+
+ impl_setInitializing();
+ try
+ {
+ aGuard.clear();
+ impl_import_nolck_throw( m_pImpl->m_aContext, *this, aResource );
+ aGuard.reset();
+ }
+ catch( const Exception& )
+ {
+ impl_reset_nothrow();
+ throw;
+ }
+ // tell our view monitor that the document has been loaded - this way it will fire the proper
+ // event (OnLoad instead of OnCreate) later on
+ m_aViewMonitor.onLoadedDocument();
+
+ // note that we do *not* call impl_setInitialized() here: The initialization is only complete
+ // when the XModel::attachResource has been called, not sooner.
+ // however, in case of embedding, XModel::attachResource is already called.
+ if (m_bEmbedded)
+ impl_setInitialized();
+
+ impl_setModified_nothrow( false, aGuard );
+ // <- SYNCHRONIZED
+}
+
+namespace
+{
+ bool lcl_hasAnyModifiedSubComponent_throw( const Reference< XController >& i_rController )
+ {
+ Reference< css::sdb::application::XDatabaseDocumentUI > xDatabaseUI( i_rController, UNO_QUERY_THROW );
+
+ const Sequence< Reference< XComponent > > aComponents( xDatabaseUI->getSubComponents() );
+
+ bool isAnyModified = false;
+ for ( auto const & xComponent : aComponents )
+ {
+ Reference< XModifiable > xModify( xComponent, UNO_QUERY );
+ if ( xModify.is() )
+ {
+ isAnyModified = xModify->isModified();
+ continue;
+ }
+
+ // TODO: clarify: anything else to care for? Both the sub components with and without model
+ // should support the XModifiable interface, so I think nothing more is needed here.
+ OSL_FAIL( "lcl_hasAnyModifiedSubComponent_throw: anything left to do here?" );
+ }
+
+ return isAnyModified;
+ }
+}
+
+sal_Bool SAL_CALL ODatabaseDocument::wasModifiedSinceLastSave()
+{
+ DocumentGuard aGuard(*this, DocumentGuard::DefaultMethod);
+
+ // The implementation here is somewhat sloppy, in that it returns whether *any* part of the whole
+ // database document, including opened sub components, is modified. This is more than what is requested:
+ // We need to return <TRUE/> if the doc itself, or any of the opened sub components, has been modified
+ // since the last call to any of the save* methods, or since the document has been loaded/created.
+ // However, the API definition explicitly allows to be that sloppy ...
+
+ if ( isModified() )
+ return true;
+
+ // auto recovery is an "UI feature", it is to restore the UI the user knows. Thus,
+ // we ask our connected controllers, not simply our existing form/report definitions.
+ // (There is some information which even cannot be obtained without asking the controller.
+ // For instance, newly created, but not yet saved, forms/reports are accessible via the
+ // controller only, but not via the model.)
+
+ try
+ {
+ for (auto const& controller : m_aControllers)
+ {
+ if ( lcl_hasAnyModifiedSubComponent_throw(controller) )
+ return true;
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+
+ return false;
+}
+
+void SAL_CALL ODatabaseDocument::storeToRecoveryFile( const OUString& i_TargetLocation, const Sequence< PropertyValue >& i_MediaDescriptor )
+{
+ DocumentGuard aGuard(*this, DocumentGuard::DefaultMethod);
+ ModifyLock aLock( *this );
+
+ try
+ {
+ // create a storage for the target location
+ Reference< XStorage > xTargetStorage( impl_createStorageFor_throw( i_TargetLocation ) );
+
+ // first store the document as a whole into this storage
+ impl_storeToStorage_throw( xTargetStorage, i_MediaDescriptor, aGuard );
+
+ // save the sub components which need saving
+ DatabaseDocumentRecovery aDocRecovery( m_pImpl->m_aContext);
+ aDocRecovery.saveModifiedSubComponents( xTargetStorage, m_aControllers );
+
+ // commit the root storage
+ tools::stor::commitStorageIfWriteable( xTargetStorage );
+ }
+ catch( const IOException& )
+ {
+ throw;
+ }
+ catch( const RuntimeException& )
+ {
+ throw;
+ }
+ catch( const WrappedTargetException& )
+ {
+ throw;
+ }
+ catch( const Exception& )
+ {
+ Any aError = ::cppu::getCaughtException();
+ throw WrappedTargetException( OUString(), *this, aError );
+ }
+}
+
+void SAL_CALL ODatabaseDocument::recoverFromFile( const OUString& i_SourceLocation, const OUString& i_SalvagedFile, const Sequence< PropertyValue >& i_MediaDescriptor )
+{
+ try
+ {
+ DocumentGuard aGuard( *this, DocumentGuard::InitMethod );
+
+ if ( i_SourceLocation.isEmpty() )
+ throw IllegalArgumentException( OUString(), *this, 1 );
+
+
+ // load the document itself, by simply delegating to our "load" method
+
+ // our load implementation expects the SalvagedFile and URL to be in the media descriptor
+ ::comphelper::NamedValueCollection aMediaDescriptor( i_MediaDescriptor );
+ aMediaDescriptor.put( "SalvagedFile", i_SalvagedFile );
+ aMediaDescriptor.put( "URL", i_SourceLocation );
+
+ aGuard.clear(); // (load has an own guarding scheme)
+ load( aMediaDescriptor.getPropertyValues() );
+ aGuard.reset();
+
+ // Without a controller, we are unable to recover the sub components, as they're always tied to a controller.
+ // So, everything else is done when the first controller is connected.
+ m_bHasBeenRecovered = true;
+
+ // tell the impl that we've been loaded from the given location
+ m_pImpl->setDocFileLocation( i_SourceLocation );
+
+ // by definition (of XDocumentRecovery), we're responsible for delivering a fully-initialized document,
+ // which includes an attachResource call.
+ const OUString sLogicalDocumentURL( i_SalvagedFile.isEmpty() ? i_SourceLocation : i_SalvagedFile );
+ impl_attachResource( sLogicalDocumentURL, aMediaDescriptor.getPropertyValues(), aGuard );
+ // <- SYNCHRONIZED
+ }
+ catch( const IOException& )
+ {
+ throw;
+ }
+ catch( const RuntimeException& )
+ {
+ throw;
+ }
+ catch( const WrappedTargetException& )
+ {
+ throw;
+ }
+ catch( const Exception& )
+ {
+ Any aError = ::cppu::getCaughtException();
+ throw WrappedTargetException( OUString(), *this, aError );
+ }
+}
+
+// XModel
+sal_Bool SAL_CALL ODatabaseDocument::attachResource( const OUString& _rURL, const Sequence< PropertyValue >& _rArguments )
+{
+ if (_rURL.isEmpty() && _rArguments.getLength() == 1 && _rArguments[0].Name == "SetEmbedded")
+ {
+ m_bEmbedded = true;
+ return true;
+ }
+
+ DocumentGuard aGuard( *this, DocumentGuard::MethodUsedDuringInit );
+ bool bRet = false;
+ try
+ {
+ bRet = impl_attachResource( _rURL, _rArguments, aGuard );
+ }
+ catch( const RuntimeException& )
+ {
+ throw;
+ }
+ catch( const Exception& )
+ {
+ Any aError = ::cppu::getCaughtException();
+ throw WrappedTargetRuntimeException( OUString(), *this, aError );
+ }
+ return bRet;
+}
+
+bool ODatabaseDocument::impl_attachResource( const OUString& i_rLogicalDocumentURL,
+ const Sequence< PropertyValue >& i_rMediaDescriptor, DocumentGuard& _rDocGuard )
+{
+ if (i_rLogicalDocumentURL == getURL())
+ {
+ ::comphelper::NamedValueCollection aArgs(i_rMediaDescriptor);
+
+ // this misuse of attachresource is a hack of the Basic importer code
+ // repurposing existing interfaces for uses it probably wasn't intended
+ // for
+
+ // we do not support macro signatures, so we can ignore that request
+ aArgs.remove("BreakMacroSignature");
+
+ bool bMacroEventRead = false;
+ if ((aArgs.get( "MacroEventRead" ) >>= bMacroEventRead) && bMacroEventRead)
+ m_pImpl->m_bMacroCallsSeenWhileLoading = true;
+ aArgs.remove( "MacroEventRead" );
+
+ if (aArgs.empty())
+ return false;
+ }
+
+ // if no URL has been provided, the caller was lazy enough to not call our getURL - which is not allowed anymore,
+ // now since getURL and getLocation both return the same, so calling one of those should be simple.
+ OUString sDocumentURL( i_rLogicalDocumentURL );
+ OSL_ENSURE( !sDocumentURL.isEmpty(), "ODatabaseDocument::impl_attachResource: invalid URL!" );
+ if ( sDocumentURL.isEmpty() )
+ sDocumentURL = getURL();
+
+ m_pImpl->setResource( sDocumentURL, i_rMediaDescriptor );
+
+ if ( impl_isInitializing() )
+ { // this means we've just been loaded, and this is the attachResource call which follows
+ // the load call.
+ impl_setInitialized();
+
+ // determine whether the document as a whole, or sub documents, have macros. Especially the latter
+ // controls the availability of our XEmbeddedScripts and XScriptInvocationContext interfaces, and we
+ // should know this before anybody actually uses the object.
+ m_bAllowDocumentScripting = ( m_pImpl->determineEmbeddedMacros() != ODatabaseModelImpl::eSubDocumentMacros );
+
+ _rDocGuard.clear();
+ // <- SYNCHRONIZED
+ m_aEventNotifier.notifyDocumentEvent( "OnLoadFinished" );
+ }
+
+ return true;
+}
+
+OUString SAL_CALL ODatabaseDocument::getURL( )
+{
+ DocumentGuard aGuard( *this, DocumentGuard::MethodWithoutInit );
+ return m_pImpl->getURL();
+}
+
+Sequence< PropertyValue > SAL_CALL ODatabaseDocument::getArgs( )
+{
+ DocumentGuard aGuard( *this, DocumentGuard::MethodWithoutInit );
+ return m_pImpl->getMediaDescriptor().getPropertyValues();
+}
+
+Sequence< PropertyValue > SAL_CALL ODatabaseDocument::getArgs2( const ::css::uno::Sequence< ::rtl::OUString >& requestedArgs )
+{
+ DocumentGuard aGuard( *this, DocumentGuard::MethodWithoutInit );
+ std::vector<PropertyValue> aRet;
+ for (const auto & rArgName : requestedArgs)
+ aRet.push_back(PropertyValue(rArgName, 0, m_pImpl->getMediaDescriptor().get(rArgName), PropertyState_DIRECT_VALUE));
+ return comphelper::containerToSequence(aRet);
+}
+
+void SAL_CALL ODatabaseDocument::setArgs(const Sequence<beans::PropertyValue>& /* aArgs */)
+{
+ throw NoSupportException();
+}
+
+void SAL_CALL ODatabaseDocument::connectController( const Reference< XController >& _xController )
+{
+ DocumentGuard aGuard(*this, DocumentGuard::DefaultMethod);
+
+#if OSL_DEBUG_LEVEL > 0
+ for (auto const& controller : m_aControllers)
+ {
+ OSL_ENSURE( controller != _xController, "ODatabaseDocument::connectController: this controller is already connected!" );
+ }
+#endif
+
+ m_aControllers.push_back( _xController );
+
+ m_aEventNotifier.notifyDocumentEventAsync( "OnViewCreated", Reference< XController2 >( _xController, UNO_QUERY ) );
+
+ bool bFirstControllerEver = m_aViewMonitor.onControllerConnected( _xController );
+ if ( !bFirstControllerEver )
+ return;
+
+ // check/adjust our macro mode.
+ m_pImpl->checkMacrosOnLoading();
+}
+
+void SAL_CALL ODatabaseDocument::disconnectController( const Reference< XController >& _xController )
+{
+ bool bNotifyViewClosed = false;
+ bool bLastControllerGone = false;
+ bool bIsClosing = false;
+
+ // SYNCHRONIZED ->
+ {
+ DocumentGuard aGuard(*this, DocumentGuard::DefaultMethod);
+
+ Controllers::iterator pos = std::find( m_aControllers.begin(), m_aControllers.end(), _xController );
+ OSL_ENSURE( pos != m_aControllers.end(), "ODatabaseDocument::disconnectController: don't know this controller!" );
+ if ( pos != m_aControllers.end() )
+ {
+ m_aControllers.erase( pos );
+ bNotifyViewClosed = true;
+ }
+
+ if ( m_xCurrentController == _xController )
+ m_xCurrentController = nullptr;
+
+ bLastControllerGone = m_aControllers.empty();
+ bIsClosing = m_bClosing;
+ }
+ // <- SYNCHRONIZED
+
+ if ( bNotifyViewClosed )
+ m_aEventNotifier.notifyDocumentEvent( "OnViewClosed", Reference< XController2 >( _xController, UNO_QUERY ) );
+
+ if ( !bLastControllerGone || bIsClosing )
+ return;
+
+ // if this was the last view, close the document as a whole
+ // #i51157#
+ try
+ {
+ close( true );
+ }
+ catch( const CloseVetoException& )
+ {
+ // okay, somebody vetoed and took ownership
+ }
+}
+
+void SAL_CALL ODatabaseDocument::lockControllers( )
+{
+ DocumentGuard aGuard(*this, DocumentGuard::DefaultMethod);
+
+ ++m_pImpl->m_nControllerLockCount;
+}
+
+void SAL_CALL ODatabaseDocument::unlockControllers( )
+{
+ DocumentGuard aGuard(*this, DocumentGuard::DefaultMethod);
+
+ --m_pImpl->m_nControllerLockCount;
+}
+
+sal_Bool SAL_CALL ODatabaseDocument::hasControllersLocked( )
+{
+ DocumentGuard aGuard(*this, DocumentGuard::DefaultMethod);
+
+ return m_pImpl->m_nControllerLockCount != 0;
+}
+
+Reference< XController > SAL_CALL ODatabaseDocument::getCurrentController()
+{
+ DocumentGuard aGuard(*this, DocumentGuard::DefaultMethod);
+
+ return m_xCurrentController.is() ? m_xCurrentController : ( m_aControllers.empty() ? Reference< XController >() : *m_aControllers.begin() );
+}
+
+void SAL_CALL ODatabaseDocument::setCurrentController( const Reference< XController >& _xController )
+{
+ DocumentGuard aGuard(*this, DocumentGuard::DefaultMethod);
+
+ m_xCurrentController = _xController;
+
+ if ( !m_aViewMonitor.onSetCurrentController( _xController ) )
+ return;
+
+ // check if there are sub components to recover from our document storage
+ bool bAttemptRecovery = m_bHasBeenRecovered;
+ if ( !bAttemptRecovery && m_pImpl->getMediaDescriptor().has( "ForceRecovery" ) )
+ // do not use getOrDefault, it will throw for invalid types, which is not desired here
+ m_pImpl->getMediaDescriptor().get( "ForceRecovery" ) >>= bAttemptRecovery;
+
+ if ( !bAttemptRecovery )
+ return;
+
+ try
+ {
+ DatabaseDocumentRecovery aDocRecovery( m_pImpl->m_aContext );
+ aDocRecovery.recoverSubDocuments( m_pImpl->getRootStorage(), _xController );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+}
+
+Reference< XInterface > SAL_CALL ODatabaseDocument::getCurrentSelection( )
+{
+ DocumentGuard aGuard(*this, DocumentGuard::DefaultMethod);
+
+ Reference< XInterface > xRet;
+ Reference< XSelectionSupplier > xDocView( getCurrentController(), UNO_QUERY );
+ if ( xDocView.is() )
+ xRet.set(xDocView->getSelection(),UNO_QUERY);
+
+ return xRet;
+}
+
+// XStorable
+sal_Bool SAL_CALL ODatabaseDocument::hasLocation( )
+{
+ return !getLocation().isEmpty();
+}
+
+OUString SAL_CALL ODatabaseDocument::getLocation( )
+{
+ DocumentGuard aGuard( *this, DocumentGuard::MethodWithoutInit );
+ return m_pImpl->getURL();
+ // both XStorable::getLocation and XModel::getURL have to return the URL of the document, *not*
+ // the location of the file which the document was possibly recovered from (which would be getDocFileLocation)
+}
+
+sal_Bool SAL_CALL ODatabaseDocument::isReadonly( )
+{
+ DocumentGuard aGuard( *this, DocumentGuard::MethodWithoutInit );
+ return m_pImpl->m_bDocumentReadOnly;
+}
+
+void SAL_CALL ODatabaseDocument::store( )
+{
+ DocumentGuard aGuard(*this, DocumentGuard::DefaultMethod);
+
+ OUString sDocumentURL( m_pImpl->getURL() );
+ if ( !sDocumentURL.isEmpty() )
+ {
+ if ( m_pImpl->getDocFileLocation() == m_pImpl->getURL() )
+ if ( m_pImpl->m_bDocumentReadOnly )
+ throw IOException();
+
+ impl_storeAs_throw( m_pImpl->getURL(), m_pImpl->getMediaDescriptor(), SAVE, aGuard );
+ return;
+ }
+
+ // if we have no URL, but did survive the DocumentGuard above, then we've been inited via XLoadable::initNew,
+ // i.e. we're based on a temporary storage
+ OSL_ENSURE( m_pImpl->getDocFileLocation().isEmpty(), "ODatabaseDocument::store: unexpected URL inconsistency!" );
+
+ try
+ {
+ impl_storeToStorage_throw( m_pImpl->getRootStorage(), m_pImpl->getMediaDescriptor().getPropertyValues(), aGuard );
+ }
+ catch( const Exception& )
+ {
+ Any aError = ::cppu::getCaughtException();
+ if ( aError.isExtractableTo( ::cppu::UnoType< IOException >::get() )
+ || aError.isExtractableTo( ::cppu::UnoType< RuntimeException >::get() )
+ )
+ {
+ // allowed to leave
+ throw;
+ }
+ impl_throwIOExceptionCausedBySave_throw( aError, {} );
+ }
+}
+
+void ODatabaseDocument::impl_throwIOExceptionCausedBySave_throw( const Any& i_rError, std::u16string_view i_rTargetURL ) const
+{
+ OUString sErrorMessage = extractExceptionMessage( m_pImpl->m_aContext, i_rError );
+ sErrorMessage = ResourceManager::loadString(
+ RID_STR_ERROR_WHILE_SAVING,
+ "$location$", i_rTargetURL,
+ "$message$", sErrorMessage
+ );
+ throw IOException( sErrorMessage, *const_cast< ODatabaseDocument* >( this ) );
+}
+
+void ODatabaseDocument::impl_storeAs_throw( const OUString& _rURL, const ::comphelper::NamedValueCollection& _rArguments,
+ const StoreType _eType, DocumentGuard& _rGuard )
+{
+ OSL_PRECOND( ( _eType == SAVE ) || ( _eType == SAVE_AS ),
+ "ODatabaseDocument::impl_storeAs_throw: you introduced a new type which cannot be handled here!" );
+
+ // if we're in the process of initializing the document (which effectively means it is an implicit
+ // initialization triggered in storeAsURL), the we do not notify events, since to an observer, the SaveAs
+ // should not be noticeable
+ bool bIsInitializationProcess = impl_isInitializing();
+
+ if ( !bIsInitializationProcess )
+ {
+ _rGuard.clear();
+ m_aEventNotifier.notifyDocumentEvent( _eType == SAVE ? "OnSave" : "OnSaveAs", nullptr, Any( _rURL ) );
+ _rGuard.reset();
+ }
+
+ Reference< XStorage > xNewRootStorage;
+ // will be non-NULL if our storage changed
+
+ try
+ {
+ ModifyLock aLock( *this );
+ // ignore all changes of our "modified" state during storing
+
+ bool bLocationChanged = ( _rURL != m_pImpl->getDocFileLocation() );
+ if ( bLocationChanged )
+ {
+ // create storage for target URL
+ uno::Reference<embed::XStorage> xTargetStorage(
+ impl_GetStorageOrCreateFor_throw(_rArguments, _rURL));
+
+ if ( m_pImpl->isEmbeddedDatabase() )
+ m_pImpl->clearConnections();
+
+ // commit everything
+ m_pImpl->commitEmbeddedStorage();
+ m_pImpl->commitStorages();
+
+ // copy own storage to target storage
+ Reference< XStorage > xCurrentStorage( m_pImpl->getRootStorage() );
+ if ( xCurrentStorage.is() )
+ xCurrentStorage->copyToStorage( xTargetStorage );
+
+ m_pImpl->disposeStorages();
+
+ // each and every document definition obtained via m_xForms and m_xReports depends
+ // on the sub storages which we just disposed. So, dispose the forms/reports collections, too.
+ // This ensures that they're re-created when needed.
+ clearObjectContainer( m_xForms );
+ clearObjectContainer( m_xReports );
+
+ xNewRootStorage = m_pImpl->switchToStorage( xTargetStorage );
+
+ m_pImpl->m_bDocumentReadOnly = false;
+ }
+
+ // store to current storage
+ Reference< XStorage > xCurrentStorage( m_pImpl->getOrCreateRootStorage(), UNO_SET_THROW );
+ Sequence< PropertyValue > aMediaDescriptor( lcl_appendFileNameToDescriptor( _rArguments, _rURL ) );
+ impl_storeToStorage_throw( xCurrentStorage, aMediaDescriptor, _rGuard );
+
+ // success - tell our impl
+ m_pImpl->setDocFileLocation( _rURL );
+ m_pImpl->setResource( _rURL, aMediaDescriptor );
+
+ // if we are in an initialization process, then this is finished, now that we stored the document
+ if ( bIsInitializationProcess )
+ impl_setInitialized();
+ }
+ catch( const IOException& )
+ {
+ if ( !bIsInitializationProcess )
+ m_aEventNotifier.notifyDocumentEventAsync( _eType == SAVE ? "OnSaveFailed" : "OnSaveAsFailed", nullptr, Any( _rURL ) );
+ throw;
+ }
+ catch( const RuntimeException& )
+ {
+ if ( !bIsInitializationProcess )
+ m_aEventNotifier.notifyDocumentEventAsync( _eType == SAVE ? "OnSaveFailed" : "OnSaveAsFailed", nullptr, Any( _rURL ) );
+ throw;
+ }
+ catch( const Exception& )
+ {
+ Any aError = ::cppu::getCaughtException();
+
+ // notify the failure
+ if ( !bIsInitializationProcess )
+ m_aEventNotifier.notifyDocumentEventAsync( _eType == SAVE ? "OnSaveFailed" : "OnSaveAsFailed", nullptr, Any( _rURL ) );
+
+ impl_throwIOExceptionCausedBySave_throw( aError, _rURL );
+ }
+
+ // notify the document event
+ if ( !bIsInitializationProcess )
+ m_aEventNotifier.notifyDocumentEventAsync( _eType == SAVE ? "OnSaveDone" : "OnSaveAsDone", nullptr, Any( _rURL ) );
+
+ // reset our "modified" flag, and clear the guard
+ impl_setModified_nothrow( false, _rGuard );
+ // <- SYNCHRONIZED
+
+ // notify storage listeners
+ if ( xNewRootStorage.is() )
+ impl_notifyStorageChange_nolck_nothrow( xNewRootStorage );
+}
+
+Reference< XStorage > ODatabaseDocument::impl_createStorageFor_throw( const OUString& _rURL ) const
+{
+ Reference< ucb::XSimpleFileAccess3 > xTempAccess(ucb::SimpleFileAccess::create(m_pImpl->m_aContext));
+ Reference< io::XStream > xStream = xTempAccess->openFileReadWrite( _rURL );
+ Reference< io::XTruncate > xTruncate(xStream,UNO_QUERY);
+ if ( xTruncate.is() )
+ {
+ xTruncate->truncate();
+ }
+ Sequence<Any> aParam{ Any(xStream), Any(ElementModes::READWRITE | ElementModes::TRUNCATE) };
+
+ Reference< XSingleServiceFactory > xStorageFactory( m_pImpl->createStorageFactory(), UNO_SET_THROW );
+ return Reference< XStorage >( xStorageFactory->createInstanceWithArguments( aParam ), UNO_QUERY_THROW );
+}
+
+css::uno::Reference<css::embed::XStorage> ODatabaseDocument::impl_GetStorageOrCreateFor_throw(
+ const ::comphelper::NamedValueCollection& _rArguments, const OUString& _rURL) const
+{
+ // Try to get the storage from arguments, then create storage for target URL
+ uno::Reference<embed::XStorage> xTargetStorage;
+ _rArguments.get("TargetStorage") >>= xTargetStorage;
+ if (!xTargetStorage.is())
+ xTargetStorage = impl_createStorageFor_throw(_rURL);
+
+ // In case we got a StreamRelPath, then xTargetStorage should reference that sub-storage.
+ OUString sStreamRelPath = _rArguments.getOrDefault("StreamRelPath", OUString());
+ if (!sStreamRelPath.isEmpty())
+ xTargetStorage
+ = xTargetStorage->openStorageElement(sStreamRelPath, embed::ElementModes::READWRITE);
+
+ return xTargetStorage;
+}
+
+void SAL_CALL ODatabaseDocument::storeAsURL( const OUString& _rURL, const Sequence< PropertyValue >& _rArguments )
+{
+ // SYNCHRONIZED ->
+ DocumentGuard aGuard( *this, DocumentGuard::MethodWithoutInit );
+
+ // Normally, a document initialization is done via XLoadable::load or XLoadable::initNew. For convenience
+ // reasons, and to not break existing API clients, it's allowed to call storeAsURL without having initialized
+ // the document, in which case the initialization will be done implicitly.
+ bool bImplicitInitialization = !impl_isInitialized();
+ // implicit initialization while another initialization is just running is not possible
+ if ( bImplicitInitialization && impl_isInitializing() )
+ throw RuntimeException();
+
+ if ( bImplicitInitialization )
+ impl_setInitializing();
+
+ try
+ {
+ impl_storeAs_throw( _rURL, _rArguments, SAVE_AS, aGuard );
+ // <- SYNCHRONIZED
+
+ // impl_storeAs_throw cleared the lock on our mutex, but the below lines need this lock
+ // SYNCHRONIZED ->
+ aGuard.reset();
+
+ // our title might have changed, potentially at least
+ // Sadly, we cannot check this: Calling getTitle here and now would not deliver
+ // an up-to-date result, as the call is delegated to our TitleHelper instance, which itself
+ // updates its title only if it gets the OnSaveAsDone event (which was sent asynchronously
+ // by impl_storeAs_throw). So, we simply notify always, and also asynchronously
+ m_aEventNotifier.notifyDocumentEventAsync( "OnTitleChanged" );
+ }
+ catch( const Exception& )
+ {
+ impl_reset_nothrow();
+ throw;
+ }
+
+ if ( bImplicitInitialization )
+ m_bAllowDocumentScripting = true;
+
+ aGuard.clear();
+ // <- SYNCHRONIZED
+
+ if ( bImplicitInitialization )
+ m_aEventNotifier.notifyDocumentEvent( "OnCreate" );
+}
+
+void ODatabaseDocument::impl_storeToStorage_throw( const Reference< XStorage >& _rxTargetStorage, const Sequence< PropertyValue >& _rMediaDescriptor,
+ DocumentGuard& _rDocGuard ) const
+{
+ if ( !_rxTargetStorage.is() )
+ throw IllegalArgumentException( OUString(), *const_cast< ODatabaseDocument* >( this ), 1 );
+
+ if ( !m_pImpl.is() )
+ throw DisposedException( OUString(), *const_cast< ODatabaseDocument* >( this ) );
+
+ try
+ {
+ // commit everything
+ m_pImpl->commitEmbeddedStorage();
+ m_pImpl->commitStorages();
+
+ // copy own storage to target storage
+ if ( impl_isInitialized() )
+ {
+ Reference< XStorage > xCurrentStorage = m_pImpl->getOrCreateRootStorage();
+ // Root storage may be empty in case of embedding.
+ if ( xCurrentStorage.is() && xCurrentStorage != _rxTargetStorage )
+ xCurrentStorage->copyToStorage( _rxTargetStorage );
+ }
+
+ // write into target storage
+ ::comphelper::NamedValueCollection aWriteArgs( _rMediaDescriptor );
+ lcl_triggerStatusIndicator_throw( aWriteArgs, _rDocGuard, true );
+ impl_writeStorage_throw( _rxTargetStorage, aWriteArgs );
+ lcl_triggerStatusIndicator_throw( aWriteArgs, _rDocGuard, false );
+
+ // commit target storage
+ m_pImpl->commitStorageIfWriteable_ignoreErrors(_rxTargetStorage);
+ }
+ catch( const IOException& ) { throw; }
+ catch( const RuntimeException& ) { throw; }
+ catch ( const Exception& e )
+ {
+ throw IOException( e.Message, *const_cast< ODatabaseDocument* >( this ) );
+ }
+}
+
+void SAL_CALL ODatabaseDocument::storeToURL( const OUString& _rURL, const Sequence< PropertyValue >& _rArguments )
+{
+ DocumentGuard aGuard(*this, DocumentGuard::DefaultMethod);
+ ModifyLock aLock( *this );
+
+ {
+ aGuard.clear();
+ m_aEventNotifier.notifyDocumentEvent( "OnSaveTo", nullptr, Any( _rURL ) );
+ aGuard.reset();
+ }
+
+ try
+ {
+ const ::comphelper::NamedValueCollection aArguments(_rArguments);
+ // create storage for target URL
+ Reference<XStorage> xTargetStorage(impl_GetStorageOrCreateFor_throw(aArguments, _rURL));
+
+ // extend media descriptor with URL
+ Sequence<PropertyValue> aMediaDescriptor(lcl_appendFileNameToDescriptor(aArguments, _rURL));
+
+ // store to this storage
+ impl_storeToStorage_throw( xTargetStorage, aMediaDescriptor, aGuard );
+ }
+ catch( const Exception& )
+ {
+ Any aError = ::cppu::getCaughtException();
+ m_aEventNotifier.notifyDocumentEventAsync( "OnSaveToFailed", nullptr, aError );
+
+ if ( aError.isExtractableTo( ::cppu::UnoType< IOException >::get() )
+ || aError.isExtractableTo( ::cppu::UnoType< RuntimeException >::get() )
+ )
+ {
+ // allowed to leave
+ throw;
+ }
+
+ impl_throwIOExceptionCausedBySave_throw( aError, _rURL );
+ }
+
+ m_aEventNotifier.notifyDocumentEventAsync( "OnSaveToDone", nullptr, Any( _rURL ) );
+}
+
+// XModifyBroadcaster
+void SAL_CALL ODatabaseDocument::addModifyListener( const Reference< XModifyListener >& _xListener )
+{
+ DocumentGuard aGuard(*this, DocumentGuard::DefaultMethod);
+ m_aModifyListeners.addInterface(_xListener);
+}
+
+void SAL_CALL ODatabaseDocument::removeModifyListener( const Reference< XModifyListener >& _xListener )
+{
+ DocumentGuard aGuard(*this, DocumentGuard::DefaultMethod);
+ m_aModifyListeners.removeInterface(_xListener);
+}
+
+// XModifiable
+sal_Bool SAL_CALL ODatabaseDocument::isModified( )
+{
+ DocumentGuard aGuard(*this, DocumentGuard::DefaultMethod);
+
+ return m_pImpl->m_bModified;
+}
+
+void SAL_CALL ODatabaseDocument::setModified( sal_Bool _bModified )
+{
+ DocumentGuard aGuard( *this, DocumentGuard::MethodWithoutInit );
+ if ( impl_isInitialized() )
+ impl_setModified_nothrow( _bModified, aGuard );
+ // it's allowed to call setModified without the document being initialized already. In this case,
+ // we simply ignore the call - when the initialization is finished, the respective code will set
+ // a proper "modified" flag
+}
+
+void ODatabaseDocument::impl_setModified_nothrow( bool _bModified, DocumentGuard& _rGuard )
+{
+ // SYNCHRONIZED ->
+ bool bModifiedChanged = ( m_pImpl->m_bModified != _bModified ) && ( !m_pImpl->isModifyLocked() );
+
+ if ( bModifiedChanged )
+ {
+ m_pImpl->m_bModified = _bModified;
+ m_aEventNotifier.notifyDocumentEventAsync( "OnModifyChanged" );
+ }
+ _rGuard.clear();
+ // <- SYNCHRONIZED
+
+ if ( bModifiedChanged )
+ {
+ lang::EventObject aEvent( *this );
+ m_aModifyListeners.notifyEach( &XModifyListener::modified, aEvent );
+ }
+}
+
+// css::document::XEventBroadcaster
+void SAL_CALL ODatabaseDocument::addEventListener(const uno::Reference< document::XEventListener >& Listener )
+{
+ m_aEventNotifier.addLegacyEventListener( Listener );
+}
+
+void SAL_CALL ODatabaseDocument::removeEventListener( const uno::Reference< document::XEventListener >& Listener )
+{
+ m_aEventNotifier.removeLegacyEventListener( Listener );
+}
+
+void SAL_CALL ODatabaseDocument::addDocumentEventListener( const Reference< XDocumentEventListener >& Listener )
+{
+ m_aEventNotifier.addDocumentEventListener( Listener );
+}
+
+void SAL_CALL ODatabaseDocument::removeDocumentEventListener( const Reference< XDocumentEventListener >& Listener )
+{
+ m_aEventNotifier.removeDocumentEventListener( Listener );
+}
+
+void SAL_CALL ODatabaseDocument::notifyDocumentEvent( const OUString& EventName, const Reference< XController2 >& ViewController, const Any& Supplement )
+{
+ if ( EventName.isEmpty() )
+ throw IllegalArgumentException( OUString(), *this, 1 );
+
+ // SYNCHRONIZED ->
+ DocumentGuard aGuard(*this, DocumentGuard::DefaultMethod);
+
+ if ( !DocumentEvents::needsSynchronousNotification( EventName ) )
+ {
+ m_aEventNotifier.notifyDocumentEventAsync( EventName, ViewController, Supplement );
+ return;
+ }
+ aGuard.clear();
+ // <- SYNCHRONIZED
+
+ m_aEventNotifier.notifyDocumentEvent( EventName, ViewController, Supplement );
+}
+
+Sequence< PropertyValue > SAL_CALL ODatabaseDocument::getPrinter( )
+{
+ OSL_FAIL( "ODatabaseDocument::getPrinter: not supported!" );
+ return Sequence< PropertyValue >();
+}
+
+void SAL_CALL ODatabaseDocument::setPrinter( const Sequence< PropertyValue >& /*aPrinter*/ )
+{
+ OSL_FAIL( "ODatabaseDocument::setPrinter: not supported!" );
+}
+
+void SAL_CALL ODatabaseDocument::print( const Sequence< PropertyValue >& /*xOptions*/ )
+{
+ OSL_FAIL( "ODatabaseDocument::print: not supported!" );
+}
+
+void ODatabaseDocument::impl_reparent_nothrow( const WeakReference< XNameAccess >& _rxContainer )
+{
+ Reference< XChild > xChild( _rxContainer.get(), UNO_QUERY );
+ if ( xChild.is() )
+ xChild->setParent( *this );
+}
+
+void ODatabaseDocument::clearObjectContainer( WeakReference< XNameAccess >& _rxContainer)
+{
+ Reference< XNameAccess > xContainer = _rxContainer;
+ ::comphelper::disposeComponent( xContainer );
+
+ Reference< XChild > xChild( _rxContainer.get(),UNO_QUERY );
+ if ( xChild.is() )
+ xChild->setParent( nullptr );
+ _rxContainer.clear();
+}
+
+Reference< XNameAccess > ODatabaseDocument::impl_getDocumentContainer_throw( ODatabaseModelImpl::ObjectType _eType )
+{
+ if ( ( _eType != ODatabaseModelImpl::E_FORM ) && ( _eType != ODatabaseModelImpl::E_REPORT ) )
+ throw IllegalArgumentException();
+
+ bool bFormsContainer = _eType == ODatabaseModelImpl::E_FORM;
+
+ WeakReference< XNameAccess >& rContainerRef( bFormsContainer ? m_xForms : m_xReports );
+ Reference< XNameAccess > xContainer = rContainerRef;
+ if ( !xContainer.is() )
+ {
+ Any aValue;
+ css::uno::Reference< css::uno::XInterface > xMy(*this);
+ if ( dbtools::getDataSourceSetting(xMy,bFormsContainer ? "Forms" : "Reports",aValue) )
+ {
+ OUString sSupportService;
+ aValue >>= sSupportService;
+ if ( !sSupportService.isEmpty() )
+ {
+ Sequence<Any> aArgs{ Any(NamedValue("DatabaseDocument",Any(xMy))) };
+ xContainer.set(
+ m_pImpl->m_aContext->getServiceManager()->createInstanceWithArgumentsAndContext(sSupportService, aArgs, m_pImpl->m_aContext),
+ UNO_QUERY);
+ rContainerRef = xContainer;
+ }
+ }
+ if ( !xContainer.is() )
+ {
+ TContentPtr& rContainerData( m_pImpl->getObjectContainer( _eType ) );
+ rContainerRef = xContainer = new ODocumentContainer( m_pImpl->m_aContext, *this, rContainerData, bFormsContainer );
+ }
+ impl_reparent_nothrow( xContainer );
+ }
+ return xContainer;
+}
+
+void ODatabaseDocument::impl_closeControllerFrames_nolck_throw( bool _bDeliverOwnership )
+{
+ Controllers aCopy = m_aControllers;
+
+ for (auto const& elem : aCopy)
+ {
+ if ( !elem.is() )
+ continue;
+
+ try
+ {
+ Reference< XCloseable> xFrame( elem->getFrame(), UNO_QUERY );
+ if ( xFrame.is() )
+ xFrame->close( _bDeliverOwnership );
+ }
+ catch( const CloseVetoException& ) { throw; }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+}
+
+void ODatabaseDocument::impl_disposeControllerFrames_nothrow()
+{
+ Controllers aCopy;
+ aCopy.swap( m_aControllers ); // ensure m_aControllers is empty afterwards
+ for( const auto& rController : aCopy )
+ {
+ try
+ {
+ if( rController.is() )
+ {
+ Reference< XFrame > xFrame( rController->getFrame() );
+ ::comphelper::disposeComponent( xFrame );
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+}
+
+void SAL_CALL ODatabaseDocument::close(sal_Bool bDeliverOwnership)
+{
+ // nearly everything below can/must be done without our mutex locked, the below is just for
+ // the checks for being disposed and the like
+ // SYNCHRONIZED ->
+ {
+ DocumentGuard aGuard(*this, DocumentGuard::DefaultMethod);
+ assert (!m_bClosing);
+ m_bClosing = true;
+ }
+ // <- SYNCHRONIZED
+
+ try
+ {
+ // allow listeners to veto
+ lang::EventObject aEvent( *this );
+ m_aCloseListener.forEach(
+ [&aEvent, &bDeliverOwnership] (uno::Reference<XCloseListener> const& xListener) {
+ return xListener->queryClosing(aEvent, bDeliverOwnership);
+ });
+
+ // notify that we're going to unload
+ m_aEventNotifier.notifyDocumentEvent( "OnPrepareUnload" );
+
+ impl_closeControllerFrames_nolck_throw( bDeliverOwnership );
+
+ m_aCloseListener.notifyEach( &XCloseListener::notifyClosing, const_cast<const lang::EventObject&>(aEvent) );
+
+ dispose();
+ }
+ catch ( const Exception& )
+ {
+ SolarMutexGuard g;
+ m_bClosing = false;
+ throw;
+ }
+
+ // SYNCHRONIZED ->
+ SolarMutexGuard g;
+ m_bClosing = false;
+ // <- SYNCHRONIZED
+}
+
+void SAL_CALL ODatabaseDocument::addCloseListener( const Reference< css::util::XCloseListener >& Listener )
+{
+ DocumentGuard aGuard(*this, DocumentGuard::DefaultMethod);
+ m_aCloseListener.addInterface(Listener);
+}
+
+void SAL_CALL ODatabaseDocument::removeCloseListener( const Reference< css::util::XCloseListener >& Listener )
+{
+ DocumentGuard aGuard(*this, DocumentGuard::DefaultMethod);
+ m_aCloseListener.removeInterface(Listener);
+}
+
+Reference< XNameAccess > SAL_CALL ODatabaseDocument::getFormDocuments( )
+{
+ DocumentGuard aGuard( *this, DocumentGuard::MethodUsedDuringInit );
+ return impl_getDocumentContainer_throw( ODatabaseModelImpl::E_FORM );
+}
+
+Reference< XNameAccess > SAL_CALL ODatabaseDocument::getReportDocuments( )
+{
+ DocumentGuard aGuard( *this, DocumentGuard::MethodUsedDuringInit );
+ return impl_getDocumentContainer_throw( ODatabaseModelImpl::E_REPORT );
+}
+
+void ODatabaseDocument::WriteThroughComponent( const Reference< XComponent >& xComponent, const char* pStreamName,
+ const char* pServiceName, const Sequence< Any >& _rArguments, const Sequence< PropertyValue >& rMediaDesc,
+ const Reference<XStorage>& _xStorageToSaveTo ) const
+{
+ OSL_ENSURE( pStreamName, "Need stream name!" );
+ OSL_ENSURE( pServiceName, "Need service name!" );
+
+ // open stream
+ OUString sStreamName = OUString::createFromAscii( pStreamName );
+ Reference< XStream > xStream = _xStorageToSaveTo->openStreamElement( sStreamName, ElementModes::READWRITE | ElementModes::TRUNCATE );
+ if ( !xStream.is() )
+ return;
+
+ Reference< XOutputStream > xOutputStream( xStream->getOutputStream() );
+ OSL_ENSURE( xOutputStream.is(), "Can't create output stream in package!" );
+ if ( !xOutputStream.is() )
+ return;
+
+ Reference< XSeekable > xSeek( xOutputStream, UNO_QUERY );
+ if ( xSeek.is() )
+ xSeek->seek(0);
+
+ Reference< XPropertySet > xStreamProp( xOutputStream, UNO_QUERY_THROW );
+ xStreamProp->setPropertyValue( INFO_MEDIATYPE, Any( OUString( "text/xml" ) ) );
+ xStreamProp->setPropertyValue( "Compressed", Any( true ) );
+
+ // write the stuff
+ WriteThroughComponent( xOutputStream, xComponent, pServiceName, _rArguments, rMediaDesc );
+}
+
+void ODatabaseDocument::WriteThroughComponent( const Reference< XOutputStream >& xOutputStream,
+ const Reference< XComponent >& xComponent, const char* pServiceName, const Sequence< Any >& _rArguments,
+ const Sequence< PropertyValue >& rMediaDesc ) const
+{
+ OSL_ENSURE( xOutputStream.is(), "I really need an output stream!" );
+ OSL_ENSURE( xComponent.is(), "Need component!" );
+ OSL_ENSURE( nullptr != pServiceName, "Need component name!" );
+
+ // get component
+ Reference< XWriter > xSaxWriter = xml::sax::Writer::create( m_pImpl->m_aContext );
+
+ // connect XML writer to output stream
+ xSaxWriter->setOutputStream( xOutputStream );
+
+ // prepare arguments (prepend doc handler to given arguments)
+ Sequence<Any> aArgs( 1 + _rArguments.getLength() );
+ auto pArgs = aArgs.getArray();
+ pArgs[0] <<= xSaxWriter;
+ for ( sal_Int32 i = 0; i < _rArguments.getLength(); ++i )
+ pArgs[ i+1 ] = _rArguments[i];
+
+ // get filter component
+ Reference< XExporter > xExporter( m_pImpl->m_aContext->getServiceManager()->createInstanceWithArgumentsAndContext(OUString::createFromAscii(pServiceName), aArgs, m_pImpl->m_aContext), UNO_QUERY_THROW );
+
+ // connect model and filter
+ xExporter->setSourceDocument( xComponent );
+
+ // filter
+ Reference< XFilter > xFilter( xExporter, UNO_QUERY_THROW );
+ xFilter->filter( rMediaDesc );
+}
+
+void ODatabaseDocument::impl_writeStorage_throw( const Reference< XStorage >& _rxTargetStorage, const ::comphelper::NamedValueCollection& _rMediaDescriptor ) const
+{
+ // extract status indicator
+ Sequence< Any > aDelegatorArguments;
+ lcl_extractStatusIndicator( _rMediaDescriptor, aDelegatorArguments );
+
+ uno::Reference< beans::XPropertySet > xInfoSet( comphelper::GenericPropertySet_CreateInstance( new comphelper::PropertySetInfo( aExportInfoMap ) ) );
+
+ xInfoSet->setPropertyValue("UsePrettyPrinting", uno::Any(officecfg::Office::Common::Save::Document::PrettyPrinting::get()));
+ if ( officecfg::Office::Common::Save::URL::FileSystem::get() )
+ {
+ OUString sBaseURI = _rMediaDescriptor.getOrDefault("BaseURI", OUString());
+ if (sBaseURI.isEmpty())
+ sBaseURI = _rMediaDescriptor.getOrDefault("URL",OUString());
+ xInfoSet->setPropertyValue("BaseURI", uno::Any(sBaseURI));
+ }
+
+ // Set TargetStorage, so it doesn't have to be re-constructed based on possibly empty URL.
+ xInfoSet->setPropertyValue("TargetStorage", uno::Any(m_pImpl->getRootStorage()));
+
+ // Set StreamRelPath, in case this document is an embedded one.
+ OUString sStreamRelPath;
+ OUString sURL = _rMediaDescriptor.getOrDefault("URL", OUString());
+ if (sURL.startsWithIgnoreAsciiCase("vnd.sun.star.pkg:"))
+ {
+ // In this case the host contains the real path, and the path is the embedded stream name.
+ INetURLObject aURL(sURL);
+ sStreamRelPath = aURL.GetURLPath(INetURLObject::DecodeMechanism::WithCharset);
+ if (sStreamRelPath.startsWith("/"))
+ sStreamRelPath = sStreamRelPath.copy(1);
+ }
+ if (!sStreamRelPath.isEmpty())
+ xInfoSet->setPropertyValue("StreamRelPath", uno::Any(sStreamRelPath));
+
+ sal_Int32 nArgsLen = aDelegatorArguments.getLength();
+ aDelegatorArguments.realloc(nArgsLen+1);
+ aDelegatorArguments.getArray()[nArgsLen++] <<= xInfoSet;
+
+ Reference< XPropertySet > xProp( _rxTargetStorage, UNO_QUERY_THROW );
+ xProp->setPropertyValue( INFO_MEDIATYPE, Any( OUString(MIMETYPE_OASIS_OPENDOCUMENT_DATABASE_ASCII) ) );
+
+ OUString aVersion;
+ SvtSaveOptions::ODFSaneDefaultVersion const nDefVersion =
+ GetODFSaneDefaultVersion();
+ // older versions can not have this property set,
+ // it exists only starting from ODF1.2
+ if (nDefVersion >= SvtSaveOptions::ODFSVER_013)
+ {
+ aVersion = ODFVER_013_TEXT;
+ }
+ else if (nDefVersion >= SvtSaveOptions::ODFSVER_012)
+ {
+ aVersion = ODFVER_012_TEXT;
+ }
+
+ if (!aVersion.isEmpty())
+ {
+ try
+ {
+ xProp->setPropertyValue("Version" , uno::Any(aVersion));
+ }
+ catch (const uno::Exception&)
+ {
+ TOOLS_WARN_EXCEPTION("dbaccess", "exception setting Version");
+ }
+ }
+
+ Reference< XComponent > xComponent( *const_cast< ODatabaseDocument* >( this ), UNO_QUERY_THROW );
+
+ Sequence< PropertyValue > aMediaDescriptor;
+ _rMediaDescriptor >>= aMediaDescriptor;
+
+ xInfoSet->setPropertyValue("StreamName", uno::Any(OUString("settings.xml")));
+ WriteThroughComponent( xComponent, "settings.xml", "com.sun.star.comp.sdb.XMLSettingsExporter",
+ aDelegatorArguments, aMediaDescriptor, _rxTargetStorage );
+
+ xInfoSet->setPropertyValue("StreamName", uno::Any(OUString("content.xml")));
+ WriteThroughComponent( xComponent, "content.xml", "com.sun.star.comp.sdb.DBExportFilter",
+ aDelegatorArguments, aMediaDescriptor, _rxTargetStorage );
+
+ if ( _rxTargetStorage->hasByName ( sPictures ) )
+ {
+ try
+ {
+ // Delete any previously existing Pictures folder and regenerate
+ // any needed content if needed
+ Reference< XStorageBasedLibraryContainer > xDlgs = m_pImpl->getLibraryContainer( false );
+ if ( xDlgs.is() )
+ {
+ Reference< XModel > xModel(const_cast< ODatabaseDocument*>(this));
+ lcl_uglyHackToStoreDialogeEmbedImages( m_pImpl->getLibraryContainer(false), _rxTargetStorage, xModel, m_pImpl->m_aContext );
+ }
+ }
+ catch ( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+ m_pImpl->storeLibraryContainersTo( _rxTargetStorage );
+}
+
+Reference< XUIConfigurationManager > SAL_CALL ODatabaseDocument::getUIConfigurationManager( )
+{
+ return Reference< XUIConfigurationManager >( getUIConfigurationManager2(), UNO_QUERY_THROW );
+}
+
+Reference< XUIConfigurationManager2 > const & ODatabaseDocument::getUIConfigurationManager2( )
+{
+ DocumentGuard aGuard(*this, DocumentGuard::DefaultMethod);
+
+ if ( !m_xUIConfigurationManager.is() )
+ {
+ m_xUIConfigurationManager = UIConfigurationManager::create( m_pImpl->m_aContext );
+
+ OUString aUIConfigFolderName( "Configurations2" );
+
+ // First try to open with READWRITE and then READ
+ Reference< XStorage > xConfigStorage = getDocumentSubStorage( aUIConfigFolderName, ElementModes::READWRITE );
+ if ( xConfigStorage.is() )
+ {
+ OUString aMediaType;
+ Reference< XPropertySet > xPropSet( xConfigStorage, UNO_QUERY );
+ Any a = xPropSet->getPropertyValue( INFO_MEDIATYPE );
+ if ( !( a >>= aMediaType ) || aMediaType.isEmpty() )
+ {
+ a <<= OUString("application/vnd.sun.xml.ui.configuration");
+ xPropSet->setPropertyValue( INFO_MEDIATYPE, a );
+ }
+ }
+ else
+ xConfigStorage = getDocumentSubStorage( aUIConfigFolderName, ElementModes::READ );
+
+ // initialize ui configuration manager with document substorage
+ m_xUIConfigurationManager->setStorage( xConfigStorage );
+ }
+
+ return m_xUIConfigurationManager;
+}
+
+Reference< XStorage > SAL_CALL ODatabaseDocument::getDocumentSubStorage( const OUString& aStorageName, sal_Int32 nMode )
+{
+ DocumentGuard aGuard(*this, DocumentGuard::DefaultMethod);
+
+ Reference< XDocumentSubStorageSupplier > xStorageAccess( m_pImpl->getDocumentSubStorageSupplier() );
+ return xStorageAccess->getDocumentSubStorage( aStorageName, nMode );
+}
+
+Sequence< OUString > SAL_CALL ODatabaseDocument::getDocumentSubStoragesNames( )
+{
+ Reference< XDocumentSubStorageSupplier > xStorageAccess( m_pImpl->getDocumentSubStorageSupplier() );
+ return xStorageAccess->getDocumentSubStoragesNames();
+}
+
+void ODatabaseDocument::impl_notifyStorageChange_nolck_nothrow( const Reference< XStorage >& xNewRootStorage )
+{
+ Reference< XInterface > xMe( *this );
+
+ m_aStorageListeners.forEach(
+ [&xMe, &xNewRootStorage] (uno::Reference<XStorageChangeListener> const& xListener) {
+ return xListener->notifyStorageChange(xMe, xNewRootStorage);
+ });
+}
+
+void ODatabaseDocument::disposing()
+{
+ if ( !m_pImpl.is() )
+ {
+ // this means that we're already disposed
+ OSL_ENSURE( ODatabaseDocument_OfficeDocument::rBHelper.bDisposed, "ODatabaseDocument::disposing: no impl anymore, but not yet disposed!" );
+ return;
+ }
+
+ if ( impl_isInitialized() )
+ m_aEventNotifier.notifyDocumentEvent( "OnUnload" );
+
+ Reference< XModel > xHoldAlive( this );
+
+ m_aEventNotifier.disposing();
+
+ lang::EventObject aDisposeEvent(static_cast<XWeak*>(this));
+ m_aModifyListeners.disposeAndClear( aDisposeEvent );
+ m_aCloseListener.disposeAndClear( aDisposeEvent );
+ m_aStorageListeners.disposeAndClear( aDisposeEvent );
+
+ // this is the list of objects which we currently hold as member. Upon resetting
+ // those members, we can (potentially) release the last reference to them, in which
+ // case they will be deleted - if they're C++ implementations, that is :).
+ // Some of those implementations are offending enough to require the SolarMutex, which
+ // means we should not release the last reference while our own mutex is locked ...
+ std::vector< Reference< XInterface > > aKeepAlive;
+
+ // SYNCHRONIZED ->
+ {
+ SolarMutexGuard aGuard;
+
+ OSL_ENSURE(m_aControllers.empty(),
+ "ODatabaseDocument::disposing: there still are controllers!");
+ // normally, nobody should explicitly dispose, but only XCloseable::close
+ // the document. And upon closing, our controllers are closed, too
+
+ {
+ uno::Reference<uno::XInterface> xUIInterface(m_xUIConfigurationManager);
+ aKeepAlive.push_back(xUIInterface);
+ }
+ m_xUIConfigurationManager = nullptr;
+
+ clearObjectContainer(m_xForms);
+ clearObjectContainer(m_xReports);
+
+ // reset the macro mode: in case the our impl struct stays alive (e.g. because our DataSource
+ // object still exists), and somebody subsequently re-opens the document, we want to have
+ // the security warning, again.
+ m_pImpl->resetMacroExecutionMode();
+
+ // similar arguing for our ViewMonitor
+ m_aViewMonitor.reset();
+
+ // tell our Impl to forget us
+ m_pImpl->modelIsDisposing(impl_isInitialized(), ODatabaseModelImpl::ResetModelAccess());
+
+ // now, at the latest, the controller array should be empty. Controllers are
+ // expected to listen for our disposal, and disconnect then
+ OSL_ENSURE(m_aControllers.empty(),
+ "ODatabaseDocument::disposing: there still are controllers!");
+ impl_disposeControllerFrames_nothrow();
+
+ {
+ uno::Reference<uno::XInterface> xModuleInterface(m_xModuleManager);
+ aKeepAlive.push_back(xModuleInterface);
+ }
+ m_xModuleManager.clear();
+
+ {
+ uno::Reference<uno::XInterface> xTitleInterface(m_xTitleHelper);
+ aKeepAlive.push_back(xTitleInterface);
+ }
+ m_xTitleHelper.clear();
+
+ m_pImpl.clear();
+ }
+ // <- SYNCHRONIZED
+
+ aKeepAlive.clear();
+}
+
+// XComponent
+void SAL_CALL ODatabaseDocument::dispose( )
+{
+ ::cppu::WeakComponentImplHelperBase::dispose();
+}
+
+void SAL_CALL ODatabaseDocument::addEventListener( const Reference< lang::XEventListener >& _xListener )
+{
+ ::cppu::WeakComponentImplHelperBase::addEventListener( _xListener );
+}
+
+void SAL_CALL ODatabaseDocument::removeEventListener( const Reference< lang::XEventListener >& _xListener )
+{
+ ::cppu::WeakComponentImplHelperBase::removeEventListener( _xListener );
+}
+
+// XServiceInfo
+OUString ODatabaseDocument::getImplementationName()
+{
+ return "com.sun.star.comp.dba.ODatabaseDocument";
+}
+
+Sequence< OUString > ODatabaseDocument::getSupportedServiceNames()
+{
+ return { "com.sun.star.sdb.OfficeDatabaseDocument", "com.sun.star.document.OfficeDocument" };
+}
+
+sal_Bool ODatabaseDocument::supportsService( const OUString& _rServiceName )
+{
+ return cppu::supportsService(this, _rServiceName);
+}
+
+Reference< XDataSource > SAL_CALL ODatabaseDocument::getDataSource()
+{
+ DocumentGuard aGuard( *this, DocumentGuard::MethodWithoutInit );
+ return m_pImpl->getOrCreateDataSource();
+}
+
+namespace
+{
+/// Property map for embedded import info set.
+comphelper::PropertyMapEntry const aEmbeddedImportInfoMap[] =
+{
+ {OUString("StreamRelPath"), 0, cppu::UnoType<OUString>::get(), beans::PropertyAttribute::MAYBEVOID, 0},
+ {OUString("StreamName"), 0, cppu::UnoType<OUString>::get(), beans::PropertyAttribute::MAYBEVOID, 0},
+ {OUString("SourceStorage"), 0, cppu::UnoType<embed::XStorage>::get(), beans::PropertyAttribute::MAYBEVOID, 0},
+};
+}
+
+void SAL_CALL ODatabaseDocument::loadFromStorage(const Reference<XStorage>& xStorage, const Sequence<PropertyValue>& rMediaDescriptor)
+{
+ DocumentGuard aGuard(*this, DocumentGuard::InitMethod);
+
+ uno::Reference<beans::XPropertySet> xInfoSet(comphelper::GenericPropertySet_CreateInstance(new comphelper::PropertySetInfo(aEmbeddedImportInfoMap)));
+ xInfoSet->setPropertyValue("StreamRelPath", uno::Any(comphelper::NamedValueCollection::getOrDefault(rMediaDescriptor, u"HierarchicalDocumentName", OUString())));
+ xInfoSet->setPropertyValue("StreamName", uno::Any(OUString("content.xml")));
+ xInfoSet->setPropertyValue("SourceStorage", uno::Any(xStorage));
+
+ uno::Sequence<uno::Any> aFilterCreationArgs{ Any(xInfoSet) };
+
+ uno::Reference<document::XImporter> xImporter(m_pImpl->m_aContext->getServiceManager()->createInstanceWithArgumentsAndContext("com.sun.star.comp.sdb.DBFilter", aFilterCreationArgs, m_pImpl->m_aContext), uno::UNO_QUERY_THROW);
+
+ uno::Reference<lang::XComponent> xComponent(*this, uno::UNO_QUERY_THROW);
+ xImporter->setTargetDocument(xComponent);
+
+ uno::Reference<document::XFilter> xFilter(xImporter, uno::UNO_QUERY_THROW);
+ uno::Sequence<beans::PropertyValue> aFilterArgs;
+ xFilter->filter(aFilterArgs);
+
+ // In case of embedding, XModel::attachResource is already called.
+ if (m_bEmbedded)
+ impl_setInitialized();
+
+ impl_setModified_nothrow(false, aGuard);
+}
+
+void SAL_CALL ODatabaseDocument::storeToStorage( const Reference< XStorage >& _rxStorage, const Sequence< PropertyValue >& _rMediaDescriptor )
+{
+ DocumentGuard aGuard(*this, DocumentGuard::DefaultMethod);
+ impl_storeToStorage_throw( _rxStorage, _rMediaDescriptor, aGuard );
+}
+
+void SAL_CALL ODatabaseDocument::switchToStorage( const Reference< XStorage >& _rxNewRootStorage )
+{
+ DocumentGuard aGuard(*this, DocumentGuard::DefaultMethod);
+
+ Reference< XStorage > xNewRootStorage( m_pImpl->switchToStorage( _rxNewRootStorage ) );
+
+ aGuard.clear();
+ impl_notifyStorageChange_nolck_nothrow( xNewRootStorage );
+}
+
+Reference< XStorage > SAL_CALL ODatabaseDocument::getDocumentStorage( )
+{
+ DocumentGuard aGuard(*this, DocumentGuard::MethodUsedDuringInit);
+ return m_pImpl->getOrCreateRootStorage();
+}
+
+void SAL_CALL ODatabaseDocument::addStorageChangeListener( const Reference< XStorageChangeListener >& Listener )
+{
+ DocumentGuard aGuard(*this, DocumentGuard::DefaultMethod);
+ m_aStorageListeners.addInterface( Listener );
+}
+
+void SAL_CALL ODatabaseDocument::removeStorageChangeListener( const Reference< XStorageChangeListener >& Listener )
+{
+ DocumentGuard aGuard(*this, DocumentGuard::DefaultMethod);
+ m_aStorageListeners.addInterface( Listener );
+}
+
+Reference< XStorageBasedLibraryContainer > SAL_CALL ODatabaseDocument::getBasicLibraries()
+{
+ DocumentGuard aGuard( *this, DocumentGuard::MethodUsedDuringInit );
+ return m_pImpl->getLibraryContainer( true );
+}
+
+Reference< XStorageBasedLibraryContainer > SAL_CALL ODatabaseDocument::getDialogLibraries()
+{
+ DocumentGuard aGuard(*this, DocumentGuard::DefaultMethod);
+ return m_pImpl->getLibraryContainer( false );
+}
+
+sal_Bool SAL_CALL ODatabaseDocument::getAllowMacroExecution()
+{
+ DocumentGuard aGuard(*this, DocumentGuard::DefaultMethod);
+ return m_pImpl->adjustMacroMode_AutoReject();
+}
+
+Reference< XEmbeddedScripts > SAL_CALL ODatabaseDocument::getScriptContainer()
+{
+ return this;
+}
+
+Reference< provider::XScriptProvider > SAL_CALL ODatabaseDocument::getScriptProvider( )
+{
+ DocumentGuard aGuard(*this, DocumentGuard::DefaultMethod);
+
+ Reference< XScriptProvider > xScriptProvider( m_xScriptProvider );
+ if ( !xScriptProvider.is() )
+ {
+ Reference < XScriptProviderFactory > xFactory =
+ theMasterScriptProviderFactory::get( m_pImpl->m_aContext );
+
+ Any aScriptProviderContext;
+ if ( m_bAllowDocumentScripting )
+ aScriptProviderContext <<= Reference< XModel >( this );
+
+ xScriptProvider.set( xFactory->createScriptProvider( aScriptProviderContext ), UNO_SET_THROW );
+ m_xScriptProvider = xScriptProvider;
+ }
+
+ return xScriptProvider;
+}
+
+Reference< XNameReplace > SAL_CALL ODatabaseDocument::getEvents( )
+{
+ DocumentGuard aGuard( *this, DocumentGuard::MethodUsedDuringInit );
+ return m_pEventContainer.get();
+}
+
+Reference< XInterface > ODatabaseDocument::getThis() const
+{
+ return *const_cast< ODatabaseDocument* >( this );
+}
+
+namespace {
+
+struct CreateAny
+{
+ Any operator() (const Reference<XController>& lhs) const
+ {
+ return Any(lhs);
+ }
+};
+
+}
+
+// XModel2
+Reference< XEnumeration > SAL_CALL ODatabaseDocument::getControllers( )
+{
+ DocumentGuard aGuard(*this, DocumentGuard::DefaultMethod);
+ uno::Sequence< Any> aController( m_aControllers.size() );
+ std::transform( m_aControllers.begin(), m_aControllers.end(), aController.getArray(), CreateAny() );
+ return new ::comphelper::OAnyEnumeration(aController);
+}
+
+Sequence< OUString > SAL_CALL ODatabaseDocument::getAvailableViewControllerNames( )
+{
+ Sequence< OUString > aNames { SERVICE_SDB_APPLICATIONCONTROLLER };
+ return aNames;
+}
+
+Reference< XController2 > SAL_CALL ODatabaseDocument::createDefaultViewController( const Reference< XFrame >& Frame )
+{
+ return createViewController( "Default", Sequence< PropertyValue >(), Frame);
+}
+
+Reference< XController2 > SAL_CALL ODatabaseDocument::createViewController( const OUString& ViewName, const Sequence< PropertyValue >& Arguments, const Reference< XFrame >& Frame )
+{
+ if ( ViewName != "Default" && ViewName != "Preview" )
+ throw IllegalArgumentException( OUString(), *this, 1 );
+ if ( !Frame.is() )
+ throw IllegalArgumentException( OUString(), *this, 3 );
+
+ DocumentGuard aGuard(*this, DocumentGuard::DefaultMethod);
+ aGuard.clear();
+
+ Reference< XController2 > xController(
+ m_pImpl->m_aContext->getServiceManager()->createInstanceWithContext("org.openoffice.comp.dbu.OApplicationController", m_pImpl->m_aContext),
+ UNO_QUERY_THROW );
+
+ ::comphelper::NamedValueCollection aInitArgs( Arguments );
+ aInitArgs.put( "Frame", Frame );
+ if ( ViewName == "Preview" )
+ aInitArgs.put( "Preview", true );
+ Reference< XInitialization > xInitController( xController, UNO_QUERY_THROW );
+ xInitController->initialize( aInitArgs.getWrappedPropertyValues() );
+
+ return xController;
+}
+
+Reference< XTitle > const & ODatabaseDocument::impl_getTitleHelper_throw()
+{
+ if ( ! m_xTitleHelper.is ())
+ {
+ Reference< XUntitledNumbers > xDesktop(Desktop::create(m_pImpl->m_aContext), uno::UNO_QUERY_THROW);
+ Reference< frame::XModel > xThis (getThis(), uno::UNO_QUERY_THROW);
+
+ m_xTitleHelper = new ::framework::TitleHelper(m_pImpl->m_aContext, xThis, xDesktop);
+ }
+
+ return m_xTitleHelper;
+}
+
+uno::Reference< frame::XUntitledNumbers > ODatabaseDocument::impl_getUntitledHelper_throw(const uno::Reference< uno::XInterface >& _xComponent)
+{
+ if ( !m_xModuleManager.is() )
+ m_xModuleManager.set( ModuleManager::create(m_pImpl->m_aContext) );
+
+ OUString sModuleId;
+ if (_xComponent.is())
+ sModuleId = m_xModuleManager->identify(_xComponent);
+
+ uno::Reference< frame::XUntitledNumbers > xNumberedControllers;
+
+ TNumberedController::const_iterator aFind = m_aNumberedControllers.find(sModuleId);
+ if ( aFind == m_aNumberedControllers.end() )
+ {
+ rtl::Reference<::comphelper::NumberedCollection> pHelper = new ::comphelper::NumberedCollection();
+ xNumberedControllers = pHelper;
+ pHelper->setOwner(uno::Reference< frame::XModel >(this));
+
+ m_aNumberedControllers.emplace( sModuleId,xNumberedControllers );
+ }
+ else
+ xNumberedControllers = aFind->second;
+
+ return xNumberedControllers;
+}
+
+// css.frame.XTitle
+OUString SAL_CALL ODatabaseDocument::getTitle()
+{
+ // SYNCHRONIZED ->
+ DocumentGuard aGuard( *this, DocumentGuard::MethodUsedDuringInit );
+ return impl_getTitleHelper_throw()->getTitle();
+}
+
+// css.frame.XTitle
+void SAL_CALL ODatabaseDocument::setTitle( const OUString& sTitle )
+{
+ // SYNCHRONIZED ->
+ DocumentGuard aGuard(*this, DocumentGuard::DefaultMethod);
+ impl_getTitleHelper_throw()->setTitle( sTitle );
+ m_aEventNotifier.notifyDocumentEventAsync( "OnTitleChanged" );
+ // <- SYNCHRONIZED
+}
+
+// css.frame.XTitleChangeBroadcaster
+void SAL_CALL ODatabaseDocument::addTitleChangeListener( const uno::Reference< frame::XTitleChangeListener >& xListener )
+{
+ // SYNCHRONIZED ->
+ DocumentGuard aGuard(*this, DocumentGuard::DefaultMethod);
+
+ uno::Reference< frame::XTitleChangeBroadcaster > xBroadcaster( impl_getTitleHelper_throw(), uno::UNO_QUERY_THROW );
+ xBroadcaster->addTitleChangeListener( xListener );
+}
+
+// css.frame.XTitleChangeBroadcaster
+void SAL_CALL ODatabaseDocument::removeTitleChangeListener( const uno::Reference< frame::XTitleChangeListener >& xListener )
+{
+ // SYNCHRONIZED ->
+ DocumentGuard aGuard(*this, DocumentGuard::DefaultMethod);
+
+ uno::Reference< frame::XTitleChangeBroadcaster > xBroadcaster( impl_getTitleHelper_throw(), uno::UNO_QUERY_THROW );
+ xBroadcaster->removeTitleChangeListener( xListener );
+}
+
+// css.frame.XUntitledNumbers
+::sal_Int32 SAL_CALL ODatabaseDocument::leaseNumber( const uno::Reference< uno::XInterface >& xComponent )
+{
+ DocumentGuard aGuard(*this, DocumentGuard::DefaultMethod);
+ return impl_getUntitledHelper_throw(xComponent)->leaseNumber (xComponent);
+}
+
+// css.frame.XUntitledNumbers
+void SAL_CALL ODatabaseDocument::releaseNumber( ::sal_Int32 nNumber )
+{
+ DocumentGuard aGuard(*this, DocumentGuard::DefaultMethod);
+ impl_getUntitledHelper_throw()->releaseNumber (nNumber);
+}
+
+// css.frame.XUntitledNumbers
+void SAL_CALL ODatabaseDocument::releaseNumberForComponent( const uno::Reference< uno::XInterface >& xComponent )
+{
+ DocumentGuard aGuard(*this, DocumentGuard::DefaultMethod);
+ impl_getUntitledHelper_throw(xComponent)->releaseNumberForComponent (xComponent);
+}
+
+// css.frame.XUntitledNumbers
+OUString SAL_CALL ODatabaseDocument::getUntitledPrefix()
+{
+ return OUString();
+}
+
+} // namespace dbaccess
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+com_sun_star_comp_dba_ODatabaseDocument(css::uno::XComponentContext* context,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ Reference<XUnoTunnel> xDBContextTunnel(DatabaseContext::create(context), UNO_QUERY_THROW);
+ dbaccess::ODatabaseContext* pContext
+ = comphelper::getFromUnoTunnel<dbaccess::ODatabaseContext>(xDBContextTunnel);
+ assert(pContext);
+
+ rtl::Reference pImpl(
+ new dbaccess::ODatabaseModelImpl(context, *pContext));
+ css::uno::Reference<XInterface> inst(pImpl->createNewModel_deliverOwnership());
+ inst->acquire();
+ return inst.get();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/dataaccess/databasedocument.hxx b/dbaccess/source/core/dataaccess/databasedocument.hxx
new file mode 100644
index 000000000..bd458d1b9
--- /dev/null
+++ b/dbaccess/source/core/dataaccess/databasedocument.hxx
@@ -0,0 +1,753 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <sal/config.h>
+
+#include <map>
+#include <memory>
+
+#include <ModelImpl.hxx>
+#include "documenteventnotifier.hxx"
+
+#include <com/sun/star/document/XDocumentSubStorageSupplier.hpp>
+#include <com/sun/star/frame/DoubleInitializationException.hpp>
+#include <com/sun/star/frame/XModel3.hpp>
+#include <com/sun/star/frame/XTitle.hpp>
+#include <com/sun/star/frame/XTitleChangeBroadcaster.hpp>
+#include <com/sun/star/frame/XUntitledNumbers.hpp>
+#include <com/sun/star/frame/XStorable.hpp>
+#include <com/sun/star/sdb/XReportDocumentsSupplier.hpp>
+#include <com/sun/star/sdb/XFormDocumentsSupplier.hpp>
+#include <com/sun/star/view/XPrintable.hpp>
+#include <com/sun/star/frame/XModuleManager2.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/lang/NotInitializedException.hpp>
+#include <com/sun/star/sdb/XOfficeDatabaseDocument.hpp>
+#include <com/sun/star/embed/XTransactionListener.hpp>
+#include <com/sun/star/document/XStorageBasedDocument.hpp>
+#include <com/sun/star/document/XEmbeddedScripts.hpp>
+#include <com/sun/star/document/XEventsSupplier.hpp>
+#include <com/sun/star/document/XScriptInvocationContext.hpp>
+#include <com/sun/star/script/XStorageBasedLibraryContainer.hpp>
+#include <com/sun/star/script/provider/XScriptProviderSupplier.hpp>
+#include <com/sun/star/frame/XLoadable.hpp>
+#include <com/sun/star/document/XEventBroadcaster.hpp>
+#include <com/sun/star/document/XDocumentEventBroadcaster.hpp>
+#include <com/sun/star/document/XDocumentRecovery.hpp>
+#include <com/sun/star/ui/XUIConfigurationManager2.hpp>
+#include <com/sun/star/ui/XUIConfigurationManagerSupplier.hpp>
+#include <com/sun/star/util/XCloseable.hpp>
+#include <com/sun/star/util/XModifiable.hpp>
+
+#include <comphelper/interfacecontainer3.hxx>
+#include <cppuhelper/compbase.hxx>
+#include <cppuhelper/implbase3.hxx>
+#include <rtl/ref.hxx>
+
+namespace comphelper {
+ class NamedValueCollection;
+}
+
+namespace dbaccess
+{
+
+class DocumentEvents;
+class DocumentEventExecutor;
+class DocumentGuard;
+
+typedef std::vector< css::uno::Reference< css::frame::XController > > Controllers;
+
+// ViewMonitor
+/** helper class monitoring the views of a document, and firing appropriate events
+ when views are attached / detached
+*/
+class ViewMonitor
+{
+public:
+ explicit ViewMonitor( DocumentEventNotifier& _rEventNotifier )
+ :m_rEventNotifier( _rEventNotifier )
+ ,m_bIsNewDocument( true )
+ ,m_bEverHadController( false )
+ ,m_bLastIsFirstEverController( false )
+ ,m_xLastConnectedController()
+ {
+ }
+
+ ViewMonitor(const ViewMonitor&) = delete;
+ const ViewMonitor& operator=(const ViewMonitor&) = delete;
+
+ void reset()
+ {
+ m_bEverHadController = false;
+ m_bLastIsFirstEverController = false;
+ m_xLastConnectedController.clear();
+ }
+
+ /** to be called when a view (aka controller) has been connected to the document
+ @return
+ <TRUE/> if and only if this was the first-ever controller connected to the document
+ */
+ bool onControllerConnected(
+ const css::uno::Reference< css::frame::XController >& _rxController
+ );
+
+ /** to be called when a controller is set as current controller
+ @return <TRUE/>
+ if and only if the controller connection indicates that loading the document is finished. This
+ is the case if the given controller has previously been connected, and it was the first controller
+ ever for which this happened.
+ */
+ bool onSetCurrentController(
+ const css::uno::Reference< css::frame::XController >& _rxController
+ );
+
+ void onLoadedDocument() { m_bIsNewDocument = false; }
+
+private:
+ DocumentEventNotifier& m_rEventNotifier;
+ bool m_bIsNewDocument;
+ bool m_bEverHadController;
+ bool m_bLastIsFirstEverController;
+ css::uno::Reference< css::frame::XController >
+ m_xLastConnectedController;
+};
+
+// ODatabaseDocument
+typedef cppu::PartialWeakComponentImplHelper< css::frame::XModel3
+ , css::util::XModifiable
+ , css::frame::XStorable
+ , css::document::XEventBroadcaster
+ , css::document::XDocumentEventBroadcaster
+ , css::view::XPrintable
+ , css::util::XCloseable
+ , css::lang::XServiceInfo
+ , css::sdb::XOfficeDatabaseDocument
+ , css::ui::XUIConfigurationManagerSupplier
+ , css::document::XStorageBasedDocument
+ , css::document::XEmbeddedScripts
+ , css::document::XScriptInvocationContext
+ , css::script::provider::XScriptProviderSupplier
+ , css::document::XEventsSupplier
+ , css::frame::XLoadable
+ , css::document::XDocumentRecovery
+ > ODatabaseDocument_OfficeDocument;
+
+typedef ::cppu::ImplHelper3< css::frame::XTitle
+ , css::frame::XTitleChangeBroadcaster
+ , css::frame::XUntitledNumbers
+ > ODatabaseDocument_Title;
+
+class ODatabaseDocument :public ModelDependentComponent // ModelDependentComponent must be first!
+ ,public ODatabaseDocument_OfficeDocument
+ ,public ODatabaseDocument_Title
+{
+ enum InitState
+ {
+ NotInitialized,
+ Initializing,
+ Initialized
+ };
+
+ typedef std::map< OUString, css::uno::Reference< css::frame::XUntitledNumbers > > TNumberedController;
+ css::uno::Reference< css::ui::XUIConfigurationManager2> m_xUIConfigurationManager;
+
+ ::comphelper::OInterfaceContainerHelper3<css::util::XModifyListener> m_aModifyListeners;
+ ::comphelper::OInterfaceContainerHelper3<css::util::XCloseListener> m_aCloseListener;
+ ::comphelper::OInterfaceContainerHelper3<css::document::XStorageChangeListener> m_aStorageListeners;
+
+ std::unique_ptr<DocumentEvents> m_pEventContainer;
+ ::rtl::Reference< DocumentEventExecutor > m_pEventExecutor;
+ DocumentEventNotifier m_aEventNotifier;
+
+ css::uno::Reference< css::frame::XController > m_xCurrentController;
+ Controllers m_aControllers;
+ ViewMonitor m_aViewMonitor;
+
+ css::uno::WeakReference< css::container::XNameAccess > m_xForms;
+ css::uno::WeakReference< css::container::XNameAccess > m_xReports;
+ css::uno::WeakReference< css::script::provider::XScriptProvider > m_xScriptProvider;
+
+ /** @short such module manager is used to classify new opened documents. */
+ css::uno::Reference< css::frame::XModuleManager2 > m_xModuleManager;
+ css::uno::Reference< css::frame::XTitle > m_xTitleHelper;
+ TNumberedController m_aNumberedControllers;
+
+ /** true if and only if the DatabaseDocument's "initNew" or "load" have been called (or, well,
+ the document has be initialized implicitly - see storeAsURL
+ */
+ InitState m_eInitState;
+ bool m_bClosing;
+ bool m_bAllowDocumentScripting;
+ bool m_bHasBeenRecovered;
+ /// If XModel::attachResource() was called to inform us that the document is embedded into another one.
+ bool m_bEmbedded;
+
+ enum StoreType { SAVE, SAVE_AS };
+ /** stores the document to the given URL, rebases it to the respective new storage, if necessary, resets
+ the modified flag, and notifies any listeners as required
+
+ @param _rURL
+ the URL to store the document to
+ @param _rArguments
+ arguments for storing the document (MediaDescriptor)
+ @param _eType
+ the type of the store process (Save or SaveAs). The method will automatically
+ notify the proper events for this type.
+ @param _rGuard
+ the instance lock to be released before doing synchronous notifications
+ @throws css::io::IOException
+ @throws css::uno::RuntimeException
+ */
+ void impl_storeAs_throw(
+ const OUString& _rURL,
+ const ::comphelper::NamedValueCollection& _rArguments,
+ const StoreType _eType,
+ DocumentGuard& _rGuard
+ );
+
+ /** notifies our storage change listeners that our underlying storage changed
+
+ @param _rxNewRootStorage
+ the new root storage to be notified. If <NULL/>, it is assumed that no storage change actually
+ happened, and the listeners are not notified.
+ */
+ void impl_notifyStorageChange_nolck_nothrow(
+ const css::uno::Reference< css::embed::XStorage >& _rxNewRootStorage
+ );
+
+ /// write a single XML stream into the package
+ void WriteThroughComponent(
+ const css::uno::Reference< css::lang::XComponent > & xComponent, /// the component we export
+ const char* pStreamName, /// the stream name
+ const char* pServiceName, /// service name of the component
+ const css::uno::Sequence< css::uno::Any> & rArguments, /// the argument (XInitialization)
+ const css::uno::Sequence< css::beans::PropertyValue> & rMediaDesc,/// output descriptor
+ const css::uno::Reference< css::embed::XStorage >& _xStorageToSaveTo
+ ) const;
+
+ /// write a single output stream
+ /// (to be called either directly or by WriteThroughComponent(...))
+ void WriteThroughComponent(
+ const css::uno::Reference< css::io::XOutputStream >& xOutputStream,
+ const css::uno::Reference< css::lang::XComponent >& xComponent,
+ const char* pServiceName,
+ const css::uno::Sequence< css::uno::Any >& rArguments,
+ const css::uno::Sequence< css::beans::PropertyValue> & rMediaDesc
+ ) const;
+
+ /** writes the content and settings
+ @param sURL
+ The URL
+ @param lArguments
+ The media descriptor
+ @param _xStorageToSaveTo
+ The storage which should be used for saving
+ */
+ void impl_writeStorage_throw(
+ const css::uno::Reference< css::embed::XStorage >& _rxTargetStorage,
+ const ::comphelper::NamedValueCollection& _rMediaDescriptor
+ ) const;
+
+ // ModelDependentComponent overridables
+ virtual css::uno::Reference< css::uno::XInterface > getThis() const override;
+
+ css::uno::Reference< css::frame::XTitle > const & impl_getTitleHelper_throw();
+ css::uno::Reference< css::frame::XUntitledNumbers > impl_getUntitledHelper_throw(
+ const css::uno::Reference< css::uno::XInterface >& _xComponent = css::uno::Reference< css::uno::XInterface >());
+
+private:
+ explicit ODatabaseDocument(const ::rtl::Reference<ODatabaseModelImpl>& _pImpl);
+ // Do NOT create those documents directly, always use ODatabaseModelImpl::getModel. Reason is that
+ // ODatabaseDocument requires clear ownership, and in turn lifetime synchronisation with the ModelImpl.
+ // If you create a ODatabaseDocument directly, you might easily create a leak.
+ // #i50905#
+
+protected:
+ virtual void SAL_CALL disposing() override;
+
+ virtual ~ODatabaseDocument() override;
+
+public:
+ struct FactoryAccess { friend class ODatabaseModelImpl; private: FactoryAccess() { } };
+ static rtl::Reference<ODatabaseDocument> createDatabaseDocument( const ::rtl::Reference<ODatabaseModelImpl>& _pImpl, FactoryAccess /*accessControl*/ )
+ {
+ return new ODatabaseDocument( _pImpl );
+ }
+
+ // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName( ) override;
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override;
+
+ // XInterface
+ virtual css::uno::Any SAL_CALL queryInterface(const css::uno::Type& _rType) override;
+ virtual void SAL_CALL acquire( ) noexcept override;
+ virtual void SAL_CALL release( ) noexcept override;
+
+ // XTypeProvider
+ virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes( ) override;
+ virtual css::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId( ) override;
+
+ // XComponent
+ virtual void SAL_CALL dispose( ) override;
+ virtual void SAL_CALL addEventListener( const css::uno::Reference< css::lang::XEventListener >& xListener ) override;
+ virtual void SAL_CALL removeEventListener( const css::uno::Reference< css::lang::XEventListener >& aListener ) override;
+
+ // XModel
+ virtual sal_Bool SAL_CALL attachResource( const OUString& URL, const css::uno::Sequence< css::beans::PropertyValue >& Arguments ) override ;
+ virtual OUString SAL_CALL getURL( ) override ;
+ virtual css::uno::Sequence< css::beans::PropertyValue > SAL_CALL getArgs( ) override ;
+ virtual void SAL_CALL connectController( const css::uno::Reference< css::frame::XController >& Controller ) override ;
+ virtual void SAL_CALL disconnectController( const css::uno::Reference< css::frame::XController >& Controller ) override ;
+ virtual void SAL_CALL lockControllers( ) override ;
+ virtual void SAL_CALL unlockControllers( ) override ;
+ virtual sal_Bool SAL_CALL hasControllersLocked( ) override ;
+ virtual css::uno::Reference< css::frame::XController > SAL_CALL getCurrentController( ) override ;
+ virtual void SAL_CALL setCurrentController( const css::uno::Reference< css::frame::XController >& Controller ) override ;
+ virtual css::uno::Reference< css::uno::XInterface > SAL_CALL getCurrentSelection( ) override ;
+
+ // XModel2
+ virtual css::uno::Reference< css::container::XEnumeration > SAL_CALL getControllers( ) override ;
+ virtual css::uno::Sequence< OUString > SAL_CALL getAvailableViewControllerNames( ) override ;
+ virtual css::uno::Reference< css::frame::XController2 > SAL_CALL createDefaultViewController( const css::uno::Reference< css::frame::XFrame >& Frame ) override ;
+ virtual css::uno::Reference< css::frame::XController2 > SAL_CALL createViewController( const OUString& ViewName, const css::uno::Sequence< css::beans::PropertyValue >& Arguments, const css::uno::Reference< css::frame::XFrame >& Frame ) override ;
+ virtual void SAL_CALL setArgs(const css::uno::Sequence<css::beans::PropertyValue>& aArgs) override;
+
+ // XModel3
+ virtual ::css::uno::Sequence< ::css::beans::PropertyValue > SAL_CALL getArgs2( const ::css::uno::Sequence< ::rtl::OUString >& requestedArgs ) override;
+
+ // XStorable
+ virtual sal_Bool SAL_CALL hasLocation( ) override ;
+ virtual OUString SAL_CALL getLocation( ) override ;
+ virtual sal_Bool SAL_CALL isReadonly( ) override ;
+ virtual void SAL_CALL store( ) override ;
+ virtual void SAL_CALL storeAsURL( const OUString& sURL, const css::uno::Sequence< css::beans::PropertyValue >& lArguments ) override ;
+ virtual void SAL_CALL storeToURL( const OUString& sURL, const css::uno::Sequence< css::beans::PropertyValue >& lArguments ) override ;
+
+ // XModifyBroadcaster
+ virtual void SAL_CALL addModifyListener( const css::uno::Reference< css::util::XModifyListener >& aListener ) override;
+ virtual void SAL_CALL removeModifyListener( const css::uno::Reference< css::util::XModifyListener >& aListener ) override;
+
+ // css::util::XModifiable
+ virtual sal_Bool SAL_CALL isModified( ) override ;
+ virtual void SAL_CALL setModified( sal_Bool bModified ) override ;
+
+ // XEventBroadcaster
+ virtual void SAL_CALL addEventListener( const css::uno::Reference< css::document::XEventListener >& aListener ) override;
+ virtual void SAL_CALL removeEventListener( const css::uno::Reference< css::document::XEventListener >& aListener ) override;
+
+ // XDocumentEventBroadcaster
+ virtual void SAL_CALL addDocumentEventListener( const css::uno::Reference< css::document::XDocumentEventListener >& Listener ) override;
+ virtual void SAL_CALL removeDocumentEventListener( const css::uno::Reference< css::document::XDocumentEventListener >& Listener ) override;
+ virtual void SAL_CALL notifyDocumentEvent( const OUString& EventName, const css::uno::Reference< css::frame::XController2 >& ViewController, const css::uno::Any& Supplement ) override;
+
+ // XPrintable
+ virtual css::uno::Sequence< css::beans::PropertyValue > SAL_CALL getPrinter( ) override ;
+ virtual void SAL_CALL setPrinter( const css::uno::Sequence< css::beans::PropertyValue >& aPrinter ) override ;
+ virtual void SAL_CALL print( const css::uno::Sequence< css::beans::PropertyValue >& xOptions ) override ;
+
+ // XFormDocumentsSupplier
+ virtual css::uno::Reference< css::container::XNameAccess > SAL_CALL getFormDocuments( ) override;
+
+ // XReportDocumentsSupplier
+ virtual css::uno::Reference< css::container::XNameAccess > SAL_CALL getReportDocuments( ) override;
+
+ // XCloseable
+ virtual void SAL_CALL close( sal_Bool DeliverOwnership ) override;
+ virtual void SAL_CALL addCloseListener( const css::uno::Reference< css::util::XCloseListener >& Listener ) override;
+ virtual void SAL_CALL removeCloseListener( const css::uno::Reference< css::util::XCloseListener >& Listener ) override;
+
+ // XUIConfigurationManagerSupplier
+ virtual css::uno::Reference< css::ui::XUIConfigurationManager > SAL_CALL getUIConfigurationManager( ) override;
+
+ // XDocumentSubStorageSupplier
+ virtual css::uno::Reference< css::embed::XStorage > SAL_CALL getDocumentSubStorage( const OUString& aStorageName, sal_Int32 nMode ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getDocumentSubStoragesNames( ) override;
+
+ // XOfficeDatabaseDocument
+ virtual css::uno::Reference< css::sdbc::XDataSource > SAL_CALL getDataSource() override;
+
+ // XStorageBasedDocument
+ virtual void SAL_CALL loadFromStorage( const css::uno::Reference< css::embed::XStorage >& xStorage, const css::uno::Sequence< css::beans::PropertyValue >& aMediaDescriptor ) override;
+ virtual void SAL_CALL storeToStorage( const css::uno::Reference< css::embed::XStorage >& xStorage, const css::uno::Sequence< css::beans::PropertyValue >& aMediaDescriptor ) override;
+ virtual void SAL_CALL switchToStorage( const css::uno::Reference< css::embed::XStorage >& xStorage ) override;
+ virtual css::uno::Reference< css::embed::XStorage > SAL_CALL getDocumentStorage( ) override;
+ virtual void SAL_CALL addStorageChangeListener( const css::uno::Reference< css::document::XStorageChangeListener >& xListener ) override;
+ virtual void SAL_CALL removeStorageChangeListener( const css::uno::Reference< css::document::XStorageChangeListener >& xListener ) override;
+
+ // XEmbeddedScripts
+ virtual css::uno::Reference< css::script::XStorageBasedLibraryContainer > SAL_CALL getBasicLibraries() override;
+ virtual css::uno::Reference< css::script::XStorageBasedLibraryContainer > SAL_CALL getDialogLibraries() override;
+ virtual sal_Bool SAL_CALL getAllowMacroExecution() override;
+
+ // XScriptInvocationContext
+ virtual css::uno::Reference< css::document::XEmbeddedScripts > SAL_CALL getScriptContainer() override;
+
+ // XScriptProviderSupplier
+ virtual css::uno::Reference< css::script::provider::XScriptProvider > SAL_CALL getScriptProvider( ) override;
+
+ // XEventsSupplier
+ virtual css::uno::Reference< css::container::XNameReplace > SAL_CALL getEvents( ) override;
+
+ // XLoadable
+ virtual void SAL_CALL initNew( ) override;
+ virtual void SAL_CALL load( const css::uno::Sequence< css::beans::PropertyValue >& lArguments ) override;
+
+ // css.document.XDocumentRecovery
+ virtual sal_Bool SAL_CALL wasModifiedSinceLastSave() override;
+ virtual void SAL_CALL storeToRecoveryFile( const OUString& i_TargetLocation, const css::uno::Sequence< css::beans::PropertyValue >& i_MediaDescriptor ) override;
+ virtual void SAL_CALL recoverFromFile( const OUString& i_SourceLocation, const OUString& i_SalvagedFile, const css::uno::Sequence< css::beans::PropertyValue >& i_MediaDescriptor ) override;
+
+ // XTitle
+ virtual OUString SAL_CALL getTitle( ) override;
+ virtual void SAL_CALL setTitle( const OUString& sTitle ) override;
+
+ // XTitleChangeBroadcaster
+ virtual void SAL_CALL addTitleChangeListener( const css::uno::Reference< css::frame::XTitleChangeListener >& xListener ) override;
+ virtual void SAL_CALL removeTitleChangeListener( const css::uno::Reference< css::frame::XTitleChangeListener >& xListener ) override;
+
+ // XUntitledNumbers
+ virtual ::sal_Int32 SAL_CALL leaseNumber( const css::uno::Reference< css::uno::XInterface >& xComponent ) override;
+ virtual void SAL_CALL releaseNumber( ::sal_Int32 nNumber ) override;
+ virtual void SAL_CALL releaseNumberForComponent( const css::uno::Reference< css::uno::XInterface >& xComponent ) override;
+ virtual OUString SAL_CALL getUntitledPrefix( ) override;
+
+ /** clears the given object container
+
+ Clearing is done via disposal - the method calls XComponent::dispose at the given object,
+ which must be one of our impl's or our object containers (m_xForms, m_xReports,
+ m_xTableDefinitions, m_xCommandDefinitions)
+
+ @param _rxContainer
+ the container to clear
+ */
+ static void clearObjectContainer(
+ css::uno::WeakReference< css::container::XNameAccess >& _rxContainer);
+
+ /** checks whether the component is already initialized, throws a NotInitializedException if not
+ */
+ void checkInitialized() const
+ {
+ if ( !impl_isInitialized() )
+ throw css::lang::NotInitializedException( OUString(), getThis() );
+ }
+
+ /** checks the document is currently in the initialization phase, or already initialized.
+ Throws NotInitializedException if not so.
+ */
+ void checkNotUninitialized() const
+ {
+ if ( impl_isInitialized() || impl_isInitializing() )
+ // fine
+ return;
+
+ throw css::lang::NotInitializedException( OUString(), getThis() );
+ }
+
+ /** checks whether the document is currently being initialized, or already initialized,
+ throws a DoubleInitializationException if so
+ */
+ void checkNotInitialized() const
+ {
+ if ( impl_isInitializing() || impl_isInitialized() )
+ throw css::frame::DoubleInitializationException( OUString(), getThis() );
+ }
+
+private:
+ /// @throws css::uno::RuntimeException
+ css::uno::Reference< css::ui::XUIConfigurationManager2 > const & getUIConfigurationManager2();
+
+ /** returns whether the model is currently being initialized
+ */
+ bool impl_isInitializing() const { return m_eInitState == Initializing; }
+
+ /** returns whether the model is already initialized, i.e. the XModel's "initNew" or "load" methods have been called
+ */
+ bool impl_isInitialized() const { return m_eInitState == Initialized; }
+
+ /// tells the model it is being initialized now
+ void impl_setInitializing() { m_eInitState = Initializing; }
+
+ /// tells the model its initialization is done
+ void impl_setInitialized();
+
+ /** closes the frames of all connected controllers
+
+ @param _bDeliverOwnership
+ determines if the ownership should be transferred to the component which
+ possibly vetos the closing
+
+ @throws css::util::CloseVetoException
+ if the closing was vetoed by any instance
+ */
+ void impl_closeControllerFrames_nolck_throw( bool _bDeliverOwnership );
+
+ /** disposes the frames of all controllers which are still left in m_aControllers.
+ */
+ void impl_disposeControllerFrames_nothrow();
+
+ /** does a reparenting at the given object container to ourself
+
+ Calls XChild::setParent at the given object, which must be one of our impl's or our
+ object containers (m_xForms, m_xReports, m_xTableDefinitions, m_xCommandDefinitions)
+ */
+ void impl_reparent_nothrow( const css::uno::WeakReference< css::container::XNameAccess >& _rxContainer );
+
+ /** retrieves the forms or reports contained, creates and initializes it, if necessary
+
+ @throws DisposedException
+ if the instance is already disposed
+ @throws IllegalArgumentException
+ if <arg>_eType</arg> is not ODatabaseModelImpl::E_FORM and not ODatabaseModelImpl::E_REPORT
+ */
+ css::uno::Reference< css::container::XNameAccess >
+ impl_getDocumentContainer_throw( ODatabaseModelImpl::ObjectType _eType );
+
+ /** resets everything
+
+ @precond
+ m_pImpl is not <NULL/>
+ */
+ void
+ impl_reset_nothrow();
+
+ /** imports the document from the given resource.
+ */
+ static void
+ impl_import_nolck_throw(
+ const css::uno::Reference< css::uno::XComponentContext >& _rContext,
+ const css::uno::Reference< css::uno::XInterface >& _rxTargetComponent,
+ const ::comphelper::NamedValueCollection& _rResource
+ );
+
+ /** creates a storage for the given URL, truncating it if a file with this name already exists
+
+ @throws Exception
+ if creating the storage failed
+
+ @return
+ the newly created storage for the file at the given URL
+ */
+ css::uno::Reference< css::embed::XStorage >
+ impl_createStorageFor_throw(
+ const OUString& _rURL
+ ) const;
+
+ /** Extracts storage from arguments, or creates for the given URL, truncating it if a file with
+ this name already exists
+
+ @throws Exception
+ if creating the storage failed
+
+ @return
+ the storage that is either extracted from arguments, or newly created for the file at
+ the given URL
+ */
+ css::uno::Reference<css::embed::XStorage> impl_GetStorageOrCreateFor_throw(
+ const ::comphelper::NamedValueCollection& _rArguments, const OUString& _rURL) const;
+
+ /** sets our "modified" flag
+
+ will notify all our respective listeners, if the "modified" state actually changed
+
+ @param _bModified
+ the (new) flag indicating whether the document is currently modified or not
+ @param _rGuard
+ the guard for our instance. At method entry, the guard must hold the lock. At the moment
+ of method leave, the lock will be released.
+ @precond
+ our mutex is locked
+ @postcond
+ our mutex is not locked
+ */
+ void impl_setModified_nothrow( bool _bModified, DocumentGuard& _rGuard );
+
+ /** stores the document to the given storage
+
+ Note that the document is actually not rebased to this storage, it just stores a copy of itself
+ to the given target storage.
+
+ @param _rxTargetStorage
+ denotes the storage to store the document into
+ @param _rMediaDescriptor
+ contains additional parameters for storing the document
+ @param _rDocGuard
+ a guard which holds the (only) lock to the document, and which will be temporarily
+ released where necessary (e.g. for notifications, or calling into other components)
+
+ @throws css::uno::IllegalArgumentException
+ if the given storage is <NULL/>.
+
+ @throws css::uno::RuntimeException
+ when any of the used operations throws it
+
+ @throws css::io::IOException
+ when any of the used operations throws it, or any other exception occurs which is no
+ RuntimeException and no IOException
+ */
+ void impl_storeToStorage_throw(
+ const css::uno::Reference< css::embed::XStorage >& _rxTargetStorage,
+ const css::uno::Sequence< css::beans::PropertyValue >& _rMediaDescriptor,
+ DocumentGuard& _rDocGuard
+ ) const;
+
+ /** impl-version of attachResource
+
+ @param i_rLogicalDocumentURL
+ denotes the logical URL of the document, to be reported by getURL/getLocation
+ @param i_rMediaDescriptor
+ denotes additional document parameters
+ @param _rDocGuard
+ is the guard which currently protects the document instance
+ */
+ bool impl_attachResource(
+ const OUString& i_rLogicalDocumentURL,
+ const css::uno::Sequence< css::beans::PropertyValue >& i_rMediaDescriptor,
+ DocumentGuard& _rDocGuard
+ );
+
+ /** throws an IOException with the message as defined in the RID_STR_ERROR_WHILE_SAVING resource, wrapping
+ the given caught non-IOException error
+ */
+ void impl_throwIOExceptionCausedBySave_throw(
+ const css::uno::Any& i_rError,
+ std::u16string_view i_rTargetURL
+ ) const;
+};
+
+/** an extended version of the ModelMethodGuard, which also cares for the initialization state
+ of the document
+*/
+class DocumentGuard : private ModelMethodGuard
+{
+public:
+ enum InitMethod_
+ {
+ // a method which is to initialize the document
+ InitMethod,
+ };
+
+ enum DefaultMethod_
+ {
+ // a default method
+ DefaultMethod
+ };
+
+ enum MethodUsedDuringInit_
+ {
+ // a method which is used (externally) during the initialization phase
+ MethodUsedDuringInit
+ };
+
+ enum MethodWithoutInit_
+ {
+ // a method which does not need initialization - use with care!
+ MethodWithoutInit
+ };
+
+
+ /** constructs the guard
+
+ @param _document
+ the ODatabaseDocument instance
+
+ @throws css::lang::DisposedException
+ If the given component is already disposed
+
+ @throws css::lang::NotInitializedException
+ if the given component is not yet initialized
+ */
+ DocumentGuard(const ODatabaseDocument& _document, DefaultMethod_)
+ : ModelMethodGuard(_document)
+ , m_document(_document )
+ {
+ m_document.checkInitialized();
+ }
+
+ /** constructs the guard
+
+ @param _document
+ the ODatabaseDocument instance
+
+ @throws css::lang::DisposedException
+ If the given component is already disposed
+
+ @throws css::frame::DoubleInitializationException
+ if the given component is already initialized, or currently being initialized.
+ */
+ DocumentGuard(const ODatabaseDocument& _document, InitMethod_)
+ : ModelMethodGuard(_document)
+ , m_document(_document)
+ {
+ m_document.checkNotInitialized();
+ }
+
+ /** constructs the guard
+
+ @param _document
+ the ODatabaseDocument instance
+
+ @throws css::lang::DisposedException
+ If the given component is already disposed
+
+ @throws css::lang::NotInitializedException
+ if the component is still uninitialized, and not in the initialization
+ phase currently.
+ */
+ DocumentGuard(const ODatabaseDocument& _document, MethodUsedDuringInit_)
+ : ModelMethodGuard(_document)
+ , m_document(_document)
+ {
+ m_document.checkNotUninitialized();
+ }
+
+ /** constructs the guard
+
+ @param _document
+ the ODatabaseDocument instance
+
+ @throws css::lang::DisposedException
+ If the given component is already disposed
+ */
+ DocumentGuard(const ODatabaseDocument& _document, MethodWithoutInit_)
+ : ModelMethodGuard( _document )
+ , m_document( _document )
+ {
+ }
+
+ void clear()
+ {
+ ModelMethodGuard::clear();
+ }
+ void reset()
+ {
+ ModelMethodGuard::reset();
+ m_document.checkDisposed();
+ }
+
+private:
+
+ const ODatabaseDocument& m_document;
+};
+
+} // namespace dbaccess
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/dataaccess/databaseregistrations.cxx b/dbaccess/source/core/dataaccess/databaseregistrations.cxx
new file mode 100644
index 000000000..40fa526d1
--- /dev/null
+++ b/dbaccess/source/core/dataaccess/databaseregistrations.cxx
@@ -0,0 +1,369 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+
+#include <com/sun/star/lang/IllegalAccessException.hpp>
+#include <com/sun/star/lang/IllegalArgumentException.hpp>
+#include <com/sun/star/container/ElementExistException.hpp>
+#include <com/sun/star/container/NoSuchElementException.hpp>
+#include <com/sun/star/sdb/XDatabaseRegistrations.hpp>
+
+#include <cppuhelper/basemutex.hxx>
+#include <comphelper/interfacecontainer3.hxx>
+#include <cppuhelper/implbase1.hxx>
+#include <osl/diagnose.h>
+#include <unotools/pathoptions.hxx>
+#include <tools/urlobj.hxx>
+#include <unotools/confignode.hxx>
+
+#include "databaseregistrations.hxx"
+
+namespace dbaccess
+{
+ using ::com::sun::star::uno::Reference;
+ using ::com::sun::star::uno::RuntimeException;
+ using ::com::sun::star::uno::Any;
+ using ::com::sun::star::uno::Sequence;
+ using ::com::sun::star::uno::XComponentContext;
+ using ::com::sun::star::container::NoSuchElementException;
+ using ::com::sun::star::lang::IllegalArgumentException;
+ using ::com::sun::star::lang::IllegalAccessException;
+ using ::com::sun::star::container::ElementExistException;
+ using ::com::sun::star::sdb::XDatabaseRegistrations;
+ using ::com::sun::star::sdb::XDatabaseRegistrationsListener;
+ using ::com::sun::star::sdb::DatabaseRegistrationEvent;
+ using ::com::sun::star::uno::XAggregation;
+
+ static OUString getConfigurationRootPath()
+ {
+ return "org.openoffice.Office.DataAccess/RegisteredNames";
+ }
+
+ static OUString getLocationNodeName()
+ {
+ return "Location";
+ }
+
+ static OUString getNameNodeName()
+ {
+ return "Name";
+ }
+
+ // DatabaseRegistrations - declaration
+ typedef ::cppu::WeakAggImplHelper1 < XDatabaseRegistrations
+ > DatabaseRegistrations_Base;
+
+ namespace {
+
+ class DatabaseRegistrations :public ::cppu::BaseMutex
+ ,public DatabaseRegistrations_Base
+ {
+ public:
+ explicit DatabaseRegistrations( const Reference<XComponentContext>& _rxContext );
+
+ protected:
+ virtual ~DatabaseRegistrations() override;
+
+ public:
+ virtual sal_Bool SAL_CALL hasRegisteredDatabase( const OUString& Name ) override;
+ virtual Sequence< OUString > SAL_CALL getRegistrationNames() override;
+ virtual OUString SAL_CALL getDatabaseLocation( const OUString& Name ) override;
+ virtual void SAL_CALL registerDatabaseLocation( const OUString& Name, const OUString& Location ) override;
+ virtual void SAL_CALL revokeDatabaseLocation( const OUString& Name ) override;
+ virtual void SAL_CALL changeDatabaseLocation( const OUString& Name, const OUString& NewLocation ) override;
+ virtual sal_Bool SAL_CALL isDatabaseRegistrationReadOnly( const OUString& Name ) override;
+ virtual void SAL_CALL addDatabaseRegistrationsListener( const Reference< XDatabaseRegistrationsListener >& Listener ) override;
+ virtual void SAL_CALL removeDatabaseRegistrationsListener( const Reference< XDatabaseRegistrationsListener >& Listener ) override;
+
+ private:
+ void
+ impl_checkValidName_common(std::u16string_view _rName);
+ ::utl::OConfigurationNode
+ impl_checkValidName_throw_must_exist(const OUString& _rName);
+ ::utl::OConfigurationNode
+ impl_checkValidName_throw_must_not_exist(const OUString& _rName);
+
+ void impl_checkValidLocation_throw( std::u16string_view _rLocation );
+
+ /** retrieves the configuration node whose "Name" sub node has the given value
+
+ Since we separated the name of the registration node from the "Name" value of the registration, we cannot
+ simply do a "getByName" (equivalent) when we want to retrieve the node for a given registration name.
+ Instead, we must search all nodes.
+
+ If a node with the given display name does not exist, then a NoSuchElementException is thrown.
+
+ If no exception is thrown, then a valid node is returned: If the node existed it is returned.
+ */
+ ::utl::OConfigurationNode
+ impl_getNodeForName_throw_must_exist(const OUString& _rName);
+
+ /** retrieves the configuration node whose "Name" sub node has the given value
+
+ Since we separated the name of the registration node from the "Name" value of the registration, we cannot
+ simply do a "getByName" (equivalent) when we want to retrieve the node for a given registration name.
+ Instead, we must search all nodes.
+
+ If a node with the given name already exists, then an ElementExistException is thrown.
+
+ If no exception is thrown, then a valid node is returned: If the node did not yet exist a new node is created,
+ in this case the root node is not yet committed.
+ */
+ ::utl::OConfigurationNode
+ impl_getNodeForName_throw_must_not_exist(const OUString& _rName);
+
+
+ ::utl::OConfigurationNode
+ impl_getNodeForName_nothrow(std::u16string_view _rName);
+
+ private:
+ Reference<XComponentContext> m_aContext;
+ ::utl::OConfigurationTreeRoot m_aConfigurationRoot;
+ ::comphelper::OInterfaceContainerHelper3<XDatabaseRegistrationsListener> m_aRegistrationListeners;
+ };
+
+ }
+
+ // DatabaseRegistrations - implementation
+ DatabaseRegistrations::DatabaseRegistrations( const Reference<XComponentContext> & _rxContext )
+ :m_aContext( _rxContext )
+ ,m_aRegistrationListeners( m_aMutex )
+ {
+ m_aConfigurationRoot = ::utl::OConfigurationTreeRoot::createWithComponentContext(
+ m_aContext, getConfigurationRootPath() );
+ }
+
+ DatabaseRegistrations::~DatabaseRegistrations()
+ {
+ }
+
+ ::utl::OConfigurationNode DatabaseRegistrations::impl_getNodeForName_nothrow( std::u16string_view _rName )
+ {
+ const Sequence< OUString > aNames( m_aConfigurationRoot.getNodeNames() );
+ for ( auto const & nodeName : aNames )
+ {
+ ::utl::OConfigurationNode aNodeForName = m_aConfigurationRoot.openNode( nodeName );
+
+ OUString sTestName;
+ OSL_VERIFY( aNodeForName.getNodeValue( getNameNodeName() ) >>= sTestName );
+ if ( sTestName == _rName )
+ return aNodeForName;
+ }
+ return ::utl::OConfigurationNode();
+ }
+
+ ::utl::OConfigurationNode DatabaseRegistrations::impl_getNodeForName_throw_must_exist(const OUString& _rName)
+ {
+ ::utl::OConfigurationNode aNodeForName( impl_getNodeForName_nothrow( _rName ) );
+
+ if (!aNodeForName.isValid())
+ {
+ throw NoSuchElementException( _rName, *this );
+ }
+
+ return aNodeForName;
+ }
+
+ ::utl::OConfigurationNode DatabaseRegistrations::impl_getNodeForName_throw_must_not_exist(const OUString& _rName)
+ {
+ ::utl::OConfigurationNode aNodeForName( impl_getNodeForName_nothrow( _rName ) );
+
+ if (aNodeForName.isValid())
+ throw ElementExistException( _rName, *this );
+
+ // make unique
+ OUString sNewNodeName = "org.openoffice." + _rName;
+ while ( m_aConfigurationRoot.hasByName( sNewNodeName ) )
+ {
+ sNewNodeName = "org.openoffice." + _rName + " 2";
+ }
+
+ ::utl::OConfigurationNode aNewNode( m_aConfigurationRoot.createNode( sNewNodeName ) );
+ aNewNode.setNodeValue( getNameNodeName(), Any( _rName ) );
+ return aNewNode;
+ }
+
+ void DatabaseRegistrations::impl_checkValidName_common(std::u16string_view _rName)
+ {
+ if ( !m_aConfigurationRoot.isValid() )
+ throw RuntimeException( OUString(), *this );
+
+ if ( _rName.empty() )
+ throw IllegalArgumentException( OUString(), *this, 1 );
+ }
+
+ ::utl::OConfigurationNode DatabaseRegistrations::impl_checkValidName_throw_must_exist(const OUString& _rName)
+ {
+ impl_checkValidName_common(_rName);
+ return impl_getNodeForName_throw_must_exist(_rName);
+ }
+
+ ::utl::OConfigurationNode DatabaseRegistrations::impl_checkValidName_throw_must_not_exist(const OUString& _rName)
+ {
+ impl_checkValidName_common(_rName);
+ return impl_getNodeForName_throw_must_not_exist(_rName);
+ }
+
+ void DatabaseRegistrations::impl_checkValidLocation_throw( std::u16string_view _rLocation )
+ {
+ if ( _rLocation.empty() )
+ throw IllegalArgumentException( OUString(), *this, 2 );
+
+ INetURLObject aURL( _rLocation );
+ if ( aURL.GetProtocol() == INetProtocol::NotValid )
+ throw IllegalArgumentException( OUString(), *this, 2 );
+ }
+
+ sal_Bool SAL_CALL DatabaseRegistrations::hasRegisteredDatabase( const OUString& Name )
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+ ::utl::OConfigurationNode aNodeForName = impl_getNodeForName_nothrow( Name );
+ return aNodeForName.isValid();
+ }
+
+ Sequence< OUString > SAL_CALL DatabaseRegistrations::getRegistrationNames()
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+ if ( !m_aConfigurationRoot.isValid() )
+ throw RuntimeException( OUString(), *this );
+
+ const Sequence< OUString > aProgrammaticNames( m_aConfigurationRoot.getNodeNames() );
+ Sequence< OUString > aDisplayNames( aProgrammaticNames.getLength() );
+ OUString* pDisplayName = aDisplayNames.getArray();
+
+ for ( auto const & name : aProgrammaticNames )
+ {
+ ::utl::OConfigurationNode aRegistrationNode = m_aConfigurationRoot.openNode( name );
+ OSL_VERIFY( aRegistrationNode.getNodeValue( getNameNodeName() ) >>= *pDisplayName );
+ ++pDisplayName;
+ }
+
+ return aDisplayNames;
+ }
+
+ OUString SAL_CALL DatabaseRegistrations::getDatabaseLocation( const OUString& Name )
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ ::utl::OConfigurationNode aNodeForName = impl_checkValidName_throw_must_exist(Name);
+
+ OUString sLocation;
+ OSL_VERIFY( aNodeForName.getNodeValue( getLocationNodeName() ) >>= sLocation );
+ sLocation = SvtPathOptions().SubstituteVariable( sLocation );
+
+ return sLocation;
+ }
+
+ void SAL_CALL DatabaseRegistrations::registerDatabaseLocation( const OUString& Name, const OUString& Location )
+ {
+ ::osl::ClearableMutexGuard aGuard( m_aMutex );
+
+ // check
+ impl_checkValidLocation_throw( Location );
+ ::utl::OConfigurationNode aDataSourceRegistration = impl_checkValidName_throw_must_not_exist(Name);
+
+ // register
+ aDataSourceRegistration.setNodeValue( getLocationNodeName(), Any( Location ) );
+ m_aConfigurationRoot.commit();
+
+ // notify
+ DatabaseRegistrationEvent aEvent( *this, Name, OUString(), Location );
+ aGuard.clear();
+ m_aRegistrationListeners.notifyEach( &XDatabaseRegistrationsListener::registeredDatabaseLocation, aEvent );
+ }
+
+ void SAL_CALL DatabaseRegistrations::revokeDatabaseLocation( const OUString& Name )
+ {
+ ::osl::ClearableMutexGuard aGuard( m_aMutex );
+
+ // check
+ ::utl::OConfigurationNode aNodeForName = impl_checkValidName_throw_must_exist(Name);
+
+ // obtain properties for notification
+ OUString sLocation;
+ OSL_VERIFY( aNodeForName.getNodeValue( getLocationNodeName() ) >>= sLocation );
+
+ // revoke
+ if ( aNodeForName.isReadonly()
+ || !m_aConfigurationRoot.removeNode( aNodeForName.getLocalName() )
+ )
+ throw IllegalAccessException( OUString(), *this );
+
+ m_aConfigurationRoot.commit();
+
+ // notify
+ DatabaseRegistrationEvent aEvent( *this, Name, sLocation, OUString() );
+ aGuard.clear();
+ m_aRegistrationListeners.notifyEach( &XDatabaseRegistrationsListener::revokedDatabaseLocation, aEvent );
+ }
+
+ void SAL_CALL DatabaseRegistrations::changeDatabaseLocation( const OUString& Name, const OUString& NewLocation )
+ {
+ ::osl::ClearableMutexGuard aGuard( m_aMutex );
+
+ // check
+ impl_checkValidLocation_throw( NewLocation );
+ ::utl::OConfigurationNode aDataSourceRegistration = impl_checkValidName_throw_must_exist(Name);
+
+ if ( aDataSourceRegistration.isReadonly() )
+ throw IllegalAccessException( OUString(), *this );
+
+ // obtain properties for notification
+ OUString sOldLocation;
+ OSL_VERIFY( aDataSourceRegistration.getNodeValue( getLocationNodeName() ) >>= sOldLocation );
+
+ // change
+ aDataSourceRegistration.setNodeValue( getLocationNodeName(), Any( NewLocation ) );
+ m_aConfigurationRoot.commit();
+
+ // notify
+ DatabaseRegistrationEvent aEvent( *this, Name, sOldLocation, NewLocation );
+ aGuard.clear();
+ m_aRegistrationListeners.notifyEach( &XDatabaseRegistrationsListener::changedDatabaseLocation, aEvent );
+ }
+
+ sal_Bool SAL_CALL DatabaseRegistrations::isDatabaseRegistrationReadOnly( const OUString& Name )
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+ ::utl::OConfigurationNode aDataSourceRegistration = impl_checkValidName_throw_must_exist(Name);
+ return aDataSourceRegistration.isReadonly();
+ }
+
+ void SAL_CALL DatabaseRegistrations::addDatabaseRegistrationsListener( const Reference< XDatabaseRegistrationsListener >& Listener )
+ {
+ if ( Listener.is() )
+ m_aRegistrationListeners.addInterface( Listener );
+ }
+
+ void SAL_CALL DatabaseRegistrations::removeDatabaseRegistrationsListener( const Reference< XDatabaseRegistrationsListener >& Listener )
+ {
+ if ( Listener.is() )
+ m_aRegistrationListeners.removeInterface( Listener );
+ }
+
+ // DatabaseRegistrations - factory
+ Reference< XAggregation > createDataSourceRegistrations( const Reference<XComponentContext> & _rxContext )
+ {
+ return new DatabaseRegistrations( _rxContext );
+ }
+
+} // namespace dbaccess
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/dataaccess/databaseregistrations.hxx b/dbaccess/source/core/dataaccess/databaseregistrations.hxx
new file mode 100644
index 000000000..709bc9f98
--- /dev/null
+++ b/dbaccess/source/core/dataaccess/databaseregistrations.hxx
@@ -0,0 +1,32 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <com/sun/star/uno/XAggregation.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+
+namespace dbaccess
+{
+css::uno::Reference<css::uno::XAggregation>
+createDataSourceRegistrations(const css::uno::Reference<css::uno::XComponentContext>& _rxContext);
+
+} // namespace dbaccess
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/dataaccess/datasource.cxx b/dbaccess/source/core/dataaccess/datasource.cxx
new file mode 100644
index 000000000..d88b661c9
--- /dev/null
+++ b/dbaccess/source/core/dataaccess/datasource.cxx
@@ -0,0 +1,1437 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "datasource.hxx"
+#include "commandcontainer.hxx"
+#include <stringconstants.hxx>
+#include <core_resource.hxx>
+#include <strings.hrc>
+#include <strings.hxx>
+#include "connection.hxx"
+#include "SharedConnection.hxx"
+#include "databasedocument.hxx"
+#include <OAuthenticationContinuation.hxx>
+
+#include <hsqlimport.hxx>
+#include <migrwarndlg.hxx>
+
+#include <com/sun/star/beans/NamedValue.hpp>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/beans/PropertyState.hpp>
+#include <com/sun/star/document/XDocumentSubStorageSupplier.hpp>
+#include <com/sun/star/lang/DisposedException.hpp>
+#include <com/sun/star/reflection/ProxyFactory.hpp>
+#include <com/sun/star/sdb/DatabaseContext.hpp>
+#include <com/sun/star/sdb/SQLContext.hpp>
+#include <com/sun/star/sdbc/ConnectionPool.hpp>
+#include <com/sun/star/sdbc/XDriverAccess.hpp>
+#include <com/sun/star/sdbc/XDriverManager.hpp>
+#include <com/sun/star/sdbc/DriverManager.hpp>
+#include <com/sun/star/ucb/AuthenticationRequest.hpp>
+#include <com/sun/star/ucb/XInteractionSupplyAuthentication.hpp>
+
+#include <cppuhelper/implbase.hxx>
+#include <comphelper/interaction.hxx>
+#include <comphelper/property.hxx>
+#include <comphelper/sequence.hxx>
+#include <comphelper/types.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <connectivity/dbexception.hxx>
+#include <connectivity/dbtools.hxx>
+#include <cppuhelper/typeprovider.hxx>
+#include <officecfg/Office/Common.hxx>
+#include <tools/diagnose_ex.h>
+#include <osl/diagnose.h>
+#include <osl/process.h>
+#include <sal/log.hxx>
+#include <tools/urlobj.hxx>
+#include <unotools/sharedunocomponent.hxx>
+#include <rtl/digest.h>
+
+#include <algorithm>
+#include <iterator>
+#include <set>
+
+#include <config_firebird.h>
+
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::sdbcx;
+using namespace ::com::sun::star::sdb;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::embed;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::util;
+using namespace ::com::sun::star::io;
+using namespace ::com::sun::star::task;
+using namespace ::com::sun::star::ucb;
+using namespace ::com::sun::star::frame;
+using namespace ::com::sun::star::reflection;
+using namespace ::cppu;
+using namespace ::osl;
+using namespace ::dbtools;
+using namespace ::comphelper;
+
+namespace dbaccess
+{
+
+namespace {
+
+/** helper class which implements a XFlushListener, and forwards all
+ notification events to another XFlushListener
+
+ The speciality is that the foreign XFlushListener instance, to which
+ the notifications are forwarded, is held weak.
+
+ Thus, the class can be used with XFlushable instance which hold
+ their listeners with a hard reference, if you simply do not *want*
+ to be held hard-ref-wise.
+*/
+class FlushNotificationAdapter : public ::cppu::WeakImplHelper< XFlushListener >
+{
+private:
+ WeakReference< XFlushable > m_aBroadcaster;
+ WeakReference< XFlushListener > m_aListener;
+
+public:
+ static void installAdapter( const Reference< XFlushable >& _rxBroadcaster, const Reference< XFlushListener >& _rxListener )
+ {
+ new FlushNotificationAdapter( _rxBroadcaster, _rxListener );
+ }
+
+protected:
+ FlushNotificationAdapter( const Reference< XFlushable >& _rxBroadcaster, const Reference< XFlushListener >& _rxListener );
+ virtual ~FlushNotificationAdapter() override;
+
+ void impl_dispose();
+
+protected:
+ // XFlushListener
+ virtual void SAL_CALL flushed( const css::lang::EventObject& rEvent ) override;
+ // XEventListener
+ virtual void SAL_CALL disposing( const css::lang::EventObject& Source ) override;
+};
+
+}
+
+FlushNotificationAdapter::FlushNotificationAdapter( const Reference< XFlushable >& _rxBroadcaster, const Reference< XFlushListener >& _rxListener )
+ :m_aBroadcaster( _rxBroadcaster )
+ ,m_aListener( _rxListener )
+{
+ OSL_ENSURE( _rxBroadcaster.is(), "FlushNotificationAdapter::FlushNotificationAdapter: invalid flushable!" );
+
+ osl_atomic_increment( &m_refCount );
+ {
+ if ( _rxBroadcaster.is() )
+ _rxBroadcaster->addFlushListener( this );
+ }
+ osl_atomic_decrement( &m_refCount );
+ OSL_ENSURE( m_refCount == 1, "FlushNotificationAdapter::FlushNotificationAdapter: broadcaster isn't holding by hard ref!?" );
+}
+
+FlushNotificationAdapter::~FlushNotificationAdapter()
+{
+}
+
+void FlushNotificationAdapter::impl_dispose()
+{
+ Reference< XFlushListener > xKeepAlive( this );
+
+ Reference< XFlushable > xFlushable( m_aBroadcaster );
+ if ( xFlushable.is() )
+ xFlushable->removeFlushListener( this );
+
+ m_aListener.clear();
+ m_aBroadcaster.clear();
+}
+
+void SAL_CALL FlushNotificationAdapter::flushed( const EventObject& rEvent )
+{
+ Reference< XFlushListener > xListener( m_aListener );
+ if ( xListener.is() )
+ xListener->flushed( rEvent );
+ else
+ impl_dispose();
+}
+
+void SAL_CALL FlushNotificationAdapter::disposing( const EventObject& Source )
+{
+ Reference< XFlushListener > xListener( m_aListener );
+ if ( xListener.is() )
+ xListener->disposing( Source );
+
+ impl_dispose();
+}
+
+OAuthenticationContinuation::OAuthenticationContinuation()
+ :m_bRememberPassword(true), // TODO: a meaningful default
+ m_bCanSetUserName(true)
+{
+}
+
+sal_Bool SAL_CALL OAuthenticationContinuation::canSetRealm( )
+{
+ return false;
+}
+
+void SAL_CALL OAuthenticationContinuation::setRealm( const OUString& /*Realm*/ )
+{
+ SAL_WARN("dbaccess","OAuthenticationContinuation::setRealm: not supported!");
+}
+
+sal_Bool SAL_CALL OAuthenticationContinuation::canSetUserName( )
+{
+ // we always allow this, even if the database document is read-only. In this case,
+ // it's simply that the user cannot store the new user name.
+ return m_bCanSetUserName;
+}
+
+void SAL_CALL OAuthenticationContinuation::setUserName( const OUString& _rUser )
+{
+ m_sUser = _rUser;
+}
+
+sal_Bool SAL_CALL OAuthenticationContinuation::canSetPassword( )
+{
+ return true;
+}
+
+void SAL_CALL OAuthenticationContinuation::setPassword( const OUString& _rPassword )
+{
+ m_sPassword = _rPassword;
+}
+
+Sequence< RememberAuthentication > SAL_CALL OAuthenticationContinuation::getRememberPasswordModes( RememberAuthentication& _reDefault )
+{
+ _reDefault = RememberAuthentication_SESSION;
+ return { _reDefault };
+}
+
+void SAL_CALL OAuthenticationContinuation::setRememberPassword( RememberAuthentication _eRemember )
+{
+ m_bRememberPassword = (RememberAuthentication_NO != _eRemember);
+}
+
+sal_Bool SAL_CALL OAuthenticationContinuation::canSetAccount( )
+{
+ return false;
+}
+
+void SAL_CALL OAuthenticationContinuation::setAccount( const OUString& )
+{
+ SAL_WARN("dbaccess","OAuthenticationContinuation::setAccount: not supported!");
+}
+
+Sequence< RememberAuthentication > SAL_CALL OAuthenticationContinuation::getRememberAccountModes( RememberAuthentication& _reDefault )
+{
+ _reDefault = RememberAuthentication_NO;
+ return { RememberAuthentication_NO };
+}
+
+void SAL_CALL OAuthenticationContinuation::setRememberAccount( RememberAuthentication /*Remember*/ )
+{
+ SAL_WARN("dbaccess","OAuthenticationContinuation::setRememberAccount: not supported!");
+}
+
+namespace {
+
+/** The class OSharedConnectionManager implements a structure to share connections.
+ It owns the master connections which will be disposed when the last connection proxy is gone.
+*/
+// need to hold the digest
+struct TDigestHolder
+{
+ sal_uInt8 m_pBuffer[RTL_DIGEST_LENGTH_SHA1];
+ TDigestHolder()
+ {
+ m_pBuffer[0] = 0;
+ }
+
+};
+
+}
+
+class OSharedConnectionManager : public ::cppu::WeakImplHelper< XEventListener >
+{
+
+ // contains the currently used master connections
+ struct TConnectionHolder
+ {
+ Reference< XConnection > xMasterConnection;
+ oslInterlockedCount nALiveCount;
+ };
+
+ // the less-compare functor, used for the stl::map
+ struct TDigestLess
+ {
+ bool operator() (const TDigestHolder& x, const TDigestHolder& y) const
+ {
+ sal_uInt32 i;
+ for(i=0;i < RTL_DIGEST_LENGTH_SHA1 && (x.m_pBuffer[i] >= y.m_pBuffer[i]); ++i)
+ ;
+ return i < RTL_DIGEST_LENGTH_SHA1;
+ }
+ };
+
+ typedef std::map< TDigestHolder,TConnectionHolder,TDigestLess> TConnectionMap; // holds the master connections
+ typedef std::map< Reference< XConnection >,TConnectionMap::iterator> TSharedConnectionMap;// holds the shared connections
+
+ ::osl::Mutex m_aMutex;
+ TConnectionMap m_aConnections; // remember the master connection in conjunction with the digest
+ TSharedConnectionMap m_aSharedConnection; // the shared connections with conjunction with an iterator into the connections map
+ Reference< XProxyFactory > m_xProxyFactory;
+
+protected:
+ virtual ~OSharedConnectionManager() override;
+
+public:
+ explicit OSharedConnectionManager(const Reference< XComponentContext >& _rxContext);
+
+ void SAL_CALL disposing( const css::lang::EventObject& Source ) override;
+ Reference<XConnection> getConnection( const OUString& url,
+ const OUString& user,
+ const OUString& password,
+ const Sequence< PropertyValue >& _aInfo,
+ ODatabaseSource* _pDataSource);
+ void addEventListener(const Reference<XConnection>& _rxConnection, TConnectionMap::iterator const & _rIter);
+};
+
+OSharedConnectionManager::OSharedConnectionManager(const Reference< XComponentContext >& _rxContext)
+{
+ m_xProxyFactory.set( ProxyFactory::create( _rxContext ) );
+}
+
+OSharedConnectionManager::~OSharedConnectionManager()
+{
+}
+
+void SAL_CALL OSharedConnectionManager::disposing( const css::lang::EventObject& Source )
+{
+ MutexGuard aGuard(m_aMutex);
+ Reference<XConnection> xConnection(Source.Source,UNO_QUERY);
+ TSharedConnectionMap::const_iterator aFind = m_aSharedConnection.find(xConnection);
+ if ( m_aSharedConnection.end() != aFind )
+ {
+ osl_atomic_decrement(&aFind->second->second.nALiveCount);
+ if ( !aFind->second->second.nALiveCount )
+ {
+ ::comphelper::disposeComponent(aFind->second->second.xMasterConnection);
+ m_aConnections.erase(aFind->second);
+ }
+ m_aSharedConnection.erase(aFind);
+ }
+}
+
+Reference<XConnection> OSharedConnectionManager::getConnection( const OUString& url,
+ const OUString& user,
+ const OUString& password,
+ const Sequence< PropertyValue >& _aInfo,
+ ODatabaseSource* _pDataSource)
+{
+ MutexGuard aGuard(m_aMutex);
+ TConnectionMap::key_type nId;
+ Sequence< PropertyValue > aInfoCopy(_aInfo);
+ sal_Int32 nPos = aInfoCopy.getLength();
+ aInfoCopy.realloc( nPos + 2 );
+ auto pInfoCopy = aInfoCopy.getArray();
+ pInfoCopy[nPos].Name = "TableFilter";
+ pInfoCopy[nPos++].Value <<= _pDataSource->m_pImpl->m_aTableFilter;
+ pInfoCopy[nPos].Name = "TableTypeFilter";
+ pInfoCopy[nPos++].Value <<= _pDataSource->m_pImpl->m_aTableTypeFilter;
+
+ OUString sUser = user;
+ OUString sPassword = password;
+ if ((sUser.isEmpty()) && (sPassword.isEmpty()) && (!_pDataSource->m_pImpl->m_sUser.isEmpty()))
+ { // ease the usage of this method. data source which are intended to have a user automatically
+ // fill in the user/password combination if the caller of this method does not specify otherwise
+ sUser = _pDataSource->m_pImpl->m_sUser;
+ if (!_pDataSource->m_pImpl->m_aPassword.isEmpty())
+ sPassword = _pDataSource->m_pImpl->m_aPassword;
+ }
+
+ ::connectivity::OConnectionWrapper::createUniqueId(url,aInfoCopy,nId.m_pBuffer,sUser,sPassword);
+ TConnectionMap::iterator aIter = m_aConnections.find(nId);
+
+ if ( m_aConnections.end() == aIter )
+ {
+ TConnectionHolder aHolder;
+ aHolder.nALiveCount = 0; // will be incremented by addListener
+ aHolder.xMasterConnection = _pDataSource->buildIsolatedConnection(user,password);
+ aIter = m_aConnections.emplace(nId,aHolder).first;
+ }
+
+ Reference<XConnection> xRet;
+ if ( aIter->second.xMasterConnection.is() )
+ {
+ Reference< XAggregation > xConProxy = m_xProxyFactory->createProxy(aIter->second.xMasterConnection);
+ xRet = new OSharedConnection(xConProxy);
+ m_aSharedConnection.emplace(xRet,aIter);
+ addEventListener(xRet,aIter);
+ }
+
+ return xRet;
+}
+
+void OSharedConnectionManager::addEventListener(const Reference<XConnection>& _rxConnection, TConnectionMap::iterator const & _rIter)
+{
+ Reference<XComponent> xComp(_rxConnection,UNO_QUERY);
+ xComp->addEventListener(this);
+ OSL_ENSURE( m_aConnections.end() != _rIter , "Iterator is end!");
+ osl_atomic_increment(&_rIter->second.nALiveCount);
+}
+
+namespace
+{
+ Sequence< PropertyValue > lcl_filterDriverProperties( const Reference< XDriver >& _xDriver, const OUString& _sUrl,
+ const Sequence< PropertyValue >& _rDataSourceSettings, const AsciiPropertyValue* _pKnownSettings )
+ {
+ if ( _xDriver.is() )
+ {
+ Sequence< DriverPropertyInfo > aDriverInfo(_xDriver->getPropertyInfo(_sUrl,_rDataSourceSettings));
+
+ const PropertyValue* pDataSourceSetting = _rDataSourceSettings.getConstArray();
+ const PropertyValue* pEnd = pDataSourceSetting + _rDataSourceSettings.getLength();
+
+ std::vector< PropertyValue > aRet;
+
+ for ( ; pDataSourceSetting != pEnd ; ++pDataSourceSetting )
+ {
+ bool bAllowSetting = false;
+ const AsciiPropertyValue* pSetting = _pKnownSettings;
+ for ( ; pSetting->AsciiName; ++pSetting )
+ {
+ if ( pDataSourceSetting->Name.equalsAscii( pSetting->AsciiName ) )
+ { // the particular data source setting is known
+
+ const DriverPropertyInfo* pAllowedDriverSetting = aDriverInfo.getConstArray();
+ const DriverPropertyInfo* pDriverSettingsEnd = pAllowedDriverSetting + aDriverInfo.getLength();
+ for ( ; pAllowedDriverSetting != pDriverSettingsEnd; ++pAllowedDriverSetting )
+ {
+ if ( pAllowedDriverSetting->Name.equalsAscii( pSetting->AsciiName ) )
+ { // the driver also allows this setting
+ bAllowSetting = true;
+ break;
+ }
+ }
+ break;
+ }
+ }
+ if ( bAllowSetting || !pSetting->AsciiName )
+ { // if the driver allows this particular setting, or if the setting is completely unknown,
+ // we pass it to the driver
+ aRet.push_back( *pDataSourceSetting );
+ }
+ }
+ if ( !aRet.empty() )
+ return comphelper::containerToSequence(aRet);
+ }
+ return Sequence< PropertyValue >();
+ }
+
+ typedef std::map< OUString, sal_Int32 > PropertyAttributeCache;
+
+ struct IsDefaultAndNotRemoveable
+ {
+ private:
+ const PropertyAttributeCache& m_rAttribs;
+
+ public:
+ explicit IsDefaultAndNotRemoveable( const PropertyAttributeCache& _rAttribs ) : m_rAttribs( _rAttribs ) { }
+
+ bool operator()( const PropertyValue& _rProp )
+ {
+ if ( _rProp.State != PropertyState_DEFAULT_VALUE )
+ return false;
+
+ bool bRemoveable = true;
+
+ PropertyAttributeCache::const_iterator pos = m_rAttribs.find( _rProp.Name );
+ OSL_ENSURE( pos != m_rAttribs.end(), "IsDefaultAndNotRemoveable: illegal property name!" );
+ if ( pos != m_rAttribs.end() )
+ bRemoveable = ( ( pos->second & PropertyAttribute::REMOVABLE ) != 0 );
+
+ return !bRemoveable;
+ }
+ };
+}
+
+
+ODatabaseSource::ODatabaseSource(const ::rtl::Reference<ODatabaseModelImpl>& _pImpl)
+ :ModelDependentComponent( _pImpl )
+ ,ODatabaseSource_Base( getMutex() )
+ ,OPropertySetHelper( ODatabaseSource_Base::rBHelper )
+ , m_Bookmarks(*this, getMutex())
+ ,m_aFlushListeners( getMutex() )
+{
+ // some kind of default
+ SAL_INFO("dbaccess", "DS: ctor: " << std::hex << this << ": " << std::hex << m_pImpl.get() );
+}
+
+ODatabaseSource::~ODatabaseSource()
+{
+ SAL_INFO("dbaccess", "DS: dtor: " << std::hex << this << ": " << std::hex << m_pImpl.get() );
+ if ( !ODatabaseSource_Base::rBHelper.bInDispose && !ODatabaseSource_Base::rBHelper.bDisposed )
+ {
+ acquire();
+ dispose();
+ }
+}
+
+void ODatabaseSource::setName( const Reference< XDocumentDataSource >& _rxDocument, const OUString& _rNewName, DBContextAccess )
+{
+ ODatabaseSource& rModelImpl = dynamic_cast< ODatabaseSource& >( *_rxDocument );
+
+ SolarMutexGuard g;
+ if ( rModelImpl.m_pImpl.is() )
+ rModelImpl.m_pImpl->m_sName = _rNewName;
+}
+
+// css::lang::XTypeProvider
+Sequence< Type > ODatabaseSource::getTypes()
+{
+ OTypeCollection aPropertyHelperTypes( cppu::UnoType<XFastPropertySet>::get(),
+ cppu::UnoType<XPropertySet>::get(),
+ cppu::UnoType<XMultiPropertySet>::get());
+
+ return ::comphelper::concatSequences(
+ ODatabaseSource_Base::getTypes(),
+ aPropertyHelperTypes.getTypes()
+ );
+}
+
+Sequence< sal_Int8 > ODatabaseSource::getImplementationId()
+{
+ return css::uno::Sequence<sal_Int8>();
+}
+
+// css::uno::XInterface
+Any ODatabaseSource::queryInterface( const Type & rType )
+{
+ Any aIface = ODatabaseSource_Base::queryInterface( rType );
+ if ( !aIface.hasValue() )
+ aIface = ::cppu::OPropertySetHelper::queryInterface( rType );
+ return aIface;
+}
+
+void ODatabaseSource::acquire() noexcept
+{
+ ODatabaseSource_Base::acquire();
+}
+
+void ODatabaseSource::release() noexcept
+{
+ ODatabaseSource_Base::release();
+}
+
+void SAL_CALL ODatabaseSource::disposing( const css::lang::EventObject& Source )
+{
+ if ( m_pImpl.is() )
+ m_pImpl->disposing(Source);
+}
+
+// XServiceInfo
+OUString ODatabaseSource::getImplementationName( )
+{
+ return "com.sun.star.comp.dba.ODatabaseSource";
+}
+
+Sequence< OUString > ODatabaseSource::getSupportedServiceNames( )
+{
+ return { SERVICE_SDB_DATASOURCE, "com.sun.star.sdb.DocumentDataSource" };
+}
+
+sal_Bool ODatabaseSource::supportsService( const OUString& _rServiceName )
+{
+ return cppu::supportsService(this, _rServiceName);
+}
+
+// OComponentHelper
+void ODatabaseSource::disposing()
+{
+ SAL_INFO("dbaccess", "DS: disp: " << std::hex << this << ", " << std::hex << m_pImpl.get() );
+ ODatabaseSource_Base::WeakComponentImplHelperBase::disposing();
+ OPropertySetHelper::disposing();
+
+ EventObject aDisposeEvent(static_cast<XWeak*>(this));
+ m_aFlushListeners.disposeAndClear( aDisposeEvent );
+
+ ODatabaseDocument::clearObjectContainer(m_pImpl->m_xCommandDefinitions);
+ ODatabaseDocument::clearObjectContainer(m_pImpl->m_xTableDefinitions);
+ m_pImpl.clear();
+}
+
+weld::Window* ODatabaseModelImpl::GetFrameWeld()
+{
+ if (m_xDialogParent.is())
+ return Application::GetFrameWeld(m_xDialogParent);
+
+ Reference<XModel> xModel = getModel_noCreate();
+ if (!xModel.is())
+ return nullptr;
+ Reference<XController> xController(xModel->getCurrentController());
+ if (!xController.is())
+ return nullptr;
+ Reference<XFrame> xFrame(xController->getFrame());
+ if (!xFrame.is())
+ return nullptr;
+ Reference<css::awt::XWindow> xWindow(xFrame->getContainerWindow());
+ return Application::GetFrameWeld(xWindow);
+}
+
+Reference< XConnection > ODatabaseSource::buildLowLevelConnection(const OUString& _rUid, const OUString& _rPwd)
+{
+ Reference< XConnection > xReturn;
+
+ Reference< XDriverManager > xManager;
+
+#if ENABLE_FIREBIRD_SDBC
+ bool bIgnoreMigration = false;
+ bool bNeedMigration = false;
+ Reference< XModel > xModel = m_pImpl->getModel_noCreate();
+ if ( xModel)
+ {
+ //See ODbTypeWizDialogSetup::SaveDatabaseDocument
+ ::comphelper::NamedValueCollection::get(xModel->getArgs(), u"IgnoreFirebirdMigration") >>= bIgnoreMigration;
+ }
+ else
+ {
+ //ignore when we don't have a model. E.g. Mailmerge, data sources, fields...
+ bIgnoreMigration = true;
+ }
+
+ if (!officecfg::Office::Common::Misc::ExperimentalMode::get())
+ bIgnoreMigration = true;
+
+ if(!bIgnoreMigration && m_pImpl->m_sConnectURL == "sdbc:embedded:hsqldb")
+ {
+ Reference<XStorage> const xRootStorage = m_pImpl->getOrCreateRootStorage();
+ OUString sMigrEnvVal;
+ osl_getEnvironment(OUString("DBACCESS_HSQL_MIGRATION").pData,
+ &sMigrEnvVal.pData);
+ if(!sMigrEnvVal.isEmpty())
+ bNeedMigration = true;
+ else
+ {
+ Reference<XPropertySet> const xPropSet(xRootStorage, UNO_QUERY_THROW);
+ sal_Int32 nOpenMode(0);
+ if ((xPropSet->getPropertyValue("OpenMode") >>= nOpenMode)
+ && (nOpenMode & css::embed::ElementModes::WRITE)
+ && (!Application::IsHeadlessModeEnabled()))
+ {
+ MigrationWarnDialog aWarnDlg(m_pImpl->GetFrameWeld());
+ bNeedMigration = aWarnDlg.run() == RET_OK;
+ }
+ }
+ if (bNeedMigration)
+ {
+ // back up content xml file if migration was successful
+ static constexpr OUStringLiteral BACKUP_XML_NAME = u"content_before_migration.xml";
+ try
+ {
+ if(xRootStorage->isStreamElement(BACKUP_XML_NAME))
+ xRootStorage->removeElement(BACKUP_XML_NAME);
+ }
+ catch (NoSuchElementException&)
+ {
+ SAL_INFO("dbaccess", "No file content_before_migration.xml found" );
+ }
+ xRootStorage->copyElementTo("content.xml", xRootStorage,
+ BACKUP_XML_NAME);
+
+ m_pImpl->m_sConnectURL = "sdbc:embedded:firebird";
+ }
+ }
+#endif
+
+ try {
+ xManager.set( ConnectionPool::create( m_pImpl->m_aContext ), UNO_QUERY_THROW );
+ } catch( const Exception& ) { }
+ if ( !xManager.is() )
+ // no connection pool installed, fall back to driver manager
+ xManager.set( DriverManager::create(m_pImpl->m_aContext ), UNO_QUERY_THROW );
+
+ OUString sUser(_rUid);
+ OUString sPwd(_rPwd);
+ if ((sUser.isEmpty()) && (sPwd.isEmpty()) && (!m_pImpl->m_sUser.isEmpty()))
+ { // ease the usage of this method. data source which are intended to have a user automatically
+ // fill in the user/password combination if the caller of this method does not specify otherwise
+ sUser = m_pImpl->m_sUser;
+ if (!m_pImpl->m_aPassword.isEmpty())
+ sPwd = m_pImpl->m_aPassword;
+ }
+
+ TranslateId pExceptionMessageId = RID_STR_COULDNOTCONNECT_UNSPECIFIED;
+ if (xManager.is())
+ {
+ sal_Int32 nAdditionalArgs(0);
+ if (!sUser.isEmpty()) ++nAdditionalArgs;
+ if (!sPwd.isEmpty()) ++nAdditionalArgs;
+
+ Sequence< PropertyValue > aUserPwd(nAdditionalArgs);
+ auto aUserPwdRange = asNonConstRange(aUserPwd);
+ sal_Int32 nArgPos = 0;
+ if (!sUser.isEmpty())
+ {
+ aUserPwdRange[ nArgPos ].Name = "user";
+ aUserPwdRange[ nArgPos ].Value <<= sUser;
+ ++nArgPos;
+ }
+ if (!sPwd.isEmpty())
+ {
+ aUserPwdRange[ nArgPos ].Name = "password";
+ aUserPwdRange[ nArgPos ].Value <<= sPwd;
+ }
+ Reference< XDriver > xDriver;
+ try
+ {
+
+ // choose driver
+ Reference< XDriverAccess > xAccessDrivers( xManager, UNO_QUERY );
+ if ( xAccessDrivers.is() )
+ xDriver = xAccessDrivers->getDriverByURL( m_pImpl->m_sConnectURL );
+ }
+ catch( const Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("dbaccess", "ODatabaseSource::buildLowLevelConnection: got a strange exception while analyzing the error" );
+ }
+ if ( !xDriver.is() || !xDriver->acceptsURL( m_pImpl->m_sConnectURL ) )
+ {
+ // Nowadays, it's allowed for a driver to be registered for a given URL, but actually not to accept it.
+ // This is because registration nowadays happens at compile time (by adding respective configuration data),
+ // but acceptance is decided at runtime.
+ pExceptionMessageId = RID_STR_COULDNOTCONNECT_NODRIVER;
+ }
+ else
+ {
+ Sequence< PropertyValue > aDriverInfo = lcl_filterDriverProperties(
+ xDriver,
+ m_pImpl->m_sConnectURL,
+ m_pImpl->m_xSettings->getPropertyValues(),
+ dbaccess::ODatabaseModelImpl::getDefaultDataSourceSettings()
+ );
+
+ if ( m_pImpl->isEmbeddedDatabase() )
+ {
+ sal_Int32 nCount = aDriverInfo.getLength();
+ aDriverInfo.realloc(nCount + 3 );
+ auto pDriverInfo = aDriverInfo.getArray();
+
+ pDriverInfo[nCount].Name = "URL";
+ pDriverInfo[nCount++].Value <<= m_pImpl->getURL();
+
+ pDriverInfo[nCount].Name = "Storage";
+ Reference< css::document::XDocumentSubStorageSupplier> xDocSup( m_pImpl->getDocumentSubStorageSupplier() );
+ pDriverInfo[nCount++].Value <<= xDocSup->getDocumentSubStorage("database",ElementModes::READWRITE);
+
+ pDriverInfo[nCount].Name = "Document";
+ pDriverInfo[nCount++].Value <<= getDatabaseDocument();
+ }
+ if (nAdditionalArgs)
+ xReturn = xManager->getConnectionWithInfo(m_pImpl->m_sConnectURL, ::comphelper::concatSequences(aUserPwd,aDriverInfo));
+ else
+ xReturn = xManager->getConnectionWithInfo(m_pImpl->m_sConnectURL,aDriverInfo);
+
+ if ( m_pImpl->isEmbeddedDatabase() )
+ {
+ // see ODatabaseSource::flushed for comment on why we register as FlushListener
+ // at the connection
+ Reference< XFlushable > xFlushable( xReturn, UNO_QUERY );
+ if ( xFlushable.is() )
+ FlushNotificationAdapter::installAdapter( xFlushable, this );
+ }
+ }
+ }
+ else
+ pExceptionMessageId = RID_STR_COULDNOTLOAD_MANAGER;
+
+ if ( !xReturn.is() )
+ {
+ OUString sMessage = DBA_RES(pExceptionMessageId)
+ .replaceAll("$name$", m_pImpl->m_sConnectURL);
+
+ SQLContext aContext;
+ aContext.Message = DBA_RES(RID_STR_CONNECTION_REQUEST).
+ replaceFirst("$name$", m_pImpl->m_sConnectURL);
+
+ throwGenericSQLException( sMessage, static_cast< XDataSource* >( this ), Any( aContext ) );
+ }
+
+#if ENABLE_FIREBIRD_SDBC
+ if( bNeedMigration )
+ {
+ Reference< css::document::XDocumentSubStorageSupplier> xDocSup(
+ m_pImpl->getDocumentSubStorageSupplier() );
+ dbahsql::HsqlImporter importer(xReturn,
+ xDocSup->getDocumentSubStorage("database",ElementModes::READWRITE) );
+ importer.importHsqlDatabase(m_pImpl->GetFrameWeld());
+ }
+#endif
+
+ return xReturn;
+}
+
+// OPropertySetHelper
+Reference< XPropertySetInfo > ODatabaseSource::getPropertySetInfo()
+{
+ return createPropertySetInfo( getInfoHelper() ) ;
+}
+
+// comphelper::OPropertyArrayUsageHelper
+::cppu::IPropertyArrayHelper* ODatabaseSource::createArrayHelper( ) const
+{
+ return new ::cppu::OPropertyArrayHelper
+ {
+ {
+ { PROPERTY_INFO, PROPERTY_ID_INFO, cppu::UnoType<Sequence< PropertyValue >>::get(), css::beans::PropertyAttribute::BOUND },
+ { PROPERTY_ISPASSWORDREQUIRED, PROPERTY_ID_ISPASSWORDREQUIRED, cppu::UnoType<bool>::get(), css::beans::PropertyAttribute::BOUND },
+ { PROPERTY_ISREADONLY, PROPERTY_ID_ISREADONLY, cppu::UnoType<bool>::get(), css::beans::PropertyAttribute::READONLY },
+ { PROPERTY_LAYOUTINFORMATION, PROPERTY_ID_LAYOUTINFORMATION, cppu::UnoType<Sequence< PropertyValue >>::get(), css::beans::PropertyAttribute::BOUND },
+ { PROPERTY_NAME, PROPERTY_ID_NAME, cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::READONLY },
+ { PROPERTY_NUMBERFORMATSSUPPLIER, PROPERTY_ID_NUMBERFORMATSSUPPLIER, cppu::UnoType<XNumberFormatsSupplier>::get(),
+ css::beans::PropertyAttribute::READONLY | css::beans::PropertyAttribute::TRANSIENT },
+ { PROPERTY_PASSWORD, PROPERTY_ID_PASSWORD, cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::TRANSIENT },
+ { PROPERTY_SETTINGS, PROPERTY_ID_SETTINGS, cppu::UnoType<XPropertySet>::get(), css::beans::PropertyAttribute::BOUND | css::beans::PropertyAttribute::READONLY },
+ { PROPERTY_SUPPRESSVERSIONCL, PROPERTY_ID_SUPPRESSVERSIONCL, cppu::UnoType<bool>::get(), css::beans::PropertyAttribute::BOUND },
+ { PROPERTY_TABLEFILTER, PROPERTY_ID_TABLEFILTER, cppu::UnoType<Sequence< OUString >>::get(), css::beans::PropertyAttribute::BOUND },
+ { PROPERTY_TABLETYPEFILTER, PROPERTY_ID_TABLETYPEFILTER, cppu::UnoType<Sequence< OUString >>::get(), css::beans::PropertyAttribute::BOUND },
+ { PROPERTY_URL, PROPERTY_ID_URL, cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::BOUND },
+ { PROPERTY_USER, PROPERTY_ID_USER, cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::BOUND }
+ }
+ };
+}
+
+// cppu::OPropertySetHelper
+::cppu::IPropertyArrayHelper& ODatabaseSource::getInfoHelper()
+{
+ return *getArrayHelper();
+}
+
+sal_Bool ODatabaseSource::convertFastPropertyValue(Any & rConvertedValue, Any & rOldValue, sal_Int32 nHandle, const Any& rValue )
+{
+ bool bModified(false);
+ if ( m_pImpl.is() )
+ {
+ switch (nHandle)
+ {
+ case PROPERTY_ID_TABLEFILTER:
+ bModified = ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, m_pImpl->m_aTableFilter);
+ break;
+ case PROPERTY_ID_TABLETYPEFILTER:
+ bModified = ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, m_pImpl->m_aTableTypeFilter);
+ break;
+ case PROPERTY_ID_USER:
+ bModified = ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, m_pImpl->m_sUser);
+ break;
+ case PROPERTY_ID_PASSWORD:
+ bModified = ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, m_pImpl->m_aPassword);
+ break;
+ case PROPERTY_ID_ISPASSWORDREQUIRED:
+ bModified = ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, m_pImpl->m_bPasswordRequired);
+ break;
+ case PROPERTY_ID_SUPPRESSVERSIONCL:
+ bModified = ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, m_pImpl->m_bSuppressVersionColumns);
+ break;
+ case PROPERTY_ID_LAYOUTINFORMATION:
+ bModified = ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, m_pImpl->m_aLayoutInformation);
+ break;
+ case PROPERTY_ID_URL:
+ {
+ bModified = ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, m_pImpl->m_sConnectURL);
+ } break;
+ case PROPERTY_ID_INFO:
+ {
+ Sequence<PropertyValue> aValues;
+ if (!(rValue >>= aValues))
+ throw IllegalArgumentException();
+
+ for ( auto const & checkName : std::as_const(aValues) )
+ {
+ if ( checkName.Name.isEmpty() )
+ throw IllegalArgumentException();
+ }
+
+ Sequence< PropertyValue > aSettings = m_pImpl->m_xSettings->getPropertyValues();
+ bModified = aSettings.getLength() != aValues.getLength();
+ if ( !bModified )
+ {
+ const PropertyValue* pInfoIter = aSettings.getConstArray();
+ const PropertyValue* checkValue = aValues.getConstArray();
+ for ( ;!bModified && checkValue != std::cend(aValues) ; ++checkValue,++pInfoIter)
+ {
+ bModified = checkValue->Name != pInfoIter->Name;
+ if ( !bModified )
+ {
+ bModified = checkValue->Value != pInfoIter->Value;
+ }
+ }
+ }
+
+ rConvertedValue = rValue;
+ rOldValue <<= aSettings;
+ }
+ break;
+ default:
+ SAL_WARN("dbaccess", "ODatabaseSource::convertFastPropertyValue: unknown or readonly Property!" );
+ }
+ }
+ return bModified;
+}
+
+namespace
+{
+ struct SelectPropertyName
+ {
+ public:
+ const OUString& operator()( const PropertyValue& _lhs )
+ {
+ return _lhs.Name;
+ }
+ };
+
+ /** sets a new set of property values for a given property bag instance
+
+ The method takes a property bag, and a sequence of property values to set for this bag.
+ Upon return, every property which is not part of the given sequence is
+ <ul><li>removed from the bag, if it's a removable property</li>
+ <li><em>or</em>reset to its default value, if it's not a removable property</li>
+ </ul>.
+
+ @param _rxPropertyBag
+ the property bag to operate on
+ @param _rAllNewPropertyValues
+ the new property values to set for the bag
+ */
+ void lcl_setPropertyValues_resetOrRemoveOther( const Reference< XPropertyBag >& _rxPropertyBag, const Sequence< PropertyValue >& _rAllNewPropertyValues )
+ {
+ // sequences are ugly to operate on
+ std::set<OUString> aToBeSetPropertyNames;
+ std::transform(
+ _rAllNewPropertyValues.begin(),
+ _rAllNewPropertyValues.end(),
+ std::inserter( aToBeSetPropertyNames, aToBeSetPropertyNames.end() ),
+ SelectPropertyName()
+ );
+
+ try
+ {
+ // obtain all properties currently known at the bag
+ Reference< XPropertySetInfo > xPSI( _rxPropertyBag->getPropertySetInfo(), UNO_SET_THROW );
+ const Sequence< Property > aAllExistentProperties( xPSI->getProperties() );
+
+ Reference< XPropertyState > xPropertyState( _rxPropertyBag, UNO_QUERY_THROW );
+
+ // loop through them, and reset resp. default properties which are not to be set
+ for ( auto const & existentProperty : aAllExistentProperties )
+ {
+ if ( aToBeSetPropertyNames.find( existentProperty.Name ) != aToBeSetPropertyNames.end() )
+ continue;
+
+ // this property is not to be set, but currently exists in the bag.
+ // -> Remove it, or reset it to the default.
+ if ( ( existentProperty.Attributes & PropertyAttribute::REMOVABLE ) != 0 )
+ _rxPropertyBag->removeProperty( existentProperty.Name );
+ else
+ xPropertyState->setPropertyToDefault( existentProperty.Name );
+ }
+
+ // finally, set the new property values
+ _rxPropertyBag->setPropertyValues( _rAllNewPropertyValues );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+}
+
+void ODatabaseSource::setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const Any& rValue )
+{
+ if ( !m_pImpl.is() )
+ return;
+
+ switch(nHandle)
+ {
+ case PROPERTY_ID_TABLEFILTER:
+ rValue >>= m_pImpl->m_aTableFilter;
+ break;
+ case PROPERTY_ID_TABLETYPEFILTER:
+ rValue >>= m_pImpl->m_aTableTypeFilter;
+ break;
+ case PROPERTY_ID_USER:
+ rValue >>= m_pImpl->m_sUser;
+ // if the user name has changed, reset the password
+ m_pImpl->m_aPassword.clear();
+ break;
+ case PROPERTY_ID_PASSWORD:
+ rValue >>= m_pImpl->m_aPassword;
+ break;
+ case PROPERTY_ID_ISPASSWORDREQUIRED:
+ m_pImpl->m_bPasswordRequired = any2bool(rValue);
+ break;
+ case PROPERTY_ID_SUPPRESSVERSIONCL:
+ m_pImpl->m_bSuppressVersionColumns = any2bool(rValue);
+ break;
+ case PROPERTY_ID_URL:
+ rValue >>= m_pImpl->m_sConnectURL;
+ break;
+ case PROPERTY_ID_INFO:
+ {
+ Sequence< PropertyValue > aInfo;
+ OSL_VERIFY( rValue >>= aInfo );
+ lcl_setPropertyValues_resetOrRemoveOther( m_pImpl->m_xSettings, aInfo );
+ }
+ break;
+ case PROPERTY_ID_LAYOUTINFORMATION:
+ rValue >>= m_pImpl->m_aLayoutInformation;
+ break;
+ }
+ m_pImpl->setModified(true);
+}
+
+void ODatabaseSource::getFastPropertyValue( Any& rValue, sal_Int32 nHandle ) const
+{
+ if ( !m_pImpl.is() )
+ return;
+
+ switch (nHandle)
+ {
+ case PROPERTY_ID_TABLEFILTER:
+ rValue <<= m_pImpl->m_aTableFilter;
+ break;
+ case PROPERTY_ID_TABLETYPEFILTER:
+ rValue <<= m_pImpl->m_aTableTypeFilter;
+ break;
+ case PROPERTY_ID_USER:
+ rValue <<= m_pImpl->m_sUser;
+ break;
+ case PROPERTY_ID_PASSWORD:
+ rValue <<= m_pImpl->m_aPassword;
+ break;
+ case PROPERTY_ID_ISPASSWORDREQUIRED:
+ rValue <<= m_pImpl->m_bPasswordRequired;
+ break;
+ case PROPERTY_ID_SUPPRESSVERSIONCL:
+ rValue <<= m_pImpl->m_bSuppressVersionColumns;
+ break;
+ case PROPERTY_ID_ISREADONLY:
+ rValue <<= m_pImpl->m_bReadOnly;
+ break;
+ case PROPERTY_ID_INFO:
+ {
+ try
+ {
+ // collect the property attributes of all current settings
+ Reference< XPropertySet > xSettingsAsProps( m_pImpl->m_xSettings, UNO_QUERY_THROW );
+ Reference< XPropertySetInfo > xPST( xSettingsAsProps->getPropertySetInfo(), UNO_SET_THROW );
+ const Sequence< Property > aSettings( xPST->getProperties() );
+ std::map< OUString, sal_Int32 > aPropertyAttributes;
+ for ( auto const & setting : aSettings )
+ {
+ aPropertyAttributes[ setting.Name ] = setting.Attributes;
+ }
+
+ // get all current settings with their values
+ Sequence< PropertyValue > aValues( m_pImpl->m_xSettings->getPropertyValues() );
+
+ // transform them so that only property values which fulfill certain
+ // criteria survive
+ Sequence< PropertyValue > aNonDefaultOrUserDefined( aValues.getLength() );
+ auto [begin, end] = asNonConstRange(aValues);
+ auto pCopyStart = aNonDefaultOrUserDefined.getArray();
+ const PropertyValue* pCopyEnd = std::remove_copy_if(
+ begin,
+ end,
+ pCopyStart,
+ IsDefaultAndNotRemoveable( aPropertyAttributes )
+ );
+ aNonDefaultOrUserDefined.realloc( pCopyEnd - pCopyStart );
+ rValue <<= aNonDefaultOrUserDefined;
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+ break;
+ case PROPERTY_ID_SETTINGS:
+ rValue <<= m_pImpl->m_xSettings;
+ break;
+ case PROPERTY_ID_URL:
+ rValue <<= m_pImpl->m_sConnectURL;
+ break;
+ case PROPERTY_ID_NUMBERFORMATSSUPPLIER:
+ rValue <<= m_pImpl->getNumberFormatsSupplier();
+ break;
+ case PROPERTY_ID_NAME:
+ rValue <<= m_pImpl->m_sName;
+ break;
+ case PROPERTY_ID_LAYOUTINFORMATION:
+ rValue <<= m_pImpl->m_aLayoutInformation;
+ break;
+ default:
+ SAL_WARN("dbaccess","unknown Property");
+ }
+}
+
+// XDataSource
+void ODatabaseSource::setLoginTimeout(sal_Int32 seconds)
+{
+ ModelMethodGuard aGuard( *this );
+ m_pImpl->m_nLoginTimeout = seconds;
+}
+
+sal_Int32 ODatabaseSource::getLoginTimeout()
+{
+ ModelMethodGuard aGuard( *this );
+ return m_pImpl->m_nLoginTimeout;
+}
+
+// XCompletedConnection
+Reference< XConnection > SAL_CALL ODatabaseSource::connectWithCompletion( const Reference< XInteractionHandler >& _rxHandler )
+{
+ return connectWithCompletion(_rxHandler,false);
+}
+
+Reference< XConnection > ODatabaseSource::getConnection(const OUString& user, const OUString& password)
+{
+ return getConnection(user,password,false);
+}
+
+Reference< XConnection > SAL_CALL ODatabaseSource::getIsolatedConnection( const OUString& user, const OUString& password )
+{
+ return getConnection(user,password,true);
+}
+
+Reference< XConnection > SAL_CALL ODatabaseSource::getIsolatedConnectionWithCompletion( const Reference< XInteractionHandler >& _rxHandler )
+{
+ return connectWithCompletion(_rxHandler,true);
+}
+
+Reference< XConnection > ODatabaseSource::connectWithCompletion( const Reference< XInteractionHandler >& _rxHandler,bool _bIsolated )
+{
+ ModelMethodGuard aGuard( *this );
+
+ if (!_rxHandler.is())
+ {
+ SAL_WARN("dbaccess","ODatabaseSource::connectWithCompletion: invalid interaction handler!");
+ return getConnection(m_pImpl->m_sUser, m_pImpl->m_aPassword,_bIsolated);
+ }
+
+ OUString sUser(m_pImpl->m_sUser), sPassword(m_pImpl->m_aPassword);
+ bool bNewPasswordGiven = false;
+
+ if (m_pImpl->m_bPasswordRequired && sPassword.isEmpty())
+ { // we need a password, but don't have one yet.
+ // -> ask the user
+
+ // build an interaction request
+ // two continuations (Ok and Cancel)
+ rtl::Reference<OInteractionAbort> pAbort = new OInteractionAbort;
+ rtl::Reference<OAuthenticationContinuation> pAuthenticate = new OAuthenticationContinuation;
+
+ // the name which should be referred in the login dialog
+ OUString sServerName( m_pImpl->m_sName );
+ INetURLObject aURLCheck( sServerName );
+ if ( aURLCheck.GetProtocol() != INetProtocol::NotValid )
+ sServerName = aURLCheck.getBase( INetURLObject::LAST_SEGMENT, true, INetURLObject::DecodeMechanism::Unambiguous );
+
+ // the request
+ AuthenticationRequest aRequest;
+ aRequest.ServerName = sServerName;
+ aRequest.HasRealm = aRequest.HasAccount = false;
+ aRequest.HasUserName = aRequest.HasPassword = true;
+ aRequest.UserName = m_pImpl->m_sUser;
+ aRequest.Password = m_pImpl->m_sFailedPassword.isEmpty() ? m_pImpl->m_aPassword : m_pImpl->m_sFailedPassword;
+ rtl::Reference<OInteractionRequest> pRequest = new OInteractionRequest(Any(aRequest));
+ // some knittings
+ pRequest->addContinuation(pAbort);
+ pRequest->addContinuation(pAuthenticate);
+
+ // handle the request
+ try
+ {
+ _rxHandler->handle(pRequest);
+ }
+ catch(Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+
+ if (!pAuthenticate->wasSelected())
+ return Reference< XConnection >();
+
+ // get the result
+ sUser = m_pImpl->m_sUser = pAuthenticate->getUser();
+ sPassword = pAuthenticate->getPassword();
+
+ if (pAuthenticate->getRememberPassword())
+ {
+ m_pImpl->m_aPassword = pAuthenticate->getPassword();
+ bNewPasswordGiven = true;
+ }
+ m_pImpl->m_sFailedPassword.clear();
+ }
+
+ try
+ {
+ return getConnection(sUser, sPassword,_bIsolated);
+ }
+ catch(Exception&)
+ {
+ if (bNewPasswordGiven)
+ {
+ m_pImpl->m_sFailedPassword = m_pImpl->m_aPassword;
+ // assume that we had an authentication problem. Without this we may, after an unsuccessful connect, while
+ // the user gave us a password and the order to remember it, never allow a password input again (at least
+ // not without restarting the session)
+ m_pImpl->m_aPassword.clear();
+ }
+ throw;
+ }
+}
+
+Reference< XConnection > ODatabaseSource::buildIsolatedConnection(const OUString& user, const OUString& password)
+{
+ Reference< XConnection > xConn;
+ Reference< XConnection > xSdbcConn = buildLowLevelConnection(user, password);
+ OSL_ENSURE( xSdbcConn.is(), "ODatabaseSource::buildIsolatedConnection: invalid return value of buildLowLevelConnection!" );
+ // buildLowLevelConnection is expected to always succeed
+ if ( xSdbcConn.is() )
+ {
+ // build a connection server and return it (no stubs)
+ xConn = new OConnection(*this, xSdbcConn, m_pImpl->m_aContext);
+ }
+ return xConn;
+}
+
+Reference< XConnection > ODatabaseSource::getConnection(const OUString& user, const OUString& password,bool _bIsolated)
+{
+ ModelMethodGuard aGuard( *this );
+
+ Reference< XConnection > xConn;
+ if ( _bIsolated )
+ {
+ xConn = buildIsolatedConnection(user,password);
+ }
+ else
+ { // create a new proxy for the connection
+ if ( !m_pImpl->m_xSharedConnectionManager.is() )
+ {
+ // TODO ideally we could just have one field, but to make that work
+ // we'd need to move OSharedConnectionManager into its own file and header
+ rtl::Reference<OSharedConnectionManager> manager =
+ new OSharedConnectionManager( m_pImpl->m_aContext );
+ m_pImpl->m_pSharedConnectionManager = manager.get();
+ m_pImpl->m_xSharedConnectionManager = m_pImpl->m_pSharedConnectionManager;
+ }
+ xConn = m_pImpl->m_pSharedConnectionManager->getConnection(
+ m_pImpl->m_sConnectURL, user, password, m_pImpl->m_xSettings->getPropertyValues(), this );
+ }
+
+ if ( xConn.is() )
+ {
+ Reference< XComponent> xComp(xConn,UNO_QUERY);
+ if ( xComp.is() )
+ xComp->addEventListener( static_cast< XContainerListener* >( this ) );
+ m_pImpl->m_aConnections.emplace_back(xConn);
+ }
+
+ return xConn;
+}
+
+Reference< XNameAccess > SAL_CALL ODatabaseSource::getBookmarks( )
+{
+ ModelMethodGuard aGuard( *this );
+ // tdf#114596 this may look nutty but see OBookmarkContainer::acquire()
+ return static_cast<XNameContainer*>(&m_Bookmarks);
+}
+
+Reference< XNameAccess > SAL_CALL ODatabaseSource::getQueryDefinitions( )
+{
+ ModelMethodGuard aGuard( *this );
+
+ Reference< XNameAccess > xContainer = m_pImpl->m_xCommandDefinitions;
+ if ( !xContainer.is() )
+ {
+ Any aValue;
+ css::uno::Reference< css::uno::XInterface > xMy(*this);
+ if ( dbtools::getDataSourceSetting(xMy,"CommandDefinitions",aValue) )
+ {
+ OUString sSupportService;
+ aValue >>= sSupportService;
+ if ( !sSupportService.isEmpty() )
+ {
+ Sequence<Any> aArgs{ Any(NamedValue("DataSource",Any(xMy))) };
+ xContainer.set( m_pImpl->m_aContext->getServiceManager()->createInstanceWithArgumentsAndContext(sSupportService, aArgs, m_pImpl->m_aContext), UNO_QUERY);
+ }
+ }
+ if ( !xContainer.is() )
+ {
+ TContentPtr& rContainerData( m_pImpl->getObjectContainer( ODatabaseModelImpl::E_QUERY ) );
+ xContainer = new OCommandContainer( m_pImpl->m_aContext, *this, rContainerData, false );
+ }
+ m_pImpl->m_xCommandDefinitions = xContainer;
+ }
+ return xContainer;
+}
+
+// XTablesSupplier
+Reference< XNameAccess > ODatabaseSource::getTables()
+{
+ ModelMethodGuard aGuard( *this );
+
+ Reference< XNameAccess > xContainer = m_pImpl->m_xTableDefinitions;
+ if ( !xContainer.is() )
+ {
+ TContentPtr& rContainerData( m_pImpl->getObjectContainer( ODatabaseModelImpl::E_TABLE ) );
+ xContainer = new OCommandContainer( m_pImpl->m_aContext, *this, rContainerData, true );
+ m_pImpl->m_xTableDefinitions = xContainer;
+ }
+ return xContainer;
+}
+
+void SAL_CALL ODatabaseSource::flush( )
+{
+ try
+ {
+ // SYNCHRONIZED ->
+ {
+ ModelMethodGuard aGuard( *this );
+
+ typedef ::utl::SharedUNOComponent< XModel, ::utl::CloseableComponent > SharedModel;
+ SharedModel xModel( m_pImpl->getModel_noCreate(), SharedModel::NoTakeOwnership );
+
+ if ( !xModel.is() )
+ xModel.reset( m_pImpl->createNewModel_deliverOwnership(), SharedModel::TakeOwnership );
+
+ Reference< css::frame::XStorable> xStorable( xModel, UNO_QUERY_THROW );
+ xStorable->store();
+ }
+ // <- SYNCHRONIZED
+
+ css::lang::EventObject aFlushedEvent(*this);
+ m_aFlushListeners.notifyEach( &XFlushListener::flushed, aFlushedEvent );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+}
+
+void SAL_CALL ODatabaseSource::flushed( const EventObject& /*rEvent*/ )
+{
+ ModelMethodGuard aGuard( *this );
+
+ // Okay, this is some hack.
+ //
+ // In general, we have the problem that embedded databases write into their underlying storage, which
+ // logically is one of our sub storage, and practically is a temporary file maintained by the
+ // package implementation. As long as we did not commit this storage and our main storage,
+ // the changes made by the embedded database engine are not really reflected in the database document
+ // file. This is Bad (TM) for a "real" database application - imagine somebody entering some
+ // data, and then crashing: For a database application, you would expect that the data still is present
+ // when you connect to the database next time.
+ //
+ // Since this is a conceptual problem as long as we do use those ZIP packages (in fact, we *cannot*
+ // provide the desired functionality as long as we do not have a package format which allows O(1) writes),
+ // we cannot completely fix this. However, we can relax the problem by committing more often - often
+ // enough so that data loss is more seldom, and seldom enough so that there's no noticeable performance
+ // decrease.
+ //
+ // For this, we introduced a few places which XFlushable::flush their connections, and register as
+ // XFlushListener at the embedded connection (which needs to provide the XFlushable functionality).
+ // Then, when the connection is flushed, we commit both the database storage and our main storage.
+ //
+ // #i55274#
+
+ OSL_ENSURE( m_pImpl->isEmbeddedDatabase(), "ODatabaseSource::flushed: no embedded database?!" );
+ bool bWasModified = m_pImpl->m_bModified;
+ m_pImpl->commitEmbeddedStorage();
+ m_pImpl->setModified( bWasModified );
+}
+
+void SAL_CALL ODatabaseSource::addFlushListener( const Reference< css::util::XFlushListener >& _xListener )
+{
+ m_aFlushListeners.addInterface(_xListener);
+}
+
+void SAL_CALL ODatabaseSource::removeFlushListener( const Reference< css::util::XFlushListener >& _xListener )
+{
+ m_aFlushListeners.removeInterface(_xListener);
+}
+
+void SAL_CALL ODatabaseSource::elementInserted( const ContainerEvent& /*Event*/ )
+{
+ ModelMethodGuard aGuard( *this );
+ if ( m_pImpl.is() )
+ m_pImpl->setModified(true);
+}
+
+void SAL_CALL ODatabaseSource::elementRemoved( const ContainerEvent& /*Event*/ )
+{
+ ModelMethodGuard aGuard( *this );
+ if ( m_pImpl.is() )
+ m_pImpl->setModified(true);
+}
+
+void SAL_CALL ODatabaseSource::elementReplaced( const ContainerEvent& /*Event*/ )
+{
+ ModelMethodGuard aGuard( *this );
+ if ( m_pImpl.is() )
+ m_pImpl->setModified(true);
+}
+
+// XDocumentDataSource
+Reference< XOfficeDatabaseDocument > SAL_CALL ODatabaseSource::getDatabaseDocument()
+{
+ ModelMethodGuard aGuard( *this );
+
+ Reference< XModel > xModel( m_pImpl->getModel_noCreate() );
+ if ( !xModel.is() )
+ xModel = m_pImpl->createNewModel_deliverOwnership();
+
+ return Reference< XOfficeDatabaseDocument >( xModel, UNO_QUERY_THROW );
+}
+
+void SAL_CALL ODatabaseSource::initialize( css::uno::Sequence< css::uno::Any > const & rArguments)
+{
+ ::comphelper::NamedValueCollection aProperties( rArguments );
+ if (aProperties.has("ParentWindow"))
+ aProperties.get("ParentWindow") >>= m_pImpl->m_xDialogParent;
+}
+
+Reference< XInterface > ODatabaseSource::getThis() const
+{
+ return *const_cast< ODatabaseSource* >( this );
+}
+
+} // namespace dbaccess
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+com_sun_star_comp_dba_ODatabaseSource(css::uno::XComponentContext* context,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ css::uno::Reference<XInterface> inst(
+ DatabaseContext::create(context)->createInstance());
+ inst->acquire();
+ return inst.get();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/dataaccess/datasource.hxx b/dbaccess/source/core/dataaccess/datasource.hxx
new file mode 100644
index 000000000..5b5985eac
--- /dev/null
+++ b/dbaccess/source/core/dataaccess/datasource.hxx
@@ -0,0 +1,220 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <com/sun/star/util/XNumberFormatsSupplier.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/sdbc/XDataSource.hpp>
+#include <com/sun/star/container/XContainerListener.hpp>
+#include <com/sun/star/sdb/XBookmarksSupplier.hpp>
+#include <com/sun/star/sdb/XQueryDefinitionsSupplier.hpp>
+#include <com/sun/star/sdbc/XIsolatedConnection.hpp>
+#include <com/sun/star/util/XNumberFormatter.hpp>
+#include <com/sun/star/document/XEventListener.hpp>
+#include <com/sun/star/util/XFlushable.hpp>
+#include <cppuhelper/propshlp.hxx>
+#include <comphelper/interfacecontainer3.hxx>
+#include <comphelper/proparrhlp.hxx>
+#include <cppuhelper/weakref.hxx>
+#include <cppuhelper/compbase.hxx>
+#include <com/sun/star/embed/XTransactionListener.hpp>
+#include <apitools.hxx>
+#include <bookmarkcontainer.hxx>
+#include <rtl/ref.hxx>
+#include <connectivity/CommonTools.hxx>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/beans/PropertyValue.hpp>
+#include <com/sun/star/sdb/XCompletedConnection.hpp>
+#include <com/sun/star/sdbcx/XTablesSupplier.hpp>
+#include <com/sun/star/embed/XStorage.hpp>
+#include <ContentHelper.hxx>
+#include <com/sun/star/document/XStorageBasedDocument.hpp>
+#include <com/sun/star/embed/ElementModes.hpp>
+#include <com/sun/star/util/XRefreshable.hpp>
+#include <com/sun/star/sdb/XDocumentDataSource.hpp>
+#include <ModelImpl.hxx>
+
+namespace dbaccess
+{
+
+class OSharedConnectionManager;
+
+// ODatabaseSource
+typedef ::cppu::WeakComponentImplHelper< css::lang::XServiceInfo
+ , css::sdbc::XDataSource
+ , css::sdb::XBookmarksSupplier
+ , css::sdb::XQueryDefinitionsSupplier
+ , css::sdb::XCompletedConnection
+ , css::container::XContainerListener
+ , css::sdbc::XIsolatedConnection
+ , css::sdbcx::XTablesSupplier
+ , css::util::XFlushable
+ , css::util::XFlushListener
+ , css::sdb::XDocumentDataSource
+ , css::lang::XInitialization
+ > ODatabaseSource_Base;
+
+class ODatabaseSource :public ModelDependentComponent // must be first
+ ,public ODatabaseSource_Base
+ ,public ::cppu::OPropertySetHelper
+ ,public ::comphelper::OPropertyArrayUsageHelper < ODatabaseSource >
+{
+ friend class ODatabaseContext;
+ friend class OConnection;
+ friend class OSharedConnectionManager;
+
+private:
+ using ODatabaseSource_Base::rBHelper;
+ // note: this thing uses the ref-count of "this", see OBookmarkContainer::acquire!
+ OBookmarkContainer m_Bookmarks;
+ ::comphelper::OInterfaceContainerHelper3<css::util::XFlushListener> m_aFlushListeners;
+
+private:
+ virtual ~ODatabaseSource() override;
+
+public:
+ explicit ODatabaseSource( const ::rtl::Reference< ODatabaseModelImpl >& _pImpl );
+
+ struct DBContextAccess { friend class ODatabaseContext; private: DBContextAccess() { } };
+
+ /** sets a new name for the data source
+
+ The name of a data source (our m_sName member) is the registration name, *if* the
+ data source actually *is* registered at the database context.
+
+ Normally, this name is passed at time of creation of the ODatabaseModelImpl instance,
+ but if a newly created data source is registered, then it must be possible to propagate
+ the new registration name.
+ */
+ static void setName(
+ const css::uno::Reference< css::sdb::XDocumentDataSource >& _rxDocument,
+ const OUString& _rNewName,
+ DBContextAccess
+ );
+
+ // XContainerListener
+ virtual void SAL_CALL elementInserted( const css::container::ContainerEvent& Event ) override;
+ virtual void SAL_CALL elementRemoved( const css::container::ContainerEvent& Event ) override;
+ virtual void SAL_CALL elementReplaced( const css::container::ContainerEvent& Event ) override;
+ // css::sdbcx::XTablesSupplier
+ virtual css::uno::Reference< css::container::XNameAccess > SAL_CALL getTables( ) override;
+
+// css::lang::XTypeProvider
+ virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes() override;
+ virtual css::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId() override;
+
+// css::uno::XInterface
+ virtual css::uno::Any SAL_CALL queryInterface( const css::uno::Type & rType ) override;
+ virtual void SAL_CALL acquire() noexcept override;
+ virtual void SAL_CALL release() noexcept override;
+
+// css::lang::XServiceInfo
+ virtual OUString SAL_CALL getImplementationName( ) override;
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override;
+
+// OComponentHelper
+ virtual void SAL_CALL disposing() override;
+
+// css::beans::XPropertySet
+ virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo( ) override;
+ // XEventListener
+ virtual void SAL_CALL disposing( const css::lang::EventObject& Source ) override;
+
+// comphelper::OPropertyArrayUsageHelper
+ virtual ::cppu::IPropertyArrayHelper* createArrayHelper( ) const override;
+
+// cppu::OPropertySetHelper
+ virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper() override;
+
+ virtual sal_Bool SAL_CALL convertFastPropertyValue(
+ css::uno::Any & rConvertedValue,
+ css::uno::Any & rOldValue,
+ sal_Int32 nHandle,
+ const css::uno::Any& rValue ) override;
+ virtual void SAL_CALL setFastPropertyValue_NoBroadcast(
+ sal_Int32 nHandle,
+ const css::uno::Any& rValue
+ ) override;
+ virtual void SAL_CALL getFastPropertyValue( css::uno::Any& rValue, sal_Int32 nHandle ) const override;
+
+// css::sdb::XCompletedConnection
+ virtual css::uno::Reference< css::sdbc::XConnection > SAL_CALL connectWithCompletion( const css::uno::Reference< css::task::XInteractionHandler >& handler ) override;
+
+// css::sdbc::XDataSource
+ virtual css::uno::Reference< css::sdbc::XConnection > SAL_CALL getConnection( const OUString& user, const OUString& password ) override;
+ virtual void SAL_CALL setLoginTimeout( sal_Int32 seconds ) override;
+ virtual sal_Int32 SAL_CALL getLoginTimeout( ) override;
+
+//::css::sdb::XBookmarksSupplier
+ virtual css::uno::Reference< css::container::XNameAccess > SAL_CALL getBookmarks( ) override;
+
+//::css::sdb::XQueryDefinitionsSupplier
+ virtual css::uno::Reference< css::container::XNameAccess > SAL_CALL getQueryDefinitions( ) override;
+
+// css::sdbc::XIsolatedConnection
+ virtual css::uno::Reference< css::sdbc::XConnection > SAL_CALL getIsolatedConnection( const OUString& user, const OUString& password ) override;
+ virtual css::uno::Reference< css::sdbc::XConnection > SAL_CALL getIsolatedConnectionWithCompletion( const css::uno::Reference< css::task::XInteractionHandler >& handler ) override;
+
+// XFlushable
+ virtual void SAL_CALL flush( ) override;
+ virtual void SAL_CALL addFlushListener( const css::uno::Reference< css::util::XFlushListener >& l ) override;
+ virtual void SAL_CALL removeFlushListener( const css::uno::Reference< css::util::XFlushListener >& l ) override;
+
+ // XFlushListener
+ virtual void SAL_CALL flushed( const css::lang::EventObject& rEvent ) override;
+
+ // XDocumentDataSource
+ virtual css::uno::Reference< css::sdb::XOfficeDatabaseDocument > SAL_CALL getDatabaseDocument() override;
+
+ // XInitialization
+ virtual void SAL_CALL initialize( const css::uno::Sequence< css::uno::Any >& aArguments ) override;
+
+protected:
+ // ModelDependentComponent overridables
+ virtual css::uno::Reference< css::uno::XInterface > getThis() const override;
+
+private:
+// helper
+ /** open a connection for the current settings. this is the simple connection we get from the driver
+ manager, so it can be used as a master for a "high level" sdb connection.
+ */
+ css::uno::Reference< css::sdbc::XConnection > buildLowLevelConnection(
+ const OUString& _rUid, const OUString& _rPwd
+ );
+
+ css::uno::Reference< css::sdbc::XConnection > buildIsolatedConnection(
+ const OUString& user, const OUString& password
+ );
+
+ /// @throws css::sdbc::SQLException
+ /// @throws css::uno::RuntimeException
+ css::uno::Reference< css::sdbc::XConnection > getConnection( const OUString& user, const OUString& password , bool _bIsolated);
+ /// @throws css::sdbc::SQLException
+ /// @throws css::uno::RuntimeException
+ css::uno::Reference< css::sdbc::XConnection > connectWithCompletion( const css::uno::Reference< css::task::XInteractionHandler >& handler , bool _bIsolated);
+
+protected:
+ using ::cppu::OPropertySetHelper::getFastPropertyValue;
+};
+
+} // namespace dbaccess
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/dataaccess/definitioncontainer.cxx b/dbaccess/source/core/dataaccess/definitioncontainer.cxx
new file mode 100644
index 000000000..81d8b0302
--- /dev/null
+++ b/dbaccess/source/core/dataaccess/definitioncontainer.cxx
@@ -0,0 +1,679 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <definitioncontainer.hxx>
+#include <core_resource.hxx>
+#include <strings.hrc>
+#include <strings.hxx>
+
+#include <tools/diagnose_ex.h>
+#include <o3tl/safeint.hxx>
+#include <osl/diagnose.h>
+#include <comphelper/enumhelper.hxx>
+#include <cppuhelper/exc_hlp.hxx>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/sdb/ErrorCondition.hpp>
+#include <comphelper/servicehelper.hxx>
+#include <comphelper/types.hxx>
+#include <rtl/ref.hxx>
+
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::util;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::sdbcx;
+using namespace ::com::sun::star::sdb;
+using namespace ::osl;
+using namespace ::comphelper;
+using namespace ::cppu;
+using namespace ::com::sun::star::ucb;
+
+namespace dbaccess
+{
+
+// ODefinitionContainer_Impl
+void ODefinitionContainer_Impl::erase( const TContentPtr& _pDefinition )
+{
+ NamedDefinitions::const_iterator aPos = find( _pDefinition );
+ if ( aPos != end() )
+ m_aDefinitions.erase( aPos );
+}
+
+ODefinitionContainer_Impl::const_iterator ODefinitionContainer_Impl::find( const TContentPtr& _pDefinition ) const
+{
+ return std::find_if(
+ m_aDefinitions.begin(),
+ m_aDefinitions.end(),
+ [&_pDefinition] (const NamedDefinitions::value_type& namedDef) {
+ return namedDef.second == _pDefinition;
+ });
+}
+
+ODefinitionContainer_Impl::iterator ODefinitionContainer_Impl::find( const TContentPtr& _pDefinition )
+{
+ return std::find_if(
+ m_aDefinitions.begin(),
+ m_aDefinitions.end(),
+ [&_pDefinition] (const NamedDefinitions::value_type& namedDef) {
+ return namedDef.second == _pDefinition;
+ });
+}
+
+// ODefinitionContainer
+
+ODefinitionContainer::ODefinitionContainer( const Reference< XComponentContext >& _xORB
+ , const Reference< XInterface >& _xParentContainer
+ , const TContentPtr& _pImpl
+ , bool _bCheckSlash
+ )
+ :OContentHelper(_xORB,_xParentContainer,_pImpl)
+ ,m_aApproveListeners(m_aMutex)
+ ,m_aContainerListeners(m_aMutex)
+ ,m_bInPropertyChange(false)
+ ,m_bCheckSlash(_bCheckSlash)
+{
+ assert(m_pImpl);
+ m_pImpl->m_aProps.bIsDocument = false;
+ m_pImpl->m_aProps.bIsFolder = true;
+
+ const ODefinitionContainer_Impl& rDefinitions( getDefinitions() );
+ for (auto const& definition : rDefinitions)
+ m_aDocuments.push_back(
+ m_aDocumentMap.emplace(definition.first, Documents::mapped_type() ).first );
+
+}
+
+void SAL_CALL ODefinitionContainer::disposing()
+{
+ OContentHelper::disposing();
+
+ MutexGuard aGuard(m_aMutex);
+
+ // say goodbye to our listeners
+ EventObject aEvt(*this);
+ m_aApproveListeners.disposeAndClear(aEvt);
+ m_aContainerListeners.disposeAndClear(aEvt);
+
+ // dispose our elements
+ for (auto const& elem : m_aDocumentMap)
+ {
+ Reference<XContent> xProp = elem.second;
+ if ( xProp.is() )
+ {
+ removeObjectListener(xProp);
+ ::comphelper::disposeComponent(xProp);
+ }
+ }
+
+ // remove our elements
+ m_aDocuments.clear();
+ // !!! do this before clearing the map which the vector elements refer to !!!
+ m_aDocumentMap.clear();
+}
+
+ODefinitionContainer::~ODefinitionContainer()
+{
+}
+
+IMPLEMENT_FORWARD_XINTERFACE2( ODefinitionContainer,OContentHelper,ODefinitionContainer_Base)
+css::uno::Sequence< css::uno::Type > ODefinitionContainer::getTypes()
+{
+ return ::comphelper::concatSequences(
+ OContentHelper::getTypes( ),
+ ODefinitionContainer_Base::getTypes( )
+ );
+}
+
+
+css::uno::Sequence<sal_Int8> ODefinitionContainer::getImplementationId()
+{
+ return css::uno::Sequence<sal_Int8>();
+}
+
+// XServiceInfo
+OUString SAL_CALL ODefinitionContainer::getImplementationName( )
+{
+ return "com.sun.star.sdb.ODefinitionContainer";
+}
+
+Sequence< OUString > SAL_CALL ODefinitionContainer::getSupportedServiceNames( )
+{
+ return { "com.sun.star.sdb.DefinitionContainer", "com.sun.star.ucb.Content" };
+}
+
+// XNameContainer
+void SAL_CALL ODefinitionContainer::insertByName( const OUString& _rName, const Any& aElement )
+{
+ ResettableMutexGuard aGuard(m_aMutex);
+
+ // approve the new object
+ Reference< XContent > xNewElement(aElement,UNO_QUERY);
+ approveNewObject( _rName, xNewElement ); // will throw if necessary
+
+ notifyByName( aGuard, _rName, xNewElement, nullptr, E_INSERTED, ApproveListeners );
+ implAppend( _rName, xNewElement );
+ notifyByName( aGuard, _rName, xNewElement, nullptr, E_INSERTED, ContainerListemers );
+}
+
+void SAL_CALL ODefinitionContainer::removeByName( const OUString& _rName )
+{
+ ResettableMutexGuard aGuard(m_aMutex);
+
+ // check the arguments
+ if (_rName.isEmpty())
+ throw IllegalArgumentException();
+
+ if (!checkExistence(_rName))
+ throw NoSuchElementException(_rName,*this);
+
+ // the old element (for the notifications)
+ Reference< XContent > xOldElement = implGetByName( _rName, impl_haveAnyListeners_nothrow() );
+
+ // do the removal
+ notifyByName( aGuard, _rName, nullptr, xOldElement, E_REMOVED, ApproveListeners );
+ implRemove( _rName );
+ notifyByName( aGuard, _rName, nullptr, xOldElement, E_REMOVED, ContainerListemers );
+
+ removeObjectListener( xOldElement );
+ disposeComponent(xOldElement);
+}
+
+// XNameReplace
+void SAL_CALL ODefinitionContainer::replaceByName( const OUString& _rName, const Any& aElement )
+{
+ ResettableMutexGuard aGuard(m_aMutex);
+
+ try
+ {
+ // let derived classes approve the new object
+ Reference< XContent > xNewElement(aElement,UNO_QUERY);
+ approveNewObject( _rName, xNewElement ); // will throw if necessary
+
+ // the old element (for the notifications)
+ Reference< XContent > xOldElement = implGetByName( _rName, impl_haveAnyListeners_nothrow() );
+
+ notifyByName( aGuard, _rName, xNewElement, xOldElement, E_REPLACED, ApproveListeners );
+ implReplace( _rName, xNewElement );
+ notifyByName( aGuard, _rName, xNewElement, xOldElement, E_REPLACED, ContainerListemers );
+
+ // and dispose it
+ disposeComponent(xOldElement);
+ }
+ catch (const RuntimeException&)
+ {
+ throw;
+ }
+ catch (const NoSuchElementException&)
+ {
+ throw;
+ }
+ catch (const WrappedTargetException&)
+ {
+ throw;
+ }
+ catch (const Exception& e)
+ {
+ css::uno::Any a(cppu::getCaughtException());
+ throw css::lang::WrappedTargetException(
+ "wrapped Exception " + e.Message,
+ css::uno::Reference<css::uno::XInterface>(), a);
+ }
+}
+
+namespace
+{
+ typedef Reference< XVeto > ( SAL_CALL XContainerApproveListener::*ContainerApprovalMethod )( const ContainerEvent& );
+
+ struct RaiseExceptionFromVeto
+ {
+ private:
+ ContainerApprovalMethod m_pMethod;
+ const ContainerEvent& m_rEvent;
+
+ public:
+ explicit RaiseExceptionFromVeto( ContainerApprovalMethod _pMethod, const ContainerEvent& _rEvent )
+ :m_pMethod( _pMethod )
+ ,m_rEvent( _rEvent )
+ {
+ }
+
+ void operator()( const Reference< XContainerApproveListener >& Listener ) const
+ {
+ Reference< XVeto > xVeto = (Listener.get()->*m_pMethod)( m_rEvent );
+ if ( !xVeto.is() )
+ return;
+
+ Any eVetoDetails = xVeto->getDetails();
+
+ IllegalArgumentException aIllegalArgumentError;
+ if ( eVetoDetails >>= aIllegalArgumentError )
+ throw aIllegalArgumentError;
+
+ WrappedTargetException aWrappedError;
+ if ( eVetoDetails >>= aWrappedError )
+ throw aWrappedError;
+
+ throw WrappedTargetException( xVeto->getReason(), Listener, eVetoDetails );
+ }
+ };
+}
+
+void ODefinitionContainer::notifyByName( ResettableMutexGuard& _rGuard, const OUString& _rName,
+ const Reference< XContent >& _xNewElement, const Reference< XContent >& _xOldElement,
+ ContainerOperation _eOperation, ListenerType _eType )
+{
+ bool bApprove = ( _eType == ApproveListeners );
+
+ ::comphelper::OInterfaceContainerHelper2& rContainer( bApprove ? m_aApproveListeners : m_aContainerListeners );
+ if ( !rContainer.getLength() )
+ return;
+
+ ContainerEvent aEvent( *this, Any( _rName ), Any( _xNewElement ), Any( _xOldElement ) );
+
+ _rGuard.clear();
+ switch ( _eOperation )
+ {
+ case E_INSERTED:
+ if ( bApprove )
+ rContainer.forEach< XContainerApproveListener, RaiseExceptionFromVeto >(
+ RaiseExceptionFromVeto( &XContainerApproveListener::approveInsertElement, aEvent ) );
+ else
+ rContainer.notifyEach( &XContainerListener::elementInserted, aEvent );
+ break;
+ case E_REPLACED:
+ if ( bApprove )
+ rContainer.forEach< XContainerApproveListener, RaiseExceptionFromVeto >(
+ RaiseExceptionFromVeto( &XContainerApproveListener::approveReplaceElement, aEvent ) );
+ else
+ rContainer.notifyEach( &XContainerListener::elementReplaced, aEvent );
+ break;
+ case E_REMOVED:
+ if ( bApprove )
+ rContainer.forEach< XContainerApproveListener, RaiseExceptionFromVeto >(
+ RaiseExceptionFromVeto( &XContainerApproveListener::approveRemoveElement, aEvent ) );
+ else
+ rContainer.notifyEach( &XContainerListener::elementRemoved, aEvent );
+ break;
+ }
+
+ if ( bApprove )
+ _rGuard.reset();
+}
+
+void SAL_CALL ODefinitionContainer::addContainerListener( const Reference< XContainerListener >& _rxListener )
+{
+ if (_rxListener.is())
+ m_aContainerListeners.addInterface(_rxListener);
+}
+
+void SAL_CALL ODefinitionContainer::removeContainerListener( const Reference< XContainerListener >& _rxListener )
+{
+ if (_rxListener.is())
+ m_aContainerListeners.removeInterface(_rxListener);
+}
+
+void SAL_CALL ODefinitionContainer::addContainerApproveListener( const Reference< XContainerApproveListener >& Listener )
+{
+ if ( Listener.is() )
+ m_aApproveListeners.addInterface( Listener );
+}
+
+void SAL_CALL ODefinitionContainer::removeContainerApproveListener( const Reference< XContainerApproveListener >& Listener )
+{
+ if ( Listener.is() )
+ m_aApproveListeners.removeInterface( Listener );
+}
+
+// XElementAccess
+Type SAL_CALL ODefinitionContainer::getElementType( )
+{
+ return cppu::UnoType<XContent>::get();
+}
+
+sal_Bool SAL_CALL ODefinitionContainer::hasElements( )
+{
+ MutexGuard aGuard(m_aMutex);
+ return !m_aDocuments.empty();
+}
+
+// XEnumerationAccess
+Reference< XEnumeration > SAL_CALL ODefinitionContainer::createEnumeration( )
+{
+ MutexGuard aGuard(m_aMutex);
+ return new ::comphelper::OEnumerationByIndex(static_cast<XIndexAccess*>(this));
+}
+
+// XIndexAccess
+sal_Int32 SAL_CALL ODefinitionContainer::getCount( )
+{
+ MutexGuard aGuard(m_aMutex);
+ return m_aDocuments.size();
+}
+
+Any SAL_CALL ODefinitionContainer::getByIndex( sal_Int32 _nIndex )
+{
+ MutexGuard aGuard(m_aMutex);
+
+ if ((_nIndex < 0) || (o3tl::make_unsigned(_nIndex) >= m_aDocuments.size()))
+ throw IndexOutOfBoundsException();
+
+ Documents::iterator aPos = m_aDocuments[_nIndex];
+ Reference<XContent> xProp = aPos->second;
+ if (!xProp.is())
+ { // that's the first access to the object
+ // -> create it
+ xProp = createObject(aPos->first);
+ aPos->second = Documents::mapped_type();
+ // and update the name-access map
+ }
+
+ return Any(xProp);
+}
+
+Any SAL_CALL ODefinitionContainer::getByName( const OUString& _rName )
+{
+ MutexGuard aGuard(m_aMutex);
+
+ return Any( implGetByName( _rName, true ) );
+}
+
+Reference< XContent > ODefinitionContainer::implGetByName(const OUString& _rName, bool _bReadIfNecessary)
+{
+ Documents::iterator aMapPos = m_aDocumentMap.find(_rName);
+ if (aMapPos == m_aDocumentMap.end())
+ throw NoSuchElementException(_rName,*this);
+
+ Reference< XContent > xProp = aMapPos->second;
+
+ if (_bReadIfNecessary && !xProp.is())
+ { // the object has never been accessed before, so we have to read it now
+ // (that's the expensive part)
+
+ // create the object and insert it into the map
+ xProp = createObject(_rName);
+ aMapPos->second = xProp;
+ addObjectListener(xProp);
+ }
+
+ return xProp;
+}
+
+Sequence< OUString > SAL_CALL ODefinitionContainer::getElementNames( )
+{
+ MutexGuard aGuard(m_aMutex);
+
+ Sequence< OUString > aNames(m_aDocumentMap.size());
+ OUString* pNames = aNames.getArray();
+ for (auto const& elem : m_aDocumentMap)
+ {
+ *pNames = elem.first;
+ ++pNames;
+ }
+
+ return aNames;
+}
+
+sal_Bool SAL_CALL ODefinitionContainer::hasByName( const OUString& _rName )
+{
+ MutexGuard aGuard(m_aMutex);
+
+ return checkExistence(_rName);
+}
+
+void SAL_CALL ODefinitionContainer::disposing( const EventObject& _rSource )
+{
+ MutexGuard aGuard(m_aMutex);
+ Reference< XContent > xSource(_rSource.Source, UNO_QUERY);
+ // it's one of our documents...
+ for (auto & elem : m_aDocumentMap)
+ {
+ if ( xSource == elem.second.get() )
+ {
+ removeObjectListener(xSource);
+ // and clear our document map/vector, so the object will be recreated on next access
+ elem.second = Documents::mapped_type();
+ }
+ }
+}
+
+void ODefinitionContainer::implRemove(const OUString& _rName)
+{
+ // from the object maps
+ Documents::const_iterator aFind = m_aDocumentMap.find(_rName);
+ if ( aFind != m_aDocumentMap.end() )
+ {
+ m_aDocuments.erase( std::find(m_aDocuments.begin(),m_aDocuments.end(),aFind));
+ m_aDocumentMap.erase(aFind);
+
+ getDefinitions().erase( _rName );
+
+ notifyDataSourceModified();
+ }
+}
+
+namespace
+{
+ bool lcl_ensureName( const Reference< XContent >& _rxContent, const OUString& _rName )
+ {
+ if ( !_rxContent.is() )
+ return true;
+
+ // obtain the current name. If it's the same as the new one,
+ // don't do anything
+ try
+ {
+ Reference< XPropertySet > xProps( _rxContent, UNO_QUERY );
+ if ( xProps.is() )
+ {
+ OUString sCurrentName;
+ OSL_VERIFY( xProps->getPropertyValue( PROPERTY_NAME ) >>= sCurrentName );
+ if ( sCurrentName == _rName )
+ return true;
+ }
+ }
+ catch( const Exception& )
+ {
+ TOOLS_WARN_EXCEPTION( "dbaccess", "lcl_ensureName: caught an exception while obtaining the current name!" );
+ }
+
+ // set the new name
+ Reference< XRename > xRename( _rxContent, UNO_QUERY );
+ OSL_ENSURE( xRename.is(), "lcl_ensureName: invalid content (not renameable)!" );
+ if ( !xRename.is() )
+ return false;
+ try
+ {
+ xRename->rename( _rName );
+ return true;
+ }
+ catch( const Exception& )
+ {
+ TOOLS_WARN_EXCEPTION( "dbaccess", "lcl_ensureName" );
+ }
+ return false;
+ }
+}
+
+void ODefinitionContainer::implAppend(const OUString& _rName, const Reference< XContent >& _rxNewObject)
+{
+ MutexGuard aGuard(m_aMutex);
+ try
+ {
+ Reference<XChild> xChild(_rxNewObject,UNO_QUERY);
+ if ( xChild.is() )
+ xChild->setParent(static_cast<OWeakObject*>(this));
+
+ ODefinitionContainer_Impl& rDefinitions( getDefinitions() );
+ ODefinitionContainer_Impl::const_iterator aFind = rDefinitions.find( _rName );
+ if ( aFind == rDefinitions.end() )
+ {
+ // ensure that the new object has the proper name.
+ // Somebody could create an object with name "foo", and insert it as "bar"
+ // into a container. In this case, we need to ensure that the object name
+ // is also "bar"
+ // #i44786#
+ lcl_ensureName( _rxNewObject, _rName );
+
+ ::rtl::Reference< OContentHelper > pContent = comphelper::getFromUnoTunnel<OContentHelper>( _rxNewObject );
+ if ( pContent.is() )
+ {
+ TContentPtr pImpl = pContent->getImpl();
+ rDefinitions.erase( pImpl );
+ pImpl->m_aProps.aTitle = _rName;
+ rDefinitions.insert( _rName, pImpl );
+ }
+ }
+
+ m_aDocuments.push_back(m_aDocumentMap.emplace(_rName,_rxNewObject).first);
+ notifyDataSourceModified();
+ // now update our structures
+ if ( _rxNewObject.is() )
+ addObjectListener(_rxNewObject);
+ }
+ catch(Exception&)
+ {
+ OSL_FAIL("ODefinitionContainer::implAppend: caught something !");
+ }
+}
+
+void ODefinitionContainer::implReplace(const OUString& _rName, const Reference< XContent >& _rxNewObject)
+{
+ OSL_ENSURE(checkExistence(_rName), "ODefinitionContainer::implReplace : invalid name !");
+
+ Documents::iterator aFind = m_aDocumentMap.find(_rName);
+ removeObjectListener(aFind->second);
+ aFind->second = _rxNewObject;
+ addObjectListener(aFind->second);
+}
+
+void ODefinitionContainer::approveNewObject(const OUString& _sName,const Reference< XContent >& _rxObject) const
+{
+ // check the arguments
+ if ( _sName.isEmpty() )
+ throw IllegalArgumentException(
+ DBA_RES( RID_STR_NAME_MUST_NOT_BE_EMPTY ),
+ *this,
+ 0 );
+
+ if ( m_bCheckSlash && _sName.indexOf( '/' ) != -1 )
+ throw IllegalArgumentException(
+ m_aErrorHelper.getErrorMessage( ErrorCondition::DB_OBJECT_NAME_WITH_SLASHES ),
+ *this,
+ 0 );
+
+ if ( !_rxObject.is() )
+ throw IllegalArgumentException(
+ DBA_RES( RID_STR_NO_NULL_OBJECTS_IN_CONTAINER ),
+ *this,
+ 0 );
+
+ const ODefinitionContainer_Impl& rDefinitions( getDefinitions() );
+ if ( rDefinitions.find( _sName ) != rDefinitions.end() )
+ throw ElementExistException(
+ DBA_RES( RID_STR_NAME_ALREADY_USED ),
+ *this );
+
+ ::rtl::Reference< OContentHelper > pContent( comphelper::getFromUnoTunnel<OContentHelper>( _rxObject ) );
+ if ( !pContent.is() )
+ throw IllegalArgumentException(
+ DBA_RES( RID_STR_OBJECT_CONTAINER_MISMATCH ),
+ *this,
+ 1 );
+
+ if ( rDefinitions.find( pContent->getImpl() ) != rDefinitions.end() )
+ throw ElementExistException(
+ DBA_RES( RID_STR_OBJECT_ALREADY_CONTAINED ),
+ *this );
+}
+
+// XPropertyChangeListener
+void SAL_CALL ODefinitionContainer::propertyChange( const PropertyChangeEvent& evt )
+{
+ if( evt.PropertyName != PROPERTY_NAME && evt.PropertyName != "Title" )
+ return;
+
+ MutexGuard aGuard(m_aMutex);
+
+ m_bInPropertyChange = true;
+ try
+ {
+ OUString sNewName,sOldName;
+ evt.OldValue >>= sOldName;
+ evt.NewValue >>= sNewName;
+ Reference<XContent> xContent( evt.Source, UNO_QUERY );
+ removeObjectListener( xContent );
+ implRemove( sOldName );
+ implAppend( sNewName, xContent );
+ }
+ catch(const Exception& ex)
+ {
+ css::uno::Any anyEx = cppu::getCaughtException();
+ throw css::lang::WrappedTargetRuntimeException( ex.Message,
+ nullptr, anyEx );
+ }
+ m_bInPropertyChange = false;
+}
+
+// XVetoableChangeListener
+void SAL_CALL ODefinitionContainer::vetoableChange( const PropertyChangeEvent& aEvent )
+{
+ MutexGuard aGuard(m_aMutex);
+
+ if( aEvent.PropertyName == PROPERTY_NAME || aEvent.PropertyName == "Title" )
+ {
+ OUString sNewName;
+ aEvent.NewValue >>= sNewName;
+ if(hasByName(sNewName))
+ throw PropertyVetoException();
+ }
+}
+
+void ODefinitionContainer::addObjectListener(const Reference< XContent >& _xNewObject)
+{
+ OSL_ENSURE(_xNewObject.is(),"ODefinitionContainer::addObjectListener: Object is null!");
+ Reference<XPropertySet> xProp(_xNewObject,UNO_QUERY);
+ if ( xProp.is() )
+ {
+ xProp->addPropertyChangeListener(PROPERTY_NAME, this);
+ xProp->addVetoableChangeListener(PROPERTY_NAME, this);
+ }
+}
+
+void ODefinitionContainer::removeObjectListener(const Reference< XContent >& _xNewObject)
+{
+ Reference<XPropertySet> xProp(_xNewObject,UNO_QUERY);
+ if ( xProp.is() )
+ {
+ xProp->removePropertyChangeListener(PROPERTY_NAME, this);
+ xProp->removeVetoableChangeListener(PROPERTY_NAME, this);
+ }
+}
+
+bool ODefinitionContainer::checkExistence(const OUString& _rName)
+{
+ return m_aDocumentMap.find(_rName) != m_aDocumentMap.end();
+}
+
+}
+
+// namespace dbaccess
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/dataaccess/documentcontainer.cxx b/dbaccess/source/core/dataaccess/documentcontainer.cxx
new file mode 100644
index 000000000..6a9f17adb
--- /dev/null
+++ b/dbaccess/source/core/dataaccess/documentcontainer.cxx
@@ -0,0 +1,770 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "documentcontainer.hxx"
+#include <stringconstants.hxx>
+#include "documentdefinition.hxx"
+#include <ModelImpl.hxx>
+#include <com/sun/star/ucb/OpenCommandArgument2.hpp>
+#include <com/sun/star/ucb/OpenMode.hpp>
+#include <connectivity/dbtools.hxx>
+#include "myucp_resultset.hxx"
+#include <ucbhelper/cancelcommandexecution.hxx>
+#include <com/sun/star/ucb/UnsupportedOpenModeException.hpp>
+#include <com/sun/star/ucb/InsertCommandArgument.hpp>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/sdb/ErrorCondition.hpp>
+#include <comphelper/mimeconfighelper.hxx>
+#include <connectivity/sqlerror.hxx>
+#include <core_resource.hxx>
+#include <strings.hrc>
+#include <strings.hxx>
+#include <comphelper/namedvaluecollection.hxx>
+#include <comphelper/propertysequence.hxx>
+#include <comphelper/servicehelper.hxx>
+#include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
+
+#include <vcl/svapp.hxx>
+#include <osl/mutex.hxx>
+#include <o3tl/string_view.hxx>
+
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::embed;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::ucb;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::sdb;
+using namespace ::com::sun::star::io;
+using namespace ::osl;
+using namespace ::comphelper;
+using namespace ::cppu;
+
+namespace dbaccess
+{
+
+namespace {
+
+// LocalNameApproval
+class LocalNameApproval : public IContainerApprove
+{
+ ::connectivity::SQLError m_aErrors;
+
+public:
+ void approveElement( const OUString& _rName ) override;
+};
+
+}
+
+void LocalNameApproval::approveElement( const OUString& _rName )
+{
+ if ( _rName.indexOf( '/' ) != -1 )
+ throw IllegalArgumentException(
+ m_aErrors.getErrorMessage( ErrorCondition::DB_OBJECT_NAME_WITH_SLASHES ),
+ nullptr,
+ 0
+ );
+}
+
+// ODocumentContainer
+
+ODocumentContainer::ODocumentContainer(const Reference< XComponentContext >& _xORB
+ ,const Reference< XInterface >& _xParentContainer
+ ,const TContentPtr& _pImpl
+ , bool _bFormsContainer
+ )
+ :ODefinitionContainer(_xORB,_xParentContainer,_pImpl)
+ ,OPropertyStateContainer(OContentHelper::rBHelper)
+ ,m_bFormsContainer(_bFormsContainer)
+{
+ registerProperty(PROPERTY_NAME, PROPERTY_ID_NAME, PropertyAttribute::BOUND | PropertyAttribute::READONLY | PropertyAttribute::CONSTRAINED,
+ &m_pImpl->m_aProps.aTitle, cppu::UnoType<decltype(m_pImpl->m_aProps.aTitle)>::get());
+
+ setElementApproval( std::make_shared<LocalNameApproval>() );
+}
+
+ODocumentContainer::~ODocumentContainer()
+{
+
+ if ( !OContentHelper::rBHelper.bInDispose && !OContentHelper::rBHelper.bDisposed )
+ {
+ acquire();
+ dispose();
+ }
+}
+
+IMPLEMENT_FORWARD_XINTERFACE3( ODocumentContainer,ODefinitionContainer,ODocumentContainer_Base,OPropertyStateContainer)
+
+css::uno::Sequence<sal_Int8> ODocumentContainer::getImplementationId()
+{
+ return css::uno::Sequence<sal_Int8>();
+}
+
+css::uno::Sequence< css::uno::Type > ODocumentContainer::getTypes()
+{
+ return ::comphelper::concatSequences(
+ ODefinitionContainer::getTypes( ),
+ OPropertyStateContainer::getTypes( ),
+ ODocumentContainer_Base::getTypes( )
+ );
+}
+OUString SAL_CALL ODocumentContainer::getImplementationName()
+ {
+ return "com.sun.star.comp.dba.ODocumentContainer";
+ };
+sal_Bool SAL_CALL ODocumentContainer::supportsService(const OUString& _rServiceName)
+ {
+ const css::uno::Sequence< OUString > aSupported(getSupportedServiceNames());
+ for (const OUString& s : aSupported)
+ if (s == _rServiceName)
+ return true;
+
+ return false;
+ };
+css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL ODocumentContainer::getPropertySetInfo()
+{
+ Reference< XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) );
+ return xInfo;
+}
+::cppu::IPropertyArrayHelper& ODocumentContainer::getInfoHelper()
+{
+ return *ODocumentContainer::getArrayHelper();
+}
+::cppu::IPropertyArrayHelper* ODocumentContainer::createArrayHelper( ) const
+{
+ css::uno::Sequence< css::beans::Property > aProps;
+ describeProperties(aProps);
+ return new ::cppu::OPropertyArrayHelper(aProps);
+}
+
+
+Sequence< OUString > SAL_CALL ODocumentContainer::getSupportedServiceNames( )
+{
+ return { m_bFormsContainer ? OUString(SERVICE_NAME_FORM_COLLECTION) : OUString(SERVICE_NAME_REPORT_COLLECTION) };
+}
+
+OUString ODocumentContainer::determineContentType() const
+{
+ return OUString();
+}
+
+Reference< XContent > ODocumentContainer::createObject( const OUString& _rName)
+{
+ const ODefinitionContainer_Impl& rDefinitions( getDefinitions() );
+ ODefinitionContainer_Impl::const_iterator aFind = rDefinitions.find( _rName );
+ OSL_ENSURE( aFind != rDefinitions.end(), "ODocumentContainer::createObject:Invalid entry in map!" );
+ if ( aFind->second->m_aProps.bIsFolder )
+ return new ODocumentContainer( m_aContext, *this, aFind->second, m_bFormsContainer );
+ return new ODocumentDefinition( *this, m_aContext, aFind->second, m_bFormsContainer );
+}
+
+Reference< XInterface > SAL_CALL ODocumentContainer::createInstance( const OUString& aServiceSpecifier )
+{
+ return createInstanceWithArguments( aServiceSpecifier, Sequence< Any >() );
+}
+
+namespace
+{
+ template< class TYPE >
+ void lcl_extractAndRemove( ::comphelper::NamedValueCollection& io_rArguments, const OUString& i_rName, TYPE& o_rValue )
+ {
+ if ( io_rArguments.has( i_rName ) )
+ {
+ io_rArguments.get_ensureType( i_rName, o_rValue );
+ io_rArguments.remove( i_rName );
+ }
+ }
+}
+
+Reference< XInterface > SAL_CALL ODocumentContainer::createInstanceWithArguments( const OUString& ServiceSpecifier, const Sequence< Any >& _aArguments )
+{
+ Reference< XInterface > xRet;
+ Reference< XContent > xContent;
+ if ( ServiceSpecifier == SERVICE_SDB_DOCUMENTDEFINITION )
+ {
+ MutexGuard aGuard(m_aMutex);
+
+ // extract known arguments
+ OUString sName, sPersistentName, sURL, sMediaType, sDocServiceName;
+ Reference< XCommandProcessor > xCopyFrom;
+ Reference< XConnection > xConnection;
+ bool bAsTemplate( false );
+ Sequence< sal_Int8 > aClassID;
+
+ ::comphelper::NamedValueCollection aArgs( _aArguments );
+ lcl_extractAndRemove( aArgs, PROPERTY_NAME, sName );
+ lcl_extractAndRemove( aArgs, PROPERTY_PERSISTENT_NAME, sPersistentName );
+ lcl_extractAndRemove( aArgs, PROPERTY_URL, sURL );
+ lcl_extractAndRemove( aArgs, PROPERTY_EMBEDDEDOBJECT, xCopyFrom );
+ lcl_extractAndRemove( aArgs, PROPERTY_ACTIVE_CONNECTION, xConnection );
+ lcl_extractAndRemove( aArgs, PROPERTY_AS_TEMPLATE, bAsTemplate );
+ lcl_extractAndRemove( aArgs, INFO_MEDIATYPE, sMediaType );
+ lcl_extractAndRemove( aArgs, "DocumentServiceName" , sDocServiceName );
+
+ // ClassID has two allowed types, so a special treatment here
+ Any aClassIDArg = aArgs.get( "ClassID" );
+ if ( aClassIDArg.hasValue() )
+ {
+ if ( !( aClassIDArg >>= aClassID ) )
+ {
+ // Extended for usage also with a string
+ OUString sClassIDString;
+ if ( !( aClassIDArg >>= sClassIDString ) )
+ throw IllegalArgumentException( OUString(), *this, 2 );
+
+ aClassID = ::comphelper::MimeConfigurationHelper::GetSequenceClassIDRepresentation( sClassIDString );
+ }
+
+#if OSL_DEBUG_LEVEL > 0
+ OUString sClassIDString = ::comphelper::MimeConfigurationHelper::GetStringClassIDRepresentation( aClassID );
+ (void)sClassIDString;
+#endif
+ aArgs.remove( "ClassID" );
+ }
+ // Everything which now is still present in the arguments is passed to the embedded object
+ const Sequence< PropertyValue > aCreationArgs( aArgs.getPropertyValues() );
+
+ const ODefinitionContainer_Impl& rDefinitions( getDefinitions() );
+ bool bNew = sPersistentName.isEmpty();
+ if ( bNew )
+ {
+ sPersistentName = "Obj" + OUString::number(rDefinitions.size() + 1);
+ Reference<XNameAccess> xElements = getContainerStorage();
+ if ( xElements.is() )
+ sPersistentName = ::dbtools::createUniqueName(xElements,sPersistentName);
+
+ const bool bNeedClassID = !aClassID.hasElements() && sURL.isEmpty() ;
+ if ( xCopyFrom.is() )
+ {
+ Sequence<Any> aIni{ Any(getContainerStorage()), Any(sPersistentName) };
+ Command aCommand;
+ aCommand.Name = "copyTo";
+ aCommand.Argument <<= aIni;
+
+ xCopyFrom->execute(aCommand,-1,Reference< XCommandEnvironment >());
+ Reference<XPropertySet> xProp(xCopyFrom,UNO_QUERY);
+ if ( xProp.is() && xProp->getPropertySetInfo().is() && xProp->getPropertySetInfo()->hasPropertyByName(PROPERTY_AS_TEMPLATE) )
+ xProp->getPropertyValue(PROPERTY_AS_TEMPLATE) >>= bAsTemplate;
+
+ // if we do not have an own class ID, see if we can determine one from the copy we just created
+ if ( bNeedClassID )
+ ODocumentDefinition::GetDocumentServiceFromMediaType( getContainerStorage(), sPersistentName, m_aContext, aClassID );
+ }
+ else
+ {
+ if ( bNeedClassID )
+ {
+ if ( !sMediaType.isEmpty() )
+ ODocumentDefinition::GetDocumentServiceFromMediaType( sMediaType, m_aContext, aClassID );
+ else if ( !sDocServiceName.isEmpty() )
+ {
+ ::comphelper::MimeConfigurationHelper aConfigHelper( m_aContext );
+ const Sequence< NamedValue > aProps( aConfigHelper.GetObjectPropsByDocumentName( sDocServiceName ) );
+ const ::comphelper::NamedValueCollection aMediaTypeProps( aProps );
+ aClassID = aMediaTypeProps.getOrDefault( "ClassID", Sequence< sal_Int8 >() );
+ }
+ }
+ }
+ }
+
+ ODefinitionContainer_Impl::const_iterator aFind = rDefinitions.find( sName );
+ TContentPtr pElementImpl;
+ if ( bNew || ( aFind == rDefinitions.end() ) )
+ {
+ pElementImpl = std::make_shared<OContentHelper_Impl>();
+ if ( !bNew )
+ pElementImpl->m_aProps.aTitle = sName;
+
+ pElementImpl->m_aProps.sPersistentName = sPersistentName;
+ pElementImpl->m_aProps.bAsTemplate = bAsTemplate;
+ pElementImpl->m_pDataSource = m_pImpl->m_pDataSource;
+ }
+ else
+ pElementImpl = aFind->second;
+
+ ::rtl::Reference< ODocumentDefinition > pDocDef = new ODocumentDefinition( *this, m_aContext, pElementImpl, m_bFormsContainer );
+ if ( aClassID.hasElements() )
+ {
+ pDocDef->initialLoad( aClassID, aCreationArgs, xConnection );
+ }
+ else
+ {
+ OSL_ENSURE( !aCreationArgs.hasElements(), "ODocumentContainer::createInstance: additional creation args are lost, if you do not provide a class ID." );
+ }
+ xContent = pDocDef.get();
+
+ if ( !sURL.isEmpty() )
+ {
+ Sequence<Any> aIni{ Any(sURL) };
+ Command aCommand;
+ aCommand.Name = "insert";
+ aCommand.Argument <<= aIni;
+ Reference< XCommandProcessor > xCommandProcessor(xContent,UNO_QUERY);
+ if ( xContent.is() )
+ {
+ xCommandProcessor->execute(aCommand,-1,Reference< XCommandEnvironment >());
+ }
+ }
+ }
+ else if ( ServiceSpecifier == SERVICE_NAME_FORM_COLLECTION || SERVICE_NAME_REPORT_COLLECTION == ServiceSpecifier )
+ {
+ const Any* pBegin = _aArguments.getConstArray();
+ const Any* pEnd = pBegin + _aArguments.getLength();
+ PropertyValue aValue;
+ OUString sName;
+ Reference<XNameAccess> xCopyFrom;
+ for(;pBegin != pEnd;++pBegin)
+ {
+ *pBegin >>= aValue;
+ if ( aValue.Name == PROPERTY_NAME)
+ {
+ aValue.Value >>= sName;
+ }
+ else if ( aValue.Name == PROPERTY_EMBEDDEDOBJECT)
+ {
+ xCopyFrom.set(aValue.Value,UNO_QUERY);
+ }
+ }
+ OSL_ENSURE(!sName.isEmpty(),"Invalid name for a document container!");
+ const ODefinitionContainer_Impl& rDefinitions( getDefinitions() );
+ ODefinitionContainer_Impl::const_iterator aFind = rDefinitions.find( sName );
+ TContentPtr pElementImpl;
+ if ( aFind == rDefinitions.end() )
+ {
+ pElementImpl = std::make_shared<ODefinitionContainer_Impl>();
+ pElementImpl->m_aProps.aTitle = sName;
+ pElementImpl->m_pDataSource = m_pImpl->m_pDataSource;
+ }
+ else
+ pElementImpl = aFind->second;
+ OSL_ENSURE( pElementImpl ," Invalid entry in map!");
+ xContent = new ODocumentContainer( m_aContext, *this, pElementImpl, ServiceSpecifier == SERVICE_NAME_FORM_COLLECTION );
+
+ // copy children
+ if ( xCopyFrom.is() )
+ {
+ Sequence< OUString> aSeq = xCopyFrom->getElementNames();
+ const OUString* elements = aSeq.getConstArray();
+ const OUString* elementsEnd = elements + aSeq.getLength();
+ Reference<XContent> xObjectToCopy;
+
+ Reference<XMultiServiceFactory> xORB(xContent,UNO_QUERY);
+ OSL_ENSURE(xORB.is(),"No service factory given");
+ if ( xORB.is() )
+ {
+ for(;elements != elementsEnd;++elements)
+ {
+ xCopyFrom->getByName(*elements) >>= xObjectToCopy;
+ Sequence<Any> aArguments(comphelper::InitAnyPropertySequence(
+ {
+ {"Name", Any(*elements)}, // set as folder
+ {"Parent", Any(xContent)},
+ {PROPERTY_EMBEDDEDOBJECT, Any(xObjectToCopy)},
+ }));
+
+ OUString sServiceName;
+ if ( Reference< XNameAccess >( xObjectToCopy, UNO_QUERY ).is() )
+ {
+ if ( m_bFormsContainer )
+ sServiceName = SERVICE_NAME_FORM_COLLECTION;
+ else
+ sServiceName = SERVICE_NAME_REPORT_COLLECTION;
+ }
+ else
+ sServiceName = SERVICE_SDB_DOCUMENTDEFINITION;
+
+ Reference<XContent > xNew(xORB->createInstanceWithArguments(sServiceName,aArguments),UNO_QUERY);
+ Reference<XNameContainer> xNameContainer(xContent,UNO_QUERY);
+ if ( xNameContainer.is() )
+ xNameContainer->insertByName(*elements,Any(xNew));
+ }
+ }
+ }
+ }
+ xRet = xContent;
+ return xRet;
+}
+
+Sequence< OUString > SAL_CALL ODocumentContainer::getAvailableServiceNames( )
+{
+ return
+ {
+ SERVICE_SDB_DOCUMENTDEFINITION,
+ SERVICE_NAME_FORM_COLLECTION,
+ SERVICE_NAME_REPORT_COLLECTION
+ };
+}
+
+Any SAL_CALL ODocumentContainer::execute( const Command& aCommand, sal_Int32 CommandId, const Reference< XCommandEnvironment >& Environment )
+{
+ Any aRet;
+ if ( aCommand.Name == "open" )
+ {
+ // open command for a folder content
+ OpenCommandArgument2 aOpenCommand;
+ if ( !( aCommand.Argument >>= aOpenCommand ) )
+ {
+ OSL_FAIL( "Wrong argument type!" );
+ ucbhelper::cancelCommandExecution(
+ Any( IllegalArgumentException(
+ OUString(),
+ static_cast< cppu::OWeakObject * >( this ),
+ -1 ) ),
+ Environment );
+ // Unreachable
+ }
+ bool bOpenFolder =
+ ( ( aOpenCommand.Mode == OpenMode::ALL ) ||
+ ( aOpenCommand.Mode == OpenMode::FOLDERS ) ||
+ ( aOpenCommand.Mode == OpenMode::DOCUMENTS ) );
+
+ if ( bOpenFolder )
+ {
+ // open as folder - return result set
+
+ Reference< XDynamicResultSet > xSet
+ = new DynamicResultSet( m_aContext,
+ this,
+ aOpenCommand,
+ Environment );
+ aRet <<= xSet;
+ }
+ else
+ {
+ // Unsupported.
+ ucbhelper::cancelCommandExecution(
+ Any( UnsupportedOpenModeException(
+ OUString(),
+ static_cast< cppu::OWeakObject * >( this ),
+ sal_Int16( aOpenCommand.Mode ) ) ),
+ Environment );
+ // Unreachable
+ }
+ }
+ else if ( aCommand.Name == "insert" )
+ {
+ // insert
+
+ InsertCommandArgument arg;
+ if ( !( aCommand.Argument >>= arg ) )
+ {
+ OSL_FAIL( "Wrong argument type!" );
+ ucbhelper::cancelCommandExecution(
+ Any( IllegalArgumentException(
+ OUString(),
+ static_cast< cppu::OWeakObject * >( this ),
+ -1 ) ),
+ Environment );
+ // Unreachable
+ }
+ }
+ else if ( aCommand.Name == "delete" )
+ {
+ // delete
+ Sequence< OUString> aSeq = getElementNames();
+ const OUString* pIter = aSeq.getConstArray();
+ const OUString* pEnd = pIter + aSeq.getLength();
+ for(;pIter != pEnd;++pIter)
+ removeByName(*pIter);
+
+ dispose();
+ }
+ else
+ aRet = OContentHelper::execute(aCommand,CommandId,Environment);
+ return aRet;
+}
+
+namespace
+{
+ bool lcl_queryContent(std::u16string_view _sName,Reference< XNameContainer >& _xNameContainer,Any& _rRet,OUString& _sSimpleName)
+ {
+ sal_Int32 nIndex = 0;
+ OUString sName( o3tl::getToken(_sName,0,'/',nIndex) );
+ bool bRet = _xNameContainer->hasByName(sName);
+ if ( bRet )
+ {
+ _sSimpleName = sName;
+ _rRet = _xNameContainer->getByName(_sSimpleName);
+ while ( nIndex != -1 && bRet )
+ {
+ sName = o3tl::getToken(_sName,0,'/',nIndex);
+ _xNameContainer.set(_rRet,UNO_QUERY);
+ bRet = _xNameContainer.is();
+ if ( bRet )
+ {
+ bRet = _xNameContainer->hasByName(sName);
+ _sSimpleName = sName;
+ if ( bRet )
+ _rRet = _xNameContainer->getByName(sName);
+ }
+ }
+ }
+ if ( nIndex == -1 )
+ _sSimpleName = sName; // a content
+ else
+ _xNameContainer.clear(); // a sub folder doesn't exist
+ return bRet;
+ }
+}
+
+Reference< XComponent > SAL_CALL ODocumentContainer::loadComponentFromURL( const OUString& _sURL
+ , const OUString& /*TargetFrameName*/
+ , sal_Int32 /*SearchFlags*/
+ , const Sequence< PropertyValue >& Arguments )
+{
+ ::SolarMutexGuard aSolarGuard;
+
+ MutexGuard aGuard(m_aMutex);
+ Reference< XComponent > xComp;
+ try
+ {
+ Any aContent;
+ Reference< XNameContainer > xNameContainer(this);
+ OUString sName;
+ if ( !lcl_queryContent(_sURL,xNameContainer,aContent,sName) )
+ {
+ OUString sMessage(
+ DBA_RES(RID_STR_NAME_NOT_FOUND).replaceFirst("$name$", _sURL));
+ throw IllegalArgumentException( sMessage, *this, 1 );
+ }
+
+ Reference< XCommandProcessor > xContent(aContent,UNO_QUERY);
+ if ( xContent.is() )
+ {
+ Command aCommand;
+
+ ::comphelper::NamedValueCollection aArgs( Arguments );
+ aCommand.Name = aArgs.getOrDefault( "OpenMode", OUString("open") );
+ aArgs.remove( "OpenMode" );
+
+ OpenCommandArgument2 aOpenCommand;
+ aOpenCommand.Mode = OpenMode::DOCUMENT;
+ aArgs.put( "OpenCommandArgument", aOpenCommand );
+
+ aCommand.Argument <<= aArgs.getPropertyValues();
+ xComp.set(xContent->execute(aCommand,xContent->createCommandIdentifier(),Reference< XCommandEnvironment >()),UNO_QUERY);
+ }
+ }
+ catch(const NoSuchElementException&)
+ {
+ throw IllegalArgumentException();
+ }
+ catch(const WrappedTargetException &e)
+ {
+ throw WrappedTargetRuntimeException(e.Message, e.Context, e.TargetException);
+ }
+ return xComp;
+}
+
+Any SAL_CALL ODocumentContainer::getByHierarchicalName( const OUString& _sName )
+{
+ MutexGuard aGuard(m_aMutex);
+ Any aContent;
+ Reference< XNameContainer > xNameContainer(this);
+ OUString sName;
+ if ( lcl_queryContent(_sName,xNameContainer,aContent,sName) )
+ return aContent;
+ throw NoSuchElementException(_sName,*this);
+}
+
+sal_Bool SAL_CALL ODocumentContainer::hasByHierarchicalName( const OUString& _sName )
+{
+ MutexGuard aGuard(m_aMutex);
+ Any aContent;
+ Reference< XNameContainer > xNameContainer(this);
+ OUString sName;
+ return lcl_queryContent(_sName,xNameContainer,aContent,sName);
+}
+
+// XHierarchicalNameContainer
+void SAL_CALL ODocumentContainer::insertByHierarchicalName( const OUString& _sName, const Any& _aElement )
+{
+ Reference< XContent > xContent(_aElement,UNO_QUERY);
+ if ( !xContent.is() )
+ throw IllegalArgumentException();
+
+ MutexGuard aGuard(m_aMutex);
+ Any aContent;
+ Reference< XNameContainer > xNameContainer(this);
+ OUString sName;
+ if ( lcl_queryContent(_sName,xNameContainer,aContent,sName) )
+ throw ElementExistException(_sName,*this);
+
+ if ( !xNameContainer.is() )
+ {
+ sal_Int32 index = sName.getLength();
+ OUString sMessage(
+ DBA_RES(RID_STR_NO_SUB_FOLDER).replaceFirst("$folder$",
+ o3tl::getToken(_sName, 0,'/',index)));
+ throw IllegalArgumentException( sMessage, *this, 1 );
+ }
+
+ xNameContainer->insertByName(sName,_aElement);
+}
+
+void SAL_CALL ODocumentContainer::removeByHierarchicalName( const OUString& _sName )
+{
+ if ( _sName.isEmpty() )
+ throw NoSuchElementException(_sName,*this);
+
+ MutexGuard aGuard(m_aMutex);
+ Any aContent;
+ OUString sName;
+ Reference< XNameContainer > xNameContainer(this);
+ if ( !lcl_queryContent(_sName,xNameContainer,aContent,sName) )
+ throw NoSuchElementException(_sName,*this);
+
+ xNameContainer->removeByName(sName);
+}
+
+// XHierarchicalNameReplace
+void SAL_CALL ODocumentContainer::replaceByHierarchicalName( const OUString& _sName, const Any& _aElement )
+{
+ Reference< XContent > xContent(_aElement,UNO_QUERY);
+ if ( !xContent.is() )
+ throw IllegalArgumentException();
+
+ MutexGuard aGuard(m_aMutex);
+ Any aContent;
+ OUString sName;
+ Reference< XNameContainer > xNameContainer(this);
+ if ( !lcl_queryContent(_sName,xNameContainer,aContent,sName) )
+ throw NoSuchElementException(_sName,*this);
+
+ xNameContainer->replaceByName(sName,_aElement);
+}
+
+OUString SAL_CALL ODocumentContainer::getHierarchicalName()
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ return impl_getHierarchicalName( false );
+}
+
+OUString SAL_CALL ODocumentContainer::composeHierarchicalName( const OUString& i_rRelativeName )
+{
+ OUString aBuffer = getHierarchicalName() + "/" + i_rRelativeName;
+ return aBuffer;
+}
+
+::rtl::Reference<OContentHelper> ODocumentContainer::getContent(const OUString& _sName) const
+{
+ ::rtl::Reference<OContentHelper> pContent;
+ try
+ {
+ pContent = comphelper::getFromUnoTunnel<OContentHelper>(const_cast<ODocumentContainer*>(this)->implGetByName( _sName, true ));
+ }
+ catch(const Exception&)
+ {
+ }
+ return pContent;
+}
+
+void ODocumentContainer::getPropertyDefaultByHandle( sal_Int32 /*_nHandle*/, Any& _rDefault ) const
+{
+ _rDefault.clear();
+}
+
+void SAL_CALL ODocumentContainer::commit( )
+{
+ MutexGuard aGuard(m_aMutex);
+ for (auto const& elem : m_aDocumentMap)
+ {
+ Reference<XTransactedObject> xTrans(elem.second.get(),UNO_QUERY);
+ if ( xTrans.is() )
+ xTrans->commit();
+ }
+ Reference<XTransactedObject> xTrans(getContainerStorage(),UNO_QUERY);
+ if ( xTrans.is() )
+ xTrans->commit();
+}
+
+void SAL_CALL ODocumentContainer::revert( )
+{
+ MutexGuard aGuard(m_aMutex);
+ for (auto const& elem : m_aDocumentMap)
+ {
+ Reference<XTransactedObject> xTrans(elem.second.get(),UNO_QUERY);
+ if ( xTrans.is() )
+ xTrans->revert();
+ }
+ Reference<XTransactedObject> xTrans(getContainerStorage(),UNO_QUERY);
+ if ( xTrans.is() )
+ xTrans->revert();
+}
+
+Reference< XStorage> ODocumentContainer::getContainerStorage() const
+{
+ return m_pImpl->m_pDataSource
+ ? m_pImpl->m_pDataSource->getStorage( m_bFormsContainer ? ODatabaseModelImpl::E_FORM : ODatabaseModelImpl::E_REPORT )
+ : Reference< XStorage>();
+}
+
+void SAL_CALL ODocumentContainer::removeByName( const OUString& _rName )
+{
+ ResettableMutexGuard aGuard(m_aMutex);
+
+ // check the arguments
+ if (_rName.isEmpty())
+ throw IllegalArgumentException();
+
+ if (!checkExistence(_rName))
+ throw NoSuchElementException(_rName,*this);
+
+ Reference< XCommandProcessor > xContent( implGetByName( _rName, true ), UNO_QUERY );
+ if ( xContent.is() )
+ {
+ Command aCommand;
+
+ aCommand.Name = "delete";
+ xContent->execute(aCommand,xContent->createCommandIdentifier(),Reference< XCommandEnvironment >());
+ }
+
+ // do the removal
+ implRemove(_rName);
+
+ notifyByName( aGuard, _rName, nullptr, nullptr, E_REMOVED, ContainerListemers );
+}
+
+void SAL_CALL ODocumentContainer::rename( const OUString& newName )
+{
+ try
+ {
+ osl::ClearableGuard< osl::Mutex > aGuard(m_aMutex);
+ if ( newName == m_pImpl->m_aProps.aTitle )
+ return;
+
+ sal_Int32 nHandle = PROPERTY_ID_NAME;
+ Any aOld(m_pImpl->m_aProps.aTitle);
+ Any aNew(newName);
+
+ aGuard.clear();
+ fire(&nHandle, &aNew, &aOld, 1, true );
+ m_pImpl->m_aProps.aTitle = newName;
+ fire(&nHandle, &aNew, &aOld, 1, false );
+ }
+ catch(const PropertyVetoException&)
+ {
+ throw ElementExistException(newName,*this);
+ }
+}
+
+} // namespace dbaccess
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/dataaccess/documentcontainer.hxx b/dbaccess/source/core/dataaccess/documentcontainer.hxx
new file mode 100644
index 000000000..d47709e80
--- /dev/null
+++ b/dbaccess/source/core/dataaccess/documentcontainer.hxx
@@ -0,0 +1,137 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <definitioncontainer.hxx>
+#include <cppuhelper/implbase5.hxx>
+#include <connectivity/CommonTools.hxx>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/frame/XComponentLoader.hpp>
+#include <com/sun/star/container/XHierarchicalNameContainer.hpp>
+#include <com/sun/star/container/XHierarchicalName.hpp>
+#include <com/sun/star/embed/XStorage.hpp>
+#include <com/sun/star/embed/XTransactedObject.hpp>
+#include <comphelper/propertystatecontainer.hxx>
+#include <comphelper/proparrhlp.hxx>
+#include <rtl/ref.hxx>
+#include <apitools.hxx>
+
+namespace dbaccess
+{
+typedef ::cppu::ImplHelper5 < css::frame::XComponentLoader
+ , css::lang::XMultiServiceFactory
+ , css::container::XHierarchicalNameContainer
+ , css::container::XHierarchicalName
+ , css::embed::XTransactedObject
+ > ODocumentContainer_Base;
+// ODocumentContainer - collections of database documents (reports/forms)
+class ODocumentContainer : public ODefinitionContainer
+ , public ODocumentContainer_Base
+ , public ::comphelper::OPropertyStateContainer
+ , public ::comphelper::OPropertyArrayUsageHelper< ODocumentContainer >
+{
+ bool m_bFormsContainer;
+
+public:
+ /** constructs the container.<BR>
+ */
+ ODocumentContainer(
+ const css::uno::Reference< css::uno::XComponentContext >& _xORB
+ , const css::uno::Reference< css::uno::XInterface >& _xParentContainer
+ ,const TContentPtr& _pImpl
+ , bool _bFormsContainer
+ );
+
+ // css::uno::XInterface
+ DECLARE_XINTERFACE( )
+
+ virtual css::uno::Sequence<css::uno::Type> SAL_CALL getTypes() override;
+ virtual css::uno::Sequence<sal_Int8> SAL_CALL getImplementationId() override;
+
+ // css::lang::XServiceInfo
+ DECLARE_SERVICE_INFO();
+
+ // XComponentLoader
+ virtual css::uno::Reference< css::lang::XComponent > SAL_CALL loadComponentFromURL( const OUString& URL, const OUString& TargetFrameName, sal_Int32 SearchFlags, const css::uno::Sequence< css::beans::PropertyValue >& Arguments ) override;
+
+ // css::lang::XMultiServiceFactory
+ virtual css::uno::Reference< css::uno::XInterface > SAL_CALL createInstance( const OUString& aServiceSpecifier ) override;
+ virtual css::uno::Reference< css::uno::XInterface > SAL_CALL createInstanceWithArguments( const OUString& ServiceSpecifier, const css::uno::Sequence< css::uno::Any >& Arguments ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getAvailableServiceNames( ) override;
+
+ // XCommandProcessor
+ virtual css::uno::Any SAL_CALL execute( const css::ucb::Command& aCommand, sal_Int32 CommandId, const css::uno::Reference< css::ucb::XCommandEnvironment >& Environment ) override ;
+
+ // XHierarchicalNameAccess
+ virtual css::uno::Any SAL_CALL getByHierarchicalName( const OUString& _sName ) override;
+ virtual sal_Bool SAL_CALL hasByHierarchicalName( const OUString& _sName ) override;
+
+ // XHierarchicalNameContainer
+ virtual void SAL_CALL insertByHierarchicalName( const OUString& aName, const css::uno::Any& aElement ) override;
+ virtual void SAL_CALL removeByHierarchicalName( const OUString& Name ) override;
+
+ // XHierarchicalName
+ virtual OUString SAL_CALL getHierarchicalName( ) override;
+ virtual OUString SAL_CALL composeHierarchicalName( const OUString& aRelativeName ) override;
+
+ // XNameContainer
+ virtual void SAL_CALL removeByName( const OUString& _rName ) override;
+
+ // XHierarchicalNameReplace
+ virtual void SAL_CALL replaceByHierarchicalName( const OUString& aName, const css::uno::Any& aElement ) override;
+
+ // css::beans::XPropertySet
+ virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo( ) override;
+
+ // XTransactedObject
+ virtual void SAL_CALL commit( ) override;
+ virtual void SAL_CALL revert( ) override;
+
+ // XRename
+ virtual void SAL_CALL rename( const OUString& newName ) override;
+
+ // OPropertySetHelper
+ virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper() override;
+
+ // helper
+ ::rtl::Reference<OContentHelper> getContent(const OUString& _sName) const;
+ css::uno::Reference< css::embed::XStorage > getContainerStorage() const;
+
+protected:
+ virtual ~ODocumentContainer() override;
+
+ /** OContentHelper
+ */
+ virtual OUString determineContentType() const override;
+
+ // ODefinitionContainer
+ virtual css::uno::Reference< css::ucb::XContent > createObject(
+ const OUString& _rName
+ ) override;
+
+ virtual void getPropertyDefaultByHandle( sal_Int32 _nHandle, css::uno::Any& _rDefault ) const override;
+
+ // OPropertyArrayUsageHelper
+ virtual ::cppu::IPropertyArrayHelper* createArrayHelper( ) const override;
+};
+
+} // namespace dbaccess
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/dataaccess/documentdefinition.cxx b/dbaccess/source/core/dataaccess/documentdefinition.cxx
new file mode 100644
index 000000000..98e84d6d4
--- /dev/null
+++ b/dbaccess/source/core/dataaccess/documentdefinition.cxx
@@ -0,0 +1,2102 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "documentdefinition.hxx"
+#include <ModelImpl.hxx>
+#include <stringconstants.hxx>
+#include <sdbcoretools.hxx>
+#include <tools/diagnose_ex.h>
+#include <osl/diagnose.h>
+#include <comphelper/sequence.hxx>
+#include <comphelper/namedvaluecollection.hxx>
+#include <comphelper/classids.hxx>
+#include <comphelper/propertysequence.hxx>
+#include <comphelper/propertyvalue.hxx>
+#include <comphelper/types.hxx>
+#include <com/sun/star/frame/XUntitledNumbers.hpp>
+#include <com/sun/star/awt/Size.hpp>
+#include <com/sun/star/lang/DisposedException.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/frame/Desktop.hpp>
+#include <com/sun/star/frame/XModel.hpp>
+#include <com/sun/star/frame/XTitle.hpp>
+#include <com/sun/star/frame/XController.hpp>
+#include <com/sun/star/task/XJobExecutor.hpp>
+#include <com/sun/star/report/XReportDefinition.hpp>
+#include <com/sun/star/report/XReportEngine.hpp>
+#include <com/sun/star/ucb/OpenMode.hpp>
+#include <com/sun/star/embed/WrongStateException.hpp>
+#include <com/sun/star/embed/EmbeddedObjectCreator.hpp>
+#include <com/sun/star/embed/Aspects.hpp>
+#include <com/sun/star/embed/OOoEmbeddedObjectFactory.hpp>
+#include <ucbhelper/cancelcommandexecution.hxx>
+#include <com/sun/star/ucb/UnsupportedOpenModeException.hpp>
+#include <com/sun/star/embed/ElementModes.hpp>
+#include <com/sun/star/embed/XEmbedPersist.hpp>
+#include <com/sun/star/embed/EmbedStates.hpp>
+#include <com/sun/star/embed/EntryInitModes.hpp>
+#include <com/sun/star/ucb/MissingPropertiesException.hpp>
+#include <com/sun/star/ucb/OpenCommandArgument2.hpp>
+#include <com/sun/star/util/CloseVetoException.hpp>
+#include <com/sun/star/frame/XModule.hpp>
+#include <com/sun/star/datatransfer/DataFlavor.hpp>
+#include <com/sun/star/datatransfer/XTransferable.hpp>
+#include <com/sun/star/container/XNameContainer.hpp>
+#include <com/sun/star/embed/XCommonEmbedPersist.hpp>
+#include "intercept.hxx"
+#include <com/sun/star/sdb/ErrorCondition.hpp>
+#include <com/sun/star/sdb/XInteractionDocumentSave.hpp>
+#include <com/sun/star/task/InteractionHandler.hpp>
+#include <com/sun/star/sdb/DocumentSaveRequest.hpp>
+#include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
+#include <com/sun/star/document/MacroExecMode.hpp>
+#include <com/sun/star/drawing/XDrawPageSupplier.hpp>
+#include <com/sun/star/form/XFormsSupplier.hpp>
+#include <com/sun/star/form/XForm.hpp>
+#include <comphelper/interaction.hxx>
+#include <connectivity/dbtools.hxx>
+#include <vcl/svapp.hxx>
+#include <osl/mutex.hxx>
+#include <com/sun/star/view/XViewSettingsSupplier.hpp>
+#include <core_resource.hxx>
+#include <strings.hrc>
+#include <strings.hxx>
+#include <com/sun/star/task/XInteractionApprove.hpp>
+#include <com/sun/star/task/XInteractionDisapprove.hpp>
+#include <com/sun/star/frame/XLayoutManager.hpp>
+#include <cppuhelper/compbase.hxx>
+#include <cppuhelper/exc_hlp.hxx>
+#include <cppuhelper/implbase.hxx>
+#include <comphelper/mimeconfighelper.hxx>
+#include <com/sun/star/container/XContentEnumerationAccess.hpp>
+#include <com/sun/star/io/WrongFormatException.hpp>
+#include <com/sun/star/sdb/application/XDatabaseDocumentUI.hpp>
+#include <com/sun/star/sdb/application/DatabaseObject.hpp>
+#include <com/sun/star/util/XModifiable2.hpp>
+
+using namespace ::com::sun::star;
+using namespace view;
+using namespace uno;
+using namespace util;
+using namespace ucb;
+using namespace beans;
+using namespace lang;
+using namespace awt;
+using namespace embed;
+using namespace frame;
+using namespace document;
+using namespace sdbc;
+using namespace sdb;
+using namespace io;
+using namespace container;
+using namespace datatransfer;
+using namespace task;
+using namespace form;
+using namespace drawing;
+using namespace ::osl;
+using namespace ::comphelper;
+using namespace ::cppu;
+
+using sdb::application::XDatabaseDocumentUI;
+namespace DatabaseObject = sdb::application::DatabaseObject;
+
+#define DEFAULT_WIDTH 10000
+#define DEFAULT_HEIGHT 7500
+
+namespace dbaccess
+{
+
+ typedef ::std::optional< bool > optional_bool;
+
+ // helper
+ namespace
+ {
+ OUString lcl_determineContentType_nothrow( const Reference< XStorage >& _rxContainerStorage,
+ const OUString& _rEntityName )
+ {
+ OUString sContentType;
+ try
+ {
+ ::utl::SharedUNOComponent< XPropertySet > xStorageProps(
+ _rxContainerStorage->openStorageElement( _rEntityName, ElementModes::READ ), UNO_QUERY_THROW );
+ OSL_VERIFY( xStorageProps->getPropertyValue( INFO_MEDIATYPE ) >>= sContentType );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ return sContentType;
+ }
+ }
+
+ // OEmbedObjectHolder
+ typedef ::cppu::WeakComponentImplHelper< embed::XStateChangeListener > TEmbedObjectHolder;
+
+ namespace {
+
+ class OEmbedObjectHolder : public ::cppu::BaseMutex
+ ,public TEmbedObjectHolder
+ {
+ Reference< XEmbeddedObject > m_xBroadCaster;
+ ODocumentDefinition* m_pDefinition;
+ bool m_bInStateChange;
+ protected:
+ virtual void SAL_CALL disposing() override;
+ public:
+ OEmbedObjectHolder(const Reference< XEmbeddedObject >& _xBroadCaster,ODocumentDefinition* _pDefinition)
+ : TEmbedObjectHolder(m_aMutex)
+ ,m_xBroadCaster(_xBroadCaster)
+ ,m_pDefinition(_pDefinition)
+ ,m_bInStateChange(false)
+ {
+ osl_atomic_increment( &m_refCount );
+ {
+ if ( m_xBroadCaster.is() )
+ m_xBroadCaster->addStateChangeListener(this);
+ }
+ osl_atomic_decrement( &m_refCount );
+ }
+
+ virtual void SAL_CALL changingState( const lang::EventObject& aEvent, ::sal_Int32 nOldState, ::sal_Int32 nNewState ) override;
+ virtual void SAL_CALL stateChanged( const lang::EventObject& aEvent, ::sal_Int32 nOldState, ::sal_Int32 nNewState ) override;
+ virtual void SAL_CALL disposing( const lang::EventObject& Source ) override;
+ };
+
+ }
+
+ void SAL_CALL OEmbedObjectHolder::disposing()
+ {
+ if ( m_xBroadCaster.is() )
+ m_xBroadCaster->removeStateChangeListener(this);
+ m_xBroadCaster = nullptr;
+ m_pDefinition = nullptr;
+ }
+
+ void SAL_CALL OEmbedObjectHolder::changingState( const lang::EventObject& /*aEvent*/, ::sal_Int32 /*nOldState*/, ::sal_Int32 /*nNewState*/ )
+ {
+ }
+
+ void SAL_CALL OEmbedObjectHolder::stateChanged( const lang::EventObject& aEvent, ::sal_Int32 nOldState, ::sal_Int32 nNewState )
+ {
+ if ( !m_bInStateChange && nNewState == EmbedStates::RUNNING && nOldState == EmbedStates::ACTIVE && m_pDefinition )
+ {
+ m_bInStateChange = true;
+ Reference<XInterface> xHoldAlive(static_cast< ::cppu::OWeakObject* >(m_pDefinition),UNO_QUERY);
+ {
+ Reference<XEmbeddedObject> xEmbeddedObject(aEvent.Source,UNO_QUERY);
+ if ( xEmbeddedObject.is() )
+ xEmbeddedObject->changeState(EmbedStates::LOADED);
+ }
+ m_bInStateChange = false;
+ }
+ }
+
+ void SAL_CALL OEmbedObjectHolder::disposing( const lang::EventObject& /*Source*/ )
+ {
+ m_xBroadCaster = nullptr;
+ }
+
+ // OEmbeddedClientHelper
+ class OEmbeddedClientHelper : public ::cppu::WeakImplHelper<XEmbeddedClient>
+ {
+ public:
+ virtual void SAL_CALL saveObject( ) override
+ {
+ }
+ // XComponentSupplier
+ virtual Reference< util::XCloseable > SAL_CALL getComponent( ) override
+ {
+ return Reference< css::util::XCloseable >();
+ }
+
+ // XEmbeddedClient
+ virtual void SAL_CALL visibilityChanged( sal_Bool /*bVisible*/ ) override
+ {
+ }
+ };
+
+ namespace {
+
+ // LockModifiable
+ class LockModifiable
+ {
+ public:
+ explicit LockModifiable( const Reference< XInterface >& i_rModifiable )
+ :m_xModifiable( i_rModifiable, UNO_QUERY )
+ {
+ OSL_ENSURE( m_xModifiable.is(), "LockModifiable::LockModifiable: invalid component!" );
+ if ( m_xModifiable.is() )
+ {
+ if ( !m_xModifiable->isSetModifiedEnabled() )
+ {
+ // somebody already locked that, no need to lock it, again, and no need to unlock it later
+ m_xModifiable.clear();
+ }
+ else
+ {
+ m_xModifiable->disableSetModified();
+ }
+ }
+ }
+
+ ~LockModifiable()
+ {
+ if ( m_xModifiable.is() )
+ m_xModifiable->enableSetModified();
+ }
+
+ private:
+ Reference< XModifiable2 > m_xModifiable;
+ };
+
+ }
+
+ // LifetimeCoupler
+ typedef ::cppu::WeakImplHelper< css::lang::XEventListener
+ > LifetimeCoupler_Base;
+
+ namespace {
+
+ /** helper class which couples the lifetime of a component to the lifetime
+ of another component
+
+ Instances of this class are constructed with two components. The first is
+ simply held by reference, and thus kept alive. The second one is observed
+ for <code>disposing</code> calls - if they occur, i.e. if the component dies,
+ the reference to the first component is cleared.
+
+ This way, you can ensure that a certain component is kept alive as long
+ as a second component is not disposed.
+ */
+ class LifetimeCoupler : public LifetimeCoupler_Base
+ {
+ private:
+ Reference< XInterface > m_xClient;
+
+ public:
+ static void couple( const Reference< XInterface >& _rxClient, const Reference< XComponent >& _rxActor )
+ {
+ new LifetimeCoupler( _rxClient, _rxActor );
+ }
+
+ private:
+ LifetimeCoupler( const Reference< XInterface >& _rxClient, const Reference< XComponent >& _rxActor )
+ :m_xClient( _rxClient )
+ {
+ OSL_ENSURE( _rxActor.is(), "LifetimeCoupler::LifetimeCoupler: this will crash!" );
+ osl_atomic_increment( &m_refCount );
+ {
+ _rxActor->addEventListener( this );
+ }
+ osl_atomic_decrement( &m_refCount );
+ OSL_ENSURE( m_refCount, "LifetimeCoupler::LifetimeCoupler: the actor is not holding us by hard ref - this won't work!" );
+ }
+
+ virtual void SAL_CALL disposing( const css::lang::EventObject& Source ) override;
+ protected:
+ };
+
+ }
+
+ void SAL_CALL LifetimeCoupler::disposing( const css::lang::EventObject& /*Source*/ )
+ {
+ m_xClient.clear();
+ }
+
+ namespace {
+
+ // ODocumentSaveContinuation
+ class ODocumentSaveContinuation : public OInteraction< XInteractionDocumentSave >
+ {
+ OUString m_sName;
+ Reference<XContent> m_xParentContainer;
+
+ public:
+ ODocumentSaveContinuation() { }
+
+ const Reference<XContent>& getContent() const { return m_xParentContainer; }
+ const OUString& getName() const { return m_sName; }
+
+ // XInteractionDocumentSave
+ virtual void SAL_CALL setName( const OUString& _sName,const Reference<XContent>& _xParent) override;
+ };
+
+ }
+
+ void SAL_CALL ODocumentSaveContinuation::setName( const OUString& _sName,const Reference<XContent>& _xParent)
+ {
+ m_sName = _sName;
+ m_xParentContainer = _xParent;
+ }
+
+OUString ODocumentDefinition::GetDocumentServiceFromMediaType( const Reference< XStorage >& _rxContainerStorage,
+ const OUString& _rEntityName, const Reference< XComponentContext >& _rContext,
+ Sequence< sal_Int8 >& _rClassId )
+{
+ return GetDocumentServiceFromMediaType(
+ lcl_determineContentType_nothrow( _rxContainerStorage, _rEntityName ),
+ _rContext, _rClassId );
+}
+
+OUString ODocumentDefinition::GetDocumentServiceFromMediaType( const OUString& _rMediaType,
+ const Reference< XComponentContext >& _rContext, Sequence< sal_Int8 >& _rClassId )
+{
+ OUString sResult;
+ try
+ {
+ ::comphelper::MimeConfigurationHelper aConfigHelper( _rContext );
+ sResult = aConfigHelper.GetDocServiceNameFromMediaType( _rMediaType );
+ _rClassId = comphelper::MimeConfigurationHelper::GetSequenceClassIDRepresentation(aConfigHelper.GetExplicitlyRegisteredObjClassID( _rMediaType ));
+ if ( !_rClassId.hasElements() && !sResult.isEmpty() )
+ {
+ Reference< XNameAccess > xObjConfig = aConfigHelper.GetObjConfiguration();
+ if ( xObjConfig.is() )
+ {
+ const Sequence< OUString > aClassIDs = xObjConfig->getElementNames();
+ for ( OUString const & classId : aClassIDs )
+ {
+ Reference< XNameAccess > xObjectProps;
+ OUString aEntryDocName;
+
+ if ( ( xObjConfig->getByName( classId ) >>= xObjectProps ) && xObjectProps.is()
+ && ( xObjectProps->getByName("ObjectDocumentServiceName") >>= aEntryDocName )
+ && aEntryDocName == sResult )
+ {
+ _rClassId = comphelper::MimeConfigurationHelper::GetSequenceClassIDRepresentation(classId);
+ break;
+ }
+ }
+ }
+ }
+#if OSL_DEBUG_LEVEL > 0
+ // alternative, shorter approach
+ const Sequence< NamedValue > aProps( aConfigHelper.GetObjectPropsByMediaType( _rMediaType ) );
+ const ::comphelper::NamedValueCollection aMediaTypeProps( aProps );
+ const OUString sAlternativeResult = aMediaTypeProps.getOrDefault( "ObjectDocumentServiceName", OUString() );
+ OSL_ENSURE( sAlternativeResult == sResult, "ODocumentDefinition::GetDocumentServiceFromMediaType: failed, this approach is *not* equivalent (1)!" );
+ const Sequence< sal_Int8 > aAlternativeClassID = aMediaTypeProps.getOrDefault( "ClassID", Sequence< sal_Int8 >() );
+ OSL_ENSURE( aAlternativeClassID == _rClassId, "ODocumentDefinition::GetDocumentServiceFromMediaType: failed, this approach is *not* equivalent (2)!" );
+#endif
+ }
+ catch ( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ return sResult;
+}
+
+// ODocumentDefinition
+
+ODocumentDefinition::ODocumentDefinition( const Reference< XInterface >& _rxContainer, const Reference< XComponentContext >& _xORB,
+ const TContentPtr& _pImpl, bool _bForm )
+ :OContentHelper(_xORB,_rxContainer,_pImpl)
+ ,OPropertyStateContainer(OContentHelper::rBHelper)
+ ,m_bForm(_bForm)
+ ,m_bOpenInDesign(false)
+ ,m_bInExecute(false)
+ ,m_bRemoveListener(false)
+{
+ registerProperties();
+}
+
+void ODocumentDefinition::initialLoad( const Sequence< sal_Int8 >& i_rClassID, const Sequence< PropertyValue >& i_rCreationArgs,
+ const Reference< XConnection >& i_rConnection )
+{
+ OSL_ENSURE( i_rClassID.hasElements(), "ODocumentDefinition::initialLoad: illegal class ID!" );
+ if ( !i_rClassID.hasElements() )
+ return;
+
+ loadEmbeddedObject( i_rConnection, i_rClassID, i_rCreationArgs, false, false );
+}
+
+ODocumentDefinition::~ODocumentDefinition()
+{
+ if ( !OContentHelper::rBHelper.bInDispose && !OContentHelper::rBHelper.bDisposed )
+ {
+ acquire();
+ dispose();
+ }
+
+ if ( m_pInterceptor.is() )
+ {
+ m_pInterceptor->dispose();
+ m_pInterceptor.clear();
+ }
+}
+
+void ODocumentDefinition::closeObject()
+{
+ ::osl::MutexGuard aGuard(m_aMutex);
+ if ( m_xEmbeddedObject.is() )
+ {
+ try
+ {
+ m_xEmbeddedObject->close(true);
+ }
+ catch(const Exception&)
+ {
+ }
+ m_xEmbeddedObject = nullptr;
+ m_pClientHelper.clear();
+ }
+}
+
+void SAL_CALL ODocumentDefinition::disposing()
+{
+ OContentHelper::disposing();
+ ::osl::MutexGuard aGuard(m_aMutex);
+ closeObject();
+ ::comphelper::disposeComponent(m_xListener);
+ if ( m_bRemoveListener )
+ {
+ Reference<util::XCloseable> xCloseable(m_pImpl->m_pDataSource->getModel_noCreate(),UNO_QUERY);
+ if ( xCloseable.is() )
+ xCloseable->removeCloseListener(this);
+ }
+}
+
+css::uno::Sequence<sal_Int8> ODocumentDefinition::getImplementationId()
+{
+ return css::uno::Sequence<sal_Int8>();
+}
+
+css::uno::Sequence< css::uno::Type > ODocumentDefinition::getTypes()
+{
+ return ::comphelper::concatSequences(
+ OContentHelper::getTypes( ),
+ OPropertyStateContainer::getTypes( ),
+ ODocumentDefinition_Base::getTypes( )
+ );
+}
+IMPLEMENT_FORWARD_XINTERFACE3( ODocumentDefinition,OContentHelper,OPropertyStateContainer,ODocumentDefinition_Base)
+
+void ODocumentDefinition::registerProperties()
+{
+ registerProperty(PROPERTY_NAME, PROPERTY_ID_NAME, PropertyAttribute::CONSTRAINED | PropertyAttribute::BOUND | PropertyAttribute::READONLY,
+ &m_pImpl->m_aProps.aTitle, cppu::UnoType<decltype(m_pImpl->m_aProps.aTitle)>::get());
+
+ registerProperty(PROPERTY_AS_TEMPLATE, PROPERTY_ID_AS_TEMPLATE, PropertyAttribute::READONLY, &m_pImpl->m_aProps.bAsTemplate,
+ cppu::UnoType<decltype(m_pImpl->m_aProps.bAsTemplate)>::get());
+
+ registerProperty(PROPERTY_PERSISTENT_NAME, PROPERTY_ID_PERSISTENT_NAME, PropertyAttribute::READONLY, &m_pImpl->m_aProps.sPersistentName,
+ cppu::UnoType<decltype(m_pImpl->m_aProps.sPersistentName)>::get());
+
+ registerProperty(PROPERTY_IS_FORM, PROPERTY_ID_IS_FORM, PropertyAttribute::READONLY, &m_bForm, cppu::UnoType<decltype(m_bForm)>::get());
+}
+
+void SAL_CALL ODocumentDefinition::getFastPropertyValue( Any& o_rValue, sal_Int32 i_nHandle ) const
+{
+ if ( i_nHandle == PROPERTY_ID_PERSISTENT_PATH )
+ {
+ OUString sPersistentPath;
+ if ( !m_pImpl->m_aProps.sPersistentName.isEmpty() )
+ {
+ sPersistentPath = ODatabaseModelImpl::getObjectContainerStorageName( m_bForm ? ODatabaseModelImpl::E_FORM : ODatabaseModelImpl::E_REPORT )
+ + "/" + m_pImpl->m_aProps.sPersistentName;
+ }
+ o_rValue <<= sPersistentPath;
+ return;
+ }
+
+ OPropertyStateContainer::getFastPropertyValue( o_rValue, i_nHandle );
+}
+
+Reference< XPropertySetInfo > SAL_CALL ODocumentDefinition::getPropertySetInfo( )
+{
+ Reference<XPropertySetInfo> xInfo( createPropertySetInfo( getInfoHelper() ) );
+ return xInfo;
+}
+
+IPropertyArrayHelper& ODocumentDefinition::getInfoHelper()
+{
+ return *getArrayHelper();
+}
+
+IPropertyArrayHelper* ODocumentDefinition::createArrayHelper( ) const
+{
+ // properties maintained by our base class (see registerProperties)
+ Sequence< Property > aProps;
+ describeProperties( aProps );
+
+ // properties not maintained by our base class
+ Sequence< Property > aManualProps{ { /* Name */ PROPERTY_PERSISTENT_PATH,
+ /* Handle */ PROPERTY_ID_PERSISTENT_PATH,
+ /* Type */ ::cppu::UnoType<OUString>::get(),
+ /* Attributes */ PropertyAttribute::READONLY } };
+
+ return new OPropertyArrayHelper( ::comphelper::concatSequences( aProps, aManualProps ) );
+}
+
+namespace {
+
+class OExecuteImpl
+{
+ bool& m_rbSet;
+public:
+ explicit OExecuteImpl(bool& _rbSet) : m_rbSet(_rbSet){ m_rbSet=true; }
+ ~OExecuteImpl(){ m_rbSet = false; }
+};
+
+ bool lcl_extractOpenMode( const Any& _rValue, sal_Int32& _out_rMode )
+ {
+ OpenCommandArgument aOpenCommand;
+ if ( _rValue >>= aOpenCommand )
+ _out_rMode = aOpenCommand.Mode;
+ else
+ {
+ OpenCommandArgument2 aOpenCommand2;
+ if ( _rValue >>= aOpenCommand2 )
+ _out_rMode = aOpenCommand2.Mode;
+ else
+ return false;
+ }
+ return true;
+ }
+}
+
+void ODocumentDefinition::impl_removeFrameFromDesktop_throw( const Reference<XComponentContext> & _rxContext, const Reference< XFrame >& _rxFrame )
+{
+ Reference< XDesktop2 > xDesktop = Desktop::create( _rxContext );
+ Reference< XFrames > xFrames( xDesktop->getFrames(), UNO_SET_THROW );
+ xFrames->remove( _rxFrame );
+}
+
+void ODocumentDefinition::impl_onActivateEmbeddedObject_nothrow( const bool i_bReactivated )
+{
+ try
+ {
+ Reference< XModel > xModel( getComponent(), UNO_QUERY );
+ Reference< XController > xController( xModel.is() ? xModel->getCurrentController() : Reference< XController >() );
+ if ( !xController.is() )
+ return;
+
+ if ( !m_xListener.is() )
+ // it's the first time the embedded object has been activated
+ // create an OEmbedObjectHolder
+ m_xListener = new OEmbedObjectHolder( m_xEmbeddedObject, this );
+
+ // raise the window to top (especially necessary if this is not the first activation)
+ Reference< XFrame > xFrame( xController->getFrame(), UNO_SET_THROW );
+ Reference< XTopWindow > xTopWindow( xFrame->getContainerWindow(), UNO_QUERY_THROW );
+ xTopWindow->toFront();
+
+ // remove the frame from the desktop's frame collection because we need full control of it.
+ impl_removeFrameFromDesktop_throw( m_aContext, xFrame );
+
+ // ensure that we ourself are kept alive as long as the embedded object's frame is
+ // opened
+ LifetimeCoupler::couple( *this, xFrame );
+
+ // init the edit view
+ if ( m_bForm && m_bOpenInDesign && !i_bReactivated )
+ impl_initFormEditView( xController );
+ }
+ catch( const RuntimeException& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+}
+
+namespace
+{
+ // PreserveVisualAreaSize
+ /** stack-guard for preserving the size of the VisArea of an XModel
+ */
+ class PreserveVisualAreaSize
+ {
+ private:
+ Reference< XVisualObject > m_xVisObject;
+ awt::Size m_aOriginalSize;
+
+ public:
+ explicit PreserveVisualAreaSize( const Reference< XModel >& _rxModel )
+ :m_xVisObject( _rxModel, UNO_QUERY )
+ {
+ if ( m_xVisObject.is() )
+ {
+ try
+ {
+ m_aOriginalSize = m_xVisObject->getVisualAreaSize( Aspects::MSOLE_CONTENT );
+ }
+ catch ( const Exception& )
+ {
+ TOOLS_WARN_EXCEPTION( "dbaccess", "PreserveVisualAreaSize::PreserveVisualAreaSize" );
+ }
+ }
+ }
+
+ ~PreserveVisualAreaSize()
+ {
+ if ( m_xVisObject.is() && m_aOriginalSize.Width && m_aOriginalSize.Height )
+ {
+ try
+ {
+ m_xVisObject->setVisualAreaSize( Aspects::MSOLE_CONTENT, m_aOriginalSize );
+ }
+ catch ( const Exception& )
+ {
+ TOOLS_WARN_EXCEPTION( "dbaccess", "PreserveVisualAreaSize::~PreserveVisualAreaSize" );
+ }
+ }
+ }
+ };
+
+ // LayoutManagerLock
+ /** helper class for stack-usage which during its lifetime locks a layout manager
+ */
+ class LayoutManagerLock
+ {
+ private:
+ Reference< XLayoutManager > m_xLayoutManager;
+
+ public:
+ explicit LayoutManagerLock( const Reference< XController >& _rxController )
+ {
+ OSL_ENSURE( _rxController.is(), "LayoutManagerLock::LayoutManagerLock: this will crash!" );
+ Reference< XFrame > xFrame( _rxController->getFrame() );
+ try
+ {
+ Reference< XPropertySet > xPropSet( xFrame, UNO_QUERY_THROW );
+ m_xLayoutManager.set(
+ xPropSet->getPropertyValue( "LayoutManager" ),
+ UNO_QUERY_THROW );
+ m_xLayoutManager->lock();
+
+ }
+ catch( const Exception& )
+ {
+ TOOLS_WARN_EXCEPTION( "dbaccess", "LayoutManagerLock::LayoutManagerLock" );
+ }
+ }
+
+ ~LayoutManagerLock()
+ {
+ try
+ {
+ // unlock the layout manager
+ if ( m_xLayoutManager.is() )
+ m_xLayoutManager->unlock();
+ }
+ catch( const Exception& )
+ {
+ TOOLS_WARN_EXCEPTION( "dbaccess", "LayoutManagerLock::~LayoutManagerLock" );
+ }
+ }
+ };
+}
+
+void ODocumentDefinition::impl_initFormEditView( const Reference< XController >& _rxController )
+{
+ try
+ {
+ Reference< XViewSettingsSupplier > xSettingsSupplier( _rxController, UNO_QUERY_THROW );
+ Reference< XPropertySet > xViewSettings( xSettingsSupplier->getViewSettings(), UNO_SET_THROW );
+
+ // the below code could indirectly tamper with the "modified" flag of the model, temporarily disable this
+ LockModifiable aLockModify( _rxController->getModel() );
+
+ // The visual area size can be changed by the setting of the following properties
+ // so it should be restored later
+ PreserveVisualAreaSize aPreserveVisAreaSize( _rxController->getModel() );
+
+ // Layout manager should not layout while the size is still not restored
+ // so it will stay locked for this time
+ LayoutManagerLock aLockLayout( _rxController );
+
+ // setting of the visual properties
+ xViewSettings->setPropertyValue("ShowRulers",Any(true));
+ xViewSettings->setPropertyValue("ShowVertRuler",Any(true));
+ xViewSettings->setPropertyValue("ShowHoriRuler",Any(true));
+ xViewSettings->setPropertyValue("IsRasterVisible",Any(true));
+ xViewSettings->setPropertyValue("IsSnapToRaster",Any(true));
+ xViewSettings->setPropertyValue("ShowOnlineLayout",Any(true));
+ xViewSettings->setPropertyValue("RasterSubdivisionX",Any(sal_Int32(5)));
+ xViewSettings->setPropertyValue("RasterSubdivisionY",Any(sal_Int32(5)));
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+}
+
+void ODocumentDefinition::impl_showOrHideComponent_throw( const bool i_bShow )
+{
+ const sal_Int32 nCurrentState = m_xEmbeddedObject.is() ? m_xEmbeddedObject->getCurrentState() : EmbedStates::LOADED;
+ switch ( nCurrentState )
+ {
+ default:
+ case EmbedStates::LOADED:
+ throw embed::WrongStateException( OUString(), *this );
+
+ case EmbedStates::RUNNING:
+ if ( !i_bShow )
+ // fine, a running (and not yet active) object is never visible
+ return;
+ {
+ LockModifiable aLockModify( impl_getComponent_throw() );
+ m_xEmbeddedObject->changeState( EmbedStates::ACTIVE );
+ impl_onActivateEmbeddedObject_nothrow( false );
+ }
+ break;
+
+ case EmbedStates::ACTIVE:
+ {
+ Reference< XModel > xEmbeddedDoc( impl_getComponent_throw(), UNO_QUERY_THROW );
+ Reference< XController > xEmbeddedController( xEmbeddedDoc->getCurrentController(), UNO_SET_THROW );
+ Reference< XFrame > xEmbeddedFrame( xEmbeddedController->getFrame(), UNO_SET_THROW );
+ Reference< XWindow > xEmbeddedWindow( xEmbeddedFrame->getContainerWindow(), UNO_SET_THROW );
+ xEmbeddedWindow->setVisible( i_bShow );
+ }
+ break;
+ }
+}
+
+Any ODocumentDefinition::onCommandOpenSomething( const Any& _rOpenArgument, const bool _bActivate,
+ const Reference< XCommandEnvironment >& _rxEnvironment )
+{
+ OExecuteImpl aExecuteGuard( m_bInExecute );
+
+ Reference< XConnection > xConnection;
+ sal_Int32 nOpenMode = OpenMode::DOCUMENT;
+
+ ::comphelper::NamedValueCollection aDocumentArgs;
+
+ // for the document, default to the interaction handler as used for loading the DB doc
+ // This might be overwritten below, when examining _rOpenArgument.
+ const ::comphelper::NamedValueCollection& aDBDocArgs( m_pImpl->m_pDataSource->getMediaDescriptor() );
+ Reference< XInteractionHandler > xHandler( aDBDocArgs.getOrDefault( "InteractionHandler", Reference< XInteractionHandler >() ) );
+ if ( xHandler.is() )
+ aDocumentArgs.put( "InteractionHandler", xHandler );
+
+ ::std::optional< sal_Int16 > aDocumentMacroMode;
+
+ if ( !lcl_extractOpenMode( _rOpenArgument, nOpenMode ) )
+ {
+ Sequence< PropertyValue > aArguments;
+ if ( _rOpenArgument >>= aArguments )
+ {
+ const PropertyValue* pIter = aArguments.getConstArray();
+ const PropertyValue* pEnd = pIter + aArguments.getLength();
+ for ( ;pIter != pEnd; ++pIter )
+ {
+ if ( pIter->Name == PROPERTY_ACTIVE_CONNECTION )
+ {
+ xConnection.set( pIter->Value, UNO_QUERY );
+ continue;
+ }
+
+ if ( lcl_extractOpenMode( pIter->Value, nOpenMode ) )
+ continue;
+
+ if ( pIter->Name == "MacroExecutionMode" )
+ {
+ sal_Int16 nMacroExecMode( !aDocumentMacroMode ? MacroExecMode::USE_CONFIG : *aDocumentMacroMode );
+ OSL_VERIFY( pIter->Value >>= nMacroExecMode );
+ aDocumentMacroMode = nMacroExecMode;
+ continue;
+ }
+
+ // unknown argument -> pass to the loaded document
+ aDocumentArgs.put( pIter->Name, pIter->Value );
+ }
+ }
+ }
+
+ bool bExecuteDBDocMacros = m_pImpl->m_pDataSource->checkMacrosOnLoading();
+ // Note that this call implies the user might be asked for the macro execution mode.
+ // Normally, this would happen when the database document is loaded, and subsequent calls
+ // will simply use the user's decision from this point in time.
+ // However, it is possible to programmatically load forms/reports, without actually
+ // loading the database document into a frame. In this case, the user will be asked
+ // here and now.
+ // #i87741#
+
+ // allow the command arguments to downgrade the macro execution mode, but not to upgrade
+ // it
+ if ( ( m_pImpl->m_pDataSource->getImposedMacroExecMode() == MacroExecMode::USE_CONFIG )
+ && bExecuteDBDocMacros
+ )
+ {
+ // while loading the whole database document, USE_CONFIG, was passed.
+ // Additionally, *by now* executing macros from the DB doc is allowed (this is what bExecuteDBDocMacros
+ // indicates). This means either one of:
+ // 1. The DB doc or one of the sub docs contained macros and
+ // 1a. the user explicitly allowed executing them
+ // 1b. the configuration allows executing them without asking the user
+ // 2. Neither the DB doc nor the sub docs contained macros, thus macro
+ // execution was silently enabled, assuming that any macro will be a
+ // user-created macro
+ //
+ // The problem with this: If the to-be-opened sub document has macros embedded in
+ // the content.xml (which is valid ODF, but normally not produced by OOo itself),
+ // then this has not been detected while loading the database document - it would
+ // be too expensive, as it effectively would require loading all forms/reports.
+ //
+ // So, in such a case, and with 2. above, we would silently execute those macros,
+ // regardless of the global security settings - which would be a security issue, of
+ // course.
+ if ( m_pImpl->m_pDataSource->determineEmbeddedMacros() == ODatabaseModelImpl::eNoMacros )
+ {
+ // this is case 2. from above
+ // So, pass a USE_CONFIG to the to-be-loaded document. This means that
+ // the user will be prompted with a security message upon opening this
+ // sub document, in case the settings require this, *and* the document
+ // contains scripts in the content.xml. But this is better than the security
+ // issue we had before ...
+ aDocumentMacroMode = MacroExecMode::USE_CONFIG;
+ }
+ }
+
+ if ( !aDocumentMacroMode )
+ {
+ // nobody so far felt responsible for setting it
+ // => use the DBDoc-wide macro exec mode for the document, too
+ aDocumentMacroMode = bExecuteDBDocMacros ? MacroExecMode::ALWAYS_EXECUTE_NO_WARN
+ : MacroExecMode::NEVER_EXECUTE;
+ }
+ aDocumentArgs.put( "MacroExecutionMode", *aDocumentMacroMode );
+
+ if ( ( nOpenMode == OpenMode::ALL )
+ || ( nOpenMode == OpenMode::FOLDERS )
+ || ( nOpenMode == OpenMode::DOCUMENTS )
+ || ( nOpenMode == OpenMode::DOCUMENT_SHARE_DENY_NONE )
+ || ( nOpenMode == OpenMode::DOCUMENT_SHARE_DENY_WRITE )
+ )
+ {
+ // not supported
+ ucbhelper::cancelCommandExecution(
+ Any( UnsupportedOpenModeException(
+ OUString(),
+ static_cast< cppu::OWeakObject * >( this ),
+ sal_Int16( nOpenMode ) ) ),
+ _rxEnvironment );
+ // Unreachable
+ OSL_FAIL( "unreachable" );
+ }
+
+ OSL_ENSURE( !m_pImpl->m_aProps.sPersistentName.isEmpty(),
+ "ODocumentDefinition::onCommandOpenSomething: no persistent name - cannot load!" );
+ if ( m_pImpl->m_aProps.sPersistentName.isEmpty() )
+ return Any();
+
+ // embedded objects themself do not support the hidden flag. We implement support for
+ // it by changing the STATE to RUNNING only, instead of ACTIVE.
+ bool bOpenHidden = aDocumentArgs.getOrDefault( "Hidden", false );
+ aDocumentArgs.remove( "Hidden" );
+
+ loadEmbeddedObject( xConnection, Sequence< sal_Int8 >(), aDocumentArgs.getPropertyValues(), false, !m_bOpenInDesign );
+ OSL_ENSURE( m_xEmbeddedObject.is(), "ODocumentDefinition::onCommandOpenSomething: what's this?" );
+ if ( !m_xEmbeddedObject.is() )
+ return Any();
+
+ Reference< XModel > xModel( getComponent(), UNO_QUERY );
+ Reference< report::XReportDefinition > xReportDefinition(xModel,UNO_QUERY);
+
+ Reference< XModule > xModule( xModel, UNO_QUERY );
+ if ( xModule.is() )
+ {
+ if ( m_bForm )
+ xModule->setIdentifier( "com.sun.star.sdb.FormDesign" );
+ else if ( !xReportDefinition.is() )
+ xModule->setIdentifier( "com.sun.star.text.TextDocument" );
+
+ updateDocumentTitle();
+ }
+
+ bool bIsAliveNewStyleReport = ( !m_bOpenInDesign && xReportDefinition.is() );
+ if ( bIsAliveNewStyleReport )
+ {
+ // we are in ReadOnly mode
+ // we would like to open the Writer or Calc with the report direct, without design it.
+ Reference< report::XReportEngine > xReportEngine( m_aContext->getServiceManager()->createInstanceWithContext("com.sun.star.comp.report.OReportEngineJFree", m_aContext), UNO_QUERY_THROW );
+
+ xReportEngine->setReportDefinition(xReportDefinition);
+ xReportEngine->setActiveConnection(m_xLastKnownConnection);
+ if ( bOpenHidden )
+ return Any( xReportEngine->createDocumentModel() );
+ return Any( xReportEngine->createDocumentAlive( nullptr ) );
+ }
+
+ if ( _bActivate && !bOpenHidden )
+ {
+ LockModifiable aLockModify( impl_getComponent_throw() );
+ m_xEmbeddedObject->changeState( EmbedStates::ACTIVE );
+ impl_onActivateEmbeddedObject_nothrow( false );
+ }
+ else
+ {
+ // ensure that we ourself are kept alive as long as the document is open
+ LifetimeCoupler::couple( *this, xModel );
+ }
+
+ if ( !m_bForm && m_pImpl->m_aProps.bAsTemplate && !m_bOpenInDesign )
+ ODocumentDefinition::fillReportData( m_aContext, getComponent(), xConnection );
+
+ return Any( xModel );
+}
+
+Any SAL_CALL ODocumentDefinition::execute( const Command& aCommand, sal_Int32 CommandId, const Reference< XCommandEnvironment >& Environment )
+{
+ Any aRet;
+
+ bool bOpen = aCommand.Name == "open";
+ bool bOpenInDesign = aCommand.Name == "openDesign";
+ bool bOpenForMail = aCommand.Name == "openForMail";
+ if ( bOpen || bOpenInDesign || bOpenForMail )
+ {
+ // opening the document involves a lot of VCL code, which is not thread-safe, but needs the SolarMutex locked.
+ // Unfortunately, the DocumentDefinition, as well as the EmbeddedObject implementation, calls into VCL-dependent
+ // components *without* releasing the own mutex, which is a guaranteed recipe for deadlocks.
+ // We have control over this implementation here, and in modifying it to release the own mutex before calling into
+ // the VCL-dependent components is not too difficult (was there, seen it).
+ // However, we do /not/ have control over the EmbeddedObject implementation, and from a first look, it seems as
+ // making it release the own mutex before calling SolarMutex-code is ... difficult, at least.
+ // So, to be on the same side, we lock the SolarMutex here. Yes, it sucks.
+ ::SolarMutexGuard aSolarGuard;
+ osl::MutexGuard aGuard(m_aMutex);
+ if ( m_bInExecute )
+ return aRet;
+
+ bool bActivateObject = true;
+ if ( bOpenForMail )
+ {
+ OSL_FAIL( "ODocumentDefinition::execute: 'openForMail' should not be used anymore - use the 'Hidden' parameter instead!" );
+ bActivateObject = false;
+ }
+
+ // if the object is already opened, do nothing
+ if ( m_xEmbeddedObject.is() )
+ {
+ sal_Int32 nCurrentState = m_xEmbeddedObject->getCurrentState();
+ bool bIsActive = ( nCurrentState == EmbedStates::ACTIVE );
+
+ if ( bIsActive )
+ {
+ // exception: new-style reports always create a new document when "open" is executed
+ Reference< report::XReportDefinition > xReportDefinition( impl_getComponent_throw( false ), UNO_QUERY );
+ bool bIsAliveNewStyleReport = ( xReportDefinition.is() && ( bOpen || bOpenForMail ) );
+
+ if ( !bIsAliveNewStyleReport )
+ {
+ impl_onActivateEmbeddedObject_nothrow( true );
+ return Any( getComponent() );
+ }
+ }
+ }
+
+ m_bOpenInDesign = bOpenInDesign || bOpenForMail;
+ return onCommandOpenSomething( aCommand.Argument, bActivateObject, Environment );
+ }
+
+ osl::MutexGuard aGuard(m_aMutex);
+ if ( m_bInExecute )
+ return aRet;
+
+ if ( aCommand.Name == "copyTo" )
+ {
+ Sequence<Any> aIni;
+ aCommand.Argument >>= aIni;
+ if ( aIni.getLength() != 2 )
+ {
+ OSL_FAIL( "Wrong argument type!" );
+ ucbhelper::cancelCommandExecution(
+ Any( IllegalArgumentException(
+ OUString(),
+ static_cast< cppu::OWeakObject * >( this ),
+ -1 ) ),
+ Environment );
+ // Unreachable
+ }
+ Reference< XStorage> xDest(aIni[0],UNO_QUERY);
+ OUString sPersistentName;
+ aIni[1] >>= sPersistentName;
+ Reference< XStorage> xStorage = getContainerStorage();
+
+ xStorage->copyElementTo(m_pImpl->m_aProps.sPersistentName,xDest,sPersistentName);
+ }
+ else if ( aCommand.Name == "preview" )
+ {
+ onCommandPreview(aRet);
+ }
+ else if ( aCommand.Name == "insert" )
+ {
+ Sequence<Any> aIni;
+ aCommand.Argument >>= aIni;
+ if ( !aIni.hasElements() )
+ {
+ OSL_FAIL( "Wrong argument count!" );
+ ucbhelper::cancelCommandExecution(
+ Any( IllegalArgumentException(
+ OUString(),
+ static_cast< cppu::OWeakObject * >( this ),
+ -1 ) ),
+ Environment );
+ // Unreachable
+ }
+ OUString sURL;
+ aIni[0] >>= sURL;
+ onCommandInsert( sURL, Environment );
+ }
+ else if ( aCommand.Name == "getdocumentinfo" // compatibility
+ || aCommand.Name == "getDocumentInfo" )
+ {
+ onCommandGetDocumentProperties( aRet );
+ }
+ else if ( aCommand.Name == "delete" )
+ {
+ // delete
+ closeObject();
+ Reference< XStorage> xStorage = getContainerStorage();
+ if ( xStorage.is() )
+ xStorage->removeElement(m_pImpl->m_aProps.sPersistentName);
+
+ dispose();
+
+ }
+ else if ( aCommand.Name == "storeOwn" // compatibility
+ || aCommand.Name == "store"
+ )
+ {
+ impl_store_throw();
+ }
+ else if ( aCommand.Name == "shutdown" // compatibility
+ || aCommand.Name == "close"
+ )
+ {
+ aRet <<= impl_close_throw();
+ }
+ else if ( aCommand.Name == "show" )
+ {
+ impl_showOrHideComponent_throw( true );
+ }
+ else if ( aCommand.Name == "hide" )
+ {
+ impl_showOrHideComponent_throw( false );
+ }
+ else
+ {
+ aRet = OContentHelper::execute(aCommand,CommandId,Environment);
+ }
+
+ return aRet;
+}
+
+namespace
+{
+ void lcl_resetChildFormsToEmptyDataSource( const Reference< XIndexAccess>& _rxFormsContainer )
+ {
+ OSL_PRECOND( _rxFormsContainer.is(), "lcl_resetChildFormsToEmptyDataSource: illegal call!" );
+ sal_Int32 count = _rxFormsContainer->getCount();
+ for ( sal_Int32 i = 0; i < count; ++i )
+ {
+ Reference< XForm > xForm( _rxFormsContainer->getByIndex( i ), UNO_QUERY );
+ if ( !xForm.is() )
+ continue;
+
+ // if the element is a form, reset its DataSourceName property to an empty string
+ try
+ {
+ Reference< XPropertySet > xFormProps( xForm, UNO_QUERY_THROW );
+ xFormProps->setPropertyValue( PROPERTY_DATASOURCENAME, Any( OUString() ) );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+
+ // if the element is a container itself, step down the component hierarchy
+ Reference< XIndexAccess > xContainer( xForm, UNO_QUERY );
+ if ( xContainer.is() )
+ lcl_resetChildFormsToEmptyDataSource( xContainer );
+ }
+ }
+
+ void lcl_resetFormsToEmptyDataSource( const Reference< XEmbeddedObject>& _rxEmbeddedObject )
+ {
+ try
+ {
+ Reference< XDrawPageSupplier > xSuppPage( _rxEmbeddedObject->getComponent(), UNO_QUERY_THROW );
+ // if this interface does not exist, then either getComponent returned NULL,
+ // or the document is a multi-page document. The latter is allowed, but currently
+ // simply not handled by this code, as it would not normally happen.
+
+ Reference< XFormsSupplier > xSuppForms( xSuppPage->getDrawPage(), UNO_QUERY_THROW );
+ Reference< XIndexAccess > xForms( xSuppForms->getForms(), UNO_QUERY_THROW );
+ lcl_resetChildFormsToEmptyDataSource( xForms );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+
+ }
+}
+
+void ODocumentDefinition::onCommandInsert( const OUString& _sURL, const Reference< XCommandEnvironment >& Environment )
+{
+ osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
+
+ // Check, if all required properties were set.
+ if ( _sURL.isEmpty() || m_xEmbeddedObject.is() )
+ {
+ OSL_FAIL( "Content::onCommandInsert - property value missing!" );
+
+ Sequence<OUString> aProps { PROPERTY_URL };
+ ucbhelper::cancelCommandExecution(
+ Any( MissingPropertiesException(
+ OUString(),
+ static_cast< cppu::OWeakObject * >( this ),
+ aProps ) ),
+ Environment );
+ // Unreachable
+ }
+
+ if ( !m_xEmbeddedObject.is() )
+ {
+ Reference< XStorage> xStorage = getContainerStorage();
+ if ( xStorage.is() )
+ {
+ Reference< XEmbeddedObjectCreator> xEmbedFactory = EmbeddedObjectCreator::create(m_aContext);
+ Sequence<PropertyValue> aEmpty;
+ Sequence<PropertyValue> aMediaDesc{ comphelper::makePropertyValue(PROPERTY_URL,
+ _sURL) };
+ m_xEmbeddedObject.set(xEmbedFactory->createInstanceInitFromMediaDescriptor( xStorage
+ ,m_pImpl->m_aProps.sPersistentName
+ ,aMediaDesc
+ ,aEmpty),UNO_QUERY);
+
+ lcl_resetFormsToEmptyDataSource( m_xEmbeddedObject );
+ // #i57669#
+
+ Reference<XEmbedPersist> xPersist(m_xEmbeddedObject,UNO_QUERY);
+ if ( xPersist.is() )
+ {
+ xPersist->storeOwn();
+ }
+ try
+ {
+ if ( m_xEmbeddedObject.is() )
+ m_xEmbeddedObject->close(true);
+ }
+ catch(const Exception&)
+ {
+ }
+ m_xEmbeddedObject = nullptr;
+ }
+ }
+
+ aGuard.clear();
+}
+
+bool ODocumentDefinition::save(bool _bApprove, const css::uno::Reference<css::awt::XTopWindow>& rDialogParent)
+{
+ // default handling: instantiate an interaction handler and let it handle the parameter request
+ if ( !m_bOpenInDesign )
+ return false;
+ try
+ {
+
+ {
+ ::SolarMutexGuard aSolarGuard;
+
+ // the request
+ Reference<XNameAccess> xName(m_xParentContainer,UNO_QUERY);
+ DocumentSaveRequest aRequest;
+ aRequest.Name = m_pImpl->m_aProps.aTitle;
+ if ( aRequest.Name.isEmpty() )
+ {
+ if ( m_bForm )
+ aRequest.Name = DBA_RES( RID_STR_FORM );
+ else
+ aRequest.Name = DBA_RES( RID_STR_REPORT );
+ aRequest.Name = ::dbtools::createUniqueName(xName,aRequest.Name);
+ }
+
+ aRequest.Content.set(m_xParentContainer,UNO_QUERY);
+ rtl::Reference<OInteractionRequest> pRequest = new OInteractionRequest(Any(aRequest));
+ // some knittings
+ // two continuations allowed: OK and Cancel
+ rtl::Reference<ODocumentSaveContinuation> pDocuSave;
+
+ if ( m_pImpl->m_aProps.aTitle.isEmpty() )
+ {
+ pDocuSave = new ODocumentSaveContinuation;
+ pRequest->addContinuation(pDocuSave);
+ }
+ if ( _bApprove )
+ {
+ rtl::Reference<OInteraction< XInteractionApprove >> pApprove = new OInteraction< XInteractionApprove >;
+ pRequest->addContinuation(pApprove);
+ }
+
+ rtl::Reference<OInteraction< XInteractionDisapprove >> pDisApprove = new OInteraction< XInteractionDisapprove >;
+ pRequest->addContinuation(pDisApprove);
+
+ rtl::Reference<OInteractionAbort> pAbort = new OInteractionAbort;
+ pRequest->addContinuation(pAbort);
+
+ Reference<XWindow> xDialogParent(rDialogParent, UNO_QUERY);
+
+ // create the handler, let it handle the request
+ Reference<XInteractionHandler2> xHandler(InteractionHandler::createWithParent(m_aContext, xDialogParent));
+ xHandler->handle(pRequest);
+
+ if ( pAbort->wasSelected() )
+ return false;
+ if ( pDisApprove->wasSelected() )
+ return true;
+ if ( pDocuSave && pDocuSave->wasSelected() )
+ {
+ Reference<XNameContainer> xNC( pDocuSave->getContent(), UNO_QUERY_THROW );
+
+ ::osl::ResettableMutexGuard aGuard( m_aMutex );
+ NameChangeNotifier aNameChangeAndNotify( *this, pDocuSave->getName(), aGuard );
+ m_pImpl->m_aProps.aTitle = pDocuSave->getName();
+
+ Reference< XContent> xContent = this;
+ xNC->insertByName(pDocuSave->getName(),Any(xContent));
+
+ updateDocumentTitle();
+ }
+ }
+
+ ::osl::MutexGuard aGuard(m_aMutex);
+ Reference<XEmbedPersist> xPersist(m_xEmbeddedObject,UNO_QUERY);
+ if ( xPersist.is() )
+ {
+ xPersist->storeOwn();
+ notifyDataSourceModified();
+ }
+ }
+ catch(const Exception&)
+ {
+ TOOLS_WARN_EXCEPTION( "dbaccess", "ODocumentDefinition::save: caught an Exception (tried to let the InteractionHandler handle it)!");
+ }
+ return true;
+}
+
+void ODocumentDefinition::saveAs()
+{
+ // default handling: instantiate an interaction handler and let it handle the parameter request
+ if ( !m_bOpenInDesign )
+ return;
+
+ {
+ osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
+ if ( m_pImpl->m_aProps.aTitle.isEmpty() )
+ {
+ aGuard.clear();
+ save(false, css::uno::Reference<css::awt::XTopWindow>()); // (sal_False) : we don't want an approve dialog
+ return;
+ }
+ }
+ try
+ {
+ ::SolarMutexGuard aSolarGuard;
+
+ // the request
+ DocumentSaveRequest aRequest;
+ aRequest.Name = m_pImpl->m_aProps.aTitle;
+
+ aRequest.Content.set(m_xParentContainer,UNO_QUERY);
+ rtl::Reference<OInteractionRequest> pRequest = new OInteractionRequest(Any(aRequest));
+ // some knittings
+ // two continuations allowed: OK and Cancel
+ rtl::Reference<ODocumentSaveContinuation> pDocuSave = new ODocumentSaveContinuation;
+ pRequest->addContinuation(pDocuSave);
+ rtl::Reference<OInteraction< XInteractionDisapprove >> pDisApprove = new OInteraction< XInteractionDisapprove >;
+ pRequest->addContinuation(pDisApprove);
+ rtl::Reference<OInteractionAbort> pAbort = new OInteractionAbort;
+ pRequest->addContinuation(pAbort);
+
+ // create the handler, let it handle the request
+ Reference< XInteractionHandler2 > xHandler( InteractionHandler::createWithParent(m_aContext, nullptr) );
+ xHandler->handle(pRequest);
+
+ if ( pAbort->wasSelected() )
+ return;
+ if ( pDisApprove->wasSelected() )
+ return;
+ if ( pDocuSave->wasSelected() )
+ {
+ ::osl::MutexGuard aGuard(m_aMutex);
+ Reference<XNameContainer> xNC(pDocuSave->getContent(),UNO_QUERY);
+ if ( xNC.is() )
+ {
+ if ( m_pImpl->m_aProps.aTitle != pDocuSave->getName() )
+ {
+ try
+ {
+ Reference< XStorage> xStorage = getContainerStorage();
+
+ OUString sPersistentName = ::dbtools::createUniqueName(xStorage,"Obj");
+ xStorage->copyElementTo(m_pImpl->m_aProps.sPersistentName,xStorage,sPersistentName);
+
+ OUString sOldName = m_pImpl->m_aProps.aTitle;
+ rename(pDocuSave->getName());
+ updateDocumentTitle();
+
+ uno::Sequence<uno::Any> aArguments(comphelper::InitAnyPropertySequence(
+ {
+ {PROPERTY_NAME, uno::Any(sOldName)}, // set as folder
+ {PROPERTY_PERSISTENT_NAME, uno::Any(sPersistentName)},
+ {PROPERTY_AS_TEMPLATE, uno::Any(m_pImpl->m_aProps.bAsTemplate)},
+ }));
+ Reference< XMultiServiceFactory > xORB( m_xParentContainer, UNO_QUERY_THROW );
+ Reference< XInterface > xComponent( xORB->createInstanceWithArguments( SERVICE_SDB_DOCUMENTDEFINITION, aArguments ) );
+ Reference< XNameContainer > xNameContainer( m_xParentContainer, UNO_QUERY_THROW );
+ xNameContainer->insertByName( sOldName, Any( xComponent ) );
+ }
+ catch(const Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+ Reference<XEmbedPersist> xPersist(m_xEmbeddedObject,UNO_QUERY);
+ if ( xPersist.is() )
+ {
+ xPersist->storeOwn();
+ notifyDataSourceModified();
+ }
+ }
+ }
+ }
+ catch(const Exception&)
+ {
+ TOOLS_WARN_EXCEPTION( "dbaccess", "ODocumentDefinition::save: caught an Exception (tried to let the InteractionHandler handle it)!");
+ }
+}
+
+namespace
+{
+ void lcl_putLoadArgs( ::comphelper::NamedValueCollection& _io_rArgs, const optional_bool& _bSuppressMacros, const optional_bool& _bReadOnly )
+ {
+ if ( !!_bSuppressMacros )
+ {
+ if ( *_bSuppressMacros )
+ {
+ // if we're to suppress macros, do exactly this
+ _io_rArgs.put( "MacroExecutionMode", MacroExecMode::NEVER_EXECUTE );
+ }
+ else
+ {
+ // otherwise, put the setting only if not already present
+ if ( !_io_rArgs.has( "MacroExecutionMode" ) )
+ {
+ _io_rArgs.put( "MacroExecutionMode", MacroExecMode::USE_CONFIG );
+ }
+ }
+ }
+
+ if ( !!_bReadOnly )
+ _io_rArgs.put( "ReadOnly", *_bReadOnly );
+ }
+}
+
+namespace
+{
+ Reference< XFrame > lcl_getDatabaseDocumentFrame( ODatabaseModelImpl const & _rImpl )
+ {
+ Reference< XModel > xDatabaseDocumentModel( _rImpl.getModel_noCreate() );
+
+ Reference< XController > xDatabaseDocumentController;
+ if ( xDatabaseDocumentModel.is() )
+ xDatabaseDocumentController = xDatabaseDocumentModel->getCurrentController();
+
+ Reference< XFrame > xFrame;
+ if ( xDatabaseDocumentController.is() )
+ xFrame = xDatabaseDocumentController->getFrame();
+
+ return xFrame;
+ }
+}
+
+bool ODocumentDefinition::objectSupportsEmbeddedScripts() const
+{
+ bool bAllowDocumentMacros = !m_pImpl->m_pDataSource
+ || ( m_pImpl->m_pDataSource->determineEmbeddedMacros() == ODatabaseModelImpl::eSubDocumentMacros );
+
+ // if *any* of the objects of the database document already has macros, we
+ // continue to allow it to have them, until the user does a migration.
+ // If there are no macros, we don't allow them to be created.
+
+ return bAllowDocumentMacros;
+}
+
+OUString ODocumentDefinition::determineContentType() const
+{
+ return lcl_determineContentType_nothrow( getContainerStorage(), m_pImpl->m_aProps.sPersistentName );
+}
+
+void ODocumentDefinition::separateOpenCommandArguments( const Sequence< PropertyValue >& i_rOpenCommandArguments,
+ ::comphelper::NamedValueCollection& o_rDocumentLoadArgs, ::comphelper::NamedValueCollection& o_rEmbeddedObjectDescriptor )
+{
+ ::comphelper::NamedValueCollection aOpenCommandArguments( i_rOpenCommandArguments );
+
+ static const std::u16string_view sObjectDescriptorArgs[] = { u"RecoveryStorage" };
+ for (const auto& rObjectDescriptorArg : sObjectDescriptorArgs)
+ {
+ const OUString sObjectDescriptorArg(rObjectDescriptorArg);
+ if ( aOpenCommandArguments.has( sObjectDescriptorArg ) )
+ {
+ o_rEmbeddedObjectDescriptor.put( sObjectDescriptorArg, aOpenCommandArguments.get( sObjectDescriptorArg ) );
+ aOpenCommandArguments.remove( sObjectDescriptorArg );
+ }
+ }
+
+ o_rDocumentLoadArgs.merge( aOpenCommandArguments, false );
+}
+
+Sequence< PropertyValue > ODocumentDefinition::fillLoadArgs( const Reference< XConnection>& _xConnection, const bool _bSuppressMacros, const bool _bReadOnly,
+ const Sequence< PropertyValue >& i_rOpenCommandArguments, Sequence< PropertyValue >& _out_rEmbeddedObjectDescriptor )
+{
+ // (re-)create interceptor, and put it into the descriptor of the embedded object
+ if ( m_pInterceptor.is() )
+ {
+ m_pInterceptor->dispose();
+ m_pInterceptor.clear();
+ }
+
+ m_pInterceptor = new OInterceptor( this );
+ Reference<XDispatchProviderInterceptor> xInterceptor = m_pInterceptor;
+
+ ::comphelper::NamedValueCollection aEmbeddedDescriptor;
+ aEmbeddedDescriptor.put( "OutplaceDispatchInterceptor", xInterceptor );
+
+ ::comphelper::NamedValueCollection aMediaDesc;
+ separateOpenCommandArguments( i_rOpenCommandArguments, aMediaDesc, aEmbeddedDescriptor );
+
+ // create the OutplaceFrameProperties, and put them into the descriptor of the embedded object
+ ::comphelper::NamedValueCollection OutplaceFrameProperties;
+ OutplaceFrameProperties.put( "TopWindow", true );
+ OutplaceFrameProperties.put( "SupportPersistentWindowState", true );
+
+ Reference< XFrame > xParentFrame;
+ if ( m_pImpl->m_pDataSource )
+ xParentFrame = lcl_getDatabaseDocumentFrame( *m_pImpl->m_pDataSource );
+ if ( !xParentFrame.is() )
+ { // i87957 we need a parent frame
+ Reference< XDesktop2 > xDesktop = Desktop::create( m_aContext );
+ xParentFrame.set( xDesktop, UNO_QUERY_THROW );
+ Reference<util::XCloseable> xCloseable(m_pImpl->m_pDataSource->getModel_noCreate(),UNO_QUERY);
+ if ( xCloseable.is() )
+ {
+ xCloseable->addCloseListener(this);
+ m_bRemoveListener = true;
+ }
+ }
+ OSL_ENSURE( xParentFrame.is(), "ODocumentDefinition::fillLoadArgs: no parent frame!" );
+ if ( xParentFrame.is() )
+ OutplaceFrameProperties.put( "ParentFrame", xParentFrame );
+
+ aEmbeddedDescriptor.put( "OutplaceFrameProperties", OutplaceFrameProperties.getNamedValues() );
+
+ // tell the embedded object to have (or not have) script support
+ aEmbeddedDescriptor.put( "EmbeddedScriptSupport", objectSupportsEmbeddedScripts() );
+
+ // tell the embedded object to not participate in the document recovery game - the DB doc will handle it
+ aEmbeddedDescriptor.put( "DocumentRecoverySupport", false );
+
+ // pass the descriptor of the embedded object to the caller
+ aEmbeddedDescriptor >>= _out_rEmbeddedObjectDescriptor;
+
+ // create the ComponentData, and put it into the document's media descriptor
+ {
+ ::comphelper::NamedValueCollection aComponentData;
+ aComponentData.put( "ActiveConnection", _xConnection );
+ aComponentData.put( "ApplyFormDesignMode", !_bReadOnly );
+ aMediaDesc.put( "ComponentData", aComponentData.getPropertyValues() );
+ }
+
+ if ( !m_pImpl->m_aProps.aTitle.isEmpty() )
+ aMediaDesc.put( "DocumentTitle", m_pImpl->m_aProps.aTitle );
+
+ aMediaDesc.put( "DocumentBaseURL", m_pImpl->m_pDataSource->getURL() );
+
+ // put the common load arguments into the document's media descriptor
+ lcl_putLoadArgs( aMediaDesc, optional_bool( _bSuppressMacros ), optional_bool( _bReadOnly ) );
+
+ return aMediaDesc.getPropertyValues();
+}
+
+void ODocumentDefinition::loadEmbeddedObject( const Reference< XConnection >& i_rConnection, const Sequence< sal_Int8 >& _aClassID,
+ const Sequence< PropertyValue >& i_rOpenCommandArguments, const bool _bSuppressMacros, const bool _bReadOnly )
+{
+ if ( !m_xEmbeddedObject.is() )
+ {
+ Reference< XStorage> xStorage = getContainerStorage();
+ if ( xStorage.is() )
+ {
+ Reference< XEmbeddedObjectCreator> xEmbedFactory = OOoEmbeddedObjectFactory::create(m_aContext);
+ OUString sDocumentService;
+ bool bSetSize = false;
+ sal_Int32 nEntryConnectionMode = EntryInitModes::DEFAULT_INIT;
+ Sequence< sal_Int8 > aClassID = _aClassID;
+ if ( aClassID.hasElements() )
+ {
+ nEntryConnectionMode = EntryInitModes::TRUNCATE_INIT;
+ bSetSize = true;
+ }
+ else
+ {
+ sDocumentService = GetDocumentServiceFromMediaType( getContentType(), m_aContext, aClassID );
+ // check if we are not a form and
+ // the org.libreoffice.report.pentaho.SOReportJobFactory is not present.
+ if ( !m_bForm && sDocumentService != "com.sun.star.text.TextDocument")
+ {
+ // we seem to be a "new style" report, check if report extension is present.
+ Reference< XContentEnumerationAccess > xEnumAccess( m_aContext->getServiceManager(), UNO_QUERY );
+ const OUString sReportEngineServiceName = ::dbtools::getDefaultReportEngineServiceName(m_aContext);
+ Reference< XEnumeration > xEnumDrivers = xEnumAccess->createContentEnumeration(sReportEngineServiceName);
+ if ( !xEnumDrivers.is() || !xEnumDrivers->hasMoreElements() )
+ {
+ css::io::WrongFormatException aWFE;
+ aWFE.Message = DBA_RES( RID_STR_MISSING_EXTENSION );
+ throw aWFE;
+ }
+ }
+ if ( !aClassID.hasElements() )
+ {
+ if ( m_bForm )
+ aClassID = MimeConfigurationHelper::GetSequenceClassID(SO3_SW_CLASSID);
+ else
+ {
+ aClassID = MimeConfigurationHelper::GetSequenceClassID(SO3_RPT_CLASSID_90);
+ }
+ }
+ }
+
+ OSL_ENSURE( aClassID.hasElements(),"No Class ID" );
+
+ Sequence< PropertyValue > aEmbeddedObjectDescriptor;
+ Sequence< PropertyValue > aLoadArgs( fillLoadArgs(
+ i_rConnection, _bSuppressMacros, _bReadOnly, i_rOpenCommandArguments, aEmbeddedObjectDescriptor ) );
+
+ m_xEmbeddedObject.set(xEmbedFactory->createInstanceUserInit(aClassID
+ ,sDocumentService
+ ,xStorage
+ ,m_pImpl->m_aProps.sPersistentName
+ ,nEntryConnectionMode
+ ,aLoadArgs
+ ,aEmbeddedObjectDescriptor
+ ),UNO_QUERY);
+ if ( m_xEmbeddedObject.is() )
+ {
+ if ( !m_pClientHelper.is() )
+ {
+ m_pClientHelper = new OEmbeddedClientHelper;
+ }
+ m_xEmbeddedObject->setClientSite(m_pClientHelper);
+ m_xEmbeddedObject->changeState(EmbedStates::RUNNING);
+ if ( bSetSize )
+ {
+ LockModifiable aLockModify( impl_getComponent_throw( false ) );
+
+ awt::Size aSize( DEFAULT_WIDTH, DEFAULT_HEIGHT );
+ m_xEmbeddedObject->setVisualAreaSize(Aspects::MSOLE_CONTENT,aSize);
+ }
+ }
+ }
+ }
+ else
+ {
+ sal_Int32 nCurrentState = m_xEmbeddedObject->getCurrentState();
+ if ( nCurrentState == EmbedStates::LOADED )
+ {
+ if ( !m_pClientHelper.is() )
+ {
+ m_pClientHelper = new OEmbeddedClientHelper;
+ }
+ m_xEmbeddedObject->setClientSite(m_pClientHelper);
+
+ Sequence< PropertyValue > aEmbeddedObjectDescriptor;
+ Sequence< PropertyValue > aLoadArgs( fillLoadArgs(
+ i_rConnection, _bSuppressMacros, _bReadOnly, i_rOpenCommandArguments, aEmbeddedObjectDescriptor ) );
+
+ Reference<XCommonEmbedPersist> xCommon(m_xEmbeddedObject,UNO_QUERY);
+ OSL_ENSURE(xCommon.is(),"unsupported interface!");
+ if ( xCommon.is() )
+ xCommon->reload( aLoadArgs, aEmbeddedObjectDescriptor );
+ m_xEmbeddedObject->changeState(EmbedStates::RUNNING);
+ }
+ else
+ {
+ OSL_ENSURE( ( nCurrentState == EmbedStates::RUNNING ) || ( nCurrentState == EmbedStates::ACTIVE ),
+ "ODocumentDefinition::loadEmbeddedObject: unexpected state!" );
+
+ // if the document was already loaded (which means the embedded object is in state RUNNING or ACTIVE),
+ // then just re-set some model parameters
+ try
+ {
+ // ensure the media descriptor doesn't contain any values which are intended for the
+ // EmbeddedObjectDescriptor only
+ ::comphelper::NamedValueCollection aEmbeddedObjectDescriptor;
+ ::comphelper::NamedValueCollection aNewMediaDesc;
+ separateOpenCommandArguments( i_rOpenCommandArguments, aNewMediaDesc, aEmbeddedObjectDescriptor );
+
+ // merge the new media descriptor into the existing media descriptor
+ const Reference< XModel > xModel( getComponent(), UNO_QUERY_THROW );
+ const Sequence< PropertyValue > aArgs = xModel->getArgs();
+ ::comphelper::NamedValueCollection aExistentMediaDesc( aArgs );
+ aExistentMediaDesc.merge( aNewMediaDesc, false );
+
+ lcl_putLoadArgs( aExistentMediaDesc, optional_bool(), optional_bool() );
+ // don't put _bSuppressMacros and _bReadOnly here - if the document was already
+ // loaded, we should not tamper with its settings.
+ // #i88977# #i86872#
+
+ xModel->attachResource( xModel->getURL(), aExistentMediaDesc.getPropertyValues() );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+ }
+
+ // set the OfficeDatabaseDocument instance as parent of the embedded document
+ // #i40358#
+ Reference< XChild > xDepdendDocAsChild( getComponent(), UNO_QUERY );
+ if ( xDepdendDocAsChild.is() )
+ {
+ try
+ {
+ if ( !xDepdendDocAsChild->getParent().is() )
+ { // first encounter
+ xDepdendDocAsChild->setParent( getDataSource( m_xParentContainer ) );
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+
+ if ( i_rConnection.is() )
+ m_xLastKnownConnection = i_rConnection;
+}
+
+void ODocumentDefinition::onCommandPreview(Any& _rImage)
+{
+ loadEmbeddedObjectForPreview();
+ if ( !m_xEmbeddedObject.is() )
+ return;
+
+ try
+ {
+ Reference<XTransferable> xTransfer(getComponent(),UNO_QUERY);
+ if ( xTransfer.is() )
+ {
+ DataFlavor aFlavor;
+ aFlavor.MimeType = "image/png";
+ aFlavor.HumanPresentableName = "Portable Network Graphics";
+ aFlavor.DataType = cppu::UnoType<Sequence < sal_Int8 >>::get();
+
+ _rImage = xTransfer->getTransferData( aFlavor );
+ }
+ }
+ catch( const Exception& )
+ {
+ }
+}
+
+void ODocumentDefinition::getPropertyDefaultByHandle( sal_Int32 /*_nHandle*/, Any& _rDefault ) const
+{
+ _rDefault.clear();
+}
+
+void ODocumentDefinition::onCommandGetDocumentProperties( Any& _rProps )
+{
+ loadEmbeddedObjectForPreview();
+ if ( !m_xEmbeddedObject.is() )
+ return;
+
+ try
+ {
+ Reference<XDocumentPropertiesSupplier> xDocSup(
+ getComponent(), UNO_QUERY );
+ if ( xDocSup.is() )
+ _rProps <<= xDocSup->getDocumentProperties();
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+}
+
+Reference< util::XCloseable > ODocumentDefinition::impl_getComponent_throw( const bool i_ForceCreate )
+{
+ OSL_ENSURE(m_xEmbeddedObject.is(),"Illegal call for embeddedObject");
+ Reference< util::XCloseable > xComp;
+ if ( m_xEmbeddedObject.is() )
+ {
+ int nState = m_xEmbeddedObject->getCurrentState();
+ if ( ( nState == EmbedStates::LOADED ) && i_ForceCreate )
+ {
+ m_xEmbeddedObject->changeState( EmbedStates::RUNNING );
+ nState = m_xEmbeddedObject->getCurrentState();
+ OSL_ENSURE( nState == EmbedStates::RUNNING, "ODocumentDefinition::impl_getComponent_throw: could not switch to RUNNING!" );
+ }
+
+ if ( nState == EmbedStates::ACTIVE || nState == EmbedStates::RUNNING )
+ {
+ if ( m_xEmbeddedObject.is() )
+ {
+ xComp = m_xEmbeddedObject->getComponent();
+ OSL_ENSURE(xComp.is(),"No valid component");
+ }
+ }
+ }
+ return xComp;
+}
+
+Reference< util::XCloseable > ODocumentDefinition::getComponent()
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ return impl_getComponent_throw();
+}
+
+namespace
+{
+ Reference< XDatabaseDocumentUI > lcl_getDatabaseDocumentUI( ODatabaseModelImpl const & _rModelImpl )
+ {
+ Reference< XDatabaseDocumentUI > xUI;
+
+ Reference< XModel > xModel( _rModelImpl.getModel_noCreate() );
+ if ( xModel.is() )
+ xUI.set( xModel->getCurrentController(), UNO_QUERY );
+ return xUI;
+ }
+}
+
+Reference< XComponent > ODocumentDefinition::impl_openUI_nolck_throw( bool _bForEditing )
+{
+ ::osl::ClearableMutexGuard aGuard( m_aMutex );
+ if ( !m_pImpl || !m_pImpl->m_pDataSource )
+ throw DisposedException();
+
+ Reference< XComponent > xComponent;
+ try
+ {
+ Reference< XDatabaseDocumentUI > xUI( lcl_getDatabaseDocumentUI( *m_pImpl->m_pDataSource ) );
+ if ( !xUI.is() )
+ {
+ // no XDatabaseDocumentUI -> just execute the respective command
+ m_bOpenInDesign = _bForEditing;
+ xComponent = Reference<XComponent>(onCommandOpenSomething(Any(), true, nullptr), UNO_QUERY);
+ OSL_ENSURE( xComponent.is(), "ODocumentDefinition::impl_openUI_nolck_throw: opening the thingie failed." );
+ return xComponent;
+ }
+
+
+ OUString sName( impl_getHierarchicalName( false ) );
+ sal_Int32 nObjectType = m_bForm ? DatabaseObject::FORM : DatabaseObject::REPORT;
+ aGuard.clear();
+
+ xComponent = xUI->loadComponent(
+ nObjectType, sName, _bForEditing
+ );
+ }
+ catch( const RuntimeException& ) { throw; }
+ catch( const Exception& )
+ {
+ throw WrappedTargetException(
+ OUString(), *this, ::cppu::getCaughtException() );
+ }
+
+ return xComponent;
+}
+
+void ODocumentDefinition::impl_store_throw()
+{
+ Reference<XEmbedPersist> xPersist( m_xEmbeddedObject, UNO_QUERY );
+ if ( xPersist.is() )
+ {
+ xPersist->storeOwn();
+ notifyDataSourceModified();
+ }
+}
+
+bool ODocumentDefinition::impl_close_throw()
+{
+ bool bSuccess = prepareClose();
+ if ( bSuccess && m_xEmbeddedObject.is() )
+ {
+ m_xEmbeddedObject->changeState( EmbedStates::LOADED );
+ bSuccess = m_xEmbeddedObject->getCurrentState() == EmbedStates::LOADED;
+ }
+ return bSuccess;
+}
+
+Reference< XComponent > SAL_CALL ODocumentDefinition::open( )
+{
+ return impl_openUI_nolck_throw( false );
+}
+
+Reference< XComponent > SAL_CALL ODocumentDefinition::openDesign( )
+{
+ return impl_openUI_nolck_throw( true );
+}
+
+void SAL_CALL ODocumentDefinition::store( )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ try
+ {
+ impl_store_throw();
+ }
+ catch( const RuntimeException& ) { throw; }
+ catch( const Exception& )
+ {
+ throw WrappedTargetException(
+ OUString(), *this, ::cppu::getCaughtException() );
+ }
+}
+
+sal_Bool SAL_CALL ODocumentDefinition::close( )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ bool bSuccess = false;
+ try
+ {
+ bSuccess = impl_close_throw();
+ }
+ catch( const RuntimeException& ) { throw; }
+ catch( const Exception& )
+ {
+ throw WrappedTargetException(
+ OUString(), *this, ::cppu::getCaughtException() );
+ }
+ return bSuccess;
+}
+
+OUString SAL_CALL ODocumentDefinition::getHierarchicalName()
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ return impl_getHierarchicalName( false );
+}
+
+OUString SAL_CALL ODocumentDefinition::composeHierarchicalName( const OUString& i_rRelativeName )
+{
+ return getHierarchicalName() + "/" + i_rRelativeName;
+}
+
+void SAL_CALL ODocumentDefinition::rename( const OUString& _rNewName )
+{
+ try
+ {
+ ::osl::ResettableMutexGuard aGuard(m_aMutex);
+ if ( _rNewName == m_pImpl->m_aProps.aTitle )
+ return;
+
+ // document definitions are organized in a hierarchical way, so reject names
+ // which contain a /, as this is reserved for hierarchy level separation
+ if ( _rNewName.indexOf( '/' ) != -1 )
+ m_aErrorHelper.raiseException( ErrorCondition::DB_OBJECT_NAME_WITH_SLASHES, *this );
+
+ NameChangeNotifier aNameChangeAndNotify( *this, _rNewName, aGuard );
+ m_pImpl->m_aProps.aTitle = _rNewName;
+
+ if ( m_xEmbeddedObject.is() && m_xEmbeddedObject->getCurrentState() == EmbedStates::ACTIVE )
+ updateDocumentTitle();
+ }
+ catch(const PropertyVetoException&)
+ {
+ throw ElementExistException(_rNewName,*this);
+ }
+}
+
+Reference< XStorage> ODocumentDefinition::getContainerStorage() const
+{
+ return m_pImpl->m_pDataSource
+ ? m_pImpl->m_pDataSource->getStorage( m_bForm ? ODatabaseModelImpl::E_FORM : ODatabaseModelImpl::E_REPORT )
+ : Reference< XStorage>();
+}
+
+bool ODocumentDefinition::isModified()
+{
+ osl::ClearableGuard< osl::Mutex > aGuard(m_aMutex);
+ bool bRet = false;
+ if ( m_xEmbeddedObject.is() )
+ {
+ Reference<XModifiable> xModel(getComponent(),UNO_QUERY);
+ bRet = xModel.is() && xModel->isModified();
+ }
+ return bRet;
+}
+
+bool ODocumentDefinition::prepareClose()
+{
+ if ( !m_xEmbeddedObject.is() )
+ return true;
+
+ try
+ {
+ // suspend the controller. Embedded objects are not allowed to raise
+ // own UI at their own discretion, instead, this has always to be triggered
+ // by the embedding component. Thus, we do the suspend call here.
+ // #i49370#
+
+ Reference< util::XCloseable > xComponent( impl_getComponent_throw( false ) );
+ if ( !xComponent.is() )
+ return true;
+
+ Reference< XModel > xModel( xComponent, UNO_QUERY );
+ Reference< XController > xController;
+ if ( xModel.is() )
+ xController = xModel->getCurrentController();
+
+ OSL_ENSURE( xController.is() || ( m_xEmbeddedObject->getCurrentState() < EmbedStates::ACTIVE ),
+ "ODocumentDefinition::prepareClose: no controller!" );
+ if ( !xController.is() )
+ // document has not yet been activated, i.e. has no UI, yet
+ return true;
+
+ if (!xController->suspend(true))
+ // controller vetoed the closing
+ return false;
+
+ if ( isModified() )
+ {
+ Reference< XFrame > xFrame( xController->getFrame() );
+ Reference<XTopWindow> xTopWindow;
+ if ( xFrame.is() )
+ {
+ xTopWindow = Reference<XTopWindow>(xFrame->getContainerWindow(), UNO_QUERY_THROW);
+ xTopWindow->toFront();
+ }
+ if (!save(true, xTopWindow))
+ {
+ // revert suspension
+ xController->suspend(false);
+ // saving failed or was cancelled
+ return false;
+ }
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+
+ return true;
+}
+
+void ODocumentDefinition::fillReportData( const Reference< XComponentContext >& _rContext,
+ const Reference< util::XCloseable >& _rxComponent,
+ const Reference< XConnection >& _rxActiveConnection )
+{
+ uno::Sequence<uno::Any> aArgs(comphelper::InitAnyPropertySequence(
+ {
+ {"TextDocument", uno::Any(_rxComponent)},
+ {"ActiveConnection", uno::Any(_rxActiveConnection)}
+ }));
+ try
+ {
+ Reference< XJobExecutor > xExecutable(
+ _rContext->getServiceManager()->createInstanceWithArgumentsAndContext("com.sun.star.wizards.report.CallReportWizard", aArgs, _rContext), UNO_QUERY_THROW );
+ xExecutable->trigger( "fill" );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+}
+
+void ODocumentDefinition::updateDocumentTitle()
+{
+ OUString sName = m_pImpl->m_aProps.aTitle;
+ if ( m_pImpl->m_pDataSource )
+ {
+ if ( sName.isEmpty() )
+ {
+ if ( m_bForm )
+ sName = DBA_RES( RID_STR_FORM );
+ else
+ sName = DBA_RES( RID_STR_REPORT );
+ Reference< XUntitledNumbers > xUntitledProvider(m_pImpl->m_pDataSource->getModel_noCreate(), UNO_QUERY );
+ if ( xUntitledProvider.is() )
+ sName += OUString::number( xUntitledProvider->leaseNumber(getComponent()) );
+ }
+
+ Reference< XTitle > xDatabaseDocumentModel(m_pImpl->m_pDataSource->getModel_noCreate(),uno::UNO_QUERY);
+ if ( xDatabaseDocumentModel.is() )
+ sName = xDatabaseDocumentModel->getTitle() + " : " + sName;
+ }
+ Reference< XTitle> xTitle(getComponent(),UNO_QUERY);
+ if ( xTitle.is() )
+ xTitle->setTitle(sName);
+}
+
+void SAL_CALL ODocumentDefinition::queryClosing( const lang::EventObject&, sal_Bool )
+{
+ try
+ {
+ if ( !close() )
+ throw util::CloseVetoException();
+ }
+ catch(const lang::WrappedTargetException&)
+ {
+ throw util::CloseVetoException();
+ }
+}
+
+void SAL_CALL ODocumentDefinition::notifyClosing( const lang::EventObject& /*Source*/ )
+{
+}
+
+void SAL_CALL ODocumentDefinition::disposing( const lang::EventObject& /*Source*/ )
+{
+}
+
+void ODocumentDefinition::firePropertyChange( sal_Int32 i_nHandle, const Any& i_rNewValue, const Any& i_rOldValue,
+ bool i_bVetoable, const NotifierAccess& )
+{
+ fire( &i_nHandle, &i_rNewValue, &i_rOldValue, 1, i_bVetoable );
+}
+
+// NameChangeNotifier
+NameChangeNotifier::NameChangeNotifier( ODocumentDefinition& i_rDocumentDefinition, const OUString& i_rNewName,
+ ::osl::ResettableMutexGuard& i_rClearForNotify )
+ :m_rDocumentDefinition( i_rDocumentDefinition )
+ ,m_aOldValue( Any( i_rDocumentDefinition.getCurrentName() ) )
+ ,m_aNewValue( Any( i_rNewName ) )
+ ,m_rClearForNotify( i_rClearForNotify )
+{
+ impl_fireEvent_throw( true );
+}
+
+NameChangeNotifier::~NameChangeNotifier()
+{
+ impl_fireEvent_throw( false );
+}
+
+void NameChangeNotifier::impl_fireEvent_throw( const bool i_bVetoable )
+{
+ m_rClearForNotify.clear();
+ m_rDocumentDefinition.firePropertyChange(
+ PROPERTY_ID_NAME, m_aNewValue, m_aOldValue, i_bVetoable, ODocumentDefinition::NotifierAccess() );
+ m_rClearForNotify.reset();
+}
+
+} // namespace dbaccess
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/dataaccess/documentdefinition.hxx b/dbaccess/source/core/dataaccess/documentdefinition.hxx
new file mode 100644
index 000000000..5569276d4
--- /dev/null
+++ b/dbaccess/source/core/dataaccess/documentdefinition.hxx
@@ -0,0 +1,356 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <cppuhelper/propshlp.hxx>
+#include <cppuhelper/implbase4.hxx>
+#include <ContentHelper.hxx>
+#include <comphelper/propertystatecontainer.hxx>
+#include <comphelper/proparrhlp.hxx>
+#include <apitools.hxx>
+#include <comphelper/uno3.hxx>
+#include <com/sun/star/awt/XTopWindow.hpp>
+#include <com/sun/star/sdbc/XConnection.hpp>
+#include <com/sun/star/frame/XController.hpp>
+#include <com/sun/star/embed/XStateChangeListener.hpp>
+#include <com/sun/star/embed/XEmbeddedObject.hpp>
+#include <com/sun/star/embed/XStorage.hpp>
+#include <com/sun/star/sdb/XSubDocument.hpp>
+#include <com/sun/star/util/XCloseListener.hpp>
+#include <com/sun/star/container/XHierarchicalName.hpp>
+#include <rtl/ref.hxx>
+
+namespace comphelper
+{
+ class NamedValueCollection;
+}
+
+namespace dbaccess
+{
+
+ class OInterceptor;
+ class OEmbeddedClientHelper;
+// ODocumentDefinition - a database "document" which is simply a link to a real
+// document
+
+typedef ::cppu::ImplHelper4 < css::embed::XComponentSupplier
+ , css::sdb::XSubDocument
+ , css::util::XCloseListener
+ , css::container::XHierarchicalName
+ > ODocumentDefinition_Base;
+
+class ODocumentDefinition
+ :public OContentHelper
+ ,public ::comphelper::OPropertyStateContainer
+ ,public ::comphelper::OPropertyArrayUsageHelper< ODocumentDefinition >
+ ,public ODocumentDefinition_Base
+{
+ css::uno::Reference< css::embed::XEmbeddedObject> m_xEmbeddedObject;
+ css::uno::Reference< css::embed::XStateChangeListener > m_xListener;
+ css::uno::Reference< css::sdbc::XConnection > m_xLastKnownConnection;
+
+ rtl::Reference<OInterceptor> m_pInterceptor;
+ bool m_bForm; // <TRUE/> if it is a form
+ bool m_bOpenInDesign;
+ bool m_bInExecute;
+ bool m_bRemoveListener;
+ rtl::Reference<OEmbeddedClientHelper> m_pClientHelper;
+
+protected:
+ virtual ~ODocumentDefinition() override;
+
+public:
+
+ ODocumentDefinition(
+ const css::uno::Reference< css::uno::XInterface >& _rxContainer,
+ const css::uno::Reference< css::uno::XComponentContext >&,
+ const TContentPtr& _pImpl,
+ bool _bForm
+ );
+
+ void initialLoad(
+ const css::uno::Sequence< sal_Int8 >& i_rClassID,
+ const css::uno::Sequence< css::beans::PropertyValue >& i_rCreationArgs,
+ const css::uno::Reference< css::sdbc::XConnection >& i_rConnection
+ );
+
+ virtual css::uno::Sequence<css::uno::Type> SAL_CALL getTypes() override;
+ virtual css::uno::Sequence<sal_Int8> SAL_CALL getImplementationId() override;
+
+// css::uno::XInterface
+ DECLARE_XINTERFACE( )
+
+// css::beans::XPropertySet
+ virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo( ) override;
+
+ // OPropertySetHelper
+ virtual void SAL_CALL getFastPropertyValue(
+ css::uno::Any& o_rValue,
+ sal_Int32 i_nHandle
+ ) const override;
+
+ // XComponentSupplier
+ virtual css::uno::Reference< css::util::XCloseable > SAL_CALL getComponent( ) override;
+
+ // XSubDocument
+ virtual css::uno::Reference< css::lang::XComponent > SAL_CALL open( ) override;
+ virtual css::uno::Reference< css::lang::XComponent > SAL_CALL openDesign( ) override;
+ virtual void SAL_CALL store( ) override;
+ virtual sal_Bool SAL_CALL close( ) override;
+
+ // XHierarchicalName
+ virtual OUString SAL_CALL getHierarchicalName( ) override;
+ virtual OUString SAL_CALL composeHierarchicalName( const OUString& aRelativeName ) override;
+
+// OPropertySetHelper
+ virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper() override;
+
+ // XCommandProcessor
+ virtual css::uno::Any SAL_CALL execute( const css::ucb::Command& aCommand, sal_Int32 CommandId, const css::uno::Reference< css::ucb::XCommandEnvironment >& Environment ) override ;
+
+ // XRename
+ virtual void SAL_CALL rename( const OUString& newName ) override;
+
+ // XCloseListener
+ virtual void SAL_CALL queryClosing( const css::lang::EventObject& Source, sal_Bool GetsOwnership ) override;
+ virtual void SAL_CALL notifyClosing( const css::lang::EventObject& Source ) override;
+
+ // XEventListener
+ virtual void SAL_CALL disposing( const css::lang::EventObject& Source ) override;
+
+ /** returns the forms/reports container storage, depending on m_bForm. Our own storage
+ inside this container storage is the one with the name as indicated by m_pImpl->m_aProps.sPersistentName.
+ */
+ css::uno::Reference< css::embed::XStorage >
+ getContainerStorage() const;
+
+ bool save(bool _bApprove, const css::uno::Reference<css::awt::XTopWindow>& rDialogParent);
+ void saveAs();
+ void closeObject();
+ bool isModified();
+ bool isNewReport() const { return !m_bForm && !m_pImpl->m_aProps.bAsTemplate; }
+
+ static void fillReportData(
+ const css::uno::Reference< css::uno::XComponentContext > & _rxContext,
+ const css::uno::Reference< css::util::XCloseable >& _rxComponent,
+ const css::uno::Reference< css::sdbc::XConnection >& _rxActiveConnection
+ );
+
+ const css::uno::Reference< css::sdbc::XConnection >&
+ getConnection() const { return m_xLastKnownConnection; }
+
+ /** prepares closing the document component
+
+ The method suspends the controller associated with the document, and saves the document
+ if necessary.
+
+ @return
+ <TRUE/> if and only if the document component can be closed
+ */
+ bool prepareClose();
+
+ static OUString GetDocumentServiceFromMediaType(
+ const OUString& _rMediaType,
+ const css::uno::Reference< css::uno::XComponentContext > & _rxContext,
+ css::uno::Sequence< sal_Int8 >& _rClassId
+ );
+ static OUString GetDocumentServiceFromMediaType(
+ const css::uno::Reference< css::embed::XStorage >& _rxContainerStorage,
+ const OUString& _rEntityName,
+ const css::uno::Reference< css::uno::XComponentContext > & _rxContext,
+ css::uno::Sequence< sal_Int8 >& _rClassId
+ );
+
+ struct NotifierAccess { friend class NameChangeNotifier; private: NotifierAccess() { } };
+ const OUString& getCurrentName() const { return m_pImpl->m_aProps.aTitle; }
+ void firePropertyChange(
+ sal_Int32 i_nHandle,
+ const css::uno::Any& i_rNewValue,
+ const css::uno::Any& i_rOldValue,
+ bool i_bVetoable,
+ const NotifierAccess&
+ );
+
+private:
+ /** does necessary initializations after our embedded object has been switched to ACTIVE
+ */
+ void impl_onActivateEmbeddedObject_nothrow( const bool i_bReactivated );
+
+ /** initializes a newly created view/controller of a form which is displaying our embedded object
+
+ Has only to be called if the respective embedded object has been loaded for design (and
+ not for data entry)
+
+ @param _rxController
+ the controller which belongs to the XModel of our (active) embedded object
+ */
+ static void impl_initFormEditView( const css::uno::Reference< css::frame::XController >& _rxController );
+
+ /** removes the given frame from the desktop's frame collection
+ @throws css::uno::RuntimeException
+ */
+ static void impl_removeFrameFromDesktop_throw(
+ const css::uno::Reference< css::uno::XComponentContext >& _rContext,
+ const css::uno::Reference< css::frame::XFrame >& _rxFrame
+ );
+
+ /** opens the UI for this sub document
+ */
+ css::uno::Reference< css::lang::XComponent >
+ impl_openUI_nolck_throw( bool _bForEditing );
+
+ /** stores our document, if it's already loaded
+ */
+ void impl_store_throw();
+
+ /** closes our document, if it's open
+ */
+ bool impl_close_throw();
+
+ /** returns our component, creates it if necessary
+ */
+ css::uno::Reference< css::util::XCloseable >
+ impl_getComponent_throw( const bool i_ForceCreate = true );
+
+ /** shows or hides our component
+
+ The embedded object must exist, and be in state LOADED, at least.
+ */
+ void impl_showOrHideComponent_throw( const bool i_bShow );
+
+ // OPropertyArrayUsageHelper
+ virtual ::cppu::IPropertyArrayHelper* createArrayHelper( ) const override;
+
+ virtual void getPropertyDefaultByHandle( sal_Int32 _nHandle, css::uno::Any& _rDefault ) const override;
+
+ // helper
+ virtual void SAL_CALL disposing() override;
+
+ // OContentHelper overridables
+ virtual OUString determineContentType() const override;
+
+ /** fills the load arguments
+ */
+ css::uno::Sequence< css::beans::PropertyValue >
+ fillLoadArgs(
+ const css::uno::Reference< css::sdbc::XConnection>& _xConnection,
+ const bool _bSuppressMacros,
+ const bool _bReadOnly,
+ const css::uno::Sequence< css::beans::PropertyValue >& i_rOpenCommandArguments,
+ css::uno::Sequence< css::beans::PropertyValue >& _out_rEmbeddedObjectDescriptor
+ );
+
+ /** splits the given arguments to an "open*" command into arguments for loading the document, and arguments to be
+ put into the EmbeddedObjectDescriptor
+
+ Any values already present in <code>o_rDocumentLoadArgs</code> and <code>o_rEmbeddedObjectDescriptor</code>
+ will be overwritten by values from <code>i_rOpenCommandArguments</code>, if applicable, otherwise they will
+ be preserved.
+
+ @param i_rOpenCommandArguments
+ the arguments passed to the "open*" command at the content
+ @param o_rDocumentLoadArgs
+ the arguments to be passed when actually loading the embedded document.
+ @param o_rEmbeddedObjectDescriptor
+ the EmbeddedObjectDescriptor to be passed when initializing the embedded object
+ */
+ static void separateOpenCommandArguments(
+ const css::uno::Sequence< css::beans::PropertyValue >& i_rOpenCommandArguments,
+ ::comphelper::NamedValueCollection& o_rDocumentLoadArgs,
+ ::comphelper::NamedValueCollection& o_rEmbeddedObjectDescriptor
+ );
+
+ /** loads the EmbeddedObject if not already loaded
+ @param _aClassID
+ If set, it will be used to create the embedded object.
+ */
+ void loadEmbeddedObject(
+ const css::uno::Reference< css::sdbc::XConnection>& _xConnection,
+ const css::uno::Sequence< sal_Int8 >& _aClassID,
+ const css::uno::Sequence< css::beans::PropertyValue >& _rAdditionalArgs,
+ const bool _bSuppressMacros,
+ const bool _bReadOnly
+ );
+
+ /** loads the embedded object for preview. Macros will be suppressed, and the document will
+ be read-only.
+ */
+ void loadEmbeddedObjectForPreview()
+ {
+ loadEmbeddedObject(
+ nullptr,
+ css::uno::Sequence< sal_Int8 >(),
+ css::uno::Sequence< css::beans::PropertyValue >(),
+ true,
+ true
+ );
+ }
+
+ /** searches for read-only flag in the args of the model and sets it to the given value,
+ if the value was not found, it will be appended.
+ @param _bReadOnly
+ If <TRUE/> the document will be switched to readonly mode
+ */
+ void updateDocumentTitle();
+
+ void registerProperties();
+
+ /** determines whether the document we represent supports embedded scripts and macros
+ */
+ bool objectSupportsEmbeddedScripts() const;
+
+ //- commands
+
+ void onCommandGetDocumentProperties( css::uno::Any& _rProps );
+ /// @throws css::uno::Exception
+ void onCommandInsert( const OUString& _sURL, const css::uno::Reference< css::ucb::XCommandEnvironment >& Environment );
+ void onCommandPreview( css::uno::Any& _rImage );
+ css::uno::Any
+ onCommandOpenSomething(
+ const css::uno::Any& _rArgument,
+ const bool _bActivate,
+ const css::uno::Reference< css::ucb::XCommandEnvironment >& _rxEnvironment
+ );
+private:
+ using ::cppu::OPropertySetHelper::getFastPropertyValue;
+};
+
+class NameChangeNotifier
+{
+public:
+ NameChangeNotifier(
+ ODocumentDefinition& i_rDocumentDefinition,
+ const OUString& i_rNewName,
+ ::osl::ResettableMutexGuard& i_rClearForNotify
+ );
+ ~NameChangeNotifier();
+
+private:
+ ODocumentDefinition& m_rDocumentDefinition;
+ const css::uno::Any m_aOldValue;
+ const css::uno::Any m_aNewValue;
+ ::osl::ResettableMutexGuard& m_rClearForNotify;
+
+ void impl_fireEvent_throw( const bool i_bVetoable );
+};
+
+} // namespace dbaccess
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/dataaccess/documenteventexecutor.cxx b/dbaccess/source/core/dataaccess/documenteventexecutor.cxx
new file mode 100644
index 000000000..3d16ee6eb
--- /dev/null
+++ b/dbaccess/source/core/dataaccess/documenteventexecutor.cxx
@@ -0,0 +1,199 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "documenteventexecutor.hxx"
+
+#include <com/sun/star/document/XDocumentEventBroadcaster.hpp>
+#include <com/sun/star/util/URLTransformer.hpp>
+#include <com/sun/star/util/XURLTransformer.hpp>
+#include <com/sun/star/frame/XModel.hpp>
+#include <com/sun/star/frame/XDispatchProvider.hpp>
+
+#include <comphelper/namedvaluecollection.hxx>
+#include <cppuhelper/weakref.hxx>
+#include <tools/diagnose_ex.h>
+#include <vcl/svapp.hxx>
+
+namespace dbaccess
+{
+
+ using ::com::sun::star::uno::Reference;
+ using ::com::sun::star::uno::UNO_QUERY;
+ using ::com::sun::star::uno::UNO_QUERY_THROW;
+ using ::com::sun::star::uno::UNO_SET_THROW;
+ using ::com::sun::star::uno::Exception;
+ using ::com::sun::star::uno::RuntimeException;
+ using ::com::sun::star::uno::Sequence;
+ using ::com::sun::star::uno::WeakReference;
+ using ::com::sun::star::uno::XComponentContext;
+ using ::com::sun::star::document::XDocumentEventBroadcaster;
+ using ::com::sun::star::document::XEventsSupplier;
+ using ::com::sun::star::container::XNameAccess;
+ using ::com::sun::star::frame::XModel;
+ using ::com::sun::star::util::URLTransformer;
+ using ::com::sun::star::util::XURLTransformer;
+ using ::com::sun::star::frame::XDispatchProvider;
+ using ::com::sun::star::frame::XDispatch;
+ using ::com::sun::star::util::URL;
+ using ::com::sun::star::beans::PropertyValue;
+ using ::com::sun::star::frame::XController;
+ using ::com::sun::star::document::DocumentEvent;
+
+ using namespace ::com::sun::star;
+
+ // DocumentEventExecutor_Data
+ struct DocumentEventExecutor_Data
+ {
+ WeakReference< XEventsSupplier > xDocument;
+ Reference< XURLTransformer > xURLTransformer;
+
+ explicit DocumentEventExecutor_Data( const Reference< XEventsSupplier >& _rxDocument )
+ :xDocument( _rxDocument )
+ {
+ }
+ };
+
+ namespace
+ {
+ void lcl_dispatchScriptURL_throw( DocumentEventExecutor_Data const & _rDocExecData,
+ const OUString& _rScriptURL, const DocumentEvent& _rTrigger )
+ {
+ Reference< XModel > xDocument( _rDocExecData.xDocument.get(), UNO_QUERY_THROW );
+
+ Reference< XController > xController( xDocument->getCurrentController() );
+ Reference< XDispatchProvider > xDispProv;
+ if ( xController.is() )
+ xDispProv.set( xController->getFrame(), UNO_QUERY );
+ if ( !xDispProv.is() )
+ {
+ OSL_FAIL( "lcl_dispatchScriptURL_throw: no controller/frame? How should I dispatch?" );
+ return;
+ }
+
+ URL aScriptURL;
+ aScriptURL.Complete = _rScriptURL;
+ if ( _rDocExecData.xURLTransformer.is() )
+ _rDocExecData.xURLTransformer->parseStrict( aScriptURL );
+
+ // unfortunately, executing a script can trigger all kind of complex stuff, and unfortunately, not
+ // every component involved into this properly cares for thread safety. To be on the safe side,
+ // we lock the solar mutex here.
+ SolarMutexGuard aSolarGuard;
+
+ Reference< XDispatch > xDispatch( xDispProv->queryDispatch( aScriptURL, OUString(), 0 ) );
+ if ( !xDispatch.is() )
+ {
+ OSL_FAIL( "lcl_dispatchScriptURL_throw: no dispatcher for the script URL!" );
+ return;
+ }
+
+ PropertyValue aEventParam;
+ aEventParam.Value <<= _rTrigger;
+ Sequence< PropertyValue > aDispatchArgs( &aEventParam, 1 );
+ xDispatch->dispatch( aScriptURL, aDispatchArgs );
+ }
+ }
+
+ // DocumentEventExecutor
+ DocumentEventExecutor::DocumentEventExecutor( const Reference<XComponentContext> & _rContext,
+ const Reference< XEventsSupplier >& _rxDocument )
+ :m_pData( new DocumentEventExecutor_Data( _rxDocument ) )
+ {
+ Reference< XDocumentEventBroadcaster > xBroadcaster( _rxDocument, UNO_QUERY_THROW );
+
+ osl_atomic_increment( &m_refCount );
+ {
+ xBroadcaster->addDocumentEventListener( this );
+ }
+ osl_atomic_decrement( &m_refCount );
+
+ try
+ {
+ m_pData->xURLTransformer = URLTransformer::create(_rContext);
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+
+ DocumentEventExecutor::~DocumentEventExecutor()
+ {
+ }
+
+ void SAL_CALL DocumentEventExecutor::documentEventOccured( const DocumentEvent& Event )
+ {
+ Reference< XEventsSupplier > xEventsSupplier( m_pData->xDocument.get(), UNO_QUERY );
+ if ( !xEventsSupplier.is() )
+ {
+ OSL_FAIL( "DocumentEventExecutor::documentEventOccurred: no document anymore, but still being notified?" );
+ return;
+ }
+
+ Reference< XModel > xDocument( xEventsSupplier, UNO_QUERY_THROW );
+
+ try
+ {
+ Reference< XNameAccess > xDocEvents( xEventsSupplier->getEvents(), UNO_SET_THROW );
+ if ( !xDocEvents->hasByName( Event.EventName ) )
+ {
+ // this is worth an assertion: We are listener at the very same document which we just asked
+ // for its events. So when EventName is fired, why isn't it supported by xDocEvents?
+ OSL_FAIL( "DocumentEventExecutor::documentEventOccurred: an unsupported event is notified!" );
+ return;
+ }
+
+ const ::comphelper::NamedValueCollection aScriptDescriptor( xDocEvents->getByName( Event.EventName ) );
+
+ OUString sEventType;
+ bool bScriptAssigned = aScriptDescriptor.get_ensureType( "EventType", sEventType );
+
+ OUString sScript;
+ bScriptAssigned = bScriptAssigned && aScriptDescriptor.get_ensureType( "Script", sScript );
+
+ if ( !bScriptAssigned )
+ // no script is assigned to this event
+ return;
+
+ bool bDispatchScriptURL = ( sEventType == "Script" || sEventType == "Service" );
+ bool bNonEmptyScript = !sScript.isEmpty();
+
+ OSL_ENSURE( bDispatchScriptURL && bNonEmptyScript,
+ "DocumentEventExecutor::documentEventOccurred: invalid/unsupported script descriptor" );
+
+ if ( bDispatchScriptURL && bNonEmptyScript )
+ {
+ lcl_dispatchScriptURL_throw( *m_pData, sScript, Event );
+ }
+ }
+ catch( const RuntimeException& ) { throw; }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+
+ void SAL_CALL DocumentEventExecutor::disposing( const lang::EventObject& /*_Source*/ )
+ {
+ // not interested in
+ }
+
+} // namespace dbaccess
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/dataaccess/documenteventexecutor.hxx b/dbaccess/source/core/dataaccess/documenteventexecutor.hxx
new file mode 100644
index 000000000..90dc9083c
--- /dev/null
+++ b/dbaccess/source/core/dataaccess/documenteventexecutor.hxx
@@ -0,0 +1,59 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <com/sun/star/document/XDocumentEventListener.hpp>
+#include <com/sun/star/document/XEventsSupplier.hpp>
+
+#include <cppuhelper/implbase.hxx>
+
+#include <memory>
+
+namespace com::sun::star::uno { class XComponentContext; }
+
+namespace dbaccess
+{
+
+ struct DocumentEventExecutor_Data;
+ // DocumentEventExecutor
+ typedef ::cppu::WeakImplHelper < css::document::XDocumentEventListener
+ > DocumentEventExecutor_Base;
+ class DocumentEventExecutor : public DocumentEventExecutor_Base
+ {
+ public:
+ DocumentEventExecutor(
+ const css::uno::Reference< css::uno::XComponentContext >& _rContext,
+ const css::uno::Reference< css::document::XEventsSupplier >& _rxDocument );
+
+ protected:
+ virtual ~DocumentEventExecutor() override;
+
+ // css.document.XDocumentEventListener
+ virtual void SAL_CALL documentEventOccured( const css::document::DocumentEvent& Event ) override;
+ // css.lang.XEventListener
+ virtual void SAL_CALL disposing( const css::lang::EventObject& Source ) override;
+
+ private:
+ std::unique_ptr< DocumentEventExecutor_Data > m_pData;
+ };
+
+} // namespace dbaccess
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/dataaccess/documenteventnotifier.cxx b/dbaccess/source/core/dataaccess/documenteventnotifier.cxx
new file mode 100644
index 000000000..6a7088f95
--- /dev/null
+++ b/dbaccess/source/core/dataaccess/documenteventnotifier.cxx
@@ -0,0 +1,290 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "documenteventnotifier.hxx"
+
+#include <com/sun/star/frame/DoubleInitializationException.hpp>
+
+#include <comphelper/asyncnotification.hxx>
+#include <comphelper/interfacecontainer3.hxx>
+#include <cppuhelper/weak.hxx>
+#include <tools/diagnose_ex.h>
+#include <vcl/svapp.hxx>
+
+namespace dbaccess
+{
+
+ using ::com::sun::star::uno::Reference;
+ using ::com::sun::star::uno::Exception;
+ using ::com::sun::star::uno::Any;
+ using ::com::sun::star::frame::DoubleInitializationException;
+ using ::com::sun::star::document::XDocumentEventListener;
+ using ::com::sun::star::document::DocumentEvent;
+ using ::com::sun::star::frame::XController2;
+
+ using namespace ::com::sun::star;
+
+ // DocumentEventHolder
+ typedef ::comphelper::EventHolder< DocumentEvent > DocumentEventHolder;
+
+ // DocumentEventNotifier_Impl
+ class DocumentEventNotifier_Impl : public ::comphelper::IEventProcessor
+ {
+ oslInterlockedCount m_refCount;
+ ::cppu::OWeakObject& m_rDocument;
+ ::osl::Mutex& m_rMutex;
+ bool m_bInitialized;
+ bool m_bDisposed;
+ std::shared_ptr<::comphelper::AsyncEventNotifierAutoJoin> m_pEventBroadcaster;
+ ::comphelper::OInterfaceContainerHelper3<css::document::XEventListener> m_aLegacyEventListeners;
+ ::comphelper::OInterfaceContainerHelper3<XDocumentEventListener> m_aDocumentEventListeners;
+
+ public:
+ DocumentEventNotifier_Impl( ::cppu::OWeakObject& _rBroadcasterDocument, ::osl::Mutex& _rMutex )
+ :m_refCount( 0 )
+ ,m_rDocument( _rBroadcasterDocument )
+ ,m_rMutex( _rMutex )
+ ,m_bInitialized( false )
+ ,m_bDisposed( false )
+ ,m_aLegacyEventListeners( _rMutex )
+ ,m_aDocumentEventListeners( _rMutex )
+ {
+ }
+
+ // IEventProcessor
+ virtual void SAL_CALL acquire() noexcept override;
+ virtual void SAL_CALL release() noexcept override;
+
+ void addLegacyEventListener( const Reference< document::XEventListener >& Listener )
+ {
+ m_aLegacyEventListeners.addInterface( Listener );
+ }
+
+ void removeLegacyEventListener( const Reference< document::XEventListener >& Listener )
+ {
+ m_aLegacyEventListeners.removeInterface( Listener );
+ }
+
+ void addDocumentEventListener( const Reference< XDocumentEventListener >& Listener )
+ {
+ m_aDocumentEventListeners.addInterface( Listener );
+ }
+
+ void removeDocumentEventListener( const Reference< XDocumentEventListener >& Listener )
+ {
+ m_aDocumentEventListeners.removeInterface( Listener );
+ }
+
+ void disposing();
+
+ void onDocumentInitialized();
+
+ void notifyDocumentEvent( const OUString& EventName, const Reference< XController2 >& ViewController,
+ const Any& Supplement )
+ {
+ impl_notifyEvent_nothrow( DocumentEvent(
+ m_rDocument, EventName, ViewController, Supplement ) );
+ }
+
+ void notifyDocumentEventAsync( const OUString& EventName, const Reference< XController2 >& ViewController,
+ const Any& Supplement )
+ {
+ impl_notifyEventAsync_nothrow( DocumentEvent(
+ m_rDocument, EventName, ViewController, Supplement ) );
+ }
+
+ protected:
+ virtual ~DocumentEventNotifier_Impl()
+ {
+ }
+
+ // IEventProcessor
+ virtual void processEvent( const ::comphelper::AnyEvent& _rEvent ) override;
+
+ private:
+ void impl_notifyEvent_nothrow( const DocumentEvent& _rEvent );
+ void impl_notifyEventAsync_nothrow( const DocumentEvent& _rEvent );
+ };
+
+ void SAL_CALL DocumentEventNotifier_Impl::acquire() noexcept
+ {
+ osl_atomic_increment( &m_refCount );
+ }
+
+ void SAL_CALL DocumentEventNotifier_Impl::release() noexcept
+ {
+ if ( 0 == osl_atomic_decrement( &m_refCount ) )
+ delete this;
+ }
+
+ void DocumentEventNotifier_Impl::disposing()
+ {
+ // SYNCHRONIZED ->
+ // cancel any pending asynchronous events
+ ::osl::ResettableMutexGuard aGuard( m_rMutex );
+ if (m_pEventBroadcaster)
+ {
+ m_pEventBroadcaster->removeEventsForProcessor( this );
+ m_pEventBroadcaster->terminate();
+ }
+
+ auto xEventBroadcaster = std::exchange(m_pEventBroadcaster, {});
+
+ lang::EventObject aEvent( m_rDocument );
+ aGuard.clear();
+ // <-- SYNCHRONIZED
+
+ if (xEventBroadcaster)
+ {
+ comphelper::SolarMutex& rSolarMutex = Application::GetSolarMutex();
+ // unblock threads blocked on that so we can join
+ sal_uInt32 nLockCount = (rSolarMutex.IsCurrentThread()) ? rSolarMutex.release(true) : 0;
+ xEventBroadcaster->join();
+ if (nLockCount)
+ rSolarMutex.acquire(nLockCount);
+ xEventBroadcaster.reset();
+ }
+ m_aLegacyEventListeners.disposeAndClear( aEvent );
+ m_aDocumentEventListeners.disposeAndClear( aEvent );
+
+ // SYNCHRONIZED ->
+ aGuard.reset();
+ m_bDisposed = true;
+ // <-- SYNCHRONIZED
+ }
+
+ void DocumentEventNotifier_Impl::onDocumentInitialized()
+ {
+ if ( m_bInitialized )
+ throw DoubleInitializationException();
+
+ m_bInitialized = true;
+ if (m_pEventBroadcaster)
+ {
+ // there are already pending asynchronous events
+ ::comphelper::AsyncEventNotifierAutoJoin::launch(m_pEventBroadcaster);
+ }
+ }
+
+ void DocumentEventNotifier_Impl::impl_notifyEvent_nothrow( const DocumentEvent& _rEvent )
+ {
+ OSL_PRECOND( m_bInitialized,
+ "DocumentEventNotifier_Impl::impl_notifyEvent_nothrow: only to be called when the document is already initialized!" );
+ try
+ {
+ document::EventObject aLegacyEvent( _rEvent.Source, _rEvent.EventName );
+ m_aLegacyEventListeners.notifyEach( &document::XEventListener::notifyEvent, aLegacyEvent );
+ }
+ catch(const Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ try
+ {
+ m_aDocumentEventListeners.notifyEach( &XDocumentEventListener::documentEventOccured, _rEvent );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+
+ void DocumentEventNotifier_Impl::impl_notifyEventAsync_nothrow( const DocumentEvent& _rEvent )
+ {
+ if (!m_pEventBroadcaster)
+ {
+ m_pEventBroadcaster = ::comphelper::AsyncEventNotifierAutoJoin
+ ::newAsyncEventNotifierAutoJoin("DocumentEventNotifier");
+ if ( m_bInitialized )
+ {
+ // start processing the events if and only if we (our document, respectively) are
+ // already initialized
+ ::comphelper::AsyncEventNotifierAutoJoin::launch(m_pEventBroadcaster);
+ }
+ }
+ m_pEventBroadcaster->addEvent( new DocumentEventHolder( _rEvent ), this );
+ }
+
+ void DocumentEventNotifier_Impl::processEvent( const ::comphelper::AnyEvent& _rEvent )
+ {
+ // beware, this is called from the notification thread
+ {
+ ::osl::MutexGuard aGuard( m_rMutex );
+ if ( m_bDisposed )
+ return;
+ }
+ const DocumentEventHolder& rEventHolder = dynamic_cast< const DocumentEventHolder& >( _rEvent );
+ impl_notifyEvent_nothrow( rEventHolder.getEventObject() );
+ }
+
+ // DocumentEventNotifier
+ DocumentEventNotifier::DocumentEventNotifier( ::cppu::OWeakObject& _rBroadcasterDocument, ::osl::Mutex& _rMutex )
+ :m_pImpl( new DocumentEventNotifier_Impl( _rBroadcasterDocument, _rMutex ) )
+ {
+ }
+
+ DocumentEventNotifier::~DocumentEventNotifier()
+ {
+ }
+
+ void DocumentEventNotifier::disposing()
+ {
+ m_pImpl->disposing();
+ }
+
+ void DocumentEventNotifier::onDocumentInitialized()
+ {
+ m_pImpl->onDocumentInitialized();
+ }
+
+ void DocumentEventNotifier::addLegacyEventListener( const Reference< document::XEventListener >& Listener )
+ {
+ m_pImpl->addLegacyEventListener( Listener );
+ }
+
+ void DocumentEventNotifier::removeLegacyEventListener( const Reference< document::XEventListener >& Listener )
+ {
+ m_pImpl->removeLegacyEventListener( Listener );
+ }
+
+ void DocumentEventNotifier::addDocumentEventListener( const Reference< XDocumentEventListener >& Listener )
+ {
+ m_pImpl->addDocumentEventListener( Listener );
+ }
+
+ void DocumentEventNotifier::removeDocumentEventListener( const Reference< XDocumentEventListener >& Listener )
+ {
+ m_pImpl->removeDocumentEventListener( Listener );
+ }
+
+ void DocumentEventNotifier::notifyDocumentEvent( const OUString& EventName,
+ const Reference< XController2 >& ViewController, const Any& Supplement )
+ {
+ m_pImpl->notifyDocumentEvent( EventName, ViewController, Supplement );
+ }
+
+ void DocumentEventNotifier::notifyDocumentEventAsync( const OUString& EventName,
+ const Reference< XController2 >& ViewController, const Any& Supplement )
+ {
+ m_pImpl->notifyDocumentEventAsync( EventName, ViewController, Supplement );
+ }
+
+} // namespace dbaccess
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/dataaccess/documenteventnotifier.hxx b/dbaccess/source/core/dataaccess/documenteventnotifier.hxx
new file mode 100644
index 000000000..6f3bffc4c
--- /dev/null
+++ b/dbaccess/source/core/dataaccess/documenteventnotifier.hxx
@@ -0,0 +1,128 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <com/sun/star/document/XEventListener.hpp>
+#include <com/sun/star/document/XDocumentEventListener.hpp>
+
+#include <rtl/ref.hxx>
+
+namespace cppu
+{
+ class OWeakObject;
+}
+
+namespace dbaccess
+{
+
+ class DocumentEventNotifier_Impl;
+ // DocumentEventNotifier
+ class DocumentEventNotifier
+ {
+ public:
+ DocumentEventNotifier( ::cppu::OWeakObject& _rBroadcasterDocument, ::osl::Mutex& _rMutex );
+ ~DocumentEventNotifier();
+
+ void addLegacyEventListener( const css::uno::Reference< css::document::XEventListener >& Listener );
+ void removeLegacyEventListener( const css::uno::Reference< css::document::XEventListener >& Listener );
+ void addDocumentEventListener( const css::uno::Reference< css::document::XDocumentEventListener >& Listener );
+ void removeDocumentEventListener( const css::uno::Reference< css::document::XDocumentEventListener >& Listener );
+
+ /** disposes the instance
+ @precond
+ the mutex is not locked
+ */
+ void disposing();
+
+ /** tells the instance that its document is completely initialized now.
+
+ Before you call this method, no notification will actually happen
+
+ @precond
+ the mutex is locked
+ */
+ void onDocumentInitialized();
+
+ /** notifies a document event described by the given parameters
+
+ @precond
+ the mutex is not locked
+ @precond
+ ->onDocumentInitialized has been called
+ */
+ void notifyDocumentEvent(
+ const OUString& EventName,
+ const css::uno::Reference< css::frame::XController2 >& _rxViewController,
+ const css::uno::Any& Supplement
+ );
+
+ /** notifies a document event, described by the given parameters, asynchronously
+
+ Note that no event is actually notified before you called ->onDocumentInitialized.
+
+ @precond
+ the mutex is locked
+ */
+ void notifyDocumentEventAsync(
+ const OUString& EventName,
+ const css::uno::Reference< css::frame::XController2 >& ViewController,
+ const css::uno::Any& Supplement
+ );
+
+ /** notifies a document event to all registered listeners
+
+ @precond
+ the mutex is not locked
+ @precond
+ ->onDocumentInitialized has been called
+ */
+ void notifyDocumentEvent(
+ const char* _pAsciiEventName,
+ const css::uno::Reference< css::frame::XController2 >& _rxViewController = nullptr,
+ const css::uno::Any& _rSupplement = css::uno::Any()
+ )
+ {
+ notifyDocumentEvent( OUString::createFromAscii( _pAsciiEventName ), _rxViewController, _rSupplement );
+ }
+
+ /** notifies a document event to all registered listeners, asynchronously
+
+ Note that no event is actually notified before you called ->onDocumentInitialized.
+
+ @precond
+ the mutex is locked
+ */
+ void notifyDocumentEventAsync(
+ const char* _pAsciiEventName,
+ const css::uno::Reference< css::frame::XController2 >& _rxViewController = nullptr,
+ const css::uno::Any& _rSupplement = css::uno::Any()
+ )
+ {
+ notifyDocumentEventAsync( OUString::createFromAscii( _pAsciiEventName ), _rxViewController, _rSupplement );
+ }
+
+ private:
+ ::rtl::Reference< DocumentEventNotifier_Impl > m_pImpl;
+ };
+
+} // namespace dbaccess
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/dataaccess/documentevents.cxx b/dbaccess/source/core/dataaccess/documentevents.cxx
new file mode 100644
index 000000000..571ad2c6f
--- /dev/null
+++ b/dbaccess/source/core/dataaccess/documentevents.cxx
@@ -0,0 +1,216 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <documentevents.hxx>
+
+#include <com/sun/star/beans/PropertyValue.hpp>
+
+#include <o3tl/string_view.hxx>
+#include <osl/diagnose.h>
+#include <comphelper/namedvaluecollection.hxx>
+#include <comphelper/sequence.hxx>
+
+namespace dbaccess
+{
+
+ using ::com::sun::star::uno::Any;
+ using ::com::sun::star::beans::PropertyValue;
+ using ::com::sun::star::container::NoSuchElementException;
+ using ::com::sun::star::lang::IllegalArgumentException;
+ using ::com::sun::star::uno::Sequence;
+ using ::com::sun::star::uno::Type;
+
+ // DocumentEvents_Data
+ struct DocumentEvents_Data
+ {
+ ::cppu::OWeakObject& rParent;
+ ::osl::Mutex& rMutex;
+ DocumentEventsData& rEventsData;
+
+ DocumentEvents_Data( ::cppu::OWeakObject& _rParent, ::osl::Mutex& _rMutex, DocumentEventsData& _rEventsData )
+ :rParent( _rParent )
+ ,rMutex( _rMutex )
+ ,rEventsData( _rEventsData )
+ {
+ }
+ DocumentEvents_Data(const DocumentEvents_Data&) = delete;
+ const DocumentEvents_Data& operator=(const DocumentEvents_Data&) = delete;
+ };
+
+ namespace {
+
+ // helper
+ struct DocumentEventData
+ {
+ const char* pAsciiEventName;
+ bool bNeedsSyncNotify;
+ };
+
+ const DocumentEventData* lcl_getDocumentEventData()
+ {
+ static const DocumentEventData s_aData[] = {
+ { "OnCreate", true },
+ { "OnLoadFinished", true },
+ { "OnNew", false }, // compatibility, see https://bz.apache.org/ooo/show_bug.cgi?id=46484
+ { "OnLoad", false }, // compatibility, see https://bz.apache.org/ooo/show_bug.cgi?id=46484
+ { "OnSaveAs", true },
+ { "OnSaveAsDone", false },
+ { "OnSaveAsFailed", false },
+ { "OnSave", true },
+ { "OnSaveDone", false },
+ { "OnSaveFailed", false },
+ { "OnSaveTo", true },
+ { "OnSaveToDone", false },
+ { "OnSaveToFailed", false },
+ { "OnPrepareUnload", true },
+ { "OnUnload", true },
+ { "OnFocus", false },
+ { "OnUnfocus", false },
+ { "OnModifyChanged", false },
+ { "OnViewCreated", false },
+ { "OnPrepareViewClosing", true },
+ { "OnViewClosed", false },
+ { "OnTitleChanged", false },
+ { "OnSubComponentOpened", false },
+ { "OnSubComponentClosed", false },
+ { nullptr, false }
+ };
+ return s_aData;
+ }
+ }
+
+ // DocumentEvents
+ DocumentEvents::DocumentEvents( ::cppu::OWeakObject& _rParent, ::osl::Mutex& _rMutex, DocumentEventsData& _rEventsData )
+ :m_pData( new DocumentEvents_Data( _rParent, _rMutex, _rEventsData ) )
+ {
+ const DocumentEventData* pEventData = lcl_getDocumentEventData();
+ while ( pEventData->pAsciiEventName )
+ {
+ OUString sEventName = OUString::createFromAscii( pEventData->pAsciiEventName );
+ DocumentEventsData::const_iterator existingPos = m_pData->rEventsData.find( sEventName );
+ if ( existingPos == m_pData->rEventsData.end() )
+ m_pData->rEventsData[ sEventName ] = Sequence< PropertyValue >();
+ ++pEventData;
+ }
+ }
+
+ DocumentEvents::~DocumentEvents()
+ {
+ }
+
+ void SAL_CALL DocumentEvents::acquire() noexcept
+ {
+ m_pData->rParent.acquire();
+ }
+
+ void SAL_CALL DocumentEvents::release() noexcept
+ {
+ m_pData->rParent.release();
+ }
+
+ bool DocumentEvents::needsSynchronousNotification( std::u16string_view _rEventName )
+ {
+ const DocumentEventData* pEventData = lcl_getDocumentEventData();
+ while ( pEventData->pAsciiEventName )
+ {
+ if ( o3tl::equalsAscii( _rEventName, pEventData->pAsciiEventName ) )
+ return pEventData->bNeedsSyncNotify;
+ ++pEventData;
+ }
+
+ // this is an unknown event ... assume async notification
+ return false;
+ }
+
+ void SAL_CALL DocumentEvents::replaceByName( const OUString& Name, const Any& Element )
+ {
+ ::osl::MutexGuard aGuard( m_pData->rMutex );
+
+ DocumentEventsData::iterator elementPos = m_pData->rEventsData.find( Name );
+ if ( elementPos == m_pData->rEventsData.end() )
+ throw NoSuchElementException( Name, *this );
+
+ Sequence< PropertyValue > aEventDescriptor;
+ if ( Element.hasValue() && !( Element >>= aEventDescriptor ) )
+ throw IllegalArgumentException( Element.getValueTypeName(), *this, 2 );
+
+ // Weird enough, the event assignment UI has (well: had) the idea of using an empty "EventType"/"Script"
+ // to indicate the event descriptor should be reset, instead of just passing an empty event descriptor.
+ ::comphelper::NamedValueCollection aCheck( aEventDescriptor );
+ if ( aCheck.has( "EventType" ) )
+ {
+ OUString sEventType = aCheck.getOrDefault( "EventType", OUString() );
+ OSL_ENSURE( !sEventType.isEmpty(), "DocumentEvents::replaceByName: doing a reset via an empty EventType is weird!" );
+ if ( sEventType.isEmpty() )
+ aEventDescriptor.realloc( 0 );
+ }
+ if ( aCheck.has( "Script" ) )
+ {
+ OUString sScript = aCheck.getOrDefault( "Script", OUString() );
+ OSL_ENSURE( !sScript.isEmpty(), "DocumentEvents::replaceByName: doing a reset via an empty Script is weird!" );
+ if ( sScript.isEmpty() )
+ aEventDescriptor.realloc( 0 );
+ }
+
+ elementPos->second = aEventDescriptor;
+ }
+
+ Any SAL_CALL DocumentEvents::getByName( const OUString& Name )
+ {
+ ::osl::MutexGuard aGuard( m_pData->rMutex );
+
+ DocumentEventsData::const_iterator elementPos = m_pData->rEventsData.find( Name );
+ if ( elementPos == m_pData->rEventsData.end() )
+ throw NoSuchElementException( Name, *this );
+
+ Any aReturn;
+ const Sequence< PropertyValue >& rEventDesc( elementPos->second );
+ if ( rEventDesc.hasElements() )
+ aReturn <<= rEventDesc;
+ return aReturn;
+ }
+
+ Sequence< OUString > SAL_CALL DocumentEvents::getElementNames( )
+ {
+ ::osl::MutexGuard aGuard( m_pData->rMutex );
+
+ return comphelper::mapKeysToSequence( m_pData->rEventsData );
+ }
+
+ sal_Bool SAL_CALL DocumentEvents::hasByName( const OUString& Name )
+ {
+ ::osl::MutexGuard aGuard( m_pData->rMutex );
+
+ return m_pData->rEventsData.find( Name ) != m_pData->rEventsData.end();
+ }
+
+ Type SAL_CALL DocumentEvents::getElementType( )
+ {
+ return ::cppu::UnoType< Sequence< PropertyValue > >::get();
+ }
+
+ sal_Bool SAL_CALL DocumentEvents::hasElements( )
+ {
+ ::osl::MutexGuard aGuard( m_pData->rMutex );
+ return !m_pData->rEventsData.empty();
+ }
+
+} // namespace dbaccess
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/dataaccess/intercept.cxx b/dbaccess/source/core/dataaccess/intercept.cxx
new file mode 100644
index 000000000..bef079d47
--- /dev/null
+++ b/dbaccess/source/core/dataaccess/intercept.cxx
@@ -0,0 +1,363 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#include "intercept.hxx"
+
+#include <tools/diagnose_ex.h>
+
+#include <memory>
+
+namespace dbaccess
+{
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::util;
+using namespace ::com::sun::star::ucb;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::frame;
+using namespace ::com::sun::star::io;
+using namespace ::com::sun::star::embed;
+using namespace ::com::sun::star::container;
+using namespace ::comphelper;
+using namespace ::cppu;
+
+#define DISPATCH_SAVEAS 0
+#define DISPATCH_SAVE 1
+#define DISPATCH_CLOSEDOC 2
+#define DISPATCH_CLOSEWIN 3
+#define DISPATCH_CLOSEFRAME 4
+#define DISPATCH_RELOAD 5
+// the OSL_ENSURE in CTOR has to be changed too, when adding new defines
+
+void OInterceptor::dispose()
+{
+ EventObject aEvt( *this );
+
+ osl::MutexGuard aGuard(m_aMutex);
+
+ if ( m_pStatCL )
+ m_pStatCL->disposeAndClear( aEvt );
+
+ m_xSlaveDispatchProvider.clear();
+ m_xMasterDispatchProvider.clear();
+
+ m_pContentHolder = nullptr;
+}
+
+
+OInterceptor::OInterceptor( ODocumentDefinition* _pContentHolder )
+ :m_pContentHolder( _pContentHolder )
+ ,m_aInterceptedURL{ /* DISPATCH_SAVEAS */ ".uno:SaveAs",
+ /* DISPATCH_SAVE */ ".uno:Save",
+ /* DISPATCH_CLOSEDOC */ ".uno:CloseDoc",
+ /* DISPATCH_CLOSEWIN */ ".uno:CloseWin",
+ /* DISPATCH_CLOSEFRAME */ ".uno:CloseFrame",
+ /* DISPATCH_RELOAD */ ".uno:Reload" }
+{
+ OSL_ENSURE(DISPATCH_RELOAD < m_aInterceptedURL.getLength(),"Illegal size.");
+}
+
+
+OInterceptor::~OInterceptor()
+{
+}
+
+namespace {
+
+struct DispatchHelper
+{
+ URL aURL;
+ Sequence<PropertyValue > aArguments;
+};
+
+}
+
+//XDispatch
+void SAL_CALL OInterceptor::dispatch( const URL& URL,const Sequence<PropertyValue >& Arguments )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ if ( !m_pContentHolder )
+ return;
+
+ if ( URL.Complete == m_aInterceptedURL[ DISPATCH_SAVE ] )
+ {
+ m_pContentHolder->save(false, css::uno::Reference<css::awt::XTopWindow>());
+ return;
+ }
+
+ if ( URL.Complete == m_aInterceptedURL[ DISPATCH_RELOAD ] )
+ {
+ ODocumentDefinition::fillReportData(
+ m_pContentHolder->getContext(),
+ m_pContentHolder->getComponent(),
+ m_pContentHolder->getConnection()
+ );
+ return;
+ }
+
+ if( URL.Complete == m_aInterceptedURL[ DISPATCH_SAVEAS ] )
+ {
+ if ( m_pContentHolder->isNewReport() )
+ {
+ m_pContentHolder->saveAs();
+ }
+ else if ( m_xSlaveDispatchProvider.is() )
+ {
+ Sequence< PropertyValue > aNewArgs = Arguments;
+ sal_Int32 nInd = 0;
+
+ while( nInd < aNewArgs.getLength() )
+ {
+ if ( aNewArgs[nInd].Name == "SaveTo" )
+ {
+ aNewArgs.getArray()[nInd].Value <<= true;
+ break;
+ }
+ nInd++;
+ }
+
+ if ( nInd == aNewArgs.getLength() )
+ {
+ aNewArgs.realloc( nInd + 1 );
+ auto pNewArgs = aNewArgs.getArray();
+ pNewArgs[nInd].Name = "SaveTo";
+ pNewArgs[nInd].Value <<= true;
+ }
+
+ Reference< XDispatch > xDispatch = m_xSlaveDispatchProvider->queryDispatch(URL, "_self", 0 );
+ if ( xDispatch.is() )
+ xDispatch->dispatch( URL, aNewArgs );
+ }
+ return;
+ }
+
+ if ( URL.Complete == m_aInterceptedURL[ DISPATCH_CLOSEDOC ]
+ || URL.Complete == m_aInterceptedURL[ DISPATCH_CLOSEWIN ]
+ || URL.Complete == m_aInterceptedURL[ DISPATCH_CLOSEFRAME ]
+ )
+ {
+ DispatchHelper* pHelper = new DispatchHelper;
+ pHelper->aArguments = Arguments;
+ pHelper->aURL = URL;
+ Application::PostUserEvent( LINK( this, OInterceptor, OnDispatch ), pHelper );
+ return;
+ }
+}
+
+IMPL_LINK( OInterceptor, OnDispatch, void*, _pDispatcher, void )
+{
+ std::unique_ptr<DispatchHelper> pHelper( static_cast< DispatchHelper* >( _pDispatcher ) );
+ try
+ {
+ if ( m_pContentHolder && m_pContentHolder->prepareClose() && m_xSlaveDispatchProvider.is() )
+ {
+ Reference< XDispatch > xDispatch = m_xSlaveDispatchProvider->queryDispatch(pHelper->aURL, "_self", 0 );
+ if ( xDispatch.is() )
+ {
+ Reference< XInterface > xKeepContentHolderAlive( *m_pContentHolder );
+ xDispatch->dispatch( pHelper->aURL,pHelper->aArguments);
+ }
+ }
+ }
+ catch ( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+}
+
+void SAL_CALL OInterceptor::addStatusListener(
+ const Reference<
+ XStatusListener >& Control,
+ const URL& URL )
+{
+ if(!Control.is())
+ return;
+
+ if ( m_pContentHolder && URL.Complete == m_aInterceptedURL[DISPATCH_SAVEAS] )
+ { // SaveAs
+
+ if ( !m_pContentHolder->isNewReport() )
+ {
+ FeatureStateEvent aStateEvent;
+ aStateEvent.FeatureURL.Complete = m_aInterceptedURL[DISPATCH_SAVEAS];
+ aStateEvent.FeatureDescriptor = "SaveCopyTo";
+ aStateEvent.IsEnabled = true;
+ aStateEvent.Requery = false;
+ aStateEvent.State <<= OUString("($3)");
+ Control->statusChanged(aStateEvent);
+ }
+
+ {
+ osl::MutexGuard aGuard(m_aMutex);
+ if(!m_pStatCL)
+ m_pStatCL.reset( new StatusListenerContainer(m_aMutex) );
+ }
+
+ m_pStatCL->addInterface(URL.Complete,Control);
+ }
+ else if ( m_pContentHolder && URL.Complete == m_aInterceptedURL[DISPATCH_SAVE] )
+ { // Save
+ FeatureStateEvent aStateEvent;
+ aStateEvent.FeatureURL.Complete = m_aInterceptedURL[DISPATCH_SAVE];
+ aStateEvent.FeatureDescriptor = "Update";
+ aStateEvent.IsEnabled = true;
+ aStateEvent.Requery = false;
+
+ Control->statusChanged(aStateEvent);
+ {
+ osl::MutexGuard aGuard(m_aMutex);
+ if(!m_pStatCL)
+ m_pStatCL.reset( new StatusListenerContainer(m_aMutex) );
+ }
+
+ m_pStatCL->addInterface(URL.Complete,Control);
+ }
+ else
+ {
+ sal_Int32 i = 2;
+ if(URL.Complete == m_aInterceptedURL[i] ||
+ URL.Complete == m_aInterceptedURL[++i] ||
+ URL.Complete == m_aInterceptedURL[++i] ||
+ URL.Complete == m_aInterceptedURL[i = DISPATCH_RELOAD] )
+ { // Close and return
+ FeatureStateEvent aStateEvent;
+ aStateEvent.FeatureURL.Complete = m_aInterceptedURL[i];
+ aStateEvent.FeatureDescriptor = "Close and Return";
+ aStateEvent.IsEnabled = true;
+ aStateEvent.Requery = false;
+ Control->statusChanged(aStateEvent);
+
+
+ {
+ osl::MutexGuard aGuard(m_aMutex);
+ if(!m_pStatCL)
+ m_pStatCL.reset( new StatusListenerContainer(m_aMutex) );
+ }
+
+ m_pStatCL->addInterface(URL.Complete,Control);
+ return;
+ }
+ }
+}
+
+
+void SAL_CALL OInterceptor::removeStatusListener(
+ const Reference<
+ XStatusListener >& Control,
+ const URL& URL )
+{
+ if(!(Control.is() && m_pStatCL))
+ return;
+ else
+ {
+ m_pStatCL->removeInterface(URL.Complete,Control);
+ return;
+ }
+}
+
+
+//XInterceptorInfo
+Sequence< OUString > SAL_CALL OInterceptor::getInterceptedURLs( )
+{
+ // now implemented as update
+ return m_aInterceptedURL;
+}
+
+
+// XDispatchProvider
+
+Reference< XDispatch > SAL_CALL OInterceptor::queryDispatch( const URL& URL,const OUString& TargetFrameName,sal_Int32 SearchFlags )
+{
+ osl::MutexGuard aGuard(m_aMutex);
+ const OUString* pIter = m_aInterceptedURL.getConstArray();
+ const OUString* pEnd = pIter + m_aInterceptedURL.getLength();
+ for(;pIter != pEnd;++pIter)
+ {
+ if ( URL.Complete == *pIter )
+ return static_cast<XDispatch*>(this);
+ }
+
+ if(m_xSlaveDispatchProvider.is())
+ return m_xSlaveDispatchProvider->queryDispatch(URL,TargetFrameName,SearchFlags);
+ else
+ return Reference<XDispatch>();
+}
+
+Sequence< Reference< XDispatch > > SAL_CALL OInterceptor::queryDispatches( const Sequence<DispatchDescriptor >& Requests )
+{
+ osl::MutexGuard aGuard(m_aMutex);
+ typedef Sequence<Reference<XDispatch>> DispatchSeq;
+ DispatchSeq aRet = m_xSlaveDispatchProvider.is() ?
+ m_xSlaveDispatchProvider->queryDispatches(Requests) :
+ DispatchSeq(Requests.getLength());
+
+ auto aRetRange = asNonConstRange(aRet);
+ for(sal_Int32 i = 0; i < Requests.getLength(); ++i)
+ {
+ const OUString* pIter = m_aInterceptedURL.getConstArray();
+ const OUString* pEnd = pIter + m_aInterceptedURL.getLength();
+ for(;pIter != pEnd;++pIter)
+ {
+ if ( Requests[i].FeatureURL.Complete == *pIter )
+ {
+ aRetRange[i] = static_cast<XDispatch*>(this);
+ break;
+ }
+ }
+ }
+
+ return aRet;
+}
+
+
+//XDispatchProviderInterceptor
+
+Reference< XDispatchProvider > SAL_CALL OInterceptor::getSlaveDispatchProvider( )
+{
+ osl::MutexGuard aGuard(m_aMutex);
+ return m_xSlaveDispatchProvider;
+}
+
+void SAL_CALL
+OInterceptor::setSlaveDispatchProvider( const Reference< XDispatchProvider >& NewDispatchProvider )
+{
+ osl::MutexGuard aGuard(m_aMutex);
+ m_xSlaveDispatchProvider = NewDispatchProvider;
+}
+
+
+Reference< XDispatchProvider > SAL_CALL OInterceptor::getMasterDispatchProvider( )
+{
+ osl::MutexGuard aGuard(m_aMutex);
+ return m_xMasterDispatchProvider;
+}
+
+
+void SAL_CALL OInterceptor::setMasterDispatchProvider(
+ const Reference< XDispatchProvider >& NewSupplier )
+{
+ osl::MutexGuard aGuard(m_aMutex);
+ m_xMasterDispatchProvider = NewSupplier;
+}
+
+} // namespace dbaccess
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/dataaccess/intercept.hxx b/dbaccess/source/core/dataaccess/intercept.hxx
new file mode 100644
index 000000000..7ce53752f
--- /dev/null
+++ b/dbaccess/source/core/dataaccess/intercept.hxx
@@ -0,0 +1,113 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <osl/mutex.hxx>
+#include <cppuhelper/implbase.hxx>
+#include <cppuhelper/interfacecontainer.hxx>
+#include <com/sun/star/frame/XDispatchProviderInterceptor.hpp>
+#include <com/sun/star/frame/XInterceptorInfo.hpp>
+#include <com/sun/star/frame/XDispatch.hpp>
+#include "documentdefinition.hxx"
+#include <vcl/svapp.hxx>
+
+namespace dbaccess
+{
+
+
+class OInterceptor : public ::cppu::WeakImplHelper< css::frame::XDispatchProviderInterceptor,
+ css::frame::XInterceptorInfo,
+ css::frame::XDispatch >
+{
+ DECL_LINK( OnDispatch, void*, void );
+protected:
+ virtual ~OInterceptor() override;
+public:
+
+ explicit OInterceptor( ODocumentDefinition* _pContentHolder );
+
+ /// @throws css::uno::RuntimeException
+ void dispose();
+
+ //XDispatch
+ virtual void SAL_CALL
+ dispatch(
+ const css::util::URL& URL,
+ const css::uno::Sequence< css::beans::PropertyValue >& Arguments ) override;
+
+ virtual void SAL_CALL
+ addStatusListener(
+ const css::uno::Reference< css::frame::XStatusListener >& Control,
+ const css::util::URL& URL ) override;
+
+ virtual void SAL_CALL
+ removeStatusListener(
+ const css::uno::Reference< css::frame::XStatusListener >& Control,
+ const css::util::URL& URL ) override;
+
+ //XInterceptorInfo
+ virtual css::uno::Sequence< OUString >
+ SAL_CALL getInterceptedURLs( ) override;
+
+ //XDispatchProvider ( inherited by XDispatchProviderInterceptor )
+ virtual css::uno::Reference< css::frame::XDispatch > SAL_CALL
+ queryDispatch(
+ const css::util::URL& URL,
+ const OUString& TargetFrameName,
+ sal_Int32 SearchFlags ) override;
+
+ virtual css::uno::Sequence< css::uno::Reference< css::frame::XDispatch > > SAL_CALL
+ queryDispatches(
+ const css::uno::Sequence< css::frame::DispatchDescriptor >& Requests ) override;
+
+ //XDispatchProviderInterceptor
+ virtual css::uno::Reference< css::frame::XDispatchProvider > SAL_CALL
+ getSlaveDispatchProvider( ) override;
+
+ virtual void SAL_CALL
+ setSlaveDispatchProvider(
+ const css::uno::Reference< css::frame::XDispatchProvider >& NewDispatchProvider ) override;
+
+ virtual css::uno::Reference< css::frame::XDispatchProvider > SAL_CALL
+ getMasterDispatchProvider( ) override;
+
+ virtual void SAL_CALL
+ setMasterDispatchProvider(
+ const css::uno::Reference< css::frame::XDispatchProvider >& NewSupplier ) override;
+
+private:
+
+ osl::Mutex m_aMutex;
+
+ ODocumentDefinition* m_pContentHolder;
+
+ css::uno::Reference< css::frame::XDispatchProvider > m_xSlaveDispatchProvider;
+ css::uno::Reference< css::frame::XDispatchProvider > m_xMasterDispatchProvider;
+
+ css::uno::Sequence< OUString > m_aInterceptedURL;
+
+ typedef comphelper::OMultiTypeInterfaceContainerHelperVar3<css::frame::XStatusListener, OUString>
+ StatusListenerContainer;
+ std::unique_ptr<StatusListenerContainer> m_pStatCL;
+};
+
+} // namespace dbaccess
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/dataaccess/myucp_datasupplier.cxx b/dbaccess/source/core/dataaccess/myucp_datasupplier.cxx
new file mode 100644
index 000000000..e0d32d569
--- /dev/null
+++ b/dbaccess/source/core/dataaccess/myucp_datasupplier.cxx
@@ -0,0 +1,330 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <vector>
+
+#include <ucbhelper/contentidentifier.hxx>
+
+#include "myucp_datasupplier.hxx"
+#include <ContentHelper.hxx>
+#include <com/sun/star/ucb/IllegalIdentifierException.hpp>
+
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::ucb;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::io;
+using namespace ::com::sun::star::container;
+
+// @@@ Adjust namespace name.
+using namespace dbaccess;
+
+// @@@ Adjust namespace name.
+namespace dbaccess
+{
+
+namespace {
+
+// struct ResultListEntry.
+struct ResultListEntry
+{
+ OUString aId;
+ Reference< XContentIdentifier > xId;
+ ::rtl::Reference< OContentHelper > xContent;
+ Reference< XRow > xRow;
+ const ContentProperties& rData;
+
+ explicit ResultListEntry(const ContentProperties& rEntry) : rData( rEntry ) {}
+};
+
+}
+
+// struct DataSupplier_Impl.
+struct DataSupplier_Impl
+{
+ osl::Mutex m_aMutex;
+ std::vector< std::unique_ptr<ResultListEntry> > m_aResults;
+ rtl::Reference< ODocumentContainer > m_xContent;
+ bool m_bCountFinal;
+
+ explicit DataSupplier_Impl(const rtl::Reference< ODocumentContainer >& rContent)
+ : m_xContent(rContent)
+ , m_bCountFinal(false)
+ {
+ }
+};
+
+}
+
+// DataSupplier Implementation.
+
+DataSupplier::DataSupplier( const rtl::Reference< ODocumentContainer >& rContent )
+: m_pImpl( new DataSupplier_Impl( rContent ) )
+{
+
+}
+
+DataSupplier::~DataSupplier()
+{
+
+}
+
+OUString DataSupplier::queryContentIdentifierString( sal_uInt32 nIndex )
+{
+ osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
+
+ if ( static_cast<size_t>(nIndex) < m_pImpl->m_aResults.size() )
+ {
+ OUString aId = m_pImpl->m_aResults[ nIndex ]->aId;
+ if ( !aId.isEmpty() )
+ {
+ // Already cached.
+ return aId;
+ }
+ }
+
+ if ( getResult( nIndex ) )
+ {
+ OUString aId = m_pImpl->m_xContent->getIdentifier()->getContentIdentifier();
+
+ if ( !aId.isEmpty() )
+ aId += "/";
+
+ aId += m_pImpl->m_aResults[ nIndex ]->rData.aTitle;
+
+ m_pImpl->m_aResults[ nIndex ]->aId = aId;
+ return aId;
+ }
+ return OUString();
+}
+
+Reference< XContentIdentifier >
+DataSupplier::queryContentIdentifier( sal_uInt32 nIndex )
+{
+ osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
+
+ if ( static_cast<size_t>(nIndex) < m_pImpl->m_aResults.size() )
+ {
+ Reference< XContentIdentifier > xId = m_pImpl->m_aResults[ nIndex ]->xId;
+ if ( xId.is() )
+ {
+ // Already cached.
+ return xId;
+ }
+ }
+
+ OUString aId = queryContentIdentifierString( nIndex );
+ if ( !aId.isEmpty() )
+ {
+ Reference< XContentIdentifier > xId = new ::ucbhelper::ContentIdentifier( aId );
+ m_pImpl->m_aResults[ nIndex ]->xId = xId;
+ return xId;
+ }
+ return Reference< XContentIdentifier >();
+}
+
+Reference< XContent >
+DataSupplier::queryContent( sal_uInt32 _nIndex )
+{
+ osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
+
+ if ( static_cast<size_t>(_nIndex) < m_pImpl->m_aResults.size() )
+ {
+ Reference< XContent > xContent = m_pImpl->m_aResults[ _nIndex ]->xContent;
+ if ( xContent.is() )
+ {
+ // Already cached.
+ return xContent;
+ }
+ }
+
+ Reference< XContentIdentifier > xId = queryContentIdentifier( _nIndex );
+ if ( xId.is() )
+ {
+ try
+ {
+ Reference< XContent > xContent;
+ OUString sName = xId->getContentIdentifier();
+ sName = sName.copy(sName.lastIndexOf('/')+1);
+
+ m_pImpl->m_aResults[ _nIndex ]->xContent = m_pImpl->m_xContent->getContent(sName);
+
+ xContent = m_pImpl->m_aResults[ _nIndex ]->xContent.get();
+ return xContent;
+
+ }
+ catch ( IllegalIdentifierException& )
+ {
+ }
+ }
+ return Reference< XContent >();
+}
+
+bool DataSupplier::getResult( sal_uInt32 nIndex )
+{
+ osl::ClearableGuard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
+
+ if ( static_cast<size_t>(nIndex) < m_pImpl->m_aResults.size() )
+ {
+ // Result already present.
+ return true;
+ }
+
+ // Result not (yet) present.
+
+ if ( m_pImpl->m_bCountFinal )
+ return false;
+
+ // Try to obtain result...
+
+ sal_uInt32 nOldCount = m_pImpl->m_aResults.size();
+ bool bFound = false;
+ sal_uInt32 nPos = nOldCount;
+
+ // @@@ Obtain data and put it into result list...
+ Sequence< OUString> aSeq = m_pImpl->m_xContent->getElementNames();
+ if ( nIndex < sal::static_int_cast< sal_uInt32 >( aSeq.getLength() ) )
+ {
+ const OUString* pIter = aSeq.getConstArray();
+ const OUString* pEnd = pIter + aSeq.getLength();
+ for(pIter = pIter + nPos;pIter != pEnd;++pIter,++nPos)
+ {
+ m_pImpl->m_aResults.emplace_back(
+ new ResultListEntry( m_pImpl->m_xContent->getContent(*pIter)->getContentProperties() ) );
+
+ if ( nPos == nIndex )
+ {
+ // Result obtained.
+ bFound = true;
+ break;
+ }
+ }
+ }
+
+ if ( !bFound )
+ m_pImpl->m_bCountFinal = true;
+
+ rtl::Reference< ::ucbhelper::ResultSet > xResultSet = getResultSet();
+ if ( xResultSet.is() )
+ {
+ // Callbacks follow!
+ aGuard.clear();
+
+ if ( static_cast<size_t>(nOldCount) < m_pImpl->m_aResults.size() )
+ xResultSet->rowCountChanged(
+ nOldCount, m_pImpl->m_aResults.size() );
+
+ if ( m_pImpl->m_bCountFinal )
+ xResultSet->rowCountFinal();
+ }
+
+ return bFound;
+}
+
+sal_uInt32 DataSupplier::totalCount()
+{
+ osl::ClearableGuard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
+
+ if ( m_pImpl->m_bCountFinal )
+ return m_pImpl->m_aResults.size();
+
+ sal_uInt32 nOldCount = m_pImpl->m_aResults.size();
+
+ // @@@ Obtain data and put it into result list...
+ Sequence< OUString> aSeq = m_pImpl->m_xContent->getElementNames();
+ const OUString* pIter = aSeq.getConstArray();
+ const OUString* pEnd = pIter + aSeq.getLength();
+ for(;pIter != pEnd;++pIter)
+ m_pImpl->m_aResults.emplace_back(
+ new ResultListEntry( m_pImpl->m_xContent->getContent(*pIter)->getContentProperties() ) );
+
+ m_pImpl->m_bCountFinal = true;
+
+ rtl::Reference< ::ucbhelper::ResultSet > xResultSet = getResultSet();
+ if ( xResultSet.is() )
+ {
+ // Callbacks follow!
+ aGuard.clear();
+
+ if ( static_cast<size_t>(nOldCount) < m_pImpl->m_aResults.size() )
+ xResultSet->rowCountChanged(
+ nOldCount, m_pImpl->m_aResults.size() );
+
+ xResultSet->rowCountFinal();
+ }
+
+ return m_pImpl->m_aResults.size();
+}
+
+sal_uInt32 DataSupplier::currentCount()
+{
+ return m_pImpl->m_aResults.size();
+}
+
+bool DataSupplier::isCountFinal()
+{
+ return m_pImpl->m_bCountFinal;
+}
+
+Reference< XRow >
+DataSupplier::queryPropertyValues( sal_uInt32 nIndex )
+{
+ osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
+
+ if ( static_cast<size_t>(nIndex) < m_pImpl->m_aResults.size() )
+ {
+ Reference< XRow > xRow = m_pImpl->m_aResults[ nIndex ]->xRow;
+ if ( xRow.is() )
+ {
+ // Already cached.
+ return xRow;
+ }
+ }
+
+ if ( getResult( nIndex ) )
+ {
+ if ( !m_pImpl->m_aResults[ nIndex ]->xContent.is() )
+ queryContent(nIndex);
+
+ Reference< XRow > xRow = m_pImpl->m_aResults[ nIndex ]->xContent->getPropertyValues(getResultSet()->getProperties());
+ m_pImpl->m_aResults[ nIndex ]->xRow = xRow;
+ return xRow;
+ }
+
+ return Reference< XRow >();
+}
+
+void DataSupplier::releasePropertyValues( sal_uInt32 nIndex )
+{
+ osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
+
+ if ( static_cast<size_t>(nIndex) < m_pImpl->m_aResults.size() )
+ m_pImpl->m_aResults[ nIndex ]->xRow.clear();
+}
+
+void DataSupplier::close()
+{
+}
+
+void DataSupplier::validate()
+{
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/dataaccess/myucp_datasupplier.hxx b/dbaccess/source/core/dataaccess/myucp_datasupplier.hxx
new file mode 100644
index 000000000..8083f5ef5
--- /dev/null
+++ b/dbaccess/source/core/dataaccess/myucp_datasupplier.hxx
@@ -0,0 +1,59 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <rtl/ref.hxx>
+#include <ucbhelper/resultset.hxx>
+#include "documentcontainer.hxx"
+#include <memory>
+
+namespace dbaccess
+{
+struct DataSupplier_Impl;
+
+class DataSupplier : public ucbhelper::ResultSetDataSupplier
+{
+ std::unique_ptr<DataSupplier_Impl> m_pImpl;
+
+public:
+ explicit DataSupplier(const rtl::Reference<ODocumentContainer>& rxContent);
+ virtual ~DataSupplier() override;
+
+ virtual OUString queryContentIdentifierString(sal_uInt32 nIndex) override;
+ virtual css::uno::Reference<css::ucb::XContentIdentifier>
+ queryContentIdentifier(sal_uInt32 nIndex) override;
+ virtual css::uno::Reference<css::ucb::XContent> queryContent(sal_uInt32 nIndex) override;
+
+ virtual bool getResult(sal_uInt32 nIndex) override;
+
+ virtual sal_uInt32 totalCount() override;
+ virtual sal_uInt32 currentCount() override;
+ virtual bool isCountFinal() override;
+
+ virtual css::uno::Reference<css::sdbc::XRow> queryPropertyValues(sal_uInt32 nIndex) override;
+ virtual void releasePropertyValues(sal_uInt32 nIndex) override;
+
+ virtual void close() override;
+
+ virtual void validate() override;
+};
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/dataaccess/myucp_resultset.cxx b/dbaccess/source/core/dataaccess/myucp_resultset.cxx
new file mode 100644
index 000000000..67c1ad7c8
--- /dev/null
+++ b/dbaccess/source/core/dataaccess/myucp_resultset.cxx
@@ -0,0 +1,74 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+/**************************************************************************
+ TODO
+ **************************************************************************
+
+ - This implementation is not a dynamic result set!!! It only implements
+ the necessary interfaces, but never recognizes/notifies changes!!!
+
+ *************************************************************************/
+
+#include "myucp_datasupplier.hxx"
+#include "myucp_resultset.hxx"
+
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::ucb;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::io;
+using namespace ::com::sun::star::container;
+
+using namespace dbaccess;
+
+// DynamicResultSet Implementation.
+DynamicResultSet::DynamicResultSet(
+ const Reference< XComponentContext >& rxContext,
+ const rtl::Reference< ODocumentContainer >& rxContent,
+ const OpenCommandArgument2& rCommand,
+ const Reference< XCommandEnvironment >& rxEnv )
+ :ResultSetImplHelper( rxContext, rCommand )
+ ,m_xContent(rxContent)
+ ,m_xEnv( rxEnv )
+{
+}
+
+// Non-interface methods.
+void DynamicResultSet::initStatic()
+{
+ m_xResultSet1
+ = new ::ucbhelper::ResultSet( m_xContext,
+ m_aCommand.Properties,
+ new DataSupplier( m_xContent ),
+ m_xEnv );
+}
+
+void DynamicResultSet::initDynamic()
+{
+ m_xResultSet1
+ = new ::ucbhelper::ResultSet( m_xContext,
+ m_aCommand.Properties,
+ new DataSupplier( m_xContent ),
+ m_xEnv );
+ m_xResultSet2 = m_xResultSet1;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/dataaccess/myucp_resultset.hxx b/dbaccess/source/core/dataaccess/myucp_resultset.hxx
new file mode 100644
index 000000000..ae269ffb8
--- /dev/null
+++ b/dbaccess/source/core/dataaccess/myucp_resultset.hxx
@@ -0,0 +1,49 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <rtl/ref.hxx>
+#include <ucbhelper/resultsethelper.hxx>
+#include "documentcontainer.hxx"
+
+
+// @@@ Adjust namespace name.
+namespace dbaccess {
+
+class DynamicResultSet : public ::ucbhelper::ResultSetImplHelper
+{
+ rtl::Reference< ODocumentContainer > m_xContent;
+ css::uno::Reference< css::ucb::XCommandEnvironment > m_xEnv;
+
+private:
+ virtual void initStatic() override;
+ virtual void initDynamic() override;
+
+public:
+ DynamicResultSet(
+ const css::uno::Reference< css::uno::XComponentContext >& rxContext,
+ const rtl::Reference< ODocumentContainer >& rxContent,
+ const css::ucb::OpenCommandArgument2& rCommand,
+ const css::uno::Reference< css::ucb::XCommandEnvironment >& rxEnv );
+};
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/inc/ContainerMediator.hxx b/dbaccess/source/core/inc/ContainerMediator.hxx
new file mode 100644
index 000000000..37bfc0eba
--- /dev/null
+++ b/dbaccess/source/core/inc/ContainerMediator.hxx
@@ -0,0 +1,79 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <com/sun/star/container/XContainerListener.hpp>
+#include <com/sun/star/container/XContainer.hpp>
+#include <com/sun/star/container/XNameAccess.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+
+#include <cppuhelper/basemutex.hxx>
+#include <cppuhelper/implbase.hxx>
+#include <rtl/ref.hxx>
+
+#include <map>
+
+namespace dbaccess
+{
+
+ class OPropertyForward;
+
+ class OContainerMediator : public ::cppu::BaseMutex
+ ,public ::cppu::WeakImplHelper< css::container::XContainerListener >
+ {
+ private:
+ typedef std::map< OUString, ::rtl::Reference< OPropertyForward > > PropertyForwardList;
+ PropertyForwardList m_aForwardList;
+ css::uno::Reference< css::container::XNameAccess > m_xSettings; // can not be weak
+ css::uno::Reference< css::container::XContainer > m_xContainer; // can not be weak
+
+ protected:
+ virtual ~OContainerMediator() override;
+
+ public:
+ OContainerMediator(
+ const css::uno::Reference< css::container::XContainer >& _xContainer,
+ const css::uno::Reference< css::container::XNameAccess >& _xSettings
+ );
+
+ virtual void SAL_CALL elementInserted( const css::container::ContainerEvent& _rEvent ) override;
+ virtual void SAL_CALL elementRemoved( const css::container::ContainerEvent& _rEvent ) override;
+ virtual void SAL_CALL elementReplaced( const css::container::ContainerEvent& _rEvent ) override;
+ virtual void SAL_CALL disposing( const css::lang::EventObject& Source ) override;
+
+ void notifyElementCreated(const OUString& _sElementName
+ ,const css::uno::Reference< css::beans::XPropertySet>& _xElement);
+
+ private:
+ /** cleans up the instance, by deregistering as listener at the containers,
+ and resetting them to <NULL/>
+ */
+ void impl_cleanup_nothrow();
+
+ /** initializes the properties of the given object from its counterpart in our settings container
+ */
+ void impl_initSettings_nothrow(
+ const OUString& _rName,
+ const css::uno::Reference< css::beans::XPropertySet >& _rxDestination
+ );
+ };
+
+} // namespace dbaccess
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/inc/ContentHelper.hxx b/dbaccess/source/core/inc/ContentHelper.hxx
new file mode 100644
index 000000000..004b785ef
--- /dev/null
+++ b/dbaccess/source/core/inc/ContentHelper.hxx
@@ -0,0 +1,183 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <com/sun/star/ucb/XContent.hpp>
+#include <com/sun/star/ucb/XCommandProcessor.hpp>
+#include <com/sun/star/beans/XPropertiesChangeNotifier.hpp>
+#include <com/sun/star/beans/XPropertyContainer.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/lang/XInitialization.hpp>
+#include <com/sun/star/sdbc/XRow.hpp>
+#include <com/sun/star/lang/XUnoTunnel.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <cppuhelper/compbase.hxx>
+#include <cppuhelper/basemutex.hxx>
+#include <comphelper/interfacecontainer3.hxx>
+#include <comphelper/multiinterfacecontainer3.hxx>
+#include <com/sun/star/beans/Property.hpp>
+#include <com/sun/star/container/XChild.hpp>
+#include <com/sun/star/sdbcx/XRename.hpp>
+#include <connectivity/sqlerror.hxx>
+#include <memory>
+
+namespace com::sun::star::beans { struct PropertyValue; }
+
+namespace dbaccess
+{
+ class ODatabaseModelImpl;
+ struct ContentProperties
+ {
+ OUString aTitle; // Title
+ ::std::optional< OUString >
+ aContentType; // ContentType (aka MediaType aka MimeType)
+ bool bIsDocument; // IsDocument
+ bool bIsFolder; // IsFolder
+ bool bAsTemplate; // AsTemplate
+ OUString sPersistentName;// persistent name of the document
+
+ ContentProperties()
+ :bIsDocument( true )
+ ,bIsFolder( false )
+ ,bAsTemplate( false )
+ {
+ }
+ };
+
+ class OContentHelper_Impl
+ {
+ public:
+ OContentHelper_Impl();
+ virtual ~OContentHelper_Impl();
+
+ ContentProperties m_aProps;
+ ODatabaseModelImpl* m_pDataSource; // this will stay alive as long as the content exists
+ };
+
+ typedef std::shared_ptr<OContentHelper_Impl> TContentPtr;
+
+ typedef comphelper::OMultiTypeInterfaceContainerHelperVar3<css::beans::XPropertiesChangeListener, OUString>
+ PropertyChangeListenerContainer;
+ typedef ::cppu::WeakComponentImplHelper< css::ucb::XContent
+ , css::ucb::XCommandProcessor
+ , css::lang::XServiceInfo
+ , css::beans::XPropertiesChangeNotifier
+ , css::beans::XPropertyContainer
+ , css::lang::XInitialization
+ , css::lang::XUnoTunnel
+ , css::container::XChild
+ , css::sdbcx::XRename
+ > OContentHelper_COMPBASE;
+
+ class OContentHelper : public ::cppu::BaseMutex
+ ,public OContentHelper_COMPBASE
+ {
+ css::uno::Sequence< css::uno::Any >
+ setPropertyValues( const css::uno::Sequence< css::beans::PropertyValue >& rValues );
+
+ void impl_rename_throw(const OUString& _sNewName,bool _bNotify = true);
+
+ protected:
+ ::comphelper::OInterfaceContainerHelper3<css::ucb::XContentEventListener> m_aContentListeners;
+ PropertyChangeListenerContainer m_aPropertyChangeListeners;
+ css::uno::Reference< css::uno::XInterface >
+ m_xParentContainer;
+ const css::uno::Reference< css::uno::XComponentContext >
+ m_aContext;
+ const ::connectivity::SQLError m_aErrorHelper;
+ TContentPtr m_pImpl;
+ sal_uInt32 m_nCommandId;
+
+ // helper
+ virtual void SAL_CALL disposing() override;
+
+ void notifyDataSourceModified();
+
+ /**
+ * This method can be used to propagate changes of property values.
+ *
+ * @param evt is a sequence of property change events.
+ */
+ void notifyPropertiesChange( const css::uno::Sequence< css::beans::PropertyChangeEvent >& evt ) const;
+
+ OUString impl_getHierarchicalName( bool _includingRootContainer ) const;
+
+ public:
+
+ OContentHelper( const css::uno::Reference< css::uno::XComponentContext >& _xORB
+ ,const css::uno::Reference< css::uno::XInterface >& _xParentContainer
+ ,const TContentPtr& _pImpl
+ );
+
+ // css::lang::XTypeProvider
+ virtual css::uno::Sequence<sal_Int8> SAL_CALL getImplementationId( ) override;
+
+ // css::lang::XServiceInfo
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override;
+ virtual OUString SAL_CALL getImplementationName( ) override;
+
+ // XContent
+ virtual css::uno::Reference< css::ucb::XContentIdentifier > SAL_CALL getIdentifier( ) override ;
+ virtual OUString SAL_CALL getContentType( ) override ;
+ virtual void SAL_CALL addContentEventListener( const css::uno::Reference< css::ucb::XContentEventListener >& Listener ) override ;
+ virtual void SAL_CALL removeContentEventListener( const css::uno::Reference< css::ucb::XContentEventListener >& Listener ) override ;
+
+ // XCommandProcessor
+ virtual sal_Int32 SAL_CALL createCommandIdentifier( ) override ;
+ virtual css::uno::Any SAL_CALL execute( const css::ucb::Command& aCommand, sal_Int32 CommandId, const css::uno::Reference< css::ucb::XCommandEnvironment >& Environment ) override ;
+ virtual void SAL_CALL abort( sal_Int32 CommandId ) override ;
+
+ // XPropertiesChangeNotifier
+ virtual void SAL_CALL addPropertiesChangeListener( const css::uno::Sequence< OUString >& PropertyNames, const css::uno::Reference< css::beans::XPropertiesChangeListener >& Listener ) override ;
+ virtual void SAL_CALL removePropertiesChangeListener( const css::uno::Sequence< OUString >& PropertyNames, const css::uno::Reference< css::beans::XPropertiesChangeListener >& Listener ) override ;
+
+ // XPropertyContainer
+ virtual void SAL_CALL addProperty( const OUString& Name, sal_Int16 Attributes, const css::uno::Any& DefaultValue ) override ;
+ virtual void SAL_CALL removeProperty( const OUString& Name ) override ;
+
+ // XInitialization
+ virtual void SAL_CALL initialize( const css::uno::Sequence< css::uno::Any >& aArguments ) override;
+
+ // css::lang::XUnoTunnel
+ virtual sal_Int64 SAL_CALL getSomething( const css::uno::Sequence< sal_Int8 >& aIdentifier ) override;
+ static const css::uno::Sequence< sal_Int8 > & getUnoTunnelId();
+
+ // css::container::XChild
+ virtual css::uno::Reference< css::uno::XInterface > SAL_CALL getParent( ) override;
+ virtual void SAL_CALL setParent( const css::uno::Reference< css::uno::XInterface >& Parent ) override;
+
+ // XRename
+ virtual void SAL_CALL rename( const OUString& newName ) override;
+
+ const ContentProperties& getContentProperties() const { return m_pImpl->m_aProps; }
+ css::uno::Reference< css::sdbc::XRow >
+ getPropertyValues( const css::uno::Sequence< css::beans::Property >& rProperties );
+
+ const css::uno::Reference< css::uno::XComponentContext >& getContext() const { return m_aContext; }
+
+ const TContentPtr& getImpl() const { return m_pImpl; }
+
+ protected:
+ virtual OUString determineContentType() const = 0;
+ };
+
+} // namespace dbaccess
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/inc/DatabaseDataProvider.hxx b/dbaccess/source/core/inc/DatabaseDataProvider.hxx
new file mode 100644
index 000000000..8c2029634
--- /dev/null
+++ b/dbaccess/source/core/inc/DatabaseDataProvider.hxx
@@ -0,0 +1,262 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <sal/config.h>
+
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/chart2/data/XDatabaseDataProvider.hpp>
+#include <com/sun/star/chart2/XInternalDataProvider.hpp>
+#include <com/sun/star/chart/XComplexDescriptionAccess.hpp>
+#include <com/sun/star/sdbc/XRowSet.hpp>
+#include <com/sun/star/container/XChild.hpp>
+
+#include <cppuhelper/compbase.hxx>
+#include <cppuhelper/basemutex.hxx>
+#include <cppuhelper/propertysetmixin.hxx>
+
+#include <connectivity/parameters.hxx>
+#include <connectivity/filtermanager.hxx>
+
+
+namespace dbaccess
+{
+
+typedef ::cppu::WeakComponentImplHelper< css::chart2::data::XDatabaseDataProvider
+ , css::container::XChild
+ , css::chart::XComplexDescriptionAccess
+ , css::lang::XServiceInfo > TDatabaseDataProvider;
+
+class DatabaseDataProvider: private ::cppu::BaseMutex,
+ public TDatabaseDataProvider,
+ public ::cppu::PropertySetMixin< css::chart2::data::XDatabaseDataProvider >
+{
+public:
+ explicit DatabaseDataProvider(css::uno::Reference< css::uno::XComponentContext > const & context);
+
+private:
+ // css::uno::XInterface:
+ virtual css::uno::Any SAL_CALL queryInterface(css::uno::Type const & type) override;
+ virtual void SAL_CALL acquire() noexcept override
+ { TDatabaseDataProvider::acquire(); }
+ virtual void SAL_CALL release() noexcept override
+ { TDatabaseDataProvider::release(); }
+
+ // css::lang::XServiceInfo
+ virtual OUString SAL_CALL getImplementationName( ) override;
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override;
+
+ // css::chart2::data::XDataProvider:
+ virtual sal_Bool SAL_CALL createDataSourcePossible(const css::uno::Sequence< css::beans::PropertyValue > & aArguments) override;
+ virtual css::uno::Reference< css::chart2::data::XDataSource > SAL_CALL createDataSource(const css::uno::Sequence< css::beans::PropertyValue > & aArguments) override;
+ virtual css::uno::Sequence< css::beans::PropertyValue > SAL_CALL detectArguments(const css::uno::Reference< css::chart2::data::XDataSource > & xDataSource) override;
+ virtual sal_Bool SAL_CALL createDataSequenceByRangeRepresentationPossible(const OUString & aRangeRepresentation) override;
+ virtual css::uno::Reference< css::chart2::data::XDataSequence > SAL_CALL createDataSequenceByRangeRepresentation(const OUString & aRangeRepresentation) override;
+
+ virtual css::uno::Reference<css::chart2::data::XDataSequence> SAL_CALL
+ createDataSequenceByValueArray(
+ const OUString& aRole, const OUString & aRangeRepresentation, const OUString& aRoleQualifier) override;
+
+ virtual css::uno::Reference< css::sheet::XRangeSelection > SAL_CALL getRangeSelection() override;
+
+ // css::chart2::data::XRangeXMLConversion:
+ virtual OUString SAL_CALL convertRangeToXML(const OUString & aRangeRepresentation) override;
+ virtual OUString SAL_CALL convertRangeFromXML(const OUString & aXMLRange) override;
+
+ // css::lang::XInitialization:
+ virtual void SAL_CALL initialize(const css::uno::Sequence< css::uno::Any > & aArguments) override;
+
+ // css::beans::XPropertySet:
+ virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo() override;
+ virtual void SAL_CALL setPropertyValue(const OUString & aPropertyName, const css::uno::Any & aValue) override;
+ virtual css::uno::Any SAL_CALL getPropertyValue(const OUString & PropertyName) override;
+ virtual void SAL_CALL addPropertyChangeListener(const OUString & aPropertyName, const css::uno::Reference< css::beans::XPropertyChangeListener > & xListener) override;
+ virtual void SAL_CALL removePropertyChangeListener(const OUString & aPropertyName, const css::uno::Reference< css::beans::XPropertyChangeListener > & aListener) override;
+ virtual void SAL_CALL addVetoableChangeListener(const OUString & PropertyName, const css::uno::Reference< css::beans::XVetoableChangeListener > & aListener) override;
+ virtual void SAL_CALL removeVetoableChangeListener(const OUString & PropertyName, const css::uno::Reference< css::beans::XVetoableChangeListener > & aListener) override;
+
+ // css::chart2::data::XDatabaseDataProvider:
+ virtual css::uno::Sequence< OUString > SAL_CALL getMasterFields() override;
+ virtual void SAL_CALL setMasterFields(const css::uno::Sequence< OUString > & the_value) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getDetailFields() override;
+ virtual void SAL_CALL setDetailFields(const css::uno::Sequence< OUString > & the_value) override;
+ virtual OUString SAL_CALL getCommand() override;
+ virtual void SAL_CALL setCommand(const OUString & the_value) override;
+ virtual ::sal_Int32 SAL_CALL getCommandType() override;
+ virtual void SAL_CALL setCommandType(::sal_Int32 the_value) override;
+ virtual OUString SAL_CALL getFilter() override;
+ virtual void SAL_CALL setFilter(const OUString & the_value) override;
+ virtual sal_Bool SAL_CALL getApplyFilter() override;
+ virtual void SAL_CALL setApplyFilter( sal_Bool _applyfilter ) override;
+ virtual OUString SAL_CALL getHavingClause() override;
+ virtual void SAL_CALL setHavingClause( const OUString& _havingclause ) override;
+ virtual OUString SAL_CALL getGroupBy() override;
+ virtual void SAL_CALL setGroupBy( const OUString& _groupby ) override;
+ virtual OUString SAL_CALL getOrder() override;
+ virtual void SAL_CALL setOrder( const OUString& _order ) override;
+ virtual sal_Bool SAL_CALL getEscapeProcessing() override;
+ virtual void SAL_CALL setEscapeProcessing(sal_Bool the_value) override;
+ virtual ::sal_Int32 SAL_CALL getRowLimit() override;
+ virtual void SAL_CALL setRowLimit( ::sal_Int32 _rowlimit ) override;
+ virtual css::uno::Reference< css::sdbc::XConnection > SAL_CALL getActiveConnection() override;
+ virtual void SAL_CALL setActiveConnection(const css::uno::Reference< css::sdbc::XConnection > & the_value) override;
+ virtual OUString SAL_CALL getDataSourceName() override;
+ virtual void SAL_CALL setDataSourceName( const OUString& _datasourcename ) override;
+
+ // css::sdbc::XParameters
+ virtual void SAL_CALL setNull(sal_Int32 parameterIndex, sal_Int32 sqlType) override;
+ virtual void SAL_CALL setObjectNull(sal_Int32 parameterIndex, sal_Int32 sqlType, const OUString& typeName) override;
+ virtual void SAL_CALL setBoolean(sal_Int32 parameterIndex, sal_Bool x) override;
+ virtual void SAL_CALL setByte(sal_Int32 parameterIndex, sal_Int8 x) override;
+ virtual void SAL_CALL setShort(sal_Int32 parameterIndex, sal_Int16 x) override;
+ virtual void SAL_CALL setInt(sal_Int32 parameterIndex, sal_Int32 x) override;
+ virtual void SAL_CALL setLong(sal_Int32 parameterIndex, sal_Int64 x) override;
+ virtual void SAL_CALL setFloat(sal_Int32 parameterIndex, float x) override;
+ virtual void SAL_CALL setDouble(sal_Int32 parameterIndex, double x) override;
+ virtual void SAL_CALL setString(sal_Int32 parameterIndex, const OUString& x) override;
+ virtual void SAL_CALL setBytes(sal_Int32 parameterIndex, const css::uno::Sequence< sal_Int8 >& x) override;
+ virtual void SAL_CALL setDate(sal_Int32 parameterIndex, const css::util::Date& x) override;
+ virtual void SAL_CALL setTime(sal_Int32 parameterIndex, const css::util::Time& x) override;
+ virtual void SAL_CALL setTimestamp(sal_Int32 parameterIndex, const css::util::DateTime& x) override;
+ virtual void SAL_CALL setBinaryStream(sal_Int32 parameterIndex, const css::uno::Reference< css::io::XInputStream>& x, sal_Int32 length) override;
+ virtual void SAL_CALL setCharacterStream(sal_Int32 parameterIndex, const css::uno::Reference< css::io::XInputStream>& x, sal_Int32 length) override;
+ virtual void SAL_CALL setObject(sal_Int32 parameterIndex, const css::uno::Any& x) override;
+ virtual void SAL_CALL setObjectWithInfo(sal_Int32 parameterIndex, const css::uno::Any& x, sal_Int32 targetSqlType, sal_Int32 scale) override;
+ virtual void SAL_CALL setRef(sal_Int32 parameterIndex, const css::uno::Reference< css::sdbc::XRef>& x) override;
+ virtual void SAL_CALL setBlob(sal_Int32 parameterIndex, const css::uno::Reference< css::sdbc::XBlob>& x) override;
+ virtual void SAL_CALL setClob(sal_Int32 parameterIndex, const css::uno::Reference< css::sdbc::XClob>& x) override;
+ virtual void SAL_CALL setArray(sal_Int32 parameterIndex, const css::uno::Reference< css::sdbc::XArray>& x) override;
+ virtual void SAL_CALL clearParameters() override;
+
+ // css::sdbc::XRowSet
+ virtual void SAL_CALL execute() override;
+ virtual void SAL_CALL addRowSetListener(const css::uno::Reference< css::sdbc::XRowSetListener>& _rxListener) override;
+ virtual void SAL_CALL removeRowSetListener(const css::uno::Reference< css::sdbc::XRowSetListener>& _rxListener) override;
+
+ // css::sdbc::XResultSet
+ virtual sal_Bool SAL_CALL next() override;
+ virtual sal_Bool SAL_CALL isBeforeFirst() override;
+ virtual sal_Bool SAL_CALL isAfterLast() override;
+ virtual sal_Bool SAL_CALL isFirst() override;
+ virtual sal_Bool SAL_CALL isLast() override;
+ virtual void SAL_CALL beforeFirst() override;
+ virtual void SAL_CALL afterLast() override;
+ virtual sal_Bool SAL_CALL first() override;
+ virtual sal_Bool SAL_CALL last() override;
+ virtual sal_Int32 SAL_CALL getRow() override;
+ virtual sal_Bool SAL_CALL absolute(sal_Int32 row) override;
+ virtual sal_Bool SAL_CALL relative(sal_Int32 rows) override;
+ virtual sal_Bool SAL_CALL previous() override;
+ virtual void SAL_CALL refreshRow() override;
+ virtual sal_Bool SAL_CALL rowUpdated() override;
+ virtual sal_Bool SAL_CALL rowInserted() override;
+ virtual sal_Bool SAL_CALL rowDeleted() override;
+ virtual css::uno::Reference< css::uno::XInterface > SAL_CALL getStatement() override;
+
+ // container::XChild
+ virtual css::uno::Reference< css::uno::XInterface > SAL_CALL getParent( ) override;
+ virtual void SAL_CALL setParent( const css::uno::Reference< css::uno::XInterface >& Parent ) override;
+
+ // ____ XComplexDescriptionAccess ____
+ virtual css::uno::Sequence< css::uno::Sequence< OUString > > SAL_CALL getComplexRowDescriptions() override;
+ virtual void SAL_CALL setComplexRowDescriptions( const css::uno::Sequence< css::uno::Sequence< OUString > >& aRowDescriptions ) override;
+ virtual css::uno::Sequence< css::uno::Sequence< OUString > > SAL_CALL getComplexColumnDescriptions() override;
+ virtual void SAL_CALL setComplexColumnDescriptions( const css::uno::Sequence< css::uno::Sequence< OUString > >& aColumnDescriptions ) override;
+
+ // ____ XChartDataArray (base of XComplexDescriptionAccess) ____
+ virtual css::uno::Sequence< css::uno::Sequence< double > > SAL_CALL getData() override;
+ virtual void SAL_CALL setData( const css::uno::Sequence< css::uno::Sequence< double > >& aData ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getRowDescriptions() override;
+ virtual void SAL_CALL setRowDescriptions( const css::uno::Sequence< OUString >& aRowDescriptions ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getColumnDescriptions() override;
+ virtual void SAL_CALL setColumnDescriptions( const css::uno::Sequence< OUString >& aColumnDescriptions ) override;
+
+ // ____ XChartData (base of XChartDataArray) ____
+ virtual void SAL_CALL addChartDataChangeEventListener(const css::uno::Reference< css::chart::XChartDataChangeEventListener >& aListener ) override;
+ virtual void SAL_CALL removeChartDataChangeEventListener(const css::uno::Reference< css::chart::XChartDataChangeEventListener >& aListener ) override;
+ virtual double SAL_CALL getNotANumber() override;
+ virtual sal_Bool SAL_CALL isNotANumber(double nNumber ) override;
+private:
+ DatabaseDataProvider(DatabaseDataProvider const &) = delete;
+ DatabaseDataProvider& operator =(DatabaseDataProvider const &) = delete;
+
+ virtual ~DatabaseDataProvider() override {}
+
+ // This function is called upon disposing the component,
+ // if your component needs special work when it becomes
+ // disposed, do it here.
+ virtual void SAL_CALL disposing() override;
+
+ void impl_fillRowSet_throw();
+ bool impl_fillParameters_nothrow( ::osl::ResettableMutexGuard& _rClearForNotifies);
+ void impl_fillInternalDataProvider_throw(bool _bHasCategories,const css::uno::Sequence< OUString >& i_aColumnNames);
+ void impl_invalidateParameter_nothrow();
+ css::uno::Any impl_getNumberFormatKey_nothrow(const OUString & _sRangeRepresentation) const;
+
+ template <typename T> void set( const OUString& _sProperty
+ ,const T& Value
+ ,T& _member)
+ {
+ BoundListeners l;
+ {
+ ::osl::MutexGuard aGuard(m_aMutex);
+ if ( _member != Value )
+ {
+ prepareSet(_sProperty, css::uno::Any(_member), css::uno::Any(Value), &l);
+ _member = Value;
+ }
+ }
+ l.notify();
+ }
+
+ ::dbtools::ParameterManager m_aParameterManager;
+ ::dbtools::FilterManager m_aFilterManager;
+ std::map< OUString, css::uno::Any> m_aNumberFormats;
+
+ css::uno::Reference< css::uno::XComponentContext > m_xContext;
+ css::uno::Reference< css::sdbc::XConnection > m_xActiveConnection;
+ css::uno::Reference< css::sdbc::XRowSet > m_xRowSet;
+ css::uno::Reference< css::chart2::XInternalDataProvider > m_xInternal;
+ css::uno::Reference< css::chart::XComplexDescriptionAccess > m_xComplexDescriptionAccess;
+ css::uno::Reference< css::chart2::data::XRangeXMLConversion> m_xRangeConversion;
+ css::uno::Reference< css::task::XInteractionHandler> m_xHandler;
+ // the object doin' most of the work - an SDB-rowset
+ css::uno::Reference< css::uno::XAggregation> m_xAggregate;
+ css::uno::Reference< css::beans::XPropertySet> m_xAggregateSet;
+ css::uno::Reference< css::uno::XInterface> m_xParent;
+ css::uno::Sequence< OUString > m_MasterFields;
+ css::uno::Sequence< OUString > m_DetailFields;
+
+ OUString m_Command;
+ OUString m_DataSourceName;
+ sal_Int32 m_CommandType;
+ sal_Int32 m_RowLimit;
+ OUString m_Filter;
+ OUString m_HavingClause;
+ OUString m_Order;
+ OUString m_GroupBy;
+ bool m_EscapeProcessing;
+ bool m_ApplyFilter;
+};
+
+} // namespace dbaccess
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/inc/FilteredContainer.hxx b/dbaccess/source/core/inc/FilteredContainer.hxx
new file mode 100644
index 000000000..968f3a1d6
--- /dev/null
+++ b/dbaccess/source/core/inc/FilteredContainer.hxx
@@ -0,0 +1,136 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <sal/config.h>
+
+#include <atomic>
+#include <cstddef>
+
+#include <com/sun/star/container/XNameAccess.hpp>
+#include <com/sun/star/sdbc/XConnection.hpp>
+
+#include <connectivity/sdbcx/VCollection.hxx>
+
+namespace dbtools
+{
+ class WarningsContainer;
+}
+
+namespace dbaccess
+{
+ class IRefreshListener;
+
+ class OFilteredContainer : public ::connectivity::sdbcx::OCollection
+ {
+ private:
+ mutable bool m_bConstructed; // late ctor called
+
+ protected:
+ IRefreshListener* m_pRefreshListener;
+ std::atomic<std::size_t>& m_nInAppend;
+
+ // holds the original container which where set in construct but they can be null
+ css::uno::Reference< css::container::XNameAccess > m_xMasterContainer;
+ css::uno::WeakReference< css::sdbc::XConnection > m_xConnection;
+ css::uno::Reference< css::sdbc::XDatabaseMetaData > m_xMetaData;
+
+ /** returns a string denoting the only type of tables allowed in this container, or an empty string
+ if there is no such restriction
+ */
+ virtual OUString getTableTypeRestriction() const = 0;
+
+ virtual void addMasterContainerListener(){}
+ virtual void removeMasterContainerListener(){}
+
+ // ::connectivity::sdbcx::OCollection
+ virtual void impl_refresh() override;
+
+ virtual OUString getNameForObject(const ::connectivity::sdbcx::ObjectType& _xObject) override;
+
+ /** tell the container to free all elements and all additional resources.<BR>
+ After using this method the object may be reconstructed by calling one of the <code>construct</code> methods.
+ */
+ virtual void disposing() override;
+
+ class EnsureReset
+ {
+ public:
+ EnsureReset( std::atomic<std::size_t>& _rValueLocation)
+ :m_rValue( _rValueLocation )
+ {
+ ++m_rValue;
+ }
+
+ ~EnsureReset()
+ {
+ --m_rValue;
+ }
+
+ private:
+ std::atomic<std::size_t>& m_rValue;
+ };
+
+ /** retrieve a table type filter to pass to <member scope="css::sdbc">XDatabaseMetaData::getTables</member>,
+ according to the current data source settings
+ */
+ void getAllTableTypeFilter( css::uno::Sequence< OUString >& /* [out] */ _rFilter ) const;
+
+ public:
+ /** ctor of the container. The parent has to support the <type scope="css::sdbc">XConnection</type>
+ interface.<BR>
+ @param _rParent the object which acts as parent for the container.
+ all refcounting is rerouted to this object
+ @param _rMutex the access safety object of the parent
+ @param _rTableFilter restricts the visible tables by name
+ @param _rTableTypeFilter restricts the visible tables by type
+ @see construct
+ */
+ OFilteredContainer( ::cppu::OWeakObject& _rParent,
+ ::osl::Mutex& _rMutex,
+ const css::uno::Reference< css::sdbc::XConnection >& _xCon,
+ bool _bCase,
+ IRefreshListener* _pRefreshListener,
+ std::atomic<std::size_t>& _nInAppend
+ );
+
+ void dispose() { disposing(); }
+
+ /** late ctor. The container will fill itself with the data got by the connection meta data, considering the
+ filters given (the connection is the parent object you passed in the ctor).
+ */
+ void construct(
+ const css::uno::Sequence< OUString >& _rTableFilter,
+ const css::uno::Sequence< OUString >& _rTableTypeFilter
+ );
+
+ /** late ctor. The container will fill itself with wrapper objects for the tables returned by the given
+ name container.
+ */
+ void construct(
+ const css::uno::Reference< css::container::XNameAccess >& _rxMasterContainer,
+ const css::uno::Sequence< OUString >& _rTableFilter,
+ const css::uno::Sequence< OUString >& _rTableTypeFilter
+ );
+
+ bool isInitialized() const { return m_bConstructed; }
+ };
+} // namespace
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/inc/ModelImpl.hxx b/dbaccess/source/core/inc/ModelImpl.hxx
new file mode 100644
index 000000000..b6e2fe729
--- /dev/null
+++ b/dbaccess/source/core/inc/ModelImpl.hxx
@@ -0,0 +1,542 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include "ContentHelper.hxx"
+#include "documentevents.hxx"
+
+#include <com/sun/star/beans/PropertyValue.hpp>
+#include <com/sun/star/beans/XPropertyBag.hpp>
+#include <com/sun/star/document/XDocumentSubStorageSupplier.hpp>
+#include <com/sun/star/embed/XStorage.hpp>
+#include <com/sun/star/frame/XModel.hpp>
+#include <com/sun/star/lang/XSingleServiceFactory.hpp>
+#include <com/sun/star/script/XStorageBasedLibraryContainer.hpp>
+#include <com/sun/star/sdbc/XDataSource.hpp>
+#include <com/sun/star/util/XNumberFormatsSupplier.hpp>
+
+#include <comphelper/namedvaluecollection.hxx>
+#include <cppuhelper/weakref.hxx>
+#include <vcl/svapp.hxx>
+#include <sfx2/docmacromode.hxx>
+#include <sfx2/docstoragemodifylistener.hxx>
+#include <unotools/sharedunocomponent.hxx>
+#include <rtl/ref.hxx>
+
+namespace comphelper
+{
+ class NamedValueCollection;
+}
+
+namespace dbaccess
+{
+
+typedef std::vector< css::uno::WeakReference< css::sdbc::XConnection > > OWeakConnectionArray;
+
+struct AsciiPropertyValue
+{
+ // note: the canonic member order would be AsciiName / DefaultValue, but
+ // this crashes on unxlngi6.pro, since there's a bug which somehow results in
+ // getDefaultDataSourceSettings returning corrupted Any instances then.
+ css::uno::Any DefaultValue;
+ const char* AsciiName;
+ const css::uno::Type& ValueType;
+
+ AsciiPropertyValue()
+ :DefaultValue( )
+ ,AsciiName( nullptr )
+ ,ValueType( ::cppu::UnoType<void>::get() )
+ {
+ }
+
+ AsciiPropertyValue( const char* _pAsciiName, const css::uno::Any& _rDefaultValue )
+ :DefaultValue( _rDefaultValue )
+ ,AsciiName( _pAsciiName )
+ ,ValueType( _rDefaultValue.getValueType() )
+ {
+ OSL_ENSURE( ValueType.getTypeClass() != css::uno::TypeClass_VOID,
+ "AsciiPropertyValue::AsciiPropertyValue: NULL values not allowed here, use the other CTOR for this!" );
+ }
+ AsciiPropertyValue( const char* _pAsciiName, const css::uno::Type& _rValeType )
+ :DefaultValue()
+ ,AsciiName( _pAsciiName )
+ ,ValueType( _rValeType )
+ {
+ OSL_ENSURE( ValueType.getTypeClass() != css::uno::TypeClass_VOID,
+ "AsciiPropertyValue::AsciiPropertyValue: VOID property values not supported!" );
+ }
+};
+
+class ODatabaseContext;
+class OSharedConnectionManager;
+
+// ODatabaseModelImpl
+typedef ::utl::SharedUNOComponent< css::embed::XStorage > SharedStorage;
+
+class ODatabaseContext;
+class DocumentStorageAccess;
+class OSharedConnectionManager;
+class ODatabaseModelImpl :public ::sfx2::IMacroDocumentAccess
+ ,public ::sfx2::IModifiableDocument
+{
+public:
+ enum ObjectType
+ {
+ E_FORM = 0,
+ E_REPORT = 1,
+ E_QUERY = 2,
+ E_TABLE = 3
+ };
+
+ enum EmbeddedMacros
+ {
+ // the database document (storage) itself contains macros
+ eDocumentWideMacros,
+ // there are sub document( storage)s containing macros
+ eSubDocumentMacros,
+ // there are no known macro( storage)s
+ eNoMacros
+ };
+
+private:
+ css::uno::WeakReference< css::frame::XModel > m_xModel;
+ css::uno::WeakReference< css::sdbc::XDataSource > m_xDataSource;
+
+ rtl::Reference<DocumentStorageAccess> m_pStorageAccess;
+ std::vector< TContentPtr > m_aContainer; // one for each ObjectType
+ ::sfx2::DocumentMacroMode m_aMacroMode;
+ sal_Int16 m_nImposedMacroExecMode;
+
+ css::uno::Reference< css::script::XStorageBasedLibraryContainer > m_xBasicLibraries;
+ css::uno::Reference< css::script::XStorageBasedLibraryContainer > m_xDialogLibraries;
+
+ SharedStorage m_xDocumentStorage;
+ ::rtl::Reference< ::sfx2::DocumentStorageModifyListener > m_pStorageModifyListener;
+ ODatabaseContext& m_rDBContext;
+ DocumentEventsData m_aDocumentEvents;
+
+ ::comphelper::NamedValueCollection m_aMediaDescriptor;
+ /// the URL the document was loaded from
+ OUString m_sDocFileLocation;
+
+ oslInterlockedCount m_refCount;
+
+ /// do we have any object (forms/reports) which contains macros?
+ ::std::optional< EmbeddedMacros > m_aEmbeddedMacros;
+
+ /// true if setting the Modified flag of the document is currently locked
+ bool m_bModificationLock;
+
+ /// true if and only if a database document existed previously (though meanwhile disposed), and was already initialized
+ bool m_bDocumentInitialized;
+
+ /** the URL which the document should report as its URL
+
+ This might differ from ->m_sDocFileLocation in case the document was loaded
+ as part of a crash recovery process. In this case, ->m_sDocFileLocation points to
+ the temporary file where the DB had been saved to, after a crash.
+ ->m_sDocumentURL then is the URL of the document which actually had
+ been recovered.
+ */
+ OUString m_sDocumentURL;
+
+ SignatureState m_nScriptingSignatureState;
+
+public:
+ OWeakConnectionArray m_aConnections;
+ const css::uno::Reference< css::uno::XComponentContext > m_aContext;
+
+public:
+ css::uno::WeakReference< css::container::XNameAccess > m_xCommandDefinitions;
+ css::uno::WeakReference< css::container::XNameAccess > m_xTableDefinitions;
+
+ css::uno::Reference< css::util::XNumberFormatsSupplier >
+ m_xNumberFormatsSupplier;
+ OUString m_sConnectURL;
+ OUString m_sName; // transient, our creator has to tell us the title
+ OUString m_sUser;
+ OUString m_aPassword; // transient !
+ OUString m_sFailedPassword;
+ css::uno::Sequence< css::beans::PropertyValue>
+ m_aLayoutInformation;
+ sal_Int32 m_nLoginTimeout;
+ bool m_bReadOnly : 1;
+ bool m_bPasswordRequired : 1;
+ bool m_bSuppressVersionColumns : 1;
+ bool m_bModified : 1;
+ bool m_bDocumentReadOnly : 1;
+ bool m_bMacroCallsSeenWhileLoading : 1;
+ css::uno::Reference< css::beans::XPropertyBag >
+ m_xSettings;
+ css::uno::Sequence< OUString > m_aTableFilter;
+ css::uno::Sequence< OUString > m_aTableTypeFilter;
+ OSharedConnectionManager* m_pSharedConnectionManager;
+ css::uno::Reference< css::lang::XEventListener >
+ m_xSharedConnectionManager;
+ css::uno::Reference<css::awt::XWindow>
+ m_xDialogParent;
+ sal_uInt16 m_nControllerLockCount;
+
+ void reset();
+
+ /** determines whether the database document has an embedded data storage
+ */
+ bool isEmbeddedDatabase() const { return m_sConnectURL.startsWith("sdbc:embedded:"); }
+
+ /** stores the embedded storage ("database")
+
+ @param _bPreventRootCommits
+ Normally, committing the embedded storage results in also committing the root storage
+ - this is an automatism for data safety reasons.
+ If you pass <TRUE/> here, committing the root storage is prevented for this particular
+ call.
+ @return <TRUE/> if the storage could be committed, otherwise <FALSE/>
+ */
+ bool commitEmbeddedStorage( bool _bPreventRootCommits = false );
+
+ /// commits all sub storages
+ void commitStorages();
+
+ ODatabaseModelImpl(
+ const css::uno::Reference< css::uno::XComponentContext >& _rxContext,
+ ODatabaseContext& _pDBContext
+ );
+ virtual ~ODatabaseModelImpl();
+
+ ODatabaseModelImpl(
+ const OUString& _rRegistrationName,
+ const css::uno::Reference< css::uno::XComponentContext >& _rxContext,
+ ODatabaseContext& _rDBContext
+ );
+
+ // XEventListener
+ /// @throws css::uno::RuntimeException
+ void disposing( const css::lang::EventObject& Source );
+
+ void setModified( bool bModified );
+
+ void dispose();
+
+ const OUString& getURL() const { return m_sDocumentURL; }
+ const OUString& getDocFileLocation() const { return m_sDocFileLocation; }
+
+ css::uno::Reference< css::embed::XStorage >
+ getStorage( const ObjectType _eType );
+
+// helper
+ const css::uno::Reference< css::util::XNumberFormatsSupplier >&
+ getNumberFormatsSupplier();
+
+ DocumentEventsData&
+ getDocumentEvents() { return m_aDocumentEvents; }
+
+ const ::comphelper::NamedValueCollection&
+ getMediaDescriptor() const { return m_aMediaDescriptor; }
+
+ void setResource(
+ const OUString& _rURL,
+ const css::uno::Sequence< css::beans::PropertyValue >& _rArgs
+ );
+ void setDocFileLocation(
+ const OUString& i_rLoadedFrom
+ );
+
+ static ::comphelper::NamedValueCollection
+ stripLoadArguments( const ::comphelper::NamedValueCollection& _rArguments );
+
+// other stuff
+
+ // disposes all elements in m_aStorages, and clears it
+ void disposeStorages();
+
+ /// creates a ->css::embed::StorageFactory
+ css::uno::Reference< css::lang::XSingleServiceFactory >
+ createStorageFactory() const;
+
+ /// commits our storage
+ void commitRootStorage();
+
+ /// commits a given storage if it's not readonly, ignoring (but asserting) all errors
+ bool commitStorageIfWriteable_ignoreErrors(
+ const css::uno::Reference< css::embed::XStorage >& _rxStorage
+ );
+
+ void clearConnections();
+
+ css::uno::Reference< css::embed::XStorage > const & getOrCreateRootStorage();
+ css::uno::Reference< css::embed::XStorage > const & getRootStorage() const { return m_xDocumentStorage.getTyped(); }
+ void resetRootStorage() { impl_switchToStorage_throw( nullptr ); }
+
+ /** returns the data source. If it doesn't exist it will be created
+ */
+ css::uno::Reference< css::sdbc::XDataSource> getOrCreateDataSource();
+
+ /** returns the model, if there already exists one
+ */
+ css::uno::Reference< css::frame::XModel > getModel_noCreate() const;
+
+ /** returns a new ->ODatabaseDocument
+
+ @precond
+ No ->ODatabaseDocument exists so far
+
+ @seealso
+ getModel_noCreate
+ */
+ css::uno::Reference< css::frame::XModel > createNewModel_deliverOwnership();
+
+ struct ResetModelAccess { friend class ODatabaseDocument; private: ResetModelAccess() { } };
+
+ /** resets the model to NULL
+
+ Only to be called when the model is being disposed
+ */
+ void modelIsDisposing( const bool _wasInitialized, ResetModelAccess );
+
+ bool hadInitializedDocument() const { return m_bDocumentInitialized; }
+
+ DocumentStorageAccess*
+ getDocumentStorageAccess();
+
+ css::uno::Reference< css::document::XDocumentSubStorageSupplier >
+ getDocumentSubStorageSupplier();
+
+ void acquire();
+
+ void release();
+
+ /// returns all known data source settings, including their default values
+ static const AsciiPropertyValue* getDefaultDataSourceSettings();
+
+ /** retrieves the requested container of objects (forms/reports/tables/queries)
+ */
+ TContentPtr& getObjectContainer( const ObjectType _eType );
+
+ /** returns the name of the storage which is used to stored objects of the given type, if applicable
+ */
+ static OUString
+ getObjectContainerStorageName( const ObjectType _eType );
+
+ /** determines whether a given object storage contains macros
+ */
+ static bool objectHasMacros(
+ const css::uno::Reference< css::embed::XStorage >& _rxContainerStorage,
+ const OUString& _rPersistentName
+ );
+
+ /** determines which kind of embedded macros are present in the document
+ */
+ EmbeddedMacros determineEmbeddedMacros();
+
+ /** checks our document's macro execution mode, using the interaction handler as supplied with our
+ load arguments
+ */
+ bool checkMacrosOnLoading();
+
+ /** adjusts our document's macro execution mode, without using any UI, assuming the user
+ would reject execution of macros, if she would have been asked.
+
+ If checkMacrosOnLoading has been called before (and thus the macro execution mode
+ is already adjusted), then the current execution mode is simply returned.
+
+ @return
+ whether or not macro execution is allowed
+ */
+ bool adjustMacroMode_AutoReject();
+
+ /** resets our macro execute mode, so next time the checkMacrosOnLoading is called, it will
+ behave as if it has never been called before
+ */
+ void resetMacroExecutionMode();
+
+ /** ensures that ->m_xBasicLibraries resp. m_xDialogLibraries exists
+
+ @return
+ the requested library container. Is never <NULL/>.
+
+ @throws RuntimeException
+ if something does wrong, which indicates a server error in the installation
+ */
+ css::uno::Reference< css::script::XStorageBasedLibraryContainer >
+ getLibraryContainer( bool _bScript );
+
+ /** lets our library containers store themself into the given root storage
+ */
+ void storeLibraryContainersTo( const css::uno::Reference< css::embed::XStorage >& _rxToRootStorage );
+
+ /** rebases the document to the given storage
+
+ No actual committing, copying, saving, whatsoever happens. The storage is just remembered as the documents
+ new storage, nothing more.
+
+ @throws css::lang::IllegalArgumentException
+ if the given storage is <NULL/>
+ @throws css::lang::RuntimeException
+ if any of the invoked operations does so
+ */
+ css::uno::Reference< css::embed::XStorage >
+ switchToStorage(
+ const css::uno::Reference< css::embed::XStorage >& _rxNewRootStorage
+ );
+
+ /** returns the macro mode imposed by an external instance, which passed it to attachResource
+ */
+ sal_Int16 getImposedMacroExecMode() const
+ {
+ return m_nImposedMacroExecMode;
+ }
+ void setImposedMacroExecMode( const sal_Int16 _nMacroMode )
+ {
+ m_nImposedMacroExecMode = _nMacroMode;
+ }
+
+public:
+ // IMacroDocumentAccess overridables
+ virtual sal_Int16 getCurrentMacroExecMode() const override;
+ virtual void setCurrentMacroExecMode( sal_uInt16 ) override;
+ virtual OUString getDocumentLocation() const override;
+ virtual bool documentStorageHasMacros() const override;
+ virtual bool macroCallsSeenWhileLoading() const override;
+ virtual css::uno::Reference< css::document::XEmbeddedScripts > getEmbeddedDocumentScripts() const override;
+ virtual SignatureState getScriptingSignatureState() override;
+ virtual bool hasTrustedScriptingSignature( bool bAllowUIToAddAuthor ) override;
+
+ // IModifiableDocument
+ virtual void storageIsModified() override;
+
+ // don't use directly, use the ModifyLock class instead
+ void lockModify() { m_bModificationLock = true; }
+ void unlockModify() { m_bModificationLock = false; }
+ bool isModifyLocked() const { return m_bModificationLock; }
+
+ weld::Window* GetFrameWeld();
+
+private:
+ void impl_construct_nothrow();
+ css::uno::Reference< css::embed::XStorage > const &
+ impl_switchToStorage_throw( const css::uno::Reference< css::embed::XStorage >& _rxNewRootStorage );
+
+ /** switches to the given document URL, which denotes the logical URL of the document, not necessarily the
+ URL where the doc was loaded/recovered from
+ */
+ void impl_switchToLogicalURL(
+ const OUString& i_rDocumentURL
+ );
+
+};
+
+/** a small base class for UNO components whose functionality depends on an ODatabaseModelImpl
+*/
+class ModelDependentComponent
+{
+protected:
+ ::rtl::Reference< ODatabaseModelImpl > m_pImpl;
+ ::osl::Mutex m_aMutex; // only use this to init WeakComponentImplHelper
+
+protected:
+ explicit ModelDependentComponent( const ::rtl::Reference< ODatabaseModelImpl >& _model );
+ virtual ~ModelDependentComponent();
+
+ /** returns the component itself
+ */
+ virtual css::uno::Reference< css::uno::XInterface > getThis() const = 0;
+
+ ::osl::Mutex& getMutex()
+ {
+ return m_aMutex;
+ }
+
+public:
+ /// checks whether the component is already disposed, throws a DisposedException if so
+ void checkDisposed() const
+ {
+ if ( !m_pImpl.is() )
+ throw css::lang::DisposedException( "Component is already disposed.", getThis() );
+ }
+
+ void lockModify()
+ {
+ m_pImpl->lockModify();
+ }
+
+ void unlockModify()
+ {
+ m_pImpl->unlockModify();
+ }
+};
+
+class ModifyLock
+{
+public:
+ explicit ModifyLock( ModelDependentComponent& _component )
+ :m_rComponent( _component )
+ {
+ m_rComponent.lockModify();
+ }
+
+ ~ModifyLock()
+ {
+ m_rComponent.unlockModify();
+ }
+
+private:
+ ModelDependentComponent& m_rComponent;
+};
+
+/** a guard for public methods of objects dependent on an ODatabaseModelImpl instance
+
+ Just put this guard onto the stack at the beginning of your method. Don't bother yourself
+ with a MutexGuard, checks for being disposed, and the like.
+*/
+class ModelMethodGuard
+{
+private:
+ // to avoid deadlocks, lock SolarMutex
+ SolarMutexResettableGuard m_SolarGuard;
+
+public:
+ /** constructs the guard
+
+ @param _component
+ the component whose functionality depends on an ODatabaseModelImpl instance
+
+ @throws css::lang::DisposedException
+ If the given component is already disposed
+ */
+ explicit ModelMethodGuard( const ModelDependentComponent& _component )
+ {
+ _component.checkDisposed();
+ }
+
+ void clear()
+ {
+ // note: this only releases *once* so may still be locked
+ m_SolarGuard.clear();
+ }
+
+ void reset()
+ {
+ m_SolarGuard.reset();
+ }
+};
+
+} // namespace dbaccess
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/inc/PropertyForward.hxx b/dbaccess/source/core/inc/PropertyForward.hxx
new file mode 100644
index 000000000..b8e602fc0
--- /dev/null
+++ b/dbaccess/source/core/inc/PropertyForward.hxx
@@ -0,0 +1,69 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <com/sun/star/beans/XPropertyChangeListener.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/beans/XPropertySetInfo.hpp>
+#include <com/sun/star/container/XNameAccess.hpp>
+#include <cppuhelper/implbase.hxx>
+#include <cppuhelper/basemutex.hxx>
+
+#include <vector>
+
+namespace dbaccess
+{
+
+ // OPropertyForward
+ typedef ::cppu::WeakImplHelper< css::beans::XPropertyChangeListener
+ > OPropertyForward_Base;
+ class OPropertyForward :public ::cppu::BaseMutex
+ ,public OPropertyForward_Base
+ {
+ css::uno::Reference< css::beans::XPropertySet > m_xSource;
+ css::uno::Reference< css::beans::XPropertySet > m_xDest;
+ css::uno::Reference< css::beans::XPropertySetInfo > m_xDestInfo;
+ css::uno::Reference< css::container::XNameAccess > m_xDestContainer;
+ OUString m_sName;
+ bool m_bInInsert;
+
+ protected:
+ virtual ~OPropertyForward() override;
+
+ public:
+ OPropertyForward( const css::uno::Reference< css::beans::XPropertySet>& _xSource,
+ const css::uno::Reference< css::container::XNameAccess>& _xDestContainer,
+ const OUString& _sName,
+ const std::vector< OUString >& _aPropertyList
+ );
+
+ // css::beans::XPropertyChangeListener
+ virtual void SAL_CALL propertyChange( const css::beans::PropertyChangeEvent& evt ) override;
+
+ // css::lang::XEventListener
+ virtual void SAL_CALL disposing( const css::lang::EventObject& _rSource ) override;
+
+ void setName( const OUString& _sName ) { m_sName = _sName; }
+ void setDefinition( const css::uno::Reference< css::beans::XPropertySet >& _xDest);
+ const css::uno::Reference< css::beans::XPropertySet >& getDefinition() const { return m_xDest; }
+ };
+
+} // namespace dbaccess
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/inc/RefreshListener.hxx b/dbaccess/source/core/inc/RefreshListener.hxx
new file mode 100644
index 000000000..03836c308
--- /dev/null
+++ b/dbaccess/source/core/inc/RefreshListener.hxx
@@ -0,0 +1,42 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <com/sun/star/uno/Reference.h>
+
+namespace com::sun::star::container { class XNameAccess; }
+
+
+namespace dbaccess
+{
+
+ // IRefreshListener
+ class SAL_NO_VTABLE IRefreshListener
+ {
+ public:
+ virtual void refresh(const css::uno::Reference< css::container::XNameAccess >& _rToBeRefreshed) = 0;
+
+ protected:
+ ~IRefreshListener() {}
+ };
+
+} // namespace dbaccess
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/inc/SingleSelectQueryComposer.hxx b/dbaccess/source/core/inc/SingleSelectQueryComposer.hxx
new file mode 100644
index 000000000..a0edfd195
--- /dev/null
+++ b/dbaccess/source/core/inc/SingleSelectQueryComposer.hxx
@@ -0,0 +1,263 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <com/sun/star/sdb/XParametersSupplier.hpp>
+#include <com/sun/star/sdbcx/XTablesSupplier.hpp>
+#include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
+#include <com/sun/star/sdb/XSingleSelectQueryComposer.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/script/XTypeConverter.hpp>
+#include <cppuhelper/implbase5.hxx>
+#include <connectivity/sqliterator.hxx>
+#include <connectivity/sqlparse.hxx>
+#include <apitools.hxx>
+#include <comphelper/broadcasthelper.hxx>
+#include <comphelper/uno3.hxx>
+#include <comphelper/proparrhlp.hxx>
+#include <comphelper/propertycontainer.hxx>
+#include <svx/ParseContext.hxx>
+
+namespace com::sun::star::util {
+ class XNumberFormatsSupplier;
+ class XNumberFormatter;
+}
+
+namespace dbaccess
+{
+ typedef ::cppu::ImplHelper5< css::sdb::XSingleSelectQueryComposer,
+ css::sdb::XParametersSupplier,
+ css::sdbcx::XColumnsSupplier,
+ css::sdbcx::XTablesSupplier,
+ css::lang::XServiceInfo > OSingleSelectQueryComposer_BASE;
+
+ class OPrivateColumns;
+ class OPrivateTables;
+
+ class OSingleSelectQueryComposer : public ::comphelper::OMutexAndBroadcastHelper
+ ,public OSubComponent
+ ,public ::comphelper::OPropertyContainer
+ ,public ::comphelper::OPropertyArrayUsageHelper < OSingleSelectQueryComposer >
+ ,public OSingleSelectQueryComposer_BASE
+ {
+ enum SQLPart
+ {
+ Where = 0, // the 0 is important, as it will be used as index into arrays
+ Group,
+ Having,
+ Order,
+
+ SQLPartCount
+ };
+ static void incSQLPart( SQLPart& e ) { e = static_cast<SQLPart>(1 + static_cast<size_t>(e)); }
+ enum EColumnType
+ {
+ SelectColumns = 0,
+ GroupByColumns = 1,
+ OrderColumns = 2,
+ ParameterColumns = 3
+ };
+ typedef std::function<const ::connectivity::OSQLParseNode*(::connectivity::OSQLParseTreeIterator *)>
+ TGetParseNode;
+ ::svxform::OSystemParseContext m_aParseContext;
+ ::connectivity::OSQLParser m_aSqlParser;
+ ::connectivity::OSQLParseTreeIterator m_aSqlIterator; // the iterator for the complete statement
+ ::connectivity::OSQLParseTreeIterator m_aAdditiveIterator; // the iterator for the "additive statement" (means without the clauses of the elementary statement)
+ std::vector<std::unique_ptr<OPrivateColumns>>
+ m_aColumnsCollection; // used for columns and parameters of old queries
+ std::vector<std::unique_ptr<OPrivateTables>>
+ m_aTablesCollection;
+
+ std::vector< OUString > m_aElementaryParts; // the filter/groupby/having/order of the elementary statement
+
+ css::uno::Reference< css::sdbc::XConnection> m_xConnection;
+ css::uno::Reference< css::sdbc::XDatabaseMetaData> m_xMetaData;
+ css::uno::Reference< css::container::XNameAccess> m_xConnectionTables;
+ css::uno::Reference< css::container::XNameAccess> m_xConnectionQueries;
+ css::uno::Reference< css::util::XNumberFormatsSupplier > m_xNumberFormatsSupplier;
+ css::uno::Reference< css::uno::XComponentContext> m_aContext;
+ css::uno::Reference< css::script::XTypeConverter > m_xTypeConverter;
+
+ std::vector<std::unique_ptr<OPrivateColumns>> m_aCurrentColumns;
+ std::unique_ptr<OPrivateTables> m_pTables; // currently used tables
+
+ OUString m_aPureSelectSQL; // the pure select statement, without filter/order/groupby/having
+ OUString m_sDecimalSep;
+ OUString m_sCommand;
+ css::lang::Locale m_aLocale;
+ sal_Int32 m_nBoolCompareMode; // how to compare bool values
+ sal_Int32 m_nCommandType;
+
+ // <properties>
+ OUString m_sOriginal;
+ // </properties>
+
+
+ bool setORCriteria(::connectivity::OSQLParseNode const * pCondition, ::connectivity::OSQLParseTreeIterator& _rIterator,
+ std::vector< std::vector < css::beans::PropertyValue > >& rFilters, const css::uno::Reference< css::util::XNumberFormatter > & xFormatter) const;
+ bool setANDCriteria(::connectivity::OSQLParseNode const * pCondition, ::connectivity::OSQLParseTreeIterator& _rIterator,
+ std::vector < css::beans::PropertyValue > & rFilters, const css::uno::Reference< css::util::XNumberFormatter > & xFormatter) const;
+ bool setLikePredicate(::connectivity::OSQLParseNode const * pCondition, ::connectivity::OSQLParseTreeIterator const & _rIterator,
+ std::vector < css::beans::PropertyValue > & rFilters, const css::uno::Reference< css::util::XNumberFormatter > & xFormatter) const;
+ bool setComparisonPredicate(::connectivity::OSQLParseNode const * pCondition, ::connectivity::OSQLParseTreeIterator const & _rIterator,
+ std::vector < css::beans::PropertyValue > & rFilters, const css::uno::Reference< css::util::XNumberFormatter > & xFormatter) const;
+
+ static OUString getColumnName(::connectivity::OSQLParseNode const * pColumnRef, ::connectivity::OSQLParseTreeIterator const & _rIterator);
+ OUString getTableAlias(const css::uno::Reference< css::beans::XPropertySet >& column ) const;
+ static sal_Int32 getPredicateType(::connectivity::OSQLParseNode const * _pPredicate);
+ // clears all Columns,Parameters and tables and insert it to their vectors
+ void clearCurrentCollections();
+ // clears the columns collection given by EColumnType
+ void clearColumns( const EColumnType _eType );
+
+ /** retrieves a particular part of a statement
+ @param _rIterator
+ the iterator to use.
+ */
+ OUString getStatementPart( TGetParseNode const & _aGetFunctor, ::connectivity::OSQLParseTreeIterator& _rIterator );
+ void setQuery_Impl( const OUString& command );
+
+ void setConditionByColumn( const css::uno::Reference< css::beans::XPropertySet >& column
+ , bool andCriteria
+ , std::function<bool(OSingleSelectQueryComposer *, const OUString&)> const & _aSetFunctor
+ ,sal_Int32 filterOperator);
+
+ /** getStructuredCondition returns the structured condition for the where or having clause
+ @param _aGetFunctor
+ A member function to get the correct parse node.
+
+ @return
+ The structured filter
+ */
+ css::uno::Sequence< css::uno::Sequence< css::beans::PropertyValue > >
+ getStructuredCondition( TGetParseNode const & _aGetFunctor );
+
+ css::uno::Reference< css::container::XIndexAccess >
+ setCurrentColumns( EColumnType _eType, const ::rtl::Reference< ::connectivity::OSQLColumns >& _rCols );
+
+ //helper methods for mem_fun_t
+ bool implSetFilter(const OUString& _sFilter) { setFilter(_sFilter); return true;}
+ bool implSetHavingClause(const OUString& _sFilter) { setHavingClause(_sFilter); return true;}
+
+ /** returns the part of the select statement
+ @param _ePart
+ Which part should be returned.
+ @param _bWithKeyword
+ If <TRUE/> the keyword will be added too. Otherwise not.
+ @param _rIterator
+ The iterator to use.
+
+ @return
+ The part of the select statement.
+ */
+ OUString getSQLPart( SQLPart _ePart, ::connectivity::OSQLParseTreeIterator& _rIterator, bool _bWithKeyword );
+
+ /** retrieves the keyword for the given SQLPart
+ */
+ static OUString getKeyword( SQLPart _ePart );
+
+ /** sets a single "additive" clause, means a filter/groupby/having/order clause
+ */
+ void setSingleAdditiveClause( SQLPart _ePart, const OUString& _rClause );
+
+ /** composes a statement from m_aPureSelectSQL and the 4 usual clauses
+ */
+ OUString composeStatementFromParts( const std::vector< OUString >& _rParts );
+
+ /** return the name of the column in the *source* *table*.
+
+ That is, for (SELECT a AS b FROM t), it returns A or "t"."A", as appropriate.
+
+ Use e.g. for WHERE, GROUP BY and HAVING clauses.
+
+ @param bGroupBy: for GROUP BY clause? In that case, throw exception if trying to use an unrelated column and the database does not support that.
+ */
+ OUString impl_getColumnRealName_throw(const css::uno::Reference< css::beans::XPropertySet >& column, bool bGroupBy);
+
+ /** return the name of the column in the *query* for ORDER BY clause.
+
+ That is, for (SELECT a AS b FROM t), it returns "b"
+
+ Throws exception if trying to use an unrelated column and the database does not support that.
+ */
+ OUString impl_getColumnNameOrderBy_throw(const css::uno::Reference< css::beans::XPropertySet >& column);
+
+ protected:
+ virtual ~OSingleSelectQueryComposer() override;
+ public:
+
+ OSingleSelectQueryComposer( const css::uno::Reference< css::container::XNameAccess>& _xTableSupplier,
+ const css::uno::Reference< css::sdbc::XConnection>& _xConnection,
+ const css::uno::Reference< css::uno::XComponentContext>& _rContext);
+
+
+ void SAL_CALL disposing() override;
+
+ virtual css::uno::Sequence<css::uno::Type> SAL_CALL getTypes() override;
+ virtual css::uno::Sequence<sal_Int8> SAL_CALL getImplementationId() override;
+
+ // css::uno::XInterface
+ DECLARE_XINTERFACE( )
+
+ // XServiceInfo
+ DECLARE_SERVICE_INFO();
+
+ virtual css::uno::Reference< css::beans::XPropertySetInfo> SAL_CALL getPropertySetInfo() override;
+ virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper() override;
+ virtual ::cppu::IPropertyArrayHelper* createArrayHelper() const override;
+
+
+ // css::sdb::XSingleSelectQueryComposer
+ virtual OUString SAL_CALL getElementaryQuery() override;
+ virtual void SAL_CALL setElementaryQuery( const OUString& _rElementary ) override;
+ virtual void SAL_CALL setFilter( const OUString& filter ) override;
+ virtual void SAL_CALL setStructuredFilter( const css::uno::Sequence< css::uno::Sequence< css::beans::PropertyValue > >& filter ) override;
+ virtual void SAL_CALL appendFilterByColumn( const css::uno::Reference< css::beans::XPropertySet >& column, sal_Bool andCriteria,sal_Int32 filterOperator ) override;
+ virtual void SAL_CALL appendGroupByColumn( const css::uno::Reference< css::beans::XPropertySet >& column ) override;
+ virtual void SAL_CALL setGroup( const OUString& group ) override;
+ virtual void SAL_CALL setHavingClause( const OUString& filter ) override;
+ virtual void SAL_CALL setStructuredHavingClause( const css::uno::Sequence< css::uno::Sequence< css::beans::PropertyValue > >& filter ) override;
+ virtual void SAL_CALL appendHavingClauseByColumn( const css::uno::Reference< css::beans::XPropertySet >& column, sal_Bool andCriteria,sal_Int32 filterOperator ) override;
+ virtual void SAL_CALL appendOrderByColumn( const css::uno::Reference< css::beans::XPropertySet >& column, sal_Bool ascending ) override;
+ virtual void SAL_CALL setOrder( const OUString& order ) override;
+
+ // XSingleSelectQueryAnalyzer
+ virtual OUString SAL_CALL getQuery( ) override;
+ virtual void SAL_CALL setQuery( const OUString& command ) override;
+ virtual void SAL_CALL setCommand( const OUString& command,sal_Int32 CommandType ) override;
+ virtual OUString SAL_CALL getFilter( ) override;
+ virtual css::uno::Sequence< css::uno::Sequence< css::beans::PropertyValue > > SAL_CALL getStructuredFilter( ) override;
+ virtual OUString SAL_CALL getGroup( ) override;
+ virtual css::uno::Reference< css::container::XIndexAccess > SAL_CALL getGroupColumns( ) override;
+ virtual OUString SAL_CALL getHavingClause( ) override;
+ virtual css::uno::Sequence< css::uno::Sequence< css::beans::PropertyValue > > SAL_CALL getStructuredHavingClause( ) override;
+ virtual OUString SAL_CALL getOrder( ) override;
+ virtual css::uno::Reference< css::container::XIndexAccess > SAL_CALL getOrderColumns( ) override;
+ virtual OUString SAL_CALL getQueryWithSubstitution( ) override;
+
+ // XColumnsSupplier
+ virtual css::uno::Reference< css::container::XNameAccess > SAL_CALL getColumns( ) override;
+ // XTablesSupplier
+ virtual css::uno::Reference< css::container::XNameAccess > SAL_CALL getTables( ) override;
+ // XParametersSupplier
+ virtual css::uno::Reference< css::container::XIndexAccess > SAL_CALL getParameters( ) override;
+ };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/inc/TableDeco.hxx b/dbaccess/source/core/inc/TableDeco.hxx
new file mode 100644
index 000000000..e40fac802
--- /dev/null
+++ b/dbaccess/source/core/inc/TableDeco.hxx
@@ -0,0 +1,164 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <memory>
+#include <com/sun/star/util/XNumberFormatsSupplier.hpp>
+#include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
+#include <com/sun/star/sdbcx/XDataDescriptorFactory.hpp>
+#include <com/sun/star/sdbcx/XIndexesSupplier.hpp>
+#include <com/sun/star/sdbcx/XKeysSupplier.hpp>
+#include <com/sun/star/sdbcx/XRename.hpp>
+#include <com/sun/star/sdbcx/XAlterTable.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/lang/XUnoTunnel.hpp>
+#include <com/sun/star/sdbc/XConnection.hpp>
+#include <cppuhelper/compbase.hxx>
+#include "datasettings.hxx"
+#include "column.hxx"
+
+#include <connectivity/CommonTools.hxx>
+#include <connectivity/sdbcx/IRefreshable.hxx>
+#include <comphelper/IdPropArrayHelper.hxx>
+
+namespace dbaccess
+{
+ typedef ::cppu::WeakComponentImplHelper< css::sdbcx::XColumnsSupplier,
+ css::sdbcx::XKeysSupplier,
+ css::container::XNamed,
+ css::lang::XServiceInfo,
+ css::sdbcx::XDataDescriptorFactory,
+ css::sdbcx::XIndexesSupplier,
+ css::sdbcx::XRename,
+ css::lang::XUnoTunnel,
+ css::sdbcx::XAlterTable> OTableDescriptor_BASE;
+ // OTables
+ class ODBTableDecorator;
+ typedef ::comphelper::OIdPropertyArrayUsageHelper< ODBTableDecorator > ODBTableDecorator_PROP;
+
+ class ODBTableDecorator :public cppu::BaseMutex
+ ,public OTableDescriptor_BASE
+ ,public ODataSettings //ODataSettings_Base
+ ,public IColumnFactory
+ ,public ::connectivity::sdbcx::IRefreshableColumns
+ ,public ODBTableDecorator_PROP
+ {
+ void fillPrivileges() const;
+ protected:
+ css::uno::Reference< css::container::XContainerListener > m_xColumnMediator;
+ css::uno::Reference< css::sdbcx::XColumnsSupplier > m_xTable;
+ css::uno::Reference< css::container::XNameAccess > m_xColumnDefinitions;
+ css::uno::Reference< css::sdbc::XConnection > m_xConnection;
+ css::uno::Reference< css::sdbc::XDatabaseMetaData > m_xMetaData;
+ css::uno::Reference< css::util::XNumberFormatsSupplier > m_xNumberFormats;
+
+ // <properties>
+ mutable sal_Int32 m_nPrivileges;
+ // </properties>
+ // note: this thing uses the ref-count of "this", see OCollection::acquire()!
+ std::unique_ptr<::connectivity::sdbcx::OCollection> m_pColumns;
+
+ // IColumnFactory
+ virtual rtl::Reference<OColumn> createColumn(const OUString& _rName) const override;
+ virtual css::uno::Reference< css::beans::XPropertySet > createColumnDescriptor() override;
+ virtual void columnAppended( const css::uno::Reference< css::beans::XPropertySet >& _rxSourceDescriptor ) override;
+ virtual void columnDropped(const OUString& _sName) override;
+
+ virtual void refreshColumns() override;
+
+ virtual ::cppu::IPropertyArrayHelper* createArrayHelper(sal_Int32 _nId) const override;
+ virtual ::cppu::IPropertyArrayHelper & SAL_CALL getInfoHelper() override;
+
+ // OPropertySetHelper
+ virtual sal_Bool SAL_CALL convertFastPropertyValue(
+ css::uno::Any & rConvertedValue,
+ css::uno::Any & rOldValue,
+ sal_Int32 nHandle,
+ const css::uno::Any& rValue ) override;
+ virtual void SAL_CALL getFastPropertyValue(css::uno::Any& rValue, sal_Int32 nHandle) const override;
+ virtual void SAL_CALL setFastPropertyValue_NoBroadcast(
+ sal_Int32 nHandle,
+ const css::uno::Any& rValue
+ ) override;
+
+ virtual ~ODBTableDecorator() override;
+ public:
+ /** constructs a wrapper supporting the com.sun.star.sdb.Table service.
+
+ @param _rxConn
+ the connection the table belongs to. Must not be <NULL/>
+ @param _rxTable
+ the table from the driver can be <NULL/>
+ @throws css::sdbc::SQLException
+ */
+ ODBTableDecorator(
+ const css::uno::Reference< css::sdbc::XConnection >& _rxConn,
+ const css::uno::Reference< css::sdbcx::XColumnsSupplier >& _rxTable,
+ const css::uno::Reference< css::util::XNumberFormatsSupplier >& _rxNumberFormats,
+ const css::uno::Reference< css::container::XNameAccess >& _rxColumnDefinitions
+ );
+
+ // ODescriptor
+ void construct();
+
+ //XInterface
+ virtual css::uno::Any SAL_CALL queryInterface( const css::uno::Type & rType ) override;
+ virtual void SAL_CALL acquire() noexcept override;
+ virtual void SAL_CALL release() noexcept override;
+ //XTypeProvider
+ virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes( ) override;
+ virtual css::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId() override;
+
+ // OComponentHelper
+ virtual void SAL_CALL disposing() override;
+
+ // css::lang::XServiceInfo
+ DECLARE_SERVICE_INFO();
+ // XPropertySet
+ virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo( ) override;
+ // css::sdbcx::XRename,
+ virtual void SAL_CALL rename( const OUString& _rNewName ) override;
+
+ // css::sdbcx::XAlterTable,
+ virtual void SAL_CALL alterColumnByName( const OUString& _rName, const css::uno::Reference< css::beans::XPropertySet >& _rxDescriptor ) override;
+ virtual void SAL_CALL alterColumnByIndex( sal_Int32 _nIndex, const css::uno::Reference< css::beans::XPropertySet >& _rxDescriptor ) override;
+
+ // XNamed
+ virtual OUString SAL_CALL getName() override;
+ virtual void SAL_CALL setName( const OUString& aName ) override;
+ // css::lang::XUnoTunnel
+ virtual sal_Int64 SAL_CALL getSomething( const css::uno::Sequence< sal_Int8 >& aIdentifier ) override;
+ static const css::uno::Sequence< sal_Int8 > & getUnoTunnelId();
+
+ // XColumnsSupplier
+ virtual css::uno::Reference< css::container::XNameAccess > SAL_CALL getColumns( ) override;
+ // XKeysSupplier
+ virtual css::uno::Reference< css::container::XIndexAccess > SAL_CALL getKeys( ) override;
+ // XIndexesSupplier
+ virtual css::uno::Reference< css::container::XNameAccess > SAL_CALL getIndexes( ) override;
+ // XDataDescriptorFactory
+ virtual css::uno::Reference< css::beans::XPropertySet > SAL_CALL createDataDescriptor( ) override;
+
+ protected:
+ using ODataSettings::getFastPropertyValue;
+ };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/inc/View.hxx b/dbaccess/source/core/inc/View.hxx
new file mode 100644
index 000000000..d3889ff56
--- /dev/null
+++ b/dbaccess/source/core/inc/View.hxx
@@ -0,0 +1,71 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <connectivity/sdbcx/VView.hxx>
+
+#include <com/sun/star/sdbcx/XAlterView.hpp>
+#include <com/sun/star/sdb/tools/XViewAccess.hpp>
+
+#include <comphelper/uno3.hxx>
+#include <cppuhelper/implbase1.hxx>
+
+namespace dbaccess
+{
+
+ // View
+ typedef ::connectivity::sdbcx::OView View_Base;
+ typedef ::cppu::ImplHelper1< css::sdbcx::XAlterView > View_IBASE;
+ class View :public View_Base
+ ,public View_IBASE
+ {
+ public:
+ View(
+ const css::uno::Reference< css::sdbc::XConnection >& _rxConnection,
+ bool _bCaseSensitive,
+ const OUString& _rCatalogName,
+ const OUString& _rSchemaName,
+ const OUString& _rName
+ );
+
+ // UNO
+ DECLARE_XINTERFACE()
+ DECLARE_XTYPEPROVIDER()
+
+ // XAlterView
+ virtual void SAL_CALL alterCommand( const OUString& NewCommand ) override;
+
+ protected:
+ virtual ~View() override;
+
+ protected:
+ // OPropertyContainer
+ virtual void SAL_CALL getFastPropertyValue( css::uno::Any& _rValue, sal_Int32 _nHandle ) const override;
+
+ private:
+ css::uno::Reference< css::sdb::tools::XViewAccess> m_xViewAccess;
+ sal_Int32 m_nCommandHandle;
+ private:
+ using View_Base::getFastPropertyValue;
+ };
+
+} // namespace dbaccess
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/inc/bookmarkcontainer.hxx b/dbaccess/source/core/inc/bookmarkcontainer.hxx
new file mode 100644
index 000000000..464192542
--- /dev/null
+++ b/dbaccess/source/core/inc/bookmarkcontainer.hxx
@@ -0,0 +1,148 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <sal/config.h>
+
+#include <map>
+#include <vector>
+
+#include <comphelper/interfacecontainer3.hxx>
+#include <cppuhelper/implbase.hxx>
+#include <osl/mutex.hxx>
+#include <com/sun/star/container/XChild.hpp>
+#include <com/sun/star/container/XNameContainer.hpp>
+#include <com/sun/star/container/XContainer.hpp>
+#include <com/sun/star/container/XEnumerationAccess.hpp>
+#include <com/sun/star/container/XIndexAccess.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+
+namespace dbaccess
+{
+
+// OBookmarkContainer - base class of collections of database definition
+// documents
+typedef ::cppu::WeakImplHelper<
+ css::container::XIndexAccess
+ , css::container::XNameContainer
+ , css::container::XEnumerationAccess
+ , css::container::XContainer
+ , css::lang::XServiceInfo
+ , css::container::XChild
+ > OBookmarkContainer_Base;
+
+class OBookmarkContainer final
+ :public OBookmarkContainer_Base
+{
+ typedef std::map<OUString, OUString> MapString2String;
+ typedef std::vector<MapString2String::iterator> MapIteratorVector;
+
+ MapString2String m_aBookmarks; // the bookmarks itself
+ MapIteratorVector m_aBookmarksIndexed; // for index access to the
+
+ ::cppu::OWeakObject& m_rParent; // for the ref counting
+ ::comphelper::OInterfaceContainerHelper3<css::container::XContainerListener>
+ m_aContainerListeners;
+ ::osl::Mutex& m_rMutex;
+
+public:
+ /** constructs the container.<BR>
+ after the construction of the object the creator has to call <code>initialize</code>.
+ @param _rParent the parent object which is used for ref counting
+ @param _rMutex the parent's mutex object for access safety
+ */
+ OBookmarkContainer(
+ ::cppu::OWeakObject& _rParent,
+ ::osl::Mutex& _rMutex
+ );
+
+ /** looks like the dtor ...
+ */
+ virtual ~OBookmarkContainer() override;
+
+// css::uno::XInterface
+ virtual void SAL_CALL acquire( ) noexcept override;
+ virtual void SAL_CALL release( ) noexcept override;
+
+// css::lang::XServiceInfo
+ virtual OUString SAL_CALL getImplementationName( ) override;
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override;
+
+// css::container::XElementAccess
+ virtual css::uno::Type SAL_CALL getElementType( ) override;
+ virtual sal_Bool SAL_CALL hasElements( ) override;
+
+// css::container::XEnumerationAccess
+ virtual css::uno::Reference< css::container::XEnumeration > SAL_CALL createEnumeration( ) override;
+
+// css::container::XIndexAccess
+ virtual sal_Int32 SAL_CALL getCount( ) override;
+ virtual css::uno::Any SAL_CALL getByIndex( sal_Int32 _nIndex ) override;
+
+// css::container::XNameContainer
+ virtual void SAL_CALL insertByName( const OUString& _rName, const css::uno::Any& aElement ) override;
+ virtual void SAL_CALL removeByName( const OUString& _rName ) override;
+
+// css::container::XNameReplace
+ virtual void SAL_CALL replaceByName( const OUString& _rName, const css::uno::Any& aElement ) override;
+
+// css::container::XNameAccess
+ virtual css::uno::Any SAL_CALL getByName( const OUString& aName ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getElementNames( ) override;
+ virtual sal_Bool SAL_CALL hasByName( const OUString& aName ) override;
+
+// css::container::XContainer
+ virtual void SAL_CALL addContainerListener( const css::uno::Reference< css::container::XContainerListener >& xListener ) override;
+ virtual void SAL_CALL removeContainerListener( const css::uno::Reference< css::container::XContainerListener >& xListener ) override;
+
+// css::container::XChild
+ virtual css::uno::Reference< css::uno::XInterface > SAL_CALL getParent( ) override;
+ virtual void SAL_CALL setParent( const css::uno::Reference< css::uno::XInterface >& Parent ) override;
+
+private:
+ /** quickly checks if there already is an element with a given name. No access to the configuration occurs, i.e.
+ if there is such an object which is not already loaded, it won't be loaded now.
+ @param _rName the object name to check
+ @return sal_True if there already exists such an object
+ */
+ inline bool checkExistence(const OUString& _rName);
+
+ void implAppend(
+ const OUString& _rName,
+ const OUString& _rDocumentLocation
+ );
+
+ void implRemove(const OUString& _rName);
+
+ void implReplace(
+ const OUString& _rName,
+ const OUString& _rNewLink);
+
+};
+
+inline bool OBookmarkContainer::checkExistence(const OUString& _rName)
+{
+ return m_aBookmarks.find(_rName) != m_aBookmarks.end();
+}
+
+} // namespace dbaccess
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/inc/callablestatement.hxx b/dbaccess/source/core/inc/callablestatement.hxx
new file mode 100644
index 000000000..58e21189a
--- /dev/null
+++ b/dbaccess/source/core/inc/callablestatement.hxx
@@ -0,0 +1,80 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <com/sun/star/sdbc/XRow.hpp>
+#include <com/sun/star/sdbc/XOutParameters.hpp>
+#include "preparedstatement.hxx"
+
+namespace dbaccess
+{
+
+ // OCallableStatement
+
+ class OCallableStatement : public OPreparedStatement,
+ public css::sdbc::XRow,
+ public css::sdbc::XOutParameters
+ {
+ public:
+ OCallableStatement(const css::uno::Reference< css::sdbc::XConnection > & _xConn,
+ const css::uno::Reference< css::uno::XInterface > & _xStatement)
+ :OPreparedStatement(_xConn, _xStatement){}
+
+ // css::lang::XTypeProvider
+ virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes() override;
+ virtual css::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId() override;
+
+ // css::uno::XInterface
+ virtual css::uno::Any SAL_CALL queryInterface( const css::uno::Type & rType ) override;
+ virtual void SAL_CALL acquire() noexcept override;
+ virtual void SAL_CALL release() noexcept override;
+
+ // css::lang::XServiceInfo
+ virtual OUString SAL_CALL getImplementationName( ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override;
+
+ // css::sdbc::XOutParameters
+ virtual void SAL_CALL registerOutParameter( sal_Int32 parameterIndex, sal_Int32 sqlType, const OUString& typeName ) override;
+ virtual void SAL_CALL registerNumericOutParameter( sal_Int32 parameterIndex, sal_Int32 sqlType, sal_Int32 scale ) override;
+
+ // css::sdbc::XRow
+ virtual sal_Bool SAL_CALL wasNull( ) override;
+ virtual OUString SAL_CALL getString( sal_Int32 columnIndex ) override;
+ virtual sal_Bool SAL_CALL getBoolean( sal_Int32 columnIndex ) override;
+ virtual sal_Int8 SAL_CALL getByte( sal_Int32 columnIndex ) override;
+ virtual sal_Int16 SAL_CALL getShort( sal_Int32 columnIndex ) override;
+ virtual sal_Int32 SAL_CALL getInt( sal_Int32 columnIndex ) override;
+ virtual sal_Int64 SAL_CALL getLong( sal_Int32 columnIndex ) override;
+ virtual float SAL_CALL getFloat( sal_Int32 columnIndex ) override;
+ virtual double SAL_CALL getDouble( sal_Int32 columnIndex ) override;
+ virtual css::uno::Sequence< sal_Int8 > SAL_CALL getBytes( sal_Int32 columnIndex ) override;
+ virtual css::util::Date SAL_CALL getDate( sal_Int32 columnIndex ) override;
+ virtual css::util::Time SAL_CALL getTime( sal_Int32 columnIndex ) override;
+ virtual css::util::DateTime SAL_CALL getTimestamp( sal_Int32 columnIndex ) override;
+ virtual css::uno::Reference< css::io::XInputStream > SAL_CALL getBinaryStream( sal_Int32 columnIndex ) override;
+ virtual css::uno::Reference< css::io::XInputStream > SAL_CALL getCharacterStream( sal_Int32 columnIndex ) override;
+ virtual css::uno::Any SAL_CALL getObject( sal_Int32 columnIndex, const css::uno::Reference< css::container::XNameAccess >& typeMap ) override;
+ virtual css::uno::Reference< css::sdbc::XRef > SAL_CALL getRef( sal_Int32 columnIndex ) override;
+ virtual css::uno::Reference< css::sdbc::XBlob > SAL_CALL getBlob( sal_Int32 columnIndex ) override;
+ virtual css::uno::Reference< css::sdbc::XClob > SAL_CALL getClob( sal_Int32 columnIndex ) override;
+ virtual css::uno::Reference< css::sdbc::XArray > SAL_CALL getArray( sal_Int32 columnIndex ) override;
+ };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/inc/column.hxx b/dbaccess/source/core/inc/column.hxx
new file mode 100644
index 000000000..aebc376b1
--- /dev/null
+++ b/dbaccess/source/core/inc/column.hxx
@@ -0,0 +1,217 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include "columnsettings.hxx"
+
+#include <com/sun/star/container/XChild.hpp>
+#include <com/sun/star/container/XNameAccess.hpp>
+#include <com/sun/star/container/XNamed.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+
+#include <comphelper/propertycontainer.hxx>
+#include <connectivity/TColumnsHelper.hxx>
+#include <connectivity/sdbcx/IRefreshable.hxx>
+#include <cppuhelper/basemutex.hxx>
+#include <cppuhelper/compbase.hxx>
+#include <cppuhelper/implbase1.hxx>
+
+namespace dbaccess
+{
+
+
+ // OColumn
+
+ typedef ::cppu::WeakComponentImplHelper< css::lang::XServiceInfo,
+ css::container::XNamed
+ > OColumnBase;
+
+ class OColumn :public cppu::BaseMutex
+ ,public OColumnBase
+ ,public ::comphelper::OPropertyContainer
+ ,public IPropertyContainer // convenience for the derived class which also derive from OColumnSettings
+ {
+ friend class OColumns;
+
+ protected:
+ // <properties>
+ OUString m_sName;
+ // </properties>
+
+ protected:
+ OColumn( const bool _bNameIsReadOnly );
+
+ public:
+ virtual ~OColumn() override;
+
+ // css::lang::XTypeProvider
+ virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes() override;
+ virtual css::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId() override = 0;
+
+ // css::uno::XInterface
+ virtual css::uno::Any SAL_CALL queryInterface( const css::uno::Type & rType ) override;
+ virtual void SAL_CALL acquire() noexcept override;
+ virtual void SAL_CALL release() noexcept override;
+
+ // css::beans::XPropertySet
+ virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo( ) override;
+
+ // cppu::OComponentHelper
+ virtual void SAL_CALL disposing() override;
+
+ // css::lang::XServiceInfo
+ virtual OUString SAL_CALL getImplementationName( ) override;
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override;
+
+ // XNamed
+ virtual OUString SAL_CALL getName( ) override;
+ virtual void SAL_CALL setName( const OUString& _rName ) override;
+
+ protected:
+ // IPropertyContainer
+ virtual void registerProperty( const OUString& _rName, sal_Int32 _nHandle, sal_Int32 _nAttributes, void* _pPointerToMember, const css::uno::Type& _rMemberType ) override;
+ virtual void registerMayBeVoidProperty( const OUString& _rName, sal_Int32 _nHandle, sal_Int32 _nAttributes, css::uno::Any* _pPointerToMember, const css::uno::Type& _rExpectedType ) override;
+ };
+
+ // IColumnFactory - used by OColumns for creating new columns
+ class SAL_NO_VTABLE IColumnFactory
+ {
+ public:
+ /** creates an OColumn object which should represent the column with a given name
+ */
+ virtual rtl::Reference<OColumn>
+ createColumn( const OUString& _rName ) const = 0;
+
+ /** creates a column descriptor object.
+
+ A column descriptor object is used to append new columns to the collection. If such an append
+ actually happened, columnAppended is called afterwards.
+ */
+ virtual css::uno::Reference< css::beans::XPropertySet > createColumnDescriptor() = 0;
+
+ /** notifies that a column, created from a column descriptor, has been appended
+ */
+ virtual void columnAppended( const css::uno::Reference< css::beans::XPropertySet >& _rxSourceDescriptor ) = 0;
+
+ /** notifies that a column with a given name has been dropped
+ */
+ virtual void columnDropped( const OUString& _sName ) = 0;
+
+ protected:
+ ~IColumnFactory() {}
+ };
+
+ class OContainerMediator;
+ typedef ::cppu::ImplHelper1< css::container::XChild > TXChild;
+ typedef connectivity::OColumnsHelper OColumns_BASE;
+
+ class OColumns : public OColumns_BASE
+ ,public TXChild
+ {
+ OContainerMediator* m_pMediator;
+
+ protected:
+ // comes from the driver can be null
+ css::uno::Reference< css::container::XNameAccess > m_xDrvColumns;
+ css::uno::WeakReference< css::uno::XInterface > m_xParent;
+ IColumnFactory* m_pColFactoryImpl;
+ ::connectivity::sdbcx::IRefreshableColumns* m_pRefreshColumns;
+
+ bool m_bInitialized : 1;
+ bool m_bAddColumn : 1;
+ bool m_bDropColumn : 1;
+
+ virtual void impl_refresh() override;
+ virtual connectivity::sdbcx::ObjectType createObject(const OUString& _rName) override;
+ virtual css::uno::Reference< css::beans::XPropertySet > createDescriptor() override;
+ virtual connectivity::sdbcx::ObjectType appendObject( const OUString& _rForName, const css::uno::Reference< css::beans::XPropertySet >& descriptor ) override;
+ virtual void dropObject(sal_Int32 _nPos, const OUString& _sElementName) override;
+
+ public:
+ connectivity::sdbcx::ObjectType createBaseObject(const OUString& _rName)
+ {
+ return OColumns_BASE::createObject(_rName);
+ }
+ /** flag which determines whether the container is filled or not
+ */
+ bool isInitialized() const { return m_bInitialized; }
+ void setInitialized() {m_bInitialized = true;}
+ void setMediator(OContainerMediator* _pMediator) { m_pMediator = _pMediator; }
+
+ public:
+ /** constructs an empty container without configuration location.
+ @param rParent the parent object. This instance will be used for refcounting, so the parent
+ cannot die before the container does.
+ @param _rMutex the mutex of the parent.
+ @param _bCaseSensitive the initial case sensitivity flag
+ @see setCaseSensitive
+ */
+ OColumns(
+ ::cppu::OWeakObject& _rParent,
+ ::osl::Mutex& _rMutex,
+ bool _bCaseSensitive,
+ const std::vector< OUString>& _rVector,
+ IColumnFactory* _pColFactory,
+ ::connectivity::sdbcx::IRefreshableColumns* _pRefresh,
+ bool _bAddColumn = false,
+ bool _bDropColumn = false,
+ bool _bUseHardRef = true);
+
+ OColumns(
+ ::cppu::OWeakObject& _rParent,
+ ::osl::Mutex& _rMutex,
+ const css::uno::Reference< css::container::XNameAccess >& _rxDrvColumns,
+ bool _bCaseSensitive,
+ const std::vector< OUString> &_rVector,
+ IColumnFactory* _pColFactory,
+ ::connectivity::sdbcx::IRefreshableColumns* _pRefresh,
+ bool _bAddColumn = false,
+ bool _bDropColumn = false,
+ bool _bUseHardRef = true);
+ virtual ~OColumns() override;
+
+ //XInterface
+ virtual css::uno::Any SAL_CALL queryInterface( const css::uno::Type & rType ) override;
+ virtual void SAL_CALL acquire() noexcept override { OColumns_BASE::acquire(); }
+ virtual void SAL_CALL release() noexcept override { OColumns_BASE::release(); }
+ //XTypeProvider
+ virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes( ) override;
+
+ // css::lang::XServiceInfo
+ virtual OUString SAL_CALL getImplementationName( ) override;
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override;
+
+ // css::container::XChild
+ virtual css::uno::Reference< css::uno::XInterface > SAL_CALL getParent( ) override;
+ virtual void SAL_CALL setParent( const css::uno::Reference< css::uno::XInterface >& Parent ) override;
+
+ void append(const OUString& rName, OColumn*);
+ void clearColumns();
+ // only the name is identical to ::cppu::OComponentHelper
+ virtual void disposing() override;
+
+ private:
+ using OColumns_BASE::setParent;
+ };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/inc/columnsettings.hxx b/dbaccess/source/core/inc/columnsettings.hxx
new file mode 100644
index 000000000..6b6c5d4c1
--- /dev/null
+++ b/dbaccess/source/core/inc/columnsettings.hxx
@@ -0,0 +1,88 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <com/sun/star/beans/XPropertySet.hpp>
+
+namespace dbaccess
+{
+
+ // TODO: move the following to comphelper/propertycontainerhelper.hxx
+ class IPropertyContainer
+ {
+ public:
+ virtual void registerProperty(
+ const OUString& _rName,
+ sal_Int32 _nHandle,
+ sal_Int32 _nAttributes,
+ void* _pPointerToMember,
+ const css::uno::Type& _rMemberType
+ ) = 0;
+
+ virtual void registerMayBeVoidProperty(
+ const OUString& _rName,
+ sal_Int32 _nHandle,
+ sal_Int32 _nAttributes,
+ css::uno::Any* _pPointerToMember,
+ const css::uno::Type& _rExpectedType
+ ) = 0;
+
+ protected:
+ ~IPropertyContainer() {}
+ };
+
+ // OColumnSettings
+ class OColumnSettings
+ {
+ // <properties>
+ css::uno::Any m_aWidth; // sal_Int32 or void
+ css::uno::Any m_aFormatKey; // sal_Int32 or void
+ css::uno::Any m_aRelativePosition; // sal_Int32 or void
+ css::uno::Any m_aAlignment; // sal_Int32 (css::awt::TextAlign) or void
+ css::uno::Any m_aHelpText; // the description of the column which is visible in the helptext of the column
+ css::uno::Any m_aControlDefault; // the default value which should be displayed as by a control when moving to a new row
+ css::uno::Reference< css::beans::XPropertySet >
+ m_xControlModel;
+ bool m_bHidden;
+ // </properties>
+
+ protected:
+ virtual ~OColumnSettings();
+
+ public:
+ OColumnSettings();
+
+ protected:
+ void registerProperties( IPropertyContainer& _rPropertyContainer );
+
+ /** determines whether the property with the given handle is handled by the class
+ */
+ static bool isColumnSettingProperty( const sal_Int32 _nPropertyHandle );
+ static bool isDefaulted( const sal_Int32 _nPropertyHandle, const css::uno::Any& _rPropertyValue );
+
+ public:
+ /** check if the persistent settings have their default value
+ */
+ static bool hasDefaultSettings( const css::uno::Reference< css::beans::XPropertySet >& _rxColumn );
+ };
+
+} // namespace dbaccess
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/inc/commandbase.hxx b/dbaccess/source/core/inc/commandbase.hxx
new file mode 100644
index 000000000..1a0bd91d8
--- /dev/null
+++ b/dbaccess/source/core/inc/commandbase.hxx
@@ -0,0 +1,50 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <com/sun/star/uno/Sequence.hxx>
+#include <com/sun/star/beans/PropertyValue.hpp>
+
+namespace dbaccess
+{
+
+// OCommandBase - a base class (in fact just a container for some members)
+// for classes implementing the sdb.CommandDefinition service
+class OCommandBase
+{
+public: // need public access
+// <properties>
+ css::uno::Sequence< css::beans::PropertyValue>
+ m_aLayoutInformation;
+ OUString m_sCommand;
+ bool m_bEscapeProcessing; // no BitField! So it can be used with an OPropertyStateContainer
+ OUString m_sUpdateTableName;
+ OUString m_sUpdateSchemaName;
+ OUString m_sUpdateCatalogName;
+// </properties>
+
+protected:
+ OCommandBase() : m_bEscapeProcessing(true) { }
+
+};
+
+} // namespace dbaccess
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/inc/composertools.hxx b/dbaccess/source/core/inc/composertools.hxx
new file mode 100644
index 000000000..337064757
--- /dev/null
+++ b/dbaccess/source/core/inc/composertools.hxx
@@ -0,0 +1,121 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <rtl/ustrbuf.hxx>
+#include <osl/diagnose.h>
+
+namespace dbaccess
+{
+
+ // TokenComposer
+ struct TokenComposer
+ {
+ private:
+ #ifdef DBG_UTIL
+ bool m_bUsed;
+ #endif
+
+ protected:
+ OUStringBuffer m_aBuffer;
+
+ public:
+ OUString getComposedAndClear()
+ {
+ #ifdef DBG_UTIL
+ m_bUsed = true;
+ #endif
+ return m_aBuffer.makeStringAndClear();
+ }
+
+ void clear()
+ {
+ #ifdef DBG_UTIL
+ m_bUsed = false;
+ #endif
+ m_aBuffer.setLength(0);
+ }
+
+ public:
+ TokenComposer()
+ #ifdef DBG_UTIL
+ :m_bUsed( false )
+ #endif
+ {
+ }
+
+ virtual ~TokenComposer()
+ {
+ }
+
+ TokenComposer(TokenComposer const &) = default;
+ TokenComposer(TokenComposer &&) = default;
+ TokenComposer & operator =(TokenComposer const &) = default;
+ TokenComposer & operator =(TokenComposer &&) = default;
+
+ void operator() (const OUString& lhs)
+ {
+ append(lhs);
+ }
+
+ void append( const OUString& lhs )
+ {
+ #ifdef DBG_UTIL
+ OSL_ENSURE( !m_bUsed, "FilterCreator::append: already used up!" );
+ #endif
+ if ( !lhs.isEmpty() )
+ {
+ if ( !m_aBuffer.isEmpty() )
+ appendNonEmptyToNonEmpty( lhs );
+ else
+ m_aBuffer.append( lhs );
+ }
+ }
+
+ /// append the given part. Only to be called when both the part and our buffer so far are not empty
+ virtual void appendNonEmptyToNonEmpty( const OUString& lhs ) = 0;
+ };
+
+ // FilterCreator
+ struct FilterCreator : public TokenComposer
+ {
+ virtual void appendNonEmptyToNonEmpty( const OUString& lhs ) override
+ {
+ m_aBuffer.insert( 0, ' ' );
+ m_aBuffer.insert( 0, '(' );
+ m_aBuffer.append( " ) AND ( " );
+ m_aBuffer.append( lhs );
+ m_aBuffer.append( " )" );
+ }
+ };
+
+ // FilterCreator
+ struct OrderCreator : public TokenComposer
+ {
+ virtual void appendNonEmptyToNonEmpty( const OUString& lhs ) override
+ {
+ m_aBuffer.append( ", " );
+ m_aBuffer.append( lhs );
+ }
+ };
+
+} // namespace dbaccess
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/inc/containerapprove.hxx b/dbaccess/source/core/inc/containerapprove.hxx
new file mode 100644
index 000000000..f780e224a
--- /dev/null
+++ b/dbaccess/source/core/inc/containerapprove.hxx
@@ -0,0 +1,57 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <rtl/ustring.hxx>
+
+#include <memory>
+
+namespace dbaccess
+{
+
+ // IContainerApprove
+ /** interface for approving elements to be inserted into a container
+
+ On the long run, one could imagine that this interface completely encapsulates
+ container/element approvals in all our various container classes herein (document
+ containers, definition containers, table containers, query containers,
+ command definition containers, bookmark containers). This would decrease coupling
+ of the respective classes.
+ */
+ class SAL_NO_VTABLE IContainerApprove
+ {
+ public:
+ virtual ~IContainerApprove() {}
+
+ /** approves a given element for insertion into the container
+ @param _rName
+ specifies the name under which the element is going to be inserted
+ @throws Exception
+ if the name or the object are invalid, or not eligible for insertion
+ into the container
+ */
+ virtual void approveElement( const OUString& _rName ) = 0;
+ };
+
+ typedef std::shared_ptr< IContainerApprove > PContainerApprove;
+
+} // namespace dbaccess
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/inc/databasecontext.hxx b/dbaccess/source/core/inc/databasecontext.hxx
new file mode 100644
index 000000000..e15585c81
--- /dev/null
+++ b/dbaccess/source/core/inc/databasecontext.hxx
@@ -0,0 +1,180 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <sal/config.h>
+
+#include <config_features.h>
+
+#include <map>
+
+#include "ModelImpl.hxx"
+
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/lang/XUnoTunnel.hpp>
+#include <com/sun/star/sdb/XDatabaseContext.hpp>
+#include <com/sun/star/sdb/XDatabaseRegistrations.hpp>
+#include <com/sun/star/uno/XAggregation.hpp>
+
+#if HAVE_FEATURE_SCRIPTING
+#include <basic/basrdll.hxx>
+#endif
+
+#include <basic/basicmanagerrepository.hxx>
+#include <cppuhelper/compbase.hxx>
+
+// needed for registration
+namespace com::sun::star {
+ namespace lang
+ {
+ class XMultiServiceFactory;
+ class IllegalArgumentException;
+ }
+}
+
+namespace dbaccess
+{
+class DatabaseDocumentLoader;
+
+typedef ::cppu::WeakComponentImplHelper< css::lang::XServiceInfo
+ , css::sdb::XDatabaseContext
+ , css::lang::XUnoTunnel
+ > DatabaseAccessContext_Base;
+
+class ODatabaseContext :public DatabaseAccessContext_Base
+ ,public ::basic::BasicManagerCreationListener
+{
+private:
+ /** loads the given object from the given URL
+ @throws WrappedTargetException
+ if an error occurs accessing the URL via the UCB
+ */
+ css::uno::Reference< css::uno::XInterface > loadObjectFromURL(const OUString& _rName,const OUString& _sURL);
+ css::uno::Reference< css::uno::XInterface > getObject( const OUString& _rURL );
+
+ /** sets all properties which were transient at the data source. e.g. password
+ @param _sURL The file URL of the data source
+ @param _xObject The data source itself.
+ */
+ void setTransientProperties(const OUString& _sURL, ODatabaseModelImpl& _rDataSourceModel );
+
+ /** creates a new data source
+ */
+ css::uno::Reference< css::uno::XInterface >
+ impl_createNewDataSource();
+
+#if HAVE_FEATURE_SCRIPTING
+ BasicDLL m_aBasicDLL;
+#endif
+
+protected:
+ ::osl::Mutex m_aMutex;
+ css::uno::Reference< css::uno::XComponentContext >
+ m_aContext;
+
+ css::uno::Reference< css::uno::XAggregation >
+ m_xDBRegistrationAggregate;
+ css::uno::Reference< css::sdb::XDatabaseRegistrations >
+ m_xDatabaseRegistrations;
+
+ typedef std::map<OUString, ODatabaseModelImpl*> ObjectCache;
+ ObjectCache m_aDatabaseObjects;
+
+ typedef std::map< OUString, css::uno::Sequence< css::beans::PropertyValue > > PropertyCache;
+ PropertyCache m_aDatasourceProperties;
+ // as we hold our data sources weak, we have to cache all properties on the data sources which are
+ // transient but stored as long as the session lasts. The database context is the session (as it lives
+ // as long as the session does), but the data sources may die before the session does, and then be
+ // recreated afterwards. So it's our (the context's) responsibility to store the session-persistent
+ // properties.
+
+ ::comphelper::OInterfaceContainerHelper3<css::container::XContainerListener> m_aContainerListeners;
+ rtl::Reference<DatabaseDocumentLoader> m_xDatabaseDocumentLoader;
+
+public:
+ explicit ODatabaseContext( const css::uno::Reference< css::uno::XComponentContext >& );
+ virtual ~ODatabaseContext() override;
+
+ // OComponentHelper
+ virtual void SAL_CALL disposing() override;
+
+ // XSingleServiceFactory
+ virtual css::uno::Reference< css::uno::XInterface > SAL_CALL createInstance( ) override;
+ virtual css::uno::Reference< css::uno::XInterface > SAL_CALL createInstanceWithArguments( const css::uno::Sequence< css::uno::Any >& _rArguments ) override;
+
+ // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName( ) override;
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override;
+
+ // XElementAccess
+ virtual css::uno::Type SAL_CALL getElementType( ) override;
+ virtual sal_Bool SAL_CALL hasElements( ) override;
+
+ // XEnumerationAccess
+ virtual css::uno::Reference< css::container::XEnumeration > SAL_CALL createEnumeration( ) override;
+
+ // XNameAccess
+ virtual css::uno::Any SAL_CALL getByName( const OUString& aName ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getElementNames( ) override;
+ virtual sal_Bool SAL_CALL hasByName( const OUString& aName ) override;
+
+ // XNamingService
+ virtual css::uno::Reference< css::uno::XInterface > SAL_CALL getRegisteredObject( const OUString& Name ) override;
+ virtual void SAL_CALL registerObject( const OUString& Name, const css::uno::Reference< css::uno::XInterface >& Object ) override;
+ virtual void SAL_CALL revokeObject( const OUString& Name ) override;
+
+ // XDatabaseRegistrations
+ virtual sal_Bool SAL_CALL hasRegisteredDatabase( const OUString& Name ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getRegistrationNames() override;
+ virtual OUString SAL_CALL getDatabaseLocation( const OUString& Name ) override;
+ virtual void SAL_CALL registerDatabaseLocation( const OUString& Name, const OUString& Location ) override;
+ virtual void SAL_CALL revokeDatabaseLocation( const OUString& Name ) override;
+ virtual void SAL_CALL changeDatabaseLocation( const OUString& Name, const OUString& NewLocation ) override;
+ virtual sal_Bool SAL_CALL isDatabaseRegistrationReadOnly( const OUString& Name ) override;
+ virtual void SAL_CALL addDatabaseRegistrationsListener( const css::uno::Reference< css::sdb::XDatabaseRegistrationsListener >& Listener ) override;
+ virtual void SAL_CALL removeDatabaseRegistrationsListener( const css::uno::Reference< css::sdb::XDatabaseRegistrationsListener >& Listener ) override;
+
+ // XContainer
+ virtual void SAL_CALL addContainerListener( const css::uno::Reference< css::container::XContainerListener >& xListener ) override;
+ virtual void SAL_CALL removeContainerListener( const css::uno::Reference< css::container::XContainerListener >& xListener ) override;
+
+ // css::lang::XUnoTunnel
+ virtual sal_Int64 SAL_CALL getSomething( const css::uno::Sequence< sal_Int8 >& aIdentifier ) override;
+ static const css::uno::Sequence< sal_Int8 > & getUnoTunnelId();
+
+ void registerDatabaseDocument( ODatabaseModelImpl& _rModelImpl);
+ void revokeDatabaseDocument( const ODatabaseModelImpl& _rModelImpl);
+ void databaseDocumentURLChange(const OUString& _sOldName, const OUString& _sNewName);
+ void storeTransientProperties( ODatabaseModelImpl& _rModelImpl);
+ void appendAtTerminateListener(const ODatabaseModelImpl& _rDataSourceModel);
+ void removeFromTerminateListener(const ODatabaseModelImpl& _rDataSourceModel);
+
+private:
+ // BasicManagerCreationListener
+ virtual void onBasicManagerCreated(
+ const css::uno::Reference< css::frame::XModel >& _rxForDocument,
+ BasicManager& _rBasicManager
+ ) override;
+};
+
+} // namespace dbaccess
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/inc/datasettings.hxx b/dbaccess/source/core/inc/datasettings.hxx
new file mode 100644
index 000000000..8e24ebb71
--- /dev/null
+++ b/dbaccess/source/core/inc/datasettings.hxx
@@ -0,0 +1,77 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <com/sun/star/awt/FontDescriptor.hpp>
+#include <rtl/ustring.hxx>
+#include <comphelper/propertystatecontainer.hxx>
+
+namespace dbaccess
+{
+
+// ODataSettings_Base - a base class which implements the property member
+// for an object implementing the sdb::DataSettings
+// service
+// the properties have to be registered when used
+class ODataSettings_Base
+{
+public:
+// <properties>
+ OUString m_sFilter;
+ OUString m_sHavingClause;
+ OUString m_sGroupBy;
+ OUString m_sOrder;
+ bool m_bApplyFilter; // no BitField ! the base class needs a pointer to this member !
+ bool m_bAutoGrow;
+ css::awt::FontDescriptor m_aFont;
+ css::uno::Any m_aRowHeight;
+ css::uno::Any m_aTextColor;
+ css::uno::Any m_aTextLineColor;
+ sal_Int16 m_nFontEmphasis;
+ sal_Int16 m_nFontRelief;
+// </properties>
+
+protected:
+ ODataSettings_Base();
+ ODataSettings_Base(const ODataSettings_Base& _rSource) = delete;
+ ~ODataSettings_Base();
+};
+// ODataSettings - a base class which implements the property handling
+// for an object implementing the sdb::DataSettings
+// service
+
+class ODataSettings : public ::comphelper::OPropertyStateContainer
+ , public ODataSettings_Base
+{
+ bool m_bQuery;
+protected:
+ ODataSettings(::cppu::OBroadcastHelper& _rBHelper,bool _bQuery = false);
+ virtual void getPropertyDefaultByHandle( sal_Int32 _nHandle, css::uno::Any& _rDefault ) const override;
+
+ /** register the properties from the param given. The parameter instance must be alive as long as its object lives.
+ @param _pItem
+ The database settings, can be <br>this</br>
+ */
+ void registerPropertiesFor(ODataSettings_Base* _pItem);
+};
+
+} // namespace dbaccess
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/inc/definitioncolumn.hxx b/dbaccess/source/core/inc/definitioncolumn.hxx
new file mode 100644
index 000000000..4d7ff3e17
--- /dev/null
+++ b/dbaccess/source/core/inc/definitioncolumn.hxx
@@ -0,0 +1,291 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "column.hxx"
+#include "columnsettings.hxx"
+
+#include <com/sun/star/sdbc/DataType.hpp>
+#include <com/sun/star/sdbc/ColumnValue.hpp>
+#include <com/sun/star/sdbc/XConnection.hpp>
+#include <com/sun/star/container/XChild.hpp>
+
+#include <comphelper/IdPropArrayHelper.hxx>
+#include <comphelper/proparrhlp.hxx>
+#include <comphelper/uno3.hxx>
+#include <cppuhelper/implbase1.hxx>
+
+namespace dbaccess
+{
+
+ typedef ::cppu::ImplHelper1< css::container::XChild > TXChild;
+ // OTableColumnDescriptor
+ /**
+ * provides the properties for description. A descriptor could be used to create a new table column.
+ */
+ class OTableColumnDescriptor : public OColumn
+ ,public OColumnSettings
+ ,public ::comphelper::OPropertyArrayUsageHelper < OTableColumnDescriptor >
+ ,public TXChild
+ {
+ css::uno::Reference< css::uno::XInterface > m_xParent;
+ const bool m_bActAsDescriptor;
+
+ protected:
+ // <properties>
+ OUString m_aTypeName;
+ OUString m_aDescription;
+ OUString m_aDefaultValue;
+ OUString m_aAutoIncrementValue;
+ sal_Int32 m_nType;
+ sal_Int32 m_nPrecision;
+ sal_Int32 m_nScale;
+ sal_Int32 m_nIsNullable;
+ bool m_bAutoIncrement;
+ bool m_bRowVersion;
+ bool m_bCurrency;
+ // </properties>
+
+ public:
+ OTableColumnDescriptor( const bool _bActAsDescriptor )
+ :OColumn( !_bActAsDescriptor )
+ ,m_bActAsDescriptor( _bActAsDescriptor )
+ ,m_nType( css::sdbc::DataType::SQLNULL )
+ ,m_nPrecision( 0 )
+ ,m_nScale( 0 )
+ ,m_nIsNullable( css::sdbc::ColumnValue::NULLABLE_UNKNOWN )
+ ,m_bAutoIncrement( false )
+ ,m_bRowVersion( false )
+ ,m_bCurrency( false )
+ {
+ impl_registerProperties();
+ }
+
+ DECLARE_XINTERFACE( )
+
+ // css::lang::XTypeProvider
+ virtual css::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId() override;
+
+ // css::lang::XServiceInfo
+ virtual OUString SAL_CALL getImplementationName( ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override;
+
+ // css::container::XChild
+ virtual css::uno::Reference< css::uno::XInterface > SAL_CALL getParent( ) override;
+ virtual void SAL_CALL setParent( const css::uno::Reference< css::uno::XInterface >& Parent ) override;
+
+ // ::comphelper::OPropertyArrayUsageHelper
+ virtual ::cppu::IPropertyArrayHelper* createArrayHelper() const override;
+
+ // ::cppu::OPropertySetHelper
+ virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper() override;
+ virtual void SAL_CALL setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const css::uno::Any& rValue ) override;
+
+ private:
+ void impl_registerProperties();
+ };
+
+ // OTableColumn
+ class OTableColumn;
+ typedef ::comphelper::OPropertyArrayUsageHelper < OTableColumn > OTableColumn_PBase;
+ /** describes a column of a table
+ */
+ class OTableColumn :public OTableColumnDescriptor
+ ,public OTableColumn_PBase
+ {
+ protected:
+ virtual ~OTableColumn() override;
+
+ public:
+ OTableColumn(const OUString& _rName);
+
+ // XTypeProvider
+ virtual css::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId() override;
+
+ // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName( ) override;
+
+ // OPropertyArrayUsageHelper
+ virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper() override;
+ virtual ::cppu::IPropertyArrayHelper* createArrayHelper() const override;
+ };
+
+ // OQueryColumn
+ class OQueryColumn;
+ typedef ::comphelper::OPropertyArrayUsageHelper< OQueryColumn > OQueryColumn_PBase;
+ /** a column of a Query, with additional information obtained from parsing the query statement
+ */
+ class OQueryColumn :public OTableColumnDescriptor
+ ,public OQueryColumn_PBase
+ {
+ // <properties>
+ OUString m_sCatalogName;
+ OUString m_sSchemaName;
+ OUString m_sTableName;
+ OUString m_sRealName;
+ OUString m_sLabel;
+ // </properties>
+
+ css::uno::Reference< css::beans::XPropertySet > m_xOriginalTableColumn;
+
+ protected:
+ virtual ~OQueryColumn() override;
+
+ public:
+ OQueryColumn(
+ const css::uno::Reference< css::beans::XPropertySet>& _rxParserColumn,
+ const css::uno::Reference< css::sdbc::XConnection >& _rxConnection,
+ const OUString &i_sLabel
+ );
+
+ // XTypeProvider
+ virtual css::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId() override;
+
+ // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName( ) override;
+
+ // *Property*
+ virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper() override;
+ virtual ::cppu::IPropertyArrayHelper* createArrayHelper() const override;
+ virtual void SAL_CALL getFastPropertyValue( css::uno::Any& rValue, sal_Int32 nHandle ) const override;
+
+ private:
+ css::uno::Reference< css::beans::XPropertySet >
+ impl_determineOriginalTableColumn(
+ const css::uno::Reference< css::sdbc::XConnection >& _rxConnection
+ );
+
+ using ::cppu::OPropertySetHelper::getFastPropertyValue;
+ };
+
+ // OColumnWrapper
+ /**
+ * describes all properties for a columns of a table. Only the view parts are provided
+ * directly, all the other parts are derived from a driver implementation
+ */
+ class OColumnWrapper :public OColumn
+ {
+ protected:
+ // definition which is provided by a driver!
+ css::uno::Reference< css::beans::XPropertySet >
+ m_xAggregate;
+
+ sal_Int32 m_nColTypeID;
+
+ protected:
+ OColumnWrapper( const css::uno::Reference< css::beans::XPropertySet >& _rCol, const bool _bNameIsReadOnly );
+ virtual ~OColumnWrapper() override;
+
+ public:
+ virtual void SAL_CALL getFastPropertyValue(
+ css::uno::Any& rValue,
+ sal_Int32 nHandle
+ ) const override;
+ virtual sal_Bool SAL_CALL convertFastPropertyValue(
+ css::uno::Any & rConvertedValue,
+ css::uno::Any & rOldValue,
+ sal_Int32 nHandle,
+ const css::uno::Any& rValue ) override;
+ virtual void SAL_CALL setFastPropertyValue_NoBroadcast(
+ sal_Int32 nHandle,
+ const css::uno::Any& rValue
+ ) override;
+
+ protected:
+ OUString impl_getPropertyNameFromHandle( const sal_Int32 _nHandle ) const;
+
+ protected:
+ using OColumn::getFastPropertyValue;
+ };
+
+ // OTableColumnDescriptorWrapper
+ /**
+ * provides the properties for description. A descriptor could be used to create a new table column.
+ */
+ class OTableColumnDescriptorWrapper :public OColumnWrapper
+ ,public OColumnSettings
+ ,public ::comphelper::OIdPropertyArrayUsageHelper < OTableColumnDescriptorWrapper >
+ {
+ const bool m_bPureWrap;
+ const bool m_bIsDescriptor;
+
+ public:
+ OTableColumnDescriptorWrapper(const css::uno::Reference< css::beans::XPropertySet >& rCol,
+ const bool _bPureWrap, const bool _bIsDescriptor );
+
+ // css::lang::XTypeProvider
+ virtual css::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId() override;
+
+ // css::lang::XServiceInfo
+ virtual OUString SAL_CALL getImplementationName( ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override;
+
+ // OIdPropertyArrayUsageHelper
+ virtual ::cppu::IPropertyArrayHelper* createArrayHelper(sal_Int32 nId) const override;
+
+ // cppu::OPropertySetHelper
+ virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper() override;
+ virtual void SAL_CALL getFastPropertyValue(
+ css::uno::Any& rValue,
+ sal_Int32 nHandle
+ ) const override;
+ virtual sal_Bool SAL_CALL convertFastPropertyValue(
+ css::uno::Any & rConvertedValue,
+ css::uno::Any & rOldValue,
+ sal_Int32 nHandle,
+ const css::uno::Any& rValue ) override;
+ virtual void SAL_CALL setFastPropertyValue_NoBroadcast(
+ sal_Int32 nHandle,
+ const css::uno::Any& rValue
+ ) override;
+
+ protected:
+ using OColumnWrapper::getFastPropertyValue;
+ };
+
+ // OTableColumnWrapper
+ /**
+ * describes all properties for a columns of a table. Only the view parts are provided
+ * directly, all the other parts are derived from a driver implementation
+ */
+ class OTableColumnWrapper :public OTableColumnDescriptorWrapper
+ ,public ::comphelper::OIdPropertyArrayUsageHelper < OTableColumnWrapper >
+ {
+ protected:
+ virtual ~OTableColumnWrapper() override;
+
+ public:
+ OTableColumnWrapper( const css::uno::Reference< css::beans::XPropertySet >& rCol,
+ const css::uno::Reference< css::beans::XPropertySet >& rColDefinition,
+ const bool _bPureWrap );
+
+ // css::lang::XTypeProvider
+ virtual css::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId() override;
+
+ // css::lang::XServiceInfo
+ virtual OUString SAL_CALL getImplementationName( ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override;
+
+ // OIdPropertyArrayUsageHelper
+ virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper() override;
+ virtual ::cppu::IPropertyArrayHelper* createArrayHelper(sal_Int32 nId) const override;
+ };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/inc/definitioncontainer.hxx b/dbaccess/source/core/inc/definitioncontainer.hxx
new file mode 100644
index 000000000..9c871601a
--- /dev/null
+++ b/dbaccess/source/core/inc/definitioncontainer.hxx
@@ -0,0 +1,323 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <sal/config.h>
+
+#include <map>
+#include <vector>
+
+#include <cppuhelper/implbase7.hxx>
+#include <osl/mutex.hxx>
+#include <com/sun/star/container/XNameContainer.hpp>
+#include <com/sun/star/container/XContainer.hpp>
+#include <com/sun/star/container/XEnumerationAccess.hpp>
+#include <com/sun/star/container/XIndexAccess.hpp>
+#include <com/sun/star/beans/XPropertyChangeListener.hpp>
+#include <com/sun/star/beans/XVetoableChangeListener.hpp>
+#include <com/sun/star/container/XContainerApproveBroadcaster.hpp>
+#include "ContentHelper.hxx"
+#include "containerapprove.hxx"
+#include <comphelper/uno3.hxx>
+#include <comphelper/interfacecontainer2.hxx>
+
+namespace dbaccess
+{
+
+class ODefinitionContainer_Impl : public OContentHelper_Impl
+{
+public:
+ typedef std::map< OUString, TContentPtr > NamedDefinitions;
+ typedef NamedDefinitions::iterator iterator;
+ typedef NamedDefinitions::const_iterator const_iterator;
+
+private:
+ NamedDefinitions m_aDefinitions;
+
+public:
+ size_t size() const { return m_aDefinitions.size(); }
+
+ const_iterator begin() const { return m_aDefinitions.begin(); }
+ const_iterator end() const { return m_aDefinitions.end(); }
+
+ const_iterator find( const OUString& _rName ) const { return m_aDefinitions.find( _rName ); }
+ const_iterator find( const TContentPtr& _pDefinition ) const;
+
+ void erase( const OUString& _rName ) { m_aDefinitions.erase( _rName ); }
+ void erase( const TContentPtr& _pDefinition );
+
+ void insert( const OUString& _rName, TContentPtr _pDefinition )
+ {
+ m_aDefinitions.emplace( _rName, _pDefinition );
+ }
+
+private:
+ iterator find( const TContentPtr& _pDefinition );
+ // (for the moment, this is private. Make it public if needed. If really needed.)
+};
+
+// ODefinitionContainer - base class of collections of database definition
+// documents
+typedef ::cppu::ImplHelper7 < css::container::XIndexAccess
+ , css::container::XNameContainer
+ , css::container::XEnumerationAccess
+ , css::container::XContainer
+ , css::container::XContainerApproveBroadcaster
+ , css::beans::XPropertyChangeListener
+ , css::beans::XVetoableChangeListener
+ > ODefinitionContainer_Base;
+
+class ODefinitionContainer
+ :public OContentHelper
+ ,public ODefinitionContainer_Base
+{
+protected:
+ typedef std::map< OUString, css::uno::WeakReference< css::ucb::XContent > > Documents;
+
+ enum ContainerOperation
+ {
+ E_REPLACED,
+ E_REMOVED,
+ E_INSERTED
+ };
+
+ enum ListenerType
+ {
+ ApproveListeners,
+ ContainerListemers
+ };
+
+private:
+ PContainerApprove m_pElementApproval;
+
+protected:
+ // we can't just hold a vector of XContentRefs, as after initialization they're all empty
+ // cause we load them only on access
+ std::vector<Documents::iterator>
+ m_aDocuments; // for an efficient index access
+ Documents m_aDocumentMap; // for an efficient name access
+
+ ::comphelper::OInterfaceContainerHelper2
+ m_aApproveListeners;
+ ::comphelper::OInterfaceContainerHelper2
+ m_aContainerListeners;
+
+ bool m_bInPropertyChange;
+ bool m_bCheckSlash;
+
+protected:
+ /** Additionally to our own approvals which new elements must pass, derived classes
+ can specify an additional approval instance here.
+
+ Every time a new element is inserted into the container (or an element is replaced
+ with a new one), this new element must pass our own internal approval, plus the approval
+ given here.
+ */
+ void setElementApproval( PContainerApprove _pElementApproval ) { m_pElementApproval = _pElementApproval; }
+ const PContainerApprove& getElementApproval() const { return m_pElementApproval; }
+
+protected:
+ virtual ~ODefinitionContainer() override;
+
+ const ODefinitionContainer_Impl& getDefinitions() const
+ {
+ return dynamic_cast< const ODefinitionContainer_Impl& >( *m_pImpl );
+ }
+
+ ODefinitionContainer_Impl& getDefinitions()
+ {
+ return dynamic_cast< ODefinitionContainer_Impl& >( *m_pImpl );
+ }
+public:
+ /** constructs the container.
+ */
+ ODefinitionContainer(
+ const css::uno::Reference< css::uno::XComponentContext >& _xORB
+ , const css::uno::Reference< css::uno::XInterface >& _xParentContainer
+ , const TContentPtr& _pImpl
+ , bool _bCheckSlash = true
+ );
+
+// css::uno::XInterface
+ DECLARE_XINTERFACE( )
+
+ virtual css::uno::Sequence<css::uno::Type> SAL_CALL getTypes() override;
+ virtual css::uno::Sequence<sal_Int8> SAL_CALL getImplementationId() override;
+
+// css::lang::XServiceInfo
+ virtual OUString SAL_CALL getImplementationName( ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override;
+
+// css::container::XElementAccess
+ virtual css::uno::Type SAL_CALL getElementType( ) override;
+ virtual sal_Bool SAL_CALL hasElements( ) override;
+
+// css::container::XEnumerationAccess
+ virtual css::uno::Reference< css::container::XEnumeration > SAL_CALL createEnumeration( ) override;
+
+// css::container::XIndexAccess
+ virtual sal_Int32 SAL_CALL getCount( ) override;
+ virtual css::uno::Any SAL_CALL getByIndex( sal_Int32 _nIndex ) override;
+
+// css::container::XNameContainer
+ virtual void SAL_CALL insertByName( const OUString& _rName, const css::uno::Any& aElement ) override;
+ virtual void SAL_CALL removeByName( const OUString& _rName ) override;
+
+// css::container::XNameReplace
+ virtual void SAL_CALL replaceByName( const OUString& _rName, const css::uno::Any& aElement ) override;
+
+// css::container::XNameAccess
+ virtual css::uno::Any SAL_CALL getByName( const OUString& aName ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getElementNames( ) override;
+ virtual sal_Bool SAL_CALL hasByName( const OUString& aName ) override;
+
+// css::container::XContainer
+ virtual void SAL_CALL addContainerListener( const css::uno::Reference< css::container::XContainerListener >& xListener ) override;
+ virtual void SAL_CALL removeContainerListener( const css::uno::Reference< css::container::XContainerListener >& xListener ) override;
+
+ // XContainerApproveBroadcaster
+ virtual void SAL_CALL addContainerApproveListener( const css::uno::Reference< css::container::XContainerApproveListener >& Listener ) override;
+ virtual void SAL_CALL removeContainerApproveListener( const css::uno::Reference< css::container::XContainerApproveListener >& Listener ) override;
+
+// css::lang::XEventListener
+ virtual void SAL_CALL disposing( const css::lang::EventObject& Source ) override;
+
+ // XPropertyChangeListener
+ virtual void SAL_CALL propertyChange( const css::beans::PropertyChangeEvent& evt ) override;
+ // XVetoableChangeListener
+ virtual void SAL_CALL vetoableChange( const css::beans::PropertyChangeEvent& aEvent ) override;
+
+protected:
+ // helper
+ virtual void SAL_CALL disposing() override;
+
+ /** create an object from its persistent data within the configuration. To be overwritten by derived classes.
+ @param _rName the name the object has within the container
+ @return the newly created object or an empty reference if something went wrong
+ */
+ virtual css::uno::Reference< css::ucb::XContent > createObject(
+ const OUString& _rName) = 0;
+
+ /** get the object specified by the given name. If desired, the object will be read if not already done so.<BR>
+ @param _rName the object name
+ @param _bReadIfNecessary if sal_True, the object will be created if necessary
+ @return the property set interface of the object. Usually the return value is not NULL, but
+ if so, then the object could not be read from the configuration
+ @throws NoSuchElementException if there is no object with the given name.
+ @see createObject
+ */
+ css::uno::Reference< css::ucb::XContent >
+ implGetByName(const OUString& _rName, bool _bCreateIfNecessary);
+
+ /** quickly checks if there already is an element with a given name. No access to the configuration occurs, i.e.
+ if there is such an object which is not already loaded, it won't be loaded now.
+ @param _rName the object name to check
+ @return sal_True if there already exists such an object
+ */
+ virtual bool checkExistence(const OUString& _rName);
+
+ /** append a new object to the container. No plausibility checks are done, e.g. if the object is non-NULL or
+ if the name is already used by another object or anything like this. This method is for derived classes
+ which may support different methods to create and/or append objects, and don't want to deal with the
+ internal structures of this class.<BR>
+ The old component will not be disposed, this is the callers responsibility, too.
+ @param _rName the name of the new object
+ @param _rxNewObject the new object (not surprising, is it ?)
+ @see createConfigKey
+ @see implReplace
+ @see implRemove
+ */
+ void implAppend(
+ const OUString& _rName,
+ const css::uno::Reference< css::ucb::XContent >& _rxNewObject
+ );
+
+ /** remove all references to an object from the container. No plausibility checks are done, e.g. whether
+ or not there exists an object with the given name. This is the responsibility of the caller.<BR>
+ Additionally the node for the given object will be removed from the registry (including all sub nodes).<BR>
+ The old component will not be disposed, this is the callers responsibility, too.
+ @param _rName the objects name
+ @see implReplace
+ @see implAppend
+ */
+ void implRemove(const OUString& _rName);
+
+ /** remove an object in the container. No plausibility checks are done, e.g. whether
+ or not there exists an object with the given name or the object is non-NULL. This is the responsibility of the caller.<BR>
+ Additionally all object-related information within the registry will be deleted. The new object config node,
+ where the caller may want to store the new objects information, is returned.<BR>
+ The old component will not be disposed, this is the callers responsibility, too.
+ @param _rName the objects name
+ @param _rxNewObject the new object
+ @param _rNewObjectNode the configuration node where the new object may be stored
+ @see implAppend
+ @see implRemove
+ */
+ void implReplace(
+ const OUString& _rName,
+ const css::uno::Reference< css::ucb::XContent >& _rxNewObject
+ );
+
+ /** notifies our container/approve listeners
+ */
+ void notifyByName(
+ ::osl::ResettableMutexGuard& _rGuard,
+ const OUString& _rName,
+ const css::uno::Reference< css::ucb::XContent >& _xNewElement,
+ const css::uno::Reference< css::ucb::XContent >& xOldElement,
+ ContainerOperation _eOperation,
+ ListenerType _eType
+ );
+
+ operator css::uno::Reference< css::uno::XInterface > () const
+ {
+ return const_cast< XContainer* >( static_cast< const XContainer* >( this ) );
+ }
+
+private:
+ void addObjectListener(const css::uno::Reference< css::ucb::XContent >& _xNewObject);
+ void removeObjectListener(const css::uno::Reference< css::ucb::XContent >& _xNewObject);
+
+ /** approve that the object given may be inserted into the container.
+ Should be overridden by derived classes,
+ the default implementation just checks the object to be non-void.
+
+ @throws IllegalArgumentException
+ if the name or the object are invalid
+ @throws ElementExistException
+ if the object already exists in the container, or another object with the same name
+ already exists
+ @throws WrappedTargetException
+ if another error occurs which prevents insertion of the object into the container
+ */
+ void approveNewObject(
+ const OUString& _sName,
+ const css::uno::Reference< css::ucb::XContent >& _rxObject
+ ) const;
+
+ bool impl_haveAnyListeners_nothrow() const
+ {
+ return ( m_aContainerListeners.getLength() > 0 ) || ( m_aApproveListeners.getLength() > 0 );
+ }
+};
+
+} // namespace dbaccess
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/inc/documentevents.hxx b/dbaccess/source/core/inc/documentevents.hxx
new file mode 100644
index 000000000..e7f7ef9ff
--- /dev/null
+++ b/dbaccess/source/core/inc/documentevents.hxx
@@ -0,0 +1,75 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <com/sun/star/container/XNameReplace.hpp>
+#include <com/sun/star/beans/PropertyValue.hpp>
+
+#include <cppuhelper/implbase.hxx>
+
+#include <memory>
+#include <map>
+
+namespace dbaccess
+{
+
+ typedef std::map< OUString, css::uno::Sequence< css::beans::PropertyValue > >
+ DocumentEventsData;
+
+ // DocumentEvents
+ struct DocumentEvents_Data;
+
+ typedef ::cppu::WeakImplHelper< css::container::XNameReplace
+ > DocumentEvents_Base;
+
+ class DocumentEvents :public DocumentEvents_Base
+ {
+ public:
+ DocumentEvents( ::cppu::OWeakObject& _rParent, ::osl::Mutex& _rMutex, DocumentEventsData& _rEventsData );
+ virtual ~DocumentEvents() override;
+
+ DocumentEvents(const DocumentEvents&) = delete;
+ const DocumentEvents& operator=(const DocumentEvents&) = delete;
+
+ static bool needsSynchronousNotification( std::u16string_view _rEventName );
+
+ // XInterface
+ virtual void SAL_CALL acquire() noexcept override;
+ virtual void SAL_CALL release() noexcept override;
+
+ // XNameReplace
+ virtual void SAL_CALL replaceByName( const OUString& aName, const css::uno::Any& aElement ) override;
+
+ // XNameAccess
+ virtual css::uno::Any SAL_CALL getByName( const OUString& aName ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getElementNames( ) override;
+ virtual sal_Bool SAL_CALL hasByName( const OUString& aName ) override;
+
+ // XElementAccess
+ virtual css::uno::Type SAL_CALL getElementType( ) override;
+ virtual sal_Bool SAL_CALL hasElements( ) override;
+
+ private:
+ std::unique_ptr< DocumentEvents_Data > m_pData;
+ };
+
+} // namespace dbaccess
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/inc/migrwarndlg.hxx b/dbaccess/source/core/inc/migrwarndlg.hxx
new file mode 100644
index 000000000..24bacf300
--- /dev/null
+++ b/dbaccess/source/core/inc/migrwarndlg.hxx
@@ -0,0 +1,24 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+#pragma once
+
+#include <vcl/weld.hxx>
+
+namespace dbaccess
+{
+class MigrationWarnDialog : public weld::MessageDialogController
+{
+ std::unique_ptr<weld::Button> m_xLater;
+
+public:
+ MigrationWarnDialog(weld::Window* pParent);
+};
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/inc/object.hxx b/dbaccess/source/core/inc/object.hxx
new file mode 100644
index 000000000..a947f9c57
--- /dev/null
+++ b/dbaccess/source/core/inc/object.hxx
@@ -0,0 +1,30 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+enum ObjectType
+{
+ dbaTable,
+ dbaQuery,
+ dbaForm,
+ dbaReport
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/inc/objectnameapproval.hxx b/dbaccess/source/core/inc/objectnameapproval.hxx
new file mode 100644
index 000000000..ddd538c79
--- /dev/null
+++ b/dbaccess/source/core/inc/objectnameapproval.hxx
@@ -0,0 +1,75 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <memory>
+#include "containerapprove.hxx"
+
+#include <com/sun/star/sdbc/XConnection.hpp>
+
+namespace dbaccess
+{
+
+ // ObjectNameApproval
+ struct ObjectNameApproval_Impl;
+ /** implementation of the IContainerApprove interface which approves
+ elements for insertion into a query or tables container.
+
+ The only check done by this instance is whether the query name is
+ not already used, taking into account that in some databases, queries
+ and tables share the same namespace.
+
+ The class is not thread-safe.
+ */
+ class ObjectNameApproval : public IContainerApprove
+ {
+ std::unique_ptr< ObjectNameApproval_Impl > m_pImpl;
+
+ public:
+ enum ObjectType
+ {
+ TypeQuery,
+ TypeTable
+ };
+
+ public:
+ /** constructs the instance
+
+ @param _rxConnection
+ the connection relative to which the names should be checked. This connection
+ will be held weak. In case it is closed, subsequent calls to this instance's
+ methods throw a DisposedException.
+ @param _eType
+ specifies which type of objects is to be approved with this instance
+ */
+ ObjectNameApproval(
+ const css::uno::Reference< css::sdbc::XConnection >& _rxConnection,
+ ObjectType _eType
+ );
+ virtual ~ObjectNameApproval() override;
+
+ // IContainerApprove
+ virtual void approveElement( const OUString& _rName ) override;
+
+ };
+
+} // namespace dbaccess
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/inc/preparedstatement.hxx b/dbaccess/source/core/inc/preparedstatement.hxx
new file mode 100644
index 000000000..cea06d79a
--- /dev/null
+++ b/dbaccess/source/core/inc/preparedstatement.hxx
@@ -0,0 +1,105 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/sdbc/XPreparedStatement.hpp>
+#include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
+#include <com/sun/star/sdbc/XParameters.hpp>
+#include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp>
+#include "statement.hxx"
+#include "column.hxx"
+
+namespace dbaccess
+{
+
+ // OPreparedStatement
+
+ class OPreparedStatement : public OStatementBase,
+ public css::sdbc::XPreparedStatement,
+ public css::sdbc::XParameters,
+ public css::sdbc::XResultSetMetaDataSupplier,
+ public css::sdbcx::XColumnsSupplier,
+ public css::lang::XServiceInfo
+ {
+ std::unique_ptr<OColumns> m_pColumns;
+ css::uno::Reference< css::sdbc::XParameters > m_xAggregateAsParameters;
+
+ public:
+ OPreparedStatement(const css::uno::Reference< css::sdbc::XConnection > & _xConn,
+ const css::uno::Reference< css::uno::XInterface > & _xStatement);
+ virtual ~OPreparedStatement() override;
+
+ // css::lang::XTypeProvider
+ virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes() override;
+ virtual css::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId() override;
+
+ // css::uno::XInterface
+ virtual css::uno::Any SAL_CALL queryInterface( const css::uno::Type & rType ) override;
+ virtual void SAL_CALL acquire() noexcept override;
+ virtual void SAL_CALL release() noexcept override;
+
+ // css::lang::XServiceInfo
+ virtual OUString SAL_CALL getImplementationName( ) override;
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override;
+
+ // OComponentHelper
+ virtual void SAL_CALL disposing() override;
+
+ // css::sdbc::XPreparedStatement
+ virtual css::uno::Reference< css::sdbc::XResultSet > SAL_CALL executeQuery( ) override;
+ virtual sal_Int32 SAL_CALL executeUpdate( ) override;
+ virtual sal_Bool SAL_CALL execute( ) override;
+ virtual css::uno::Reference< css::sdbc::XConnection > SAL_CALL getConnection( ) override;
+
+ // css::sdbcx::XColumnsSupplier
+ virtual css::uno::Reference< css::container::XNameAccess > SAL_CALL getColumns( ) override;
+
+ // css::sdbc::XResultSetMetaDataSupplier
+ virtual css::uno::Reference< css::sdbc::XResultSetMetaData > SAL_CALL getMetaData( ) override;
+
+ // css::sdbc::XParameters
+ virtual void SAL_CALL setNull( sal_Int32 parameterIndex, sal_Int32 sqlType ) override;
+ virtual void SAL_CALL setObjectNull( sal_Int32 parameterIndex, sal_Int32 sqlType, const OUString& typeName ) override;
+ virtual void SAL_CALL setBoolean( sal_Int32 parameterIndex, sal_Bool x ) override;
+ virtual void SAL_CALL setByte( sal_Int32 parameterIndex, sal_Int8 x ) override;
+ virtual void SAL_CALL setShort( sal_Int32 parameterIndex, sal_Int16 x ) override;
+ virtual void SAL_CALL setInt( sal_Int32 parameterIndex, sal_Int32 x ) override;
+ virtual void SAL_CALL setLong( sal_Int32 parameterIndex, sal_Int64 x ) override;
+ virtual void SAL_CALL setFloat( sal_Int32 parameterIndex, float x ) override;
+ virtual void SAL_CALL setDouble( sal_Int32 parameterIndex, double x ) override;
+ virtual void SAL_CALL setString( sal_Int32 parameterIndex, const OUString& x ) override;
+ virtual void SAL_CALL setBytes( sal_Int32 parameterIndex, const css::uno::Sequence< sal_Int8 >& x ) override;
+ virtual void SAL_CALL setDate( sal_Int32 parameterIndex, const css::util::Date& x ) override;
+ virtual void SAL_CALL setTime( sal_Int32 parameterIndex, const css::util::Time& x ) override;
+ virtual void SAL_CALL setTimestamp( sal_Int32 parameterIndex, const css::util::DateTime& x ) override;
+ virtual void SAL_CALL setBinaryStream( sal_Int32 parameterIndex, const css::uno::Reference< css::io::XInputStream >& x, sal_Int32 length ) override;
+ virtual void SAL_CALL setCharacterStream( sal_Int32 parameterIndex, const css::uno::Reference< css::io::XInputStream >& x, sal_Int32 length ) override;
+ virtual void SAL_CALL setObject( sal_Int32 parameterIndex, const css::uno::Any& x ) override;
+ virtual void SAL_CALL setObjectWithInfo( sal_Int32 parameterIndex, const css::uno::Any& x, sal_Int32 targetSqlType, sal_Int32 scale ) override;
+ virtual void SAL_CALL setRef( sal_Int32 parameterIndex, const css::uno::Reference< css::sdbc::XRef >& x ) override;
+ virtual void SAL_CALL setBlob( sal_Int32 parameterIndex, const css::uno::Reference< css::sdbc::XBlob >& x ) override;
+ virtual void SAL_CALL setClob( sal_Int32 parameterIndex, const css::uno::Reference< css::sdbc::XClob >& x ) override;
+ virtual void SAL_CALL setArray( sal_Int32 parameterIndex, const css::uno::Reference< css::sdbc::XArray >& x ) override;
+ virtual void SAL_CALL clearParameters( ) override;
+ };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/inc/querycomposer.hxx b/dbaccess/source/core/inc/querycomposer.hxx
new file mode 100644
index 000000000..c5d764d98
--- /dev/null
+++ b/dbaccess/source/core/inc/querycomposer.hxx
@@ -0,0 +1,91 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <com/sun/star/sdb/XSQLQueryComposer.hpp>
+#include <com/sun/star/sdb/XParametersSupplier.hpp>
+#include <com/sun/star/sdbcx/XTablesSupplier.hpp>
+#include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <cppuhelper/implbase5.hxx>
+#include <cppuhelper/basemutex.hxx>
+#include <connectivity/sqliterator.hxx>
+#include <apitools.hxx>
+#include <com/sun/star/sdb/XSingleSelectQueryComposer.hpp>
+
+
+namespace dbaccess
+{
+ typedef ::cppu::ImplHelper5< css::sdb::XSQLQueryComposer,
+ css::sdb::XParametersSupplier,
+ css::sdbcx::XTablesSupplier,
+ css::sdbcx::XColumnsSupplier,
+ css::lang::XServiceInfo > OQueryComposer_BASE;
+
+ class OQueryComposer : public ::cppu::BaseMutex,
+ public OSubComponent,
+ public OQueryComposer_BASE
+ {
+ std::vector< OUString> m_aFilters;
+ std::vector< OUString> m_aOrders;
+ OUString m_sOrgFilter;
+ OUString m_sOrgOrder;
+ css::uno::Reference< css::sdb::XSingleSelectQueryComposer> m_xComposer;
+ css::uno::Reference< css::sdb::XSingleSelectQueryComposer> m_xComposerHelper;
+
+ protected:
+ virtual void SAL_CALL disposing() override;
+ virtual ~OQueryComposer() override;
+ public:
+
+ OQueryComposer( const css::uno::Reference< css::sdbc::XConnection>& _xConnection );
+
+ // css::lang::XTypeProvider
+ virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes() override;
+ virtual css::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId() override;
+
+ // css::uno::XInterface
+ virtual css::uno::Any SAL_CALL queryInterface( const css::uno::Type & rType ) override;
+ virtual void SAL_CALL acquire() noexcept override;
+ virtual void SAL_CALL release() noexcept override;
+ // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName( ) override;
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override;
+ // XSQLQueryComposer
+ virtual OUString SAL_CALL getQuery( ) override;
+ virtual void SAL_CALL setQuery( const OUString& command ) override;
+ virtual OUString SAL_CALL getComposedQuery( ) override;
+ virtual OUString SAL_CALL getFilter( ) override;
+ virtual css::uno::Sequence< css::uno::Sequence< css::beans::PropertyValue > > SAL_CALL getStructuredFilter( ) override;
+ virtual OUString SAL_CALL getOrder( ) override;
+ virtual void SAL_CALL appendFilterByColumn( const css::uno::Reference< css::beans::XPropertySet >& column ) override;
+ virtual void SAL_CALL appendOrderByColumn( const css::uno::Reference< css::beans::XPropertySet >& column, sal_Bool ascending ) override;
+ virtual void SAL_CALL setFilter( const OUString& filter ) override;
+ virtual void SAL_CALL setOrder( const OUString& order ) override;
+ // XTablesSupplier
+ virtual css::uno::Reference< css::container::XNameAccess > SAL_CALL getTables( ) override;
+ // XColumnsSupplier
+ virtual css::uno::Reference< css::container::XNameAccess > SAL_CALL getColumns( ) override;
+ // XParametersSupplier
+ virtual css::uno::Reference< css::container::XIndexAccess > SAL_CALL getParameters( ) override;
+ };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/inc/querycontainer.hxx b/dbaccess/source/core/inc/querycontainer.hxx
new file mode 100644
index 000000000..a04a1ddf3
--- /dev/null
+++ b/dbaccess/source/core/inc/querycontainer.hxx
@@ -0,0 +1,165 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <cppuhelper/implbase5.hxx>
+#include <connectivity/CommonTools.hxx>
+#include <rtl/ref.hxx>
+
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/container/XContainerListener.hpp>
+#include <com/sun/star/container/XNameContainer.hpp>
+#include <com/sun/star/uno/Sequence.hxx>
+#include <com/sun/star/sdbcx/XDataDescriptorFactory.hpp>
+#include <com/sun/star/sdbcx/XAppend.hpp>
+#include <com/sun/star/sdbcx/XDrop.hpp>
+#include <com/sun/star/sdbc/XConnection.hpp>
+#include <com/sun/star/container/XContainerApproveListener.hpp>
+
+#include "definitioncontainer.hxx"
+
+namespace dbtools
+{
+ class WarningsContainer;
+}
+
+namespace dbaccess
+{
+
+ typedef ::cppu::ImplHelper5 < css::container::XContainerListener
+ , css::container::XContainerApproveListener
+ , css::sdbcx::XDataDescriptorFactory
+ , css::sdbcx::XAppend
+ , css::sdbcx::XDrop
+ > OQueryContainer_Base;
+
+ // OQueryContainer
+ class OQueryContainer : public ODefinitionContainer
+ , public OQueryContainer_Base
+ {
+ private:
+ ::dbtools::WarningsContainer* m_pWarnings;
+ css::uno::Reference< css::container::XNameContainer >
+ m_xCommandDefinitions;
+ css::uno::Reference< css::sdbc::XConnection >
+ m_xConnection;
+ // possible actions on our "aggregate"
+ enum class AggregateAction { NONE, Inserting };
+ AggregateAction m_eDoingCurrently;
+
+ /** a class which automatically resets m_eDoingCurrently in its destructor
+ */
+ class OAutoActionReset; // just for the following friend declaration
+ friend class OAutoActionReset;
+ class OAutoActionReset
+ {
+ OQueryContainer& m_rActor;
+ public:
+ OAutoActionReset(OQueryContainer& _rActor) : m_rActor(_rActor) { }
+ ~OAutoActionReset() { m_rActor.m_eDoingCurrently = AggregateAction::NONE; }
+ };
+
+ // ODefinitionContainer
+ virtual css::uno::Reference< css::ucb::XContent > createObject( const OUString& _rName) override;
+ virtual bool checkExistence(const OUString& _rName) override;
+
+ // helper
+ virtual void SAL_CALL disposing() override;
+ virtual ~OQueryContainer() override;
+
+ /** ctor of the container. The parent has to support the <type scope="css::sdbc">XConnection</type>
+ interface.<BR>
+
+ @param _pWarnings
+ specifies a warnings container (May be <NULL/>)
+
+ Any errors which occur during the lifetime of the query container,
+ which cannot be reported as exceptions (for instance in methods where throwing an SQLException is
+ not allowed) will be appended to this container.</p>
+ <p>The caller is responsible for ensuring the lifetime of the object pointed to by this parameter.
+ */
+ OQueryContainer(
+ const css::uno::Reference< css::container::XNameContainer >& _rxCommandDefinitions,
+ const css::uno::Reference< css::sdbc::XConnection >& _rxConn,
+ const css::uno::Reference< css::uno::XComponentContext >& _rxORB,
+ ::dbtools::WarningsContainer* _pWarnings
+ );
+
+ void init();
+
+ public:
+ static rtl::Reference<OQueryContainer> create(
+ const css::uno::Reference< css::container::XNameContainer >& _rxCommandDefinitions,
+ const css::uno::Reference< css::sdbc::XConnection >& _rxConn,
+ const css::uno::Reference< css::uno::XComponentContext >& _rxORB,
+ ::dbtools::WarningsContainer* _pWarnings
+ );
+
+ DECLARE_XINTERFACE( )
+ DECLARE_XTYPEPROVIDER( )
+ DECLARE_SERVICE_INFO();
+
+ // css::container::XContainerListener
+ virtual void SAL_CALL elementInserted( const css::container::ContainerEvent& Event ) override;
+ virtual void SAL_CALL elementRemoved( const css::container::ContainerEvent& Event ) override;
+ virtual void SAL_CALL elementReplaced( const css::container::ContainerEvent& Event ) override;
+
+ // XContainerApproveListener
+ virtual css::uno::Reference< css::util::XVeto > SAL_CALL approveInsertElement( const css::container::ContainerEvent& Event ) override;
+ virtual css::uno::Reference< css::util::XVeto > SAL_CALL approveReplaceElement( const css::container::ContainerEvent& Event ) override;
+ virtual css::uno::Reference< css::util::XVeto > SAL_CALL approveRemoveElement( const css::container::ContainerEvent& Event ) override;
+
+ // css::lang::XEventListener
+ virtual void SAL_CALL disposing( const css::lang::EventObject& Source ) override;
+
+ // css::sdbcx::XDataDescriptorFactory
+ virtual css::uno::Reference< css::beans::XPropertySet > SAL_CALL createDataDescriptor( ) override;
+
+ // css::sdbcx::XAppend
+ virtual void SAL_CALL appendByDescriptor( const css::uno::Reference< css::beans::XPropertySet >& descriptor ) override;
+
+ // css::sdbcx::XDrop
+ virtual void SAL_CALL dropByName( const OUString& elementName ) override;
+ virtual void SAL_CALL dropByIndex( sal_Int32 index ) override;
+
+ // css::container::XElementAccess
+ virtual sal_Bool SAL_CALL hasElements( ) override;
+ // css::container::XIndexAccess
+ virtual sal_Int32 SAL_CALL getCount( ) override;
+ // css::container::XNameAccess
+ virtual css::uno::Sequence< OUString > SAL_CALL getElementNames( ) override;
+
+ private:
+ // OContentHelper overridables
+ virtual OUString determineContentType() const override;
+
+ // helper
+ /** create a query object wrapping a CommandDefinition given by name. To retrieve the object, the CommandDescription
+ container will be asked for the given name.<BR>
+ The returned object is acquired once.
+ */
+ css::uno::Reference< css::ucb::XContent > implCreateWrapper(const OUString& _rName);
+ /// create a query object wrapping a CommandDefinition. The returned object is acquired once.
+ css::uno::Reference< css::ucb::XContent > implCreateWrapper(const css::uno::Reference< css::ucb::XContent >& _rxCommandDesc);
+
+ };
+} // namespace dbaccess
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/inc/recovery/dbdocrecovery.hxx b/dbaccess/source/core/inc/recovery/dbdocrecovery.hxx
new file mode 100644
index 000000000..e5f924650
--- /dev/null
+++ b/dbaccess/source/core/inc/recovery/dbdocrecovery.hxx
@@ -0,0 +1,71 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <com/sun/star/embed/XStorage.hpp>
+#include <com/sun/star/frame/XController.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+
+#include <vector>
+#include <memory>
+
+namespace dbaccess
+{
+
+ // DatabaseDocumentRecovery
+ struct DatabaseDocumentRecovery_Data;
+ class DatabaseDocumentRecovery
+ {
+ public:
+ DatabaseDocumentRecovery(
+ const css::uno::Reference< css::uno::XComponentContext >& i_rContext
+ );
+ ~DatabaseDocumentRecovery();
+
+ /** saves the modified sub components of the given controller(s) to the "recovery" sub storage of the document
+ storage.
+
+ @throws css::uno::Exception
+ in case of an error.
+ */
+ void saveModifiedSubComponents(
+ const css::uno::Reference< css::embed::XStorage >& i_rTargetStorage,
+ const std::vector< css::uno::Reference< css::frame::XController > >& i_rControllers
+ );
+
+ /** recovery sub components from the given document storage, if applicable
+
+ If the given document storage does not contain a recovery folder, the method silently returns.
+
+ @throws css::uno::Exception
+ in case of an error.
+ */
+ void recoverSubDocuments(
+ const css::uno::Reference< css::embed::XStorage >& i_rDocumentStorage,
+ const css::uno::Reference< css::frame::XController >& i_rTargetController
+ );
+
+ private:
+ const std::unique_ptr< DatabaseDocumentRecovery_Data > m_pData;
+ };
+
+} // namespace dbaccess
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/inc/sdbcoretools.hxx b/dbaccess/source/core/inc/sdbcoretools.hxx
new file mode 100644
index 000000000..5b100dcf1
--- /dev/null
+++ b/dbaccess/source/core/inc/sdbcoretools.hxx
@@ -0,0 +1,55 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <com/sun/star/embed/XStorage.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+
+namespace dbaccess
+{
+
+ void notifyDataSourceModified(const css::uno::Reference< css::uno::XInterface >& _rxObject);
+
+ css::uno::Reference< css::uno::XInterface >
+ getDataSource( const css::uno::Reference< css::uno::XInterface >& _rxDependentObject );
+
+ /** retrieves a to-be-displayed string for a given caught exception;
+ */
+ OUString extractExceptionMessage( const css::uno::Reference< css::uno::XComponentContext >& _rContext, const css::uno::Any& _rError );
+
+ namespace tools
+ {
+ namespace stor
+ {
+ bool storageIsWritable_nothrow(
+ const css::uno::Reference< css::embed::XStorage >& _rxStorage
+ );
+
+ /// commits a given storage if it's not readonly
+ bool commitStorageIfWriteable(
+ const css::uno::Reference< css::embed::XStorage >& _rxStorage
+ );
+ }
+
+ }
+
+} // namespace dbaccess
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/inc/statement.hxx b/dbaccess/source/core/inc/statement.hxx
new file mode 100644
index 000000000..f43704068
--- /dev/null
+++ b/dbaccess/source/core/inc/statement.hxx
@@ -0,0 +1,179 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/sdbc/XStatement.hpp>
+#include <com/sun/star/sdbc/XConnection.hpp>
+#include <com/sun/star/util/XCancellable.hpp>
+#include <com/sun/star/sdbc/XWarningsSupplier.hpp>
+#include <com/sun/star/sdbc/XCloseable.hpp>
+#include <com/sun/star/sdbc/XMultipleResults.hpp>
+#include <com/sun/star/sdbc/XPreparedBatchExecution.hpp>
+#include <com/sun/star/sdbc/XBatchExecution.hpp>
+#include <com/sun/star/sdbc/XGeneratedResultSet.hpp>
+#include <com/sun/star/sdb/XSingleSelectQueryComposer.hpp>
+#include <cppuhelper/propshlp.hxx>
+#include <comphelper/proparrhlp.hxx>
+#include <cppuhelper/basemutex.hxx>
+#include <cppuhelper/implbase3.hxx>
+#include <apitools.hxx>
+
+
+// OStatementBase
+
+class OStatementBase : public cppu::BaseMutex,
+ public OSubComponent,
+ public ::cppu::OPropertySetHelper,
+ public ::comphelper::OPropertyArrayUsageHelper < OStatementBase >,
+ public css::util::XCancellable,
+ public css::sdbc::XWarningsSupplier,
+ public css::sdbc::XPreparedBatchExecution,
+ public css::sdbc::XMultipleResults,
+ public css::sdbc::XCloseable,
+ public css::sdbc::XGeneratedResultSet
+{
+protected:
+ ::osl::Mutex m_aCancelMutex;
+
+ css::uno::WeakReferenceHelper m_aResultSet;
+ css::uno::Reference< css::beans::XPropertySet > m_xAggregateAsSet;
+ css::uno::Reference< css::util::XCancellable > m_xAggregateAsCancellable;
+ bool m_bUseBookmarks;
+ bool m_bEscapeProcessing;
+
+ virtual ~OStatementBase() override;
+
+public:
+ OStatementBase(const css::uno::Reference< css::sdbc::XConnection > & _xConn,
+ const css::uno::Reference< css::uno::XInterface > & _xStatement);
+
+
+// css::lang::XTypeProvider
+ virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes() override;
+
+// css::uno::XInterface
+ virtual css::uno::Any SAL_CALL queryInterface( const css::uno::Type & rType ) override;
+ virtual void SAL_CALL acquire() noexcept override;
+ virtual void SAL_CALL release() noexcept override;
+
+// OComponentHelper
+ virtual void SAL_CALL disposing() override;
+
+// css::beans::XPropertySet
+ virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo( ) override;
+
+// comphelper::OPropertyArrayUsageHelper
+ virtual ::cppu::IPropertyArrayHelper* createArrayHelper( ) const override;
+
+// cppu::OPropertySetHelper
+ virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper() override;
+
+ virtual sal_Bool SAL_CALL convertFastPropertyValue(
+ css::uno::Any & rConvertedValue,
+ css::uno::Any & rOldValue,
+ sal_Int32 nHandle,
+ const css::uno::Any& rValue ) override;
+ virtual void SAL_CALL setFastPropertyValue_NoBroadcast(
+ sal_Int32 nHandle,
+ const css::uno::Any& rValue
+ ) override;
+ virtual void SAL_CALL getFastPropertyValue( css::uno::Any& rValue, sal_Int32 nHandle ) const override;
+
+// css::sdbc::XWarningsSupplier
+ virtual css::uno::Any SAL_CALL getWarnings( ) override;
+ virtual void SAL_CALL clearWarnings( ) override;
+
+// css::util::XCancellable
+ virtual void SAL_CALL cancel( ) override;
+
+// css::sdbc::XCloseable
+ virtual void SAL_CALL close( ) override;
+
+// css::sdbc::XMultipleResults
+ virtual css::uno::Reference< css::sdbc::XResultSet > SAL_CALL getResultSet( ) override;
+ virtual sal_Int32 SAL_CALL getUpdateCount( ) override;
+ virtual sal_Bool SAL_CALL getMoreResults( ) override;
+
+// css::sdbc::XPreparedBatchExecution
+ virtual void SAL_CALL addBatch( ) override;
+ virtual void SAL_CALL clearBatch( ) override;
+ virtual css::uno::Sequence< sal_Int32 > SAL_CALL executeBatch( ) override;
+// css::sdbc::XGeneratedResultSet
+ virtual css::uno::Reference< css::sdbc::XResultSet > SAL_CALL getGeneratedValues( ) override;
+
+// Helper
+ void disposeResultSet();
+
+protected:
+ using ::cppu::OPropertySetHelper::getFastPropertyValue;
+};
+
+
+// OStatement
+
+typedef ::cppu::ImplHelper3 < css::sdbc::XStatement
+ , css::lang::XServiceInfo
+ , css::sdbc::XBatchExecution
+ > OStatement_IFACE;
+class OStatement :public OStatementBase
+ ,public OStatement_IFACE
+{
+private:
+ css::uno::Reference< css::sdbc::XStatement > m_xAggregateStatement;
+ css::uno::Reference< css::sdb::XSingleSelectQueryComposer > m_xComposer;
+ bool m_bAttemptedComposerCreation;
+
+public:
+ OStatement(const css::uno::Reference< css::sdbc::XConnection > & _xConn,
+ const css::uno::Reference< css::uno::XInterface > & _xStatement);
+
+ DECLARE_XINTERFACE()
+ DECLARE_XTYPEPROVIDER()
+
+// css::lang::XServiceInfo
+ virtual OUString SAL_CALL getImplementationName( ) override;
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override;
+
+// css::sdbc::XStatement
+ virtual css::uno::Reference< css::sdbc::XResultSet > SAL_CALL executeQuery( const OUString& sql ) override;
+ virtual sal_Int32 SAL_CALL executeUpdate( const OUString& sql ) override;
+ virtual sal_Bool SAL_CALL execute( const OUString& sql ) override;
+ virtual css::uno::Reference< css::sdbc::XConnection > SAL_CALL getConnection( ) override;
+
+ // OComponentHelper
+ virtual void SAL_CALL disposing() override;
+
+ // XBatchExecution
+ virtual void SAL_CALL addBatch( const OUString& sql ) override;
+ virtual void SAL_CALL clearBatch( ) override;
+ virtual css::uno::Sequence< sal_Int32 > SAL_CALL executeBatch( ) override;
+
+ using OStatementBase::addBatch;
+
+private:
+ /** does escape processing for the given SQL command, if the our EscapeProcessing
+ property allows so.
+ */
+ OUString impl_doEscapeProcessing_nothrow( const OUString& _rSQL ) const;
+ bool impl_ensureComposer_nothrow() const;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/inc/table.hxx b/dbaccess/source/core/inc/table.hxx
new file mode 100644
index 000000000..8c29bff44
--- /dev/null
+++ b/dbaccess/source/core/inc/table.hxx
@@ -0,0 +1,140 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <com/sun/star/sdbc/XConnection.hpp>
+
+#include "datasettings.hxx"
+#include "column.hxx"
+#include <connectivity/CommonTools.hxx>
+#include <connectivity/TTableHelper.hxx>
+#include <comphelper/IdPropArrayHelper.hxx>
+
+namespace dbaccess
+{
+
+ // OTables
+ class ODBTable;
+ class OContainerMediator;
+ typedef ::comphelper::OIdPropertyArrayUsageHelper< ODBTable > ODBTable_PROP;
+ typedef ::connectivity::OTableHelper OTable_Base;
+
+ class ODBTable :public ODataSettings_Base
+ ,public ODBTable_PROP
+ ,public OTable_Base
+ ,public IColumnFactory
+ {
+ private:
+ ::rtl::Reference< OContainerMediator > m_pColumnMediator;
+
+ protected:
+ css::uno::Reference< css::container::XNameAccess > m_xColumnDefinitions;
+ css::uno::Reference< css::container::XNameAccess > m_xDriverColumns;
+
+ // <properties>
+ sal_Int32 m_nPrivileges;
+ // </properties>
+
+ virtual ::cppu::IPropertyArrayHelper* createArrayHelper( sal_Int32 _nId) const override;
+ virtual ::cppu::IPropertyArrayHelper & SAL_CALL getInfoHelper() override;
+
+ // IColumnFactory
+ virtual rtl::Reference<OColumn> createColumn(const OUString& _rName) const override;
+ virtual css::uno::Reference< css::beans::XPropertySet > createColumnDescriptor() override;
+ virtual void columnAppended( const css::uno::Reference< css::beans::XPropertySet >& _rxSourceDescriptor ) override;
+ virtual void columnDropped(const OUString& _sName) override;
+
+ /** creates the column collection for the table
+ @param _rNames
+ The column names.
+ */
+ virtual ::connectivity::sdbcx::OCollection* createColumns(const ::std::vector< OUString>& _rNames) override;
+
+ /** creates the key collection for the table
+ @param _rNames
+ The key names.
+ */
+ virtual ::connectivity::sdbcx::OCollection* createKeys(const ::std::vector< OUString>& _rNames) override;
+
+ /** creates the index collection for the table
+ @param _rNames
+ The index names.
+ */
+ virtual ::connectivity::sdbcx::OCollection* createIndexes(const ::std::vector< OUString>& _rNames) override;
+
+ // OComponentHelper
+ virtual void SAL_CALL disposing() override;
+ public:
+ /** constructs a wrapper supporting the com.sun.star.sdb.Table service.<BR>
+ @param _rxConn the connection the table belongs to
+ @param _rxTable the table from the driver can be null
+ @param _rCatalog the name of the catalog the table belongs to. May be empty.
+ @param _rSchema the name of the schema the table belongs to. May be empty.
+ @param _rName the name of the table
+ @param _rType the type of the table, as supplied by the driver
+ @param _rDesc the description of the table, as supplied by the driver
+ @throws css::sdbc::SQLException
+ */
+ ODBTable(connectivity::sdbcx::OCollection* _pTables
+ ,const css::uno::Reference< css::sdbc::XConnection >& _rxConn
+ ,const OUString& _rCatalog
+ , const OUString& _rSchema
+ , const OUString& _rName
+ ,const OUString& _rType
+ , const OUString& _rDesc
+ ,const css::uno::Reference< css::container::XNameAccess >& _rxColumnDefinitions);
+
+ /// @throws css::sdbc::SQLException
+ ODBTable(connectivity::sdbcx::OCollection* _pTables
+ ,const css::uno::Reference< css::sdbc::XConnection >& _rxConn);
+ virtual ~ODBTable() override;
+
+ // ODescriptor
+ virtual void construct() override;
+
+ //XInterface
+ virtual css::uno::Any SAL_CALL queryInterface( const css::uno::Type& aType ) override;
+ //XTypeProvider
+ virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes( ) override;
+ virtual css::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId() override;
+ static const css::uno::Sequence< sal_Int8 > & getUnoTunnelId();
+
+ // css::lang::XServiceInfo
+ DECLARE_SERVICE_INFO();
+
+ // css::beans::XPropertySet
+ virtual void SAL_CALL getFastPropertyValue(css::uno::Any& rValue, sal_Int32 nHandle) const override;
+
+ // css::sdbcx::XRename,
+ virtual void SAL_CALL rename( const OUString& _rNewName ) override;
+
+ // css::sdbcx::XAlterTable,
+ virtual void SAL_CALL alterColumnByName( const OUString& _rName, const css::uno::Reference< css::beans::XPropertySet >& _rxDescriptor ) override;
+
+ // css::lang::XUnoTunnel
+ virtual sal_Int64 SAL_CALL getSomething( const css::uno::Sequence< sal_Int8 >& aIdentifier ) override;
+
+ private:
+ using OTable_Base::createArrayHelper;
+ using OTable_Base::getFastPropertyValue;
+ };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/inc/tablecontainer.hxx b/dbaccess/source/core/inc/tablecontainer.hxx
new file mode 100644
index 000000000..44358e4e2
--- /dev/null
+++ b/dbaccess/source/core/inc/tablecontainer.hxx
@@ -0,0 +1,96 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <sal/config.h>
+
+#include <atomic>
+#include <cstddef>
+
+#include <cppuhelper/implbase1.hxx>
+#include <rtl/ref.hxx>
+#include <com/sun/star/sdbc/XConnection.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/container/XContainerListener.hpp>
+#include <com/sun/star/container/XNameContainer.hpp>
+#include "FilteredContainer.hxx"
+#include "RefreshListener.hxx"
+
+namespace dbaccess
+{
+ // OTableContainer
+ class OContainerMediator;
+
+ class OTableContainer : public OFilteredContainer,
+ public ::cppu::ImplHelper1< css::container::XContainerListener>
+ {
+ css::uno::Reference< css::container::XNameContainer > m_xTableDefinitions;
+ ::rtl::Reference< OContainerMediator > m_pTableMediator;
+
+ // OFilteredContainer
+ virtual void addMasterContainerListener() override;
+ virtual void removeMasterContainerListener() override;
+ virtual OUString getTableTypeRestriction() const override;
+
+ // ::connectivity::sdbcx::OCollection
+ virtual connectivity::sdbcx::ObjectType createObject(const OUString& _rName) override;
+ virtual css::uno::Reference< css::beans::XPropertySet > createDescriptor() override;
+ virtual connectivity::sdbcx::ObjectType appendObject( const OUString& _rForName, const css::uno::Reference< css::beans::XPropertySet >& descriptor ) override;
+ virtual void dropObject(sal_Int32 _nPos, const OUString& _sElementName) override;
+
+ virtual void disposing() override;
+
+ // css::lang::XServiceInfo
+ DECLARE_SERVICE_INFO();
+
+ // XEventListener
+ virtual void SAL_CALL disposing( const css::lang::EventObject& Source ) override;
+ // XContainerListener
+ virtual void SAL_CALL elementInserted( const css::container::ContainerEvent& Event ) override;
+ virtual void SAL_CALL elementRemoved( const css::container::ContainerEvent& Event ) override;
+ virtual void SAL_CALL elementReplaced( const css::container::ContainerEvent& Event ) override;
+
+ public:
+ virtual void SAL_CALL acquire() noexcept override { OFilteredContainer::acquire();}
+ virtual void SAL_CALL release() noexcept override { OFilteredContainer::release();}
+
+ /** ctor of the container. The parent has to support the <type scope="css::sdbc">XConnection</type>
+ interface.<BR>
+ @param _rParent the object which acts as parent for the container.
+ all refcounting is rerouted to this object
+ @param _rMutex the access safety object of the parent
+ @param _rTableFilter restricts the visible tables by name
+ @param _rTableTypeFilter restricts the visible tables by type
+ @see construct
+ */
+ OTableContainer( ::cppu::OWeakObject& _rParent,
+ ::osl::Mutex& _rMutex,
+ const css::uno::Reference< css::sdbc::XConnection >& _xCon,
+ bool _bCase,
+ const css::uno::Reference< css::container::XNameContainer >& _xTableDefinitions,
+ IRefreshListener* _pRefreshListener,
+ std::atomic<std::size_t>& _nInAppend
+ );
+
+ virtual ~OTableContainer() override;
+ };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/inc/veto.hxx b/dbaccess/source/core/inc/veto.hxx
new file mode 100644
index 000000000..5608e87d1
--- /dev/null
+++ b/dbaccess/source/core/inc/veto.hxx
@@ -0,0 +1,55 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <com/sun/star/util/XVeto.hpp>
+
+#include <cppuhelper/implbase.hxx>
+
+namespace dbaccess
+{
+
+ // Veto
+ typedef ::cppu::WeakImplHelper< css::util::XVeto
+ > Veto_Base;
+ /** implements css::util::XVeto
+ */
+ class Veto : public Veto_Base
+ {
+ private:
+ const css::uno::Any m_aDetails;
+
+ public:
+ Veto( const css::uno::Any& _rDetails );
+
+ virtual OUString SAL_CALL getReason() override;
+ virtual css::uno::Any SAL_CALL getDetails() override;
+
+ protected:
+ virtual ~Veto() override;
+
+ private:
+ Veto( const Veto& ) = delete;
+ Veto& operator=( const Veto& ) = delete;
+ };
+
+} // namespace dbaccess
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/inc/viewcontainer.hxx b/dbaccess/source/core/inc/viewcontainer.hxx
new file mode 100644
index 000000000..2f7f48cec
--- /dev/null
+++ b/dbaccess/source/core/inc/viewcontainer.hxx
@@ -0,0 +1,94 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <sal/config.h>
+
+#include <atomic>
+#include <cstddef>
+
+#include <cppuhelper/implbase1.hxx>
+
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/container/XContainerListener.hpp>
+
+#include "FilteredContainer.hxx"
+
+namespace dbtools
+{
+ class WarningsContainer;
+}
+
+namespace dbaccess
+{
+ // OViewContainer
+ class OViewContainer : public OFilteredContainer,
+ public ::cppu::ImplHelper1< css::container::XContainerListener>
+ {
+ public:
+ /** ctor of the container. The parent has to support the <type scope="css::sdbc">XConnection</type>
+ interface.<BR>
+ @param _rParent the object which acts as parent for the container.
+ all refcounting is rerouted to this object
+ @param _rMutex the access safety object of the parent
+ @param _rTableFilter restricts the visible tables by name
+ @param _rTableTypeFilter restricts the visible tables by type
+ @see construct
+ */
+ OViewContainer( ::cppu::OWeakObject& _rParent,
+ ::osl::Mutex& _rMutex,
+ const css::uno::Reference< css::sdbc::XConnection >& _xCon,
+ bool _bCase,
+ IRefreshListener* _pRefreshListener,
+ std::atomic<std::size_t>& _nInAppend
+ );
+
+ virtual ~OViewContainer() override;
+
+ protected:
+ // OFilteredContainer overridables
+ virtual OUString getTableTypeRestriction() const override;
+
+ private:
+ virtual void SAL_CALL acquire() noexcept override { OFilteredContainer::acquire();}
+ virtual void SAL_CALL release() noexcept override { OFilteredContainer::release();}
+ // css::lang::XServiceInfo
+ DECLARE_SERVICE_INFO();
+
+ // XEventListener
+ virtual void SAL_CALL disposing( const css::lang::EventObject& Source ) override;
+ // XContainerListener
+ virtual void SAL_CALL elementInserted( const css::container::ContainerEvent& Event ) override;
+ virtual void SAL_CALL elementRemoved( const css::container::ContainerEvent& Event ) override;
+ virtual void SAL_CALL elementReplaced( const css::container::ContainerEvent& Event ) override;
+
+ // ::connectivity::sdbcx::OCollection
+ virtual ::connectivity::sdbcx::ObjectType createObject(const OUString& _rName) override;
+ virtual css::uno::Reference< css::beans::XPropertySet > createDescriptor() override;
+ virtual connectivity::sdbcx::ObjectType appendObject( const OUString& _rForName, const css::uno::Reference< css::beans::XPropertySet >& descriptor ) override;
+ virtual void dropObject(sal_Int32 _nPos, const OUString& _sElementName) override;
+
+ using OFilteredContainer::disposing;
+
+ bool m_bInElementRemoved;
+ };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/misc/ContainerMediator.cxx b/dbaccess/source/core/misc/ContainerMediator.cxx
new file mode 100644
index 000000000..338858c87
--- /dev/null
+++ b/dbaccess/source/core/misc/ContainerMediator.cxx
@@ -0,0 +1,231 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <ContainerMediator.hxx>
+#include <PropertyForward.hxx>
+
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/container/XNameContainer.hpp>
+#include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
+#include <com/sun/star/sdbcx/XRename.hpp>
+#include <comphelper/property.hxx>
+#include <tools/diagnose_ex.h>
+
+namespace dbaccess
+{
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::lang;
+ using namespace ::com::sun::star::sdbcx;
+ using namespace ::com::sun::star::beans;
+ using namespace ::com::sun::star::container;
+
+OContainerMediator::OContainerMediator( const Reference< XContainer >& _xContainer, const Reference< XNameAccess >& _xSettings )
+ : m_xSettings( _xSettings )
+ , m_xContainer( _xContainer )
+{
+
+ if ( _xSettings.is() && _xContainer.is() )
+ {
+ osl_atomic_increment(&m_refCount);
+ try
+ {
+ m_xContainer->addContainerListener(this);
+ Reference< XContainer > xContainer(_xSettings, UNO_QUERY);
+ if ( xContainer.is() )
+ xContainer->addContainerListener(this);
+ }
+ catch(Exception&)
+ {
+ TOOLS_WARN_EXCEPTION("dbaccess", "OContainerMediator::OContainerMediator");
+ }
+ osl_atomic_decrement( &m_refCount );
+ }
+ else
+ {
+ m_xSettings.clear();
+ m_xContainer.clear();
+ }
+}
+
+OContainerMediator::~OContainerMediator()
+{
+ acquire();
+ impl_cleanup_nothrow();
+}
+
+void OContainerMediator::impl_cleanup_nothrow()
+{
+ try
+ {
+ Reference< XContainer > xContainer( m_xSettings, UNO_QUERY );
+ if ( xContainer.is() )
+ xContainer->removeContainerListener( this );
+ m_xSettings.clear();
+
+ xContainer = m_xContainer;
+ if ( xContainer.is() )
+ xContainer->removeContainerListener( this );
+ m_xContainer.clear();
+
+ m_aForwardList.clear();
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+}
+
+void SAL_CALL OContainerMediator::elementInserted( const ContainerEvent& _rEvent )
+{
+ ::osl::MutexGuard aGuard(m_aMutex);
+ if ( _rEvent.Source == m_xSettings && m_xSettings.is() )
+ {
+ OUString sElementName;
+ _rEvent.Accessor >>= sElementName;
+ PropertyForwardList::const_iterator aFind = m_aForwardList.find(sElementName);
+ if ( aFind != m_aForwardList.end() )
+ {
+ Reference< XPropertySet> xDest(_rEvent.Element,UNO_QUERY);
+ aFind->second->setDefinition( xDest );
+ }
+ }
+}
+
+void SAL_CALL OContainerMediator::elementRemoved( const ContainerEvent& _rEvent )
+{
+ ::osl::MutexGuard aGuard(m_aMutex);
+ Reference< XContainer > xContainer = m_xContainer;
+ if ( !(_rEvent.Source == xContainer && xContainer.is()) )
+ return;
+
+ OUString sElementName;
+ _rEvent.Accessor >>= sElementName;
+ m_aForwardList.erase(sElementName);
+ try
+ {
+ Reference<XNameContainer> xNameContainer( m_xSettings, UNO_QUERY );
+ if ( xNameContainer.is() && m_xSettings->hasByName( sElementName ) )
+ xNameContainer->removeByName( sElementName );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+}
+
+void SAL_CALL OContainerMediator::elementReplaced( const ContainerEvent& _rEvent )
+{
+ Reference< XContainer > xContainer = m_xContainer;
+ if ( !(_rEvent.Source == xContainer && xContainer.is()) )
+ return;
+
+ OUString sElementName;
+ _rEvent.ReplacedElement >>= sElementName;
+
+ PropertyForwardList::const_iterator aFind = m_aForwardList.find(sElementName);
+ if ( aFind == m_aForwardList.end() )
+ return;
+
+ OUString sNewName;
+ _rEvent.Accessor >>= sNewName;
+ try
+ {
+ Reference<XNameContainer> xNameContainer( m_xSettings, UNO_QUERY_THROW );
+ if ( xNameContainer.is() && m_xSettings->hasByName( sElementName ) )
+ {
+ Reference<XRename> xSource(m_xSettings->getByName(sElementName),UNO_QUERY_THROW);
+ xSource->rename(sNewName);
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+
+ aFind->second->setName(sNewName);
+}
+
+void SAL_CALL OContainerMediator::disposing( const EventObject& /*Source*/ )
+{
+ ::osl::MutexGuard aGuard(m_aMutex);
+
+ impl_cleanup_nothrow();
+}
+
+void OContainerMediator::impl_initSettings_nothrow( const OUString& _rName, const Reference< XPropertySet >& _rxDestination )
+{
+ try
+ {
+ if ( m_xSettings.is() && m_xSettings->hasByName( _rName ) )
+ {
+ Reference< XPropertySet > xSettings( m_xSettings->getByName( _rName ), UNO_QUERY_THROW );
+ ::comphelper::copyProperties( xSettings, _rxDestination );
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+}
+
+void OContainerMediator::notifyElementCreated( const OUString& _sName, const Reference< XPropertySet >& _xDest )
+{
+ if ( !m_xSettings.is() )
+ return;
+
+ PropertyForwardList::const_iterator aFind = m_aForwardList.find( _sName );
+ if ( aFind != m_aForwardList.end()
+ && aFind->second->getDefinition().is()
+ )
+ {
+ OSL_FAIL( "OContainerMediator::notifyElementCreated: is this really a valid case?" );
+ return;
+ }
+
+ std::vector< OUString > aPropertyList;
+ try
+ {
+ // initially copy from the settings object (if existent) to the newly created object
+ impl_initSettings_nothrow( _sName, _xDest );
+
+ // collect the to-be-monitored properties
+ Reference< XPropertySetInfo > xPSI( _xDest->getPropertySetInfo(), UNO_SET_THROW );
+ const Sequence< Property > aProperties( xPSI->getProperties() );
+ for ( auto const & property : aProperties )
+ {
+ if ( ( property.Attributes & PropertyAttribute::READONLY ) != 0 )
+ continue;
+ if ( ( property.Attributes & PropertyAttribute::BOUND ) == 0 )
+ continue;
+
+ aPropertyList.push_back( property.Name );
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+
+ ::rtl::Reference pForward( new OPropertyForward( _xDest, m_xSettings, _sName, aPropertyList ) );
+ m_aForwardList[ _sName ] = pForward;
+}
+
+} // namespace dbaccess
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/misc/DatabaseDataProvider.cxx b/dbaccess/source/core/misc/DatabaseDataProvider.cxx
new file mode 100644
index 000000000..8695d518c
--- /dev/null
+++ b/dbaccess/source/core/misc/DatabaseDataProvider.cxx
@@ -0,0 +1,1066 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <DatabaseDataProvider.hxx>
+#include <strings.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <comphelper/types.hxx>
+#include <comphelper/namedvaluecollection.hxx>
+#include <connectivity/FValue.hxx>
+#include <sal/macros.h>
+#include <tools/diagnose_ex.h>
+
+#include <com/sun/star/task/XInteractionHandler.hpp>
+#include <com/sun/star/sdb/CommandType.hpp>
+#include <com/sun/star/sdbc/DataType.hpp>
+#include <com/sun/star/sdbc/XRow.hpp>
+#include <com/sun/star/sdbc/XResultSet.hpp>
+#include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp>
+#include <com/sun/star/sdbc/XColumnLocate.hpp>
+#include <com/sun/star/beans/NamedValue.hpp>
+#include <com/sun/star/chart/ChartDataRowSource.hpp>
+#include <com/sun/star/chart/XChartDataArray.hpp>
+
+#include <vector>
+
+// TODO: update for new HavingClause-aware FilterManager
+
+namespace dbaccess
+{
+using namespace ::com::sun::star;
+using ::com::sun::star::uno::Reference;
+
+DatabaseDataProvider::DatabaseDataProvider(uno::Reference< uno::XComponentContext > const & context) :
+ TDatabaseDataProvider(m_aMutex),
+ ::cppu::PropertySetMixin< chart2::data::XDatabaseDataProvider >(
+ context, IMPLEMENTS_PROPERTY_SET, uno::Sequence< OUString >()),
+ m_aParameterManager( m_aMutex, context ),
+ m_xContext(context),
+ m_CommandType(sdb::CommandType::COMMAND), // #i94114
+ m_RowLimit(0),
+ m_EscapeProcessing(true),
+ m_ApplyFilter(true)
+{
+ m_xInternal.set( m_xContext->getServiceManager()->createInstanceWithContext("com.sun.star.comp.chart.InternalDataProvider",m_xContext ), uno::UNO_QUERY );
+ m_xRangeConversion.set(m_xInternal,uno::UNO_QUERY);
+ m_xComplexDescriptionAccess.set(m_xInternal,uno::UNO_QUERY);
+
+ osl_atomic_increment( &m_refCount );
+ {
+ m_xRowSet.set( m_xContext->getServiceManager()->createInstanceWithContext(SERVICE_SDB_ROWSET,m_xContext ), uno::UNO_QUERY );
+ m_xAggregate.set(m_xRowSet,uno::UNO_QUERY);
+ m_xAggregateSet.set(m_xRowSet,uno::UNO_QUERY);
+ uno::Reference<beans::XPropertySet> xProp(static_cast< ::cppu::OWeakObject* >( this ),uno::UNO_QUERY);
+ m_aFilterManager.initialize( m_xAggregateSet );
+ m_aParameterManager.initialize( xProp, m_xAggregate );
+ m_xAggregateSet->setPropertyValue(PROPERTY_COMMAND_TYPE,uno::Any(m_CommandType));
+ m_xAggregateSet->setPropertyValue(PROPERTY_ESCAPE_PROCESSING,uno::Any(m_EscapeProcessing));
+ }
+ osl_atomic_decrement( &m_refCount );
+}
+
+void SAL_CALL DatabaseDataProvider::disposing()
+{
+ m_aParameterManager.dispose(); // (to free any references it may have to me)
+ m_aFilterManager.dispose(); // (ditto)
+
+ m_xParent.clear();
+ m_xAggregateSet.clear();
+ m_xAggregate.clear();
+ m_xRangeConversion.clear();
+ ::comphelper::disposeComponent(m_xRowSet);
+ ::comphelper::disposeComponent(m_xInternal);
+ m_xActiveConnection.clear();
+}
+
+uno::Any DatabaseDataProvider::queryInterface(uno::Type const & type)
+{
+ return TDatabaseDataProvider::queryInterface(type);
+}
+
+// XServiceInfo
+OUString SAL_CALL DatabaseDataProvider::getImplementationName( )
+{
+ return "com.sun.star.comp.dbaccess.DatabaseDataProvider";
+}
+
+sal_Bool SAL_CALL DatabaseDataProvider::supportsService( const OUString& _rServiceName )
+{
+ return cppu::supportsService(this, _rServiceName);
+}
+
+uno::Sequence< OUString > SAL_CALL DatabaseDataProvider::getSupportedServiceNames( )
+{
+ return { "com.sun.star.chart2.data.DatabaseDataProvider" };
+}
+
+// lang::XInitialization:
+void SAL_CALL DatabaseDataProvider::initialize(const uno::Sequence< uno::Any > & aArguments)
+{
+ osl::MutexGuard g(m_aMutex);
+ const uno::Any* pIter = aArguments.getConstArray();
+ const uno::Any* pEnd = pIter + aArguments.getLength();
+ for(;pIter != pEnd;++pIter)
+ {
+ if ( !m_xActiveConnection.is() )
+ (*pIter) >>= m_xActiveConnection;
+ else if ( !m_xHandler.is() )
+ (*pIter) >>= m_xHandler;
+ }
+ m_xAggregateSet->setPropertyValue( PROPERTY_ACTIVE_CONNECTION, uno::Any( m_xActiveConnection ) );
+}
+
+// chart2::data::XDataProvider:
+sal_Bool SAL_CALL DatabaseDataProvider::createDataSourcePossible(const uno::Sequence< beans::PropertyValue > & _aArguments)
+{
+ const beans::PropertyValue* pArgIter = _aArguments.getConstArray();
+ const beans::PropertyValue* pArgEnd = pArgIter + _aArguments.getLength();
+ for(;pArgIter != pArgEnd;++pArgIter)
+ {
+ if ( pArgIter->Name == "DataRowSource" )
+ {
+ css::chart::ChartDataRowSource eRowSource = css::chart::ChartDataRowSource_COLUMNS;
+ pArgIter->Value >>= eRowSource;
+ if ( eRowSource != css::chart::ChartDataRowSource_COLUMNS )
+ return false;
+ }
+ else if ( pArgIter->Name == "CellRangeRepresentation" )
+ {
+ OUString sRange;
+ pArgIter->Value >>= sRange;
+ if ( sRange != "all" )
+ return false;
+ }
+ else if ( pArgIter->Name == "FirstCellAsLabel" )
+ {
+ bool bFirstCellAsLabel = true;
+ pArgIter->Value >>= bFirstCellAsLabel;
+ if ( !bFirstCellAsLabel )
+ return false;
+ }
+ }
+ return true;
+}
+
+uno::Reference< chart2::data::XDataSource > SAL_CALL DatabaseDataProvider::createDataSource(const uno::Sequence< beans::PropertyValue > & _aArguments)
+{
+ osl::ResettableMutexGuard aClearForNotifies(m_aMutex);
+ if ( createDataSourcePossible(_aArguments) )
+ {
+ try
+ {
+ uno::Reference< chart::XChartDataArray> xChartData( m_xInternal, uno::UNO_QUERY_THROW );
+ xChartData->setData( uno::Sequence< uno::Sequence< double > >() );
+ xChartData->setColumnDescriptions( uno::Sequence< OUString >() );
+ if ( m_xInternal->hasDataByRangeRepresentation( OUString::number( 0 ) ) )
+ m_xInternal->deleteSequence(0);
+ }
+ catch( const uno::Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+
+ ::comphelper::NamedValueCollection aArgs( _aArguments );
+ const bool bHasCategories = aArgs.getOrDefault( "HasCategories", true );
+ uno::Sequence< OUString > aColumnNames =
+ aArgs.getOrDefault( "ColumnDescriptions", uno::Sequence< OUString >() );
+
+ bool bRet = false;
+ if ( !m_Command.isEmpty() && m_xActiveConnection.is() )
+ {
+ try
+ {
+ impl_fillRowSet_throw();
+ if ( impl_fillParameters_nothrow(aClearForNotifies) )
+ m_xRowSet->execute();
+ impl_fillInternalDataProvider_throw(bHasCategories,aColumnNames);
+ bRet = true;
+ }
+ catch(const uno::Exception& /*e*/)
+ {
+ }
+ }
+ if ( !bRet ) // no command set or an error occurred, use Internal data handler
+ {
+ uno::Reference< lang::XInitialization> xIni(m_xInternal,uno::UNO_QUERY);
+ if ( xIni.is() )
+ {
+ beans::NamedValue aParam("CreateDefaultData",uno::Any(true));
+ uno::Sequence< uno::Any > aInitArgs{ uno::Any(aParam) };
+ xIni->initialize(aInitArgs);
+ }
+ }
+
+ }
+ return m_xInternal->createDataSource(_aArguments);
+}
+
+uno::Sequence< beans::PropertyValue > SAL_CALL DatabaseDataProvider::detectArguments(const uno::Reference< chart2::data::XDataSource > & _xDataSource)
+{
+ ::comphelper::NamedValueCollection aArguments;
+ aArguments.put( "CellRangeRepresentation", uno::Any( OUString( "all" ) ) );
+ aArguments.put( "DataRowSource", uno::Any( chart::ChartDataRowSource_COLUMNS ) );
+ // internal data always contains labels
+ aArguments.put( "FirstCellAsLabel", uno::Any( true ) );
+
+ bool bHasCategories = false;
+ if( _xDataSource.is())
+ {
+ uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence > > aSequences(_xDataSource->getDataSequences());
+ const sal_Int32 nCount( aSequences.getLength());
+ for( sal_Int32 nIdx=0; nIdx<nCount; ++nIdx )
+ {
+ if( aSequences[nIdx].is() )
+ {
+ uno::Reference< beans::XPropertySet > xSeqProp( aSequences[nIdx]->getValues(), uno::UNO_QUERY );
+ OUString aRole;
+ if ( xSeqProp.is()
+ && ( xSeqProp->getPropertyValue( "Role" ) >>= aRole )
+ && aRole == "categories"
+ )
+ {
+ bHasCategories = true;
+ break;
+ }
+ }
+ }
+ }
+ aArguments.put( "HasCategories", uno::Any( bHasCategories ) );
+ return aArguments.getPropertyValues();
+}
+
+sal_Bool SAL_CALL DatabaseDataProvider::createDataSequenceByRangeRepresentationPossible(const OUString & /*aRangeRepresentation*/)
+{
+ return true;
+}
+
+uno::Any DatabaseDataProvider::impl_getNumberFormatKey_nothrow(const OUString & _sRangeRepresentation) const
+{
+ std::map< OUString,css::uno::Any>::const_iterator aFind = m_aNumberFormats.find(_sRangeRepresentation);
+ if ( aFind != m_aNumberFormats.end() )
+ return aFind->second;
+ return uno::Any(sal_Int32(0));
+}
+
+uno::Reference< chart2::data::XDataSequence > SAL_CALL DatabaseDataProvider::createDataSequenceByRangeRepresentation(const OUString & _sRangeRepresentation)
+{
+ osl::MutexGuard g(m_aMutex);
+ uno::Reference< chart2::data::XDataSequence > xData = m_xInternal->createDataSequenceByRangeRepresentation(_sRangeRepresentation);
+ uno::Reference<beans::XPropertySet> xProp(xData,uno::UNO_QUERY);
+ static constexpr OUStringLiteral s_sNumberFormatKey = u"NumberFormatKey";
+ if ( xProp.is() && xProp->getPropertySetInfo()->hasPropertyByName(s_sNumberFormatKey) )
+ {
+ xProp->setPropertyValue(s_sNumberFormatKey,impl_getNumberFormatKey_nothrow(_sRangeRepresentation));
+ }
+ return xData;
+}
+
+uno::Reference<chart2::data::XDataSequence>
+SAL_CALL DatabaseDataProvider::createDataSequenceByValueArray(
+ const OUString& /*aRole*/, const OUString& /*aRangeRepresentation*/, const OUString& /*aRoleQualifier*/ )
+{
+ return uno::Reference<chart2::data::XDataSequence>();
+}
+
+uno::Sequence< uno::Sequence< OUString > > SAL_CALL DatabaseDataProvider::getComplexRowDescriptions()
+{
+ return m_xComplexDescriptionAccess->getComplexRowDescriptions();
+}
+
+void SAL_CALL DatabaseDataProvider::setComplexRowDescriptions( const uno::Sequence< uno::Sequence< OUString > >& aRowDescriptions )
+{
+ m_xComplexDescriptionAccess->setComplexRowDescriptions(aRowDescriptions);
+}
+
+uno::Sequence< uno::Sequence< OUString > > SAL_CALL DatabaseDataProvider::getComplexColumnDescriptions()
+{
+ return m_xComplexDescriptionAccess->getComplexColumnDescriptions();
+}
+
+void SAL_CALL DatabaseDataProvider::setComplexColumnDescriptions( const uno::Sequence< uno::Sequence< OUString > >& aColumnDescriptions )
+{
+ m_xComplexDescriptionAccess->setComplexColumnDescriptions(aColumnDescriptions);
+}
+
+// ____ XChartDataArray ____
+uno::Sequence< uno::Sequence< double > > SAL_CALL DatabaseDataProvider::getData()
+{
+ return m_xComplexDescriptionAccess->getData();
+}
+
+void SAL_CALL DatabaseDataProvider::setData( const uno::Sequence< uno::Sequence< double > >& rDataInRows )
+{
+ m_xComplexDescriptionAccess->setData(rDataInRows);
+}
+
+void SAL_CALL DatabaseDataProvider::setRowDescriptions( const uno::Sequence< OUString >& aRowDescriptions )
+{
+ m_xComplexDescriptionAccess->setRowDescriptions(aRowDescriptions);
+}
+
+void SAL_CALL DatabaseDataProvider::setColumnDescriptions( const uno::Sequence< OUString >& aColumnDescriptions )
+{
+ m_xComplexDescriptionAccess->setColumnDescriptions(aColumnDescriptions);
+}
+
+uno::Sequence< OUString > SAL_CALL DatabaseDataProvider::getRowDescriptions()
+{
+ return m_xComplexDescriptionAccess->getRowDescriptions();
+}
+
+uno::Sequence< OUString > SAL_CALL DatabaseDataProvider::getColumnDescriptions()
+{
+ return m_xComplexDescriptionAccess->getColumnDescriptions();
+}
+
+// ____ XChartData (base of XChartDataArray) ____
+void SAL_CALL DatabaseDataProvider::addChartDataChangeEventListener(const uno::Reference< css::chart::XChartDataChangeEventListener >& x)
+{
+ m_xComplexDescriptionAccess->addChartDataChangeEventListener(x);
+}
+
+void SAL_CALL DatabaseDataProvider::removeChartDataChangeEventListener(const uno::Reference< css::chart::XChartDataChangeEventListener >& x)
+{
+ m_xComplexDescriptionAccess->removeChartDataChangeEventListener(x);
+}
+
+double SAL_CALL DatabaseDataProvider::getNotANumber()
+{
+ return m_xComplexDescriptionAccess->getNotANumber();
+}
+
+sal_Bool SAL_CALL DatabaseDataProvider::isNotANumber( double nNumber )
+{
+ return m_xComplexDescriptionAccess->isNotANumber(nNumber);
+}
+
+uno::Reference< sheet::XRangeSelection > SAL_CALL DatabaseDataProvider::getRangeSelection()
+{
+ // TODO: Exchange the default return implementation for "getRangeSelection" !!!
+ // Exchange the default return implementation.
+ // NOTE: Default initialized polymorphic structs can cause problems because of
+ // missing default initialization of primitive types of some C++ compilers or
+ // different Any initialization in Java and C++ polymorphic structs.
+ return uno::Reference< sheet::XRangeSelection >();
+}
+
+// chart2::data::XRangeXMLConversion:
+OUString SAL_CALL DatabaseDataProvider::convertRangeToXML(const OUString & _sRangeRepresentation)
+{
+ osl::MutexGuard g(m_aMutex);
+ return m_xRangeConversion->convertRangeToXML(_sRangeRepresentation);
+}
+
+OUString SAL_CALL DatabaseDataProvider::convertRangeFromXML(const OUString & _sXMLRange)
+{
+ osl::MutexGuard g(m_aMutex);
+ return m_xRangeConversion->convertRangeFromXML(_sXMLRange);
+}
+
+// com.sun.star.beans.XPropertySet:
+uno::Reference< beans::XPropertySetInfo > SAL_CALL DatabaseDataProvider::getPropertySetInfo()
+{
+ return ::cppu::PropertySetMixin< chart2::data::XDatabaseDataProvider >::getPropertySetInfo();
+}
+
+void SAL_CALL DatabaseDataProvider::setPropertyValue(const OUString & aPropertyName, const uno::Any & aValue)
+{
+ ::cppu::PropertySetMixin< chart2::data::XDatabaseDataProvider >::setPropertyValue(aPropertyName, aValue);
+}
+
+uno::Any SAL_CALL DatabaseDataProvider::getPropertyValue(const OUString & aPropertyName)
+{
+ return ::cppu::PropertySetMixin< chart2::data::XDatabaseDataProvider >::getPropertyValue(aPropertyName);
+}
+
+void SAL_CALL DatabaseDataProvider::addPropertyChangeListener(const OUString & aPropertyName, const uno::Reference< beans::XPropertyChangeListener > & xListener)
+{
+ ::cppu::PropertySetMixin< chart2::data::XDatabaseDataProvider >::addPropertyChangeListener(aPropertyName, xListener);
+}
+
+void SAL_CALL DatabaseDataProvider::removePropertyChangeListener(const OUString & aPropertyName, const uno::Reference< beans::XPropertyChangeListener > & xListener)
+{
+ ::cppu::PropertySetMixin< chart2::data::XDatabaseDataProvider >::removePropertyChangeListener(aPropertyName, xListener);
+}
+
+void SAL_CALL DatabaseDataProvider::addVetoableChangeListener(const OUString & aPropertyName, const uno::Reference< beans::XVetoableChangeListener > & xListener)
+{
+ ::cppu::PropertySetMixin< chart2::data::XDatabaseDataProvider >::addVetoableChangeListener(aPropertyName, xListener);
+}
+
+void SAL_CALL DatabaseDataProvider::removeVetoableChangeListener(const OUString & aPropertyName, const uno::Reference< beans::XVetoableChangeListener > & xListener)
+{
+ ::cppu::PropertySetMixin< chart2::data::XDatabaseDataProvider >::removeVetoableChangeListener(aPropertyName, xListener);
+}
+
+// chart2::data::XDatabaseDataProvider:
+uno::Sequence< OUString > SAL_CALL DatabaseDataProvider::getMasterFields()
+{
+ osl::MutexGuard g(m_aMutex);
+ return m_MasterFields;
+}
+
+void SAL_CALL DatabaseDataProvider::setMasterFields(const uno::Sequence< OUString > & the_value)
+{
+ impl_invalidateParameter_nothrow();
+ set("MasterFields",the_value,m_MasterFields);
+}
+
+uno::Sequence< OUString > SAL_CALL DatabaseDataProvider::getDetailFields()
+{
+ osl::MutexGuard g(m_aMutex);
+ return m_DetailFields;
+}
+
+void SAL_CALL DatabaseDataProvider::setDetailFields(const uno::Sequence< OUString > & the_value)
+{
+ set("DetailFields",the_value,m_DetailFields);
+}
+
+OUString SAL_CALL DatabaseDataProvider::getCommand()
+{
+ osl::MutexGuard g(m_aMutex);
+ return m_Command;
+}
+
+void SAL_CALL DatabaseDataProvider::setCommand(const OUString & the_value)
+{
+ {
+ osl::MutexGuard g(m_aMutex);
+ impl_invalidateParameter_nothrow();
+ m_xAggregateSet->setPropertyValue( PROPERTY_COMMAND, uno::Any( the_value ) );
+ }
+ set(PROPERTY_COMMAND,the_value,m_Command);
+}
+
+::sal_Int32 SAL_CALL DatabaseDataProvider::getCommandType()
+{
+ osl::MutexGuard g(m_aMutex);
+ return m_CommandType;
+}
+
+void SAL_CALL DatabaseDataProvider::setCommandType(::sal_Int32 the_value)
+{
+ {
+ osl::MutexGuard g(m_aMutex);
+ m_xAggregateSet->setPropertyValue( PROPERTY_COMMAND_TYPE, uno::Any( the_value ) );
+ }
+ set(PROPERTY_COMMAND_TYPE,the_value,m_CommandType);
+}
+
+OUString SAL_CALL DatabaseDataProvider::getFilter()
+{
+ osl::MutexGuard g(m_aMutex);
+ return m_aFilterManager.getFilterComponent( dbtools::FilterManager::FilterComponent::PublicFilter );
+}
+
+void SAL_CALL DatabaseDataProvider::setFilter(const OUString & the_value)
+{
+ {
+ osl::MutexGuard g(m_aMutex);
+ m_aFilterManager.setFilterComponent( dbtools::FilterManager::FilterComponent::PublicFilter, the_value );
+ }
+ set(PROPERTY_FILTER,the_value,m_Filter);
+}
+
+sal_Bool SAL_CALL DatabaseDataProvider::getApplyFilter()
+{
+ osl::MutexGuard g(m_aMutex);
+ return m_ApplyFilter;
+}
+
+void SAL_CALL DatabaseDataProvider::setApplyFilter( sal_Bool the_value )
+{
+ {
+ osl::MutexGuard g(m_aMutex);
+ m_xAggregateSet->setPropertyValue( PROPERTY_APPLYFILTER, uno::Any( the_value ) );
+ }
+ set(PROPERTY_APPLYFILTER,static_cast<bool>(the_value),m_ApplyFilter);
+}
+
+OUString SAL_CALL DatabaseDataProvider::getHavingClause()
+{
+ osl::MutexGuard g(m_aMutex);
+ return m_HavingClause;
+}
+
+void SAL_CALL DatabaseDataProvider::setHavingClause( const OUString& the_value )
+{
+ {
+ osl::MutexGuard g(m_aMutex);
+ m_xAggregateSet->setPropertyValue( PROPERTY_HAVING_CLAUSE, uno::Any( the_value ) );
+ }
+ set(PROPERTY_HAVING_CLAUSE,the_value,m_HavingClause);
+}
+
+OUString SAL_CALL DatabaseDataProvider::getGroupBy()
+{
+ osl::MutexGuard g(m_aMutex);
+ return m_GroupBy;
+}
+
+void SAL_CALL DatabaseDataProvider::setGroupBy( const OUString& the_value )
+{
+ {
+ osl::MutexGuard g(m_aMutex);
+ m_xAggregateSet->setPropertyValue( PROPERTY_GROUP_BY, uno::Any( the_value ) );
+ }
+ set(PROPERTY_GROUP_BY,the_value,m_GroupBy);
+}
+
+OUString SAL_CALL DatabaseDataProvider::getOrder()
+{
+ osl::MutexGuard g(m_aMutex);
+ return m_Order;
+}
+
+void SAL_CALL DatabaseDataProvider::setOrder( const OUString& the_value )
+{
+ {
+ osl::MutexGuard g(m_aMutex);
+ m_xAggregateSet->setPropertyValue( PROPERTY_ORDER, uno::Any( the_value ) );
+ }
+ set(PROPERTY_ORDER,the_value,m_Order);
+}
+
+sal_Bool SAL_CALL DatabaseDataProvider::getEscapeProcessing()
+{
+ osl::MutexGuard g(m_aMutex);
+ return m_EscapeProcessing;
+}
+
+void SAL_CALL DatabaseDataProvider::setEscapeProcessing(sal_Bool the_value)
+{
+ set(PROPERTY_ESCAPE_PROCESSING,static_cast<bool>(the_value),m_EscapeProcessing);
+}
+
+::sal_Int32 SAL_CALL DatabaseDataProvider::getRowLimit()
+{
+ osl::MutexGuard g(m_aMutex);
+ return m_RowLimit;
+}
+
+void SAL_CALL DatabaseDataProvider::setRowLimit(::sal_Int32 the_value)
+{
+ set("RowLimit",the_value,m_RowLimit);
+}
+
+uno::Reference< sdbc::XConnection > SAL_CALL DatabaseDataProvider::getActiveConnection()
+{
+ osl::MutexGuard g(m_aMutex);
+ return m_xActiveConnection;
+}
+
+void SAL_CALL DatabaseDataProvider::setActiveConnection(const uno::Reference< sdbc::XConnection > & the_value)
+{
+ if ( !the_value.is() )
+ throw lang::IllegalArgumentException();
+ set(PROPERTY_ACTIVE_CONNECTION,the_value,m_xActiveConnection);
+}
+
+OUString SAL_CALL DatabaseDataProvider::getDataSourceName()
+{
+ osl::MutexGuard g(m_aMutex);
+ return m_DataSourceName;
+}
+
+void SAL_CALL DatabaseDataProvider::setDataSourceName(const OUString& the_value)
+{
+ set(PROPERTY_DATASOURCENAME,the_value,m_DataSourceName);
+}
+
+namespace
+{
+ struct ColumnDescription
+ {
+ OUString sName;
+ sal_Int32 nResultSetPosition;
+ sal_Int32 nDataType;
+
+ ColumnDescription()
+ :nResultSetPosition( 0 )
+ ,nDataType( sdbc::DataType::VARCHAR )
+ {
+ }
+ explicit ColumnDescription( const OUString& i_rName )
+ :sName( i_rName )
+ ,nResultSetPosition( 0 )
+ ,nDataType( sdbc::DataType::VARCHAR )
+ {
+ }
+ };
+
+ struct CreateColumnDescription
+ {
+ ColumnDescription operator()( const OUString& i_rName )
+ {
+ return ColumnDescription( i_rName );
+ }
+ };
+
+ struct SelectColumnName
+ {
+ const OUString& operator()( const ColumnDescription& i_rColumn )
+ {
+ return i_rColumn.sName;
+ }
+ };
+}
+
+void DatabaseDataProvider::impl_fillInternalDataProvider_throw(bool _bHasCategories,const uno::Sequence< OUString >& i_aColumnNames)
+{
+ // clear the data before fill the new one
+ uno::Reference< sdbcx::XColumnsSupplier > xColSup(m_xRowSet,uno::UNO_QUERY_THROW);
+ uno::Reference< container::XNameAccess > xColumns( xColSup->getColumns(), uno::UNO_SET_THROW );
+ const uno::Sequence< OUString > aRowSetColumnNames( xColumns->getElementNames() );
+
+ typedef std::vector< ColumnDescription > ColumnDescriptions;
+ ColumnDescriptions aColumns;
+ bool bFirstColumnIsCategory = _bHasCategories;
+ if ( i_aColumnNames.hasElements() )
+ {
+ // some normalizations ...
+ uno::Sequence< OUString > aImposedColumnNames( i_aColumnNames );
+
+ // strangely, there exist documents where the ColumnDescriptions end with a number of empty strings. /me
+ // thinks they're generated when you have a chart based on a result set with n columns, but remove some
+ // of those columns from the chart - it looks like a bug in the report XML export to me.
+ // So, get rid of the "trailing" empty columns
+ sal_Int32 nLastNonEmptyColName = aImposedColumnNames.getLength() - 1;
+ for ( ; nLastNonEmptyColName >= 0; --nLastNonEmptyColName )
+ {
+ if ( !aImposedColumnNames[ nLastNonEmptyColName ].isEmpty() )
+ break;
+ }
+ aImposedColumnNames.realloc( nLastNonEmptyColName + 1 );
+
+ // second, for X-Y-charts the ColumnDescriptions exported by chart miss the name of the first (non-category)
+ // column. This, this results in a ColumnDescriptions array like <"", "col2", "col3">, where you'd expect
+ // <"col1", "col2", "col3">.
+ // Fix this with some heuristics:
+ if ( aImposedColumnNames.hasElements() && ( !aImposedColumnNames[0].isEmpty() ) )
+ {
+ const sal_Int32 nAssumedRowSetColumnIndex = _bHasCategories ? 1 : 0;
+ if ( nAssumedRowSetColumnIndex < aRowSetColumnNames.getLength() )
+ aImposedColumnNames.getArray()[0] = aRowSetColumnNames[ nAssumedRowSetColumnIndex ];
+ }
+
+ const sal_Int32 nCount = aImposedColumnNames.getLength();
+ for ( sal_Int32 i = 0 ; i < nCount; ++i )
+ {
+ const OUString sColumnName( aImposedColumnNames[i] );
+ if ( !xColumns->hasByName( sColumnName ) )
+ continue;
+
+ if ( _bHasCategories && aColumns.empty() )
+ {
+ if ( aRowSetColumnNames.hasElements() )
+ aColumns.emplace_back( aRowSetColumnNames[0] );
+ else
+ aColumns.emplace_back( sColumnName );
+ bFirstColumnIsCategory = true;
+ }
+ aColumns.emplace_back( sColumnName );
+ }
+ }
+ if ( aColumns.empty() )
+ {
+ aColumns.resize( aRowSetColumnNames.getLength() );
+ std::transform(
+ aRowSetColumnNames.begin(),
+ aRowSetColumnNames.end(),
+ aColumns.begin(),
+ CreateColumnDescription()
+ );
+ }
+
+ // fill the data
+ uno::Reference< sdbc::XResultSet> xRes( m_xRowSet, uno::UNO_QUERY_THROW );
+ uno::Reference< sdbc::XRow> xRow( m_xRowSet,uno::UNO_QUERY_THROW );
+ uno::Reference< sdbc::XResultSetMetaDataSupplier > xSuppMeta( m_xRowSet,uno::UNO_QUERY_THROW );
+ uno::Reference< sdbc::XColumnLocate > xColumnLocate( m_xRowSet, uno::UNO_QUERY_THROW );
+
+ sal_Int32 columnIndex = 0;
+ for (auto & column : aColumns)
+ {
+ column.nResultSetPosition = xColumnLocate->findColumn( column.sName );
+
+ const uno::Reference< beans::XPropertySet > xColumn( xColumns->getByName( column.sName ), uno::UNO_QUERY_THROW );
+ const uno::Any aNumberFormat( xColumn->getPropertyValue( PROPERTY_NUMBERFORMAT ) );
+ OSL_VERIFY( xColumn->getPropertyValue( PROPERTY_TYPE ) >>= column.nDataType );
+
+ const OUString sRangeName = OUString::number( columnIndex );
+ m_aNumberFormats.emplace( sRangeName, aNumberFormat );
+ ++columnIndex;
+ }
+
+ std::vector< OUString > aRowLabels;
+ std::vector< std::vector< double > > aDataValues;
+ sal_Int32 nRowCount = 0;
+ ::connectivity::ORowSetValue aValue;
+ while( xRes->next() && (!m_RowLimit || nRowCount < m_RowLimit) )
+ {
+ ++nRowCount;
+
+ aValue.fill( aColumns[0].nResultSetPosition, aColumns[0].nDataType, xRow );
+ aRowLabels.push_back( aValue.getString() );
+
+ std::vector< double > aRow;
+ bool bFirstLoop = true;
+ for (auto const& column : aColumns)
+ {
+ if (bFirstLoop)
+ {
+ bFirstLoop = false;
+ if (bFirstColumnIsCategory)
+ continue;
+ }
+
+ aValue.fill( column.nResultSetPosition, column.nDataType, xRow );
+ if ( aValue.isNull() )
+ aRow.push_back( std::numeric_limits<double>::quiet_NaN() );
+ else
+ aRow.push_back( aValue.getDouble() );
+ }
+
+ aDataValues.push_back( aRow );
+ }
+
+ // insert default data when no rows exist
+ if ( !nRowCount )
+ {
+ nRowCount = 3;
+ static const double fDefaultData[ ] =
+ { 9.10, 3.20, 4.54,
+ 2.40, 8.80, 9.65,
+ 3.10, 1.50, 3.70,
+ 4.30, 9.02, 6.20 };
+ for(sal_Int32 h = 0,k = 0; h < nRowCount; ++h,++k )
+ {
+ aRowLabels.push_back(OUString::number(h+1));
+ std::vector< double > aRow;
+ const sal_Int32 nSize = SAL_N_ELEMENTS(fDefaultData);
+ for (size_t j = 0; j < (aColumns.size()-1); ++j,++k)
+ {
+ if ( k >= nSize )
+ k = 0;
+ aRow.push_back(fDefaultData[k]);
+ }
+ aDataValues.push_back(aRow);
+ }
+ }
+
+ uno::Reference< chart::XChartDataArray> xData(m_xInternal,uno::UNO_QUERY);
+ xData->setRowDescriptions(comphelper::containerToSequence(aRowLabels));
+
+ const size_t nOffset = bFirstColumnIsCategory ? 1 : 0;
+ uno::Sequence< OUString > aColumnDescriptions( aColumns.size() - nOffset );
+ std::transform(
+ aColumns.begin() + nOffset,
+ aColumns.end(),
+ aColumnDescriptions.getArray(),
+ SelectColumnName()
+ );
+ xData->setColumnDescriptions( aColumnDescriptions );
+
+ uno::Sequence< uno::Sequence< double > > aData(aDataValues.size());
+ uno::Sequence< double >* pDataIter = aData.getArray();
+ uno::Sequence< double >* pDataEnd = pDataIter + aData.getLength();
+ for(sal_Int32 i= 0;pDataIter != pDataEnd; ++pDataIter,++i )
+ {
+ if ( !aDataValues[i].empty() )
+ *pDataIter = comphelper::containerToSequence(aDataValues[i]);
+ }
+ xData->setData(aData);
+}
+
+void DatabaseDataProvider::impl_fillRowSet_throw()
+{
+ m_xAggregateSet->setPropertyValue( PROPERTY_FILTER, uno::Any( getFilter() ) );
+ uno::Reference< sdbc::XParameters> xParam(m_xRowSet,uno::UNO_QUERY_THROW);
+ xParam->clearParameters( );
+}
+
+bool DatabaseDataProvider::impl_fillParameters_nothrow( ::osl::ResettableMutexGuard& _rClearForNotifies)
+{
+ // do we have to fill the parameters again?
+ if ( !m_aParameterManager.isUpToDate() )
+ m_aParameterManager.updateParameterInfo( m_aFilterManager );
+
+ if ( m_aParameterManager.isUpToDate() )
+ return m_aParameterManager.fillParameterValues( m_xHandler, _rClearForNotifies );
+
+ return true;
+}
+
+// css::sdbc::XParameters
+void SAL_CALL DatabaseDataProvider::setNull(sal_Int32 parameterIndex, sal_Int32 sqlType)
+{
+ m_aParameterManager.setNull(parameterIndex, sqlType);
+}
+
+void SAL_CALL DatabaseDataProvider::setObjectNull(sal_Int32 parameterIndex, sal_Int32 sqlType, const OUString& typeName)
+{
+ m_aParameterManager.setObjectNull(parameterIndex, sqlType, typeName);
+}
+
+void SAL_CALL DatabaseDataProvider::setBoolean(sal_Int32 parameterIndex, sal_Bool x)
+{
+ m_aParameterManager.setBoolean(parameterIndex, x);
+}
+
+void SAL_CALL DatabaseDataProvider::setByte(sal_Int32 parameterIndex, sal_Int8 x)
+{
+ m_aParameterManager.setByte(parameterIndex, x);
+}
+
+void SAL_CALL DatabaseDataProvider::setShort(sal_Int32 parameterIndex, sal_Int16 x)
+{
+ m_aParameterManager.setShort(parameterIndex, x);
+}
+
+void SAL_CALL DatabaseDataProvider::setInt(sal_Int32 parameterIndex, sal_Int32 x)
+{
+ m_aParameterManager.setInt(parameterIndex, x);
+}
+
+void SAL_CALL DatabaseDataProvider::setLong(sal_Int32 parameterIndex, sal_Int64 x)
+{
+ m_aParameterManager.setLong(parameterIndex, x);
+}
+
+void SAL_CALL DatabaseDataProvider::setFloat(sal_Int32 parameterIndex, float x)
+{
+ m_aParameterManager.setFloat(parameterIndex, x);
+}
+
+void SAL_CALL DatabaseDataProvider::setDouble(sal_Int32 parameterIndex, double x)
+{
+ m_aParameterManager.setDouble(parameterIndex, x);
+}
+
+void SAL_CALL DatabaseDataProvider::setString(sal_Int32 parameterIndex, const OUString& x)
+{
+ m_aParameterManager.setString(parameterIndex, x);
+}
+
+void SAL_CALL DatabaseDataProvider::setBytes(sal_Int32 parameterIndex, const uno::Sequence< sal_Int8 >& x)
+{
+ m_aParameterManager.setBytes(parameterIndex, x);
+}
+
+void SAL_CALL DatabaseDataProvider::setDate(sal_Int32 parameterIndex, const util::Date& x)
+{
+ m_aParameterManager.setDate(parameterIndex, x);
+}
+
+void SAL_CALL DatabaseDataProvider::setTime(sal_Int32 parameterIndex, const util::Time& x)
+{
+ m_aParameterManager.setTime(parameterIndex, x);
+}
+
+void SAL_CALL DatabaseDataProvider::setTimestamp(sal_Int32 parameterIndex, const util::DateTime& x)
+{
+ m_aParameterManager.setTimestamp(parameterIndex, x);
+}
+
+void SAL_CALL DatabaseDataProvider::setBinaryStream(sal_Int32 parameterIndex, const uno::Reference<io::XInputStream>& x, sal_Int32 length)
+{
+ m_aParameterManager.setBinaryStream(parameterIndex, x, length);
+}
+
+void SAL_CALL DatabaseDataProvider::setCharacterStream(sal_Int32 parameterIndex, const uno::Reference<io::XInputStream>& x, sal_Int32 length)
+{
+ m_aParameterManager.setCharacterStream(parameterIndex, x, length);
+}
+
+void SAL_CALL DatabaseDataProvider::setObjectWithInfo(sal_Int32 parameterIndex, const uno::Any& x, sal_Int32 targetSqlType, sal_Int32 scale)
+{
+ m_aParameterManager.setObjectWithInfo(parameterIndex, x, targetSqlType, scale);
+}
+
+void SAL_CALL DatabaseDataProvider::setObject(sal_Int32 parameterIndex, const uno::Any& x)
+{
+ m_aParameterManager.setObject(parameterIndex, x);
+}
+
+void SAL_CALL DatabaseDataProvider::setRef(sal_Int32 parameterIndex, const uno::Reference<sdbc::XRef>& x)
+{
+ m_aParameterManager.setRef(parameterIndex, x);
+}
+
+void SAL_CALL DatabaseDataProvider::setBlob(sal_Int32 parameterIndex, const uno::Reference<sdbc::XBlob>& x)
+{
+ m_aParameterManager.setBlob(parameterIndex, x);
+}
+
+void SAL_CALL DatabaseDataProvider::setClob(sal_Int32 parameterIndex, const uno::Reference<sdbc::XClob>& x)
+{
+ m_aParameterManager.setClob(parameterIndex, x);
+}
+
+void SAL_CALL DatabaseDataProvider::setArray(sal_Int32 parameterIndex, const Reference<sdbc::XArray>& x)
+{
+ m_aParameterManager.setArray(parameterIndex, x);
+}
+
+void SAL_CALL DatabaseDataProvider::clearParameters()
+{
+ m_aParameterManager.clearParameters();
+}
+
+// css::sdbc::XRowSet
+void SAL_CALL DatabaseDataProvider::execute()
+{
+ uno::Sequence< beans::PropertyValue > aEmpty;
+ createDataSource(aEmpty);
+}
+
+void SAL_CALL DatabaseDataProvider::addRowSetListener(const uno::Reference<sdbc::XRowSetListener>& _rListener)
+{
+ if (m_xRowSet.is())
+ m_xRowSet->addRowSetListener(_rListener);
+}
+
+void SAL_CALL DatabaseDataProvider::removeRowSetListener(const uno::Reference<sdbc::XRowSetListener>& _rListener)
+{
+ if (m_xRowSet.is())
+ m_xRowSet->removeRowSetListener(_rListener);
+}
+
+// css::sdbc::XResultSet
+sal_Bool SAL_CALL DatabaseDataProvider::next()
+{
+ return m_xRowSet->next();
+}
+
+sal_Bool SAL_CALL DatabaseDataProvider::isBeforeFirst()
+{
+ return m_xRowSet->isBeforeFirst();
+}
+
+sal_Bool SAL_CALL DatabaseDataProvider::isAfterLast()
+{
+ return m_xRowSet->isAfterLast();
+}
+
+sal_Bool SAL_CALL DatabaseDataProvider::isFirst()
+{
+ return m_xRowSet->isFirst();
+}
+
+sal_Bool SAL_CALL DatabaseDataProvider::isLast()
+{
+ return m_xRowSet->isLast();
+}
+
+void SAL_CALL DatabaseDataProvider::beforeFirst()
+{
+ m_xRowSet->beforeFirst();
+}
+
+void SAL_CALL DatabaseDataProvider::afterLast()
+{
+ m_xRowSet->afterLast();
+}
+
+sal_Bool SAL_CALL DatabaseDataProvider::first()
+{
+ return m_xRowSet->first();
+}
+
+sal_Bool SAL_CALL DatabaseDataProvider::last()
+{
+ return m_xRowSet->last();
+}
+
+sal_Int32 SAL_CALL DatabaseDataProvider::getRow()
+{
+ return m_xRowSet->getRow();
+}
+
+sal_Bool SAL_CALL DatabaseDataProvider::absolute(sal_Int32 row)
+{
+ return m_xRowSet->absolute(row);
+}
+
+sal_Bool SAL_CALL DatabaseDataProvider::relative(sal_Int32 rows)
+{
+ return m_xRowSet->relative(rows);
+}
+
+sal_Bool SAL_CALL DatabaseDataProvider::previous()
+{
+ return m_xRowSet->previous();
+}
+
+void SAL_CALL DatabaseDataProvider::refreshRow()
+{
+ m_xRowSet->refreshRow();
+}
+
+sal_Bool SAL_CALL DatabaseDataProvider::rowUpdated()
+{
+ return m_xRowSet->rowUpdated();
+}
+
+sal_Bool SAL_CALL DatabaseDataProvider::rowInserted()
+{
+ return m_xRowSet->rowInserted();
+}
+
+sal_Bool SAL_CALL DatabaseDataProvider::rowDeleted()
+{
+ return m_xRowSet->rowDeleted();
+}
+
+uno::Reference< uno::XInterface > SAL_CALL DatabaseDataProvider::getStatement()
+{
+ return m_xRowSet->getStatement();
+}
+
+uno::Reference< uno::XInterface > SAL_CALL DatabaseDataProvider::getParent( )
+{
+ return m_xParent;
+}
+
+void SAL_CALL DatabaseDataProvider::setParent( const uno::Reference< uno::XInterface >& _xParent )
+{
+ osl::MutexGuard g(m_aMutex);
+ m_xParent = _xParent;
+}
+
+void DatabaseDataProvider::impl_invalidateParameter_nothrow()
+{
+ osl::MutexGuard g(m_aMutex);
+ m_aParameterManager.clearAllParameterInformation();
+}
+
+} // namespace dbaccess
+
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+com_sun_star_comp_dbaccess_DatabaseDataProvider_get_implementation(
+ css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const& )
+{
+ return cppu::acquire(new dbaccess::DatabaseDataProvider(context));
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/misc/PropertyForward.cxx b/dbaccess/source/core/misc/PropertyForward.cxx
new file mode 100644
index 000000000..239bd422f
--- /dev/null
+++ b/dbaccess/source/core/misc/PropertyForward.cxx
@@ -0,0 +1,146 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <PropertyForward.hxx>
+
+#include <com/sun/star/lang/DisposedException.hpp>
+#include <com/sun/star/sdbcx/XDataDescriptorFactory.hpp>
+#include <com/sun/star/sdbcx/XAppend.hpp>
+
+#include <comphelper/property.hxx>
+#include <tools/diagnose_ex.h>
+
+namespace dbaccess
+{
+
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::beans;
+ using namespace ::com::sun::star::container;
+ using namespace ::com::sun::star::sdbcx;
+ using namespace ::com::sun::star::lang;
+
+
+ OPropertyForward::OPropertyForward( const Reference< XPropertySet>& _xSource, const Reference< XNameAccess>& _xDestContainer,
+ const OUString& _sName, const std::vector< OUString>& _aPropertyList )
+ :m_xSource( _xSource, UNO_SET_THROW )
+ ,m_xDestContainer( _xDestContainer, UNO_SET_THROW )
+ ,m_sName( _sName )
+ ,m_bInInsert( false )
+ {
+
+ osl_atomic_increment(&m_refCount);
+ try
+ {
+ if ( _aPropertyList.empty() )
+ _xSource->addPropertyChangeListener( OUString(), this );
+ else
+ {
+ for (auto const& property : _aPropertyList)
+ _xSource->addPropertyChangeListener(property, this);
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ osl_atomic_decrement( &m_refCount );
+ }
+
+ OPropertyForward::~OPropertyForward()
+ {
+ }
+
+ void SAL_CALL OPropertyForward::propertyChange( const PropertyChangeEvent& evt )
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ if ( !m_xDestContainer.is() )
+ throw DisposedException( OUString(), *this );
+
+ try
+ {
+ if ( !m_xDest.is() )
+ {
+ if ( m_xDestContainer->hasByName( m_sName ) )
+ {
+ m_xDest.set( m_xDestContainer->getByName( m_sName ), UNO_QUERY_THROW );
+ }
+ else
+ {
+ Reference< XDataDescriptorFactory > xFactory( m_xDestContainer, UNO_QUERY_THROW );
+ m_xDest.set( xFactory->createDataDescriptor(), UNO_SET_THROW );
+
+ ::comphelper::copyProperties( m_xSource, m_xDest );
+
+ m_bInInsert = true;
+ Reference< XAppend > xAppend( m_xDestContainer, UNO_QUERY_THROW );
+ xAppend->appendByDescriptor( m_xDest );
+ m_bInInsert = false;
+ }
+
+ m_xDestInfo.set( m_xDest->getPropertySetInfo(), UNO_SET_THROW );
+ }
+
+ if ( m_xDestInfo->hasPropertyByName( evt.PropertyName ) )
+ {
+ m_xDest->setPropertyValue( evt.PropertyName, evt.NewValue );
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+
+ void SAL_CALL OPropertyForward::disposing( const css::lang::EventObject& /*_rSource*/ )
+ {
+ ::osl::MutexGuard aGuard(m_aMutex);
+
+ if ( !m_xSource.is() )
+ throw DisposedException( OUString(), *this );
+
+ m_xSource->removePropertyChangeListener( OUString(), this );
+ m_xSource = nullptr;
+ m_xDestContainer = nullptr;
+ m_xDestInfo = nullptr;
+ m_xDest = nullptr;
+ }
+
+ void OPropertyForward::setDefinition( const css::uno::Reference< css::beans::XPropertySet>& _xDest )
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+ if ( m_bInInsert )
+ return;
+
+ OSL_ENSURE( !m_xDest.is(), "OPropertyForward::setDefinition: definition object is already set!" );
+ try
+ {
+ m_xDest.set( _xDest, UNO_SET_THROW );
+ m_xDestInfo.set( m_xDest->getPropertySetInfo(), UNO_SET_THROW );
+ ::comphelper::copyProperties( m_xDest, m_xSource );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+
+} // namespace dbaccess
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/misc/apitools.cxx b/dbaccess/source/core/misc/apitools.cxx
new file mode 100644
index 000000000..efec92cf5
--- /dev/null
+++ b/dbaccess/source/core/misc/apitools.cxx
@@ -0,0 +1,114 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <apitools.hxx>
+#include <cppuhelper/typeprovider.hxx>
+#include <sal/log.hxx>
+
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace cppu;
+using namespace osl;
+
+// various helper functions
+// OSubComponent
+OSubComponent::OSubComponent(Mutex& _rMutex, const Reference< XInterface > & xParent)
+ :OComponentHelper(_rMutex)
+ ,m_xParent(xParent)
+{
+
+}
+
+OSubComponent::~OSubComponent()
+{
+ m_xParent = nullptr;
+
+}
+
+// css::lang::XTypeProvider
+Sequence< Type > OSubComponent::getTypes()
+{
+ OTypeCollection aTypes(cppu::UnoType<XComponent>::get(),
+ cppu::UnoType<XTypeProvider>::get(),
+ cppu::UnoType<XWeak>::get());
+
+ return aTypes.getTypes();
+}
+
+// XInterface
+
+void OSubComponent::release() noexcept
+{
+ Reference< XInterface > x( xDelegator );
+ if (! x.is())
+ {
+ if (osl_atomic_decrement( &m_refCount ) == 0 )
+ {
+ if (! rBHelper.bDisposed)
+ {
+ // *before* again incrementing our ref count, ensure that our weak connection point
+ // will not create references to us anymore (via XAdapter::queryAdapted)
+ disposeWeakConnectionPoint();
+
+ Reference< XInterface > xHoldAlive( *this );
+ // remember the parent
+ Reference< XInterface > xParent;
+ {
+ MutexGuard aGuard( rBHelper.rMutex );
+ xParent = m_xParent;
+ m_xParent = nullptr;
+ }
+
+ SAL_WARN_IF( m_refCount != 1, "dbaccess.core", "OSubComponent::release: invalid ref count (before dispose)!" );
+
+ // First dispose
+ dispose();
+
+ // only the alive ref holds the object
+ SAL_WARN_IF( m_refCount != 1, "dbaccess.core", "OSubComponent::release: invalid ref count (after dispose)!" );
+
+ // release the parent in the ~
+ if (xParent.is())
+ {
+ MutexGuard aGuard( rBHelper.rMutex );
+ m_xParent = xParent;
+ }
+
+ // destroy the object if xHoldAlive decrement the refcount to 0
+ return;
+ }
+ }
+ // restore the reference count
+ osl_atomic_increment( &m_refCount );
+ }
+
+ // as we cover the job of the componenthelper we use the ...
+ OWeakAggObject::release();
+}
+
+Any OSubComponent::queryInterface( const Type & rType )
+{
+ Any aReturn;
+ if (!rType.equals(cppu::UnoType<XAggregation>::get()))
+ aReturn = OComponentHelper::queryInterface(rType);
+
+ return aReturn;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/misc/dsntypes.cxx b/dbaccess/source/core/misc/dsntypes.cxx
new file mode 100644
index 000000000..d8ceed402
--- /dev/null
+++ b/dbaccess/source/core/misc/dsntypes.cxx
@@ -0,0 +1,565 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <config_java.h>
+#include <dsntypes.hxx>
+#include <unotools/confignode.hxx>
+#include <o3tl/safeint.hxx>
+#include <o3tl/string_view.hxx>
+#include <osl/diagnose.h>
+#include <tools/wldcrd.hxx>
+#include <osl/file.hxx>
+#include <officecfg/Office/Common.hxx>
+#include <comphelper/string.hxx>
+
+namespace dbaccess
+{
+
+ using namespace ::com::sun::star;
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::beans;
+ using namespace ::com::sun::star::lang;
+
+ namespace
+ {
+ void lcl_extractHostAndPort(std::u16string_view _sUrl, OUString& _sHostname, sal_Int32& _nPortNumber)
+ {
+ if ( comphelper::string::getTokenCount(_sUrl, ':') >= 2 )
+ {
+ sal_Int32 nPos {0};
+ _sHostname = o3tl::getToken(_sUrl, 0, ':', nPos);
+ _nPortNumber = o3tl::toInt32(o3tl::getToken(_sUrl, 0, ':', nPos));
+ }
+ }
+ }
+// ODsnTypeCollection
+ODsnTypeCollection::ODsnTypeCollection(const css::uno::Reference< css::uno::XComponentContext >& _xContext)
+:m_aDriverConfig(_xContext)
+#if OSL_DEBUG_LEVEL > 0
+,m_nLivingIterators(0)
+#endif
+{
+ const uno::Sequence< OUString > aURLs = m_aDriverConfig.getURLs();
+ const OUString* pIter = aURLs.getConstArray();
+ const OUString* pEnd = pIter + aURLs.getLength();
+ for(;pIter != pEnd;++pIter )
+ {
+ m_aDsnPrefixes.push_back(*pIter);
+ m_aDsnTypesDisplayNames.push_back(m_aDriverConfig.getDriverTypeDisplayName(*pIter));
+ }
+
+ OSL_ENSURE(m_aDsnTypesDisplayNames.size() == m_aDsnPrefixes.size(),
+ "ODsnTypeCollection::ODsnTypeCollection : invalid resources !");
+}
+
+ODsnTypeCollection::~ODsnTypeCollection()
+{
+#if OSL_DEBUG_LEVEL > 0
+ OSL_ENSURE(0 == m_nLivingIterators, "ODsnTypeCollection::~ODsnTypeCollection : there are still living iterator objects!");
+#endif
+}
+
+OUString ODsnTypeCollection::getTypeDisplayName(std::u16string_view _sURL) const
+{
+ return m_aDriverConfig.getDriverTypeDisplayName(_sURL);
+}
+
+OUString ODsnTypeCollection::cutPrefix(std::u16string_view _sURL) const
+{
+ OUString sRet;
+ OUString sOldPattern;
+
+ // on Windows or with gen rendering, the urls may begin with an ~
+ std::u16string_view sCleanURL = comphelper::string::stripStart(_sURL, '~');
+
+ for (auto const& dsnPrefix : m_aDsnPrefixes)
+ {
+ WildCard aWildCard(dsnPrefix);
+ if ( sOldPattern.getLength() < dsnPrefix.getLength() && aWildCard.Matches(sCleanURL) )
+ {
+ // This relies on the fact that all patterns are of the form
+ // foo*
+ // that is, the very concept of "prefix" applies.
+ OUString prefix(comphelper::string::stripEnd(dsnPrefix, '*'));
+ OSL_ENSURE(o3tl::make_unsigned(prefix.getLength()) <= sCleanURL.size(), "How can A match B when A shorter than B?");
+ sRet = sCleanURL.substr(prefix.getLength());
+ sOldPattern = dsnPrefix;
+ }
+ }
+
+ return sRet;
+}
+
+OUString ODsnTypeCollection::getPrefix(const OUString& _sURL) const
+{
+ OUString sRet;
+ OUString sOldPattern;
+ for (auto const& dsnPrefix : m_aDsnPrefixes)
+ {
+ WildCard aWildCard(dsnPrefix);
+ if ( sOldPattern.getLength() < dsnPrefix.getLength() && aWildCard.Matches(_sURL) )
+ {
+ // This relies on the fact that all patterns are of the form
+ // foo*
+ // that is, the very concept of "prefix" applies.
+ sRet = comphelper::string::stripEnd(dsnPrefix, '*');
+ OSL_ENSURE(sRet.getLength() <= _sURL.getLength(), "How can A match B when A shorter than B?");
+ sOldPattern = dsnPrefix;
+ }
+ }
+
+ return sRet;
+}
+
+bool ODsnTypeCollection::hasDriver( const char* _pAsciiPattern ) const
+{
+ OUString sPrefix( getPrefix( OUString::createFromAscii( _pAsciiPattern ) ) );
+ return !sPrefix.isEmpty();
+}
+
+bool ODsnTypeCollection::isConnectionUrlRequired(std::u16string_view _sURL) const
+{
+ OUString sRet;
+ OUString sOldPattern;
+ for (auto const& dsnPrefix : m_aDsnPrefixes)
+ {
+ WildCard aWildCard(dsnPrefix);
+ if ( sOldPattern.getLength() < dsnPrefix.getLength() && aWildCard.Matches(_sURL) )
+ {
+ sRet = dsnPrefix;
+ sOldPattern = dsnPrefix;
+ }
+ }
+ return !sRet.isEmpty() && sRet[sRet.getLength()-1] == '*';
+}
+
+OUString ODsnTypeCollection::getMediaType(std::u16string_view _sURL) const
+{
+ const ::comphelper::NamedValueCollection& aFeatures = m_aDriverConfig.getMetaData(_sURL);
+ return aFeatures.getOrDefault("MediaType",OUString());
+}
+
+OUString ODsnTypeCollection::getDatasourcePrefixFromMediaType(std::u16string_view _sMediaType,std::u16string_view _sExtension)
+{
+ OUString sURL, sFallbackURL;
+ const uno::Sequence< OUString > aURLs = m_aDriverConfig.getURLs();
+ const OUString* pIter = aURLs.getConstArray();
+ const OUString* pEnd = pIter + aURLs.getLength();
+ for(;pIter != pEnd;++pIter )
+ {
+ const ::comphelper::NamedValueCollection& aFeatures = m_aDriverConfig.getMetaData(*pIter);
+ if ( aFeatures.getOrDefault("MediaType",OUString()) == _sMediaType )
+ {
+ const OUString sFileExtension = aFeatures.getOrDefault("Extension",OUString());
+ if ( _sExtension == sFileExtension )
+ {
+ sURL = *pIter;
+ break;
+ }
+ if ( sFileExtension.isEmpty() && !_sExtension.empty() )
+ sFallbackURL = *pIter;
+ }
+ }
+
+ if ( sURL.isEmpty() && !sFallbackURL.isEmpty() )
+ sURL = sFallbackURL;
+
+ sURL = comphelper::string::stripEnd(sURL, '*');
+ return sURL;
+}
+
+bool ODsnTypeCollection::isShowPropertiesEnabled( const OUString& _sURL )
+{
+ return !( _sURL.startsWithIgnoreAsciiCase("sdbc:embedded:hsqldb")
+ || _sURL.startsWithIgnoreAsciiCase("sdbc:embedded:firebird")
+ || _sURL.startsWithIgnoreAsciiCase("sdbc:address:outlook")
+ || _sURL.startsWithIgnoreAsciiCase("sdbc:address:outlookexp")
+ || _sURL.startsWithIgnoreAsciiCase("sdbc:address:mozilla:")
+ || _sURL.startsWithIgnoreAsciiCase("sdbc:address:kab")
+ || _sURL.startsWithIgnoreAsciiCase("sdbc:address:evolution:local")
+ || _sURL.startsWithIgnoreAsciiCase("sdbc:address:evolution:groupwise")
+ || _sURL.startsWithIgnoreAsciiCase("sdbc:address:evolution:ldap")
+ || _sURL.startsWithIgnoreAsciiCase("sdbc:address:macab") );
+}
+
+void ODsnTypeCollection::extractHostNamePort(const OUString& _rDsn,OUString& _sDatabaseName,OUString& _rsHostname,sal_Int32& _nPortNumber) const
+{
+ OUString sUrl = cutPrefix(_rDsn);
+ if ( _rDsn.startsWithIgnoreAsciiCase("jdbc:oracle:thin:") )
+ {
+ lcl_extractHostAndPort(sUrl,_rsHostname,_nPortNumber);
+ const sal_Int32 nUrlTokens {comphelper::string::getTokenCount(sUrl, ':')};
+ if ( _rsHostname.isEmpty() && nUrlTokens == 2 )
+ {
+ _nPortNumber = -1;
+ _rsHostname = sUrl.getToken(0,':');
+ }
+ if ( !_rsHostname.isEmpty() )
+ _rsHostname = _rsHostname.copy(_rsHostname.lastIndexOf('@')+1);
+ _sDatabaseName = sUrl.copy(sUrl.lastIndexOf(':')+1);
+ }
+ else if ( _rDsn.startsWithIgnoreAsciiCase("sdbc:address:ldap:") )
+ {
+ lcl_extractHostAndPort(sUrl,_sDatabaseName,_nPortNumber);
+ }
+ else if ( _rDsn.startsWithIgnoreAsciiCase("sdbc:mysql:mysqlc:")
+ || _rDsn.startsWithIgnoreAsciiCase("sdbc:mysql:jdbc:") )
+ {
+ lcl_extractHostAndPort(sUrl,_rsHostname,_nPortNumber);
+
+ const sal_Int32 nUrlTokens {comphelper::string::getTokenCount(sUrl, '/')};
+ if ( _nPortNumber == -1 && _rsHostname.isEmpty() && nUrlTokens == 2 )
+ _rsHostname = sUrl.getToken(0,'/');
+ _sDatabaseName = sUrl.copy(sUrl.lastIndexOf('/')+1);
+ }
+ else if ( _rDsn.startsWithIgnoreAsciiCase("sdbc:ado:access:Provider=Microsoft.ACE.OLEDB.12.0;DATA SOURCE=")
+ || _rDsn.startsWithIgnoreAsciiCase("sdbc:ado:access:PROVIDER=Microsoft.Jet.OLEDB.4.0;DATA SOURCE=") )
+ {
+ OUString sNewFileName;
+ if ( ::osl::FileBase::getFileURLFromSystemPath( sUrl, sNewFileName ) == ::osl::FileBase::E_None )
+ {
+ _sDatabaseName = sNewFileName;
+ }
+ }
+}
+
+OUString ODsnTypeCollection::getJavaDriverClass(std::u16string_view _sURL) const
+{
+ const ::comphelper::NamedValueCollection& aFeatures = m_aDriverConfig.getProperties(_sURL);
+ return aFeatures.getOrDefault("JavaDriverClass",OUString());
+}
+
+bool ODsnTypeCollection::isFileSystemBased(std::u16string_view _sURL) const
+{
+ const ::comphelper::NamedValueCollection& aFeatures = m_aDriverConfig.getMetaData(_sURL);
+ return aFeatures.getOrDefault("FileSystemBased",false);
+}
+
+bool ODsnTypeCollection::supportsTableCreation(std::u16string_view _sURL) const
+{
+ const ::comphelper::NamedValueCollection& aFeatures = m_aDriverConfig.getMetaData(_sURL);
+ return aFeatures.getOrDefault("SupportsTableCreation",false);
+}
+
+bool ODsnTypeCollection::supportsColumnDescription(std::u16string_view _sURL) const
+{
+ const ::comphelper::NamedValueCollection& aFeatures = m_aDriverConfig.getMetaData(_sURL);
+ return aFeatures.getOrDefault("SupportsColumnDescription",false);
+}
+
+bool ODsnTypeCollection::supportsBrowsing(std::u16string_view _sURL) const
+{
+ const ::comphelper::NamedValueCollection& aFeatures = m_aDriverConfig.getMetaData(_sURL);
+ return aFeatures.getOrDefault("SupportsBrowsing",false);
+}
+
+bool ODsnTypeCollection::supportsDBCreation(std::u16string_view _sURL) const
+{
+ const ::comphelper::NamedValueCollection& aFeatures = m_aDriverConfig.getMetaData(_sURL);
+ return aFeatures.getOrDefault("SupportsDBCreation",false);
+}
+
+Sequence<PropertyValue> ODsnTypeCollection::getDefaultDBSettings( std::u16string_view _sURL ) const
+{
+ const ::comphelper::NamedValueCollection& aProperties = m_aDriverConfig.getProperties(_sURL);
+ return aProperties.getPropertyValues();
+}
+
+bool ODsnTypeCollection::isEmbeddedDatabase( std::u16string_view _sURL )
+{
+ return o3tl::starts_with( _sURL, u"sdbc:embedded:" );
+}
+
+OUString ODsnTypeCollection::getEmbeddedDatabase()
+{
+ if (!HAVE_FEATURE_JAVA || officecfg::Office::Common::Misc::ExperimentalMode::get())
+ return "sdbc:embedded:firebird";
+ else
+ return "sdbc:embedded:hsqldb";
+}
+
+
+DATASOURCE_TYPE ODsnTypeCollection::determineType(std::u16string_view _rDsn) const
+{
+ OUString sDsn(comphelper::string::stripEnd(_rDsn, '*'));
+ sal_Int32 nSeparator = sDsn.indexOf(u':');
+ if (-1 == nSeparator)
+ {
+ if (!sDsn.isEmpty())
+ {
+ // there should be at least one such separator
+ OSL_FAIL("ODsnTypeCollection::implDetermineType : missing the colon !");
+ }
+
+ return DST_UNKNOWN;
+ }
+
+ // find first :
+ if (sDsn.startsWithIgnoreAsciiCase("jdbc:oracle:thin:"))
+ return DST_ORACLE_JDBC;
+
+ if (sDsn.startsWithIgnoreAsciiCase("jdbc:"))
+ return DST_JDBC;
+
+ if (sDsn.equalsIgnoreAsciiCase("sdbc:embedded:hsqldb"))
+ return DST_EMBEDDED_HSQLDB;
+
+ if (sDsn.equalsIgnoreAsciiCase("sdbc:embedded:firebird"))
+ return DST_EMBEDDED_FIREBIRD;
+
+ // find second :
+ nSeparator = sDsn.indexOf(u':', nSeparator + 1);
+ if (-1 == nSeparator)
+ {
+ // at the moment only jdbc is allowed to have just one separator
+ OSL_FAIL("ODsnTypeCollection::implDetermineType : missing the second colon !");
+ return DST_UNKNOWN;
+ }
+
+ if (sDsn.startsWithIgnoreAsciiCase("sdbc:ado:"))
+ {
+ if (sDsn.startsWithIgnoreAsciiCase("sdbc:ado:access:"))
+ {
+ if (sDsn.startsWithIgnoreAsciiCase("sdbc:ado:access:Provider=Microsoft.ACE.OLEDB.12.0;"))
+ return DST_MSACCESS_2007;
+ else
+ return DST_MSACCESS;
+ }
+ return DST_ADO;
+ }
+
+ struct KnownPrefix
+ {
+ const OUString sPrefix;
+ const DATASOURCE_TYPE eType;
+ const bool bMatchComplete;
+
+ KnownPrefix( const OUString &_s, const DATASOURCE_TYPE _t, const bool _m )
+ :sPrefix( _s )
+ ,eType ( _t )
+ ,bMatchComplete( _m )
+ {
+ }
+
+ bool match( const OUString &url) const
+ {
+ if(bMatchComplete)
+ {
+ return url.equalsIgnoreAsciiCase(sPrefix);
+ }
+ else
+ {
+ return url.startsWithIgnoreAsciiCase(sPrefix);
+ }
+ }
+ };
+ const KnownPrefix aKnowPrefixes[] =
+ {
+ KnownPrefix( "sdbc:calc:", DST_CALC, false ),
+ KnownPrefix( "sdbc:writer:", DST_WRITER, false ),
+ KnownPrefix( "sdbc:flat:", DST_FLAT, false ),
+ KnownPrefix( "sdbc:odbc:", DST_ODBC, false ),
+ KnownPrefix( "sdbc:dbase:", DST_DBASE, false ),
+ KnownPrefix( "sdbc:firebird:", DST_FIREBIRD, false ),
+ KnownPrefix( "sdbc:mysql:odbc:", DST_MYSQL_ODBC, false ),
+ KnownPrefix( "sdbc:mysql:jdbc:", DST_MYSQL_JDBC, false ),
+ KnownPrefix( "sdbc:mysql:mysqlc:", DST_MYSQL_NATIVE, false ),
+ KnownPrefix( "sdbc:mysqlc:", DST_MYSQL_NATIVE_DIRECT,false ),
+ KnownPrefix( "sdbc:postgresql:", DST_POSTGRES ,false ),
+
+ KnownPrefix( "sdbc:address:mozilla:", DST_MOZILLA, true ),
+ KnownPrefix( "sdbc:address:thunderbird:", DST_THUNDERBIRD, true ),
+ KnownPrefix( "sdbc:address:ldap:", DST_LDAP, true ),
+ KnownPrefix( "sdbc:address:outlook", DST_OUTLOOK, true ),
+ KnownPrefix( "sdbc:address:outlookexp", DST_OUTLOOKEXP, true ),
+ KnownPrefix( "sdbc:address:evolution:ldap", DST_EVOLUTION_LDAP, true ),
+ KnownPrefix( "sdbc:address:evolution:groupwise",DST_EVOLUTION_GROUPWISE,true ),
+ KnownPrefix( "sdbc:address:evolution:local", DST_EVOLUTION, true ),
+ KnownPrefix( "sdbc:address:kab", DST_KAB, true ),
+ KnownPrefix( "sdbc:address:macab", DST_MACAB, true )
+ };
+
+ for (const auto & aKnowPrefixe : aKnowPrefixes)
+ {
+ if( aKnowPrefixe.match(sDsn) )
+ {
+ return aKnowPrefixe.eType;
+ }
+ }
+
+ return DST_UNKNOWN;
+}
+
+void ODsnTypeCollection::fillPageIds(std::u16string_view _sURL,std::vector<sal_Int16>& _rOutPathIds) const
+{
+ DATASOURCE_TYPE eType = determineType(_sURL);
+ switch(eType)
+ {
+ case DST_ADO:
+ _rOutPathIds.push_back(PAGE_DBSETUPWIZARD_ADO);
+ break;
+ case DST_DBASE:
+ _rOutPathIds.push_back(PAGE_DBSETUPWIZARD_DBASE);
+ break;
+ case DST_FLAT:
+ _rOutPathIds.push_back(PAGE_DBSETUPWIZARD_TEXT);
+ break;
+ case DST_CALC:
+ case DST_WRITER:
+ _rOutPathIds.push_back(PAGE_DBSETUPWIZARD_DOCUMENT_OR_SPREADSHEET);
+ break;
+ case DST_ODBC:
+ _rOutPathIds.push_back(PAGE_DBSETUPWIZARD_ODBC);
+ break;
+ case DST_JDBC:
+ _rOutPathIds.push_back(PAGE_DBSETUPWIZARD_JDBC);
+ break;
+ case DST_MYSQL_ODBC:
+ _rOutPathIds.push_back(PAGE_DBSETUPWIZARD_MYSQL_INTRO);
+ _rOutPathIds.push_back(PAGE_DBSETUPWIZARD_MYSQL_ODBC);
+ break;
+ case DST_MYSQL_JDBC:
+ _rOutPathIds.push_back(PAGE_DBSETUPWIZARD_MYSQL_INTRO);
+ _rOutPathIds.push_back(PAGE_DBSETUPWIZARD_MYSQL_JDBC);
+ break;
+ case DST_MYSQL_NATIVE:
+ _rOutPathIds.push_back(PAGE_DBSETUPWIZARD_MYSQL_INTRO);
+ _rOutPathIds.push_back(PAGE_DBSETUPWIZARD_MYSQL_NATIVE);
+ break;
+ case DST_ORACLE_JDBC:
+ _rOutPathIds.push_back(PAGE_DBSETUPWIZARD_ORACLE);
+ break;
+ case DST_LDAP:
+ _rOutPathIds.push_back(PAGE_DBSETUPWIZARD_LDAP);
+ break;
+ case DST_MSACCESS:
+ case DST_MSACCESS_2007:
+ _rOutPathIds.push_back(PAGE_DBSETUPWIZARD_MSACCESS);
+ break;
+ case DST_OUTLOOKEXP:
+ case DST_OUTLOOK:
+ case DST_MOZILLA:
+ case DST_THUNDERBIRD:
+ case DST_EVOLUTION:
+ case DST_EVOLUTION_GROUPWISE:
+ case DST_EVOLUTION_LDAP:
+ case DST_KAB:
+ case DST_MACAB:
+ case DST_EMBEDDED_HSQLDB:
+ case DST_EMBEDDED_FIREBIRD:
+ break;
+ default:
+ _rOutPathIds.push_back(PAGE_DBSETUPWIZARD_USERDEFINED);
+ break;
+ }
+}
+
+OUString ODsnTypeCollection::getType(std::u16string_view _sURL) const
+{
+ OUString sOldPattern;
+ for (auto const& dsnPrefix : m_aDsnPrefixes)
+ {
+ WildCard aWildCard(dsnPrefix);
+ if ( sOldPattern.getLength() < dsnPrefix.getLength() && aWildCard.Matches(_sURL) )
+ {
+ sOldPattern = dsnPrefix;
+ }
+ }
+ return sOldPattern;
+}
+
+sal_Int32 ODsnTypeCollection::getIndexOf(std::u16string_view _sURL) const
+{
+ sal_Int32 nRet = -1;
+ OUString sOldPattern;
+ sal_Int32 i = 0;
+ for (auto const& dsnPrefix : m_aDsnPrefixes)
+ {
+ WildCard aWildCard(dsnPrefix);
+ if ( sOldPattern.getLength() < dsnPrefix.getLength() && aWildCard.Matches(_sURL) )
+ {
+ nRet = i;
+ sOldPattern = dsnPrefix;
+ }
+ ++i;
+ }
+
+ return nRet;
+}
+
+sal_Int32 ODsnTypeCollection::size() const
+{
+ return m_aDsnPrefixes.size();
+}
+
+// ODsnTypeCollection::TypeIterator
+ODsnTypeCollection::TypeIterator::TypeIterator(const ODsnTypeCollection* _pContainer, sal_Int32 _nInitialPos)
+ :m_pContainer(_pContainer)
+ ,m_nPosition(_nInitialPos)
+{
+ OSL_ENSURE(m_pContainer, "ODsnTypeCollection::TypeIterator::TypeIterator : invalid container!");
+#if OSL_DEBUG_LEVEL > 0
+ ++const_cast<ODsnTypeCollection*>(m_pContainer)->m_nLivingIterators;
+#endif
+}
+
+ODsnTypeCollection::TypeIterator::TypeIterator(const TypeIterator& _rSource)
+ :m_pContainer(_rSource.m_pContainer)
+ ,m_nPosition(_rSource.m_nPosition)
+{
+#if OSL_DEBUG_LEVEL > 0
+ ++const_cast<ODsnTypeCollection*>(m_pContainer)->m_nLivingIterators;
+#endif
+}
+
+ODsnTypeCollection::TypeIterator::~TypeIterator()
+{
+#if OSL_DEBUG_LEVEL > 0
+ --const_cast<ODsnTypeCollection*>(m_pContainer)->m_nLivingIterators;
+#endif
+}
+
+OUString const & ODsnTypeCollection::TypeIterator::getDisplayName() const
+{
+ OSL_ENSURE(m_nPosition < static_cast<sal_Int32>(m_pContainer->m_aDsnTypesDisplayNames.size()), "ODsnTypeCollection::TypeIterator::getDisplayName : invalid position!");
+ return m_pContainer->m_aDsnTypesDisplayNames[m_nPosition];
+}
+
+OUString const & ODsnTypeCollection::TypeIterator::getURLPrefix() const
+{
+ OSL_ENSURE(m_nPosition < static_cast<sal_Int32>(m_pContainer->m_aDsnPrefixes.size()), "ODsnTypeCollection::TypeIterator::getDisplayName : invalid position!");
+ return m_pContainer->m_aDsnPrefixes[m_nPosition];
+}
+
+const ODsnTypeCollection::TypeIterator& ODsnTypeCollection::TypeIterator::operator++()
+{
+ OSL_ENSURE(m_nPosition < static_cast<sal_Int32>(m_pContainer->m_aDsnTypesDisplayNames.size()), "ODsnTypeCollection::TypeIterator::operator++ : invalid position!");
+ if (m_nPosition < static_cast<sal_Int32>(m_pContainer->m_aDsnTypesDisplayNames.size()))
+ ++m_nPosition;
+ return *this;
+}
+
+bool operator==(const ODsnTypeCollection::TypeIterator& lhs, const ODsnTypeCollection::TypeIterator& rhs)
+{
+ return (lhs.m_pContainer == rhs.m_pContainer) && (lhs.m_nPosition == rhs.m_nPosition);
+}
+
+} // namespace dbaccess
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/misc/migrwarndlg.cxx b/dbaccess/source/core/misc/migrwarndlg.cxx
new file mode 100644
index 000000000..d1712fba3
--- /dev/null
+++ b/dbaccess/source/core/misc/migrwarndlg.cxx
@@ -0,0 +1,22 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <migrwarndlg.hxx>
+
+namespace dbaccess
+{
+MigrationWarnDialog::MigrationWarnDialog(weld::Window* pParent)
+ : MessageDialogController(pParent, "dbaccess/ui/migrwarndlg.ui", "MigrationWarnDialog")
+ , m_xLater(m_xBuilder->weld_button("no"))
+{
+ m_xLater->grab_focus();
+}
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/misc/objectnameapproval.cxx b/dbaccess/source/core/misc/objectnameapproval.cxx
new file mode 100644
index 000000000..3ec15caaa
--- /dev/null
+++ b/dbaccess/source/core/misc/objectnameapproval.cxx
@@ -0,0 +1,74 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <objectnameapproval.hxx>
+
+#include <com/sun/star/lang/DisposedException.hpp>
+#include <com/sun/star/sdb/tools/XConnectionTools.hpp>
+#include <com/sun/star/sdb/CommandType.hpp>
+
+#include <cppuhelper/weakref.hxx>
+
+namespace dbaccess
+{
+
+ using ::com::sun::star::sdbc::XConnection;
+ using ::com::sun::star::uno::WeakReference;
+ using ::com::sun::star::uno::Reference;
+ using ::com::sun::star::lang::DisposedException;
+ using ::com::sun::star::sdb::tools::XConnectionTools;
+ using ::com::sun::star::uno::UNO_QUERY_THROW;
+ using ::com::sun::star::sdb::tools::XObjectNames;
+ using ::com::sun::star::uno::XInterface;
+
+ namespace CommandType = com::sun::star::sdb::CommandType;
+
+ // ObjectNameApproval_Impl
+ struct ObjectNameApproval_Impl
+ {
+ WeakReference< XConnection > aConnection;
+ sal_Int32 nCommandType;
+ };
+
+ // ObjectNameApproval
+ ObjectNameApproval::ObjectNameApproval( const Reference< XConnection >& _rxConnection, ObjectType _eType )
+ :m_pImpl( new ObjectNameApproval_Impl )
+ {
+ m_pImpl->aConnection = _rxConnection;
+ m_pImpl->nCommandType = _eType == TypeQuery ? CommandType::QUERY : CommandType::TABLE;
+ }
+
+ ObjectNameApproval::~ObjectNameApproval()
+ {
+ }
+
+ void ObjectNameApproval::approveElement( const OUString& _rName )
+ {
+ Reference< XConnection > xConnection( m_pImpl->aConnection );
+ if ( !xConnection.is() )
+ throw DisposedException();
+
+ Reference< XConnectionTools > xConnectionTools( xConnection, UNO_QUERY_THROW );
+ Reference< XObjectNames > xObjectNames( xConnectionTools->getObjectNames(), css::uno::UNO_SET_THROW );
+ xObjectNames->checkNameForCreate( m_pImpl->nCommandType, _rName );
+ }
+
+} // namespace dbaccess
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/misc/sdbcoretools.cxx b/dbaccess/source/core/misc/sdbcoretools.cxx
new file mode 100644
index 000000000..1789aea84
--- /dev/null
+++ b/dbaccess/source/core/misc/sdbcoretools.cxx
@@ -0,0 +1,142 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sdbcoretools.hxx>
+
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/container/XChild.hpp>
+#include <com/sun/star/util/XModifiable.hpp>
+#include <com/sun/star/sdb/XDocumentDataSource.hpp>
+#include <com/sun/star/task/InteractionRequestStringResolver.hpp>
+#include <com/sun/star/embed/XTransactedObject.hpp>
+#include <com/sun/star/embed/ElementModes.hpp>
+
+#include <tools/diagnose_ex.h>
+#include <comphelper/interaction.hxx>
+#include <rtl/ref.hxx>
+
+namespace dbaccess
+{
+
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::lang;
+ using namespace ::com::sun::star::util;
+ using namespace ::com::sun::star::io;
+ using namespace ::com::sun::star::sdbc;
+ using namespace ::com::sun::star::sdb;
+ using namespace ::com::sun::star::beans;
+ using namespace ::com::sun::star::task;
+ using namespace ::com::sun::star::embed;
+ using namespace ::com::sun::star::container;
+
+ void notifyDataSourceModified(const css::uno::Reference< css::uno::XInterface >& _rxObject)
+ {
+ Reference< XInterface > xDs = getDataSource( _rxObject );
+ Reference<XDocumentDataSource> xDocumentDataSource(xDs,UNO_QUERY);
+ if ( xDocumentDataSource.is() )
+ xDs = xDocumentDataSource->getDatabaseDocument();
+ Reference< XModifiable > xModi( xDs, UNO_QUERY );
+ if ( xModi.is() )
+ xModi->setModified(true);
+ }
+
+ Reference< XInterface > getDataSource( const Reference< XInterface >& _rxDependentObject )
+ {
+ Reference< XInterface > xParent = _rxDependentObject;
+ Reference< XInterface > xReturn;
+ while( xParent.is() )
+ {
+ xReturn = xParent;
+ Reference<XChild> xChild(xParent,UNO_QUERY);
+ xParent.set(xChild.is() ? xChild->getParent() : Reference< XInterface >(),UNO_QUERY);
+ }
+ return xReturn;
+ }
+
+ OUString extractExceptionMessage( const Reference<XComponentContext> & _rContext, const Any& _rError )
+ {
+ OUString sDisplayMessage;
+
+ try
+ {
+ Reference< XInteractionRequestStringResolver > xStringResolver = InteractionRequestStringResolver::create(_rContext);
+
+ ::rtl::Reference pRequest( new ::comphelper::OInteractionRequest( _rError ) );
+ ::rtl::Reference pApprove( new ::comphelper::OInteractionApprove );
+ pRequest->addContinuation( pApprove );
+ Optional< OUString > aMessage = xStringResolver->getStringFromInformationalRequest( pRequest );
+ if ( aMessage.IsPresent )
+ sDisplayMessage = aMessage.Value;
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+
+ if ( sDisplayMessage.isEmpty() )
+ {
+ Exception aExcept;
+ _rError >>= aExcept;
+
+ sDisplayMessage = _rError.getValueTypeName() +
+ ":\n" +
+ aExcept.Message;
+ }
+
+ return sDisplayMessage;
+ }
+
+ namespace tools::stor {
+
+ bool storageIsWritable_nothrow( const Reference< XStorage >& _rxStorage )
+ {
+ if ( !_rxStorage.is() )
+ return false;
+
+ sal_Int32 nMode = ElementModes::READ;
+ try
+ {
+ Reference< XPropertySet > xStorageProps( _rxStorage, UNO_QUERY_THROW );
+ xStorageProps->getPropertyValue( "OpenMode" ) >>= nMode;
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ return ( nMode & ElementModes::WRITE ) != 0;
+ }
+
+ bool commitStorageIfWriteable( const Reference< XStorage >& _rxStorage )
+ {
+ bool bSuccess = false;
+ Reference< XTransactedObject > xTrans( _rxStorage, UNO_QUERY );
+ if ( xTrans.is() )
+ {
+ if ( storageIsWritable_nothrow( _rxStorage ) )
+ xTrans->commit();
+ bSuccess = true;
+ }
+ return bSuccess;
+ }
+
+}
+
+} // namespace dbaccess
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/misc/veto.cxx b/dbaccess/source/core/misc/veto.cxx
new file mode 100644
index 000000000..d2596d4e1
--- /dev/null
+++ b/dbaccess/source/core/misc/veto.cxx
@@ -0,0 +1,49 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <veto.hxx>
+
+namespace dbaccess
+{
+
+ using ::com::sun::star::uno::Any;
+
+ // Veto
+ Veto::Veto( const Any& _rDetails )
+ :m_aDetails( _rDetails )
+ {
+ }
+
+ Veto::~Veto()
+ {
+ }
+
+ OUString SAL_CALL Veto::getReason()
+ {
+ return OUString();
+ }
+
+ Any SAL_CALL Veto::getDetails()
+ {
+ return m_aDetails;
+ }
+
+} // namespace dbaccess
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/recovery/dbdocrecovery.cxx b/dbaccess/source/core/recovery/dbdocrecovery.cxx
new file mode 100644
index 000000000..db7bb53bd
--- /dev/null
+++ b/dbaccess/source/core/recovery/dbdocrecovery.cxx
@@ -0,0 +1,347 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <recovery/dbdocrecovery.hxx>
+#include <sdbcoretools.hxx>
+#include "storagetextstream.hxx"
+#include "subcomponentrecovery.hxx"
+#include "subcomponents.hxx"
+
+#include <com/sun/star/sdb/application/XDatabaseDocumentUI.hpp>
+#include <com/sun/star/embed/ElementModes.hpp>
+#include <com/sun/star/io/TextInputStream.hpp>
+#include <com/sun/star/util/XModifiable.hpp>
+
+#include <rtl/ustrbuf.hxx>
+#include <sal/log.hxx>
+#include <tools/diagnose_ex.h>
+
+namespace dbaccess
+{
+
+ using css::uno::Reference;
+ using css::uno::UNO_QUERY;
+ using css::uno::UNO_QUERY_THROW;
+ using css::uno::UNO_SET_THROW;
+ using css::uno::Exception;
+ using css::uno::Sequence;
+ using css::uno::XComponentContext;
+ using css::embed::XStorage;
+ using css::frame::XController;
+ using css::sdb::application::XDatabaseDocumentUI;
+ using css::lang::XComponent;
+ using css::io::XStream;
+ using css::io::TextInputStream;
+ using css::io::XTextInputStream2;
+ using css::util::XModifiable;
+
+ namespace ElementModes = css::embed::ElementModes;
+
+ // helpers
+ namespace
+ {
+ void lcl_getPersistentRepresentation( const MapStringToCompDesc::value_type& i_rComponentDesc, OUStringBuffer& o_rBuffer )
+ {
+ o_rBuffer.append( i_rComponentDesc.first );
+ o_rBuffer.append( '=' );
+ o_rBuffer.append( i_rComponentDesc.second.sName );
+ o_rBuffer.append( ',' );
+ o_rBuffer.append( sal_Unicode( i_rComponentDesc.second.bForEditing ? '1' : '0' ) );
+ }
+
+ bool lcl_extractCompDesc( const OUString& i_rIniLine, OUString& o_rStorName, SubComponentDescriptor& o_rCompDesc )
+ {
+ const sal_Int32 nEqualSignPos = i_rIniLine.indexOf( '=' );
+ if ( nEqualSignPos < 1 )
+ {
+ OSL_FAIL( "lcl_extractCompDesc: invalid map file entry - unexpected pos of '='" );
+ return false;
+ }
+ o_rStorName = i_rIniLine.copy( 0, nEqualSignPos );
+
+ const sal_Int32 nCommaPos = i_rIniLine.lastIndexOf( ',' );
+ if ( nCommaPos != i_rIniLine.getLength() - 2 )
+ {
+ OSL_FAIL( "lcl_extractCompDesc: invalid map file entry - unexpected pos of ','" );
+ return false;
+ }
+ o_rCompDesc.sName = i_rIniLine.copy( nEqualSignPos + 1, nCommaPos - nEqualSignPos - 1 );
+ o_rCompDesc.bForEditing = ( i_rIniLine[ nCommaPos + 1 ] == '1' );
+ return true;
+ }
+
+ constexpr OUStringLiteral sRecoveryDataSubStorageName = u"recovery";
+
+ constexpr OUStringLiteral sObjectMapStreamName = u"storage-component-map.ini";
+
+ void lcl_writeObjectMap_throw( const Reference<XComponentContext> & i_rContext, const Reference< XStorage >& i_rStorage,
+ const MapStringToCompDesc& i_mapStorageToCompDesc )
+ {
+ if ( i_mapStorageToCompDesc.empty() )
+ // nothing to do
+ return;
+
+ StorageTextOutputStream aTextOutput( i_rContext, i_rStorage, sObjectMapStreamName );
+
+ aTextOutput.writeLine( "[storages]" );
+
+ for (auto const& elem : i_mapStorageToCompDesc)
+ {
+ OUStringBuffer aLine;
+ lcl_getPersistentRepresentation(elem, aLine);
+
+ aTextOutput.writeLine( aLine.makeStringAndClear() );
+ }
+
+ aTextOutput.writeLine();
+ }
+
+ bool lcl_isSectionStart( const OUString& i_rIniLine, OUString& o_rSectionName )
+ {
+ const sal_Int32 nLen = i_rIniLine.getLength();
+ if ( i_rIniLine.startsWith("[") && i_rIniLine.endsWith("]") )
+ {
+ o_rSectionName = i_rIniLine.copy( 1, nLen -2 );
+ return true;
+ }
+ return false;
+ }
+
+ void lcl_stripTrailingLineFeed( OUString& io_rLine )
+ {
+ const sal_Int32 nLen = io_rLine.getLength();
+ if ( io_rLine.endsWith("\n") )
+ io_rLine = io_rLine.copy( 0, nLen - 1 );
+ }
+
+ void lcl_readObjectMap_throw( const Reference<XComponentContext> & i_rxContext, const Reference< XStorage >& i_rStorage,
+ MapStringToCompDesc& o_mapStorageToObjectName )
+ {
+ ENSURE_OR_THROW( i_rStorage.is(), "invalid storage" );
+ if ( !i_rStorage->hasByName( sObjectMapStreamName ) )
+ { // nothing to do, though suspicious
+ OSL_FAIL( "lcl_readObjectMap_throw: if there's no map file, then there's expected to be no storage, too!" );
+ return;
+ }
+
+ Reference< XStream > xIniStream( i_rStorage->openStreamElement(
+ sObjectMapStreamName, ElementModes::READ ), UNO_SET_THROW );
+
+ Reference< XTextInputStream2 > xTextInput = TextInputStream::create( i_rxContext );
+ xTextInput->setEncoding( "UTF-8" );
+ xTextInput->setInputStream( xIniStream->getInputStream() );
+
+ OUString sCurrentSection;
+ bool bCurrentSectionIsKnownToBeUnsupported = true;
+ while ( !xTextInput->isEOF() )
+ {
+ OUString sLine = xTextInput->readLine();
+ lcl_stripTrailingLineFeed( sLine );
+
+ if ( sLine.isEmpty() )
+ continue;
+
+ if ( lcl_isSectionStart( sLine, sCurrentSection ) )
+ {
+ bCurrentSectionIsKnownToBeUnsupported = false;
+ continue;
+ }
+
+ if ( bCurrentSectionIsKnownToBeUnsupported )
+ continue;
+
+ // the only section we support so far is "storages"
+ if ( sCurrentSection != "storages" )
+ {
+ bCurrentSectionIsKnownToBeUnsupported = true;
+ continue;
+ }
+
+ OUString sStorageName;
+ SubComponentDescriptor aCompDesc;
+ if ( !lcl_extractCompDesc( sLine, sStorageName, aCompDesc ) )
+ continue;
+ o_mapStorageToObjectName[ sStorageName ] = aCompDesc;
+ }
+ }
+
+ void lcl_markModified( const Reference< XComponent >& i_rSubComponent )
+ {
+ const Reference< XModifiable > xModify( i_rSubComponent, UNO_QUERY );
+ if ( !xModify.is() )
+ {
+ OSL_FAIL( "lcl_markModified: unhandled case!" );
+ return;
+ }
+
+ xModify->setModified( true );
+ }
+ }
+
+ // DatabaseDocumentRecovery_Data
+ struct DatabaseDocumentRecovery_Data
+ {
+ const Reference<XComponentContext> aContext;
+
+ explicit DatabaseDocumentRecovery_Data( const Reference<XComponentContext> & i_rContext )
+ :aContext( i_rContext )
+ {
+ }
+ };
+
+ // DatabaseDocumentRecovery
+ DatabaseDocumentRecovery::DatabaseDocumentRecovery( const Reference<XComponentContext> & i_rContext )
+ :m_pData( new DatabaseDocumentRecovery_Data( i_rContext ) )
+ {
+ }
+
+ DatabaseDocumentRecovery::~DatabaseDocumentRecovery()
+ {
+ }
+
+ void DatabaseDocumentRecovery::saveModifiedSubComponents( const Reference< XStorage >& i_rTargetStorage,
+ const std::vector< Reference< XController > >& i_rControllers )
+ {
+ ENSURE_OR_THROW( i_rTargetStorage.is(), "invalid document storage" );
+
+ // create a sub storage for recovery data
+ if ( i_rTargetStorage->hasByName( sRecoveryDataSubStorageName ) )
+ i_rTargetStorage->removeElement( sRecoveryDataSubStorageName );
+ Reference< XStorage > xRecoveryStorage = i_rTargetStorage->openStorageElement( sRecoveryDataSubStorageName, ElementModes::READWRITE );
+
+ // store recovery data for open sub components of the given controller(s)
+ if ( !i_rControllers.empty() )
+ {
+ ENSURE_OR_THROW( i_rControllers.size() == 1, "can't handle more than one controller" );
+ // At the moment, there can be only one view to a database document. If we ever allow for more than this,
+ // then we need a concept for sub documents opened from different controllers (i.e. two document views,
+ // and the user opens the very same form in both views). And depending on this, we need a concept for
+ // how those are saved to the recovery file.
+
+ MapCompTypeToCompDescs aMapCompDescs;
+
+ for (auto const& controller : i_rControllers)
+ {
+ Reference< XDatabaseDocumentUI > xDatabaseUI(controller, UNO_QUERY_THROW);
+ const Sequence< Reference< XComponent > > aComponents( xDatabaseUI->getSubComponents() );
+
+ for ( auto const & component : aComponents )
+ {
+ SubComponentRecovery aComponentRecovery( m_pData->aContext, xDatabaseUI, component );
+ aComponentRecovery.saveToRecoveryStorage( xRecoveryStorage, aMapCompDescs );
+ }
+ }
+
+ for (auto const& elem : aMapCompDescs)
+ {
+ Reference< XStorage > xComponentsStor( xRecoveryStorage->openStorageElement(
+ SubComponentRecovery::getComponentsStorageName( elem.first ), ElementModes::WRITE | ElementModes::NOCREATE ) );
+ lcl_writeObjectMap_throw( m_pData->aContext, xComponentsStor, elem.second );
+ tools::stor::commitStorageIfWriteable( xComponentsStor );
+ }
+ }
+
+ // commit the recovery storage
+ tools::stor::commitStorageIfWriteable( xRecoveryStorage );
+ }
+
+ void DatabaseDocumentRecovery::recoverSubDocuments( const Reference< XStorage >& i_rDocumentStorage,
+ const Reference< XController >& i_rTargetController )
+ {
+ ENSURE_OR_THROW( i_rDocumentStorage.is(), "illegal document storage" );
+ Reference< XDatabaseDocumentUI > xDocumentUI( i_rTargetController, UNO_QUERY_THROW );
+
+ if ( !i_rDocumentStorage->hasByName( sRecoveryDataSubStorageName ) )
+ // that's allowed
+ return;
+
+ // the "recovery" sub storage
+ Reference< XStorage > xRecoveryStorage = i_rDocumentStorage->openStorageElement( sRecoveryDataSubStorageName, ElementModes::READ );
+
+ // read the map from sub storages to object names
+ MapCompTypeToCompDescs aMapCompDescs;
+ const SubComponentType aKnownTypes[] = { TABLE, QUERY, FORM, REPORT, RELATION_DESIGN };
+ for (SubComponentType aKnownType : aKnownTypes)
+ {
+ if ( !xRecoveryStorage->hasByName( SubComponentRecovery::getComponentsStorageName( aKnownType ) ) )
+ continue;
+
+ Reference< XStorage > xComponentsStor( xRecoveryStorage->openStorageElement(
+ SubComponentRecovery::getComponentsStorageName( aKnownType ), ElementModes::READ ) );
+ lcl_readObjectMap_throw( m_pData->aContext, xComponentsStor, aMapCompDescs[ aKnownType ] );
+ xComponentsStor->dispose();
+ }
+
+ // recover all sub components as indicated by the map
+ for (auto const& elemMapCompDescs : aMapCompDescs)
+ {
+ const SubComponentType eComponentType = elemMapCompDescs.first;
+
+ // the storage for all components of the current type
+ Reference< XStorage > xComponentsStor( xRecoveryStorage->openStorageElement(
+ SubComponentRecovery::getComponentsStorageName( eComponentType ), ElementModes::READ ), UNO_SET_THROW );
+
+ // loop through all components of this type
+ for (auto const& elem : elemMapCompDescs.second)
+ {
+ const OUString sComponentName(elem.second.sName);
+ if ( !xComponentsStor->hasByName(elem.first) )
+ {
+ SAL_WARN( "dbaccess",
+ "DatabaseDocumentRecovery::recoverSubDocuments: inconsistent recovery storage: storage '" <<
+ elem.first <<
+ "' not found in '" <<
+ SubComponentRecovery::getComponentsStorageName( eComponentType ) <<
+ "', but required per map file!" );
+ continue;
+ }
+
+ // the controller needs to have a connection to be able to open sub components
+ if ( !xDocumentUI->isConnected() )
+ xDocumentUI->connect();
+
+ // recover the single component
+ Reference< XStorage > xCompStor( xComponentsStor->openStorageElement( elem.first, ElementModes::READ ) );
+ SubComponentRecovery aComponentRecovery( m_pData->aContext, xDocumentUI, eComponentType );
+ Reference< XComponent > xSubComponent( aComponentRecovery.recoverFromStorage( xCompStor, sComponentName, elem.second.bForEditing ) );
+
+ // at the moment, we only store, during session save, sub components which are modified. So, set this
+ // recovered sub component to "modified", too.
+ lcl_markModified( xSubComponent );
+ }
+
+ xComponentsStor->dispose();
+ }
+
+ xRecoveryStorage->dispose();
+
+ // now that we successfully recovered, removed the "recovery" sub storage
+ try
+ {
+ i_rDocumentStorage->removeElement( sRecoveryDataSubStorageName );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+
+} // namespace dbaccess
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/recovery/settingsimport.cxx b/dbaccess/source/core/recovery/settingsimport.cxx
new file mode 100644
index 000000000..821dea045
--- /dev/null
+++ b/dbaccess/source/core/recovery/settingsimport.cxx
@@ -0,0 +1,216 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "settingsimport.hxx"
+
+#include <tools/diagnose_ex.h>
+#include <sal/log.hxx>
+#include <sax/tools/converter.hxx>
+#include <xmloff/xmltoken.hxx>
+
+namespace dbaccess
+{
+
+ using ::com::sun::star::uno::Reference;
+ using ::com::sun::star::uno::Any;
+ using ::com::sun::star::xml::sax::XAttributeList;
+
+ // SettingsImport
+ SettingsImport::SettingsImport()
+ {
+ }
+
+ SettingsImport::~SettingsImport()
+ {
+ }
+
+ void SettingsImport::startElement( const Reference< XAttributeList >& i_rAttributes )
+ {
+ // find the name of the setting
+ if ( i_rAttributes.is() )
+ {
+ m_sItemName = i_rAttributes->getValueByName( "config:name" );
+ m_sItemType = i_rAttributes->getValueByName( "config:type" );
+ }
+ }
+
+ void SettingsImport::endElement()
+ {
+ }
+
+ void SettingsImport::characters( std::u16string_view i_rCharacters )
+ {
+ m_aCharacters.append( i_rCharacters );
+ }
+
+ void SettingsImport::split( const OUString& i_rElementName, OUString& o_rNamespace, OUString& o_rLocalName )
+ {
+ o_rNamespace.clear();
+ o_rLocalName = i_rElementName;
+ const sal_Int32 nSeparatorPos = i_rElementName.indexOf( ':' );
+ if ( nSeparatorPos > -1 )
+ {
+ o_rNamespace = i_rElementName.copy( 0, nSeparatorPos );
+ o_rLocalName = i_rElementName.copy( nSeparatorPos + 1 );
+ }
+
+ OSL_ENSURE( o_rNamespace == "config", "SettingsImport::split: unexpected namespace!" );
+ // our recovery file is kind of hand-made, so there shouldn't be anything else than "config".
+ // If there is, then just ignore it ...
+ }
+
+ // IgnoringSettingsImport
+ ::rtl::Reference< SettingsImport > IgnoringSettingsImport::nextState( const OUString& )
+ {
+ return this;
+ }
+
+ // OfficeSettingsImport
+ OfficeSettingsImport::OfficeSettingsImport( ::comphelper::NamedValueCollection& o_rSettings )
+ :m_rSettings( o_rSettings )
+ {
+ }
+
+ OfficeSettingsImport::~OfficeSettingsImport()
+ {
+ }
+
+ ::rtl::Reference< SettingsImport > OfficeSettingsImport::nextState( const OUString& i_rElementName )
+ {
+ // separate the namespace part from the element name
+ OUString sNamespace;
+ OUString sLocalName;
+ split( i_rElementName, sNamespace, sLocalName );
+
+ if ( sLocalName == "config-item-set" )
+ return new ConfigItemSetImport( m_rSettings );
+
+ SAL_WARN( "dbaccess", "unknown (or unsupported at this place) element name '"
+ << i_rElementName
+ << "', ignoring");
+ return new IgnoringSettingsImport;
+ }
+
+ // ConfigItemImport
+ ConfigItemImport::ConfigItemImport( ::comphelper::NamedValueCollection& o_rSettings )
+ :m_rSettings( o_rSettings )
+ {
+ }
+
+ ConfigItemImport::~ConfigItemImport()
+ {
+ }
+
+ ::rtl::Reference< SettingsImport > ConfigItemImport::nextState( const OUString& )
+ {
+ OSL_FAIL( "ConfigItemImport::nextState: unexpected: this class is responsible for child-less items only!" );
+ return new IgnoringSettingsImport;
+ }
+
+ void ConfigItemImport::endElement()
+ {
+ SettingsImport::endElement();
+
+ const OUString sItemName( getItemName() );
+ ENSURE_OR_RETURN_VOID( !sItemName.isEmpty(), "no item name -> no item value" );
+ Any aValue;
+ getItemValue( aValue );
+ m_rSettings.put( sItemName, aValue );
+ }
+
+ void ConfigItemImport::getItemValue( css::uno::Any& o_rValue ) const
+ {
+ o_rValue.clear();
+
+ // the characters building up th evalue
+ std::u16string_view sValue = getAccumulatedCharacters();
+
+ const OUString& rItemType( getItemType() );
+ ENSURE_OR_RETURN_VOID( !rItemType.isEmpty(), "no item type -> no item value" );
+
+ if ( ::xmloff::token::IsXMLToken( rItemType, ::xmloff::token::XML_INT ) )
+ {
+ sal_Int32 nValue(0);
+ if (::sax::Converter::convertNumber( nValue, sValue ))
+ {
+ o_rValue <<= nValue;
+ }
+ else
+ {
+ OSL_FAIL( "ConfigItemImport::getItemValue: could not convert an int value!" );
+ }
+ }
+ else if ( ::xmloff::token::IsXMLToken( rItemType, ::xmloff::token::XML_BOOLEAN ) )
+ {
+ bool bValue(false);
+ if (::sax::Converter::convertBool( bValue, sValue ))
+ {
+ o_rValue <<= bValue;
+ }
+ else
+ {
+ OSL_FAIL( "ConfigItemImport::getItemValue: could not convert a boolean value!" );
+ }
+ }
+ else if ( ::xmloff::token::IsXMLToken( rItemType, ::xmloff::token::XML_STRING ) )
+ {
+ o_rValue <<= OUString(sValue);
+ }
+ else
+ {
+ SAL_WARN( "dbaccess", "ConfigItemImport::getItemValue: unsupported item type '"
+ << rItemType << "', ignoring");
+ }
+ }
+
+ // ConfigItemSetImport
+ ConfigItemSetImport::ConfigItemSetImport( ::comphelper::NamedValueCollection& o_rSettings )
+ :ConfigItemImport( o_rSettings )
+ {
+ }
+
+ ConfigItemSetImport::~ConfigItemSetImport()
+ {
+ }
+
+ ::rtl::Reference< SettingsImport > ConfigItemSetImport::nextState( const OUString& i_rElementName )
+ {
+ // separate the namespace part from the element name
+ OUString sNamespace;
+ OUString sLocalName;
+ split( i_rElementName, sNamespace, sLocalName );
+
+ if ( sLocalName == "config-item-set" )
+ return new ConfigItemSetImport( m_aChildSettings );
+ if ( sLocalName == "config-item" )
+ return new ConfigItemImport( m_aChildSettings );
+
+ SAL_WARN( "dbaccess", "unknown element name '"
+ << i_rElementName << "', ignoring");
+ return new IgnoringSettingsImport;
+ }
+
+ void ConfigItemSetImport::getItemValue( Any& o_rValue ) const
+ {
+ o_rValue <<= m_aChildSettings.getPropertyValues();
+ }
+
+} // namespace dbaccess
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/recovery/settingsimport.hxx b/dbaccess/source/core/recovery/settingsimport.hxx
new file mode 100644
index 000000000..bc29bd727
--- /dev/null
+++ b/dbaccess/source/core/recovery/settingsimport.hxx
@@ -0,0 +1,163 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <com/sun/star/xml/sax/XAttributeList.hpp>
+
+#include <comphelper/namedvaluecollection.hxx>
+#include <rtl/ref.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <salhelper/simplereferenceobject.hxx>
+
+namespace dbaccess
+{
+
+ // SettingsImport
+ /** a simplified version of xmloff/DocumentSettingsContext
+
+ It would be nice if the DocumentSettingsContext would not be that tightly interwoven with the SvXMLImport
+ class, so we could re-use it here ...
+ */
+ class SettingsImport : public salhelper::SimpleReferenceObject
+ {
+ public:
+ SettingsImport();
+
+ // own overridables
+ virtual ::rtl::Reference< SettingsImport > nextState(
+ const OUString& i_rElementName
+ ) = 0;
+ void startElement(
+ const css::uno::Reference< css::xml::sax::XAttributeList >& i_rAttributes
+ );
+ virtual void endElement();
+ void characters( std::u16string_view i_rCharacters );
+
+ protected:
+ virtual ~SettingsImport() override;
+
+ protected:
+ static void split( const OUString& i_rElementName, OUString& o_rNamespace, OUString& o_rLocalName );
+
+ protected:
+ const OUString& getItemName() const { return m_sItemName; }
+ const OUString& getItemType() const { return m_sItemType; }
+ const OUStringBuffer& getAccumulatedCharacters() const { return m_aCharacters; }
+
+ private:
+ // value of the config:name attribute, if any
+ OUString m_sItemName;
+ // value of the config:type attribute, if any
+ OUString m_sItemType;
+ // accumulated characters, if any
+ OUStringBuffer m_aCharacters;
+ };
+
+ // IgnoringSettingsImport
+ class IgnoringSettingsImport : public SettingsImport
+ {
+ public:
+ IgnoringSettingsImport()
+ {
+ }
+
+ // SettingsImport overridables
+ virtual ::rtl::Reference< SettingsImport > nextState(
+ const OUString& i_rElementName
+ ) override;
+
+ private:
+ virtual ~IgnoringSettingsImport() override
+ {
+ }
+ };
+
+ // OfficeSettingsImport
+ class OfficeSettingsImport : public SettingsImport
+ {
+ public:
+ explicit OfficeSettingsImport( ::comphelper::NamedValueCollection& o_rSettings );
+
+ // SettingsImport overridables
+ virtual ::rtl::Reference< SettingsImport > nextState(
+ const OUString& i_rElementName
+ ) override;
+
+ protected:
+ virtual ~OfficeSettingsImport() override;
+
+ private:
+ // the settings collection to which |this| will contribute a single setting
+ ::comphelper::NamedValueCollection& m_rSettings;
+ };
+
+ // ConfigItemSetImport
+ class ConfigItemImport : public SettingsImport
+ {
+ public:
+ explicit ConfigItemImport( ::comphelper::NamedValueCollection& o_rSettings );
+
+ protected:
+ virtual ~ConfigItemImport() override;
+
+ public:
+ // SettingsImport overridables
+ virtual ::rtl::Reference< SettingsImport > nextState(
+ const OUString& i_rElementName
+ ) override;
+ virtual void endElement() override;
+
+ protected:
+ // own overridables
+ /// retrieves the value represented by the element
+ virtual void getItemValue( css::uno::Any& o_rValue ) const;
+
+ private:
+ // the settings collection to which |this| will contribute a single setting
+ ::comphelper::NamedValueCollection& m_rSettings;
+ };
+
+ // ConfigItemSetImport
+ class ConfigItemSetImport : public ConfigItemImport
+ {
+ public:
+ explicit ConfigItemSetImport( ::comphelper::NamedValueCollection& o_rSettings );
+
+ protected:
+ virtual ~ConfigItemSetImport() override;
+
+ public:
+ // SettingsImport overridables
+ virtual ::rtl::Reference< SettingsImport > nextState(
+ const OUString& i_rElementName
+ ) override;
+
+ protected:
+ // ConfigItemImport overridables
+ virtual void getItemValue( css::uno::Any& o_rValue ) const override;
+
+ private:
+ /// the settings represented by our child elements
+ ::comphelper::NamedValueCollection m_aChildSettings;
+ };
+
+} // namespace dbaccess
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/recovery/storagestream.cxx b/dbaccess/source/core/recovery/storagestream.cxx
new file mode 100644
index 000000000..2831f406b
--- /dev/null
+++ b/dbaccess/source/core/recovery/storagestream.cxx
@@ -0,0 +1,55 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "storagestream.hxx"
+
+#include <com/sun/star/embed/ElementModes.hpp>
+
+#include <tools/diagnose_ex.h>
+
+namespace dbaccess
+{
+
+ using ::com::sun::star::uno::Reference;
+ using ::com::sun::star::uno::UNO_QUERY_THROW;
+ using ::com::sun::star::uno::UNO_SET_THROW;
+ using ::com::sun::star::embed::XStorage;
+ using ::com::sun::star::io::XStream;
+
+ namespace ElementModes = ::com::sun::star::embed::ElementModes;
+
+ // StorageOutputStream
+ StorageOutputStream::StorageOutputStream( const Reference< XStorage >& i_rParentStorage,
+ const OUString& i_rStreamName
+ )
+ {
+ ENSURE_OR_THROW( i_rParentStorage.is(), "illegal stream" );
+
+ const Reference< XStream > xStream(
+ i_rParentStorage->openStreamElement( i_rStreamName, ElementModes::READWRITE ), UNO_SET_THROW );
+ m_xOutputStream.set( xStream->getOutputStream(), UNO_SET_THROW );
+ }
+
+ StorageOutputStream::~StorageOutputStream()
+ {
+ }
+
+} // namespace dbaccess
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/recovery/storagestream.hxx b/dbaccess/source/core/recovery/storagestream.hxx
new file mode 100644
index 000000000..64c7e369d
--- /dev/null
+++ b/dbaccess/source/core/recovery/storagestream.hxx
@@ -0,0 +1,51 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <com/sun/star/embed/XStorage.hpp>
+
+namespace dbaccess
+{
+
+ // StorageOutputStream
+ /** convenience wrapper around a stream living in a storage
+ */
+ class StorageOutputStream
+ {
+ public:
+ StorageOutputStream(
+ const css::uno::Reference< css::embed::XStorage >& i_rParentStorage,
+ const OUString& i_rStreamName
+ );
+ virtual ~StorageOutputStream();
+
+ protected:
+ const css::uno::Reference< css::io::XOutputStream >&
+ getOutputStream() const { return m_xOutputStream; }
+
+ private:
+ css::uno::Reference< css::io::XOutputStream >
+ m_xOutputStream;
+ };
+
+
+} // namespace dbaccess
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/recovery/storagetextstream.cxx b/dbaccess/source/core/recovery/storagetextstream.cxx
new file mode 100644
index 000000000..32f68da9a
--- /dev/null
+++ b/dbaccess/source/core/recovery/storagetextstream.cxx
@@ -0,0 +1,71 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "storagetextstream.hxx"
+
+#include <com/sun/star/io/TextOutputStream.hpp>
+
+namespace dbaccess
+{
+
+ using ::com::sun::star::uno::Reference;
+ using ::com::sun::star::uno::XComponentContext;
+ using ::com::sun::star::embed::XStorage;
+ using ::com::sun::star::io::TextOutputStream;
+ using ::com::sun::star::io::XTextOutputStream2;
+
+ // StorageTextOutputStream_Data
+ struct StorageTextOutputStream_Data
+ {
+ Reference< XTextOutputStream2 > xTextOutput;
+ };
+
+ constexpr OUStringLiteral sLineFeed = u"\n";
+
+ // StorageTextOutputStream
+ StorageTextOutputStream::StorageTextOutputStream( const Reference<XComponentContext>& i_rContext,
+ const Reference< XStorage >& i_rParentStorage,
+ const OUString& i_rStreamName
+ )
+ :StorageOutputStream( i_rParentStorage, i_rStreamName )
+ ,m_pData( new StorageTextOutputStream_Data )
+ {
+ m_pData->xTextOutput = TextOutputStream::create( i_rContext );
+ m_pData->xTextOutput->setEncoding( "UTF-8" );
+ m_pData->xTextOutput->setOutputStream( getOutputStream() );
+ }
+
+ StorageTextOutputStream::~StorageTextOutputStream()
+ {
+ }
+
+ void StorageTextOutputStream::writeLine( const OUString& i_rLine )
+ {
+ m_pData->xTextOutput->writeString( i_rLine );
+ m_pData->xTextOutput->writeString( sLineFeed );
+ }
+
+ void StorageTextOutputStream::writeLine()
+ {
+ m_pData->xTextOutput->writeString( sLineFeed );
+ }
+
+} // namespace dbaccess
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/recovery/storagetextstream.hxx b/dbaccess/source/core/recovery/storagetextstream.hxx
new file mode 100644
index 000000000..46c3e5b2e
--- /dev/null
+++ b/dbaccess/source/core/recovery/storagetextstream.hxx
@@ -0,0 +1,52 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include "storagestream.hxx"
+
+#include <com/sun/star/uno/XComponentContext.hpp>
+
+#include <memory>
+
+namespace dbaccess
+{
+
+ // StorageTextStream
+ struct StorageTextOutputStream_Data;
+ class StorageTextOutputStream : public StorageOutputStream
+ {
+ public:
+ StorageTextOutputStream(
+ const css::uno::Reference< css::uno::XComponentContext >& i_rContext,
+ const css::uno::Reference< css::embed::XStorage >& i_rParentStorage,
+ const OUString& i_rStreamName
+ );
+ virtual ~StorageTextOutputStream() override;
+
+ void writeLine( const OUString& i_rLine );
+ void writeLine();
+
+ private:
+ std::unique_ptr< StorageTextOutputStream_Data > m_pData;
+ };
+
+} // namespace dbaccess
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/recovery/storagexmlstream.cxx b/dbaccess/source/core/recovery/storagexmlstream.cxx
new file mode 100644
index 000000000..e76dabefe
--- /dev/null
+++ b/dbaccess/source/core/recovery/storagexmlstream.cxx
@@ -0,0 +1,151 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "storagexmlstream.hxx"
+
+#include <com/sun/star/embed/ElementModes.hpp>
+#include <com/sun/star/xml/sax/XDocumentHandler.hpp>
+#include <com/sun/star/xml/sax/Parser.hpp>
+#include <com/sun/star/xml/sax/Writer.hpp>
+
+#include <rtl/ref.hxx>
+#include <tools/diagnose_ex.h>
+#include <xmloff/attrlist.hxx>
+
+#include <stack>
+
+namespace dbaccess
+{
+
+ using ::com::sun::star::uno::Reference;
+ using ::com::sun::star::uno::UNO_QUERY_THROW;
+ using ::com::sun::star::uno::XComponentContext;
+ using ::com::sun::star::embed::XStorage;
+ using ::com::sun::star::xml::sax::XDocumentHandler;
+ using ::com::sun::star::xml::sax::XWriter;
+ using ::com::sun::star::xml::sax::Writer;
+ using ::com::sun::star::xml::sax::Parser;
+ using ::com::sun::star::xml::sax::InputSource;
+
+ // StorageXMLOutputStream_Data
+ struct StorageXMLOutputStream_Data
+ {
+ Reference< XDocumentHandler > xHandler;
+ std::stack< OUString > aElements;
+ ::rtl::Reference< SvXMLAttributeList > xAttributes;
+ };
+
+ // StorageXMLOutputStream
+ StorageXMLOutputStream::StorageXMLOutputStream( const Reference<XComponentContext>& i_rContext,
+ const Reference< XStorage >& i_rParentStorage,
+ const OUString& i_rStreamName )
+ :StorageOutputStream( i_rParentStorage, i_rStreamName )
+ ,m_pData( new StorageXMLOutputStream_Data )
+ {
+ const Reference< XWriter > xSaxWriter = Writer::create( i_rContext );
+ xSaxWriter->setOutputStream( getOutputStream() );
+
+ m_pData->xHandler.set( xSaxWriter, UNO_QUERY_THROW );
+ m_pData->xHandler->startDocument();
+
+ m_pData->xAttributes = new SvXMLAttributeList;
+ }
+
+ StorageXMLOutputStream::~StorageXMLOutputStream()
+ {
+ }
+
+ void StorageXMLOutputStream::close()
+ {
+ ENSURE_OR_RETURN_VOID( m_pData->xHandler.is(), "illegal document handler" );
+ m_pData->xHandler->endDocument();
+ // do not call the base class, it would call closeOutput on the output stream, which is already done by
+ // endDocument
+ }
+
+ void StorageXMLOutputStream::addAttribute( const OUString& i_rName, const OUString& i_rValue ) const
+ {
+ m_pData->xAttributes->AddAttribute( i_rName, i_rValue );
+ }
+
+ void StorageXMLOutputStream::startElement( const OUString& i_rElementName ) const
+ {
+ ENSURE_OR_RETURN_VOID( m_pData->xHandler.is(), "no document handler" );
+
+ m_pData->xHandler->startElement( i_rElementName, m_pData->xAttributes );
+ m_pData->xAttributes = new SvXMLAttributeList;
+ m_pData->aElements.push( i_rElementName );
+ }
+
+ void StorageXMLOutputStream::endElement() const
+ {
+ ENSURE_OR_RETURN_VOID( m_pData->xHandler.is(), "no document handler" );
+ ENSURE_OR_RETURN_VOID( !m_pData->aElements.empty(), "no element on the stack" );
+
+ const OUString sElementName( m_pData->aElements.top() );
+ m_pData->xHandler->endElement( sElementName );
+ m_pData->aElements.pop();
+ }
+
+ void StorageXMLOutputStream::ignorableWhitespace( const OUString& i_rWhitespace ) const
+ {
+ ENSURE_OR_RETURN_VOID( m_pData->xHandler.is(), "no document handler" );
+
+ m_pData->xHandler->ignorableWhitespace( i_rWhitespace );
+ }
+
+ void StorageXMLOutputStream::characters( const OUString& i_rCharacters ) const
+ {
+ ENSURE_OR_RETURN_VOID( m_pData->xHandler.is(), "no document handler" );
+
+ m_pData->xHandler->characters( i_rCharacters );
+ }
+
+ // StorageXMLInputStream
+ StorageXMLInputStream::StorageXMLInputStream( const Reference<XComponentContext>& i_rContext,
+ const Reference< XStorage >& i_rParentStorage,
+ const OUString& i_rStreamName )
+ {
+ ENSURE_OR_THROW( i_rParentStorage.is(), "illegal stream" );
+
+ const Reference< css::io::XStream > xStream(
+ i_rParentStorage->openStreamElement( i_rStreamName, css::embed::ElementModes::READ ), css::uno::UNO_SET_THROW );
+ m_xInputStream.set( xStream->getInputStream(), css::uno::UNO_SET_THROW );
+
+ m_xParser.set( Parser::create(i_rContext) );
+ }
+
+ void StorageXMLInputStream::import( const Reference< XDocumentHandler >& i_rHandler )
+ {
+ ENSURE_OR_THROW( i_rHandler.is(), "illegal document handler (NULL)" );
+
+ InputSource aInputSource;
+ aInputSource.aInputStream = m_xInputStream;
+
+ m_xParser->setDocumentHandler( i_rHandler );
+ m_xParser->parseStream( aInputSource );
+ }
+
+ StorageXMLInputStream::~StorageXMLInputStream()
+ {
+ }
+
+} // namespace dbaccess
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/recovery/storagexmlstream.hxx b/dbaccess/source/core/recovery/storagexmlstream.hxx
new file mode 100644
index 000000000..fd762ae05
--- /dev/null
+++ b/dbaccess/source/core/recovery/storagexmlstream.hxx
@@ -0,0 +1,88 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include "storagestream.hxx"
+
+#include <com/sun/star/xml/sax/XParser.hpp>
+#include <com/sun/star/embed/XStorage.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <com/sun/star/xml/sax/XDocumentHandler.hpp>
+
+#include <memory>
+
+namespace dbaccess
+{
+
+ // StorageXMLOutputStream
+ struct StorageXMLOutputStream_Data;
+ class StorageXMLOutputStream : public StorageOutputStream
+ {
+ public:
+ StorageXMLOutputStream(
+ const css::uno::Reference< css::uno::XComponentContext >& i_rContext,
+ const css::uno::Reference< css::embed::XStorage >& i_rParentStorage,
+ const OUString& i_rStreamName
+ );
+ virtual ~StorageXMLOutputStream() override;
+
+ void close();
+
+ void addAttribute( const OUString& i_rName, const OUString& i_rValue ) const;
+
+ void startElement( const OUString& i_rElementName ) const;
+ void endElement() const;
+
+ void ignorableWhitespace( const OUString& i_rWhitespace ) const;
+ void characters( const OUString& i_rCharacters ) const;
+
+ private:
+ StorageXMLOutputStream( const StorageXMLOutputStream& ) = delete;
+ StorageXMLOutputStream& operator=( const StorageXMLOutputStream& ) = delete;
+
+ private:
+ std::unique_ptr< StorageXMLOutputStream_Data > m_pData;
+ };
+
+ class StorageXMLInputStream
+ {
+ public:
+ StorageXMLInputStream(
+ const css::uno::Reference< css::uno::XComponentContext >& i_rContext,
+ const css::uno::Reference< css::embed::XStorage >& i_rParentStorage,
+ const OUString& i_rStreamName
+ );
+ ~StorageXMLInputStream();
+
+ void import(
+ const css::uno::Reference< css::xml::sax::XDocumentHandler >& i_rHandler
+ );
+
+ StorageXMLInputStream( const StorageXMLInputStream& ) = delete;
+ StorageXMLInputStream& operator=( const StorageXMLInputStream& ) = delete;
+
+ private:
+ css::uno::Reference< css::xml::sax::XParser > m_xParser;
+ css::uno::Reference< css::io::XInputStream > m_xInputStream;
+ };
+
+} // namespace dbaccess
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/recovery/subcomponentloader.cxx b/dbaccess/source/core/recovery/subcomponentloader.cxx
new file mode 100644
index 000000000..3393c3d13
--- /dev/null
+++ b/dbaccess/source/core/recovery/subcomponentloader.cxx
@@ -0,0 +1,124 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "subcomponentloader.hxx"
+
+#include <com/sun/star/ucb/Command.hpp>
+#include <com/sun/star/frame/XController2.hpp>
+
+#include <tools/diagnose_ex.h>
+
+namespace dbaccess
+{
+
+ using ::com::sun::star::uno::Reference;
+ using ::com::sun::star::uno::UNO_QUERY_THROW;
+ using ::com::sun::star::uno::UNO_SET_THROW;
+ using ::com::sun::star::uno::Exception;
+ using ::com::sun::star::frame::XController;
+ using ::com::sun::star::frame::XFrame;
+ using ::com::sun::star::awt::XWindow;
+ using ::com::sun::star::awt::WindowEvent;
+ using ::com::sun::star::lang::EventObject;
+ using ::com::sun::star::ucb::Command;
+ using ::com::sun::star::ucb::XCommandProcessor;
+ using ::com::sun::star::frame::XController2;
+ using ::com::sun::star::lang::XComponent;
+
+ // SubComponentLoader
+ SubComponentLoader::SubComponentLoader( const Reference< XController >& i_rApplicationController,
+ const Reference< XCommandProcessor >& i_rSubDocumentDefinition )
+ :mxDocDefCommands( i_rSubDocumentDefinition )
+ {
+ // add as window listener to the controller's container window, so we get notified when it is shown
+ Reference< XController2 > xController( i_rApplicationController, UNO_QUERY_THROW );
+ mxAppComponentWindow.set( xController->getComponentWindow(), UNO_SET_THROW );
+
+ osl_atomic_increment( &m_refCount );
+ {
+ mxAppComponentWindow->addWindowListener( this );
+ }
+ osl_atomic_decrement( &m_refCount );
+ }
+
+ SubComponentLoader::SubComponentLoader( const Reference< XController >& i_rApplicationController,
+ const Reference< XComponent >& i_rNonDocumentComponent )
+ :mxNonDocComponent( i_rNonDocumentComponent )
+ {
+ // add as window listener to the controller's container window, so we get notified when it is shown
+ Reference< XController2 > xController( i_rApplicationController, UNO_QUERY_THROW );
+ mxAppComponentWindow.set( xController->getComponentWindow(), UNO_SET_THROW );
+
+ osl_atomic_increment( &m_refCount );
+ {
+ mxAppComponentWindow->addWindowListener( this );
+ }
+ osl_atomic_decrement( &m_refCount );
+ }
+
+ SubComponentLoader::~SubComponentLoader()
+ {
+ }
+
+ void SAL_CALL SubComponentLoader::windowResized( const WindowEvent& )
+ {
+ }
+
+ void SAL_CALL SubComponentLoader::windowMoved( const WindowEvent& )
+ {
+ }
+
+ void SAL_CALL SubComponentLoader::windowShown( const EventObject& )
+ {
+ try
+ {
+ if ( mxDocDefCommands.is() )
+ {
+ Command aCommandOpen;
+ aCommandOpen.Name = "show";
+
+ const sal_Int32 nCommandIdentifier = mxDocDefCommands->createCommandIdentifier();
+ mxDocDefCommands->execute( aCommandOpen, nCommandIdentifier, nullptr );
+ }
+ else
+ {
+ const Reference< XController > xController( mxNonDocComponent, UNO_QUERY_THROW );
+ const Reference< XFrame > xFrame( xController->getFrame(), UNO_SET_THROW );
+ const Reference< XWindow > xWindow( xFrame->getContainerWindow(), UNO_SET_THROW );
+ xWindow->setVisible( true );
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ mxAppComponentWindow->removeWindowListener( this );
+ }
+
+ void SAL_CALL SubComponentLoader::windowHidden( const EventObject& )
+ {
+ }
+
+ void SAL_CALL SubComponentLoader::disposing( const EventObject& )
+ {
+ }
+
+} // namespace dbaccess
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/recovery/subcomponentloader.hxx b/dbaccess/source/core/recovery/subcomponentloader.hxx
new file mode 100644
index 000000000..4ab867880
--- /dev/null
+++ b/dbaccess/source/core/recovery/subcomponentloader.hxx
@@ -0,0 +1,71 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <com/sun/star/awt/XWindowListener.hpp>
+#include <com/sun/star/frame/XController.hpp>
+#include <com/sun/star/lang/XComponent.hpp>
+#include <com/sun/star/ucb/XCommandProcessor.hpp>
+
+#include <cppuhelper/implbase.hxx>
+
+namespace dbaccess
+{
+
+ // SubComponentLoader
+ typedef ::cppu::WeakImplHelper< css::awt::XWindowListener
+ > SubComponentLoader_Base;
+ /** is a helper class which loads/opens a given sub component as soon as the main application
+ window becomes visible.
+ */
+ class SubComponentLoader : public SubComponentLoader_Base
+ {
+ public:
+ SubComponentLoader(
+ const css::uno::Reference< css::frame::XController >& i_rApplicationController,
+ const css::uno::Reference< css::ucb::XCommandProcessor >& i_rSubDocumentDefinition
+ );
+
+ SubComponentLoader(
+ const css::uno::Reference< css::frame::XController >& i_rApplicationController,
+ const css::uno::Reference< css::lang::XComponent >& i_rNonDocumentComponent
+ );
+
+ // XWindowListener
+ virtual void SAL_CALL windowResized( const css::awt::WindowEvent& e ) override;
+ virtual void SAL_CALL windowMoved( const css::awt::WindowEvent& e ) override;
+ virtual void SAL_CALL windowShown( const css::lang::EventObject& e ) override;
+ virtual void SAL_CALL windowHidden( const css::lang::EventObject& e ) override;
+
+ // XEventListener
+ virtual void SAL_CALL disposing( const css::lang::EventObject& Source ) override;
+
+ protected:
+ virtual ~SubComponentLoader() override;
+
+ private:
+ const css::uno::Reference< css::ucb::XCommandProcessor > mxDocDefCommands;
+ const css::uno::Reference< css::lang::XComponent > mxNonDocComponent;
+ css::uno::Reference< css::awt::XWindow > mxAppComponentWindow;
+ };
+
+} // namespace dbaccess
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/recovery/subcomponentrecovery.cxx b/dbaccess/source/core/recovery/subcomponentrecovery.cxx
new file mode 100644
index 000000000..e7ffffd61
--- /dev/null
+++ b/dbaccess/source/core/recovery/subcomponentrecovery.cxx
@@ -0,0 +1,628 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "subcomponentrecovery.hxx"
+
+#include <sdbcoretools.hxx>
+#include "storagexmlstream.hxx"
+#include "subcomponentloader.hxx"
+#include "settingsimport.hxx"
+
+#include <com/sun/star/embed/ElementModes.hpp>
+#include <com/sun/star/frame/ModuleManager.hpp>
+#include <com/sun/star/document/XStorageBasedDocument.hpp>
+#include <com/sun/star/ucb/XCommandProcessor.hpp>
+#include <com/sun/star/container/XHierarchicalNameAccess.hpp>
+#include <com/sun/star/sdb/XFormDocumentsSupplier.hpp>
+#include <com/sun/star/sdb/XReportDocumentsSupplier.hpp>
+#include <com/sun/star/xml/sax/XDocumentHandler.hpp>
+
+#include <comphelper/namedvaluecollection.hxx>
+#include <cppuhelper/implbase.hxx>
+#include <connectivity/dbtools.hxx>
+#include <tools/diagnose_ex.h>
+#include <sal/log.hxx>
+#include <xmloff/XMLSettingsExportContext.hxx>
+#include <xmloff/SettingsExportHelper.hxx>
+
+#include <stack>
+
+namespace dbaccess
+{
+
+ using css::uno::Reference;
+ using css::uno::XInterface;
+ using css::uno::UNO_QUERY;
+ using css::uno::UNO_QUERY_THROW;
+ using css::uno::UNO_SET_THROW;
+ using css::uno::Exception;
+ using css::uno::RuntimeException;
+ using css::uno::Any;
+ using css::uno::Sequence;
+ using css::uno::XComponentContext;
+ using css::embed::XStorage;
+ using css::sdb::application::XDatabaseDocumentUI;
+ using css::beans::Pair;
+ using css::frame::ModuleManager;
+ using css::frame::XModuleManager2;
+ using css::lang::XComponent;
+ using css::frame::XModel;
+ using css::frame::XController;
+ using css::beans::XPropertySet;
+ using css::beans::PropertyValue;
+ using css::document::XStorageBasedDocument;
+ using css::ucb::XCommandProcessor;
+ using css::container::XHierarchicalNameAccess;
+ using css::sdb::XFormDocumentsSupplier;
+ using css::sdb::XReportDocumentsSupplier;
+ using css::xml::sax::XLocator;
+ using css::xml::sax::XDocumentHandler;
+ using css::xml::sax::XAttributeList;
+
+ namespace ElementModes = css::embed::ElementModes;
+ namespace DatabaseObject = css::sdb::application::DatabaseObject;
+
+ // helper
+ namespace
+ {
+ OUString lcl_getComponentStorageBaseName( const SubComponentType i_eType )
+ {
+ switch ( i_eType )
+ {
+ case FORM:
+ return "form";
+ case REPORT:
+ return "report";
+ case TABLE:
+ return "table";
+ case QUERY:
+ return "query";
+ default:
+ break;
+ }
+
+ OSL_FAIL( "lcl_getComponentStorageBaseName: unimplemented case!" );
+ return OUString();
+ }
+
+ SubComponentType lcl_databaseObjectToSubComponentType( const sal_Int32 i_nObjectType )
+ {
+ switch ( i_nObjectType )
+ {
+ case DatabaseObject::TABLE: return TABLE;
+ case DatabaseObject::QUERY: return QUERY;
+ case DatabaseObject::FORM: return FORM;
+ case DatabaseObject::REPORT:return REPORT;
+ default:
+ break;
+ }
+ return UNKNOWN;
+ }
+
+ bool lcl_determineReadOnly( const Reference< XComponent >& i_rComponent )
+ {
+ Reference< XModel > xDocument( i_rComponent, UNO_QUERY );
+ if ( !xDocument.is() )
+ {
+ Reference< XController > xController( i_rComponent, UNO_QUERY_THROW );
+ xDocument = xController->getModel();
+ }
+
+ if ( !xDocument.is() )
+ return false;
+
+ ::comphelper::NamedValueCollection aDocArgs( xDocument->getArgs() );
+ return aDocArgs.getOrDefault( "ReadOnly", false );
+ }
+
+ Reference< XCommandProcessor > lcl_getSubComponentDef_nothrow( const Reference< XDatabaseDocumentUI >& i_rAppUI,
+ const SubComponentType i_eType, const OUString& i_rName )
+ {
+ Reference< XController > xController( i_rAppUI, UNO_QUERY_THROW );
+ ENSURE_OR_RETURN( ( i_eType == FORM ) || ( i_eType == REPORT ), "lcl_getSubComponentDef_nothrow: illegal controller", nullptr );
+
+ Reference< XCommandProcessor > xCommandProcessor;
+ try
+ {
+ Reference< XHierarchicalNameAccess > xDefinitionContainer;
+ if ( i_eType == FORM )
+ {
+ Reference< XFormDocumentsSupplier > xSuppForms( xController->getModel(), UNO_QUERY_THROW );
+ xDefinitionContainer.set( xSuppForms->getFormDocuments(), UNO_QUERY_THROW );
+ }
+ else
+ {
+ Reference< XReportDocumentsSupplier > xSuppReports( xController->getModel(), UNO_QUERY_THROW );
+ xDefinitionContainer.set( xSuppReports->getReportDocuments(), UNO_QUERY_THROW );
+ }
+ xCommandProcessor.set( xDefinitionContainer->getByHierarchicalName( i_rName ), UNO_QUERY_THROW );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ return xCommandProcessor;
+ }
+
+ constexpr OUStringLiteral sSettingsStreamName = u"settings.xml";
+ constexpr OUStringLiteral sCurrentQueryDesignName = u"ooo:current-query-design";
+ }
+
+ namespace {
+
+ // SettingsExportContext
+ class SettingsExportContext : public ::xmloff::XMLSettingsExportContext
+ {
+ public:
+ SettingsExportContext( const Reference<XComponentContext>& i_rContext, const StorageXMLOutputStream& i_rDelegator )
+ :m_rContext( i_rContext )
+ ,m_rDelegator( i_rDelegator )
+ ,m_aNamespace( ::xmloff::token::GetXMLToken( ::xmloff::token::XML_NP_CONFIG ) )
+ {
+ }
+
+ virtual ~SettingsExportContext()
+ {
+ }
+
+ public:
+ virtual void AddAttribute( enum ::xmloff::token::XMLTokenEnum i_eName, const OUString& i_rValue ) override;
+ virtual void AddAttribute( enum ::xmloff::token::XMLTokenEnum i_eName, enum ::xmloff::token::XMLTokenEnum i_eValue ) override;
+ virtual void StartElement( enum ::xmloff::token::XMLTokenEnum i_eName ) override;
+ virtual void EndElement ( const bool i_bIgnoreWhitespace ) override;
+ virtual void Characters( const OUString& i_rCharacters ) override;
+
+ virtual css::uno::Reference< css::uno::XComponentContext >
+ GetComponentContext() const override;
+
+ private:
+ OUString impl_prefix( const ::xmloff::token::XMLTokenEnum i_eToken )
+ {
+ return m_aNamespace + ":" + ::xmloff::token::GetXMLToken( i_eToken );
+ }
+
+ private:
+ const Reference<XComponentContext>& m_rContext;
+ const StorageXMLOutputStream& m_rDelegator;
+ const OUString m_aNamespace;
+ };
+
+ }
+
+ void SettingsExportContext::AddAttribute( enum ::xmloff::token::XMLTokenEnum i_eName, const OUString& i_rValue )
+ {
+ m_rDelegator.addAttribute( impl_prefix( i_eName ), i_rValue );
+ }
+
+ void SettingsExportContext::AddAttribute( enum ::xmloff::token::XMLTokenEnum i_eName, enum ::xmloff::token::XMLTokenEnum i_eValue )
+ {
+ m_rDelegator.addAttribute( impl_prefix( i_eName ), ::xmloff::token::GetXMLToken( i_eValue ) );
+ }
+
+ void SettingsExportContext::StartElement( enum ::xmloff::token::XMLTokenEnum i_eName )
+ {
+ m_rDelegator.ignorableWhitespace( " " );
+
+ m_rDelegator.startElement( impl_prefix( i_eName ) );
+ }
+
+ void SettingsExportContext::EndElement( const bool i_bIgnoreWhitespace )
+ {
+ if ( i_bIgnoreWhitespace )
+ m_rDelegator.ignorableWhitespace( " " );
+ m_rDelegator.endElement();
+ }
+
+ void SettingsExportContext::Characters( const OUString& i_rCharacters )
+ {
+ m_rDelegator.characters( i_rCharacters );
+ }
+
+ Reference< css::uno::XComponentContext > SettingsExportContext::GetComponentContext() const
+ {
+ return m_rContext;
+ }
+
+ // SettingsDocumentHandler
+ typedef ::cppu::WeakImplHelper< XDocumentHandler
+ > SettingsDocumentHandler_Base;
+
+ namespace {
+
+ class SettingsDocumentHandler : public SettingsDocumentHandler_Base
+ {
+ public:
+ SettingsDocumentHandler()
+ {
+ }
+
+ protected:
+ virtual ~SettingsDocumentHandler() override
+ {
+ }
+
+ public:
+ // XDocumentHandler
+ virtual void SAL_CALL startDocument( ) override;
+ virtual void SAL_CALL endDocument( ) override;
+ virtual void SAL_CALL startElement( const OUString& aName, const Reference< XAttributeList >& xAttribs ) override;
+ virtual void SAL_CALL endElement( const OUString& aName ) override;
+ virtual void SAL_CALL characters( const OUString& aChars ) override;
+ virtual void SAL_CALL ignorableWhitespace( const OUString& aWhitespaces ) override;
+ virtual void SAL_CALL processingInstruction( const OUString& aTarget, const OUString& aData ) override;
+ virtual void SAL_CALL setDocumentLocator( const Reference< XLocator >& xLocator ) override;
+
+ const ::comphelper::NamedValueCollection& getSettings() const { return m_aSettings; }
+
+ private:
+ std::stack< ::rtl::Reference< SettingsImport > > m_aStates;
+ ::comphelper::NamedValueCollection m_aSettings;
+ };
+
+ }
+
+ void SAL_CALL SettingsDocumentHandler::startDocument( )
+ {
+ }
+
+ void SAL_CALL SettingsDocumentHandler::endDocument( )
+ {
+ }
+
+ void SAL_CALL SettingsDocumentHandler::startElement( const OUString& i_Name, const Reference< XAttributeList >& i_Attribs )
+ {
+ ::rtl::Reference< SettingsImport > pNewState;
+
+ if ( m_aStates.empty() )
+ {
+ if ( i_Name == "office:settings" )
+ {
+ pNewState = new OfficeSettingsImport( m_aSettings );
+ }
+ else
+ {
+ OSL_FAIL( "SettingsDocumentHandler::startElement: invalid settings file!" );
+ // Yes, that's not correct. Somebody could, in theory, give us a document which starts with "foo:settings",
+ // where "foo" is mapped to the proper namespace URL.
+ // However, there's no need to bother with this. The "recovery" sub storage we're recovering from is
+ // not part of ODF, so we can impose any format restrictions on it ...
+ }
+ }
+ else
+ {
+ ::rtl::Reference< SettingsImport > pCurrentState( m_aStates.top() );
+ pNewState = pCurrentState->nextState( i_Name );
+ }
+
+ ENSURE_OR_THROW( pNewState.is(), "no new state - aborting import" );
+ pNewState->startElement( i_Attribs );
+
+ m_aStates.push( pNewState );
+ }
+
+ void SAL_CALL SettingsDocumentHandler::endElement( const OUString& )
+ {
+ ENSURE_OR_THROW( !m_aStates.empty(), "no active element" );
+
+ ::rtl::Reference< SettingsImport > pCurrentState( m_aStates.top() );
+ pCurrentState->endElement();
+ m_aStates.pop();
+ }
+
+ void SAL_CALL SettingsDocumentHandler::characters( const OUString& i_Chars )
+ {
+ ENSURE_OR_THROW( !m_aStates.empty(), "no active element" );
+
+ ::rtl::Reference< SettingsImport > pCurrentState( m_aStates.top() );
+ pCurrentState->characters( i_Chars );
+ }
+
+ void SAL_CALL SettingsDocumentHandler::ignorableWhitespace( const OUString& )
+ {
+ // ignore them - that's why they're called "ignorable"
+ }
+
+ void SAL_CALL SettingsDocumentHandler::processingInstruction( const OUString&, const OUString& )
+ {
+ OSL_FAIL( "SettingsDocumentHandler::processingInstruction: unexpected ..." );
+ }
+
+ void SAL_CALL SettingsDocumentHandler::setDocumentLocator( const Reference< XLocator >& ) {}
+
+ // SubComponentRecovery
+ OUString SubComponentRecovery::getComponentsStorageName( const SubComponentType i_eType )
+ {
+ switch ( i_eType )
+ {
+ case FORM:
+ return "forms";
+ case REPORT:
+ return "reports";
+ case TABLE:
+ return "tables";
+ case QUERY:
+ return "queries";
+ case RELATION_DESIGN:
+ return "relations";
+ default:
+ break;
+ }
+
+ OSL_FAIL( "SubComponentRecovery::getComponentsStorageName: unimplemented case!" );
+ return OUString();
+ }
+
+ void SubComponentRecovery::saveToRecoveryStorage( const Reference< XStorage >& i_rRecoveryStorage,
+ MapCompTypeToCompDescs& io_mapCompDescs )
+ {
+ if ( m_eType == UNKNOWN )
+ // quite fatal, but has already been reported (as assertion) before
+ return;
+
+ // open the sub storage for the given kind of components
+ const OUString& rStorageName( getComponentsStorageName( m_eType ) );
+ const Reference< XStorage > xComponentsStorage( i_rRecoveryStorage->openStorageElement(
+ rStorageName, ElementModes::READWRITE ), UNO_SET_THROW );
+
+ // find a free sub storage name, and create Yet Another Sub Storage
+ const OUString& rBaseName( lcl_getComponentStorageBaseName( m_eType ) );
+ const OUString sStorName = ::dbtools::createUniqueName( xComponentsStorage, rBaseName );
+ const Reference< XStorage > xObjectStor( xComponentsStorage->openStorageElement(
+ sStorName, ElementModes::READWRITE ), UNO_SET_THROW );
+
+ switch ( m_eType )
+ {
+ case FORM:
+ case REPORT:
+ impl_saveSubDocument_throw( xObjectStor );
+ break;
+
+ case QUERY:
+ impl_saveQueryDesign_throw( xObjectStor );
+ break;
+
+ default:
+ // TODO
+ OSL_FAIL( "SubComponentRecoverys::saveToRecoveryStorage: unimplemented case!" );
+ break;
+ }
+
+ // commit the storage(s)
+ tools::stor::commitStorageIfWriteable( xObjectStor );
+ tools::stor::commitStorageIfWriteable( xComponentsStorage );
+
+ // remember the relationship from the component name to the storage name
+ MapStringToCompDesc& rMapCompDescs = io_mapCompDescs[ m_eType ];
+ OSL_ENSURE( rMapCompDescs.find( sStorName ) == rMapCompDescs.end(),
+ "SubComponentRecoverys::saveToRecoveryStorage: object name already used!" );
+ rMapCompDescs[ sStorName ] = m_aCompDesc;
+ }
+
+ void SubComponentRecovery::impl_identifyComponent_throw()
+ {
+ // ask the controller
+ Pair< sal_Int32, OUString > aComponentIdentity = m_xDocumentUI->identifySubComponent( m_xComponent );
+ m_eType = lcl_databaseObjectToSubComponentType( aComponentIdentity.First );
+ m_aCompDesc.sName = aComponentIdentity.Second;
+
+ // what the controller didn't give us is the information whether this is in edit mode or not ...
+ Reference< XModuleManager2 > xModuleManager( ModuleManager::create(m_rContext) );
+ const OUString sModuleIdentifier = xModuleManager->identify( m_xComponent );
+
+ switch ( m_eType )
+ {
+ case TABLE:
+ m_aCompDesc.bForEditing = sModuleIdentifier == "com.sun.star.sdb.TableDesign";
+ break;
+
+ case QUERY:
+ m_aCompDesc.bForEditing = sModuleIdentifier == "com.sun.star.sdb.QueryDesign";
+ break;
+
+ case REPORT:
+ if ( sModuleIdentifier == "com.sun.star.report.ReportDefinition" )
+ {
+ // it's an SRB report designer
+ m_aCompDesc.bForEditing = true;
+ break;
+ }
+ [[fallthrough]];
+
+ case FORM:
+ m_aCompDesc.bForEditing = !lcl_determineReadOnly( m_xComponent );
+ break;
+
+ default:
+ if ( sModuleIdentifier == "com.sun.star.sdb.RelationDesign" )
+ {
+ m_eType = RELATION_DESIGN;
+ m_aCompDesc.bForEditing = true;
+ }
+ else
+ {
+ OSL_FAIL( "SubComponentRecovery::impl_identifyComponent_throw: couldn't classify the given sub component!" );
+ }
+ break;
+ }
+
+ SAL_WARN_IF( m_eType == UNKNOWN, "dbaccess",
+ "SubComponentRecovery::impl_identifyComponent_throw: couldn't classify the component!" );
+ }
+
+ void SubComponentRecovery::impl_saveQueryDesign_throw( const Reference< XStorage >& i_rObjectStorage )
+ {
+ ENSURE_OR_THROW( m_eType == QUERY, "illegal sub component type" );
+ ENSURE_OR_THROW( i_rObjectStorage.is(), "illegal storage" );
+
+ // retrieve the current query design (which might differ from what we can retrieve as ActiveCommand property, since
+ // the latter is updated only upon successful save of the design)
+ Reference< XPropertySet > xDesignerProps( m_xComponent, UNO_QUERY_THROW );
+ Sequence< PropertyValue > aCurrentQueryDesign;
+ OSL_VERIFY( xDesignerProps->getPropertyValue( "CurrentQueryDesign" ) >>= aCurrentQueryDesign );
+
+ // write the query design
+ StorageXMLOutputStream aDesignOutput( m_rContext, i_rObjectStorage, sSettingsStreamName );
+ SettingsExportContext aSettingsExportContext( m_rContext, aDesignOutput );
+
+ static const OUStringLiteral sWhitespace( u" " );
+
+ aDesignOutput.startElement( "office:settings" );
+ aDesignOutput.ignorableWhitespace( sWhitespace );
+
+ XMLSettingsExportHelper aSettingsExporter( aSettingsExportContext );
+ aSettingsExporter.exportAllSettings( aCurrentQueryDesign, sCurrentQueryDesignName );
+
+ aDesignOutput.ignorableWhitespace( sWhitespace );
+ aDesignOutput.endElement();
+ aDesignOutput.close();
+ }
+
+ void SubComponentRecovery::impl_saveSubDocument_throw( const Reference< XStorage >& i_rObjectStorage )
+ {
+ ENSURE_OR_THROW( ( m_eType == FORM ) || ( m_eType == REPORT ), "illegal sub component type" );
+ ENSURE_OR_THROW( i_rObjectStorage.is(), "illegal storage" );
+
+ // store the document into the storage
+ Reference< XStorageBasedDocument > xStorageDocument( m_xComponent, UNO_QUERY_THROW );
+ xStorageDocument->storeToStorage( i_rObjectStorage, Sequence< PropertyValue >() );
+ }
+
+ Reference< XComponent > SubComponentRecovery::impl_recoverSubDocument_throw( const Reference< XStorage >& i_rRecoveryStorage,
+ const OUString& i_rComponentName, const bool i_bForEditing )
+ {
+ Reference< XComponent > xSubComponent;
+ Reference< XCommandProcessor > xDocDefinition;
+
+ ::comphelper::NamedValueCollection aLoadArgs;
+ aLoadArgs.put( "RecoveryStorage", i_rRecoveryStorage );
+
+ // load/create the sub component hidden. We'll show it when the main app window is shown.
+ aLoadArgs.put( "Hidden", true );
+
+ if ( !i_rComponentName.isEmpty() )
+ {
+ xDocDefinition = lcl_getSubComponentDef_nothrow( m_xDocumentUI, m_eType, i_rComponentName );
+ xSubComponent.set( m_xDocumentUI->loadComponentWithArguments(
+ m_eType,
+ i_rComponentName,
+ i_bForEditing,
+ aLoadArgs.getPropertyValues()
+ ),
+ UNO_SET_THROW
+ );
+ }
+ else
+ {
+ Reference< XComponent > xDocDefComponent;
+ xSubComponent.set( m_xDocumentUI->createComponentWithArguments(
+ m_eType,
+ aLoadArgs.getPropertyValues(),
+ xDocDefComponent
+ ),
+ UNO_SET_THROW
+ );
+
+ xDocDefinition.set( xDocDefComponent, UNO_QUERY );
+ OSL_ENSURE( xDocDefinition.is(), "DatabaseDocumentRecovery::recoverSubDocuments: loaded a form/report, but don't have a document definition?!" );
+ }
+
+ if ( xDocDefinition.is() )
+ {
+ Reference< XController > xController( m_xDocumentUI, UNO_QUERY_THROW );
+ rtl::Reference( new SubComponentLoader( xController, xDocDefinition ) );
+ }
+
+ return xSubComponent;
+ }
+
+ Reference< XComponent > SubComponentRecovery::impl_recoverQueryDesign_throw( const Reference< XStorage >& i_rRecoveryStorage,
+ const OUString& i_rComponentName, const bool i_bForEditing )
+ {
+ Reference< XComponent > xSubComponent;
+
+ // first read the settings query design settings from the storage
+ StorageXMLInputStream aDesignInput( m_rContext, i_rRecoveryStorage, sSettingsStreamName );
+
+ ::rtl::Reference< SettingsDocumentHandler > pDocHandler( new SettingsDocumentHandler );
+ aDesignInput.import( pDocHandler );
+
+ const ::comphelper::NamedValueCollection& rSettings( pDocHandler->getSettings() );
+ const Any& aCurrentQueryDesign = rSettings.get( sCurrentQueryDesignName );
+#if OSL_DEBUG_LEVEL > 0
+ Sequence< PropertyValue > aQueryDesignLayout;
+ OSL_VERIFY( aCurrentQueryDesign >>= aQueryDesignLayout );
+#endif
+
+ // then load the query designer
+ ::comphelper::NamedValueCollection aLoadArgs;
+ aLoadArgs.put( "CurrentQueryDesign", aCurrentQueryDesign );
+ aLoadArgs.put( "Hidden", true );
+
+ if ( !i_rComponentName.isEmpty() )
+ {
+ xSubComponent.set( m_xDocumentUI->loadComponentWithArguments(
+ m_eType,
+ i_rComponentName,
+ i_bForEditing,
+ aLoadArgs.getPropertyValues()
+ ),
+ UNO_SET_THROW
+ );
+ }
+ else
+ {
+ Reference< XComponent > xDummy;
+ xSubComponent.set( m_xDocumentUI->createComponentWithArguments(
+ m_eType,
+ aLoadArgs.getPropertyValues(),
+ xDummy
+ ),
+ UNO_SET_THROW
+ );
+ }
+
+ Reference< XController > xController( m_xDocumentUI, UNO_QUERY_THROW );
+ rtl::Reference( new SubComponentLoader( xController, xSubComponent ) );
+
+ return xSubComponent;
+ }
+
+ Reference< XComponent > SubComponentRecovery::recoverFromStorage( const Reference< XStorage >& i_rRecoveryStorage,
+ const OUString& i_rComponentName, const bool i_bForEditing )
+ {
+ Reference< XComponent > xSubComponent;
+ switch ( m_eType )
+ {
+ case FORM:
+ case REPORT:
+ xSubComponent = impl_recoverSubDocument_throw( i_rRecoveryStorage, i_rComponentName, i_bForEditing );
+ break;
+ case QUERY:
+ xSubComponent = impl_recoverQueryDesign_throw( i_rRecoveryStorage, i_rComponentName, i_bForEditing );
+ break;
+ default:
+ OSL_FAIL( "SubComponentRecovery::recoverFromStorage: unimplemented case!" );
+ break;
+ }
+ return xSubComponent;
+ }
+
+} // namespace dbaccess
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/recovery/subcomponentrecovery.hxx b/dbaccess/source/core/recovery/subcomponentrecovery.hxx
new file mode 100644
index 000000000..26b81c63f
--- /dev/null
+++ b/dbaccess/source/core/recovery/subcomponentrecovery.hxx
@@ -0,0 +1,114 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include "subcomponents.hxx"
+
+#include <com/sun/star/sdb/application/XDatabaseDocumentUI.hpp>
+#include <com/sun/star/embed/XStorage.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+
+namespace dbaccess
+{
+
+ // SubComponentRecovery
+ class SubComponentRecovery
+ {
+ public:
+ SubComponentRecovery(
+ const css::uno::Reference< css::uno::XComponentContext >& i_rContext,
+ const css::uno::Reference< css::sdb::application::XDatabaseDocumentUI >& i_rController,
+ const css::uno::Reference< css::lang::XComponent >& i_rComponent )
+ :m_rContext( i_rContext )
+ ,m_xDocumentUI( i_rController, css::uno::UNO_SET_THROW )
+ ,m_xComponent( i_rComponent )
+ ,m_eType( UNKNOWN )
+ ,m_aCompDesc()
+ {
+ impl_identifyComponent_throw();
+ }
+
+ SubComponentRecovery(
+ const css::uno::Reference< css::uno::XComponentContext >& i_rContext,
+ const css::uno::Reference< css::sdb::application::XDatabaseDocumentUI >& i_rController,
+ const SubComponentType i_eType )
+ :m_rContext( i_rContext )
+ ,m_xDocumentUI( i_rController, css::uno::UNO_SET_THROW )
+ ,m_xComponent()
+ ,m_eType( i_eType )
+ ,m_aCompDesc()
+ {
+ }
+
+ // only to be used after being constructed with a component
+ void saveToRecoveryStorage(
+ const css::uno::Reference< css::embed::XStorage >& i_rRecoveryStorage,
+ MapCompTypeToCompDescs& io_mapCompDescs
+ );
+
+ // only to be used after being constructed with a type
+ css::uno::Reference< css::lang::XComponent >
+ recoverFromStorage(
+ const css::uno::Reference< css::embed::XStorage >& i_rRecoveryStorage,
+ const OUString& i_rComponentName,
+ const bool i_bForEditing
+ );
+
+ static OUString getComponentsStorageName( const SubComponentType i_eType );
+
+ private:
+ void impl_saveSubDocument_throw(
+ const css::uno::Reference< css::embed::XStorage >& i_rObjectStorage
+ );
+
+ void impl_saveQueryDesign_throw(
+ const css::uno::Reference< css::embed::XStorage >& i_rObjectStorage
+ );
+
+ css::uno::Reference< css::lang::XComponent >
+ impl_recoverSubDocument_throw(
+ const css::uno::Reference< css::embed::XStorage >& i_rRecoveryStorage,
+ const OUString& i_rComponentName,
+ const bool i_bForEditing
+ );
+
+ css::uno::Reference< css::lang::XComponent >
+ impl_recoverQueryDesign_throw(
+ const css::uno::Reference< css::embed::XStorage >& i_rRecoveryStorage,
+ const OUString& i_rComponentName,
+ const bool i_bForEditing
+ );
+
+ void impl_identifyComponent_throw();
+
+ private:
+ const css::uno::Reference< css::uno::XComponentContext >&
+ m_rContext;
+ css::uno::Reference< css::sdb::application::XDatabaseDocumentUI >
+ m_xDocumentUI;
+ const css::uno::Reference< css::lang::XComponent >
+ m_xComponent;
+ SubComponentType m_eType;
+ SubComponentDescriptor m_aCompDesc;
+ };
+
+} // namespace dbaccess
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/recovery/subcomponents.hxx b/dbaccess/source/core/recovery/subcomponents.hxx
new file mode 100644
index 000000000..5e4173605
--- /dev/null
+++ b/dbaccess/source/core/recovery/subcomponents.hxx
@@ -0,0 +1,61 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <com/sun/star/sdb/application/DatabaseObject.hpp>
+
+#include <rtl/ustring.hxx>
+
+#include <map>
+#include <unordered_map>
+
+namespace dbaccess
+{
+
+ enum SubComponentType
+ {
+ TABLE = css::sdb::application::DatabaseObject::TABLE,
+ QUERY = css::sdb::application::DatabaseObject::QUERY,
+ FORM = css::sdb::application::DatabaseObject::FORM,
+ REPORT = css::sdb::application::DatabaseObject::REPORT,
+
+ RELATION_DESIGN = 1000,
+
+ UNKNOWN = 10001
+ };
+
+ struct SubComponentDescriptor
+ {
+ OUString sName;
+ bool bForEditing;
+
+ SubComponentDescriptor()
+ :sName()
+ ,bForEditing( false )
+ {
+ }
+ };
+
+ typedef std::unordered_map< OUString, SubComponentDescriptor > MapStringToCompDesc;
+ typedef std::map< SubComponentType, MapStringToCompDesc > MapCompTypeToCompDescs;
+
+} // namespace dbaccess
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/resource/core_resource.cxx b/dbaccess/source/core/resource/core_resource.cxx
new file mode 100644
index 000000000..fdef07e1f
--- /dev/null
+++ b/dbaccess/source/core/resource/core_resource.cxx
@@ -0,0 +1,41 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <core_resource.hxx>
+
+#include <unotools/resmgr.hxx>
+
+namespace dbaccess
+{
+ OUString ResourceManager::loadString(TranslateId pResId)
+ {
+ return Translate::get(pResId, Translate::Create("dba"));
+ }
+
+ OUString ResourceManager::loadString(TranslateId pResId, const char* _pPlaceholderAscii1, std::u16string_view _rReplace1,
+ const char* _pPlaceholderAscii2, std::u16string_view _rReplace2)
+ {
+ OUString sString(loadString(pResId));
+ sString = sString.replaceFirst( OUString::createFromAscii(_pPlaceholderAscii1), _rReplace1 );
+ sString = sString.replaceFirst( OUString::createFromAscii(_pPlaceholderAscii2), _rReplace2 );
+ return sString;
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/filter/hsqldb/alterparser.cxx b/dbaccess/source/filter/hsqldb/alterparser.cxx
new file mode 100644
index 000000000..1dd770b1f
--- /dev/null
+++ b/dbaccess/source/filter/hsqldb/alterparser.cxx
@@ -0,0 +1,56 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <comphelper/string.hxx>
+#include <sal/log.hxx>
+#include "alterparser.hxx"
+#include "utils.hxx"
+
+namespace dbahsql
+{
+void AlterStmtParser::parse(const OUString& sSql)
+{
+ m_sStmt = sSql;
+ if (!sSql.startsWith("ALTER"))
+ {
+ SAL_WARN("dbaccess", "Not an ALTER statement");
+ return;
+ }
+
+ m_sTableName = utils::getTableNameFromStmt(sSql);
+ auto words = comphelper::string::split(sSql, sal_Unicode(u' '));
+
+ if (words[3] == "ALTER" && words[4] == "COLUMN")
+ {
+ m_sColumnName = words[5];
+ if (words[6] == "RESTART" && words[7] == "WITH")
+ {
+ m_eAction = AlterAction::IDENTITY_RESTART;
+ m_nIdentityParam = words[8].toInt32();
+ }
+ }
+ else if (words[3] == "ADD" && words[4] == "CONSTRAINT")
+ {
+ m_eAction = AlterAction::ADD_FOREIGN;
+ }
+}
+
+} // namespace dbahsql
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/filter/hsqldb/alterparser.hxx b/dbaccess/source/filter/hsqldb/alterparser.hxx
new file mode 100644
index 000000000..813ca7b0b
--- /dev/null
+++ b/dbaccess/source/filter/hsqldb/alterparser.hxx
@@ -0,0 +1,52 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+#include <rtl/ustring.hxx>
+
+namespace dbahsql
+{
+enum class AlterAction
+{
+ UNKNOWN,
+ ADD_FOREIGN,
+ IDENTITY_RESTART
+};
+
+class AlterStmtParser
+{
+private:
+ OUString m_sStmt;
+ OUString m_sTableName;
+ OUString m_sColumnName;
+ AlterAction m_eAction = AlterAction::UNKNOWN;
+ sal_Int32 m_nIdentityParam = 0;
+
+protected:
+ AlterAction getActionType() const { return m_eAction; }
+ OUString const& getColumnName() const { return m_sColumnName; }
+ sal_Int32 getIdentityParam() const { return m_nIdentityParam; }
+ OUString const& getStatement() const { return m_sStmt; }
+
+public:
+ virtual ~AlterStmtParser() = default;
+
+ /**
+ * @return name of the table which is to be created.
+ */
+ OUString const& getTableName() const { return m_sTableName; }
+
+ void parse(const OUString& sSql);
+
+ virtual OUString compose() const = 0;
+};
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/filter/hsqldb/columndef.cxx b/dbaccess/source/filter/hsqldb/columndef.cxx
new file mode 100644
index 000000000..5a7b74108
--- /dev/null
+++ b/dbaccess/source/filter/hsqldb/columndef.cxx
@@ -0,0 +1,44 @@
+
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "columndef.hxx"
+#include <com/sun/star/sdbc/DataType.hpp>
+
+namespace dbahsql
+{
+using namespace css::sdbc;
+
+ColumnDefinition::ColumnDefinition(const OUString& sName, sal_Int32 eType,
+ std::vector<sal_Int32>&& aParams, bool bPrimary,
+ sal_Int32 nAutoIncr, bool bNullable, bool bCaseInsensitive,
+ const OUString& sDefault)
+ : m_sName(sName)
+ , m_eType(eType)
+ , m_aParams(std::move(aParams))
+ , m_bPrimaryKey(bPrimary)
+ , m_nAutoIncrement(nAutoIncr)
+ , m_bNullable(bNullable)
+ , m_bCaseInsensitive(bCaseInsensitive)
+ , m_sDefaultValue(sDefault)
+{
+}
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/filter/hsqldb/columndef.hxx b/dbaccess/source/filter/hsqldb/columndef.hxx
new file mode 100644
index 000000000..5ffa18ba5
--- /dev/null
+++ b/dbaccess/source/filter/hsqldb/columndef.hxx
@@ -0,0 +1,47 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+#include <rtl/ustring.hxx>
+#include <vector>
+
+namespace dbahsql
+{
+/// nAutoIncrement: column is auto incremented started with value nAutoIncrement
+class ColumnDefinition
+{
+private:
+ OUString m_sName;
+ sal_Int32 m_eType; // css::sdbc::DataType
+ std::vector<sal_Int32> m_aParams;
+ bool m_bPrimaryKey;
+ sal_Int32 m_nAutoIncrement;
+ bool m_bNullable;
+ bool m_bCaseInsensitive;
+ OUString m_sDefaultValue;
+
+public:
+ ColumnDefinition(const OUString& sName, sal_Int32 eType, std::vector<sal_Int32>&& aParams,
+ bool bPrimary = false, sal_Int32 nAutoIncr = -1, bool bNullable = true,
+ bool bCaseInsensitive = false, const OUString& sDefault = OUString{});
+
+ OUString const& getName() const { return m_sName; }
+ sal_Int32 getDataType() const { return m_eType; }
+ bool isPrimaryKey() const { return m_bPrimaryKey; }
+ bool isNullable() const { return m_bNullable; }
+ bool isAutoIncremental() const { return m_nAutoIncrement >= 0; }
+ bool isCaseInsensitive() const { return m_bCaseInsensitive; }
+ sal_Int32 getStartValue() const { return m_nAutoIncrement; }
+ const std::vector<sal_Int32>& getParams() const { return m_aParams; }
+ OUString const& getDefault() const { return m_sDefaultValue; }
+};
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/filter/hsqldb/createparser.cxx b/dbaccess/source/filter/hsqldb/createparser.cxx
new file mode 100644
index 000000000..360741ce0
--- /dev/null
+++ b/dbaccess/source/filter/hsqldb/createparser.cxx
@@ -0,0 +1,298 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <comphelper/string.hxx>
+#include <sal/log.hxx>
+#include <o3tl/string_view.hxx>
+#include "createparser.hxx"
+#include "utils.hxx"
+#include <com/sun/star/sdbc/DataType.hpp>
+
+using namespace ::comphelper;
+using namespace css::sdbc;
+
+namespace
+{
+/// Returns substring of sSql from the first occurrence of '(' until the
+/// last occurrence of ')' (excluding the parenthesis)
+std::u16string_view lcl_getColumnPart(std::u16string_view sSql)
+{
+ size_t nBeginIndex = sSql.find('(');
+ if (nBeginIndex == std::u16string_view::npos)
+ {
+ SAL_WARN("dbaccess", "No column definitions found");
+ return std::u16string_view();
+ }
+ sal_Int32 nCount = sSql.rfind(')') - nBeginIndex - 1;
+ auto sPart = sSql.substr(nBeginIndex + 1, nCount);
+ return sPart;
+}
+
+/// Constructs a vector of strings that represents the definitions of each
+/// column or constraint.
+///
+/// @param sColumnPart part of the create statement inside the parenthesis
+/// containing the column definitions
+std::vector<OUString> lcl_splitColumnPart(std::u16string_view sColumnPart)
+{
+ std::vector<OUString> sParts = string::split(sColumnPart, sal_Unicode(u','));
+ std::vector<OUString> sReturn;
+
+ OUStringBuffer current(128);
+ for (auto const& part : sParts)
+ {
+ current.append(part);
+ if (current.lastIndexOf("(") > current.lastIndexOf(")"))
+ current.append(","); // it was false split
+ else
+ {
+ sReturn.push_back(current.toString());
+ current.setLength(0);
+ }
+ }
+ return sReturn;
+}
+
+sal_Int32 lcl_getAutoIncrementDefault(std::u16string_view sColumnDef)
+{
+ // TODO what if there are more spaces?
+ size_t nPos = sColumnDef.find(u"GENERATED BY DEFAULT AS IDENTITY");
+ if (nPos != std::u16string_view::npos && nPos > 0)
+ {
+ // TODO parse starting sequence stated by "START WITH"
+ return 0;
+ }
+ return -1;
+}
+
+std::u16string_view lcl_getDefaultValue(std::u16string_view sColumnDef)
+{
+ constexpr std::u16string_view DEFAULT_KW = u"DEFAULT";
+ size_t nDefPos = sColumnDef.find(DEFAULT_KW);
+ if (nDefPos > 0 && nDefPos != std::u16string_view::npos
+ && lcl_getAutoIncrementDefault(sColumnDef) < 0)
+ {
+ std::u16string_view fromDefault
+ = o3tl::trim(sColumnDef.substr(nDefPos + DEFAULT_KW.size()));
+
+ // next word is the value
+ size_t nNextSpace = fromDefault.find(' ');
+ return (nNextSpace > 0 && nNextSpace != std::u16string_view::npos)
+ ? fromDefault.substr(0, nNextSpace)
+ : fromDefault;
+ }
+ return std::u16string_view();
+}
+
+bool lcl_isNullable(std::u16string_view sColumnDef)
+{
+ return sColumnDef.find(u"NOT NULL") == std::u16string_view::npos;
+}
+
+bool lcl_isPrimaryKey(std::u16string_view sColumnDef)
+{
+ return sColumnDef.find(u"PRIMARY KEY") != std::u16string_view::npos;
+}
+
+sal_Int32 lcl_getDataTypeFromHsql(std::u16string_view sTypeName)
+{
+ if (sTypeName == u"CHAR")
+ return DataType::CHAR;
+ else if (sTypeName == u"VARCHAR" || sTypeName == u"VARCHAR_IGNORECASE")
+ return DataType::VARCHAR;
+ else if (sTypeName == u"TINYINT")
+ return DataType::TINYINT;
+ else if (sTypeName == u"SMALLINT")
+ return DataType::SMALLINT;
+ else if (sTypeName == u"INTEGER")
+ return DataType::INTEGER;
+ else if (sTypeName == u"BIGINT")
+ return DataType::BIGINT;
+ else if (sTypeName == u"NUMERIC")
+ return DataType::NUMERIC;
+ else if (sTypeName == u"DECIMAL")
+ return DataType::DECIMAL;
+ else if (sTypeName == u"BOOLEAN")
+ return DataType::BOOLEAN;
+ else if (sTypeName == u"LONGVARCHAR")
+ return DataType::LONGVARCHAR;
+ else if (sTypeName == u"LONGVARBINARY")
+ return DataType::LONGVARBINARY;
+ else if (sTypeName == u"CLOB")
+ return DataType::CLOB;
+ else if (sTypeName == u"BLOB")
+ return DataType::BLOB;
+ else if (sTypeName == u"BINARY")
+ return DataType::BINARY;
+ else if (sTypeName == u"VARBINARY")
+ return DataType::VARBINARY;
+ else if (sTypeName == u"DATE")
+ return DataType::DATE;
+ else if (sTypeName == u"TIME")
+ return DataType::TIME;
+ else if (sTypeName == u"TIMESTAMP")
+ return DataType::TIMESTAMP;
+ else if (sTypeName == u"DOUBLE")
+ return DataType::DOUBLE;
+ else if (sTypeName == u"REAL")
+ return DataType::REAL;
+ else if (sTypeName == u"FLOAT")
+ return DataType::FLOAT;
+
+ assert(false);
+ return -1;
+}
+
+void lcl_addDefaultParameters(std::vector<sal_Int32>& aParams, sal_Int32 eType)
+{
+ if (eType == DataType::CHAR || eType == DataType::BINARY || eType == DataType::VARBINARY
+ || eType == DataType::VARCHAR)
+ aParams.push_back(8000); // from SQL standard
+}
+
+struct ColumnTypeParts
+{
+ OUString typeName;
+ std::vector<sal_Int32> params;
+};
+
+/**
+ * Separates full type descriptions (e.g. NUMERIC(5,4)) to type name (NUMERIC) and
+ * parameters (5,4)
+ */
+ColumnTypeParts lcl_getColumnTypeParts(std::u16string_view sFullTypeName)
+{
+ ColumnTypeParts parts;
+ auto nParenPos = sFullTypeName.find('(');
+ if (nParenPos > 0 && nParenPos != std::u16string_view::npos)
+ {
+ parts.typeName = o3tl::trim(sFullTypeName.substr(0, nParenPos));
+ std::u16string_view sParamStr
+ = sFullTypeName.substr(nParenPos + 1, sFullTypeName.find(')') - nParenPos - 1);
+ auto sParams = string::split(sParamStr, sal_Unicode(u','));
+ for (const auto& sParam : sParams)
+ {
+ parts.params.push_back(sParam.toInt32());
+ }
+ }
+ else
+ {
+ parts.typeName = o3tl::trim(sFullTypeName);
+ lcl_addDefaultParameters(parts.params, lcl_getDataTypeFromHsql(parts.typeName));
+ }
+ return parts;
+}
+
+} // unnamed namespace
+
+namespace dbahsql
+{
+CreateStmtParser::CreateStmtParser() {}
+
+void CreateStmtParser::parsePrimaryKeys(std::u16string_view sPrimaryPart)
+{
+ size_t nParenPos = sPrimaryPart.find('(');
+ if (nParenPos > 0 && nParenPos != std::u16string_view::npos)
+ {
+ std::u16string_view sParamStr
+ = sPrimaryPart.substr(nParenPos + 1, sPrimaryPart.rfind(')') - nParenPos - 1);
+ auto sParams = string::split(sParamStr, sal_Unicode(u','));
+ for (const auto& sParam : sParams)
+ {
+ m_PrimaryKeys.push_back(sParam);
+ }
+ }
+}
+
+void CreateStmtParser::parseColumnPart(std::u16string_view sColumnPart)
+{
+ auto sColumns = lcl_splitColumnPart(sColumnPart);
+ for (const OUString& sColumn : sColumns)
+ {
+ if (sColumn.startsWithIgnoreAsciiCase("PRIMARY KEY"))
+ {
+ parsePrimaryKeys(sColumn);
+ continue;
+ }
+
+ if (sColumn.startsWithIgnoreAsciiCase("CONSTRAINT"))
+ {
+ m_aForeignParts.push_back(sColumn);
+ continue;
+ }
+
+ bool bIsQuoteUsedForColumnName(sColumn[0] == '\"');
+
+ // find next quote after the initial quote
+ // or next space if quote isn't used as delimiter
+ auto nEndColumnName
+ = bIsQuoteUsedForColumnName ? sColumn.indexOf("\"", 1) + 1 : sColumn.indexOf(" ");
+ OUString rColumnName = sColumn.copy(0, nEndColumnName);
+
+ const OUString sFromTypeName(o3tl::trim(sColumn.subView(nEndColumnName)));
+
+ // Now let's manage the column type
+ // search next space to get the whole type name
+ // eg: INTEGER, VARCHAR(10), DECIMAL(6,3)
+ auto nNextSpace = sFromTypeName.indexOf(" ");
+ std::u16string_view sFullTypeName;
+ if (nNextSpace > 0)
+ sFullTypeName = sFromTypeName.subView(0, nNextSpace);
+ // perhaps column type corresponds to the last info here
+ else
+ sFullTypeName = sFromTypeName;
+
+ ColumnTypeParts typeParts = lcl_getColumnTypeParts(sFullTypeName);
+
+ bool bCaseInsensitive = typeParts.typeName.indexOf("IGNORECASE") >= 0;
+ bool isPrimaryKey = lcl_isPrimaryKey(sColumn);
+
+ if (isPrimaryKey)
+ m_PrimaryKeys.push_back(rColumnName);
+
+ const std::u16string_view sColumnWithoutName
+ = sColumn.subView(sColumn.indexOf(typeParts.typeName));
+
+ ColumnDefinition aColDef(rColumnName, lcl_getDataTypeFromHsql(typeParts.typeName),
+ std::move(typeParts.params), isPrimaryKey,
+ lcl_getAutoIncrementDefault(sColumnWithoutName),
+ lcl_isNullable(sColumnWithoutName), bCaseInsensitive,
+ OUString(lcl_getDefaultValue(sColumnWithoutName)));
+
+ m_aColumns.push_back(aColDef);
+ }
+}
+
+void CreateStmtParser::parse(std::u16string_view sSql)
+{
+ // TODO Foreign keys
+ if (!o3tl::starts_with(sSql, u"CREATE"))
+ {
+ SAL_WARN("dbaccess", "Not a create statement");
+ return;
+ }
+
+ m_sTableName = utils::getTableNameFromStmt(sSql);
+ std::u16string_view sColumnPart = lcl_getColumnPart(sSql);
+ parseColumnPart(sColumnPart);
+}
+
+} // namespace dbahsql
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/filter/hsqldb/createparser.hxx b/dbaccess/source/filter/hsqldb/createparser.hxx
new file mode 100644
index 000000000..a92f74586
--- /dev/null
+++ b/dbaccess/source/filter/hsqldb/createparser.hxx
@@ -0,0 +1,68 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+#include <vector>
+#include "columndef.hxx"
+
+namespace dbahsql
+{
+class SAL_DLLPUBLIC_EXPORT CreateStmtParser
+{
+private:
+ std::vector<ColumnDefinition> m_aColumns;
+ std::vector<OUString> m_aForeignParts;
+ std::vector<OUString> m_PrimaryKeys;
+ OUString m_sTableName;
+
+protected:
+ void parseColumnPart(std::u16string_view sColumnPart);
+ void parsePrimaryKeys(std::u16string_view sPrimaryPart);
+
+public:
+ CreateStmtParser();
+ virtual ~CreateStmtParser() {}
+
+ /**
+ * @return name of the table which is to be created.
+ */
+ OUString const& getTableName() const { return m_sTableName; }
+
+ /**
+ * @return primary keys of parsed table.
+ */
+ std::vector<OUString> const& getPrimaryKeys() const { return m_PrimaryKeys; }
+
+ /**
+ * @return a vector of column descriptors, representing the columns of the
+ * parsed statement.
+ */
+ const std::vector<ColumnDefinition>& getColumnDef() const { return m_aColumns; }
+
+ /**
+ * @return a vector of words.
+ */
+ const std::vector<OUString>& getForeignParts() const { return m_aForeignParts; }
+
+ /**
+ * Parses a create statement.
+ *
+ * @param SQL "CREATE" statement
+ */
+ void parse(std::u16string_view sSql);
+
+ /**
+ * Recreate the sql statement.
+ */
+ virtual OUString compose() const = 0;
+};
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/filter/hsqldb/fbalterparser.cxx b/dbaccess/source/filter/hsqldb/fbalterparser.cxx
new file mode 100644
index 000000000..024598c0b
--- /dev/null
+++ b/dbaccess/source/filter/hsqldb/fbalterparser.cxx
@@ -0,0 +1,53 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "fbalterparser.hxx"
+#include <rtl/ustrbuf.hxx>
+#include <sal/log.hxx>
+
+namespace dbahsql
+{
+OUString FbAlterStmtParser::compose() const
+{
+ if (getActionType() == AlterAction::UNKNOWN)
+ {
+ SAL_WARN("dbaccess", "Unknown type of ALTER statement in FbAlterStmtParser");
+ return OUString{};
+ }
+ else if (getActionType() == AlterAction::ADD_FOREIGN)
+ return getStatement(); // do nothing with that
+ OUStringBuffer sSql("ALTER TABLE ");
+ sSql.append(getTableName());
+
+ if (getActionType() == AlterAction::IDENTITY_RESTART)
+ {
+ sSql.append(" ALTER COLUMN ");
+ }
+ sSql.append(getColumnName());
+ sSql.append(" RESTART WITH ");
+
+ // Firebird: restart with 0 means the first number is 1, not 0.
+ sSql.append(getIdentityParam() - 1);
+
+ return sSql.makeStringAndClear();
+}
+
+} // dbahsql
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/filter/hsqldb/fbalterparser.hxx b/dbaccess/source/filter/hsqldb/fbalterparser.hxx
new file mode 100644
index 000000000..cd48d94d5
--- /dev/null
+++ b/dbaccess/source/filter/hsqldb/fbalterparser.hxx
@@ -0,0 +1,30 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+#include "alterparser.hxx"
+
+namespace dbahsql
+{
+class FbAlterStmtParser : public AlterStmtParser
+{
+protected:
+ void ensureProperTableLengths() const;
+
+public:
+ /**
+ * Compose the result of the parser to statements of Firebird dialect
+ */
+ virtual OUString compose() const override;
+};
+
+} // dbahsql
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/filter/hsqldb/fbcreateparser.cxx b/dbaccess/source/filter/hsqldb/fbcreateparser.cxx
new file mode 100644
index 000000000..f3399474c
--- /dev/null
+++ b/dbaccess/source/filter/hsqldb/fbcreateparser.cxx
@@ -0,0 +1,218 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "fbcreateparser.hxx"
+#include "columndef.hxx"
+#include "utils.hxx"
+
+#include <com/sun/star/sdbc/DataType.hpp>
+
+#include <rtl/ustrbuf.hxx>
+
+using namespace css::sdbc;
+
+namespace
+{
+void lcl_appendWithSpace(OUStringBuffer& sBuff, std::u16string_view sStr)
+{
+ sBuff.append(" ");
+ sBuff.append(sStr);
+}
+
+OUString lcl_DataTypetoFbTypeName(sal_Int32 eType)
+{
+ switch (eType)
+ {
+ case DataType::CHAR:
+ case DataType::BINARY:
+ return "CHAR";
+ case DataType::VARCHAR:
+ case DataType::VARBINARY:
+ return "VARCHAR";
+ case DataType::TINYINT: // no such type in Firebird
+ case DataType::SMALLINT:
+ return "SMALLINT";
+ case DataType::INTEGER:
+ return "INTEGER";
+ case DataType::BIGINT:
+ return "BIGINT";
+ case DataType::NUMERIC:
+ return "NUMERIC";
+ case DataType::DECIMAL:
+ return "DECIMAL";
+ case DataType::BOOLEAN:
+ return "BOOLEAN";
+ case DataType::LONGVARCHAR:
+ case DataType::LONGVARBINARY:
+ case DataType::CLOB:
+ case DataType::BLOB:
+ case DataType::OTHER:
+ return "BLOB";
+ case DataType::DATE:
+ return "DATE";
+ case DataType::TIME:
+ return "TIME";
+ case DataType::TIMESTAMP:
+ return "TIMESTAMP";
+ case DataType::DOUBLE:
+ case DataType::REAL:
+ return "DOUBLE PRECISION";
+ case DataType::FLOAT:
+ return "FLOAT";
+ default:
+ assert(false);
+ return OUString();
+ }
+}
+
+OUString lcl_getTypeModifier(sal_Int32 eType)
+{
+ // TODO bind -9546 magic number to a common definition. It also appears
+ // in the connectivity module.
+ switch (eType)
+ {
+ case DataType::CLOB:
+ case DataType::LONGVARCHAR:
+ return "SUB_TYPE 1";
+ case DataType::LONGVARBINARY:
+ return "SUB_TYPE -9546";
+ case DataType::BINARY:
+ case DataType::VARBINARY:
+ return "CHARACTER SET OCTETS";
+ default:
+ return OUString();
+ }
+}
+
+} // unnamed namespace
+
+namespace dbahsql
+{
+void FbCreateStmtParser::appendPrimaryKeyPart(OUStringBuffer& rSql) const
+{
+ const std::vector<OUString>& sPrimaryKeys = getPrimaryKeys();
+ if (sPrimaryKeys.empty())
+ return; // no primary key specified
+
+ rSql.append(",");
+ rSql.append("PRIMARY KEY(");
+ auto it = sPrimaryKeys.cbegin();
+ while (it != sPrimaryKeys.end())
+ {
+ rSql.append(*it);
+ ++it;
+ if (it != sPrimaryKeys.end())
+ rSql.append(",");
+ }
+
+ rSql.append(")"); // end of primary key declaration
+}
+
+void FbCreateStmtParser::ensureProperTableLengths() const
+{
+ const std::vector<ColumnDefinition>& rColumns = getColumnDef();
+ for (const auto& col : rColumns)
+ utils::ensureFirebirdTableLength(col.getName());
+}
+
+OUString FbCreateStmtParser::compose() const
+{
+ ensureProperTableLengths();
+ OUStringBuffer sSql(128);
+ sSql.append("CREATE TABLE ");
+ sSql.append(getTableName());
+
+ lcl_appendWithSpace(sSql, u"("); // column declaration
+ auto& rColumns = getColumnDef();
+ auto columnIter = rColumns.cbegin();
+ while (columnIter != rColumns.end())
+ {
+ lcl_appendWithSpace(sSql, columnIter->getName());
+ lcl_appendWithSpace(sSql, lcl_DataTypetoFbTypeName(columnIter->getDataType()));
+
+ std::vector<sal_Int32> params{ columnIter->getParams() };
+
+ if (columnIter->getDataType() == DataType::NUMERIC
+ || columnIter->getDataType() == DataType::DECIMAL)
+ {
+ // max precision is 18 here
+ if (params.at(0) > 18)
+ params[0] = 18;
+ }
+
+ // Firebird SQL dialect does not like parameters for TIMESTAMP
+ if (!params.empty() && columnIter->getDataType() != DataType::TIMESTAMP)
+ {
+ sSql.append("(");
+ auto it = params.cbegin();
+ while (it != params.end())
+ {
+ sSql.append(*it);
+ ++it;
+ if (it != params.end())
+ sSql.append(",");
+ }
+ sSql.append(")"); // end of param declaration
+ }
+
+ // special modifiers here, based on type (e.g. charset, subtype)
+ OUString sModifier = lcl_getTypeModifier(columnIter->getDataType());
+ if (!sModifier.isEmpty())
+ lcl_appendWithSpace(sSql, sModifier);
+
+ if (columnIter->isAutoIncremental())
+ {
+ lcl_appendWithSpace(sSql, u"GENERATED BY DEFAULT AS IDENTITY (START WITH ");
+
+ // start with 0:
+ // HSQLDB: first value will be 0.
+ // Firebird: first value will be 1.
+ sSql.append(columnIter->getStartValue() - 1);
+ sSql.append(")");
+ }
+ else if (!columnIter->isNullable())
+ lcl_appendWithSpace(sSql, u"NOT NULL");
+
+ if (columnIter->isCaseInsensitive())
+ lcl_appendWithSpace(sSql, u"COLLATE UNICODE_CI");
+
+ const OUString& sDefaultVal = columnIter->getDefault();
+ if (!sDefaultVal.isEmpty())
+ {
+ lcl_appendWithSpace(sSql, u"DEFAULT");
+ if (sDefaultVal.equalsIgnoreAsciiCase("NOW"))
+ lcl_appendWithSpace(sSql, u"\'NOW\'"); // Fb likes it single quoted
+ else
+ lcl_appendWithSpace(sSql, sDefaultVal);
+ }
+
+ ++columnIter;
+ if (columnIter != rColumns.end())
+ sSql.append(",");
+ }
+
+ appendPrimaryKeyPart(sSql);
+
+ sSql.append(")"); // end of column declaration
+ return sSql.makeStringAndClear();
+}
+
+} // dbahsql
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/filter/hsqldb/fbcreateparser.hxx b/dbaccess/source/filter/hsqldb/fbcreateparser.hxx
new file mode 100644
index 000000000..6706c05be
--- /dev/null
+++ b/dbaccess/source/filter/hsqldb/fbcreateparser.hxx
@@ -0,0 +1,37 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+#include "createparser.hxx"
+
+namespace dbahsql
+{
+class SAL_DLLPUBLIC_EXPORT FbCreateStmtParser : public CreateStmtParser
+{
+protected:
+ void ensureProperTableLengths() const;
+ void appendPrimaryKeyPart(rtl::OUStringBuffer& rSql) const;
+
+public:
+ /**
+ * Create statement parser, which can compose the result to statements of
+ * Firebird dialect.
+ */
+ FbCreateStmtParser() = default;
+
+ /**
+ * Compose the result of the parser to statements of Firebird dialect
+ */
+ virtual OUString compose() const override;
+};
+
+} // dbahsql
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/filter/hsqldb/hsqlbinarynode.cxx b/dbaccess/source/filter/hsqldb/hsqlbinarynode.cxx
new file mode 100644
index 000000000..c02da2c4b
--- /dev/null
+++ b/dbaccess/source/filter/hsqldb/hsqlbinarynode.cxx
@@ -0,0 +1,58 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "hsqlbinarynode.hxx"
+#include "rowinputbinary.hxx"
+
+namespace dbahsql
+{
+HsqlBinaryNode::HsqlBinaryNode(sal_Int32 nPos)
+ : m_nPos(nPos)
+{
+}
+
+void HsqlBinaryNode::readChildren(HsqlRowInputStream const& input)
+{
+ SvStream* pStream = input.getInputStream();
+ if (!pStream)
+ return;
+
+ pStream->Seek(m_nPos + 8); // skip size and balance
+ pStream->ReadInt32(m_nLeft);
+ if (m_nLeft <= 0)
+ m_nLeft = -1;
+ pStream->ReadInt32(m_nRight);
+ if (m_nRight <= 0)
+ m_nRight = -1;
+}
+
+std::vector<css::uno::Any> HsqlBinaryNode::readRow(HsqlRowInputStream& input,
+ const std::vector<ColumnDefinition>& aColTypes,
+ sal_Int32 nIndexCount)
+{
+ // skip first 4 bytes (size), and index nodes, 16 bytes each
+ input.seek(m_nPos + 4 + nIndexCount * 16);
+ return input.readOneRow(aColTypes);
+}
+
+sal_Int32 HsqlBinaryNode::getLeft() const { return m_nLeft; }
+sal_Int32 HsqlBinaryNode::getRight() const { return m_nRight; }
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/filter/hsqldb/hsqlbinarynode.hxx b/dbaccess/source/filter/hsqldb/hsqlbinarynode.hxx
new file mode 100644
index 000000000..97777e7d1
--- /dev/null
+++ b/dbaccess/source/filter/hsqldb/hsqlbinarynode.hxx
@@ -0,0 +1,63 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+#include <vector>
+
+#include "rowinputbinary.hxx"
+#include "columndef.hxx"
+
+namespace dbahsql
+{
+class HsqlBinaryNode
+{
+private:
+ sal_Int32 m_nLeft = -1;
+ sal_Int32 m_nRight = -1;
+ sal_Int32 m_nPos = -1;
+
+public:
+ /**
+ * Represents one element of an AVL tree in the binary file which contains
+ * the data.
+ */
+ HsqlBinaryNode(sal_Int32 nPos);
+
+ /**
+ * Read position of children from data file.
+ *
+ * @param rInput input stream where the positions should be read from.
+ */
+ void readChildren(HsqlRowInputStream const& rInput);
+
+ /**
+ * Get Position of left children. It should be called only after position of
+ * children is read.
+ */
+ sal_Int32 getLeft() const;
+
+ /**
+ * Get Position of right children. It should be called only after position of
+ * children is read.
+ */
+ sal_Int32 getRight() const;
+
+ /**
+ * Read the row represented by this node.
+ *
+ * @param rInput input stream where the row should be read from.
+ */
+ std::vector<css::uno::Any> readRow(HsqlRowInputStream& rInput,
+ const std::vector<ColumnDefinition>& aColTypes,
+ sal_Int32 nIndexCount);
+};
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/filter/hsqldb/hsqlimport.cxx b/dbaccess/source/filter/hsqldb/hsqlimport.cxx
new file mode 100644
index 000000000..045a32f93
--- /dev/null
+++ b/dbaccess/source/filter/hsqldb/hsqlimport.cxx
@@ -0,0 +1,388 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <com/sun/star/embed/XStorage.hpp>
+#include <com/sun/star/embed/ElementModes.hpp>
+#include <com/sun/star/io/XInputStream.hpp>
+#include <com/sun/star/io/WrongFormatException.hpp>
+#include <com/sun/star/util/Date.hpp>
+
+#include <com/sun/star/sdbc/XConnection.hpp>
+#include <com/sun/star/sdbc/XParameters.hpp>
+#include <com/sun/star/sdbc/DataType.hpp>
+#include <com/sun/star/sdbc/SQLException.hpp>
+
+#include <rtl/ustrbuf.hxx>
+#include <sal/log.hxx>
+#include <connectivity/dbtools.hxx>
+#include <connectivity/dbexception.hxx>
+#include <comphelper/processfactory.hxx>
+
+#include <vcl/weld.hxx>
+
+#include "hsqlimport.hxx"
+#include "parseschema.hxx"
+#include "rowinputbinary.hxx"
+
+namespace
+{
+using namespace css::io;
+using namespace css::uno;
+using namespace css::sdbc;
+
+void lcl_setParams(const std::vector<Any>& row, Reference<XParameters> const& xParam,
+ const std::vector<dbahsql::ColumnDefinition>& rColTypes)
+{
+ assert(row.size() == rColTypes.size());
+ size_t nColIndex = 0;
+ for (size_t i = 0; i < rColTypes.size(); ++i)
+ {
+ if (!row.at(i).hasValue())
+ xParam->setNull(i + 1, rColTypes.at(i).getDataType());
+
+ switch (rColTypes.at(i).getDataType())
+ {
+ case DataType::CHAR:
+ case DataType::VARCHAR:
+ case DataType::LONGVARCHAR:
+ {
+ OUString sVal;
+ if (row.at(i) >>= sVal)
+ {
+ xParam->setString(nColIndex + 1, sVal);
+ }
+ }
+ break;
+ case DataType::TINYINT:
+ case DataType::SMALLINT:
+ {
+ sal_Int16 nVal;
+ if (row.at(i) >>= nVal)
+ {
+ xParam->setShort(nColIndex + 1, nVal);
+ }
+ }
+ break;
+ case DataType::INTEGER:
+ {
+ sal_Int32 nVal;
+ if (row.at(i) >>= nVal)
+ {
+ xParam->setInt(nColIndex + 1, nVal);
+ }
+ }
+ break;
+ case DataType::BIGINT:
+ {
+ sal_Int64 nVal;
+ if (row.at(i) >>= nVal)
+ {
+ xParam->setLong(nColIndex + 1, nVal);
+ }
+ }
+ break;
+ case DataType::REAL:
+ case DataType::FLOAT:
+ case DataType::DOUBLE:
+ {
+ double nVal;
+ if (row.at(i) >>= nVal)
+ {
+ xParam->setDouble(nColIndex + 1, nVal);
+ }
+ }
+ break;
+ case DataType::NUMERIC:
+ case DataType::DECIMAL:
+ {
+ Sequence<Any> aNumeric;
+ if (row.at(i) >>= aNumeric)
+ {
+ sal_Int32 nScale = 0;
+ if (aNumeric[1] >>= nScale)
+ xParam->setObjectWithInfo(nColIndex + 1, aNumeric[0],
+ rColTypes.at(i).getDataType(), nScale);
+ }
+ }
+ break;
+ case DataType::DATE:
+ {
+ css::util::Date date;
+ if (row.at(i) >>= date)
+ {
+ xParam->setDate(nColIndex + 1, date);
+ }
+ }
+ break;
+ case DataType::TIME:
+ {
+ css::util::Time time;
+ if (row.at(i) >>= time)
+ {
+ xParam->setTime(nColIndex + 1, time);
+ }
+ }
+ break;
+ case DataType::TIMESTAMP:
+ {
+ css::util::DateTime dateTime;
+ if (row.at(i) >>= dateTime)
+ {
+ xParam->setTimestamp(nColIndex + 1, dateTime);
+ }
+ }
+ break;
+ case DataType::BOOLEAN:
+ {
+ bool bVal = false;
+ if (row.at(i) >>= bVal)
+ xParam->setBoolean(nColIndex + 1, bVal);
+ }
+ break;
+ case DataType::OTHER:
+ // TODO
+ break;
+ case DataType::BINARY:
+ case DataType::VARBINARY:
+ case DataType::LONGVARBINARY:
+ {
+ Sequence<sal_Int8> nVal;
+ if (row.at(i) >>= nVal)
+ {
+ xParam->setBytes(nColIndex + 1, nVal);
+ }
+ break;
+ }
+ default:
+ throw WrongFormatException();
+ }
+ ++nColIndex;
+ }
+}
+
+OUString lcl_createInsertStatement(std::u16string_view sTableName,
+ const std::vector<dbahsql::ColumnDefinition>& rColTypes)
+{
+ assert(rColTypes.size() > 0);
+ OUStringBuffer sql("INSERT INTO ");
+ sql.append(sTableName);
+ sql.append(" (");
+
+ // column names
+ for (size_t i = 0; i < rColTypes.size(); ++i)
+ {
+ sql.append(rColTypes.at(i).getName());
+ if (i < rColTypes.size() - 1)
+ sql.append(", ");
+ }
+ sql.append(")");
+
+ sql.append(" VALUES (");
+ for (size_t i = 0; i < rColTypes.size(); ++i)
+ {
+ sql.append("?");
+ if (i < rColTypes.size() - 1)
+ sql.append(", ");
+ }
+ sql.append(")");
+ return sql.makeStringAndClear();
+}
+
+} // unnamed namespace
+
+namespace dbahsql
+{
+using namespace css::embed;
+
+HsqlImporter::HsqlImporter(Reference<XConnection>& rConnection, const Reference<XStorage>& rStorage)
+ : m_rConnection(rConnection)
+{
+ m_xStorage.set(rStorage);
+}
+
+void HsqlImporter::insertRow(const std::vector<css::uno::Any>& xRows,
+ std::u16string_view sTableName,
+ const std::vector<ColumnDefinition>& rColTypes)
+{
+ OUString sStatement = lcl_createInsertStatement(sTableName, rColTypes);
+ Reference<XPreparedStatement> xStatement = m_rConnection->prepareStatement(sStatement);
+
+ Reference<XParameters> xParameter(xStatement, UNO_QUERY);
+ assert(xParameter.is());
+ xParameter->clearParameters();
+
+ lcl_setParams(xRows, xParameter, rColTypes);
+ xStatement->executeQuery();
+}
+
+void HsqlImporter::processTree(HsqlBinaryNode& rNode, HsqlRowInputStream& rStream,
+ const std::vector<ColumnDefinition>& rColTypes,
+ const OUString& sTableName, sal_Int32 nIndexCount)
+{
+ rNode.readChildren(rStream);
+ sal_Int32 nNext = rNode.getLeft();
+ if (nNext > 0)
+ {
+ HsqlBinaryNode aLeft{ nNext };
+ processTree(aLeft, rStream, rColTypes, sTableName, nIndexCount);
+ }
+ std::vector<Any> row = rNode.readRow(rStream, rColTypes, nIndexCount);
+ insertRow(row, sTableName, rColTypes);
+
+ nNext = rNode.getRight();
+ if (nNext > 0)
+ {
+ HsqlBinaryNode aRight{ nNext };
+ processTree(aRight, rStream, rColTypes, sTableName, nIndexCount);
+ }
+}
+
+/**
+ * Format from the indexed file position is the following:
+ * <Node x20><Row>
+ * Where Node is a 20 byte data, representing the rows in a binary tree:
+ * <Size x4><Balance x4><Left x4> <Right x4><Parent x4>
+ *
+ * Size is the size of <Row>;
+ * Balance: ?
+ * Left/Right/Parent: File position of the Left/Right/Parent child
+ */
+void HsqlImporter::parseTableRows(const std::vector<sal_Int32>& rIndexes,
+ const std::vector<ColumnDefinition>& rColTypes,
+ const OUString& sTableName)
+{
+ static constexpr OUStringLiteral BINARY_FILENAME = u"data";
+
+ if (!m_xStorage->hasByName(BINARY_FILENAME))
+ {
+ SAL_WARN("dbaccess", "data file does not exist in storage during hsqldb import");
+ assert(false); // TODO throw error
+ }
+
+ Reference<css::io::XStream> xStream(
+ m_xStorage->openStreamElement(BINARY_FILENAME, ElementModes::READ));
+
+ HsqlRowInputStream rowInput;
+ Reference<XInputStream> xInput = xStream->getInputStream();
+ rowInput.setInputStream(xInput);
+
+ if (!rIndexes.empty())
+ {
+ HsqlBinaryNode aPrimaryNode{ rIndexes.at(0) };
+ processTree(aPrimaryNode, rowInput, rColTypes, sTableName, rIndexes.size());
+ }
+
+ xInput->closeInput();
+}
+
+void HsqlImporter::importHsqlDatabase(weld::Window* pParent)
+{
+ assert(m_xStorage);
+
+ SchemaParser parser(m_xStorage);
+ std::unique_ptr<SQLException> pException;
+ try
+ {
+ parser.parseSchema();
+ }
+ catch (SQLException& ex)
+ {
+ pException.reset(new SQLException{ std::move(ex) });
+ }
+
+ auto statements = parser.getCreateStatements();
+
+ if (statements.empty() && !pException)
+ {
+ SAL_WARN("dbaccess", "dbashql: there is nothing to import");
+ return; // there is nothing to import
+ }
+
+ // schema
+ for (const auto& sSql : statements)
+ {
+ Reference<XStatement> statement = m_rConnection->createStatement();
+ try
+ {
+ statement->executeQuery(sSql);
+ }
+ catch (SQLException& ex)
+ {
+ // chain errors and keep going
+ if (pException)
+ ex.NextException <<= *pException;
+ pException.reset(new SQLException{ std::move(ex) });
+ }
+ }
+
+ // data
+ for (const auto& tableIndex : parser.getTableIndexes())
+ {
+ try
+ {
+ std::vector<ColumnDefinition> aColTypes = parser.getTableColumnTypes(tableIndex.first);
+ parseTableRows(tableIndex.second, aColTypes, tableIndex.first);
+ }
+ catch (const std::out_of_range& e)
+ {
+ std::unique_ptr<SQLException> ex(new SQLException);
+ const char* msg = e.what();
+ ex->SQLState = OUString(msg, strlen(msg), RTL_TEXTENCODING_ASCII_US);
+ // chain errors and keep going
+ if (pException)
+ ex->NextException <<= *pException;
+ pException = std::move(ex);
+ }
+ catch (SQLException& ex)
+ {
+ // chain errors and keep going
+ if (pException)
+ ex.NextException <<= *pException;
+ pException.reset(new SQLException{ std::move(ex) });
+ }
+ }
+
+ // alter stmts
+ for (const auto& sSql : parser.getAlterStatements())
+ {
+ Reference<XStatement> statement = m_rConnection->createStatement();
+ try
+ {
+ statement->executeQuery(sSql);
+ }
+ catch (SQLException& ex)
+ {
+ // chain errors and keep going
+ if (pException)
+ ex.NextException <<= *pException;
+ pException.reset(new SQLException{ std::move(ex) });
+ }
+ }
+
+ if (pException)
+ {
+ SAL_WARN("dbaccess", "Error during migration");
+ dbtools::showError(dbtools::SQLExceptionInfo{ *pException },
+ pParent ? pParent->GetXWindow() : nullptr,
+ ::comphelper::getProcessComponentContext());
+ }
+}
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/filter/hsqldb/hsqlimport.hxx b/dbaccess/source/filter/hsqldb/hsqlimport.hxx
new file mode 100644
index 000000000..7bab53c24
--- /dev/null
+++ b/dbaccess/source/filter/hsqldb/hsqlimport.hxx
@@ -0,0 +1,60 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+#include <com/sun/star/embed/XStorage.hpp>
+#include <com/sun/star/sdbc/XConnection.hpp>
+
+#include "rowinputbinary.hxx"
+#include "hsqlbinarynode.hxx"
+#include "columndef.hxx"
+
+namespace weld
+{
+class Window;
+}
+
+namespace dbahsql
+{
+class SAL_DLLPUBLIC_EXPORT HsqlImporter
+{
+private:
+ css::uno::Reference<css::sdbc::XConnection>& m_rConnection;
+ css::uno::Reference<css::embed::XStorage> m_xStorage;
+
+protected:
+ void insertRow(const std::vector<css::uno::Any>& xRows, std::u16string_view sTable,
+ const std::vector<ColumnDefinition>& rColTypes);
+ void processTree(HsqlBinaryNode& rNode, HsqlRowInputStream& rStream,
+ const std::vector<ColumnDefinition>& rColTypes, const OUString& sTableName,
+ sal_Int32 nIndexCount);
+ void parseTableRows(const std::vector<sal_Int32>& rIndexes,
+ const std::vector<ColumnDefinition>& rColTypes, const OUString& sTableName);
+
+public:
+ /**
+ * @param rConnection reference to an sdbc connection. The migration will
+ * perform to this connection.
+ *
+ * @param rStorage Storage where the HSQL database can be found. The schema
+ * definition should be in file "script" in form of DDL SQL statements. The
+ * data should be found in file "data". These are HSQLDB's own format.
+ */
+ HsqlImporter(css::uno::Reference<css::sdbc::XConnection>& rConnection,
+ const css::uno::Reference<css::embed::XStorage>& rStorage);
+
+ /**
+ * Migrate a HSQL database to another.
+ */
+ void importHsqlDatabase(weld::Window* pParent);
+};
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/filter/hsqldb/parseschema.cxx b/dbaccess/source/filter/hsqldb/parseschema.cxx
new file mode 100644
index 000000000..b55340f2d
--- /dev/null
+++ b/dbaccess/source/filter/hsqldb/parseschema.cxx
@@ -0,0 +1,204 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+
+#include <string_view>
+
+#include "parseschema.hxx"
+#include "fbcreateparser.hxx"
+#include "fbalterparser.hxx"
+#include "utils.hxx"
+
+#include <com/sun/star/io/TextInputStream.hpp>
+#include <com/sun/star/embed/XStorage.hpp>
+#include <com/sun/star/embed/ElementModes.hpp>
+#include <comphelper/processfactory.hxx>
+#include <comphelper/string.hxx>
+#include <sal/log.hxx>
+#include <connectivity/dbexception.hxx>
+
+namespace
+{
+using namespace ::comphelper;
+
+using IndexVector = std::vector<sal_Int32>;
+
+class IndexStmtParser
+{
+private:
+ OUString m_sql;
+
+public:
+ IndexStmtParser(const OUString& sSql)
+ : m_sql(sSql)
+ {
+ }
+
+ bool isIndexStatement() const
+ {
+ return m_sql.startsWith("SET TABLE") && m_sql.indexOf("INDEX") >= 0;
+ }
+
+ IndexVector getIndexes() const
+ {
+ assert(isIndexStatement());
+
+ std::u16string_view sIndexPart = m_sql.subView(m_sql.indexOf("INDEX") + 5);
+ size_t nQuotePos = sIndexPart.find('\'');
+ if (nQuotePos == std::u16string_view::npos)
+ nQuotePos = 0;
+ else
+ ++nQuotePos;
+ std::u16string_view sIndexNums
+ = sIndexPart.substr(nQuotePos, sIndexPart.rfind('\'') - nQuotePos);
+
+ std::vector<OUString> sIndexes = string::split(sIndexNums, u' ');
+ IndexVector indexes;
+ for (const auto& sIndex : sIndexes)
+ indexes.push_back(sIndex.toInt32());
+
+ // ignore last element
+ // TODO this is an identity peek, which indicates the value of the next
+ // identity. At the current state all migrated identities start with 0.
+ indexes.pop_back();
+
+ return indexes;
+ }
+
+ OUString getTableName() const
+ {
+ // SET TABLE <tableName> or SET TABLE "<multi word table name>"
+ OUString sName = string::split(m_sql, u' ')[2];
+ if (sName.indexOf('"') >= 0)
+ {
+ // Table name with string delimiter
+ sName = "\"" + string::split(m_sql, u'"')[1] + "\"";
+ }
+ return sName;
+ }
+};
+
+OUString lcl_createAlterForeign(std::u16string_view sForeignPart, std::u16string_view sTableName)
+{
+ return OUString::Concat("ALTER TABLE ") + sTableName + " ADD " + sForeignPart;
+}
+
+} // anonymous namespace
+
+namespace dbahsql
+{
+using namespace css::io;
+using namespace css::uno;
+using namespace css::embed;
+
+SchemaParser::SchemaParser(Reference<XStorage>& rStorage)
+ : m_rStorage(rStorage)
+{
+}
+
+void SchemaParser::parseSchema()
+{
+ assert(m_rStorage);
+
+ static constexpr OUStringLiteral SCHEMA_FILENAME = u"script";
+ if (!m_rStorage->hasByName(SCHEMA_FILENAME))
+ {
+ SAL_WARN("dbaccess", "script file does not exist in storage during hsqldb import");
+ return;
+ }
+
+ Reference<XStream> xStream(m_rStorage->openStreamElement(SCHEMA_FILENAME, ElementModes::READ));
+
+ Reference<XComponentContext> rContext = comphelper::getProcessComponentContext();
+ Reference<XTextInputStream2> xTextInput = TextInputStream::create(rContext);
+ xTextInput->setEncoding("UTF-8");
+ xTextInput->setInputStream(xStream->getInputStream());
+
+ while (!xTextInput->isEOF())
+ {
+ // every line contains exactly one DDL statement
+ OUString sSql = utils::convertToUTF8(
+ OUStringToOString(xTextInput->readLine(), RTL_TEXTENCODING_UTF8));
+
+ IndexStmtParser indexParser{ sSql };
+ if (indexParser.isIndexStatement())
+ {
+ m_Indexes[indexParser.getTableName()] = indexParser.getIndexes();
+ }
+ else if (sSql.startsWith("SET") || sSql.startsWith("CREATE USER")
+ || sSql.startsWith("CREATE SCHEMA") || sSql.startsWith("GRANT"))
+ continue;
+ else if (sSql.startsWith("CREATE CACHED TABLE") || sSql.startsWith("CREATE TABLE"))
+ {
+ FbCreateStmtParser aCreateParser;
+ aCreateParser.parse(sSql);
+
+ for (const auto& foreignParts : aCreateParser.getForeignParts())
+ {
+ m_sAlterStatements.push_back(
+ lcl_createAlterForeign(foreignParts, aCreateParser.getTableName()));
+ }
+
+ sSql = aCreateParser.compose();
+
+ // save column definitions
+ m_ColumnTypes[aCreateParser.getTableName()] = aCreateParser.getColumnDef();
+
+ m_sCreateStatements.push_back(sSql);
+ }
+ else if (sSql.startsWith("ALTER"))
+ {
+ FbAlterStmtParser aAlterParser;
+ aAlterParser.parse(sSql);
+ OUString parsedStmt = aAlterParser.compose();
+
+ if (!parsedStmt.isEmpty())
+ m_sAlterStatements.push_back(parsedStmt);
+ }
+ else if (sSql.startsWith("CREATE VIEW"))
+ m_sCreateStatements.push_back(sSql);
+ }
+}
+
+std::vector<ColumnDefinition> SchemaParser::getTableColumnTypes(const OUString& sTableName) const
+{
+ if (m_ColumnTypes.count(sTableName) < 1)
+ {
+ static constexpr OUStringLiteral NOT_EXIST
+ = u"Internal error while getting column information of table";
+ SAL_WARN("dbaccess", NOT_EXIST << ". Table name is: " << sTableName);
+ dbtools::throwGenericSQLException(NOT_EXIST, ::comphelper::getProcessComponentContext());
+ }
+ return m_ColumnTypes.at(sTableName);
+}
+
+const std::map<OUString, std::vector<sal_Int32>>& SchemaParser::getTableIndexes() const
+{
+ return m_Indexes;
+}
+
+const std::map<OUString, std::vector<OUString>>& SchemaParser::getPrimaryKeys() const
+{
+ return m_PrimaryKeys;
+}
+
+} // namespace dbahsql
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/filter/hsqldb/parseschema.hxx b/dbaccess/source/filter/hsqldb/parseschema.hxx
new file mode 100644
index 000000000..04a8e0905
--- /dev/null
+++ b/dbaccess/source/filter/hsqldb/parseschema.hxx
@@ -0,0 +1,84 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+#include <com/sun/star/embed/XStorage.hpp>
+#include <vector>
+#include <map>
+
+#include "columndef.hxx"
+
+namespace dbahsql
+{
+using SqlStatementVector = std::vector<OUString>;
+
+class SchemaParser
+{
+private:
+ css::uno::Reference<css::embed::XStorage>& m_rStorage;
+
+ // column type for each table. It is filled after parsing schema.
+ std::map<OUString, std::vector<ColumnDefinition>> m_ColumnTypes;
+
+ // root element's position of data for each table
+ std::map<OUString, std::vector<sal_Int32>> m_Indexes;
+
+ // primary keys of each table
+ std::map<OUString, std::vector<OUString>> m_PrimaryKeys;
+
+ SqlStatementVector m_sCreateStatements;
+ SqlStatementVector m_sAlterStatements;
+
+public:
+ explicit SchemaParser(css::uno::Reference<css::embed::XStorage>& rStorage);
+
+ /**
+ * Parses table definitions contained by a file called "script" in storage.
+ */
+ void parseSchema();
+
+ /**
+ * @return A vector of schema definition SQL strings in Firebird dialect.
+ */
+ const SqlStatementVector& getCreateStatements() const { return m_sCreateStatements; }
+
+ /**
+ * @return A vector of alter SQL strings in Firebird dialect.
+ */
+ const SqlStatementVector& getAlterStatements() const { return m_sAlterStatements; }
+
+ /**
+ * Returns the column types of a table. It should not be called before
+ * calling parseSchema().
+ *
+ * @param sTableName name of the table.
+ *
+ * @return A vector of column descriptors.
+ */
+ std::vector<ColumnDefinition> getTableColumnTypes(const OUString& sTableName) const;
+
+ /**
+ * Returns a vector of indexes for each table. These indexes are used for
+ * locating the data related to the actual table in the binary file.
+ *
+ * The indexes point to root elements of AVL trees. Each node of the tree
+ * contains one row.
+ */
+ const std::map<OUString, std::vector<sal_Int32>>& getTableIndexes() const;
+
+ /**
+ * Returns a vector of column names for each table. These columns are the
+ * primary keys of the table.
+ */
+ const std::map<OUString, std::vector<OUString>>& getPrimaryKeys() const;
+};
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/filter/hsqldb/rowinputbinary.cxx b/dbaccess/source/filter/hsqldb/rowinputbinary.cxx
new file mode 100644
index 000000000..95ce05f69
--- /dev/null
+++ b/dbaccess/source/filter/hsqldb/rowinputbinary.cxx
@@ -0,0 +1,399 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+
+#include <string_view>
+
+#include "rowinputbinary.hxx"
+#include <com/sun/star/sdbc/DataType.hpp>
+#include <com/sun/star/io/WrongFormatException.hpp>
+#include <com/sun/star/util/Time.hpp>
+#include <com/sun/star/util/Date.hpp>
+#include <com/sun/star/util/DateTime.hpp>
+
+#include <unotools/ucbstreamhelper.hxx>
+#include <tools/stream.hxx>
+#include <rtl/ustrbuf.hxx>
+
+#include <boost/date_time/posix_time/posix_time.hpp>
+
+namespace
+{
+/**
+ * Converts binary represented big integer value to BCD (Binary Coded
+ * Decimal), and returns a string representation of the number.
+ *
+ * Bytes[0] is the most significant part of the number.
+ */
+OUString lcl_double_dabble(const std::vector<sal_uInt8>& bytes)
+{
+ size_t nbits = 8 * bytes.size(); // length of array in bits
+ size_t nscratch = nbits / 2; // length of scratch in bytes
+ std::vector<char> scratch(nscratch, 0);
+
+ for (size_t i = 0; i < bytes.size(); ++i)
+ {
+ for (size_t j = 0; j < 8; ++j)
+ {
+ /* This bit will be shifted in on the right. */
+ int shifted_in = (bytes[i] & (1 << (7 - j))) ? 1 : 0;
+
+ /* Add 3 everywhere that scratch[k] >= 5. */
+ for (size_t k = 0; k < nscratch; ++k)
+ scratch[k] += (scratch[k] >= 5) ? 3 : 0;
+
+ /* Shift scratch to the left by one position. */
+ for (size_t k = 0; k < nscratch - 1; ++k)
+ {
+ scratch[k] <<= 1;
+ scratch[k] &= 0xF;
+ scratch[k] |= (scratch[k + 1] >= 8) ? 1 : 0;
+ }
+
+ /* Shift in the new bit from arr. */
+ scratch[nscratch - 1] <<= 1;
+ scratch[nscratch - 1] &= 0xF;
+ scratch[nscratch - 1] |= shifted_in;
+ }
+ }
+
+ auto it = scratch.begin();
+ /* Remove leading zeros from the scratch space. */
+ while (*it == 0 && scratch.size() > 1)
+ {
+ it = scratch.erase(it);
+ }
+
+ /* Convert the scratch space from BCD digits to ASCII. */
+ for (auto& digit : scratch)
+ digit += '0';
+
+ /* Resize and return the resulting string. */
+ return OStringToOUString(std::string_view(scratch.data(), scratch.size()),
+ RTL_TEXTENCODING_UTF8);
+}
+
+OUString lcl_makeStringFromBigint(std::vector<sal_uInt8>&& aBytes)
+{
+ OUStringBuffer sRet;
+
+ // two's complement
+ if ((aBytes[0] & 0x80) != 0)
+ {
+ sRet.append("-");
+ for (auto& byte : aBytes)
+ byte = ~byte;
+ // add 1 to byte array
+ // FIXME e.g. 10000 valid ?
+ for (size_t i = aBytes.size() - 1; i != 0; --i)
+ {
+ aBytes[i] += 1;
+ if (aBytes[i] != 0)
+ break;
+ }
+ }
+ // convert binary to BCD
+ OUString sNum = lcl_double_dabble(aBytes);
+ sRet.append(sNum);
+ return sRet.makeStringAndClear();
+}
+
+OUString lcl_putDot(const OUString& sNum, sal_Int32 nScale)
+{
+ // e.g. sNum = "0", nScale = 2 -> "0.00"
+ OUStringBuffer sBuf{ sNum };
+ sal_Int32 nNullsToAppend = nScale - sNum.getLength() + 1;
+ for (sal_Int32 i = 0; i < nNullsToAppend; ++i)
+ sBuf.insert(0, "0");
+
+ if (nScale > 0)
+ sBuf.insert(sBuf.getLength() - 1 - nScale, ".");
+ return sBuf.makeStringAndClear();
+}
+}
+
+namespace dbahsql
+{
+using namespace css::uno;
+using namespace css::sdbc;
+using namespace css::io;
+using namespace boost::posix_time;
+using namespace boost::gregorian;
+
+HsqlRowInputStream::HsqlRowInputStream() {}
+
+void HsqlRowInputStream::setInputStream(Reference<XInputStream> const& rStream)
+{
+ m_pStream = utl::UcbStreamHelper::CreateStream(rStream, true);
+ m_pStream->SetEndian(SvStreamEndian::BIG);
+}
+
+SvStream* HsqlRowInputStream::getInputStream() const { return m_pStream.get(); }
+
+void HsqlRowInputStream::seek(sal_Int32 nPos) { m_pStream->Seek(nPos); }
+
+OUString HsqlRowInputStream::readString()
+{
+ sal_Int32 nLen = 0;
+ m_pStream->ReadInt32(nLen);
+ return readUTF(nLen);
+}
+
+OUString HsqlRowInputStream::readUTF(sal_Int32 nUTFLen)
+{
+ Sequence<sal_Unicode> aBuffer(nUTFLen);
+ sal_Unicode* pStr = aBuffer.getArray();
+
+ sal_Int32 nCount = 0;
+ sal_Int32 nStrLen = 0;
+ while (nCount < nUTFLen)
+ {
+ sal_uInt8 c = 0;
+ m_pStream->ReadUChar(c);
+ sal_uInt8 char2, char3;
+ switch (c >> 4)
+ {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ // 0xxxxxxx
+ nCount++;
+ pStr[nStrLen++] = c;
+ break;
+
+ case 12:
+ case 13:
+ // 110x xxxx 10xx xxxx
+ nCount += 2;
+ if (nCount > nUTFLen)
+ {
+ throw WrongFormatException();
+ }
+
+ m_pStream->ReadUChar(char2);
+ if ((char2 & 0xC0) != 0x80)
+ {
+ throw WrongFormatException();
+ }
+
+ pStr[nStrLen++] = (sal_Unicode(c & 0x1F) << 6) | (char2 & 0x3F);
+ break;
+
+ case 14:
+ // 1110 xxxx 10xx xxxx 10xx xxxx
+ nCount += 3;
+ if (nCount > nUTFLen)
+ {
+ throw WrongFormatException();
+ }
+
+ m_pStream->ReadUChar(char2);
+ m_pStream->ReadUChar(char3);
+
+ if (((char2 & 0xC0) != 0x80) || ((char3 & 0xC0) != 0x80))
+ {
+ throw WrongFormatException();
+ }
+ pStr[nStrLen++] = (sal_Unicode(c & 0x0F) << 12) | (sal_Unicode(char2 & 0x3F) << 6)
+ | (char3 & 0x3F);
+ break;
+
+ default:
+ // 10xx xxxx, 1111 xxxx
+ throw WrongFormatException();
+ }
+ }
+ return OUString(pStr, nStrLen);
+}
+
+bool HsqlRowInputStream::checkNull()
+{
+ sal_uInt8 nNull = 0;
+ m_pStream->ReadUChar(nNull);
+ return nNull == 0;
+}
+
+std::vector<Any> HsqlRowInputStream::readOneRow(const std::vector<ColumnDefinition>& nColTypes)
+{
+ auto nLen = nColTypes.size();
+ std::vector<Any> aData;
+
+ for (size_t i = 0; i < nLen; ++i)
+ {
+ if (checkNull())
+ {
+ aData.push_back(Any());
+ continue;
+ }
+
+ sal_Int32 nType = nColTypes[i].getDataType();
+
+ // TODO throw error on EoF
+
+ switch (nType)
+ {
+ case DataType::CHAR:
+ case DataType::VARCHAR:
+ case DataType::LONGVARCHAR:
+ aData.push_back(Any(readString()));
+ break;
+ case DataType::TINYINT:
+ case DataType::SMALLINT:
+ {
+ sal_Int16 value = 0;
+ m_pStream->ReadInt16(value);
+ aData.push_back(Any(value));
+ }
+ break;
+ case DataType::INTEGER:
+ {
+ sal_Int32 value = 0;
+ m_pStream->ReadInt32(value);
+ aData.push_back(Any(value));
+ }
+ break;
+ case DataType::BIGINT:
+ {
+ sal_Int64 value = 0;
+ m_pStream->ReadInt64(value);
+ aData.push_back(Any(value));
+ }
+ break;
+ case DataType::REAL:
+ case DataType::FLOAT:
+ case DataType::DOUBLE:
+ {
+ double value = 0;
+ m_pStream->ReadDouble(value);
+ // FIXME double is not necessarily 4 bytes
+ aData.push_back(Any(value));
+ }
+ break;
+ case DataType::NUMERIC:
+ case DataType::DECIMAL:
+ {
+ sal_Int32 nSize = 0;
+ m_pStream->ReadInt32(nSize);
+
+ std::vector<sal_uInt8> aBytes(nSize);
+ m_pStream->ReadBytes(aBytes.data(), nSize);
+ assert(aBytes.size() > 0);
+
+ sal_Int32 nScale = 0;
+ m_pStream->ReadInt32(nScale);
+
+ OUString sNum = lcl_makeStringFromBigint(std::move(aBytes));
+ Sequence<Any> result{ Any(lcl_putDot(sNum, nScale)), Any(nScale) };
+ aData.push_back(Any(result));
+ }
+ break;
+ case DataType::DATE:
+ {
+ sal_Int64 value = 0;
+ m_pStream->ReadInt64(value); // in millisec, from 1970
+ ptime epoch = time_from_string("1970-01-01 00:00:00.000");
+ ptime time = epoch + milliseconds(value);
+ date asDate = time.date();
+
+ css::util::Date loDate(asDate.day(), asDate.month(),
+ asDate.year()); // day, month, year
+ aData.push_back(Any(loDate));
+ }
+ break;
+ case DataType::TIME:
+ {
+ sal_Int64 value = 0;
+ m_pStream->ReadInt64(value);
+ auto valueInSecs = value / 1000;
+ /* Observed valueInSecs fall in the range from
+ negative one day to positive two days. Coerce
+ valueInSecs between zero and positive one day.*/
+ const int secPerDay = 24 * 60 * 60;
+ valueInSecs = (valueInSecs + secPerDay) % secPerDay;
+
+ auto nHours = valueInSecs / (60 * 60);
+ valueInSecs = valueInSecs % 3600;
+ const sal_uInt16 nMins = valueInSecs / 60;
+ const sal_uInt16 nSecs = valueInSecs % 60;
+ css::util::Time time((value % 1000) * 1000000, nSecs, nMins, nHours, true);
+ aData.push_back(Any(time));
+ }
+ break;
+ case DataType::TIMESTAMP:
+ {
+ sal_Int64 nEpochMillis = 0;
+ m_pStream->ReadInt64(nEpochMillis);
+ ptime epoch = time_from_string("1970-01-01 00:00:00.000");
+ ptime time = epoch + milliseconds(nEpochMillis);
+ date asDate = time.date();
+
+ sal_Int32 nNanos = 0;
+ m_pStream->ReadInt32(nNanos);
+
+ // convert into LO internal representation of dateTime
+ css::util::DateTime dateTime;
+ dateTime.NanoSeconds = nNanos;
+ dateTime.Seconds = time.time_of_day().seconds();
+ dateTime.Minutes = time.time_of_day().minutes();
+ dateTime.Hours = time.time_of_day().hours();
+ dateTime.Day = asDate.day();
+ dateTime.Month = asDate.month();
+ dateTime.Year = asDate.year();
+ aData.push_back(Any(dateTime));
+ }
+ break;
+ case DataType::BOOLEAN:
+ {
+ sal_uInt8 nBool = 0;
+ m_pStream->ReadUChar(nBool);
+ aData.push_back(Any(static_cast<bool>(nBool)));
+ }
+ break;
+ case DataType::OTHER:
+ aData.push_back(Any{}); // TODO
+ break;
+ case DataType::BINARY:
+ case DataType::VARBINARY:
+ case DataType::LONGVARBINARY:
+ {
+ sal_Int32 nSize = 0;
+ m_pStream->ReadInt32(nSize);
+
+ Sequence<sal_Int8> aBytes(nSize);
+ m_pStream->ReadBytes(aBytes.getArray(), nSize);
+ aData.push_back(Any(aBytes));
+ }
+ break;
+
+ default:
+ throw WrongFormatException();
+ }
+ }
+ return aData;
+}
+
+} // namespace dbahsql
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/filter/hsqldb/rowinputbinary.hxx b/dbaccess/source/filter/hsqldb/rowinputbinary.hxx
new file mode 100644
index 000000000..f81fa446f
--- /dev/null
+++ b/dbaccess/source/filter/hsqldb/rowinputbinary.hxx
@@ -0,0 +1,52 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+#include <vector>
+#include <tools/stream.hxx>
+
+#include <com/sun/star/io/XInputStream.hpp>
+
+#include "columndef.hxx"
+
+namespace dbahsql
+{
+class HsqlRowInputStream
+{
+private:
+ std::unique_ptr<SvStream> m_pStream;
+
+protected:
+ OUString readString();
+ bool checkNull();
+
+ OUString readUTF(sal_Int32 nLen);
+
+public:
+ HsqlRowInputStream();
+
+ /**
+ * Reads one row from the actual position.
+ * @param colTypes Field types of the row, in a strict order.
+ */
+ std::vector<css::uno::Any> readOneRow(const std::vector<ColumnDefinition>& colTypes);
+
+ /**
+ * Sets the file-pointer offset, measured from the beginning of the file
+ */
+ void seek(sal_Int32 nPos);
+
+ void setInputStream(css::uno::Reference<css::io::XInputStream> const& rStream);
+ SvStream* getInputStream() const;
+};
+
+} // namespace dbahsql
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/filter/hsqldb/utils.cxx b/dbaccess/source/filter/hsqldb/utils.cxx
new file mode 100644
index 000000000..724ffccfb
--- /dev/null
+++ b/dbaccess/source/filter/hsqldb/utils.cxx
@@ -0,0 +1,141 @@
+
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <comphelper/string.hxx>
+#include <comphelper/processfactory.hxx>
+#include <connectivity/dbexception.hxx>
+
+#include "utils.hxx"
+
+using namespace dbahsql;
+
+namespace
+{
+int getHexValue(sal_Unicode c)
+{
+ if (c >= '0' && c <= '9')
+ {
+ return c - '0';
+ }
+ else if (c >= 'A' && c <= 'F')
+ {
+ return c - 'A' + 10;
+ }
+ else if (c >= 'a' && c <= 'f')
+ {
+ return c - 'a' + 10;
+ }
+ else
+ {
+ return -1;
+ }
+}
+
+} // unnamed namespace
+
+//Convert ascii escaped unicode to utf-8
+OUString utils::convertToUTF8(std::string_view original)
+{
+ OUString res = OStringToOUString(original, RTL_TEXTENCODING_UTF8);
+ for (sal_Int32 i = 0;;)
+ {
+ i = res.indexOf("\\u", i);
+ if (i == -1)
+ {
+ break;
+ }
+ i += 2;
+ if (res.getLength() - i >= 4)
+ {
+ bool escape = true;
+ sal_Unicode c = 0;
+ for (sal_Int32 j = 0; j != 4; ++j)
+ {
+ auto const n = getHexValue(res[i + j]);
+ if (n == -1)
+ {
+ escape = false;
+ break;
+ }
+ c = (c << 4) | n;
+ }
+ if (escape)
+ {
+ i -= 2;
+ res = res.replaceAt(i, 6, rtl::OUStringChar(c));
+ ++i;
+ }
+ }
+ }
+ return res;
+}
+
+OUString utils::getTableNameFromStmt(std::u16string_view sSql)
+{
+ auto stmtComponents = comphelper::string::split(sSql, sal_Unicode(u' '));
+ assert(stmtComponents.size() > 2);
+ auto wordIter = stmtComponents.begin();
+
+ if (*wordIter == "CREATE" || *wordIter == "ALTER")
+ ++wordIter;
+ if (*wordIter == "CACHED")
+ ++wordIter;
+ if (*wordIter == "TABLE")
+ ++wordIter;
+
+ // it may contain spaces if it's put into apostrophes.
+ if (wordIter->indexOf("\"") >= 0)
+ {
+ size_t nAposBegin = sSql.find('"');
+ size_t nAposEnd = nAposBegin;
+ bool bProperEndAposFound = false;
+ while (!bProperEndAposFound)
+ {
+ nAposEnd = sSql.find('"', nAposEnd + 1);
+ if (sSql[nAposEnd - 1] != u'\\')
+ bProperEndAposFound = true;
+ }
+ std::u16string_view result = sSql.substr(nAposBegin, nAposEnd - nAposBegin + 1);
+ return OUString(result);
+ }
+
+ // next word is the table's name
+ // it might stuck together with the column definitions.
+ sal_Int32 nParenPos = wordIter->indexOf("(");
+ if (nParenPos > 0)
+ return wordIter->copy(0, nParenPos);
+ else
+ return *wordIter;
+}
+
+void utils::ensureFirebirdTableLength(const OUString& sName)
+{
+ if (sName.getLength() > 30) // Firebird limitation
+ {
+ static constexpr OUStringLiteral NAME_TOO_LONG
+ = u"Firebird 3 doesn't support object (table, field) names "
+ "of more than 30 characters; please shorten your object "
+ "names in the original file and try again.";
+ dbtools::throwGenericSQLException(NAME_TOO_LONG,
+ ::comphelper::getProcessComponentContext());
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/filter/hsqldb/utils.hxx b/dbaccess/source/filter/hsqldb/utils.hxx
new file mode 100644
index 000000000..cc3e2f0df
--- /dev/null
+++ b/dbaccess/source/filter/hsqldb/utils.hxx
@@ -0,0 +1,27 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+#include <sal/config.h>
+
+#include <string_view>
+
+#include <rtl/ustring.hxx>
+
+namespace dbahsql::utils
+{
+OUString convertToUTF8(std::string_view original);
+
+OUString getTableNameFromStmt(std::u16string_view sSql);
+
+void ensureFirebirdTableLength(const OUString& sName);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/filter/xml/dbaxml.component b/dbaccess/source/filter/xml/dbaxml.component
new file mode 100644
index 000000000..4842eb4ad
--- /dev/null
+++ b/dbaccess/source/filter/xml/dbaxml.component
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ -->
+
+<component loader="com.sun.star.loader.SharedLibrary" environment="@CPPU_ENV@"
+ xmlns="http://openoffice.org/2010/uno-components">
+ <implementation name="com.sun.star.comp.sdb.DBExportFilter"
+ constructor="com_sun_star_comp_sdb_DBExportFilter_get_implementation">
+ <service name="com.sun.star.document.ExportFilter"/>
+ </implementation>
+ <implementation name="com.sun.star.comp.sdb.DBFilter"
+ constructor="com_sun_star_comp_sdb_DBFilter_get_implementation">
+ <service name="com.sun.star.document.ImportFilter"/>
+ </implementation>
+ <implementation name="com.sun.star.comp.sdb.XMLFullExporter"
+ constructor="com_sun_star_comp_sdb_XMLFullExporter_get_implementation">
+ <service name="com.sun.star.document.ExportFilter"/>
+ </implementation>
+ <implementation name="com.sun.star.comp.sdb.XMLSettingsExporter"
+ constructor="com_sun_star_comp_sdb_XMLSettingsExporter_get_implementation">
+ <service name="com.sun.star.document.ExportFilter"/>
+ </implementation>
+ <implementation name="org.openoffice.comp.dbflt.DBContentLoader2"
+ constructor="org_openoffice_comp_dbflt_DBContentLoader2_get_implementation">
+ <service name="com.sun.star.frame.FrameLoader"/>
+ </implementation>
+ <implementation name="org.openoffice.comp.dbflt.DBTypeDetection"
+ constructor="org_openoffice_comp_dbflt_DBTypeDetection_get_implementation">
+ <service name="com.sun.star.document.ExtendedTypeDetection"/>
+ </implementation>
+</component>
diff --git a/dbaccess/source/filter/xml/dbloader2.cxx b/dbaccess/source/filter/xml/dbloader2.cxx
new file mode 100644
index 000000000..0513af5a2
--- /dev/null
+++ b/dbaccess/source/filter/xml/dbloader2.cxx
@@ -0,0 +1,535 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <strings.hxx>
+
+#include <com/sun/star/beans/NamedValue.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/document/XExtendedFilterDetection.hpp>
+#include <com/sun/star/embed/ElementModes.hpp>
+#include <com/sun/star/embed/XStorage.hpp>
+#include <com/sun/star/frame/Desktop.hpp>
+#include <com/sun/star/frame/XController2.hpp>
+#include <com/sun/star/frame/XFrame.hpp>
+#include <com/sun/star/frame/XFrameLoader.hpp>
+#include <com/sun/star/frame/XLoadEventListener.hpp>
+#include <com/sun/star/frame/XModel2.hpp>
+#include <com/sun/star/io/XInputStream.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/sdb/DatabaseContext.hpp>
+#include <com/sun/star/sdb/XDocumentDataSource.hpp>
+#include <com/sun/star/task/XJobExecutor.hpp>
+#include <com/sun/star/ui/dialogs/XExecutableDialog.hpp>
+#include <com/sun/star/task/InteractionHandler.hpp>
+#include <com/sun/star/util/URLTransformer.hpp>
+#include <com/sun/star/util/XURLTransformer.hpp>
+#include <com/sun/star/view/XSelectionSupplier.hpp>
+#include <com/sun/star/sdb/application/DatabaseObjectContainer.hpp>
+#include <com/sun/star/sdb/application/NamedDatabaseObject.hpp>
+#include <com/sun/star/frame/XLoadable.hpp>
+
+#include <comphelper/documentconstants.hxx>
+#include <comphelper/namedvaluecollection.hxx>
+#include <comphelper/storagehelper.hxx>
+#include <comphelper/types.hxx>
+#include <comphelper/propertysequence.hxx>
+#include <cppuhelper/implbase.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <sfx2/docfile.hxx>
+#include <unotools/moduleoptions.hxx>
+#include <tools/diagnose_ex.h>
+#include <vcl/svapp.hxx>
+
+using namespace ::ucbhelper;
+using namespace ::com::sun::star::task;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::ucb;
+using namespace ::com::sun::star::io;
+using namespace ::com::sun::star::util;
+using namespace ::com::sun::star::frame;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::document;
+using namespace ::com::sun::star::sdb;
+using namespace ::com::sun::star::embed;
+using namespace ::com::sun::star::ui::dialogs;
+using ::com::sun::star::awt::XWindow;
+using ::com::sun::star::sdb::application::NamedDatabaseObject;
+
+namespace dbaxml
+{
+
+namespace {
+
+class DBTypeDetection : public ::cppu::WeakImplHelper< XExtendedFilterDetection, XServiceInfo>
+{
+ const Reference< XComponentContext > m_aContext;
+
+public:
+ explicit DBTypeDetection(const Reference< XComponentContext >&);
+
+ // XServiceInfo
+ OUString SAL_CALL getImplementationName() override;
+ sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
+ Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+
+ virtual OUString SAL_CALL detect( css::uno::Sequence< css::beans::PropertyValue >& Descriptor ) override;
+};
+
+}
+
+DBTypeDetection::DBTypeDetection(const Reference< XComponentContext >& _rxContext)
+ :m_aContext( _rxContext )
+{
+}
+
+OUString SAL_CALL DBTypeDetection::detect( css::uno::Sequence< css::beans::PropertyValue >& Descriptor )
+{
+ try
+ {
+ ::comphelper::NamedValueCollection aMedia( Descriptor );
+ bool bStreamFromDescr = false;
+ OUString sURL = aMedia.getOrDefault( "URL", OUString() );
+
+ Reference< XInputStream > xInStream( aMedia.getOrDefault( "InputStream", Reference< XInputStream >() ) );
+ Reference< XPropertySet > xStorageProperties;
+ if ( xInStream.is() )
+ {
+ bStreamFromDescr = true;
+ xStorageProperties.set( ::comphelper::OStorageHelper::GetStorageFromInputStream(
+ xInStream, m_aContext ), UNO_QUERY );
+ }
+ else
+ {
+ OUString sSalvagedURL( aMedia.getOrDefault( "SalvagedFile", OUString() ) );
+
+ OUString sFileLocation( sSalvagedURL.isEmpty() ? sURL : sSalvagedURL );
+ if ( !sFileLocation.isEmpty() )
+ {
+ xStorageProperties.set( ::comphelper::OStorageHelper::GetStorageFromURL(
+ sFileLocation, ElementModes::READ, m_aContext ), UNO_QUERY );
+ }
+ }
+
+ if ( xStorageProperties.is() )
+ {
+ OUString sMediaType;
+ xStorageProperties->getPropertyValue( INFO_MEDIATYPE ) >>= sMediaType;
+ if ( sMediaType == MIMETYPE_OASIS_OPENDOCUMENT_DATABASE_ASCII || sMediaType == MIMETYPE_VND_SUN_XML_BASE_ASCII )
+ {
+ if ( bStreamFromDescr && !sURL.startsWith( "private:stream" ) )
+ {
+ // After fixing of the i88522 issue ( use the new file locking for database files ) the stream from the type detection can be used further
+ // for now the file should be reopened to have read/write access
+ aMedia.remove( "InputStream" );
+ aMedia.remove( "Stream" );
+ aMedia >>= Descriptor;
+ try
+ {
+ ::comphelper::disposeComponent(xStorageProperties);
+ if ( xInStream.is() )
+ xInStream->closeInput();
+ }
+ catch( Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+
+ return "StarBase";
+ }
+ ::comphelper::disposeComponent(xStorageProperties);
+ }
+ } catch(Exception&){}
+ return OUString();
+}
+
+// XServiceInfo
+OUString SAL_CALL DBTypeDetection::getImplementationName()
+{
+ return "org.openoffice.comp.dbflt.DBTypeDetection";
+}
+
+// XServiceInfo
+sal_Bool SAL_CALL DBTypeDetection::supportsService(const OUString& ServiceName)
+{
+ return cppu::supportsService(this, ServiceName);
+}
+
+// XServiceInfo
+Sequence< OUString > SAL_CALL DBTypeDetection::getSupportedServiceNames()
+{
+ return { "com.sun.star.document.ExtendedTypeDetection" };
+}
+
+} // namespace dbaxml
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+org_openoffice_comp_dbflt_DBTypeDetection_get_implementation(
+ css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const& )
+{
+ return cppu::acquire(new ::dbaxml::DBTypeDetection(context));
+}
+
+namespace dbaxml
+{
+
+namespace {
+
+class DBContentLoader : public ::cppu::WeakImplHelper< XFrameLoader, XServiceInfo>
+{
+private:
+ const Reference< XComponentContext > m_aContext;
+ Reference< XFrameLoader > m_xMySelf;
+ OUString m_sCurrentURL;
+ ImplSVEvent * m_nStartWizard;
+
+ DECL_LINK( OnStartTableWizard, void*, void );
+public:
+ explicit DBContentLoader(const Reference< XComponentContext >&);
+
+ // XServiceInfo
+ OUString SAL_CALL getImplementationName() override;
+ sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
+ Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+
+ // XLoader
+ virtual void SAL_CALL load( const Reference< XFrame > & _rFrame, const OUString& _rURL,
+ const Sequence< PropertyValue >& _rArgs,
+ const Reference< XLoadEventListener > & _rListener) override;
+ virtual void SAL_CALL cancel() override;
+
+private:
+ bool impl_executeNewDatabaseWizard( Reference< XModel > const & _rxModel, bool& _bShouldStartTableWizard );
+};
+
+}
+
+DBContentLoader::DBContentLoader(const Reference< XComponentContext >& _rxFactory)
+ :m_aContext( _rxFactory )
+ ,m_nStartWizard(nullptr)
+{
+
+}
+
+// XServiceInfo
+OUString SAL_CALL DBContentLoader::getImplementationName()
+{
+ return "org.openoffice.comp.dbflt.DBContentLoader2";
+}
+
+// XServiceInfo
+sal_Bool SAL_CALL DBContentLoader::supportsService(const OUString& ServiceName)
+{
+ return cppu::supportsService(this, ServiceName);
+}
+
+// XServiceInfo
+Sequence< OUString > SAL_CALL DBContentLoader::getSupportedServiceNames()
+{
+ return { "com.sun.star.frame.FrameLoader" };
+}
+
+
+namespace
+{
+ bool lcl_urlAllowsInteraction( const Reference<XComponentContext> & _rContext, const OUString& _rURL )
+ {
+ bool bDoesAllow = false;
+ try
+ {
+ Reference< XURLTransformer > xTransformer( URLTransformer::create(_rContext) );
+ URL aURL;
+ aURL.Complete = _rURL;
+ xTransformer->parseStrict( aURL );
+ bDoesAllow = aURL.Arguments == "Interactive";
+ }
+ catch( const Exception& )
+ {
+ TOOLS_WARN_EXCEPTION( "dbaccess", "lcl_urlAllowsInteraction: caught an exception while analyzing the URL!" );
+ }
+ return bDoesAllow;
+ }
+
+ Reference< XWindow > lcl_getTopMostWindow( const Reference<XComponentContext> & _rxContext )
+ {
+ Reference< XWindow > xWindow;
+ // get the top most window
+ Reference < XDesktop2 > xDesktop = Desktop::create(_rxContext);
+ Reference < XFrame > xActiveFrame = xDesktop->getActiveFrame();
+ if ( xActiveFrame.is() )
+ {
+ xWindow = xActiveFrame->getContainerWindow();
+ Reference<XFrame> xFrame = xActiveFrame;
+ while ( xFrame.is() && !xFrame->isTop() )
+ xFrame = xFrame->getCreator();
+
+ if ( xFrame.is() )
+ xWindow = xFrame->getContainerWindow();
+ }
+ return xWindow;
+ }
+}
+
+bool DBContentLoader::impl_executeNewDatabaseWizard( Reference< XModel > const & _rxModel, bool& _bShouldStartTableWizard )
+{
+ Sequence<Any> aWizardArgs(comphelper::InitAnyPropertySequence(
+ {
+ {"ParentWindow", Any(lcl_getTopMostWindow( m_aContext ))},
+ {"InitialSelection", Any(_rxModel)}
+ }));
+
+ // create the dialog
+ Reference< XExecutableDialog > xAdminDialog( m_aContext->getServiceManager()->createInstanceWithArgumentsAndContext("com.sun.star.sdb.DatabaseWizardDialog", aWizardArgs, m_aContext), UNO_QUERY_THROW);
+
+ // execute it
+ if ( RET_OK != xAdminDialog->execute() )
+ return false;
+
+ Reference<XPropertySet> xProp(xAdminDialog,UNO_QUERY);
+ bool bSuccess = false;
+ xProp->getPropertyValue("OpenDatabase") >>= bSuccess;
+ xProp->getPropertyValue("StartTableWizard") >>= _bShouldStartTableWizard;
+ return bSuccess;
+}
+
+void SAL_CALL DBContentLoader::load(const Reference< XFrame > & rFrame, const OUString& _rURL,
+ const Sequence< PropertyValue >& rArgs,
+ const Reference< XLoadEventListener > & rListener)
+{
+ // first check if preview is true, if so return without creating a controller. Preview is not supported
+ ::comphelper::NamedValueCollection aMediaDesc( rArgs );
+ bool bPreview = aMediaDesc.getOrDefault( "Preview", false );
+ if ( bPreview )
+ {
+ if (rListener.is())
+ rListener->loadCancelled(this);
+ return;
+ }
+
+ Reference< XModel > xModel = aMediaDesc.getOrDefault( "Model", Reference< XModel >() );
+ OUString sSalvagedURL = aMediaDesc.getOrDefault( "SalvagedFile", _rURL );
+
+ bool bCreateNew = false; // does the URL denote the private:factory URL?
+ bool bStartTableWizard = false; // start the table wizard after everything was loaded successfully?
+
+ bool bSuccess = true;
+
+ // If there's no interaction handler in the media descriptor, put one.
+ // By definition, loading via loadComponentFromURL (and thus via the content loader here)
+ // is allowed to raise UI. To not burden every place inside the document with creating
+ // a default handler, we simply ensure there is one.
+ // If a handler is present in the media descriptor, even if it is NULL, we will
+ // not touch it.
+ if ( !aMediaDesc.has( "InteractionHandler" ) )
+ {
+ Reference< XInteractionHandler2 > xHandler( InteractionHandler::createWithParent(m_aContext, nullptr) );
+ aMediaDesc.put( "InteractionHandler", xHandler );
+ }
+
+ // it's allowed to pass an existing document
+ Reference< XOfficeDatabaseDocument > xExistentDBDoc;
+ xModel.set( aMediaDesc.getOrDefault( "Model", xExistentDBDoc ), UNO_QUERY );
+ aMediaDesc.remove( "Model" );
+
+ // also, it's allowed to specify the type of view which should be created
+ OUString sViewName = aMediaDesc.getOrDefault( "ViewName", OUString( "Default" ) );
+ aMediaDesc.remove( "ViewName" );
+
+ // this needs to stay alive for duration of this method
+ Reference< XDatabaseContext > xDatabaseContext;
+
+ sal_Int32 nInitialSelection = -1;
+ if ( !xModel.is() )
+ {
+ xDatabaseContext = DatabaseContext::create(m_aContext);
+
+ OUString sFactoryName = SvtModuleOptions().GetFactoryEmptyDocumentURL(SvtModuleOptions::EFactory::DATABASE);
+ bCreateNew = sFactoryName.match(_rURL);
+
+ Reference< XDocumentDataSource > xDocumentDataSource;
+ bool bNewAndInteractive = false;
+ if ( bCreateNew )
+ {
+ bNewAndInteractive = lcl_urlAllowsInteraction( m_aContext, _rURL );
+ xDocumentDataSource.set( xDatabaseContext->createInstance(), UNO_QUERY_THROW );
+ }
+ else
+ {
+ ::comphelper::NamedValueCollection aCreationArgs;
+ aCreationArgs.put( INFO_POOLURL, sSalvagedURL );
+ xDocumentDataSource.set( xDatabaseContext->createInstanceWithArguments( aCreationArgs.getWrappedNamedValues() ), UNO_QUERY_THROW );
+ }
+
+ xModel.set( xDocumentDataSource->getDatabaseDocument(), UNO_QUERY );
+
+ if ( bCreateNew && xModel.is() )
+ {
+ if ( bNewAndInteractive )
+ {
+ bSuccess = impl_executeNewDatabaseWizard( xModel, bStartTableWizard );
+ }
+ else
+ {
+ try
+ {
+ Reference< XLoadable > xLoad( xModel, UNO_QUERY_THROW );
+ xLoad->initNew();
+ bSuccess = true;
+ }
+ catch( const Exception& )
+ {
+ bSuccess = false;
+ }
+ }
+
+ // initially select the "Tables" category (will be done below)
+ nInitialSelection = css::sdb::application::DatabaseObjectContainer::TABLES;
+ }
+ }
+
+ if ( !xModel.is() )
+ {
+ if ( rListener.is() )
+ rListener->loadCancelled(this);
+ return;
+ }
+
+ if ( !bCreateNew )
+ {
+ // We need to XLoadable::load the document if it does not yet have a URL.
+ // If it already *does* have a URL, then it was either passed in the arguments, or a previous incarnation
+ // of that model existed before (which can happen if a model is closed, but an associated DataSource is kept
+ // alive 'til loading the document again).
+ bool bNeedLoad = xModel->getURL().isEmpty();
+ try
+ {
+ aMediaDesc.put( "FileName", _rURL );
+ Sequence< PropertyValue > aResource( aMediaDesc.getPropertyValues() );
+
+ if ( bNeedLoad )
+ {
+ Reference< XLoadable > xLoad( xModel, UNO_QUERY_THROW );
+ xLoad->load( aResource );
+ }
+
+ // always attach the resource, even if the document has not been freshly loaded
+ xModel->attachResource( _rURL, aResource );
+ }
+ catch(const Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ bSuccess = false;
+ }
+ }
+
+ if ( bSuccess )
+ {
+ try
+ {
+ Reference< XModel2 > xModel2( xModel, UNO_QUERY_THROW );
+ Reference< XController2 > xController( xModel2->createViewController( sViewName, Sequence< PropertyValue >(), rFrame ), UNO_SET_THROW );
+
+ xController->attachModel( xModel );
+ xModel->connectController( xController );
+ rFrame->setComponent( xController->getComponentWindow(), xController );
+ xController->attachFrame( rFrame );
+ xModel->setCurrentController( xController );
+
+ bSuccess = true;
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ bSuccess = false;
+ }
+ }
+
+ if (bSuccess)
+ {
+ if ( rListener.is() )
+ rListener->loadFinished(this);
+
+ if ( nInitialSelection != -1 )
+ {
+ Reference< css::view::XSelectionSupplier > xDocView( xModel->getCurrentController(), UNO_QUERY );
+ if ( xDocView.is() )
+ {
+ NamedDatabaseObject aSelection;
+ aSelection.Type = nInitialSelection;
+ xDocView->select( Any( aSelection ) );
+ }
+ }
+
+ if ( bStartTableWizard )
+ {
+ // reset the data of the previous async drop (if any)
+ if ( m_nStartWizard )
+ Application::RemoveUserEvent(m_nStartWizard);
+ m_sCurrentURL = xModel->getURL();
+ m_xMySelf = this;
+ m_nStartWizard = Application::PostUserEvent(LINK(this, DBContentLoader, OnStartTableWizard));
+ }
+ }
+ else
+ {
+ if ( rListener.is() )
+ rListener->loadCancelled( this );
+ }
+
+ if ( !bSuccess )
+ ::comphelper::disposeComponent(xModel);
+}
+
+void DBContentLoader::cancel()
+{
+}
+
+IMPL_LINK_NOARG( DBContentLoader, OnStartTableWizard, void*, void )
+{
+ m_nStartWizard = nullptr;
+ try
+ {
+ Sequence<Any> aWizArgs(comphelper::InitAnyPropertySequence(
+ {
+ {"DatabaseLocation", Any(m_sCurrentURL)}
+ }));
+ SolarMutexGuard aGuard;
+ Reference< XJobExecutor > xTableWizard( m_aContext->getServiceManager()->createInstanceWithArgumentsAndContext("com.sun.star.wizards.table.CallTableWizard", aWizArgs, m_aContext), UNO_QUERY);
+ if ( xTableWizard.is() )
+ xTableWizard->trigger("start");
+ }
+ catch(const Exception&)
+ {
+ TOOLS_WARN_EXCEPTION( "dbaccess", "caught an exception while starting the table wizard!");
+ }
+ m_xMySelf = nullptr;
+}
+
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+org_openoffice_comp_dbflt_DBContentLoader2_get_implementation(
+ css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const& )
+{
+ return cppu::acquire(new ::dbaxml::DBContentLoader(context));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/filter/xml/xmlAutoStyle.cxx b/dbaccess/source/filter/xml/xmlAutoStyle.cxx
new file mode 100644
index 000000000..991015671
--- /dev/null
+++ b/dbaccess/source/filter/xml/xmlAutoStyle.cxx
@@ -0,0 +1,82 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "xmlAutoStyle.hxx"
+#include "xmlHelper.hxx"
+#include "xmlExport.hxx"
+#include <xmloff/families.hxx>
+namespace dbaxml
+{
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::xml::sax;
+
+void OXMLAutoStylePoolP::exportStyleAttributes(
+ SvXMLAttributeList& rAttrList,
+ XmlStyleFamily nFamily,
+ const std::vector< XMLPropertyState >& rProperties,
+ const SvXMLExportPropertyMapper& rPropExp
+ , const SvXMLUnitConverter& rUnitConverter,
+ const SvXMLNamespaceMap& rNamespaceMap
+ ) const
+{
+ SvXMLAutoStylePoolP::exportStyleAttributes( rAttrList, nFamily, rProperties, rPropExp, rUnitConverter, rNamespaceMap );
+ if ( nFamily != XmlStyleFamily::TABLE_COLUMN )
+ return;
+
+ rtl::Reference< XMLPropertySetMapper > aPropMapper = rODBExport.GetColumnStylesPropertySetMapper();
+ for (auto const& property : rProperties)
+ {
+ sal_Int16 nContextID = aPropMapper->GetEntryContextId(property.mnIndex);
+ switch (nContextID)
+ {
+ case CTF_DB_NUMBERFORMAT :
+ {
+ sal_Int32 nNumberFormat = 0;
+ if ( property.maValue >>= nNumberFormat )
+ {
+ OUString sAttrValue = rODBExport.getDataStyleName(nNumberFormat);
+ if ( !sAttrValue.isEmpty() )
+ {
+ GetExport().AddAttribute(
+ aPropMapper->GetEntryNameSpace(property.mnIndex),
+ aPropMapper->GetEntryXMLName(property.mnIndex),
+ sAttrValue );
+ }
+ }
+ break;
+ }
+ }
+ }
+}
+
+OXMLAutoStylePoolP::OXMLAutoStylePoolP(ODBExport& rTempODBExport):
+ SvXMLAutoStylePoolP(rTempODBExport),
+ rODBExport(rTempODBExport)
+{
+
+}
+
+OXMLAutoStylePoolP::~OXMLAutoStylePoolP()
+{
+
+}
+
+} // namespace dbaxml
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/filter/xml/xmlAutoStyle.hxx b/dbaccess/source/filter/xml/xmlAutoStyle.hxx
new file mode 100644
index 000000000..54748a22c
--- /dev/null
+++ b/dbaccess/source/filter/xml/xmlAutoStyle.hxx
@@ -0,0 +1,45 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+#include <xmloff/maptype.hxx>
+#include <xmloff/xmlaustp.hxx>
+
+namespace dbaxml
+{
+ class ODBExport;
+ class OXMLAutoStylePoolP : public SvXMLAutoStylePoolP
+ {
+ ODBExport& rODBExport;
+
+ virtual void exportStyleAttributes(
+ SvXMLAttributeList& rAttrList,
+ XmlStyleFamily nFamily,
+ const std::vector< XMLPropertyState >& rProperties,
+ const SvXMLExportPropertyMapper& rPropExp,
+ const SvXMLUnitConverter& rUnitConverter,
+ const SvXMLNamespaceMap& rNamespaceMap
+ ) const override;
+
+ public:
+ explicit OXMLAutoStylePoolP(ODBExport& rXMLExport);
+ virtual ~OXMLAutoStylePoolP() override;
+ };
+} // dbaxml
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/filter/xml/xmlColumn.cxx b/dbaccess/source/filter/xml/xmlColumn.cxx
new file mode 100644
index 000000000..1afbf9f0f
--- /dev/null
+++ b/dbaccess/source/filter/xml/xmlColumn.cxx
@@ -0,0 +1,162 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "xmlColumn.hxx"
+#include "xmlfilter.hxx"
+#include <xmloff/xmltoken.hxx>
+#include <strings.hxx>
+#include <com/sun/star/sdbcx/XDataDescriptorFactory.hpp>
+#include <com/sun/star/sdbcx/XAppend.hpp>
+#include "xmlStyleImport.hxx"
+#include <osl/diagnose.h>
+
+namespace dbaxml
+{
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::beans;
+ using namespace ::com::sun::star::sdbcx;
+ using namespace ::com::sun::star::container;
+ using namespace ::com::sun::star::xml::sax;
+
+OXMLColumn::OXMLColumn( ODBFilter& rImport
+ ,const Reference< XFastAttributeList > & _xAttrList
+ ,const Reference< XNameAccess >& _xParentContainer
+ ,const Reference< XPropertySet >& _xTable
+ ) :
+ SvXMLImportContext( rImport )
+ ,m_xParentContainer(_xParentContainer)
+ ,m_xTable(_xTable)
+ ,m_bHidden(false)
+{
+ OUString sType;
+ for (auto &aIter : sax_fastparser::castToFastAttributeList( _xAttrList ))
+ {
+ switch( aIter.getToken() & TOKEN_MASK )
+ {
+ case XML_NAME:
+ m_sName = aIter.toString();
+ break;
+ case XML_STYLE_NAME:
+ m_sStyleName = aIter.toString();
+ break;
+ case XML_HELP_MESSAGE:
+ m_sHelpMessage = aIter.toString();
+ break;
+ case XML_VISIBILITY:
+ m_bHidden = aIter.toView() != "visible";
+ break;
+ case XML_TYPE_NAME:
+ sType = aIter.toString();
+ OSL_ENSURE(!sType.isEmpty(),"No type name set");
+ break;
+ case XML_DEFAULT_VALUE:
+ if ( !(aIter.isEmpty() || sType.isEmpty()) )
+ m_aDefaultValue <<= aIter.toString();
+ break;
+ case XML_VISIBLE:
+ m_bHidden = aIter.toView() == "false";
+ break;
+ case XML_DEFAULT_CELL_STYLE_NAME:
+ m_sCellStyleName = aIter.toString();
+ break;
+ default:
+ XMLOFF_WARN_UNKNOWN("dbaccess", aIter);
+ }
+ }
+}
+
+OXMLColumn::~OXMLColumn()
+{
+
+}
+
+void OXMLColumn::endFastElement(sal_Int32 )
+{
+ Reference<XDataDescriptorFactory> xFac(m_xParentContainer,UNO_QUERY);
+ if ( xFac.is() && !m_sName.isEmpty() )
+ {
+ Reference<XPropertySet> xProp(xFac->createDataDescriptor());
+ if ( xProp.is() )
+ {
+ xProp->setPropertyValue(PROPERTY_NAME,Any(m_sName));
+ xProp->setPropertyValue(PROPERTY_HIDDEN,Any(m_bHidden));
+ if ( !m_sHelpMessage.isEmpty() )
+ xProp->setPropertyValue(PROPERTY_HELPTEXT,Any(m_sHelpMessage));
+
+ if ( m_aDefaultValue.hasValue() )
+ xProp->setPropertyValue(PROPERTY_CONTROLDEFAULT,m_aDefaultValue);
+
+ Reference<XAppend> xAppend(m_xParentContainer,UNO_QUERY);
+ if ( xAppend.is() )
+ xAppend->appendByDescriptor(xProp);
+ m_xParentContainer->getByName(m_sName) >>= xProp;
+
+ if ( !m_sStyleName.isEmpty() )
+ {
+ const SvXMLStylesContext* pAutoStyles = GetOwnImport().GetAutoStyles();
+ if ( pAutoStyles )
+ {
+ OTableStyleContext* pAutoStyle = const_cast<OTableStyleContext*>(
+ dynamic_cast< const OTableStyleContext* >(pAutoStyles->FindStyleChildContext(XmlStyleFamily::TABLE_COLUMN,m_sStyleName)));
+ if ( pAutoStyle )
+ {
+ pAutoStyle->FillPropertySet(xProp);
+ }
+ }
+ }
+ if ( !m_sCellStyleName.isEmpty() )
+ {
+ const SvXMLStylesContext* pAutoStyles = GetOwnImport().GetAutoStyles();
+ if ( pAutoStyles )
+ {
+ OTableStyleContext* pAutoStyle = const_cast<OTableStyleContext*>(dynamic_cast<const OTableStyleContext* >(pAutoStyles->FindStyleChildContext(XmlStyleFamily::TABLE_CELL,m_sCellStyleName)));
+ if ( pAutoStyle )
+ {
+ pAutoStyle->FillPropertySet(xProp);
+ // we also have to do this on the table to import text-properties
+ pAutoStyle->FillPropertySet(m_xTable);
+ }
+ }
+ }
+
+ }
+ }
+ else if ( !m_sCellStyleName.isEmpty() )
+ {
+ const SvXMLStylesContext* pAutoStyles = GetOwnImport().GetAutoStyles();
+ if ( pAutoStyles )
+ {
+ OTableStyleContext* pAutoStyle = const_cast<OTableStyleContext*>(dynamic_cast< const OTableStyleContext* >(pAutoStyles->FindStyleChildContext(XmlStyleFamily::TABLE_CELL,m_sCellStyleName)));
+ if ( pAutoStyle )
+ {
+ // we also have to do this on the table to import text-properties
+ pAutoStyle->FillPropertySet(m_xTable);
+ }
+ }
+ }
+}
+
+ODBFilter& OXMLColumn::GetOwnImport()
+{
+ return static_cast<ODBFilter&>(GetImport());
+}
+
+} // namespace dbaxml
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/filter/xml/xmlColumn.hxx b/dbaccess/source/filter/xml/xmlColumn.hxx
new file mode 100644
index 000000000..8deca87c7
--- /dev/null
+++ b/dbaccess/source/filter/xml/xmlColumn.hxx
@@ -0,0 +1,53 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <xmloff/xmlictxt.hxx>
+#include <com/sun/star/container/XNameAccess.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+
+namespace dbaxml
+{
+ class ODBFilter;
+ class OXMLColumn : public SvXMLImportContext
+ {
+ css::uno::Reference< css::container::XNameAccess > m_xParentContainer;
+ css::uno::Reference< css::beans::XPropertySet > m_xTable;
+
+ OUString m_sName;
+ OUString m_sStyleName;
+ OUString m_sCellStyleName;
+ OUString m_sHelpMessage;
+ css::uno::Any m_aDefaultValue;
+ bool m_bHidden;
+
+ ODBFilter& GetOwnImport();
+ public:
+
+ OXMLColumn( ODBFilter& rImport
+ ,const css::uno::Reference< css::xml::sax::XFastAttributeList > & xAttrList
+ ,const css::uno::Reference< css::container::XNameAccess >& _xParentContainer
+ ,const css::uno::Reference< css::beans::XPropertySet >& _xTable
+ );
+ virtual ~OXMLColumn() override;
+ virtual void SAL_CALL endFastElement(sal_Int32 nElement) override;
+ };
+} // namespace dbaxml
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/filter/xml/xmlComponent.cxx b/dbaccess/source/filter/xml/xmlComponent.cxx
new file mode 100644
index 000000000..97423f14a
--- /dev/null
+++ b/dbaccess/source/filter/xml/xmlComponent.cxx
@@ -0,0 +1,99 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "xmlComponent.hxx"
+#include "xmlfilter.hxx"
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <strings.hxx>
+#include <com/sun/star/container/XNameContainer.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <tools/diagnose_ex.h>
+#include <comphelper/propertysequence.hxx>
+
+namespace dbaxml
+{
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::beans;
+ using namespace ::com::sun::star::container;
+ using namespace ::com::sun::star::xml::sax;
+
+OXMLComponent::OXMLComponent( ODBFilter& rImport
+ ,const Reference< XFastAttributeList > & _xAttrList
+ ,const Reference< XNameAccess >& _xParentContainer
+ ,const OUString& _sComponentServiceName
+ ) :
+ SvXMLImportContext( rImport )
+{
+ OUString sName;
+ OUString sHREF;
+ bool bAsTemplate(false);
+ for (auto &aIter : sax_fastparser::castToFastAttributeList( _xAttrList ))
+ {
+ switch( aIter.getToken() )
+ {
+ case XML_ELEMENT(XLINK, XML_HREF):
+ sHREF = aIter.toString();
+ break;
+ case XML_ELEMENT(DB, XML_NAME):
+ case XML_ELEMENT(DB_OASIS, XML_NAME):
+ sName = aIter.toString();
+ // sanitize the name. Previously, we allowed to create forms/reports/queries which contain
+ // a / in their name, which nowadays is forbidden. To not lose such objects if they're contained
+ // in older files, we replace the slash with something less offending.
+ sName = sName.replace( '/', '_' );
+ break;
+ case XML_ELEMENT(DB, XML_AS_TEMPLATE):
+ case XML_ELEMENT(DB_OASIS, XML_AS_TEMPLATE):
+ bAsTemplate = IsXMLToken(aIter, XML_TRUE);
+ break;
+ default:
+ XMLOFF_WARN_UNKNOWN("dbaccess", aIter);
+ }
+ }
+ if ( !(!sHREF.isEmpty() && !sName.isEmpty() && _xParentContainer.is()) )
+ return;
+
+ Sequence<Any> aArguments(comphelper::InitAnyPropertySequence(
+ {
+ {PROPERTY_NAME, Any(sName)}, // set as folder
+ {PROPERTY_PERSISTENT_NAME, Any(sHREF.copy(sHREF.lastIndexOf('/')+1))},
+ {PROPERTY_AS_TEMPLATE, Any(bAsTemplate)},
+ }));
+ try
+ {
+ Reference< XMultiServiceFactory > xORB( _xParentContainer, UNO_QUERY_THROW );
+ Reference< XInterface > xComponent( xORB->createInstanceWithArguments( _sComponentServiceName, aArguments ) );
+ Reference< XNameContainer > xNameContainer( _xParentContainer, UNO_QUERY_THROW );
+ xNameContainer->insertByName( sName, Any( xComponent ) );
+ }
+ catch(Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+}
+
+OXMLComponent::~OXMLComponent()
+{
+
+}
+
+} // namespace dbaxml
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/filter/xml/xmlComponent.hxx b/dbaccess/source/filter/xml/xmlComponent.hxx
new file mode 100644
index 000000000..136d5b685
--- /dev/null
+++ b/dbaccess/source/filter/xml/xmlComponent.hxx
@@ -0,0 +1,40 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <xmloff/xmlictxt.hxx>
+#include <com/sun/star/container/XNameAccess.hpp>
+
+namespace dbaxml
+{
+ class ODBFilter;
+ class OXMLComponent : public SvXMLImportContext
+ {
+ public:
+
+ OXMLComponent( ODBFilter& rImport
+ ,const css::uno::Reference< css::xml::sax::XFastAttributeList > & _xAttrList
+ ,const css::uno::Reference< css::container::XNameAccess >& _xParentContainer
+ ,const OUString& _sComponentServiceName
+ );
+ virtual ~OXMLComponent() override;
+ };
+} // namespace dbaxml
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/filter/xml/xmlConnectionData.cxx b/dbaccess/source/filter/xml/xmlConnectionData.cxx
new file mode 100644
index 000000000..221358537
--- /dev/null
+++ b/dbaccess/source/filter/xml/xmlConnectionData.cxx
@@ -0,0 +1,93 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "xmlConnectionData.hxx"
+#include "xmlLogin.hxx"
+#include "xmlfilter.hxx"
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/ProgressBarHelper.hxx>
+#include "xmlEnums.hxx"
+#include "xmlDatabaseDescription.hxx"
+#include "xmlConnectionResource.hxx"
+#include <osl/diagnose.h>
+
+namespace dbaxml
+{
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::xml::sax;
+
+OXMLConnectionData::OXMLConnectionData( ODBFilter& rImport) :
+ SvXMLImportContext( rImport )
+ ,m_bFoundOne(false)
+{
+ rImport.setNewFormat(true);
+}
+
+OXMLConnectionData::~OXMLConnectionData()
+{
+
+}
+
+css::uno::Reference< css::xml::sax::XFastContextHandler > OXMLConnectionData::createFastChildContext(
+ sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
+{
+ SvXMLImportContext *pContext = nullptr;
+
+ switch( nElement & TOKEN_MASK )
+ {
+ case XML_LOGIN:
+ GetOwnImport().GetProgressBarHelper()->Increment( PROGRESS_BAR_STEP );
+ pContext = new OXMLLogin( GetOwnImport(), xAttrList );
+ break;
+ case XML_DATABASE_DESCRIPTION:
+ if ( !m_bFoundOne )
+ {
+ m_bFoundOne = true;
+ GetOwnImport().GetProgressBarHelper()->Increment( PROGRESS_BAR_STEP );
+ pContext = new OXMLDatabaseDescription( GetOwnImport() );
+ }
+ break;
+ case XML_CONNECTION_RESOURCE:
+ if ( !m_bFoundOne )
+ {
+ m_bFoundOne = true;
+ GetOwnImport().GetProgressBarHelper()->Increment( PROGRESS_BAR_STEP );
+ pContext = new OXMLConnectionResource( GetOwnImport(), xAttrList );
+ }
+ break;
+ case XML_COMPOUND_DATABASE:
+ if ( !m_bFoundOne )
+ {
+ m_bFoundOne = true;
+ OSL_FAIL("Not supported yet!");
+ }
+ break;
+ }
+
+ return pContext;
+}
+
+ODBFilter& OXMLConnectionData::GetOwnImport()
+{
+ return static_cast<ODBFilter&>(GetImport());
+}
+
+} // namespace dbaxml
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/filter/xml/xmlConnectionData.hxx b/dbaccess/source/filter/xml/xmlConnectionData.hxx
new file mode 100644
index 000000000..466c04788
--- /dev/null
+++ b/dbaccess/source/filter/xml/xmlConnectionData.hxx
@@ -0,0 +1,41 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <xmloff/xmlictxt.hxx>
+
+namespace dbaxml
+{
+ class ODBFilter;
+ class OXMLConnectionData : public SvXMLImportContext
+ {
+ bool m_bFoundOne;
+
+ ODBFilter& GetOwnImport();
+ public:
+
+ OXMLConnectionData( ODBFilter& rImport );
+ virtual ~OXMLConnectionData() override;
+
+ virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
+ sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList >& AttrList ) override;
+ };
+} // namespace dbaxml
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/filter/xml/xmlConnectionResource.cxx b/dbaccess/source/filter/xml/xmlConnectionResource.cxx
new file mode 100644
index 000000000..2df2a1a73
--- /dev/null
+++ b/dbaccess/source/filter/xml/xmlConnectionResource.cxx
@@ -0,0 +1,88 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "xmlConnectionResource.hxx"
+#include "xmlfilter.hxx"
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <strings.hxx>
+#include <tools/diagnose_ex.h>
+
+namespace dbaxml
+{
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::xml::sax;
+
+OXMLConnectionResource::OXMLConnectionResource( ODBFilter& rImport,
+ const Reference< XFastAttributeList > & _xAttrList) :
+ SvXMLImportContext( rImport )
+{
+ Reference<XPropertySet> xDataSource = rImport.getDataSource();
+
+ PropertyValue aProperty;
+
+ if (!xDataSource.is())
+ return;
+
+ for (auto &aIter : sax_fastparser::castToFastAttributeList( _xAttrList ))
+ {
+ aProperty.Name.clear();
+ aProperty.Value = Any();
+
+ switch( aIter.getToken() )
+ {
+ case XML_ELEMENT(XLINK, XML_HREF):
+ try
+ {
+ xDataSource->setPropertyValue(PROPERTY_URL,Any(aIter.toString()));
+ }
+ catch(const Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ break;
+ case XML_ELEMENT(XLINK, XML_TYPE):
+ aProperty.Name = PROPERTY_TYPE;
+ break;
+ case XML_ELEMENT(XLINK, XML_SHOW):
+ aProperty.Name = "Show";
+ break;
+ case XML_ELEMENT(XLINK, XML_ACTUATE):
+ aProperty.Name = "Actuate";
+ break;
+ default:
+ XMLOFF_WARN_UNKNOWN("dbaccess", aIter);
+ }
+ if ( !aProperty.Name.isEmpty() )
+ {
+ if ( !aProperty.Value.hasValue() )
+ aProperty.Value <<= aIter.toString();
+ rImport.addInfo(aProperty);
+ }
+ }
+}
+
+OXMLConnectionResource::~OXMLConnectionResource()
+{
+
+}
+
+} // namespace dbaxml
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/filter/xml/xmlConnectionResource.hxx b/dbaccess/source/filter/xml/xmlConnectionResource.hxx
new file mode 100644
index 000000000..357bbe1e1
--- /dev/null
+++ b/dbaccess/source/filter/xml/xmlConnectionResource.hxx
@@ -0,0 +1,36 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <xmloff/xmlictxt.hxx>
+
+namespace dbaxml
+{
+ class ODBFilter;
+ class OXMLConnectionResource : public SvXMLImportContext
+ {
+ public:
+
+ OXMLConnectionResource( ODBFilter& rImport,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList );
+ virtual ~OXMLConnectionResource() override;
+ };
+} // namespace dbaxml
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/filter/xml/xmlDataSource.cxx b/dbaccess/source/filter/xml/xmlDataSource.cxx
new file mode 100644
index 000000000..bf63d4f79
--- /dev/null
+++ b/dbaccess/source/filter/xml/xmlDataSource.cxx
@@ -0,0 +1,251 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "xmlDataSource.hxx"
+#include "xmlLogin.hxx"
+#include "xmlTableFilterList.hxx"
+#include "xmlDataSourceInfo.hxx"
+#include "xmlDataSourceSettings.hxx"
+#include "xmlfilter.hxx"
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/ProgressBarHelper.hxx>
+#include "xmlEnums.hxx"
+#include <strings.hxx>
+#include <tools/diagnose_ex.h>
+#include "xmlConnectionData.hxx"
+
+namespace dbaxml
+{
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::xml::sax;
+
+OXMLDataSource::OXMLDataSource( ODBFilter& rImport,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& _xAttrList,
+ const UsedFor _eUsedFor ) :
+ SvXMLImportContext( rImport )
+{
+
+ Reference<XPropertySet> xDataSource = rImport.getDataSource();
+
+ PropertyValue aProperty;
+ bool bFoundParamNameSubstitution = false;
+ bool bFoundTableNameLengthLimited = false;
+ bool bFoundAppendTableAliasName = false;
+ bool bFoundSuppressVersionColumns = false;
+
+ if (xDataSource.is())
+ {
+ for (auto &aIter : sax_fastparser::castToFastAttributeList( _xAttrList ))
+ {
+ aProperty.Name.clear();
+ aProperty.Value = Any();
+
+ switch( aIter.getToken() & TOKEN_MASK )
+ {
+ case XML_CONNECTION_RESOURCE:
+ try
+ {
+ xDataSource->setPropertyValue(PROPERTY_URL,Any(aIter.toString()));
+ }
+ catch(const Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ break;
+ case XML_SUPPRESS_VERSION_COLUMNS:
+ try
+ {
+ xDataSource->setPropertyValue(PROPERTY_SUPPRESSVERSIONCL,Any(IsXMLToken(aIter, XML_TRUE)));
+ bFoundSuppressVersionColumns = true;
+ }
+ catch(const Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ break;
+ case XML_JAVA_DRIVER_CLASS:
+ aProperty.Name = INFO_JDBCDRIVERCLASS;
+ break;
+ case XML_EXTENSION:
+ aProperty.Name = INFO_TEXTFILEEXTENSION;
+ break;
+ case XML_IS_FIRST_ROW_HEADER_LINE:
+ aProperty.Name = INFO_TEXTFILEHEADER;
+ aProperty.Value <<= IsXMLToken(aIter, XML_TRUE);
+ break;
+ case XML_SHOW_DELETED:
+ aProperty.Name = INFO_SHOWDELETEDROWS;
+ aProperty.Value <<= IsXMLToken(aIter, XML_TRUE);
+ break;
+ case XML_IS_TABLE_NAME_LENGTH_LIMITED:
+ aProperty.Name = INFO_ALLOWLONGTABLENAMES;
+ aProperty.Value <<= IsXMLToken(aIter, XML_TRUE);
+ bFoundTableNameLengthLimited = true;
+ break;
+ case XML_SYSTEM_DRIVER_SETTINGS:
+ aProperty.Name = INFO_ADDITIONALOPTIONS;
+ break;
+ case XML_ENABLE_SQL92_CHECK:
+ aProperty.Name = PROPERTY_ENABLESQL92CHECK;
+ aProperty.Value <<= IsXMLToken(aIter, XML_TRUE);
+ break;
+ case XML_APPEND_TABLE_ALIAS_NAME:
+ aProperty.Name = INFO_APPEND_TABLE_ALIAS;
+ aProperty.Value <<= IsXMLToken(aIter, XML_TRUE);
+ bFoundAppendTableAliasName = true;
+ break;
+ case XML_PARAMETER_NAME_SUBSTITUTION:
+ aProperty.Name = INFO_PARAMETERNAMESUBST;
+ aProperty.Value <<= IsXMLToken(aIter, XML_TRUE);
+ bFoundParamNameSubstitution = true;
+ break;
+ case XML_IGNORE_DRIVER_PRIVILEGES:
+ aProperty.Name = INFO_IGNOREDRIVER_PRIV;
+ aProperty.Value <<= IsXMLToken(aIter, XML_TRUE);
+ break;
+ case XML_BOOLEAN_COMPARISON_MODE:
+ aProperty.Name = PROPERTY_BOOLEANCOMPARISONMODE;
+ if ( aIter.toView() == "equal-integer" )
+ aProperty.Value <<= sal_Int32(0);
+ else if ( aIter.toView() == "is-boolean" )
+ aProperty.Value <<= sal_Int32(1);
+ else if ( aIter.toView() == "equal-boolean" )
+ aProperty.Value <<= sal_Int32(2);
+ else if ( aIter.toView() == "equal-use-only-zero" )
+ aProperty.Value <<= sal_Int32(3);
+ break;
+ case XML_USE_CATALOG:
+ aProperty.Name = INFO_USECATALOG;
+ aProperty.Value <<= IsXMLToken(aIter, XML_TRUE);
+ break;
+ case XML_BASE_DN:
+ aProperty.Name = INFO_CONN_LDAP_BASEDN;
+ break;
+ case XML_MAX_ROW_COUNT:
+ aProperty.Name = INFO_CONN_LDAP_ROWCOUNT;
+ aProperty.Value <<= aIter.toInt32();
+ break;
+ case XML_JAVA_CLASSPATH:
+ aProperty.Name = "JavaDriverClassPath";
+ break;
+ default:
+ XMLOFF_WARN_UNKNOWN("dbaccess", aIter);
+ }
+ if ( !aProperty.Name.isEmpty() )
+ {
+ if ( !aProperty.Value.hasValue() )
+ aProperty.Value <<= aIter.toString();
+ rImport.addInfo(aProperty);
+ }
+ }
+ }
+ if ( !rImport.isNewFormat() )
+ return;
+
+ if ( !bFoundTableNameLengthLimited && ( _eUsedFor == eAppSettings ) )
+ {
+ aProperty.Name = INFO_ALLOWLONGTABLENAMES;
+ aProperty.Value <<= true;
+ rImport.addInfo(aProperty);
+ }
+ if ( !bFoundParamNameSubstitution && ( _eUsedFor == eDriverSettings ) )
+ {
+ aProperty.Name = INFO_PARAMETERNAMESUBST;
+ aProperty.Value <<= true;
+ rImport.addInfo(aProperty);
+ }
+ if ( !bFoundAppendTableAliasName && ( _eUsedFor == eAppSettings ) )
+ {
+ aProperty.Name = INFO_APPEND_TABLE_ALIAS;
+ aProperty.Value <<= true;
+ rImport.addInfo(aProperty);
+ }
+ if ( !bFoundSuppressVersionColumns && ( _eUsedFor == eAppSettings ) )
+ {
+ try
+ {
+ xDataSource->setPropertyValue(PROPERTY_SUPPRESSVERSIONCL,Any(true));
+ }
+ catch(const Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+}
+
+OXMLDataSource::~OXMLDataSource()
+{
+
+}
+
+css::uno::Reference< css::xml::sax::XFastContextHandler > OXMLDataSource::createFastChildContext(
+ sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
+{
+ SvXMLImportContext *pContext = nullptr;
+
+ switch( nElement & TOKEN_MASK )
+ {
+ case XML_LOGIN:
+ GetOwnImport().GetProgressBarHelper()->Increment( PROGRESS_BAR_STEP );
+ pContext = new OXMLLogin( GetOwnImport(), xAttrList );
+ break;
+
+ case XML_TABLE_FILTER:
+ case XML_TABLE_TYPE_FILTER:
+ GetOwnImport().GetProgressBarHelper()->Increment( PROGRESS_BAR_STEP );
+ pContext = new OXMLTableFilterList( GetImport() );
+ break;
+ case XML_AUTO_INCREMENT:
+ case XML_DELIMITER:
+ case XML_FONT_CHARSET:
+ case XML_CHARACTER_SET:
+ GetOwnImport().GetProgressBarHelper()->Increment( PROGRESS_BAR_STEP );
+ pContext = new OXMLDataSourceInfo( GetOwnImport(), nElement, xAttrList );
+ break;
+ case XML_DATA_SOURCE_SETTINGS:
+ GetOwnImport().GetProgressBarHelper()->Increment( PROGRESS_BAR_STEP );
+ pContext = new OXMLDataSourceSettings( GetOwnImport() );
+ break;
+ case XML_CONNECTION_DATA:
+ GetOwnImport().GetProgressBarHelper()->Increment( PROGRESS_BAR_STEP );
+ pContext = new OXMLConnectionData( GetOwnImport() );
+ break;
+ case XML_DRIVER_SETTINGS:
+ GetOwnImport().GetProgressBarHelper()->Increment( PROGRESS_BAR_STEP );
+ pContext = new OXMLDataSource( GetOwnImport(), xAttrList, OXMLDataSource::eDriverSettings );
+ break;
+ case XML_APPLICATION_CONNECTION_SETTINGS:
+ GetOwnImport().GetProgressBarHelper()->Increment( PROGRESS_BAR_STEP );
+ pContext = new OXMLDataSource( GetOwnImport(), xAttrList, OXMLDataSource::eAppSettings );
+ break;
+ default:
+ SAL_WARN("dbaccess", "unknown element " << nElement);
+ }
+
+ return pContext;
+}
+
+ODBFilter& OXMLDataSource::GetOwnImport()
+{
+ return static_cast<ODBFilter&>(GetImport());
+}
+
+} // namespace dbaxml
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/filter/xml/xmlDataSource.hxx b/dbaccess/source/filter/xml/xmlDataSource.hxx
new file mode 100644
index 000000000..5b78ff4fe
--- /dev/null
+++ b/dbaccess/source/filter/xml/xmlDataSource.hxx
@@ -0,0 +1,47 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <xmloff/xmlictxt.hxx>
+
+namespace dbaxml
+{
+ class ODBFilter;
+ class OXMLDataSource : public SvXMLImportContext
+ {
+ ODBFilter& GetOwnImport();
+ public:
+ enum UsedFor
+ {
+ eDataSource,
+ eDriverSettings,
+ eAppSettings
+ };
+
+ OXMLDataSource( ODBFilter& rImport,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& _xAttrList,
+ const UsedFor _eUsedFor );
+ virtual ~OXMLDataSource() override;
+
+ virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
+ sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList >& AttrList ) override;
+ };
+} // namespace dbaxml
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/filter/xml/xmlDataSourceInfo.cxx b/dbaccess/source/filter/xml/xmlDataSourceInfo.cxx
new file mode 100644
index 000000000..eefc08e41
--- /dev/null
+++ b/dbaccess/source/filter/xml/xmlDataSourceInfo.cxx
@@ -0,0 +1,119 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "xmlDataSourceInfo.hxx"
+#include "xmlfilter.hxx"
+#include <xmloff/xmltoken.hxx>
+#include <strings.hxx>
+#include <com/sun/star/beans/PropertyValue.hpp>
+
+namespace dbaxml
+{
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::xml::sax;
+
+OXMLDataSourceInfo::OXMLDataSourceInfo( ODBFilter& rImport
+ ,sal_Int32 nElement
+ ,const Reference< XFastAttributeList > & _xAttrList) :
+ SvXMLImportContext( rImport )
+{
+ PropertyValue aProperty;
+ bool bAutoEnabled = false;
+ bool bFoundField = false,bFoundThousand = false, bFoundCharset = false;
+ for (auto &aIter : sax_fastparser::castToFastAttributeList( _xAttrList ))
+ {
+ aProperty.Name.clear();
+
+ switch( aIter.getToken() & TOKEN_MASK )
+ {
+ case XML_ADDITIONAL_COLUMN_STATEMENT:
+ aProperty.Name = PROPERTY_AUTOINCREMENTCREATION;
+ bAutoEnabled = true;
+ break;
+ case XML_ROW_RETRIEVING_STATEMENT:
+ aProperty.Name = INFO_AUTORETRIEVEVALUE;
+ bAutoEnabled = true;
+ break;
+ case XML_STRING:
+ aProperty.Name = INFO_TEXTDELIMITER;
+ break;
+ case XML_FIELD:
+ aProperty.Name = INFO_FIELDDELIMITER;
+ bFoundField = true;
+ break;
+ case XML_DECIMAL:
+ aProperty.Name = INFO_DECIMALDELIMITER;
+ break;
+ case XML_THOUSAND:
+ aProperty.Name = INFO_THOUSANDSDELIMITER;
+ bFoundThousand = true;
+ break;
+ case XML_ENCODING:
+ aProperty.Name = INFO_CHARSET;
+ bFoundCharset = true;
+ break;
+ default:
+ XMLOFF_WARN_UNKNOWN("dbaccess", aIter);
+ }
+ if ( !aProperty.Name.isEmpty() )
+ {
+ aProperty.Value <<= aIter.toString();
+ rImport.addInfo(aProperty);
+ }
+ }
+ if ( bAutoEnabled )
+ {
+ aProperty.Name = INFO_AUTORETRIEVEENABLED;
+ aProperty.Value <<= true;
+ rImport.addInfo(aProperty);
+ }
+ if ( !rImport.isNewFormat() )
+ return;
+
+ if ( (nElement & TOKEN_MASK) == XML_DELIMITER )
+ {
+ if ( !bFoundField )
+ {
+ aProperty.Name = INFO_FIELDDELIMITER;
+ aProperty.Value <<= OUString(";");
+ rImport.addInfo(aProperty);
+ }
+ if ( !bFoundThousand )
+ {
+ aProperty.Name = INFO_THOUSANDSDELIMITER;
+ aProperty.Value <<= OUString(",");
+ rImport.addInfo(aProperty);
+ }
+ }
+ if ( (nElement & TOKEN_MASK) == XML_FONT_CHARSET && !bFoundCharset )
+ {
+ aProperty.Name = INFO_CHARSET;
+ aProperty.Value <<= OUString("utf8");
+ rImport.addInfo(aProperty);
+ }
+}
+
+OXMLDataSourceInfo::~OXMLDataSourceInfo()
+{
+
+}
+
+} // namespace dbaxml
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/filter/xml/xmlDataSourceInfo.hxx b/dbaccess/source/filter/xml/xmlDataSourceInfo.hxx
new file mode 100644
index 000000000..e29d37a7d
--- /dev/null
+++ b/dbaccess/source/filter/xml/xmlDataSourceInfo.hxx
@@ -0,0 +1,37 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <xmloff/xmlictxt.hxx>
+
+namespace dbaxml
+{
+ class ODBFilter;
+ class OXMLDataSourceInfo : public SvXMLImportContext
+ {
+ public:
+
+ OXMLDataSourceInfo( ODBFilter& rImport,
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList > & _xAttrList);
+ virtual ~OXMLDataSourceInfo() override;
+ };
+} // namespace dbaxml
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/filter/xml/xmlDataSourceSetting.cxx b/dbaccess/source/filter/xml/xmlDataSourceSetting.cxx
new file mode 100644
index 000000000..9402bb399
--- /dev/null
+++ b/dbaccess/source/filter/xml/xmlDataSourceSetting.cxx
@@ -0,0 +1,215 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+#include <sal/log.hxx>
+
+#include <map>
+
+#include "xmlDataSourceSetting.hxx"
+#include <sax/tools/converter.hxx>
+#include "xmlfilter.hxx"
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/ProgressBarHelper.hxx>
+#include "xmlEnums.hxx"
+#include <osl/diagnose.h>
+
+namespace dbaxml
+{
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::xml::sax;
+
+OXMLDataSourceSetting::OXMLDataSourceSetting( ODBFilter& rImport
+ ,const Reference< XFastAttributeList > & _xAttrList
+ ,OXMLDataSourceSetting* _pContainer) :
+ SvXMLImportContext( rImport )
+ ,m_pContainer(_pContainer)
+ ,m_bIsList(false)
+{
+
+ m_aPropType = cppu::UnoType<void>::get();
+
+ for (auto &aIter : sax_fastparser::castToFastAttributeList( _xAttrList ))
+ {
+ switch( aIter.getToken() & TOKEN_MASK )
+ {
+ case XML_DATA_SOURCE_SETTING_IS_LIST:
+ m_bIsList = aIter.toView() == "true";
+ break;
+ case XML_DATA_SOURCE_SETTING_TYPE:
+ {
+ // needs to be translated into a css::uno::Type
+ static std::map< OUString, css::uno::Type > s_aTypeNameMap = []()
+ {
+ std::map< OUString, css::uno::Type > tmp;
+ tmp[GetXMLToken( XML_BOOLEAN)] = cppu::UnoType<bool>::get();
+ // Not a copy paste error, see comment xmloff/source/forms/propertyimport.cxx lines 244-248
+ tmp[GetXMLToken( XML_FLOAT)] = ::cppu::UnoType<double>::get();
+ tmp[GetXMLToken( XML_DOUBLE)] = ::cppu::UnoType<double>::get();
+ tmp[GetXMLToken( XML_STRING)] = ::cppu::UnoType<OUString>::get();
+ tmp[GetXMLToken( XML_INT)] = ::cppu::UnoType<sal_Int32>::get();
+ tmp[GetXMLToken( XML_SHORT)] = ::cppu::UnoType<sal_Int16>::get();
+ tmp[GetXMLToken( XML_VOID)] = cppu::UnoType<void>::get();
+ return tmp;
+ }();
+
+ const std::map< OUString, css::uno::Type >::const_iterator aTypePos = s_aTypeNameMap.find(aIter.toString());
+ OSL_ENSURE(s_aTypeNameMap.end() != aTypePos, "OXMLDataSourceSetting::OXMLDataSourceSetting: invalid type!");
+ if (s_aTypeNameMap.end() != aTypePos)
+ m_aPropType = aTypePos->second;
+ }
+ break;
+ case XML_DATA_SOURCE_SETTING_NAME:
+ m_aSetting.Name = aIter.toString();
+ break;
+ default:
+ XMLOFF_WARN_UNKNOWN("dbaccess", aIter);
+ }
+ }
+
+}
+
+OXMLDataSourceSetting::~OXMLDataSourceSetting()
+{
+}
+
+css::uno::Reference< css::xml::sax::XFastContextHandler > OXMLDataSourceSetting::createFastChildContext(
+ sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
+{
+ SvXMLImportContext *pContext = nullptr;
+
+ switch( nElement & TOKEN_MASK )
+ {
+ case XML_DATA_SOURCE_SETTING:
+ GetOwnImport().GetProgressBarHelper()->Increment( PROGRESS_BAR_STEP );
+ pContext = new OXMLDataSourceSetting( GetOwnImport(), xAttrList);
+ break;
+ case XML_DATA_SOURCE_SETTING_VALUE:
+ GetOwnImport().GetProgressBarHelper()->Increment( PROGRESS_BAR_STEP );
+ pContext = new OXMLDataSourceSetting( GetOwnImport(), xAttrList,this );
+ break;
+ }
+
+ return pContext;
+}
+
+void OXMLDataSourceSetting::endFastElement(sal_Int32 )
+{
+ if ( !m_aSetting.Name.isEmpty() )
+ {
+ if ( m_bIsList && m_aInfoSequence.hasElements() )
+ m_aSetting.Value <<= m_aInfoSequence;
+
+ // if our property is of type string, but was empty, ensure that
+ // we don't add a VOID value
+ if ( !m_bIsList && ( m_aPropType.getTypeClass() == TypeClass_STRING ) && !m_aSetting.Value.hasValue() )
+ m_aSetting.Value <<= OUString();
+
+ GetOwnImport().addInfo(m_aSetting);
+ }
+}
+
+void OXMLDataSourceSetting::characters( const OUString& rChars )
+{
+ if ( m_pContainer )
+ m_pContainer->addValue(rChars);
+}
+
+void OXMLDataSourceSetting::addValue(const OUString& _sValue)
+{
+ Any aValue;
+ if( TypeClass_VOID != m_aPropType.getTypeClass() )
+ aValue = convertString(m_aPropType, _sValue);
+
+ if ( !m_bIsList )
+ m_aSetting.Value = aValue;
+ else
+ {
+ sal_Int32 nPos = m_aInfoSequence.getLength();
+ m_aInfoSequence.realloc(nPos+1);
+ m_aInfoSequence.getArray()[nPos] = aValue;
+ }
+}
+
+ODBFilter& OXMLDataSourceSetting::GetOwnImport()
+{
+ return static_cast<ODBFilter&>(GetImport());
+}
+
+Any OXMLDataSourceSetting::convertString(const css::uno::Type& _rExpectedType, const OUString& _rReadCharacters)
+{
+ Any aReturn;
+ switch (_rExpectedType.getTypeClass())
+ {
+ case TypeClass_BOOLEAN: // sal_Bool
+ {
+ bool bValue(false);
+ bool const bSuccess =
+ ::sax::Converter::convertBool(bValue, _rReadCharacters);
+ SAL_WARN_IF(!bSuccess, "dbaccess",
+ "OXMLDataSourceSetting::convertString: could not convert \""
+ << _rReadCharacters << "\" into a boolean!");
+ aReturn <<= bValue;
+ }
+ break;
+ case TypeClass_SHORT: // sal_Int16
+ case TypeClass_LONG: // sal_Int32
+ { // it's a real int32/16 property
+ sal_Int32 nValue(0);
+ bool const bSuccess =
+ ::sax::Converter::convertNumber(nValue, _rReadCharacters);
+ SAL_WARN_IF(!bSuccess, "dbaccess",
+ "OXMLDataSourceSetting::convertString: could not convert \""
+ << _rReadCharacters << "\" into an integer!");
+ if (TypeClass_SHORT == _rExpectedType.getTypeClass())
+ aReturn <<= static_cast<sal_Int16>(nValue);
+ else
+ aReturn <<= nValue;
+ break;
+ }
+ case TypeClass_HYPER:
+ {
+ OSL_FAIL("OXMLDataSourceSetting::convertString: 64-bit integers not implemented yet!");
+ }
+ break;
+ case TypeClass_DOUBLE:
+ {
+ double nValue = 0.0;
+ bool const bSuccess =
+ ::sax::Converter::convertDouble(nValue, _rReadCharacters);
+ SAL_WARN_IF(!bSuccess, "dbaccess",
+ "OXMLDataSourceSetting::convertString: could not convert \""
+ << _rReadCharacters << "\" into a double!");
+ aReturn <<= nValue;
+ }
+ break;
+ case TypeClass_STRING:
+ aReturn <<= _rReadCharacters;
+ break;
+ default:
+ SAL_WARN("dbaccess",
+ "OXMLDataSourceSetting::convertString: invalid type class!");
+ }
+
+ return aReturn;
+}
+
+} // namespace dbaxml
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/filter/xml/xmlDataSourceSetting.hxx b/dbaccess/source/filter/xml/xmlDataSourceSetting.hxx
new file mode 100644
index 000000000..3ed92f80e
--- /dev/null
+++ b/dbaccess/source/filter/xml/xmlDataSourceSetting.hxx
@@ -0,0 +1,60 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <xmloff/xmlictxt.hxx>
+#include <com/sun/star/beans/PropertyValue.hpp>
+#include <com/sun/star/uno/Sequence.hxx>
+
+namespace dbaxml
+{
+ class ODBFilter;
+ class OXMLDataSourceSetting : public SvXMLImportContext
+ {
+ css::beans::PropertyValue m_aSetting;
+ css::uno::Sequence< css::uno::Any> m_aInfoSequence;
+ OXMLDataSourceSetting* m_pContainer;
+ css::uno::Type m_aPropType; // the type of the property the instance imports currently
+ bool m_bIsList;
+
+ ODBFilter& GetOwnImport();
+ static css::uno::Any convertString(const css::uno::Type& _rExpectedType, const OUString& _rReadCharacters);
+ public:
+
+ OXMLDataSourceSetting( ODBFilter& rImport
+ ,const css::uno::Reference< css::xml::sax::XFastAttributeList > & _xAttrList
+ ,OXMLDataSourceSetting* _pContainer = nullptr);
+ virtual ~OXMLDataSourceSetting() override;
+
+ virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
+ sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList >& AttrList ) override;
+
+ virtual void SAL_CALL endFastElement(sal_Int32 nElement) override;
+
+ virtual void SAL_CALL characters( const OUString& rChars ) override;
+
+ /** adds value to property
+ @param _sValue
+ The value to add.
+ */
+ void addValue(const OUString& _sValue);
+ };
+} // namespace dbaxml
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/filter/xml/xmlDataSourceSettings.cxx b/dbaccess/source/filter/xml/xmlDataSourceSettings.cxx
new file mode 100644
index 000000000..49847ef54
--- /dev/null
+++ b/dbaccess/source/filter/xml/xmlDataSourceSettings.cxx
@@ -0,0 +1,66 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "xmlDataSourceSettings.hxx"
+#include "xmlDataSourceSetting.hxx"
+#include "xmlfilter.hxx"
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/ProgressBarHelper.hxx>
+#include "xmlEnums.hxx"
+
+namespace dbaxml
+{
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::xml::sax;
+
+OXMLDataSourceSettings::OXMLDataSourceSettings( ODBFilter& rImport ) :
+ SvXMLImportContext( rImport )
+{
+
+}
+
+OXMLDataSourceSettings::~OXMLDataSourceSettings()
+{
+
+}
+
+css::uno::Reference< css::xml::sax::XFastContextHandler > OXMLDataSourceSettings::createFastChildContext(
+ sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
+{
+ SvXMLImportContext *pContext = nullptr;
+
+ switch( nElement & TOKEN_MASK )
+ {
+ case XML_DATA_SOURCE_SETTING:
+ GetOwnImport().GetProgressBarHelper()->Increment( PROGRESS_BAR_STEP );
+ pContext = new OXMLDataSourceSetting( GetOwnImport(), xAttrList );
+ break;
+ }
+
+ return pContext;
+}
+
+ODBFilter& OXMLDataSourceSettings::GetOwnImport()
+{
+ return static_cast<ODBFilter&>(GetImport());
+}
+
+} // namespace dbaxml
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/filter/xml/xmlDataSourceSettings.hxx b/dbaccess/source/filter/xml/xmlDataSourceSettings.hxx
new file mode 100644
index 000000000..50fea5c00
--- /dev/null
+++ b/dbaccess/source/filter/xml/xmlDataSourceSettings.hxx
@@ -0,0 +1,39 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <xmloff/xmlictxt.hxx>
+
+namespace dbaxml
+{
+ class ODBFilter;
+ class OXMLDataSourceSettings : public SvXMLImportContext
+ {
+ ODBFilter& GetOwnImport();
+ public:
+
+ OXMLDataSourceSettings( ODBFilter& rImport );
+ virtual ~OXMLDataSourceSettings() override;
+
+ virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
+ sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList >& AttrList ) override;
+ };
+} // namespace dbaxml
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/filter/xml/xmlDatabase.cxx b/dbaccess/source/filter/xml/xmlDatabase.cxx
new file mode 100644
index 000000000..2f629caff
--- /dev/null
+++ b/dbaccess/source/filter/xml/xmlDatabase.cxx
@@ -0,0 +1,135 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "xmlDatabase.hxx"
+#include "xmlfilter.hxx"
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/ProgressBarHelper.hxx>
+#include "xmlDataSource.hxx"
+#include "xmlDocuments.hxx"
+#include "xmlEnums.hxx"
+#include <com/sun/star/frame/XModel.hpp>
+#include <com/sun/star/sdb/XReportDocumentsSupplier.hpp>
+#include <com/sun/star/sdb/XFormDocumentsSupplier.hpp>
+#include <com/sun/star/sdbcx/XTablesSupplier.hpp>
+#include <com/sun/star/sdb/XQueryDefinitionsSupplier.hpp>
+#include <strings.hxx>
+#include <connectivity/dbtools.hxx>
+
+namespace dbaxml
+{
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::sdb;
+ using namespace ::com::sun::star::sdbcx;
+ using namespace ::com::sun::star::xml::sax;
+
+OXMLDatabase::OXMLDatabase( ODBFilter& rImport ) :
+ SvXMLImportContext( rImport )
+{
+
+}
+
+OXMLDatabase::~OXMLDatabase()
+{
+
+}
+
+css::uno::Reference< css::xml::sax::XFastContextHandler > OXMLDatabase::createFastChildContext(
+ sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
+{
+ SvXMLImportContext *pContext = nullptr;
+
+ switch( nElement & TOKEN_MASK )
+ {
+ case XML_DATA_SOURCE:
+ GetOwnImport().GetProgressBarHelper()->Increment( PROGRESS_BAR_STEP );
+ pContext = new OXMLDataSource( GetOwnImport(), xAttrList, OXMLDataSource::eDataSource );
+ break;
+ case XML_FORMS:
+ {
+ GetOwnImport().GetProgressBarHelper()->Increment( PROGRESS_BAR_STEP );
+ Any aValue;
+ OUString sService;
+ dbtools::getDataSourceSetting(GetOwnImport().getDataSource(),"Forms",aValue);
+ aValue >>= sService;
+ if ( sService.isEmpty() )
+ {
+ Reference<XFormDocumentsSupplier> xSup(GetOwnImport().GetModel(),UNO_QUERY);
+ if ( xSup.is() )
+ pContext = new OXMLDocuments( GetOwnImport(), xSup->getFormDocuments(),SERVICE_NAME_FORM_COLLECTION,SERVICE_SDB_DOCUMENTDEFINITION);
+ }
+ }
+ break;
+ case XML_REPORTS:
+ {
+ GetOwnImport().GetProgressBarHelper()->Increment( PROGRESS_BAR_STEP );
+ Any aValue;
+ OUString sService;
+ dbtools::getDataSourceSetting(GetOwnImport().getDataSource(),"Reports",aValue);
+ aValue >>= sService;
+ if ( sService.isEmpty() )
+ {
+ Reference<XReportDocumentsSupplier> xSup(GetOwnImport().GetModel(),UNO_QUERY);
+ if ( xSup.is() )
+ pContext = new OXMLDocuments( GetOwnImport(), xSup->getReportDocuments(),SERVICE_NAME_REPORT_COLLECTION,SERVICE_SDB_DOCUMENTDEFINITION);
+ }
+ }
+ break;
+ case XML_QUERIES:
+ {
+ GetOwnImport().GetProgressBarHelper()->Increment( PROGRESS_BAR_STEP );
+ Any aValue;
+ OUString sService;
+ dbtools::getDataSourceSetting(GetOwnImport().getDataSource(),"CommandDefinitions",aValue);
+ aValue >>= sService;
+ if ( sService.isEmpty() )
+ {
+ Reference<XQueryDefinitionsSupplier> xSup(GetOwnImport().getDataSource(),UNO_QUERY);
+ if ( xSup.is() )
+ pContext = new OXMLDocuments( GetOwnImport(), xSup->getQueryDefinitions(),SERVICE_NAME_QUERY_COLLECTION);
+ }
+ }
+ break;
+ case XML_TABLE_REPRESENTATIONS:
+ case XML_SCHEMA_DEFINITION:
+ {
+ GetOwnImport().GetProgressBarHelper()->Increment( PROGRESS_BAR_STEP );
+ Reference<XTablesSupplier> xSup(GetOwnImport().getDataSource(),UNO_QUERY);
+ if ( xSup.is() )
+ pContext = new OXMLDocuments( GetOwnImport(), xSup->getTables());
+ }
+ break;
+ }
+
+ return pContext;
+}
+
+ODBFilter& OXMLDatabase::GetOwnImport()
+{
+ return static_cast<ODBFilter&>(GetImport());
+}
+
+void OXMLDatabase::endFastElement(sal_Int32)
+{
+ GetOwnImport().setPropertyInfo();
+}
+
+} // namespace dbaxml
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/filter/xml/xmlDatabase.hxx b/dbaccess/source/filter/xml/xmlDatabase.hxx
new file mode 100644
index 000000000..0dab56c51
--- /dev/null
+++ b/dbaccess/source/filter/xml/xmlDatabase.hxx
@@ -0,0 +1,41 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <xmloff/xmlictxt.hxx>
+
+namespace dbaxml
+{
+ class ODBFilter;
+ class OXMLDatabase final : public SvXMLImportContext
+ {
+ ODBFilter& GetOwnImport();
+ public:
+
+ OXMLDatabase( ODBFilter& rImport );
+ virtual ~OXMLDatabase() override;
+
+ virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
+ sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList >& AttrList ) override;
+
+ virtual void SAL_CALL endFastElement(sal_Int32 nElement) override;
+ };
+} // namespace dbaxml
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/filter/xml/xmlDatabaseDescription.cxx b/dbaccess/source/filter/xml/xmlDatabaseDescription.cxx
new file mode 100644
index 000000000..a8168e129
--- /dev/null
+++ b/dbaccess/source/filter/xml/xmlDatabaseDescription.cxx
@@ -0,0 +1,79 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "xmlDatabaseDescription.hxx"
+#include "xmlfilter.hxx"
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/ProgressBarHelper.hxx>
+#include "xmlEnums.hxx"
+#include "xmlFileBasedDatabase.hxx"
+#include "xmlServerDatabase.hxx"
+
+namespace dbaxml
+{
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::xml::sax;
+
+OXMLDatabaseDescription::OXMLDatabaseDescription( ODBFilter& rImport ) :
+ SvXMLImportContext( rImport )
+ ,m_bFoundOne(false)
+{
+}
+
+OXMLDatabaseDescription::~OXMLDatabaseDescription()
+{
+
+}
+
+css::uno::Reference< css::xml::sax::XFastContextHandler > OXMLDatabaseDescription::createFastChildContext(
+ sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
+{
+ SvXMLImportContext *pContext = nullptr;
+
+ switch( nElement & TOKEN_MASK )
+ {
+ case XML_FILE_BASED_DATABASE:
+ if ( !m_bFoundOne )
+ {
+ m_bFoundOne = true;
+ GetOwnImport().GetProgressBarHelper()->Increment( PROGRESS_BAR_STEP );
+ pContext = new OXMLFileBasedDatabase( GetOwnImport(), xAttrList );
+ }
+ break;
+ case XML_SERVER_DATABASE:
+ if ( !m_bFoundOne )
+ {
+ m_bFoundOne = true;
+ GetOwnImport().GetProgressBarHelper()->Increment( PROGRESS_BAR_STEP );
+ pContext = new OXMLServerDatabase( GetOwnImport(), xAttrList );
+ }
+ break;
+ }
+
+ return pContext;
+}
+
+ODBFilter& OXMLDatabaseDescription::GetOwnImport()
+{
+ return static_cast<ODBFilter&>(GetImport());
+}
+
+} // namespace dbaxml
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/filter/xml/xmlDatabaseDescription.hxx b/dbaccess/source/filter/xml/xmlDatabaseDescription.hxx
new file mode 100644
index 000000000..146ecb401
--- /dev/null
+++ b/dbaccess/source/filter/xml/xmlDatabaseDescription.hxx
@@ -0,0 +1,41 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <xmloff/xmlictxt.hxx>
+
+namespace dbaxml
+{
+ class ODBFilter;
+ class OXMLDatabaseDescription : public SvXMLImportContext
+ {
+ bool m_bFoundOne;
+
+ ODBFilter& GetOwnImport();
+ public:
+
+ OXMLDatabaseDescription( ODBFilter& rImport);
+ virtual ~OXMLDatabaseDescription() override;
+
+ virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
+ sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList >& AttrList ) override;
+ };
+} // namespace dbaxml
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/filter/xml/xmlDocuments.cxx b/dbaccess/source/filter/xml/xmlDocuments.cxx
new file mode 100644
index 000000000..71d5b4589
--- /dev/null
+++ b/dbaccess/source/filter/xml/xmlDocuments.cxx
@@ -0,0 +1,99 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "xmlDocuments.hxx"
+#include "xmlfilter.hxx"
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/ProgressBarHelper.hxx>
+#include "xmlQuery.hxx"
+#include "xmlTable.hxx"
+#include "xmlComponent.hxx"
+#include "xmlHierarchyCollection.hxx"
+#include "xmlEnums.hxx"
+
+namespace dbaxml
+{
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::container;
+ using namespace ::com::sun::star::xml::sax;
+
+OXMLDocuments::OXMLDocuments( ODBFilter& rImport
+ ,const Reference< XNameAccess >& _xContainer
+ ,const OUString& _sCollectionServiceName
+ ,const OUString& _sComponentServiceName) :
+ SvXMLImportContext( rImport )
+ ,m_xContainer(_xContainer)
+ ,m_sCollectionServiceName(_sCollectionServiceName)
+ ,m_sComponentServiceName(_sComponentServiceName)
+{
+
+}
+
+OXMLDocuments::OXMLDocuments( ODBFilter& rImport
+ ,const Reference< XNameAccess >& _xContainer
+ ,const OUString& _sCollectionServiceName
+ ) :
+ SvXMLImportContext( rImport )
+ ,m_xContainer(_xContainer)
+ ,m_sCollectionServiceName(_sCollectionServiceName)
+{
+}
+
+OXMLDocuments::~OXMLDocuments()
+{
+
+}
+
+css::uno::Reference< css::xml::sax::XFastContextHandler > OXMLDocuments::createFastChildContext(
+ sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
+{
+ SvXMLImportContext *pContext = nullptr;
+
+ switch( nElement & TOKEN_MASK )
+ {
+ case XML_TABLE:
+ case XML_TABLE_REPRESENTATION:
+ GetOwnImport().GetProgressBarHelper()->Increment( PROGRESS_BAR_STEP );
+ pContext = new OXMLTable( GetOwnImport(), xAttrList, m_xContainer, "com.sun.star.sdb.TableDefinition");
+ break;
+ case XML_QUERY:
+ GetOwnImport().GetProgressBarHelper()->Increment( PROGRESS_BAR_STEP );
+ pContext = new OXMLQuery( GetOwnImport(), xAttrList, m_xContainer );
+ break;
+ case XML_COMPONENT:
+ GetOwnImport().GetProgressBarHelper()->Increment( PROGRESS_BAR_STEP );
+ pContext = new OXMLComponent( GetOwnImport(), xAttrList, m_xContainer,m_sComponentServiceName );
+ break;
+ case XML_COMPONENT_COLLECTION:
+ GetOwnImport().GetProgressBarHelper()->Increment( PROGRESS_BAR_STEP );
+ pContext = new OXMLHierarchyCollection( GetOwnImport(), xAttrList, m_xContainer,m_sCollectionServiceName,m_sComponentServiceName );
+ break;
+ }
+
+ return pContext;
+}
+
+ODBFilter& OXMLDocuments::GetOwnImport()
+{
+ return static_cast<ODBFilter&>(GetImport());
+}
+
+} // namespace dbaxml
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/filter/xml/xmlDocuments.hxx b/dbaccess/source/filter/xml/xmlDocuments.hxx
new file mode 100644
index 000000000..c0542dcfb
--- /dev/null
+++ b/dbaccess/source/filter/xml/xmlDocuments.hxx
@@ -0,0 +1,56 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <xmloff/xmlictxt.hxx>
+#include <com/sun/star/container/XNameAccess.hpp>
+
+namespace dbaxml
+{
+ class ODBFilter;
+ class OXMLDocuments : public SvXMLImportContext
+ {
+ private:
+ css::uno::Reference< css::container::XNameAccess > m_xContainer;
+ OUString m_sCollectionServiceName;
+ OUString m_sComponentServiceName;
+
+ ODBFilter& GetOwnImport();
+ public:
+
+ // for forms and reports
+ OXMLDocuments( ODBFilter& rImport
+ ,const css::uno::Reference< css::container::XNameAccess >& _xContainer
+ ,const OUString& _sCollectionServiceName
+ ,const OUString& _sComponentServiceName);
+
+ // for queries
+ OXMLDocuments( ODBFilter& rImport
+ ,const css::uno::Reference< css::container::XNameAccess >& _xContainer
+ ,const OUString& _sCollectionServiceName = OUString()
+ );
+
+ virtual ~OXMLDocuments() override;
+
+ virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
+ sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList >& AttrList ) override;
+ };
+} // namespace dbaxml
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/filter/xml/xmlEnums.hxx b/dbaccess/source/filter/xml/xmlEnums.hxx
new file mode 100644
index 000000000..552f7eb24
--- /dev/null
+++ b/dbaccess/source/filter/xml/xmlEnums.hxx
@@ -0,0 +1,23 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#define PROGRESS_BAR_STEP 20
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/filter/xml/xmlExport.cxx b/dbaccess/source/filter/xml/xmlExport.cxx
new file mode 100644
index 000000000..74cb97721
--- /dev/null
+++ b/dbaccess/source/filter/xml/xmlExport.cxx
@@ -0,0 +1,1342 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "xmlExport.hxx"
+#include "xmlAutoStyle.hxx"
+#include <sax/tools/converter.hxx>
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/namespacemap.hxx>
+#include <comphelper/string.hxx>
+#include <comphelper/types.hxx>
+#include <strings.hxx>
+#include <sal/log.hxx>
+#include <com/sun/star/beans/XPropertyState.hpp>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/frame/XModel.hpp>
+#include <com/sun/star/util/XNumberFormatsSupplier.hpp>
+#include <com/sun/star/sdb/XFormDocumentsSupplier.hpp>
+#include <com/sun/star/sdb/XOfficeDatabaseDocument.hpp>
+#include <com/sun/star/sdb/XReportDocumentsSupplier.hpp>
+#include <com/sun/star/sdb/XQueryDefinitionsSupplier.hpp>
+#include <com/sun/star/sdbcx/XTablesSupplier.hpp>
+#include <com/sun/star/sdbcx/XDataDescriptorFactory.hpp>
+
+#include <com/sun/star/awt/TextAlign.hpp>
+#include <xmloff/xmluconv.hxx>
+#include "xmlHelper.hxx"
+#include <com/sun/star/awt/FontDescriptor.hpp>
+#include <svl/filenotation.hxx>
+#include <unotools/pathoptions.hxx>
+#include <tools/diagnose_ex.h>
+#include <connectivity/DriversConfig.hxx>
+#include <connectivity/dbtools.hxx>
+
+#include <optional>
+#include <memory>
+
+using namespace comphelper;
+using namespace ::com::sun::star::sdb;
+using namespace ::com::sun::star::sdbcx;
+using namespace ::com::sun::star::util;
+using namespace ::com::sun::star;
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+com_sun_star_comp_sdb_DBExportFilter_get_implementation(
+ css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const&)
+{
+ return cppu::acquire(new ::dbaxml::ODBExport(context,
+ "com.sun.star.comp.sdb.DBExportFilter"));
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+com_sun_star_comp_sdb_XMLSettingsExporter_get_implementation(
+ css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const&)
+{
+ return cppu::acquire(new ::dbaxml::ODBExport(context,
+ "com.sun.star.comp.sdb.XMLSettingsExporter",
+ SvXMLExportFlags::SETTINGS | SvXMLExportFlags::PRETTY ));
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+com_sun_star_comp_sdb_XMLFullExporter_get_implementation(
+ css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const&)
+{
+ return cppu::acquire(new ::dbaxml::ODBExport(context,
+ "com.sun.star.comp.sdb.XMLFullExporter",
+ SvXMLExportFlags::ALL));
+}
+
+namespace dbaxml
+{
+ static OUString lcl_implGetPropertyXMLType(const Type& _rType)
+ {
+ // possible types we can write (either because we recognize them directly or because we convert _rValue
+ // into one of these types)
+
+ // handle the type description
+ switch (_rType.getTypeClass())
+ {
+ case TypeClass_STRING:
+ return "string";
+ case TypeClass_DOUBLE:
+ return "double";
+ case TypeClass_BOOLEAN:
+ return "boolean";
+ case TypeClass_BYTE:
+ case TypeClass_SHORT:
+ return "short";
+ case TypeClass_LONG:
+ return "int";
+ case TypeClass_HYPER:
+ return "long";
+ case TypeClass_ENUM:
+ return "int";
+
+ default:
+ OSL_FAIL( "lcl_implGetPropertyXMLType: unsupported value type!" );
+ return "double";
+ }
+ }
+
+ namespace {
+
+ class OSpecialHandleXMLExportPropertyMapper : public SvXMLExportPropertyMapper
+ {
+ public:
+ explicit OSpecialHandleXMLExportPropertyMapper(const rtl::Reference< XMLPropertySetMapper >& rMapper) : SvXMLExportPropertyMapper(rMapper )
+ {
+ }
+ /** this method is called for every item that has the
+ MID_FLAG_SPECIAL_ITEM_EXPORT flag set */
+ virtual void handleSpecialItem(
+ SvXMLAttributeList& /*rAttrList*/,
+ const XMLPropertyState& /*rProperty*/,
+ const SvXMLUnitConverter& /*rUnitConverter*/,
+ const SvXMLNamespaceMap& /*rNamespaceMap*/,
+ const std::vector< XMLPropertyState > * /*pProperties*/ ,
+ sal_uInt32 /*nIdx*/ ) const override
+ {
+ // nothing to do here
+ }
+ };
+
+ }
+
+ODBExport::ODBExport(const Reference< XComponentContext >& _rxContext, OUString const & implementationName, SvXMLExportFlags nExportFlag)
+: SvXMLExport( _rxContext, implementationName, util::MeasureUnit::MM_10TH, XML_DATABASE,
+ SvXMLExportFlags::OASIS | nExportFlag)
+,m_aTypeCollection(_rxContext)
+,m_bAllreadyFilled(false)
+{
+ GetMM100UnitConverter().SetCoreMeasureUnit(util::MeasureUnit::MM_10TH);
+ GetMM100UnitConverter().SetXMLMeasureUnit(util::MeasureUnit::CM);
+
+ GetNamespaceMap_().Add( GetXMLToken(XML_NP_OFFICE), GetXMLToken(XML_N_OFFICE), XML_NAMESPACE_OFFICE );
+ GetNamespaceMap_().Add( GetXMLToken(XML_NP_OOO), GetXMLToken(XML_N_OOO), XML_NAMESPACE_OOO );
+ GetNamespaceMap_().Add( GetXMLToken(XML_NP_SVG), GetXMLToken(XML_N_SVG), XML_NAMESPACE_SVG );
+
+ GetNamespaceMap_().Add( GetXMLToken(XML_NP_DB), GetXMLToken(XML_N_DB_OASIS), XML_NAMESPACE_DB );
+
+ if( nExportFlag & (SvXMLExportFlags::STYLES|SvXMLExportFlags::MASTERSTYLES|SvXMLExportFlags::AUTOSTYLES|SvXMLExportFlags::FONTDECLS) )
+ GetNamespaceMap_().Add( GetXMLToken(XML_NP_FO), GetXMLToken(XML_N_FO_COMPAT), XML_NAMESPACE_FO );
+
+ if( nExportFlag & (SvXMLExportFlags::META|SvXMLExportFlags::STYLES|SvXMLExportFlags::MASTERSTYLES|SvXMLExportFlags::AUTOSTYLES|SvXMLExportFlags::CONTENT|SvXMLExportFlags::SCRIPTS|SvXMLExportFlags::SETTINGS) )
+ {
+ GetNamespaceMap_().Add( GetXMLToken(XML_NP_XLINK), GetXMLToken(XML_N_XLINK), XML_NAMESPACE_XLINK );
+ }
+ if( nExportFlag & SvXMLExportFlags::SETTINGS )
+ {
+ GetNamespaceMap_().Add( GetXMLToken(XML_NP_CONFIG), GetXMLToken(XML_N_CONFIG), XML_NAMESPACE_CONFIG );
+ }
+
+ if( nExportFlag & (SvXMLExportFlags::STYLES|SvXMLExportFlags::MASTERSTYLES|SvXMLExportFlags::AUTOSTYLES|SvXMLExportFlags::CONTENT|SvXMLExportFlags::FONTDECLS) )
+ {
+ GetNamespaceMap_().Add( GetXMLToken(XML_NP_STYLE), GetXMLToken(XML_N_STYLE), XML_NAMESPACE_STYLE );
+ }
+
+ GetNamespaceMap_().Add( GetXMLToken(XML_NP_TABLE), GetXMLToken(XML_N_TABLE), XML_NAMESPACE_TABLE );
+ GetNamespaceMap_().Add( GetXMLToken(XML_NP_NUMBER), GetXMLToken(XML_N_NUMBER), XML_NAMESPACE_NUMBER );
+
+ m_xExportHelper = new SvXMLExportPropertyMapper(GetTableStylesPropertySetMapper());
+ m_xColumnExportHelper = new OSpecialHandleXMLExportPropertyMapper(GetColumnStylesPropertySetMapper());
+
+ m_xCellExportHelper = new OSpecialHandleXMLExportPropertyMapper(GetCellStylesPropertySetMapper());
+ m_xRowExportHelper = new OSpecialHandleXMLExportPropertyMapper(OXMLHelper::GetRowStylesPropertySetMapper());
+
+ GetAutoStylePool()->AddFamily(
+ XmlStyleFamily::TABLE_TABLE,
+ OUString(XML_STYLE_FAMILY_TABLE_TABLE_STYLES_NAME ),
+ m_xExportHelper.get(),
+ OUString(XML_STYLE_FAMILY_TABLE_TABLE_STYLES_PREFIX ));
+
+ GetAutoStylePool()->AddFamily(
+ XmlStyleFamily::TABLE_COLUMN,
+ OUString(XML_STYLE_FAMILY_TABLE_COLUMN_STYLES_NAME ),
+ m_xColumnExportHelper.get(),
+ OUString(XML_STYLE_FAMILY_TABLE_COLUMN_STYLES_PREFIX ));
+
+ GetAutoStylePool()->AddFamily(
+ XmlStyleFamily::TABLE_CELL,
+ OUString(XML_STYLE_FAMILY_TABLE_CELL_STYLES_NAME ),
+ m_xCellExportHelper.get(),
+ OUString(XML_STYLE_FAMILY_TABLE_CELL_STYLES_PREFIX ));
+
+ GetAutoStylePool()->AddFamily(
+ XmlStyleFamily::TABLE_ROW,
+ OUString(XML_STYLE_FAMILY_TABLE_ROW_STYLES_NAME ),
+ m_xRowExportHelper.get(),
+ OUString(XML_STYLE_FAMILY_TABLE_ROW_STYLES_PREFIX ));
+}
+
+void ODBExport::exportDataSource()
+{
+ try
+ {
+ Reference<XPropertySet> xProp( getDataSource(), UNO_SET_THROW );
+
+ bool bAutoIncrementEnabled = true;
+ TStringPair aAutoIncrement;
+
+ Reference< XPropertySet > xDataSourceSettings;
+ OSL_VERIFY( xProp->getPropertyValue( PROPERTY_SETTINGS ) >>= xDataSourceSettings );
+ Reference< XPropertyState > xSettingsState( xDataSourceSettings, UNO_QUERY_THROW );
+ Reference< XPropertySetInfo > xSettingsInfo( xDataSourceSettings->getPropertySetInfo(), UNO_SET_THROW );
+
+ TDelimiter aDelimiter;
+ xSettingsState->getPropertyDefault( INFO_TEXTDELIMITER ) >>= aDelimiter.sText;
+ xSettingsState->getPropertyDefault( INFO_FIELDDELIMITER ) >>= aDelimiter.sField;
+ xSettingsState->getPropertyDefault( INFO_DECIMALDELIMITER ) >>= aDelimiter.sDecimal;
+ xSettingsState->getPropertyDefault( INFO_THOUSANDSDELIMITER ) >>= aDelimiter.sThousand;
+
+ ::connectivity::DriversConfig aDriverConfig(getComponentContext());
+ const OUString sURL = ::comphelper::getString(xProp->getPropertyValue(PROPERTY_URL));
+ const ::comphelper::NamedValueCollection& aDriverSupportedProperties( aDriverConfig.getProperties( sURL ) );
+
+ static OUString s_sTrue(::xmloff::token::GetXMLToken( XML_TRUE ));
+ static OUString s_sFalse(::xmloff::token::GetXMLToken( XML_FALSE ));
+ // loop through the properties, and export only those which are not defaulted
+ TSettingsMap aSettingsMap;
+ // Don't try to get XPropertySetInfo from xProp, simply wrap the attempt into try block
+ try
+ {
+ const Any aValue = xProp->getPropertyValue(PROPERTY_SUPPRESSVERSIONCL);
+ if (!getBOOL(aValue)) // default in the XML schema is true -> only write false
+ aSettingsMap.emplace(XML_SUPPRESS_VERSION_COLUMNS, s_sFalse);
+ }
+ catch (const UnknownPropertyException&)
+ {
+ }
+
+ Sequence< Property > aProperties = xSettingsInfo->getProperties();
+ const Property* pProperties = aProperties.getConstArray();
+ const Property* pPropertiesEnd = pProperties + aProperties.getLength();
+ for ( ; pProperties != pPropertiesEnd; ++pProperties )
+ {
+ OUString sValue;
+ Any aValue = xDataSourceSettings->getPropertyValue( pProperties->Name );
+ switch ( aValue.getValueTypeClass() )
+ {
+ case TypeClass_STRING:
+ aValue >>= sValue;
+ break;
+ case TypeClass_DOUBLE:
+ // let the unit converter format is as string
+ sValue = OUString::number( getDouble( aValue ) );
+ break;
+ case TypeClass_BOOLEAN:
+ sValue = ::xmloff::token::GetXMLToken( getBOOL( aValue ) ? XML_TRUE : XML_FALSE );
+ break;
+ case TypeClass_BYTE:
+ case TypeClass_SHORT:
+ case TypeClass_LONG:
+ // let the unit converter format is as string
+ sValue = OUString::number( getINT32( aValue ) );
+ break;
+ default:
+ break;
+ }
+
+ ::xmloff::token::XMLTokenEnum eToken = XML_TOKEN_INVALID;
+
+ struct PropertyMap
+ {
+ const OUString sPropertyName;
+ const XMLTokenEnum eAttributeToken;
+ const ::std::optional< OUString > aXMLDefault;
+
+ PropertyMap( const OUString& _rPropertyName, const XMLTokenEnum _eToken )
+ :sPropertyName( _rPropertyName )
+ ,eAttributeToken( _eToken )
+ ,aXMLDefault()
+ {
+ }
+
+ PropertyMap( const OUString& _rPropertyName, const XMLTokenEnum _eToken, const OUString& _rDefault )
+ :sPropertyName( _rPropertyName )
+ ,eAttributeToken( _eToken )
+ ,aXMLDefault( _rDefault )
+ {
+ }
+ };
+
+ const PropertyMap aTokens[] =
+ {
+ PropertyMap( INFO_TEXTFILEHEADER, XML_IS_FIRST_ROW_HEADER_LINE, s_sTrue ),
+ PropertyMap( INFO_SHOWDELETEDROWS, XML_SHOW_DELETED, s_sFalse ),
+ PropertyMap( INFO_ALLOWLONGTABLENAMES, XML_IS_TABLE_NAME_LENGTH_LIMITED, s_sTrue ),
+ PropertyMap( INFO_ADDITIONALOPTIONS, XML_SYSTEM_DRIVER_SETTINGS ),
+ PropertyMap( PROPERTY_ENABLESQL92CHECK, XML_ENABLE_SQL92_CHECK, s_sFalse ),
+ PropertyMap( INFO_APPEND_TABLE_ALIAS, XML_APPEND_TABLE_ALIAS_NAME, s_sTrue ),
+ PropertyMap( INFO_PARAMETERNAMESUBST, XML_PARAMETER_NAME_SUBSTITUTION, s_sTrue ),
+ PropertyMap( INFO_IGNOREDRIVER_PRIV, XML_IGNORE_DRIVER_PRIVILEGES, s_sTrue ),
+ PropertyMap( INFO_USECATALOG, XML_USE_CATALOG, s_sFalse ),
+ PropertyMap( INFO_CONN_LDAP_BASEDN, XML_BASE_DN ),
+ PropertyMap( INFO_CONN_LDAP_ROWCOUNT, XML_MAX_ROW_COUNT )
+ };
+
+ bool bIsXMLDefault = false;
+ for (const auto & aToken : aTokens)
+ {
+ if ( pProperties->Name == aToken.sPropertyName )
+ {
+ eToken = aToken.eAttributeToken;
+
+ if ( !!aToken.aXMLDefault
+ && ( sValue == *aToken.aXMLDefault )
+ )
+ {
+ bIsXMLDefault = true;
+ }
+ break;
+ }
+ }
+
+ if ( bIsXMLDefault )
+ // the property has the value which is specified as default in the XML schema -> no need to write it
+ continue;
+
+ if ( eToken == XML_TOKEN_INVALID )
+ {
+ // for properties which are not REMOVABLE, we care for their state, and
+ // only export them if they're not DEFAULTed
+ if ( ( pProperties->Attributes & PropertyAttribute::REMOVABLE ) == 0 )
+ {
+ PropertyState ePropertyState = xSettingsState->getPropertyState( pProperties->Name );
+ if ( PropertyState_DEFAULT_VALUE == ePropertyState )
+ continue;
+ }
+
+ // special handlings
+ if ( pProperties->Name == PROPERTY_BOOLEANCOMPARISONMODE )
+ {
+ if ( sValue == "0" )
+ sValue = "equal-integer";
+ else if ( sValue == "1" )
+ sValue = "is-boolean";
+ else if ( sValue == "2" )
+ sValue = "equal-boolean";
+ else if ( sValue == "3" )
+ sValue = "equal-use-only-zero";
+ if ( sValue == "equal-integer" )
+ continue;
+ eToken = XML_BOOLEAN_COMPARISON_MODE;
+ }
+ else if ( pProperties->Name == INFO_AUTORETRIEVEENABLED )
+ {
+ aValue >>= bAutoIncrementEnabled;
+ continue;
+ }
+ else if ( pProperties->Name == INFO_AUTORETRIEVEVALUE )
+ {
+ aAutoIncrement.first = sValue;
+ continue;
+ }
+ else if ( pProperties->Name == PROPERTY_AUTOINCREMENTCREATION )
+ {
+ aAutoIncrement.second = sValue;
+ continue;
+ }
+ else if ( pProperties->Name == INFO_TEXTDELIMITER )
+ {
+ aDelimiter.sText = sValue;
+ aDelimiter.bUsed = true;
+ continue;
+ }
+ else if ( pProperties->Name == INFO_FIELDDELIMITER )
+ {
+ aDelimiter.sField = sValue;
+ aDelimiter.bUsed = true;
+ continue;
+ }
+ else if ( pProperties->Name == INFO_DECIMALDELIMITER )
+ {
+ aDelimiter.sDecimal = sValue;
+ aDelimiter.bUsed = true;
+ continue;
+ }
+ else if ( pProperties->Name == INFO_THOUSANDSDELIMITER )
+ {
+ aDelimiter.sThousand = sValue;
+ aDelimiter.bUsed = true;
+ continue;
+ }
+ else if ( pProperties->Name == INFO_CHARSET )
+ {
+ m_sCharSet = sValue;
+ continue;
+ }
+ else
+ {
+ if ( !aDriverSupportedProperties.has(pProperties->Name) || aDriverSupportedProperties.get(pProperties->Name) != aValue )
+ {
+ m_aDataSourceSettings.emplace_back(
+ pProperties->Name, pProperties->Type, aValue );
+ }
+ continue;
+ }
+ }
+
+ aSettingsMap.emplace(eToken,sValue);
+ }
+ if ( bAutoIncrementEnabled && !(aAutoIncrement.first.isEmpty() && aAutoIncrement.second.isEmpty()) )
+ m_aAutoIncrement.reset( new TStringPair(aAutoIncrement));
+ if ( aDelimiter.bUsed )
+ m_aDelimiter.reset( new TDelimiter( aDelimiter ) );
+
+ SvXMLElementExport aElem(*this, XML_NAMESPACE_DB, XML_DATA_SOURCE, true, true);
+
+ exportConnectionData();
+ exportDriverSettings(aSettingsMap);
+ exportApplicationConnectionSettings(aSettingsMap);
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+}
+
+void ODBExport::exportApplicationConnectionSettings(const TSettingsMap& _aSettings)
+{
+ const ::xmloff::token::XMLTokenEnum pSettings[] = {
+ XML_IS_TABLE_NAME_LENGTH_LIMITED
+ ,XML_ENABLE_SQL92_CHECK
+ ,XML_APPEND_TABLE_ALIAS_NAME
+ ,XML_IGNORE_DRIVER_PRIVILEGES
+ ,XML_BOOLEAN_COMPARISON_MODE
+ ,XML_USE_CATALOG
+ ,XML_MAX_ROW_COUNT
+ ,XML_SUPPRESS_VERSION_COLUMNS
+ };
+ for (::xmloff::token::XMLTokenEnum i : pSettings)
+ {
+ TSettingsMap::const_iterator aFind = _aSettings.find(i);
+ if ( aFind != _aSettings.end() )
+ AddAttribute(XML_NAMESPACE_DB, aFind->first,aFind->second);
+ }
+ SvXMLElementExport aElem(*this,XML_NAMESPACE_DB, XML_APPLICATION_CONNECTION_SETTINGS, true, true);
+
+ Reference<XPropertySet> xProp(getDataSource());
+ Sequence< OUString> aValue;
+ xProp->getPropertyValue(PROPERTY_TABLEFILTER) >>= aValue;
+ if ( aValue.hasElements() )
+ {
+ SvXMLElementExport aElem2(*this,XML_NAMESPACE_DB, XML_TABLE_FILTER, true, true);
+ exportSequence(aValue,XML_TABLE_INCLUDE_FILTER,XML_TABLE_FILTER_PATTERN);
+ }
+
+ xProp->getPropertyValue(PROPERTY_TABLETYPEFILTER) >>= aValue;
+ if ( aValue.hasElements() )
+ exportSequence(aValue,XML_TABLE_TYPE_FILTER,XML_TABLE_TYPE);
+
+ exportDataSourceSettings();
+}
+
+void ODBExport::exportDriverSettings(const TSettingsMap& _aSettings)
+{
+ const ::xmloff::token::XMLTokenEnum pSettings[] = {
+ XML_SHOW_DELETED
+ ,XML_SYSTEM_DRIVER_SETTINGS
+ ,XML_BASE_DN
+ ,XML_IS_FIRST_ROW_HEADER_LINE
+ ,XML_PARAMETER_NAME_SUBSTITUTION
+ };
+ for (::xmloff::token::XMLTokenEnum nSetting : pSettings)
+ {
+ TSettingsMap::const_iterator aFind = _aSettings.find(nSetting);
+ if ( aFind != _aSettings.end() )
+ AddAttribute(XML_NAMESPACE_DB, aFind->first,aFind->second);
+ }
+ SvXMLElementExport aElem(*this,XML_NAMESPACE_DB, XML_DRIVER_SETTINGS, true, true);
+ exportAutoIncrement();
+ exportDelimiter();
+ exportCharSet();
+}
+
+void ODBExport::exportConnectionData()
+{
+ SvXMLElementExport aConnData(*this,XML_NAMESPACE_DB, XML_CONNECTION_DATA, true, true);
+
+ {
+ OUString sValue;
+ Reference<XPropertySet> xProp(getDataSource());
+ xProp->getPropertyValue(PROPERTY_URL) >>= sValue;
+ if ( m_aTypeCollection.isFileSystemBased(sValue) )
+ {
+ SvXMLElementExport aDatabaseDescription(*this,XML_NAMESPACE_DB, XML_DATABASE_DESCRIPTION, true, true);
+ {
+ SvtPathOptions aPathOptions;
+ const OUString sOrigUrl = m_aTypeCollection.cutPrefix(sValue);
+ OUString sFileName = aPathOptions.SubstituteVariable(sOrigUrl);
+ if ( sOrigUrl == sFileName )
+ {
+ ::svt::OFileNotation aTransformer( sFileName );
+ OUStringBuffer sURL( aTransformer.get( ::svt::OFileNotation::N_URL ) );
+ if (sURL.isEmpty() || sURL[sURL.getLength() - 1] != '/')
+ sURL.append('/');
+
+ AddAttribute(XML_NAMESPACE_XLINK,XML_HREF,GetRelativeReference(sURL.makeStringAndClear()));
+ }
+ else
+ AddAttribute(XML_NAMESPACE_XLINK,XML_HREF,sOrigUrl);
+ AddAttribute(XML_NAMESPACE_DB,XML_MEDIA_TYPE,m_aTypeCollection.getMediaType(sValue));
+ const ::dbaccess::DATASOURCE_TYPE eType = m_aTypeCollection.determineType(sValue);
+ try
+ {
+ OUString sExtension;
+ if ( eType == dbaccess::DST_MSACCESS )
+ sExtension = "mdb";
+ else
+ {
+ Reference< XPropertySet > xDataSourceSettings;
+ OSL_VERIFY( xProp->getPropertyValue( PROPERTY_SETTINGS ) >>= xDataSourceSettings );
+ xDataSourceSettings->getPropertyValue( INFO_TEXTFILEEXTENSION ) >>= sExtension;
+ }
+ if ( !sExtension.isEmpty() )
+ AddAttribute(XML_NAMESPACE_DB,XML_EXTENSION,sExtension);
+ }
+ catch(const Exception&)
+ {
+ }
+ SvXMLElementExport aFileBasedDB(*this,XML_NAMESPACE_DB, XML_FILE_BASED_DATABASE, true, true);
+ }
+ }
+ else
+ {
+ OUString sDatabaseName,sHostName;
+ sal_Int32 nPort = -1;
+ m_aTypeCollection.extractHostNamePort(sValue,sDatabaseName,sHostName,nPort);
+ if ( sHostName.getLength() )
+ {
+ SvXMLElementExport aDatabaseDescription(*this,XML_NAMESPACE_DB, XML_DATABASE_DESCRIPTION, true, true);
+ {
+ OUString sType = comphelper::string::stripEnd(m_aTypeCollection.getPrefix(sValue), ':');
+ AddAttribute(XML_NAMESPACE_DB,XML_TYPE,sType);
+ AddAttribute(XML_NAMESPACE_DB,XML_HOSTNAME,sHostName);
+ if ( nPort != -1 )
+ AddAttribute(XML_NAMESPACE_DB,XML_PORT,OUString::number(nPort));
+ if ( sDatabaseName.getLength() )
+ AddAttribute(XML_NAMESPACE_DB,XML_DATABASE_NAME,sDatabaseName);
+
+ try
+ {
+ Reference< XPropertySet > xDataSourceSettings( xProp->getPropertyValue( PROPERTY_SETTINGS ), UNO_QUERY_THROW );
+ Reference< XPropertySetInfo > xSettingsInfo( xDataSourceSettings->getPropertySetInfo(), UNO_SET_THROW );
+
+
+ static const OUStringLiteral sPropertyName = u"LocalSocket";
+ if ( xSettingsInfo->hasPropertyByName( sPropertyName ) )
+ {
+ OUString sPropertyValue;
+ if ( ( xDataSourceSettings->getPropertyValue( sPropertyName ) >>= sPropertyValue ) && !sPropertyValue.isEmpty() )
+ AddAttribute( XML_NAMESPACE_DB, XML_LOCAL_SOCKET, sPropertyValue );
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+
+ SvXMLElementExport aServerDB(*this,XML_NAMESPACE_DB, XML_SERVER_DATABASE, true, true);
+ }
+ }
+ else
+ {
+ AddAttribute(XML_NAMESPACE_XLINK, XML_HREF,sValue);
+ AddAttribute(XML_NAMESPACE_XLINK, XML_TYPE, XML_SIMPLE);
+ SvXMLElementExport aElem(*this,XML_NAMESPACE_DB, XML_CONNECTION_RESOURCE, true, true);
+ }
+ }
+
+ }
+
+ exportLogin();
+}
+
+template< typename T > void ODBExport::exportDataSourceSettingsSequence(
+ std::vector< TypedPropertyValue >::iterator const & in)
+{
+ css::uno::Sequence<T> anySeq;
+ bool bSuccess = in->Value >>= anySeq;
+ assert(bSuccess); (void)bSuccess;
+ for (T const & i : std::as_const(anySeq) )
+ {
+ SvXMLElementExport aDataValue(*this,XML_NAMESPACE_DB, XML_DATA_SOURCE_SETTING_VALUE, true, false);
+ // (no whitespace inside the tag)
+ Characters(implConvertAny(css::uno::Any(i)));
+ }
+}
+
+void ODBExport::exportDataSourceSettings()
+{
+ if ( m_aDataSourceSettings.empty() )
+ return;
+
+ SvXMLElementExport aElem(*this,XML_NAMESPACE_DB, XML_DATA_SOURCE_SETTINGS, true, true);
+ std::vector< TypedPropertyValue >::iterator aIter = m_aDataSourceSettings.begin();
+ std::vector< TypedPropertyValue >::const_iterator aEnd = m_aDataSourceSettings.end();
+ for ( ; aIter != aEnd; ++aIter )
+ {
+ const bool bIsSequence = TypeClass_SEQUENCE == aIter->Type.getTypeClass();
+
+ Type aSimpleType(bIsSequence ? comphelper::getSequenceElementType(aIter->Value.getValueType()) : aIter->Type);
+
+ AddAttribute( XML_NAMESPACE_DB, XML_DATA_SOURCE_SETTING_IS_LIST,bIsSequence ? XML_TRUE : XML_FALSE );
+ AddAttribute( XML_NAMESPACE_DB, XML_DATA_SOURCE_SETTING_NAME, aIter->Name );
+
+ OUString sTypeName = lcl_implGetPropertyXMLType( aSimpleType );
+ if ( bIsSequence && aSimpleType.getTypeClass() == TypeClass_ANY )
+ {
+ Sequence<Any> aSeq;
+ aIter->Value >>= aSeq;
+ if ( aSeq.hasElements() )
+ sTypeName = lcl_implGetPropertyXMLType(aSeq[0].getValueType());
+ }
+
+ AddAttribute( XML_NAMESPACE_DB, XML_DATA_SOURCE_SETTING_TYPE, sTypeName );
+
+ SvXMLElementExport aDataSourceSetting( *this, XML_NAMESPACE_DB, XML_DATA_SOURCE_SETTING, true, true );
+
+ if ( !bIsSequence )
+ {
+ SvXMLElementExport aDataValue( *this, XML_NAMESPACE_DB, XML_DATA_SOURCE_SETTING_VALUE, true, false );
+ // (no whitespace inside the tag)
+ Characters( implConvertAny( aIter->Value ) );
+ }
+ else
+ {
+ // the not-that-simple case, we need to iterate through the sequence elements
+ switch (aSimpleType.getTypeClass())
+ {
+ case TypeClass_STRING:
+ exportDataSourceSettingsSequence< OUString >(
+ aIter );
+ break;
+ case TypeClass_DOUBLE:
+ exportDataSourceSettingsSequence< double >( aIter );
+ break;
+ case TypeClass_BOOLEAN:
+ exportDataSourceSettingsSequence< sal_Bool >( aIter );
+ break;
+ case TypeClass_BYTE:
+ exportDataSourceSettingsSequence< sal_Int8 >( aIter );
+ break;
+ case TypeClass_SHORT:
+ exportDataSourceSettingsSequence< sal_Int16 >( aIter );
+ break;
+ case TypeClass_LONG:
+ exportDataSourceSettingsSequence< sal_Int32 >( aIter );
+ break;
+ case TypeClass_ANY:
+ exportDataSourceSettingsSequence< Any >( aIter );
+ break;
+ default:
+ OSL_FAIL("unsupported sequence type !");
+ break;
+ }
+ }
+ }
+}
+
+void ODBExport::exportCharSet()
+{
+ if ( !m_sCharSet.isEmpty() )
+ {
+ AddAttribute(XML_NAMESPACE_DB, XML_ENCODING,m_sCharSet);
+
+ SvXMLElementExport aElem(*this,XML_NAMESPACE_DB, XML_FONT_CHARSET, true, true);
+ }
+}
+
+void ODBExport::exportDelimiter()
+{
+ if ( m_aDelimiter && m_aDelimiter->bUsed )
+ {
+ AddAttribute(XML_NAMESPACE_DB, XML_FIELD,m_aDelimiter->sField);
+ AddAttribute(XML_NAMESPACE_DB, XML_STRING,m_aDelimiter->sText);
+ AddAttribute(XML_NAMESPACE_DB, XML_DECIMAL,m_aDelimiter->sDecimal);
+ AddAttribute(XML_NAMESPACE_DB, XML_THOUSAND,m_aDelimiter->sThousand);
+ SvXMLElementExport aElem(*this,XML_NAMESPACE_DB, XML_DELIMITER, true, true);
+ }
+}
+
+void ODBExport::exportAutoIncrement()
+{
+ if (m_aAutoIncrement)
+ {
+ AddAttribute(XML_NAMESPACE_DB, XML_ADDITIONAL_COLUMN_STATEMENT,m_aAutoIncrement->second);
+ AddAttribute(XML_NAMESPACE_DB, XML_ROW_RETRIEVING_STATEMENT,m_aAutoIncrement->first);
+ SvXMLElementExport aElem(*this,XML_NAMESPACE_DB, XML_AUTO_INCREMENT, true, true);
+ }
+}
+
+void ODBExport::exportSequence(const Sequence< OUString>& _aValue
+ ,::xmloff::token::XMLTokenEnum _eTokenFilter
+ ,::xmloff::token::XMLTokenEnum _eTokenType)
+{
+ if ( _aValue.hasElements() )
+ {
+ SvXMLElementExport aElem(*this,XML_NAMESPACE_DB, _eTokenFilter, true, true);
+
+ const OUString* pIter = _aValue.getConstArray();
+ const OUString* pEnd = pIter + _aValue.getLength();
+ for(;pIter != pEnd;++pIter)
+ {
+ SvXMLElementExport aDataSource(*this,XML_NAMESPACE_DB, _eTokenType, true, false);
+ Characters(*pIter);
+ }
+ }
+}
+
+void ODBExport::exportLogin()
+{
+ Reference<XPropertySet> xProp(getDataSource());
+ OUString sValue;
+ xProp->getPropertyValue(PROPERTY_USER) >>= sValue;
+ bool bAddLogin = !sValue.isEmpty();
+ if ( bAddLogin )
+ AddAttribute(XML_NAMESPACE_DB, XML_USER_NAME,sValue);
+ bool bValue = false;
+ if ( xProp->getPropertyValue(PROPERTY_ISPASSWORDREQUIRED) >>= bValue )
+ {
+ bAddLogin = true;
+ AddAttribute(XML_NAMESPACE_DB, XML_IS_PASSWORD_REQUIRED,bValue ? XML_TRUE : XML_FALSE);
+ }
+ if ( bAddLogin )
+ SvXMLElementExport aElem(*this,XML_NAMESPACE_DB, XML_LOGIN, true, true);
+}
+
+void ODBExport::exportCollection(const Reference< XNameAccess >& _xCollection
+ ,enum ::xmloff::token::XMLTokenEnum _eComponents
+ ,enum ::xmloff::token::XMLTokenEnum _eSubComponents
+ ,bool _bExportContext
+ ,const ::comphelper::mem_fun1_t<ODBExport,XPropertySet* >& _aMemFunc
+ )
+{
+ if ( !_xCollection.is() )
+ return;
+
+ std::unique_ptr<SvXMLElementExport> pComponents;
+ if ( _bExportContext )
+ pComponents.reset( new SvXMLElementExport(*this,XML_NAMESPACE_DB, _eComponents, true, true));
+ Sequence< OUString> aSeq = _xCollection->getElementNames();
+ const OUString* pIter = aSeq.getConstArray();
+ const OUString* pEnd = pIter + aSeq.getLength();
+ for(;pIter != pEnd;++pIter)
+ {
+ Reference<XPropertySet> xProp(_xCollection->getByName(*pIter),UNO_QUERY);
+ if ( _bExportContext && XML_TABLE_REPRESENTATIONS != _eComponents )
+ AddAttribute(XML_NAMESPACE_DB, XML_NAME,*pIter);
+ Reference< XNameAccess > xSub(xProp,UNO_QUERY);
+ if ( xSub.is() )
+ {
+ exportCollection(xSub,_eSubComponents,_eSubComponents,_bExportContext,_aMemFunc);
+ }
+ else if ( xProp.is() )
+ _aMemFunc(this,xProp.get());
+ }
+}
+
+void ODBExport::exportComponent(XPropertySet* _xProp)
+{
+ OUString sValue;
+ _xProp->getPropertyValue(PROPERTY_PERSISTENT_NAME) >>= sValue;
+ bool bIsForm = true;
+ _xProp->getPropertyValue("IsForm") >>= bIsForm;
+ if ( bIsForm )
+ sValue = "forms/" + sValue;
+ else
+ sValue = "reports/" + sValue;
+
+ AddAttribute(XML_NAMESPACE_XLINK, XML_HREF, sValue);
+ AddAttribute(XML_NAMESPACE_XLINK, XML_TYPE, XML_SIMPLE);
+ bool bAsTemplate = false;
+ _xProp->getPropertyValue(PROPERTY_AS_TEMPLATE) >>= bAsTemplate;
+ AddAttribute(XML_NAMESPACE_DB, XML_AS_TEMPLATE,bAsTemplate ? XML_TRUE : XML_FALSE);
+ SvXMLElementExport aComponents(*this,XML_NAMESPACE_DB, XML_COMPONENT, true, true);
+}
+
+void ODBExport::exportQuery(XPropertySet* _xProp)
+{
+ AddAttribute(XML_NAMESPACE_DB, XML_COMMAND,getString(_xProp->getPropertyValue(PROPERTY_COMMAND)));
+
+ if ( getBOOL(_xProp->getPropertyValue(PROPERTY_APPLYFILTER)) )
+ AddAttribute(XML_NAMESPACE_DB, XML_APPLY_FILTER,XML_TRUE);
+
+ if ( _xProp->getPropertySetInfo()->hasPropertyByName(PROPERTY_APPLYORDER)
+ && getBOOL(_xProp->getPropertyValue(PROPERTY_APPLYORDER)) )
+ AddAttribute(XML_NAMESPACE_DB, XML_APPLY_ORDER,XML_TRUE);
+
+ if ( ! getBOOL(_xProp->getPropertyValue(PROPERTY_ESCAPE_PROCESSING)) )
+ AddAttribute(XML_NAMESPACE_DB, XML_ESCAPE_PROCESSING,XML_FALSE);
+
+ exportStyleName(_xProp,GetAttrList());
+
+ SvXMLElementExport aComponents(*this,XML_NAMESPACE_DB, XML_QUERY, true, true);
+ Reference<XColumnsSupplier> xCol(_xProp,UNO_QUERY);
+ exportColumns(xCol);
+ exportFilter(_xProp,PROPERTY_FILTER,XML_FILTER_STATEMENT);
+ exportFilter(_xProp,PROPERTY_ORDER,XML_ORDER_STATEMENT);
+ exportTableName(_xProp,true);
+}
+
+void ODBExport::exportTable(XPropertySet* _xProp)
+{
+ exportTableName(_xProp,false);
+
+ if ( _xProp->getPropertySetInfo()->hasPropertyByName(PROPERTY_DESCRIPTION) )
+ AddAttribute(XML_NAMESPACE_DB, XML_DESCRIPTION,getString(_xProp->getPropertyValue(PROPERTY_DESCRIPTION)));
+
+ if ( getBOOL(_xProp->getPropertyValue(PROPERTY_APPLYFILTER)) )
+ AddAttribute(XML_NAMESPACE_DB, XML_APPLY_FILTER,XML_TRUE);
+
+ if ( _xProp->getPropertySetInfo()->hasPropertyByName(PROPERTY_APPLYORDER)
+ && getBOOL(_xProp->getPropertyValue(PROPERTY_APPLYORDER)) )
+ AddAttribute(XML_NAMESPACE_DB, XML_APPLY_ORDER,XML_TRUE);
+
+ exportStyleName(_xProp,GetAttrList());
+
+ SvXMLElementExport aComponents(*this,XML_NAMESPACE_DB, XML_TABLE_REPRESENTATION, true, true);
+ Reference<XColumnsSupplier> xCol(_xProp,UNO_QUERY);
+ exportColumns(xCol);
+ exportFilter(_xProp,PROPERTY_FILTER,XML_FILTER_STATEMENT);
+ exportFilter(_xProp,PROPERTY_ORDER,XML_ORDER_STATEMENT);
+}
+
+void ODBExport::exportStyleName(XPropertySet* _xProp,SvXMLAttributeList& _rAtt)
+{
+ Reference<XPropertySet> xFind(_xProp);
+ exportStyleName(XML_STYLE_NAME,xFind,_rAtt,m_aAutoStyleNames);
+ exportStyleName(XML_DEFAULT_CELL_STYLE_NAME,xFind,_rAtt,m_aCellAutoStyleNames);
+ exportStyleName(XML_DEFAULT_ROW_STYLE_NAME,xFind,_rAtt,m_aRowAutoStyleNames);
+}
+
+void ODBExport::exportStyleName(const ::xmloff::token::XMLTokenEnum _eToken,const uno::Reference<beans::XPropertySet>& _xProp,SvXMLAttributeList& _rAtt,TPropertyStyleMap& _rMap)
+{
+ TPropertyStyleMap::const_iterator aFind = _rMap.find(_xProp);
+ if ( aFind != _rMap.end() )
+ {
+ _rAtt.AddAttribute( GetNamespaceMap().GetQNameByKey( XML_NAMESPACE_DB, GetXMLToken(_eToken) ),
+ aFind->second );
+ _rMap.erase(aFind);
+ }
+}
+
+void ODBExport::exportTableName(XPropertySet* _xProp,bool _bUpdate)
+{
+ OUString sValue;
+ _xProp->getPropertyValue(_bUpdate ? OUString(PROPERTY_UPDATE_TABLENAME) : OUString(PROPERTY_NAME)) >>= sValue;
+ if ( sValue.isEmpty() )
+ return;
+
+ AddAttribute(XML_NAMESPACE_DB, XML_NAME,sValue);
+ _xProp->getPropertyValue(_bUpdate ? OUString(PROPERTY_UPDATE_SCHEMANAME) : OUString(PROPERTY_SCHEMANAME)) >>= sValue;
+ if ( !sValue.isEmpty() )
+ AddAttribute(XML_NAMESPACE_DB, XML_SCHEMA_NAME,sValue);
+ _xProp->getPropertyValue(_bUpdate ? OUString(PROPERTY_UPDATE_CATALOGNAME) : OUString(PROPERTY_CATALOGNAME)) >>= sValue;
+ if ( !sValue.isEmpty() )
+ AddAttribute(XML_NAMESPACE_DB, XML_CATALOG_NAME,sValue);
+
+ if ( _bUpdate )
+ {
+ SvXMLElementExport aComponents(*this,XML_NAMESPACE_DB, XML_UPDATE_TABLE, true, true);
+ }
+}
+
+void ODBExport::exportFilter(XPropertySet* _xProp
+ ,const OUString& _sProp
+ ,enum ::xmloff::token::XMLTokenEnum _eStatementType)
+{
+ OSL_PRECOND(!GetAttrList().getLength(),"Invalid attribute length!");
+ OUString sCommand;
+ _xProp->getPropertyValue(_sProp) >>= sCommand;
+ if ( !sCommand.isEmpty() )
+ {
+ AddAttribute(XML_NAMESPACE_DB, XML_COMMAND,sCommand);
+ SvXMLElementExport aComponents(*this,XML_NAMESPACE_DB, _eStatementType, true, true);
+ }
+ SAL_WARN_IF(GetAttrList().getLength(), "dbaccess", "Invalid attribute length!");
+}
+
+void ODBExport::exportColumns(const Reference<XColumnsSupplier>& _xColSup)
+{
+ OSL_PRECOND( _xColSup.is(), "ODBExport::exportColumns: invalid columns supplier!" );
+ if ( !_xColSup.is() )
+ return;
+
+ try
+ {
+ Reference<XNameAccess> xNameAccess( _xColSup->getColumns(), UNO_SET_THROW );
+ if ( !xNameAccess->hasElements() )
+ {
+ Reference< XPropertySet > xComponent(_xColSup,UNO_QUERY);
+ TTableColumnMap::const_iterator aFind = m_aTableDummyColumns.find(xComponent);
+ if ( aFind != m_aTableDummyColumns.end() )
+ {
+ SvXMLElementExport aColumns(*this,XML_NAMESPACE_DB, XML_COLUMNS, true, true);
+ rtl::Reference<SvXMLAttributeList> pAtt = new SvXMLAttributeList;
+ exportStyleName(aFind->second.get(),*pAtt);
+ AddAttributeList(pAtt);
+ SvXMLElementExport aColumn(*this,XML_NAMESPACE_DB, XML_COLUMN, true, true);
+
+ }
+ return;
+ }
+
+ SvXMLElementExport aColumns(*this,XML_NAMESPACE_DB, XML_COLUMNS, true, true);
+ Sequence< OUString> aSeq = xNameAccess->getElementNames();
+ const OUString* pIter = aSeq.getConstArray();
+ const OUString* pEnd = pIter + aSeq.getLength();
+ for( ; pIter != pEnd ; ++pIter)
+ {
+ Reference<XPropertySet> xProp(xNameAccess->getByName(*pIter),UNO_QUERY);
+ if ( xProp.is() )
+ {
+ rtl::Reference<SvXMLAttributeList> pAtt = new SvXMLAttributeList;
+ exportStyleName(xProp.get(),*pAtt);
+
+ bool bHidden = getBOOL(xProp->getPropertyValue(PROPERTY_HIDDEN));
+
+ OUString sValue;
+ xProp->getPropertyValue(PROPERTY_HELPTEXT) >>= sValue;
+ Any aColumnDefault = xProp->getPropertyValue(PROPERTY_CONTROLDEFAULT);
+
+ if ( bHidden || !sValue.isEmpty() || aColumnDefault.hasValue() || pAtt->getLength() )
+ {
+ AddAttribute(XML_NAMESPACE_DB, XML_NAME,*pIter);
+ if ( bHidden )
+ AddAttribute(XML_NAMESPACE_DB, XML_VISIBLE,XML_FALSE);
+
+ if ( !sValue.isEmpty() )
+ AddAttribute(XML_NAMESPACE_DB, XML_HELP_MESSAGE,sValue);
+
+ if ( aColumnDefault.hasValue() )
+ {
+ OUStringBuffer sColumnDefaultString,sType;
+ ::sax::Converter::convertAny(
+ sColumnDefaultString, sType, aColumnDefault );
+ AddAttribute(XML_NAMESPACE_DB, XML_TYPE_NAME,sType.makeStringAndClear());
+ AddAttribute(XML_NAMESPACE_DB, XML_DEFAULT_VALUE,sColumnDefaultString.makeStringAndClear());
+ }
+
+ if ( pAtt->getLength() )
+ AddAttributeList(pAtt);
+ }
+
+ if ( GetAttrList().getLength() )
+ {
+ SvXMLElementExport aComponents(*this,XML_NAMESPACE_DB, XML_COLUMN, true, true);
+ }
+ }
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+}
+
+void ODBExport::exportForms()
+{
+ Any aValue;
+ OUString sService;
+ dbtools::getDataSourceSetting(getDataSource(),"Forms",aValue);
+ aValue >>= sService;
+ if ( !sService.isEmpty() )
+ return;
+
+ Reference<XFormDocumentsSupplier> xSup(GetModel(),UNO_QUERY);
+ if ( xSup.is() )
+ {
+ Reference< XNameAccess > xCollection = xSup->getFormDocuments();
+ if ( xCollection.is() && xCollection->hasElements() )
+ {
+ ::comphelper::mem_fun1_t<ODBExport,XPropertySet* > aMemFunc(&ODBExport::exportComponent);
+ exportCollection(xCollection,XML_FORMS,XML_COMPONENT_COLLECTION,true,aMemFunc);
+ }
+ }
+}
+
+void ODBExport::exportReports()
+{
+ Any aValue;
+ OUString sService;
+ dbtools::getDataSourceSetting(getDataSource(),"Reports",aValue);
+ aValue >>= sService;
+ if ( !sService.isEmpty() )
+ return;
+
+ Reference<XReportDocumentsSupplier> xSup(GetModel(),UNO_QUERY);
+ if ( xSup.is() )
+ {
+ Reference< XNameAccess > xCollection = xSup->getReportDocuments();
+ if ( xCollection.is() && xCollection->hasElements() )
+ {
+ ::comphelper::mem_fun1_t<ODBExport,XPropertySet* > aMemFunc(&ODBExport::exportComponent);
+ exportCollection(xCollection,XML_REPORTS,XML_COMPONENT_COLLECTION,true,aMemFunc);
+ }
+ }
+}
+
+void ODBExport::exportQueries(bool _bExportContext)
+{
+ Any aValue;
+ OUString sService;
+ dbtools::getDataSourceSetting(getDataSource(),"CommandDefinitions",aValue);
+ aValue >>= sService;
+ if ( !sService.isEmpty() )
+ return;
+
+ Reference<XQueryDefinitionsSupplier> xSup(getDataSource(),UNO_QUERY);
+ if ( !xSup.is() )
+ return;
+
+ Reference< XNameAccess > xCollection = xSup->getQueryDefinitions();
+ if ( xCollection.is() && xCollection->hasElements() )
+ {
+ std::unique_ptr< ::comphelper::mem_fun1_t<ODBExport,XPropertySet* > > pMemFunc;
+ if ( _bExportContext )
+ pMemFunc.reset( new ::comphelper::mem_fun1_t<ODBExport,XPropertySet* >(&ODBExport::exportQuery) );
+ else
+ pMemFunc.reset( new ::comphelper::mem_fun1_t<ODBExport,XPropertySet* >(&ODBExport::exportAutoStyle) );
+
+ exportCollection(xCollection,XML_QUERIES,XML_QUERY_COLLECTION,_bExportContext,*pMemFunc);
+ }
+}
+
+void ODBExport::exportTables(bool _bExportContext)
+{
+ Reference<XTablesSupplier> xSup(getDataSource(),UNO_QUERY);
+ if ( !xSup.is() )
+ return;
+
+ Reference< XNameAccess > xCollection = xSup->getTables();
+ if ( xCollection.is() && xCollection->hasElements() )
+ {
+ std::unique_ptr< ::comphelper::mem_fun1_t<ODBExport,XPropertySet* > > pMemFunc;
+ if ( _bExportContext )
+ pMemFunc.reset( new ::comphelper::mem_fun1_t<ODBExport,XPropertySet* >(&ODBExport::exportTable) );
+ else
+ pMemFunc.reset( new ::comphelper::mem_fun1_t<ODBExport,XPropertySet* >(&ODBExport::exportAutoStyle) );
+ exportCollection(xCollection,XML_TABLE_REPRESENTATIONS,XML_TOKEN_INVALID,_bExportContext,*pMemFunc);
+ }
+}
+
+void ODBExport::exportAutoStyle(XPropertySet* _xProp)
+{
+ typedef std::pair<TPropertyStyleMap*,XmlStyleFamily> TEnumMapperPair;
+ typedef std::pair< rtl::Reference < SvXMLExportPropertyMapper> , TEnumMapperPair> TExportPropMapperPair;
+ Reference<XColumnsSupplier> xSup(_xProp,UNO_QUERY);
+ if ( xSup.is() )
+ {
+ const TExportPropMapperPair pExportHelper[] = {
+ TExportPropMapperPair(m_xExportHelper,TEnumMapperPair(&m_aAutoStyleNames,XmlStyleFamily::TABLE_TABLE ))
+ // ,TExportPropMapperPair(m_xCellExportHelper,TEnumMapperPair(&m_aCellAutoStyleNames,XmlStyleFamily::TABLE_CELL))
+ ,TExportPropMapperPair(m_xRowExportHelper,TEnumMapperPair(&m_aRowAutoStyleNames,XmlStyleFamily::TABLE_ROW))
+ };
+
+ for (const auto & i : pExportHelper)
+ {
+ std::vector< XMLPropertyState > aPropertyStates = i.first->Filter(*this, _xProp);
+ if ( !aPropertyStates.empty() )
+ i.second.first->emplace( _xProp,GetAutoStylePool()->Add( i.second.second, std::move(aPropertyStates) ) );
+ }
+
+ Reference< XNameAccess > xCollection;
+ try
+ {
+ xCollection.set( xSup->getColumns(), UNO_SET_THROW );
+ awt::FontDescriptor aFont;
+ _xProp->getPropertyValue(PROPERTY_FONT) >>= aFont;
+ GetFontAutoStylePool()->Add(aFont.Name,aFont.StyleName,static_cast<FontFamily>(aFont.Family),
+ static_cast<FontPitch>(aFont.Pitch),aFont.CharSet );
+
+ m_aCurrentPropertyStates = m_xCellExportHelper->Filter(*this, _xProp);
+ if ( !m_aCurrentPropertyStates.empty() && !xCollection->hasElements() )
+ {
+ Reference< XDataDescriptorFactory> xFac(xCollection,UNO_QUERY);
+ if ( xFac.is() )
+ {
+ Reference< XPropertySet> xColumn = xFac->createDataDescriptor();
+ m_aTableDummyColumns.emplace( Reference< XPropertySet>(_xProp),xColumn );
+ exportAutoStyle(xColumn.get());
+ }
+ }
+ else
+ {
+ ::comphelper::mem_fun1_t<ODBExport,XPropertySet* > aMemFunc(&ODBExport::exportAutoStyle);
+ exportCollection(xCollection,XML_TOKEN_INVALID,XML_TOKEN_INVALID,false,aMemFunc);
+ }
+ }
+ catch(const Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ m_aCurrentPropertyStates.clear();
+ }
+ else
+ { // here I know I have a column
+ const TExportPropMapperPair pExportHelper[] = {
+ TExportPropMapperPair(m_xColumnExportHelper,TEnumMapperPair(&m_aAutoStyleNames,XmlStyleFamily::TABLE_COLUMN ))
+ ,TExportPropMapperPair(m_xCellExportHelper,TEnumMapperPair(&m_aCellAutoStyleNames,XmlStyleFamily::TABLE_CELL))
+ };
+ for (const auto & i : pExportHelper)
+ {
+ std::vector< XMLPropertyState > aPropStates = i.first->Filter(*this, _xProp);
+ if ( !aPropStates.empty() )
+ {
+ const rtl::Reference < XMLPropertySetMapper >& pStyle = i.first->getPropertySetMapper();
+ for (auto & propState : aPropStates)
+ {
+ if ( propState.mnIndex != -1 )
+ {
+ switch ( pStyle->GetEntryContextId(propState.mnIndex) )
+ {
+ case CTF_DB_NUMBERFORMAT:
+ {
+ sal_Int32 nNumberFormat = -1;
+ if ( propState.maValue >>= nNumberFormat )
+ addDataStyle(nNumberFormat);
+ }
+ break;
+ case CTF_DB_COLUMN_TEXT_ALIGN:
+ if ( !propState.maValue.hasValue() )
+ propState.maValue <<= css::awt::TextAlign::LEFT;
+ break;
+ }
+ }
+ }
+
+ }
+ if ( XmlStyleFamily::TABLE_CELL == i.second.second )
+ aPropStates.insert( aPropStates.end(), m_aCurrentPropertyStates.begin(), m_aCurrentPropertyStates.end() );
+ if ( !aPropStates.empty() )
+ i.second.first->emplace( _xProp,GetAutoStylePool()->Add( i.second.second, std::move(aPropStates) ) );
+ }
+ }
+}
+
+void ODBExport::ExportContent_()
+{
+ exportDataSource();
+ exportForms();
+ exportReports();
+ exportQueries(true);
+ exportTables(true);
+}
+
+void ODBExport::ExportMasterStyles_()
+{
+ GetPageExport()->exportMasterStyles( true );
+}
+
+void ODBExport::ExportAutoStyles_()
+{
+ // there are no styles that require their own autostyles
+ if ( getExportFlags() & SvXMLExportFlags::CONTENT )
+ {
+ collectComponentStyles();
+ GetAutoStylePool()->exportXML(XmlStyleFamily::TABLE_TABLE);
+ GetAutoStylePool()->exportXML(XmlStyleFamily::TABLE_COLUMN);
+ GetAutoStylePool()->exportXML(XmlStyleFamily::TABLE_CELL);
+ GetAutoStylePool()->exportXML(XmlStyleFamily::TABLE_ROW);
+ exportDataStyles();
+ }
+}
+
+void ODBExport::GetViewSettings(Sequence<PropertyValue>& aProps)
+{
+ Reference<XQueryDefinitionsSupplier> xSup(getDataSource(),UNO_QUERY);
+ if ( !xSup.is() )
+ return;
+
+ Reference< XNameAccess > xCollection = xSup->getQueryDefinitions();
+ if ( !(xCollection.is() && xCollection->hasElements()) )
+ return;
+
+ try
+ {
+ sal_Int32 nLength = aProps.getLength();
+ aProps.realloc(nLength + 1);
+ auto pProps = aProps.getArray();
+ pProps[nLength].Name = "Queries";
+ Sequence< OUString> aSeq = xCollection->getElementNames();
+ const OUString* pIter = aSeq.getConstArray();
+ const OUString* pEnd = pIter + aSeq.getLength();
+
+ Sequence<PropertyValue> aQueries(aSeq.getLength());
+ auto aQueriesRange = asNonConstRange(aQueries);
+ for(sal_Int32 i = 0;pIter != pEnd;++pIter,++i)
+ {
+ Reference<XPropertySet> xProp(xCollection->getByName(*pIter),UNO_QUERY);
+ if ( xProp.is() )
+ {
+ aQueriesRange[i].Name = *pIter;
+ aQueriesRange[i].Value = xProp->getPropertyValue(PROPERTY_LAYOUTINFORMATION);
+ }
+ }
+ pProps[nLength].Value <<= aQueries;
+ }
+ catch(const Exception&)
+ {
+ TOOLS_WARN_EXCEPTION( "dbaccess", "ODBExport::GetViewSettings");
+ }
+
+}
+
+void ODBExport::GetConfigurationSettings(Sequence<PropertyValue>& aProps)
+{
+ Reference<XPropertySet> xProp(getDataSource());
+ if ( !xProp.is() )
+ return;
+
+ sal_Int32 nLength = aProps.getLength();
+ try
+ {
+ Any aValue = xProp->getPropertyValue(PROPERTY_LAYOUTINFORMATION);
+ Sequence< PropertyValue > aPropValues;
+ aValue >>= aPropValues;
+ if ( aPropValues.hasElements() )
+ {
+ aProps.realloc(nLength + 1);
+ auto pProps = aProps.getArray();
+ pProps[nLength].Name = "layout-settings";
+ pProps[nLength].Value = aValue;
+ }
+ }
+ catch(const Exception&)
+ {
+ OSL_FAIL("Could not access layout information from the data source!");
+ }
+}
+
+OUString ODBExport::implConvertAny(const Any& _rValue)
+{
+ OUStringBuffer aBuffer;
+ switch (_rValue.getValueTypeClass())
+ {
+ case TypeClass_STRING:
+ { // extract the string
+ OUString sCurrentValue;
+ _rValue >>= sCurrentValue;
+ aBuffer.append(sCurrentValue);
+ }
+ break;
+ case TypeClass_DOUBLE:
+ // let the unit converter format is as string
+ ::sax::Converter::convertDouble(aBuffer, getDouble(_rValue));
+ break;
+ case TypeClass_BOOLEAN:
+ aBuffer = getBOOL(_rValue) ? ::xmloff::token::GetXMLToken(XML_TRUE) : ::xmloff::token::GetXMLToken(XML_FALSE);
+ break;
+ case TypeClass_BYTE:
+ case TypeClass_SHORT:
+ case TypeClass_LONG:
+ // let the unit converter format is as string
+ aBuffer.append(getINT32(_rValue));
+ break;
+ default:
+ OSL_FAIL("ODBExport::implConvertAny: Invalid type");
+ }
+
+ return aBuffer.makeStringAndClear();
+}
+
+rtl::Reference < XMLPropertySetMapper > const & ODBExport::GetTableStylesPropertySetMapper() const
+{
+ if ( !m_xTableStylesPropertySetMapper.is() )
+ {
+ m_xTableStylesPropertySetMapper = OXMLHelper::GetTableStylesPropertySetMapper( true);
+ }
+ return m_xTableStylesPropertySetMapper;
+}
+
+rtl::Reference < XMLPropertySetMapper > const & ODBExport::GetCellStylesPropertySetMapper() const
+{
+ if ( !m_xCellStylesPropertySetMapper.is() )
+ {
+ m_xCellStylesPropertySetMapper = OXMLHelper::GetCellStylesPropertySetMapper( true);
+ }
+ return m_xCellStylesPropertySetMapper;
+}
+
+rtl::Reference < XMLPropertySetMapper > const & ODBExport::GetColumnStylesPropertySetMapper() const
+{
+ if ( !m_xColumnStylesPropertySetMapper.is() )
+ {
+ m_xColumnStylesPropertySetMapper = OXMLHelper::GetColumnStylesPropertySetMapper( true);
+ }
+ return m_xColumnStylesPropertySetMapper;
+}
+
+SvXMLAutoStylePoolP* ODBExport::CreateAutoStylePool()
+{
+ return new OXMLAutoStylePoolP(*this);
+}
+
+void SAL_CALL ODBExport::setSourceDocument( const Reference< XComponent >& xDoc )
+{
+ Reference<XOfficeDatabaseDocument> xOfficeDoc(xDoc,UNO_QUERY_THROW);
+ m_xDataSource.set(xOfficeDoc->getDataSource(),UNO_QUERY_THROW);
+ OSL_ENSURE(m_xDataSource.is(),"DataSource is NULL!");
+ Reference< XNumberFormatsSupplier > xNum(m_xDataSource->getPropertyValue(PROPERTY_NUMBERFORMATSSUPPLIER),UNO_QUERY);
+ SetNumberFormatsSupplier(xNum);
+ SvXMLExport::setSourceDocument(xDoc);
+}
+
+void ODBExport::ExportFontDecls_()
+{
+ GetFontAutoStylePool(); // make sure the pool is created
+ collectComponentStyles();
+ SvXMLExport::ExportFontDecls_();
+}
+
+void ODBExport::collectComponentStyles()
+{
+ if ( m_bAllreadyFilled )
+ return;
+
+ m_bAllreadyFilled = true;
+ exportQueries(false);
+ exportTables(false);
+}
+
+}// dbaxml
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/filter/xml/xmlExport.hxx b/dbaccess/source/filter/xml/xmlExport.hxx
new file mode 100644
index 000000000..7e1d148e1
--- /dev/null
+++ b/dbaccess/source/filter/xml/xmlExport.hxx
@@ -0,0 +1,176 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <com/sun/star/container/XNamed.hpp>
+#include <com/sun/star/document/XFilter.hpp>
+#include <com/sun/star/document/XImporter.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/lang/XComponent.hpp>
+#include <com/sun/star/io/XActiveDataSource.hpp>
+#include <xmloff/maptype.hxx>
+#include <xmloff/txtprmap.hxx>
+#include <xmloff/xmlexp.hxx>
+#include <xmloff/xmlexppr.hxx>
+#include <dsntypes.hxx>
+#include <comphelper/stl_types.hxx>
+#include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
+
+#include <memory>
+
+
+namespace dbaxml {
+
+using namespace ::xmloff::token;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::document;
+using namespace ::com::sun::star::sdbcx;
+using namespace ::com::sun::star::text;
+using namespace ::com::sun::star::io;
+using namespace ::com::sun::star::xml::sax;
+
+
+class ODBExport : public SvXMLExport
+{
+ typedef std::map< ::xmloff::token::XMLTokenEnum, OUString> TSettingsMap;
+
+ typedef std::pair< OUString ,OUString> TStringPair;
+ struct TDelimiter
+ {
+ OUString sText;
+ OUString sField;
+ OUString sDecimal;
+ OUString sThousand;
+ bool bUsed;
+
+ TDelimiter() : bUsed( false ) { }
+ };
+ typedef std::map< Reference<XPropertySet> ,OUString > TPropertyStyleMap;
+ typedef std::map< Reference<XPropertySet> ,Reference<XPropertySet> > TTableColumnMap;
+
+ struct TypedPropertyValue
+ {
+ OUString Name;
+ css::uno::Type Type;
+ css::uno::Any Value;
+
+ TypedPropertyValue( const OUString& _name, const css::uno::Type& _type, const css::uno::Any& _value )
+ :Name( _name )
+ ,Type( _type )
+ ,Value( _value )
+ {
+ }
+ };
+
+ std::unique_ptr< TStringPair > m_aAutoIncrement;
+ std::unique_ptr< TDelimiter > m_aDelimiter;
+ std::vector< TypedPropertyValue > m_aDataSourceSettings;
+ std::vector< XMLPropertyState > m_aCurrentPropertyStates;
+ TPropertyStyleMap m_aAutoStyleNames;
+ TPropertyStyleMap m_aCellAutoStyleNames;
+ TPropertyStyleMap m_aRowAutoStyleNames;
+ TTableColumnMap m_aTableDummyColumns;
+ OUString m_sCharSet;
+ rtl::Reference < SvXMLExportPropertyMapper> m_xExportHelper;
+ rtl::Reference < SvXMLExportPropertyMapper> m_xColumnExportHelper;
+ rtl::Reference < SvXMLExportPropertyMapper> m_xCellExportHelper;
+ rtl::Reference < SvXMLExportPropertyMapper> m_xRowExportHelper;
+
+ mutable rtl::Reference < XMLPropertySetMapper > m_xTableStylesPropertySetMapper;
+ mutable rtl::Reference < XMLPropertySetMapper > m_xColumnStylesPropertySetMapper;
+ mutable rtl::Reference < XMLPropertySetMapper > m_xCellStylesPropertySetMapper;
+
+ Reference<XPropertySet> m_xDataSource;
+ ::dbaccess::ODsnTypeCollection m_aTypeCollection;
+ bool m_bAllreadyFilled;
+
+ void exportDataSource();
+ void exportConnectionData();
+ void exportDriverSettings(const TSettingsMap& _aSettings);
+ void exportApplicationConnectionSettings(const TSettingsMap& _aSettings);
+ void exportLogin();
+ void exportSequence(const Sequence< OUString>& _aValue
+ ,::xmloff::token::XMLTokenEnum _eTokenFilter
+ ,::xmloff::token::XMLTokenEnum _eTokenType);
+ void exportDelimiter();
+ void exportAutoIncrement();
+ void exportCharSet();
+ template< typename T > void exportDataSourceSettingsSequence(
+ std::vector< TypedPropertyValue >::iterator const & in);
+ void exportDataSourceSettings();
+ void exportForms();
+ void exportReports();
+ void exportQueries(bool _bExportContext);
+ void exportTables(bool _bExportContext);
+ void exportStyleName(XPropertySet* _xProp,SvXMLAttributeList& _rAtt);
+ void exportStyleName(const ::xmloff::token::XMLTokenEnum _eToken,const Reference<XPropertySet>& _xProp,SvXMLAttributeList& _rAtt,TPropertyStyleMap& _rMap);
+ void exportCollection(const Reference< XNameAccess >& _xCollection
+ ,enum ::xmloff::token::XMLTokenEnum _eComponents
+ ,enum ::xmloff::token::XMLTokenEnum _eSubComponents
+ ,bool _bExportContext
+ ,const ::comphelper::mem_fun1_t<ODBExport,XPropertySet* >& _aMemFunc
+ );
+ void exportComponent(XPropertySet* _xProp);
+ void exportQuery(XPropertySet* _xProp);
+ void exportTable(XPropertySet* _xProp);
+ void exportFilter(XPropertySet* _xProp
+ ,const OUString& _sProp
+ ,enum ::xmloff::token::XMLTokenEnum _eStatementType);
+ void exportTableName(XPropertySet* _xProp,bool _bUpdate);
+ void exportAutoStyle(XPropertySet* _xProp);
+ void exportColumns(const Reference<XColumnsSupplier>& _xColSup);
+ void collectComponentStyles();
+
+ static OUString implConvertAny(const Any& _rValue);
+
+ rtl::Reference < XMLPropertySetMapper > const & GetTableStylesPropertySetMapper() const;
+
+ ODBExport() = delete;
+protected:
+
+ virtual void ExportAutoStyles_() override;
+ virtual void ExportContent_() override;
+ virtual void ExportMasterStyles_() override;
+ virtual void ExportFontDecls_() override;
+ virtual SvXMLAutoStylePoolP* CreateAutoStylePool() override;
+
+ virtual void GetViewSettings(css::uno::Sequence<css::beans::PropertyValue>& aProps) override;
+ virtual void GetConfigurationSettings(css::uno::Sequence<css::beans::PropertyValue>& aProps) override;
+
+ virtual ~ODBExport() override {};
+public:
+
+ ODBExport(const Reference< XComponentContext >& _rxContext, OUString const & implementationName, SvXMLExportFlags nExportFlag = SvXMLExportFlags::CONTENT | SvXMLExportFlags::AUTOSTYLES | SvXMLExportFlags::PRETTY | SvXMLExportFlags::FONTDECLS | SvXMLExportFlags::SCRIPTS );
+
+ rtl::Reference < XMLPropertySetMapper > const & GetColumnStylesPropertySetMapper() const;
+ rtl::Reference < XMLPropertySetMapper > const & GetCellStylesPropertySetMapper() const;
+
+ // XExporter
+ virtual void SAL_CALL setSourceDocument( const css::uno::Reference< css::lang::XComponent >& xDoc ) override;
+
+ const Reference<XPropertySet>& getDataSource() const { return m_xDataSource; }
+};
+
+} // dbaxml
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/filter/xml/xmlFileBasedDatabase.cxx b/dbaccess/source/filter/xml/xmlFileBasedDatabase.cxx
new file mode 100644
index 000000000..37e4058ab
--- /dev/null
+++ b/dbaccess/source/filter/xml/xmlFileBasedDatabase.cxx
@@ -0,0 +1,113 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "xmlFileBasedDatabase.hxx"
+#include "xmlfilter.hxx"
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <strings.hxx>
+#include <tools/diagnose_ex.h>
+#include <svl/filenotation.hxx>
+#include <unotools/pathoptions.hxx>
+#include <dsntypes.hxx>
+namespace dbaxml
+{
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::xml::sax;
+
+OXMLFileBasedDatabase::OXMLFileBasedDatabase( ODBFilter& rImport,
+ const Reference< XFastAttributeList > & _xAttrList) :
+ SvXMLImportContext( rImport )
+{
+ Reference<XPropertySet> xDataSource = rImport.getDataSource();
+
+ PropertyValue aProperty;
+
+ OUString sLocation,sMediaType,sFileTypeExtension;
+ if (xDataSource.is())
+ {
+ for (auto &aIter : sax_fastparser::castToFastAttributeList( _xAttrList ))
+ {
+ OUString sValue = aIter.toString();
+
+ aProperty.Name.clear();
+ aProperty.Value = Any();
+
+ switch( aIter.getToken() )
+ {
+ case XML_ELEMENT(XLINK, XML_HREF):
+ {
+ SvtPathOptions aPathOptions;
+ OUString sFileName = aPathOptions.SubstituteVariable(sValue);
+ if ( sValue == sFileName )
+ {
+ const sal_Int32 nFileNameLength = sFileName.getLength();
+ if ( sFileName.endsWith("/") )
+ sFileName = sFileName.copy( 0, nFileNameLength - 1 );
+
+ sLocation = ::svt::OFileNotation( rImport.GetAbsoluteReference( sFileName ) ).get( ::svt::OFileNotation::N_SYSTEM );
+ }
+
+ if ( sLocation.isEmpty() )
+ sLocation = sValue;
+ }
+ break;
+ case XML_ELEMENT(DB, XML_MEDIA_TYPE):
+ case XML_ELEMENT(DB_OASIS, XML_MEDIA_TYPE):
+ sMediaType = sValue;
+ break;
+ case XML_ELEMENT(DB, XML_EXTENSION):
+ case XML_ELEMENT(DB_OASIS, XML_EXTENSION):
+ aProperty.Name = INFO_TEXTFILEEXTENSION;
+ sFileTypeExtension = sValue;
+ break;
+ default:
+ XMLOFF_WARN_UNKNOWN("dbaccess", aIter);
+ }
+ if ( !aProperty.Name.isEmpty() )
+ {
+ if ( !aProperty.Value.hasValue() )
+ aProperty.Value <<= sValue;
+ rImport.addInfo(aProperty);
+ }
+ }
+ }
+ if ( sLocation.isEmpty() || sMediaType.isEmpty() )
+ return;
+
+ ::dbaccess::ODsnTypeCollection aTypeCollection(rImport.GetComponentContext());
+ OUString sURL = aTypeCollection.getDatasourcePrefixFromMediaType(sMediaType,sFileTypeExtension) + sLocation;
+ try
+ {
+ xDataSource->setPropertyValue(PROPERTY_URL,Any(sURL));
+ }
+ catch(const Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+}
+
+OXMLFileBasedDatabase::~OXMLFileBasedDatabase()
+{
+
+}
+
+} // namespace dbaxml
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/filter/xml/xmlFileBasedDatabase.hxx b/dbaccess/source/filter/xml/xmlFileBasedDatabase.hxx
new file mode 100644
index 000000000..3720e1da3
--- /dev/null
+++ b/dbaccess/source/filter/xml/xmlFileBasedDatabase.hxx
@@ -0,0 +1,36 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <xmloff/xmlictxt.hxx>
+
+namespace dbaxml
+{
+ class ODBFilter;
+ class OXMLFileBasedDatabase : public SvXMLImportContext
+ {
+ public:
+
+ OXMLFileBasedDatabase( ODBFilter& rImport,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList > & _xAttrList );
+ virtual ~OXMLFileBasedDatabase() override;
+ };
+} // namespace dbaxml
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/filter/xml/xmlHelper.cxx b/dbaccess/source/filter/xml/xmlHelper.cxx
new file mode 100644
index 000000000..85b98ec1e
--- /dev/null
+++ b/dbaccess/source/filter/xml/xmlHelper.cxx
@@ -0,0 +1,157 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "xmlHelper.hxx"
+#include <xmloff/XMLConstantsPropertyHandler.hxx>
+#include <xmloff/xmlement.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/xmltypes.hxx>
+#include <xmloff/maptype.hxx>
+
+#include <com/sun/star/awt/TextAlign.hpp>
+#include <strings.hxx>
+#include <rtl/ref.hxx>
+
+namespace dbaxml
+{
+ using namespace ::xmloff::token;
+ using namespace ::com::sun::star::awt;
+
+OPropertyHandlerFactory::OPropertyHandlerFactory()
+{
+}
+
+OPropertyHandlerFactory::~OPropertyHandlerFactory()
+{
+
+}
+
+const XMLPropertyHandler* OPropertyHandlerFactory::GetPropertyHandler(sal_Int32 _nType) const
+{
+ const XMLPropertyHandler* pHandler = nullptr;
+
+ switch (_nType)
+ {
+ case XML_DB_TYPE_EQUAL:
+ if (!m_pDisplayHandler)
+ {
+ static const SvXMLEnumMapEntry<bool> aDisplayMap[] =
+ {
+ { XML_VISIBLE, true },
+ { XML_COLLAPSE, false },
+ { XML_TOKEN_INVALID, false }
+ };
+ m_pDisplayHandler.reset(new XMLConstantsPropertyHandler(aDisplayMap, XML_TOKEN_INVALID ));
+ }
+ pHandler = m_pDisplayHandler.get();
+ break;
+ }
+ if ( !pHandler )
+ pHandler = OControlPropertyHandlerFactory::GetPropertyHandler(_nType);
+ return pHandler;
+}
+
+rtl::Reference < XMLPropertySetMapper > OXMLHelper::GetTableStylesPropertySetMapper( bool bForExport )
+{
+ static const XMLPropertyMapEntry s_aTableStylesProperties[] =
+ {
+ { nullptr, 0, XML_TOKEN_INVALID, 0 , 0, SvtSaveOptions::ODFSVER_010, false}
+ };
+ rtl::Reference < XMLPropertyHandlerFactory> xFac = new ::xmloff::OControlPropertyHandlerFactory();
+ return new XMLPropertySetMapper(s_aTableStylesProperties, xFac, bForExport);
+}
+
+rtl::Reference < XMLPropertySetMapper > OXMLHelper::GetColumnStylesPropertySetMapper( bool bForExport )
+{
+ static const XMLPropertyMapEntry s_aColumnStylesProperties[] =
+ {
+ { PROPERTY_WIDTH, XML_NAMESPACE_STYLE, XML_COLUMN_WIDTH, XML_TYPE_MEASURE|XML_TYPE_PROP_TABLE_COLUMN, 0, SvtSaveOptions::ODFSVER_010, false },
+ { PROPERTY_HIDDEN, XML_NAMESPACE_TABLE, XML_DISPLAY, XML_DB_TYPE_EQUAL|MID_FLAG_SPECIAL_ITEM|XML_TYPE_PROP_TABLE_COLUMN,
+ CTF_DB_ISVISIBLE, SvtSaveOptions::ODFSVER_010, false },
+ { PROPERTY_NUMBERFORMAT, XML_NAMESPACE_STYLE, XML_DATA_STYLE_NAME, XML_TYPE_NUMBER|MID_FLAG_SPECIAL_ITEM|XML_TYPE_PROP_TABLE_COLUMN,
+ CTF_DB_NUMBERFORMAT, SvtSaveOptions::ODFSVER_010, false },
+ { nullptr, 0, XML_TOKEN_INVALID, 0 , 0, SvtSaveOptions::ODFSVER_010, false}
+ };
+ rtl::Reference < XMLPropertyHandlerFactory> xFac = new OPropertyHandlerFactory();
+ return new XMLPropertySetMapper(s_aColumnStylesProperties, xFac, bForExport);
+}
+
+rtl::Reference < XMLPropertySetMapper > OXMLHelper::GetCellStylesPropertySetMapper( bool bForExport )
+{
+ static const XMLPropertyMapEntry s_aCellStylesProperties[] =
+ {
+ { PROPERTY_ALIGN, XML_NAMESPACE_FO, XML_TEXT_ALIGN, XML_TYPE_TEXT_ALIGN|XML_TYPE_PROP_PARAGRAPH, CTF_DB_COLUMN_TEXT_ALIGN, SvtSaveOptions::ODFSVER_010, false },
+ { PROPERTY_FONTNAME, XML_NAMESPACE_STYLE, XML_FONT_NAME, XML_TYPE_STRING|XML_TYPE_PROP_TEXT, 0 , SvtSaveOptions::ODFSVER_010, false },
+ { PROPERTY_TEXTCOLOR, XML_NAMESPACE_FO, XML_COLOR, XML_TYPE_COLOR|XML_TYPE_PROP_TEXT, 0 , SvtSaveOptions::ODFSVER_010, false },
+ { PROPERTY_TEXTLINECOLOR, XML_NAMESPACE_STYLE, XML_TEXT_UNDERLINE_COLOR,
+ XML_TYPE_TEXT_UNDERLINE_COLOR|MID_FLAG_MULTI_PROPERTY|XML_TYPE_PROP_TEXT, 0 , SvtSaveOptions::ODFSVER_010, false },
+ { PROPERTY_TEXTRELIEF, XML_NAMESPACE_STYLE, XML_FONT_RELIEF,
+ XML_TYPE_TEXT_FONT_RELIEF|MID_FLAG_MULTI_PROPERTY|XML_TYPE_PROP_TEXT, 0 , SvtSaveOptions::ODFSVER_010, false },
+ { PROPERTY_TEXTEMPHASIS, XML_NAMESPACE_STYLE, XML_TEXT_EMPHASIZE, XML_TYPE_CONTROL_TEXT_EMPHASIZE|XML_TYPE_PROP_TEXT, 0 , SvtSaveOptions::ODFSVER_010, false },
+ { PROPERTY_FONTCHARWIDTH, XML_NAMESPACE_STYLE, XML_FONT_CHAR_WIDTH, XML_TYPE_NUMBER16|XML_TYPE_PROP_TEXT, 0 , SvtSaveOptions::ODFSVER_010, false },
+ { PROPERTY_FONTCHARSET, XML_NAMESPACE_STYLE, XML_FONT_CHARSET, XML_TYPE_TEXT_FONTENCODING|XML_TYPE_PROP_TEXT, 0 , SvtSaveOptions::ODFSVER_010, false },
+ { PROPERTY_FONTFAMILY, XML_NAMESPACE_STYLE, XML_FONT_FAMILY_GENERIC, XML_TYPE_TEXT_FONTFAMILY|XML_TYPE_PROP_TEXT, 0 , SvtSaveOptions::ODFSVER_010, false },
+ { PROPERTY_FONTHEIGHT, XML_NAMESPACE_FO, XML_FONT_SIZE, XML_TYPE_MEASURE16|XML_TYPE_PROP_TEXT, 0 , SvtSaveOptions::ODFSVER_010, false },
+ { PROPERTY_FONTKERNING, XML_NAMESPACE_STYLE, XML_LETTER_KERNING, XML_TYPE_BOOL|XML_TYPE_PROP_TEXT, 0 , SvtSaveOptions::ODFSVER_010, false },
+ { PROPERTY_FONTORIENTATION, XML_NAMESPACE_STYLE, XML_ROTATION_ANGLE, XML_TYPE_ROTATION_ANGLE|XML_TYPE_PROP_TEXT, 0 , SvtSaveOptions::ODFSVER_010, false },
+ { PROPERTY_FONTPITCH, XML_NAMESPACE_STYLE, XML_FONT_PITCH, XML_TYPE_TEXT_FONTPITCH|XML_TYPE_PROP_TEXT, 0 , SvtSaveOptions::ODFSVER_010, false },
+ { PROPERTY_FONTSLANT, XML_NAMESPACE_FO, XML_FONT_STYLE, XML_TYPE_TEXT_POSTURE|XML_TYPE_PROP_TEXT, 0 , SvtSaveOptions::ODFSVER_010, false },
+ { "CharStrikeout", XML_NAMESPACE_STYLE, XML_TEXT_LINE_THROUGH_STYLE,
+ XML_TYPE_TEXT_CROSSEDOUT_STYLE|MID_FLAG_MERGE_PROPERTY|XML_TYPE_PROP_TEXT, 0, SvtSaveOptions::ODFSVER_010, false },
+ { "CharStrikeout", XML_NAMESPACE_STYLE, XML_TEXT_LINE_THROUGH_TYPE,
+ XML_TYPE_TEXT_CROSSEDOUT_TYPE|MID_FLAG_MERGE_PROPERTY|XML_TYPE_PROP_TEXT, 0, SvtSaveOptions::ODFSVER_010, false },
+ { "CharStrikeout", XML_NAMESPACE_STYLE, XML_TEXT_LINE_THROUGH_WIDTH,
+ XML_TYPE_TEXT_CROSSEDOUT_WIDTH|MID_FLAG_MERGE_PROPERTY|XML_TYPE_PROP_TEXT, 0, SvtSaveOptions::ODFSVER_010, false },
+ { "CharStrikeout", XML_NAMESPACE_STYLE, XML_TEXT_LINE_THROUGH_TEXT,
+ XML_TYPE_TEXT_CROSSEDOUT_TEXT|MID_FLAG_MERGE_PROPERTY|XML_TYPE_PROP_TEXT, 0, SvtSaveOptions::ODFSVER_010, false },
+ { PROPERTY_FONTSTYLENAME, XML_NAMESPACE_STYLE, XML_FONT_STYLE_NAME, XML_TYPE_STRING|XML_TYPE_PROP_TEXT, 0 , SvtSaveOptions::ODFSVER_010, false },
+ { "CharUnderline", XML_NAMESPACE_STYLE, XML_TEXT_UNDERLINE_STYLE,
+ XML_TYPE_TEXT_UNDERLINE_STYLE|MID_FLAG_MERGE_PROPERTY|XML_TYPE_PROP_TEXT, 0 , SvtSaveOptions::ODFSVER_010, false },
+ { "CharUnderline", XML_NAMESPACE_STYLE, XML_TEXT_UNDERLINE_TYPE,
+ XML_TYPE_TEXT_UNDERLINE_TYPE|MID_FLAG_MERGE_PROPERTY|XML_TYPE_PROP_TEXT, 0 , SvtSaveOptions::ODFSVER_010, false },
+ { "CharUnderline", XML_NAMESPACE_STYLE, XML_TEXT_UNDERLINE_WIDTH,
+ XML_TYPE_TEXT_UNDERLINE_WIDTH|MID_FLAG_MERGE_PROPERTY|XML_TYPE_PROP_TEXT, 0 , SvtSaveOptions::ODFSVER_010, false },
+ { "CharUnderlineColor", XML_NAMESPACE_STYLE, XML_TEXT_UNDERLINE_COLOR,
+ XML_TYPE_TEXT_UNDERLINE_COLOR|MID_FLAG_MULTI_PROPERTY|XML_TYPE_PROP_TEXT, 0 , SvtSaveOptions::ODFSVER_010, false },
+ { "CharUnderlineHasColor", XML_NAMESPACE_STYLE, XML_TEXT_UNDERLINE_COLOR, XML_TYPE_TEXT_UNDERLINE_HASCOLOR|MID_FLAG_MERGE_ATTRIBUTE|XML_TYPE_PROP_TEXT, 0 , SvtSaveOptions::ODFSVER_010, false },
+ { PROPERTY_FONTWEIGHT, XML_NAMESPACE_FO, XML_FONT_WEIGHT, XML_TYPE_TEXT_WEIGHT|XML_TYPE_PROP_TEXT, 0 , SvtSaveOptions::ODFSVER_010, false },
+ { PROPERTY_FONTWIDTH, XML_NAMESPACE_STYLE, XML_FONT_WIDTH, XML_TYPE_FONT_WIDTH|XML_TYPE_PROP_TEXT, 0 , SvtSaveOptions::ODFSVER_010, false },
+ { PROPERTY_FONTWORDLINEMODE, XML_NAMESPACE_STYLE, XML_TEXT_UNDERLINE_MODE,
+ XML_TYPE_TEXT_LINE_MODE|MID_FLAG_MERGE_PROPERTY|XML_TYPE_PROP_TEXT, 0 , SvtSaveOptions::ODFSVER_010, false },
+ { nullptr, 0, XML_TOKEN_INVALID, 0 , 0, SvtSaveOptions::ODFSVER_010, false}
+ };
+ rtl::Reference < XMLPropertyHandlerFactory> xFac = new /*OPropertyHandlerFactory*/::xmloff::OControlPropertyHandlerFactory();
+ return new XMLPropertySetMapper(s_aCellStylesProperties, xFac, bForExport);
+}
+
+rtl::Reference < XMLPropertySetMapper > OXMLHelper::GetRowStylesPropertySetMapper()
+{
+ static const XMLPropertyMapEntry s_aStylesProperties[] =
+ {
+ { PROPERTY_ROW_HEIGHT, XML_NAMESPACE_STYLE, XML_ROW_HEIGHT, XML_TYPE_MEASURE|XML_TYPE_PROP_TABLE_ROW, 0, SvtSaveOptions::ODFSVER_010, false },
+ { nullptr, 0, XML_TOKEN_INVALID, 0 , 0, SvtSaveOptions::ODFSVER_010, false}
+ };
+ rtl::Reference < XMLPropertyHandlerFactory> xFac = new OPropertyHandlerFactory();
+ return new XMLPropertySetMapper(s_aStylesProperties, xFac, true/*bForExport*/);
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/filter/xml/xmlHelper.hxx b/dbaccess/source/filter/xml/xmlHelper.hxx
new file mode 100644
index 000000000..a65cef9b3
--- /dev/null
+++ b/dbaccess/source/filter/xml/xmlHelper.hxx
@@ -0,0 +1,57 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <xmloff/xmlprmap.hxx>
+#include <xmloff/contextid.hxx>
+#include <xmloff/controlpropertyhdl.hxx>
+
+#include <memory>
+
+#define CTF_DB_ROWHEIGHT (XML_DB_CTF_START + 1)
+#define CTF_DB_ISVISIBLE (XML_DB_CTF_START + 2)
+#define CTF_DB_MASTERPAGENAME (XML_DB_CTF_START + 3)
+#define CTF_DB_NUMBERFORMAT (XML_DB_CTF_START + 4)
+#define CTF_DB_COLUMN_TEXT_ALIGN (XML_DB_CTF_START + 5)
+
+#define XML_DB_TYPE_EQUAL (XML_DB_TYPES_START + 1)
+
+namespace dbaxml
+{
+ class OPropertyHandlerFactory final : public ::xmloff::OControlPropertyHandlerFactory
+ {
+ mutable std::unique_ptr<XMLConstantsPropertyHandler> m_pDisplayHandler;
+ public:
+ OPropertyHandlerFactory();
+ virtual ~OPropertyHandlerFactory() override;
+
+ virtual const XMLPropertyHandler* GetPropertyHandler(sal_Int32 _nType) const override;
+ };
+
+ class OXMLHelper
+ {
+ public:
+ static rtl::Reference < XMLPropertySetMapper > GetTableStylesPropertySetMapper( bool bForExport );
+ static rtl::Reference < XMLPropertySetMapper > GetColumnStylesPropertySetMapper( bool bForExport );
+ static rtl::Reference < XMLPropertySetMapper > GetCellStylesPropertySetMapper( bool bForExport );
+ static rtl::Reference < XMLPropertySetMapper > GetRowStylesPropertySetMapper();
+ };
+} // dbaxml
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/filter/xml/xmlHierarchyCollection.cxx b/dbaccess/source/filter/xml/xmlHierarchyCollection.cxx
new file mode 100644
index 000000000..8528f11c8
--- /dev/null
+++ b/dbaccess/source/filter/xml/xmlHierarchyCollection.cxx
@@ -0,0 +1,131 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "xmlHierarchyCollection.hxx"
+#include "xmlComponent.hxx"
+#include "xmlColumn.hxx"
+#include "xmlfilter.hxx"
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/ProgressBarHelper.hxx>
+#include "xmlEnums.hxx"
+#include <com/sun/star/container/XNameContainer.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <comphelper/propertysequence.hxx>
+#include <tools/diagnose_ex.h>
+
+namespace dbaxml
+{
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::beans;
+ using namespace ::com::sun::star::container;
+ using namespace ::com::sun::star::xml::sax;
+
+OXMLHierarchyCollection::OXMLHierarchyCollection( ODBFilter& rImport
+ ,const Reference< XFastAttributeList > & _xAttrList
+ ,const Reference< XNameAccess >& _xParentContainer
+ ,const OUString& _sCollectionServiceName
+ ,const OUString& _sComponentServiceName) :
+ SvXMLImportContext( rImport )
+ ,m_sCollectionServiceName(_sCollectionServiceName)
+ ,m_sComponentServiceName(_sComponentServiceName)
+{
+ OUString sName;
+ for (auto &aIter : sax_fastparser::castToFastAttributeList( _xAttrList ))
+ {
+ switch( aIter.getToken() & TOKEN_MASK )
+ {
+ case XML_NAME:
+ sName = aIter.toString();
+ break;
+ default:
+ XMLOFF_WARN_UNKNOWN("dbaccess", aIter);
+ }
+ }
+ if ( sName.isEmpty() || !_xParentContainer.is() )
+ return;
+
+ try
+ {
+ Reference<XMultiServiceFactory> xORB(_xParentContainer,UNO_QUERY);
+ if ( xORB.is() )
+ {
+ Sequence<Any> aArguments(comphelper::InitAnyPropertySequence(
+ {
+ {"Name", Any(sName)}, // set as folder
+ {"Parent", Any(_xParentContainer)},
+ }));
+ m_xContainer.set(xORB->createInstanceWithArguments(_sCollectionServiceName,aArguments),UNO_QUERY);
+ Reference<XNameContainer> xNameContainer(_xParentContainer,UNO_QUERY);
+ if ( xNameContainer.is() && !xNameContainer->hasByName(sName) )
+ xNameContainer->insertByName(sName,Any(m_xContainer));
+ }
+ }
+ catch(Exception&)
+ {
+ TOOLS_WARN_EXCEPTION( "dbaccess", "OXMLHierarchyCollection::OXMLHierarchyCollection");
+ }
+}
+
+OXMLHierarchyCollection::OXMLHierarchyCollection( ODBFilter& rImport
+ ,const Reference< XNameAccess >& _xContainer
+ ,const Reference< XPropertySet >& _xTable
+ ) :
+ SvXMLImportContext( rImport )
+ ,m_xContainer(_xContainer)
+ ,m_xTable(_xTable)
+{
+}
+
+OXMLHierarchyCollection::~OXMLHierarchyCollection()
+{
+
+}
+
+css::uno::Reference< css::xml::sax::XFastContextHandler > OXMLHierarchyCollection::createFastChildContext(
+ sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
+{
+ SvXMLImportContext *pContext = nullptr;
+
+ switch( nElement & TOKEN_MASK )
+ {
+ case XML_COMPONENT:
+ GetOwnImport().GetProgressBarHelper()->Increment( PROGRESS_BAR_STEP );
+ pContext = new OXMLComponent( GetOwnImport(), xAttrList,m_xContainer,m_sComponentServiceName );
+ break;
+ case XML_COLUMN:
+ GetOwnImport().GetProgressBarHelper()->Increment( PROGRESS_BAR_STEP );
+ pContext = new OXMLColumn( GetOwnImport(), xAttrList,m_xContainer,m_xTable);
+ break;
+ case XML_COMPONENT_COLLECTION:
+ GetOwnImport().GetProgressBarHelper()->Increment( PROGRESS_BAR_STEP );
+ pContext = new OXMLHierarchyCollection( GetOwnImport(), xAttrList,m_xContainer,m_sCollectionServiceName,m_sComponentServiceName);
+ break;
+ }
+
+ return pContext;
+}
+
+ODBFilter& OXMLHierarchyCollection::GetOwnImport()
+{
+ return static_cast<ODBFilter&>(GetImport());
+}
+
+} // namespace dbaxml
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/filter/xml/xmlHierarchyCollection.hxx b/dbaccess/source/filter/xml/xmlHierarchyCollection.hxx
new file mode 100644
index 000000000..689434822
--- /dev/null
+++ b/dbaccess/source/filter/xml/xmlHierarchyCollection.hxx
@@ -0,0 +1,55 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <xmloff/xmlictxt.hxx>
+#include <com/sun/star/container/XNameAccess.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+
+namespace dbaxml
+{
+ class ODBFilter;
+ class OXMLHierarchyCollection : public SvXMLImportContext
+ {
+ css::uno::Reference< css::container::XNameAccess > m_xContainer;
+ css::uno::Reference< css::beans::XPropertySet > m_xTable;
+ OUString m_sCollectionServiceName;
+ OUString m_sComponentServiceName;
+
+ ODBFilter& GetOwnImport();
+ public:
+
+ OXMLHierarchyCollection( ODBFilter& rImport
+ ,const css::uno::Reference< css::xml::sax::XFastAttributeList > & _xAttrList
+ ,const css::uno::Reference< css::container::XNameAccess >& _xParentContainer
+ ,const OUString& _sCollectionServiceName
+ ,const OUString& _sComponentServiceName
+ );
+ OXMLHierarchyCollection( ODBFilter& rImport
+ ,const css::uno::Reference< css::container::XNameAccess >& _xContainer
+ ,const css::uno::Reference< css::beans::XPropertySet >& _xTable
+ );
+ virtual ~OXMLHierarchyCollection() override;
+
+ virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
+ sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList >& AttrList ) override;
+ };
+} // namespace dbaxml
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/filter/xml/xmlLogin.cxx b/dbaccess/source/filter/xml/xmlLogin.cxx
new file mode 100644
index 000000000..fb4bb9eb8
--- /dev/null
+++ b/dbaccess/source/filter/xml/xmlLogin.cxx
@@ -0,0 +1,111 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "xmlLogin.hxx"
+#include "xmlfilter.hxx"
+#include <xmloff/xmltoken.hxx>
+#include <strings.hxx>
+#include <tools/diagnose_ex.h>
+#include <com/sun/star/sdbc/XDataSource.hpp>
+
+namespace dbaxml
+{
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::sdbc;
+ using namespace ::com::sun::star::xml::sax;
+
+OXMLLogin::OXMLLogin( ODBFilter& rImport,
+ const Reference< XFastAttributeList > & _xAttrList ) :
+ SvXMLImportContext( rImport )
+{
+ Reference<XPropertySet> xDataSource(rImport.getDataSource());
+
+ bool bUserFound = false;
+ if (!xDataSource.is())
+ return;
+
+ for (auto &aIter : sax_fastparser::castToFastAttributeList( _xAttrList ))
+ {
+ try
+ {
+ switch( aIter.getToken() & TOKEN_MASK )
+ {
+ case XML_USER_NAME:
+ if ( !bUserFound )
+ {
+ bUserFound = true;
+ try
+ {
+ xDataSource->setPropertyValue(PROPERTY_USER,Any(aIter.toString()));
+ }
+ catch(const Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+ break;
+ case XML_IS_PASSWORD_REQUIRED:
+ try
+ {
+ xDataSource->setPropertyValue(PROPERTY_ISPASSWORDREQUIRED,Any(IsXMLToken(aIter, XML_TRUE)));
+ }
+ catch(const Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ break;
+ case XML_USE_SYSTEM_USER:
+ if ( !bUserFound )
+ {
+ bUserFound = true;
+ PropertyValue aProperty;
+ aProperty.Name = "UseSystemUser";
+ aProperty.Value <<= IsXMLToken(aIter, XML_TRUE);
+ rImport.addInfo(aProperty);
+ }
+ break;
+ case XML_LOGIN_TIMEOUT:
+ try
+ {
+ Reference< XDataSource>(xDataSource,UNO_QUERY_THROW)->setLoginTimeout(aIter.toInt32());
+ }
+ catch(const Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ break;
+ default:
+ XMLOFF_WARN_UNKNOWN("dbaccess", aIter);
+ }
+ }
+ catch(const Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+}
+
+OXMLLogin::~OXMLLogin()
+{
+
+}
+
+} // namespace dbaxml
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/filter/xml/xmlLogin.hxx b/dbaccess/source/filter/xml/xmlLogin.hxx
new file mode 100644
index 000000000..adb25c739
--- /dev/null
+++ b/dbaccess/source/filter/xml/xmlLogin.hxx
@@ -0,0 +1,37 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <xmloff/xmlictxt.hxx>
+
+namespace dbaxml
+{
+ class ODBFilter;
+ class OXMLLogin : public SvXMLImportContext
+ {
+ public:
+
+ OXMLLogin( ODBFilter& rImport,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList > & _xAttrList );
+ virtual ~OXMLLogin() override;
+
+ };
+} // namespace dbaxml
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/filter/xml/xmlQuery.cxx b/dbaccess/source/filter/xml/xmlQuery.cxx
new file mode 100644
index 000000000..18ba034da
--- /dev/null
+++ b/dbaccess/source/filter/xml/xmlQuery.cxx
@@ -0,0 +1,117 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "xmlQuery.hxx"
+#include "xmlfilter.hxx"
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/ProgressBarHelper.hxx>
+#include "xmlEnums.hxx"
+#include <strings.hxx>
+#include <tools/diagnose_ex.h>
+
+namespace dbaxml
+{
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::beans;
+ using namespace ::com::sun::star::container;
+ using namespace ::com::sun::star::xml::sax;
+
+
+OXMLQuery::OXMLQuery( ODBFilter& rImport
+ ,const Reference< XFastAttributeList > & _xAttrList
+ ,const css::uno::Reference< css::container::XNameAccess >& _xParentContainer
+ ) :
+ OXMLTable( rImport, _xAttrList,_xParentContainer, "com.sun.star.sdb.CommandDefinition" )
+ ,m_bEscapeProcessing(true)
+{
+ for (auto &aIter : sax_fastparser::castToFastAttributeList( _xAttrList ))
+ {
+ switch( aIter.getToken() & TOKEN_MASK )
+ {
+ case XML_COMMAND:
+ m_sCommand = aIter.toString();
+ break;
+ case XML_ESCAPE_PROCESSING:
+ m_bEscapeProcessing = aIter.toView() == "true";
+ break;
+ default:
+ XMLOFF_WARN_UNKNOWN("dbaccess", aIter);
+ }
+ }
+}
+
+OXMLQuery::~OXMLQuery()
+{
+
+}
+
+css::uno::Reference< css::xml::sax::XFastContextHandler > OXMLQuery::createFastChildContext(
+ sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
+{
+ css::uno::Reference< css::xml::sax::XFastContextHandler > xContext = OXMLTable::createFastChildContext(nElement,xAttrList );
+ if (!xContext)
+ {
+ switch( nElement & TOKEN_MASK )
+ {
+ case XML_UPDATE_TABLE:
+ {
+ GetOwnImport().GetProgressBarHelper()->Increment( PROGRESS_BAR_STEP );
+ OUString s1;
+ fillAttributes(xAttrList,s1,m_sTable,m_sSchema,m_sCatalog);
+ break;
+ }
+ }
+ }
+
+ return xContext;
+}
+
+void OXMLQuery::setProperties(Reference< XPropertySet > & _xProp )
+{
+ try
+ {
+ if ( _xProp.is() )
+ {
+ OXMLTable::setProperties(_xProp);
+
+ _xProp->setPropertyValue(PROPERTY_COMMAND,Any(m_sCommand));
+ _xProp->setPropertyValue(PROPERTY_ESCAPE_PROCESSING,Any(m_bEscapeProcessing));
+
+ if ( !m_sTable.isEmpty() )
+ _xProp->setPropertyValue(PROPERTY_UPDATE_TABLENAME,Any(m_sTable));
+ if ( !m_sCatalog.isEmpty() )
+ _xProp->setPropertyValue(PROPERTY_UPDATE_CATALOGNAME,Any(m_sCatalog));
+ if ( !m_sSchema.isEmpty() )
+ _xProp->setPropertyValue(PROPERTY_UPDATE_SCHEMANAME,Any(m_sSchema));
+
+ const ODBFilter::TPropertyNameMap& rSettings = GetOwnImport().getQuerySettings();
+ ODBFilter::TPropertyNameMap::const_iterator aFind = rSettings.find(m_sName);
+ if ( aFind != rSettings.end() )
+ _xProp->setPropertyValue(PROPERTY_LAYOUTINFORMATION,Any(aFind->second));
+ }
+ }
+ catch(Exception&)
+ {
+ TOOLS_WARN_EXCEPTION( "dbaccess", "OXMLTable::EndElement");
+ }
+}
+
+} // namespace dbaxml
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/filter/xml/xmlQuery.hxx b/dbaccess/source/filter/xml/xmlQuery.hxx
new file mode 100644
index 000000000..d3e01193c
--- /dev/null
+++ b/dbaccess/source/filter/xml/xmlQuery.hxx
@@ -0,0 +1,46 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "xmlTable.hxx"
+
+namespace dbaxml
+{
+ class ODBFilter;
+ class OXMLQuery : public OXMLTable
+ {
+ OUString m_sCommand;
+ OUString m_sTable;
+ bool m_bEscapeProcessing;
+ protected:
+ virtual void setProperties(css::uno::Reference< css::beans::XPropertySet > & _xProp) override;
+ public:
+
+ OXMLQuery( ODBFilter& rImport
+ ,const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList
+ ,const css::uno::Reference< css::container::XNameAccess >& _xParentContainer
+ );
+ virtual ~OXMLQuery() override;
+
+ virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
+ sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList >& AttrList ) override;
+ };
+} // namespace dbaxml
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/filter/xml/xmlServerDatabase.cxx b/dbaccess/source/filter/xml/xmlServerDatabase.cxx
new file mode 100644
index 000000000..ff41590f0
--- /dev/null
+++ b/dbaccess/source/filter/xml/xmlServerDatabase.cxx
@@ -0,0 +1,136 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "xmlServerDatabase.hxx"
+#include "xmlfilter.hxx"
+#include <xmloff/xmltoken.hxx>
+#include <strings.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <tools/diagnose_ex.h>
+
+namespace dbaxml
+{
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::xml::sax;
+
+OXMLServerDatabase::OXMLServerDatabase( ODBFilter& rImport,
+ const Reference< XFastAttributeList > & _xAttrList) :
+ SvXMLImportContext( rImport )
+{
+ Reference<XPropertySet> xDataSource = rImport.getDataSource();
+
+ PropertyValue aProperty;
+
+ OUString sType,sHostName,sPortNumber,sDatabaseName;
+ if (xDataSource.is())
+ {
+ for (auto &aIter : sax_fastparser::castToFastAttributeList( _xAttrList ))
+ {
+ OUString sValue = aIter.toString();
+
+ switch( aIter.getToken() & TOKEN_MASK )
+ {
+ case XML_TYPE:
+ sType = sValue;
+ break;
+ case XML_HOSTNAME:
+ sHostName = sValue;
+ break;
+ case XML_PORT:
+ sPortNumber = sValue;
+ break;
+ case XML_LOCAL_SOCKET:
+ aProperty.Name = "LocalSocket";
+ aProperty.Value <<= sValue;
+ rImport.addInfo(aProperty);
+ break;
+ case XML_DATABASE_NAME:
+ sDatabaseName = sValue;
+ break;
+ default:
+ XMLOFF_WARN_UNKNOWN("dbaccess", aIter);
+ }
+ }
+ }
+ if ( sType.isEmpty() )
+ return;
+
+ OUStringBuffer sURL;
+ if ( sType == "sdbc:mysql:jdbc" || sType == "sdbc:mysqlc" || sType == "sdbc:mysql:mysqlc" )
+ {
+ sURL.append( sType + ":" + sHostName);
+ if ( !sPortNumber.isEmpty() )
+ {
+ sURL.append(":" + sPortNumber);
+ }
+ if ( !sDatabaseName.isEmpty() )
+ {
+ sURL.append("/" + sDatabaseName);
+ }
+ }
+ else if ( sType == "jdbc:oracle:thin" )
+ {
+ sURL.append("jdbc:oracle:thin:@" + sHostName);
+ if ( !sPortNumber.isEmpty() )
+ {
+ sURL.append(":" + sPortNumber);
+ }
+ if ( !sDatabaseName.isEmpty() )
+ {
+ sURL.append(":" + sDatabaseName);
+ }
+ }
+ else if ( sType == "sdbc:address:ldap" )
+ {
+ sURL.append("sdbc:address:ldap:" + sHostName);
+ if ( !sPortNumber.isEmpty() )
+ {
+ sURL.append(":" + sPortNumber);
+ }
+ }
+ else
+ {
+ sURL.append(sType + ":" + sHostName);
+ if ( !sPortNumber.isEmpty() )
+ {
+ sURL.append(":" + sPortNumber);
+ }
+ if ( !sDatabaseName.isEmpty() )
+ {
+ sURL.append(":" + sDatabaseName);
+ }
+ }
+ try
+ {
+ xDataSource->setPropertyValue(PROPERTY_URL,Any(sURL.makeStringAndClear()));
+ }
+ catch(const Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+}
+
+OXMLServerDatabase::~OXMLServerDatabase()
+{
+
+}
+
+} // namespace dbaxml
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/filter/xml/xmlServerDatabase.hxx b/dbaccess/source/filter/xml/xmlServerDatabase.hxx
new file mode 100644
index 000000000..ec3401fff
--- /dev/null
+++ b/dbaccess/source/filter/xml/xmlServerDatabase.hxx
@@ -0,0 +1,36 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <xmloff/xmlictxt.hxx>
+
+namespace dbaxml
+{
+ class ODBFilter;
+ class OXMLServerDatabase : public SvXMLImportContext
+ {
+ public:
+
+ OXMLServerDatabase( ODBFilter& rImport,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList > & _xAttrList );
+ virtual ~OXMLServerDatabase() override;
+ };
+} // namespace dbaxml
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/filter/xml/xmlStyleImport.cxx b/dbaccess/source/filter/xml/xmlStyleImport.cxx
new file mode 100644
index 000000000..ddadc5e3b
--- /dev/null
+++ b/dbaccess/source/filter/xml/xmlStyleImport.cxx
@@ -0,0 +1,263 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "xmlStyleImport.hxx"
+
+#include <xmloff/maptype.hxx>
+#include <xmloff/xmlimppr.hxx>
+#include <xmloff/families.hxx>
+#include <xmloff/xmlnumfi.hxx>
+#include <xmloff/xmltoken.hxx>
+#include <osl/diagnose.h>
+#include "xmlfilter.hxx"
+#include "xmlHelper.hxx"
+
+namespace dbaxml
+{
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::xml::sax;
+using namespace ::com::sun::star::style;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::container;
+using namespace xmloff::token;
+
+
+OTableStyleContext::OTableStyleContext( ODBFilter& rImport,
+ SvXMLStylesContext& rStyles, XmlStyleFamily nFamily )
+ :XMLPropStyleContext( rImport, rStyles, nFamily, false )
+ ,pStyles(&rStyles)
+ ,m_nNumberFormat(-1)
+{
+
+}
+
+OTableStyleContext::~OTableStyleContext()
+{
+
+}
+
+void OTableStyleContext::FillPropertySet(
+ const Reference< XPropertySet > & rPropSet )
+{
+ if ( !IsDefaultStyle() )
+ {
+ if ( GetFamily() == XmlStyleFamily::TABLE_TABLE )
+ {
+ if ( !sPageStyle.isEmpty() )
+ {
+ AddProperty(CTF_DB_MASTERPAGENAME, Any(sPageStyle));
+ }
+ }
+ else if ( GetFamily() == XmlStyleFamily::TABLE_COLUMN )
+ {
+ if ((m_nNumberFormat == -1) && !m_sDataStyleName.isEmpty())
+ {
+ SvXMLNumFormatContext* pStyle = const_cast<SvXMLNumFormatContext*>(dynamic_cast< const SvXMLNumFormatContext* >(pStyles->FindStyleChildContext(
+ XmlStyleFamily::DATA_STYLE, m_sDataStyleName, true)));
+ if ( !pStyle )
+ {
+ OTableStylesContext* pMyStyles = dynamic_cast<OTableStylesContext* >(GetOwnImport().GetAutoStyles());
+ if ( pMyStyles )
+ pStyle = const_cast<SvXMLNumFormatContext*>(dynamic_cast< const SvXMLNumFormatContext* >(pMyStyles->
+ FindStyleChildContext(XmlStyleFamily::DATA_STYLE, m_sDataStyleName, true)));
+ else {
+ OSL_FAIL("not possible to get style");
+ }
+ }
+ if ( pStyle )
+ {
+ uno::Any aNumberFormat;
+ m_nNumberFormat = pStyle->GetKey();
+ aNumberFormat <<= m_nNumberFormat;
+ AddProperty(CTF_DB_NUMBERFORMAT, aNumberFormat);
+ }
+ }
+ }
+ }
+ XMLPropStyleContext::FillPropertySet(rPropSet);
+}
+
+void OTableStyleContext::SetDefaults()
+{
+}
+
+void OTableStyleContext::AddProperty(const sal_Int16 nContextID, const uno::Any& rValue)
+{
+ sal_Int32 nIndex(static_cast<OTableStylesContext *>(pStyles)->GetIndex(nContextID));
+ OSL_ENSURE(nIndex != -1, "Property not found in Map");
+ XMLPropertyState aPropState(nIndex, rValue);
+ GetProperties().push_back(aPropState); // has to be inserted in a sort order later
+}
+
+void OTableStyleContext::SetAttribute( sal_Int32 nElement,
+ const OUString& rValue )
+{
+ switch(nElement & TOKEN_MASK)
+ {
+ case XML_DATA_STYLE_NAME:
+ m_sDataStyleName = rValue;
+ break;
+ case XML_MASTER_PAGE_NAME:
+ sPageStyle = rValue;
+ break;
+ default:
+ XMLPropStyleContext::SetAttribute( nElement, rValue );
+ }
+}
+
+ODBFilter& OTableStyleContext::GetOwnImport()
+{
+ return static_cast<ODBFilter&>(GetImport());
+}
+
+
+OTableStylesContext::OTableStylesContext( SvXMLImport& rImport,
+ bool bTempAutoStyles )
+ : SvXMLStylesContext( rImport )
+ , m_nNumberFormatIndex(-1)
+ , m_nMasterPageNameIndex(-1)
+ , bAutoStyles(bTempAutoStyles)
+{
+
+}
+
+OTableStylesContext::~OTableStylesContext()
+{
+
+}
+
+void OTableStylesContext::endFastElement(sal_Int32 )
+{
+ if (bAutoStyles)
+ GetImport().GetTextImport()->SetAutoStyles( this );
+ else
+ GetImport().GetStyles()->CopyStylesToDoc(true);
+}
+
+rtl::Reference < SvXMLImportPropertyMapper >
+ OTableStylesContext::GetImportPropertyMapper(
+ XmlStyleFamily nFamily ) const
+{
+ rtl::Reference < SvXMLImportPropertyMapper > xMapper = SvXMLStylesContext::GetImportPropertyMapper(nFamily);
+
+ if (!xMapper.is())
+ {
+ switch( nFamily )
+ {
+ case XmlStyleFamily::TABLE_TABLE:
+ {
+ if ( !m_xTableImpPropMapper.is() )
+ m_xTableImpPropMapper = new SvXMLImportPropertyMapper( const_cast<OTableStylesContext*>(this)->GetOwnImport().GetTableStylesPropertySetMapper(), const_cast<SvXMLImport&>(GetImport()) );
+ xMapper = m_xTableImpPropMapper;
+ }
+ break;
+ case XmlStyleFamily::TABLE_COLUMN:
+ {
+ if ( !m_xColumnImpPropMapper.is() )
+ m_xColumnImpPropMapper = new SvXMLImportPropertyMapper( const_cast<OTableStylesContext*>(this)->GetOwnImport().GetColumnStylesPropertySetMapper(), const_cast<SvXMLImport&>(GetImport()) );
+ xMapper = m_xColumnImpPropMapper;
+ }
+ break;
+ case XmlStyleFamily::TABLE_CELL:
+ {
+ if ( !m_xCellImpPropMapper.is() )
+ m_xCellImpPropMapper = new SvXMLImportPropertyMapper( const_cast<OTableStylesContext*>(this)->GetOwnImport().GetCellStylesPropertySetMapper(), const_cast<SvXMLImport&>(GetImport()) );
+ xMapper = m_xCellImpPropMapper;
+ }
+ break;
+ default: break;
+ }
+ }
+
+ return xMapper;
+}
+
+SvXMLStyleContext *OTableStylesContext::CreateStyleStyleChildContext(
+ XmlStyleFamily nFamily, sal_Int32 nElement,
+ const Reference< xml::sax::XFastAttributeList > & xAttrList )
+{
+ SvXMLStyleContext *pStyle = SvXMLStylesContext::CreateStyleStyleChildContext( nFamily, nElement,
+ xAttrList );
+ if (pStyle)
+ return pStyle;
+
+ switch( nFamily )
+ {
+ case XmlStyleFamily::TABLE_TABLE:
+ case XmlStyleFamily::TABLE_COLUMN:
+ case XmlStyleFamily::TABLE_CELL:
+ return new OTableStyleContext( GetOwnImport(), *this, nFamily );
+ default: break;
+ }
+
+ return nullptr;
+}
+
+OUString OTableStylesContext::GetServiceName( XmlStyleFamily nFamily ) const
+{
+ OUString sServiceName = SvXMLStylesContext::GetServiceName(nFamily);
+ if (sServiceName.isEmpty())
+ {
+ switch( nFamily )
+ {
+ case XmlStyleFamily::TABLE_TABLE:
+ sServiceName = XML_STYLE_FAMILY_TABLE_TABLE_STYLES_NAME;
+ break;
+ case XmlStyleFamily::TABLE_COLUMN:
+ sServiceName = XML_STYLE_FAMILY_TABLE_COLUMN_STYLES_NAME;
+ break;
+ case XmlStyleFamily::TABLE_CELL:
+ sServiceName = XML_STYLE_FAMILY_TABLE_CELL_STYLES_NAME;
+ break;
+ default: break;
+ }
+ }
+ return sServiceName;
+}
+
+sal_Int32 OTableStylesContext::GetIndex(const sal_Int16 nContextID)
+{
+ if ( nContextID == CTF_DB_NUMBERFORMAT )
+ {
+ if (m_nNumberFormatIndex == -1)
+ m_nNumberFormatIndex =
+ GetImportPropertyMapper(XmlStyleFamily::TABLE_COLUMN)->getPropertySetMapper()->FindEntryIndex(nContextID);
+ return m_nNumberFormatIndex;
+ }
+ else if ( nContextID == CTF_DB_MASTERPAGENAME )
+ {
+ if (m_nMasterPageNameIndex == -1)
+ m_nMasterPageNameIndex =
+ GetImportPropertyMapper(XmlStyleFamily::TABLE_TABLE)->getPropertySetMapper()->FindEntryIndex(nContextID);
+ return m_nMasterPageNameIndex;
+ }
+ else
+ return -1;
+}
+
+ODBFilter& OTableStylesContext::GetOwnImport()
+{
+ return static_cast<ODBFilter&>(GetImport());
+}
+
+} // dbaxml
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/filter/xml/xmlStyleImport.hxx b/dbaccess/source/filter/xml/xmlStyleImport.hxx
new file mode 100644
index 000000000..d3fc001b0
--- /dev/null
+++ b/dbaccess/source/filter/xml/xmlStyleImport.hxx
@@ -0,0 +1,98 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <rtl/ustring.hxx>
+#include <xmloff/xmlimp.hxx>
+#include <xmloff/prstylei.hxx>
+#include <xmloff/xmlimppr.hxx>
+
+namespace dbaxml
+{
+ class ODBFilter;
+
+ class OTableStyleContext : public XMLPropStyleContext
+ {
+ OUString m_sDataStyleName;
+ OUString sPageStyle;
+ SvXMLStylesContext* pStyles;
+ sal_Int32 m_nNumberFormat;
+
+ ODBFilter& GetOwnImport();
+
+ protected:
+
+ virtual void SetAttribute( sal_Int32 nElement,
+ const OUString& rValue ) override;
+
+ public:
+
+
+ OTableStyleContext( ODBFilter& rImport,
+ SvXMLStylesContext& rStyles, XmlStyleFamily nFamily );
+
+ virtual ~OTableStyleContext() override;
+
+ virtual void FillPropertySet(const css::uno::Reference<
+ css::beans::XPropertySet > & rPropSet ) override;
+
+ virtual void SetDefaults() override;
+
+ void AddProperty(sal_Int16 nContextID, const css::uno::Any& aValue);
+ };
+
+ class OTableStylesContext : public SvXMLStylesContext
+ {
+ sal_Int32 m_nNumberFormatIndex;
+ sal_Int32 m_nMasterPageNameIndex;
+ bool bAutoStyles : 1;
+
+ mutable rtl::Reference < SvXMLImportPropertyMapper > m_xTableImpPropMapper;
+ mutable rtl::Reference < SvXMLImportPropertyMapper > m_xColumnImpPropMapper;
+ mutable rtl::Reference < SvXMLImportPropertyMapper > m_xCellImpPropMapper;
+
+ ODBFilter& GetOwnImport();
+
+ protected:
+
+ // Create a style context.
+ using SvXMLStylesContext::CreateStyleStyleChildContext;
+ virtual SvXMLStyleContext *CreateStyleStyleChildContext(
+ XmlStyleFamily nFamily,
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList > & xAttrList ) override;
+
+ public:
+
+
+ OTableStylesContext( SvXMLImport& rImport, bool bAutoStyles );
+ virtual ~OTableStylesContext() override;
+
+ virtual void SAL_CALL endFastElement(sal_Int32 nElement) override;
+
+ virtual rtl::Reference < SvXMLImportPropertyMapper > GetImportPropertyMapper(
+ XmlStyleFamily nFamily ) const override;
+ virtual OUString GetServiceName( XmlStyleFamily nFamily ) const override;
+
+ sal_Int32 GetIndex(const sal_Int16 nContextID);
+ };
+} // dbaxml
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/filter/xml/xmlTable.cxx b/dbaccess/source/filter/xml/xmlTable.cxx
new file mode 100644
index 000000000..403486ee5
--- /dev/null
+++ b/dbaccess/source/filter/xml/xmlTable.cxx
@@ -0,0 +1,226 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "xmlTable.hxx"
+#include "xmlfilter.hxx"
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/ProgressBarHelper.hxx>
+#include "xmlEnums.hxx"
+#include "xmlStyleImport.hxx"
+#include "xmlHierarchyCollection.hxx"
+#include <strings.hxx>
+#include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
+#include <com/sun/star/container/XNameContainer.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <comphelper/propertysequence.hxx>
+#include <tools/diagnose_ex.h>
+
+namespace dbaxml
+{
+ using namespace ::com::sun::star;
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::sdbcx;
+ using namespace ::com::sun::star::xml::sax;
+
+OXMLTable::OXMLTable( ODBFilter& _rImport
+ ,const uno::Reference< XFastAttributeList > & _xAttrList
+ ,const uno::Reference< css::container::XNameAccess >& _xParentContainer
+ ,const OUString& _sServiceName
+ )
+ :SvXMLImportContext( _rImport )
+ ,m_xParentContainer(_xParentContainer)
+ ,m_bApplyFilter(false)
+ ,m_bApplyOrder(false)
+{
+ for (auto &aIter : sax_fastparser::castToFastAttributeList( _xAttrList ))
+ {
+ OUString sValue = aIter.toString();
+
+ switch( aIter.getToken() & TOKEN_MASK )
+ {
+ case XML_NAME:
+ m_sName = sValue;
+ break;
+ case XML_CATALOG_NAME:
+ m_sCatalog = sValue;
+ break;
+ case XML_SCHEMA_NAME:
+ m_sSchema = sValue;
+ break;
+ case XML_STYLE_NAME:
+ m_sStyleName = sValue;
+ break;
+ case XML_APPLY_FILTER:
+ m_bApplyFilter = sValue == "true";
+ break;
+ case XML_APPLY_ORDER:
+ m_bApplyOrder = sValue == "true";
+ break;
+ default:
+ XMLOFF_WARN_UNKNOWN("dbaccess", aIter);
+ }
+ }
+ uno::Sequence<uno::Any> aArguments(comphelper::InitAnyPropertySequence(
+ {
+ {"Name", uno::Any(m_sName)}, // set as folder
+ {"Parent", uno::Any(m_xParentContainer)}
+ }));
+ m_xTable.set(
+ GetOwnImport().GetComponentContext()->getServiceManager()->createInstanceWithArgumentsAndContext(_sServiceName,aArguments, GetOwnImport().GetComponentContext()),
+ UNO_QUERY);
+}
+
+OXMLTable::~OXMLTable()
+{
+
+}
+
+css::uno::Reference< css::xml::sax::XFastContextHandler > OXMLTable::createFastChildContext(
+ sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
+{
+ SvXMLImportContext *pContext = nullptr;
+
+ switch( nElement & TOKEN_MASK )
+ {
+ case XML_FILTER_STATEMENT:
+ {
+ GetOwnImport().GetProgressBarHelper()->Increment( PROGRESS_BAR_STEP );
+ OUString s1,s2,s3;
+ fillAttributes(xAttrList,m_sFilterStatement,s1,s2,s3);
+ }
+ break;
+ case XML_ORDER_STATEMENT:
+ {
+ GetOwnImport().GetProgressBarHelper()->Increment( PROGRESS_BAR_STEP );
+ OUString s1,s2,s3;
+ fillAttributes(xAttrList,m_sOrderStatement,s1,s2,s3);
+ }
+ break;
+
+ case XML_COLUMNS:
+ {
+ GetOwnImport().GetProgressBarHelper()->Increment( PROGRESS_BAR_STEP );
+ uno::Reference< XColumnsSupplier > xColumnsSup(m_xTable,UNO_QUERY);
+ uno::Reference< XNameAccess > xColumns;
+ if ( xColumnsSup.is() )
+ {
+ xColumns = xColumnsSup->getColumns();
+ }
+ pContext = new OXMLHierarchyCollection( GetOwnImport(), xColumns,m_xTable);
+ }
+ break;
+ }
+
+ return pContext;
+}
+
+ODBFilter& OXMLTable::GetOwnImport()
+{
+ return static_cast<ODBFilter&>(GetImport());
+}
+
+void OXMLTable::setProperties(uno::Reference< XPropertySet > & _xProp )
+{
+ try
+ {
+ if ( _xProp.is() )
+ {
+ _xProp->setPropertyValue(PROPERTY_APPLYFILTER,Any(m_bApplyFilter));
+ _xProp->setPropertyValue(PROPERTY_FILTER,Any(m_sFilterStatement));
+
+ if ( _xProp->getPropertySetInfo()->hasPropertyByName(PROPERTY_APPLYORDER) )
+ _xProp->setPropertyValue(PROPERTY_APPLYORDER,Any(m_bApplyOrder));
+ _xProp->setPropertyValue(PROPERTY_ORDER,Any(m_sOrderStatement));
+ }
+ }
+ catch(Exception&)
+ {
+ TOOLS_WARN_EXCEPTION( "dbaccess", "OXMLTable::EndElement -> exception caught");
+ }
+}
+
+void OXMLTable::endFastElement(sal_Int32 )
+{
+ uno::Reference<XNameContainer> xNameContainer(m_xParentContainer,UNO_QUERY);
+ if ( !xNameContainer.is() )
+ return;
+
+ try
+ {
+ if ( m_xTable.is() )
+ {
+ setProperties(m_xTable);
+
+ if ( !m_sStyleName.isEmpty() )
+ {
+ const SvXMLStylesContext* pAutoStyles = GetOwnImport().GetAutoStyles();
+ if ( pAutoStyles )
+ {
+ OTableStyleContext* pAutoStyle = const_cast<OTableStyleContext*>(dynamic_cast< const OTableStyleContext* >(pAutoStyles->FindStyleChildContext(XmlStyleFamily::TABLE_TABLE,m_sStyleName)));
+ if ( pAutoStyle )
+ {
+ pAutoStyle->FillPropertySet(m_xTable);
+ }
+ }
+ }
+
+ xNameContainer->insertByName(m_sName,Any(m_xTable));
+ }
+ }
+ catch(Exception&)
+ {
+ TOOLS_WARN_EXCEPTION( "dbaccess", "OXMLQuery::EndElement");
+ }
+
+}
+
+void OXMLTable::fillAttributes(const uno::Reference< XFastAttributeList > & _xAttrList
+ ,OUString& _rsCommand
+ ,OUString& _rsTableName
+ ,OUString& _rsTableSchema
+ ,OUString& _rsTableCatalog
+ )
+{
+ for (auto &aIter : sax_fastparser::castToFastAttributeList( _xAttrList ))
+ {
+ OUString sValue = aIter.toString();
+
+ switch( aIter.getToken() & TOKEN_MASK )
+ {
+ case XML_COMMAND:
+ _rsCommand = sValue;
+ break;
+ case XML_CATALOG_NAME:
+ _rsTableCatalog = sValue;
+ break;
+ case XML_SCHEMA_NAME:
+ _rsTableSchema = sValue;
+ break;
+ case XML_QUERY_NAME:
+ _rsTableName = sValue;
+ break;
+ default:
+ XMLOFF_WARN_UNKNOWN("dbaccess", aIter);
+ }
+ }
+}
+
+} // namespace dbaxml
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/filter/xml/xmlTable.hxx b/dbaccess/source/filter/xml/xmlTable.hxx
new file mode 100644
index 000000000..cee19ef19
--- /dev/null
+++ b/dbaccess/source/filter/xml/xmlTable.hxx
@@ -0,0 +1,67 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <xmloff/xmlictxt.hxx>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/container/XNameAccess.hpp>
+
+namespace dbaxml
+{
+ class ODBFilter;
+ class OXMLTable : public SvXMLImportContext
+ {
+ protected:
+ css::uno::Reference< css::container::XNameAccess > m_xParentContainer;
+ css::uno::Reference< css::beans::XPropertySet > m_xTable;
+ OUString m_sFilterStatement;
+ OUString m_sOrderStatement;
+ OUString m_sName;
+ OUString m_sSchema;
+ OUString m_sCatalog;
+ OUString m_sStyleName;
+ bool m_bApplyFilter;
+ bool m_bApplyOrder;
+
+ ODBFilter& GetOwnImport();
+
+ static void fillAttributes( const css::uno::Reference< css::xml::sax::XFastAttributeList > & xAttrList
+ ,OUString& _rsCommand
+ ,OUString& _rsTableName
+ ,OUString& _rsTableSchema
+ ,OUString& _rsTableCatalog
+ );
+
+ virtual void setProperties(css::uno::Reference< css::beans::XPropertySet > & _xProp);
+ public:
+
+ OXMLTable( ODBFilter& rImport
+ ,const css::uno::Reference< css::xml::sax::XFastAttributeList > & _xAttrList
+ ,const css::uno::Reference< css::container::XNameAccess >& _xParentContainer
+ ,const OUString& _sServiceName
+ );
+ virtual ~OXMLTable() override;
+
+ virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
+ sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList >& AttrList ) override;
+ virtual void SAL_CALL endFastElement(sal_Int32 nElement) override;
+ };
+} // namespace dbaxml
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/filter/xml/xmlTableFilterList.cxx b/dbaccess/source/filter/xml/xmlTableFilterList.cxx
new file mode 100644
index 000000000..a6541684a
--- /dev/null
+++ b/dbaccess/source/filter/xml/xmlTableFilterList.cxx
@@ -0,0 +1,95 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "xmlTableFilterList.hxx"
+#include "xmlTableFilterPattern.hxx"
+#include "xmlEnums.hxx"
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/ProgressBarHelper.hxx>
+#include <strings.hxx>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <comphelper/sequence.hxx>
+#include <xmloff/xmlimp.hxx>
+#include "xmlfilter.hxx"
+
+namespace dbaxml
+{
+ using namespace ::xmloff::token;
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::beans;
+ using namespace ::com::sun::star::xml::sax;
+
+OXMLTableFilterList::OXMLTableFilterList( SvXMLImport& rImport)
+ :SvXMLImportContext( rImport )
+{
+
+}
+
+OXMLTableFilterList::~OXMLTableFilterList()
+{
+}
+
+css::uno::Reference< css::xml::sax::XFastContextHandler > OXMLTableFilterList::createFastChildContext(
+ sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList >& /*xAttrList*/ )
+{
+ SvXMLImportContext *pContext = nullptr;
+
+ if ( IsTokenInNamespace(nElement, XML_NAMESPACE_DB) ||
+ IsTokenInNamespace(nElement, XML_NAMESPACE_DB_OASIS) )
+ {
+ GetImport().GetProgressBarHelper()->Increment( PROGRESS_BAR_STEP );
+ switch (nElement & TOKEN_MASK)
+ {
+ case XML_TABLE_FILTER_PATTERN:
+ pContext = new OXMLTableFilterPattern( GetImport(), true,*this);
+ break;
+ case XML_TABLE_TYPE:
+ pContext = new OXMLTableFilterPattern( GetImport(), false,*this);
+ break;
+ case XML_TABLE_INCLUDE_FILTER:
+ pContext = new OXMLTableFilterList( GetImport() );
+ break;
+ default: break;
+ }
+ }
+
+ return pContext;
+}
+
+ODBFilter& OXMLTableFilterList::GetOwnImport()
+{
+ return static_cast<ODBFilter&>(GetImport());
+}
+
+void OXMLTableFilterList::endFastElement(sal_Int32 )
+{
+ Reference<XPropertySet> xDataSource(GetOwnImport().getDataSource());
+ if ( xDataSource.is() )
+ {
+ if ( !m_aPatterns.empty() )
+ xDataSource->setPropertyValue(PROPERTY_TABLEFILTER,Any(comphelper::containerToSequence(m_aPatterns)));
+ if ( !m_aTypes.empty() )
+ xDataSource->setPropertyValue(PROPERTY_TABLETYPEFILTER,Any(comphelper::containerToSequence(m_aTypes)));
+ }
+}
+
+} // namespace dbaxml
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/filter/xml/xmlTableFilterList.hxx b/dbaccess/source/filter/xml/xmlTableFilterList.hxx
new file mode 100644
index 000000000..1988bdd29
--- /dev/null
+++ b/dbaccess/source/filter/xml/xmlTableFilterList.hxx
@@ -0,0 +1,64 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <xmloff/xmlictxt.hxx>
+#include <vector>
+
+namespace dbaxml
+{
+ class ODBFilter;
+ class OXMLTableFilterList : public SvXMLImportContext
+ {
+ std::vector< OUString> m_aPatterns;
+ std::vector< OUString> m_aTypes;
+
+ ODBFilter& GetOwnImport();
+ public:
+
+ OXMLTableFilterList( SvXMLImport& rImport );
+
+ virtual ~OXMLTableFilterList() override;
+
+ virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
+ sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList >& AttrList ) override;
+
+ virtual void SAL_CALL endFastElement(sal_Int32 nElement) override;
+
+ /** pushes a new TableFilterPattern to the list of patterns
+ @param _sTableFilterPattern
+ The new filter pattern.
+ */
+ void pushTableFilterPattern(const OUString& _sTableFilterPattern)
+ {
+ m_aPatterns.push_back(_sTableFilterPattern);
+ }
+
+ /** pushes a new TableTypeFilter to the list of patterns
+ @param _sTypeFilter
+ The new type filter.
+ */
+ void pushTableTypeFilter(const OUString& _sTypeFilter)
+ {
+ m_aTypes.push_back(_sTypeFilter);
+ }
+ };
+} // namespace dbaxml
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/filter/xml/xmlTableFilterPattern.cxx b/dbaccess/source/filter/xml/xmlTableFilterPattern.cxx
new file mode 100644
index 000000000..0c4b2892d
--- /dev/null
+++ b/dbaccess/source/filter/xml/xmlTableFilterPattern.cxx
@@ -0,0 +1,59 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "xmlTableFilterPattern.hxx"
+#include "xmlTableFilterList.hxx"
+
+namespace dbaxml
+{
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::xml::sax;
+
+OXMLTableFilterPattern::OXMLTableFilterPattern( SvXMLImport& rImport
+ ,bool _bNameFilter
+ ,OXMLTableFilterList& _rParent)
+ :SvXMLImportContext( rImport )
+ ,m_rParent(_rParent)
+ ,m_bNameFilter(_bNameFilter)
+{
+
+}
+
+OXMLTableFilterPattern::~OXMLTableFilterPattern()
+{
+
+}
+
+void OXMLTableFilterPattern::characters( const OUString& rChars )
+{
+ maBuffer.append(rChars);
+}
+
+void OXMLTableFilterPattern::endFastElement( sal_Int32 )
+{
+ OUString sChars = maBuffer.makeStringAndClear();
+ if ( m_bNameFilter )
+ m_rParent.pushTableFilterPattern(sChars);
+ else
+ m_rParent.pushTableTypeFilter(sChars);
+}
+
+} // namespace dbaxml
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/filter/xml/xmlTableFilterPattern.hxx b/dbaccess/source/filter/xml/xmlTableFilterPattern.hxx
new file mode 100644
index 000000000..8f0b64f37
--- /dev/null
+++ b/dbaccess/source/filter/xml/xmlTableFilterPattern.hxx
@@ -0,0 +1,44 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <rtl/ustrbuf.hxx>
+#include <xmloff/xmlictxt.hxx>
+
+namespace dbaxml
+{
+ class OXMLTableFilterList;
+ class OXMLTableFilterPattern : public SvXMLImportContext
+ {
+ OXMLTableFilterList& m_rParent;
+ bool m_bNameFilter;
+ OUStringBuffer maBuffer;
+ public:
+ OXMLTableFilterPattern( SvXMLImport& rImport
+ ,bool _bNameFilter
+ ,OXMLTableFilterList& _rParent);
+
+ virtual ~OXMLTableFilterPattern() override;
+
+ virtual void SAL_CALL endFastElement( sal_Int32 nElement ) override;
+ virtual void SAL_CALL characters( const OUString& rChars ) override;
+ };
+} // namespace dbaxml
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/filter/xml/xmlfilter.cxx b/dbaccess/source/filter/xml/xmlfilter.cxx
new file mode 100644
index 000000000..d089359c8
--- /dev/null
+++ b/dbaccess/source/filter/xml/xmlfilter.cxx
@@ -0,0 +1,617 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+#include <sal/log.hxx>
+
+#include <vcl/errinf.hxx>
+#include <com/sun/star/frame/XModel.hpp>
+#include <com/sun/star/uri/UriReferenceFactory.hpp>
+#include <com/sun/star/util/MeasureUnit.hpp>
+#include <com/sun/star/util/XNumberFormatsSupplier.hpp>
+#include <com/sun/star/packages/WrongPasswordException.hpp>
+#include <com/sun/star/packages/zip/ZipIOException.hpp>
+#include <com/sun/star/embed/ElementModes.hpp>
+#include <com/sun/star/sdb/XOfficeDatabaseDocument.hpp>
+#include "xmlfilter.hxx"
+#include <vcl/svapp.hxx>
+#include <vcl/window.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/xmlscripti.hxx>
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/namespacemap.hxx>
+#include <com/sun/star/xml/sax/InputSource.hpp>
+#include <com/sun/star/xml/sax/SAXParseException.hpp>
+#include <xmloff/ProgressBarHelper.hxx>
+#include <sfx2/docfile.hxx>
+#include <com/sun/star/io/XInputStream.hpp>
+#include "xmlDatabase.hxx"
+#include "xmlEnums.hxx"
+#include <strings.hxx>
+#include <xmloff/DocumentSettingsContext.hxx>
+#include "xmlStyleImport.hxx"
+#include <xmloff/xmluconv.hxx>
+#include "xmlHelper.hxx"
+#include <com/sun/star/util/XModifiable.hpp>
+#include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
+#include <svtools/sfxecode.hxx>
+#include <tools/diagnose_ex.h>
+#include <osl/diagnose.h>
+#include <comphelper/sequence.hxx>
+#include <comphelper/types.hxx>
+#include <comphelper/namedvaluecollection.hxx>
+#include <cppuhelper/exc_hlp.hxx>
+#include <connectivity/DriversConfig.hxx>
+#include <rtl/uri.hxx>
+
+using namespace ::com::sun::star;
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+com_sun_star_comp_sdb_DBFilter_get_implementation(
+ css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const&)
+{
+ return cppu::acquire(new ::dbaxml::ODBFilter(context));
+}
+
+
+namespace dbaxml
+{
+ using namespace ::com::sun::star::util;
+ /// read a component (file + filter version)
+static ErrCode ReadThroughComponent(
+ const uno::Reference<XInputStream>& xInputStream,
+ const uno::Reference<XComponent>& xModelComponent,
+ const uno::Reference<XComponentContext> & rxContext,
+ ODBFilter& _rFilter )
+{
+ OSL_ENSURE(xInputStream.is(), "input stream missing");
+ OSL_ENSURE(xModelComponent.is(), "document missing");
+ OSL_ENSURE(rxContext.is(), "factory missing");
+
+ // prepare ParserInputSource
+ InputSource aParserInput;
+ aParserInput.aInputStream = xInputStream;
+
+ // connect model and filter
+ _rFilter.setTargetDocument( xModelComponent );
+
+ // finally, parser the stream
+ try
+ {
+ _rFilter.parseStream( aParserInput );
+ }
+ catch (const SAXParseException&)
+ {
+#if OSL_DEBUG_LEVEL > 0
+ TOOLS_WARN_EXCEPTION("dbaccess", "SAX parse exception caught while importing");
+#endif
+ return ErrCode(1);
+ }
+ catch (const SAXException&)
+ {
+ return ErrCode(1);
+ }
+ catch (const packages::zip::ZipIOException&)
+ {
+ return ERRCODE_IO_BROKENPACKAGE;
+ }
+ catch (const Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+
+ // success!
+ return ERRCODE_NONE;
+}
+
+
+/// read a component (storage version)
+static ErrCode ReadThroughComponent(
+ const uno::Reference< embed::XStorage >& xStorage,
+ const uno::Reference<XComponent>& xModelComponent,
+ const char* pStreamName,
+ const uno::Reference<XComponentContext> & rxContext,
+ ODBFilter& _rFilter)
+{
+ OSL_ENSURE( xStorage.is(), "Need storage!");
+ OSL_ENSURE(nullptr != pStreamName, "Please, please, give me a name!");
+
+ if ( !xStorage )
+ // TODO/LATER: better error handling
+ return ErrCode(1);
+
+ uno::Reference< io::XStream > xDocStream;
+
+ try
+ {
+ // open stream (and set parser input)
+ OUString sStreamName = OUString::createFromAscii(pStreamName);
+ if ( !xStorage->hasByName( sStreamName ) || !xStorage->isStreamElement( sStreamName ) )
+ {
+ // stream name not found! return immediately with OK signal
+ return ERRCODE_NONE;
+ }
+
+ // get input stream
+ xDocStream = xStorage->openStreamElement( sStreamName, embed::ElementModes::READ );
+ }
+ catch (const packages::WrongPasswordException&)
+ {
+ return ERRCODE_SFX_WRONGPASSWORD;
+ }
+ catch (const uno::Exception&)
+ {
+ return ErrCode(1); // TODO/LATER: error handling
+ }
+
+ uno::Reference< XInputStream > xInputStream = xDocStream->getInputStream();
+ // read from the stream
+ return ReadThroughComponent( xInputStream
+ ,xModelComponent
+ ,rxContext
+ ,_rFilter );
+}
+
+
+ODBFilter::ODBFilter( const uno::Reference< XComponentContext >& _rxContext )
+ : SvXMLImport(_rxContext, getImplementationName_Static())
+ , m_bNewFormat(false)
+{
+
+ GetMM100UnitConverter().SetCoreMeasureUnit(util::MeasureUnit::MM_10TH);
+ GetMM100UnitConverter().SetXMLMeasureUnit(util::MeasureUnit::CM);
+ GetNamespaceMap().Add( "_db",
+ GetXMLToken(XML_N_DB),
+ XML_NAMESPACE_DB );
+
+ GetNamespaceMap().Add( "__db",
+ GetXMLToken(XML_N_DB_OASIS),
+ XML_NAMESPACE_DB );
+}
+
+
+ODBFilter::~ODBFilter() noexcept
+{
+
+}
+
+
+OUString ODBFilter::getImplementationName_Static()
+{
+ return "com.sun.star.comp.sdb.DBFilter";
+}
+
+
+namespace {
+class FocusWindowWaitGuard
+{
+public:
+ FocusWindowWaitGuard()
+ {
+ SolarMutexGuard aGuard;
+ mpWindow.set(Application::GetFocusWindow());
+ if (mpWindow)
+ mpWindow->EnterWait();
+ }
+ ~FocusWindowWaitGuard()
+ {
+ if (mpWindow)
+ {
+ SolarMutexGuard aGuard;
+ mpWindow->LeaveWait();
+ }
+ }
+private:
+ VclPtr<vcl::Window> mpWindow;
+};
+}
+
+sal_Bool SAL_CALL ODBFilter::filter( const Sequence< PropertyValue >& rDescriptor )
+{
+ FocusWindowWaitGuard aWindowFocusGuard;
+ bool bRet = false;
+
+ if ( GetModel().is() )
+ bRet = implImport( rDescriptor );
+
+ return bRet;
+}
+
+
+bool ODBFilter::implImport( const Sequence< PropertyValue >& rDescriptor )
+{
+ OUString sFileName;
+ ::comphelper::NamedValueCollection aMediaDescriptor( rDescriptor );
+
+ uno::Reference<embed::XStorage> xStorage = GetSourceStorage();
+
+ bool bRet = true;
+ if (!xStorage.is())
+ {
+ if (aMediaDescriptor.has("URL"))
+ sFileName = aMediaDescriptor.getOrDefault("URL", OUString());
+ if (sFileName.isEmpty() && aMediaDescriptor.has("FileName"))
+ sFileName = aMediaDescriptor.getOrDefault("FileName", sFileName);
+
+ OSL_ENSURE(!sFileName.isEmpty(), "ODBFilter::implImport: no URL given!");
+ bRet = !sFileName.isEmpty();
+ }
+
+ if ( bRet )
+ {
+
+ tools::SvRef<SfxMedium> pMedium;
+ if (!xStorage.is())
+ {
+ OUString sStreamRelPath;
+ if (sFileName.startsWithIgnoreAsciiCase("vnd.sun.star.pkg:"))
+ {
+ // In this case the authority contains the real path, and the path is the embedded stream name.
+ auto const uri = css::uri::UriReferenceFactory::create(GetComponentContext())
+ ->parse(sFileName);
+ if (uri.is() && uri->isAbsolute()
+ && uri->hasAuthority() && !uri->hasQuery() && !uri->hasFragment())
+ {
+ auto const auth = uri->getAuthority();
+ auto const decAuth = rtl::Uri::decode(
+ auth, rtl_UriDecodeStrict, RTL_TEXTENCODING_UTF8);
+ auto path = uri->getPath();
+ if (!path.isEmpty()) {
+ assert(path[0] == '/');
+ path = path.copy(1);
+ }
+ auto const decPath = rtl::Uri::decode(
+ path, rtl_UriDecodeStrict, RTL_TEXTENCODING_UTF8);
+ //TODO: really decode path?
+ if (auth.isEmpty() == decAuth.isEmpty() && path.isEmpty() == decPath.isEmpty())
+ {
+ // Decoding of auth and path to UTF-8 succeeded:
+ sFileName = decAuth;
+ sStreamRelPath = decPath;
+ } else {
+ SAL_WARN(
+ "dbaccess",
+ "<" << sFileName << "> cannot be parse as vnd.sun.star.pkg URL");
+ }
+ } else {
+ SAL_WARN(
+ "dbaccess",
+ "<" << sFileName << "> cannot be parse as vnd.sun.star.pkg URL");
+ }
+ }
+
+ pMedium = new SfxMedium(sFileName, (StreamMode::READ | StreamMode::NOCREATE));
+ try
+ {
+ xStorage.set(pMedium->GetStorage(false), UNO_SET_THROW);
+
+ if (!sStreamRelPath.isEmpty())
+ xStorage = xStorage->openStorageElement(sStreamRelPath, embed::ElementModes::READ);
+ }
+ catch (const RuntimeException&)
+ {
+ throw;
+ }
+ catch (const Exception&)
+ {
+ Any aError = ::cppu::getCaughtException();
+ throw lang::WrappedTargetRuntimeException(OUString(), *this, aError);
+ }
+ }
+
+ uno::Reference<sdb::XOfficeDatabaseDocument> xOfficeDoc(GetModel(),UNO_QUERY_THROW);
+ m_xDataSource.set(xOfficeDoc->getDataSource(),UNO_QUERY_THROW);
+ uno::Reference< XNumberFormatsSupplier > xNum(m_xDataSource->getPropertyValue(PROPERTY_NUMBERFORMATSSUPPLIER),UNO_QUERY);
+ SetNumberFormatsSupplier(xNum);
+
+ uno::Reference<XComponent> xModel(GetModel());
+ ErrCode nRet = ReadThroughComponent( xStorage
+ ,xModel
+ ,"settings.xml"
+ ,GetComponentContext()
+ ,*this
+ );
+
+ if ( nRet == ERRCODE_NONE )
+ nRet = ReadThroughComponent( xStorage
+ ,xModel
+ ,"content.xml"
+ ,GetComponentContext()
+ ,*this
+ );
+
+ bRet = nRet == ERRCODE_NONE;
+
+ if ( bRet )
+ {
+ uno::Reference< XModifiable > xModi(GetModel(),UNO_QUERY);
+ if ( xModi.is() )
+ xModi->setModified(false);
+ }
+ else
+ {
+ if ( nRet == ERRCODE_IO_BROKENPACKAGE )
+ ;// TODO/LATER: no way to transport the error outside from the filter!
+ else
+ {
+ // TODO/LATER: this is completely wrong! Filter code should never call ErrorHandler directly! But for now this is the only way!
+ ErrorHandler::HandleError( nRet );
+ if( nRet.IsWarning() )
+ bRet = true;
+ }
+ }
+ }
+
+ return bRet;
+}
+
+namespace {
+
+class DBXMLDocumentSettingsContext : public SvXMLImportContext
+{
+public:
+ DBXMLDocumentSettingsContext(SvXMLImport & rImport)
+ : SvXMLImportContext(rImport)
+ {
+ }
+
+ virtual uno::Reference< xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
+ sal_Int32 nElement, const uno::Reference< xml::sax::XFastAttributeList >& /*xAttrList*/ ) override
+ {
+ if (nElement == XML_ELEMENT(OFFICE, XML_SETTINGS))
+ {
+ return new XMLDocumentSettingsContext(GetImport());
+ }
+ return nullptr;
+ }
+};
+
+class DBXMLDocumentStylesContext : public SvXMLImportContext
+{
+public:
+ DBXMLDocumentStylesContext(SvXMLImport & rImport)
+ : SvXMLImportContext(rImport)
+ {
+ }
+
+ virtual uno::Reference< xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
+ sal_Int32 nElement, const uno::Reference< xml::sax::XFastAttributeList >& /*xAttrList*/ ) override
+ {
+ ODBFilter & rImport(static_cast<ODBFilter&>(GetImport()));
+ switch (nElement)
+ {
+ case XML_ELEMENT(OFFICE, XML_STYLES):
+ case XML_ELEMENT(OOO, XML_STYLES):
+ rImport.GetProgressBarHelper()->Increment( PROGRESS_BAR_STEP );
+ return rImport.CreateStylesContext(false);
+ case XML_ELEMENT(OFFICE, XML_AUTOMATIC_STYLES):
+ case XML_ELEMENT(OOO, XML_AUTOMATIC_STYLES):
+ rImport.GetProgressBarHelper()->Increment( PROGRESS_BAR_STEP );
+ return rImport.CreateStylesContext(true);
+ }
+ return nullptr;
+ }
+};
+
+class DBXMLDocumentBodyContext : public SvXMLImportContext
+{
+public:
+ DBXMLDocumentBodyContext(SvXMLImport & rImport)
+ : SvXMLImportContext(rImport)
+ {
+ }
+
+ virtual uno::Reference< xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
+ sal_Int32 nElement, const uno::Reference< xml::sax::XFastAttributeList >& /*xAttrList*/ ) override
+ {
+ ODBFilter & rImport(static_cast<ODBFilter&>(GetImport()));
+ switch (nElement)
+ {
+ case XML_ELEMENT(OFFICE, XML_DATABASE):
+ case XML_ELEMENT(OOO, XML_DATABASE):
+ rImport.GetProgressBarHelper()->Increment( PROGRESS_BAR_STEP );
+ return new OXMLDatabase(rImport);
+ default: break;
+ }
+ return nullptr;
+ }
+};
+
+class DBXMLDocumentContentContext : public SvXMLImportContext
+{
+public:
+ DBXMLDocumentContentContext(SvXMLImport & rImport)
+ : SvXMLImportContext(rImport)
+ {
+ }
+
+ virtual uno::Reference< xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
+ sal_Int32 nElement, const uno::Reference< xml::sax::XFastAttributeList >& /*xAttrList*/ ) override
+ {
+ ODBFilter & rImport(static_cast<ODBFilter&>(GetImport()));
+ switch (nElement)
+ {
+ case XML_ELEMENT(OFFICE, XML_BODY):
+ case XML_ELEMENT(OOO, XML_BODY):
+ return new DBXMLDocumentBodyContext(rImport);
+ case XML_ELEMENT(OFFICE, XML_SCRIPTS):
+ return new XMLScriptContext(GetImport(), rImport.GetModel());
+ case XML_ELEMENT(OFFICE, XML_AUTOMATIC_STYLES):
+ case XML_ELEMENT(OOO, XML_AUTOMATIC_STYLES):
+ rImport.GetProgressBarHelper()->Increment( PROGRESS_BAR_STEP );
+ return rImport.CreateStylesContext(true);
+ default: break;
+ }
+ return nullptr;
+ }
+};
+
+}
+
+SvXMLImportContext* ODBFilter::CreateFastContext(sal_Int32 nElement,
+ const ::css::uno::Reference< ::css::xml::sax::XFastAttributeList >& /*xAttrList*/ )
+{
+ SvXMLImportContext *pContext = nullptr;
+
+ switch( nElement )
+ {
+ case XML_ELEMENT(OFFICE, XML_DOCUMENT_SETTINGS):
+ case XML_ELEMENT(OOO, XML_DOCUMENT_SETTINGS):
+ GetProgressBarHelper()->Increment( PROGRESS_BAR_STEP );
+ pContext = new DBXMLDocumentSettingsContext(*this);
+ break;
+ case XML_ELEMENT(OFFICE, XML_DOCUMENT_STYLES):
+ case XML_ELEMENT(OOO, XML_DOCUMENT_STYLES):
+ pContext = new DBXMLDocumentStylesContext(*this);
+ break;
+ case XML_ELEMENT(OFFICE, XML_DOCUMENT_CONTENT):
+ case XML_ELEMENT(OOO, XML_DOCUMENT_CONTENT):
+ pContext = new DBXMLDocumentContentContext(*this);
+ break;
+ }
+
+ return pContext;
+}
+
+
+void ODBFilter::SetViewSettings(const Sequence<PropertyValue>& aViewProps)
+{
+ const PropertyValue *pIter = aViewProps.getConstArray();
+ const PropertyValue *pEnd = pIter + aViewProps.getLength();
+ for (; pIter != pEnd; ++pIter)
+ {
+ if ( pIter->Name == "Queries" )
+ {
+ fillPropertyMap(pIter->Value,m_aQuerySettings);
+ }
+ else if ( pIter->Name == "Tables" )
+ {
+ fillPropertyMap(pIter->Value,m_aTablesSettings);
+ }
+ }
+}
+
+
+void ODBFilter::SetConfigurationSettings(const Sequence<PropertyValue>& aConfigProps)
+{
+ const PropertyValue *pIter = aConfigProps.getConstArray();
+ const PropertyValue *pEnd = pIter + aConfigProps.getLength();
+ for (; pIter != pEnd; ++pIter)
+ {
+ if ( pIter->Name == "layout-settings" )
+ {
+ Sequence<PropertyValue> aWindows;
+ pIter->Value >>= aWindows;
+ uno::Reference<XPropertySet> xProp(getDataSource());
+ if ( xProp.is() )
+ xProp->setPropertyValue(PROPERTY_LAYOUTINFORMATION,Any(aWindows));
+ }
+ }
+}
+
+
+void ODBFilter::fillPropertyMap(const Any& _rValue,TPropertyNameMap& _rMap)
+{
+ Sequence<PropertyValue> aWindows;
+ _rValue >>= aWindows;
+ const PropertyValue *pIter = aWindows.getConstArray();
+ const PropertyValue *pEnd = pIter + aWindows.getLength();
+ for (; pIter != pEnd; ++pIter)
+ {
+ Sequence<PropertyValue> aValue;
+ pIter->Value >>= aValue;
+ _rMap.emplace( pIter->Name,aValue );
+ }
+
+}
+
+SvXMLImportContext* ODBFilter::CreateStylesContext( bool bIsAutoStyle )
+{
+ SvXMLImportContext *pContext = new OTableStylesContext(*this, bIsAutoStyle);
+ if (bIsAutoStyle)
+ SetAutoStyles(static_cast<SvXMLStylesContext*>(pContext));
+ else
+ SetStyles(static_cast<SvXMLStylesContext*>(pContext));
+
+ return pContext;
+}
+
+
+rtl::Reference < XMLPropertySetMapper > const & ODBFilter::GetTableStylesPropertySetMapper() const
+{
+ if ( !m_xTableStylesPropertySetMapper.is() )
+ {
+ m_xTableStylesPropertySetMapper = OXMLHelper::GetTableStylesPropertySetMapper( false);
+ }
+ return m_xTableStylesPropertySetMapper;
+}
+
+
+rtl::Reference < XMLPropertySetMapper > const & ODBFilter::GetColumnStylesPropertySetMapper() const
+{
+ if ( !m_xColumnStylesPropertySetMapper.is() )
+ {
+ m_xColumnStylesPropertySetMapper = OXMLHelper::GetColumnStylesPropertySetMapper( false);
+ }
+ return m_xColumnStylesPropertySetMapper;
+}
+
+
+rtl::Reference < XMLPropertySetMapper > const & ODBFilter::GetCellStylesPropertySetMapper() const
+{
+ if ( !m_xCellStylesPropertySetMapper.is() )
+ {
+ m_xCellStylesPropertySetMapper = OXMLHelper::GetCellStylesPropertySetMapper( false);
+ }
+ return m_xCellStylesPropertySetMapper;
+}
+
+
+void ODBFilter::setPropertyInfo()
+{
+ Reference<XPropertySet> xDataSource(getDataSource());
+ if ( !xDataSource.is() )
+ return;
+
+ ::connectivity::DriversConfig aDriverConfig(GetComponentContext());
+ const OUString sURL = ::comphelper::getString(xDataSource->getPropertyValue(PROPERTY_URL));
+ ::comphelper::NamedValueCollection aDataSourceSettings = aDriverConfig.getProperties( sURL );
+
+ Sequence<PropertyValue> aInfo;
+ if ( !m_aInfoSequence.empty() )
+ aInfo = comphelper::containerToSequence(m_aInfoSequence);
+ aDataSourceSettings.merge( ::comphelper::NamedValueCollection( aInfo ), true );
+
+ aDataSourceSettings >>= aInfo;
+ if ( aInfo.hasElements() )
+ {
+ try
+ {
+ xDataSource->setPropertyValue(PROPERTY_INFO,Any(aInfo));
+ }
+ catch (const Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+}
+
+} // namespace dbaxml
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/filter/xml/xmlfilter.hxx b/dbaccess/source/filter/xml/xmlfilter.hxx
new file mode 100644
index 000000000..ec776cd75
--- /dev/null
+++ b/dbaccess/source/filter/xml/xmlfilter.hxx
@@ -0,0 +1,121 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <com/sun/star/container/XNamed.hpp>
+#include <com/sun/star/document/XFilter.hpp>
+#include <com/sun/star/document/XImporter.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/io/XActiveDataSource.hpp>
+#include <xmloff/xmlimp.hxx>
+#include <xmloff/xmlprmap.hxx>
+
+#include <map>
+#include <memory>
+
+
+namespace dbaxml
+{
+
+using namespace ::xmloff::token;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::document;
+using namespace ::com::sun::star::text;
+using namespace ::com::sun::star::io;
+using namespace ::com::sun::star::xml::sax;
+
+
+class ODBFilter : public SvXMLImport
+{
+public:
+ typedef std::map< OUString, Sequence<PropertyValue> > TPropertyNameMap;
+private:
+ TPropertyNameMap m_aQuerySettings;
+ TPropertyNameMap m_aTablesSettings;
+ std::vector< css::beans::PropertyValue> m_aInfoSequence;
+
+ mutable rtl::Reference < XMLPropertySetMapper > m_xTableStylesPropertySetMapper;
+ mutable rtl::Reference < XMLPropertySetMapper > m_xColumnStylesPropertySetMapper;
+ mutable rtl::Reference < XMLPropertySetMapper > m_xCellStylesPropertySetMapper;
+ Reference<XPropertySet> m_xDataSource;
+ bool m_bNewFormat;
+
+ /// @throws RuntimeException
+ bool implImport( const Sequence< PropertyValue >& rDescriptor );
+
+ /** fills the map with the Properties
+ @param _rValue
+ The Any where the sequence resists in.
+ @param _rMap
+ The map to fill.
+ */
+ static void fillPropertyMap(const Any& _rValue,TPropertyNameMap& _rMap);
+
+public:
+ SvXMLImportContext* CreateStylesContext( bool bIsAutoStyle );
+
+protected:
+ // SvXMLImport
+ virtual SvXMLImportContext *CreateFastContext(sal_Int32 Element,
+ const ::css::uno::Reference< ::css::xml::sax::XFastAttributeList >& xAttrList ) override;
+
+ virtual ~ODBFilter() noexcept override;
+public:
+
+ explicit ODBFilter( const Reference< XComponentContext >& _rxContext );
+
+ // XFilter
+ virtual sal_Bool SAL_CALL filter( const Sequence< PropertyValue >& rDescriptor ) override;
+
+ /// @throws css::uno::RuntimeException
+ static OUString getImplementationName_Static();
+
+ // helper class
+ virtual void SetViewSettings(const css::uno::Sequence<css::beans::PropertyValue>& aViewProps) override;
+ virtual void SetConfigurationSettings(const css::uno::Sequence<css::beans::PropertyValue>& aConfigProps) override;
+
+ const Reference<XPropertySet>& getDataSource() const { return m_xDataSource; }
+
+ const TPropertyNameMap& getQuerySettings() const { return m_aQuerySettings;}
+
+ rtl::Reference < XMLPropertySetMapper > const & GetTableStylesPropertySetMapper() const;
+ rtl::Reference < XMLPropertySetMapper > const & GetColumnStylesPropertySetMapper() const;
+ rtl::Reference < XMLPropertySetMapper > const & GetCellStylesPropertySetMapper() const;
+
+ /** add an Info to the sequence which will be appended to the data source
+ @param _rInfo The property to append.
+ */
+ void addInfo(const css::beans::PropertyValue& _rInfo)
+ {
+ m_aInfoSequence.push_back(_rInfo);
+ }
+
+ void setPropertyInfo();
+
+ bool isNewFormat() const { return m_bNewFormat; }
+ void setNewFormat(bool _bNewFormat) { m_bNewFormat = _bNewFormat; }
+};
+
+} // namespace dbaxml
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/inc/OAuthenticationContinuation.hxx b/dbaccess/source/inc/OAuthenticationContinuation.hxx
new file mode 100644
index 000000000..d1eac7b54
--- /dev/null
+++ b/dbaccess/source/inc/OAuthenticationContinuation.hxx
@@ -0,0 +1,67 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <dbadllapi.hxx>
+
+#include <com/sun/star/ucb/XInteractionSupplyAuthentication.hpp>
+#include <com/sun/star/ucb/RememberAuthentication.hpp>
+#include <com/sun/star/uno/Sequence.hxx>
+
+#include <rtl/ustring.hxx>
+#include <comphelper/interaction.hxx>
+
+namespace dbaccess
+{
+
+class OOO_DLLPUBLIC_DBA OAuthenticationContinuation :
+ public comphelper::OInteraction< css::ucb::XInteractionSupplyAuthentication >
+{
+ bool m_bRememberPassword : 1; // remember the password for this session ?
+
+ bool m_bCanSetUserName;
+ OUString m_sUser; // the user
+ OUString m_sPassword; // the user's password
+
+public:
+ OAuthenticationContinuation();
+
+ sal_Bool SAL_CALL canSetRealm( ) override;
+ void SAL_CALL setRealm( const OUString& Realm ) override;
+ sal_Bool SAL_CALL canSetUserName( ) override;
+ void SAL_CALL setUserName( const OUString& UserName ) override;
+ sal_Bool SAL_CALL canSetPassword( ) override;
+ void SAL_CALL setPassword( const OUString& Password ) override;
+ css::uno::Sequence< css::ucb::RememberAuthentication > SAL_CALL getRememberPasswordModes( css::ucb::RememberAuthentication& Default ) override;
+ void SAL_CALL setRememberPassword( css::ucb::RememberAuthentication Remember ) override;
+ sal_Bool SAL_CALL canSetAccount( ) override;
+ void SAL_CALL setAccount( const OUString& Account ) override;
+ css::uno::Sequence< css::ucb::RememberAuthentication > SAL_CALL getRememberAccountModes( css::ucb::RememberAuthentication& Default ) override;
+ void SAL_CALL setRememberAccount( css::ucb::RememberAuthentication Remember ) override;
+
+ void setCanChangeUserName( bool bVal ) { m_bCanSetUserName = bVal; }
+ const OUString& getUser() const { return m_sUser; }
+ const OUString& getPassword() const { return m_sPassword; }
+ bool getRememberPassword() const { return m_bRememberPassword; }
+};
+
+} // namespace dbaccess
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/inc/apitools.hxx b/dbaccess/source/inc/apitools.hxx
new file mode 100644
index 000000000..7438c0872
--- /dev/null
+++ b/dbaccess/source/inc/apitools.hxx
@@ -0,0 +1,52 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <sal/config.h>
+
+#include <cppuhelper/component.hxx>
+#include <osl/mutex.hxx>
+
+// OSubComponent - a component which holds a hard ref to its parent
+// and is been hold itself (by the parent) with a weak ref
+class OSubComponent : public ::cppu::OComponentHelper
+{
+protected:
+ // the parent must support the tunnel implementation
+ css::uno::Reference< css::uno::XInterface > m_xParent;
+ virtual ~OSubComponent() override;
+
+public:
+ OSubComponent(::osl::Mutex& _rMutex,
+ const css::uno::Reference< css::uno::XInterface >& _xParent);
+
+// css::lang::XTypeProvider
+ virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes() override;
+
+// css::uno::XInterface
+ virtual css::uno::Any SAL_CALL queryInterface( const css::uno::Type & rType ) override;
+ virtual void SAL_CALL release() noexcept override;
+
+ operator css::uno::Reference< css::uno::XInterface > () const
+ { return static_cast<css::uno::XWeak *>(const_cast<OSubComponent *>(this)); }
+
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/inc/dsntypes.hxx b/dbaccess/source/inc/dsntypes.hxx
new file mode 100644
index 000000000..875d781d1
--- /dev/null
+++ b/dbaccess/source/inc/dsntypes.hxx
@@ -0,0 +1,218 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <sal/config.h>
+
+#include <string_view>
+#include <vector>
+
+#include <dbadllapi.hxx>
+#include <connectivity/DriversConfig.hxx>
+
+namespace dbaccess
+{
+
+// DATASOURCE_TYPE
+/// known datasource types
+enum DATASOURCE_TYPE
+{
+ DST_MSACCESS = 1,
+ DST_MYSQL_ODBC = 2,
+ DST_MYSQL_JDBC = 3,
+ DST_ORACLE_JDBC = 4,
+ //5 was DST_ADABAS
+ DST_CALC = 6,
+ DST_DBASE = 7,
+ DST_FLAT = 8,
+ DST_JDBC = 9,
+ DST_ODBC = 10,
+ DST_ADO = 11,
+ DST_MOZILLA = 12,
+ DST_THUNDERBIRD = 13,
+ DST_LDAP = 14,
+ DST_OUTLOOK = 15,
+ DST_OUTLOOKEXP = 16,
+ DST_EVOLUTION = 17,
+ DST_EVOLUTION_GROUPWISE = 18,
+ DST_EVOLUTION_LDAP = 19,
+ DST_KAB = 20,
+ DST_MACAB = 21,
+ DST_MSACCESS_2007 = 22,
+ DST_EMBEDDED_HSQLDB = 23,
+ DST_MYSQL_NATIVE = 24,
+ DST_MYSQL_NATIVE_DIRECT = 25,
+ DST_FIREBIRD = 26,
+ DST_EMBEDDED_FIREBIRD = 27,
+ DST_POSTGRES = 28,
+ DST_WRITER = 29,
+
+ DST_USERDEFINE1, /// first user defined driver
+ DST_USERDEFINE2,
+ DST_USERDEFINE3,
+ DST_USERDEFINE4,
+ DST_USERDEFINE5,
+ DST_USERDEFINE6,
+ DST_USERDEFINE7,
+ DST_USERDEFINE8,
+ DST_USERDEFINE9,
+ DST_USERDEFINE10,
+
+ DST_UNKNOWN /// unrecognized type
+};
+
+#define PAGE_DBSETUPWIZARD_INTRO 0
+#define PAGE_DBSETUPWIZARD_DBASE 1
+#define PAGE_DBSETUPWIZARD_TEXT 2
+#define PAGE_DBSETUPWIZARD_MSACCESS 3
+#define PAGE_DBSETUPWIZARD_LDAP 4
+//5 was PAGE_DBSETUPWIZARD_ADABAS
+#define PAGE_DBSETUPWIZARD_MYSQL_INTRO 6
+#define PAGE_DBSETUPWIZARD_MYSQL_JDBC 7
+#define PAGE_DBSETUPWIZARD_MYSQL_ODBC 8
+#define PAGE_DBSETUPWIZARD_ORACLE 9
+#define PAGE_DBSETUPWIZARD_JDBC 10
+#define PAGE_DBSETUPWIZARD_ADO 11
+#define PAGE_DBSETUPWIZARD_ODBC 12
+#define PAGE_DBSETUPWIZARD_DOCUMENT_OR_SPREADSHEET 13
+#define PAGE_DBSETUPWIZARD_AUTHENTIFICATION 14
+#define PAGE_DBSETUPWIZARD_FINAL 16
+#define PAGE_DBSETUPWIZARD_USERDEFINED 17
+#define PAGE_DBSETUPWIZARD_MYSQL_NATIVE 18
+
+// ODsnTypeCollection
+class OOO_DLLPUBLIC_DBA ODsnTypeCollection final
+{
+
+ std::vector<OUString> m_aDsnTypesDisplayNames; /// user readable names for the datasource types
+ std::vector<OUString> m_aDsnPrefixes; /// DSN prefixes which determine the type of a datasource
+ ::connectivity::DriversConfig m_aDriverConfig;
+
+#if OSL_DEBUG_LEVEL > 0
+ sal_Int32 m_nLivingIterators; /// just for debugging reasons, counts the living iterators
+#endif
+
+public:
+ class TypeIterator;
+ friend class ODsnTypeCollection::TypeIterator;
+
+ ODsnTypeCollection(const css::uno::Reference< css::uno::XComponentContext >& _xContext);
+ ~ODsnTypeCollection();
+
+ /// get the datasource type display name from a DSN string
+ OUString getTypeDisplayName(std::u16string_view _sURL) const;
+
+ /// on a given string, cut the type prefix and return the result
+ OUString cutPrefix(std::u16string_view _sURL) const;
+
+ /// on a given string, return the type prefix
+ OUString getPrefix(const OUString& _sURL) const;
+
+ /// determines whether there is a driver for the given URL prefix/pattern
+ bool hasDriver( const char* _pAsciiPattern ) const;
+
+ /// on a given string, return the Java Driver Class
+ OUString getJavaDriverClass(std::u16string_view _sURL) const;
+
+ /// returns the media type of a file based database
+ OUString getMediaType(std::u16string_view _sURL) const;
+
+ /// returns the dsn prefix for a given media type
+ OUString getDatasourcePrefixFromMediaType(std::u16string_view _sMediaType, std::u16string_view _sExtension );
+
+ void extractHostNamePort(const OUString& _rDsn,OUString& _sDatabaseName,OUString& _rHostname,sal_Int32& _nPortNumber) const;
+
+ /// check if the given data source allows creation of tables
+ bool supportsTableCreation(std::u16string_view _sURL) const;
+
+ /// check if the given data source allows to show column description.
+ bool supportsColumnDescription(std::u16string_view _sURL) const;
+
+ // check if a Browse button may be shown to insert connection url
+ bool supportsBrowsing(std::u16string_view _sURL) const;
+
+ // check if a Create New Database button may be shown to insert connection url
+ bool supportsDBCreation(std::u16string_view _sURL) const;
+
+ /// check if the given data source type is based on the file system - i.e. the URL is a prefix plus a file URL
+ bool isFileSystemBased(std::u16string_view _sURL) const;
+
+ bool isConnectionUrlRequired(std::u16string_view _sURL) const;
+
+ /// checks if the given data source type embeds its data into the database document
+ static bool isEmbeddedDatabase( std::u16string_view _sURL );
+
+ static OUString getEmbeddedDatabase();
+
+ // returns true when the properties dialog can be shown, otherwise false.
+ static bool isShowPropertiesEnabled( const OUString& _sURL );
+
+ /** returns default settings for newly created databases of the given type.
+ */
+ css::uno::Sequence< css::beans::PropertyValue>
+ getDefaultDBSettings( std::u16string_view _sURL ) const;
+
+ /// get access to the first element of the types collection
+ inline TypeIterator begin() const;
+ /// get access to the (last + 1st) element of the types collection
+ inline TypeIterator end() const;
+
+ void fillPageIds(std::u16string_view _sURL,std::vector<sal_Int16>& _rOutPathIds) const;
+
+ DATASOURCE_TYPE determineType(std::u16string_view _rDsn) const;
+
+ sal_Int32 getIndexOf(std::u16string_view _sURL) const;
+ sal_Int32 size() const;
+ OUString getType(std::u16string_view _sURL) const;
+};
+
+//- ODsnTypeCollection::TypeIterator
+class OOO_DLLPUBLIC_DBA ODsnTypeCollection::TypeIterator
+{
+ friend class ODsnTypeCollection;
+
+ friend bool OOO_DLLPUBLIC_DBA operator==(const TypeIterator& lhs, const TypeIterator& rhs);
+ friend bool OOO_DLLPUBLIC_DBA operator!=(const TypeIterator& lhs, const TypeIterator& rhs) { return !(lhs == rhs); }
+
+protected:
+ const ODsnTypeCollection* m_pContainer;
+ sal_Int32 m_nPosition;
+
+public:
+ TypeIterator(const TypeIterator& _rSource);
+ ~TypeIterator();
+
+ OUString const & getURLPrefix() const;
+ OUString const & getDisplayName() const;
+
+ /// prefix increment
+ const TypeIterator& operator++();
+
+protected:
+ TypeIterator(const ODsnTypeCollection* _pContainer, sal_Int32 _nInitialPos);
+};
+
+
+inline ODsnTypeCollection::TypeIterator ODsnTypeCollection::begin() const { return ODsnTypeCollection::TypeIterator(this, 0);}
+inline ODsnTypeCollection::TypeIterator ODsnTypeCollection::end() const { return ODsnTypeCollection::TypeIterator(this, m_aDsnTypesDisplayNames.size());}
+
+} // namespace dbaccess
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/inc/stringconstants.hxx b/dbaccess/source/inc/stringconstants.hxx
new file mode 100644
index 000000000..1f20962a7
--- /dev/null
+++ b/dbaccess/source/inc/stringconstants.hxx
@@ -0,0 +1,171 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+// property ids
+
+#define PROPERTY_ID_TITLE 1
+#define PROPERTY_ID_URL 2
+#define PROPERTY_ID_INFO 4
+#define PROPERTY_ID_ISPASSWORDREQUIRED 5
+#define PROPERTY_ID_TABLEFILTER 6
+#define PROPERTY_ID_NAME 7
+#define PROPERTY_ID_SCHEMANAME 8
+#define PROPERTY_ID_CATALOGNAME 9
+#define PROPERTY_ID_PRIVILEGES 10
+#define PROPERTY_ID_ESCAPE_PROCESSING 11
+#define PROPERTY_ID_COMMAND 12
+#define PROPERTY_ID_TYPE 13
+#define PROPERTY_ID_TYPENAME 14
+#define PROPERTY_ID_PRECISION 15
+#define PROPERTY_ID_SCALE 16
+#define PROPERTY_ID_ISNULLABLE 17
+#define PROPERTY_ID_ISAUTOINCREMENT 18
+#define PROPERTY_ID_ISROWVERSION 19
+#define PROPERTY_ID_DESCRIPTION 20
+#define PROPERTY_ID_DEFAULTVALUE 21
+#define PROPERTY_ID_NUMBERFORMAT 22
+#define PROPERTY_ID_QUERYTIMEOUT 23
+#define PROPERTY_ID_MAXFIELDSIZE 24
+#define PROPERTY_ID_MAXROWS 25
+#define PROPERTY_ID_CURSORNAME 26
+#define PROPERTY_ID_RESULTSETCONCURRENCY 27
+#define PROPERTY_ID_RESULTSETTYPE 28
+#define PROPERTY_ID_FETCHDIRECTION 29
+#define PROPERTY_ID_FETCHSIZE 30
+#define PROPERTY_ID_USEBOOKMARKS 31
+#define PROPERTY_ID_ISSEARCHABLE 32
+#define PROPERTY_ID_ISCURRENCY 33
+#define PROPERTY_ID_ISSIGNED 34
+#define PROPERTY_ID_DISPLAYSIZE 35
+#define PROPERTY_ID_LABEL 36
+#define PROPERTY_ID_ISREADONLY 37
+#define PROPERTY_ID_ISWRITABLE 38
+#define PROPERTY_ID_ISDEFINITELYWRITABLE 39
+#define PROPERTY_ID_VALUE 40
+#define PROPERTY_ID_TABLENAME 41
+#define PROPERTY_ID_ISCASESENSITIVE 42
+#define PROPERTY_ID_SERVICENAME 43
+#define PROPERTY_ID_ISBOOKMARKABLE 44
+#define PROPERTY_ID_CANUPDATEINSERTEDROWS 45
+#define PROPERTY_ID_ISSET 46
+#define PROPERTY_ID_ISOUTPARAMETER 47
+#define PROPERTY_ID_NUMBERFORMATSSUPPLIER 48
+#define PROPERTY_ID_ISCALCULATED 49
+#define PROPERTY_ID_DATASOURCENAME 50
+#define PROPERTY_ID_TRANSACTIONISOLATION 51
+#define PROPERTY_ID_TYPEMAP 52
+#define PROPERTY_ID_USER 53
+#define PROPERTY_ID_PASSWORD 54
+#define PROPERTY_ID_COMMAND_TYPE 55
+#define PROPERTY_ID_ACTIVECOMMAND 56
+#define PROPERTY_ID_ACTIVE_CONNECTION 57
+#define PROPERTY_ID_FILTER 58
+#define PROPERTY_ID_APPLYFILTER 59
+#define PROPERTY_ID_ORDER 60
+#define PROPERTY_ID_ISMODIFIED 61
+#define PROPERTY_ID_ISNEW 62
+#define PROPERTY_ID_ROWCOUNT 63
+#define PROPERTY_ID_ISROWCOUNTFINAL 64
+#define PROPERTY_ID_HELPFILENAME 65
+#define PROPERTY_ID_REALNAME 66
+#define PROPERTY_ID_HIDDEN 67
+#define PROPERTY_ID_ALIGN 68
+#define PROPERTY_ID_WIDTH 69
+#define PROPERTY_ID_TABLETYPEFILTER 70
+#define PROPERTY_ID_DATABASE_LOCATION 71
+#define PROPERTY_ID_FONT 72
+#define PROPERTY_ID_ROW_HEIGHT 73
+#define PROPERTY_ID_TEXTCOLOR 74
+#define PROPERTY_ID_UPDATE_TABLENAME 75
+#define PROPERTY_ID_UPDATE_SCHEMANAME 76
+#define PROPERTY_ID_UPDATE_CATALOGNAME 77
+#define PROPERTY_ID_CONTROLMODEL 78
+#define PROPERTY_ID_RELATIVEPOSITION 79
+#define PROPERTY_ID_ISASCENDING 80
+#define PROPERTY_ID_RELATEDCOLUMN 81
+#define PROPERTY_ID_ISUNIQUE 82
+#define PROPERTY_ID_ISPRIMARYKEYINDEX 83
+#define PROPERTY_ID_IGNORERESULT 84
+#define PROPERTY_ID_DELETERULE 85
+#define PROPERTY_ID_UPDATERULE 86
+#define PROPERTY_ID_REFERENCEDTABLE 87
+#define PROPERTY_ID_REFERENCEDCOLUMN 88
+#define PROPERTY_ID_PARENTWINDOW 89
+#define PROPERTY_ID_SQLEXCEPTION 90
+#define PROPERTY_ID_ISHIDDEN 91
+#define PROPERTY_ID_SUPPRESSVERSIONCL 92
+#define PROPERTY_ID_LAYOUTINFORMATION 93
+#define PROPERTY_ID_TEXTLINECOLOR 94
+#define PROPERTY_ID_TEXTEMPHASIS 95
+#define PROPERTY_ID_TEXTRELIEF 96
+#define PROPERTY_ID_HELPTEXT 97
+#define PROPERTY_ID_CONTROLDEFAULT 98
+#define PROPERTY_ID_AUTOINCREMENTCREATION 99
+#define PROPERTY_ID_SPECIAL_OPTIONS 100
+#define PROPERTY_ID_FONTCHARWIDTH 101
+#define PROPERTY_ID_FONTCHARSET 102
+#define PROPERTY_ID_FONTFAMILY 103
+#define PROPERTY_ID_FONTHEIGHT 104
+#define PROPERTY_ID_FONTKERNING 105
+#define PROPERTY_ID_FONTNAME 106
+#define PROPERTY_ID_FONTORIENTATION 107
+#define PROPERTY_ID_FONTPITCH 108
+#define PROPERTY_ID_FONTSLANT 109
+#define PROPERTY_ID_FONTSTRIKEOUT 110
+#define PROPERTY_ID_FONTSTYLENAME 111
+#define PROPERTY_ID_FONTUNDERLINE 112
+#define PROPERTY_ID_FONTWEIGHT 113
+#define PROPERTY_ID_FONTWIDTH 114
+#define PROPERTY_ID_FONTWORDLINEMODE 115
+#define PROPERTY_ID_FONTTYPE 116
+#define PROPERTY_ID_PERSISTENT_NAME 117
+#define PROPERTY_ID_ORIGINAL 118
+#define PROPERTY_ID_TABSTOP 119
+#define PROPERTY_ID_DEFAULTCONTROL 120
+#define PROPERTY_ID_ENABLED 121
+#define PROPERTY_ID_BORDER 122
+#define PROPERTY_ID_COLUMN 123
+#define PROPERTY_ID_AS_TEMPLATE 124
+#define PROPERTY_ID_IS_FORM 125
+#define PROPERTY_ID_HAVING_CLAUSE 126
+#define PROPERTY_ID_GROUP_BY 127
+#define PROPERTY_ID_EDIT_WIDTH 128
+#define PROPERTY_ID_SETTINGS 129
+#define PROPERTY_ID_CONNECTION_RESOURCE 130
+#define PROPERTY_ID_RESULT_SET 131
+#define PROPERTY_ID_SELECTION 132
+#define PROPERTY_ID_BOOKMARK_SELECTION 133
+#define PROPERTY_ID_COLUMN_NAME 134
+#define PROPERTY_ID_CONNECTION_INFO 135
+#define PROPERTY_ID_HEADER_LINE 136
+#define PROPERTY_ID_FIELD_DELIMITER 137
+#define PROPERTY_ID_STRING_DELIMITER 138
+#define PROPERTY_ID_DECIMAL_DELIMITER 139
+#define PROPERTY_ID_THOUSAND_DELIMITER 140
+#define PROPERTY_ID_ENCODING 141
+#define PROPERTY_ID_HELP_URL 142
+#define PROPERTY_ID_PERSISTENT_PATH 143
+#define PROPERTY_ID_CURRENT_QUERY_DESIGN 144
+#define PROPERTY_ID_SINGLESELECTQUERYCOMPOSER 145
+#define PROPERTY_ID_PROPCHANGE_NOTIFY 146
+#define PROPERTY_ID_AUTOGROW 147
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/sdbtools/connection/connectiontools.cxx b/dbaccess/source/sdbtools/connection/connectiontools.cxx
new file mode 100644
index 000000000..5dd408bac
--- /dev/null
+++ b/dbaccess/source/sdbtools/connection/connectiontools.cxx
@@ -0,0 +1,132 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <connectiontools.hxx>
+#include "tablename.hxx"
+#include "objectnames.hxx"
+#include "datasourcemetadata.hxx"
+
+#include <comphelper/namedvaluecollection.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <connectivity/dbtools.hxx>
+#include <connectivity/statementcomposer.hxx>
+
+namespace sdbtools
+{
+
+ using namespace ::com::sun::star;
+ using namespace ::com::sun::star::uno;
+ using ::com::sun::star::uno::Reference;
+ using ::com::sun::star::sdb::tools::XTableName;
+ using ::com::sun::star::sdb::tools::XObjectNames;
+ using ::com::sun::star::sdb::tools::XDataSourceMetaData;
+ using ::com::sun::star::uno::Sequence;
+ using ::com::sun::star::uno::XInterface;
+ using ::com::sun::star::uno::Any;
+ using ::com::sun::star::sdbc::XConnection;
+ using ::com::sun::star::lang::IllegalArgumentException;
+ using ::com::sun::star::uno::XComponentContext;
+
+ // ConnectionTools
+ ConnectionTools::ConnectionTools( const Reference<XComponentContext>& _rContext )
+ :ConnectionDependentComponent( _rContext )
+ {
+ }
+
+ ConnectionTools::~ConnectionTools()
+ {
+ }
+
+ Reference< XTableName > SAL_CALL ConnectionTools::createTableName()
+ {
+ EntryGuard aGuard( *this );
+ return new TableName( getContext(), getConnection() );
+ }
+
+ Reference< XObjectNames > SAL_CALL ConnectionTools::getObjectNames()
+ {
+ EntryGuard aGuard( *this );
+ return new ObjectNames( getContext(), getConnection() );
+ }
+
+ Reference< XDataSourceMetaData > SAL_CALL ConnectionTools::getDataSourceMetaData()
+ {
+ EntryGuard aGuard( *this );
+ return new DataSourceMetaData( getContext(), getConnection() );
+ }
+ Reference< container::XNameAccess > SAL_CALL ConnectionTools::getFieldsByCommandDescriptor( ::sal_Int32 commandType, const OUString& command, Reference< lang::XComponent >& keepFieldsAlive )
+ {
+ EntryGuard aGuard( *this );
+ ::dbtools::SQLExceptionInfo aErrorInfo;
+ Reference< container::XNameAccess > xRet = ::dbtools::getFieldsByCommandDescriptor(getConnection(),commandType,command,keepFieldsAlive,&aErrorInfo);
+ if ( aErrorInfo.isValid() )
+ aErrorInfo.doThrow();
+ return xRet;
+ }
+ Reference< sdb::XSingleSelectQueryComposer > SAL_CALL ConnectionTools::getComposer( ::sal_Int32 commandType, const OUString& command )
+ {
+ EntryGuard aGuard( *this );
+ dbtools::StatementComposer aComposer(getConnection(), command, commandType, true );
+ aComposer.setDisposeComposer(false);
+ return aComposer.getComposer();
+ }
+
+ OUString SAL_CALL ConnectionTools::getImplementationName()
+ {
+ return "com.sun.star.comp.dbaccess.ConnectionTools";
+ }
+
+ sal_Bool SAL_CALL ConnectionTools::supportsService(const OUString & ServiceName)
+ {
+ return cppu::supportsService(this, ServiceName);
+ }
+
+ Sequence< OUString > SAL_CALL ConnectionTools::getSupportedServiceNames()
+ {
+ return { "com.sun.star.sdb.tools.ConnectionTools" };
+ }
+
+ void SAL_CALL ConnectionTools::initialize(const Sequence< Any > & _rArguments)
+ {
+ ::osl::MutexGuard aGuard( getMutex() );
+
+ Reference< XConnection > xConnection;
+ if (_rArguments.getLength()==1 && (_rArguments[0] >>= xConnection))
+ {
+ }
+ else
+ {
+ ::comphelper::NamedValueCollection aArguments( _rArguments );
+ aArguments.get( "Connection" ) >>= xConnection;
+ }
+ if ( !xConnection.is() )
+ throw IllegalArgumentException();
+
+ setWeakConnection( xConnection );
+ }
+
+} // namespace sdbtools
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+com_sun_star_comp_dbaccess_ConnectionTools_get_implementation(
+ css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const& )
+{
+ return cppu::acquire(new sdbtools::ConnectionTools(context));
+}
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/sdbtools/connection/datasourcemetadata.cxx b/dbaccess/source/sdbtools/connection/datasourcemetadata.cxx
new file mode 100644
index 000000000..a446885b8
--- /dev/null
+++ b/dbaccess/source/sdbtools/connection/datasourcemetadata.cxx
@@ -0,0 +1,51 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "datasourcemetadata.hxx"
+
+#include <connectivity/dbmetadata.hxx>
+
+namespace sdbtools
+{
+
+ using ::com::sun::star::uno::Reference;
+ using ::com::sun::star::sdbc::XConnection;
+ using ::com::sun::star::uno::XComponentContext;
+
+ // DataSourceMetaData
+ DataSourceMetaData::DataSourceMetaData( const Reference<XComponentContext>& _rContext, const Reference< XConnection >& _rxConnection )
+ :ConnectionDependentComponent( _rContext )
+ {
+ setWeakConnection( _rxConnection );
+ }
+
+ DataSourceMetaData::~DataSourceMetaData()
+ {
+ }
+
+ sal_Bool SAL_CALL DataSourceMetaData::supportsQueriesInFrom( )
+ {
+ EntryGuard aGuard( *this );
+ ::dbtools::DatabaseMetaData aMeta( getConnection() );
+ return aMeta.supportsSubqueriesInFrom();
+ }
+
+} // namespace sdbtools
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/sdbtools/connection/datasourcemetadata.hxx b/dbaccess/source/sdbtools/connection/datasourcemetadata.hxx
new file mode 100644
index 000000000..232f97f60
--- /dev/null
+++ b/dbaccess/source/sdbtools/connection/datasourcemetadata.hxx
@@ -0,0 +1,69 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <connectiondependent.hxx>
+
+#include <com/sun/star/sdb/tools/XDataSourceMetaData.hpp>
+
+#include <cppuhelper/implbase.hxx>
+
+#include <memory>
+
+namespace sdbtools
+{
+
+ // DataSourceMetaData
+ typedef ::cppu::WeakImplHelper< css::sdb::tools::XDataSourceMetaData
+ > DataSourceMetaData_Base;
+ /** default implementation for XDataSourceMetaData
+ */
+ class DataSourceMetaData :public DataSourceMetaData_Base
+ ,public ConnectionDependentComponent
+ {
+
+ public:
+ /** constructs the instance
+ @param _rContext
+ the component's context
+ @param _rxConnection
+ the connection to work with. Will be held weak. Must not be <NULL/>.
+ @throws css::lang::NullPointerException
+ if _rxConnection is <NULL/>
+ */
+ DataSourceMetaData(
+ const css::uno::Reference< css::uno::XComponentContext >& _rContext,
+ const css::uno::Reference< css::sdbc::XConnection >& _rxConnection
+ );
+
+ // XDataSourceMetaData
+ virtual sal_Bool SAL_CALL supportsQueriesInFrom() override;
+
+ protected:
+ virtual ~DataSourceMetaData() override;
+
+ private:
+ DataSourceMetaData( const DataSourceMetaData& ) = delete;
+ DataSourceMetaData& operator=( const DataSourceMetaData& ) = delete;
+ };
+
+} // namespace sdbtools
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/sdbtools/connection/objectnames.cxx b/dbaccess/source/sdbtools/connection/objectnames.cxx
new file mode 100644
index 000000000..66dd03787
--- /dev/null
+++ b/dbaccess/source/sdbtools/connection/objectnames.cxx
@@ -0,0 +1,420 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "objectnames.hxx"
+#include <core_resource.hxx>
+
+#include <strings.hrc>
+
+#include <com/sun/star/sdb/CommandType.hpp>
+#include <com/sun/star/sdbcx/XTablesSupplier.hpp>
+#include <com/sun/star/sdb/XQueriesSupplier.hpp>
+#include <com/sun/star/sdb/ErrorCondition.hpp>
+
+#include <connectivity/dbmetadata.hxx>
+#include <connectivity/dbtools.hxx>
+#include <connectivity/sqlerror.hxx>
+#include <osl/diagnose.h>
+
+#include <memory>
+
+namespace sdbtools
+{
+
+ using ::com::sun::star::uno::Reference;
+ using ::com::sun::star::sdbc::XConnection;
+ using ::com::sun::star::lang::IllegalArgumentException;
+ using ::com::sun::star::sdbc::SQLException;
+ using ::com::sun::star::sdbc::XDatabaseMetaData;
+ using ::com::sun::star::container::XNameAccess;
+ using ::com::sun::star::uno::UNO_QUERY_THROW;
+ using ::com::sun::star::sdbcx::XTablesSupplier;
+ using ::com::sun::star::sdb::XQueriesSupplier;
+ using ::com::sun::star::uno::Exception;
+ using ::com::sun::star::uno::Any;
+ using ::com::sun::star::uno::XComponentContext;
+
+ namespace CommandType = ::com::sun::star::sdb::CommandType;
+ namespace ErrorCondition = ::com::sun::star::sdb::ErrorCondition;
+
+ namespace {
+
+ // INameValidation
+ class INameValidation
+ {
+ public:
+ virtual bool validateName( const OUString& _rName ) = 0;
+ virtual void validateName_throw( const OUString& _rName ) = 0;
+
+ virtual ~INameValidation() { }
+ };
+
+ }
+
+ typedef std::shared_ptr< INameValidation > PNameValidation;
+
+ namespace {
+
+ // PlainExistenceCheck
+ class PlainExistenceCheck : public INameValidation
+ {
+ private:
+ Reference< XConnection > m_xConnection;
+ Reference< XNameAccess > m_xContainer;
+
+ public:
+ PlainExistenceCheck( const Reference< XConnection >& _rxConnection, const Reference< XNameAccess >& _rxContainer )
+ :m_xConnection( _rxConnection )
+ ,m_xContainer( _rxContainer )
+ {
+ OSL_ENSURE( m_xContainer.is(), "PlainExistenceCheck::PlainExistenceCheck: this will crash!" );
+ }
+
+ // INameValidation
+ virtual bool validateName( const OUString& _rName ) override
+ {
+ return !m_xContainer->hasByName( _rName );
+ }
+
+ virtual void validateName_throw( const OUString& _rName ) override
+ {
+ if ( validateName( _rName ) )
+ return;
+
+ ::connectivity::SQLError aErrors;
+ SQLException aError( aErrors.getSQLException( ErrorCondition::DB_OBJECT_NAME_IS_USED, m_xConnection, _rName ) );
+
+ ::dbtools::DatabaseMetaData aMeta( m_xConnection );
+ if ( aMeta.supportsSubqueriesInFrom() )
+ {
+ OUString sNeedDistinctNames( DBA_RES( STR_QUERY_AND_TABLE_DISTINCT_NAMES ) );
+ aError.NextException <<= SQLException( sNeedDistinctNames, m_xConnection, OUString(), 0, Any() );
+ }
+
+ throw aError;
+ }
+ };
+
+ // TableValidityCheck
+ class TableValidityCheck : public INameValidation
+ {
+ const Reference< XConnection > m_xConnection;
+
+ public:
+ TableValidityCheck( const Reference< XConnection >& _rxConnection )
+ :m_xConnection( _rxConnection )
+ {
+ }
+
+ virtual bool validateName( const OUString& _rName ) override
+ {
+ ::dbtools::DatabaseMetaData aMeta( m_xConnection );
+ if ( !aMeta.restrictIdentifiersToSQL92() )
+ return true;
+
+ OUString sCatalog, sSchema, sName;
+ ::dbtools::qualifiedNameComponents(
+ m_xConnection->getMetaData(), _rName, sCatalog, sSchema, sName, ::dbtools::EComposeRule::InTableDefinitions );
+
+ OUString sExtraNameCharacters( m_xConnection->getMetaData()->getExtraNameCharacters() );
+ return !( ( !sCatalog.isEmpty() && !::dbtools::isValidSQLName( sCatalog, sExtraNameCharacters ) )
+ || ( !sSchema.isEmpty() && !::dbtools::isValidSQLName( sSchema, sExtraNameCharacters ) )
+ || ( !sName.isEmpty() && !::dbtools::isValidSQLName( sName, sExtraNameCharacters ) ));
+ }
+
+ virtual void validateName_throw( const OUString& _rName ) override
+ {
+ if ( validateName( _rName ) )
+ return;
+
+ ::connectivity::SQLError aErrors;
+ aErrors.raiseException( ErrorCondition::DB_INVALID_SQL_NAME, m_xConnection, _rName );
+ }
+ };
+
+ // QueryValidityCheck
+ class QueryValidityCheck : public INameValidation
+ {
+ const Reference< XConnection > m_xConnection;
+
+ public:
+ QueryValidityCheck( const Reference< XConnection >& _rxConnection )
+ :m_xConnection( _rxConnection )
+ {
+ }
+
+ static ::connectivity::ErrorCondition validateName_getErrorCondition( std::u16string_view _rName )
+ {
+ if ( ( _rName.find( u'"' ) != std::u16string_view::npos )
+ || ( _rName.find( u'\'' ) != std::u16string_view::npos )
+ || ( _rName.find( u'`' ) != std::u16string_view::npos )
+ || ( _rName.find( u'\x0091' ) != std::u16string_view::npos )
+ || ( _rName.find( u'\x0092' ) != std::u16string_view::npos )
+ || ( _rName.find( u'\x00B4' ) != std::u16string_view::npos ) // removed unparsable chars
+ )
+ return ErrorCondition::DB_QUERY_NAME_WITH_QUOTES;
+
+ if ( _rName.find( '/') != std::u16string_view::npos )
+ return ErrorCondition::DB_OBJECT_NAME_WITH_SLASHES;
+
+ return 0;
+ }
+
+ virtual bool validateName( const OUString& _rName ) override
+ {
+ return validateName_getErrorCondition( _rName ) == 0;
+ }
+
+ virtual void validateName_throw( const OUString& _rName ) override
+ {
+ ::connectivity::ErrorCondition nErrorCondition = validateName_getErrorCondition( _rName );
+ if ( nErrorCondition != 0 )
+ {
+ ::connectivity::SQLError aErrors;
+ aErrors.raiseException( nErrorCondition, m_xConnection );
+ }
+ }
+ };
+
+ // CombinedNameCheck
+ class CombinedNameCheck : public INameValidation
+ {
+ private:
+ PNameValidation m_pPrimary;
+ PNameValidation m_pSecondary;
+
+ public:
+ CombinedNameCheck(const PNameValidation& _pPrimary, const PNameValidation& _pSecondary)
+ :m_pPrimary( _pPrimary )
+ ,m_pSecondary( _pSecondary )
+ {
+ OSL_ENSURE( m_pPrimary && m_pSecondary, "CombinedNameCheck::CombinedNameCheck: this will crash!" );
+ }
+
+ // INameValidation
+ virtual bool validateName( const OUString& _rName ) override
+ {
+ return m_pPrimary->validateName( _rName ) && m_pSecondary->validateName( _rName );
+ }
+
+ virtual void validateName_throw( const OUString& _rName ) override
+ {
+ m_pPrimary->validateName_throw( _rName );
+ m_pSecondary->validateName_throw( _rName );
+ }
+ };
+
+ // NameCheckFactory
+ class NameCheckFactory
+ {
+ public:
+ NameCheckFactory(const NameCheckFactory&) = delete;
+ const NameCheckFactory& operator=(const NameCheckFactory&) = delete;
+ /** creates an INameValidation instance which can be used to check the existence of query or table names
+
+ @param _nCommandType
+ the type of objects (CommandType::TABLE or CommandType::QUERY) of which names shall be checked for existence
+
+ @param _rxConnection
+ the connection relative to which the names are to be checked. Must be an SDB-level connection
+
+ @throws IllegalArgumentException
+ if the given connection is no SDB-level connection
+
+ @throws IllegalArgumentException
+ if the given command type is neither CommandType::TABLE or CommandType::QUERY
+ */
+ static PNameValidation createExistenceCheck(
+ sal_Int32 _nCommandType,
+ const Reference< XConnection >& _rxConnection
+ );
+
+ /** creates an INameValidation instance which can be used to check the validity of a query or table name
+
+ @param _nCommandType
+ the type of objects (CommandType::TABLE or CommandType::QUERY) of which names shall be validated
+
+ @param _rxConnection
+ the connection relative to which the names are to be checked. Must be an SDB-level connection
+
+ @throws IllegalArgumentException
+ if the given connection is no SDB-level connection
+
+ @throws IllegalArgumentException
+ if the given command type is neither CommandType::TABLE or CommandType::QUERY
+ */
+ static PNameValidation createValidityCheck(
+ const sal_Int32 _nCommandType,
+ const Reference< XConnection >& _rxConnection
+ );
+
+ private:
+ static void verifyCommandType( sal_Int32 _nCommandType );
+ };
+
+ }
+
+ void NameCheckFactory::verifyCommandType( sal_Int32 _nCommandType )
+ {
+ if ( ( _nCommandType != CommandType::TABLE )
+ && ( _nCommandType != CommandType::QUERY )
+ )
+ throw IllegalArgumentException(
+ DBA_RES( STR_INVALID_COMMAND_TYPE ),
+ nullptr,
+ 0
+ );
+ }
+
+ PNameValidation NameCheckFactory::createExistenceCheck( sal_Int32 _nCommandType, const Reference< XConnection >& _rxConnection )
+ {
+ verifyCommandType( _nCommandType );
+
+ ::dbtools::DatabaseMetaData aMeta( _rxConnection );
+
+ Reference< XNameAccess > xTables, xQueries;
+ try
+ {
+ Reference< XTablesSupplier > xSuppTables( _rxConnection, UNO_QUERY_THROW );
+ Reference< XQueriesSupplier > xQueriesSupplier( _rxConnection, UNO_QUERY_THROW );
+ xTables.set( xSuppTables->getTables(), css::uno::UNO_SET_THROW );
+ xQueries.set( xQueriesSupplier->getQueries(), css::uno::UNO_SET_THROW );
+ }
+ catch( const Exception& )
+ {
+ throw IllegalArgumentException(
+ DBA_RES( STR_CONN_WITHOUT_QUERIES_OR_TABLES ),
+ nullptr,
+ 0
+ );
+ }
+
+ PNameValidation pTableCheck = std::make_shared<PlainExistenceCheck>( _rxConnection, xTables );
+ PNameValidation pQueryCheck = std::make_shared<PlainExistenceCheck>( _rxConnection, xQueries );
+ PNameValidation pReturn;
+
+ if ( aMeta.supportsSubqueriesInFrom() )
+ pReturn = std::make_shared<CombinedNameCheck>( pTableCheck, pQueryCheck );
+ else if ( _nCommandType == CommandType::TABLE )
+ pReturn = pTableCheck;
+ else
+ pReturn = pQueryCheck;
+ return pReturn;
+ }
+
+ PNameValidation NameCheckFactory::createValidityCheck( sal_Int32 _nCommandType, const Reference< XConnection >& _rxConnection )
+ {
+ verifyCommandType( _nCommandType );
+
+ Reference< XDatabaseMetaData > xMeta;
+ try
+ {
+ xMeta.set( _rxConnection->getMetaData(), css::uno::UNO_SET_THROW );
+ }
+ catch( const Exception& )
+ {
+ throw IllegalArgumentException(
+ "The connection could not provide its database's meta data.",
+ nullptr,
+ 0
+ );
+ }
+
+ if ( _nCommandType == CommandType::TABLE )
+ return std::make_shared<TableValidityCheck>( _rxConnection );
+ return std::make_shared<QueryValidityCheck>( _rxConnection );
+ }
+
+ // ObjectNames
+ ObjectNames::ObjectNames( const Reference<XComponentContext>& _rContext, const Reference< XConnection >& _rxConnection )
+ :ConnectionDependentComponent( _rContext )
+ {
+ setWeakConnection( _rxConnection );
+ }
+
+ ObjectNames::~ObjectNames()
+ {
+ }
+
+ OUString SAL_CALL ObjectNames::suggestName( ::sal_Int32 CommandType, const OUString& BaseName )
+ {
+ EntryGuard aGuard( *this );
+
+ PNameValidation pNameCheck( NameCheckFactory::createExistenceCheck( CommandType, getConnection() ) );
+
+ OUString sBaseName( BaseName );
+ if ( sBaseName.isEmpty() )
+ {
+ if ( CommandType == CommandType::TABLE )
+ sBaseName = DBA_RES(STR_BASENAME_TABLE);
+ else
+ sBaseName = DBA_RES(STR_BASENAME_QUERY);
+ }
+ else if( CommandType == CommandType::QUERY )
+ {
+ sBaseName=sBaseName.replace('/', '_');
+ }
+
+ OUString sName( sBaseName );
+ sal_Int32 i = 1;
+ while ( !pNameCheck->validateName( sName ) )
+ {
+ sName = sBaseName + " " + OUString::number(++i);
+ }
+
+ return sName;
+ }
+
+ OUString SAL_CALL ObjectNames::convertToSQLName( const OUString& Name )
+ {
+ EntryGuard aGuard( *this );
+ Reference< XDatabaseMetaData > xMeta( getConnection()->getMetaData(), css::uno::UNO_SET_THROW );
+ return ::dbtools::convertName2SQLName( Name, xMeta->getExtraNameCharacters() );
+ }
+
+ sal_Bool SAL_CALL ObjectNames::isNameUsed( ::sal_Int32 CommandType, const OUString& Name )
+ {
+ EntryGuard aGuard( *this );
+
+ PNameValidation pNameCheck( NameCheckFactory::createExistenceCheck( CommandType, getConnection()) );
+ return !pNameCheck->validateName( Name );
+ }
+
+ sal_Bool SAL_CALL ObjectNames::isNameValid( ::sal_Int32 CommandType, const OUString& Name )
+ {
+ EntryGuard aGuard( *this );
+
+ PNameValidation pNameCheck( NameCheckFactory::createValidityCheck( CommandType, getConnection()) );
+ return pNameCheck->validateName( Name );
+ }
+
+ void SAL_CALL ObjectNames::checkNameForCreate( ::sal_Int32 CommandType, const OUString& Name )
+ {
+ EntryGuard aGuard( *this );
+
+ PNameValidation pNameCheck( NameCheckFactory::createExistenceCheck( CommandType, getConnection() ) );
+ pNameCheck->validateName_throw( Name );
+
+ pNameCheck = NameCheckFactory::createValidityCheck( CommandType, getConnection() );
+ pNameCheck->validateName_throw( Name );
+ }
+
+} // namespace sdbtools
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/sdbtools/connection/objectnames.hxx b/dbaccess/source/sdbtools/connection/objectnames.hxx
new file mode 100644
index 000000000..439db0967
--- /dev/null
+++ b/dbaccess/source/sdbtools/connection/objectnames.hxx
@@ -0,0 +1,74 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <connectiondependent.hxx>
+
+#include <com/sun/star/sdb/tools/XObjectNames.hpp>
+
+#include <cppuhelper/implbase.hxx>
+
+#include <memory>
+
+namespace sdbtools
+{
+
+ // ObjectNames
+ typedef ::cppu::WeakImplHelper< css::sdb::tools::XObjectNames
+ > ObjectNames_Base;
+ /** default implementation for XObjectNames
+ */
+ class ObjectNames :public ObjectNames_Base
+ ,public ConnectionDependentComponent
+ {
+ public:
+ /** constructs the instance
+
+ @param _rContext
+ the component's context
+ @param _rxConnection
+ the connection to work with. Will be held weak. Must not be <NULL/>.
+
+ @throws css::lang::NullPointerException
+ if _rxConnection is <NULL/>
+ */
+ ObjectNames(
+ const css::uno::Reference< css::uno::XComponentContext >& _rContext,
+ const css::uno::Reference< css::sdbc::XConnection >& _rxConnection
+ );
+
+ // XObjectNames
+ virtual OUString SAL_CALL suggestName( ::sal_Int32 CommandType, const OUString& BaseName ) override;
+ virtual OUString SAL_CALL convertToSQLName( const OUString& Name ) override;
+ virtual sal_Bool SAL_CALL isNameUsed( ::sal_Int32 CommandType, const OUString& Name ) override;
+ virtual sal_Bool SAL_CALL isNameValid( ::sal_Int32 CommandType, const OUString& Name ) override;
+ virtual void SAL_CALL checkNameForCreate( ::sal_Int32 CommandType, const OUString& Name ) override;
+
+ protected:
+ virtual ~ObjectNames() override;
+
+ private:
+ ObjectNames( const ObjectNames& ) = delete;
+ ObjectNames& operator=( const ObjectNames& ) = delete;
+ };
+
+} // namespace sdbtools
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/sdbtools/connection/tablename.cxx b/dbaccess/source/sdbtools/connection/tablename.cxx
new file mode 100644
index 000000000..132484a24
--- /dev/null
+++ b/dbaccess/source/sdbtools/connection/tablename.cxx
@@ -0,0 +1,232 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "tablename.hxx"
+#include <core_resource.hxx>
+#include <strings.hrc>
+#include <strings.hxx>
+
+#include <com/sun/star/sdb/tools/CompositionType.hpp>
+#include <com/sun/star/sdbcx/XTablesSupplier.hpp>
+
+#include <connectivity/dbtools.hxx>
+#include <tools/diagnose_ex.h>
+
+namespace sdbtools
+{
+
+ using ::com::sun::star::uno::Reference;
+ using ::com::sun::star::sdbc::XConnection;
+ using ::com::sun::star::uno::RuntimeException;
+ using ::com::sun::star::lang::IllegalArgumentException;
+ using ::com::sun::star::beans::XPropertySet;
+ using ::com::sun::star::container::NoSuchElementException;
+ using ::com::sun::star::sdbcx::XTablesSupplier;
+ using ::com::sun::star::container::XNameAccess;
+ using ::com::sun::star::uno::UNO_QUERY_THROW;
+ using ::com::sun::star::lang::WrappedTargetException;
+ using ::com::sun::star::uno::Exception;
+ using ::com::sun::star::uno::UNO_QUERY;
+ using ::com::sun::star::beans::XPropertySetInfo;
+ using ::com::sun::star::uno::XComponentContext;
+
+ namespace CompositionType = ::com::sun::star::sdb::tools::CompositionType;
+
+ using namespace ::dbtools;
+
+ // TableName
+ struct TableName_Impl
+ {
+ OUString sCatalog;
+ OUString sSchema;
+ OUString sName;
+ };
+
+ // TableName
+ TableName::TableName( const Reference<XComponentContext>& _rContext, const Reference< XConnection >& _rxConnection )
+ :ConnectionDependentComponent( _rContext )
+ ,m_pImpl( new TableName_Impl )
+ {
+ setWeakConnection( _rxConnection );
+ }
+
+ TableName::~TableName()
+ {
+ }
+
+ OUString SAL_CALL TableName::getCatalogName()
+ {
+ EntryGuard aGuard( *this );
+ return m_pImpl->sCatalog;
+ }
+
+ void SAL_CALL TableName::setCatalogName( const OUString& _catalogName )
+ {
+ EntryGuard aGuard( *this );
+ m_pImpl->sCatalog = _catalogName;
+ }
+
+ OUString SAL_CALL TableName::getSchemaName()
+ {
+ EntryGuard aGuard( *this );
+ return m_pImpl->sSchema;
+ }
+
+ void SAL_CALL TableName::setSchemaName( const OUString& _schemaName )
+ {
+ EntryGuard aGuard( *this );
+ m_pImpl->sSchema = _schemaName;
+ }
+
+ OUString SAL_CALL TableName::getTableName()
+ {
+ EntryGuard aGuard( *this );
+ return m_pImpl->sName;
+ }
+
+ void SAL_CALL TableName::setTableName( const OUString& _tableName )
+ {
+ EntryGuard aGuard( *this );
+ m_pImpl->sName = _tableName;
+ }
+
+ OUString SAL_CALL TableName::getNameForSelect()
+ {
+ EntryGuard aGuard( *this );
+ return composeTableNameForSelect( getConnection(), m_pImpl->sCatalog, m_pImpl->sSchema, m_pImpl->sName );
+ }
+
+ Reference< XPropertySet > SAL_CALL TableName::getTable()
+ {
+ EntryGuard aGuard( *this );
+
+ Reference< XTablesSupplier > xSuppTables( getConnection(), UNO_QUERY_THROW );
+ Reference< XNameAccess > xTables( xSuppTables->getTables(), css::uno::UNO_SET_THROW );
+
+ Reference< XPropertySet > xTable;
+ try
+ {
+ xTable.set( xTables->getByName( getComposedName( CompositionType::Complete, false ) ), UNO_QUERY_THROW );
+ }
+ catch( const WrappedTargetException& )
+ {
+ throw NoSuchElementException();
+ }
+ catch( const RuntimeException& ) { throw; }
+ catch( const NoSuchElementException& ) { throw; }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ throw NoSuchElementException();
+ }
+
+ return xTable;
+ }
+
+ void SAL_CALL TableName::setTable( const Reference< XPropertySet >& _table )
+ {
+ EntryGuard aGuard( *this );
+
+ Reference< XPropertySetInfo > xPSI( _table, UNO_QUERY );
+ if ( !xPSI.is()
+ || !xPSI->hasPropertyByName( PROPERTY_CATALOGNAME )
+ || !xPSI->hasPropertyByName( PROPERTY_SCHEMANAME )
+ || !xPSI->hasPropertyByName( PROPERTY_NAME )
+ )
+ throw IllegalArgumentException(
+ DBA_RES( STR_NO_TABLE_OBJECT ),
+ *this,
+ 0
+ );
+
+ try
+ {
+ OSL_VERIFY( _table->getPropertyValue( PROPERTY_CATALOGNAME ) >>= m_pImpl->sCatalog );
+ OSL_VERIFY( _table->getPropertyValue( PROPERTY_SCHEMANAME ) >>= m_pImpl->sSchema );
+ OSL_VERIFY( _table->getPropertyValue( PROPERTY_NAME ) >>= m_pImpl->sName );
+ }
+ catch( const RuntimeException& ) { throw; }
+ catch( const Exception& e )
+ {
+ throw IllegalArgumentException( e.Message, e.Context, 0 );
+ }
+ }
+
+ namespace
+ {
+ /** translates a CompositionType into an EComposeRule
+ @throws IllegalArgumentException
+ if the given value does not denote a valid CompositionType
+ */
+ EComposeRule lcl_translateCompositionType_throw( sal_Int32 _nType )
+ {
+ static const struct
+ {
+ sal_Int32 nCompositionType;
+ EComposeRule eComposeRule;
+ } TypeTable[] =
+ {
+ { CompositionType::ForTableDefinitions, EComposeRule::InTableDefinitions },
+ { CompositionType::ForIndexDefinitions, EComposeRule::InIndexDefinitions },
+ { CompositionType::ForDataManipulation, EComposeRule::InDataManipulation },
+ { CompositionType::ForProcedureCalls, EComposeRule::InProcedureCalls },
+ { CompositionType::ForPrivilegeDefinitions, EComposeRule::InPrivilegeDefinitions },
+ { CompositionType::Complete, EComposeRule::Complete }
+ };
+
+ bool found = false;
+ size_t i = 0;
+ for ( ; i < SAL_N_ELEMENTS( TypeTable ) && !found; ++i )
+ if ( TypeTable[i].nCompositionType == _nType )
+ found = true;
+ if ( !found )
+ throw IllegalArgumentException(
+ DBA_RES( STR_INVALID_COMPOSITION_TYPE ),
+ nullptr,
+ 0
+ );
+
+ return TypeTable[i].eComposeRule;
+ }
+ }
+
+ OUString SAL_CALL TableName::getComposedName( ::sal_Int32 Type, sal_Bool Quote )
+ {
+ EntryGuard aGuard( *this );
+
+ return composeTableName(
+ getConnection()->getMetaData(),
+ m_pImpl->sCatalog, m_pImpl->sSchema, m_pImpl->sName, Quote,
+ lcl_translateCompositionType_throw( Type ) );
+ }
+
+ void SAL_CALL TableName::setComposedName( const OUString& ComposedName, ::sal_Int32 Type )
+ {
+ EntryGuard aGuard( *this );
+
+ qualifiedNameComponents(
+ getConnection()->getMetaData(),
+ ComposedName,
+ m_pImpl->sCatalog, m_pImpl->sSchema, m_pImpl->sName,
+ lcl_translateCompositionType_throw( Type ) );
+ }
+
+} // namespace sdbtools
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/sdbtools/connection/tablename.hxx b/dbaccess/source/sdbtools/connection/tablename.hxx
new file mode 100644
index 000000000..3a7ece21a
--- /dev/null
+++ b/dbaccess/source/sdbtools/connection/tablename.hxx
@@ -0,0 +1,84 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <connectiondependent.hxx>
+
+#include <com/sun/star/sdb/tools/XTableName.hpp>
+
+#include <cppuhelper/implbase.hxx>
+
+#include <memory>
+
+namespace sdbtools
+{
+
+ // TableName
+ typedef ::cppu::WeakImplHelper< css::sdb::tools::XTableName
+ > TableName_Base;
+ struct TableName_Impl;
+ /** default implementation for XTableName
+ */
+ class TableName :public TableName_Base
+ ,public ConnectionDependentComponent
+ {
+ private:
+ std::unique_ptr< TableName_Impl > m_pImpl;
+
+ public:
+ /** constructs the instance
+
+ @param _rContext
+ the component's context
+ @param _rxConnection
+ the connection to work with. Will be held weak. Must not be <NULL/>.
+
+ @throws css::lang::NullPointerException
+ if _rxConnection is <NULL/>
+ */
+ TableName(
+ const css::uno::Reference< css::uno::XComponentContext >& _rContext,
+ const css::uno::Reference< css::sdbc::XConnection >& _rxConnection
+ );
+
+ // XTableName
+ virtual OUString SAL_CALL getCatalogName() override;
+ virtual void SAL_CALL setCatalogName( const OUString& _catalogname ) override;
+ virtual OUString SAL_CALL getSchemaName() override;
+ virtual void SAL_CALL setSchemaName( const OUString& _schemaname ) override;
+ virtual OUString SAL_CALL getTableName() override;
+ virtual void SAL_CALL setTableName( const OUString& _tablename ) override;
+ virtual OUString SAL_CALL getNameForSelect() override;
+ virtual css::uno::Reference< css::beans::XPropertySet > SAL_CALL getTable() override;
+ virtual void SAL_CALL setTable( const css::uno::Reference< css::beans::XPropertySet >& _table ) override;
+ virtual OUString SAL_CALL getComposedName( ::sal_Int32 Type, sal_Bool Quote ) override;
+ virtual void SAL_CALL setComposedName( const OUString& ComposedName, ::sal_Int32 Type ) override;
+
+ protected:
+ virtual ~TableName() override;
+
+ private:
+ TableName( const TableName& ) = delete;
+ TableName& operator=( const TableName& ) = delete;
+ };
+
+} // namespace sdbtools
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/sdbtools/inc/connectiondependent.hxx b/dbaccess/source/sdbtools/inc/connectiondependent.hxx
new file mode 100644
index 000000000..d315d7018
--- /dev/null
+++ b/dbaccess/source/sdbtools/inc/connectiondependent.hxx
@@ -0,0 +1,135 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <com/sun/star/sdbc/XConnection.hpp>
+#include <com/sun/star/lang/DisposedException.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+
+#include <cppuhelper/weakref.hxx>
+#include <osl/mutex.hxx>
+
+namespace sdbtools
+{
+
+ // ConnectionDependentComponent
+ class ConnectionDependentComponent
+ {
+ private:
+ mutable ::osl::Mutex m_aMutex;
+ css::uno::WeakReference< css::sdbc::XConnection >
+ m_aConnection;
+ css::uno::Reference< css::uno::XComponentContext >
+ m_aContext;
+
+ /** a hard reference to the connection we're working for
+
+ This member is only valid as long as a EntryGuard is on the stack.
+ The guard will, in its constructor, set the member, and reset it in its destructor.
+ This ensures that the connection is only held hard when it's needed, and weak otherwise.
+ */
+ css::uno::Reference< css::sdbc::XConnection >
+ m_xConnection;
+
+ protected:
+ ::osl::Mutex& getMutex() const { return m_aMutex; }
+
+ const css::uno::Reference< css::uno::XComponentContext >&
+ getContext() const { return m_aContext; }
+
+ protected:
+ class EntryGuard;
+
+ protected:
+ explicit ConnectionDependentComponent( const css::uno::Reference< css::uno::XComponentContext > & _rContext )
+ :m_aContext( _rContext )
+ {
+ }
+
+ /** sets the connection we depend on.
+
+ To be called exactly once.
+
+ @param _rxConnection
+ the connection to set
+ */
+ void setWeakConnection( const css::uno::Reference< css::sdbc::XConnection >& _rxConnection )
+ {
+ m_aConnection = _rxConnection;
+ }
+
+ const css::uno::Reference< css::sdbc::XConnection >&
+ getConnection() const { return m_xConnection; }
+
+ public:
+ struct GuardAccess;
+ friend struct GuardAccess;
+ /** helper for granting exclusive access to various other methods
+ */
+ struct GuardAccess { friend class EntryGuard; private: GuardAccess() { } };
+
+ ::osl::Mutex& getMutex( GuardAccess ) const { return m_aMutex; }
+
+ bool acquireConnection( GuardAccess )
+ {
+ m_xConnection.set(m_aConnection);
+ return m_xConnection.is();
+ }
+ void releaseConnection( GuardAccess )
+ {
+ m_xConnection.clear();
+ }
+ };
+
+ // ConnectionDependentComponent::EntryGuard
+ /** a class for guarding methods of a connection-dependent component
+
+ This class serves multiple purposes:
+ <ul><li>It ensures multi-threading safety by guarding the component's mutex
+ as long as it lives.</li>
+ <li>It ensures that the component's connection is alive. The constructor
+ throws a DisposedException if no hard reference to the connection can
+ be obtained.</li>
+ </ul>
+ */
+ class ConnectionDependentComponent::EntryGuard
+ {
+ private:
+ ::osl::MutexGuard m_aMutexGuard;
+ ConnectionDependentComponent& m_rComponent;
+
+ public:
+ explicit EntryGuard( ConnectionDependentComponent& _rComponent )
+ :m_aMutexGuard( _rComponent.getMutex( ConnectionDependentComponent::GuardAccess() ) )
+ ,m_rComponent( _rComponent )
+ {
+ if ( !m_rComponent.acquireConnection( ConnectionDependentComponent::GuardAccess() ) )
+ throw css::lang::DisposedException();
+ }
+
+ ~EntryGuard()
+ {
+ m_rComponent.releaseConnection( ConnectionDependentComponent::GuardAccess() );
+ }
+ };
+
+} // namespace sdbtools
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/sdbtools/inc/connectiontools.hxx b/dbaccess/source/sdbtools/inc/connectiontools.hxx
new file mode 100644
index 000000000..876f713af
--- /dev/null
+++ b/dbaccess/source/sdbtools/inc/connectiontools.hxx
@@ -0,0 +1,77 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include "connectiondependent.hxx"
+
+#include <com/sun/star/sdb/tools/XConnectionTools.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/lang/XInitialization.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+
+#include <cppuhelper/implbase.hxx>
+
+namespace sdbtools
+{
+
+ // ConnectionTools
+ typedef ::cppu::WeakImplHelper< css::sdb::tools::XConnectionTools
+ , css::lang::XServiceInfo
+ , css::lang::XInitialization
+ > ConnectionTools_Base;
+ /** implements the css::sdb::tools::XConnectionTools functionality
+ */
+ class ConnectionTools :public ConnectionTools_Base
+ ,public ConnectionDependentComponent
+ {
+ public:
+ /** constructs a ConnectionTools instance
+
+ @param _rxContext
+ the context of the component
+ */
+ explicit ConnectionTools( const css::uno::Reference< css::uno::XComponentContext >& _rContext );
+
+ // XConnectionTools
+ virtual css::uno::Reference< css::sdb::tools::XTableName > SAL_CALL createTableName() override;
+ virtual css::uno::Reference< css::sdb::tools::XObjectNames > SAL_CALL getObjectNames() override;
+ virtual css::uno::Reference< css::sdb::tools::XDataSourceMetaData > SAL_CALL getDataSourceMetaData() override;
+ virtual css::uno::Reference< css::container::XNameAccess > SAL_CALL getFieldsByCommandDescriptor( ::sal_Int32 commandType, const OUString& command, css::uno::Reference< css::lang::XComponent >& keepFieldsAlive ) override;
+ virtual css::uno::Reference< css::sdb::XSingleSelectQueryComposer > SAL_CALL getComposer( ::sal_Int32 commandType, const OUString& command ) override;
+
+ // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService(const OUString & ServiceName) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+
+ // XInitialization
+ virtual void SAL_CALL initialize(const css::uno::Sequence< css::uno::Any > & aArguments) override;
+
+ protected:
+ virtual ~ConnectionTools() override;
+
+ private:
+ ConnectionTools( const ConnectionTools& ) = delete;
+ ConnectionTools& operator=( const ConnectionTools& ) = delete;
+ };
+
+} // namespace sdbtools
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/app/AppController.cxx b/dbaccess/source/ui/app/AppController.cxx
new file mode 100644
index 000000000..06508d5c2
--- /dev/null
+++ b/dbaccess/source/ui/app/AppController.cxx
@@ -0,0 +1,2834 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <memory>
+#include "AppController.hxx"
+#include <core_resource.hxx>
+#include <dbexchange.hxx>
+#include <strings.hxx>
+#include <advancedsettingsdlg.hxx>
+#include "subcomponentmanager.hxx"
+
+#include <com/sun/star/beans/NamedValue.hpp>
+#include <com/sun/star/container/XChild.hpp>
+#include <com/sun/star/container/XContainer.hpp>
+#include <com/sun/star/container/XContentEnumerationAccess.hpp>
+#include <com/sun/star/container/XHierarchicalNameAccess.hpp>
+#include <com/sun/star/container/XHierarchicalNameContainer.hpp>
+#include <com/sun/star/frame/XStorable.hpp>
+#include <com/sun/star/sdb/CommandType.hpp>
+#include <com/sun/star/sdb/ErrorMessageDialog.hpp>
+#include <com/sun/star/sdb/XOfficeDatabaseDocument.hpp>
+#include <com/sun/star/sdbc/SQLException.hpp>
+#include <com/sun/star/sdbc/SQLWarning.hpp>
+#include <com/sun/star/sdbc/XDataSource.hpp>
+#include <com/sun/star/sdbcx/XAlterView.hpp>
+#include <com/sun/star/sdbcx/XAppend.hpp>
+#include <com/sun/star/sdbcx/XRename.hpp>
+#include <com/sun/star/sdbcx/XTablesSupplier.hpp>
+#include <com/sun/star/sdbcx/XViewsSupplier.hpp>
+#include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
+#include <com/sun/star/util/XFlushable.hpp>
+#include <com/sun/star/util/XModifiable.hpp>
+#include <com/sun/star/util/XModifyBroadcaster.hpp>
+#include <com/sun/star/util/XURLTransformer.hpp>
+#include <com/sun/star/ui/dialogs/XExecutableDialog.hpp>
+#include <com/sun/star/document/XEmbeddedScripts.hpp>
+#include <com/sun/star/frame/XModel2.hpp>
+#include <com/sun/star/task/XInteractionHandler.hpp>
+#include <com/sun/star/sdb/application/DatabaseObject.hpp>
+#include <com/sun/star/sdb/application/DatabaseObjectContainer.hpp>
+#include <com/sun/star/document/XDocumentEventBroadcaster.hpp>
+#include <tools/diagnose_ex.h>
+#include <tools/urlobj.hxx>
+#include <osl/diagnose.h>
+
+#include <svl/filenotation.hxx>
+#include <vcl/transfer.hxx>
+#include <svtools/cliplistener.hxx>
+
+#include <comphelper/interfacecontainer3.hxx>
+#include <comphelper/sequence.hxx>
+#include <comphelper/uno3.hxx>
+#include <comphelper/types.hxx>
+#include <comphelper/interaction.hxx>
+
+#include <vcl/svapp.hxx>
+#include <vcl/weld.hxx>
+
+#include <unotools/closeveto.hxx>
+#include <unotools/pathoptions.hxx>
+#include <unotools/moduleoptions.hxx>
+#include <unotools/historyoptions.hxx>
+
+#include <sfx2/mailmodelapi.hxx>
+#include <sfx2/filedlghelper.hxx>
+#include <sfx2/docfilt.hxx>
+#include <sfx2/QuerySaveDocument.hxx>
+
+#include <cppuhelper/exc_hlp.hxx>
+
+#include <connectivity/dbtools.hxx>
+#include <connectivity/dbexception.hxx>
+
+#include <svx/dbaexchange.hxx>
+#include <svx/dbaobjectex.hxx>
+#include <svx/svxdlg.hxx>
+
+#include <osl/mutex.hxx>
+#include "AppView.hxx"
+#include <browserids.hxx>
+#include <strings.hrc>
+#include <defaultobjectnamecheck.hxx>
+#include <databaseobjectview.hxx>
+#include <dbtreelistbox.hxx>
+#include "AppDetailView.hxx"
+#include <linkeddocuments.hxx>
+#include <UITools.hxx>
+#include <dsntypes.hxx>
+#include <dlgsave.hxx>
+#include <dbaccess_slotid.hrc>
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+org_openoffice_comp_dbu_OApplicationController_get_implementation(
+ css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const& )
+{
+ return cppu::acquire(new ::dbaui::OApplicationController(context));
+}
+
+namespace dbaui
+{
+using namespace ::dbtools;
+using namespace ::svx;
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::ucb;
+using namespace ::com::sun::star::view;
+using namespace ::com::sun::star::util;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::frame;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::sdb;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::sdbcx;
+using namespace ::com::sun::star::datatransfer;
+using namespace ::com::sun::star::ui::dialogs;
+using namespace ::com::sun::star::task;
+using ::com::sun::star::document::XEmbeddedScripts;
+using ::com::sun::star::document::XDocumentEventBroadcaster;
+using ::com::sun::star::sdb::application::NamedDatabaseObject;
+
+namespace DatabaseObject = ::com::sun::star::sdb::application::DatabaseObject;
+namespace DatabaseObjectContainer = ::com::sun::star::sdb::application::DatabaseObjectContainer;
+
+OUString SAL_CALL OApplicationController::getImplementationName()
+{
+ return SERVICE_SDB_APPLICATIONCONTROLLER;
+}
+
+Sequence< OUString> SAL_CALL OApplicationController::getSupportedServiceNames()
+{
+ return { "com.sun.star.sdb.application.DefaultViewController" };
+}
+
+namespace {
+
+class SelectionGuard;
+
+}
+
+// OApplicationController
+class SelectionNotifier
+{
+private:
+ ::comphelper::OInterfaceContainerHelper3<XSelectionChangeListener> m_aSelectionListeners;
+ ::cppu::OWeakObject& m_rContext;
+ sal_Int32 m_nSelectionNestingLevel;
+
+public:
+ SelectionNotifier( ::osl::Mutex& _rMutex, ::cppu::OWeakObject& _rContext )
+ :m_aSelectionListeners( _rMutex )
+ ,m_rContext( _rContext )
+ ,m_nSelectionNestingLevel( 0 )
+ {
+ }
+
+ SelectionNotifier(const SelectionNotifier&) = delete;
+ const SelectionNotifier& operator=(const SelectionNotifier&) = delete;
+
+ void addListener( const Reference< XSelectionChangeListener >& Listener )
+ {
+ m_aSelectionListeners.addInterface( Listener );
+ }
+
+ void removeListener( const Reference< XSelectionChangeListener >& Listener )
+ {
+ m_aSelectionListeners.removeInterface( Listener );
+ }
+
+ void disposing()
+ {
+ EventObject aEvent( m_rContext );
+ m_aSelectionListeners.disposeAndClear( aEvent );
+ }
+
+ struct SelectionGuardAccess { friend SelectionGuard; private: SelectionGuardAccess() { } };
+
+ /** enters a block which modifies the selection of our owner.
+
+ Can be called multiple times, the only important thing is to call leaveSelection
+ equally often.
+ */
+ void enterSelection( SelectionGuardAccess )
+ {
+ ++m_nSelectionNestingLevel;
+ }
+
+ /** leaves a block which modifies the selection of our owner
+
+ Must be paired with enterSelection calls.
+
+ When the last block is left, i.e. the last leaveSelection call is made on the current stack,
+ then our SelectionChangeListeners are notified
+ */
+ void leaveSelection( SelectionGuardAccess )
+ {
+ if ( --m_nSelectionNestingLevel == 0 )
+ {
+ EventObject aEvent( m_rContext );
+ m_aSelectionListeners.notifyEach( &XSelectionChangeListener::selectionChanged, aEvent );
+ }
+ }
+};
+
+namespace {
+
+class SelectionGuard
+{
+public:
+ explicit SelectionGuard( SelectionNotifier& _rNotifier )
+ :m_rNotifier( _rNotifier )
+ {
+ m_rNotifier.enterSelection( SelectionNotifier::SelectionGuardAccess() );
+ }
+
+ ~SelectionGuard()
+ {
+ m_rNotifier.leaveSelection( SelectionNotifier::SelectionGuardAccess() );
+ }
+
+ SelectionGuard(const SelectionGuard&) = delete;
+ const SelectionGuard& operator=(const SelectionGuard&) = delete;
+
+private:
+ SelectionNotifier& m_rNotifier;
+};
+
+}
+
+// OApplicationController
+OApplicationController::OApplicationController(const Reference< XComponentContext >& _rxORB)
+ :OGenericUnoController( _rxORB )
+ ,m_aContextMenuInterceptors( getMutex() )
+ ,m_pSubComponentManager( new SubComponentManager( *this, getSharedMutex() ) )
+ ,m_aTypeCollection( _rxORB )
+ ,m_aTableCopyHelper(this)
+ ,m_nAsyncDrop(nullptr)
+ ,m_aSelectContainerEvent( LINK( this, OApplicationController, OnSelectContainer ) )
+ ,m_ePreviewMode(E_PREVIEWNONE)
+ ,m_eCurrentType(E_NONE)
+ ,m_bNeedToReconnect(false)
+ ,m_bSuspended( false )
+ ,m_pSelectionNotifier( new SelectionNotifier( getMutex(), *this ) )
+{
+}
+
+OApplicationController::~OApplicationController()
+{
+ if ( !rBHelper.bDisposed && !rBHelper.bInDispose )
+ {
+ OSL_FAIL("Please check who doesn't dispose this component!");
+ // increment ref count to prevent double call of Dtor
+ osl_atomic_increment( &m_refCount );
+ dispose();
+ }
+ clearView();
+}
+
+IMPLEMENT_FORWARD_XTYPEPROVIDER2(OApplicationController,OGenericUnoController,OApplicationController_Base)
+IMPLEMENT_FORWARD_XINTERFACE2(OApplicationController,OGenericUnoController,OApplicationController_Base)
+void OApplicationController::disconnect()
+{
+ if ( m_xDataSourceConnection.is() )
+ stopConnectionListening( m_xDataSourceConnection );
+
+ try
+ {
+ // temporary (hopefully!) hack for #i55274#
+ Reference< XFlushable > xFlush( m_xDataSourceConnection, UNO_QUERY );
+ if ( xFlush.is() && m_xMetaData.is() && !m_xMetaData->isReadOnly() )
+ xFlush->flush();
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+
+ m_xDataSourceConnection.clear();
+ m_xMetaData.clear();
+
+ InvalidateAll();
+}
+
+void SAL_CALL OApplicationController::disposing()
+{
+ for( const auto& rContainerListener : m_aCurrentContainers )
+ {
+ if( rContainerListener.is() )
+ {
+ rContainerListener->removeContainerListener( this );
+ }
+ }
+
+ m_aCurrentContainers.clear();
+ m_pSubComponentManager->disposing();
+ m_pSelectionNotifier->disposing();
+
+ if ( getView() )
+ {
+ getContainer()->showPreview(nullptr);
+ m_pClipboardNotifier->ClearCallbackLink();
+ m_pClipboardNotifier->RemoveListener( getView() );
+ m_pClipboardNotifier.clear();
+ }
+
+ disconnect();
+ try
+ {
+ Reference < XFrame > xFrame;
+ attachFrame( xFrame );
+
+ if ( m_xDataSource.is() )
+ {
+ m_xDataSource->removePropertyChangeListener(OUString(), this);
+ m_xDataSource->removePropertyChangeListener(PROPERTY_INFO, this);
+ m_xDataSource->removePropertyChangeListener(PROPERTY_URL, this);
+ m_xDataSource->removePropertyChangeListener(PROPERTY_ISPASSWORDREQUIRED, this);
+ m_xDataSource->removePropertyChangeListener(PROPERTY_LAYOUTINFORMATION, this);
+ m_xDataSource->removePropertyChangeListener(PROPERTY_SUPPRESSVERSIONCL, this);
+ m_xDataSource->removePropertyChangeListener(PROPERTY_TABLEFILTER, this);
+ m_xDataSource->removePropertyChangeListener(PROPERTY_TABLETYPEFILTER, this);
+ m_xDataSource->removePropertyChangeListener(PROPERTY_USER, this);
+ m_xDataSource = nullptr;
+ }
+
+ Reference< XModifyBroadcaster > xBroadcaster( m_xModel, UNO_QUERY );
+ if ( xBroadcaster.is() )
+ xBroadcaster->removeModifyListener(static_cast<XModifyListener*>(this));
+
+ if ( m_xModel.is() )
+ {
+ OUString sUrl = m_xModel->getURL();
+ if ( !sUrl.isEmpty() )
+ {
+ if ( ::comphelper::NamedValueCollection::getOrDefault( m_xModel->getArgs(), u"PickListEntry", true ) )
+ {
+ OUString aFilter;
+ INetURLObject aURL( m_xModel->getURL() );
+ std::shared_ptr<const SfxFilter> pFilter = getStandardDatabaseFilter();
+ if ( pFilter )
+ aFilter = pFilter->GetFilterName();
+
+ // add to svtool history options
+ SvtHistoryOptions::AppendItem( EHistoryType::PickList,
+ aURL.GetURLNoPass( INetURLObject::DecodeMechanism::NONE ),
+ aFilter,
+ getStrippedDatabaseName(),
+ std::nullopt, std::nullopt);
+
+ // add to recent document list
+ if ( aURL.GetProtocol() == INetProtocol::File )
+ Application::AddToRecentDocumentList( aURL.GetURLNoPass( INetURLObject::DecodeMechanism::NONE ),
+ pFilter ? pFilter->GetMimeType() : OUString(),
+ pFilter ? pFilter->GetServiceName() : OUString() );
+ }
+ }
+
+ m_xModel->disconnectController( this );
+
+ m_xModel.clear();
+ }
+ }
+ catch(const Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+
+ clearView();
+ OGenericUnoController::disposing(); // here the m_refCount must be equal 5
+}
+
+bool OApplicationController::Construct(vcl::Window* _pParent)
+{
+ setView( VclPtr<OApplicationView>::Create( _pParent, getORB(), *this, m_ePreviewMode ) );
+
+ // late construction
+ bool bSuccess = false;
+ try
+ {
+ getContainer()->Construct();
+ bSuccess = true;
+ }
+ catch(const SQLException&)
+ {
+ }
+ catch(const Exception&)
+ {
+ OSL_FAIL("OApplicationController::Construct : the construction of UnoDataBrowserView failed !");
+ }
+
+ if ( !bSuccess )
+ {
+ clearView();
+ return false;
+ }
+
+ // now that we have a view we can create the clipboard listener
+ m_aSystemClipboard = TransferableDataHelper::CreateFromSystemClipboard( getView() );
+ m_aSystemClipboard.StartClipboardListening( );
+
+ m_pClipboardNotifier = new TransferableClipboardListener( LINK( this, OApplicationController, OnClipboardChanged ) );
+ m_pClipboardNotifier->AddListener( getView() );
+
+ OGenericUnoController::Construct( _pParent );
+ getView()->Show();
+
+ return true;
+}
+
+void SAL_CALL OApplicationController::disposing(const EventObject& _rSource)
+{
+ ::osl::MutexGuard aGuard( getMutex() );
+ Reference<XConnection> xCon(_rSource.Source, UNO_QUERY);
+ if ( xCon.is() )
+ {
+ OSL_ENSURE( m_xDataSourceConnection == xCon,
+ "OApplicationController::disposing: which connection does this come from?" );
+
+ if ( getContainer() && getContainer()->getElementType() == E_TABLE )
+ getContainer()->clearPages();
+ if ( m_xDataSourceConnection == xCon )
+ {
+ m_xMetaData.clear();
+ m_xDataSourceConnection.clear();
+ }
+ }
+ else if ( _rSource.Source == m_xModel )
+ {
+ m_xModel.clear();
+ }
+ else if ( _rSource.Source == m_xDataSource )
+ {
+ m_xDataSource = nullptr;
+ }
+ else
+ {
+ Reference<XContainer> xContainer( _rSource.Source, UNO_QUERY );
+ if ( xContainer.is() )
+ {
+ TContainerVector::iterator aFind = std::find(m_aCurrentContainers.begin(),m_aCurrentContainers.end(),xContainer);
+ if ( aFind != m_aCurrentContainers.end() )
+ m_aCurrentContainers.erase(aFind);
+ }
+ OGenericUnoController::disposing( _rSource );
+ }
+}
+
+sal_Bool SAL_CALL OApplicationController::suspend(sal_Bool bSuspend)
+{
+ // notify the OnPrepareViewClosing event (before locking any mutex)
+ Reference< XDocumentEventBroadcaster > xBroadcaster( m_xModel, UNO_QUERY );
+ if ( xBroadcaster.is() )
+ {
+ xBroadcaster->notifyDocumentEvent(
+ "OnPrepareViewClosing",
+ this,
+ Any()
+ );
+ }
+
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( getMutex() );
+
+ if ( getView() && getView()->IsInModalMode() )
+ return false;
+
+ bool bCanSuspend = true;
+
+ if ( m_bSuspended != bool(bSuspend) )
+ {
+ if ( bSuspend && !closeSubComponents() )
+ return false;
+
+ Reference<XModifiable> xModi(m_xModel,UNO_QUERY);
+ Reference<XStorable> xStor(getModel(),UNO_QUERY);
+
+ if ( bSuspend
+ && xStor.is()
+ && !xStor->isReadonly()
+ && ( xModi.is()
+ && xModi->isModified()
+ )
+ )
+ {
+ switch (ExecuteQuerySaveDocument(getFrameWeld(), getStrippedDatabaseName()))
+ {
+ case RET_YES:
+ Execute(ID_BROWSER_SAVEDOC,Sequence<PropertyValue>());
+ bCanSuspend = !xModi->isModified();
+ // when we save the document this must be false else some press cancel
+ break;
+ case RET_CANCEL:
+ bCanSuspend = false;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ if ( bCanSuspend )
+ m_bSuspended = bSuspend;
+
+ return bCanSuspend;
+}
+
+FeatureState OApplicationController::GetState(sal_uInt16 _nId) const
+{
+ FeatureState aReturn;
+ aReturn.bEnabled = false;
+ // check this first
+ if ( !getContainer() || m_bReadOnly )
+ return aReturn;
+
+ try
+ {
+ switch (_nId)
+ {
+ case SID_NEWDOCDIRECT:
+ aReturn.bEnabled = true;
+ aReturn.sTitle = "private:factory/sdatabase";
+ break;
+ case SID_OPENURL:
+ aReturn.bEnabled = true;
+ if ( m_xModel.is() )
+ aReturn.sTitle = m_xModel->getURL();
+ break;
+ case ID_BROWSER_COPY:
+ {
+ sal_Int32 nCount = getContainer()->getSelectionCount();
+ aReturn.bEnabled = nCount >= 1;
+ if ( aReturn.bEnabled && nCount == 1 && getContainer()->getElementType() == E_TABLE )
+ aReturn.bEnabled = getContainer()->isALeafSelected();
+ }
+ break;
+ case ID_BROWSER_CUT:
+ aReturn.bEnabled = !isDataSourceReadOnly() && getContainer()->getSelectionCount() >= 1;
+ aReturn.bEnabled = aReturn.bEnabled && (getContainer()->getElementType() != E_TABLE || getContainer()->isCutAllowed());
+ break;
+ case ID_BROWSER_PASTE:
+ switch( getContainer()->getElementType() )
+ {
+ case E_TABLE:
+ aReturn.bEnabled = !isDataSourceReadOnly() && !isConnectionReadOnly() && isTableFormat();
+ break;
+ case E_QUERY:
+ aReturn.bEnabled = !isDataSourceReadOnly() && getViewClipboard().HasFormat(SotClipboardFormatId::DBACCESS_QUERY);
+ break;
+ default:
+ aReturn.bEnabled = !isDataSourceReadOnly() && OComponentTransferable::canExtractComponentDescriptor(getViewClipboard().GetDataFlavorExVector(),getContainer()->getElementType() == E_FORM);
+ }
+ break;
+ case SID_DB_APP_PASTE_SPECIAL:
+ aReturn.bEnabled = getContainer()->getElementType() == E_TABLE && !isDataSourceReadOnly() && !isConnectionReadOnly() && isTableFormat();
+ break;
+ case SID_OPENDOC:
+ aReturn.bEnabled = true;
+ break;
+ case ID_BROWSER_SAVEDOC:
+ aReturn.bEnabled = !isDataSourceReadOnly();
+ break;
+ case ID_BROWSER_SAVEASDOC:
+ aReturn.bEnabled = true;
+ break;
+ case ID_BROWSER_SORTUP:
+ aReturn.bEnabled = getContainer()->isFilled() && getContainer()->getElementCount();
+ aReturn.bChecked = aReturn.bEnabled && getContainer()->isSortUp();
+ break;
+ case ID_BROWSER_SORTDOWN:
+ aReturn.bEnabled = getContainer()->isFilled() && getContainer()->getElementCount();
+ aReturn.bChecked = aReturn.bEnabled && !getContainer()->isSortUp();
+ break;
+
+ case SID_NEWDOC:
+ case SID_APP_NEW_FORM:
+ case ID_DOCUMENT_CREATE_REPWIZ:
+ aReturn.bEnabled = !isDataSourceReadOnly() && SvtModuleOptions().IsModuleInstalled(SvtModuleOptions::EModule::WRITER);
+ break;
+ case SID_APP_NEW_REPORT:
+ aReturn.bEnabled = !isDataSourceReadOnly()
+ && SvtModuleOptions().IsModuleInstalled(SvtModuleOptions::EModule::WRITER);
+ if ( aReturn.bEnabled )
+ {
+ Reference< XContentEnumerationAccess > xEnumAccess(m_xContext->getServiceManager(), UNO_QUERY);
+ aReturn.bEnabled = xEnumAccess.is();
+ if ( aReturn.bEnabled )
+ {
+ const OUString sReportEngineServiceName = ::dbtools::getDefaultReportEngineServiceName(m_xContext);
+ aReturn.bEnabled = !sReportEngineServiceName.isEmpty();
+ if ( aReturn.bEnabled )
+ {
+ const Reference< XEnumeration > xEnumDrivers = xEnumAccess->createContentEnumeration(sReportEngineServiceName);
+ aReturn.bEnabled = xEnumDrivers.is() && xEnumDrivers->hasMoreElements();
+ }
+ }
+ }
+ break;
+ case SID_DB_APP_VIEW_TABLES:
+ aReturn.bEnabled = true;
+ aReturn.bChecked = getContainer()->getElementType() == E_TABLE;
+ break;
+ case SID_DB_APP_VIEW_QUERIES:
+ aReturn.bEnabled = true;
+ aReturn.bChecked = getContainer()->getElementType() == E_QUERY;
+ break;
+ case SID_DB_APP_VIEW_FORMS:
+ aReturn.bEnabled = true;
+ aReturn.bChecked = getContainer()->getElementType() == E_FORM;
+ break;
+ case SID_DB_APP_VIEW_REPORTS:
+ aReturn.bEnabled = true;
+ aReturn.bChecked = getContainer()->getElementType() == E_REPORT;
+ break;
+ case ID_NEW_QUERY_DESIGN:
+ case ID_NEW_QUERY_SQL:
+ case ID_APP_NEW_QUERY_AUTO_PILOT:
+ case SID_DB_FORM_NEW_PILOT:
+ aReturn.bEnabled = !isDataSourceReadOnly();
+ break;
+ case ID_NEW_VIEW_DESIGN:
+ case SID_DB_NEW_VIEW_SQL:
+ case ID_NEW_VIEW_DESIGN_AUTO_PILOT:
+ aReturn.bEnabled = !isDataSourceReadOnly() && !isConnectionReadOnly();
+ if ( aReturn.bEnabled )
+ {
+ Reference<XViewsSupplier> xViewsSup( getConnection(), UNO_QUERY );
+ aReturn.bEnabled = xViewsSup.is();
+ }
+ break;
+ case ID_NEW_TABLE_DESIGN:
+ case ID_NEW_TABLE_DESIGN_AUTO_PILOT:
+ aReturn.bEnabled = !isDataSourceReadOnly() && !isConnectionReadOnly();
+ break;
+ case ID_DIRECT_SQL:
+ aReturn.bEnabled = true;
+ break;
+ case SID_APP_NEW_FOLDER:
+ aReturn.bEnabled = !isDataSourceReadOnly() && getContainer()->getSelectionCount() <= 1;
+ if ( aReturn.bEnabled )
+ {
+ const ElementType eType = getContainer()->getElementType();
+ aReturn.bEnabled = eType == E_REPORT || eType == E_FORM;
+ }
+ break;
+ case SID_FORM_CREATE_REPWIZ_PRE_SEL:
+ case SID_REPORT_CREATE_REPWIZ_PRE_SEL:
+ case SID_APP_NEW_REPORT_PRE_SEL:
+ aReturn.bEnabled = !isDataSourceReadOnly()
+ && SvtModuleOptions().IsModuleInstalled(SvtModuleOptions::EModule::WRITER)
+ && getContainer()->isALeafSelected();
+ if ( aReturn.bEnabled )
+ {
+ ElementType eType = getContainer()->getElementType();
+ aReturn.bEnabled = eType == E_QUERY || eType == E_TABLE;
+ if ( aReturn.bEnabled && SID_APP_NEW_REPORT_PRE_SEL == _nId )
+ {
+ Reference< XContentEnumerationAccess > xEnumAccess(m_xContext->getServiceManager(), UNO_QUERY);
+ aReturn.bEnabled = xEnumAccess.is();
+ if ( aReturn.bEnabled )
+ {
+ static constexpr OUStringLiteral s_sReportDesign = u"org.libreoffice.report.pentaho.SOReportJobFactory";
+ Reference< XEnumeration > xEnumDrivers = xEnumAccess->createContentEnumeration(s_sReportDesign);
+ aReturn.bEnabled = xEnumDrivers.is() && xEnumDrivers->hasMoreElements();
+ }
+ }
+ }
+ break;
+ case SID_DB_APP_DELETE:
+ case SID_DB_APP_RENAME:
+ aReturn.bEnabled = isRenameDeleteAllowed(getContainer()->getElementType(), _nId == SID_DB_APP_DELETE);
+ break;
+ case SID_DB_APP_TABLE_DELETE:
+ case SID_DB_APP_TABLE_RENAME:
+ aReturn.bEnabled = isRenameDeleteAllowed(E_TABLE, _nId == SID_DB_APP_TABLE_DELETE);
+ break;
+ case SID_DB_APP_QUERY_DELETE:
+ case SID_DB_APP_QUERY_RENAME:
+ aReturn.bEnabled = isRenameDeleteAllowed(E_QUERY, _nId == SID_DB_APP_QUERY_DELETE);
+ break;
+ case SID_DB_APP_FORM_DELETE:
+ case SID_DB_APP_FORM_RENAME:
+ aReturn.bEnabled = isRenameDeleteAllowed(E_FORM, _nId == SID_DB_APP_FORM_DELETE);
+ break;
+ case SID_DB_APP_REPORT_DELETE:
+ case SID_DB_APP_REPORT_RENAME:
+ aReturn.bEnabled = isRenameDeleteAllowed(E_REPORT, _nId == SID_DB_APP_REPORT_DELETE);
+ break;
+
+ case SID_SELECTALL:
+ aReturn.bEnabled = getContainer()->getElementCount() > 0 && getContainer()->getSelectionCount() != getContainer()->getElementCount();
+ break;
+ case SID_DB_APP_EDIT:
+ case SID_DB_APP_TABLE_EDIT:
+ case SID_DB_APP_QUERY_EDIT:
+ case SID_DB_APP_FORM_EDIT:
+ case SID_DB_APP_REPORT_EDIT:
+ aReturn.bEnabled = !isDataSourceReadOnly() && getContainer()->getSelectionCount() > 0
+ && getContainer()->isALeafSelected();
+ break;
+ case SID_DB_APP_EDIT_SQL_VIEW:
+ if ( isDataSourceReadOnly() )
+ aReturn.bEnabled = false;
+ else
+ {
+ switch ( getContainer()->getElementType() )
+ {
+ case E_QUERY:
+ aReturn.bEnabled = ( getContainer()->getSelectionCount() > 0 )
+ && ( getContainer()->isALeafSelected() );
+ break;
+ case E_TABLE:
+ aReturn.bEnabled = false;
+ // there's one exception: views which support altering their underlying
+ // command can be edited in SQL view, too
+ if ( ( getContainer()->getSelectionCount() > 0 )
+ && ( getContainer()->isALeafSelected() )
+ )
+ {
+ std::vector< OUString > aSelected;
+ getSelectionElementNames( aSelected );
+ bool bAlterableViews = true;
+ for (auto const& selectedName : aSelected)
+ {
+ bAlterableViews &= impl_isAlterableView_nothrow(selectedName);
+ if (!bAlterableViews)
+ break;
+ }
+ aReturn.bEnabled = bAlterableViews;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ break;
+ case SID_DB_APP_OPEN:
+ case SID_DB_APP_TABLE_OPEN:
+ case SID_DB_APP_QUERY_OPEN:
+ case SID_DB_APP_FORM_OPEN:
+ case SID_DB_APP_REPORT_OPEN:
+ aReturn.bEnabled = getContainer()->getSelectionCount() > 0 && getContainer()->isALeafSelected();
+ break;
+ case SID_DB_APP_DSUSERADMIN:
+ aReturn.bEnabled = !dbaccess::ODsnTypeCollection::isEmbeddedDatabase(::comphelper::getString(m_xDataSource->getPropertyValue(PROPERTY_URL)));
+ break;
+ case SID_DB_APP_DSRELDESIGN:
+ aReturn.bEnabled = true;
+ break;
+ case SID_DB_APP_TABLEFILTER:
+ aReturn.bEnabled = !isDataSourceReadOnly();
+ break;
+ case SID_DB_APP_REFRESH_TABLES:
+ aReturn.bEnabled = getContainer()->getElementType() == E_TABLE && isConnected();
+ break;
+ case SID_DB_APP_DSPROPS:
+ aReturn.bEnabled = m_xDataSource.is() && dbaccess::ODsnTypeCollection::isShowPropertiesEnabled(::comphelper::getString(m_xDataSource->getPropertyValue(PROPERTY_URL)));
+ break;
+ case SID_DB_APP_DSCONNECTION_TYPE:
+ aReturn.bEnabled = !isDataSourceReadOnly() && m_xDataSource.is() && !dbaccess::ODsnTypeCollection::isEmbeddedDatabase(::comphelper::getString(m_xDataSource->getPropertyValue(PROPERTY_URL)));
+ break;
+ case SID_DB_APP_DSADVANCED_SETTINGS:
+ aReturn.bEnabled = m_xDataSource.is() && AdvancedSettingsDialog::doesHaveAnyAdvancedSettings( m_aTypeCollection.getType(::comphelper::getString( m_xDataSource->getPropertyValue( PROPERTY_URL ) )) );
+ break;
+ case SID_DB_APP_CONVERTTOVIEW:
+ aReturn.bEnabled = !isDataSourceReadOnly();
+ if ( aReturn.bEnabled )
+ {
+ ElementType eType = getContainer()->getElementType();
+ aReturn.bEnabled = eType == E_QUERY && getContainer()->getSelectionCount() > 0;
+ if ( aReturn.bEnabled )
+ {
+ Reference<XViewsSupplier> xViewSup( getConnection(), UNO_QUERY );
+ aReturn.bEnabled = xViewSup.is() && Reference<XAppend>(xViewSup->getViews(),UNO_QUERY).is();
+ }
+ }
+ break;
+ case SID_DB_APP_DISABLE_PREVIEW:
+ aReturn.bEnabled = true;
+ aReturn.bChecked = getContainer()->getPreviewMode() == E_PREVIEWNONE;
+ break;
+ case SID_DB_APP_VIEW_DOCINFO_PREVIEW:
+ {
+ ElementType eType = getContainer()->getElementType();
+ aReturn.bEnabled = (E_REPORT == eType || E_FORM == eType);
+ aReturn.bChecked = getContainer()->getPreviewMode() == E_DOCUMENTINFO;
+ }
+ break;
+ case SID_DB_APP_VIEW_DOC_PREVIEW:
+ aReturn.bEnabled = true;
+ aReturn.bChecked = getContainer()->getPreviewMode() == E_DOCUMENT;
+ break;
+ case ID_BROWSER_UNDO:
+ aReturn.bEnabled = false;
+ break;
+ case SID_MAIL_SENDDOC:
+ aReturn.bEnabled = true;
+ break;
+ case SID_DB_APP_SENDREPORTASMAIL:
+ {
+ ElementType eType = getContainer()->getElementType();
+ aReturn.bEnabled = E_REPORT == eType && getContainer()->getSelectionCount() > 0 && getContainer()->isALeafSelected();
+ }
+ break;
+ case SID_DB_APP_SENDREPORTTOWRITER:
+ case SID_DB_APP_DBADMIN:
+ aReturn.bEnabled = false;
+ break;
+ case SID_DB_APP_STATUS_TYPE:
+ aReturn.bEnabled = m_xDataSource.is();
+ if ( aReturn.bEnabled )
+ {
+ OUString sURL;
+ m_xDataSource->getPropertyValue(PROPERTY_URL) >>= sURL;
+ OUString sDSTypeName;
+ if ( dbaccess::ODsnTypeCollection::isEmbeddedDatabase( sURL ) )
+ {
+ sDSTypeName = DBA_RES(RID_STR_EMBEDDED_DATABASE);
+ }
+ else
+ {
+ sDSTypeName = m_aTypeCollection.getTypeDisplayName(sURL);
+ }
+ aReturn.sTitle = sDSTypeName;
+ }
+ break;
+ case SID_DB_APP_STATUS_DBNAME:
+ aReturn.bEnabled = m_xDataSource.is();
+ if ( aReturn.bEnabled )
+ {
+ OUString sURL;
+ m_xDataSource->getPropertyValue(PROPERTY_URL) >>= sURL;
+ OUString sDatabaseName;
+ OUString sHostName;
+ sal_Int32 nPortNumber( -1 );
+
+ m_aTypeCollection.extractHostNamePort( sURL, sDatabaseName, sHostName, nPortNumber );
+
+ if ( sDatabaseName.isEmpty() )
+ sDatabaseName = m_aTypeCollection.cutPrefix( sURL );
+ if ( m_aTypeCollection.isFileSystemBased(sURL) )
+ {
+ sDatabaseName = SvtPathOptions().SubstituteVariable( sDatabaseName );
+ if ( !sDatabaseName.isEmpty() )
+ {
+ ::svt::OFileNotation aFileNotation(sDatabaseName);
+ // set this decoded URL as text
+ sDatabaseName = aFileNotation.get(::svt::OFileNotation::N_SYSTEM);
+ }
+ }
+
+ if ( sDatabaseName.isEmpty() )
+ sDatabaseName = m_aTypeCollection.getTypeDisplayName( sURL );
+
+ aReturn.sTitle = sDatabaseName;
+ }
+ break;
+ case SID_DB_APP_STATUS_USERNAME:
+ aReturn.bEnabled = m_xDataSource.is();
+ if ( aReturn.bEnabled )
+ m_xDataSource->getPropertyValue( PROPERTY_USER ) >>= aReturn.sTitle;
+ break;
+ case SID_DB_APP_STATUS_HOSTNAME:
+ aReturn.bEnabled = m_xDataSource.is();
+ if ( aReturn.bEnabled )
+ {
+ OUString sURL;
+ m_xDataSource->getPropertyValue( PROPERTY_URL ) >>= sURL;
+
+ OUString sHostName, sDatabaseName;
+ sal_Int32 nPortNumber = -1;
+ m_aTypeCollection.extractHostNamePort( sURL, sDatabaseName, sHostName, nPortNumber );
+ aReturn.sTitle = sHostName;
+ }
+ break;
+ default:
+ aReturn = OGenericUnoController::GetState(_nId);
+ }
+ }
+ catch(const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ return aReturn;
+}
+
+namespace
+{
+ bool lcl_handleException_nothrow( const Reference< XModel >& _rxDocument, const Any& _rException )
+ {
+ bool bHandled = false;
+
+ // try handling the error with an interaction handler
+ Reference< XInteractionHandler > xHandler = ::comphelper::NamedValueCollection::getOrDefault( _rxDocument->getArgs(), u"InteractionHandler", Reference< XInteractionHandler >() );
+ if ( xHandler.is() )
+ {
+ rtl::Reference pRequest( new ::comphelper::OInteractionRequest( _rException ) );
+ rtl::Reference pApprove( new ::comphelper::OInteractionApprove );
+ pRequest->addContinuation( pApprove );
+
+ try
+ {
+ xHandler->handle( pRequest );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+
+ bHandled = pApprove->wasSelected();
+ }
+ return bHandled;
+ }
+}
+
+void OApplicationController::Execute(sal_uInt16 _nId, const Sequence< PropertyValue >& aArgs)
+{
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( getMutex() );
+
+ if ( isUserDefinedFeature( _nId ) )
+ {
+ OGenericUnoController::Execute( _nId, aArgs );
+ return;
+ }
+
+ if ( !getContainer() || m_bReadOnly )
+ return; // return without execution
+
+ try
+ {
+ switch(_nId)
+ {
+ case ID_BROWSER_CUT:
+ getContainer()->cut();
+ break;
+ case ID_BROWSER_COPY:
+ {
+ rtl::Reference<TransferableHelper> pTransfer = copyObject();
+ if ( pTransfer )
+ pTransfer->CopyToClipboard(getView());
+ }
+ break;
+ case ID_BROWSER_PASTE:
+ {
+ const TransferableDataHelper& rTransferData( getViewClipboard() );
+ ElementType eType = getContainer()->getElementType();
+
+ switch( eType )
+ {
+ case E_TABLE:
+ {
+ // get the selected tablename
+ std::vector< OUString > aList;
+ getSelectionElementNames( aList );
+ if ( !aList.empty() )
+ m_aTableCopyHelper.SetTableNameForAppend( *aList.begin() );
+ else
+ m_aTableCopyHelper.ResetTableNameForAppend();
+
+ m_aTableCopyHelper.pasteTable( rTransferData , getDatabaseName(), ensureConnection() );
+ }
+ break;
+
+ case E_QUERY:
+ if ( rTransferData.HasFormat(SotClipboardFormatId::DBACCESS_QUERY) )
+ paste( E_QUERY, ODataAccessObjectTransferable::extractObjectDescriptor( rTransferData ) );
+ break;
+ default:
+ {
+ std::vector< OUString> aList;
+ getSelectionElementNames(aList);
+ OUString sFolderNameToInsertInto;
+ if ( !aList.empty() )
+ {
+ Reference< XHierarchicalNameAccess > xContainer(getElements(eType),UNO_QUERY);
+ if ( xContainer.is()
+ && xContainer->hasByHierarchicalName(*aList.begin())
+ && (xContainer->getByHierarchicalName(*aList.begin()) >>= xContainer)
+ && xContainer.is()
+ )
+ sFolderNameToInsertInto = *aList.begin();
+ }
+ paste( eType, OComponentTransferable::extractComponentDescriptor( rTransferData ),
+ sFolderNameToInsertInto );
+ }
+ break;
+ }
+ }
+ break;
+ case SID_DB_APP_PASTE_SPECIAL:
+ {
+ if ( !aArgs.hasElements() )
+ {
+ SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
+ ScopedVclPtr<SfxAbstractPasteDialog> pDlg(pFact->CreatePasteDialog(getFrameWeld()));
+ std::vector<SotClipboardFormatId> aFormatIds;
+ getSupportedFormats(getContainer()->getElementType(),aFormatIds);
+ for (auto const& formatId : aFormatIds)
+ pDlg->Insert(formatId,"");
+
+ const TransferableDataHelper& rClipboard = getViewClipboard();
+ pasteFormat(pDlg->GetFormat(rClipboard.GetTransferable()));
+ }
+ else
+ {
+ const PropertyValue* pIter = aArgs.getConstArray();
+ const PropertyValue* pEnd = pIter + aArgs.getLength();
+ for( ; pIter != pEnd ; ++pIter)
+ {
+ if ( pIter->Name == "FormatStringId" )
+ {
+ sal_uLong nTmp;
+ if ( pIter->Value >>= nTmp )
+ pasteFormat(static_cast<SotClipboardFormatId>(nTmp));
+ break;
+ }
+ }
+ }
+ }
+ break;
+ case SID_NEWDOCDIRECT:
+ case SID_OPENDOC:
+ {
+ Reference < XDispatchProvider > xProv( getFrame(), UNO_QUERY );
+ if ( xProv.is() )
+ {
+ URL aURL;
+ OUString aTarget;
+ if ( _nId == SID_NEWDOCDIRECT )
+ {
+ aURL.Complete = "private:factory/sdatabase?Interactive";
+ aTarget = "_default";
+ }
+ else
+ aURL.Complete = ".uno:Open";
+
+ if ( m_xUrlTransformer.is() )
+ m_xUrlTransformer->parseStrict( aURL );
+ Reference < XDispatch > xDisp = xProv->queryDispatch( aURL, aTarget, 0 );
+ if ( xDisp.is() )
+ xDisp->dispatch( aURL, Sequence < PropertyValue >() );
+ }
+ }
+ break;
+ case ID_BROWSER_SAVEDOC:
+ {
+ Reference< XStorable > xStore( m_xModel, UNO_QUERY_THROW );
+ try
+ {
+ xStore->store();
+ }
+ catch( const Exception& )
+ {
+ lcl_handleException_nothrow( m_xModel, ::cppu::getCaughtException() );
+ }
+ }
+ break;
+
+ case ID_BROWSER_SAVEASDOC:
+ {
+ OUString sUrl;
+ if ( m_xModel.is() )
+ sUrl = m_xModel->getURL();
+
+ ::sfx2::FileDialogHelper aFileDlg(
+ ui::dialogs::TemplateDescription::FILESAVE_AUTOEXTENSION,
+ FileDialogFlags::NONE, getFrameWeld());
+ aFileDlg.SetContext(sfx2::FileDialogHelper::BaseSaveAs);
+ if (!sUrl.isEmpty())
+ aFileDlg.SetDisplayDirectory( sUrl );
+
+ std::shared_ptr<const SfxFilter> pFilter = getStandardDatabaseFilter();
+ if ( pFilter )
+ {
+ aFileDlg.AddFilter(pFilter->GetUIName(),pFilter->GetDefaultExtension());
+ aFileDlg.SetCurrentFilter(pFilter->GetUIName());
+ }
+
+ if ( aFileDlg.Execute() != ERRCODE_NONE )
+ break;
+
+ Reference<XStorable> xStore( m_xModel, UNO_QUERY_THROW );
+ INetURLObject aURL( aFileDlg.GetPath() );
+ try
+ {
+ xStore->storeAsURL( aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ), Sequence< PropertyValue >() );
+ }
+ catch( const Exception& )
+ {
+ lcl_handleException_nothrow( m_xModel, ::cppu::getCaughtException() );
+ }
+
+ /*updateTitle();*/
+ m_bCurrentlyModified = false;
+ InvalidateFeature(ID_BROWSER_SAVEDOC);
+ if ( getContainer()->getElementType() == E_NONE )
+ {
+ getContainer()->selectContainer(E_NONE);
+ getContainer()->selectContainer(E_TABLE);
+ // #i95524#
+ getContainer()->Invalidate();
+ refreshTables();
+ }
+
+ }
+ break;
+ case ID_BROWSER_SORTUP:
+ getContainer()->sortUp();
+ InvalidateFeature(ID_BROWSER_SORTDOWN);
+ break;
+ case ID_BROWSER_SORTDOWN:
+ getContainer()->sortDown();
+ InvalidateFeature(ID_BROWSER_SORTUP);
+ break;
+
+ case ID_NEW_TABLE_DESIGN_AUTO_PILOT:
+ case ID_NEW_VIEW_DESIGN_AUTO_PILOT:
+ case ID_APP_NEW_QUERY_AUTO_PILOT:
+ case SID_DB_FORM_NEW_PILOT:
+ case SID_REPORT_CREATE_REPWIZ_PRE_SEL:
+ case SID_APP_NEW_REPORT_PRE_SEL:
+ case SID_FORM_CREATE_REPWIZ_PRE_SEL:
+ case ID_DOCUMENT_CREATE_REPWIZ:
+ case SID_APP_NEW_FORM:
+ case SID_APP_NEW_REPORT:
+ case ID_NEW_QUERY_SQL:
+ case ID_NEW_QUERY_DESIGN:
+ case ID_NEW_TABLE_DESIGN:
+ {
+ ElementType eType = E_TABLE;
+ bool bAutoPilot = false;
+ ::comphelper::NamedValueCollection aCreationArgs;
+
+ switch( _nId )
+ {
+ case SID_DB_FORM_NEW_PILOT:
+ case SID_FORM_CREATE_REPWIZ_PRE_SEL:
+ bAutoPilot = true;
+ [[fallthrough]];
+ case SID_APP_NEW_FORM:
+ eType = E_FORM;
+ break;
+ case ID_DOCUMENT_CREATE_REPWIZ:
+ case SID_REPORT_CREATE_REPWIZ_PRE_SEL:
+ bAutoPilot = true;
+ [[fallthrough]];
+ case SID_APP_NEW_REPORT:
+ case SID_APP_NEW_REPORT_PRE_SEL:
+ eType = E_REPORT;
+ break;
+ case ID_APP_NEW_QUERY_AUTO_PILOT:
+ bAutoPilot = true;
+ eType = E_QUERY;
+ break;
+ case ID_NEW_QUERY_DESIGN:
+ aCreationArgs.put( PROPERTY_GRAPHICAL_DESIGN, true );
+ [[fallthrough]];
+ case ID_NEW_QUERY_SQL:
+ eType = E_QUERY;
+ break;
+ case ID_NEW_TABLE_DESIGN_AUTO_PILOT:
+ bAutoPilot = true;
+ [[fallthrough]];
+ case ID_NEW_TABLE_DESIGN:
+ break;
+ default:
+ OSL_FAIL("illegal switch call!");
+ }
+ if ( bAutoPilot )
+ getContainer()->PostUserEvent( LINK( this, OApplicationController, OnCreateWithPilot ), reinterpret_cast< void* >( eType ) );
+ else
+ {
+ Reference< XComponent > xDocDefinition;
+ newElement( eType, aCreationArgs, xDocDefinition );
+ }
+ }
+ break;
+ case SID_APP_NEW_FOLDER:
+ {
+ ElementType eType = getContainer()->getElementType();
+ OUString sName = getContainer()->getQualifiedName( nullptr );
+ insertHierarchyElement(eType,sName);
+ }
+ break;
+ case ID_NEW_VIEW_DESIGN:
+ case SID_DB_NEW_VIEW_SQL:
+ {
+ SharedConnection xConnection( ensureConnection() );
+ if ( xConnection.is() )
+ {
+ QueryDesigner aDesigner( getORB(), this, getFrame(), true );
+
+ ::comphelper::NamedValueCollection aCreationArgs;
+ aCreationArgs.put( PROPERTY_GRAPHICAL_DESIGN, ID_NEW_VIEW_DESIGN == _nId );
+
+ const Reference< XDataSource > xDataSource( m_xDataSource, UNO_QUERY );
+ const Reference< XComponent > xComponent = aDesigner.createNew( xDataSource, aCreationArgs );
+ onDocumentOpened( OUString(), E_QUERY, E_OPEN_DESIGN, xComponent, nullptr );
+ }
+ }
+ break;
+ case SID_DB_APP_DELETE:
+ case SID_DB_APP_TABLE_DELETE:
+ case SID_DB_APP_QUERY_DELETE:
+ case SID_DB_APP_FORM_DELETE:
+ case SID_DB_APP_REPORT_DELETE:
+ deleteEntries();
+ break;
+ case SID_DB_APP_RENAME:
+ case SID_DB_APP_TABLE_RENAME:
+ case SID_DB_APP_QUERY_RENAME:
+ case SID_DB_APP_FORM_RENAME:
+ case SID_DB_APP_REPORT_RENAME:
+ renameEntry();
+ break;
+ case SID_DB_APP_EDIT:
+ case SID_DB_APP_EDIT_SQL_VIEW:
+ case SID_DB_APP_TABLE_EDIT:
+ case SID_DB_APP_QUERY_EDIT:
+ case SID_DB_APP_FORM_EDIT:
+ case SID_DB_APP_REPORT_EDIT:
+ doAction( _nId, E_OPEN_DESIGN );
+ break;
+ case SID_DB_APP_OPEN:
+ case SID_DB_APP_TABLE_OPEN:
+ case SID_DB_APP_QUERY_OPEN:
+ case SID_DB_APP_FORM_OPEN:
+ case SID_DB_APP_REPORT_OPEN:
+ doAction( _nId, E_OPEN_NORMAL );
+ break;
+ case SID_DB_APP_CONVERTTOVIEW:
+ doAction( _nId, E_OPEN_NORMAL );
+ break;
+ case SID_SELECTALL:
+ getContainer()->selectAll();
+ InvalidateAll();
+ break;
+ case SID_DB_APP_DSRELDESIGN:
+ {
+ Reference< XComponent > xRelationDesigner;
+ if ( !m_pSubComponentManager->activateSubFrame( OUString(), SID_DB_APP_DSRELDESIGN, E_OPEN_DESIGN, xRelationDesigner ) )
+ {
+ SharedConnection xConnection( ensureConnection() );
+ if ( xConnection.is() )
+ {
+ RelationDesigner aDesigner( getORB(), this, m_aCurrentFrame.getFrame() );
+
+ const Reference< XDataSource > xDataSource( m_xDataSource, UNO_QUERY );
+ const Reference< XComponent > xComponent = aDesigner.createNew( xDataSource );
+ onDocumentOpened( OUString(), SID_DB_APP_DSRELDESIGN, E_OPEN_DESIGN, xComponent, nullptr );
+ }
+ }
+ }
+ break;
+ case SID_DB_APP_DSUSERADMIN:
+ {
+ SharedConnection xConnection( ensureConnection() );
+ if ( xConnection.is() )
+ openDialog("com.sun.star.sdb.UserAdministrationDialog");
+ }
+ break;
+ case SID_DB_APP_TABLEFILTER:
+ // opens the table filter dialog for the selected data source
+ openDialog( "com.sun.star.sdb.TableFilterDialog" );
+ askToReconnect();
+ break;
+ case SID_DB_APP_REFRESH_TABLES:
+ refreshTables();
+ break;
+ case SID_DB_APP_DSPROPS:
+ // opens the administration dialog for the selected data source
+ openDialog( "com.sun.star.sdb.DatasourceAdministrationDialog" );
+ askToReconnect();
+ break;
+ case SID_DB_APP_DSADVANCED_SETTINGS:
+ openDialog("com.sun.star.sdb.AdvancedDatabaseSettingsDialog");
+ askToReconnect();
+ break;
+ case SID_DB_APP_DSCONNECTION_TYPE:
+ openDialog("com.sun.star.sdb.DataSourceTypeChangeDialog");
+ askToReconnect();
+ break;
+ case ID_DIRECT_SQL:
+ {
+ SharedConnection xConnection( ensureConnection() );
+ if ( xConnection.is() )
+ // opens the DirectSQLDialog to execute hand made sql statements.
+ openDialog( SERVICE_SDB_DIRECTSQLDIALOG );
+ }
+ break;
+ case SID_DB_APP_VIEW_TABLES:
+ m_aSelectContainerEvent.Call( reinterpret_cast< void* >( E_TABLE ) );
+ break;
+ case SID_DB_APP_VIEW_QUERIES:
+ m_aSelectContainerEvent.Call( reinterpret_cast< void* >( E_QUERY ) );
+ break;
+ case SID_DB_APP_VIEW_FORMS:
+ m_aSelectContainerEvent.Call( reinterpret_cast< void* >( E_FORM ) );
+ break;
+ case SID_DB_APP_VIEW_REPORTS:
+ m_aSelectContainerEvent.Call( reinterpret_cast< void* >( E_REPORT ) );
+ break;
+ case SID_DB_APP_DISABLE_PREVIEW:
+ m_ePreviewMode = E_PREVIEWNONE;
+ getContainer()->switchPreview(m_ePreviewMode);
+ break;
+ case SID_DB_APP_VIEW_DOCINFO_PREVIEW:
+ m_ePreviewMode = E_DOCUMENTINFO;
+ getContainer()->switchPreview(m_ePreviewMode);
+ break;
+ case SID_DB_APP_VIEW_DOC_PREVIEW:
+ m_ePreviewMode = E_DOCUMENT;
+ getContainer()->switchPreview(m_ePreviewMode);
+ break;
+ case SID_MAIL_SENDDOC:
+ {
+ SfxMailModel aSendMail;
+ if ( aSendMail.AttachDocument(getModel(), OUString()) == SfxMailModel::SEND_MAIL_OK )
+ aSendMail.Send( getFrame() );
+ }
+ break;
+ case SID_DB_APP_SENDREPORTASMAIL:
+ doAction( _nId, E_OPEN_FOR_MAIL );
+ break;
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ InvalidateFeature(_nId);
+}
+
+void OApplicationController::describeSupportedFeatures()
+{
+ OGenericUnoController::describeSupportedFeatures();
+
+ implDescribeSupportedFeature( ".uno:AddDirect", SID_NEWDOCDIRECT, CommandGroup::APPLICATION );
+ implDescribeSupportedFeature( ".uno:Save", ID_BROWSER_SAVEDOC, CommandGroup::DOCUMENT );
+ implDescribeSupportedFeature( ".uno:SaveAs", ID_BROWSER_SAVEASDOC, CommandGroup::DOCUMENT );
+ implDescribeSupportedFeature( ".uno:SendMail", SID_MAIL_SENDDOC, CommandGroup::DOCUMENT );
+ implDescribeSupportedFeature( ".uno:DBSendReportAsMail",SID_DB_APP_SENDREPORTASMAIL,
+ CommandGroup::DOCUMENT );
+ implDescribeSupportedFeature( ".uno:DBSendReportToWriter",SID_DB_APP_SENDREPORTTOWRITER,
+ CommandGroup::DOCUMENT );
+ implDescribeSupportedFeature( ".uno:DBNewForm", SID_APP_NEW_FORM, CommandGroup::INSERT );
+ implDescribeSupportedFeature( ".uno:DBNewFolder", SID_APP_NEW_FOLDER, CommandGroup::INSERT );
+ implDescribeSupportedFeature( ".uno:DBNewFormAutoPilot", SID_DB_FORM_NEW_PILOT, CommandGroup::INSERT );
+ implDescribeSupportedFeature( ".uno:DBNewFormAutoPilotWithPreSelection",
+ SID_FORM_CREATE_REPWIZ_PRE_SEL,
+ CommandGroup::APPLICATION );
+
+ implDescribeSupportedFeature( ".uno:DBNewReport", SID_APP_NEW_REPORT, CommandGroup::INSERT );
+ implDescribeSupportedFeature( ".uno:DBNewReportAutoPilot",
+ ID_DOCUMENT_CREATE_REPWIZ, CommandGroup::INSERT );
+ implDescribeSupportedFeature( ".uno:DBNewReportAutoPilotWithPreSelection",
+ SID_REPORT_CREATE_REPWIZ_PRE_SEL,
+ CommandGroup::APPLICATION );
+ implDescribeSupportedFeature( ".uno:DBNewQuery", ID_NEW_QUERY_DESIGN, CommandGroup::INSERT );
+ implDescribeSupportedFeature( ".uno:DBNewQuerySql", ID_NEW_QUERY_SQL, CommandGroup::INSERT );
+ implDescribeSupportedFeature( ".uno:DBNewQueryAutoPilot",ID_APP_NEW_QUERY_AUTO_PILOT,
+ CommandGroup::INSERT );
+ implDescribeSupportedFeature( ".uno:DBNewTable", ID_NEW_TABLE_DESIGN, CommandGroup::INSERT );
+ implDescribeSupportedFeature( ".uno:DBNewTableAutoPilot",ID_NEW_TABLE_DESIGN_AUTO_PILOT,
+ CommandGroup::INSERT );
+ implDescribeSupportedFeature( ".uno:DBNewView", ID_NEW_VIEW_DESIGN, CommandGroup::INSERT );
+ implDescribeSupportedFeature( ".uno:DBNewViewSQL", SID_DB_NEW_VIEW_SQL, CommandGroup::INSERT );
+
+ implDescribeSupportedFeature( ".uno:DBDelete", SID_DB_APP_DELETE, CommandGroup::EDIT );
+ implDescribeSupportedFeature( ".uno:Delete", SID_DB_APP_DELETE, CommandGroup::EDIT );
+ implDescribeSupportedFeature( ".uno:DBRename", SID_DB_APP_RENAME, CommandGroup::EDIT );
+ implDescribeSupportedFeature( ".uno:DBEdit", SID_DB_APP_EDIT, CommandGroup::EDIT );
+ implDescribeSupportedFeature( ".uno:DBEditSqlView", SID_DB_APP_EDIT_SQL_VIEW, CommandGroup::EDIT );
+ implDescribeSupportedFeature( ".uno:DBOpen", SID_DB_APP_OPEN, CommandGroup::EDIT );
+
+ implDescribeSupportedFeature( ".uno:DBTableDelete", SID_DB_APP_TABLE_DELETE, CommandGroup::EDIT );
+ implDescribeSupportedFeature( ".uno:DBTableRename", SID_DB_APP_TABLE_RENAME, CommandGroup::EDIT );
+ implDescribeSupportedFeature( ".uno:DBTableEdit", SID_DB_APP_TABLE_EDIT, CommandGroup::EDIT );
+ implDescribeSupportedFeature( ".uno:DBTableOpen", SID_DB_APP_TABLE_OPEN, CommandGroup::EDIT );
+
+ implDescribeSupportedFeature( ".uno:DBQueryDelete", SID_DB_APP_QUERY_DELETE, CommandGroup::EDIT );
+ implDescribeSupportedFeature( ".uno:DBQueryRename", SID_DB_APP_QUERY_RENAME, CommandGroup::EDIT );
+ implDescribeSupportedFeature( ".uno:DBQueryEdit", SID_DB_APP_QUERY_EDIT, CommandGroup::EDIT );
+ implDescribeSupportedFeature( ".uno:DBQueryOpen", SID_DB_APP_QUERY_OPEN, CommandGroup::EDIT );
+
+ implDescribeSupportedFeature( ".uno:DBFormDelete", SID_DB_APP_FORM_DELETE, CommandGroup::EDIT );
+ implDescribeSupportedFeature( ".uno:DBFormRename", SID_DB_APP_FORM_RENAME, CommandGroup::EDIT );
+ implDescribeSupportedFeature( ".uno:DBFormEdit", SID_DB_APP_FORM_EDIT, CommandGroup::EDIT );
+ implDescribeSupportedFeature( ".uno:DBFormOpen", SID_DB_APP_FORM_OPEN, CommandGroup::EDIT );
+
+ implDescribeSupportedFeature( ".uno:DBReportDelete", SID_DB_APP_REPORT_DELETE, CommandGroup::EDIT );
+ implDescribeSupportedFeature( ".uno:DBReportRename", SID_DB_APP_REPORT_RENAME, CommandGroup::EDIT );
+ implDescribeSupportedFeature( ".uno:DBReportEdit", SID_DB_APP_REPORT_EDIT, CommandGroup::EDIT );
+ implDescribeSupportedFeature( ".uno:DBReportOpen", SID_DB_APP_REPORT_OPEN, CommandGroup::EDIT );
+
+ implDescribeSupportedFeature( ".uno:SelectAll", SID_SELECTALL, CommandGroup::EDIT );
+ implDescribeSupportedFeature( ".uno:Undo", ID_BROWSER_UNDO, CommandGroup::EDIT );
+
+ implDescribeSupportedFeature( ".uno:Sortup", ID_BROWSER_SORTUP, CommandGroup::VIEW );
+ implDescribeSupportedFeature( ".uno:SortDown", ID_BROWSER_SORTDOWN, CommandGroup::VIEW );
+ implDescribeSupportedFeature( ".uno:DBRelationDesign", SID_DB_APP_DSRELDESIGN, CommandGroup::APPLICATION );
+ implDescribeSupportedFeature( ".uno:DBUserAdmin", SID_DB_APP_DSUSERADMIN, CommandGroup::APPLICATION );
+ implDescribeSupportedFeature( ".uno:DBTableFilter", SID_DB_APP_TABLEFILTER, CommandGroup::APPLICATION );
+ implDescribeSupportedFeature( ".uno:DBDSProperties", SID_DB_APP_DSPROPS, CommandGroup::EDIT );
+ implDescribeSupportedFeature( ".uno:DBDSConnectionType", SID_DB_APP_DSCONNECTION_TYPE,
+ CommandGroup::EDIT );
+ implDescribeSupportedFeature( ".uno:DBDSAdvancedSettings",
+ SID_DB_APP_DSADVANCED_SETTINGS,
+ CommandGroup::EDIT );
+ implDescribeSupportedFeature( ".uno:PasteSpecial", SID_DB_APP_PASTE_SPECIAL, CommandGroup::EDIT );
+ implDescribeSupportedFeature( ".uno:DBConvertToView", SID_DB_APP_CONVERTTOVIEW, CommandGroup::EDIT );
+ implDescribeSupportedFeature( ".uno:DBRefreshTables", SID_DB_APP_REFRESH_TABLES, CommandGroup::APPLICATION );
+ implDescribeSupportedFeature( ".uno:DBDirectSQL", ID_DIRECT_SQL, CommandGroup::APPLICATION );
+ implDescribeSupportedFeature( ".uno:DBViewTables", SID_DB_APP_VIEW_TABLES, CommandGroup::VIEW );
+ implDescribeSupportedFeature( ".uno:DBViewQueries", SID_DB_APP_VIEW_QUERIES, CommandGroup::VIEW );
+ implDescribeSupportedFeature( ".uno:DBViewForms", SID_DB_APP_VIEW_FORMS, CommandGroup::VIEW );
+ implDescribeSupportedFeature( ".uno:DBViewReports", SID_DB_APP_VIEW_REPORTS, CommandGroup::VIEW );
+ implDescribeSupportedFeature( ".uno:DBDisablePreview", SID_DB_APP_DISABLE_PREVIEW,CommandGroup::VIEW );
+ implDescribeSupportedFeature( ".uno:DBShowDocInfoPreview",
+ SID_DB_APP_VIEW_DOCINFO_PREVIEW,
+ CommandGroup::VIEW );
+ implDescribeSupportedFeature( ".uno:DBShowDocPreview", SID_DB_APP_VIEW_DOC_PREVIEW,
+ CommandGroup::VIEW );
+
+ implDescribeSupportedFeature( ".uno:OpenUrl", SID_OPENURL, CommandGroup::APPLICATION );
+
+ // this one should not appear under Tools->Customize->Keyboard
+ implDescribeSupportedFeature( ".uno:DBNewReportWithPreSelection",
+ SID_APP_NEW_REPORT_PRE_SEL );
+ implDescribeSupportedFeature( ".uno:DBDSImport", SID_DB_APP_DSIMPORT);
+ implDescribeSupportedFeature( ".uno:DBDSExport", SID_DB_APP_DSEXPORT);
+ implDescribeSupportedFeature( ".uno:DBDBAdmin", SID_DB_APP_DBADMIN);
+
+ // status info
+ implDescribeSupportedFeature( ".uno:DBStatusType", SID_DB_APP_STATUS_TYPE);
+ implDescribeSupportedFeature( ".uno:DBStatusDBName", SID_DB_APP_STATUS_DBNAME);
+ implDescribeSupportedFeature( ".uno:DBStatusUserName", SID_DB_APP_STATUS_USERNAME);
+ implDescribeSupportedFeature( ".uno:DBStatusHostName", SID_DB_APP_STATUS_HOSTNAME);
+}
+
+OApplicationView* OApplicationController::getContainer() const
+{
+ return static_cast< OApplicationView* >( getView() );
+}
+
+// css::container::XContainerListener
+void SAL_CALL OApplicationController::elementInserted( const ContainerEvent& _rEvent )
+{
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( getMutex() );
+
+ Reference< XContainer > xContainer(_rEvent.Source, UNO_QUERY);
+ if ( std::find(m_aCurrentContainers.begin(),m_aCurrentContainers.end(),xContainer) == m_aCurrentContainers.end() )
+ return;
+
+ OSL_ENSURE(getContainer(),"View is NULL! -> GPF");
+ if ( !getContainer() )
+ return;
+
+ OUString sName;
+ _rEvent.Accessor >>= sName;
+ ElementType eType = getElementType(xContainer);
+
+ switch( eType )
+ {
+ case E_TABLE:
+ ensureConnection();
+ break;
+ case E_FORM:
+ case E_REPORT:
+ {
+ Reference< XContainer > xSubContainer(_rEvent.Element,UNO_QUERY);
+ if ( xSubContainer.is() )
+ containerFound(xSubContainer);
+ }
+ break;
+ default:
+ break;
+ }
+ getContainer()->elementAdded(eType,sName,_rEvent.Element);
+}
+
+void SAL_CALL OApplicationController::elementRemoved( const ContainerEvent& _rEvent )
+{
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( getMutex() );
+
+ Reference< XContainer > xContainer(_rEvent.Source, UNO_QUERY);
+ if ( std::find(m_aCurrentContainers.begin(),m_aCurrentContainers.end(),xContainer) == m_aCurrentContainers.end() )
+ return;
+
+ OSL_ENSURE(getContainer(),"View is NULL! -> GPF");
+ OUString sName;
+ _rEvent.Accessor >>= sName;
+ ElementType eType = getElementType(xContainer);
+ switch( eType )
+ {
+ case E_TABLE:
+ ensureConnection();
+ break;
+ case E_FORM:
+ case E_REPORT:
+ {
+ Reference<XContent> xContent(xContainer,UNO_QUERY);
+ if ( xContent.is() )
+ {
+ sName = xContent->getIdentifier()->getContentIdentifier() + "/" + sName;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ getContainer()->elementRemoved(eType,sName);
+}
+
+void SAL_CALL OApplicationController::elementReplaced( const ContainerEvent& _rEvent )
+{
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( getMutex() );
+
+ Reference< XContainer > xContainer(_rEvent.Source, UNO_QUERY);
+ if ( std::find(m_aCurrentContainers.begin(),m_aCurrentContainers.end(),xContainer) == m_aCurrentContainers.end() )
+ return;
+
+ OSL_ENSURE(getContainer(),"View is NULL! -> GPF");
+ OUString sName;
+ try
+ {
+ _rEvent.Accessor >>= sName;
+ Reference<XPropertySet> xProp(_rEvent.Element,UNO_QUERY);
+
+ ElementType eType = getElementType(xContainer);
+ switch( eType )
+ {
+ case E_TABLE:
+ {
+ ensureConnection();
+ if ( xProp.is() && m_xMetaData.is() )
+ //TODO: tdf#133497 "OApplicationController::elementReplaced effectively does
+ // nothing":
+ (void) ::dbaui::composeTableName( m_xMetaData, xProp, ::dbtools::EComposeRule::InDataManipulation, false );
+ }
+ break;
+ case E_FORM:
+ case E_REPORT:
+ {
+ Reference<XContent> xContent(xContainer,UNO_QUERY);
+ if ( xContent.is() )
+ {
+ sName = xContent->getIdentifier()->getContentIdentifier() + "/" + sName;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ // getContainer()->elementReplaced(getContainer()->getElementType(),sName,sNewName);
+ }
+ catch( Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+}
+
+namespace
+{
+ OUString lcl_getToolBarResource(ElementType _eType)
+ {
+ OUString sToolbar;
+ switch(_eType)
+ {
+ case E_TABLE:
+ sToolbar = "private:resource/toolbar/tableobjectbar";
+ break;
+ case E_QUERY:
+ sToolbar = "private:resource/toolbar/queryobjectbar";
+ break;
+ case E_FORM:
+ sToolbar = "private:resource/toolbar/formobjectbar";
+ break;
+ case E_REPORT:
+ sToolbar = "private:resource/toolbar/reportobjectbar";
+ break;
+ case E_NONE:
+ break;
+ default:
+ OSL_FAIL("Invalid ElementType!");
+ break;
+ }
+ return sToolbar;
+ }
+}
+
+bool OApplicationController::onContainerSelect(ElementType _eType)
+{
+ OSL_ENSURE(getContainer(),"View is NULL! -> GPF");
+
+ if ( m_eCurrentType != _eType && _eType != E_NONE )
+ {
+ SelectionGuard aSelGuard( *m_pSelectionNotifier );
+
+ if ( _eType == E_TABLE )
+ {
+ try
+ {
+ SharedConnection xConnection( ensureConnection() );
+ if ( xConnection.is() && getContainer()->getDetailView() )
+ {
+ getContainer()->getDetailView()->createTablesPage(xConnection);
+ Reference<XTablesSupplier> xTabSup(xConnection,UNO_QUERY);
+ if ( xTabSup.is() )
+ addContainerListener(xTabSup->getTables());
+ }
+ else
+ {
+ return false;
+ }
+ }
+ catch( const Exception& )
+ {
+ return false;
+ }
+ }
+ else if ( _eType == E_QUERY )
+ {
+ // tdf#126578: retrieve connection to be able to call "Create as View"
+ ensureConnection();
+ }
+ Reference< XLayoutManager > xLayoutManager = getLayoutManager( getFrame() );
+ if ( xLayoutManager.is() )
+ {
+ OUString sToolbar = lcl_getToolBarResource(_eType);
+ OUString sDestroyToolbar = lcl_getToolBarResource(m_eCurrentType);
+
+ xLayoutManager->lock();
+ xLayoutManager->destroyElement( sDestroyToolbar );
+ if ( !sToolbar.isEmpty() )
+ {
+ xLayoutManager->createElement( sToolbar );
+ xLayoutManager->requestElement( sToolbar );
+ }
+ xLayoutManager->unlock();
+ xLayoutManager->doLayout();
+ }
+
+ if ( _eType != E_TABLE && getContainer()->getDetailView() )
+ {
+ Reference< XNameAccess > xContainer = getElements(_eType);
+ addContainerListener(xContainer);
+ getContainer()->getDetailView()->createPage(_eType,xContainer);
+ }
+
+ SelectionByElementType::const_iterator pendingSelection = m_aPendingSelection.find( _eType );
+ if ( pendingSelection != m_aPendingSelection.end() )
+ {
+ getContainer()->selectElements( comphelper::containerToSequence(pendingSelection->second) );
+
+ m_aPendingSelection.erase( pendingSelection );
+ }
+
+ InvalidateAll();
+ }
+ m_eCurrentType = _eType;
+
+ return true;
+}
+
+bool OApplicationController::onEntryDoubleClick(const weld::TreeView& rTreeView)
+{
+ OApplicationView* pContainer = getContainer();
+ if (!pContainer)
+ return false; // not handled
+
+ std::unique_ptr<weld::TreeIter> xHdlEntry = rTreeView.make_iterator();
+ if (!rTreeView.get_cursor(xHdlEntry.get()))
+ return false;
+
+ if (!pContainer->isLeaf(rTreeView, *xHdlEntry))
+ return false; // not handled
+
+ try
+ {
+ // opens a new frame with either the table or the query or report or form or view
+ openElementWithArguments(
+ getContainer()->getQualifiedName(xHdlEntry.get()),
+ getContainer()->getElementType(),
+ E_OPEN_NORMAL,
+ 0,
+ ::comphelper::NamedValueCollection() );
+ return true; // handled
+ }
+ catch(const Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+
+ return false; // not handled
+}
+
+bool OApplicationController::impl_isAlterableView_nothrow( const OUString& _rTableOrViewName ) const
+{
+ OSL_PRECOND( m_xDataSourceConnection.is(), "OApplicationController::impl_isAlterableView_nothrow: no connection!" );
+
+ bool bIsAlterableView( false );
+ try
+ {
+ Reference< XViewsSupplier > xViewsSupp( m_xDataSourceConnection, UNO_QUERY );
+ Reference< XNameAccess > xViews;
+ if ( xViewsSupp.is() )
+ xViews = xViewsSupp->getViews();
+
+ Reference< XAlterView > xAsAlterableView;
+ if ( xViews.is() && xViews->hasByName( _rTableOrViewName ) )
+ xAsAlterableView.set( xViews->getByName( _rTableOrViewName ), UNO_QUERY );
+
+ bIsAlterableView = xAsAlterableView.is();
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ return bIsAlterableView;
+}
+
+Reference< XComponent > OApplicationController::openElementWithArguments( const OUString& _sName, ElementType _eType,
+ ElementOpenMode _eOpenMode, sal_uInt16 _nInstigatorCommand, const ::comphelper::NamedValueCollection& _rAdditionalArguments )
+{
+ OSL_PRECOND( getContainer(), "OApplicationController::openElementWithArguments: no view!" );
+ if ( !getContainer() )
+ return nullptr;
+
+ Reference< XComponent > xRet;
+ if ( _eOpenMode == E_OPEN_DESIGN )
+ {
+ // https://bz.apache.org/ooo/show_bug.cgi?id=30382
+ getContainer()->showPreview(nullptr);
+ }
+
+ bool isStandaloneDocument = false;
+ switch ( _eType )
+ {
+ case E_REPORT:
+ if ( _eOpenMode != E_OPEN_DESIGN )
+ {
+ // reports which are opened in a mode other than design are no sub components of our application
+ // component, but standalone documents.
+ isStandaloneDocument = true;
+ }
+ [[fallthrough]];
+ case E_FORM:
+ {
+ if ( isStandaloneDocument || !m_pSubComponentManager->activateSubFrame( _sName, _eType, _eOpenMode, xRet ) )
+ {
+ std::unique_ptr< OLinkedDocumentsAccess > aHelper = getDocumentsAccess( _eType );
+ if ( !aHelper->isConnected() )
+ break;
+
+ Reference< XComponent > xDefinition;
+ xRet = aHelper->open( _sName, xDefinition, _eOpenMode, _rAdditionalArguments );
+
+ if ( !isStandaloneDocument )
+ onDocumentOpened( _sName, _eType, _eOpenMode, xRet, xDefinition );
+ }
+ }
+ break;
+
+ case E_QUERY:
+ case E_TABLE:
+ {
+ if ( !m_pSubComponentManager->activateSubFrame( _sName, _eType, _eOpenMode, xRet ) )
+ {
+ SharedConnection xConnection( ensureConnection() );
+ if ( !xConnection.is() )
+ break;
+
+ std::unique_ptr< DatabaseObjectView > pDesigner;
+ ::comphelper::NamedValueCollection aArguments( _rAdditionalArguments );
+
+ Any aDataSource;
+ if ( _eOpenMode == E_OPEN_DESIGN )
+ {
+ bool bAddViewTypeArg = false;
+
+ if ( _eType == E_TABLE )
+ {
+ if ( impl_isAlterableView_nothrow( _sName ) )
+ {
+ pDesigner.reset( new QueryDesigner( getORB(), this, m_aCurrentFrame.getFrame(), true ) );
+ bAddViewTypeArg = true;
+ }
+ else
+ {
+ pDesigner.reset( new TableDesigner( getORB(), this, m_aCurrentFrame.getFrame() ) );
+ }
+ }
+ else if ( _eType == E_QUERY )
+ {
+ pDesigner.reset( new QueryDesigner( getORB(), this, m_aCurrentFrame.getFrame(), false ) );
+ bAddViewTypeArg = true;
+ }
+ aDataSource <<= m_xDataSource;
+
+ if ( bAddViewTypeArg )
+ {
+ const bool bQueryGraphicalMode =( _nInstigatorCommand != SID_DB_APP_EDIT_SQL_VIEW );
+ aArguments.put( PROPERTY_GRAPHICAL_DESIGN, bQueryGraphicalMode );
+ }
+
+ }
+ else
+ {
+ pDesigner.reset( new ResultSetBrowser( getORB(), this, m_aCurrentFrame.getFrame(), _eType == E_TABLE ) );
+
+ if ( !aArguments.has( PROPERTY_SHOWMENU ) )
+ aArguments.put( PROPERTY_SHOWMENU, Any( true ) );
+
+ aDataSource <<= getDatabaseName();
+ }
+
+ xRet.set( pDesigner->openExisting( aDataSource, _sName, aArguments ) );
+ onDocumentOpened( _sName, _eType, _eOpenMode, xRet, nullptr );
+ }
+ }
+ break;
+
+ default:
+ OSL_FAIL( "OApplicationController::openElement: illegal object type!" );
+ break;
+ }
+ return xRet;
+}
+
+IMPL_LINK( OApplicationController, OnSelectContainer, void*, _pType, void )
+{
+ ElementType eType = static_cast<ElementType>(reinterpret_cast< sal_IntPtr >( _pType ));
+ if (getContainer())
+ getContainer()->selectContainer(eType);
+}
+
+IMPL_LINK( OApplicationController, OnCreateWithPilot, void*, _pType, void )
+{
+ ElementType eType = static_cast<ElementType>(reinterpret_cast< sal_IntPtr >( _pType ));
+ newElementWithPilot( eType );
+}
+
+void OApplicationController::newElementWithPilot( ElementType _eType )
+{
+ utl::CloseVeto aKeepDoc( getFrame() );
+ // prevent the document being closed while the wizard is open
+
+ OSL_ENSURE( getContainer(), "OApplicationController::newElementWithPilot: without a view?" );
+
+ switch ( _eType )
+ {
+ case E_REPORT:
+ case E_FORM:
+ {
+ std::unique_ptr<OLinkedDocumentsAccess> aHelper = getDocumentsAccess(_eType);
+ if ( aHelper->isConnected() )
+ {
+ sal_Int32 nCommandType = -1;
+ const OUString sCurrentSelected( getCurrentlySelectedName( nCommandType ) );
+ if ( E_REPORT == _eType )
+ aHelper->newReportWithPilot( nCommandType, sCurrentSelected );
+ else
+ aHelper->newFormWithPilot( nCommandType, sCurrentSelected );
+ }
+ }
+ break;
+ case E_QUERY:
+ case E_TABLE:
+ {
+ std::unique_ptr<OLinkedDocumentsAccess> aHelper = getDocumentsAccess(_eType);
+ if ( aHelper->isConnected() )
+ {
+ if ( E_QUERY == _eType )
+ aHelper->newQueryWithPilot();
+ else
+ aHelper->newTableWithPilot();
+ }
+ }
+ break;
+ case E_NONE:
+ break;
+ }
+
+ // no need for onDocumentOpened, the table wizard opens the created table by using
+ // XDatabaseDocumentUI::loadComponent method.
+}
+
+Reference< XComponent > OApplicationController::newElement( ElementType _eType, const ::comphelper::NamedValueCollection& i_rAdditionalArguments,
+ Reference< XComponent >& o_rDocumentDefinition )
+{
+ OSL_ENSURE(getContainer(),"View is NULL! -> GPF");
+
+ Reference< XComponent > xComponent;
+ o_rDocumentDefinition.clear();
+
+ switch ( _eType )
+ {
+ case E_FORM:
+ case E_REPORT:
+ {
+ std::unique_ptr<OLinkedDocumentsAccess> aHelper = getDocumentsAccess( _eType );
+ if ( !aHelper->isConnected() )
+ break;
+
+ xComponent = aHelper->newDocument( _eType == E_FORM ? ID_FORM_NEW_TEXT : ID_REPORT_NEW_TEXT, i_rAdditionalArguments, o_rDocumentDefinition );
+ }
+ break;
+
+ case E_QUERY:
+ case E_TABLE:
+ {
+ std::unique_ptr< DatabaseObjectView > pDesigner;
+ SharedConnection xConnection( ensureConnection() );
+ if ( !xConnection.is() )
+ break;
+
+ if ( _eType == E_TABLE )
+ {
+ pDesigner.reset( new TableDesigner( getORB(), this, getFrame() ) );
+ }
+ else if ( _eType == E_QUERY )
+ {
+ pDesigner.reset( new QueryDesigner( getORB(), this, getFrame(), false ) );
+ }
+
+ Reference< XDataSource > xDataSource( m_xDataSource, UNO_QUERY );
+ xComponent = pDesigner->createNew( xDataSource, i_rAdditionalArguments );
+ }
+ break;
+
+ default:
+ OSL_FAIL( "OApplicationController::newElement: illegal type!" );
+ break;
+ }
+
+ if ( xComponent.is() )
+ onDocumentOpened( OUString(), _eType, E_OPEN_DESIGN, xComponent, o_rDocumentDefinition );
+
+ return xComponent;
+}
+
+void OApplicationController::addContainerListener(const Reference<XNameAccess>& _xCollection)
+{
+ try
+ {
+ Reference< XContainer > xCont(_xCollection, UNO_QUERY);
+ if ( xCont.is() )
+ {
+ // add as listener to get notified if elements are inserted or removed
+ TContainerVector::const_iterator aFind = std::find(m_aCurrentContainers.begin(),m_aCurrentContainers.end(),xCont);
+ if ( aFind == m_aCurrentContainers.end() )
+ {
+ xCont->addContainerListener(this);
+ m_aCurrentContainers.push_back(xCont);
+ }
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+}
+
+void OApplicationController::renameEntry()
+{
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( getMutex() );
+
+ OSL_ENSURE(getContainer(),"View is NULL! -> GPF");
+ std::vector< OUString> aList;
+ getSelectionElementNames(aList);
+
+ Reference< XNameAccess > xContainer = getElements(getContainer()->getElementType());
+ OSL_ENSURE(aList.size() == 1,"Invalid rename call here. More than one element!");
+ if ( aList.empty() )
+ return;
+
+ try
+ {
+ if ( xContainer.is() )
+ {
+ std::unique_ptr< IObjectNameCheck > pNameChecker;
+ std::unique_ptr<OSaveAsDlg> xDialog;
+
+ Reference<XRename> xRename;
+ const ElementType eType = getContainer()->getElementType();
+ switch( eType )
+ {
+ case E_FORM:
+ case E_REPORT:
+ {
+ Reference<XHierarchicalNameContainer> xHNames(xContainer, UNO_QUERY);
+ if ( xHNames.is() )
+ {
+ OUString sLabel;
+ if ( eType == E_FORM )
+ sLabel = DBA_RES(STR_FRM_LABEL);
+ else
+ sLabel = DBA_RES(STR_RPT_LABEL);
+
+ OUString sName = *aList.begin();
+ if ( xHNames->hasByHierarchicalName(sName) )
+ {
+ xRename.set(xHNames->getByHierarchicalName(sName),UNO_QUERY);
+ Reference<XChild> xChild(xRename,UNO_QUERY);
+ if ( xChild.is() )
+ {
+ Reference<XHierarchicalNameContainer> xParent(xChild->getParent(),UNO_QUERY);
+ if ( xParent.is() )
+ {
+ xHNames = xParent;
+ Reference<XPropertySet>(xRename,UNO_QUERY_THROW)->getPropertyValue(PROPERTY_NAME) >>= sName;
+ }
+ }
+ pNameChecker.reset( new HierarchicalNameCheck( xHNames, OUString() ) );
+ xDialog.reset(new OSaveAsDlg(
+ getFrameWeld(), getORB(), sName, sLabel, *pNameChecker, SADFlags::TitleRename));
+ }
+ }
+ }
+ break;
+ case E_TABLE:
+ ensureConnection();
+ if ( !getConnection().is() )
+ break;
+ [[fallthrough]];
+ case E_QUERY:
+ if ( xContainer->hasByName(*aList.begin()) )
+ {
+ xRename.set(xContainer->getByName(*aList.begin()),UNO_QUERY);
+ sal_Int32 nCommandType = eType == E_QUERY ? CommandType::QUERY : CommandType::TABLE;
+
+ ensureConnection();
+ pNameChecker.reset( new DynamicTableOrQueryNameCheck( getConnection(), nCommandType ) );
+ xDialog.reset(new OSaveAsDlg(getFrameWeld(), nCommandType, getORB(), getConnection(),
+ *aList.begin(), *pNameChecker, SADFlags::TitleRename));
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (xRename.is() && xDialog)
+ {
+
+ bool bTryAgain = true;
+ while( bTryAgain )
+ {
+ if (xDialog->run() == RET_OK)
+ {
+ try
+ {
+ OUString sNewName;
+ if ( eType == E_TABLE )
+ {
+ OUString sName = xDialog->getName();
+ OUString sCatalog = xDialog->getCatalog();
+ OUString sSchema = xDialog->getSchema();
+
+ sNewName = ::dbtools::composeTableName( m_xMetaData, sCatalog, sSchema, sName, false, ::dbtools::EComposeRule::InDataManipulation );
+ }
+ else
+ sNewName = xDialog->getName();
+
+ OUString sOldName = *aList.begin();
+ if ( eType == E_FORM || eType == E_REPORT )
+ {
+ Reference<XContent> xContent(xRename,UNO_QUERY);
+ if ( xContent.is() )
+ {
+ sOldName = xContent->getIdentifier()->getContentIdentifier();
+ }
+ }
+
+ xRename->rename(sNewName);
+
+ if ( eType == E_TABLE )
+ {
+ Reference<XPropertySet> xProp(xRename,UNO_QUERY);
+ sNewName = ::dbaui::composeTableName( m_xMetaData, xProp, ::dbtools::EComposeRule::InDataManipulation, false );
+ }
+ getContainer()->elementReplaced( eType , sOldName, sNewName );
+
+ bTryAgain = false;
+ }
+ catch(const SQLException& )
+ {
+ showError( SQLExceptionInfo( ::cppu::getCaughtException() ) );
+
+ }
+ catch(const ElementExistException& e)
+ {
+ OUString sMsg(DBA_RES(STR_NAME_ALREADY_EXISTS));
+ showError(SQLExceptionInfo(SQLException(sMsg.replaceAll("#", e.Message), e.Context, "S1000", 0, Any())));
+ }
+ catch(const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+ else
+ bTryAgain = false;
+ }
+ }
+ }
+ }
+ catch(const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+}
+
+void OApplicationController::onSelectionChanged()
+{
+ InvalidateAll();
+
+ SelectionGuard aSelGuard( *m_pSelectionNotifier );
+
+ OApplicationView* pView = getContainer();
+ if ( !pView )
+ return;
+
+ if ( pView->getSelectionCount() == 1 )
+ {
+ const ElementType eType = pView->getElementType();
+ if ( pView->isALeafSelected() )
+ {
+ const OUString sName = pView->getQualifiedName( nullptr /* means 'first selected' */ );
+ showPreviewFor( eType, sName );
+ }
+ }
+}
+
+void OApplicationController::showPreviewFor(const ElementType _eType,const OUString& _sName)
+{
+ if ( m_ePreviewMode == E_PREVIEWNONE )
+ return;
+
+ OApplicationView* pView = getContainer();
+ if ( !pView )
+ return;
+
+ try
+ {
+ switch( _eType )
+ {
+ case E_FORM:
+ case E_REPORT:
+ {
+ Reference< XHierarchicalNameAccess > xContainer( getElements( _eType ), UNO_QUERY_THROW );
+ Reference< XContent> xContent( xContainer->getByHierarchicalName( _sName ), UNO_QUERY_THROW );
+ pView->showPreview( xContent );
+ }
+ break;
+
+ case E_TABLE:
+ case E_QUERY:
+ {
+ SharedConnection xConnection( ensureConnection() );
+ if ( xConnection.is() )
+ pView->showPreview( getDatabaseName(), xConnection, _sName, _eType == E_TABLE );
+ }
+ return;
+
+ default:
+ OSL_FAIL( "OApplicationController::showPreviewFor: unexpected element type!" );
+ break;
+ }
+ }
+ catch( const SQLException& )
+ {
+ showError( SQLExceptionInfo( ::cppu::getCaughtException() ) );
+ }
+ catch(const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+}
+
+IMPL_LINK_NOARG(OApplicationController, OnClipboardChanged, TransferableDataHelper*, void)
+{
+ OnInvalidateClipboard();
+}
+
+void OApplicationController::OnInvalidateClipboard()
+{
+ InvalidateFeature(ID_BROWSER_CUT);
+ InvalidateFeature(ID_BROWSER_COPY);
+ InvalidateFeature(ID_BROWSER_PASTE);
+ InvalidateFeature(SID_DB_APP_PASTE_SPECIAL);
+}
+
+void OApplicationController::onCopyEntry()
+{
+ Execute(ID_BROWSER_COPY,Sequence<PropertyValue>());
+}
+
+void OApplicationController::onPasteEntry()
+{
+ Execute(ID_BROWSER_PASTE,Sequence<PropertyValue>());
+}
+
+void OApplicationController::onDeleteEntry()
+{
+ ElementType eType = getContainer()->getElementType();
+ sal_uInt16 nId = 0;
+ switch(eType)
+ {
+ case E_TABLE:
+ nId = SID_DB_APP_TABLE_DELETE;
+ break;
+ case E_QUERY:
+ nId = SID_DB_APP_QUERY_DELETE;
+ break;
+ case E_FORM:
+ nId = SID_DB_APP_FORM_DELETE;
+ break;
+ case E_REPORT:
+ nId = SID_DB_APP_REPORT_DELETE;
+ break;
+ default:
+ OSL_FAIL("Invalid ElementType!");
+ break;
+ }
+ executeChecked(nId,Sequence<PropertyValue>());
+}
+
+OUString OApplicationController::getContextMenuResourceName() const
+{
+ return "edit";
+}
+
+IController& OApplicationController::getCommandController()
+{
+ return *this;
+}
+
+::comphelper::OInterfaceContainerHelper2* OApplicationController::getContextMenuInterceptors()
+{
+ return &m_aContextMenuInterceptors;
+}
+
+Any OApplicationController::getCurrentSelection(weld::TreeView& rControl) const
+{
+ Sequence< NamedDatabaseObject > aSelection;
+ getContainer()->describeCurrentSelectionForControl(rControl, aSelection);
+ return Any( aSelection );
+}
+
+vcl::Window* OApplicationController::getMenuParent() const
+{
+ return getContainer()->getMenuParent();
+}
+
+void OApplicationController::adjustMenuPosition(const weld::TreeView& rControl, ::Point& rPos) const
+{
+ getContainer()->adjustMenuPosition(rControl, rPos);
+}
+
+bool OApplicationController::requestQuickHelp(const void* /*pUserData*/, OUString& /*rText*/) const
+{
+ return false;
+}
+
+bool OApplicationController::requestDrag(const weld::TreeIter& /*rEntry*/)
+{
+ bool bSuccess = false;
+
+ OApplicationView* pContainer = getContainer();
+ if (pContainer && pContainer->getSelectionCount())
+ {
+ try
+ {
+ if (getContainer()->getDetailView())
+ {
+ TreeListBox* pTreeListBox = getContainer()->getDetailView()->getTreeWindow();
+
+ ElementType eType = getContainer()->getElementType();
+ if (eType == E_TABLE || eType == E_QUERY)
+ {
+ ODataClipboard& rExchange = static_cast<ODataClipboard&>(pTreeListBox->GetDataTransfer());
+ bSuccess = copySQLObject(rExchange);
+ }
+ else
+ {
+ svx::OComponentTransferable& rExchange = static_cast<svx::OComponentTransferable&>(pTreeListBox->GetDataTransfer());
+ bSuccess = copyDocObject(rExchange);
+ }
+ }
+ }
+ catch(const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+
+ return bSuccess;
+}
+
+sal_Int8 OApplicationController::queryDrop( const AcceptDropEvent& _rEvt, const DataFlavorExVector& _rFlavors )
+{
+ sal_Int8 nActionAskedFor = _rEvt.mnAction;
+ // check if we're a table or query container
+ OApplicationView* pView = getContainer();
+ if ( !pView || isDataSourceReadOnly() )
+ return DND_ACTION_NONE;
+
+ ElementType eType = pView->getElementType();
+ if ( eType == E_NONE || (eType == E_TABLE && isConnectionReadOnly()) )
+ return DND_ACTION_NONE;
+
+ // check for the concrete type
+ if(std::any_of(_rFlavors.begin(),_rFlavors.end(),TAppSupportedSotFunctor(eType)))
+ return DND_ACTION_COPY;
+
+ if ( eType != E_FORM && eType != E_REPORT )
+ return DND_ACTION_NONE;
+
+ sal_Int8 nAction = OComponentTransferable::canExtractComponentDescriptor(_rFlavors,eType == E_FORM) ? DND_ACTION_COPY : DND_ACTION_NONE;
+ if ( nAction == DND_ACTION_NONE )
+ return DND_ACTION_NONE;
+
+ auto xHitEntry = pView->getEntry(_rEvt.maPosPixel);
+ if (xHitEntry)
+ {
+ OUString sName = pView->getQualifiedName(xHitEntry.get());
+ if ( !sName.isEmpty() )
+ {
+ Reference< XHierarchicalNameAccess > xContainer(getElements(pView->getElementType()),UNO_QUERY);
+ if ( xContainer.is() && xContainer->hasByHierarchicalName(sName) )
+ {
+ Reference< XHierarchicalNameAccess > xHitObject(xContainer->getByHierarchicalName(sName),UNO_QUERY);
+ if ( xHitObject.is() )
+ nAction = nActionAskedFor & DND_ACTION_COPYMOVE;
+ }
+ else
+ nAction = DND_ACTION_NONE;
+ }
+ }
+ return nAction;
+}
+
+sal_Int8 OApplicationController::executeDrop( const ExecuteDropEvent& _rEvt )
+{
+ OApplicationView* pView = getContainer();
+ if ( !pView || pView->getElementType() == E_NONE )
+ {
+ OSL_FAIL("OApplicationController::executeDrop: what the hell did queryDrop do?");
+ // queryDrop should not have allowed us to reach this situation...
+ return DND_ACTION_NONE;
+ }
+
+ // a TransferableDataHelper for accessing the dropped data
+ TransferableDataHelper aDroppedData(_rEvt.maDropEvent.Transferable);
+
+ // reset the data of the previous async drop (if any)
+ if ( m_nAsyncDrop )
+ Application::RemoveUserEvent(m_nAsyncDrop);
+
+ m_nAsyncDrop = nullptr;
+ m_aAsyncDrop.aDroppedData.clear();
+ m_aAsyncDrop.nType = pView->getElementType();
+ m_aAsyncDrop.nAction = _rEvt.mnAction;
+ m_aAsyncDrop.bError = false;
+ m_aAsyncDrop.bHtml = false;
+ m_aAsyncDrop.aUrl.clear();
+
+ // loop through the available formats and see what we can do...
+ // first we have to check if it is our own format, if not we have to copy the stream :-(
+ if ( ODataAccessObjectTransferable::canExtractObjectDescriptor(aDroppedData.GetDataFlavorExVector()) )
+ {
+ m_aAsyncDrop.aDroppedData = ODataAccessObjectTransferable::extractObjectDescriptor(aDroppedData);
+
+ // asynchron because we some dialogs and we aren't allowed to show them while in D&D
+ m_nAsyncDrop = Application::PostUserEvent(LINK(this, OApplicationController, OnAsyncDrop));
+ return DND_ACTION_COPY;
+ }
+ else if ( OComponentTransferable::canExtractComponentDescriptor(aDroppedData.GetDataFlavorExVector(),m_aAsyncDrop.nType == E_FORM) )
+ {
+ m_aAsyncDrop.aDroppedData = OComponentTransferable::extractComponentDescriptor(aDroppedData);
+ auto xHitEntry = pView->getEntry(_rEvt.maPosPixel);
+ if ( xHitEntry )
+ m_aAsyncDrop.aUrl = pView->getQualifiedName(xHitEntry.get());
+
+ sal_Int8 nAction = _rEvt.mnAction;
+ Reference<XContent> xContent;
+ m_aAsyncDrop.aDroppedData[DataAccessDescriptorProperty::Component] >>= xContent;
+ if ( xContent.is() )
+ {
+ OUString sName = xContent->getIdentifier()->getContentIdentifier();
+ sName = sName.copy(sName.indexOf('/') + 1);
+ if ( m_aAsyncDrop.aUrl.getLength() >= sName.getLength() && m_aAsyncDrop.aUrl.startsWith(sName) )
+ {
+ m_aAsyncDrop.aDroppedData.clear();
+ return DND_ACTION_NONE;
+ }
+
+ // check if move is allowed, if another object with the same name exists only copy is allowed
+ Reference< XHierarchicalNameAccess > xContainer(getElements(m_aAsyncDrop.nType),UNO_QUERY);
+ Reference<XNameAccess> xNameAccess(xContainer,UNO_QUERY);
+
+ if ( !m_aAsyncDrop.aUrl.isEmpty() && xContainer.is() && xContainer->hasByHierarchicalName(m_aAsyncDrop.aUrl) )
+ xNameAccess.set(xContainer->getByHierarchicalName(m_aAsyncDrop.aUrl),UNO_QUERY);
+
+ if ( xNameAccess.is() )
+ {
+ Reference<XPropertySet> xProp(xContent,UNO_QUERY);
+ if ( xProp.is() )
+ {
+ xProp->getPropertyValue(PROPERTY_NAME) >>= sName;
+ if ( xNameAccess.is() && xNameAccess->hasByName(sName) )
+ nAction &= ~DND_ACTION_MOVE;
+ }
+ else
+ nAction &= ~DND_ACTION_MOVE;
+ }
+ }
+ if ( nAction != DND_ACTION_NONE )
+ {
+ m_aAsyncDrop.nAction = nAction;
+ // asynchron because we some dialogs and we aren't allowed to show them while in D&D
+ m_nAsyncDrop = Application::PostUserEvent(LINK(this, OApplicationController, OnAsyncDrop));
+ }
+ else
+ m_aAsyncDrop.aDroppedData.clear();
+ return nAction;
+ }
+ else
+ {
+ SharedConnection xConnection( ensureConnection() );
+ if ( xConnection.is() && m_aTableCopyHelper.copyTagTable( aDroppedData, m_aAsyncDrop, xConnection ) )
+ {
+ // asynchron because we some dialogs and we aren't allowed to show them while in D&D
+ m_nAsyncDrop = Application::PostUserEvent(LINK(this, OApplicationController, OnAsyncDrop));
+ return DND_ACTION_COPY;
+ }
+ }
+
+ return DND_ACTION_NONE;
+}
+
+Reference< XModel > SAL_CALL OApplicationController::getModel()
+{
+ return m_xModel;
+}
+
+void OApplicationController::onAttachedFrame()
+{
+ sal_Int32 nConnectedControllers( 0 );
+ try
+ {
+ Reference< XModel2 > xModel( m_xModel, UNO_QUERY_THROW );
+ Reference< XEnumeration > xEnumControllers( xModel->getControllers(), UNO_SET_THROW );
+ while ( xEnumControllers->hasMoreElements() )
+ {
+ Reference< XController > xController( xEnumControllers->nextElement(), UNO_QUERY_THROW );
+ ++nConnectedControllers;
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+
+ if ( nConnectedControllers > 1 )
+ { // we are not the first connected controller, there were already others
+ return;
+ }
+
+ OnFirstControllerConnected();
+}
+
+void OApplicationController::OnFirstControllerConnected()
+{
+ if ( !m_xModel.is() )
+ {
+ OSL_FAIL( "OApplicationController::OnFirstControllerConnected: too late!" );
+ }
+
+ // if we have forms or reports which contain macros/scripts, then show a warning
+ // which suggests the user to migrate them to the database document
+ Reference< XEmbeddedScripts > xDocumentScripts( m_xModel, UNO_QUERY );
+ if ( xDocumentScripts.is() )
+ {
+ // no need to show this warning, obviously the document supports embedding scripts
+ // into itself, so there are no "old-style" forms/reports which have macros/scripts
+ // themselves
+ return;
+ }
+
+ try
+ {
+ // If the migration just happened, but was not successful, the document is reloaded.
+ // In this case, we should not show the warning, again.
+ if ( ::comphelper::NamedValueCollection::getOrDefault( m_xModel->getArgs(), u"SuppressMigrationWarning", false ) )
+ return;
+
+ // also, if the document is read-only, then no migration is possible, and the
+ // respective menu entry is hidden. So, don't show the warning in this case, too.
+ if ( Reference< XStorable >( m_xModel, UNO_QUERY_THROW )->isReadonly() )
+ return;
+
+ SQLWarning aWarning;
+ aWarning.Message = DBA_RES(STR_SUB_DOCS_WITH_SCRIPTS);
+ SQLException aDetail;
+ aDetail.Message = DBA_RES(STR_SUB_DOCS_WITH_SCRIPTS_DETAIL);
+ aWarning.NextException <<= aDetail;
+
+ Reference< XExecutableDialog > xDialog = ErrorMessageDialog::create( getORB(), "", nullptr, Any( aWarning ) );
+ xDialog->execute();
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+}
+
+void SAL_CALL OApplicationController::attachFrame( const Reference< XFrame > & i_rxFrame )
+{
+ SolarMutexGuard aSolarGuard; // avoid deadlock in XModel calls
+ ::osl::MutexGuard aGuard( getMutex() );
+
+ OGenericUnoController::attachFrame( i_rxFrame );
+ if ( getFrame().is() )
+ onAttachedFrame();
+}
+
+sal_Bool SAL_CALL OApplicationController::attachModel(const Reference< XModel > & _rxModel)
+{
+ ::osl::MutexGuard aGuard( getMutex() );
+ const Reference< XOfficeDatabaseDocument > xOfficeDoc( _rxModel, UNO_QUERY );
+ const Reference< XModifiable > xDocModify( _rxModel, UNO_QUERY );
+ if ( ( !xOfficeDoc.is() || !xDocModify.is() ) && _rxModel.is() )
+ {
+ OSL_FAIL( "OApplicationController::attachModel: invalid model!" );
+ return false;
+ }
+
+ if ( m_xModel.is() && ( m_xModel != _rxModel ) && ( _rxModel.is() ) )
+ {
+ OSL_ENSURE( false, "OApplicationController::attachModel: missing implementation: setting a new model while we have another one!" );
+ // we'd need to completely update our view here, close sub components, and the like
+ return false;
+ }
+
+ const OUString aPropertyNames[] =
+ {
+ OUString(PROPERTY_URL), OUString(PROPERTY_USER)
+ };
+
+ // disconnect from old model
+ try
+ {
+ if ( m_xDataSource.is() )
+ {
+ for (const auto & aPropertyName : aPropertyNames)
+ {
+ m_xDataSource->removePropertyChangeListener( aPropertyName, this );
+ }
+ }
+
+ Reference< XModifyBroadcaster > xBroadcaster( m_xModel, UNO_QUERY );
+ if ( xBroadcaster.is() )
+ xBroadcaster->removeModifyListener( this );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+
+ m_xModel = _rxModel;
+ m_xDataSource.set( xOfficeDoc.is() ? xOfficeDoc->getDataSource() : Reference< XDataSource >(), UNO_QUERY );
+
+ // connect to new model
+ try
+ {
+ if ( m_xDataSource.is() )
+ {
+ for (const auto & aPropertyName : aPropertyNames)
+ {
+ m_xDataSource->addPropertyChangeListener( aPropertyName, this );
+ }
+ }
+
+ Reference< XModifyBroadcaster > xBroadcaster( m_xModel, UNO_QUERY_THROW );
+ xBroadcaster->addModifyListener( this );
+
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+
+ // initial preview mode
+ if ( !m_xDataSource )
+ return true;
+
+ try
+ {
+ // to get the 'modified' for the data source
+ ::comphelper::NamedValueCollection aLayoutInfo( m_xDataSource->getPropertyValue( PROPERTY_LAYOUTINFORMATION ) );
+ if ( aLayoutInfo.has( INFO_PREVIEW ) )
+ {
+ const sal_Int32 nPreviewMode( aLayoutInfo.getOrDefault( INFO_PREVIEW, sal_Int32(0) ) );
+ m_ePreviewMode = static_cast< PreviewMode >( nPreviewMode );
+ if ( getView() )
+ getContainer()->switchPreview( m_ePreviewMode );
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+
+ return true;
+}
+
+void OApplicationController::containerFound( const Reference< XContainer >& _xContainer)
+{
+ try
+ {
+ if ( _xContainer.is() )
+ {
+ m_aCurrentContainers.push_back(_xContainer);
+ _xContainer->addContainerListener(this);
+ }
+ }
+ catch(const Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+}
+
+OUString OApplicationController::getCurrentlySelectedName(sal_Int32& _rnCommandType) const
+{
+ _rnCommandType = ( (getContainer()->getElementType() == E_QUERY)
+ ? CommandType::QUERY : ( (getContainer()->getElementType() == E_TABLE) ? CommandType::TABLE : -1 ));
+
+ OUString sName;
+ if ( _rnCommandType != -1 )
+ {
+ try
+ {
+ sName = getContainer()->getQualifiedName( nullptr );
+ OSL_ENSURE( !sName.isEmpty(), "OApplicationController::getCurrentlySelectedName: no name given!" );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+ return sName;
+}
+
+void SAL_CALL OApplicationController::addSelectionChangeListener( const Reference< view::XSelectionChangeListener >& Listener )
+{
+ m_pSelectionNotifier->addListener( Listener );
+}
+
+void SAL_CALL OApplicationController::removeSelectionChangeListener( const Reference< view::XSelectionChangeListener >& Listener )
+{
+ m_pSelectionNotifier->removeListener( Listener );
+}
+
+sal_Bool SAL_CALL OApplicationController::select( const Any& _aSelection )
+{
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( getMutex() );
+ Sequence< OUString> aSelection;
+ if ( !_aSelection.hasValue() || !getView() )
+ {
+ getContainer()->selectElements(aSelection);
+ return true;
+ }
+
+ // BEGIN compatibility
+ Sequence< NamedValue > aCurrentSelection;
+ if ( (_aSelection >>= aCurrentSelection) && aCurrentSelection.hasElements() )
+ {
+ ElementType eType = E_NONE;
+ const NamedValue* pIter = aCurrentSelection.getConstArray();
+ const NamedValue* pEnd = pIter + aCurrentSelection.getLength();
+ for(;pIter != pEnd;++pIter)
+ {
+ if ( pIter->Name == "Type" )
+ {
+ sal_Int32 nType = 0;
+ pIter->Value >>= nType;
+ if ( nType < DatabaseObject::TABLE || nType > DatabaseObject::REPORT )
+ throw IllegalArgumentException();
+ eType = static_cast< ElementType >( nType );
+ }
+ else if ( pIter->Name == "Selection" )
+ pIter->Value >>= aSelection;
+ }
+
+ m_aSelectContainerEvent.CancelCall(); // just in case the async select request was running
+ getContainer()->selectContainer(eType);
+ getContainer()->selectElements(aSelection);
+ return true;
+ }
+ // END compatibility
+
+ Sequence< NamedDatabaseObject > aSelectedObjects;
+ if ( !( _aSelection >>= aSelectedObjects ) )
+ {
+ aSelectedObjects.realloc( 1 );
+ if ( !( _aSelection >>= aSelectedObjects.getArray()[0] ) )
+ throw IllegalArgumentException();
+ }
+
+ SelectionByElementType aSelectedElements;
+ ElementType eSelectedCategory = E_NONE;
+ for ( const NamedDatabaseObject* pObject = aSelectedObjects.getConstArray();
+ pObject != aSelectedObjects.getConstArray() + aSelectedObjects.getLength();
+ ++pObject
+ )
+ {
+ switch ( pObject->Type )
+ {
+ case DatabaseObject::TABLE:
+ case DatabaseObjectContainer::SCHEMA:
+ case DatabaseObjectContainer::CATALOG:
+ aSelectedElements[ E_TABLE ].push_back( pObject->Name );
+ break;
+ case DatabaseObject::QUERY:
+ aSelectedElements[ E_QUERY ].push_back( pObject->Name );
+ break;
+ case DatabaseObject::FORM:
+ case DatabaseObjectContainer::FORMS_FOLDER:
+ aSelectedElements[ E_FORM ].push_back( pObject->Name );
+ break;
+ case DatabaseObject::REPORT:
+ case DatabaseObjectContainer::REPORTS_FOLDER:
+ aSelectedElements[ E_REPORT ].push_back( pObject->Name );
+ break;
+ case DatabaseObjectContainer::TABLES:
+ case DatabaseObjectContainer::QUERIES:
+ case DatabaseObjectContainer::FORMS:
+ case DatabaseObjectContainer::REPORTS:
+ if ( eSelectedCategory != E_NONE )
+ throw IllegalArgumentException(
+ DBA_RES(RID_STR_NO_DIFF_CAT),
+ *this, sal_Int16( pObject - aSelectedObjects.getConstArray() ) );
+ eSelectedCategory =
+ ( pObject->Type == DatabaseObjectContainer::TABLES ) ? E_TABLE
+ : ( pObject->Type == DatabaseObjectContainer::QUERIES ) ? E_QUERY
+ : ( pObject->Type == DatabaseObjectContainer::FORMS ) ? E_FORM
+ : ( pObject->Type == DatabaseObjectContainer::REPORTS ) ? E_REPORT
+ : E_NONE;
+ break;
+
+ default:
+ case DatabaseObjectContainer::DATA_SOURCE:
+ {
+ OUString sMessage(
+ DBA_RES(RID_STR_UNSUPPORTED_OBJECT_TYPE).
+ replaceFirst("$type$", OUString::number(pObject->Type)));
+ throw IllegalArgumentException(sMessage, *this, sal_Int16( pObject - aSelectedObjects.getConstArray() ));
+ }
+ }
+ }
+ for (auto const& selectedElement : aSelectedElements)
+ {
+ if ( selectedElement.first == m_eCurrentType )
+ {
+ getContainer()->selectElements( comphelper::containerToSequence(selectedElement.second) );
+ }
+ else
+ {
+ m_aPendingSelection[ selectedElement.first ] = selectedElement.second;
+ }
+ }
+
+ m_aSelectContainerEvent.CancelCall(); // just in case the async select request was running
+ getContainer()->selectContainer( eSelectedCategory );
+
+ return true;
+}
+
+Any SAL_CALL OApplicationController::getSelection( )
+{
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( getMutex() );
+
+ Sequence< NamedDatabaseObject > aCurrentSelection;
+ const ElementType eType( getContainer()->getElementType() );
+ if ( eType != E_NONE )
+ {
+ getContainer()->describeCurrentSelectionForType( eType, aCurrentSelection );
+ if ( !aCurrentSelection.hasElements() )
+ { // if no objects are selected, add an entry to the sequence which describes the overall category
+ // which is selected currently
+ aCurrentSelection.realloc(1);
+ auto pCurrentSelection = aCurrentSelection.getArray();
+ pCurrentSelection[0].Name = getDatabaseName();
+ switch ( eType )
+ {
+ case E_TABLE: pCurrentSelection[0].Type = DatabaseObjectContainer::TABLES; break;
+ case E_QUERY: pCurrentSelection[0].Type = DatabaseObjectContainer::QUERIES; break;
+ case E_FORM: pCurrentSelection[0].Type = DatabaseObjectContainer::FORMS; break;
+ case E_REPORT: pCurrentSelection[0].Type = DatabaseObjectContainer::REPORTS; break;
+ default:
+ OSL_FAIL( "OApplicationController::getSelection: unexpected current element type!" );
+ break;
+ }
+ }
+ }
+ return Any( aCurrentSelection );
+}
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/app/AppController.hxx b/dbaccess/source/ui/app/AppController.hxx
new file mode 100644
index 000000000..b7579c0cf
--- /dev/null
+++ b/dbaccess/source/ui/app/AppController.hxx
@@ -0,0 +1,540 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <AppElementType.hxx>
+#include <callbacks.hxx>
+#include <commontypes.hxx>
+#include <dsntypes.hxx>
+#include <dbaccess/genericcontroller.hxx>
+#include <linkeddocuments.hxx>
+#include <TableCopyHelper.hxx>
+
+#include <com/sun/star/beans/XPropertyChangeListener.hpp>
+#include <com/sun/star/container/XContainerListener.hpp>
+#include <com/sun/star/sdb/application/XDatabaseDocumentUI.hpp>
+#include <com/sun/star/ui/XContextMenuInterception.hpp>
+
+#include <comphelper/namedvaluecollection.hxx>
+#include <comphelper/uno3.hxx>
+#include <cppuhelper/implbase5.hxx>
+#include <comphelper/interfacecontainer2.hxx>
+#include <vcl/transfer.hxx>
+#include <svx/dataaccessdescriptor.hxx>
+
+#include <memory>
+
+class TransferableHelper;
+class TransferableClipboardListener;
+
+namespace com::sun::star {
+ namespace container {
+ class XNameContainer;
+ class XContainer;
+ }
+ namespace ucb {
+ class XContent;
+ }
+}
+
+namespace svx
+{
+ class OComponentTransferable;
+}
+
+namespace weld
+{
+ class TreeView;
+}
+
+namespace dbaui
+{
+ class ODataClipboard;
+ class TreeListBox;
+ class SubComponentManager;
+ class OApplicationController;
+ class OApplicationView;
+ class OLinkedDocumentsAccess;
+ class SelectionNotifier;
+
+ typedef ::cppu::ImplHelper5 < css::container::XContainerListener
+ , css::beans::XPropertyChangeListener
+ , css::sdb::application::XDatabaseDocumentUI
+ , css::ui::XContextMenuInterception
+ , css::view::XSelectionSupplier
+ > OApplicationController_Base;
+
+
+ class OApplicationController
+ :public OGenericUnoController
+ ,public OApplicationController_Base
+ ,public IControlActionListener
+ ,public IContextMenuProvider
+ {
+ public:
+ typedef std::vector< css::uno::Reference< css::container::XContainer > > TContainerVector;
+
+ private:
+
+ OTableCopyHelper::DropDescriptor m_aAsyncDrop;
+
+ SharedConnection m_xDataSourceConnection;
+ css::uno::Reference< css::sdbc::XDatabaseMetaData >
+ m_xMetaData;
+
+ TransferableDataHelper m_aSystemClipboard; // content of the clipboard
+ css::uno::Reference< css::beans::XPropertySet >
+ m_xDataSource;
+ css::uno::Reference< css::frame::XModel >
+ m_xModel;
+ ::comphelper::OInterfaceContainerHelper2
+ m_aContextMenuInterceptors;
+
+ TContainerVector m_aCurrentContainers; // the containers where we are listener on
+ ::rtl::Reference< SubComponentManager >
+ m_pSubComponentManager;
+ ::dbaccess::ODsnTypeCollection
+ m_aTypeCollection;
+ OTableCopyHelper m_aTableCopyHelper;
+ rtl::Reference<TransferableClipboardListener>
+ m_pClipboardNotifier; // notifier for changes in the clipboard
+ ImplSVEvent * m_nAsyncDrop;
+ OAsynchronousLink m_aSelectContainerEvent;
+ PreviewMode m_ePreviewMode; // the mode of the preview
+ ElementType m_eCurrentType;
+ bool m_bNeedToReconnect; // true when the settings of the data source were modified and the connection is no longer up to date
+ bool m_bSuspended; // is true when the controller was already suspended
+
+ std::unique_ptr< SelectionNotifier >
+ m_pSelectionNotifier;
+ typedef std::map< ElementType, std::vector< OUString > > SelectionByElementType;
+ SelectionByElementType m_aPendingSelection;
+
+ private:
+
+ OApplicationView* getContainer() const;
+
+ /** returns the database name
+ @return
+ the database name
+ */
+ OUString getDatabaseName() const;
+
+ /** returns the stripped database name.
+ @return
+ The stripped database name either the registered name or if it is a file url the last segment.
+ */
+ OUString getStrippedDatabaseName() const;
+
+ /** return the element type for given container
+ @param _xContainer The container where the element type has to be found
+ @return the element type corresponding to the given container
+ */
+ static ElementType getElementType(const css::uno::Reference< css::container::XContainer >& _xContainer);
+
+ /** opens a new sub frame with a table/query/form/report/view, passing additional arguments
+ */
+ css::uno::Reference< css::lang::XComponent > openElementWithArguments(
+ const OUString& _sName,
+ ElementType _eType,
+ ElementOpenMode _eOpenMode,
+ sal_uInt16 _nInstigatorCommand,
+ const ::comphelper::NamedValueCollection& _rAdditionalArguments
+ );
+
+ /** opens a new frame for creation or auto pilot
+ @param _eType
+ Defines the type to open
+ @param i_rAdditionalArguments
+ Additional arguments to pass when creating the component
+ */
+ css::uno::Reference< css::lang::XComponent >
+ newElement(
+ ElementType _eType,
+ const ::comphelper::NamedValueCollection& i_rAdditionalArguments,
+ css::uno::Reference< css::lang::XComponent >& o_rDocumentDefinition
+ );
+
+ /** creates a new database object, using an auto pilot
+ @param _eType
+ Defines the type of the object to create
+ @precond
+ Our mutex must not be locked.
+ @since #i39203#
+ */
+ void newElementWithPilot( ElementType _eType );
+
+ /** converts the query to a view
+ @param _sName
+ The name of the query.
+ */
+ void convertToView(const OUString& _sName);
+
+ /** checks if the connection for the selected data source is read only. If the connection doesn't exist, <TRUE/> will be returned.
+ @return
+ <TRUE/> if read only or doesn't exist, otherwise <FALSE/>
+ */
+ bool isConnectionReadOnly() const;
+
+ /// fills the list with the selected entries.
+ void getSelectionElementNames( std::vector< OUString>& _rNames ) const;
+
+ /// deletes the entries selected.
+ void deleteEntries();
+
+ /// renames the selected entry in the detail page
+ void renameEntry();
+
+ /** deletes queries, forms, or reports
+ @param _eType
+ the type of the objects
+ @param _rList
+ The names of the elements to delete
+ @param _bConfirm
+ determines whether the user must confirm the deletion
+ */
+ void deleteObjects( ElementType _eType,
+ const std::vector< OUString>& _rList,
+ bool _bConfirm );
+
+ /** deletes tables.
+ @param _rList
+ The list of tables.
+ */
+ void deleteTables(const std::vector< OUString>& _rList);
+
+ /// copies the current object into clipboard
+ rtl::Reference<TransferableHelper> copyObject();
+
+ /// fills rExchange with current object if it's a Table or Query
+ bool copySQLObject(ODataClipboard& rExchange);
+
+ /// fills rExchange with current object if it's a Form or Report
+ bool copyDocObject(svx::OComponentTransferable& rExchange);
+
+ /// returns the nameaccess
+ css::uno::Reference< css::container::XNameAccess > getElements(ElementType _eType);
+
+ /** returns the document access for the specific type
+ @param _eType
+ the type
+ @return std::unique_ptr<OLinkedDocumentsAccess>
+ */
+ std::unique_ptr<OLinkedDocumentsAccess> getDocumentsAccess(ElementType _eType);
+
+ /// returns the query definitions of the active data source.
+ css::uno::Reference< css::container::XNameContainer> getQueryDefinitions() const;
+
+ /** pastes a special format from the system clipboard to the currently selected object types
+ @param _nFormatId
+ The format to be copied.
+ */
+ void pasteFormat(SotClipboardFormatId _nFormatId);
+
+ /** pastes a query, form or report into the data source
+ @param _eType
+ The type of the object to paste.
+ @param _rPasteData
+ The data descriptor.
+ @param _sParentFolder
+ The name of the parent folder if it exists.
+ @param _bMove
+ if <TRUE/> the name of the content must be inserted without any change, otherwise not.
+ @return
+ <TRUE/> if the paste operations was successful, otherwise <FALSE/>.
+ */
+ bool paste( ElementType _eType, const svx::ODataAccessDescriptor& _rPasteData, const OUString& _sParentFolder = OUString(), bool _bMove = false);
+
+ /// returns the system clipboard.
+ const TransferableDataHelper& getViewClipboard() const { return m_aSystemClipboard; }
+
+ /// returns <TRUE/> if the clipboard supports a table format, otherwise <FALSE/>.
+ bool isTableFormat() const;
+
+ /** fills the vector with all supported formats
+ @param _eType
+ The type for which we need the formats
+ @param _rFormatIds
+ The vector to be filled up.
+ */
+ static void getSupportedFormats(ElementType _eType,std::vector<SotClipboardFormatId>& _rFormatIds);
+
+ /** adds a listener to the current name access.
+ @param _xCollection
+ The collection where we want to listen on.
+ */
+ void addContainerListener(const css::uno::Reference< css::container::XNameAccess>& _xCollection);
+
+ /** opens a uno dialog with the currently selected data source as initialize argument
+ @param _sServiceName
+ The service name of the dialog to be executed.
+ */
+ void openDialog(const OUString& _sServiceName);
+
+ /** when the settings of the data source changed,
+ it opens a dialog which ask to close all depending documents, then recreate the connection.
+ The SolarMutex has to be locked before calling this.
+ */
+ void askToReconnect();
+
+ /** remember a newly opened sub document for later access
+ */
+ void onDocumentOpened(
+ const OUString& _rName,
+ const sal_Int32 _nType,
+ const ElementOpenMode _eMode,
+ const css::uno::Reference< css::lang::XComponent >& _xDocument,
+ const css::uno::Reference< css::lang::XComponent >& _xDefinition
+ );
+
+ /** Inserts a new object into the hierarchy given be the type.
+ @param _eType
+ Where to insert the new item.
+ @param _sParentFolder
+ The name of the parent folder if it exists.
+ @param _xContent
+ The content to insert.
+ @param _bMove
+ if <TRUE/> the name of the content must be inserted without any change, otherwise not.
+ @return
+ <TRUE/> if the insert operations was successful, otherwise <FALSE/>.
+ */
+ bool insertHierarchyElement( ElementType _eType
+ ,const OUString& _sParentFolder
+ ,bool _bCollection = true
+ ,const css::uno::Reference< css::ucb::XContent>& _xContent = css::uno::Reference< css::ucb::XContent>()
+ ,bool _bMove = false);
+ /** checks if delete command or rename command is allowed
+ @param _eType
+ The element type.
+ @param _bDelete
+ If <TRUE> then the delete command should be checked.
+ @return
+ <TRUE> if the command is allowed
+ */
+ bool isRenameDeleteAllowed(ElementType _eType, bool _bDelete) const;
+ /** all selected entries will be opened, or edited, or converted to a view
+ @param _nId
+ The slot which should be executed.
+ @param _eOpenMode
+ Defines the mode of opening. @see ElementOpenMode
+ */
+ void doAction(sal_uInt16 _nId, ElementOpenMode _eOpenMode);
+
+ /** returns the currently selected table or query name.
+ *
+ * \return the name of the currently table or query. If the tables or query container is selected otherwise an empty string will be returned.
+ */
+ OUString getCurrentlySelectedName(sal_Int32& _rnCommandType) const;
+
+ /** shows the preview for the given entry
+ */
+ void showPreviewFor( const ElementType _eType,const OUString& _sName );
+
+ /** called we were attached to a frame
+
+ In particular, this is called *after* the controller has been announced to the model
+ (XModel::connectController)
+ */
+ void onAttachedFrame();
+
+ /// determines whether the given table name denotes a view which can be altered
+ bool impl_isAlterableView_nothrow( const OUString& _rTableOrViewName ) const;
+
+ /** verifies the object type denotes a valid DatabaseObject, and the object name denotes an existing
+ object of this type. Throws if not.
+ */
+ void impl_validateObjectTypeAndName_throw( const sal_Int32 _nObjectType, const ::std::optional< OUString >& i_rObjectName );
+
+ protected:
+ // initializing members
+
+ // state of a feature. 'feature' may be the handle of a css::util::URL somebody requested a dispatch interface for OR a toolbar slot.
+ virtual FeatureState GetState(sal_uInt16 nId) const override;
+ // execute a feature
+ virtual void Execute(sal_uInt16 nId, const css::uno::Sequence< css::beans::PropertyValue>& aArgs) override;
+
+ // OGenericUnoController
+ virtual void onLoadedMenu( const css::uno::Reference< css::frame::XLayoutManager >& _xLayoutManager ) override;
+
+ virtual css::uno::Reference< css::frame::XModel > getPrivateModel() const override
+ {
+ return m_xModel;
+ }
+
+ virtual ~OApplicationController() override;
+
+ public:
+ explicit OApplicationController(const css::uno::Reference< css::uno::XComponentContext >& _rxORB);
+
+ DECLARE_XINTERFACE( )
+ DECLARE_XTYPEPROVIDER( )
+
+ // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual css::uno::Sequence< OUString> SAL_CALL getSupportedServiceNames() override;
+
+ // css::frame::XController
+ virtual void SAL_CALL attachFrame(const css::uno::Reference< css::frame::XFrame > & xFrame) override;
+ virtual sal_Bool SAL_CALL suspend(sal_Bool bSuspend) override;
+ virtual sal_Bool SAL_CALL attachModel(const css::uno::Reference< css::frame::XModel > & xModel) override;
+ virtual css::uno::Reference< css::frame::XModel > SAL_CALL getModel() override;
+
+ // css::container::XContainerListener
+ virtual void SAL_CALL elementInserted(const css::container::ContainerEvent& Event) override;
+ virtual void SAL_CALL elementRemoved(const css::container::ContainerEvent& Event) override;
+ virtual void SAL_CALL elementReplaced(const css::container::ContainerEvent& Event) override;
+
+ // XPropertyChangeListener
+ virtual void SAL_CALL propertyChange( const css::beans::PropertyChangeEvent& evt ) override;
+
+ // XDatabaseDocumentUI
+ virtual css::uno::Reference< css::sdbc::XDataSource > SAL_CALL getDataSource() override;
+ virtual css::uno::Reference< css::awt::XWindow > SAL_CALL getApplicationMainWindow() override;
+ virtual css::uno::Reference< css::sdbc::XConnection > SAL_CALL getActiveConnection() override;
+ virtual css::uno::Sequence< css::uno::Reference< css::lang::XComponent > > SAL_CALL getSubComponents() override;
+ virtual sal_Bool SAL_CALL isConnected( ) override;
+ // DO NOT CALL with getMutex() held!!
+ virtual void SAL_CALL connect( ) override;
+ virtual css::beans::Pair< ::sal_Int32, OUString > SAL_CALL identifySubComponent( const css::uno::Reference< css::lang::XComponent >& SubComponent ) override;
+ virtual sal_Bool SAL_CALL closeSubComponents( ) override;
+ virtual css::uno::Reference< css::lang::XComponent > SAL_CALL loadComponent( ::sal_Int32 ObjectType, const OUString& ObjectName, sal_Bool ForEditing ) override;
+ virtual css::uno::Reference< css::lang::XComponent > SAL_CALL loadComponentWithArguments( ::sal_Int32 ObjectType, const OUString& ObjectName, sal_Bool ForEditing, const css::uno::Sequence< css::beans::PropertyValue >& Arguments ) override;
+ virtual css::uno::Reference< css::lang::XComponent > SAL_CALL createComponent( ::sal_Int32 ObjectType, css::uno::Reference< css::lang::XComponent >& o_DocumentDefinition ) override;
+ virtual css::uno::Reference< css::lang::XComponent > SAL_CALL createComponentWithArguments( ::sal_Int32 ObjectType, const css::uno::Sequence< css::beans::PropertyValue >& Arguments, css::uno::Reference< css::lang::XComponent >& o_DocumentDefinition ) override;
+
+ // XContextMenuInterception
+ virtual void SAL_CALL registerContextMenuInterceptor( const css::uno::Reference< css::ui::XContextMenuInterceptor >& Interceptor ) override;
+ virtual void SAL_CALL releaseContextMenuInterceptor( const css::uno::Reference< css::ui::XContextMenuInterceptor >& Interceptor ) override;
+
+ // XSelectionSupplier
+ virtual sal_Bool SAL_CALL select( const css::uno::Any& xSelection ) override;
+ virtual css::uno::Any SAL_CALL getSelection( ) override;
+ virtual void SAL_CALL addSelectionChangeListener( const css::uno::Reference< css::view::XSelectionChangeListener >& xListener ) override;
+ virtual void SAL_CALL removeSelectionChangeListener( const css::uno::Reference< css::view::XSelectionChangeListener >& xListener ) override;
+
+ /** retrieves the current connection, creates it if necessary
+
+ If an error occurs, then this is either stored in the location pointed to by <arg>_pErrorInfo</arg>,
+ or, if <code>_pErrorInfo</code> is <NULL/>, then the error is displayed to the user.
+
+ DO NOT CALL with getMutex() held!!
+ */
+ const SharedConnection& ensureConnection( ::dbtools::SQLExceptionInfo* _pErrorInfo = nullptr );
+
+ /** retrieves the current connection
+ */
+ const SharedConnection& getConnection() const { return m_xDataSourceConnection; }
+
+ /// determines whether we're currently connected to the database
+ bool isConnected() const { return m_xDataSourceConnection.is(); }
+
+ /** refreshes the tables
+ */
+ void refreshTables();
+
+ /** called when an entry in a tree list box has been double-clicked
+ @param _rTree
+ The tree list box.
+ @return
+ <TRUE/> if the double click event has been handled by the called, and should not
+ be processed further.
+ */
+ bool onEntryDoubleClick(const weld::TreeView& rTree);
+
+ /** called when a container (category) in the application view has been selected
+ @param _pTree
+ The tree list box.
+ @return
+ <TRUE/> if the container could be changed otherwise <FALSE/>
+ */
+ bool onContainerSelect(ElementType _eType);
+
+ /** called when an entry in a tree view has been selected
+ @param _pEntry
+ the selected entry
+ */
+ void onSelectionChanged();
+
+ /** called when a "Copy" command is executed in a tree view
+ */
+ void onCopyEntry();
+
+ /** called when a "Paste" command is executed in a tree view
+ */
+ void onPasteEntry();
+
+ /** called when a "Delete" command is executed in a tree view
+ */
+ void onDeleteEntry();
+
+ /// called when the preview mode was changed
+ void previewChanged( sal_Int32 _nMode);
+
+ /// called when an object container of any kind was found during enumerating tree view elements
+ void containerFound( const css::uno::Reference< css::container::XContainer >& _xContainer);
+
+ // IController
+ virtual bool isDataSourceReadOnly() const override;
+
+ // IControlActionListener overridables
+ virtual bool requestQuickHelp(const void* pUserData, OUString& rText) const override;
+ virtual bool requestDrag(const weld::TreeIter& rEntry) override;
+ virtual sal_Int8 queryDrop( const AcceptDropEvent& _rEvt, const DataFlavorExVector& _rFlavors ) override;
+ virtual sal_Int8 executeDrop( const ExecuteDropEvent& _rEvt ) override;
+
+ // IContextMenuProvider
+ virtual OUString getContextMenuResourceName() const override;
+ virtual IController& getCommandController() override;
+ virtual ::comphelper::OInterfaceContainerHelper2*
+ getContextMenuInterceptors() override;
+ virtual css::uno::Any getCurrentSelection(weld::TreeView& rControl) const override;
+ virtual vcl::Window* getMenuParent() const override;
+ virtual void adjustMenuPosition(const weld::TreeView& rControl, ::Point& rPos) const override;
+
+ void OnInvalidateClipboard();
+ DECL_LINK( OnClipboardChanged, TransferableDataHelper*, void );
+ DECL_LINK( OnAsyncDrop, void*, void );
+ DECL_LINK( OnCreateWithPilot, void*, void );
+ DECL_LINK( OnSelectContainer, void*, void );
+ void OnFirstControllerConnected();
+
+ protected:
+ using OGenericUnoController::connect;
+
+ /** disconnects from our XConnection, and cleans up this connection
+ */
+ void disconnect();
+
+ // late construction
+ virtual bool Construct(vcl::Window* pParent) override;
+ virtual void describeSupportedFeatures() override;
+
+ protected:
+ // XEventListener
+ virtual void SAL_CALL disposing(const css::lang::EventObject& Source) override;
+
+ // OComponentHelper
+ virtual void SAL_CALL disposing() override;
+ };
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/app/AppControllerDnD.cxx b/dbaccess/source/ui/app/AppControllerDnD.cxx
new file mode 100644
index 000000000..3cc758acd
--- /dev/null
+++ b/dbaccess/source/ui/app/AppControllerDnD.cxx
@@ -0,0 +1,869 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <memory>
+#include "AppController.hxx"
+#include <comphelper/property.hxx>
+#include <core_resource.hxx>
+#include <strings.hxx>
+#include <com/sun/star/sdbcx/XDataDescriptorFactory.hpp>
+#include <com/sun/star/sdbcx/XAppend.hpp>
+#include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
+#include <com/sun/star/container/XNameContainer.hpp>
+#include <com/sun/star/frame/XStorable.hpp>
+#include <com/sun/star/container/XHierarchicalNameContainer.hpp>
+#include <com/sun/star/lang/XSingleServiceFactory.hpp>
+#include <com/sun/star/sdb/CommandType.hpp>
+#include <com/sun/star/sdb/SQLContext.hpp>
+#include <com/sun/star/sdbcx/XTablesSupplier.hpp>
+#include <com/sun/star/sdbcx/XViewsSupplier.hpp>
+#include <com/sun/star/sdb/XQueryDefinitionsSupplier.hpp>
+#include <com/sun/star/sdbcx/XDrop.hpp>
+#include <dlgsave.hxx>
+#include <vcl/weld.hxx>
+#include <cppuhelper/exc_hlp.hxx>
+#include <connectivity/dbexception.hxx>
+#include <sal/log.hxx>
+#include "AppView.hxx"
+#include <svx/dataaccessdescriptor.hxx>
+#include <svx/dbaobjectex.hxx>
+#include <strings.hrc>
+#include <vcl/svapp.hxx>
+#include <linkeddocuments.hxx>
+#include <connectivity/dbtools.hxx>
+#include <dbexchange.hxx>
+#include <UITools.hxx>
+#include <com/sun/star/sdb/XReportDocumentsSupplier.hpp>
+#include <com/sun/star/sdb/XFormDocumentsSupplier.hpp>
+#include <svtools/querydelete.hxx>
+#include <tools/diagnose_ex.h>
+#include <osl/diagnose.h>
+#include <defaultobjectnamecheck.hxx>
+#include <osl/mutex.hxx>
+#include "subcomponentmanager.hxx"
+#include <set>
+
+namespace dbaui
+{
+using namespace ::dbtools;
+using namespace ::svx;
+using namespace ::svtools;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::task;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::sdb;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::sdbcx;
+using namespace ::com::sun::star::frame;
+using namespace ::com::sun::star::ucb;
+using namespace ::com::sun::star::util;
+
+void OApplicationController::deleteTables(const std::vector< OUString>& _rList)
+{
+ SharedConnection xConnection( ensureConnection() );
+
+ Reference<XTablesSupplier> xSup(xConnection,UNO_QUERY);
+ OSL_ENSURE(xSup.is(),"OApplicationController::deleteTable: no XTablesSupplier!");
+ if ( !xSup.is() )
+ return;
+
+ Reference<XNameAccess> xTables = xSup->getTables();
+ Reference<XDrop> xDrop(xTables,UNO_QUERY);
+ if ( xDrop.is() )
+ {
+ bool bConfirm = true;
+ std::vector< OUString>::const_iterator aEnd = _rList.end();
+ for (std::vector< OUString>::const_iterator aIter = _rList.begin(); aIter != aEnd; ++aIter)
+ {
+ OUString sTableName = *aIter;
+
+ sal_Int32 nResult = RET_YES;
+ if ( bConfirm )
+ nResult = ::dbaui::askForUserAction(getFrameWeld(), STR_TITLE_CONFIRM_DELETION, STR_QUERY_DELETE_TABLE, _rList.size() > 1 && (aIter+1) != _rList.end(), sTableName);
+
+ bool bUserConfirmedDelete =
+ ( RET_YES == nResult )
+ || ( RET_ALL == nResult );
+ if ( bUserConfirmedDelete && m_pSubComponentManager->closeSubFrames( sTableName, E_TABLE ) )
+ {
+ SQLExceptionInfo aErrorInfo;
+ try
+ {
+ if ( xTables->hasByName(sTableName) )
+ xDrop->dropByName(sTableName);
+ else
+ {// could be a view
+ Reference<XViewsSupplier> xViewsSup(xConnection,UNO_QUERY);
+
+ Reference<XNameAccess> xViews;
+ if ( xViewsSup.is() )
+ {
+ xViews = xViewsSup->getViews();
+ if ( xViews.is() && xViews->hasByName(sTableName) )
+ {
+ xDrop.set(xViews,UNO_QUERY);
+ if ( xDrop.is() )
+ xDrop->dropByName(sTableName);
+ }
+ }
+ }
+ }
+ catch(SQLContext& e) { aErrorInfo = e; }
+ catch(SQLWarning& e) { aErrorInfo = e; }
+ catch(SQLException& e) { aErrorInfo = e; }
+ catch(WrappedTargetException& e)
+ {
+ SQLException aSql;
+ if(e.TargetException >>= aSql)
+ aErrorInfo = aSql;
+ else
+ OSL_FAIL("OApplicationController::implDropTable: something strange happened!");
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+
+ if ( aErrorInfo.isValid() )
+ showError(aErrorInfo);
+
+ if ( RET_ALL == nResult )
+ bConfirm = false;
+ }
+ else
+ break;
+ }
+ }
+ else
+ {
+ OUString sMessage(DBA_RES(STR_MISSING_TABLES_XDROP));
+ std::unique_ptr<weld::MessageDialog> xError(Application::CreateMessageDialog(getFrameWeld(),
+ VclMessageType::Warning, VclButtonsType::Ok,
+ sMessage));
+ xError->run();
+ }
+}
+
+void OApplicationController::deleteObjects( ElementType _eType, const std::vector< OUString>& _rList, bool _bConfirm )
+{
+ Reference< XNameContainer > xNames( getElements( _eType ), UNO_QUERY );
+ Reference< XHierarchicalNameContainer > xHierarchyName( xNames, UNO_QUERY );
+ if ( !xNames.is() )
+ return;
+
+ short eResult = _bConfirm ? svtools::QUERYDELETE_YES : svtools::QUERYDELETE_ALL;
+
+ // The list of elements to delete is allowed to contain related elements: A given element may
+ // be the ancestor or child of another element from the list.
+ // We want to ensure that ancestors get deleted first, so we normalize the list in this respect.
+ // #i33353#
+ // Note that this implicitly uses std::less< OUString > a comparison operation, which
+ // results in lexicographical order, which is exactly what we need, because "foo" is *before*
+ // any "foo/bar" in this order.
+ std::set< OUString > aDeleteNames(_rList.begin(), _rList.end());
+
+ std::set< OUString >::size_type nCount = aDeleteNames.size();
+ for ( std::set< OUString >::size_type nObjectsLeft = nCount; !aDeleteNames.empty(); )
+ {
+ std::set< OUString >::const_iterator aThisRound = aDeleteNames.begin();
+
+ if ( eResult != svtools::QUERYDELETE_ALL )
+ {
+ svtools::QueryDeleteDlg_Impl aDlg(getFrameWeld(), *aThisRound);
+
+ if ( nObjectsLeft > 1 )
+ aDlg.EnableAllButton();
+
+ eResult = aDlg.run();
+ }
+
+ bool bSuccess = false;
+
+ bool bUserConfirmedDelete =
+ ( eResult == svtools::QUERYDELETE_ALL )
+ || ( eResult == svtools::QUERYDELETE_YES );
+
+ if ( bUserConfirmedDelete
+ && ( _eType != E_QUERY || m_pSubComponentManager->closeSubFrames( *aThisRound, _eType ) )
+ )
+ {
+ try
+ {
+ if ( xHierarchyName.is() )
+ xHierarchyName->removeByHierarchicalName( *aThisRound );
+ else
+ xNames->removeByName( *aThisRound );
+
+ bSuccess = true;
+
+ // now that we removed the element, care for all its child elements
+ // which may also be a part of the list
+ // #i33353#
+ OSL_ENSURE( aThisRound->getLength() - 1 >= 0, "OApplicationController::deleteObjects: empty name?" );
+ OUString sSmallestSiblingName = *aThisRound + OUStringChar( sal_Unicode( '/' + 1) );
+
+ std::set< OUString >::const_iterator aUpperChildrenBound = aDeleteNames.lower_bound( sSmallestSiblingName );
+ for ( std::set< OUString >::const_iterator aObsolete = aThisRound;
+ aObsolete != aUpperChildrenBound;
+ )
+ {
+ std::set< OUString >::const_iterator aNextObsolete = aObsolete; ++aNextObsolete;
+ aDeleteNames.erase( aObsolete );
+ --nObjectsLeft;
+ aObsolete = aNextObsolete;
+ }
+ }
+ catch(const SQLException&)
+ {
+ showError( SQLExceptionInfo( ::cppu::getCaughtException() ) );
+ }
+ catch(const WrappedTargetException& e)
+ {
+ SQLException aSql;
+ if ( e.TargetException >>= aSql )
+ showError( SQLExceptionInfo( e.TargetException ) );
+ else
+ OSL_FAIL( "OApplicationController::deleteObjects: something strange happened!" );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+
+ if ( !bSuccess )
+ {
+ // okay, this object could not be deleted (or the user did not want to delete it),
+ // but continue with the rest
+ aDeleteNames.erase( aThisRound );
+ --nObjectsLeft;
+ }
+ }
+}
+
+void OApplicationController::deleteEntries()
+{
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( getMutex() );
+
+ if ( !getContainer() )
+ return;
+
+ std::vector< OUString> aList;
+ getSelectionElementNames(aList);
+ ElementType eType = getContainer()->getElementType();
+ switch(eType)
+ {
+ case E_TABLE:
+ deleteTables(aList);
+ break;
+ case E_QUERY:
+ deleteObjects( E_QUERY, aList, true );
+ break;
+ case E_FORM:
+ deleteObjects( E_FORM, aList, true );
+ break;
+ case E_REPORT:
+ deleteObjects( E_REPORT, aList, true );
+ break;
+ case E_NONE:
+ break;
+ }
+}
+
+// DO NOT CALL with getMutex() held!!
+const SharedConnection& OApplicationController::ensureConnection( ::dbtools::SQLExceptionInfo* _pErrorInfo )
+{
+
+ // This looks like double checked locking, but it is not,
+ // because every access (read *or* write) to m_xDataSourceConnection
+ // is mutexed.
+ // See http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html
+ // for what I'm referring to.
+ // We cannot use the TLS (thread-local storage) solution
+ // since support for TLS is not up to the snuff on Windows :-(
+
+ {
+ ::osl::MutexGuard aGuard( getMutex() );
+
+ if ( m_xDataSourceConnection.is() )
+ return m_xDataSourceConnection;
+ }
+
+ weld::WaitObject aWO(getFrameWeld());
+ Reference<XConnection> conn;
+ {
+ SolarMutexGuard aSolarGuard;
+
+ OUString sConnectingContext(DBA_RES(STR_COULDNOTCONNECT_DATASOURCE));
+ sConnectingContext = sConnectingContext.replaceFirst("$name$", getStrippedDatabaseName());
+
+ // do the connection *without* holding getMutex() to avoid deadlock
+ // when we are not in the main thread and we need username/password
+ // (and thus to display a dialog, which will be done by the main thread)
+ // and there is an event that needs getMutex() *before* us in the main thread's queue
+ // See fdo#63391
+ conn.set( connect( getDatabaseName(), sConnectingContext, _pErrorInfo ) );
+ }
+
+ if (conn.is())
+ {
+ ::osl::MutexGuard aGuard( getMutex() );
+ if ( m_xDataSourceConnection.is() )
+ {
+ Reference< XComponent > comp (conn, UNO_QUERY);
+ if(comp.is())
+ {
+ try
+ {
+ comp->dispose();
+ }
+ catch( const Exception& )
+ {
+ OSL_FAIL( "dbaui::OApplicationController::ensureConnection could not dispose of temporary unused connection" );
+ }
+ }
+ conn.clear();
+ }
+ else
+ {
+ m_xDataSourceConnection.reset(conn);
+ SQLExceptionInfo aError;
+ try
+ {
+ m_xMetaData = m_xDataSourceConnection->getMetaData();
+ }
+ catch( const SQLException& )
+ {
+ aError = ::cppu::getCaughtException();
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ if ( aError.isValid() )
+ {
+ if ( _pErrorInfo )
+ {
+ *_pErrorInfo = aError;
+ }
+ else
+ {
+ SolarMutexGuard aSolarGuard;
+ showError( aError );
+ }
+ }
+ }
+ }
+
+ return m_xDataSourceConnection;
+}
+
+bool OApplicationController::isDataSourceReadOnly() const
+{
+ Reference<XStorable> xStore(m_xModel,UNO_QUERY);
+ return !xStore.is() || xStore->isReadonly();
+}
+
+bool OApplicationController::isConnectionReadOnly() const
+{
+ bool bIsConnectionReadOnly = true;
+ if ( m_xMetaData.is() )
+ {
+ try
+ {
+ bIsConnectionReadOnly = m_xMetaData->isReadOnly();
+ }
+ catch(const SQLException&)
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+ // TODO check configuration
+ return bIsConnectionReadOnly;
+}
+
+Reference< XNameAccess > OApplicationController::getElements( ElementType _eType )
+{
+ Reference< XNameAccess > xElements;
+ try
+ {
+ switch ( _eType )
+ {
+ case E_REPORT:
+ {
+ Reference< XReportDocumentsSupplier > xSupp( m_xModel, UNO_QUERY_THROW );
+ xElements.set( xSupp->getReportDocuments(), UNO_SET_THROW );
+ }
+ break;
+
+ case E_FORM:
+ {
+ Reference< XFormDocumentsSupplier > xSupp( m_xModel, UNO_QUERY_THROW );
+ xElements.set( xSupp->getFormDocuments(), UNO_SET_THROW );
+ }
+ break;
+
+ case E_QUERY:
+ {
+ xElements.set( getQueryDefinitions(), UNO_QUERY_THROW );
+ }
+ break;
+
+ case E_TABLE:
+ {
+ if ( m_xDataSourceConnection.is() )
+ {
+ Reference< XTablesSupplier > xSup( getConnection(), UNO_QUERY_THROW );
+ xElements.set( xSup->getTables(), UNO_SET_THROW );
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+ catch(const Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+
+ return xElements;
+}
+
+void OApplicationController::getSelectionElementNames(std::vector< OUString>& _rNames) const
+{
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( getMutex() );
+
+ OSL_ENSURE(getContainer(),"View isn't valid! -> GPF");
+
+ getContainer()->getSelectionElementNames( _rNames );
+}
+
+std::unique_ptr< OLinkedDocumentsAccess > OApplicationController::getDocumentsAccess( ElementType _eType )
+{
+ OSL_ENSURE( ( _eType == E_TABLE ) || ( _eType == E_QUERY ) || ( _eType == E_FORM ) || ( _eType == E_REPORT ),
+ "OApplicationController::getDocumentsAccess: only forms and reports are supported here!" );
+
+ SharedConnection xConnection( ensureConnection() );
+ Reference< XNameAccess > xDocContainer;
+
+ if ( ( _eType == E_FORM ) || ( _eType == E_REPORT ) )
+ {
+ xDocContainer.set( getElements( _eType ) );
+ OSL_ENSURE( xDocContainer.is(), "OApplicationController::getDocumentsAccess: invalid container!" );
+ }
+
+ std::unique_ptr< OLinkedDocumentsAccess > pDocuments( new OLinkedDocumentsAccess(
+ getFrameWeld(), this, getORB(), xDocContainer, xConnection, getDatabaseName()
+ ) );
+ return pDocuments;
+}
+
+bool OApplicationController::copySQLObject(ODataClipboard& rExchange)
+{
+ bool bSuccess = false;
+ try
+ {
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( getMutex() );
+
+ ElementType eType = getContainer()->getElementType();
+ switch( eType )
+ {
+ case E_TABLE:
+ case E_QUERY:
+ {
+ SharedConnection xConnection( ensureConnection() );
+ Reference< XDatabaseMetaData> xMetaData;
+ if ( xConnection.is() )
+ xMetaData = xConnection->getMetaData();
+
+ OUString sName = getContainer()->getQualifiedName( nullptr );
+ if ( !sName.isEmpty() )
+ {
+ OUString sDataSource = getDatabaseName();
+
+ if ( eType == E_TABLE )
+ {
+ rExchange.Update(sDataSource, CommandType::TABLE, sName, xConnection, getNumberFormatter(xConnection, getORB()), getORB());
+ }
+ else
+ {
+ rExchange.Update(sDataSource, CommandType::QUERY, sName, getNumberFormatter(xConnection, getORB()), getORB());
+ }
+ bSuccess = true;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ catch(const SQLException&)
+ {
+ showError( SQLExceptionInfo( ::cppu::getCaughtException() ) );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ return bSuccess;
+}
+
+bool OApplicationController::copyDocObject(svx::OComponentTransferable& rExchange)
+{
+ bool bSuccess = false;
+ try
+ {
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( getMutex() );
+
+ ElementType eType = getContainer()->getElementType();
+ switch( eType )
+ {
+ case E_FORM:
+ case E_REPORT:
+ {
+ std::vector< OUString> aList;
+ getSelectionElementNames(aList);
+ Reference< XHierarchicalNameAccess > xElements(getElements(eType),UNO_QUERY);
+ if ( xElements.is() && !aList.empty() )
+ {
+ Reference< XContent> xContent(xElements->getByHierarchicalName(*aList.begin()),UNO_QUERY);
+ rExchange.Update(getDatabaseName(), xContent);
+ bSuccess = true;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ catch(const SQLException&)
+ {
+ showError( SQLExceptionInfo( ::cppu::getCaughtException() ) );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ return bSuccess;
+}
+
+rtl::Reference<TransferableHelper> OApplicationController::copyObject()
+{
+ try
+ {
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( getMutex() );
+
+ ElementType eType = getContainer()->getElementType();
+ switch( eType )
+ {
+ case E_TABLE:
+ case E_QUERY:
+ {
+ rtl::Reference<ODataClipboard> xExchange(new ODataClipboard);
+ if (copySQLObject(*xExchange))
+ return xExchange;
+ break;
+ }
+ case E_FORM:
+ case E_REPORT:
+ {
+ rtl::Reference<svx::OComponentTransferable> xExchange(new svx::OComponentTransferable);
+ if (copyDocObject(*xExchange))
+ return xExchange;
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ catch(const SQLException&)
+ {
+ showError( SQLExceptionInfo( ::cppu::getCaughtException() ) );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ return nullptr;
+}
+
+bool OApplicationController::paste( ElementType _eType, const svx::ODataAccessDescriptor& _rPasteData, const OUString& _sParentFolder, bool _bMove)
+{
+ try
+ {
+ if ( _eType == E_QUERY )
+ {
+ sal_Int32 nCommandType = CommandType::TABLE;
+ if ( _rPasteData.has(DataAccessDescriptorProperty::CommandType) )
+ _rPasteData[DataAccessDescriptorProperty::CommandType] >>= nCommandType;
+
+ if ( CommandType::QUERY == nCommandType || CommandType::COMMAND == nCommandType )
+ {
+ // read all necessary data
+
+ OUString sCommand;
+ bool bEscapeProcessing = true;
+
+ _rPasteData[DataAccessDescriptorProperty::Command] >>= sCommand;
+ if ( _rPasteData.has(DataAccessDescriptorProperty::EscapeProcessing) )
+ _rPasteData[DataAccessDescriptorProperty::EscapeProcessing] >>= bEscapeProcessing;
+
+ // plausibility check
+ bool bValidDescriptor = false;
+ OUString sDataSourceName = _rPasteData.getDataSource();
+ if (CommandType::QUERY == nCommandType)
+ bValidDescriptor = sDataSourceName.getLength() && sCommand.getLength();
+ else if (CommandType::COMMAND == nCommandType)
+ bValidDescriptor = !sCommand.isEmpty();
+ if (!bValidDescriptor)
+ {
+ OSL_FAIL("OApplicationController::paste: invalid descriptor!");
+ return false;
+ }
+
+ // the target object name (as we'll suggest it to the user)
+ OUString sTargetName;
+ try
+ {
+ if ( CommandType::QUERY == nCommandType )
+ sTargetName = sCommand;
+
+ if ( sTargetName.isEmpty() )
+ {
+ OUString sDefaultName = DBA_RES(STR_QRY_TITLE);
+ sDefaultName = sDefaultName.getToken( 0, ' ' );
+
+ Reference< XNameAccess > xQueries( getQueryDefinitions(), UNO_QUERY_THROW );
+ sTargetName = ::dbtools::createUniqueName( xQueries, sDefaultName, false );
+ }
+ }
+ catch(const Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+
+ Reference< XPropertySet > xQuery;
+ if (CommandType::QUERY == nCommandType)
+ {
+ // need to extract the statement and the escape processing flag from the query object
+ bool bSuccess = false;
+ try
+ {
+ // the concrete query
+ Reference< XQueryDefinitionsSupplier > xSourceQuerySup(
+ getDataSourceByName( sDataSourceName, getFrameWeld(), getORB(), nullptr ),
+ UNO_QUERY_THROW );
+ Reference< XNameAccess > xQueries( xSourceQuerySup->getQueryDefinitions(), UNO_SET_THROW );
+ if ( xQueries->hasByName( sCommand ) )
+ {
+ xQuery.set( xQueries->getByName(sCommand), UNO_QUERY_THROW );
+ bSuccess = true;
+ }
+ }
+ catch(SQLException&) { throw; } // caught and handled by the outer catch
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+
+ if (!bSuccess)
+ {
+ OSL_FAIL("OApplicationController::paste: could not extract the source query object!");
+ // TODO: maybe this is worth an error message to be displayed to the user...
+ return false;
+ }
+ }
+
+ Reference< XNameContainer > xDestQueries = getQueryDefinitions();
+ Reference< XSingleServiceFactory > xQueryFactory(xDestQueries, UNO_QUERY);
+ if (!xQueryFactory.is())
+ {
+ OSL_FAIL("OApplicationController::paste: invalid destination query container!");
+ return false;
+ }
+
+ // here we have everything needed to create a new query object...
+ // ... ehm, except a new name
+ ensureConnection();
+
+ DynamicTableOrQueryNameCheck aNameChecker( getConnection(), CommandType::QUERY );
+ ::dbtools::SQLExceptionInfo aDummy;
+ bool bNeedAskForName = ( sCommand.isEmpty() )
+ /* we did not have a source name, so the target name was auto-generated */
+ || ( !aNameChecker.isNameValid( sTargetName, aDummy ) );
+ /* name is invalid in the target DB (e.g. because it already
+ has a /table/ with that name) */
+ if ( bNeedAskForName )
+ {
+ OSaveAsDlg aAskForName(getFrameWeld(),
+ CommandType::QUERY,
+ getORB(),
+ getConnection(),
+ sTargetName,
+ aNameChecker,
+ SADFlags::AdditionalDescription | SADFlags::TitlePasteAs );
+ if ( RET_OK != aAskForName.run() )
+ // cancelled by the user
+ return false;
+ sTargetName = aAskForName.getName();
+ }
+
+ // create a new object
+ Reference< XPropertySet > xNewQuery(xQueryFactory->createInstance(), UNO_QUERY);
+ OSL_ENSURE(xNewQuery.is(), "OApplicationController::paste: invalid object created by factory!");
+ if (xNewQuery.is())
+ {
+ // initialize
+ if ( xQuery.is() )
+ ::comphelper::copyProperties(xQuery,xNewQuery);
+ else
+ {
+ xNewQuery->setPropertyValue(PROPERTY_COMMAND,Any(sCommand));
+ xNewQuery->setPropertyValue(PROPERTY_ESCAPE_PROCESSING,Any(bEscapeProcessing));
+ }
+ // insert
+ xDestQueries->insertByName( sTargetName, Any(xNewQuery) );
+ xNewQuery.set(xDestQueries->getByName( sTargetName),UNO_QUERY);
+ if ( xQuery.is() && xNewQuery.is() )
+ {
+ Reference<XColumnsSupplier> xSrcColSup(xQuery,UNO_QUERY);
+ Reference<XColumnsSupplier> xDstColSup(xNewQuery,UNO_QUERY);
+ if ( xSrcColSup.is() && xDstColSup.is() )
+ {
+ Reference<XNameAccess> xSrcNameAccess = xSrcColSup->getColumns();
+ Reference<XNameAccess> xDstNameAccess = xDstColSup->getColumns();
+ Reference<XDataDescriptorFactory> xFac(xDstNameAccess,UNO_QUERY);
+ Reference<XAppend> xAppend(xFac,UNO_QUERY);
+ if ( xSrcNameAccess.is() && xDstNameAccess.is() && xSrcNameAccess->hasElements() && xAppend.is() )
+ {
+ Reference<XPropertySet> xDstProp(xFac->createDataDescriptor());
+
+ Sequence< OUString> aSeq = xSrcNameAccess->getElementNames();
+ const OUString* pIter = aSeq.getConstArray();
+ const OUString* pEnd = pIter + aSeq.getLength();
+ for( ; pIter != pEnd ; ++pIter)
+ {
+ Reference<XPropertySet> xSrcProp(xSrcNameAccess->getByName(*pIter),UNO_QUERY);
+ ::comphelper::copyProperties(xSrcProp,xDstProp);
+ xAppend->appendByDescriptor(xDstProp);
+ }
+ }
+ }
+ }
+ }
+ }
+ else
+ SAL_WARN("dbaccess", "There should be a sequence in it!");
+ return true;
+ }
+ else if ( _rPasteData.has(DataAccessDescriptorProperty::Component) ) // forms or reports
+ {
+ Reference<XContent> xContent;
+ _rPasteData[DataAccessDescriptorProperty::Component] >>= xContent;
+ return insertHierarchyElement(_eType,_sParentFolder,Reference<XNameAccess>(xContent,UNO_QUERY).is(),xContent,_bMove);
+ }
+ }
+ catch(const SQLException&) { showError( SQLExceptionInfo( ::cppu::getCaughtException() ) ); }
+ catch(const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ return false;
+}
+
+Reference<XNameContainer> OApplicationController::getQueryDefinitions() const
+{
+ Reference<XQueryDefinitionsSupplier> xSet(m_xDataSource,UNO_QUERY);
+ Reference<XNameContainer> xNames;
+ if ( xSet.is() )
+ {
+ xNames.set(xSet->getQueryDefinitions(),UNO_QUERY);
+ }
+ return xNames;
+}
+
+void OApplicationController::getSupportedFormats(ElementType _eType,std::vector<SotClipboardFormatId>& _rFormatIds)
+{
+ switch( _eType )
+ {
+ case E_TABLE:
+ _rFormatIds.push_back(SotClipboardFormatId::DBACCESS_TABLE);
+ _rFormatIds.push_back(SotClipboardFormatId::RTF);
+ _rFormatIds.push_back(SotClipboardFormatId::HTML);
+ [[fallthrough]];
+ case E_QUERY:
+ _rFormatIds.push_back(SotClipboardFormatId::DBACCESS_QUERY);
+ break;
+ default:
+ break;
+ }
+}
+
+bool OApplicationController::isTableFormat() const
+{
+ return OTableCopyHelper::isTableFormat(getViewClipboard());
+}
+
+IMPL_LINK_NOARG( OApplicationController, OnAsyncDrop, void*, void )
+{
+ m_nAsyncDrop = nullptr;
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( getMutex() );
+
+ if ( m_aAsyncDrop.nType == E_TABLE )
+ {
+ SharedConnection xConnection( ensureConnection() );
+ if ( xConnection.is() )
+ m_aTableCopyHelper.asyncCopyTagTable( m_aAsyncDrop, getDatabaseName(), xConnection );
+ }
+ else
+ {
+ if ( paste(m_aAsyncDrop.nType,m_aAsyncDrop.aDroppedData,m_aAsyncDrop.aUrl,m_aAsyncDrop.nAction == DND_ACTION_MOVE)
+ && m_aAsyncDrop.nAction == DND_ACTION_MOVE )
+ {
+ Reference<XContent> xContent;
+ m_aAsyncDrop.aDroppedData[DataAccessDescriptorProperty::Component] >>= xContent;
+ std::vector< OUString> aList;
+ sal_Int32 nIndex = 0;
+ OUString sName = xContent->getIdentifier()->getContentIdentifier();
+ std::u16string_view sErase = o3tl::getToken(sName,0,'/',nIndex); // we don't want to have the "private:forms" part
+ if ( nIndex != -1 )
+ {
+ aList.push_back(sName.copy(sErase.size() + 1));
+ deleteObjects( m_aAsyncDrop.nType, aList, false );
+ }
+ }
+ }
+
+ m_aAsyncDrop.aDroppedData.clear();
+}
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/app/AppControllerGen.cxx b/dbaccess/source/ui/app/AppControllerGen.cxx
new file mode 100644
index 000000000..22dfb3663
--- /dev/null
+++ b/dbaccess/source/ui/app/AppControllerGen.cxx
@@ -0,0 +1,736 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "AppController.hxx"
+#include "AppDetailView.hxx"
+#include "AppView.hxx"
+#include <core_resource.hxx>
+#include <dbaccess_slotid.hrc>
+#include <strings.hrc>
+#include <strings.hxx>
+#include <defaultobjectnamecheck.hxx>
+#include <dlgsave.hxx>
+#include <UITools.hxx>
+#include "subcomponentmanager.hxx"
+
+#include <com/sun/star/container/XChild.hpp>
+#include <com/sun/star/container/XContainer.hpp>
+#include <com/sun/star/container/XHierarchicalNameContainer.hpp>
+#include <com/sun/star/container/XNameAccess.hpp>
+#include <com/sun/star/sdb/CommandType.hpp>
+#include <com/sun/star/sdb/XQueriesSupplier.hpp>
+#include <com/sun/star/sdbcx/XRename.hpp>
+#include <com/sun/star/sdb/ErrorCondition.hpp>
+#include <com/sun/star/sdb/application/DatabaseObject.hpp>
+#include <com/sun/star/sdbcx/XTablesSupplier.hpp>
+#include <com/sun/star/ui/dialogs/XExecutableDialog.hpp>
+#include <com/sun/star/util/XRefreshable.hpp>
+
+#include <cppuhelper/exc_hlp.hxx>
+#include <comphelper/types.hxx>
+#include <connectivity/dbexception.hxx>
+#include <connectivity/dbtools.hxx>
+#include <connectivity/sqlerror.hxx>
+#include <sfx2/mailmodelapi.hxx>
+#include <svx/dbaexchange.hxx>
+#include <toolkit/helper/vclunohelper.hxx>
+#include <tools/diagnose_ex.h>
+#include <osl/diagnose.h>
+#include <vcl/mnemonic.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/syswin.hxx>
+#include <vcl/weld.hxx>
+#include <osl/mutex.hxx>
+
+namespace dbaui
+{
+using namespace ::dbtools;
+using namespace ::connectivity;
+using namespace ::svx;
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::awt;
+using namespace ::com::sun::star::util;
+using namespace ::com::sun::star::frame;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::ui::dialogs;
+using namespace ::com::sun::star::sdb;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::sdbcx;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::ucb;
+
+using ::com::sun::star::ui::XContextMenuInterceptor;
+
+namespace DatabaseObject = ::com::sun::star::sdb::application::DatabaseObject;
+namespace ErrorCondition = ::com::sun::star::sdb::ErrorCondition;
+
+void OApplicationController::convertToView(const OUString& _sName)
+{
+ try
+ {
+ SharedConnection xConnection( getConnection() );
+ Reference< XQueriesSupplier > xSup( xConnection, UNO_QUERY_THROW );
+ Reference< XNameAccess > xQueries( xSup->getQueries(), UNO_SET_THROW );
+ Reference< XPropertySet > xSourceObject( xQueries->getByName( _sName ), UNO_QUERY_THROW );
+
+ Reference< XTablesSupplier > xTablesSup( xConnection, UNO_QUERY_THROW );
+ Reference< XNameAccess > xTables( xTablesSup->getTables(), UNO_SET_THROW );
+
+ Reference< XDatabaseMetaData > xMeta = xConnection->getMetaData();
+
+ const OUString aDefaultName = ::dbaui::createDefaultName(xMeta, xTables, DBA_RES(STR_TBL_TITLE).getToken(0, ' '));
+
+ DynamicTableOrQueryNameCheck aNameChecker( xConnection, CommandType::TABLE );
+ OSaveAsDlg aDlg(getFrameWeld(), CommandType::TABLE, getORB(), xConnection, aDefaultName, aNameChecker, SADFlags::NONE);
+ if (aDlg.run() == RET_OK)
+ {
+ OUString sName = aDlg.getName();
+ OUString sCatalog = aDlg.getCatalog();
+ OUString sSchema = aDlg.getSchema();
+ OUString sNewName(
+ ::dbtools::composeTableName( xMeta, sCatalog, sSchema, sName, false, ::dbtools::EComposeRule::InTableDefinitions ) );
+ Reference<XPropertySet> xView = ::dbaui::createView(sNewName,xConnection,xSourceObject);
+ if ( !xView.is() )
+ throw SQLException(DBA_RES(STR_NO_TABLE_FORMAT_INSIDE),*this, "S1000",0,Any());
+ getContainer()->elementAdded(E_TABLE,sNewName,Any(xView));
+ }
+ }
+ catch(const SQLException& )
+ {
+ showError( SQLExceptionInfo( ::cppu::getCaughtException() ) );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+}
+
+void OApplicationController::pasteFormat(SotClipboardFormatId _nFormatId)
+{
+ if ( _nFormatId == SotClipboardFormatId::NONE )
+ return;
+
+ try
+ {
+ const TransferableDataHelper& rClipboard = getViewClipboard();
+ ElementType eType = getContainer()->getElementType();
+ if ( eType == E_TABLE )
+ {
+ m_aTableCopyHelper.pasteTable( _nFormatId, rClipboard, getDatabaseName(), ensureConnection() );
+ }
+ else
+ paste( eType, ODataAccessObjectTransferable::extractObjectDescriptor( rClipboard ) );
+
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+}
+
+void OApplicationController::openDialog( const OUString& _sServiceName )
+{
+ try
+ {
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( getMutex() );
+ weld::WaitObject aWO(getFrameWeld());
+
+ Sequence< Any > aArgs(3);
+ auto pArgs = aArgs.getArray();
+ sal_Int32 nArgPos = 0;
+
+ Reference< css::awt::XWindow> xWindow = getTopMostContainerWindow();
+ if ( !xWindow.is() )
+ {
+ OSL_ENSURE( getContainer(), "OApplicationController::Construct: have no view!" );
+ if ( getContainer() )
+ xWindow = VCLUnoHelper::GetInterface(getView()->Window::GetParent());
+ }
+ // the parent window
+ pArgs[nArgPos++] <<= PropertyValue( "ParentWindow",
+ 0,
+ Any(xWindow),
+ PropertyState_DIRECT_VALUE);
+
+ // the initial selection
+ OUString sInitialSelection;
+ if ( getContainer() )
+ sInitialSelection = getDatabaseName();
+ if ( !sInitialSelection.isEmpty() )
+ {
+ pArgs[ nArgPos++ ] <<= PropertyValue(
+ "InitialSelection", 0,
+ Any( sInitialSelection ), PropertyState_DIRECT_VALUE );
+ }
+
+ SharedConnection xConnection( getConnection() );
+ if ( xConnection.is() )
+ {
+ pArgs[ nArgPos++ ] <<= PropertyValue(
+ PROPERTY_ACTIVE_CONNECTION, 0,
+ makeAny( xConnection ), PropertyState_DIRECT_VALUE );
+ }
+ aArgs.realloc( nArgPos );
+
+ // create the dialog
+ Reference< XExecutableDialog > xAdminDialog;
+ xAdminDialog.set(
+ getORB()->getServiceManager()->createInstanceWithArgumentsAndContext(_sServiceName, aArgs, getORB()),
+ UNO_QUERY);
+
+ // execute it
+ if (xAdminDialog.is())
+ xAdminDialog->execute();
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+}
+
+void OApplicationController::refreshTables()
+{
+ if ( !(getContainer() && getContainer()->getDetailView()) )
+ return;
+
+ weld::WaitObject aWO(getFrameWeld());
+ OSL_ENSURE(getContainer()->getElementType() == E_TABLE,"Only allowed when the tables container is selected!");
+ try
+ {
+ Reference<XRefreshable> xRefresh(getElements(E_TABLE),UNO_QUERY);
+ if ( xRefresh.is() )
+ xRefresh->refresh();
+ }
+ catch(const Exception&)
+ {
+ OSL_FAIL("Could not refresh tables!");
+ }
+
+ getContainer()->getDetailView()->clearPages(false);
+ getContainer()->getDetailView()->createTablesPage( ensureConnection() );
+}
+
+void SAL_CALL OApplicationController::propertyChange( const PropertyChangeEvent& evt )
+{
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( getMutex() );
+ if ( evt.PropertyName == PROPERTY_USER )
+ {
+ m_bNeedToReconnect = true;
+ InvalidateFeature(SID_DB_APP_STATUS_USERNAME);
+ }
+ else if ( evt.PropertyName == PROPERTY_URL )
+ {
+ m_bNeedToReconnect = true;
+ InvalidateFeature(SID_DB_APP_STATUS_DBNAME);
+ InvalidateFeature(SID_DB_APP_STATUS_TYPE);
+ InvalidateFeature(SID_DB_APP_STATUS_HOSTNAME);
+ }
+ else if ( PROPERTY_NAME == evt.PropertyName )
+ {
+ const ElementType eType = getContainer()->getElementType();
+ if ( eType == E_FORM || eType == E_REPORT )
+ {
+ OUString sOldName,sNewName;
+ evt.OldValue >>= sOldName;
+ evt.NewValue >>= sNewName;
+
+ // if the old name is empty, then this is a newly inserted content. We're notified of it via the
+ // elementInserted method, so there's no need to handle it here.
+
+ if ( !sOldName.isEmpty() )
+ {
+ Reference<XChild> xChild(evt.Source,UNO_QUERY);
+ if ( xChild.is() )
+ {
+ Reference<XContent> xContent(xChild->getParent(),UNO_QUERY);
+ if ( xContent.is() )
+ sOldName = xContent->getIdentifier()->getContentIdentifier() + "/" + sOldName;
+ }
+
+ getContainer()->elementReplaced( eType , sOldName, sNewName );
+ }
+ }
+ }
+
+ EventObject aEvt;
+ aEvt.Source = m_xModel;
+ modified(aEvt);
+}
+
+Reference< XDataSource > SAL_CALL OApplicationController::getDataSource()
+{
+ ::osl::MutexGuard aGuard( getMutex() );
+ Reference< XDataSource > xDataSource( m_xDataSource, UNO_QUERY );
+ return xDataSource;
+}
+
+Reference< XWindow > SAL_CALL OApplicationController::getApplicationMainWindow()
+{
+ ::osl::MutexGuard aGuard( getMutex() );
+ Reference< XFrame > xFrame( getFrame(), UNO_SET_THROW );
+ Reference< XWindow > xWindow( xFrame->getContainerWindow(), UNO_SET_THROW );
+ return xWindow;
+}
+
+Sequence< Reference< XComponent > > SAL_CALL OApplicationController::getSubComponents()
+{
+ ::osl::MutexGuard aGuard( getMutex() );
+ return m_pSubComponentManager->getSubComponents();
+}
+
+Reference< XConnection > SAL_CALL OApplicationController::getActiveConnection()
+{
+ ::osl::MutexGuard aGuard( getMutex() );
+ return m_xDataSourceConnection.getTyped();
+}
+
+sal_Bool SAL_CALL OApplicationController::isConnected( )
+{
+ ::osl::MutexGuard aGuard( getMutex() );
+ return m_xDataSourceConnection.is();
+}
+
+void SAL_CALL OApplicationController::connect( )
+{
+ SQLExceptionInfo aError;
+ SharedConnection xConnection = ensureConnection( &aError );
+ if ( !xConnection.is() )
+ {
+ if ( aError.isValid() )
+ aError.doThrow();
+
+ // no particular error, but nonetheless could not connect -> throw a generic exception
+ OUString sConnectingContext( DBA_RES( STR_COULDNOTCONNECT_DATASOURCE ) );
+ ::dbtools::throwGenericSQLException( sConnectingContext.replaceFirst( "$name$", getStrippedDatabaseName() ), *this );
+ }
+}
+
+beans::Pair< ::sal_Int32, OUString > SAL_CALL OApplicationController::identifySubComponent( const Reference< XComponent >& i_rSubComponent )
+{
+ ::osl::MutexGuard aGuard( getMutex() );
+
+ sal_Int32 nType = -1;
+ OUString sName;
+
+ if ( !m_pSubComponentManager->lookupSubComponent( i_rSubComponent, sName, nType ) )
+ throw IllegalArgumentException( OUString(), *this, 1 );
+
+ if ( nType == SID_DB_APP_DSRELDESIGN )
+ // this is somewhat hacky ... we're expected to return a DatabaseObject value. However, there is no such
+ // value for the relation design. /me thinks we should change the API definition here ...
+ nType = -1;
+
+ return beans::Pair< ::sal_Int32, OUString >( nType, sName );
+}
+
+sal_Bool SAL_CALL OApplicationController::closeSubComponents( )
+{
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( getMutex() );
+ return m_pSubComponentManager->closeSubComponents();
+}
+
+namespace
+{
+ ElementType lcl_objectType2ElementType( const sal_Int32 _nObjectType )
+ {
+ ElementType eType( E_NONE );
+ switch ( _nObjectType )
+ {
+ case DatabaseObject::TABLE: eType = E_TABLE; break;
+ case DatabaseObject::QUERY: eType = E_QUERY; break;
+ case DatabaseObject::FORM: eType = E_FORM; break;
+ case DatabaseObject::REPORT: eType = E_REPORT; break;
+ default:
+ OSL_FAIL( "lcl_objectType2ElementType: unsupported object type!" );
+ // this should have been caught earlier
+ }
+ return eType;
+ }
+}
+
+void OApplicationController::impl_validateObjectTypeAndName_throw( const sal_Int32 _nObjectType, const ::std::optional< OUString >& i_rObjectName )
+{
+ // ensure we're connected
+ if ( !isConnected() )
+ {
+ SQLError aError;
+ aError.raiseException( ErrorCondition::DB_NOT_CONNECTED, *this );
+ }
+
+ // ensure a proper object type
+ if ( ( _nObjectType != DatabaseObject::TABLE )
+ && ( _nObjectType != DatabaseObject::QUERY )
+ && ( _nObjectType != DatabaseObject::FORM )
+ && ( _nObjectType != DatabaseObject::REPORT )
+ )
+ throw IllegalArgumentException( OUString(), *this, 1 );
+
+ if ( !i_rObjectName )
+ return;
+
+ // ensure an existing object
+ Reference< XNameAccess > xContainer( getElements( lcl_objectType2ElementType( _nObjectType ) ) );
+ if ( !xContainer.is() )
+ // all possible reasons for this (e.g. not being connected currently) should
+ // have been handled before
+ throw RuntimeException( OUString(), *this );
+
+ bool bExistentObject = false;
+ switch ( _nObjectType )
+ {
+ case DatabaseObject::TABLE:
+ case DatabaseObject::QUERY:
+ bExistentObject = xContainer->hasByName( *i_rObjectName );
+ break;
+ case DatabaseObject::FORM:
+ case DatabaseObject::REPORT:
+ {
+ Reference< XHierarchicalNameAccess > xHierarchy( xContainer, UNO_QUERY_THROW );
+ bExistentObject = xHierarchy->hasByHierarchicalName( *i_rObjectName );
+ }
+ break;
+ }
+
+ if ( !bExistentObject )
+ throw NoSuchElementException( *i_rObjectName, *this );
+}
+
+Reference< XComponent > SAL_CALL OApplicationController::loadComponent( ::sal_Int32 ObjectType,
+ const OUString& ObjectName, sal_Bool ForEditing )
+{
+ return loadComponentWithArguments( ObjectType, ObjectName, ForEditing, Sequence< PropertyValue >() );
+}
+
+Reference< XComponent > SAL_CALL OApplicationController::loadComponentWithArguments( ::sal_Int32 ObjectType,
+ const OUString& ObjectName, sal_Bool ForEditing, const Sequence< PropertyValue >& Arguments )
+{
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( getMutex() );
+
+ impl_validateObjectTypeAndName_throw( ObjectType, ObjectName );
+
+ Reference< XComponent > xComponent( openElementWithArguments(
+ ObjectName,
+ lcl_objectType2ElementType( ObjectType ),
+ ForEditing ? E_OPEN_DESIGN : E_OPEN_NORMAL,
+ ForEditing ? SID_DB_APP_EDIT : SID_DB_APP_OPEN,
+ ::comphelper::NamedValueCollection( Arguments )
+ ) );
+
+ return xComponent;
+}
+
+Reference< XComponent > SAL_CALL OApplicationController::createComponent( ::sal_Int32 i_nObjectType, Reference< XComponent >& o_DocumentDefinition )
+{
+ return createComponentWithArguments( i_nObjectType, Sequence< PropertyValue >(), o_DocumentDefinition );
+}
+
+Reference< XComponent > SAL_CALL OApplicationController::createComponentWithArguments( ::sal_Int32 i_nObjectType, const Sequence< PropertyValue >& i_rArguments, Reference< XComponent >& o_DocumentDefinition )
+{
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( getMutex() );
+
+ impl_validateObjectTypeAndName_throw( i_nObjectType, ::std::optional< OUString >() );
+
+ Reference< XComponent > xComponent( newElement(
+ lcl_objectType2ElementType( i_nObjectType ),
+ ::comphelper::NamedValueCollection( i_rArguments ),
+ o_DocumentDefinition
+ ) );
+
+ return xComponent;
+}
+
+void SAL_CALL OApplicationController::registerContextMenuInterceptor( const Reference< XContextMenuInterceptor >& Interceptor )
+{
+ if ( Interceptor.is() )
+ m_aContextMenuInterceptors.addInterface( Interceptor );
+}
+
+void SAL_CALL OApplicationController::releaseContextMenuInterceptor( const Reference< XContextMenuInterceptor >& Interceptor )
+{
+ m_aContextMenuInterceptors.removeInterface( Interceptor );
+}
+
+void OApplicationController::previewChanged( sal_Int32 _nMode )
+{
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( getMutex() );
+
+ if ( m_xDataSource.is() && !isDataSourceReadOnly() )
+ {
+ try
+ {
+ ::comphelper::NamedValueCollection aLayoutInfo( m_xDataSource->getPropertyValue( PROPERTY_LAYOUTINFORMATION ) );
+ sal_Int32 nOldMode = aLayoutInfo.getOrDefault( "Preview", _nMode );
+ if ( nOldMode != _nMode )
+ {
+ aLayoutInfo.put( "Preview", _nMode );
+ m_xDataSource->setPropertyValue( PROPERTY_LAYOUTINFORMATION, Any( aLayoutInfo.getPropertyValues() ) );
+ }
+ }
+ catch ( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+ InvalidateFeature(SID_DB_APP_DISABLE_PREVIEW);
+ InvalidateFeature(SID_DB_APP_VIEW_DOCINFO_PREVIEW);
+ InvalidateFeature(SID_DB_APP_VIEW_DOC_PREVIEW);
+}
+
+void OApplicationController::askToReconnect()
+{
+ if ( !m_bNeedToReconnect )
+ return;
+
+ m_bNeedToReconnect = false;
+ bool bClear = true;
+ if ( !m_pSubComponentManager->empty() )
+ {
+ std::unique_ptr<weld::MessageDialog> xQry(Application::CreateMessageDialog(getFrameWeld(),
+ VclMessageType::Question, VclButtonsType::YesNo,
+ DBA_RES(STR_QUERY_CLOSEDOCUMENTS)));
+ switch (xQry->run())
+ {
+ case RET_YES:
+ closeSubComponents();
+ break;
+ default:
+ bClear = false;
+ break;
+ }
+ }
+ if ( bClear )
+ {
+ ElementType eType = getContainer()->getElementType();
+ disconnect();
+ getContainer()->getDetailView()->clearPages(false);
+ getContainer()->selectContainer(E_NONE); // invalidate the old selection
+ m_eCurrentType = E_NONE;
+ getContainer()->selectContainer(eType); // reselect the current one again
+ }
+}
+
+OUString OApplicationController::getDatabaseName() const
+{
+ OUString sDatabaseName;
+ try
+ {
+ if ( m_xDataSource.is() )
+ {
+ OSL_VERIFY( m_xDataSource->getPropertyValue( PROPERTY_NAME ) >>= sDatabaseName );
+ }
+ }
+ catch ( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ return sDatabaseName;
+}
+
+OUString OApplicationController::getStrippedDatabaseName() const
+{
+ OUString sDatabaseName;
+ return ::dbaui::getStrippedDatabaseName( m_xDataSource, sDatabaseName );
+}
+
+void OApplicationController::onDocumentOpened( const OUString& _rName, const sal_Int32 _nType,
+ const ElementOpenMode _eMode, const Reference< XComponent >& _xDocument, const Reference< XComponent >& _rxDefinition )
+{
+ if ( !_xDocument.is() )
+ return;
+
+ try
+ {
+ OSL_ENSURE( _xDocument.is(), "OApplicationController::onDocumentOpened: is there any *valid* scenario where this fails?" );
+ m_pSubComponentManager->onSubComponentOpened( _rName, _nType, _eMode, _xDocument.is() ? _xDocument : _rxDefinition );
+
+ if ( _rxDefinition.is() )
+ {
+ Reference< XPropertySet > xProp( _rxDefinition, UNO_QUERY_THROW );
+ Reference< XPropertySetInfo > xPSI( xProp->getPropertySetInfo(), UNO_SET_THROW );
+ xProp->addPropertyChangeListener( PROPERTY_NAME, static_cast< XPropertyChangeListener* >( this ) );
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+}
+
+bool OApplicationController::insertHierarchyElement(ElementType _eType, const OUString& _sParentFolder, bool _bCollection, const Reference<XContent>& _xContent, bool _bMove)
+{
+ Reference<XHierarchicalNameContainer> xNames(getElements(_eType), UNO_QUERY);
+ return dbaui::insertHierarchyElement(getFrameWeld()
+ ,getORB()
+ ,xNames
+ ,_sParentFolder
+ ,_eType == E_FORM
+ ,_bCollection
+ ,_xContent
+ ,_bMove);
+}
+
+bool OApplicationController::isRenameDeleteAllowed(ElementType _eType, bool _bDelete) const
+{
+ ElementType eType = getContainer()->getElementType();
+ bool bEnabled = !isDataSourceReadOnly() && eType == _eType;
+ if ( bEnabled )
+ {
+
+ if ( E_TABLE == eType )
+ bEnabled = !isConnectionReadOnly() && getContainer()->isALeafSelected();
+
+ bool bCompareRes = false;
+ if ( _bDelete )
+ bCompareRes = getContainer()->getSelectionCount() > 0;
+ else
+ {
+ bCompareRes = getContainer()->getSelectionCount() == 1;
+ if ( bEnabled && bCompareRes && E_TABLE == eType )
+ {
+ std::vector< OUString> aList;
+ getSelectionElementNames(aList);
+
+ try
+ {
+ Reference< XNameAccess > xContainer = const_cast<OApplicationController*>(this)->getElements(eType);
+ bEnabled = (xContainer.is() && xContainer->hasByName(*aList.begin()));
+ if ( bEnabled )
+ bEnabled = Reference<XRename>(xContainer->getByName(*aList.begin()),UNO_QUERY).is();
+ }
+ catch(Exception&)
+ {
+ bEnabled = false;
+ }
+ }
+ }
+
+ bEnabled = bEnabled && bCompareRes;
+ }
+ return bEnabled;
+}
+
+void OApplicationController::onLoadedMenu(const Reference< css::frame::XLayoutManager >& _xLayoutManager)
+{
+
+ if ( !_xLayoutManager.is() )
+ return;
+
+ static constexpr OUStringLiteral s_sStatusbar = u"private:resource/statusbar/statusbar";
+ _xLayoutManager->createElement( s_sStatusbar );
+ _xLayoutManager->requestElement( s_sStatusbar );
+
+ if ( getContainer() )
+ {
+ // we need to share the "mnemonic space":
+ MnemonicGenerator aMnemonicGenerator;
+ // - the menu already has mnemonics
+ if (SystemWindow* pSystemWindow = getContainer()->GetSystemWindow())
+ pSystemWindow->CollectMenuBarMnemonics(aMnemonicGenerator);
+ // - the icons should use automatic ones
+ getContainer()->createIconAutoMnemonics( aMnemonicGenerator );
+ // - as well as the entries in the task pane
+ getContainer()->setTaskExternalMnemonics( aMnemonicGenerator );
+ }
+
+ Execute( SID_DB_APP_VIEW_FORMS, Sequence< PropertyValue >() );
+ InvalidateAll();
+}
+
+void OApplicationController::doAction(sal_uInt16 _nId, const ElementOpenMode _eOpenMode)
+{
+ std::vector< OUString> aList;
+ getSelectionElementNames(aList);
+ ElementType eType = getContainer()->getElementType();
+ ::comphelper::NamedValueCollection aArguments;
+ ElementOpenMode eOpenMode = _eOpenMode;
+ if ( eType == E_REPORT && E_OPEN_FOR_MAIL == _eOpenMode )
+ {
+ aArguments.put("Hidden",true);
+ eOpenMode = E_OPEN_NORMAL;
+ }
+
+ std::vector< std::pair< OUString ,Reference< XModel > > > aComponents;
+ for (auto const& elem : aList)
+ {
+ if ( SID_DB_APP_CONVERTTOVIEW == _nId )
+ convertToView(elem);
+ else
+ {
+ Reference< XModel > xModel( openElementWithArguments( elem, eType, eOpenMode, _nId,aArguments ), UNO_QUERY );
+ aComponents.emplace_back( elem, xModel );
+ }
+ }
+
+ // special handling for mail, if more than one document is selected attach them all
+ if ( _eOpenMode != E_OPEN_FOR_MAIL )
+ return;
+
+
+ SfxMailModel aSendMail;
+ SfxMailModel::SendMailResult eResult = SfxMailModel::SEND_MAIL_OK;
+ for (auto const& component : aComponents)
+ {
+ try
+ {
+ Reference< XModel > xModel = component.second;
+
+ // Send document as e-Mail using stored/default type
+ eResult = aSendMail.AttachDocument(xModel,component.first);
+ ::comphelper::disposeComponent(xModel);
+ if (eResult != SfxMailModel::SEND_MAIL_OK)
+ break;
+ }
+ catch(const Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+ if ( !aSendMail.IsEmpty() )
+ aSendMail.Send( getFrame() );
+}
+
+ElementType OApplicationController::getElementType(const Reference< XContainer >& _xContainer)
+{
+ ElementType eRet = E_NONE;
+ Reference<XServiceInfo> xServiceInfo(_xContainer,UNO_QUERY);
+ if ( xServiceInfo.is() )
+ {
+ if ( xServiceInfo->supportsService(SERVICE_SDBCX_TABLES) )
+ eRet = E_TABLE;
+ else if ( xServiceInfo->supportsService(SERVICE_NAME_FORM_COLLECTION) )
+ eRet = E_FORM;
+ else if ( xServiceInfo->supportsService(SERVICE_NAME_REPORT_COLLECTION) )
+ eRet = E_REPORT;
+ else
+ eRet = E_QUERY;
+ }
+ return eRet;
+}
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/app/AppDetailPageHelper.cxx b/dbaccess/source/ui/app/AppDetailPageHelper.cxx
new file mode 100644
index 000000000..b7506744d
--- /dev/null
+++ b/dbaccess/source/ui/app/AppDetailPageHelper.cxx
@@ -0,0 +1,1221 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "AppDetailPageHelper.hxx"
+#include <tools/diagnose_ex.h>
+#include <tabletree.hxx>
+#include <dbtreelistbox.hxx>
+#include <com/sun/star/awt/PopupMenu.hpp>
+#include <com/sun/star/awt/XTabController.hpp>
+#include <com/sun/star/container/XChild.hpp>
+#include <com/sun/star/container/XContainer.hpp>
+#include <com/sun/star/form/XLoadable.hpp>
+#include <com/sun/star/frame/thePopupMenuControllerFactory.hpp>
+#include <com/sun/star/frame/XLayoutManager.hpp>
+#include <com/sun/star/frame/Frame.hpp>
+#include <com/sun/star/frame/FrameSearchFlag.hpp>
+#include <com/sun/star/frame/XFrames.hpp>
+#include <com/sun/star/frame/XFramesSupplier.hpp>
+#include <com/sun/star/frame/XPopupMenuController.hpp>
+#include <com/sun/star/sdb/application/XDatabaseDocumentUI.hpp>
+#include <com/sun/star/sdb/application/DatabaseObject.hpp>
+#include <com/sun/star/sdb/application/DatabaseObjectContainer.hpp>
+#include <com/sun/star/sdbc/XConnection.hpp>
+#include <com/sun/star/ucb/XCommandEnvironment.hpp>
+#include <com/sun/star/ucb/XCommandProcessor.hpp>
+#include <com/sun/star/ucb/Command.hpp>
+#include <com/sun/star/util/XCloseable.hpp>
+#include <comphelper/propertyvalue.hxx>
+#include <comphelper/string.hxx>
+#include <o3tl/string_view.hxx>
+#include "AppView.hxx"
+#include <helpids.h>
+#include <strings.hxx>
+#include <dbaccess_slotid.hrc>
+#include <databaseobjectview.hxx>
+#include <imageprovider.hxx>
+#include <vcl/commandinfoprovider.hxx>
+#include <vcl/cvtgrf.hxx>
+#include <tools/stream.hxx>
+#include "AppController.hxx"
+
+#include <com/sun/star/document/XDocumentProperties.hpp>
+
+#include <memory>
+
+using namespace ::dbaui;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::ucb;
+using namespace ::com::sun::star::frame;
+using namespace ::com::sun::star::form;
+using namespace ::com::sun::star::sdb;
+using namespace ::com::sun::star::sdb::application;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star;
+using ::com::sun::star::awt::XTabController;
+
+namespace dbaui
+{
+ namespace DatabaseObject = css::sdb::application::DatabaseObject;
+ namespace DatabaseObjectContainer = css::sdb::application::DatabaseObjectContainer;
+}
+
+namespace
+{
+ bool lcl_findEntry_impl(const TreeListBox& rTree, std::u16string_view rName, weld::TreeIter& rIter)
+ {
+ bool bReturn = false;
+ sal_Int32 nIndex = 0;
+ std::u16string_view sName( o3tl::getToken(rName,0,'/',nIndex) );
+
+ const weld::TreeView& rTreeView = rTree.GetWidget();
+ bool bEntry = true;
+ do
+ {
+ if (rTreeView.get_text(rIter) == sName)
+ {
+ if ( nIndex != -1 )
+ {
+ sName = o3tl::getToken(rName,0,'/',nIndex);
+ bEntry = rTreeView.iter_children(rIter);
+ }
+ else
+ {
+ bReturn = true;
+ break;
+ }
+ }
+ else
+ bEntry = rTreeView.iter_next_sibling(rIter);
+ }
+ while (bEntry);
+
+ return bReturn;
+ }
+
+ bool lcl_findEntry(const TreeListBox& rTree, std::u16string_view rName, weld::TreeIter& rIter)
+ {
+ sal_Int32 nIndex = 0;
+ std::u16string_view sErase = o3tl::getToken(rName,0,'/',nIndex); // we don't want to have the "private:forms" part
+ return nIndex != -1 && lcl_findEntry_impl(rTree, rName.substr(sErase.size() + 1), rIter);
+ }
+}
+
+OAppDetailPageHelper::OAppDetailPageHelper(weld::Container* pParent, OAppBorderWindow& rBorderWin, PreviewMode ePreviewMode)
+ : OChildWindow(pParent, "dbaccess/ui/detailwindow.ui", "DetailWindow")
+ , m_rBorderWin(rBorderWin)
+ , m_xBox(m_xBuilder->weld_container("box"))
+ , m_xFL(m_xBuilder->weld_widget("separator"))
+ , m_xMBPreview(m_xBuilder->weld_menu_button("disablepreview"))
+ , m_xPreview(new OPreviewWindow)
+ , m_xPreviewWin(new weld::CustomWeld(*m_xBuilder, "preview", *m_xPreview))
+ , m_xDocumentInfo(new ODocumentInfoPreview)
+ , m_xDocumentInfoWin(new weld::CustomWeld(*m_xBuilder, "infopreview", *m_xDocumentInfo))
+ , m_xTablePreview(m_xBuilder->weld_container("tablepreview"))
+ , m_ePreviewMode(ePreviewMode)
+{
+ m_xContainer->set_stack_background();
+
+ auto aProperties = vcl::CommandInfoProvider::GetCommandProperties(".uno:DBDisablePreview",
+ "com.sun.star.sdb.OfficeDatabaseDocument");
+ m_xMBPreview->set_label(vcl::CommandInfoProvider::GetLabelForCommand(aProperties));
+ m_xMBPreview->set_help_id(HID_APP_VIEW_PREVIEW_CB);
+
+ m_xMBPreview->connect_selected(LINK(this, OAppDetailPageHelper, MenuSelectHdl));
+ m_xMBPreview->connect_toggled(LINK(this, OAppDetailPageHelper, OnDropdownClickHdl));
+
+ m_xPreview->SetHelpId(HID_APP_VIEW_PREVIEW_1);
+
+ m_xTablePreview->set_help_id(HID_APP_VIEW_PREVIEW_2);
+ m_xDocumentInfo->SetHelpId(HID_APP_VIEW_PREVIEW_3);
+
+ m_xWindow = m_xTablePreview->CreateChildFrame();
+}
+
+OAppDetailPageHelper::~OAppDetailPageHelper()
+{
+ try
+ {
+ Reference< ::util::XCloseable> xCloseable(m_xFrame,UNO_QUERY);
+ if ( xCloseable.is() )
+ xCloseable->close(true);
+ m_xFrame.clear();
+ }
+ catch(const Exception&)
+ {
+ TOOLS_WARN_EXCEPTION( "dbaccess", "Exception thrown while disposing preview frame!");
+ }
+
+ for (auto& rpBox : m_aLists)
+ {
+ if (!rpBox)
+ continue;
+ rpBox.reset();
+ }
+
+ m_xWindow->dispose();
+ m_xWindow.clear();
+
+ m_xTablePreview.reset();
+ m_xDocumentInfoWin.reset();
+ m_xDocumentInfo.reset();
+ m_xPreviewWin.reset();
+ m_xPreview.reset();
+ m_xMBPreview.reset();
+ m_xFL.reset();
+ m_xBox.reset();
+}
+
+int OAppDetailPageHelper::getVisibleControlIndex() const
+{
+ int i = 0;
+ for (; i < E_ELEMENT_TYPE_COUNT ; ++i)
+ {
+ if (m_aLists[i] && m_aLists[i]->get_visible())
+ break;
+ }
+ return i;
+}
+
+void OAppDetailPageHelper::selectAll()
+{
+ int nPos = getVisibleControlIndex();
+ if (nPos < E_ELEMENT_TYPE_COUNT)
+ {
+ m_aLists[nPos]->GetWidget().select_all();
+ }
+}
+
+void OAppDetailPageHelper::GrabFocus()
+{
+ int nPos = getVisibleControlIndex();
+ if (nPos < E_ELEMENT_TYPE_COUNT)
+ m_aLists[nPos]->GetWidget().grab_focus();
+ else if (m_xMBPreview && m_xMBPreview->get_visible())
+ m_xMBPreview->grab_focus();
+}
+
+bool OAppDetailPageHelper::HasChildPathFocus() const
+{
+ int nPos = getVisibleControlIndex();
+ if (nPos < E_ELEMENT_TYPE_COUNT && m_aLists[nPos]->GetWidget().has_focus())
+ return true;
+ return m_xMBPreview && m_xMBPreview->has_focus();
+}
+
+void OAppDetailPageHelper::sort(int nPos, bool bAscending)
+{
+ assert(m_aLists[nPos] && "List can not be NULL! ->GPF");
+ m_aLists[nPos]->GetWidget().set_sort_order(bAscending);
+}
+
+bool OAppDetailPageHelper::isSortUp() const
+{
+ bool bAscending = false;
+
+ int nPos = getVisibleControlIndex();
+ if (nPos < E_ELEMENT_TYPE_COUNT)
+ bAscending = m_aLists[nPos]->GetWidget().get_sort_order();
+
+ return bAscending;
+}
+
+void OAppDetailPageHelper::sortDown()
+{
+ int nPos = getVisibleControlIndex();
+ if ( nPos < E_ELEMENT_TYPE_COUNT )
+ sort(nPos, false);
+}
+
+void OAppDetailPageHelper::sortUp()
+{
+ int nPos = getVisibleControlIndex();
+ if ( nPos < E_ELEMENT_TYPE_COUNT )
+ sort(nPos, true);
+}
+
+void OAppDetailPageHelper::getSelectionElementNames(std::vector<OUString>& rNames) const
+{
+ int nPos = getVisibleControlIndex();
+ if ( nPos >= E_ELEMENT_TYPE_COUNT )
+ return;
+
+ DBTreeViewBase& rTree = *m_aLists[nPos];
+ weld::TreeView& rTreeView = rTree.GetWidget();
+ sal_Int32 nCount = rTreeView.n_children();
+ rNames.reserve(nCount);
+ ElementType eType = getElementType();
+
+ rTreeView.selected_foreach([this, eType, &rTreeView, &rNames](weld::TreeIter& rEntry){
+ if ( eType == E_TABLE )
+ {
+ if (!rTreeView.iter_has_child(rEntry))
+ rNames.push_back(getQualifiedName(&rEntry));
+ }
+ else
+ {
+ OUString sName = rTreeView.get_text(rEntry);
+ std::unique_ptr<weld::TreeIter> xParent(rTreeView.make_iterator(&rEntry));
+ bool bParent = rTreeView.iter_parent(*xParent);
+ while (bParent)
+ {
+ sName = rTreeView.get_text(*xParent) + "/" + sName;
+ bParent = rTreeView.iter_parent(*xParent);
+ }
+ rNames.push_back(sName);
+ }
+
+ return false;
+ });
+}
+
+void OAppDetailPageHelper::describeCurrentSelectionForControl(const weld::TreeView& rControl, Sequence< NamedDatabaseObject >& out_rSelectedObjects)
+{
+ for (size_t i=0; i < E_ELEMENT_TYPE_COUNT; ++i)
+ {
+ if (&m_aLists[i]->GetWidget() == &rControl)
+ {
+ describeCurrentSelectionForType(static_cast<ElementType>(i), out_rSelectedObjects);
+ return;
+ }
+ }
+ OSL_FAIL( "OAppDetailPageHelper::describeCurrentSelectionForControl: invalid control!" );
+}
+
+void OAppDetailPageHelper::describeCurrentSelectionForType(const ElementType eType, Sequence< NamedDatabaseObject >& _out_rSelectedObjects)
+{
+ OSL_ENSURE( eType < E_ELEMENT_TYPE_COUNT, "OAppDetailPageHelper::describeCurrentSelectionForType: invalid type!" );
+ DBTreeViewBase* pList = ( eType < E_ELEMENT_TYPE_COUNT ) ? m_aLists[eType].get() : nullptr;
+ OSL_ENSURE( pList, "OAppDetailPageHelper::describeCurrentSelectionForType: "
+ "You really should ensure this type has already been viewed before!" );
+ if ( !pList )
+ return;
+
+ std::vector< NamedDatabaseObject > aSelected;
+
+ weld::TreeView& rTreeView = pList->GetWidget();
+ rTreeView.selected_foreach([pList, eType, &rTreeView, &aSelected](weld::TreeIter& rEntry){
+ NamedDatabaseObject aObject;
+ switch (eType)
+ {
+ case E_TABLE:
+ {
+ OTableTreeListBox& rTableTree = static_cast<OTableTreeListBox&>(pList->getListBox());
+ aObject = rTableTree.describeObject(rEntry);
+ break;
+ }
+ case E_QUERY:
+ aObject.Type = DatabaseObject::QUERY;
+ aObject.Name = rTreeView.get_text(rEntry);
+ break;
+ case E_FORM:
+ case E_REPORT:
+ {
+ OUString sName = rTreeView.get_text(rEntry);
+ std::unique_ptr<weld::TreeIter> xParent(rTreeView.make_iterator(&rEntry));
+ bool bParent = rTreeView.iter_parent(*xParent);
+ while (bParent)
+ {
+ sName = rTreeView.get_text(*xParent) + "/" + sName;
+ bParent = rTreeView.iter_parent(*xParent);
+ }
+
+ if (isLeaf(rTreeView, rEntry))
+ aObject.Type = (eType == E_FORM) ? DatabaseObject::FORM : DatabaseObject::REPORT;
+ else
+ aObject.Type = (eType == E_FORM) ? DatabaseObjectContainer::FORMS_FOLDER : DatabaseObjectContainer::REPORTS_FOLDER;
+ aObject.Name = sName;
+ break;
+ }
+ default:
+ OSL_FAIL( "OAppDetailPageHelper::describeCurrentSelectionForType: unexpected type!" );
+ break;
+ }
+
+ if (!aObject.Name.isEmpty())
+ aSelected.push_back(aObject);
+
+ return false;
+ });
+
+ _out_rSelectedObjects = comphelper::containerToSequence(aSelected);
+}
+
+vcl::Window* OAppDetailPageHelper::getMenuParent() const
+{
+ return &m_rBorderWin;
+}
+
+void OAppDetailPageHelper::adjustMenuPosition(const weld::TreeView& rControl, ::Point& rPos) const
+{
+ int x, y, width, height;
+ if (rControl.get_extents_relative_to(m_rBorderWin.getTopLevel(), x, y, width, height))
+ {
+ rPos.AdjustX(x);
+ rPos.AdjustY(y);
+ }
+}
+
+void OAppDetailPageHelper::selectElements(const Sequence< OUString>& _aNames)
+{
+ int nPos = getVisibleControlIndex();
+ if ( nPos >= E_ELEMENT_TYPE_COUNT )
+ return;
+
+ DBTreeViewBase& rTree = *m_aLists[nPos];
+ weld::TreeView& rTreeView = rTree.GetWidget();
+ rTreeView.unselect_all();
+ const OUString* pIter = _aNames.getConstArray();
+ const OUString* pEnd = pIter + _aNames.getLength();
+ for(;pIter != pEnd;++pIter)
+ {
+ auto xEntry = rTree.getListBox().GetEntryPosByName(*pIter);
+ if (!xEntry)
+ continue;
+ rTreeView.select(*xEntry);
+ }
+}
+
+OUString OAppDetailPageHelper::getQualifiedName(const weld::TreeIter* _pEntry) const
+{
+ int nPos = getVisibleControlIndex();
+ OUString sComposedName;
+
+ if ( nPos >= E_ELEMENT_TYPE_COUNT )
+ return sComposedName;
+
+ OSL_ENSURE(m_aLists[nPos],"Tables tree view is NULL! -> GPF");
+ DBTreeViewBase& rTree = *m_aLists[nPos];
+ weld::TreeView& rTreeView = rTree.GetWidget();
+
+ std::unique_ptr<weld::TreeIter> xEntry(rTreeView.make_iterator(_pEntry));
+ if (!_pEntry)
+ {
+ if (!rTreeView.get_selected(xEntry.get()))
+ xEntry.reset();
+ }
+
+ if (!xEntry)
+ return sComposedName;
+
+ if ( getElementType() == E_TABLE )
+ {
+ const OTableTreeListBox& rTableTreeListBox = static_cast<const OTableTreeListBox&>(m_aLists[nPos]->getListBox());
+ sComposedName = rTableTreeListBox.getQualifiedTableName(*xEntry);
+ }
+ else
+ {
+ sComposedName = rTreeView.get_text(*xEntry);
+ bool bParent = rTreeView.iter_parent(*xEntry);
+ while (bParent)
+ {
+ sComposedName = rTreeView.get_text(*xEntry) + "/" + sComposedName;
+ bParent = rTreeView.iter_parent(*xEntry);
+ }
+ }
+
+ return sComposedName;
+}
+
+ElementType OAppDetailPageHelper::getElementType() const
+{
+ int nPos = getVisibleControlIndex();
+ return static_cast<ElementType>(nPos);
+}
+
+sal_Int32 OAppDetailPageHelper::getSelectionCount()
+{
+ sal_Int32 nCount = 0;
+ int nPos = getVisibleControlIndex();
+ if ( nPos < E_ELEMENT_TYPE_COUNT )
+ {
+ DBTreeViewBase& rTree = *m_aLists[nPos];
+ weld::TreeView& rTreeView = rTree.GetWidget();
+ nCount = rTreeView.count_selected_rows();
+ }
+ return nCount;
+}
+
+sal_Int32 OAppDetailPageHelper::getElementCount() const
+{
+ sal_Int32 nCount = 0;
+ int nPos = getVisibleControlIndex();
+ if ( nPos < E_ELEMENT_TYPE_COUNT )
+ {
+ DBTreeViewBase& rTree = *m_aLists[nPos];
+ weld::TreeView& rTreeView = rTree.GetWidget();
+ nCount = rTreeView.n_children();
+ }
+ return nCount;
+}
+
+bool OAppDetailPageHelper::isLeaf(const weld::TreeView& rTreeView, const weld::TreeIter& rEntry)
+{
+ sal_Int32 nEntryType = rTreeView.get_id(rEntry).toInt32();
+ return !( ( nEntryType == DatabaseObjectContainer::TABLES )
+ || ( nEntryType == DatabaseObjectContainer::CATALOG )
+ || ( nEntryType == DatabaseObjectContainer::SCHEMA )
+ || ( nEntryType == DatabaseObjectContainer::FORMS_FOLDER )
+ || ( nEntryType == DatabaseObjectContainer::REPORTS_FOLDER ));
+}
+
+bool OAppDetailPageHelper::isALeafSelected() const
+{
+ int nPos = getVisibleControlIndex();
+ bool bLeafSelected = false;
+ if ( nPos < E_ELEMENT_TYPE_COUNT )
+ {
+ DBTreeViewBase& rTree = *m_aLists[nPos];
+ weld::TreeView& rTreeView = rTree.GetWidget();
+ rTreeView.selected_foreach([&rTreeView, &bLeafSelected](weld::TreeIter& rEntry){
+ bLeafSelected = isLeaf(rTreeView, rEntry);
+ return bLeafSelected;
+ });
+ }
+ return bLeafSelected;
+}
+
+std::unique_ptr<weld::TreeIter> OAppDetailPageHelper::getEntry( const Point& _aPosPixel) const
+{
+ std::unique_ptr<weld::TreeIter> xReturn;
+ int nPos = getVisibleControlIndex();
+ if ( nPos < E_ELEMENT_TYPE_COUNT )
+ {
+ DBTreeViewBase& rTree = *m_aLists[nPos];
+ weld::TreeView& rTreeView = rTree.GetWidget();
+ xReturn = rTreeView.make_iterator();
+ if (!rTreeView.get_dest_row_at_pos(_aPosPixel, xReturn.get(), false))
+ xReturn.reset();
+ }
+ return xReturn;
+}
+
+void OAppDetailPageHelper::createTablesPage(const Reference< XConnection>& _xConnection)
+{
+ OSL_ENSURE(_xConnection.is(),"Connection is NULL! -> GPF");
+
+ if ( !m_aLists[E_TABLE] )
+ {
+ m_aLists[E_TABLE].reset(new DBTableTreeView(m_xBox.get()));
+ setupTree(*m_aLists[E_TABLE]);
+ m_aLists[E_TABLE]->GetWidget().set_help_id(HID_APP_TABLE_TREE);
+ }
+
+ weld::TreeView& rTreeView = m_aLists[E_TABLE]->GetWidget();
+ if (!rTreeView.n_children())
+ {
+ static_cast<OTableTreeListBox&>(m_aLists[E_TABLE]->getListBox()).UpdateTableList(_xConnection);
+
+ std::unique_ptr<weld::TreeIter> xFirst(rTreeView.make_iterator());
+ if (rTreeView.get_iter_first(*xFirst))
+ rTreeView.expand_row(*xFirst);
+ rTreeView.unselect_all();
+ }
+
+ setDetailPage(*m_aLists[E_TABLE]);
+}
+
+OUString OAppDetailPageHelper::getElementIcons(ElementType _eType)
+{
+ sal_Int32 nDatabaseObjectType( 0 );
+ switch(_eType )
+ {
+ case E_FORM: nDatabaseObjectType = DatabaseObject::FORM; break;
+ case E_REPORT: nDatabaseObjectType = DatabaseObject::REPORT; break;
+ case E_QUERY: nDatabaseObjectType = DatabaseObject::QUERY; break;
+ default:
+ OSL_FAIL( "OAppDetailPageHelper::GetElementIcons: invalid element type!" );
+ return OUString();
+ }
+
+ return ImageProvider::getDefaultImageResourceID(nDatabaseObjectType);
+}
+
+void OAppDetailPageHelper::createPage(ElementType _eType,const Reference< XNameAccess >& _xContainer)
+{
+ OSL_ENSURE(E_TABLE != _eType,"E_TABLE isn't allowed.");
+
+ OString sHelpId;
+ switch( _eType )
+ {
+ case E_FORM:
+ sHelpId = HID_APP_FORM_TREE;
+ break;
+ case E_REPORT:
+ sHelpId = HID_APP_REPORT_TREE;
+ break;
+ case E_QUERY:
+ sHelpId = HID_APP_QUERY_TREE;
+ break;
+ default:
+ OSL_FAIL("Illegal call!");
+ }
+ OUString sImageId = getElementIcons(_eType);
+
+ if ( !m_aLists[_eType] )
+ {
+ m_aLists[_eType] = createSimpleTree(sHelpId, _eType);
+ }
+
+ if ( !m_aLists[_eType] )
+ return;
+
+ weld::TreeView& rTreeView = m_aLists[_eType]->GetWidget();
+ if (!rTreeView.n_children() && _xContainer.is())
+ {
+ rTreeView.make_unsorted();
+ fillNames( _xContainer, _eType, sImageId, nullptr );
+ rTreeView.make_sorted();
+
+ rTreeView.unselect_all();
+ }
+ setDetailPage(*m_aLists[_eType]);
+}
+
+void OAppDetailPageHelper::setDetailPage(DBTreeViewBase& rTreeView)
+{
+ bool bHasFocus = false;
+
+ DBTreeViewBase* pCurrent = getCurrentView();
+ if (pCurrent)
+ {
+ weld::Widget& rCurrent = pCurrent->GetWidget();
+ bHasFocus = rCurrent.has_focus();
+ pCurrent->hide();
+ }
+
+ showPreview(nullptr);
+ m_xFL->show();
+ rTreeView.show();
+ m_xMBPreview->show();
+ switchPreview(m_ePreviewMode,true);
+
+ if (bHasFocus)
+ rTreeView.GetWidget().grab_focus();
+}
+
+namespace
+{
+ namespace DatabaseObjectContainer = ::com::sun::star::sdb::application::DatabaseObjectContainer;
+
+ sal_Int32 lcl_getFolderIndicatorForType( const ElementType _eType )
+ {
+ const sal_Int32 nFolderIndicator =
+ ( _eType == E_FORM ) ? DatabaseObjectContainer::FORMS_FOLDER
+ : ( _eType == E_REPORT ) ? DatabaseObjectContainer::REPORTS_FOLDER : -1;
+ return nFolderIndicator;
+ }
+}
+
+void OAppDetailPageHelper::fillNames( const Reference< XNameAccess >& _xContainer, const ElementType _eType,
+ const OUString& rImageId, const weld::TreeIter* _pParent )
+{
+ OSL_ENSURE(_xContainer.is(),"Data source is NULL! -> GPF");
+ OSL_ENSURE( ( _eType >= E_TABLE ) && ( _eType < E_ELEMENT_TYPE_COUNT ), "OAppDetailPageHelper::fillNames: invalid type!" );
+
+ DBTreeViewBase* pList = m_aLists[_eType].get();
+ OSL_ENSURE( pList, "OAppDetailPageHelper::fillNames: you really should create the list before calling this!" );
+ if ( !pList )
+ return;
+
+ if ( !(_xContainer.is() && _xContainer->hasElements()) )
+ return;
+
+ weld::TreeView& rTreeView = pList->GetWidget();
+
+ std::unique_ptr<weld::TreeIter> xRet = rTreeView.make_iterator();
+ const sal_Int32 nFolderIndicator = lcl_getFolderIndicatorForType( _eType );
+
+ Sequence< OUString> aSeq = _xContainer->getElementNames();
+ const OUString* pIter = aSeq.getConstArray();
+ const OUString* pEnd = pIter + aSeq.getLength();
+ for(;pIter != pEnd;++pIter)
+ {
+ Reference<XNameAccess> xSubElements(_xContainer->getByName(*pIter),UNO_QUERY);
+ if ( xSubElements.is() )
+ {
+ OUString sId(OUString::number(nFolderIndicator));
+
+ rTreeView.insert(_pParent, -1, nullptr, &sId, nullptr, nullptr, false, xRet.get());
+ rTreeView.set_text(*xRet, *pIter, 0);
+ rTreeView.set_text_emphasis(*xRet, false, 0);
+ getBorderWin().getView()->getAppController().containerFound( Reference< XContainer >( xSubElements, UNO_QUERY ) );
+ fillNames( xSubElements, _eType, rImageId, xRet.get());
+ }
+ else
+ {
+ rTreeView.insert(_pParent, -1, nullptr, nullptr, nullptr, nullptr, false, xRet.get());
+ rTreeView.set_text(*xRet, *pIter, 0);
+ rTreeView.set_text_emphasis(*xRet, false, 0);
+ rTreeView.set_image(*xRet, rImageId);
+ }
+ }
+}
+
+std::unique_ptr<DBTreeViewBase> OAppDetailPageHelper::createSimpleTree(const OString& rHelpId, ElementType eType)
+{
+ const bool bSQLType = eType == E_TABLE || eType == E_QUERY;
+ std::unique_ptr<DBTreeViewBase> xTreeView(new DBTreeView(m_xBox.get(), bSQLType));
+ xTreeView->GetWidget().set_help_id(rHelpId);
+ setupTree(*xTreeView);
+ return xTreeView;
+}
+
+void OAppDetailPageHelper::setupTree(DBTreeViewBase& rDBTreeView)
+{
+ weld::WaitObject aWaitCursor(m_rBorderWin.GetFrameWeld());
+
+ rDBTreeView.getListBox().setCopyHandler(LINK(this, OAppDetailPageHelper, OnCopyEntry));
+ rDBTreeView.getListBox().setPasteHandler(LINK(this, OAppDetailPageHelper, OnPasteEntry));
+ rDBTreeView.getListBox().setDeleteHandler(LINK(this, OAppDetailPageHelper, OnDeleteEntry));
+
+ weld::TreeView& rTreeView = rDBTreeView.GetWidget();
+ rTreeView.make_sorted();
+ rTreeView.set_selection_mode(SelectionMode::Multiple);
+ // an arbitrary small size it's allowed to shrink to
+ rTreeView.set_size_request(42, 42);
+
+ rTreeView.connect_row_activated(LINK(this, OAppDetailPageHelper, OnEntryDoubleClick));
+
+ rDBTreeView.getListBox().SetSelChangeHdl(LINK(this, OAppDetailPageHelper, OnEntrySelChange));
+
+ rDBTreeView.getListBox().setControlActionListener(&getBorderWin().getView()->getAppController());
+ rDBTreeView.getListBox().setContextMenuProvider(&getBorderWin().getView()->getAppController());
+}
+
+void OAppDetailPageHelper::clearPages()
+{
+ showPreview(nullptr);
+ for (auto& rpBox : m_aLists)
+ {
+ if ( rpBox )
+ rpBox->GetWidget().clear();
+ }
+}
+
+bool OAppDetailPageHelper::isFilled() const
+{
+ size_t i = 0;
+ for (; i < E_ELEMENT_TYPE_COUNT && !m_aLists[i]; ++i)
+ ;
+ return i != E_ELEMENT_TYPE_COUNT;
+}
+
+void OAppDetailPageHelper::elementReplaced(ElementType eType,
+ const OUString& rOldName,
+ const OUString& rNewName)
+{
+ DBTreeViewBase* pTreeView = getCurrentView();
+ if (!pTreeView)
+ return;
+
+ weld::TreeView& rTreeView = pTreeView->GetWidget();
+ rTreeView.make_unsorted();
+
+ switch (eType)
+ {
+ case E_TABLE:
+ static_cast<OTableTreeListBox&>(pTreeView->getListBox()).removedTable(rOldName);
+ static_cast<OTableTreeListBox&>(pTreeView->getListBox()).addedTable(rNewName);
+ break;
+ case E_QUERY:
+ {
+ std::unique_ptr<weld::TreeIter> xIter(rTreeView.make_iterator());
+ if (rTreeView.get_iter_first(*xIter) && lcl_findEntry_impl(pTreeView->getListBox(), rOldName, *xIter))
+ rTreeView.set_text(*xIter, rNewName);
+ break;
+ }
+ case E_FORM:
+ case E_REPORT:
+ {
+ std::unique_ptr<weld::TreeIter> xIter(rTreeView.make_iterator());
+ if (rTreeView.get_iter_first(*xIter) && lcl_findEntry(pTreeView->getListBox(), rOldName, *xIter))
+ rTreeView.set_text(*xIter, rNewName);
+ break;
+ }
+ default:
+ OSL_FAIL("Invalid element type");
+ }
+
+ rTreeView.make_sorted();
+}
+
+std::unique_ptr<weld::TreeIter> OAppDetailPageHelper::elementAdded(ElementType _eType,const OUString& _rName, const Any& _rObject )
+{
+ std::unique_ptr<weld::TreeIter> xRet;
+ DBTreeViewBase* pTreeView = m_aLists[_eType].get();
+ if (!pTreeView)
+ return xRet;
+ weld::TreeView& rTreeView = pTreeView->GetWidget();
+ rTreeView.make_unsorted();
+ if (_eType == E_TABLE)
+ {
+ xRet = static_cast<OTableTreeListBox&>(pTreeView->getListBox()).addedTable( _rName );
+ }
+ else
+ {
+ std::unique_ptr<weld::TreeIter> xEntry;
+ Reference<XChild> xChild(_rObject,UNO_QUERY);
+ if ( xChild.is() && E_QUERY != _eType )
+ {
+ Reference<XContent> xContent(xChild->getParent(),UNO_QUERY);
+ if ( xContent.is() )
+ {
+ OUString sName = xContent->getIdentifier()->getContentIdentifier();
+ std::unique_ptr<weld::TreeIter> xIter(rTreeView.make_iterator());
+ if (rTreeView.get_iter_first(*xIter) && lcl_findEntry(pTreeView->getListBox(), sName, *xIter))
+ xEntry = std::move(xIter);
+ }
+ }
+
+ OUString sImageId = getElementIcons(_eType);
+ Reference<XNameAccess> xContainer(_rObject,UNO_QUERY);
+ if ( xContainer.is() )
+ {
+ const sal_Int32 nFolderIndicator = lcl_getFolderIndicatorForType( _eType );
+ OUString sId(OUString::number(nFolderIndicator));
+
+ xRet = rTreeView.make_iterator();
+ rTreeView.insert(xEntry.get(), -1, nullptr, &sId, nullptr, nullptr, false, xRet.get());
+ rTreeView.set_text(*xRet, _rName, 0);
+ rTreeView.set_text_emphasis(*xRet, false, 0);
+ fillNames(xContainer, _eType, sImageId, xRet.get());
+ }
+ else
+ {
+ xRet = rTreeView.make_iterator();
+ rTreeView.insert(xEntry.get(), -1, nullptr, nullptr, nullptr, nullptr, false, xRet.get());
+ rTreeView.set_text(*xRet, _rName, 0);
+ rTreeView.set_text_emphasis(*xRet, false, 0);
+ rTreeView.set_image(*xRet, sImageId);
+ }
+ }
+ rTreeView.make_sorted();
+ return xRet;
+}
+
+void OAppDetailPageHelper::elementRemoved( ElementType _eType,const OUString& _rName )
+{
+ DBTreeViewBase* pTreeView = getCurrentView();
+ if ( !pTreeView )
+ return;
+
+ weld::TreeView& rTreeView = pTreeView->GetWidget();
+
+ switch( _eType )
+ {
+ case E_TABLE:
+ // we don't need to clear the table here, it is already done by the dispose listener
+ static_cast<OTableTreeListBox&>(pTreeView->getListBox()).removedTable(_rName);
+ break;
+ case E_QUERY:
+ {
+ std::unique_ptr<weld::TreeIter> xIter(rTreeView.make_iterator());
+ if (rTreeView.get_iter_first(*xIter) && lcl_findEntry_impl(pTreeView->getListBox(), _rName, *xIter))
+ rTreeView.remove(*xIter);
+ break;
+ }
+ case E_FORM:
+ case E_REPORT:
+ {
+ std::unique_ptr<weld::TreeIter> xIter(rTreeView.make_iterator());
+ if (rTreeView.get_iter_first(*xIter) && lcl_findEntry(pTreeView->getListBox(), _rName, *xIter))
+ rTreeView.remove(*xIter);
+ break;
+ }
+ default:
+ OSL_FAIL("Invalid element type");
+ }
+ if (!rTreeView.n_children())
+ showPreview(nullptr);
+}
+
+IMPL_LINK(OAppDetailPageHelper, OnEntryDoubleClick, weld::TreeView&, rTreeView, bool)
+{
+ return getBorderWin().getView()->getAppController().onEntryDoubleClick(rTreeView);
+}
+
+IMPL_LINK_NOARG(OAppDetailPageHelper, OnEntrySelChange, LinkParamNone*, void)
+{
+ getBorderWin().getView()->getAppController().onSelectionChanged();
+}
+
+IMPL_LINK_NOARG( OAppDetailPageHelper, OnCopyEntry, LinkParamNone*, void )
+{
+ getBorderWin().getView()->getAppController().onCopyEntry();
+}
+
+IMPL_LINK_NOARG( OAppDetailPageHelper, OnPasteEntry, LinkParamNone*, void )
+{
+ getBorderWin().getView()->getAppController().onPasteEntry();
+}
+
+IMPL_LINK_NOARG( OAppDetailPageHelper, OnDeleteEntry, LinkParamNone*, void )
+{
+ getBorderWin().getView()->getAppController().onDeleteEntry();
+}
+
+bool OAppDetailPageHelper::isPreviewEnabled() const
+{
+ return m_ePreviewMode != E_PREVIEWNONE;
+}
+
+namespace
+{
+ OUString stripTrailingDots(std::u16string_view rStr)
+ {
+ return OUString(comphelper::string::stripEnd(rStr, '.'));
+ }
+}
+
+void OAppDetailPageHelper::switchPreview(PreviewMode _eMode,bool _bForce)
+{
+ if ( !(m_ePreviewMode != _eMode || _bForce) )
+ return;
+
+ m_ePreviewMode = _eMode;
+
+ getBorderWin().getView()->getAppController().previewChanged(static_cast<sal_Int32>(m_ePreviewMode));
+
+ OUString aCommand;
+ switch ( m_ePreviewMode )
+ {
+ case E_PREVIEWNONE:
+ aCommand = ".uno:DBDisablePreview";
+ break;
+ case E_DOCUMENT:
+ aCommand = ".uno:DBShowDocPreview";
+ break;
+ case E_DOCUMENTINFO:
+ if ( getBorderWin().getView()->getAppController().isCommandEnabled(SID_DB_APP_VIEW_DOCINFO_PREVIEW) )
+ aCommand = ".uno:DBShowDocInfoPreview";
+ else
+ {
+ m_ePreviewMode = E_PREVIEWNONE;
+ aCommand = ".uno:DBDisablePreview";
+ }
+ break;
+ }
+
+ auto aProperties = vcl::CommandInfoProvider::GetCommandProperties(aCommand, "com.sun.star.sdb.OfficeDatabaseDocument");
+ OUString aCommandLabel = vcl::CommandInfoProvider::GetLabelForCommand(aProperties);
+ m_xMBPreview->set_label(stripTrailingDots(aCommandLabel));
+
+ // simulate a selectionChanged event at the controller, to force the preview to be updated
+ if ( isPreviewEnabled() )
+ {
+ DBTreeViewBase* pCurrent = getCurrentView();
+ if (pCurrent && pCurrent->GetWidget().get_selected(nullptr))
+ {
+ getBorderWin().getView()->getAppController().onSelectionChanged();
+ }
+ }
+ else
+ {
+ m_xTablePreview->hide();
+ m_xPreview->Hide();
+ m_xDocumentInfo->Hide();
+ }
+}
+
+void OAppDetailPageHelper::showPreview(const Reference< XContent >& _xContent)
+{
+ if ( !isPreviewEnabled() )
+ return;
+
+ m_xTablePreview->hide();
+
+ weld::WaitObject aWaitCursor(m_rBorderWin.GetFrameWeld());
+ try
+ {
+ Reference<XCommandProcessor> xContent(_xContent,UNO_QUERY);
+ if ( xContent.is() )
+ {
+ css::ucb::Command aCommand;
+ if ( m_ePreviewMode == E_DOCUMENT )
+ aCommand.Name = "preview";
+ else
+ aCommand.Name = "getDocumentInfo";
+
+ Any aPreview = xContent->execute(aCommand,xContent->createCommandIdentifier(),Reference< XCommandEnvironment >());
+ if ( m_ePreviewMode == E_DOCUMENT )
+ {
+ m_xDocumentInfo->Hide();
+ m_xPreview->Show();
+
+ Graphic aGraphic;
+ Sequence < sal_Int8 > aBmpSequence;
+ if ( aPreview >>= aBmpSequence )
+ {
+ SvMemoryStream aData( aBmpSequence.getArray(),
+ aBmpSequence.getLength(),
+ StreamMode::READ );
+
+ GraphicConverter::Import(aData,aGraphic);
+ }
+ m_xPreview->setGraphic( aGraphic );
+ m_xPreview->Invalidate();
+ }
+ else
+ {
+ m_xPreview->Hide();
+ m_xDocumentInfo->clear();
+ m_xDocumentInfo->Show();
+ Reference<document::XDocumentProperties> xProp(
+ aPreview, UNO_QUERY);
+ if ( xProp.is() )
+ m_xDocumentInfo->fill(xProp);
+ }
+ }
+ else
+ {
+ m_xPreview->Hide();
+ m_xDocumentInfo->Hide();
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+}
+
+void OAppDetailPageHelper::showPreview( const OUString& _sDataSourceName,
+ const OUString& _sName,
+ bool _bTable)
+{
+ if ( !isPreviewEnabled() )
+ return;
+
+ weld::WaitObject aWaitCursor(m_rBorderWin.GetFrameWeld());
+ m_xPreview->Hide();
+ m_xDocumentInfo->Hide();
+ m_xTablePreview->show();
+ if ( !m_xFrame.is() )
+ {
+ try
+ {
+ m_xFrame = Frame::create( getBorderWin().getView()->getORB() );
+ m_xFrame->initialize( m_xWindow );
+
+ // no layout manager (and thus no toolbars) in the preview
+ // Must be called after initialize ... but before any other call to this frame.
+ // Otherwise frame throws "life time exceptions" as e.g. NON_INITIALIZED
+ m_xFrame->setLayoutManager( Reference< XLayoutManager >() );
+
+ Reference<XFramesSupplier> xSup(getBorderWin().getView()->getAppController().getXController()->getFrame(),UNO_QUERY);
+ if ( xSup.is() )
+ {
+ Reference<XFrames> xFrames = xSup->getFrames();
+ xFrames->append( Reference<XFrame>(m_xFrame,UNO_QUERY_THROW));
+ }
+ }
+ catch(const Exception&)
+ {
+ }
+ }
+
+ Reference< XDatabaseDocumentUI > xApplication( getBorderWin().getView()->getAppController().getXController(), UNO_QUERY );
+ std::unique_ptr< DatabaseObjectView > pDispatcher( new ResultSetBrowser(
+ getBorderWin().getView()->getORB(),
+ xApplication, nullptr, _bTable
+ ) );
+ pDispatcher->setTargetFrame( Reference<XFrame>(m_xFrame,UNO_QUERY_THROW) );
+
+ ::comphelper::NamedValueCollection aArgs;
+ aArgs.put( "Preview", true );
+ aArgs.put( "ReadOnly", true );
+ aArgs.put( "AsTemplate", false );
+ aArgs.put( PROPERTY_SHOWMENU, false );
+
+ Reference< XController > xPreview( pDispatcher->openExisting( Any( _sDataSourceName ), _sName, aArgs ), UNO_QUERY );
+ bool bClearPreview = !xPreview.is();
+
+ // clear the preview when the query or table could not be loaded
+ if ( !bClearPreview )
+ {
+ Reference< XTabController > xTabController( xPreview, UNO_QUERY );
+ bClearPreview = !xTabController.is();
+ if ( !bClearPreview )
+ {
+ Reference< XLoadable > xLoadable( xTabController->getModel(), UNO_QUERY );
+ bClearPreview = !( xLoadable.is() && xLoadable->isLoaded() );
+ }
+ }
+ if ( bClearPreview )
+ showPreview(nullptr);
+}
+
+namespace
+{
+ class MenuStatusListener final : public ::cppu::WeakImplHelper<css::frame::XStatusListener>
+ {
+ weld::MenuButton& m_rMBPreview;
+ public:
+ MenuStatusListener(weld::MenuButton& rMBPreview)
+ : m_rMBPreview(rMBPreview)
+ {
+ }
+
+ virtual void SAL_CALL statusChanged( const css::frame::FeatureStateEvent &rEvent) override
+ {
+ if (!rEvent.IsEnabled)
+ {
+ const OUString &rURL = rEvent.FeatureURL.Complete;
+ m_rMBPreview.remove_item(rURL.toUtf8());
+ }
+ }
+
+ virtual void SAL_CALL disposing( const css::lang::EventObject& /*rSource*/) override
+ {
+ }
+ };
+};
+
+IMPL_LINK_NOARG(OAppDetailPageHelper, OnDropdownClickHdl, weld::Toggleable&, void)
+{
+ if (!m_xMBPreview->get_active())
+ return;
+
+ m_xMBPreview->clear();
+
+ // execute the menu
+ css::uno::Reference<css::uno::XComponentContext> xContext(getBorderWin().getView()->getORB());
+ css::uno::Reference<css::frame::XUIControllerFactory> xPopupMenuFactory(css::frame::thePopupMenuControllerFactory::get(xContext));
+ if (!xPopupMenuFactory.is())
+ return;
+
+ auto xFrame = getBorderWin().getView()->getAppController().getFrame();
+
+ css::uno::Sequence<css::uno::Any> aArgs {
+ css::uno::Any(comphelper::makePropertyValue("InToolbar", true)),
+ css::uno::Any(comphelper::makePropertyValue("ModuleIdentifier", OUString("com.sun.star.sdb.OfficeDatabaseDocument"))),
+ css::uno::Any(comphelper::makePropertyValue("Frame", xFrame)) };
+
+ css::uno::Reference<css::frame::XPopupMenuController> xPopupController
+ (xPopupMenuFactory->createInstanceWithArgumentsAndContext(".uno:DBPreview", aArgs, xContext), css::uno::UNO_QUERY);
+
+ if (!xPopupController.is())
+ return;
+
+ css::uno::Reference<css::awt::XPopupMenu> xPopupMenu(css::awt::PopupMenu::create(xContext));
+ xPopupController->setPopupMenu(xPopupMenu);
+
+ css::util::URL aTargetURL;
+ Reference<XDispatchProvider> xDispatchProvider(xFrame, css::uno::UNO_QUERY);
+
+ css::uno::Reference<css::frame::XStatusListener> xStatusListener(new MenuStatusListener(*m_xMBPreview));
+
+ for (int i = 0, nCount = xPopupMenu->getItemCount(); i < nCount; ++i)
+ {
+ auto nItemId = xPopupMenu->getItemId(i);
+ // in practice disabled items are initially enabled so this doesn't have an effect and
+ // an status update is needed to query the enabled/disabled state
+ if (!xPopupMenu->isItemEnabled(nItemId))
+ continue;
+
+ aTargetURL.Complete = xPopupMenu->getCommand(nItemId);
+
+ auto aProperties = vcl::CommandInfoProvider::GetCommandProperties(aTargetURL.Complete,
+ "com.sun.star.sdb.OfficeDatabaseDocument");
+ m_xMBPreview->append_item(aTargetURL.Complete, vcl::CommandInfoProvider::GetLabelForCommand(aProperties));
+
+ // Add/remove status listener to get a status update once so we can remove any disabled items from the menu
+ auto xDispatch = xDispatchProvider->queryDispatch(aTargetURL, "_self",
+ css::frame::FrameSearchFlag::SELF);
+ if (xDispatch.is())
+ {
+ xDispatch->addStatusListener(xStatusListener, aTargetURL);
+ xDispatch->removeStatusListener(xStatusListener, aTargetURL);
+ }
+ }
+
+ css::uno::Reference<css::lang::XComponent> xComponent(xPopupController, css::uno::UNO_QUERY);
+ if (xComponent.is())
+ xComponent->dispose();
+}
+
+IMPL_LINK(OAppDetailPageHelper, MenuSelectHdl, const OString&, rIdent, void)
+{
+ if (rIdent.isEmpty())
+ return;
+
+ css::util::URL aURL;
+ aURL.Complete = OUString::fromUtf8(rIdent);
+
+ Reference<XDispatchProvider> xProvider(getBorderWin().getView()->getAppController().getFrame(), UNO_QUERY);
+ Reference<XDispatch> xDisp = xProvider->queryDispatch(aURL, "_self", 0);
+ xDisp->dispatch(aURL, css::uno::Sequence<css::beans::PropertyValue>());
+
+ m_xMBPreview->set_label(stripTrailingDots(m_xMBPreview->get_item_label(rIdent)));
+}
+
+OPreviewWindow::OPreviewWindow()
+{
+}
+
+bool OPreviewWindow::ImplGetGraphicCenterRect(const vcl::RenderContext& rRenderContext, const Graphic& rGraphic, tools::Rectangle& rResultRect) const
+{
+ const Size aWinSize( GetOutputSizePixel() );
+ Size aNewSize(rRenderContext.LogicToPixel(rGraphic.GetPrefSize(), rGraphic.GetPrefMapMode()));
+ bool bRet = false;
+
+ if( aNewSize.Width() && aNewSize.Height() )
+ {
+ // scale to fit window
+ const double fGrfWH = static_cast<double>(aNewSize.Width()) / aNewSize.Height();
+ const double fWinWH = static_cast<double>(aWinSize.Width()) / aWinSize.Height();
+
+ if ( fGrfWH < fWinWH )
+ {
+ aNewSize.setWidth( static_cast<tools::Long>( aWinSize.Height() * fGrfWH ) );
+ aNewSize.setHeight( aWinSize.Height() );
+ }
+ else
+ {
+ aNewSize.setWidth( aWinSize.Width() );
+ aNewSize.setHeight( static_cast<tools::Long>( aWinSize.Width() / fGrfWH) );
+ }
+
+ const Point aNewPos( ( aWinSize.Width() - aNewSize.Width() ) >> 1,
+ ( aWinSize.Height() - aNewSize.Height() ) >> 1 );
+
+ rResultRect = tools::Rectangle( aNewPos, aNewSize );
+ bRet = true;
+ }
+
+ return bRet;
+}
+
+void OPreviewWindow::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& /*rRect*/)
+{
+ if (ImplGetGraphicCenterRect(rRenderContext, m_aGraphicObj.GetGraphic(), m_aPreviewRect))
+ {
+ const Point aPos(m_aPreviewRect.TopLeft());
+ const Size aSize(m_aPreviewRect.GetSize());
+
+ if (m_aGraphicObj.IsAnimated())
+ m_aGraphicObj.StartAnimation(rRenderContext, aPos, aSize);
+ else
+ m_aGraphicObj.Draw(rRenderContext, aPos, aSize);
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/app/AppDetailPageHelper.hxx b/dbaccess/source/ui/app/AppDetailPageHelper.hxx
new file mode 100644
index 000000000..25cc3229a
--- /dev/null
+++ b/dbaccess/source/ui/app/AppDetailPageHelper.hxx
@@ -0,0 +1,349 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <vector>
+
+#include <rtl/ustring.hxx>
+#include <com/sun/star/sdb/application/NamedDatabaseObject.hpp>
+#include <com/sun/star/sdbc/XConnection.hpp>
+#include <com/sun/star/ucb/XContent.hpp>
+#include <com/sun/star/container/XNameAccess.hpp>
+#include <vcl/graph.hxx>
+#include <vcl/GraphicObject.hxx>
+#include <vcl/customweld.hxx>
+#include <vcl/weld.hxx>
+#include <AppElementType.hxx>
+#include <ChildWindow.hxx>
+#include "DocumentInfoPreview.hxx"
+
+namespace com::sun::star::awt { class XWindow; }
+namespace com::sun::star::frame { class XFrame2; }
+namespace com::sun::star::io { class XPersist; }
+
+namespace dbaui
+{
+ class OAppBorderWindow;
+ class ODocumentInfoPreview;
+ class DBTreeViewBase;
+ class TreeListBox;
+
+ class OPreviewWindow final : public weld::CustomWidgetController
+ {
+ GraphicObject m_aGraphicObj;
+ tools::Rectangle m_aPreviewRect;
+
+ /** gets the graphic center rect
+ @param rRenderContext
+ the context to which we are drawing
+ @param rGraphic
+ the graphic
+ @param rResultRect
+ the resulting rectangle
+
+ @return
+ <TRUE/> when successful
+ */
+ bool ImplGetGraphicCenterRect(const vcl::RenderContext& rRenderContext, const Graphic& rGraphic, tools::Rectangle& rResultRect) const;
+
+ public:
+ OPreviewWindow();
+
+ virtual void Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect) override;
+
+ void setGraphic(const Graphic& _rGraphic ) { m_aGraphicObj.SetGraphic(_rGraphic); }
+ };
+
+ // A helper class for the controls in the detail page.
+ // Combines general functionality.
+ class OAppDetailPageHelper final : public OChildWindow
+ {
+ std::unique_ptr<DBTreeViewBase> m_aLists[size_t(E_ELEMENT_TYPE_COUNT)];
+ OAppBorderWindow& m_rBorderWin;
+ std::unique_ptr<weld::Container> m_xBox;
+ std::unique_ptr<weld::Widget> m_xFL;
+ std::unique_ptr<weld::MenuButton> m_xMBPreview;
+
+ std::unique_ptr<OPreviewWindow> m_xPreview;
+ std::unique_ptr<weld::CustomWeld> m_xPreviewWin;
+
+ std::unique_ptr<ODocumentInfoPreview> m_xDocumentInfo;
+ std::unique_ptr<weld::CustomWeld> m_xDocumentInfoWin;
+
+ std::unique_ptr<weld::Container> m_xTablePreview;
+
+ PreviewMode m_ePreviewMode;
+ css::uno::Reference < css::frame::XFrame2 >
+ m_xFrame;
+ css::uno::Reference< css::awt::XWindow >
+ m_xWindow;
+
+ /// returns the index of the visible control
+ int getVisibleControlIndex() const;
+
+ /** sorts the entries in the tree list box.
+ @param nPos
+ Which list should be sorted.
+ @param bAscending
+ If sort should be Ascending of Descending
+ */
+ void sort(int nPos, bool bAscending);
+
+ /** retrieves the resource ids of the images representing elements of the given type
+ */
+ static OUString getElementIcons(ElementType _eType);
+
+ /** fills the names in the listbox
+ @param _xContainer
+ This can either be the queries, forms or report names.
+ @param _eType
+ the type of elements which are being filled
+ @param _nImageId
+ the resource id of the image to use for non-container entries
+ @param _pParent
+ The parent of the entries to be inserted.
+ */
+ void fillNames( const css::uno::Reference< css::container::XNameAccess >& _xContainer,
+ const ElementType _eType,
+ const OUString& rImageId,
+ const weld::TreeIter* _pParent );
+
+ /** sets the detail page
+ @param rTreeView
+ The control which should be visible.
+ */
+ void setDetailPage(DBTreeViewBase& rTreeView);
+
+ /** sets all HandleCallbacks
+ @param rTreeView
+ The newly created DBTreeViewBase
+ */
+ void setupTree(DBTreeViewBase& rTreeView);
+
+ /** creates the tree and sets all HandleCallbacks
+ @param nHelpId
+ The help id of the control
+ @param eType
+ The element type of the control
+ @return
+ The new tree.
+ */
+ std::unique_ptr<DBTreeViewBase> createSimpleTree(const OString& rHelpId, ElementType eType);
+
+ DECL_LINK( OnEntryDoubleClick, weld::TreeView&, bool );
+ DECL_LINK( OnEntrySelChange, LinkParamNone*, void );
+
+ DECL_LINK( OnCopyEntry, LinkParamNone*, void );
+ DECL_LINK( OnPasteEntry, LinkParamNone*, void );
+ DECL_LINK( OnDeleteEntry, LinkParamNone*, void );
+
+ DECL_LINK(OnDropdownClickHdl, weld::Toggleable&, void);
+ DECL_LINK(MenuSelectHdl, const OString&, void);
+
+ OAppBorderWindow& getBorderWin() const { return m_rBorderWin; }
+
+ public:
+ OAppDetailPageHelper(weld::Container* pParent, OAppBorderWindow& rBorderWin, PreviewMode ePreviewMode);
+ virtual ~OAppDetailPageHelper() override;
+
+ virtual void GrabFocus() override;
+ virtual bool HasChildPathFocus() const override;
+
+ /** creates the tables page
+ @param _xConnection
+ The connection to get the table names
+ */
+ void createTablesPage(const css::uno::Reference< css::sdbc::XConnection>& _xConnection);
+
+ /** creates the page for the specific type.
+ @param _eType
+ The type which should be created. E_TABLE isn't allowed.
+ @param _xContainer
+ The container of the elements to be inserted.
+ */
+ void createPage(ElementType _eType,const css::uno::Reference< css::container::XNameAccess >& _xContainer);
+
+ /** returns the current visible tree list box
+ */
+ DBTreeViewBase* getCurrentView() const
+ {
+ ElementType eType = getElementType();
+ return (eType != E_NONE ) ? m_aLists[static_cast<sal_Int32>(eType)].get() : nullptr;
+ }
+
+ /// select all entries in the visible control
+ void selectAll();
+
+ /// returns <TRUE/> if it sorts ascending
+ bool isSortUp() const;
+
+ /// sorts all entries ascending
+ void sortDown();
+
+ /// sorts all entries descending
+ void sortUp();
+
+ /** returns the element names which are selected
+ @param _rNames
+ The list will be filled.
+ */
+ void getSelectionElementNames( std::vector< OUString>& _rNames ) const;
+
+ /** describes the current selection for the given control
+ */
+ void describeCurrentSelectionForControl(
+ const weld::TreeView& rControl,
+ css::uno::Sequence< css::sdb::application::NamedDatabaseObject >& _out_rSelectedObjects
+ );
+
+ /** describes the current selection for the given ElementType
+ */
+ void describeCurrentSelectionForType(
+ const ElementType _eType,
+ css::uno::Sequence< css::sdb::application::NamedDatabaseObject >& _out_rSelectedObjects
+ );
+
+ /** get the menu parent window for the given control
+ */
+ vcl::Window* getMenuParent() const;
+ void adjustMenuPosition(const weld::TreeView& rControl, ::Point& rPos) const;
+
+ /** select all names on the currently selected container. Non existence names where ignored.
+ *
+ * \param _aNames the element names
+ */
+ void selectElements(const css::uno::Sequence< OUString>& _aNames);
+
+ /** return the qualified name.
+ @param _pEntry
+ The entry of a table, or query, form, report to get the qualified name.
+ If the entry is <NULL/>, the first selected is chosen.
+ @return
+ the qualified name
+ */
+ OUString getQualifiedName( const weld::TreeIter* _pEntry ) const;
+
+ /// return the element of currently select entry
+ ElementType getElementType() const;
+
+ /// returns the count of selected entries
+ sal_Int32 getSelectionCount();
+
+ /// returns the count of entries
+ sal_Int32 getElementCount() const;
+
+ /** returns if an entry is a leaf
+ @param rTreeView
+ The TreeView rEntry belongs to
+ @param rEntry
+ The entry to check
+ @return
+ <TRUE/> if the entry is a leaf, otherwise <FALSE/>
+ */
+ static bool isLeaf(const weld::TreeView& rTreeView, const weld::TreeIter& rEntry);
+
+ /** returns if one of the selected entries is a leaf
+ @return
+ <TRUE/> if the entry is a leaf, otherwise <FALSE/>
+ */
+ bool isALeafSelected() const;
+
+ std::unique_ptr<weld::TreeIter> getEntry(const Point& rPosPixel) const;
+
+ /// clears the detail pages
+ void clearPages();
+
+ /// returns <TRUE/> when a detail page was filled
+ bool isFilled() const;
+
+ /** adds a new object to the detail page.
+ @param _eType
+ The type where the entry should be appended.
+ @param _rName
+ The name of the object to be inserted
+ @param _rObject
+ The object to add.
+ @param _rxConn
+ If we insert a table, the connection must be set.
+ */
+ std::unique_ptr<weld::TreeIter> elementAdded(ElementType eType,
+ const OUString& rName,
+ const css::uno::Any& rObject);
+
+ /** replaces an objects name with a new one
+ @param _eType
+ The type where the entry should be appended.
+ @param _rOldName
+ The old name of the object to be replaced
+ @param _rNewName
+ The new name of the object to be replaced
+ @param _rxConn
+ If we insert a table, the connection must be set.
+ */
+ void elementReplaced(ElementType eType
+ ,const OUString& _rOldName
+ ,const OUString& _rNewName );
+
+ /** removes an element from the detail page.
+ @param _eType
+ The type where the entry should be appended.
+ @param _rName
+ The name of the element to be removed.
+ @param _rxConn
+ If we remove a table, the connection must be set.
+ */
+ void elementRemoved(ElementType _eType
+ ,const OUString& _rName );
+
+ /// returns the preview mode
+ PreviewMode getPreviewMode() const { return m_ePreviewMode;}
+
+ /// <TRUE/> if the preview is enabled
+ bool isPreviewEnabled() const;
+
+ /** switches to the given preview mode
+ @param _eMode
+ the mode to set for the preview
+ @param _bForce
+ Force the preview to be reset
+ */
+ void switchPreview(PreviewMode _eMode,bool _bForce = false);
+
+ /** shows the Preview of the content when it is enabled.
+ @param _xContent
+ The content which must support the "preview" command.
+ */
+ void showPreview(const css::uno::Reference< css::ucb::XContent >& _xContent);
+
+ /** shows the Preview of a table or query
+ @param _sDataSourceName
+ the name of the data source
+ @param _sName
+ the name of table or query
+ @param _bTable
+ <TRUE/> if it is a table, otherwise <FALSE/>
+ @return void
+ */
+ void showPreview( const OUString& _sDataSourceName,
+ const OUString& _sName,
+ bool _bTable);
+ };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/app/AppDetailView.cxx b/dbaccess/source/ui/app/AppDetailView.cxx
new file mode 100644
index 000000000..63a9f7f39
--- /dev/null
+++ b/dbaccess/source/ui/app/AppDetailView.cxx
@@ -0,0 +1,510 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "AppDetailView.hxx"
+#include <osl/diagnose.h>
+#include <helpids.h>
+#include <strings.hrc>
+#include "AppView.hxx"
+#include <com/sun/star/ui/XUIConfigurationManager.hpp>
+#include <com/sun/star/ui/theModuleUIConfigurationManagerSupplier.hpp>
+#include <com/sun/star/ui/XImageManager.hpp>
+#include <com/sun/star/ui/ImageType.hpp>
+#include <com/sun/star/sdbcx/XViewsSupplier.hpp>
+#include <com/sun/star/graphic/XGraphic.hpp>
+#include <com/sun/star/util/URL.hpp>
+#include <core_resource.hxx>
+#include <vcl/svapp.hxx>
+#include "AppDetailPageHelper.hxx"
+#include <dbaccess/IController.hxx>
+#include <algorithm>
+#include <dbtreelistbox.hxx>
+#include "AppController.hxx"
+
+using namespace ::dbaui;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::sdbcx;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::ucb;
+using namespace ::com::sun::star::graphic;
+using namespace ::com::sun::star::ui;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::beans;
+using ::com::sun::star::util::URL;
+using ::com::sun::star::sdb::application::NamedDatabaseObject;
+
+TaskEntry::TaskEntry( const char* _pAsciiUNOCommand, TranslateId _pHelpID, TranslateId pTitleResourceID, bool _bHideWhenDisabled )
+ :sUNOCommand( OUString::createFromAscii( _pAsciiUNOCommand ) )
+ ,pHelpID( _pHelpID )
+ ,sTitle( DBA_RES(pTitleResourceID) )
+ ,bHideWhenDisabled( _bHideWhenDisabled )
+{
+}
+
+void OTasksWindow::updateHelpText()
+{
+ TranslateId pHelpTextId;
+ int nCurEntry = m_xTreeView->get_selected_index();
+ if (nCurEntry != -1)
+ pHelpTextId = weld::fromId<TaskEntry*>(m_xTreeView->get_id(nCurEntry))->pHelpID;
+ setHelpText(pHelpTextId);
+}
+
+IMPL_LINK(OTasksWindow, onSelected, weld::TreeView&, rTreeView, bool)
+{
+ m_nCursorIndex = rTreeView.get_cursor_index();
+ if (m_nCursorIndex != -1)
+ {
+ URL aCommand;
+ aCommand.Complete = weld::fromId<TaskEntry*>(rTreeView.get_id(m_nCursorIndex))->sUNOCommand;
+ getDetailView()->getBorderWin().getView()->getAppController().executeChecked( aCommand, Sequence< PropertyValue >() );
+ }
+ return true;
+}
+
+void OTasksWindow::GrabFocus()
+{
+ if (!m_xTreeView)
+ return;
+ m_xTreeView->grab_focus();
+}
+
+bool OTasksWindow::HasChildPathFocus() const
+{
+ return m_xTreeView && m_xTreeView->has_focus();
+}
+
+IMPL_LINK_NOARG(OTasksWindow, FocusInHdl, weld::Widget&, void)
+{
+ m_xTreeView->select(m_nCursorIndex != -1 ? m_nCursorIndex : 0);
+}
+
+IMPL_LINK_NOARG(OTasksWindow, FocusOutHdl, weld::Widget&, void)
+{
+ m_nCursorIndex = m_xTreeView->get_cursor_index();
+ m_xTreeView->unselect_all();
+}
+
+IMPL_LINK_NOARG(OTasksWindow, OnEntrySelectHdl, weld::TreeView&, void)
+{
+ m_nCursorIndex = m_xTreeView->get_cursor_index();
+ updateHelpText();
+}
+
+OTasksWindow::OTasksWindow(weld::Container* pParent, OApplicationDetailView* pDetailView)
+ : OChildWindow(pParent, "dbaccess/ui/taskwindow.ui", "TaskWindow")
+ , m_xTreeView(m_xBuilder->weld_tree_view("treeview"))
+ , m_xDescription(m_xBuilder->weld_label("description"))
+ , m_xHelpText(m_xBuilder->weld_text_view("helptext"))
+ , m_pDetailView(pDetailView)
+ , m_nCursorIndex(-1)
+{
+ m_xContainer->set_stack_background();
+
+ m_xTreeView->set_help_id(HID_APP_CREATION_LIST);
+ m_xTreeView->connect_row_activated(LINK(this, OTasksWindow, onSelected));
+ m_xTreeView->connect_changed(LINK(this, OTasksWindow, OnEntrySelectHdl));
+ m_xTreeView->connect_focus_in(LINK(this, OTasksWindow, FocusInHdl));
+ m_xTreeView->connect_focus_out(LINK(this, OTasksWindow, FocusOutHdl));
+ // an arbitrary small size it's allowed to shrink to
+ m_xTreeView->set_size_request(42, 42);
+
+ m_xHelpText->set_help_id(HID_APP_HELP_TEXT);
+ m_xDescription->set_help_id(HID_APP_DESCRIPTION_TEXT);
+}
+
+OTasksWindow::~OTasksWindow()
+{
+ Clear();
+}
+
+void OTasksWindow::setHelpText(TranslateId pId)
+{
+ if (pId)
+ m_xHelpText->set_text(DBA_RES(pId));
+ else
+ m_xHelpText->set_text(OUString());
+}
+
+void OTasksWindow::fillTaskEntryList( const TaskEntryList& _rList )
+{
+ Clear();
+
+ try
+ {
+ Reference< XModuleUIConfigurationManagerSupplier > xModuleCfgMgrSupplier =
+ theModuleUIConfigurationManagerSupplier::get( getDetailView()->getBorderWin().getView()->getORB() );
+ Reference< XUIConfigurationManager > xUIConfigMgr = xModuleCfgMgrSupplier->getUIConfigurationManager(
+ "com.sun.star.sdb.OfficeDatabaseDocument"
+ );
+ Reference< XImageManager > xImageMgr( xUIConfigMgr->getImageManager(), UNO_QUERY );
+
+ // copy the commands so we can use them with the config managers
+ Sequence< OUString > aCommands( _rList.size() );
+ OUString* pCommands = aCommands.getArray();
+ for (auto const& copyTask : _rList)
+ {
+ *pCommands = copyTask.sUNOCommand;
+ ++pCommands;
+ }
+
+ Sequence< Reference< XGraphic> > aImages = xImageMgr->getImages(
+ ImageType::SIZE_DEFAULT | ImageType::COLOR_NORMAL ,
+ aCommands
+ );
+
+ const Reference< XGraphic >* pImages( aImages.getConstArray() );
+
+ size_t nIndex = 0;
+ for (auto const& task : _rList)
+ {
+ OUString sId = weld::toId(new TaskEntry(task));
+ m_xTreeView->append(sId, task.sTitle);
+ m_xTreeView->set_image(nIndex++, *pImages++);
+ }
+ }
+ catch(Exception&)
+ {
+ }
+
+ m_xTreeView->unselect_all();
+ updateHelpText();
+ Enable(!_rList.empty());
+}
+
+void OTasksWindow::Clear()
+{
+ m_xTreeView->all_foreach([this](weld::TreeIter& rEntry){
+ TaskEntry* pUserData = weld::fromId<TaskEntry*>(m_xTreeView->get_id(rEntry));
+ delete pUserData;
+ return false;
+ });
+
+ m_xTreeView->clear();
+}
+
+OApplicationDetailView::OApplicationDetailView(weld::Container* pParent, OAppBorderWindow& rBorder,
+ PreviewMode ePreviewMode)
+ : m_xBuilder(Application::CreateBuilder(pParent, "dbaccess/ui/appdetailwindow.ui"))
+ , m_xContainer(m_xBuilder->weld_container("AppDetailWindow"))
+ , m_xHorzSplitter(m_xBuilder->weld_paned("splitter"))
+ , m_xTasksParent(m_xBuilder->weld_container("tasks"))
+ , m_xContainerParent(m_xBuilder->weld_container("container"))
+ , m_xTasks(new dbaui::OTitleWindow(m_xTasksParent.get(), STR_TASKS))
+ , m_xTitleContainer(new dbaui::OTitleWindow(m_xContainerParent.get(), TranslateId()))
+ , m_rBorderWin(rBorder)
+{
+ m_xControlHelper = std::make_shared<OAppDetailPageHelper>(m_xTitleContainer->getChildContainer(), m_rBorderWin, ePreviewMode);
+ m_xTitleContainer->setChildWindow(m_xControlHelper);
+
+ std::shared_ptr<OChildWindow> xTasks = std::make_shared<OTasksWindow>(m_xTasks->getChildContainer(), this);
+ xTasks->Enable(!m_rBorderWin.getView()->getCommandController().isDataSourceReadOnly());
+ m_xTasks->setChildWindow(xTasks);
+}
+
+OApplicationDetailView::~OApplicationDetailView()
+{
+}
+
+void OApplicationDetailView::setTaskExternalMnemonics( MnemonicGenerator const & rMnemonics )
+{
+ m_aExternalMnemonics = rMnemonics;
+}
+
+void OApplicationDetailView::createTablesPage(const Reference< XConnection >& _xConnection )
+{
+ impl_createPage( E_TABLE, _xConnection, nullptr );
+}
+
+void OApplicationDetailView::createPage( ElementType _eType,const Reference< XNameAccess >& _xContainer )
+{
+ impl_createPage( _eType, nullptr, _xContainer );
+}
+
+void OApplicationDetailView::impl_createPage( ElementType _eType, const Reference< XConnection >& _rxConnection,
+ const Reference< XNameAccess >& _rxNonTableElements )
+{
+ // get the data for the pane
+ const TaskPaneData& rData = impl_getTaskPaneData( _eType );
+ getTasksWindow().fillTaskEntryList( rData.aTasks );
+
+ // enable the pane as a whole, depending on the availability of the first command
+ OSL_ENSURE( !rData.aTasks.empty(), "OApplicationDetailView::impl_createPage: no tasks at all!?" );
+ bool bEnabled = !rData.aTasks.empty()
+ && getBorderWin().getView()->getCommandController().isCommandEnabled( rData.aTasks[0].sUNOCommand );
+ getTasksWindow().Enable( bEnabled );
+ m_xTitleContainer->setTitle(rData.pTitleId);
+
+ // let our helper create the object list
+ if ( _eType == E_TABLE )
+ GetControlHelper()->createTablesPage( _rxConnection );
+ else
+ GetControlHelper()->createPage( _eType, _rxNonTableElements );
+}
+
+void OApplicationDetailView::impl_fillTaskPaneData(ElementType _eType, TaskPaneData& _rData) const
+{
+ TaskEntryList& rList( _rData.aTasks );
+ rList.clear(); rList.reserve( 4 );
+
+ switch ( _eType )
+ {
+ case E_TABLE:
+ rList.emplace_back( ".uno:DBNewTable", RID_STR_TABLES_HELP_TEXT_DESIGN, RID_STR_NEW_TABLE );
+ rList.emplace_back( ".uno:DBNewTableAutoPilot", RID_STR_TABLES_HELP_TEXT_WIZARD, RID_STR_NEW_TABLE_AUTO );
+ rList.emplace_back( ".uno:DBNewView", RID_STR_VIEWS_HELP_TEXT_DESIGN, RID_STR_NEW_VIEW, true );
+ _rData.pTitleId = RID_STR_TABLES_CONTAINER;
+ break;
+
+ case E_FORM:
+ rList.emplace_back( ".uno:DBNewForm", RID_STR_FORMS_HELP_TEXT, RID_STR_NEW_FORM );
+ rList.emplace_back( ".uno:DBNewFormAutoPilot", RID_STR_FORMS_HELP_TEXT_WIZARD, RID_STR_NEW_FORM_AUTO );
+ _rData.pTitleId = RID_STR_FORMS_CONTAINER;
+ break;
+
+ case E_REPORT:
+ rList.emplace_back( ".uno:DBNewReport", RID_STR_REPORT_HELP_TEXT, RID_STR_NEW_REPORT, true );
+ rList.emplace_back( ".uno:DBNewReportAutoPilot", RID_STR_REPORTS_HELP_TEXT_WIZARD, RID_STR_NEW_REPORT_AUTO );
+ _rData.pTitleId = RID_STR_REPORTS_CONTAINER;
+ break;
+
+ case E_QUERY:
+ rList.emplace_back( ".uno:DBNewQuery", RID_STR_QUERIES_HELP_TEXT, RID_STR_NEW_QUERY );
+ rList.emplace_back( ".uno:DBNewQueryAutoPilot", RID_STR_QUERIES_HELP_TEXT_WIZARD, RID_STR_NEW_QUERY_AUTO );
+ rList.emplace_back( ".uno:DBNewQuerySql", RID_STR_QUERIES_HELP_TEXT_SQL, RID_STR_NEW_QUERY_SQL );
+ _rData.pTitleId = RID_STR_QUERIES_CONTAINER;
+ break;
+
+ default:
+ OSL_FAIL( "OApplicationDetailView::impl_fillTaskPaneData: illegal element type!" );
+ }
+
+ // remove the entries which are not enabled currently
+ for (TaskEntryList::iterator pTask = rList.begin(); pTask != rList.end();)
+ {
+ if ( pTask->bHideWhenDisabled
+ && !getBorderWin().getView()->getCommandController().isCommandEnabled( pTask->sUNOCommand )
+ )
+ pTask = rList.erase( pTask );
+ else
+ {
+ ++pTask;
+ }
+ }
+}
+
+const TaskPaneData& OApplicationDetailView::impl_getTaskPaneData( ElementType _eType )
+{
+ if ( m_aTaskPaneData.empty() )
+ m_aTaskPaneData.resize( size_t(E_ELEMENT_TYPE_COUNT) );
+ OSL_ENSURE( ( _eType >= 0 ) && ( _eType < E_ELEMENT_TYPE_COUNT ), "OApplicationDetailView::impl_getTaskPaneData: illegal element type!" );
+ TaskPaneData& rData = m_aTaskPaneData[ _eType ];
+
+ //oj: do not check, otherwise extensions will only be visible after a reload.
+ impl_fillTaskPaneData( _eType, rData );
+
+ return rData;
+}
+
+OUString OApplicationDetailView::getQualifiedName(const weld::TreeIter* _pEntry) const
+{
+ return GetControlHelper()->getQualifiedName( _pEntry );
+}
+
+bool OApplicationDetailView::isLeaf(const weld::TreeView& rTreeView, const weld::TreeIter& rEntry)
+{
+ return OAppDetailPageHelper::isLeaf(rTreeView, rEntry);
+}
+
+bool OApplicationDetailView::isALeafSelected() const
+{
+ return GetControlHelper()->isALeafSelected();
+}
+
+void OApplicationDetailView::selectAll()
+{
+ GetControlHelper()->selectAll();
+}
+
+void OApplicationDetailView::sortDown()
+{
+ GetControlHelper()->sortDown();
+}
+
+void OApplicationDetailView::sortUp()
+{
+ GetControlHelper()->sortUp();
+}
+
+bool OApplicationDetailView::isFilled() const
+{
+ return GetControlHelper()->isFilled();
+}
+
+ElementType OApplicationDetailView::getElementType() const
+{
+ return GetControlHelper()->getElementType();
+}
+
+void OApplicationDetailView::clearPages(bool _bTaskAlso)
+{
+ if ( _bTaskAlso )
+ getTasksWindow().Clear();
+ GetControlHelper()->clearPages();
+}
+
+sal_Int32 OApplicationDetailView::getSelectionCount()
+{
+ return GetControlHelper()->getSelectionCount();
+}
+
+sal_Int32 OApplicationDetailView::getElementCount() const
+{
+ return GetControlHelper()->getElementCount();
+}
+
+void OApplicationDetailView::getSelectionElementNames( std::vector< OUString>& _rNames ) const
+{
+ GetControlHelper()->getSelectionElementNames( _rNames );
+}
+
+void OApplicationDetailView::describeCurrentSelectionForControl(const weld::TreeView& rControl, Sequence< NamedDatabaseObject >& out_rSelectedObjects)
+{
+ GetControlHelper()->describeCurrentSelectionForControl(rControl, out_rSelectedObjects);
+}
+
+void OApplicationDetailView::describeCurrentSelectionForType( const ElementType _eType, Sequence< NamedDatabaseObject >& _out_rSelectedObjects )
+{
+ GetControlHelper()->describeCurrentSelectionForType( _eType, _out_rSelectedObjects );
+}
+
+vcl::Window* OApplicationDetailView::getMenuParent() const
+{
+ return GetControlHelper()->getMenuParent();
+}
+
+void OApplicationDetailView::adjustMenuPosition(const weld::TreeView& rControl, ::Point& rPos) const
+{
+ return GetControlHelper()->adjustMenuPosition(rControl, rPos);
+}
+
+void OApplicationDetailView::selectElements(const Sequence< OUString>& _aNames)
+{
+ GetControlHelper()->selectElements( _aNames );
+}
+
+std::unique_ptr<weld::TreeIter> OApplicationDetailView::getEntry(const Point& rPoint) const
+{
+ return GetControlHelper()->getEntry(rPoint);
+}
+
+bool OApplicationDetailView::isCutAllowed()
+{
+ return false;
+}
+
+bool OApplicationDetailView::isCopyAllowed()
+{
+ return true;
+}
+
+bool OApplicationDetailView::isPasteAllowed() { return true; }
+
+void OApplicationDetailView::copy() { }
+
+void OApplicationDetailView::cut() { }
+
+void OApplicationDetailView::paste() { }
+
+std::unique_ptr<weld::TreeIter> OApplicationDetailView::elementAdded(ElementType _eType,const OUString& _rName, const Any& _rObject )
+{
+ return GetControlHelper()->elementAdded(_eType, _rName, _rObject);
+}
+
+void OApplicationDetailView::elementRemoved(ElementType _eType,const OUString& _rName )
+{
+ GetControlHelper()->elementRemoved(_eType,_rName );
+}
+
+void OApplicationDetailView::elementReplaced(ElementType _eType
+ ,const OUString& _rOldName
+ ,const OUString& _rNewName )
+{
+ GetControlHelper()->elementReplaced( _eType, _rOldName, _rNewName );
+}
+
+PreviewMode OApplicationDetailView::getPreviewMode() const
+{
+ return GetControlHelper()->getPreviewMode();
+}
+
+bool OApplicationDetailView::isPreviewEnabled() const
+{
+ return GetControlHelper()->isPreviewEnabled();
+}
+
+void OApplicationDetailView::switchPreview(PreviewMode _eMode)
+{
+ GetControlHelper()->switchPreview(_eMode);
+}
+
+void OApplicationDetailView::showPreview(const Reference< XContent >& _xContent)
+{
+ GetControlHelper()->showPreview(_xContent);
+}
+
+void OApplicationDetailView::showPreview( const OUString& _sDataSourceName,
+ const OUString& _sName,
+ bool _bTable)
+{
+ GetControlHelper()->showPreview(_sDataSourceName,_sName,_bTable);
+}
+
+bool OApplicationDetailView::isSortUp() const
+{
+ return GetControlHelper()->isSortUp();
+}
+
+TreeListBox* OApplicationDetailView::getTreeWindow() const
+{
+ DBTreeViewBase* pCurrent = GetControlHelper()->getCurrentView();
+ if (!pCurrent)
+ return nullptr;
+ return &pCurrent->getListBox();
+}
+
+OAppDetailPageHelper* OApplicationDetailView::GetControlHelper()
+{
+ return static_cast<OAppDetailPageHelper*>(m_xControlHelper.get());
+}
+
+const OAppDetailPageHelper* OApplicationDetailView::GetControlHelper() const
+{
+ return static_cast<const OAppDetailPageHelper*>(m_xControlHelper.get());
+}
+
+bool OApplicationDetailView::HasChildPathFocus() const
+{
+ return m_xHorzSplitter->has_focus() ||
+ m_xTasks->HasChildPathFocus() ||
+ m_xTitleContainer->HasChildPathFocus();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/app/AppDetailView.hxx b/dbaccess/source/ui/app/AppDetailView.hxx
new file mode 100644
index 000000000..f074df440
--- /dev/null
+++ b/dbaccess/source/ui/app/AppDetailView.hxx
@@ -0,0 +1,318 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <com/sun/star/container/XNameAccess.hpp>
+#include <com/sun/star/sdbc/XConnection.hpp>
+#include <com/sun/star/ucb/XContent.hpp>
+#include <com/sun/star/sdb/application/NamedDatabaseObject.hpp>
+#include <vcl/mnemonic.hxx>
+#include <IClipBoardTest.hxx>
+#include "AppTitleWindow.hxx"
+#include <AppElementType.hxx>
+
+#include <vector>
+
+namespace dbaui
+{
+ class OAppBorderWindow;
+ class OApplicationDetailView;
+ class OAppDetailPageHelper;
+ class OTasksWindow;
+ class TreeListBox;
+
+ struct TaskEntry
+ {
+ OUString sUNOCommand;
+ TranslateId pHelpID;
+ OUString sTitle;
+ bool bHideWhenDisabled;
+ // TODO: we should be consistent in the task pane and the menus/toolbars:
+ // If an entry is disabled in the latter, it should also be disabled in the former.
+ // If an entry is *hidden* in the former, it should also be hidden in the latter.
+
+ TaskEntry( const char* _pAsciiUNOCommand, TranslateId pHelpID, TranslateId pTitleResourceID, bool _bHideWhenDisabled = false );
+ };
+ typedef std::vector< TaskEntry > TaskEntryList;
+
+ struct TaskPaneData
+ {
+ /// the tasks available in the pane
+ TaskEntryList aTasks;
+ /// the resource ID for the title of the pane
+ TranslateId pTitleId;
+ };
+
+ class OTasksWindow final : public OChildWindow
+ {
+ std::unique_ptr<weld::TreeView> m_xTreeView;
+ std::unique_ptr<weld::Label> m_xDescription;
+ std::unique_ptr<weld::TextView> m_xHelpText;
+ OApplicationDetailView* m_pDetailView;
+
+ int m_nCursorIndex;
+
+ DECL_LINK(onSelected, weld::TreeView&, bool);
+ DECL_LINK(OnEntrySelectHdl, weld::TreeView&, void);
+ DECL_LINK(FocusInHdl, weld::Widget&, void);
+ DECL_LINK(FocusOutHdl, weld::Widget&, void);
+
+ void updateHelpText();
+
+ public:
+ OTasksWindow(weld::Container* pParent, OApplicationDetailView* pDetailView);
+ ~OTasksWindow();
+
+ virtual void GrabFocus() override;
+
+ virtual bool HasChildPathFocus() const override;
+
+ OApplicationDetailView* getDetailView() const { return m_pDetailView; }
+
+ /// fills the Creation listbox with the necessary strings and images
+ void fillTaskEntryList( const TaskEntryList& _rList );
+
+ void Clear();
+ void setHelpText(TranslateId pId);
+ };
+
+ class OApplicationDetailView final : public IClipboardTest
+ {
+ std::unique_ptr<weld::Builder> m_xBuilder;
+ std::unique_ptr<weld::Container> m_xContainer;
+ std::unique_ptr<weld::Paned> m_xHorzSplitter;
+ std::unique_ptr<weld::Container> m_xTasksParent;
+ std::unique_ptr<weld::Container> m_xContainerParent;
+ std::unique_ptr<OTitleWindow> m_xTasks;
+ std::unique_ptr<OTitleWindow> m_xTitleContainer;
+ OAppBorderWindow& m_rBorderWin; // my parent
+ std::shared_ptr<OChildWindow> m_xControlHelper;
+ std::vector< TaskPaneData > m_aTaskPaneData;
+ MnemonicGenerator m_aExternalMnemonics;
+
+ const OAppDetailPageHelper* GetControlHelper() const;
+ OAppDetailPageHelper* GetControlHelper();
+
+ public:
+ OApplicationDetailView(weld::Container* pParent, OAppBorderWindow& rBorder, PreviewMode ePreviewMode);
+ ~OApplicationDetailView();
+
+ /** creates the tables page
+ @param _xConnection
+ The connection to get the table names
+ */
+ void createTablesPage(const css::uno::Reference< css::sdbc::XConnection>& _xConnection);
+
+ /** creates the page for the specific type.
+ @param _eType
+ The type which should be created. E_TABLE isn't allowed.
+ @param _xContainer
+ The container of the elements to be inserted.
+ */
+ void createPage(ElementType _eType,const css::uno::Reference< css::container::XNameAccess >& _xContainer);
+
+ void setTaskExternalMnemonics( MnemonicGenerator const & _rMnemonics );
+
+ OAppBorderWindow& getBorderWin() const { return m_rBorderWin; }
+ OTasksWindow& getTasksWindow() const { return *static_cast< OTasksWindow* >( m_xTasks->getChildWindow() ); }
+
+ bool isCutAllowed() override ;
+ bool isCopyAllowed() override ;
+ bool isPasteAllowed() override;
+ void copy() override;
+ void cut() override;
+ void paste() override;
+
+ /** return the qualified name.
+ @param _pEntry
+ The entry of a table, or query, form, report to get the qualified name.
+ If the entry is <NULL/>, the first selected is chosen.
+ @return
+ the qualified name
+ */
+ OUString getQualifiedName(const weld::TreeIter* _pEntry) const;
+
+ /** returns if an entry is a leaf
+ @param rTreeView
+ The TreeView pEntry belongs to
+ @param rEntry
+ The entry to check
+ @return
+ <TRUE/> if the entry is a leaf, otherwise <FALSE/>
+ */
+ static bool isLeaf(const weld::TreeView& rTreeView, const weld::TreeIter& rEntry);
+
+ /** returns if one of the selected entries is a leaf
+ @return
+ <TRUE/> if the entry is a leaf, otherwise <FALSE/>
+ */
+ bool isALeafSelected() const;
+
+ /** select all entries in the detail page
+ */
+ void selectAll();
+
+ /// returns <TRUE/> if it sorts ascending
+ bool isSortUp() const;
+
+ /// sort the entries in the detail page down
+ void sortDown();
+
+ /// sort the entries in the detail page up
+ void sortUp();
+
+ /// returns <TRUE/> when a detail page was filled
+ bool isFilled() const;
+
+ /// return the element of currently select entry
+ ElementType getElementType() const;
+
+ /** clears the detail pages.
+ @param _bTaskAlso
+ If <TRUE/> the task window will also be cleared.
+ */
+ void clearPages(bool _bTaskAlso = true);
+
+ /// returns the count of entries
+ sal_Int32 getElementCount() const;
+
+ /// returns the count of selected entries
+ sal_Int32 getSelectionCount();
+
+ /** returns the element names which are selected
+ @param _rNames
+ The list will be filled.
+ */
+ void getSelectionElementNames(std::vector< OUString>& _rNames ) const;
+
+ /** describes the current selection for the given control
+ */
+ void describeCurrentSelectionForControl(
+ const weld::TreeView& rControl,
+ css::uno::Sequence< css::sdb::application::NamedDatabaseObject >& _out_rSelectedObjects
+ );
+
+ /** describes the current selection for the given ElementType
+ */
+ void describeCurrentSelectionForType(
+ const ElementType _eType,
+ css::uno::Sequence< css::sdb::application::NamedDatabaseObject >& _out_rSelectedObjects
+ );
+
+ /** get the menu parent window for the given control
+ */
+ vcl::Window* getMenuParent() const;
+ void adjustMenuPosition(const weld::TreeView& rControl, ::Point& rPos) const;
+
+ /** select all names on the currently selected container. Non existence names where ignored.
+ *
+ * \param _aNames the element names
+ */
+ void selectElements(const css::uno::Sequence< OUString>& _aNames);
+
+ /** adds a new object to the detail page.
+ @param _eType
+ The type where the entry should be appended.
+ @param _rName
+ The name of the object to be inserted
+ @param _rObject
+ The object to add.
+ @param _rxConn
+ If we insert a table, the connection must be set.
+ */
+ std::unique_ptr<weld::TreeIter> elementAdded(ElementType eType,
+ const OUString& rName,
+ const css::uno::Any& rObject);
+
+ /** replaces an objects name with a new one
+ @param _eType
+ The type where the entry should be appended.
+ @param _rOldName
+ The old name of the object to be replaced
+ @param _rNewName
+ The new name of the object to be replaced
+ @param _rxConn
+ If we insert a table, the connection must be set.
+ @param _xObject
+ The object which was replaced
+ */
+ void elementReplaced(ElementType eType
+ ,const OUString& _rOldName
+ ,const OUString& _rNewName );
+
+ /** removes an element from the detail page.
+ @param _eType
+ The type where the entry should be appended.
+ @param _rName
+ The name of the element to be removed.
+ @param _rxConn
+ If we remove a table, the connection must be set.
+ */
+ void elementRemoved(ElementType _eType
+ ,const OUString& _rName );
+
+ /// returns the preview mode
+ PreviewMode getPreviewMode() const;
+
+ /// <TRUE/> if the preview is enabled
+ bool isPreviewEnabled() const;
+
+ /** switches to the given preview mode
+ @param _eMode
+ the mode to set for the preview
+ */
+ void switchPreview(PreviewMode _eMode);
+
+ /** shows the Preview of the content when it is enabled.
+ @param _xContent
+ The content which must support the "preview" command.
+ */
+ void showPreview(const css::uno::Reference< css::ucb::XContent >& _xContent);
+
+ /** shows the Preview of a table or query
+ @param _sDataSourceName
+ the name of the data source
+ @param _sName
+ the name of table or query
+ @param _bTable
+ <TRUE/> if it is a table, otherwise <FALSE/>
+ @return void
+ */
+ void showPreview( const OUString& _sDataSourceName,
+ const OUString& _sName,
+ bool _bTable);
+
+ std::unique_ptr<weld::TreeIter> getEntry(const Point& rPosPixel) const;
+
+ TreeListBox* getTreeWindow() const;
+
+ bool HasChildPathFocus() const;
+ private:
+ void impl_createPage(
+ ElementType _eType,
+ const css::uno::Reference< css::sdbc::XConnection >& _rxConnection,
+ const css::uno::Reference< css::container::XNameAccess >& _rxNonTableElements
+ );
+
+ const TaskPaneData& impl_getTaskPaneData( ElementType _eType );
+ void impl_fillTaskPaneData( ElementType _eType, TaskPaneData& _rData ) const;
+ };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/app/AppIconControl.cxx b/dbaccess/source/ui/app/AppIconControl.cxx
new file mode 100644
index 000000000..1448c4015
--- /dev/null
+++ b/dbaccess/source/ui/app/AppIconControl.cxx
@@ -0,0 +1,238 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "AppIconControl.hxx"
+#include <core_resource.hxx>
+#include <strings.hrc>
+#include <bitmaps.hlst>
+#include <sfx2/thumbnailviewitem.hxx>
+#include <vcl/bitmapex.hxx>
+#include <vcl/event.hxx>
+#include <vcl/i18nhelp.hxx>
+#include <vcl/mnemonic.hxx>
+#include <vcl/settings.hxx>
+#include <vcl/svapp.hxx>
+#include <callbacks.hxx>
+#include <AppElementType.hxx>
+
+namespace dbaui
+{
+class OApplicationIconControlDropTarget final : public DropTargetHelper
+{
+private:
+ OApplicationIconControl& m_rControl;
+
+public:
+ OApplicationIconControlDropTarget(OApplicationIconControl& rControl)
+ : DropTargetHelper(rControl.GetDrawingArea()->get_drop_target())
+ , m_rControl(rControl)
+ {
+ }
+
+ virtual sal_Int8 AcceptDrop(const AcceptDropEvent& rEvt) override
+ {
+ return m_rControl.AcceptDrop(rEvt);
+ }
+
+ virtual sal_Int8 ExecuteDrop(const ExecuteDropEvent& rEvt) override
+ {
+ return m_rControl.ExecuteDrop(rEvt);
+ }
+};
+
+OApplicationIconControl::OApplicationIconControl(std::unique_ptr<weld::ScrolledWindow> xScroll)
+ : ThumbnailView(std::move(xScroll), nullptr)
+ , m_pActionListener(nullptr)
+ , m_nMaxWidth(0)
+ , m_nMaxHeight(0)
+{
+ mnVItemSpace = 6; // row spacing
+ mbSelectOnFocus = false;
+ DrawMnemonics(true);
+}
+
+void OApplicationIconControl::Fill()
+{
+ static const struct CategoryDescriptor
+ {
+ TranslateId pLabelResId;
+ ElementType eType;
+ rtl::OUStringConstExpr aImageResId;
+ } aCategories[] = { { RID_STR_TABLES_CONTAINER, E_TABLE, BMP_TABLEFOLDER_TREE_L },
+ { RID_STR_QUERIES_CONTAINER, E_QUERY, BMP_QUERYFOLDER_TREE_L },
+ { RID_STR_FORMS_CONTAINER, E_FORM, BMP_FORMFOLDER_TREE_L },
+ { RID_STR_REPORTS_CONTAINER, E_REPORT, BMP_REPORTFOLDER_TREE_L } };
+
+ for (const CategoryDescriptor& aCategorie : aCategories)
+ {
+ // E_TABLE is 0, but 0 means void so use id of enum + 1
+ std::unique_ptr<ThumbnailViewItem> xItem(
+ new ThumbnailViewItem(*this, aCategorie.eType + 1));
+ xItem->mbBorder = false;
+ xItem->maPreview1 = BitmapEx(aCategorie.aImageResId);
+ const Size& rSize = xItem->maPreview1.GetSizePixel();
+ m_nMaxWidth = std::max(m_nMaxWidth, rSize.Width());
+ m_nMaxHeight = std::max(m_nMaxHeight, rSize.Height());
+ xItem->maTitle = DBA_RES(aCategorie.pLabelResId);
+ m_nMaxWidth = std::max<tools::Long>(m_nMaxWidth, GetTextWidth(xItem->maTitle));
+ AppendItem(std::move(xItem));
+ }
+
+ const int nMargin = 12;
+ const int nWidthRequest = m_nMaxWidth + 2 * nMargin;
+ set_size_request(nWidthRequest, -1);
+ // we expect a Resize at which point we'll set the item sizes based on our final size
+}
+
+ElementType OApplicationIconControl::GetSelectedItem() const
+{
+ for (const auto& rItem : mItemList)
+ {
+ if (!rItem->mbSelected)
+ continue;
+ return static_cast<ElementType>(rItem->mnId - 1);
+ }
+ return E_NONE;
+}
+
+void OApplicationIconControl::createIconAutoMnemonics(MnemonicGenerator& rMnemonics)
+{
+ for (const auto& rItem : mItemList)
+ rMnemonics.RegisterMnemonic(rItem->maTitle);
+
+ // exchange texts with generated mnemonics
+ for (auto& rItem : mItemList)
+ rItem->maTitle = rMnemonics.CreateMnemonic(rItem->maTitle);
+}
+
+void OApplicationIconControl::Resize()
+{
+ // fill the full width of the allocated area and give two lines of space to
+ // center the title in
+ setItemDimensions(GetOutputSizePixel().Width(), m_nMaxHeight, GetTextHeight() * 2, 0);
+ ThumbnailView::Resize();
+}
+
+bool OApplicationIconControl::IsMnemonicChar(sal_Unicode cChar, ElementType& rType) const
+{
+ bool bRet = false;
+
+ const vcl::I18nHelper& rI18nHelper = Application::GetSettings().GetUILocaleI18nHelper();
+ for (const auto& rItem : mItemList)
+ {
+ if (rI18nHelper.MatchMnemonic(rItem->maTitle, cChar))
+ {
+ bRet = true;
+ rType = static_cast<ElementType>(rItem->mnId - 1);
+ break;
+ }
+ }
+
+ return bRet;
+}
+
+bool OApplicationIconControl::DoKeyShortCut(const KeyEvent& rKEvt)
+{
+ bool bMod2 = rKEvt.GetKeyCode().IsMod2();
+ sal_Unicode cChar = rKEvt.GetCharCode();
+ ElementType eType(E_NONE);
+ if (bMod2 && cChar && IsMnemonicChar(cChar, eType))
+ {
+ // shortcut is clicked
+ deselectItems();
+ SelectItem(eType + 1);
+ return true;
+ }
+
+ return false;
+}
+
+bool OApplicationIconControl::KeyInput(const KeyEvent& rKEvt)
+{
+ return DoKeyShortCut(rKEvt) || ThumbnailView::KeyInput(rKEvt);
+}
+
+void OApplicationIconControl::SetDrawingArea(weld::DrawingArea* pDrawingArea)
+{
+ ThumbnailView::SetDrawingArea(pDrawingArea);
+ m_xDropTarget.reset(new OApplicationIconControlDropTarget(*this));
+}
+
+sal_Int8 OApplicationIconControl::AcceptDrop(const AcceptDropEvent& rEvt)
+{
+ sal_Int8 nDropOption = DND_ACTION_NONE;
+ if (m_pActionListener)
+ {
+ sal_uInt16 nEntry = GetItemId(rEvt.maPosPixel);
+ if (nEntry)
+ {
+ deselectItems();
+ SelectItem(nEntry);
+ nDropOption
+ = m_pActionListener->queryDrop(rEvt, m_xDropTarget->GetDataFlavorExVector());
+ }
+ }
+ return nDropOption;
+}
+
+sal_Int8 OApplicationIconControl::ExecuteDrop(const ExecuteDropEvent& rEvt)
+{
+ if (m_pActionListener)
+ m_pActionListener->executeDrop(rEvt);
+ return DND_ACTION_NONE;
+}
+
+OApplicationIconControl::~OApplicationIconControl() {}
+
+void OApplicationIconControl::GetFocus()
+{
+ ThumbnailView::GetFocus();
+ Invalidate(); // redraw focus rect
+}
+
+void OApplicationIconControl::LoseFocus()
+{
+ ThumbnailView::LoseFocus();
+ Invalidate(); // redraw focus rect
+}
+
+tools::Rectangle OApplicationIconControl::GetFocusRect()
+{
+ if (HasFocus())
+ {
+ // Get the last selected item in the list
+ for (tools::Long i = mFilteredItemList.size() - 1; i >= 0; --i)
+ {
+ ThumbnailViewItem* pItem = mFilteredItemList[i];
+ if (pItem->isSelected())
+ {
+ tools::Rectangle aRet(pItem->getDrawArea());
+ aRet.AdjustLeft(THUMBNAILVIEW_ITEM_CORNER);
+ aRet.AdjustTop(1);
+ aRet.AdjustRight(-THUMBNAILVIEW_ITEM_CORNER);
+ aRet.AdjustBottom(-2);
+ return aRet;
+ }
+ }
+ }
+ return tools::Rectangle();
+}
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/app/AppIconControl.hxx b/dbaccess/source/ui/app/AppIconControl.hxx
new file mode 100644
index 000000000..1146a77a1
--- /dev/null
+++ b/dbaccess/source/ui/app/AppIconControl.hxx
@@ -0,0 +1,67 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <sfx2/thumbnailview.hxx>
+#include <vcl/transfer.hxx>
+#include <vcl/weld.hxx>
+#include <AppElementType.hxx>
+
+class MnemonicGenerator;
+
+namespace dbaui
+{
+ class IControlActionListener;
+ class IconControl;
+ class OApplicationIconControlDropTarget;
+
+ class OApplicationIconControl final : public ThumbnailView
+ {
+ std::unique_ptr<OApplicationIconControlDropTarget> m_xDropTarget;
+ IControlActionListener* m_pActionListener;
+
+ tools::Long m_nMaxWidth;
+ tools::Long m_nMaxHeight;
+
+ bool IsMnemonicChar(sal_Unicode cChar, ElementType& rType) const;
+
+ public:
+ explicit OApplicationIconControl(std::unique_ptr<weld::ScrolledWindow> xScroll);
+ virtual void SetDrawingArea(weld::DrawingArea* pDrawingArea) override;
+ virtual void Resize() override;
+ virtual tools::Rectangle GetFocusRect() override;
+ virtual void GetFocus() override;
+ virtual void LoseFocus() override;
+ bool DoKeyShortCut(const KeyEvent& rKEvt);
+ virtual bool KeyInput(const KeyEvent& rKEvt) override;
+ virtual ~OApplicationIconControl() override;
+
+ ElementType GetSelectedItem() const;
+
+ void setControlActionListener( IControlActionListener* _pListener ) { m_pActionListener = _pListener; }
+ void Fill();
+
+ void createIconAutoMnemonics(MnemonicGenerator& rMnemonics);
+
+ sal_Int8 AcceptDrop(const AcceptDropEvent& rEvt);
+ sal_Int8 ExecuteDrop(const ExecuteDropEvent& rEvt);
+ };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/app/AppSwapWindow.cxx b/dbaccess/source/ui/app/AppSwapWindow.cxx
new file mode 100644
index 000000000..ea2066c72
--- /dev/null
+++ b/dbaccess/source/ui/app/AppSwapWindow.cxx
@@ -0,0 +1,133 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "AppSwapWindow.hxx"
+#include <helpids.h>
+#include "AppView.hxx"
+#include <sfx2/thumbnailviewitem.hxx>
+#include <vcl/event.hxx>
+#include <vcl/mnemonic.hxx>
+#include <vcl/svapp.hxx>
+#include "AppController.hxx"
+
+using namespace ::dbaui;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::container;
+
+OApplicationSwapWindow::OApplicationSwapWindow(weld::Container* pParent,
+ OAppBorderWindow& rBorderWindow)
+ : OChildWindow(pParent, "dbaccess/ui/appswapwindow.ui", "AppSwapWindow")
+ , m_xIconControl(new OApplicationIconControl(m_xBuilder->weld_scrolled_window("scroll", true)))
+ , m_xIconControlWin(new weld::CustomWeld(*m_xBuilder, "valueset", *m_xIconControl))
+ , m_eLastType(E_NONE)
+ , m_rBorderWin(rBorderWindow)
+ , m_nChangeEvent(nullptr)
+{
+ m_xContainer->set_stack_background();
+
+ m_xIconControl->SetHelpId(HID_APP_SWAP_ICONCONTROL);
+ m_xIconControl->Fill();
+ m_xIconControl->setItemStateHdl(LINK(this, OApplicationSwapWindow, OnContainerSelectHdl));
+ m_xIconControl->setControlActionListener(&m_rBorderWin.getView()->getAppController());
+}
+
+void OApplicationSwapWindow::GrabFocus()
+{
+ if (m_xIconControl)
+ m_xIconControl->GrabFocus();
+}
+
+bool OApplicationSwapWindow::HasChildPathFocus() const
+{
+ return m_xIconControl && m_xIconControl->HasFocus();
+}
+
+OApplicationSwapWindow::~OApplicationSwapWindow()
+{
+ if (m_nChangeEvent)
+ Application::RemoveUserEvent(m_nChangeEvent);
+}
+
+void OApplicationSwapWindow::clearSelection()
+{
+ m_xIconControl->deselectItems();
+ onContainerSelected(E_NONE);
+}
+
+void OApplicationSwapWindow::createIconAutoMnemonics(MnemonicGenerator& rMnemonics)
+{
+ m_xIconControl->createIconAutoMnemonics(rMnemonics);
+}
+
+bool OApplicationSwapWindow::interceptKeyInput(const KeyEvent& _rEvent)
+{
+ const vcl::KeyCode& rKeyCode = _rEvent.GetKeyCode();
+ if (rKeyCode.GetModifier() == KEY_MOD2)
+ return m_xIconControl->DoKeyShortCut(_rEvent);
+ // not handled
+ return false;
+}
+
+ElementType OApplicationSwapWindow::getElementType() const
+{
+ return m_xIconControl->GetSelectedItem();
+}
+
+bool OApplicationSwapWindow::onContainerSelected(ElementType _eType)
+{
+ if (m_eLastType == _eType)
+ return true;
+
+ if (m_rBorderWin.getView()->getAppController().onContainerSelect(_eType))
+ {
+ if (_eType != E_NONE)
+ m_eLastType = _eType;
+ return true;
+ }
+
+ if (!m_nChangeEvent)
+ m_nChangeEvent
+ = Application::PostUserEvent(LINK(this, OApplicationSwapWindow, ChangeToLastSelected));
+ return false;
+}
+
+IMPL_LINK(OApplicationSwapWindow, OnContainerSelectHdl, const ThumbnailViewItem*, pEntry, void)
+{
+ if (pEntry->mbSelected)
+ {
+ ElementType eType = static_cast<ElementType>(pEntry->mnId - 1);
+ onContainerSelected(eType); // i87582
+ }
+}
+
+IMPL_LINK_NOARG(OApplicationSwapWindow, ChangeToLastSelected, void*, void)
+{
+ m_nChangeEvent = nullptr;
+ selectContainer(m_eLastType);
+}
+
+void OApplicationSwapWindow::selectContainer(ElementType eType)
+{
+ m_xIconControl->deselectItems();
+ m_xIconControl->SelectItem(eType + 1); // will trigger onContainerSelected
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/app/AppSwapWindow.hxx b/dbaccess/source/ui/app/AppSwapWindow.hxx
new file mode 100644
index 000000000..1ce972e3b
--- /dev/null
+++ b/dbaccess/source/ui/app/AppSwapWindow.hxx
@@ -0,0 +1,88 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <IClipBoardTest.hxx>
+#include "AppIconControl.hxx"
+#include <AppElementType.hxx>
+#include <ChildWindow.hxx>
+
+struct ImplSVEvent;
+class MnemonicGenerator;
+
+namespace dbaui
+{
+ class OAppBorderWindow;
+ class OApplicationSwapWindow : public OChildWindow
+ , public IClipboardTest
+ {
+ std::unique_ptr<OApplicationIconControl> m_xIconControl;
+ std::unique_ptr<weld::CustomWeld> m_xIconControlWin;
+ ElementType m_eLastType;
+ OAppBorderWindow& m_rBorderWin;
+ ImplSVEvent* m_nChangeEvent;
+
+ DECL_LINK( OnContainerSelectHdl, const ThumbnailViewItem*, void );
+ DECL_LINK( ChangeToLastSelected, void*, void );
+
+ public:
+ OApplicationSwapWindow(weld::Container* pParent, OAppBorderWindow& rBorderWindow);
+ virtual ~OApplicationSwapWindow() override;
+
+ virtual void GrabFocus() override;
+ virtual bool HasChildPathFocus() const override;
+
+ bool isCutAllowed() override { return false; }
+ bool isCopyAllowed() override { return false; }
+ bool isPasteAllowed() override { return false; }
+ void copy() override { }
+ void cut() override { }
+ void paste() override { }
+
+ /** automatically creates mnemonics for the icon/texts in our left hand side panel
+ */
+ void createIconAutoMnemonics( MnemonicGenerator& _rMnemonics );
+
+ /** called to give the window the chance to intercept key events, while it has not
+ the focus
+
+ @return <TRUE/> if and only if the event has been handled, and should not
+ not be further processed
+ */
+ bool interceptKeyInput( const KeyEvent& _rEvent );
+
+ /// return the element of currently select entry
+ ElementType getElementType() const;
+
+ /** clears the selection in the icon choice control and calls the handler
+ */
+ void clearSelection();
+
+ /** changes the container which should be displayed. The select handler will also be called.
+ @param _eType
+ Which container to show.
+ */
+ void selectContainer(ElementType _eType);
+
+ private:
+ bool onContainerSelected( ElementType _eType );
+ };
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/app/AppTitleWindow.cxx b/dbaccess/source/ui/app/AppTitleWindow.cxx
new file mode 100644
index 000000000..d5e604394
--- /dev/null
+++ b/dbaccess/source/ui/app/AppTitleWindow.cxx
@@ -0,0 +1,65 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <core_resource.hxx>
+#include <vcl/svapp.hxx>
+#include "AppTitleWindow.hxx"
+
+namespace dbaui
+{
+OTitleWindow::OTitleWindow(weld::Container* pParent, TranslateId pTitleId)
+ : m_xBuilder(Application::CreateBuilder(pParent, "dbaccess/ui/titlewindow.ui"))
+ , m_xContainer(m_xBuilder->weld_container("TitleWindow"))
+ , m_xTitleFrame(m_xBuilder->weld_container("titleparent"))
+ , m_xTitle(m_xBuilder->weld_label("title"))
+ , m_xChildContainer(m_xBuilder->weld_container("box"))
+{
+ setTitle(pTitleId);
+
+ m_xContainer->set_stack_background();
+ m_xTitleFrame->set_title_background();
+ m_xTitle->set_label_type(weld::LabelType::Title);
+}
+
+OTitleWindow::~OTitleWindow() {}
+
+weld::Container* OTitleWindow::getChildContainer() { return m_xChildContainer.get(); }
+
+void OTitleWindow::setChildWindow(const std::shared_ptr<OChildWindow>& rChild)
+{
+ m_xChild = rChild;
+}
+
+void OTitleWindow::setTitle(TranslateId pTitleId)
+{
+ if (!pTitleId)
+ return;
+ m_xTitle->set_label(DBA_RES(pTitleId));
+}
+
+void OTitleWindow::GrabFocus()
+{
+ if (m_xChild)
+ m_xChild->GrabFocus();
+}
+
+bool OTitleWindow::HasChildPathFocus() const { return m_xChild && m_xChild->HasChildPathFocus(); }
+
+} // namespace dbaui
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/app/AppTitleWindow.hxx b/dbaccess/source/ui/app/AppTitleWindow.hxx
new file mode 100644
index 000000000..d57f52416
--- /dev/null
+++ b/dbaccess/source/ui/app/AppTitleWindow.hxx
@@ -0,0 +1,67 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <ChildWindow.hxx>
+#include <unotools/resmgr.hxx>
+
+namespace dbaui
+{
+ class OTitleWindow final
+ {
+ std::unique_ptr<weld::Builder> m_xBuilder;
+ std::unique_ptr<weld::Container> m_xContainer;
+ std::unique_ptr<weld::Container> m_xTitleFrame;
+ std::unique_ptr<weld::Label> m_xTitle;
+ std::unique_ptr<weld::Container> m_xChildContainer;
+ std::shared_ptr<OChildWindow> m_xChild;
+
+ public:
+ OTitleWindow(weld::Container* pParent, TranslateId pTitleId);
+ ~OTitleWindow();
+
+ void GrabFocus();
+
+ bool HasChildPathFocus() const;
+
+ /** gets the window which should be used as a child's parent */
+ weld::Container* getChildContainer();
+
+ /** sets the child window which should be displayed below the title. It will be destroyed at the end.
+ @param _pChild
+ The child window.
+ */
+ void setChildWindow(const std::shared_ptr<OChildWindow>& rChild);
+
+ /** gets the child window.
+
+ @return
+ The child window.
+ */
+ OChildWindow* getChildWindow() const { return m_xChild.get(); }
+
+ /** sets the title text out of the resource
+ @param pTitleId
+ The resource id of the title text.
+ */
+ void setTitle(TranslateId pTitleId);
+ };
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/app/AppView.cxx b/dbaccess/source/ui/app/AppView.cxx
new file mode 100644
index 000000000..b300df8df
--- /dev/null
+++ b/dbaccess/source/ui/app/AppView.cxx
@@ -0,0 +1,473 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "AppView.hxx"
+#include <strings.hrc>
+#include <tools/diagnose_ex.h>
+#include <vcl/event.hxx>
+#include <vcl/weld.hxx>
+#include <com/sun/star/sdbcx/XTablesSupplier.hpp>
+#include <com/sun/star/sdb/XQueriesSupplier.hpp>
+#include "AppDetailView.hxx"
+#include "AppSwapWindow.hxx"
+#include <vcl/settings.hxx>
+#include "AppTitleWindow.hxx"
+#include "AppController.hxx"
+
+using namespace ::dbaui;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::ucb;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::sdb;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::sdbcx;
+using namespace ::com::sun::star::datatransfer::clipboard;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::container;
+using ::com::sun::star::sdb::application::NamedDatabaseObject;
+
+OAppBorderWindow::OAppBorderWindow(OApplicationView* pParent, PreviewMode ePreviewMode)
+ : InterimItemWindow(pParent, "dbaccess/ui/appborderwindow.ui", "AppBorderWindow", false)
+ , m_xPanelParent(m_xBuilder->weld_container("panel"))
+ , m_xDetailViewParent(m_xBuilder->weld_container("detail"))
+ , m_xView(pParent)
+{
+ SetStyle(GetStyle() | WB_DIALOGCONTROL);
+
+ m_xPanel.reset(new OTitleWindow(m_xPanelParent.get(), STR_DATABASE));
+ std::shared_ptr<OChildWindow> xSwap = std::make_shared<OApplicationSwapWindow>(m_xPanel->getChildContainer(), *this);
+
+ m_xPanel->setChildWindow(xSwap);
+
+ m_xDetailView.reset(new OApplicationDetailView(m_xDetailViewParent.get(), *this, ePreviewMode));
+
+ ImplInitSettings();
+}
+
+OAppBorderWindow::~OAppBorderWindow()
+{
+ disposeOnce();
+}
+
+void OAppBorderWindow::dispose()
+{
+ // destroy children
+ m_xPanel.reset();
+ m_xDetailView.reset();
+ m_xPanelParent.reset();
+ m_xDetailViewParent.reset();
+ m_xView.clear();
+ InterimItemWindow::dispose();
+}
+
+void OAppBorderWindow::GetFocus()
+{
+ if (m_xPanel)
+ m_xPanel->GrabFocus();
+}
+
+OApplicationSwapWindow* OAppBorderWindow::getPanel() const
+{
+ return static_cast<OApplicationSwapWindow*>(m_xPanel->getChildWindow());
+}
+
+OApplicationView::OApplicationView( vcl::Window* pParent
+ ,const Reference< XComponentContext >& _rxOrb
+ ,OApplicationController& _rAppController
+ ,PreviewMode _ePreviewMode
+ ) :
+ ODataView( pParent, _rAppController, _rxOrb, WB_DIALOGCONTROL )
+ ,m_rAppController( _rAppController )
+{
+ m_pWin = VclPtr<OAppBorderWindow>::Create(this,_ePreviewMode);
+ m_pWin->Show();
+
+ ImplInitSettings();
+}
+
+OApplicationView::~OApplicationView()
+{
+ disposeOnce();
+}
+
+void OApplicationView::dispose()
+{
+ stopComponentListening(m_xObject);
+ m_xObject.clear();
+ m_pWin->Hide();
+ m_pWin.disposeAndClear();
+ ODataView::dispose();
+}
+
+void OApplicationView::createIconAutoMnemonics( MnemonicGenerator& _rMnemonics )
+{
+ if ( m_pWin && m_pWin->getPanel() )
+ m_pWin->getPanel()->createIconAutoMnemonics( _rMnemonics );
+}
+
+void OApplicationView::setTaskExternalMnemonics( MnemonicGenerator const & _rMnemonics )
+{
+ if ( m_pWin && m_pWin->getDetailView() )
+ m_pWin->getDetailView()->setTaskExternalMnemonics( _rMnemonics );
+}
+
+void OApplicationView::DataChanged( const DataChangedEvent& rDCEvt )
+{
+ ODataView::DataChanged( rDCEvt );
+
+ if ( (rDCEvt.GetType() == DataChangedEventType::FONTS) ||
+ (rDCEvt.GetType() == DataChangedEventType::DISPLAY) ||
+ (rDCEvt.GetType() == DataChangedEventType::FONTSUBSTITUTION) ||
+ ((rDCEvt.GetType() == DataChangedEventType::SETTINGS) &&
+ (rDCEvt.GetFlags() & AllSettingsFlags::STYLE)) )
+ {
+ ImplInitSettings();
+ Invalidate();
+ }
+}
+
+void OApplicationView::resizeDocumentView(tools::Rectangle& _rPlayground)
+{
+ if ( m_pWin && !_rPlayground.IsEmpty() )
+ {
+ Size aFLSize = LogicToPixel(Size(3, 3), MapMode(MapUnit::MapAppFont));
+ _rPlayground.Move( aFLSize.Width(),aFLSize.Height() );
+ Size aOldSize = _rPlayground.GetSize();
+ _rPlayground.SetSize( Size(aOldSize.Width() - 2*aFLSize.Width(), aOldSize.Height() - 2*aFLSize.Height()) );
+
+ m_pWin->SetPosSizePixel(_rPlayground.TopLeft() , _rPlayground.GetSize() );
+ }
+ // just for completeness: there is no space left, we occupied it all ...
+ _rPlayground.SetPos( _rPlayground.BottomRight() );
+ _rPlayground.SetSize( Size( 0, 0 ) );
+}
+
+OApplicationView::ChildFocusState OApplicationView::getChildFocus() const
+{
+ ChildFocusState eChildFocus;
+ if( m_pWin && getPanel() && getPanel()->HasChildPathFocus() )
+ eChildFocus = PANELSWAP;
+ else if ( m_pWin && getDetailView() && getDetailView()->HasChildPathFocus() )
+ eChildFocus = DETAIL;
+ else
+ eChildFocus = NONE;
+ return eChildFocus;
+}
+
+bool OApplicationView::PreNotify( NotifyEvent& rNEvt )
+{
+ switch(rNEvt.GetType())
+ {
+ case MouseNotifyEvent::KEYINPUT:
+ {
+ const KeyEvent* pKeyEvent = rNEvt.GetKeyEvent();
+ // give the pane the chance to intercept mnemonic accelerators
+ // #i34790#
+ if ( getPanel() && getPanel()->interceptKeyInput( *pKeyEvent ) )
+ return true;
+ }
+ break;
+ default:
+ break;
+ }
+
+ return ODataView::PreNotify(rNEvt);
+}
+
+IClipboardTest* OApplicationView::getActiveChild() const
+{
+ IClipboardTest* pTest = nullptr;
+ if (getChildFocus() == DETAIL)
+ pTest = getDetailView();
+ return pTest;
+}
+
+bool OApplicationView::isCopyAllowed()
+{
+ IClipboardTest* pTest = getActiveChild();
+ return pTest && pTest->isCopyAllowed();
+}
+
+bool OApplicationView::isCutAllowed()
+{
+ IClipboardTest* pTest = getActiveChild();
+ return pTest && pTest->isCutAllowed();
+}
+
+bool OApplicationView::isPasteAllowed()
+{
+ IClipboardTest* pTest = getActiveChild();
+ return pTest && pTest->isPasteAllowed();
+}
+
+void OApplicationView::copy()
+{
+ IClipboardTest* pTest = getActiveChild();
+ if ( pTest )
+ pTest->copy();
+}
+
+void OApplicationView::cut()
+{
+ IClipboardTest* pTest = getActiveChild();
+ if ( pTest )
+ pTest->cut();
+}
+
+void OApplicationView::paste()
+{
+ IClipboardTest* pTest = getActiveChild();
+ if ( pTest )
+ pTest->paste();
+}
+
+OUString OApplicationView::getQualifiedName(const weld::TreeIter* _pEntry) const
+{
+ OSL_ENSURE(m_pWin && getDetailView(),"Detail view is NULL! -> GPF");
+ return getDetailView()->getQualifiedName( _pEntry );
+}
+
+bool OApplicationView::isLeaf(const weld::TreeView& rTreeView, const weld::TreeIter& rEntry) const
+{
+ OSL_ENSURE(m_pWin && getDetailView(),"Detail view is NULL! -> GPF");
+ return OApplicationDetailView::isLeaf(rTreeView, rEntry);
+}
+
+bool OApplicationView::isALeafSelected() const
+{
+ OSL_ENSURE(m_pWin && getDetailView(),"Detail view is NULL! -> GPF");
+ return getDetailView()->isALeafSelected();
+}
+
+void OApplicationView::selectAll()
+{
+ OSL_ENSURE(m_pWin && getDetailView(),"Detail view is NULL! -> GPF");
+ getDetailView()->selectAll();
+}
+
+bool OApplicationView::isSortUp() const
+{
+ OSL_ENSURE(m_pWin && getDetailView(),"Detail view is NULL! -> GPF");
+ return getDetailView()->isSortUp();
+}
+
+void OApplicationView::sortDown()
+{
+ OSL_ENSURE(m_pWin && getDetailView(),"Detail view is NULL! -> GPF");
+ getDetailView()->sortDown();
+}
+
+void OApplicationView::sortUp()
+{
+ OSL_ENSURE(m_pWin && getDetailView(),"Detail view is NULL! -> GPF");
+ getDetailView()->sortUp();
+}
+
+bool OApplicationView::isFilled() const
+{
+ OSL_ENSURE(m_pWin && getDetailView(),"Detail view is NULL! -> GPF");
+ return getDetailView()->isFilled();
+}
+
+ElementType OApplicationView::getElementType() const
+{
+ OSL_ENSURE(m_pWin && getDetailView() && getPanel(),"Detail view is NULL! -> GPF");
+ return getDetailView()->HasChildPathFocus() ? getDetailView()->getElementType() : getPanel()->getElementType();
+}
+
+sal_Int32 OApplicationView::getSelectionCount() const
+{
+ OSL_ENSURE(m_pWin && getDetailView(),"Detail view is NULL! -> GPF");
+ return getDetailView()->getSelectionCount();
+}
+
+sal_Int32 OApplicationView::getElementCount() const
+{
+ OSL_ENSURE(m_pWin && getDetailView(),"Detail view is NULL! -> GPF");
+ return getDetailView()->getElementCount();
+}
+
+void OApplicationView::getSelectionElementNames( std::vector< OUString>& _rNames ) const
+{
+ OSL_ENSURE(m_pWin && getDetailView(),"Detail view is NULL! -> GPF");
+ getDetailView()->getSelectionElementNames( _rNames );
+}
+
+void OApplicationView::describeCurrentSelectionForControl(const weld::TreeView& rControl, Sequence<NamedDatabaseObject>& out_rSelectedObjects)
+{
+ OSL_ENSURE(m_pWin && getDetailView(),"Detail view is NULL! -> GPF");
+ getDetailView()->describeCurrentSelectionForControl(rControl, out_rSelectedObjects);
+}
+
+vcl::Window* OApplicationView::getMenuParent() const
+{
+ OSL_ENSURE(m_pWin && getDetailView(),"Detail view is NULL! -> GPF");
+ return getDetailView()->getMenuParent();
+}
+
+void OApplicationView::adjustMenuPosition(const weld::TreeView& rControl, ::Point& rPos) const
+{
+ OSL_ENSURE(m_pWin && getDetailView(),"Detail view is NULL! -> GPF");
+ return getDetailView()->adjustMenuPosition(rControl, rPos);
+}
+
+void OApplicationView::describeCurrentSelectionForType( const ElementType _eType, Sequence< NamedDatabaseObject >& _out_rSelectedObjects )
+{
+ OSL_ENSURE(m_pWin && getDetailView(),"Detail view is NULL! -> GPF");
+ getDetailView()->describeCurrentSelectionForType( _eType, _out_rSelectedObjects );
+}
+
+void OApplicationView::selectElements(const Sequence< OUString>& _aNames)
+{
+ OSL_ENSURE(m_pWin && getDetailView(),"Detail view is NULL! -> GPF");
+ getDetailView()->selectElements( _aNames );
+}
+
+std::unique_ptr<weld::TreeIter> OApplicationView::elementAdded(ElementType eType,const OUString& _rName, const Any& _rObject )
+{
+ OSL_ENSURE(m_pWin && getDetailView(),"Detail view is NULL! -> GPF");
+ return getDetailView()->elementAdded(eType,_rName,_rObject);
+}
+
+void OApplicationView::elementRemoved(ElementType eType,const OUString& _rName )
+{
+ OSL_ENSURE(m_pWin && getDetailView(),"Detail view is NULL! -> GPF");
+ getDetailView()->elementRemoved(eType,_rName);
+}
+
+void OApplicationView::elementReplaced(ElementType _eType
+ ,const OUString& _rOldName
+ ,const OUString& _rNewName )
+{
+ OSL_ENSURE(m_pWin && getDetailView(),"Detail view is NULL! -> GPF");
+ getDetailView()->elementReplaced(_eType, _rOldName, _rNewName );
+}
+
+void OApplicationView::clearPages()
+{
+ OSL_ENSURE(m_pWin && getDetailView() && getPanel(),"Detail view is NULL! -> GPF");
+ getPanel()->clearSelection();
+ getDetailView()->clearPages();
+}
+
+void OApplicationView::selectContainer(ElementType _eType)
+{
+ OSL_ENSURE(m_pWin && getPanel(),"Detail view is NULL! -> GPF");
+ weld::WaitObject aWO(GetFrameWeld());
+ getPanel()->selectContainer(_eType);
+}
+
+std::unique_ptr<weld::TreeIter> OApplicationView::getEntry(const Point& rPosPixel) const
+{
+ OSL_ENSURE(m_pWin && getDetailView(),"Detail view is NULL! -> GPF");
+ return getDetailView()->getEntry(rPosPixel);
+}
+
+PreviewMode OApplicationView::getPreviewMode() const
+{
+ OSL_ENSURE(m_pWin && getDetailView(),"Detail view is NULL! -> GPF");
+ return getDetailView()->getPreviewMode();
+}
+
+bool OApplicationView::isPreviewEnabled() const
+{
+ OSL_ENSURE(m_pWin && getDetailView(),"Detail view is NULL! -> GPF");
+ return getDetailView()->isPreviewEnabled();
+}
+
+void OApplicationView::switchPreview(PreviewMode _eMode)
+{
+ OSL_ENSURE(m_pWin && getDetailView(),"Detail view is NULL! -> GPF");
+ getDetailView()->switchPreview(_eMode);
+}
+
+void OApplicationView::showPreview(const Reference< XContent >& _xContent)
+{
+ OSL_ENSURE(m_pWin && getDetailView(),"Detail view is NULL! -> GPF");
+ stopComponentListening(m_xObject);
+ m_xObject = nullptr;
+ getDetailView()->showPreview(_xContent);
+}
+
+void OApplicationView::showPreview( const OUString& _sDataSourceName,
+ const css::uno::Reference< css::sdbc::XConnection>& _xConnection,
+ const OUString& _sName,
+ bool _bTable)
+{
+ OSL_ENSURE(m_pWin && getDetailView(),"Detail view is NULL! -> GPF");
+ if ( !isPreviewEnabled() )
+ return;
+
+ stopComponentListening(m_xObject);
+ m_xObject = nullptr;
+ try
+ {
+ Reference<XNameAccess> xNameAccess;
+ if ( _bTable )
+ {
+ Reference<XTablesSupplier> xSup(_xConnection,UNO_QUERY);
+ if ( xSup.is() )
+ xNameAccess = xSup->getTables();
+ }
+ else
+ {
+ Reference<XQueriesSupplier> xSup(_xConnection,UNO_QUERY);
+ if ( xSup.is() )
+ xNameAccess = xSup->getQueries();
+ }
+ if ( xNameAccess.is() && xNameAccess->hasByName(_sName) )
+ m_xObject.set(xNameAccess->getByName(_sName),UNO_QUERY);
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ if ( m_xObject.is() )
+ startComponentListening(m_xObject);
+ getDetailView()->showPreview(_sDataSourceName,_sName,_bTable);
+}
+
+void OApplicationView::GetFocus()
+{
+ if (m_pWin && getChildFocus() == NONE)
+ m_pWin->GrabFocus();
+}
+
+void OApplicationView::_disposing( const css::lang::EventObject& /*_rSource*/ )
+{
+ if ( m_pWin && getDetailView() )
+ showPreview(nullptr);
+}
+
+void OApplicationView::ImplInitSettings()
+{
+ // FIXME RenderContext
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+
+ vcl::Font aFont = rStyleSettings.GetFieldFont();
+ aFont.SetColor( rStyleSettings.GetWindowTextColor() );
+ SetPointFont(*GetOutDev(), aFont);
+
+ SetTextColor( rStyleSettings.GetFieldTextColor() );
+ SetTextFillColor();
+
+ SetBackground( rStyleSettings.GetFieldColor() );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/app/AppView.hxx b/dbaccess/source/ui/app/AppView.hxx
new file mode 100644
index 000000000..59a6d477a
--- /dev/null
+++ b/dbaccess/source/ui/app/AppView.hxx
@@ -0,0 +1,302 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <dbaccess/dataview.hxx>
+#include <com/sun/star/ucb/XContent.hpp>
+#include <com/sun/star/sdb/application/NamedDatabaseObject.hpp>
+#include <com/sun/star/sdbc/XConnection.hpp>
+#include <unotools/eventlisteneradapter.hxx>
+#include <vcl/InterimItemWindow.hxx>
+#include <vcl/weld.hxx>
+#include <IClipBoardTest.hxx>
+#include <AppElementType.hxx>
+
+namespace com::sun::star::beans { class XPropertySet; }
+
+class MnemonicGenerator;
+
+namespace dbaui
+{
+ class OApplicationView;
+ class OApplicationDetailView;
+ class OApplicationSwapWindow;
+ class OTitleWindow;
+ class OApplicationController;
+
+ class OAppBorderWindow final : public InterimItemWindow
+ {
+ std::unique_ptr<weld::Container> m_xPanelParent;
+ std::unique_ptr<weld::Container> m_xDetailViewParent;
+ std::unique_ptr<OTitleWindow> m_xPanel;
+ std::unique_ptr<OApplicationDetailView> m_xDetailView;
+ VclPtr<OApplicationView> m_xView;
+
+ public:
+ OAppBorderWindow(OApplicationView* pParent, PreviewMode ePreviewMode);
+ virtual ~OAppBorderWindow() override;
+ virtual void dispose() override;
+
+ // Window overrides
+ virtual void GetFocus() override;
+
+ OApplicationView* getView() const { return m_xView.get(); }
+ OApplicationSwapWindow* getPanel() const;
+ OApplicationDetailView* getDetailView() const { return m_xDetailView.get(); }
+ weld::Container& getTopLevel() { return *m_xContainer; }
+ };
+
+ class OApplicationView : public ODataView
+ ,public IClipboardTest
+ ,public ::utl::OEventListenerAdapter
+ {
+ enum ChildFocusState
+ {
+ PANELSWAP,
+ DETAIL,
+ NONE
+ };
+ private:
+ css::uno::Reference< css::lang::XComponent >
+ m_xObject;
+ VclPtr<OAppBorderWindow> m_pWin;
+ OApplicationController& m_rAppController;
+
+ ChildFocusState getChildFocus() const;
+ IClipboardTest* getActiveChild() const;
+
+ void ImplInitSettings();
+ protected:
+
+ // return the Rectangle where I can paint myself
+ virtual void resizeDocumentView(tools::Rectangle& rRect) override;
+
+ // OEventListenerAdapter
+ virtual void _disposing( const css::lang::EventObject& _rSource ) override;
+
+ // Window
+ virtual void DataChanged( const DataChangedEvent& rDCEvt ) override;
+ public:
+ OApplicationView( vcl::Window* pParent
+ ,const css::uno::Reference< css::uno::XComponentContext >&
+ ,OApplicationController& _rAppController
+ ,PreviewMode _ePreviewMode
+ );
+ virtual ~OApplicationView() override;
+ virtual void dispose() override;
+
+ /// automatically creates mnemonics for the icon/texts in our left hand side panel
+ void createIconAutoMnemonics( MnemonicGenerator& _rMnemonics );
+
+ /// automatically creates mnemonics for the texts in our task pane
+ void setTaskExternalMnemonics( MnemonicGenerator const & _rMnemonics );
+
+ // Window overrides
+ virtual bool PreNotify( NotifyEvent& rNEvt ) override;
+ virtual void GetFocus() override;
+
+ OApplicationController& getAppController() const { return m_rAppController; }
+
+ // IClipboardTest
+ virtual bool isCutAllowed() override;
+ virtual bool isCopyAllowed() override;
+ virtual bool isPasteAllowed() override;
+ virtual void copy() override;
+ virtual void cut() override;
+ virtual void paste() override;
+
+ /// get the left panel
+ OApplicationSwapWindow* getPanel() const { return m_pWin->getPanel(); }
+ /// get the detail page
+ OApplicationDetailView* getDetailView() const { return m_pWin->getDetailView(); }
+
+ /** return the qualified name.
+ @param _pEntry
+ The entry of a table, or query, form, report to get the qualified name.
+ If the entry is <NULL/>, the first selected is chosen.
+ @return
+ the qualified name
+ */
+ OUString getQualifiedName(const weld::TreeIter* _pEntry) const;
+
+ /** returns if an entry is a leaf
+ @param rTreeView
+ The TreeView rEntry belongs to
+ @param rEntry
+ The entry to check
+ @return
+ <TRUE/> if the entry is a leaf, otherwise <FALSE/>
+ */
+ bool isLeaf(const weld::TreeView& rTreeView, const weld::TreeIter& rEntry) const;
+
+ /** returns if one of the selected entries is a leaf
+ @return
+ <TRUE/> if the entry is a leaf, otherwise <FALSE/>
+ */
+ bool isALeafSelected() const;
+
+ /** select all entries in the detail page
+ */
+ void selectAll();
+
+ /// returns <TRUE/> if it sorts ascending
+ bool isSortUp() const;
+
+ /// sort the entries in the detail page down
+ void sortDown();
+
+ /// sort the entries in the detail page up
+ void sortUp();
+
+ /// returns <TRUE/> when a detail page was filled
+ bool isFilled() const;
+
+ /// return the element of currently select entry
+ ElementType getElementType() const;
+
+ /// returns the count of entries
+ sal_Int32 getElementCount() const;
+
+ /// returns the count of selected entries
+ sal_Int32 getSelectionCount() const;
+
+ /** clears the detail page and the selection on the left side.
+ The task window will also be cleared.
+ */
+ void clearPages();
+
+ /** returns the element names which are selected
+ @param _rNames
+ The list will be filled.
+ */
+ void getSelectionElementNames( std::vector< OUString>& _rNames ) const;
+
+ /** describes the current selection for the given control
+ */
+ void describeCurrentSelectionForControl(
+ const weld::TreeView& rControl,
+ css::uno::Sequence< css::sdb::application::NamedDatabaseObject >& _out_rSelectedObjects
+ );
+
+ /** describes the current selection for the given ElementType
+ */
+ void describeCurrentSelectionForType(
+ const ElementType _eType,
+ css::uno::Sequence< css::sdb::application::NamedDatabaseObject >& _out_rSelectedObjects
+ );
+
+ /** get the menu parent window for the given control
+ */
+ vcl::Window* getMenuParent() const;
+
+ /** adjust rPos relative to rControl to instead relative to getMenuParent */
+ void adjustMenuPosition(const weld::TreeView& rControl, ::Point& rPos) const;
+
+ /** select all names on the currently selected container. Non existence names where ignored.
+ *
+ * \param _aNames the element names
+ */
+ void selectElements(const css::uno::Sequence< OUString>& _aNames);
+
+ /** adds a new object to the detail page.
+ @param _eType
+ The type where the entry should be appended.
+ @param _rName
+ The name of the object to be inserted
+ @param _rObject
+ The object to add.
+ @param _rxConn
+ If we insert a table, the connection must be set.
+ */
+ std::unique_ptr<weld::TreeIter> elementAdded(ElementType eType,
+ const OUString& rName,
+ const css::uno::Any& rObject);
+
+ /** replaces an objects name with a new one
+ @param _eType
+ The type where the entry should be appended.
+ @param _rOldName
+ The old name of the object to be replaced
+ @param _rNewName
+ The new name of the object to be replaced
+ @param _rxConn
+ If we insert a table, the connection must be set.
+ @param _xObject
+ The object which was replaced
+ */
+ void elementReplaced(ElementType eType
+ ,const OUString& _rOldName
+ ,const OUString& _rNewName );
+
+ /** removes an element from the detail page.
+ @param _eType
+ The type where the entry should be appended.
+ @param _rName
+ The name of the element to be removed.
+ @param _rxConn
+ If we remove a table, the connection must be set.
+ */
+ void elementRemoved(ElementType _eType
+ ,const OUString& _rName );
+
+ /** changes the container which should be displayed. The select handler will also be called.
+ @param _eType
+ Which container to show.
+ */
+ void selectContainer(ElementType _eType);
+
+ /// returns the preview mode
+ PreviewMode getPreviewMode() const;
+
+ /// <TRUE/> if the preview is enabled
+ bool isPreviewEnabled() const;
+
+ /** switches to the given preview mode
+ @param _eMode
+ the mode to set for the preview
+ */
+ void switchPreview(PreviewMode _eMode);
+
+ /** shows the Preview of the content when it is enabled.
+ @param _xContent
+ The content which must support the "preview" command.
+ */
+ void showPreview(const css::uno::Reference< css::ucb::XContent >& _xContent);
+
+ /** shows the Preview of a table or query
+ @param _sDataSourceName
+ the name of the data source
+ @param _xConnection
+ the connection which will be shared
+ @param _sName
+ the name of table or query
+ @param _bTable
+ <TRUE/> if it is a table, otherwise <FALSE/>
+ @return void
+ */
+ void showPreview( const OUString& _sDataSourceName,
+ const css::uno::Reference< css::sdbc::XConnection>& _xConnection,
+ const OUString& _sName,
+ bool _bTable);
+
+ std::unique_ptr<weld::TreeIter> getEntry(const Point& rPosPixel) const;
+ };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/app/ChildWindow.cxx b/dbaccess/source/ui/app/ChildWindow.cxx
new file mode 100644
index 000000000..a8091c863
--- /dev/null
+++ b/dbaccess/source/ui/app/ChildWindow.cxx
@@ -0,0 +1,25 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <vcl/svapp.hxx>
+#include <ChildWindow.hxx>
+
+namespace dbaui
+{
+OChildWindow::OChildWindow(weld::Container* pParent, const OUString& rUIXMLDescription,
+ const OString& rID)
+ : m_xBuilder(Application::CreateBuilder(pParent, rUIXMLDescription))
+ , m_xContainer(m_xBuilder->weld_container(rID))
+{
+}
+
+OChildWindow::~OChildWindow() {}
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/dbaccess/source/ui/app/DocumentInfoPreview.cxx b/dbaccess/source/ui/app/DocumentInfoPreview.cxx
new file mode 100644
index 000000000..7220eb2bd
--- /dev/null
+++ b/dbaccess/source/ui/app/DocumentInfoPreview.cxx
@@ -0,0 +1,164 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/document/XDocumentProperties.hpp>
+#include <com/sun/star/script/CannotConvertException.hpp>
+#include <com/sun/star/script/Converter.hpp>
+#include <com/sun/star/script/XTypeConverter.hpp>
+#include <comphelper/processfactory.hxx>
+#include <comphelper/string.hxx>
+#include <editeng/eeitem.hxx>
+#include <editeng/wghtitem.hxx>
+#include <rtl/ustring.hxx>
+#include "DocumentInfoPreview.hxx"
+#include <vcl/settings.hxx>
+#include <vcl/svapp.hxx>
+#include <svl/itemset.hxx>
+#include <tools/datetime.hxx>
+#include <tools/diagnose_ex.h>
+#include <unotools/localedatawrapper.hxx>
+
+#include <templwin.hrc>
+#include "templwin.hxx"
+
+namespace dbaui {
+
+ODocumentInfoPreview::ODocumentInfoPreview()
+{
+}
+
+void ODocumentInfoPreview::SetDrawingArea(weld::DrawingArea* pDrawingArea)
+{
+ WeldEditView::SetDrawingArea(pDrawingArea);
+ m_xEditView->HideCursor();
+ m_xEditView->SetReadOnly(true);
+}
+
+ODocumentInfoPreview::~ODocumentInfoPreview()
+{
+}
+
+void ODocumentInfoPreview::clear() {
+ m_xEditEngine->SetText(OUString());
+}
+
+void ODocumentInfoPreview::fill(
+ css::uno::Reference< css::document::XDocumentProperties > const & xDocProps)
+{
+ assert(xDocProps.is());
+
+ insertNonempty(DI_TITLE, xDocProps->getTitle());
+ insertNonempty(DI_FROM, xDocProps->getAuthor());
+ insertDateTime(DI_DATE, xDocProps->getCreationDate());
+ insertNonempty(DI_MODIFIEDBY, xDocProps->getModifiedBy());
+ insertDateTime(DI_MODIFIEDDATE, xDocProps->getModificationDate());
+ insertNonempty(DI_PRINTBY, xDocProps->getPrintedBy());
+ insertDateTime(DI_PRINTDATE, xDocProps->getPrintDate());
+ insertNonempty(DI_THEME, xDocProps->getSubject());
+ insertNonempty(
+ DI_KEYWORDS,
+ comphelper::string::convertCommaSeparated(xDocProps->getKeywords()));
+ insertNonempty(DI_DESCRIPTION, xDocProps->getDescription());
+
+ // User-defined (custom) properties:
+ css::uno::Reference< css::beans::XPropertySet > user(
+ xDocProps->getUserDefinedProperties(), css::uno::UNO_QUERY_THROW);
+ css::uno::Reference< css::beans::XPropertySetInfo > info(
+ user->getPropertySetInfo());
+ const css::uno::Sequence< css::beans::Property > props(info->getProperties());
+ for (const auto& rProp : props) {
+ OUString name(rProp.Name);
+ css::uno::Any aAny(user->getPropertyValue(name));
+ css::uno::Reference< css::script::XTypeConverter > conv(
+ css::script::Converter::create(
+ comphelper::getProcessComponentContext()));
+ OUString value;
+ try {
+ value = conv->convertToSimpleType(aAny, css::uno::TypeClass_STRING).
+ get< OUString >();
+ } catch (css::script::CannotConvertException &) {
+ TOOLS_INFO_EXCEPTION("svtools.contnr", "ignored");
+ }
+ if (!value.isEmpty()) {
+ insertEntry(name, value);
+ }
+ }
+
+ m_xEditView->SetSelection(ESelection(0, 0, 0, 0));
+}
+
+namespace
+{
+ ESelection InsertAtEnd(const EditEngine& rEditEngine)
+ {
+ const sal_uInt32 nPara = rEditEngine.GetParagraphCount() -1;
+ sal_Int32 nLastLen = rEditEngine.GetText(nPara).getLength();
+ return ESelection(nPara, nLastLen, nPara, nLastLen);
+ }
+}
+
+void ODocumentInfoPreview::insertEntry(
+ std::u16string_view title, OUString const & value)
+{
+ if (!m_xEditEngine->GetText().isEmpty()) {
+ m_xEditEngine->QuickInsertText("\n\n", InsertAtEnd(*m_xEditEngine));
+ }
+
+ OUString caption(OUString::Concat(title) + ":\n");
+ m_xEditEngine->QuickInsertText(caption, InsertAtEnd(*m_xEditEngine));
+
+ SfxItemSet aSet(m_xEditEngine->GetEmptyItemSet());
+ aSet.Put(SvxWeightItem(WEIGHT_BOLD, EE_CHAR_WEIGHT));
+ aSet.Put(SvxWeightItem(WEIGHT_BOLD, EE_CHAR_WEIGHT_CJK));
+ aSet.Put(SvxWeightItem(WEIGHT_BOLD, EE_CHAR_WEIGHT_CTL));
+ int nCaptionPara = m_xEditEngine->GetParagraphCount() - 2;
+ m_xEditEngine->QuickSetAttribs(aSet, ESelection(nCaptionPara, 0, nCaptionPara, caption.getLength() - 1));
+
+ m_xEditEngine->QuickInsertText(value, InsertAtEnd(*m_xEditEngine));
+}
+
+void ODocumentInfoPreview::insertNonempty(tools::Long id, OUString const & value)
+{
+ if (!value.isEmpty()) {
+ insertEntry(SvtDocInfoTable_Impl::GetString(id), value);
+ }
+}
+
+void ODocumentInfoPreview::insertDateTime(
+ tools::Long id, css::util::DateTime const & value)
+{
+ DateTime aToolsDT(
+ Date(value.Day, value.Month, value.Year),
+ tools::Time(
+ value.Hours, value.Minutes, value.Seconds, value.NanoSeconds));
+ if (aToolsDT.IsValidAndGregorian()) {
+ const LocaleDataWrapper& rLocaleWrapper( Application::GetSettings().GetLocaleDataWrapper() );
+ OUString buf = rLocaleWrapper.getDate(aToolsDT) +
+ ", " +
+ rLocaleWrapper.getTime(aToolsDT);
+ insertEntry(SvtDocInfoTable_Impl::GetString(id), buf);
+ }
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/app/DocumentInfoPreview.hxx b/dbaccess/source/ui/app/DocumentInfoPreview.hxx
new file mode 100644
index 000000000..0c9548d0a
--- /dev/null
+++ b/dbaccess/source/ui/app/DocumentInfoPreview.hxx
@@ -0,0 +1,59 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <sal/config.h>
+
+#include <string_view>
+
+#include <svx/weldeditview.hxx>
+
+namespace com :: sun :: star :: uno { template <typename > class Reference; }
+
+namespace com::sun::star {
+ namespace document { class XDocumentProperties; }
+ namespace util { struct DateTime; }
+}
+
+namespace dbaui {
+
+class ODocumentInfoPreview final : public WeldEditView {
+public:
+ ODocumentInfoPreview();
+
+ virtual void SetDrawingArea(weld::DrawingArea* pDrawingArea) override;
+
+ virtual ~ODocumentInfoPreview() override;
+
+ void clear();
+
+ void fill(css::uno::Reference< css::document::XDocumentProperties > const & xDocProps);
+
+private:
+ void insertEntry(std::u16string_view title, OUString const & value);
+
+ void insertNonempty(tools::Long id, OUString const & value);
+
+ void insertDateTime(tools::Long id, css::util::DateTime const & value);
+};
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/app/subcomponentmanager.cxx b/dbaccess/source/ui/app/subcomponentmanager.cxx
new file mode 100644
index 000000000..bf92f2400
--- /dev/null
+++ b/dbaccess/source/ui/app/subcomponentmanager.cxx
@@ -0,0 +1,551 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "subcomponentmanager.hxx"
+#include "AppController.hxx"
+#include <strings.hxx>
+
+#include <com/sun/star/frame/XFrame.hpp>
+#include <com/sun/star/frame/XModel.hpp>
+#include <com/sun/star/frame/XModel2.hpp>
+#include <com/sun/star/util/XCloseable.hpp>
+#include <com/sun/star/awt/XTopWindow.hpp>
+#include <com/sun/star/embed/XComponentSupplier.hpp>
+#include <com/sun/star/ucb/XCommandProcessor.hpp>
+#include <com/sun/star/document/XDocumentEventBroadcaster.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+
+#include <tools/diagnose_ex.h>
+#include <dbaccess/dataview.hxx>
+#include <vcl/svapp.hxx>
+#include <osl/mutex.hxx>
+
+#include <algorithm>
+
+namespace dbaui
+{
+
+ using ::com::sun::star::uno::Reference;
+ using ::com::sun::star::uno::UNO_QUERY;
+ using ::com::sun::star::uno::UNO_QUERY_THROW;
+ using ::com::sun::star::uno::UNO_SET_THROW;
+ using ::com::sun::star::uno::Exception;
+ using ::com::sun::star::uno::RuntimeException;
+ using ::com::sun::star::uno::Any;
+ using ::com::sun::star::uno::Sequence;
+ using ::com::sun::star::frame::XFrame;
+ using ::com::sun::star::frame::XController;
+ using ::com::sun::star::frame::XModel;
+ using ::com::sun::star::lang::EventObject;
+ using ::com::sun::star::lang::XComponent;
+ using ::com::sun::star::frame::XModel2;
+ using ::com::sun::star::container::XEnumeration;
+ using ::com::sun::star::util::XCloseable;
+ using ::com::sun::star::awt::XTopWindow;
+ using ::com::sun::star::embed::XComponentSupplier;
+ using ::com::sun::star::ucb::XCommandProcessor;
+ using ::com::sun::star::ucb::Command;
+ using ::com::sun::star::document::XDocumentEventBroadcaster;
+ using ::com::sun::star::beans::XPropertySet;
+ using ::com::sun::star::beans::PropertyChangeEvent;
+
+ // helper structs
+ namespace
+ {
+ struct SubComponentDescriptor
+ {
+ /// the name of the sub component, empty if it is yet unsaved
+ OUString sName;
+ /// type of the component - an ElementType value, except for relation design
+ sal_Int32 nComponentType;
+ /// the mode in which the sub component has been opened
+ ElementOpenMode eOpenMode;
+ /// the frame which the component resides in. Must not be <NULL/>
+ Reference< XFrame > xFrame;
+ /// the controller of the sub component. Must not be <NULL/>
+ Reference< XController > xController;
+ /// the model of the sub component. Might be <NULL/>
+ Reference< XModel > xModel;
+ /// the document definition which holds the component, if any; as CommandProcessor
+ Reference< XCommandProcessor > xComponentCommandProcessor;
+ /// the document definition which holds the component, if any; as PropertySet
+ Reference< XPropertySet > xDocumentDefinitionProperties;
+
+ SubComponentDescriptor()
+ :nComponentType( -1 )
+ ,eOpenMode( E_OPEN_NORMAL )
+ {
+ }
+
+ SubComponentDescriptor( const OUString& i_rName, const sal_Int32 i_nComponentType,
+ const ElementOpenMode i_eOpenMode, const Reference< XComponent >& i_rComponent )
+ :sName( i_rName )
+ ,nComponentType( i_nComponentType )
+ ,eOpenMode( i_eOpenMode )
+ {
+ if ( !impl_constructFrom( i_rComponent ) )
+ {
+ // i_rComponent is neither a model, nor a controller, nor a frame
+ // => it must be a css.sdb.DocumentDefinition
+ Reference< XComponentSupplier > xCompSupp( i_rComponent, UNO_QUERY_THROW );
+ Reference< XComponent > xComponent( xCompSupp->getComponent(), UNO_QUERY_THROW );
+ if ( !impl_constructFrom( xComponent ) )
+ throw RuntimeException("Illegal component type." );
+ xComponentCommandProcessor.set( i_rComponent, UNO_QUERY_THROW );
+ xDocumentDefinitionProperties.set( i_rComponent, UNO_QUERY_THROW );
+ }
+ }
+
+ bool is() const { return xFrame.is(); }
+
+ private:
+ bool impl_constructFrom( const Reference< XComponent >& _rxComponent )
+ {
+ // is it a model?
+ xModel.set( _rxComponent, UNO_QUERY );
+ if ( xModel.is() )
+ {
+ xController.set( xModel->getCurrentController() );
+ if ( xController.is() )
+ xFrame.set( xController->getFrame(), UNO_SET_THROW );
+ }
+ else
+ {
+ // is it a controller?
+ xController.set( _rxComponent, UNO_QUERY );
+ if ( xController.is() )
+ {
+ xFrame.set( xController->getFrame(), UNO_SET_THROW );
+ }
+ else
+ {
+ // is it a frame?
+ xFrame.set( _rxComponent, UNO_QUERY );
+ if ( !xFrame.is() )
+ return false;
+
+ // ensure we have a controller
+ xController.set( xFrame->getController(), UNO_SET_THROW );
+ }
+
+ // check whether there is a model (not required)
+ xModel.set( xController->getModel() );
+ }
+
+ return true;
+ }
+ };
+
+ struct SelectSubComponent
+ {
+ Reference< XComponent > operator()( const SubComponentDescriptor &_desc ) const
+ {
+ if ( _desc.xModel.is() )
+ return _desc.xModel;
+ OSL_ENSURE( _desc.xController.is(), "SelectSubComponent::operator(): illegal component!" );
+ return _desc.xController;
+ }
+ };
+
+ typedef std::vector< SubComponentDescriptor > SubComponents;
+
+ struct SubComponentMatch
+ {
+ public:
+ SubComponentMatch( const OUString& i_rName, const sal_Int32 i_nComponentType,
+ const ElementOpenMode i_eOpenMode )
+ :m_sName( i_rName )
+ ,m_nComponentType( i_nComponentType )
+ ,m_eOpenMode( i_eOpenMode )
+ {
+ }
+
+ bool operator()( const SubComponentDescriptor& i_rCompareWith ) const
+ {
+ return ( m_sName == i_rCompareWith.sName )
+ && ( m_nComponentType == i_rCompareWith.nComponentType )
+ && ( m_eOpenMode == i_rCompareWith.eOpenMode );
+ }
+ private:
+ const OUString m_sName;
+ const sal_Int32 m_nComponentType;
+ const ElementOpenMode m_eOpenMode;
+ };
+ }
+
+ // SubComponentManager_Data
+ struct SubComponentManager_Data
+ {
+ SubComponentManager_Data( OApplicationController& _rController, const ::comphelper::SharedMutex& _rMutex )
+ :m_rController( _rController )
+ ,m_aMutex( _rMutex )
+ {
+ }
+
+ OApplicationController& m_rController;
+ mutable ::comphelper::SharedMutex m_aMutex;
+ SubComponents m_aComponents;
+
+ ::osl::Mutex& getMutex() const { return m_aMutex; }
+ };
+
+ // SubComponentManager
+ SubComponentManager::SubComponentManager( OApplicationController& _rController, const ::comphelper::SharedMutex& _rMutex )
+ :m_pData( new SubComponentManager_Data( _rController, _rMutex ) )
+ {
+ }
+
+ SubComponentManager::~SubComponentManager()
+ {
+ }
+
+ void SubComponentManager::disposing()
+ {
+ ::osl::MutexGuard aGuard( m_pData->getMutex() );
+ m_pData->m_aComponents.clear();
+ }
+
+ namespace
+ {
+ bool lcl_fallbackToAnotherController( SubComponentDescriptor& _rCompDesc )
+ {
+ Reference< XController > xFallback;
+ OSL_PRECOND( _rCompDesc.xModel.is(), "lcl_fallbackToAnotherController: illegal call!" );
+ if ( !_rCompDesc.xModel.is() )
+ return false;
+
+ xFallback.set( _rCompDesc.xModel->getCurrentController() );
+ if ( xFallback == _rCompDesc.xController )
+ // don't accept the very same controller as fallback
+ xFallback.clear();
+
+ if ( !xFallback.is() )
+ {
+ // perhaps XModel2 can be of help here
+ Reference< XModel2 > xModel2( _rCompDesc.xModel, UNO_QUERY );
+ Reference< XEnumeration > xControllerEnum;
+ if ( xModel2.is() )
+ xControllerEnum = xModel2->getControllers();
+ while ( xControllerEnum.is() && xControllerEnum->hasMoreElements() )
+ {
+ xFallback.set( xControllerEnum->nextElement(), UNO_QUERY );
+ if ( xFallback == _rCompDesc.xController )
+ xFallback.clear();
+ }
+ }
+
+ if ( xFallback.is() )
+ {
+ _rCompDesc.xController = xFallback;
+ _rCompDesc.xFrame.set( xFallback->getFrame(), UNO_SET_THROW );
+ return true;
+ }
+
+ return false;
+ }
+
+ bool lcl_closeComponent( const Reference< XCommandProcessor >& _rxCommandProcessor )
+ {
+ bool bSuccess = false;
+ try
+ {
+ sal_Int32 nCommandIdentifier = _rxCommandProcessor->createCommandIdentifier();
+
+ Command aCommand;
+ aCommand.Name = "close";
+ _rxCommandProcessor->execute( aCommand, nCommandIdentifier, nullptr );
+ bSuccess = true;
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ return bSuccess;
+ }
+
+ bool lcl_closeComponent( const SubComponentDescriptor& _rComponent )
+ {
+ if ( _rComponent.xComponentCommandProcessor.is() )
+ return lcl_closeComponent( _rComponent.xComponentCommandProcessor );
+
+ Reference< XController > xController( _rComponent.xController );
+ OSL_ENSURE( xController.is(), "lcl_closeComponent: invalid controller!" );
+
+ // suspend the controller in the document
+ if ( xController.is() )
+ if ( !xController->suspend( true ) )
+ return false;
+
+ bool bSuccess = false;
+ try
+ {
+ Reference< XCloseable > xCloseable( _rComponent.xFrame, UNO_QUERY_THROW );
+ xCloseable->close( true );
+ bSuccess = true;
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ return bSuccess;
+ }
+
+ void lcl_notifySubComponentEvent( const SubComponentManager_Data& _rData, const char* _pAsciiEventName,
+ const SubComponentDescriptor& _rComponent )
+ {
+ try
+ {
+ Reference< XDocumentEventBroadcaster > xBroadcaster( _rData.m_rController.getModel(), UNO_QUERY_THROW );
+ xBroadcaster->notifyDocumentEvent(
+ OUString::createFromAscii( _pAsciiEventName ),
+ &_rData.m_rController,
+ Any( _rComponent.xFrame )
+ );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+ }
+
+ void SAL_CALL SubComponentManager::propertyChange( const PropertyChangeEvent& i_rEvent )
+ {
+ if ( i_rEvent.PropertyName != PROPERTY_NAME )
+ // by definition, it's allowed to broadcast more than what we've registered for
+ return;
+
+ // find the sub component whose name changed
+ for (auto & component : m_pData->m_aComponents)
+ {
+ if ( component.xDocumentDefinitionProperties != i_rEvent.Source )
+ continue;
+
+ OUString sNewName;
+ OSL_VERIFY( i_rEvent.NewValue >>= sNewName );
+
+ #if OSL_DEBUG_LEVEL > 0
+ OUString sOldKnownName( component.sName );
+ OUString sOldName;
+ OSL_VERIFY( i_rEvent.OldValue >>= sOldName );
+ OSL_ENSURE( sOldName == sOldKnownName, "SubComponentManager::propertyChange: inconsistency in the old names!" );
+ #endif
+
+ component.sName = sNewName;
+ break;
+ }
+ }
+
+ void SAL_CALL SubComponentManager::disposing( const EventObject& _rSource )
+ {
+ ::osl::ClearableMutexGuard aGuard( m_pData->getMutex() );
+
+ SubComponentDescriptor aClosedComponent;
+
+ for ( SubComponents::iterator comp = m_pData->m_aComponents.begin();
+ comp != m_pData->m_aComponents.end();
+ ++comp
+ )
+ {
+ bool bRemove = false;
+
+ if ( comp->xController == _rSource.Source )
+ {
+ if ( !comp->xModel.is() )
+ {
+ bRemove = true;
+ }
+ else
+ {
+ // maybe this is just one view to the sub document, and only this view is closed
+ if ( !lcl_fallbackToAnotherController( *comp ) )
+ {
+ bRemove = true;
+ }
+ }
+ }
+ else if ( comp->xModel == _rSource.Source )
+ {
+ bRemove = true;
+ }
+
+ if ( bRemove )
+ {
+ aClosedComponent = *comp;
+ m_pData->m_aComponents.erase( comp );
+ break;
+ }
+ }
+
+ if ( aClosedComponent.is() )
+ {
+ aGuard.clear();
+ lcl_notifySubComponentEvent( *m_pData, "OnSubComponentClosed", aClosedComponent );
+ }
+ }
+
+ Sequence< Reference< XComponent> > SubComponentManager::getSubComponents() const
+ {
+ ::osl::MutexGuard aGuard( m_pData->getMutex() );
+
+ Sequence< Reference< XComponent > > aComponents( m_pData->m_aComponents.size() );
+ std::transform(
+ m_pData->m_aComponents.begin(),
+ m_pData->m_aComponents.end(),
+ aComponents.getArray(),
+ SelectSubComponent()
+ );
+ return aComponents;
+ }
+
+ bool SubComponentManager::closeSubComponents()
+ {
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_pData->getMutex() );
+
+ try
+ {
+ SubComponents aWorkingCopy( m_pData->m_aComponents );
+ for (auto const& elem : aWorkingCopy)
+ {
+ lcl_closeComponent(elem);
+ }
+ }
+ catch ( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+
+ return empty();
+ }
+
+ bool SubComponentManager::empty() const
+ {
+ ::osl::MutexGuard aGuard( m_pData->getMutex() );
+ return m_pData->m_aComponents.empty();
+ }
+
+ void SubComponentManager::onSubComponentOpened( const OUString& _rName, const sal_Int32 _nComponentType,
+ const ElementOpenMode _eOpenMode, const Reference< XComponent >& _rxComponent )
+ {
+ ::osl::ClearableMutexGuard aGuard( m_pData->getMutex() );
+
+#if OSL_DEBUG_LEVEL > 0
+ if ( !_rName.isEmpty() )
+ {
+ // check there does not already exist such a component
+ auto subComponentNotExists = std::none_of(
+ m_pData->m_aComponents.begin(),
+ m_pData->m_aComponents.end(),
+ SubComponentMatch( _rName, _nComponentType, _eOpenMode )
+ );
+ OSL_ENSURE( subComponentNotExists, "already existent!" );
+ }
+#endif
+ SubComponentDescriptor aElement( _rName, _nComponentType, _eOpenMode, _rxComponent );
+ ENSURE_OR_THROW( aElement.xModel.is() || aElement.xController.is(), "illegal component" );
+
+ m_pData->m_aComponents.push_back( aElement );
+
+ // add as listener
+ if ( aElement.xController.is() )
+ aElement.xController->addEventListener( this );
+ if ( aElement.xModel.is() )
+ aElement.xModel->addEventListener( this );
+ if ( aElement.xDocumentDefinitionProperties.is() )
+ aElement.xDocumentDefinitionProperties->addPropertyChangeListener( PROPERTY_NAME, this );
+
+ // notify this to interested parties
+ aGuard.clear();
+ lcl_notifySubComponentEvent( *m_pData, "OnSubComponentOpened", aElement );
+ }
+
+ bool SubComponentManager::activateSubFrame( const OUString& _rName, const sal_Int32 _nComponentType,
+ const ElementOpenMode _eOpenMode, Reference< XComponent >& o_rComponent ) const
+ {
+ ::osl::MutexGuard aGuard( m_pData->getMutex() );
+
+ SubComponents::const_iterator pos = std::find_if(
+ m_pData->m_aComponents.begin(),
+ m_pData->m_aComponents.end(),
+ SubComponentMatch( _rName, _nComponentType, _eOpenMode )
+ );
+ if ( pos == m_pData->m_aComponents.end() )
+ // no component with this name/type/open mode
+ return false;
+
+ const Reference< XFrame > xFrame( pos->xFrame, UNO_SET_THROW );
+ const Reference< XTopWindow > xTopWindow( xFrame->getContainerWindow(), UNO_QUERY_THROW );
+ xTopWindow->toFront();
+
+ if ( pos->xModel.is() )
+ o_rComponent = pos->xModel.get();
+ else if ( pos->xController.is() )
+ o_rComponent = pos->xController.get();
+ else
+ o_rComponent = pos->xFrame.get();
+
+ return true;
+ }
+
+ bool SubComponentManager::closeSubFrames( std::u16string_view i_rName, const sal_Int32 _nComponentType )
+ {
+ ::osl::MutexGuard aGuard( m_pData->getMutex() );
+ ENSURE_OR_RETURN_FALSE( !i_rName.empty(), "SubComponentManager::closeSubFrames: illegal name!" );
+
+ SubComponents aWorkingCopy( m_pData->m_aComponents );
+ for (auto const& elem : aWorkingCopy)
+ {
+ if ( ( elem.sName != i_rName ) || ( elem.nComponentType != _nComponentType ) )
+ continue;
+
+ if ( !lcl_closeComponent(elem) )
+ return false;
+ }
+
+ return true;
+ }
+
+ bool SubComponentManager::lookupSubComponent( const Reference< XComponent >& i_rComponent,
+ OUString& o_rName, sal_Int32& o_rComponentType )
+ {
+ for (auto const& component : m_pData->m_aComponents)
+ {
+ if ( ( component.xModel.is()
+ && ( component.xModel == i_rComponent )
+ )
+ || ( component.xController.is()
+ && ( component.xController == i_rComponent )
+ )
+ || ( component.xFrame.is()
+ && ( component.xFrame == i_rComponent )
+ )
+ )
+ {
+ o_rName = component.sName;
+ o_rComponentType = component.nComponentType;
+ return true;
+ }
+ }
+ return false;
+ }
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/app/subcomponentmanager.hxx b/dbaccess/source/ui/app/subcomponentmanager.hxx
new file mode 100644
index 000000000..402a3d593
--- /dev/null
+++ b/dbaccess/source/ui/app/subcomponentmanager.hxx
@@ -0,0 +1,120 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <AppElementType.hxx>
+
+#include <com/sun/star/beans/XPropertyChangeListener.hpp>
+#include <com/sun/star/lang/XComponent.hpp>
+
+#include <comphelper/sharedmutex.hxx>
+#include <cppuhelper/implbase.hxx>
+
+#include <memory>
+
+namespace dbaui
+{
+
+ struct SubComponentManager_Data;
+ class OApplicationController;
+
+ // SubComponentManager
+ typedef ::cppu::WeakImplHelper< css::beans::XPropertyChangeListener
+ > SubComponentManager_Base;
+ class SubComponentManager : public SubComponentManager_Base
+ {
+ public:
+ SubComponentManager( OApplicationController& _rController, const ::comphelper::SharedMutex& _rMutex );
+ virtual ~SubComponentManager() override;
+
+ void disposing();
+
+ // XPropertyChangeListener
+ virtual void SAL_CALL propertyChange( const css::beans::PropertyChangeEvent& evt ) override;
+
+ // XEventListener
+ virtual void SAL_CALL disposing( const css::lang::EventObject& Source ) override;
+
+ // XDatabaseDocumentUI helpers
+ css::uno::Sequence< css::uno::Reference< css::lang::XComponent> >
+ getSubComponents() const;
+ bool closeSubComponents();
+
+ // container access
+ void onSubComponentOpened(
+ const OUString& _rName,
+ const sal_Int32 _nComponentType,
+ const ElementOpenMode _eOpenMode,
+ const css::uno::Reference< css::lang::XComponent >&
+ _rxComponent
+ );
+ bool empty() const;
+
+ /** activates (i.e. brings to top) the frame in which the given component is loaded, if any
+
+ @return
+ <TRUE/> if any only of such a frame was found, i.e. the component had already been loaded
+ previously
+ */
+ bool activateSubFrame(
+ const OUString& _rName,
+ const sal_Int32 _nComponentType,
+ const ElementOpenMode _eOpenMode,
+ css::uno::Reference< css::lang::XComponent >& o_rComponent
+ ) const;
+
+ /** closes all frames of the given component
+
+ If a view for the component (given by name and type) has been loaded into one or more
+ frames (with potentially different OpenModes), then those frames are gracefully closed.
+
+ @return
+ <TRUE/> if and only if closing those frames was successful, or frames for the given sub component
+ exist.
+ */
+ bool closeSubFrames(
+ std::u16string_view _rName,
+ const sal_Int32 _nComponentType
+ );
+
+ /** searches for the given sub component
+
+ @param i_rComponent
+ the sub component to look up
+ @param o_rName
+ contains, upon successful return, the name of the sub component
+ @param o_nComponentType
+ contains, upon successful return, the type of the sub component
+ @return
+ <TRUE/> if and only if the component was found
+ */
+ bool lookupSubComponent(
+ const css::uno::Reference< css::lang::XComponent >& i_rComponent,
+ OUString& o_rName,
+ sal_Int32& o_rComponentType
+ );
+
+ private:
+ std::unique_ptr< SubComponentManager_Data > m_pData;
+ };
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/app/templwin.cxx b/dbaccess/source/ui/app/templwin.cxx
new file mode 100644
index 000000000..e9940782d
--- /dev/null
+++ b/dbaccess/source/ui/app/templwin.cxx
@@ -0,0 +1,38 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <core_resource.hxx>
+#include <templwin.hrc>
+#include "templwin.hxx"
+
+namespace SvtDocInfoTable_Impl
+{
+ OUString GetString(int nId)
+ {
+ for (size_t i = 0; i < SAL_N_ELEMENTS(STRARY_SVT_DOCINFO); ++i)
+ {
+ if (STRARY_SVT_DOCINFO[i].second == nId)
+ return DBA_RES(STRARY_SVT_DOCINFO[i].first);
+ }
+
+ return OUString();
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/app/templwin.hxx b/dbaccess/source/ui/app/templwin.hxx
new file mode 100644
index 000000000..8978a6ea3
--- /dev/null
+++ b/dbaccess/source/ui/app/templwin.hxx
@@ -0,0 +1,28 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <rtl/ustring.hxx>
+
+namespace SvtDocInfoTable_Impl
+{
+OUString GetString(int nId);
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/app/window_layout.txt b/dbaccess/source/ui/app/window_layout.txt
new file mode 100644
index 000000000..abb15f00b
--- /dev/null
+++ b/dbaccess/source/ui/app/window_layout.txt
@@ -0,0 +1,49 @@
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This file incorporates work covered by the following license notice:
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed
+# with this work for additional information regarding copyright
+# ownership. The ASF licenses this file to you under the Apache
+# License, Version 2.0 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.apache.org/licenses/LICENSE-2.0 .
+#
+
+(still unfinished)
+
+OApplicationView
+|
++-OAppBorderWindow
+ |
+ +-OTitleWindow "Database"
+ | |
+ | +-OApplicationSwapWindow
+ | |
+ | +-OApplicationIconControl
+ |
+ +-OApplicationDetailView
+ |
+ +-OTitleWindow "Tasks"
+ | |
+ | +-OTasksWindow
+ | |
+ | +-OCreationList
+ |
+ +-OTitleWindow "Forms" "Tables" "Queries" "Reports"
+ |
+ +-OAppDetailPageHelper
+ |
+ +-SvTreeListBox*
+ |
+ +-FixedLine
+ |
+ +-Window (Border)
+ |
+ +-OPreviewWindow
diff --git a/dbaccess/source/ui/browser/AsynchronousLink.cxx b/dbaccess/source/ui/browser/AsynchronousLink.cxx
new file mode 100644
index 000000000..e4dcdb2f9
--- /dev/null
+++ b/dbaccess/source/ui/browser/AsynchronousLink.cxx
@@ -0,0 +1,81 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <dbaccess/AsynchronousLink.hxx>
+#include <vcl/svapp.hxx>
+
+// OAsynchronousLink
+using namespace dbaui;
+OAsynchronousLink::OAsynchronousLink(const Link<void*, void>& _rHandler)
+ : m_aHandler(_rHandler)
+ , m_nEventId(nullptr)
+{
+}
+
+OAsynchronousLink::~OAsynchronousLink()
+{
+ {
+ ::osl::MutexGuard aEventGuard(m_aEventSafety);
+ if (m_nEventId)
+ Application::RemoveUserEvent(m_nEventId);
+ m_nEventId = nullptr;
+ }
+
+ {
+ ::osl::MutexGuard aDestructionGuard(m_aDestructionSafety);
+ // this is just for the case we're deleted while another thread just handled the event :
+ // if this other thread called our link while we were deleting the event here, the
+ // link handler blocked. With leaving the above block it continued, but now we are prevented
+ // to leave this destructor 'til the link handler recognizes that nEvent == 0 and leaves.
+ }
+}
+
+void OAsynchronousLink::Call(void* _pArgument)
+{
+ ::osl::MutexGuard aEventGuard(m_aEventSafety);
+ if (m_nEventId)
+ Application::RemoveUserEvent(m_nEventId);
+ m_nEventId = Application::PostUserEvent(LINK(this, OAsynchronousLink, OnAsyncCall), _pArgument);
+}
+
+void OAsynchronousLink::CancelCall()
+{
+ ::osl::MutexGuard aEventGuard(m_aEventSafety);
+ if (m_nEventId)
+ Application::RemoveUserEvent(m_nEventId);
+ m_nEventId = nullptr;
+}
+
+IMPL_LINK(OAsynchronousLink, OnAsyncCall, void*, _pArg, void)
+{
+ {
+ ::osl::MutexGuard aDestructionGuard(m_aDestructionSafety);
+ {
+ ::osl::MutexGuard aEventGuard(m_aEventSafety);
+ if (!m_nEventId)
+ // our destructor deleted the event just while we are waiting for m_aEventSafety
+ // -> get outta here
+ return;
+ m_nEventId = nullptr;
+ }
+ }
+ m_aHandler.Call(_pArg);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/browser/brwctrlr.cxx b/dbaccess/source/ui/browser/brwctrlr.cxx
new file mode 100644
index 000000000..b8387b203
--- /dev/null
+++ b/dbaccess/source/ui/browser/brwctrlr.cxx
@@ -0,0 +1,2616 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <browserids.hxx>
+#include <brwctrlr.hxx>
+#include <brwview.hxx>
+#include <strings.hrc>
+#include <strings.hxx>
+#include <core_resource.hxx>
+#include <queryfilter.hxx>
+#include <queryorder.hxx>
+#include <sqlmessage.hxx>
+
+#include <com/sun/star/container/XNameContainer.hpp>
+#include <com/sun/star/form/XBoundControl.hpp>
+#include <com/sun/star/form/XDatabaseParameterBroadcaster.hpp>
+#include <com/sun/star/form/XLoadable.hpp>
+#include <com/sun/star/form/XReset.hpp>
+#include <com/sun/star/form/XResetListener.hpp>
+#include <com/sun/star/form/runtime/XFormController.hpp>
+#include <com/sun/star/form/runtime/FormOperations.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/lang/NoSupportException.hpp>
+#include <com/sun/star/sdb/CommandType.hpp>
+#include <com/sun/star/sdb/ErrorCondition.hpp>
+#include <com/sun/star/sdb/ParametersRequest.hpp>
+#include <com/sun/star/sdb/XInteractionSupplyParameters.hpp>
+#include <com/sun/star/sdb/XSQLErrorBroadcaster.hpp>
+#include <com/sun/star/sdb/XSingleSelectQueryComposer.hpp>
+#include <com/sun/star/sdb/SQLFilterOperator.hpp>
+#include <com/sun/star/sdbc/XConnection.hpp>
+#include <com/sun/star/sdbc/XResultSetUpdate.hpp>
+#include <com/sun/star/sdbc/XWarningsSupplier.hpp>
+#include <com/sun/star/sdbcx/Privilege.hpp>
+#include <com/sun/star/sdbcx/XRowLocate.hpp>
+#include <com/sun/star/task/InteractionHandler.hpp>
+#include <com/sun/star/util/NumberFormatter.hpp>
+
+#include <comphelper/enumhelper.hxx>
+#include <comphelper/extract.hxx>
+#include <comphelper/interaction.hxx>
+#include <comphelper/sequence.hxx>
+#include <comphelper/string.hxx>
+#include <comphelper/types.hxx>
+#include <connectivity/dbexception.hxx>
+#include <connectivity/dbtools.hxx>
+#include <connectivity/sqlerror.hxx>
+#include <cppuhelper/exc_hlp.hxx>
+#include <cppuhelper/implbase2.hxx>
+#include <osl/mutex.hxx>
+#include <sal/log.hxx>
+#include <svx/fmsearch.hxx>
+#include <svx/svxdlg.hxx>
+#include <tools/diagnose_ex.h>
+#include <osl/diagnose.h>
+#include <vcl/svapp.hxx>
+#include <vcl/weld.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::awt;
+using namespace ::com::sun::star::sdb;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::sdbcx;
+using namespace ::com::sun::star::task;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::frame;
+using namespace ::com::sun::star::form::runtime;
+using namespace ::com::sun::star::form;
+using namespace ::com::sun::star::util;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::container;
+using namespace ::dbtools;
+using namespace ::comphelper;
+using namespace ::svt;
+
+namespace dbaui
+{
+
+namespace {
+
+// OParameterContinuation
+class OParameterContinuation : public OInteraction< XInteractionSupplyParameters >
+{
+ Sequence< PropertyValue > m_aValues;
+
+public:
+ OParameterContinuation() { }
+
+ const Sequence< PropertyValue >& getValues() const { return m_aValues; }
+
+// XInteractionSupplyParameters
+ virtual void SAL_CALL setParameters( const Sequence< PropertyValue >& _rValues ) override;
+};
+
+}
+
+void SAL_CALL OParameterContinuation::setParameters( const Sequence< PropertyValue >& _rValues )
+{
+ m_aValues = _rValues;
+}
+
+// a helper class implementing a runtime::XFormController, will be aggregated by SbaXDataBrowserController
+// (we can't derive from XFormController as it's base class is XTabController and the XTabController::getModel collides
+// with the XController::getModel implemented in our base class SbaXDataBrowserController)
+class SbaXDataBrowserController::FormControllerImpl
+ : public ::cppu::WeakAggImplHelper2< css::form::runtime::XFormController,
+ css::frame::XFrameActionListener >
+{
+ friend class SbaXDataBrowserController;
+ ::comphelper::OInterfaceContainerHelper3<css::form::XFormControllerListener> m_aActivateListeners;
+ SbaXDataBrowserController* m_pOwner;
+
+public:
+ explicit FormControllerImpl(SbaXDataBrowserController* pOwner);
+
+ // XFormController
+ virtual css::uno::Reference< css::form::runtime::XFormOperations > SAL_CALL getFormOperations() override;
+ virtual css::uno::Reference< css::awt::XControl > SAL_CALL getCurrentControl() override;
+ virtual void SAL_CALL addActivateListener(const css::uno::Reference< css::form::XFormControllerListener > & l) override;
+ virtual void SAL_CALL removeActivateListener(const css::uno::Reference< css::form::XFormControllerListener > & l) override;
+ virtual void SAL_CALL addChildController( const css::uno::Reference< css::form::runtime::XFormController >& ChildController ) override;
+ virtual css::uno::Reference< css::form::runtime::XFormControllerContext > SAL_CALL getContext() override;
+ virtual void SAL_CALL setContext( const css::uno::Reference< css::form::runtime::XFormControllerContext >& _context ) override;
+ virtual css::uno::Reference< css::task::XInteractionHandler > SAL_CALL getInteractionHandler() override;
+ virtual void SAL_CALL setInteractionHandler( const css::uno::Reference< css::task::XInteractionHandler >& _interactionHandler ) override;
+
+ // XChild, base of XFormController
+ virtual css::uno::Reference< css::uno::XInterface > SAL_CALL getParent( ) override;
+ virtual void SAL_CALL setParent( const css::uno::Reference< css::uno::XInterface >& Parent ) override;
+
+ // XComponent, base of XFormController
+ virtual void SAL_CALL dispose( ) override;
+ virtual void SAL_CALL addEventListener( const css::uno::Reference< css::lang::XEventListener >& xListener ) override;
+ virtual void SAL_CALL removeEventListener( const css::uno::Reference< css::lang::XEventListener >& aListener ) override;
+
+ // XIndexAccess, base of XFormController
+ virtual ::sal_Int32 SAL_CALL getCount( ) override;
+ virtual css::uno::Any SAL_CALL getByIndex( ::sal_Int32 Index ) override;
+
+ // XElementAccess, base of XIndexAccess
+ virtual css::uno::Type SAL_CALL getElementType( ) override;
+ virtual sal_Bool SAL_CALL hasElements( ) override;
+
+ // XEnumerationAccess, base of XElementAccess
+ virtual css::uno::Reference< css::container::XEnumeration > SAL_CALL createEnumeration( ) override;
+
+ // XModifyBroadcaster, base of XFormController
+ virtual void SAL_CALL addModifyListener( const css::uno::Reference< css::util::XModifyListener >& aListener ) override;
+ virtual void SAL_CALL removeModifyListener( const css::uno::Reference< css::util::XModifyListener >& aListener ) override;
+
+ // XConfirmDeleteBroadcaster, base of XFormController
+ virtual void SAL_CALL addConfirmDeleteListener( const css::uno::Reference< css::form::XConfirmDeleteListener >& aListener ) override;
+ virtual void SAL_CALL removeConfirmDeleteListener( const css::uno::Reference< css::form::XConfirmDeleteListener >& aListener ) override;
+
+ // XSQLErrorBroadcaster, base of XFormController
+ virtual void SAL_CALL addSQLErrorListener( const css::uno::Reference< css::sdb::XSQLErrorListener >& Listener ) override;
+ virtual void SAL_CALL removeSQLErrorListener( const css::uno::Reference< css::sdb::XSQLErrorListener >& Listener ) override;
+
+ // XRowSetApproveBroadcaster, base of XFormController
+ virtual void SAL_CALL addRowSetApproveListener( const css::uno::Reference< css::sdb::XRowSetApproveListener >& listener ) override;
+ virtual void SAL_CALL removeRowSetApproveListener( const css::uno::Reference< css::sdb::XRowSetApproveListener >& listener ) override;
+
+ // XDatabaseParameterBroadcaster2, base of XFormController
+ virtual void SAL_CALL addDatabaseParameterListener( const css::uno::Reference< css::form::XDatabaseParameterListener >& aListener ) override;
+ virtual void SAL_CALL removeDatabaseParameterListener( const css::uno::Reference< css::form::XDatabaseParameterListener >& aListener ) override;
+
+ // XDatabaseParameterBroadcaster, base of XDatabaseParameterBroadcaster2
+ virtual void SAL_CALL addParameterListener( const css::uno::Reference< css::form::XDatabaseParameterListener >& aListener ) override;
+ virtual void SAL_CALL removeParameterListener( const css::uno::Reference< css::form::XDatabaseParameterListener >& aListener ) override;
+
+ // XModeSelector, base of XFormController
+ virtual void SAL_CALL setMode( const OUString& aMode ) override;
+ virtual OUString SAL_CALL getMode( ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedModes( ) override;
+ virtual sal_Bool SAL_CALL supportsMode( const OUString& aMode ) override;
+
+ // XTabController, base of XFormController
+ virtual void SAL_CALL setModel(const css::uno::Reference< css::awt::XTabControllerModel > & Model) override;
+ virtual css::uno::Reference< css::awt::XTabControllerModel > SAL_CALL getModel() override;
+ virtual void SAL_CALL setContainer(const css::uno::Reference< css::awt::XControlContainer > & Container) override;
+ virtual css::uno::Reference< css::awt::XControlContainer > SAL_CALL getContainer() override;
+ virtual css::uno::Sequence< css::uno::Reference< css::awt::XControl > > SAL_CALL getControls() override;
+ virtual void SAL_CALL autoTabOrder() override;
+ virtual void SAL_CALL activateTabOrder() override;
+ virtual void SAL_CALL activateFirst() override;
+ virtual void SAL_CALL activateLast() override;
+
+ // XFrameActionListener
+ virtual void SAL_CALL frameAction(const css::frame::FrameActionEvent& aEvent) override;
+
+ // XEventListener
+ virtual void SAL_CALL disposing(const css::lang::EventObject& Source) override;
+
+protected:
+ virtual ~FormControllerImpl() override;
+};
+
+SbaXDataBrowserController::FormControllerImpl::FormControllerImpl(SbaXDataBrowserController* _pOwner)
+ :m_aActivateListeners(_pOwner->getMutex())
+ ,m_pOwner(_pOwner)
+{
+
+ OSL_ENSURE(m_pOwner, "SbaXDataBrowserController::FormControllerImpl::FormControllerImpl : invalid Owner !");
+}
+
+SbaXDataBrowserController::FormControllerImpl::~FormControllerImpl()
+{
+
+}
+
+Reference< runtime::XFormOperations > SAL_CALL SbaXDataBrowserController::FormControllerImpl::getFormOperations()
+{
+ return FormOperations::createWithFormController( m_pOwner->m_xContext, this );
+}
+
+Reference< css::awt::XControl > SbaXDataBrowserController::FormControllerImpl::getCurrentControl()
+{
+ return m_pOwner->getBrowserView() ? m_pOwner->getBrowserView()->getGridControl() : Reference< css::awt::XControl > ();
+}
+
+void SAL_CALL SbaXDataBrowserController::FormControllerImpl::addActivateListener(const Reference< css::form::XFormControllerListener > & l)
+{
+ m_aActivateListeners.addInterface(l);
+}
+
+void SAL_CALL SbaXDataBrowserController::FormControllerImpl::removeActivateListener(const Reference< css::form::XFormControllerListener > & l)
+{
+ m_aActivateListeners.removeInterface(l);
+}
+
+void SAL_CALL SbaXDataBrowserController::FormControllerImpl::addChildController( const Reference< runtime::XFormController >& )
+{
+ // not supported
+ throw IllegalArgumentException( OUString(), *this, 1 );
+}
+
+Reference< runtime::XFormControllerContext > SAL_CALL SbaXDataBrowserController::FormControllerImpl::getContext()
+{
+ SAL_WARN("dbaccess.ui", "SbaXDataBrowserController::FormControllerImpl::getContext: no support!!" );
+ return nullptr;
+}
+
+void SAL_CALL SbaXDataBrowserController::FormControllerImpl::setContext( const Reference< runtime::XFormControllerContext >& /*_context*/ )
+{
+ SAL_WARN("dbaccess.ui", "SbaXDataBrowserController::FormControllerImpl::setContext: no support!!" );
+}
+
+Reference< XInteractionHandler > SAL_CALL SbaXDataBrowserController::FormControllerImpl::getInteractionHandler()
+{
+ SAL_WARN("dbaccess.ui", "SbaXDataBrowserController::FormControllerImpl::getInteractionHandler: no support!!" );
+ return nullptr;
+}
+
+void SAL_CALL SbaXDataBrowserController::FormControllerImpl::setInteractionHandler( const Reference< XInteractionHandler >& /*_interactionHandler*/ )
+{
+ SAL_WARN("dbaccess.ui", "SbaXDataBrowserController::FormControllerImpl::setInteractionHandler: no support!!" );
+}
+
+Reference< XInterface > SAL_CALL SbaXDataBrowserController::FormControllerImpl::getParent( )
+{
+ // don't have any parent form controllers
+ return nullptr;
+}
+
+void SAL_CALL SbaXDataBrowserController::FormControllerImpl::setParent( const Reference< XInterface >& /*Parent*/ )
+{
+ throw NoSupportException( OUString(), *this );
+}
+
+void SAL_CALL SbaXDataBrowserController::FormControllerImpl::dispose( )
+{
+ SAL_WARN("dbaccess.ui", "SbaXDataBrowserController::FormControllerImpl::dispose: no, you do *not* want to do this!" );
+}
+
+void SAL_CALL SbaXDataBrowserController::FormControllerImpl::addEventListener( const Reference< XEventListener >& /*xListener*/ )
+{
+ SAL_WARN("dbaccess.ui", "SbaXDataBrowserController::FormControllerImpl::addEventListener: no support!!" );
+}
+
+void SAL_CALL SbaXDataBrowserController::FormControllerImpl::removeEventListener( const Reference< XEventListener >& /*aListener*/ )
+{
+ SAL_WARN("dbaccess.ui", "SbaXDataBrowserController::FormControllerImpl::removeEventListener: no support!!" );
+}
+
+::sal_Int32 SAL_CALL SbaXDataBrowserController::FormControllerImpl::getCount( )
+{
+ // no sub controllers, never
+ return 0;
+}
+
+Any SAL_CALL SbaXDataBrowserController::FormControllerImpl::getByIndex( ::sal_Int32 /*Index*/ )
+{
+ // no sub controllers, never
+ throw IndexOutOfBoundsException( OUString(), *this );
+}
+
+Type SAL_CALL SbaXDataBrowserController::FormControllerImpl::getElementType( )
+{
+ return ::cppu::UnoType< runtime::XFormController >::get();
+}
+
+sal_Bool SAL_CALL SbaXDataBrowserController::FormControllerImpl::hasElements( )
+{
+ // no sub controllers, never
+ return false;
+}
+
+Reference< XEnumeration > SAL_CALL SbaXDataBrowserController::FormControllerImpl::createEnumeration( )
+{
+ return new ::comphelper::OEnumerationByIndex( this );
+}
+
+void SAL_CALL SbaXDataBrowserController::FormControllerImpl::addModifyListener( const Reference< XModifyListener >& /*_Listener*/ )
+{
+ SAL_WARN("dbaccess.ui", "SbaXDataBrowserController::FormControllerImpl::addModifyListener: no support!" );
+}
+
+void SAL_CALL SbaXDataBrowserController::FormControllerImpl::removeModifyListener( const Reference< XModifyListener >& /*_Listener*/ )
+{
+ SAL_WARN("dbaccess.ui", "SbaXDataBrowserController::FormControllerImpl::removeModifyListener: no support!" );
+}
+
+void SAL_CALL SbaXDataBrowserController::FormControllerImpl::addConfirmDeleteListener( const Reference< XConfirmDeleteListener >& /*_Listener*/ )
+{
+ SAL_WARN("dbaccess.ui", "SbaXDataBrowserController::FormControllerImpl::addConfirmDeleteListener: no support!" );
+}
+
+void SAL_CALL SbaXDataBrowserController::FormControllerImpl::removeConfirmDeleteListener( const Reference< XConfirmDeleteListener >& /*_Listener*/ )
+{
+ SAL_WARN("dbaccess.ui", "SbaXDataBrowserController::FormControllerImpl::removeConfirmDeleteListener: no support!" );
+}
+
+void SAL_CALL SbaXDataBrowserController::FormControllerImpl::addSQLErrorListener( const Reference< XSQLErrorListener >& /*_Listener*/ )
+{
+ SAL_WARN("dbaccess.ui", "SbaXDataBrowserController::FormControllerImpl::addSQLErrorListener: no support!" );
+}
+
+void SAL_CALL SbaXDataBrowserController::FormControllerImpl::removeSQLErrorListener( const Reference< XSQLErrorListener >& /*_Listener*/ )
+{
+ SAL_WARN("dbaccess.ui", "SbaXDataBrowserController::FormControllerImpl::removeSQLErrorListener: no support!" );
+}
+
+void SAL_CALL SbaXDataBrowserController::FormControllerImpl::addRowSetApproveListener( const Reference< XRowSetApproveListener >& /*_Listener*/ )
+{
+ SAL_WARN("dbaccess.ui", "SbaXDataBrowserController::FormControllerImpl::addRowSetApproveListener: no support!" );
+}
+
+void SAL_CALL SbaXDataBrowserController::FormControllerImpl::removeRowSetApproveListener( const Reference< XRowSetApproveListener >& /*_Listener*/ )
+{
+ SAL_WARN("dbaccess.ui", "SbaXDataBrowserController::FormControllerImpl::removeRowSetApproveListener: no support!" );
+}
+
+void SAL_CALL SbaXDataBrowserController::FormControllerImpl::addDatabaseParameterListener( const Reference< XDatabaseParameterListener >& /*_Listener*/ )
+{
+ SAL_WARN("dbaccess.ui", "SbaXDataBrowserController::FormControllerImpl::addDatabaseParameterListener: no support!" );
+}
+
+void SAL_CALL SbaXDataBrowserController::FormControllerImpl::removeDatabaseParameterListener( const Reference< XDatabaseParameterListener >& /*_Listener*/ )
+{
+ SAL_WARN("dbaccess.ui", "SbaXDataBrowserController::FormControllerImpl::removeDatabaseParameterListener: no support!" );
+}
+
+void SAL_CALL SbaXDataBrowserController::FormControllerImpl::addParameterListener( const Reference< XDatabaseParameterListener >& /*_Listener*/ )
+{
+ SAL_WARN("dbaccess.ui", "SbaXDataBrowserController::FormControllerImpl::addParameterListener: no support!" );
+}
+
+void SAL_CALL SbaXDataBrowserController::FormControllerImpl::removeParameterListener( const Reference< XDatabaseParameterListener >& /*_Listener*/ )
+{
+ SAL_WARN("dbaccess.ui", "SbaXDataBrowserController::FormControllerImpl::removeParameterListener: no support!" );
+}
+
+void SAL_CALL SbaXDataBrowserController::FormControllerImpl::setMode( const OUString& _rMode )
+{
+ if ( !supportsMode( _rMode ) )
+ throw NoSupportException();
+}
+
+OUString SAL_CALL SbaXDataBrowserController::FormControllerImpl::getMode( )
+{
+ return "DataMode";
+}
+
+Sequence< OUString > SAL_CALL SbaXDataBrowserController::FormControllerImpl::getSupportedModes( )
+{
+ Sequence< OUString > aModes { "DataMode" };
+ return aModes;
+}
+
+sal_Bool SAL_CALL SbaXDataBrowserController::FormControllerImpl::supportsMode( const OUString& aMode )
+{
+ return aMode == "DataMode";
+}
+
+void SAL_CALL SbaXDataBrowserController::FormControllerImpl::setModel(const Reference< css::awt::XTabControllerModel > & /*Model*/)
+{
+ SAL_WARN("dbaccess.ui","SbaXDataBrowserController::FormControllerImpl::setModel : invalid call, can't change my model !");
+}
+
+Reference< css::awt::XTabControllerModel > SAL_CALL SbaXDataBrowserController::FormControllerImpl::getModel()
+{
+ return Reference< XTabControllerModel >(m_pOwner->getRowSet(), UNO_QUERY);
+}
+
+void SAL_CALL SbaXDataBrowserController::FormControllerImpl::setContainer(const Reference< css::awt::XControlContainer > &)
+{
+ SAL_WARN("dbaccess.ui","SbaXDataBrowserController::FormControllerImpl::setContainer : invalid call, can't change my container !");
+}
+
+Reference< css::awt::XControlContainer > SAL_CALL SbaXDataBrowserController::FormControllerImpl::getContainer()
+{
+ if (m_pOwner->getBrowserView())
+ return m_pOwner->getBrowserView()->getContainer();
+ return Reference< css::awt::XControlContainer > ();
+}
+
+Sequence< Reference< css::awt::XControl > > SAL_CALL SbaXDataBrowserController::FormControllerImpl::getControls()
+{
+ if (m_pOwner->getBrowserView())
+ {
+ Reference< css::awt::XControl > xGrid = m_pOwner->getBrowserView()->getGridControl();
+ return Sequence< Reference< css::awt::XControl > >(&xGrid, 1);
+ }
+ return Sequence< Reference< css::awt::XControl > >();
+}
+
+void SAL_CALL SbaXDataBrowserController::FormControllerImpl::autoTabOrder()
+{
+ SAL_WARN("dbaccess.ui","SbaXDataBrowserController::FormControllerImpl::autoTabOrder : nothing to do (always have only one control) !");
+}
+
+void SAL_CALL SbaXDataBrowserController::FormControllerImpl::activateTabOrder()
+{
+ SAL_WARN("dbaccess.ui","SbaXDataBrowserController::FormControllerImpl::activateTabOrder : nothing to do (always have only one control) !");
+}
+
+void SAL_CALL SbaXDataBrowserController::FormControllerImpl::activateFirst()
+{
+ if (m_pOwner->getBrowserView())
+ m_pOwner->getBrowserView()->getVclControl()->ActivateCell();
+}
+
+void SAL_CALL SbaXDataBrowserController::FormControllerImpl::activateLast()
+{
+ if (m_pOwner->getBrowserView())
+ m_pOwner->getBrowserView()->getVclControl()->ActivateCell();
+}
+
+void SAL_CALL SbaXDataBrowserController::FormControllerImpl::frameAction(const css::frame::FrameActionEvent& /*aEvent*/)
+{
+}
+
+void SAL_CALL SbaXDataBrowserController::FormControllerImpl::disposing(const css::lang::EventObject& /*Source*/)
+{
+ // nothing to do
+ // we don't add ourself as listener to any broadcasters, so we are not responsible for removing us
+}
+
+// SbaXDataBrowserController
+Sequence< Type > SAL_CALL SbaXDataBrowserController::getTypes( )
+{
+ return ::comphelper::concatSequences(
+ SbaXDataBrowserController_Base::getTypes(),
+ m_xFormControllerImpl->getTypes()
+ );
+}
+
+Sequence< sal_Int8 > SAL_CALL SbaXDataBrowserController::getImplementationId( )
+{
+ return css::uno::Sequence<sal_Int8>();
+}
+
+Any SAL_CALL SbaXDataBrowserController::queryInterface(const Type& _rType)
+{
+ // check for our additional interfaces
+ Any aRet = SbaXDataBrowserController_Base::queryInterface(_rType);
+
+ // check for our aggregate (implementing the XFormController)
+ if (!aRet.hasValue())
+ aRet = m_xFormControllerImpl->queryAggregation(_rType);
+
+ // no more to offer
+ return aRet;
+}
+
+SbaXDataBrowserController::SbaXDataBrowserController(const Reference< css::uno::XComponentContext >& _rM)
+ :SbaXDataBrowserController_Base(_rM)
+ ,m_nRowSetPrivileges(0)
+ ,m_aInvalidateClipboard("dbaui::SbaXDataBrowserController m_aInvalidateClipboard")
+ ,m_aAsyncGetCellFocus(LINK(this, SbaXDataBrowserController, OnAsyncGetCellFocus))
+ ,m_aAsyncDisplayError( LINK( this, SbaXDataBrowserController, OnAsyncDisplayError ) )
+ ,m_sStateSaveRecord(DBA_RES(RID_STR_SAVE_CURRENT_RECORD))
+ ,m_sStateUndoRecord(DBA_RES(RID_STR_UNDO_MODIFY_RECORD))
+ ,m_sModuleIdentifier( OUString( "com.sun.star.sdb.DataSourceBrowser" ) )
+ ,m_nFormActionNestingLevel(0)
+ ,m_bLoadCanceled( false )
+ ,m_bCannotSelectUnfiltered( true )
+{
+ // create the form controller aggregate
+ osl_atomic_increment(&m_refCount);
+ {
+ m_xFormControllerImpl = new FormControllerImpl(this);
+ m_xFormControllerImpl->setDelegator(*this);
+ }
+ osl_atomic_decrement(&m_refCount);
+
+ m_aInvalidateClipboard.SetInvokeHandler(LINK(this, SbaXDataBrowserController, OnInvalidateClipboard));
+ m_aInvalidateClipboard.SetTimeout(300);
+}
+
+SbaXDataBrowserController::~SbaXDataBrowserController()
+{
+ // deleteView();
+ // release the aggregated form controller
+ if (m_xFormControllerImpl.is())
+ {
+ Reference< XInterface > xEmpty;
+ m_xFormControllerImpl->setDelegator(xEmpty);
+ }
+
+}
+
+void SbaXDataBrowserController::startFrameListening( const Reference< XFrame >& _rxFrame )
+{
+ SbaXDataBrowserController_Base::startFrameListening( _rxFrame );
+
+ Reference< XFrameActionListener > xAggListener;
+ if ( m_xFormControllerImpl.is() )
+ m_xFormControllerImpl->queryAggregation( cppu::UnoType<XFrameActionListener>::get() ) >>= xAggListener;
+
+ if ( _rxFrame.is() && xAggListener.is() )
+ _rxFrame->addFrameActionListener( xAggListener );
+}
+
+void SbaXDataBrowserController::stopFrameListening( const Reference< XFrame >& _rxFrame )
+{
+ SbaXDataBrowserController_Base::stopFrameListening( _rxFrame );
+
+ Reference< XFrameActionListener > xAggListener;
+ if ( m_xFormControllerImpl.is() )
+ m_xFormControllerImpl->queryAggregation( cppu::UnoType<XFrameActionListener>::get() ) >>= xAggListener;
+
+ if ( _rxFrame.is() && xAggListener.is() )
+ _rxFrame->removeFrameActionListener( xAggListener );
+}
+
+void SbaXDataBrowserController::onStartLoading( const Reference< XLoadable >& _rxLoadable )
+{
+ m_bLoadCanceled = false;
+ m_bCannotSelectUnfiltered = false;
+
+ Reference< XWarningsSupplier > xWarnings( _rxLoadable, UNO_QUERY );
+ if ( xWarnings.is() )
+ {
+ try
+ {
+ xWarnings->clearWarnings();
+ }
+ catch(const SQLException& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+}
+
+void SbaXDataBrowserController::impl_checkForCannotSelectUnfiltered( const SQLExceptionInfo& _rError )
+{
+ ::connectivity::ErrorCode nErrorCode( connectivity::SQLError::getErrorCode( sdb::ErrorCondition::DATA_CANNOT_SELECT_UNFILTERED ) );
+ if ( static_cast<const SQLException*>(_rError)->ErrorCode == nErrorCode )
+ {
+ m_bCannotSelectUnfiltered = true;
+ InvalidateFeature( ID_BROWSER_FILTERCRIT );
+ }
+}
+
+bool SbaXDataBrowserController::reloadForm( const Reference< XLoadable >& _rxLoadable )
+{
+ weld::WaitObject aWO(getFrameWeld());
+
+ onStartLoading( _rxLoadable );
+
+ FormErrorHelper aReportError(this);
+ if (_rxLoadable->isLoaded())
+ _rxLoadable->reload();
+ else
+ _rxLoadable->load();
+
+ m_xParser.clear();
+ const Reference< XPropertySet > xFormSet(getRowSet(), UNO_QUERY);
+ if (::comphelper::getBOOL(xFormSet->getPropertyValue(PROPERTY_ESCAPE_PROCESSING)))
+ xFormSet->getPropertyValue(PROPERTY_SINGLESELECTQUERYCOMPOSER) >>= m_xParser;
+#if 0
+ {
+ const Reference< XPropertySet > xRowSetProps( getRowSet(), UNO_QUERY );
+ const Reference< XSingleSelectQueryAnalyzer > xAnalyzer( xRowSetProps->getPropertyValue( PROPERTY_SINGLESELECTQUERYCOMPOSER ), UNO_QUERY );
+ if ( xAnalyzer.is() )
+ {
+ const Reference< XIndexAccess > xOrderColumns( xAnalyzer->getOrderColumns(), UNO_SET_THROW );
+ const sal_Int32 nOrderColumns( xOrderColumns->getCount() );
+ for ( sal_Int32 c=0; c<nOrderColumns; ++c )
+ {
+ const Reference< XPropertySet > xOrderColumn( xOrderColumns->getByIndex(c), UNO_QUERY_THROW );
+ OUString sColumnName;
+ OSL_VERIFY( xOrderColumn->getPropertyValue( PROPERTY_NAME ) >>= sColumnName);
+ OUString sTableName;
+ OSL_VERIFY( xOrderColumn->getPropertyValue( PROPERTY_TABLENAME ) >>= sTableName);
+ (void)sColumnName;
+ (void)sTableName;
+ }
+ }
+ }
+#endif
+
+ Reference< XWarningsSupplier > xWarnings( _rxLoadable, UNO_QUERY );
+ if ( xWarnings.is() )
+ {
+ try
+ {
+ SQLExceptionInfo aInfo( xWarnings->getWarnings() );
+ if ( aInfo.isValid() )
+ {
+ showError( aInfo );
+ impl_checkForCannotSelectUnfiltered( aInfo );
+ }
+ }
+ catch(const SQLException& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+
+ return _rxLoadable->isLoaded();
+}
+
+void SbaXDataBrowserController::initFormatter()
+{
+ // create a formatter working with the connections format supplier
+ Reference< css::util::XNumberFormatsSupplier > xSupplier(::dbtools::getNumberFormats(::dbtools::getConnection(m_xRowSet), true, getORB()));
+
+ if(xSupplier.is())
+ {
+ // create a new formatter
+ m_xFormatter.set(util::NumberFormatter::create(getORB()), UNO_QUERY_THROW);
+ m_xFormatter->attachNumberFormatsSupplier(xSupplier);
+ }
+ else // clear the formatter
+ m_xFormatter = nullptr;
+}
+
+void SbaXDataBrowserController::describeSupportedFeatures()
+{
+ SbaXDataBrowserController_Base::describeSupportedFeatures();
+ implDescribeSupportedFeature( ".uno:FormSlots/undoRecord", ID_BROWSER_UNDORECORD, CommandGroup::CONTROLS );
+ implDescribeSupportedFeature( ".uno:FormController/undoRecord", ID_BROWSER_UNDORECORD, CommandGroup::CONTROLS );
+ implDescribeSupportedFeature( ".uno:RecUndo", ID_BROWSER_UNDORECORD, CommandGroup::CONTROLS );
+ implDescribeSupportedFeature( ".uno:FormSlots/saveRecord", ID_BROWSER_SAVERECORD, CommandGroup::CONTROLS );
+ implDescribeSupportedFeature( ".uno:FormController/saveRecord", ID_BROWSER_SAVERECORD, CommandGroup::CONTROLS );
+ implDescribeSupportedFeature( ".uno:RecSave", ID_BROWSER_SAVERECORD, CommandGroup::CONTROLS );
+ implDescribeSupportedFeature( ".uno:Save", ID_BROWSER_SAVERECORD, CommandGroup::DOCUMENT );
+ implDescribeSupportedFeature( ".uno:RecSearch", SID_FM_SEARCH, CommandGroup::CONTROLS );
+ implDescribeSupportedFeature( ".uno:AutoFilter", SID_FM_AUTOFILTER, CommandGroup::CONTROLS );
+ implDescribeSupportedFeature( ".uno:Refresh", SID_FM_REFRESH, CommandGroup::CONTROLS );
+ implDescribeSupportedFeature( ".uno:OrderCrit", SID_FM_ORDERCRIT, CommandGroup::CONTROLS );
+ implDescribeSupportedFeature( ".uno:RemoveFilterSort", SID_FM_REMOVE_FILTER_SORT,CommandGroup::CONTROLS );
+ implDescribeSupportedFeature( ".uno:FormFiltered", SID_FM_FORM_FILTERED, CommandGroup::CONTROLS );
+ implDescribeSupportedFeature( ".uno:FilterCrit", SID_FM_FILTERCRIT, CommandGroup::CONTROLS );
+ implDescribeSupportedFeature( ".uno:Sortup", ID_BROWSER_SORTUP, CommandGroup::CONTROLS );
+ implDescribeSupportedFeature( ".uno:SortDown", ID_BROWSER_SORTDOWN, CommandGroup::CONTROLS );
+ implDescribeSupportedFeature( ".uno:FormSlots/deleteRecord", SID_FM_DELETEROWS, CommandGroup::EDIT );
+ implDescribeSupportedFeature( ".uno:FormSlots/insertRecord", ID_BROWSER_INSERT_ROW, CommandGroup::INSERT );
+}
+
+bool SbaXDataBrowserController::Construct(vcl::Window* pParent)
+{
+ // create/initialize the form and the grid model
+ m_xRowSet = CreateForm();
+ if (!m_xRowSet.is())
+ return false;
+
+ m_xColumnsSupplier.set(m_xRowSet,UNO_QUERY);
+ m_xLoadable.set(m_xRowSet,UNO_QUERY);
+
+ Reference< XPropertySet > xFormProperties( m_xRowSet, UNO_QUERY );
+ if ( !InitializeForm( xFormProperties ) )
+ return false;
+
+ m_xGridModel = CreateGridModel();
+ if (!m_xGridModel.is())
+ return false;
+
+ // set the formatter if available
+ initFormatter();
+
+ // we want to have a grid with a "flat" border
+ Reference< XPropertySet > xGridSet(m_xGridModel, UNO_QUERY);
+ if ( xGridSet.is() )
+ xGridSet->setPropertyValue(PROPERTY_BORDER, Any(sal_Int16(2)));
+
+
+ // marry them
+ Reference< css::container::XNameContainer > xNameCont(m_xRowSet, UNO_QUERY);
+ {
+ OUString sText(DBA_RES(STR_DATASOURCE_GRIDCONTROL_NAME));
+ xNameCont->insertByName(sText, Any(m_xGridModel));
+ }
+
+ // create the view
+ setView( VclPtr<UnoDataBrowserView>::Create( pParent, *this, getORB() ) );
+ if (!getBrowserView())
+ return false;
+
+ // late construction
+ bool bSuccess = false;
+ try
+ {
+ getBrowserView()->Construct(getControlModel());
+ bSuccess = true;
+ }
+ catch(SQLException&)
+ {
+ }
+ catch(Exception&)
+ {
+ SAL_WARN("dbaccess.ui","SbaXDataBrowserController::Construct : the construction of UnoDataBrowserView failed !");
+ }
+
+ if (!bSuccess)
+ {
+ // deleteView();
+ return false;
+ }
+
+ // now that we have a view we can create the clipboard listener
+ m_aSystemClipboard = TransferableDataHelper::CreateFromSystemClipboard( getView() );
+ m_aSystemClipboard.StartClipboardListening( );
+
+ m_pClipboardNotifier = new TransferableClipboardListener( LINK( this, SbaXDataBrowserController, OnClipboardChanged ) );
+ m_pClipboardNotifier->AddListener( getView() );
+
+ // this call create the toolbox
+ SbaXDataBrowserController_Base::Construct(pParent);
+
+ getBrowserView()->Show();
+
+ // set the callbacks for the grid control
+ SbaGridControl* pVclGrid = getBrowserView()->getVclControl();
+ OSL_ENSURE(pVclGrid, "SbaXDataBrowserController::Construct : have no VCL control !");
+ pVclGrid->SetMasterListener(this);
+
+ // add listeners...
+
+ // ... to the form model
+ Reference< XPropertySet > xFormSet(getRowSet(), UNO_QUERY);
+ if (xFormSet.is())
+ {
+ xFormSet->addPropertyChangeListener(PROPERTY_ISNEW, static_cast<XPropertyChangeListener*>(this));
+ xFormSet->addPropertyChangeListener(PROPERTY_ISMODIFIED, static_cast<XPropertyChangeListener*>(this));
+ xFormSet->addPropertyChangeListener(PROPERTY_ROWCOUNT, static_cast<XPropertyChangeListener*>(this));
+ xFormSet->addPropertyChangeListener(PROPERTY_ACTIVECOMMAND, static_cast<XPropertyChangeListener*>(this));
+ xFormSet->addPropertyChangeListener(PROPERTY_ORDER, static_cast<XPropertyChangeListener*>(this));
+ xFormSet->addPropertyChangeListener(PROPERTY_FILTER, static_cast<XPropertyChangeListener*>(this));
+ xFormSet->addPropertyChangeListener(PROPERTY_HAVING_CLAUSE, static_cast<XPropertyChangeListener*>(this));
+ xFormSet->addPropertyChangeListener(PROPERTY_APPLYFILTER, static_cast<XPropertyChangeListener*>(this));
+ }
+ Reference< css::sdb::XSQLErrorBroadcaster > xFormError(getRowSet(), UNO_QUERY);
+ if (xFormError.is())
+ xFormError->addSQLErrorListener(static_cast<css::sdb::XSQLErrorListener*>(this));
+
+ if (m_xLoadable.is())
+ m_xLoadable->addLoadListener(this);
+
+ Reference< css::form::XDatabaseParameterBroadcaster > xFormParameter(getRowSet(), UNO_QUERY);
+ if (xFormParameter.is())
+ xFormParameter->addParameterListener(static_cast<css::form::XDatabaseParameterListener*>(this));
+
+ addModelListeners(getControlModel());
+ addControlListeners(getBrowserView()->getGridControl());
+
+ // load the form
+ return LoadForm();
+}
+
+bool SbaXDataBrowserController::LoadForm()
+{
+ reloadForm( m_xLoadable );
+ return true;
+}
+
+void SbaXDataBrowserController::AddColumnListener(const Reference< XPropertySet > & /*xCol*/)
+{
+ // we're not interested in any column properties...
+}
+
+void SbaXDataBrowserController::RemoveColumnListener(const Reference< XPropertySet > & /*xCol*/)
+{
+}
+
+Reference< XRowSet > SbaXDataBrowserController::CreateForm()
+{
+ return Reference< XRowSet > (
+ getORB()->getServiceManager()->createInstanceWithContext("com.sun.star.form.component.Form", getORB()),
+ UNO_QUERY);
+}
+
+Reference< css::form::XFormComponent > SbaXDataBrowserController::CreateGridModel()
+{
+ return Reference< css::form::XFormComponent > (
+ getORB()->getServiceManager()->createInstanceWithContext("com.sun.star.form.component.GridControl", getORB()),
+ UNO_QUERY);
+}
+
+void SbaXDataBrowserController::addModelListeners(const Reference< css::awt::XControlModel > & _xGridControlModel)
+{
+ // ... all the grid columns
+ addColumnListeners(_xGridControlModel);
+
+ // (we are interested in all columns the grid has (and only in these) so we have to listen to the container, too)
+ Reference< css::container::XContainer > xColContainer(_xGridControlModel, UNO_QUERY);
+ if (xColContainer.is())
+ xColContainer->addContainerListener(static_cast<css::container::XContainerListener*>(this));
+
+ Reference< css::form::XReset > xReset(_xGridControlModel, UNO_QUERY);
+ if (xReset.is())
+ xReset->addResetListener(static_cast<css::form::XResetListener*>(this));
+}
+
+void SbaXDataBrowserController::removeModelListeners(const Reference< XControlModel > & _xGridControlModel)
+{
+ // every single column model
+ Reference< XIndexContainer > xColumns(_xGridControlModel, UNO_QUERY);
+ if (xColumns.is())
+ {
+ sal_Int32 nCount = xColumns->getCount();
+ for (sal_Int32 i=0; i < nCount; ++i)
+ {
+ Reference< XPropertySet > xCol(xColumns->getByIndex(i),UNO_QUERY);
+ RemoveColumnListener(xCol);
+ }
+ }
+
+ Reference< XContainer > xColContainer(_xGridControlModel, UNO_QUERY);
+ if (xColContainer.is())
+ xColContainer->removeContainerListener( this );
+
+ Reference< XReset > xReset(_xGridControlModel, UNO_QUERY);
+ if (xReset.is())
+ xReset->removeResetListener( this );
+}
+
+void SbaXDataBrowserController::addControlListeners(const Reference< css::awt::XControl > & _xGridControl)
+{
+ // to ge the 'modified' for the current cell
+ Reference< XModifyBroadcaster > xBroadcaster(getBrowserView()->getGridControl(), UNO_QUERY);
+ if (xBroadcaster.is())
+ xBroadcaster->addModifyListener(static_cast<XModifyListener*>(this));
+
+ // introduce ourself as dispatch provider for the grid
+ Reference< XDispatchProviderInterception > xInterception(getBrowserView()->getGridControl(), UNO_QUERY);
+ if (xInterception.is())
+ xInterception->registerDispatchProviderInterceptor(static_cast<XDispatchProviderInterceptor*>(this));
+
+ // add as focus listener to the control (needed for the form controller functionality)
+ Reference< XWindow > xWindow(_xGridControl, UNO_QUERY);
+ if (xWindow.is())
+ xWindow->addFocusListener(this);
+}
+
+void SbaXDataBrowserController::removeControlListeners(const Reference< css::awt::XControl > & _xGridControl)
+{
+ Reference< XModifyBroadcaster > xBroadcaster(_xGridControl, UNO_QUERY);
+ if (xBroadcaster.is())
+ xBroadcaster->removeModifyListener(static_cast<XModifyListener*>(this));
+
+ Reference< XDispatchProviderInterception > xInterception(_xGridControl, UNO_QUERY);
+ if (xInterception.is())
+ xInterception->releaseDispatchProviderInterceptor(static_cast<XDispatchProviderInterceptor*>(this));
+
+ Reference< XWindow > xWindow(_xGridControl, UNO_QUERY);
+ if (xWindow.is())
+ xWindow->removeFocusListener(this);
+}
+
+void SAL_CALL SbaXDataBrowserController::focusGained(const FocusEvent& /*e*/)
+{
+ // notify our activate listeners (registered on the form controller aggregate)
+ EventObject aEvt(*this);
+ m_xFormControllerImpl->m_aActivateListeners.notifyEach( &css::form::XFormControllerListener::formActivated, aEvt );
+}
+
+void SAL_CALL SbaXDataBrowserController::focusLost(const FocusEvent& e)
+{
+ // some general checks
+ if (!getBrowserView() || !getBrowserView()->getGridControl().is())
+ return;
+ Reference< XVclWindowPeer > xMyGridPeer(getBrowserView()->getGridControl()->getPeer(), UNO_QUERY);
+ if (!xMyGridPeer.is())
+ return;
+ Reference< XWindowPeer > xNextControlPeer(e.NextFocus, UNO_QUERY);
+ if (!xNextControlPeer.is())
+ return;
+
+ // don't do a notification if it remains in the family (i.e. a child of the grid control gets the focus)
+ if (xMyGridPeer->isChild(xNextControlPeer))
+ return;
+
+ if (xMyGridPeer == xNextControlPeer)
+ return;
+
+ // notify the listeners that the "form" we represent has been deactivated
+ EventObject aEvt(*this);
+ m_xFormControllerImpl->m_aActivateListeners.notifyEach( &css::form::XFormControllerListener::formDeactivated, aEvt );
+
+ // commit the changes of the grid control (as we're deactivated)
+ Reference< XBoundComponent > xCommitable(getBrowserView()->getGridControl(), UNO_QUERY);
+ if (xCommitable.is())
+ xCommitable->commit();
+ else
+ SAL_WARN("dbaccess.ui", "SbaXDataBrowserController::focusLost : why is my control not committable?");
+}
+
+void SbaXDataBrowserController::disposingFormModel(const css::lang::EventObject& Source)
+{
+ Reference< XPropertySet > xSourceSet(Source.Source, UNO_QUERY);
+ if (xSourceSet.is())
+ {
+ xSourceSet->removePropertyChangeListener(PROPERTY_ISNEW, static_cast<XPropertyChangeListener*>(this));
+ xSourceSet->removePropertyChangeListener(PROPERTY_ISMODIFIED, static_cast<XPropertyChangeListener*>(this));
+ xSourceSet->removePropertyChangeListener(PROPERTY_ROWCOUNT, static_cast<XPropertyChangeListener*>(this));
+ xSourceSet->removePropertyChangeListener(PROPERTY_ACTIVECOMMAND, static_cast<XPropertyChangeListener*>(this));
+ xSourceSet->removePropertyChangeListener(PROPERTY_ORDER, static_cast<XPropertyChangeListener*>(this));
+ xSourceSet->removePropertyChangeListener(PROPERTY_FILTER, static_cast<XPropertyChangeListener*>(this));
+ xSourceSet->removePropertyChangeListener(PROPERTY_HAVING_CLAUSE, static_cast<XPropertyChangeListener*>(this));
+ xSourceSet->removePropertyChangeListener(PROPERTY_APPLYFILTER, static_cast<XPropertyChangeListener*>(this));
+ }
+
+ Reference< css::sdb::XSQLErrorBroadcaster > xFormError(Source.Source, UNO_QUERY);
+ if (xFormError.is())
+ xFormError->removeSQLErrorListener(static_cast<css::sdb::XSQLErrorListener*>(this));
+
+ if (m_xLoadable.is())
+ m_xLoadable->removeLoadListener(this);
+
+ Reference< css::form::XDatabaseParameterBroadcaster > xFormParameter(Source.Source, UNO_QUERY);
+ if (xFormParameter.is())
+ xFormParameter->removeParameterListener(static_cast<css::form::XDatabaseParameterListener*>(this));
+}
+
+void SbaXDataBrowserController::disposingColumnModel(const css::lang::EventObject& Source)
+{
+ RemoveColumnListener(Reference< XPropertySet > (Source.Source, UNO_QUERY));
+}
+
+void SbaXDataBrowserController::disposing(const EventObject& Source)
+{
+ // if it's a component other than our aggregate, forward it to the aggregate
+ if ( uno::Reference<XInterface>(static_cast<cppu::OWeakObject*>(m_xFormControllerImpl.get()), UNO_QUERY) != Source.Source )
+ {
+ Reference< XEventListener > xAggListener;
+ m_xFormControllerImpl->queryAggregation( cppu::UnoType<decltype(xAggListener)>::get() ) >>= xAggListener;
+ if ( xAggListener.is( ))
+ xAggListener->disposing( Source );
+ }
+
+ // is it the grid control ?
+ if (getBrowserView())
+ {
+ Reference< css::awt::XControl > xSourceControl(Source.Source, UNO_QUERY);
+ if (xSourceControl == getBrowserView()->getGridControl())
+ removeControlListeners(getBrowserView()->getGridControl());
+ }
+
+ // its model (the container of the columns) ?
+ if (getControlModel() == Source.Source)
+ removeModelListeners(getControlModel());
+
+ // the form's model ?
+ if (getRowSet() == Source.Source)
+ disposingFormModel(Source);
+
+ // from a single column model ?
+ Reference< XPropertySet > xSourceSet(Source.Source, UNO_QUERY);
+ if (xSourceSet.is())
+ {
+ Reference< XPropertySetInfo > xInfo = xSourceSet->getPropertySetInfo();
+ // we assume that columns have a Width property and all other sets we are listening to don't have
+ if (xInfo->hasPropertyByName(PROPERTY_WIDTH))
+ disposingColumnModel(Source);
+ }
+ SbaXDataBrowserController_Base::OGenericUnoController::disposing( Source );
+}
+
+void SAL_CALL SbaXDataBrowserController::setIdentifier( const OUString& Identifier )
+{
+ ::osl::MutexGuard aGuard( getMutex() );
+ m_sModuleIdentifier = Identifier;
+}
+
+OUString SAL_CALL SbaXDataBrowserController::getIdentifier( )
+{
+ ::osl::MutexGuard aGuard( getMutex() );
+ return m_sModuleIdentifier;
+}
+
+void SbaXDataBrowserController::propertyChange(const PropertyChangeEvent& evt)
+{
+ Reference< XPropertySet > xSource(evt.Source, UNO_QUERY);
+ if (!xSource.is())
+ return;
+
+ SolarMutexGuard aGuard;
+ // the IsModified changed to sal_False ?
+ if ( evt.PropertyName == PROPERTY_ISMODIFIED
+ && !::comphelper::getBOOL(evt.NewValue)
+ )
+ { // -> the current field isn't modified anymore, too
+ setCurrentModified( false );
+ }
+
+ // switching to a new record ?
+ if ( evt.PropertyName == PROPERTY_ISNEW
+ && ::comphelper::getBOOL(evt.NewValue)
+ )
+ {
+ if (::comphelper::getINT32(xSource->getPropertyValue(PROPERTY_ROWCOUNT)) == 0)
+ // if we're switching to a new record and didn't have any records before we need to invalidate
+ // all slots (as the cursor was invalid before the mode change and so the slots were disabled)
+ InvalidateAll();
+ }
+
+ if (evt.PropertyName == PROPERTY_FILTER)
+ {
+ InvalidateFeature(ID_BROWSER_REMOVEFILTER);
+ }
+ else if (evt.PropertyName == PROPERTY_HAVING_CLAUSE)
+ {
+ InvalidateFeature(ID_BROWSER_REMOVEFILTER);
+ }
+ else if (evt.PropertyName == PROPERTY_ORDER)
+ {
+ InvalidateFeature(ID_BROWSER_REMOVEFILTER);
+ }
+
+ // a new record count ? -> may be our search availability has changed
+ if (evt.PropertyName == PROPERTY_ROWCOUNT)
+ {
+ sal_Int32 nNewValue = 0, nOldValue = 0;
+ evt.NewValue >>= nNewValue;
+ evt.OldValue >>= nOldValue;
+ if((nOldValue == 0 && nNewValue != 0) || (nOldValue != 0 && nNewValue == 0))
+ InvalidateAll();
+ }
+}
+
+void SbaXDataBrowserController::modified(const css::lang::EventObject& /*aEvent*/)
+{
+ setCurrentModified( true );
+}
+
+void SbaXDataBrowserController::elementInserted(const css::container::ContainerEvent& evt)
+{
+ OSL_ENSURE(Reference< XInterface >(evt.Source, UNO_QUERY).get() == Reference< XInterface >(getControlModel(), UNO_QUERY).get(),
+ "SbaXDataBrowserController::elementInserted: where did this come from (not from the grid model)?!");
+ Reference< XPropertySet > xNewColumn(evt.Element,UNO_QUERY);
+ if ( xNewColumn.is() )
+ AddColumnListener(xNewColumn);
+}
+
+void SbaXDataBrowserController::elementRemoved(const css::container::ContainerEvent& evt)
+{
+ OSL_ENSURE(Reference< XInterface >(evt.Source, UNO_QUERY).get() == Reference< XInterface >(getControlModel(), UNO_QUERY).get(),
+ "SbaXDataBrowserController::elementRemoved: where did this come from (not from the grid model)?!");
+ Reference< XPropertySet > xOldColumn(evt.Element,UNO_QUERY);
+ if ( xOldColumn.is() )
+ RemoveColumnListener(xOldColumn);
+}
+
+void SbaXDataBrowserController::elementReplaced(const css::container::ContainerEvent& evt)
+{
+ OSL_ENSURE(Reference< XInterface >(evt.Source, UNO_QUERY).get() == Reference< XInterface >(getControlModel(), UNO_QUERY).get(),
+ "SbaXDataBrowserController::elementReplaced: where did this come from (not from the grid model)?!");
+ Reference< XPropertySet > xOldColumn(evt.ReplacedElement,UNO_QUERY);
+ if ( xOldColumn.is() )
+ RemoveColumnListener(xOldColumn);
+
+ Reference< XPropertySet > xNewColumn(evt.Element,UNO_QUERY);
+ if ( xNewColumn.is() )
+ AddColumnListener(xNewColumn);
+}
+
+sal_Bool SbaXDataBrowserController::suspend(sal_Bool /*bSuspend*/)
+{
+ m_aAsyncGetCellFocus.CancelCall();
+ m_aAsyncDisplayError.CancelCall();
+ m_aAsyncInvalidateAll.CancelCall();
+
+ bool bSuccess = SaveModified();
+ return bSuccess;
+}
+
+void SbaXDataBrowserController::disposing()
+{
+ // the base class
+ SbaXDataBrowserController_Base::OGenericUnoController::disposing();
+
+ // the data source
+ Reference< XPropertySet > xFormSet(getRowSet(), UNO_QUERY);
+ if (xFormSet.is())
+ {
+ xFormSet->removePropertyChangeListener(PROPERTY_ISNEW, static_cast<XPropertyChangeListener*>(this));
+ xFormSet->removePropertyChangeListener(PROPERTY_ISMODIFIED, static_cast<XPropertyChangeListener*>(this));
+ xFormSet->removePropertyChangeListener(PROPERTY_ROWCOUNT, static_cast<XPropertyChangeListener*>(this));
+ xFormSet->removePropertyChangeListener(PROPERTY_ACTIVECOMMAND, static_cast<XPropertyChangeListener*>(this));
+ xFormSet->removePropertyChangeListener(PROPERTY_ORDER, static_cast<XPropertyChangeListener*>(this));
+ xFormSet->removePropertyChangeListener(PROPERTY_FILTER, static_cast<XPropertyChangeListener*>(this));
+ xFormSet->removePropertyChangeListener(PROPERTY_HAVING_CLAUSE, static_cast<XPropertyChangeListener*>(this));
+ xFormSet->removePropertyChangeListener(PROPERTY_APPLYFILTER, static_cast<XPropertyChangeListener*>(this));
+ }
+
+ Reference< css::sdb::XSQLErrorBroadcaster > xFormError(getRowSet(), UNO_QUERY);
+ if (xFormError.is())
+ xFormError->removeSQLErrorListener(static_cast<css::sdb::XSQLErrorListener*>(this));
+
+ if (m_xLoadable.is())
+ m_xLoadable->removeLoadListener(this);
+
+ Reference< css::form::XDatabaseParameterBroadcaster > xFormParameter(getRowSet(), UNO_QUERY);
+ if (xFormParameter.is())
+ xFormParameter->removeParameterListener(static_cast<css::form::XDatabaseParameterListener*>(this));
+
+ removeModelListeners(getControlModel());
+
+ if ( getView() && m_pClipboardNotifier.is() )
+ {
+ m_pClipboardNotifier->ClearCallbackLink();
+ m_pClipboardNotifier->RemoveListener( getView() );
+ m_pClipboardNotifier.clear();
+ }
+
+ if (getBrowserView())
+ {
+ removeControlListeners(getBrowserView()->getGridControl());
+ // don't delete explicitly, this is done by the owner (and user) of this controller (me hopes ...)
+ clearView();
+ }
+
+ if(m_aInvalidateClipboard.IsActive())
+ m_aInvalidateClipboard.Stop();
+
+ // dispose the row set
+ try
+ {
+ ::comphelper::disposeComponent(m_xRowSet);
+
+ m_xRowSet = nullptr;
+ m_xColumnsSupplier = nullptr;
+ m_xLoadable = nullptr;
+ }
+ catch(Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ m_xParser.clear();
+ // don't dispose, just reset - it's owned by the RowSet
+}
+
+void SbaXDataBrowserController::frameAction(const css::frame::FrameActionEvent& aEvent)
+{
+ ::osl::MutexGuard aGuard( getMutex() );
+
+ SbaXDataBrowserController_Base::frameAction( aEvent );
+
+ if ( aEvent.Source != getFrame() )
+ return;
+
+ switch ( aEvent.Action )
+ {
+ case FrameAction_FRAME_ACTIVATED:
+ case FrameAction_FRAME_UI_ACTIVATED:
+ // ensure that the active cell (if any) has the focus
+ m_aAsyncGetCellFocus.Call();
+ // start the clipboard timer
+ if (getBrowserView() && getBrowserView()->getVclControl() && !m_aInvalidateClipboard.IsActive())
+ {
+ m_aInvalidateClipboard.Start();
+ OnInvalidateClipboard( nullptr );
+ }
+ break;
+ case FrameAction_FRAME_DEACTIVATING:
+ case FrameAction_FRAME_UI_DEACTIVATING:
+ // stop the clipboard invalidator
+ if (getBrowserView() && getBrowserView()->getVclControl() && m_aInvalidateClipboard.IsActive())
+ {
+ m_aInvalidateClipboard.Stop();
+ OnInvalidateClipboard( nullptr );
+ }
+ // remove the "get cell focus"-event
+ m_aAsyncGetCellFocus.CancelCall();
+ break;
+ default:
+ break;
+ }
+}
+
+IMPL_LINK_NOARG( SbaXDataBrowserController, OnAsyncDisplayError, void*, void )
+{
+ if ( m_aCurrentError.isValid() )
+ {
+ OSQLMessageBox aDlg(getFrameWeld(), m_aCurrentError);
+ aDlg.run();
+ }
+}
+
+void SbaXDataBrowserController::errorOccured(const css::sdb::SQLErrorEvent& aEvent)
+{
+ ::osl::MutexGuard aGuard( getMutex() );
+
+ SQLExceptionInfo aInfo( aEvent.Reason );
+ if ( !aInfo.isValid() )
+ return;
+
+ if ( m_nFormActionNestingLevel )
+ {
+ OSL_ENSURE( !m_aCurrentError.isValid(), "SbaXDataBrowserController::errorOccurred: can handle one error per transaction only!" );
+ m_aCurrentError = aInfo;
+ }
+ else
+ {
+ m_aCurrentError = aInfo;
+ m_aAsyncDisplayError.Call();
+ }
+}
+
+sal_Bool SbaXDataBrowserController::approveParameter(const css::form::DatabaseParameterEvent& aEvent)
+{
+ if (aEvent.Source != getRowSet())
+ {
+ // not my data source -> allow anything
+ SAL_WARN("dbaccess.ui","SbaXDataBrowserController::approveParameter : invalid event source !");
+ return true;
+ }
+
+ Reference< css::container::XIndexAccess > xParameters = aEvent.Parameters;
+ SolarMutexGuard aSolarGuard;
+
+ // default handling: instantiate an interaction handler and let it handle the parameter request
+ try
+ {
+ // two continuations allowed: OK and Cancel
+ rtl::Reference<OParameterContinuation> pParamValues = new OParameterContinuation;
+ rtl::Reference<OInteractionAbort> pAbort = new OInteractionAbort;
+ // the request
+ ParametersRequest aRequest;
+ aRequest.Parameters = xParameters;
+ aRequest.Connection = getConnection(Reference< XRowSet >(aEvent.Source, UNO_QUERY));
+ rtl::Reference<OInteractionRequest> pParamRequest = new OInteractionRequest(Any(aRequest));
+ // some knittings
+ pParamRequest->addContinuation(pParamValues);
+ pParamRequest->addContinuation(pAbort);
+
+ // create the handler, let it handle the request
+ Reference< XInteractionHandler2 > xHandler(InteractionHandler::createWithParent(getORB(), getComponentWindow()));
+ xHandler->handle(pParamRequest);
+
+ if (!pParamValues->wasSelected())
+ { // canceled
+ setLoadingCancelled();
+ return false;
+ }
+
+ // transfer the values into the parameter supplier
+ Sequence< PropertyValue > aFinalValues = pParamValues->getValues();
+ if (aFinalValues.getLength() != aRequest.Parameters->getCount())
+ {
+ SAL_WARN("dbaccess.ui","SbaXDataBrowserController::approveParameter: the InteractionHandler returned nonsense!");
+ setLoadingCancelled();
+ return false;
+ }
+ const PropertyValue* pFinalValues = aFinalValues.getConstArray();
+ for (sal_Int32 i=0; i<aFinalValues.getLength(); ++i, ++pFinalValues)
+ {
+ Reference< XPropertySet > xParam(
+ aRequest.Parameters->getByIndex(i), css::uno::UNO_QUERY);
+ OSL_ENSURE(xParam.is(), "SbaXDataBrowserController::approveParameter: one of the parameters is no property set!");
+ if (xParam.is())
+ {
+#ifdef DBG_UTIL
+ OUString sName;
+ xParam->getPropertyValue(PROPERTY_NAME) >>= sName;
+ OSL_ENSURE(sName == pFinalValues->Name, "SbaXDataBrowserController::approveParameter: suspicious value names!");
+#endif
+ try { xParam->setPropertyValue(PROPERTY_VALUE, pFinalValues->Value); }
+ catch(Exception&)
+ {
+ SAL_WARN("dbaccess.ui", "SbaXDataBrowserController::approveParameter: setting one of the properties failed!");
+ }
+ }
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+
+ return true;
+}
+
+sal_Bool SbaXDataBrowserController::approveReset(const css::lang::EventObject& /*rEvent*/)
+{
+ return true;
+}
+
+void SbaXDataBrowserController::resetted(const css::lang::EventObject& rEvent)
+{
+ OSL_ENSURE(rEvent.Source == getControlModel(), "SbaXDataBrowserController::resetted : where did this come from ?");
+ setCurrentModified( false );
+}
+
+sal_Bool SbaXDataBrowserController::confirmDelete(const css::sdb::RowChangeEvent& /*aEvent*/)
+{
+ std::unique_ptr<weld::MessageDialog> xQuery(Application::CreateMessageDialog(getFrameWeld(),
+ VclMessageType::Question, VclButtonsType::YesNo,
+ DBA_RES(STR_QUERY_BRW_DELETE_ROWS)));
+ if (xQuery->run() != RET_YES)
+ return false;
+ return true;
+}
+
+FeatureState SbaXDataBrowserController::GetState(sal_uInt16 nId) const
+{
+ FeatureState aReturn;
+ // (disabled automatically)
+
+ try
+ {
+ // no chance without a view
+ if (!getBrowserView() || !getBrowserView()->getVclControl())
+ return aReturn;
+
+ switch (nId)
+ {
+ case ID_BROWSER_REMOVEFILTER:
+ if (!m_xParser.is())
+ {
+ aReturn.bEnabled = false;
+ return aReturn;
+ }
+ // any filter or sort order set ?
+ aReturn.bEnabled = m_xParser->getFilter().getLength() || m_xParser->getHavingClause().getLength() || m_xParser->getOrder().getLength();
+ return aReturn;
+ }
+ // no chance without valid models
+ if (isValid() && !isValidCursor())
+ return aReturn;
+
+ switch (nId)
+ {
+ case ID_BROWSER_SEARCH:
+ {
+ Reference< XPropertySet > xFormSet(getRowSet(), UNO_QUERY);
+ sal_Int32 nCount = ::comphelper::getINT32(xFormSet->getPropertyValue(PROPERTY_ROWCOUNT));
+ aReturn.bEnabled = nCount != 0;
+ }
+ break;
+ case ID_BROWSER_INSERT_ROW:
+ {
+ // check if it is available
+ bool bInsertPrivilege = ( m_nRowSetPrivileges & Privilege::INSERT) != 0;
+ bool bAllowInsertions = true;
+ try
+ {
+ Reference< XPropertySet > xRowSetProps( getRowSet(), UNO_QUERY_THROW );
+ OSL_VERIFY( xRowSetProps->getPropertyValue("AllowInserts") >>= bAllowInsertions );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ aReturn.bEnabled = bInsertPrivilege && bAllowInsertions;
+ }
+ break;
+ case SID_FM_DELETEROWS:
+ {
+ // check if it is available
+ bool bDeletePrivilege = ( m_nRowSetPrivileges & Privilege::INSERT) != 0;
+ bool bAllowDeletions = true;
+ sal_Int32 nRowCount = 0;
+ bool bInsertionRow = false;
+ try
+ {
+ Reference< XPropertySet > xRowSetProps( getRowSet(), UNO_QUERY_THROW );
+ OSL_VERIFY( xRowSetProps->getPropertyValue("AllowDeletes") >>= bAllowDeletions );
+ OSL_VERIFY( xRowSetProps->getPropertyValue( PROPERTY_ROWCOUNT ) >>= nRowCount );
+ OSL_VERIFY( xRowSetProps->getPropertyValue( PROPERTY_ISNEW ) >>= bInsertionRow );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ aReturn.bEnabled = bDeletePrivilege && bAllowDeletions && ( nRowCount != 0 ) && !bInsertionRow;
+ }
+ break;
+
+ case ID_BROWSER_COPY:
+ if ( getBrowserView()->getVclControl()->GetSelectRowCount() )
+ {
+ aReturn.bEnabled = m_aCurrentFrame.isActive();
+ break;
+ }
+ [[fallthrough]];
+ case ID_BROWSER_PASTE:
+ case ID_BROWSER_CUT:
+ {
+ CellControllerRef xCurrentController = getBrowserView()->getVclControl()->Controller();
+ if (const EditCellController* pController = dynamic_cast<const EditCellController*>(xCurrentController.get()))
+ {
+ const IEditImplementation* pEditImplementation = pController->GetEditImplementation();
+ bool bHasLen = pEditImplementation->GetSelection().Len() != 0;
+ bool bIsReadOnly = pEditImplementation->IsReadOnly();
+ switch (nId)
+ {
+ case ID_BROWSER_CUT: aReturn.bEnabled = m_aCurrentFrame.isActive() && bHasLen && !bIsReadOnly; break;
+ case SID_COPY : aReturn.bEnabled = m_aCurrentFrame.isActive() && bHasLen; break;
+ case ID_BROWSER_PASTE:
+ aReturn.bEnabled = m_aCurrentFrame.isActive() && !bIsReadOnly;
+ if(aReturn.bEnabled)
+ {
+ aReturn.bEnabled = IsFormatSupported( m_aSystemClipboard.GetDataFlavorExVector(), SotClipboardFormatId::STRING );
+ }
+ break;
+ }
+ }
+ }
+ break;
+
+ case ID_BROWSER_SORTUP:
+ case ID_BROWSER_SORTDOWN:
+ case ID_BROWSER_AUTOFILTER:
+ {
+ // a native statement can't be filtered or sorted
+ const Reference< XPropertySet > xFormSet(getRowSet(), UNO_QUERY);
+ if ( !::comphelper::getBOOL(xFormSet->getPropertyValue(PROPERTY_ESCAPE_PROCESSING)) || !m_xParser.is() )
+ break;
+
+ Reference< XPropertySet > xCurrentField = getBoundField();
+ if (!xCurrentField.is())
+ break;
+
+ aReturn.bEnabled = ::comphelper::getBOOL(xCurrentField->getPropertyValue(PROPERTY_ISSEARCHABLE));
+ const Reference< XRowSet > xRow = getRowSet();
+ aReturn.bEnabled = aReturn.bEnabled
+ && xRow.is()
+ && !xRow->isBeforeFirst()
+ && !xRow->isAfterLast()
+ && !xRow->rowDeleted()
+ && ( ::comphelper::getINT32( xFormSet->getPropertyValue( PROPERTY_ROWCOUNT ) ) != 0 );
+ }
+ break;
+
+ case ID_BROWSER_FILTERCRIT:
+ if ( m_bCannotSelectUnfiltered && m_xParser.is() )
+ {
+ aReturn.bEnabled = true;
+ break;
+ }
+ [[fallthrough]];
+ case ID_BROWSER_ORDERCRIT:
+ {
+ const Reference< XPropertySet > xFormSet(getRowSet(), UNO_QUERY);
+ if ( !::comphelper::getBOOL(xFormSet->getPropertyValue(PROPERTY_ESCAPE_PROCESSING)) || !m_xParser.is() )
+ break;
+
+ aReturn.bEnabled = getRowSet().is()
+ && ( ::comphelper::getINT32( xFormSet->getPropertyValue( PROPERTY_ROWCOUNT ) ) != 0 );
+ }
+ break;
+
+ case ID_BROWSER_REFRESH:
+ aReturn.bEnabled = true;
+ break;
+
+ case ID_BROWSER_REDO:
+ aReturn.bEnabled = false; // simply forget it ;). no redo possible.
+ break;
+
+ case ID_BROWSER_UNDORECORD:
+ case ID_BROWSER_SAVERECORD:
+ {
+ if (!m_bCurrentlyModified)
+ {
+ Reference< XPropertySet > xFormSet(getRowSet(), UNO_QUERY);
+ if (xFormSet.is())
+ aReturn.bEnabled = ::comphelper::getBOOL(xFormSet->getPropertyValue(PROPERTY_ISMODIFIED));
+ }
+ else
+ aReturn.bEnabled = true;
+
+ aReturn.sTitle = (ID_BROWSER_UNDORECORD == nId) ? m_sStateUndoRecord : m_sStateSaveRecord;
+ }
+ break;
+ case ID_BROWSER_EDITDOC:
+ {
+ // check if it is available
+ Reference< XPropertySet > xDataSourceSet(getRowSet(), UNO_QUERY);
+ if (!xDataSourceSet.is())
+ break; // no datasource -> no edit mode
+
+ sal_Int32 nDataSourcePrivileges = ::comphelper::getINT32(xDataSourceSet->getPropertyValue(PROPERTY_PRIVILEGES));
+ bool bInsertAllowedAndPossible = ((nDataSourcePrivileges & css::sdbcx::Privilege::INSERT) != 0) && ::comphelper::getBOOL(xDataSourceSet->getPropertyValue("AllowInserts"));
+ bool bUpdateAllowedAndPossible = ((nDataSourcePrivileges & css::sdbcx::Privilege::UPDATE) != 0) && ::comphelper::getBOOL(xDataSourceSet->getPropertyValue("AllowUpdates"));
+ bool bDeleteAllowedAndPossible = ((nDataSourcePrivileges & css::sdbcx::Privilege::DELETE) != 0) && ::comphelper::getBOOL(xDataSourceSet->getPropertyValue("AllowDeletes"));
+ if (!bInsertAllowedAndPossible && !bUpdateAllowedAndPossible && !bDeleteAllowedAndPossible)
+ break; // no insert/update/delete -> no edit mode
+
+ if (!isValidCursor() || !isLoaded())
+ break; // no cursor -> no edit mode
+
+ aReturn.bEnabled = true;
+
+ DbGridControlOptions nGridMode = getBrowserView()->getVclControl()->GetOptions();
+ aReturn.bChecked = nGridMode > DbGridControlOptions::Readonly;
+ }
+ break;
+ case ID_BROWSER_FILTERED:
+ {
+ aReturn.bEnabled = false;
+ Reference< XPropertySet > xActiveSet(getRowSet(), UNO_QUERY);
+ OUString aFilter = ::comphelper::getString(xActiveSet->getPropertyValue(PROPERTY_FILTER));
+ OUString aHaving = ::comphelper::getString(xActiveSet->getPropertyValue(PROPERTY_HAVING_CLAUSE));
+ if ( !(aFilter.isEmpty() && aHaving.isEmpty()) )
+ {
+ xActiveSet->getPropertyValue( PROPERTY_APPLYFILTER ) >>= aReturn.bChecked;
+ aReturn.bEnabled = true;
+ }
+ else
+ {
+ aReturn.bChecked = false;
+ aReturn.bEnabled = false;
+ }
+ }
+ break;
+ default:
+ return SbaXDataBrowserController_Base::GetState(nId);
+ }
+ }
+ catch(const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+
+ return aReturn;
+}
+
+void SbaXDataBrowserController::applyParserOrder(const OUString& _rOldOrder,const Reference< XSingleSelectQueryComposer >& _xParser)
+{
+ Reference< XPropertySet > xFormSet(getRowSet(), UNO_QUERY);
+ if (!m_xLoadable.is())
+ {
+ SAL_WARN("dbaccess.ui","SbaXDataBrowserController::applyParserOrder: invalid row set!");
+ return;
+ }
+
+ sal_uInt16 nPos = getCurrentColumnPosition();
+ bool bSuccess = false;
+ try
+ {
+ xFormSet->setPropertyValue(PROPERTY_ORDER, Any(_xParser->getOrder()));
+ bSuccess = reloadForm(m_xLoadable);
+ }
+ catch(Exception&)
+ {
+ }
+
+ if (!bSuccess)
+ {
+ xFormSet->setPropertyValue(PROPERTY_ORDER, Any(_rOldOrder));
+
+ try
+ {
+ if (loadingCancelled() || !reloadForm(m_xLoadable))
+ criticalFail();
+ }
+ catch(Exception&)
+ {
+ criticalFail();
+ }
+ InvalidateAll();
+ }
+ InvalidateFeature(ID_BROWSER_REMOVEFILTER);
+
+ setCurrentColumnPosition(nPos);
+}
+
+void SbaXDataBrowserController::applyParserFilter(const OUString& _rOldFilter, bool _bOldFilterApplied,const ::OUString& _sOldHaving,const Reference< XSingleSelectQueryComposer >& _xParser)
+{
+ Reference< XPropertySet > xFormSet(getRowSet(), UNO_QUERY);
+ if (!m_xLoadable.is())
+ {
+ SAL_WARN("dbaccess.ui", "SbaXDataBrowserController::applyParserFilter: invalid row set!");
+ return;
+ }
+
+ sal_uInt16 nPos = getCurrentColumnPosition();
+
+ bool bSuccess = false;
+ try
+ {
+ FormErrorHelper aError(this);
+ xFormSet->setPropertyValue(PROPERTY_FILTER, Any(_xParser->getFilter()));
+ xFormSet->setPropertyValue(PROPERTY_HAVING_CLAUSE, Any(_xParser->getHavingClause()));
+ xFormSet->setPropertyValue(PROPERTY_APPLYFILTER, css::uno::Any(true));
+
+ bSuccess = reloadForm(m_xLoadable);
+ }
+ catch(Exception&)
+ {
+ }
+
+ if (!bSuccess)
+ {
+ xFormSet->setPropertyValue(PROPERTY_FILTER, Any(_rOldFilter));
+ xFormSet->setPropertyValue(PROPERTY_HAVING_CLAUSE, Any(_sOldHaving));
+ xFormSet->setPropertyValue(PROPERTY_APPLYFILTER, css::uno::Any(_bOldFilterApplied));
+
+ try
+ {
+ if (loadingCancelled() || !reloadForm(m_xLoadable))
+ criticalFail();
+ }
+ catch(Exception&)
+ {
+ criticalFail();
+ }
+ InvalidateAll();
+ }
+ InvalidateFeature(ID_BROWSER_REMOVEFILTER);
+
+ setCurrentColumnPosition(nPos);
+}
+
+Reference< XSingleSelectQueryComposer > SbaXDataBrowserController::createParser_nothrow()
+{
+ Reference< XSingleSelectQueryComposer > xComposer;
+ try
+ {
+ const Reference< XPropertySet > xRowSetProps( getRowSet(), UNO_QUERY_THROW );
+ const Reference< XMultiServiceFactory > xFactory(
+ xRowSetProps->getPropertyValue( PROPERTY_ACTIVE_CONNECTION ), UNO_QUERY_THROW );
+ xComposer.set( xFactory->createInstance( SERVICE_NAME_SINGLESELECTQUERYCOMPOSER ), UNO_QUERY_THROW );
+
+ OUString sActiveCommand;
+ OSL_VERIFY( xRowSetProps->getPropertyValue( PROPERTY_ACTIVECOMMAND ) >>= sActiveCommand );
+ if ( !sActiveCommand.isEmpty() )
+ {
+ xComposer->setElementaryQuery( sActiveCommand );
+ }
+ else
+ {
+ OUString sCommand;
+ OSL_VERIFY( xRowSetProps->getPropertyValue( PROPERTY_COMMAND ) >>= sCommand );
+ sal_Int32 nCommandType = CommandType::COMMAND;
+ OSL_VERIFY( xRowSetProps->getPropertyValue( PROPERTY_COMMAND_TYPE ) >>= nCommandType );
+ xComposer->setCommand( sCommand, nCommandType );
+ }
+
+ OUString sFilter;
+ OSL_VERIFY( xRowSetProps->getPropertyValue( PROPERTY_FILTER ) >>= sFilter );
+ xComposer->setFilter( sFilter );
+
+ OUString sHavingClause;
+ OSL_VERIFY( xRowSetProps->getPropertyValue( PROPERTY_HAVING_CLAUSE ) >>= sHavingClause );
+ xComposer->setHavingClause( sHavingClause );
+
+ OUString sOrder;
+ OSL_VERIFY( xRowSetProps->getPropertyValue( PROPERTY_ORDER ) >>= sOrder );
+ xComposer->setOrder( sOrder );
+ }
+ catch ( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ return xComposer;
+}
+
+void SbaXDataBrowserController::ExecuteFilterSortCrit(bool bFilter)
+{
+ if (!SaveModified())
+ return;
+
+ Reference< XPropertySet > xFormSet(getRowSet(), UNO_QUERY);
+
+ const OUString sOldVal = bFilter ? m_xParser->getFilter() : m_xParser->getOrder();
+ const OUString sOldHaving = m_xParser->getHavingClause();
+ Reference< XSingleSelectQueryComposer > xParser = createParser_nothrow();
+ try
+ {
+ Reference< XConnection> xCon(xFormSet->getPropertyValue(PROPERTY_ACTIVE_CONNECTION),UNO_QUERY);
+ if(bFilter)
+ {
+ DlgFilterCrit aDlg(getFrameWeld(), getORB(), xCon, xParser, m_xColumnsSupplier->getColumns());
+ if (!aDlg.run())
+ return; // if so we don't need to update the grid
+ aDlg.BuildWherePart();
+ }
+ else
+ {
+ DlgOrderCrit aDlg(getFrameWeld(), xCon, xParser, m_xColumnsSupplier->getColumns());
+ if (!aDlg.run())
+ {
+ return; // if so we don't need to actualize the grid
+ }
+ aDlg.BuildOrderPart();
+ }
+ }
+ catch(const SQLException& )
+ {
+ SQLExceptionInfo aError( ::cppu::getCaughtException() );
+ showError( aError );
+ return;
+ }
+ catch(Exception&)
+ {
+ return;
+ }
+
+ OUString sNewVal = bFilter ? xParser->getFilter() : xParser->getOrder();
+ bool bOldFilterApplied(false);
+ if (bFilter)
+ {
+ try { bOldFilterApplied = ::comphelper::getBOOL(xFormSet->getPropertyValue(PROPERTY_APPLYFILTER)); } catch(Exception&) { } ;
+ }
+
+ OUString sNewHaving = xParser->getHavingClause();
+ if ( sOldVal == sNewVal && (!bFilter || sOldHaving == sNewHaving) )
+ // nothing to be done
+ return;
+
+ if (bFilter)
+ applyParserFilter(sOldVal, bOldFilterApplied,sOldHaving,xParser);
+ else
+ applyParserOrder(sOldVal,xParser);
+
+ ::comphelper::disposeComponent(xParser);
+}
+
+void SbaXDataBrowserController::ExecuteSearch()
+{
+ // calculate the control source of the active field
+ Reference< css::form::XGrid > xGrid(getBrowserView()->getGridControl(), UNO_QUERY);
+ OSL_ENSURE(xGrid.is(), "SbaXDataBrowserController::ExecuteSearch : the control should have a css::form::XGrid interface !");
+
+ Reference< css::form::XGridPeer > xGridPeer(getBrowserView()->getGridControl()->getPeer(), UNO_QUERY);
+ Reference< css::container::XIndexContainer > xColumns = xGridPeer->getColumns();
+ OSL_ENSURE(xGridPeer.is() && xColumns.is(), "SbaXDataBrowserController::ExecuteSearch : invalid peer !");
+
+ sal_Int16 nViewCol = xGrid->getCurrentColumnPosition();
+ sal_Int16 nModelCol = getBrowserView()->View2ModelPos(nViewCol);
+
+ Reference< XPropertySet > xCurrentCol(xColumns->getByIndex(nModelCol),UNO_QUERY);
+ OUString sActiveField = ::comphelper::getString(xCurrentCol->getPropertyValue(PROPERTY_CONTROLSOURCE));
+
+ // the text within the current cell
+ OUString sInitialText;
+ Reference< css::container::XIndexAccess > xColControls(xGridPeer, UNO_QUERY);
+ Reference< XInterface > xCurControl(xColControls->getByIndex(nViewCol),UNO_QUERY);
+ OUString aInitialText;
+ if (IsSearchableControl(xCurControl, &aInitialText))
+ sInitialText = aInitialText;
+
+ // prohibit the synchronization of the grid's display with the cursor's position
+ Reference< XPropertySet > xModelSet(getControlModel(), UNO_QUERY);
+ OSL_ENSURE(xModelSet.is(), "SbaXDataBrowserController::ExecuteSearch : no model set ?!");
+ xModelSet->setPropertyValue("DisplayIsSynchron", css::uno::Any(false));
+ xModelSet->setPropertyValue("AlwaysShowCursor", css::uno::Any(true));
+ xModelSet->setPropertyValue("CursorColor", Any(COL_LIGHTRED));
+
+ SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
+ VclPtr<AbstractFmSearchDialog> pDialog;
+ std::vector< OUString > aContextNames;
+ aContextNames.emplace_back("Standard" );
+ pDialog = pFact->CreateFmSearchDialog(getFrameWeld(), sInitialText, aContextNames, 0, LINK(this, SbaXDataBrowserController, OnSearchContextRequest));
+ pDialog->SetActiveField( sActiveField );
+ pDialog->SetFoundHandler( LINK( this, SbaXDataBrowserController, OnFoundData ) );
+ pDialog->SetCanceledNotFoundHdl( LINK( this, SbaXDataBrowserController, OnCanceledNotFound ) );
+ pDialog->Execute();
+ pDialog.disposeAndClear();
+
+ // restore the grid's normal operating state
+ xModelSet->setPropertyValue("DisplayIsSynchron", css::uno::Any(true));
+ xModelSet->setPropertyValue("AlwaysShowCursor", css::uno::Any(false));
+ xModelSet->setPropertyValue("CursorColor", Any());
+}
+
+void SbaXDataBrowserController::Execute(sal_uInt16 nId, const Sequence< PropertyValue >& _rArgs)
+{
+ bool bSortUp = true;
+
+ switch (nId)
+ {
+ default:
+ SbaXDataBrowserController_Base::Execute( nId, _rArgs );
+ return;
+
+ case ID_BROWSER_INSERT_ROW:
+ try
+ {
+ if (SaveModified())
+ {
+ getRowSet()->afterLast();
+ // check if it is available
+ Reference< XResultSetUpdate > xUpdateCursor(getRowSet(), UNO_QUERY_THROW);
+ xUpdateCursor->moveToInsertRow();
+ }
+ }
+ catch(Exception&)
+ {
+ TOOLS_WARN_EXCEPTION("dbaccess.ui", "" );
+ }
+ break;
+ case SID_FM_DELETEROWS:
+
+ if (SaveModified())
+ {
+ SbaGridControl* pVclGrid = getBrowserView()->getVclControl();
+ if ( pVclGrid )
+ {
+ if( !pVclGrid->GetSelectRowCount() )
+ {
+ pVclGrid->DeactivateCell();
+ pVclGrid->SelectRow(pVclGrid->GetCurRow());
+ }
+ pVclGrid->DeleteSelectedRows();
+ }
+ }
+ break;
+
+ case ID_BROWSER_FILTERED:
+ if (SaveModified())
+ {
+ Reference< XPropertySet > xActiveSet(getRowSet(), UNO_QUERY);
+ bool bApplied = ::comphelper::getBOOL(xActiveSet->getPropertyValue(PROPERTY_APPLYFILTER));
+ xActiveSet->setPropertyValue(PROPERTY_APPLYFILTER, css::uno::Any(!bApplied));
+ reloadForm(m_xLoadable);
+ }
+ InvalidateFeature(ID_BROWSER_FILTERED);
+ break;
+ case ID_BROWSER_EDITDOC:
+ {
+ DbGridControlOptions nGridMode = getBrowserView()->getVclControl()->GetOptions();
+ if (nGridMode == DbGridControlOptions::Readonly)
+ getBrowserView()->getVclControl()->SetOptions(DbGridControlOptions::Update | DbGridControlOptions::Insert | DbGridControlOptions::Delete);
+ // the options not supported by the data source will be removed automatically
+ else
+ {
+ if ( !SaveModified( ) )
+ // give the user a chance to save the current record (if necessary)
+ break;
+
+ // maybe the user wanted to reject the modified record ?
+ if (GetState(ID_BROWSER_UNDORECORD).bEnabled)
+ Execute(ID_BROWSER_UNDORECORD,Sequence<PropertyValue>());
+
+ getBrowserView()->getVclControl()->SetOptions(DbGridControlOptions::Readonly);
+ }
+ InvalidateFeature(ID_BROWSER_EDITDOC);
+ }
+ break;
+
+ case ID_BROWSER_SEARCH:
+ if ( SaveModified( ) )
+ ExecuteSearch();
+ break;
+
+ case ID_BROWSER_COPY:
+ if ( getBrowserView()->getVclControl()->GetSelectRowCount() > 0 )
+ {
+ getBrowserView()->getVclControl()->CopySelectedRowsToClipboard();
+ break;
+ }
+ [[fallthrough]];
+ case ID_BROWSER_CUT:
+ case ID_BROWSER_PASTE:
+ {
+ CellControllerRef xCurrentController = getBrowserView()->getVclControl()->Controller();
+ if (EditCellController* pController = dynamic_cast<EditCellController*>(xCurrentController.get()))
+ {
+ IEditImplementation* pEditImplementation = pController->GetEditImplementation();
+ switch (nId)
+ {
+ case ID_BROWSER_CUT:
+ pEditImplementation->Cut();
+ break;
+ case SID_COPY:
+ pEditImplementation->Copy();
+ break;
+ case ID_BROWSER_PASTE:
+ pEditImplementation->Paste();
+ break;
+ }
+ if (ID_BROWSER_CUT == nId || ID_BROWSER_PASTE == nId)
+ pController->Modify();
+ }
+ }
+ break;
+
+ case ID_BROWSER_SORTDOWN:
+ bSortUp = false;
+ [[fallthrough]];
+ case ID_BROWSER_SORTUP:
+ {
+ if (!SaveModified())
+ break;
+
+ if (!isValidCursor())
+ break;
+
+ // only one sort order
+ Reference< XPropertySet > xField = getBoundField();
+ if (!xField.is())
+ break;
+
+ Reference< XSingleSelectQueryComposer > xParser = createParser_nothrow();
+ const OUString sOldSort = xParser->getOrder();
+ bool bParserSuccess = false;
+ try
+ {
+ bParserSuccess = false;
+ xParser->setOrder(OUString());
+ xParser->appendOrderByColumn(xField, bSortUp);
+ bParserSuccess = true;
+ }
+ catch(SQLException& e)
+ {
+ SQLException aError = ::dbtools::prependErrorInfo(e, *this, DBA_RES(SBA_BROWSER_SETTING_ORDER));
+ css::sdb::SQLErrorEvent aEvent;
+ aEvent.Reason <<= aError;
+ errorOccured(aEvent);
+ }
+ catch(Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess", "SbaXDataBrowserController::Execute : caught an exception while composing the new filter !");
+ }
+
+ if (bParserSuccess)
+ applyParserOrder(sOldSort,xParser);
+ }
+ break;
+
+ case ID_BROWSER_AUTOFILTER:
+ {
+ if (!SaveModified())
+ break;
+
+ if (!isValidCursor())
+ break;
+
+ Reference< XPropertySet > xField = getBoundField();
+ if (!xField.is())
+ break;
+
+ // check if the column is an aggregate function
+ const bool bHaving(isAggregateColumn(m_xParser, xField));
+
+ Reference< XSingleSelectQueryComposer > xParser = createParser_nothrow();
+ const OUString sOldFilter = xParser->getFilter();
+ const OUString sOldHaving = xParser->getHavingClause();
+
+ Reference< XPropertySet > xFormSet(getRowSet(), UNO_QUERY);
+ bool bApplied = ::comphelper::getBOOL(xFormSet->getPropertyValue(PROPERTY_APPLYFILTER));
+ // do we have a filter but it's not applied ?
+ // -> completely overwrite it, else append one
+ if (!bApplied)
+ {
+ try
+ {
+ xParser->setFilter(OUString());
+ }
+ catch(Exception&)
+ {
+ SAL_WARN("dbaccess.ui", "SbaXDataBrowserController::Execute : caught an exception while resetting unapplied filter !");
+ }
+ try
+ {
+ xParser->setHavingClause(OUString());
+ }
+ catch(Exception&)
+ {
+ SAL_WARN("dbaccess.ui", "SbaXDataBrowserController::Execute : caught an exception while resetting unapplied HAVING clause !");
+ }
+ }
+
+ bool bParserSuccess = false;
+
+ const sal_Int32 nOp = SQLFilterOperator::EQUAL;
+
+ if ( bHaving )
+ {
+ try
+ {
+ bParserSuccess = false;
+ xParser->appendHavingClauseByColumn(xField,true,nOp);
+ bParserSuccess = true;
+ }
+ catch(SQLException& e)
+ {
+ SQLException aError = ::dbtools::prependErrorInfo(e, *this, DBA_RES(SBA_BROWSER_SETTING_FILTER));
+ css::sdb::SQLErrorEvent aEvent;
+ aEvent.Reason <<= aError;
+ errorOccured(aEvent);
+ }
+ catch(Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess", "SbaXDataBrowserController::Execute : caught an exception while composing the new filter !");
+ }
+ }
+ else
+ {
+ try
+ {
+ bParserSuccess = false;
+ xParser->appendFilterByColumn(xField,true,nOp);
+ bParserSuccess = true;
+ }
+ catch(SQLException& e)
+ {
+ SQLException aError = ::dbtools::prependErrorInfo(e, *this, DBA_RES(SBA_BROWSER_SETTING_FILTER));
+ css::sdb::SQLErrorEvent aEvent;
+ aEvent.Reason <<= aError;
+ errorOccured(aEvent);
+ }
+ catch(Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess", "SbaXDataBrowserController::Execute : caught an exception while composing the new filter !");
+ }
+ }
+
+ if (bParserSuccess)
+ applyParserFilter(sOldFilter, bApplied,sOldHaving,xParser);
+
+ InvalidateFeature(ID_BROWSER_REMOVEFILTER);
+ InvalidateFeature(ID_BROWSER_FILTERED);
+ }
+ break;
+
+ case ID_BROWSER_ORDERCRIT:
+ ExecuteFilterSortCrit(false);
+ break;
+
+ case ID_BROWSER_FILTERCRIT:
+ ExecuteFilterSortCrit(true);
+ InvalidateFeature(ID_BROWSER_FILTERED);
+ break;
+
+ case ID_BROWSER_REMOVEFILTER:
+ {
+ if (!SaveModified())
+ break;
+
+ bool bNeedPostReload = preReloadForm();
+ // reset the filter and the sort property simultaneously so only _one_ new statement has to be
+ // sent
+ Reference< XPropertySet > xSet(getRowSet(), UNO_QUERY);
+ if ( xSet.is() )
+ {
+ xSet->setPropertyValue(PROPERTY_FILTER,Any(OUString()));
+ xSet->setPropertyValue(PROPERTY_HAVING_CLAUSE,Any(OUString()));
+ xSet->setPropertyValue(PROPERTY_ORDER,Any(OUString()));
+ }
+ try
+ {
+ reloadForm(m_xLoadable);
+ if ( bNeedPostReload )
+ postReloadForm();
+ }
+ catch(Exception&)
+ {
+ }
+ InvalidateFeature(ID_BROWSER_REMOVEFILTER);
+ InvalidateFeature(ID_BROWSER_FILTERED);
+ }
+ break;
+
+ case ID_BROWSER_REFRESH:
+ if ( SaveModified( ) )
+ {
+ if (!reloadForm(m_xLoadable))
+ criticalFail();
+ }
+ break;
+
+ case ID_BROWSER_SAVERECORD:
+ if ( SaveModified( false ) )
+ setCurrentModified( false );
+ break;
+
+ case ID_BROWSER_UNDORECORD:
+ {
+ try
+ {
+ // restore the cursor state
+ Reference< XResultSetUpdate > xCursor(getRowSet(), UNO_QUERY);
+ Reference< XPropertySet > xSet(xCursor, UNO_QUERY);
+ Any aVal = xSet->getPropertyValue(PROPERTY_ISNEW);
+ if (aVal.hasValue() && ::comphelper::getBOOL(aVal))
+ {
+ xCursor->moveToInsertRow();
+ // no need to reset the grid model after we moved to the insert row, this is done implicitly by the
+ // form
+ // (and in some cases it may be deadly to do the reset explicitly after the form did it implicitly,
+ // cause the form's reset may be async, and this leads to some nice deadlock scenarios...)
+ }
+ else
+ {
+ xCursor->cancelRowUpdates();
+
+ // restore the grids state
+ Reference< css::form::XReset > xReset(getControlModel(), UNO_QUERY);
+ if (xReset.is())
+ xReset->reset();
+ }
+ }
+ catch(SQLException&)
+ {
+ }
+
+ setCurrentModified( false );
+ }
+ }
+}
+
+bool SbaXDataBrowserController::SaveModified(bool bAskFor)
+{
+ if ( bAskFor && GetState(ID_BROWSER_SAVERECORD).bEnabled )
+ {
+ getBrowserView()->getVclControl()->GrabFocus();
+
+ std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(getFrameWeld(), "dbaccess/ui/savemodifieddialog.ui"));
+ std::unique_ptr<weld::MessageDialog> xQry(xBuilder->weld_message_dialog("SaveModifiedDialog"));
+ switch (xQry->run())
+ {
+ case RET_NO:
+ Execute(ID_BROWSER_UNDORECORD,Sequence<PropertyValue>());
+ return true;
+ case RET_CANCEL:
+ return false;
+ }
+ }
+
+ if ( !CommitCurrent() ) // Commit the current control
+ return false;
+
+ Reference< XPropertySet > xFormSet(getRowSet(), UNO_QUERY);
+ bool bResult = false;
+ try
+ {
+ if (::comphelper::getBOOL(xFormSet->getPropertyValue(PROPERTY_ISMODIFIED)))
+ {
+ Reference< XResultSetUpdate > xCursor(getRowSet(), UNO_QUERY);
+ if (::comphelper::getBOOL(xFormSet->getPropertyValue(PROPERTY_ISNEW)))
+ xCursor->insertRow();
+ else
+ xCursor->updateRow();
+ }
+ bResult = true;
+ }
+ catch(SQLException&)
+ {
+ }
+ catch(Exception&)
+ {
+ SAL_WARN("dbaccess.ui", "SbaXDataBrowserController::SaveModified : could not save the current record !");
+ bResult = false;
+ }
+
+ InvalidateFeature(ID_BROWSER_SAVERECORD);
+ InvalidateFeature(ID_BROWSER_UNDORECORD);
+ return bResult;
+}
+
+bool SbaXDataBrowserController::CommitCurrent()
+{
+ if (!getBrowserView())
+ return true;
+
+ Reference< css::awt::XControl > xActiveControl(getBrowserView()->getGridControl());
+ Reference< css::form::XBoundControl > xLockingTest(xActiveControl, UNO_QUERY);
+ bool bControlIsLocked = xLockingTest.is() && xLockingTest->getLock();
+ if (xActiveControl.is() && !bControlIsLocked)
+ {
+ // At first check Control if it supports the IFace
+ Reference< css::form::XBoundComponent > xBoundControl(xActiveControl, UNO_QUERY);
+ if (!xBoundControl.is())
+ xBoundControl.set(xActiveControl->getModel(), UNO_QUERY);
+ if (xBoundControl.is() && !xBoundControl->commit())
+ return false;
+ }
+ return true;
+}
+
+void SbaXDataBrowserController::setCurrentModified( bool _bSet )
+{
+ m_bCurrentlyModified = _bSet;
+ InvalidateFeature( ID_BROWSER_SAVERECORD );
+ InvalidateFeature( ID_BROWSER_UNDORECORD );
+}
+
+void SbaXDataBrowserController::RowChanged()
+{
+ setCurrentModified( false );
+}
+
+void SbaXDataBrowserController::ColumnChanged()
+{
+ InvalidateFeature(ID_BROWSER_SORTUP);
+ InvalidateFeature(ID_BROWSER_SORTDOWN);
+ InvalidateFeature(ID_BROWSER_ORDERCRIT);
+ InvalidateFeature(ID_BROWSER_FILTERCRIT);
+ InvalidateFeature(ID_BROWSER_AUTOFILTER);
+ InvalidateFeature(ID_BROWSER_REMOVEFILTER);
+
+ setCurrentModified( false );
+}
+
+void SbaXDataBrowserController::SelectionChanged()
+{
+ // not interested in
+}
+
+void SbaXDataBrowserController::CellActivated()
+{
+ m_aInvalidateClipboard.Start();
+ OnInvalidateClipboard( nullptr );
+}
+
+void SbaXDataBrowserController::CellDeactivated()
+{
+ m_aInvalidateClipboard.Stop();
+ OnInvalidateClipboard( nullptr );
+}
+
+IMPL_LINK_NOARG(SbaXDataBrowserController, OnClipboardChanged, TransferableDataHelper*, void)
+{
+ SolarMutexGuard aGuard;
+ OnInvalidateClipboard( nullptr );
+}
+
+IMPL_LINK(SbaXDataBrowserController, OnInvalidateClipboard, Timer*, _pTimer, void)
+{
+ InvalidateFeature(ID_BROWSER_CUT);
+ InvalidateFeature(ID_BROWSER_COPY);
+
+ // if the invalidation was triggered by the timer, we do not need to invalidate PASTE.
+ // The timer is only for checking the CUT/COPY slots regularly, which depend on the
+ // selection state of the active cell
+ // TODO: get a callback at the Edit which allows to be notified when the selection
+ // changes. This would be much better than this cycle-eating polling mechanism here...
+ if ( _pTimer != &m_aInvalidateClipboard )
+ InvalidateFeature(ID_BROWSER_PASTE);
+}
+
+Reference< XPropertySet > SbaXDataBrowserController::getBoundField() const
+{
+ Reference< XPropertySet > xEmptyReturn;
+
+ // get the current column from the grid
+ Reference< css::form::XGrid > xGrid(getBrowserView()->getGridControl(), UNO_QUERY);
+ if (!xGrid.is())
+ return xEmptyReturn;
+ sal_uInt16 nViewPos = xGrid->getCurrentColumnPosition();
+ sal_uInt16 nCurrentCol = getBrowserView()->View2ModelPos(nViewPos);
+ if (nCurrentCol == sal_uInt16(-1))
+ return xEmptyReturn;
+
+ // get the according column from the model
+ Reference< css::container::XIndexContainer > xCols(getControlModel(), UNO_QUERY);
+ Reference< XPropertySet > xCurrentCol(xCols->getByIndex(nCurrentCol),UNO_QUERY);
+ if (!xCurrentCol.is())
+ return xEmptyReturn;
+
+ xEmptyReturn.set(xCurrentCol->getPropertyValue(PROPERTY_BOUNDFIELD) ,UNO_QUERY);
+ return xEmptyReturn;
+}
+
+IMPL_LINK(SbaXDataBrowserController, OnSearchContextRequest, FmSearchContext&, rContext, sal_uInt32)
+{
+ Reference< css::container::XIndexAccess > xPeerContainer(getBrowserView()->getGridControl(), UNO_QUERY);
+
+ // check all grid columns for their control source
+ Reference< css::container::XIndexAccess > xModelColumns(getFormComponent(), UNO_QUERY);
+ OSL_ENSURE(xModelColumns.is(), "SbaXDataBrowserController::OnSearchContextRequest : there is a grid control without columns !");
+ // the case 'no columns' should be indicated with an empty container, I think ...
+ OSL_ENSURE(xModelColumns->getCount() >= xPeerContainer->getCount(), "SbaXDataBrowserController::OnSearchContextRequest : impossible : have more view than model columns !");
+
+ OUString sFieldList;
+ for (sal_Int32 nViewPos=0; nViewPos<xPeerContainer->getCount(); ++nViewPos)
+ {
+ Reference< XInterface > xCurrentColumn(xPeerContainer->getByIndex(nViewPos),UNO_QUERY);
+ if (!xCurrentColumn.is())
+ continue;
+
+ // can we use this column control for searching ?
+ if (!IsSearchableControl(xCurrentColumn))
+ continue;
+
+ sal_uInt16 nModelPos = getBrowserView()->View2ModelPos(static_cast<sal_uInt16>(nViewPos));
+ Reference< XPropertySet > xCurrentColModel(xModelColumns->getByIndex(nModelPos),UNO_QUERY);
+ OUString aName = ::comphelper::getString(xCurrentColModel->getPropertyValue(PROPERTY_CONTROLSOURCE));
+
+ sFieldList += aName + ";";
+
+ rContext.arrFields.push_back(xCurrentColumn);
+ }
+ sFieldList = comphelper::string::stripEnd(sFieldList, ';');
+
+ rContext.xCursor = getRowSet();
+ rContext.strUsedFields = sFieldList;
+
+ // if the cursor is in a mode other than STANDARD -> reset
+ Reference< XPropertySet > xCursorSet(rContext.xCursor, UNO_QUERY);
+ OSL_ENSURE(xCursorSet.is() && !::comphelper::getBOOL(xCursorSet->getPropertyValue(PROPERTY_ISMODIFIED)),
+ "SbaXDataBrowserController::OnSearchContextRequest : please do not call for cursors with modified rows !");
+ if (xCursorSet.is() && ::comphelper::getBOOL(xCursorSet->getPropertyValue(PROPERTY_ISNEW)))
+ {
+ Reference< XResultSetUpdate > xUpdateCursor(rContext.xCursor, UNO_QUERY);
+ xUpdateCursor->moveToCurrentRow();
+ }
+ return rContext.arrFields.size();
+}
+
+IMPL_LINK(SbaXDataBrowserController, OnFoundData, FmFoundRecordInformation&, rInfo, void)
+{
+ Reference< css::sdbcx::XRowLocate > xCursor(getRowSet(), UNO_QUERY);
+ OSL_ENSURE(xCursor.is(), "SbaXDataBrowserController::OnFoundData : xCursor is empty");
+
+ // move the cursor
+ xCursor->moveToBookmark(rInfo.aPosition);
+
+ // let the grid sync its display with the cursor
+ Reference< XPropertySet > xModelSet(getControlModel(), UNO_QUERY);
+ OSL_ENSURE(xModelSet.is(), "SbaXDataBrowserController::OnFoundData : no model set ?!");
+ Any aOld = xModelSet->getPropertyValue("DisplayIsSynchron");
+ xModelSet->setPropertyValue("DisplayIsSynchron", css::uno::Any(true));
+ xModelSet->setPropertyValue("DisplayIsSynchron", aOld);
+
+ // and move to the field
+ Reference< css::container::XIndexAccess > aColumnControls(getBrowserView()->getGridControl()->getPeer(), UNO_QUERY);
+ sal_Int32 nViewPos;
+
+ for ( nViewPos = 0; nViewPos < aColumnControls->getCount(); ++nViewPos )
+ {
+ Reference< XInterface > xCurrent(aColumnControls->getByIndex(nViewPos),UNO_QUERY);
+ if (IsSearchableControl(xCurrent))
+ {
+ if (rInfo.nFieldPos)
+ --rInfo.nFieldPos;
+ else
+ break;
+ }
+ }
+
+ Reference< css::form::XGrid > xGrid(getBrowserView()->getGridControl(), UNO_QUERY);
+ xGrid->setCurrentColumnPosition(nViewPos); //TODO: sal_Int32 -> sal_Int16!
+}
+
+IMPL_LINK(SbaXDataBrowserController, OnCanceledNotFound, FmFoundRecordInformation&, rInfo, void)
+{
+ Reference< css::sdbcx::XRowLocate > xCursor(getRowSet(), UNO_QUERY);
+
+ try
+ {
+ OSL_ENSURE(xCursor.is(), "SbaXDataBrowserController::OnCanceledNotFound : xCursor is empty");
+ // move the cursor
+ xCursor->moveToBookmark(rInfo.aPosition);
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+
+ try
+ {
+ // let the grid sync its display with the cursor
+ Reference< XPropertySet > xModelSet(getControlModel(), UNO_QUERY);
+ OSL_ENSURE(xModelSet.is(), "SbaXDataBrowserController::OnCanceledNotFound : no model set ?!");
+ Any aOld = xModelSet->getPropertyValue("DisplayIsSynchron");
+ xModelSet->setPropertyValue("DisplayIsSynchron", css::uno::Any(true));
+ xModelSet->setPropertyValue("DisplayIsSynchron", aOld);
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+}
+
+IMPL_LINK_NOARG(SbaXDataBrowserController, OnAsyncGetCellFocus, void*, void)
+{
+ SbaGridControl* pVclGrid = getBrowserView() ? getBrowserView()->getVclControl() : nullptr;
+ // if we have a controller, but the window for the controller doesn't have the focus, we correct this
+ if (pVclGrid && pVclGrid->IsEditing() && pVclGrid->HasChildPathFocus())
+ pVclGrid->Controller()->GetWindow().GrabFocus();
+}
+
+void SbaXDataBrowserController::criticalFail()
+{
+ InvalidateAll();
+ m_nRowSetPrivileges = 0;
+}
+
+void SbaXDataBrowserController::LoadFinished(bool /*bWasSynch*/)
+{
+ m_nRowSetPrivileges = 0;
+
+ if (!isValid() || loadingCancelled())
+ return;
+
+ // obtain cached values
+ try
+ {
+ Reference< XPropertySet > xFormProps( m_xLoadable, UNO_QUERY_THROW );
+ OSL_VERIFY( xFormProps->getPropertyValue( PROPERTY_PRIVILEGES ) >>= m_nRowSetPrivileges );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+
+ // switch the control to alive mode
+ getBrowserView()->getGridControl()->setDesignMode(false);
+
+ initializeParser();
+
+ InvalidateAll();
+
+ m_aAsyncGetCellFocus.Call();
+}
+
+void SbaXDataBrowserController::initializeParser() const
+{
+ if ( m_xParser.is() )
+ return;
+
+ // create a parser (needed for filtering/sorting)
+ try
+ {
+ const Reference< XPropertySet > xFormSet(getRowSet(), UNO_QUERY);
+ if (::comphelper::getBOOL(xFormSet->getPropertyValue(PROPERTY_ESCAPE_PROCESSING)))
+ { // (only if the statement isn't native)
+ // (it is allowed to use the PROPERTY_ISPASSTHROUGH : _after_ loading a form it is valid)
+ xFormSet->getPropertyValue(PROPERTY_SINGLESELECTQUERYCOMPOSER) >>= m_xParser;
+ }
+ }
+ catch(Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ m_xParser = nullptr;
+ // no further handling, we ignore the error
+ }
+}
+
+void SbaXDataBrowserController::loaded(const EventObject& /*aEvent*/)
+{
+ // not interested in
+ // we're loading within a separated thread and have a handling for its "finished event"
+}
+
+void SbaXDataBrowserController::unloading(const EventObject& /*aEvent*/)
+{
+ // not interested in
+}
+
+void SbaXDataBrowserController::unloaded(const EventObject& /*aEvent*/)
+{
+ m_xParser.clear();
+ InvalidateAll();
+ // do this asynchronously, there are other listeners reacting on this message ...
+ // (it's a little hack : the grid columns are listening to this event, too, and their bound field may
+ // change as a reaction on that event. as we have no chance to be notified of this change (which is
+ // the one we're interested in) we give them time to do what they want to before invalidating our
+ // bound-field-dependent slots...
+}
+
+void SbaXDataBrowserController::reloading(const EventObject& /*aEvent*/)
+{
+ // not interested in
+}
+
+void SbaXDataBrowserController::reloaded(const EventObject& /*aEvent*/)
+{
+ InvalidateAll();
+ // do this asynchronously, there are other listeners reacting on this message ...
+ // (it's a little hack : the grid columns are listening to this event, too, and their bound field may
+ // change as a reaction on that event. as we have no chance to be notified of this change (which is
+ // the one we're interested in) we give them time to do what they want to before invalidating our
+ // bound-field-dependent slots...
+}
+
+void SbaXDataBrowserController::enterFormAction()
+{
+ if ( !m_nFormActionNestingLevel )
+ // first action -> reset
+ m_aCurrentError.clear();
+
+ ++m_nFormActionNestingLevel;
+}
+
+void SbaXDataBrowserController::leaveFormAction()
+{
+ OSL_ENSURE( m_nFormActionNestingLevel > 0, "SbaXDataBrowserController::leaveFormAction : invalid call !" );
+ if ( --m_nFormActionNestingLevel > 0 )
+ return;
+
+ if ( !m_aCurrentError.isValid() )
+ return;
+
+ m_aAsyncDisplayError.Call();
+}
+
+bool SbaXDataBrowserController::isLoaded() const
+{
+ return m_xLoadable.is() && m_xLoadable->isLoaded();
+}
+
+bool SbaXDataBrowserController::isValidCursor() const
+{
+ if (!m_xColumnsSupplier.is())
+ return false;
+ Reference< css::container::XNameAccess > xCols = m_xColumnsSupplier->getColumns();
+ if (!xCols.is() || !xCols->hasElements())
+ return false;
+
+ bool bIsValid = !(m_xRowSet->isBeforeFirst() || m_xRowSet->isAfterLast());
+ if ( !bIsValid )
+ {
+ Reference<XPropertySet> xProp(m_xRowSet,UNO_QUERY);
+ bIsValid = ::cppu::any2bool(xProp->getPropertyValue(PROPERTY_ISNEW));
+ if ( !bIsValid )
+ {
+ bIsValid = m_xParser.is();
+ }
+ }
+ return bIsValid;
+}
+
+sal_Int16 SbaXDataBrowserController::getCurrentColumnPosition() const
+{
+ Reference< css::form::XGrid > xGrid(getBrowserView()->getGridControl(), UNO_QUERY);
+ sal_Int16 nViewPos = -1;
+ try
+ {
+ if ( xGrid.is() )
+ nViewPos = xGrid->getCurrentColumnPosition();
+ }
+ catch(Exception&) {}
+ return nViewPos;
+}
+
+void SbaXDataBrowserController::setCurrentColumnPosition( sal_Int16 _nPos )
+{
+ Reference< css::form::XGrid > xGrid(getBrowserView()->getGridControl(), UNO_QUERY);
+ try
+ {
+ if ( -1 != _nPos )
+ xGrid->setCurrentColumnPosition(_nPos);
+ }
+ catch(Exception&) {}
+}
+
+void SbaXDataBrowserController::BeforeDrop()
+{
+ Reference< css::sdb::XSQLErrorBroadcaster > xFormError(getRowSet(), UNO_QUERY);
+ if (xFormError.is())
+ xFormError->removeSQLErrorListener(static_cast<css::sdb::XSQLErrorListener*>(this));
+}
+
+void SbaXDataBrowserController::AfterDrop()
+{
+ Reference< css::sdb::XSQLErrorBroadcaster > xFormError(getRowSet(), UNO_QUERY);
+ if (xFormError.is())
+ xFormError->addSQLErrorListener(static_cast<css::sdb::XSQLErrorListener*>(this));
+}
+
+void SbaXDataBrowserController::addColumnListeners(const Reference< css::awt::XControlModel > & _xGridControlModel)
+{
+// ... all the grid columns
+ Reference< css::container::XIndexContainer > xColumns(_xGridControlModel, UNO_QUERY);
+ if (xColumns.is())
+ {
+ sal_Int32 nCount = xColumns->getCount();
+ for (sal_Int32 i=0; i < nCount; ++i)
+ {
+ Reference< XPropertySet > xCol(xColumns->getByIndex(i),UNO_QUERY);
+ AddColumnListener(xCol);
+ }
+ }
+}
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/browser/brwview.cxx b/dbaccess/source/ui/browser/brwview.cxx
new file mode 100644
index 000000000..b68819d67
--- /dev/null
+++ b/dbaccess/source/ui/browser/brwview.cxx
@@ -0,0 +1,333 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <brwview.hxx>
+#include <sbagrid.hxx>
+#include <toolkit/helper/vclunohelper.hxx>
+#include <comphelper/types.hxx>
+#include <vcl/split.hxx>
+#include <strings.hxx>
+#include <com/sun/star/form/XLoadable.hpp>
+#include <com/sun/star/awt/XControlContainer.hpp>
+#include <com/sun/star/awt/PosSize.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/container/XChild.hpp>
+#include <osl/diagnose.h>
+
+using namespace dbaui;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::sdb;
+using namespace ::com::sun::star::form;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::lang;
+
+namespace
+{
+ bool isGrabVclControlFocusAllowed(const UnoDataBrowserView* _pView)
+ {
+ bool bGrabFocus = false;
+ SbaGridControl* pVclControl = _pView->getVclControl();
+ const Reference< css::awt::XControl >& xGrid = _pView->getGridControl();
+ if (pVclControl && xGrid.is())
+ {
+ bGrabFocus = true;
+ if(!pVclControl->HasChildPathFocus())
+ {
+ Reference<XChild> xChild(xGrid->getModel(),UNO_QUERY);
+ Reference<XLoadable> xLoad;
+ if(xChild.is())
+ xLoad.set(xChild->getParent(),UNO_QUERY);
+ bGrabFocus = xLoad.is() && xLoad->isLoaded();
+ }
+ }
+ return bGrabFocus;
+ }
+}
+
+// UnoDataBrowserView
+
+UnoDataBrowserView::UnoDataBrowserView( vcl::Window* pParent,
+ IController& _rController,
+ const Reference< css::uno::XComponentContext >& _rxContext)
+ :ODataView(pParent,_rController,_rxContext)
+ ,m_pTreeView(nullptr)
+ ,m_pSplitter(nullptr)
+ ,m_pVclControl(nullptr)
+{
+
+}
+
+void UnoDataBrowserView::Construct(const Reference< css::awt::XControlModel >& xModel)
+{
+ try
+ {
+ ODataView::Construct();
+
+ // our UNO representation
+ m_xMe = VCLUnoHelper::CreateControlContainer(this);
+
+ // create the (UNO-) control
+ m_xGrid = new SbaXGridControl( getORB() );
+ OSL_ENSURE(m_xGrid.is(), "UnoDataBrowserView::Construct : could not create a grid control !");
+ // in design mode (for the moment)
+ m_xGrid->setDesignMode(true);
+
+ Reference< css::awt::XWindow > xGridWindow(m_xGrid, UNO_QUERY);
+ xGridWindow->setVisible(true);
+ xGridWindow->setEnable(true);
+
+ // introduce the model to the grid
+ m_xGrid->setModel(xModel);
+ // introduce the container (me) to the grid
+ Reference< css::beans::XPropertySet > xModelSet(xModel, UNO_QUERY);
+ getContainer()->addControl(::comphelper::getString(xModelSet->getPropertyValue(PROPERTY_NAME)), m_xGrid);
+
+ // get the VCL-control
+ m_pVclControl = nullptr;
+ getVclControl();
+
+ OSL_ENSURE(m_pVclControl != nullptr, "UnoDataBrowserView::Construct : no real grid control !");
+ }
+ catch(const Exception&)
+ {
+ ::comphelper::disposeComponent(m_xGrid);
+ throw;
+ }
+}
+
+UnoDataBrowserView::~UnoDataBrowserView()
+{
+ disposeOnce();
+}
+
+void UnoDataBrowserView::dispose()
+{
+ m_pSplitter.disposeAndClear();
+ setTreeView(nullptr);
+
+ try
+ {
+ ::comphelper::disposeComponent(m_xGrid);
+ ::comphelper::disposeComponent(m_xMe);
+ }
+ catch(const Exception&)
+ {}
+ m_pTreeView.clear();
+ m_pVclControl.clear();
+ ODataView::dispose();
+}
+
+IMPL_LINK_NOARG( UnoDataBrowserView, SplitHdl, Splitter*, void )
+{
+ tools::Long nYPos = m_pSplitter->GetPosPixel().Y();
+ m_pSplitter->SetPosPixel( Point( m_pSplitter->GetSplitPosPixel(), nYPos ) );
+ Resize();
+}
+
+void UnoDataBrowserView::setSplitter(Splitter* _pSplitter)
+{
+ m_pSplitter = _pSplitter;
+ m_pSplitter->SetSplitHdl( LINK( this, UnoDataBrowserView, SplitHdl ) );
+ LINK( this, UnoDataBrowserView, SplitHdl ).Call(m_pSplitter);
+}
+
+void UnoDataBrowserView::setTreeView(InterimDBTreeListBox* pTreeView)
+{
+ if (m_pTreeView.get() != pTreeView)
+ {
+ m_pTreeView.disposeAndClear();
+ m_pTreeView = pTreeView;
+ }
+}
+
+void UnoDataBrowserView::showStatus( const OUString& _rStatus )
+{
+ if (_rStatus.isEmpty())
+ hideStatus();
+ else
+ {
+ if (!m_pTreeView)
+ return;
+ weld::Label& rLabel = m_pTreeView->GetStatusBar();
+ rLabel.set_label(_rStatus);
+ rLabel.show();
+ Resize();
+ PaintImmediately();
+ }
+}
+
+void UnoDataBrowserView::hideStatus()
+{
+ if (!m_pTreeView)
+ return;
+ weld::Label& rLabel = m_pTreeView->GetStatusBar();
+ if (!rLabel.get_visible())
+ {
+ // nothing to do
+ return;
+ }
+ rLabel.hide();
+ Resize();
+ PaintImmediately();
+}
+
+void UnoDataBrowserView::resizeDocumentView(tools::Rectangle& _rPlayground)
+{
+ Point aSplitPos;
+ Size aSplitSize;
+ Point aPlaygroundPos( _rPlayground.TopLeft() );
+ Size aPlaygroundSize( _rPlayground.GetSize() );
+
+ if (m_pTreeView && m_pTreeView->IsVisible() && m_pSplitter)
+ {
+ // calculate the splitter pos and size
+ aSplitPos = m_pSplitter->GetPosPixel();
+ aSplitPos.setY( aPlaygroundPos.Y() );
+ aSplitSize = m_pSplitter->GetOutputSizePixel();
+ aSplitSize.setHeight( aPlaygroundSize.Height() );
+
+ if( ( aSplitPos.X() + aSplitSize.Width() ) > ( aPlaygroundSize.Width() ))
+ aSplitPos.setX( aPlaygroundSize.Width() - aSplitSize.Width() );
+
+ if( aSplitPos.X() <= aPlaygroundPos.X() )
+ aSplitPos.setX( aPlaygroundPos.X() + sal_Int32(aPlaygroundSize.Width() * 0.2) );
+
+ // the tree pos and size
+ Point aTreeViewPos( aPlaygroundPos );
+ Size aTreeViewSize( aSplitPos.X(), aPlaygroundSize.Height() );
+
+ // set the size of treelistbox
+ m_pTreeView->SetPosSizePixel( aTreeViewPos, aTreeViewSize );
+ // Call this to trigger InterimItemWindow::Layout immediately, and
+ // not later on idle so the statusbar will be shown to explain
+ // a long delay on opening databases
+ m_pTreeView->Resize();
+
+ //set the size of the splitter
+ m_pSplitter->SetPosSizePixel( aSplitPos, Size( aSplitSize.Width(), aPlaygroundSize.Height() ) );
+ m_pSplitter->SetDragRectPixel( _rPlayground );
+ }
+
+ // set the size of grid control
+ Reference< css::awt::XWindow > xGridAsWindow(m_xGrid, UNO_QUERY);
+ if (xGridAsWindow.is())
+ xGridAsWindow->setPosSize( aSplitPos.X() + aSplitSize.Width(), aPlaygroundPos.Y(),
+ aPlaygroundSize.Width() - aSplitSize.Width() - aSplitPos.X(), aPlaygroundSize.Height(), css::awt::PosSize::POSSIZE);
+
+ // just for completeness: there is no space left, we occupied it all ...
+ _rPlayground.SetPos( _rPlayground.BottomRight() );
+ _rPlayground.SetSize( Size( 0, 0 ) );
+}
+
+sal_uInt16 UnoDataBrowserView::View2ModelPos(sal_uInt16 nPos) const
+{
+ return m_pVclControl ? m_pVclControl->GetModelColumnPos(m_pVclControl->GetColumnIdFromViewPos(nPos)) : -1;
+}
+
+SbaGridControl* UnoDataBrowserView::getVclControl() const
+{
+ if ( !m_pVclControl )
+ {
+ OSL_ENSURE(m_xGrid.is(),"Grid not set!");
+ if ( m_xGrid.is() )
+ {
+ Reference< css::awt::XWindowPeer > xPeer = m_xGrid->getPeer();
+ if ( xPeer.is() )
+ {
+ SbaXGridPeer* pPeer = comphelper::getFromUnoTunnel<SbaXGridPeer>(xPeer);
+ UnoDataBrowserView* pTHIS = const_cast<UnoDataBrowserView*>(this);
+ if ( pPeer )
+ {
+ m_pVclControl = static_cast<SbaGridControl*>(pPeer->GetWindow());
+ pTHIS->startComponentListening(VCLUnoHelper::GetInterface(m_pVclControl));
+ }
+ }
+ }
+ }
+ return m_pVclControl;
+}
+
+void UnoDataBrowserView::GetFocus()
+{
+ ODataView::GetFocus();
+ if( m_pTreeView && m_pTreeView->IsVisible() && !m_pTreeView->HasChildPathFocus())
+ m_pTreeView->GrabFocus();
+ else if (m_pVclControl && m_xGrid.is())
+ {
+ bool bGrabFocus = false;
+ if(!m_pVclControl->HasChildPathFocus())
+ {
+ bGrabFocus = isGrabVclControlFocusAllowed(this);
+ if( bGrabFocus )
+ m_pVclControl->GrabFocus();
+ }
+ if(!bGrabFocus && m_pTreeView && m_pTreeView->IsVisible() )
+ m_pTreeView->GrabFocus();
+ }
+}
+
+void UnoDataBrowserView::_disposing( const css::lang::EventObject& /*_rSource*/ )
+{
+ stopComponentListening(VCLUnoHelper::GetInterface(m_pVclControl));
+ m_pVclControl = nullptr;
+}
+
+bool UnoDataBrowserView::PreNotify( NotifyEvent& rNEvt )
+{
+ bool bDone = false;
+ if(rNEvt.GetType() == MouseNotifyEvent::KEYINPUT)
+ {
+ bool bGrabAllowed = isGrabVclControlFocusAllowed(this);
+ if ( bGrabAllowed )
+ {
+ const KeyEvent* pKeyEvt = rNEvt.GetKeyEvent();
+ const vcl::KeyCode& rKeyCode = pKeyEvt->GetKeyCode();
+ if ( ( rKeyCode == vcl::KeyCode( KEY_E, true, true, false, false ) )
+ || ( rKeyCode == vcl::KeyCode( KEY_TAB, true, false, false, false ) )
+ )
+ {
+ if ( m_pTreeView && m_pVclControl && m_pTreeView->HasChildPathFocus() )
+ m_pVclControl->GrabFocus();
+ else if ( m_pTreeView && m_pVclControl && m_pVclControl->HasChildPathFocus() )
+ m_pTreeView->GrabFocus();
+
+ bDone = true;
+ }
+ }
+ }
+ return bDone || ODataView::PreNotify(rNEvt);
+}
+
+BrowserViewStatusDisplay::BrowserViewStatusDisplay( UnoDataBrowserView* _pView, const OUString& _rStatus )
+ :m_pView(_pView)
+{
+
+ if (m_pView)
+ m_pView->showStatus(_rStatus);
+}
+
+BrowserViewStatusDisplay::~BrowserViewStatusDisplay( )
+{
+ if (m_pView)
+ m_pView->showStatus(OUString());
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/browser/dataview.cxx b/dbaccess/source/ui/browser/dataview.cxx
new file mode 100644
index 000000000..74ceea688
--- /dev/null
+++ b/dbaccess/source/ui/browser/dataview.cxx
@@ -0,0 +1,154 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <com/sun/star/frame/XController.hpp>
+#include <com/sun/star/frame/XModel.hpp>
+#include <dbaccess/dataview.hxx>
+#include <comphelper/namedvaluecollection.hxx>
+#include <dbaccess/IController.hxx>
+#include <svtools/acceleratorexecute.hxx>
+#include <tools/diagnose_ex.h>
+#include <vcl/event.hxx>
+#include <vcl/settings.hxx>
+
+namespace dbaui
+{
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::beans;
+ using namespace ::com::sun::star::util;
+ using namespace ::com::sun::star::lang;
+ using namespace ::com::sun::star::frame;
+
+ ODataView::ODataView( vcl::Window* pParent,
+ IController& _rController,
+ const Reference< XComponentContext >& _rxContext,
+ WinBits nStyle)
+ :Window(pParent,nStyle)
+ ,m_xContext(_rxContext)
+ ,m_xController( &_rController )
+ {
+ m_pAccel = ::svt::AcceleratorExecute::createAcceleratorHelper();
+ }
+
+ void ODataView::Construct()
+ {
+ }
+
+ ODataView::~ODataView()
+ {
+ disposeOnce();
+ }
+
+ void ODataView::dispose()
+ {
+ m_xController.clear();
+ m_pAccel.reset();
+ vcl::Window::dispose();
+ }
+
+ void ODataView::resizeDocumentView(tools::Rectangle& /*_rPlayground*/)
+ {
+ }
+
+ void ODataView::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& _rRect)
+ {
+ // draw the background
+ {
+ rRenderContext.Push(vcl::PushFlags::LINECOLOR | vcl::PushFlags::FILLCOLOR);
+ rRenderContext.SetLineColor(COL_TRANSPARENT);
+ rRenderContext.SetFillColor(GetSettings().GetStyleSettings().GetFaceColor());
+ rRenderContext.DrawRect(_rRect);
+ rRenderContext.Pop();
+ }
+
+ // let the base class do anything it needs
+ Window::Paint(rRenderContext, _rRect);
+ }
+
+ void ODataView::resizeAll(const tools::Rectangle& rPlayground)
+ {
+ // position the controls of the document's view
+ tools::Rectangle aPlayground(rPlayground);
+ resizeDocumentView(aPlayground);
+ }
+
+ void ODataView::Resize()
+ {
+ Window::Resize();
+ resizeAll( tools::Rectangle( Point( 0, 0), GetSizePixel() ) );
+ }
+ bool ODataView::PreNotify( NotifyEvent& _rNEvt )
+ {
+ bool bHandled = false;
+ switch ( _rNEvt.GetType() )
+ {
+ case MouseNotifyEvent::KEYINPUT:
+ {
+ const KeyEvent* pKeyEvent = _rNEvt.GetKeyEvent();
+ const vcl::KeyCode& aKeyCode = pKeyEvent->GetKeyCode();
+ if ( m_pAccel && m_pAccel->execute( aKeyCode ) )
+ // the accelerator consumed the event
+ return true;
+ [[fallthrough]];
+ }
+ case MouseNotifyEvent::KEYUP:
+ case MouseNotifyEvent::MOUSEBUTTONDOWN:
+ case MouseNotifyEvent::MOUSEBUTTONUP:
+ bHandled = m_xController->interceptUserInput( _rNEvt );
+ break;
+ default:
+ break;
+ }
+ return bHandled || Window::PreNotify( _rNEvt );
+ }
+ void ODataView::StateChanged( StateChangedType nType )
+ {
+ Window::StateChanged( nType );
+
+ if ( nType != StateChangedType::InitShow )
+ return;
+
+ // now that there's a view which is finally visible, remove the "Hidden" value from the
+ // model's arguments.
+ try
+ {
+ Reference< XController > xController( m_xController->getXController(), UNO_SET_THROW );
+ Reference< XModel > xModel = xController->getModel();
+ if ( xModel.is() )
+ {
+ ::comphelper::NamedValueCollection aArgs( xModel->getArgs() );
+ aArgs.remove( "Hidden" );
+ xModel->attachResource( xModel->getURL(), aArgs.getPropertyValues() );
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+
+ void ODataView::attachFrame(const Reference< XFrame >& _xFrame)
+ {
+ m_pAccel->init(m_xContext, _xFrame);
+ }
+}
+
+// namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/browser/dbexchange.cxx b/dbaccess/source/ui/browser/dbexchange.cxx
new file mode 100644
index 000000000..dc6398f48
--- /dev/null
+++ b/dbaccess/source/ui/browser/dbexchange.cxx
@@ -0,0 +1,251 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <dbexchange.hxx>
+#include <sot/formats.hxx>
+#include <sot/storage.hxx>
+#include <osl/diagnose.h>
+#include <com/sun/star/sdb/CommandType.hpp>
+#include <com/sun/star/sdb/XResultSetAccess.hpp>
+#include <com/sun/star/lang/XComponent.hpp>
+#include <TokenWriter.hxx>
+#include <svx/dataaccessdescriptor.hxx>
+#include <UITools.hxx>
+
+namespace dbaui
+{
+ constexpr sal_uInt32 FORMAT_OBJECT_ID_RTF = 1;
+ constexpr sal_uInt32 FORMAT_OBJECT_ID_HTML = 2;
+
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::beans;
+ using namespace ::com::sun::star::sdb;
+ using namespace ::com::sun::star::lang;
+ using namespace ::com::sun::star::util;
+ using namespace ::com::sun::star::sdbc;
+ using namespace ::com::sun::star::datatransfer;
+ using namespace ::svx;
+
+ namespace
+ {
+ template<class T > void lcl_setListener(const Reference<T>& _xComponent, const Reference< XEventListener >& i_rListener, const bool i_bAdd )
+ {
+ if ( !_xComponent.is() )
+ return;
+
+ Reference< XComponent> xCom( _xComponent, UNO_QUERY );
+ OSL_ENSURE( xCom.is(), "lcl_setListener: no component!" );
+ if ( !xCom.is() )
+ return;
+
+ i_bAdd ? xCom->addEventListener( i_rListener ) : xCom->removeEventListener( i_rListener );
+ }
+ }
+
+ ODataClipboard::ODataClipboard()
+ {
+ }
+
+ void ODataClipboard::Update(
+ const OUString& rDatasource,
+ const sal_Int32 nCommandType,
+ const OUString& rCommand,
+ const Reference< XConnection >& rxConnection,
+ const Reference< XNumberFormatter >& rxFormatter,
+ const Reference< XComponentContext >& rxORB)
+ {
+ ClearFormats();
+
+ ODataAccessObjectTransferable::Update(rDatasource, nCommandType, rCommand, rxConnection);
+
+ lcl_setListener(rxConnection, this, true);
+
+ m_pHtml.set(new OHTMLImportExport(getDescriptor(), rxORB, rxFormatter));
+ m_pRtf.set(new ORTFImportExport(getDescriptor(), rxORB, rxFormatter));
+
+ AddSupportedFormats();
+ }
+
+ void ODataClipboard::Update(
+ const OUString& rDatasource,
+ const sal_Int32 nCommandType,
+ const OUString& rCommand,
+ const Reference< XNumberFormatter >& rxFormatter,
+ const Reference< XComponentContext >& rxORB)
+ {
+ ClearFormats();
+
+ ODataAccessObjectTransferable::Update(rDatasource, nCommandType, rCommand);
+
+ m_pHtml.set(new OHTMLImportExport(getDescriptor(), rxORB, rxFormatter));
+ m_pRtf.set(new ORTFImportExport(getDescriptor(), rxORB, rxFormatter));
+
+ AddSupportedFormats();
+ }
+
+ ODataClipboard::ODataClipboard( const Reference< XPropertySet >& i_rAliveForm,
+ const Sequence< Any >& i_rSelectedRows,
+ const bool i_bBookmarkSelection,
+ const Reference< XComponentContext >& i_rORB )
+ :ODataAccessObjectTransferable( i_rAliveForm )
+ {
+ OSL_PRECOND( i_rORB.is(), "ODataClipboard::ODataClipboard: having no factory is not good ..." );
+
+ osl_atomic_increment( &m_refCount );
+
+ Reference<XConnection> xConnection;
+ getDescriptor()[ DataAccessDescriptorProperty::Connection ] >>= xConnection;
+ lcl_setListener( xConnection, this, true );
+
+ // do not pass the form itself as source result set, since the client might operate on the form, which
+ // might lead to undesired effects. Instead, use a clone.
+ Reference< XResultSet > xResultSetClone;
+ Reference< XResultSetAccess > xResultSetAccess( i_rAliveForm, UNO_QUERY );
+ if ( xResultSetAccess.is() )
+ xResultSetClone = xResultSetAccess->createResultSet();
+ OSL_ENSURE( xResultSetClone.is(), "ODataClipboard::ODataClipboard: could not clone the form's result set" );
+ lcl_setListener( xResultSetClone, this, true );
+
+ getDescriptor()[DataAccessDescriptorProperty::Cursor] <<= xResultSetClone;
+ getDescriptor()[DataAccessDescriptorProperty::Selection] <<= i_rSelectedRows;
+ getDescriptor()[DataAccessDescriptorProperty::BookmarkSelection]<<= i_bBookmarkSelection;
+ addCompatibleSelectionDescription( i_rSelectedRows );
+
+ if ( xConnection.is() && i_rORB.is() )
+ {
+ Reference< XNumberFormatter > xFormatter( getNumberFormatter( xConnection, i_rORB ) );
+ if ( xFormatter.is() )
+ {
+ m_pHtml.set( new OHTMLImportExport( getDescriptor(), i_rORB, xFormatter ) );
+ m_pRtf.set( new ORTFImportExport( getDescriptor(), i_rORB, xFormatter ) );
+ }
+ }
+
+ osl_atomic_decrement( &m_refCount );
+ }
+
+ bool ODataClipboard::WriteObject( ::tools::SvRef<SotTempStream>& rxOStm, void* pUserObject, sal_uInt32 nUserObjectId, const css::datatransfer::DataFlavor& /*rFlavor*/ )
+ {
+ if (nUserObjectId == FORMAT_OBJECT_ID_RTF || nUserObjectId == FORMAT_OBJECT_ID_HTML )
+ {
+ ODatabaseImportExport* pExport = static_cast<ODatabaseImportExport*>(pUserObject);
+ if ( pExport && rxOStm.is() )
+ {
+ pExport->setStream(rxOStm.get());
+ return pExport->Write();
+ }
+ }
+ return false;
+ }
+
+ void ODataClipboard::AddSupportedFormats()
+ {
+ if ( m_pRtf.is() )
+ AddFormat( SotClipboardFormatId::RTF );
+
+ if ( m_pHtml.is() )
+ AddFormat( SotClipboardFormatId::HTML );
+
+ ODataAccessObjectTransferable::AddSupportedFormats();
+ }
+
+ bool ODataClipboard::GetData( const DataFlavor& rFlavor, const OUString& rDestDoc )
+ {
+ const SotClipboardFormatId nFormat = SotExchange::GetFormat(rFlavor);
+ switch (nFormat)
+ {
+ case SotClipboardFormatId::RTF:
+ if ( m_pRtf.is() )
+ m_pRtf->initialize(getDescriptor());
+ return m_pRtf.is() && SetObject( m_pRtf.get(), FORMAT_OBJECT_ID_RTF, rFlavor );
+
+ case SotClipboardFormatId::HTML:
+ if ( m_pHtml.is() )
+ m_pHtml->initialize(getDescriptor());
+ return m_pHtml.is() && SetObject( m_pHtml.get(), FORMAT_OBJECT_ID_HTML, rFlavor );
+
+ default: break;
+ }
+
+ return ODataAccessObjectTransferable::GetData(rFlavor, rDestDoc);
+ }
+
+ void ODataClipboard::ObjectReleased()
+ {
+ if ( m_pHtml.is() )
+ {
+ m_pHtml->dispose();
+ m_pHtml.clear();
+ }
+
+ if ( m_pRtf.is() )
+ {
+ m_pRtf->dispose();
+ m_pRtf.clear();
+ }
+
+ if ( getDescriptor().has( DataAccessDescriptorProperty::Connection ) )
+ {
+ Reference<XConnection> xConnection( getDescriptor()[DataAccessDescriptorProperty::Connection], UNO_QUERY );
+ lcl_setListener( xConnection, this, false );
+ }
+
+ if ( getDescriptor().has( DataAccessDescriptorProperty::Cursor ) )
+ {
+ Reference< XResultSet > xResultSet( getDescriptor()[ DataAccessDescriptorProperty::Cursor ], UNO_QUERY );
+ lcl_setListener( xResultSet, this, false );
+ }
+
+ ODataAccessObjectTransferable::ObjectReleased( );
+ }
+
+ void SAL_CALL ODataClipboard::disposing( const css::lang::EventObject& i_rSource )
+ {
+ ODataAccessDescriptor& rDescriptor( getDescriptor() );
+
+ if ( rDescriptor.has( DataAccessDescriptorProperty::Connection ) )
+ {
+ Reference< XConnection > xConnection( rDescriptor[DataAccessDescriptorProperty::Connection], UNO_QUERY );
+ if ( xConnection == i_rSource.Source )
+ {
+ rDescriptor.erase( DataAccessDescriptorProperty::Connection );
+ }
+ }
+
+ if ( rDescriptor.has( DataAccessDescriptorProperty::Cursor ) )
+ {
+ Reference< XResultSet > xResultSet( rDescriptor[ DataAccessDescriptorProperty::Cursor ], UNO_QUERY );
+ if ( xResultSet == i_rSource.Source )
+ {
+ rDescriptor.erase( DataAccessDescriptorProperty::Cursor );
+ // Selection and BookmarkSelection are meaningless without a result set
+ if ( rDescriptor.has( DataAccessDescriptorProperty::Selection ) )
+ rDescriptor.erase( DataAccessDescriptorProperty::Selection );
+ if ( rDescriptor.has( DataAccessDescriptorProperty::BookmarkSelection ) )
+ rDescriptor.erase( DataAccessDescriptorProperty::BookmarkSelection );
+ }
+ }
+
+ // no matter whether it was the source connection or the source result set which died,
+ // we cannot provide the data anymore.
+ ClearFormats();
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/browser/dbloader.cxx b/dbaccess/source/ui/browser/dbloader.cxx
new file mode 100644
index 000000000..330d23a12
--- /dev/null
+++ b/dbaccess/source/ui/browser/dbloader.cxx
@@ -0,0 +1,269 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <strings.hxx>
+#include <UITools.hxx>
+
+#include <com/sun/star/container/XChild.hpp>
+#include <com/sun/star/frame/XController2.hpp>
+#include <com/sun/star/frame/XFrame.hpp>
+#include <com/sun/star/frame/XFrameLoader.hpp>
+#include <com/sun/star/frame/XLoadEventListener.hpp>
+#include <com/sun/star/lang/XInitialization.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/sdb/ReportDesign.hpp>
+#include <com/sun/star/sdbc/XConnection.hpp>
+#include <com/sun/star/frame/XModule.hpp>
+
+#include <com/sun/star/sdbc/XDataSource.hpp>
+#include <comphelper/namedvaluecollection.hxx>
+#include <comphelper/types.hxx>
+#include <cppuhelper/implbase.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <tools/diagnose_ex.h>
+#include <tools/urlobj.hxx>
+#include <vcl/svapp.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::frame;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::sdb;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::lang;
+using namespace dbaui;
+
+namespace {
+
+class DBContentLoader : public ::cppu::WeakImplHelper< XFrameLoader, XServiceInfo>
+{
+private:
+ Sequence< PropertyValue> m_aArgs;
+ Reference< XLoadEventListener > m_xListener;
+ Reference< XComponentContext > m_xContext;
+public:
+ explicit DBContentLoader(const Reference< XComponentContext >&);
+
+ // XServiceInfo
+ OUString SAL_CALL getImplementationName() override;
+ sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
+ Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+
+ // XLoader
+ virtual void SAL_CALL load( const Reference< XFrame > & _rFrame, const OUString& _rURL,
+ const Sequence< PropertyValue >& _rArgs,
+ const Reference< XLoadEventListener > & _rListener) override;
+ virtual void SAL_CALL cancel() override;
+};
+
+}
+
+DBContentLoader::DBContentLoader(const Reference< XComponentContext >& _rxContext)
+ :m_xContext(_rxContext)
+{
+
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+org_openoffice_comp_dbu_DBContentLoader_get_implementation(
+ css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const& )
+{
+ return cppu::acquire(new DBContentLoader(context));
+}
+
+// XServiceInfo
+OUString SAL_CALL DBContentLoader::getImplementationName()
+{
+ return "org.openoffice.comp.dbu.DBContentLoader";
+}
+
+// XServiceInfo
+sal_Bool SAL_CALL DBContentLoader::supportsService(const OUString& ServiceName)
+{
+ return cppu::supportsService(this, ServiceName);
+}
+
+// XServiceInfo
+Sequence< OUString > SAL_CALL DBContentLoader::getSupportedServiceNames()
+{
+ return { "com.sun.star.frame.FrameLoader", "com.sun.star.sdb.ContentLoader" };
+}
+
+void SAL_CALL DBContentLoader::load(const Reference< XFrame > & rFrame, const OUString& rURL,
+ const Sequence< PropertyValue >& rArgs,
+ const Reference< XLoadEventListener > & rListener)
+{
+ m_xListener = rListener;
+ m_aArgs = rArgs;
+
+ static constexpr struct ServiceNameToImplName
+ {
+ rtl::OUStringConstExpr sServiceName;
+ const char* pAsciiImplementationName;
+ } aImplementations[] = {
+ { URL_COMPONENT_FORMGRIDVIEW, "org.openoffice.comp.dbu.OFormGridView" },
+ { URL_COMPONENT_DATASOURCEBROWSER, "org.openoffice.comp.dbu.ODatasourceBrowser" },
+ { URL_COMPONENT_QUERYDESIGN, "org.openoffice.comp.dbu.OQueryDesign" },
+ { URL_COMPONENT_TABLEDESIGN, "org.openoffice.comp.dbu.OTableDesign" },
+ { URL_COMPONENT_RELATIONDESIGN, "org.openoffice.comp.dbu.ORelationDesign" },
+ { URL_COMPONENT_VIEWDESIGN, "org.openoffice.comp.dbu.OViewDesign" }
+ };
+
+ INetURLObject aParser( rURL );
+ Reference< XController2 > xController;
+
+ const OUString sComponentURL( aParser.GetMainURL( INetURLObject::DecodeMechanism::ToIUri ) );
+ for (const ServiceNameToImplName& aImplementation : aImplementations)
+ {
+ if ( sComponentURL == aImplementation.sServiceName )
+ {
+ xController.set( m_xContext->getServiceManager()->
+ createInstanceWithContext( OUString::createFromAscii( aImplementation.pAsciiImplementationName ), m_xContext), UNO_QUERY_THROW );
+ break;
+ }
+ }
+
+ // if a data source browser is loaded without its tree pane, then we assume it to be a
+ // table data view, effectively. In this case, we need to adjust the module identifier.
+ // #i85879#
+ ::comphelper::NamedValueCollection aLoadArgs( rArgs );
+
+ if ( sComponentURL == URL_COMPONENT_DATASOURCEBROWSER )
+ {
+ bool bDisableBrowser = !aLoadArgs.getOrDefault( "ShowTreeViewButton", true ) // compatibility name
+ || !aLoadArgs.getOrDefault( PROPERTY_ENABLE_BROWSER, true );
+
+ if ( bDisableBrowser )
+ {
+ try
+ {
+ Reference< XModule > xModule( xController, UNO_QUERY_THROW );
+ xModule->setIdentifier( "com.sun.star.sdb.TableDataView" );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+ }
+
+ if ( sComponentURL == URL_COMPONENT_REPORTDESIGN )
+ {
+ bool bPreview = aLoadArgs.getOrDefault( "Preview", false );
+ if ( bPreview )
+ { // report designs cannot be previewed
+ if ( rListener.is() )
+ rListener->loadCancelled( this );
+ return;
+ }
+ Reference< XModel > xReportModel( aLoadArgs.getOrDefault( "Model", Reference< XModel >() ) );
+ if ( xReportModel.is() )
+ {
+ xController.set( ReportDesign::create( m_xContext ) );
+ xController->attachModel( xReportModel );
+ xReportModel->connectController( xController );
+ xReportModel->setCurrentController( xController );
+ }
+ }
+
+ bool bSuccess = xController.is();
+ Reference< XModel > xDatabaseDocument;
+ if ( bSuccess )
+ {
+ Reference< XDataSource > xDataSource ( aLoadArgs.getOrDefault( "DataSource", Reference< XDataSource >() ) );
+ OUString sDataSourceName( aLoadArgs.getOrDefault( "DataSourceName", OUString() ) );
+ Reference< XConnection > xConnection ( aLoadArgs.getOrDefault( "ActiveConnection", Reference< XConnection >() ) );
+ if ( xDataSource.is() )
+ {
+ xDatabaseDocument.set( getDataSourceOrModel( xDataSource ), UNO_QUERY );
+ }
+ else if ( !sDataSourceName.isEmpty() )
+ {
+ ::dbtools::SQLExceptionInfo aError;
+ xDataSource.set( getDataSourceByName( sDataSourceName, nullptr, m_xContext, &aError ) );
+ xDatabaseDocument.set( getDataSourceOrModel( xDataSource ), UNO_QUERY );
+ }
+ else if ( xConnection.is() )
+ {
+ Reference< XChild > xAsChild( xConnection, UNO_QUERY );
+ if ( xAsChild.is() )
+ {
+ OSL_ENSURE( Reference< XDataSource >( xAsChild->getParent(), UNO_QUERY ).is(),
+ "DBContentLoader::load: a connection whose parent is no data source?" );
+ xDatabaseDocument.set( getDataSourceOrModel( xAsChild->getParent() ), UNO_QUERY );
+ }
+ }
+
+ // init controller
+ SolarMutexGuard aGuard;
+ try
+ {
+ Reference<XInitialization > xIni(xController,UNO_QUERY);
+ PropertyValue aFrame("Frame",0,Any(rFrame),PropertyState_DIRECT_VALUE);
+ Sequence< Any > aInitArgs(m_aArgs.getLength()+1);
+
+ Any* pBegin = aInitArgs.getArray();
+ Any* pEnd = pBegin + aInitArgs.getLength();
+ *pBegin <<= aFrame;
+ const PropertyValue* pIter = m_aArgs.getConstArray();
+ for(++pBegin;pBegin != pEnd;++pBegin,++pIter)
+ {
+ *pBegin <<= *pIter;
+ }
+
+ xIni->initialize(aInitArgs);
+ }
+ catch(const Exception&)
+ {
+ // Does this need to be shown to the user?
+ bSuccess = false;
+ try
+ {
+ ::comphelper::disposeComponent( xController );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+ }
+
+ // assign controller and frame
+ if ( bSuccess )
+ {
+ if ( xController.is() && rFrame.is() )
+ {
+ rFrame->setComponent( xController->getComponentWindow(), xController );
+ xController->attachFrame(rFrame);
+ }
+
+ if ( rListener.is() )
+ rListener->loadFinished( this );
+ }
+ else
+ if ( rListener.is() )
+ rListener->loadCancelled( this );
+}
+
+void DBContentLoader::cancel()
+{
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/browser/dbtreemodel.cxx b/dbaccess/source/ui/browser/dbtreemodel.cxx
new file mode 100644
index 000000000..88a9faeb0
--- /dev/null
+++ b/dbaccess/source/ui/browser/dbtreemodel.cxx
@@ -0,0 +1,33 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "dbtreemodel.hxx"
+
+namespace dbaui
+{
+ DBTreeListUserData::DBTreeListUserData()
+ :eType(SbaTableQueryBrowser::etQuery)
+ {
+ }
+ DBTreeListUserData::~DBTreeListUserData()
+ {
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/browser/dbtreemodel.hxx b/dbaccess/source/ui/browser/dbtreemodel.hxx
new file mode 100644
index 000000000..2ea11b900
--- /dev/null
+++ b/dbaccess/source/ui/browser/dbtreemodel.hxx
@@ -0,0 +1,57 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <unodatbr.hxx>
+#include <commontypes.hxx>
+
+// syntax of the tree userdata
+// datasource holds the connection
+// queries holds the nameaccess for the queries
+// query holds the query
+// tables holds the nameaccess for the tables
+// table holds the table
+
+#define CONTAINER_QUERIES sal_uLong( 0 )
+#define CONTAINER_TABLES sal_uLong( 1 )
+
+namespace com::sun::star::lang { class XMultiServiceFactory; }
+
+namespace dbaui
+{
+ struct DBTreeListUserData
+ {
+ /// if the entry denotes a table or query, this is the respective UNO object
+ css::uno::Reference< css::beans::XPropertySet >
+ xObjectProperties;
+ /// if the entry denotes an object container, this is the UNO interface for this container
+ css::uno::Reference< css::uno::XInterface >
+ xContainer;
+ /// if the entry denotes a data source, this is the connection for this data source (if already connection)
+ SharedConnection xConnection;
+ SbaTableQueryBrowser::EntryType eType;
+ OUString sAccessor;
+
+ DBTreeListUserData();
+ ~DBTreeListUserData();
+ };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/browser/dsEntriesNoExp.cxx b/dbaccess/source/ui/browser/dsEntriesNoExp.cxx
new file mode 100644
index 000000000..b31261df1
--- /dev/null
+++ b/dbaccess/source/ui/browser/dsEntriesNoExp.cxx
@@ -0,0 +1,154 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+
+#include <memory>
+
+#include <unodatbr.hxx>
+#include <browserids.hxx>
+#include <osl/diagnose.h>
+#include <dbtreelistbox.hxx>
+#include "dbtreemodel.hxx"
+
+using namespace ::com::sun::star::frame;
+using namespace ::dbtools;
+using namespace ::svx;
+
+namespace dbaui
+{
+SbaTableQueryBrowser::EntryType SbaTableQueryBrowser::getChildType(const weld::TreeIter& rEntry) const
+{
+ OSL_ENSURE(isContainer(rEntry), "SbaTableQueryBrowser::getChildType: invalid entry!");
+ switch (getEntryType(rEntry))
+ {
+ case etTableContainer:
+ return etTableOrView;
+ case etQueryContainer:
+ return etQuery;
+ default:
+ break;
+ }
+ return etUnknown;
+}
+
+OUString SbaTableQueryBrowser::GetEntryText(const weld::TreeIter& rEntry) const
+{
+ return m_pTreeView->GetWidget().get_text(rEntry);
+}
+
+SbaTableQueryBrowser::EntryType SbaTableQueryBrowser::getEntryType(const weld::TreeIter& rEntry) const
+{
+ const weld::TreeView& rTreeView = m_pTreeView->GetWidget();
+ DBTreeListUserData* pEntryData = weld::fromId<DBTreeListUserData*>(rTreeView.get_id(rEntry));
+ return pEntryData ? pEntryData->eType : etUnknown;
+}
+
+void SbaTableQueryBrowser::select(const weld::TreeIter* pEntry, bool bSelect)
+{
+ if (pEntry)
+ {
+ weld::TreeView& rTreeView = m_pTreeView->GetWidget();
+ rTreeView.set_text_emphasis(*pEntry, bSelect, 0);
+ }
+ else
+ {
+ OSL_FAIL("SbaTableQueryBrowser::select: invalid entry!");
+ }
+}
+
+void SbaTableQueryBrowser::selectPath(const weld::TreeIter* pEntry, bool bSelect)
+{
+ if (!pEntry)
+ return;
+ weld::TreeView& rTreeView = m_pTreeView->GetWidget();
+ std::unique_ptr<weld::TreeIter> xEntry(rTreeView.make_iterator(pEntry));
+ do
+ {
+ select(xEntry.get(), bSelect);
+ }
+ while (rTreeView.iter_parent(*xEntry));
+}
+
+bool SbaTableQueryBrowser::isSelected(const weld::TreeIter& rEntry) const
+{
+ weld::TreeView& rTreeView = m_pTreeView->GetWidget();
+ return rTreeView.get_text_emphasis(rEntry, 0);
+}
+
+void SbaTableQueryBrowser::SelectionChanged()
+{
+ if ( !m_bShowMenu )
+ {
+ InvalidateFeature(ID_BROWSER_INSERTCOLUMNS);
+ InvalidateFeature(ID_BROWSER_INSERTCONTENT);
+ InvalidateFeature(ID_BROWSER_FORMLETTER);
+ }
+ InvalidateFeature(ID_BROWSER_COPY);
+ InvalidateFeature(ID_BROWSER_CUT);
+}
+
+void SbaTableQueryBrowser::describeSupportedFeatures()
+{
+ SbaXDataBrowserController::describeSupportedFeatures();
+
+ implDescribeSupportedFeature( ".uno:Title", ID_BROWSER_TITLE );
+ if ( !m_bShowMenu )
+ {
+ implDescribeSupportedFeature( ".uno:DSBEditDB", ID_TREE_EDIT_DATABASE );
+ implDescribeSupportedFeature( ".uno:DSBCloseConnection", ID_TREE_CLOSE_CONN );
+ implDescribeSupportedFeature( ".uno:DSBAdministrate", ID_TREE_ADMINISTRATE );
+
+ implDescribeSupportedFeature( ".uno:DSBrowserExplorer", ID_BROWSER_EXPLORER, CommandGroup::VIEW );
+
+ implDescribeSupportedFeature( ".uno:DSBFormLetter", ID_BROWSER_FORMLETTER, CommandGroup::DOCUMENT );
+ implDescribeSupportedFeature( ".uno:DSBInsertColumns", ID_BROWSER_INSERTCOLUMNS, CommandGroup::INSERT );
+ implDescribeSupportedFeature( ".uno:DSBInsertContent", ID_BROWSER_INSERTCONTENT, CommandGroup::INSERT );
+ implDescribeSupportedFeature( ".uno:DSBDocumentDataSource", ID_BROWSER_DOCUMENT_DATASOURCE, CommandGroup::VIEW );
+
+ implDescribeSupportedFeature( ".uno:DataSourceBrowser/FormLetter", ID_BROWSER_FORMLETTER );
+ implDescribeSupportedFeature( ".uno:DataSourceBrowser/InsertColumns", ID_BROWSER_INSERTCOLUMNS );
+ implDescribeSupportedFeature( ".uno:DataSourceBrowser/InsertContent", ID_BROWSER_INSERTCONTENT );
+ implDescribeSupportedFeature( ".uno:DataSourceBrowser/DocumentDataSource", ID_BROWSER_DOCUMENT_DATASOURCE );
+ }
+
+ implDescribeSupportedFeature( ".uno:CloseWin", ID_BROWSER_CLOSE, CommandGroup::DOCUMENT );
+ implDescribeSupportedFeature( ".uno:DBRebuildData", ID_BROWSER_REFRESH_REBUILD, CommandGroup::DATA );
+}
+
+sal_Int32 SbaTableQueryBrowser::getDatabaseObjectType( EntryType _eType )
+{
+ switch ( _eType )
+ {
+ case etQuery:
+ case etQueryContainer:
+ return css::sdb::application::DatabaseObject::QUERY;
+ case etTableOrView:
+ case etTableContainer:
+ return css::sdb::application::DatabaseObject::TABLE;
+ default:
+ break;
+ }
+ OSL_FAIL( "SbaTableQueryBrowser::getDatabaseObjectType: folder types and 'Unknown' not allowed here!" );
+ return css::sdb::application::DatabaseObject::TABLE;
+}
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/browser/dsbrowserDnD.cxx b/dbaccess/source/ui/browser/dsbrowserDnD.cxx
new file mode 100644
index 000000000..961fd731a
--- /dev/null
+++ b/dbaccess/source/ui/browser/dsbrowserDnD.cxx
@@ -0,0 +1,258 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <dbexchange.hxx>
+#include <dbtreelistbox.hxx>
+#include "dbtreemodel.hxx"
+#include <UITools.hxx>
+#include <unodatbr.hxx>
+
+#include <com/sun/star/frame/XStorable.hpp>
+#include <com/sun/star/sdb/CommandType.hpp>
+#include <com/sun/star/sdbc/SQLException.hpp>
+
+#include <connectivity/dbexception.hxx>
+#include <connectivity/dbtools.hxx>
+#include <cppuhelper/exc_hlp.hxx>
+#include <svx/dataaccessdescriptor.hxx>
+#include <tools/diagnose_ex.h>
+#include <osl/diagnose.h>
+#include <vcl/svapp.hxx>
+
+#include <algorithm>
+
+namespace dbaui
+{
+
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::sdb;
+ using namespace ::com::sun::star::sdbc;
+ using namespace ::com::sun::star::sdbcx;
+ using namespace ::com::sun::star::beans;
+ using namespace ::com::sun::star::util;
+ using namespace ::com::sun::star::frame;
+ using namespace ::com::sun::star::container;
+ using namespace ::com::sun::star::lang;
+ using namespace ::com::sun::star::form;
+ using namespace ::com::sun::star::io;
+ using namespace ::com::sun::star::i18n;
+ using namespace ::com::sun::star::task;
+ using namespace ::com::sun::star::datatransfer;
+ using namespace ::dbtools;
+ using namespace ::svx;
+
+ bool SbaTableQueryBrowser::implCopyObject(ODataClipboard& rExchange, const weld::TreeIter& rApplyTo, sal_Int32 nCommandType)
+ {
+ try
+ {
+ OUString aName = GetEntryText(rApplyTo);
+ std::unique_ptr<weld::TreeIter> xRootEntry(m_pTreeView->GetRootLevelParent(&rApplyTo));
+ OUString aDSName = getDataSourceAccessor(*xRootEntry);
+
+ SharedConnection xConnection;
+ if ( CommandType::QUERY != nCommandType )
+ {
+ if (!ensureConnection(&rApplyTo, xConnection))
+ return false;
+ rExchange.Update(aDSName, nCommandType, aName, xConnection, getNumberFormatter(), getORB());
+ }
+ else
+ rExchange.Update(aDSName, nCommandType, aName, getNumberFormatter(), getORB());
+
+ // the ownership goes to ODataClipboards
+ return true;
+ }
+ catch(const SQLException& )
+ {
+ showError( SQLExceptionInfo( ::cppu::getCaughtException() ) );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ return false;
+ }
+
+ sal_Int8 SbaTableQueryBrowser::queryDrop( const AcceptDropEvent& _rEvt, const DataFlavorExVector& _rFlavors )
+ {
+ // check if we're a table or query container
+ weld::TreeView& rTreeView = m_pTreeView->GetWidget();
+ std::unique_ptr<weld::TreeIter> xHitEntry(rTreeView.make_iterator());
+ // get_dest_row_at_pos with false cause no drop if no entry was hit exactly
+ if (rTreeView.get_dest_row_at_pos(_rEvt.maPosPixel, xHitEntry.get(), false))
+ {
+ // it must be a container
+ EntryType eEntryType = getEntryType(*xHitEntry);
+ SharedConnection xConnection;
+ if ( eEntryType == etTableContainer && ensureConnection(xHitEntry.get(), xConnection ) && xConnection.is())
+ {
+ Reference<XChild> xChild(xConnection,UNO_QUERY);
+ Reference<XStorable> xStore;
+ if ( xChild.is() )
+ xStore.set( getDataSourceOrModel(xChild->getParent()), UNO_QUERY );
+ // check for the concrete type
+ if ( xStore.is() && !xStore->isReadonly() && std::any_of(_rFlavors.begin(),_rFlavors.end(),TAppSupportedSotFunctor(E_TABLE)) )
+ return DND_ACTION_COPY;
+ }
+ }
+
+ return DND_ACTION_NONE;
+ }
+ sal_Int8 SbaTableQueryBrowser::executeDrop( const ExecuteDropEvent& _rEvt )
+ {
+ weld::TreeView& rTreeView = m_pTreeView->GetWidget();
+ std::unique_ptr<weld::TreeIter> xHitEntry(rTreeView.make_iterator());
+ // get_dest_row_at_pos with false cause no drop if no entry was hit exactly
+ if (!rTreeView.get_dest_row_at_pos(_rEvt.maPosPixel, xHitEntry.get(), false))
+ return DND_ACTION_NONE;
+ EntryType eEntryType = getEntryType(*xHitEntry);
+ if (!isContainer(eEntryType))
+ {
+ OSL_FAIL("SbaTableQueryBrowser::executeDrop: what the hell did queryDrop do?");
+ // queryDrop should not have allowed us to reach this situation...
+ return DND_ACTION_NONE;
+ }
+ // a TransferableDataHelper for accessing the dropped data
+ TransferableDataHelper aDroppedData(_rEvt.maDropEvent.Transferable);
+
+ // reset the data of the previous async drop (if any)
+ if ( m_nAsyncDrop )
+ Application::RemoveUserEvent(m_nAsyncDrop);
+
+ m_nAsyncDrop = nullptr;
+ m_aAsyncDrop.aDroppedData.clear();
+ m_aAsyncDrop.nType = E_TABLE;
+ m_aAsyncDrop.nAction = _rEvt.mnAction;
+ m_aAsyncDrop.bError = false;
+ m_aAsyncDrop.bHtml = false;
+ m_aAsyncDrop.xDroppedAt.reset();
+ m_aAsyncDrop.aUrl.clear();
+
+ // loop through the available formats and see what we can do ...
+ // first we have to check if it is our own format, if not we have to copy the stream :-(
+ if ( ODataAccessObjectTransferable::canExtractObjectDescriptor(aDroppedData.GetDataFlavorExVector()) )
+ {
+ m_aAsyncDrop.aDroppedData = ODataAccessObjectTransferable::extractObjectDescriptor(aDroppedData);
+ m_aAsyncDrop.xDroppedAt = std::move(xHitEntry);
+
+ // asynchron because we some dialogs and we aren't allowed to show them while in D&D
+ m_nAsyncDrop = Application::PostUserEvent(LINK(this, SbaTableQueryBrowser, OnAsyncDrop));
+ return DND_ACTION_COPY;
+ }
+ else
+ {
+ SharedConnection xDestConnection;
+ if ( ensureConnection( xHitEntry.get(), xDestConnection )
+ && xDestConnection.is()
+ && m_aTableCopyHelper.copyTagTable( aDroppedData, m_aAsyncDrop, xDestConnection )
+ )
+ {
+ m_aAsyncDrop.xDroppedAt = std::move(xHitEntry);
+
+ // asynchron because we some dialogs and we aren't allowed to show them while in D&D
+ m_nAsyncDrop = Application::PostUserEvent(LINK(this, SbaTableQueryBrowser, OnAsyncDrop));
+ return DND_ACTION_COPY;
+ }
+ }
+
+ return DND_ACTION_NONE;
+ }
+
+ bool SbaTableQueryBrowser::requestDrag(const weld::TreeIter& rEntry)
+ {
+ // it must be a query/table
+ EntryType eEntryType = getEntryType(rEntry);
+ if (!isObject(eEntryType))
+ return false;
+
+ ODataClipboard& rExchange = static_cast<ODataClipboard&>(m_pTreeView->GetDataTransfer());
+ return implCopyObject(rExchange, rEntry, (etTableOrView == eEntryType) ? CommandType::TABLE : CommandType::QUERY);
+ }
+
+ IMPL_LINK_NOARG(SbaTableQueryBrowser, OnCopyEntry, LinkParamNone*, void)
+ {
+ weld::TreeView& rTreeView = m_pTreeView->GetWidget();
+ std::unique_ptr<weld::TreeIter> xSelected = rTreeView.make_iterator();
+ if (rTreeView.get_selected(xSelected.get()) && isEntryCopyAllowed(*xSelected))
+ copyEntry(*xSelected);
+ }
+
+ bool SbaTableQueryBrowser::isEntryCopyAllowed(const weld::TreeIter& rEntry) const
+ {
+ EntryType eType = getEntryType(rEntry);
+ return ( eType == etTableOrView || eType == etQuery );
+ }
+
+ void SbaTableQueryBrowser::copyEntry(const weld::TreeIter& rEntry)
+ {
+ EntryType eType = getEntryType(rEntry);
+ rtl::Reference<ODataClipboard> xTransfer(new ODataClipboard);
+ if (implCopyObject(*xTransfer, rEntry, eType == etQuery ? CommandType::QUERY : CommandType::TABLE))
+ xTransfer->CopyToClipboard(getView());
+ }
+
+ IMPL_LINK_NOARG( SbaTableQueryBrowser, OnAsyncDrop, void*, void )
+ {
+ m_nAsyncDrop = nullptr;
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( getMutex() );
+
+ if ( m_aAsyncDrop.nType == E_TABLE )
+ {
+ SharedConnection xDestConnection;
+ if ( ensureConnection(m_aAsyncDrop.xDroppedAt.get(), xDestConnection) && xDestConnection.is())
+ {
+ std::unique_ptr<weld::TreeIter> xDataSourceEntry =
+ m_pTreeView->GetRootLevelParent(m_aAsyncDrop.xDroppedAt.get());
+ m_aTableCopyHelper.asyncCopyTagTable(m_aAsyncDrop, getDataSourceAccessor(*xDataSourceEntry), xDestConnection);
+ }
+ }
+
+ m_aAsyncDrop.aDroppedData.clear();
+ }
+
+ void SbaTableQueryBrowser::clearTreeModel()
+ {
+ weld::TreeView& rTreeView = m_pTreeView->GetWidget();
+ rTreeView.all_foreach([this, &rTreeView](weld::TreeIter& rEntryLoop){
+ // clear the user data of the tree model
+ DBTreeListUserData* pData = weld::fromId<DBTreeListUserData*>(rTreeView.get_id(rEntryLoop));
+ if (pData)
+ {
+ rTreeView.set_id(rEntryLoop, OUString());
+ Reference<XContainer> xContainer(pData->xContainer, UNO_QUERY);
+ if (xContainer.is())
+ xContainer->removeContainerListener(this);
+
+ if (pData->xConnection.is())
+ {
+ // connections are to be stored *only* at the data source entries
+ impl_releaseConnection(pData->xConnection);
+ }
+
+ delete pData;
+ }
+ return false;
+ });
+
+ m_xCurrentlyDisplayed.reset();
+ }
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/browser/exsrcbrw.cxx b/dbaccess/source/ui/browser/exsrcbrw.cxx
new file mode 100644
index 000000000..1dd47e73a
--- /dev/null
+++ b/dbaccess/source/ui/browser/exsrcbrw.cxx
@@ -0,0 +1,413 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <exsrcbrw.hxx>
+#include <com/sun/star/util/XURLTransformer.hpp>
+#include <com/sun/star/form/XGridColumnFactory.hpp>
+#include <com/sun/star/form/XLoadable.hpp>
+#include <com/sun/star/frame/FrameSearchFlag.hpp>
+#include <formadapter.hxx>
+#include <strings.hxx>
+#include <o3tl/any.hxx>
+#include <tools/diagnose_ex.h>
+#include <sal/log.hxx>
+
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::sdb;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::sdbcx;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::form;
+using namespace ::com::sun::star::frame;
+using namespace dbaui;
+
+// SbaExternalSourceBrowser
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+org_openoffice_comp_dbu_OFormGridView_get_implementation(
+ css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const& )
+{
+ return cppu::acquire(new SbaExternalSourceBrowser(context));
+}
+
+Any SAL_CALL SbaExternalSourceBrowser::queryInterface(const Type& _rType)
+{
+ Any aRet = SbaXDataBrowserController::queryInterface(_rType);
+ if(!aRet.hasValue())
+ aRet = ::cppu::queryInterface(_rType,
+ static_cast<css::util::XModifyBroadcaster*>(this),
+ static_cast<css::form::XLoadListener*>(this));
+
+ return aRet;
+}
+
+SbaExternalSourceBrowser::SbaExternalSourceBrowser(const Reference< css::uno::XComponentContext >& _rM)
+ :SbaXDataBrowserController(_rM)
+ ,m_aModifyListeners(getMutex())
+ ,m_bInQueryDispatch( false )
+{
+
+}
+
+SbaExternalSourceBrowser::~SbaExternalSourceBrowser()
+{
+}
+
+css::uno::Sequence<OUString> SAL_CALL SbaExternalSourceBrowser::getSupportedServiceNames()
+{
+ return { "com.sun.star.sdb.FormGridView" };
+}
+
+OUString SAL_CALL SbaExternalSourceBrowser::getImplementationName()
+{
+ return "org.openoffice.comp.dbu.OFormGridView";
+}
+
+Reference< XRowSet > SbaExternalSourceBrowser::CreateForm()
+{
+ m_pDataSourceImpl = new SbaXFormAdapter();
+ return m_pDataSourceImpl;
+}
+
+bool SbaExternalSourceBrowser::InitializeForm(const Reference< XPropertySet > & /*i_formProperties*/)
+{
+ return true;
+}
+
+bool SbaExternalSourceBrowser::LoadForm()
+{
+ // as we don't have a main form (yet), we have nothing to do
+ // we don't call FormLoaded, because this expects a working data source
+ return true;
+}
+
+void SbaExternalSourceBrowser::modified(const css::lang::EventObject& aEvent)
+{
+ SbaXDataBrowserController::modified(aEvent);
+
+ // multiplex this event to all my listeners
+ css::lang::EventObject aEvt(*this);
+ m_aModifyListeners.notifyEach( &css::util::XModifyListener::modified, aEvt );
+}
+
+void SAL_CALL SbaExternalSourceBrowser::dispatch(const css::util::URL& aURL, const Sequence< css::beans::PropertyValue>& aArgs)
+{
+ if ( aURL.Complete == ".uno:FormSlots/AddGridColumn" )
+ {
+ // search the argument describing the column to create
+ OUString sControlType;
+ sal_Int32 nControlPos = -1;
+ Sequence< css::beans::PropertyValue> aControlProps;
+ for ( const css::beans::PropertyValue& rArgument : aArgs )
+ {
+ if ( rArgument.Name == "ColumnType" )
+ {
+ auto s = o3tl::tryAccess<OUString>(rArgument.Value);
+ OSL_ENSURE(s, "invalid type for argument \"ColumnType\" !");
+ if (s)
+ sControlType = *s;
+ }
+ else if ( rArgument.Name == "ColumnPosition" )
+ {
+ auto n = o3tl::tryAccess<sal_Int16>(rArgument.Value);
+ OSL_ENSURE(n, "invalid type for argument \"ColumnPosition\" !");
+ if (n)
+ nControlPos = *n;
+ }
+ else if ( rArgument.Name == "ColumnProperties" )
+ {
+ auto s = o3tl::tryAccess<Sequence<css::beans::PropertyValue>>(
+ rArgument.Value);
+ OSL_ENSURE(s, "invalid type for argument \"ColumnProperties\" !");
+ if (s)
+ aControlProps = *s;
+ }
+ else
+ SAL_WARN("dbaccess.ui", "SbaExternalSourceBrowser::dispatch(AddGridColumn) : unknown argument (" << rArgument.Name << ") !");
+ }
+ if (sControlType.isEmpty())
+ {
+ SAL_WARN("dbaccess.ui", "SbaExternalSourceBrowser::dispatch(AddGridColumn) : missing argument (ColumnType) !");
+ sControlType = "TextField";
+ }
+ OSL_ENSURE(aControlProps.hasElements(), "SbaExternalSourceBrowser::dispatch(AddGridColumn) : missing argument (ColumnProperties) !");
+
+ // create the col
+ Reference< css::form::XGridColumnFactory > xColFactory(getControlModel(), UNO_QUERY);
+ Reference< css::beans::XPropertySet > xNewCol = xColFactory->createColumn(sControlType);
+ Reference< XPropertySetInfo > xNewColProperties;
+ if (xNewCol.is())
+ xNewColProperties = xNewCol->getPropertySetInfo();
+ // set its properties
+ if (xNewColProperties.is())
+ {
+ for (const css::beans::PropertyValue& rControlProp : std::as_const(aControlProps))
+ {
+ try
+ {
+ if (xNewColProperties->hasPropertyByName(rControlProp.Name))
+ xNewCol->setPropertyValue(rControlProp.Name, rControlProp.Value);
+ }
+ catch (const Exception&)
+ {
+ SAL_WARN("dbaccess.ui", "SbaExternalSourceBrowser::dispatch : could not set a column property (" << rControlProp.Name << ")!");
+ }
+ }
+ }
+
+ // correct the position
+ Reference< css::container::XIndexContainer > xColContainer(getControlModel(), UNO_QUERY);
+
+ if (nControlPos > xColContainer->getCount())
+ nControlPos = xColContainer->getCount();
+ if (nControlPos < 0)
+ nControlPos = 0;
+
+ // append the column
+ xColContainer->insertByIndex(nControlPos, Any(xNewCol));
+ }
+ else if ( aURL.Complete == ".uno:FormSlots/ClearView" )
+ {
+ ClearView();
+ }
+ else if ( aURL.Complete == ".uno:FormSlots/AttachToForm" )
+ {
+ if (!m_pDataSourceImpl)
+ return;
+
+ Reference< XRowSet > xMasterForm;
+ // search the arguments for the master form
+ for (const css::beans::PropertyValue& rArgument : aArgs)
+ {
+ if ( (rArgument.Name == "MasterForm") && (rArgument.Value.getValueTypeClass() == TypeClass_INTERFACE) )
+ {
+ xMasterForm.set(rArgument.Value, UNO_QUERY);
+ break;
+ }
+ }
+ if (!xMasterForm.is())
+ {
+ SAL_WARN("dbaccess.ui", "SbaExternalSourceBrowser::dispatch(FormSlots/AttachToForm) : please specify a form to attach to as argument !");
+ return;
+ }
+
+ Attach(xMasterForm);
+ }
+ else
+ SbaXDataBrowserController::dispatch(aURL, aArgs);
+}
+
+Reference< css::frame::XDispatch > SAL_CALL SbaExternalSourceBrowser::queryDispatch(const css::util::URL& aURL, const OUString& aTargetFrameName, sal_Int32 nSearchFlags)
+{
+ Reference< css::frame::XDispatch > xReturn;
+ if (m_bInQueryDispatch)
+ return xReturn;
+
+ m_bInQueryDispatch = true;
+
+ if ( ( aURL.Complete == ".uno:FormSlots/AttachToForm" )
+ // attach a new external form
+ || ( aURL.Complete == ".uno:FormSlots/AddGridColumn" )
+ // add a column to the grid
+ || ( aURL.Complete == ".uno:FormSlots/ClearView" )
+ // clear the grid
+ )
+ xReturn = static_cast<css::frame::XDispatch*>(this);
+
+ if ( !xReturn.is()
+ && ( (aURL.Complete == ".uno:FormSlots/moveToFirst" ) || (aURL.Complete == ".uno:FormSlots/moveToPrev" )
+ || (aURL.Complete == ".uno:FormSlots/moveToNext" ) || (aURL.Complete == ".uno:FormSlots/moveToLast" )
+ || (aURL.Complete == ".uno:FormSlots/moveToNew" ) || (aURL.Complete == ".uno:FormSlots/undoRecord" )
+ )
+ )
+ {
+ OSL_ENSURE(aURL.Mark.isEmpty(), "SbaExternalSourceBrowser::queryDispatch : the css::util::URL shouldn't have a mark !");
+ css::util::URL aNewUrl = aURL;
+
+ // split the css::util::URL
+ OSL_ENSURE( m_xUrlTransformer.is(), "SbaExternalSourceBrowser::queryDispatch : could not create a URLTransformer !" );
+ if ( m_xUrlTransformer.is() )
+ m_xUrlTransformer->parseStrict( aNewUrl );
+
+ // set a new mark
+ aNewUrl.Mark = "DB/FormGridView";
+ // this controller is instantiated when somebody dispatches the ".component:DB/FormGridView" in any
+ // frame, so we use "FormGridView" as mark that a dispatch request came from this view
+
+ if (m_xUrlTransformer.is())
+ m_xUrlTransformer->assemble(aNewUrl);
+
+ Reference< XDispatchProvider > xFrameDispatcher( getFrame(), UNO_QUERY );
+ if (xFrameDispatcher.is())
+ xReturn = xFrameDispatcher->queryDispatch(aNewUrl, aTargetFrameName, FrameSearchFlag::PARENT);
+
+ }
+
+ if (!xReturn.is())
+ xReturn = SbaXDataBrowserController::queryDispatch(aURL, aTargetFrameName, nSearchFlags);
+
+ m_bInQueryDispatch = false;
+ return xReturn;
+}
+
+void SAL_CALL SbaExternalSourceBrowser::disposing()
+{
+ // say our modify listeners goodbye
+ css::lang::EventObject aEvt;
+ aEvt.Source = static_cast<XWeak*>(this);
+ m_aModifyListeners.disposeAndClear(aEvt);
+
+ stopListening();
+
+ SbaXDataBrowserController::disposing();
+}
+
+void SAL_CALL SbaExternalSourceBrowser::addModifyListener(const Reference< css::util::XModifyListener > & aListener)
+{
+ m_aModifyListeners.addInterface(aListener);
+}
+
+void SAL_CALL SbaExternalSourceBrowser::removeModifyListener(const Reference< css::util::XModifyListener > & aListener)
+{
+ m_aModifyListeners.removeInterface(aListener);
+}
+
+void SAL_CALL SbaExternalSourceBrowser::unloading(const css::lang::EventObject& aEvent)
+{
+ if (m_pDataSourceImpl && (m_pDataSourceImpl->getAttachedForm() == aEvent.Source))
+ {
+ ClearView();
+ }
+
+ SbaXDataBrowserController::unloading(aEvent);
+}
+
+void SbaExternalSourceBrowser::Attach(const Reference< XRowSet > & xMaster)
+{
+ Any aOldPos;
+ bool bWasInsertRow = false;
+ bool bBeforeFirst = true;
+ bool bAfterLast = true;
+ Reference< XRowLocate > xCursor(xMaster, UNO_QUERY);
+ Reference< XPropertySet > xMasterProps(xMaster, UNO_QUERY);
+
+ try
+ {
+ // switch the control to design mode
+ if (getBrowserView() && getBrowserView()->getGridControl().is())
+ getBrowserView()->getGridControl()->setDesignMode(true);
+
+ // the grid will move the form's cursor to the first record, but we want the form to remain unchanged
+ // restore the old position
+ if (xCursor.is() && xMaster.is())
+ {
+ bBeforeFirst = xMaster->isBeforeFirst();
+ bAfterLast = xMaster->isAfterLast();
+ if(!bBeforeFirst && !bAfterLast)
+ aOldPos = xCursor->getBookmark();
+ }
+
+ if (xMasterProps.is())
+ xMasterProps->getPropertyValue(PROPERTY_ISNEW) >>= bWasInsertRow;
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+
+ onStartLoading( Reference< XLoadable >( xMaster, UNO_QUERY ) );
+
+ stopListening();
+ m_pDataSourceImpl->AttachForm(xMaster);
+ startListening();
+
+ if (!xMaster.is())
+ return;
+
+ // at this point we have to reset the formatter for the new form
+ initFormatter();
+ // assume that the master form is already loaded
+#if OSL_DEBUG_LEVEL > 0
+ {
+ Reference< XLoadable > xLoadable( xMaster, UNO_QUERY );
+ OSL_ENSURE( xLoadable.is() && xLoadable->isLoaded(), "SbaExternalSourceBrowser::Attach: master is not loaded!" );
+ }
+#endif
+
+ LoadFinished(true);
+
+ Reference< XResultSetUpdate > xUpdate(xMaster, UNO_QUERY);
+ try
+ {
+ if (bWasInsertRow && xUpdate.is())
+ xUpdate->moveToInsertRow();
+ else if (xCursor.is() && aOldPos.hasValue())
+ xCursor->moveToBookmark(aOldPos);
+ else if(bBeforeFirst && xMaster.is())
+ xMaster->beforeFirst();
+ else if(bAfterLast && xMaster.is())
+ xMaster->afterLast();
+ }
+ catch(Exception&)
+ {
+ SAL_WARN("dbaccess.ui", "SbaExternalSourceBrowser::Attach : couldn't restore the cursor position !");
+ }
+}
+
+void SbaExternalSourceBrowser::ClearView()
+{
+ // set a new (empty) datasource
+ Attach(Reference< XRowSet > ());
+
+ // clear all cols in the grid
+ Reference< css::container::XIndexContainer > xColContainer(getControlModel(), UNO_QUERY);
+ while (xColContainer->getCount() > 0)
+ xColContainer->removeByIndex(0);
+}
+
+void SAL_CALL SbaExternalSourceBrowser::disposing(const css::lang::EventObject& Source)
+{
+ if (m_pDataSourceImpl && (m_pDataSourceImpl->getAttachedForm() == Source.Source))
+ {
+ ClearView();
+ }
+
+ SbaXDataBrowserController::disposing(Source);
+}
+
+void SbaExternalSourceBrowser::startListening()
+{
+ if (m_pDataSourceImpl && m_pDataSourceImpl->getAttachedForm().is())
+ {
+ Reference< css::form::XLoadable > xLoadable(m_pDataSourceImpl->getAttachedForm(), UNO_QUERY);
+ xLoadable->addLoadListener(static_cast<css::form::XLoadListener*>(this));
+ }
+}
+
+void SbaExternalSourceBrowser::stopListening()
+{
+ if (m_pDataSourceImpl && m_pDataSourceImpl->getAttachedForm().is())
+ {
+ Reference< css::form::XLoadable > xLoadable(m_pDataSourceImpl->getAttachedForm(), UNO_QUERY);
+ xLoadable->removeLoadListener(static_cast<css::form::XLoadListener*>(this));
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/browser/formadapter.cxx b/dbaccess/source/ui/browser/formadapter.cxx
new file mode 100644
index 000000000..9f439acd2
--- /dev/null
+++ b/dbaccess/source/ui/browser/formadapter.cxx
@@ -0,0 +1,1877 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <formadapter.hxx>
+#include <o3tl/safeint.hxx>
+#include <osl/diagnose.h>
+#include <comphelper/types.hxx>
+#include <comphelper/enumhelper.hxx>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <strings.hxx>
+#include <connectivity/dbexception.hxx>
+#include <comphelper/sequence.hxx>
+
+using namespace dbaui;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::sdb;
+using namespace ::com::sun::star::sdbcx;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::container;
+
+// SbaXFormAdapter
+
+SbaXFormAdapter::SbaXFormAdapter()
+ :m_aLoadListeners(*this, m_aMutex)
+ ,m_aRowSetListeners(*this, m_aMutex)
+ ,m_aRowSetApproveListeners(*this, m_aMutex)
+ ,m_aErrorListeners(*this, m_aMutex)
+ ,m_aParameterListeners(*this, m_aMutex)
+ ,m_aSubmitListeners(*this, m_aMutex)
+ ,m_aResetListeners(*this, m_aMutex)
+ ,m_aPropertyChangeListeners(*this, m_aMutex)
+ ,m_aVetoablePropertyChangeListeners(*this, m_aMutex)
+ ,m_aPropertiesChangeListeners(*this, m_aMutex)
+ ,m_aDisposeListeners(m_aMutex)
+ ,m_aContainerListeners(m_aMutex)
+ ,m_nNamePropHandle(-1)
+{
+
+}
+
+SbaXFormAdapter::~SbaXFormAdapter()
+{
+
+}
+
+Sequence< Type > SAL_CALL SbaXFormAdapter::getTypes( )
+{
+ return ::comphelper::concatSequences(
+ SbaXFormAdapter_BASE1::getTypes(),
+ SbaXFormAdapter_BASE2::getTypes(),
+ SbaXFormAdapter_BASE3::getTypes()
+ );
+}
+
+Sequence< sal_Int8 > SAL_CALL SbaXFormAdapter::getImplementationId( )
+{
+ return css::uno::Sequence<sal_Int8>();
+}
+
+Any SAL_CALL SbaXFormAdapter::queryInterface(const Type& _rType)
+{
+ Any aReturn = SbaXFormAdapter_BASE1::queryInterface( _rType );
+
+ if (!aReturn.hasValue())
+ aReturn = SbaXFormAdapter_BASE2::queryInterface( _rType );
+
+ if (!aReturn.hasValue())
+ aReturn = SbaXFormAdapter_BASE3::queryInterface( _rType );
+
+ return aReturn;
+}
+
+void SbaXFormAdapter::StopListening()
+{
+ // log off all our multiplexers
+ if (m_aLoadListeners.getLength())
+ {
+ css::uno::Reference< css::form::XLoadable > xBroadcaster(m_xMainForm, css::uno::UNO_QUERY);
+ if (xBroadcaster.is())
+ xBroadcaster->removeLoadListener(&m_aLoadListeners);
+ }
+ if (m_aRowSetListeners.getLength())
+ {
+ css::uno::Reference< css::sdbc::XRowSet > xBroadcaster(m_xMainForm, css::uno::UNO_QUERY);
+ if (xBroadcaster.is())
+ xBroadcaster->removeRowSetListener(&m_aRowSetListeners);
+ }
+ if (m_aRowSetApproveListeners.getLength())
+ {
+ css::uno::Reference< css::sdb::XRowSetApproveBroadcaster > xBroadcaster(m_xMainForm, css::uno::UNO_QUERY);
+ if (xBroadcaster.is())
+ xBroadcaster->removeRowSetApproveListener(&m_aRowSetApproveListeners);
+ }
+ if (m_aErrorListeners.getLength())
+ {
+ css::uno::Reference< css::sdb::XSQLErrorBroadcaster > xBroadcaster(m_xMainForm, css::uno::UNO_QUERY);
+ if (xBroadcaster.is())
+ xBroadcaster->removeSQLErrorListener(&m_aErrorListeners);
+ }
+ if (m_aSubmitListeners.getLength())
+ {
+ css::uno::Reference< css::form::XSubmit > xBroadcaster(m_xMainForm, css::uno::UNO_QUERY);
+ if (xBroadcaster.is())
+ xBroadcaster->removeSubmitListener(&m_aSubmitListeners);
+ }
+ if (m_aResetListeners.getLength())
+ {
+ css::uno::Reference< css::form::XReset > xBroadcaster(m_xMainForm, css::uno::UNO_QUERY);
+ if (xBroadcaster.is())
+ xBroadcaster->removeResetListener(&m_aResetListeners);
+ }
+ if (m_aParameterListeners.getLength())
+ {
+ Reference< css::form::XDatabaseParameterBroadcaster > xBroadcaster(m_xMainForm, UNO_QUERY);
+ if (xBroadcaster.is())
+ xBroadcaster->removeParameterListener(&m_aParameterListeners);
+ }
+
+ if (m_aPropertyChangeListeners.getOverallLen())
+ {
+ css::uno::Reference< css::beans::XPropertySet > xBroadcaster(m_xMainForm, css::uno::UNO_QUERY);
+ if (xBroadcaster.is())
+ xBroadcaster->removePropertyChangeListener(OUString(), &m_aPropertyChangeListeners);
+ }
+
+ if (m_aVetoablePropertyChangeListeners.getOverallLen())
+ {
+ css::uno::Reference< css::beans::XPropertySet > xBroadcaster(m_xMainForm, css::uno::UNO_QUERY);
+ if (xBroadcaster.is())
+ xBroadcaster->removeVetoableChangeListener(OUString(), &m_aVetoablePropertyChangeListeners);
+ }
+
+ if (m_aPropertiesChangeListeners.getLength())
+ {
+ Reference< css::beans::XMultiPropertySet > xBroadcaster(m_xMainForm, UNO_QUERY);
+ if (xBroadcaster.is())
+ xBroadcaster->removePropertiesChangeListener(&m_aPropertiesChangeListeners);
+ }
+
+ // log off ourself
+ Reference< css::lang::XComponent > xComp(m_xMainForm, UNO_QUERY);
+ if (xComp.is())
+ xComp->removeEventListener(static_cast<css::lang::XEventListener*>(static_cast<css::beans::XPropertyChangeListener*>(this)));
+}
+
+void SbaXFormAdapter::StartListening()
+{
+ // log off all our multiplexers
+ if (m_aLoadListeners.getLength())
+ {
+ css::uno::Reference< css::form::XLoadable > xBroadcaster(m_xMainForm, css::uno::UNO_QUERY);
+ if (xBroadcaster.is())
+ xBroadcaster->addLoadListener(&m_aLoadListeners);
+ }
+ if (m_aRowSetListeners.getLength())
+ {
+ css::uno::Reference< css::sdbc::XRowSet > xBroadcaster(m_xMainForm, css::uno::UNO_QUERY);
+ if (xBroadcaster.is())
+ xBroadcaster->addRowSetListener(&m_aRowSetListeners);
+ }
+ if (m_aRowSetApproveListeners.getLength())
+ {
+ css::uno::Reference< css::sdb::XRowSetApproveBroadcaster > xBroadcaster(m_xMainForm, css::uno::UNO_QUERY);
+ if (xBroadcaster.is())
+ xBroadcaster->addRowSetApproveListener(&m_aRowSetApproveListeners);
+ }
+ if (m_aErrorListeners.getLength())
+ {
+ css::uno::Reference< css::sdb::XSQLErrorBroadcaster > xBroadcaster(m_xMainForm, css::uno::UNO_QUERY);
+ if (xBroadcaster.is())
+ xBroadcaster->addSQLErrorListener(&m_aErrorListeners);
+ }
+ if (m_aSubmitListeners.getLength())
+ {
+ css::uno::Reference< css::form::XSubmit > xBroadcaster(m_xMainForm, css::uno::UNO_QUERY);
+ if (xBroadcaster.is())
+ xBroadcaster->addSubmitListener(&m_aSubmitListeners);
+ }
+ if (m_aResetListeners.getLength())
+ {
+ css::uno::Reference< css::form::XReset > xBroadcaster(m_xMainForm, css::uno::UNO_QUERY);
+ if (xBroadcaster.is())
+ xBroadcaster->addResetListener(&m_aResetListeners);
+ }
+
+ if (m_aParameterListeners.getLength())
+ {
+ Reference< css::form::XDatabaseParameterBroadcaster > xBroadcaster(m_xMainForm, UNO_QUERY);
+ if (xBroadcaster.is())
+ xBroadcaster->addParameterListener(&m_aParameterListeners);
+ }
+
+ if (m_aPropertyChangeListeners.getOverallLen())
+ {
+ css::uno::Reference< css::beans::XPropertySet > xBroadcaster(m_xMainForm, css::uno::UNO_QUERY);
+ if (xBroadcaster.is())
+ xBroadcaster->addPropertyChangeListener(OUString(), &m_aPropertyChangeListeners);
+ }
+
+ if (m_aVetoablePropertyChangeListeners.getOverallLen())
+ {
+ css::uno::Reference< css::beans::XPropertySet > xBroadcaster(m_xMainForm, css::uno::UNO_QUERY);
+ if (xBroadcaster.is())
+ xBroadcaster->addVetoableChangeListener(OUString(), &m_aVetoablePropertyChangeListeners);
+ }
+
+ if (m_aPropertiesChangeListeners.getLength())
+ {
+ Reference< css::beans::XMultiPropertySet > xBroadcaster(m_xMainForm, UNO_QUERY);
+ if (xBroadcaster.is())
+ xBroadcaster->addPropertiesChangeListener(css::uno::Sequence<OUString>{""}, &m_aPropertiesChangeListeners);
+ }
+
+ // log off ourself
+ Reference< css::lang::XComponent > xComp(m_xMainForm, UNO_QUERY);
+ if (xComp.is())
+ xComp->addEventListener(static_cast<css::lang::XEventListener*>(static_cast<css::beans::XPropertyChangeListener*>(this)));
+}
+
+void SbaXFormAdapter::AttachForm(const Reference< css::sdbc::XRowSet >& xNewMaster)
+{
+ if (xNewMaster == m_xMainForm)
+ return;
+
+ OSL_ENSURE(xNewMaster.get() != static_cast< css::sdbc::XRowSet* >(this), "SbaXFormAdapter::AttachForm : invalid argument !");
+
+ if (m_xMainForm.is())
+ {
+ StopListening();
+
+ // if our old master is loaded we have to send an 'unloaded' event
+ Reference< css::form::XLoadable > xLoadable(m_xMainForm, UNO_QUERY);
+ if (xLoadable->isLoaded())
+ {
+ css::lang::EventObject aEvt(*this);
+ m_aLoadListeners.notifyEach( &css::form::XLoadListener::unloaded, aEvt );
+ }
+ }
+
+ m_xMainForm = xNewMaster;
+
+ if (!m_xMainForm.is())
+ return;
+
+ StartListening();
+
+ // if our new master is loaded we have to send an 'loaded' event
+ Reference< css::form::XLoadable > xLoadable(m_xMainForm, UNO_QUERY);
+ if (xLoadable->isLoaded())
+ {
+ css::lang::EventObject aEvt(*this);
+ m_aLoadListeners.notifyEach( &css::form::XLoadListener::loaded, aEvt );
+ }
+
+ // TODO : perhaps _all_ of our listeners should be notified about our new state
+ // (nearly every aspect of us may have changed with new master form)
+}
+
+// css::sdbc::XCloseable
+void SAL_CALL SbaXFormAdapter::close()
+{
+ Reference< css::sdbc::XCloseable > xIface(m_xMainForm, UNO_QUERY);
+ if (xIface.is())
+ xIface->close();
+}
+
+// css::sdbc::XResultSetMetaDataSupplier
+Reference< css::sdbc::XResultSetMetaData > SAL_CALL SbaXFormAdapter::getMetaData()
+{
+ Reference< css::sdbc::XResultSetMetaDataSupplier > xIface(m_xMainForm, UNO_QUERY);
+ if (xIface.is())
+ return xIface->getMetaData();
+ return Reference< css::sdbc::XResultSetMetaData > ();
+}
+
+// css::sdbc::XColumnLocate
+sal_Int32 SAL_CALL SbaXFormAdapter::findColumn(const OUString& columnName)
+{
+ Reference< css::sdbc::XColumnLocate > xIface(m_xMainForm, UNO_QUERY);
+ if (xIface.is())
+ return xIface->findColumn(columnName);
+
+ ::dbtools::throwInvalidColumnException( columnName, *this );
+ assert(false);
+ return 0; // Never reached
+}
+
+// css::sdbcx::XColumnsSupplier
+Reference< css::container::XNameAccess > SAL_CALL SbaXFormAdapter::getColumns()
+{
+ Reference< css::sdbcx::XColumnsSupplier > xIface(m_xMainForm, UNO_QUERY);
+ if (xIface.is())
+ return xIface->getColumns();
+ return Reference< css::container::XNameAccess > ();
+}
+
+// css::sdbc::XRow
+sal_Bool SAL_CALL SbaXFormAdapter::wasNull()
+{
+ Reference< css::sdbc::XRow > xIface(m_xMainForm, UNO_QUERY);
+ if (xIface.is())
+ return xIface->wasNull();
+ return true;
+}
+
+OUString SAL_CALL SbaXFormAdapter::getString(sal_Int32 columnIndex)
+{
+ Reference< css::sdbc::XRow > xIface(m_xMainForm, UNO_QUERY);
+ if (xIface.is())
+ return xIface->getString(columnIndex);
+ return OUString();
+}
+
+sal_Bool SAL_CALL SbaXFormAdapter::getBoolean(sal_Int32 columnIndex)
+{
+ Reference< css::sdbc::XRow > xIface(m_xMainForm, UNO_QUERY);
+ if (xIface.is())
+ return xIface->getBoolean(columnIndex);
+ return false;
+}
+
+sal_Int8 SAL_CALL SbaXFormAdapter::getByte(sal_Int32 columnIndex)
+
+{
+ Reference< css::sdbc::XRow > xIface(m_xMainForm, UNO_QUERY);
+ if (xIface.is())
+ return xIface->getByte(columnIndex);
+ return 0;
+}
+
+sal_Int16 SAL_CALL SbaXFormAdapter::getShort(sal_Int32 columnIndex)
+{
+ Reference< css::sdbc::XRow > xIface(m_xMainForm, UNO_QUERY);
+ if (xIface.is())
+ return xIface->getShort(columnIndex);
+ return 0;
+}
+
+sal_Int32 SAL_CALL SbaXFormAdapter::getInt(sal_Int32 columnIndex)
+{
+ Reference< css::sdbc::XRow > xIface(m_xMainForm, UNO_QUERY);
+ if (xIface.is())
+ return xIface->getInt(columnIndex);
+ return 0;
+}
+
+sal_Int64 SAL_CALL SbaXFormAdapter::getLong(sal_Int32 columnIndex)
+{
+ Reference< css::sdbc::XRow > xIface(m_xMainForm, UNO_QUERY);
+ if (xIface.is())
+ return xIface->getLong(columnIndex);
+ return 0;
+}
+
+float SAL_CALL SbaXFormAdapter::getFloat(sal_Int32 columnIndex)
+{
+ Reference< css::sdbc::XRow > xIface(m_xMainForm, UNO_QUERY);
+ if (xIface.is())
+ return xIface->getFloat(columnIndex);
+ return 0.0;
+}
+
+double SAL_CALL SbaXFormAdapter::getDouble(sal_Int32 columnIndex)
+{
+ Reference< css::sdbc::XRow > xIface(m_xMainForm, UNO_QUERY);
+ if (xIface.is())
+ return xIface->getDouble(columnIndex);
+ return 0.0;
+}
+
+Sequence< sal_Int8 > SAL_CALL SbaXFormAdapter::getBytes(sal_Int32 columnIndex)
+{
+ Reference< css::sdbc::XRow > xIface(m_xMainForm, UNO_QUERY);
+ if (xIface.is())
+ return xIface->getBytes(columnIndex);
+ return Sequence <sal_Int8> ();
+}
+
+css::util::Date SAL_CALL SbaXFormAdapter::getDate(sal_Int32 columnIndex)
+{
+ Reference< css::sdbc::XRow > xIface(m_xMainForm, UNO_QUERY);
+ if (xIface.is())
+ return xIface->getDate(columnIndex);
+ return css::util::Date();
+}
+
+css::util::Time SAL_CALL SbaXFormAdapter::getTime(sal_Int32 columnIndex)
+{
+ Reference< css::sdbc::XRow > xIface(m_xMainForm, UNO_QUERY);
+ if (xIface.is())
+ return xIface->getTime(columnIndex);
+ return css::util::Time();
+}
+
+css::util::DateTime SAL_CALL SbaXFormAdapter::getTimestamp(sal_Int32 columnIndex)
+{
+ Reference< css::sdbc::XRow > xIface(m_xMainForm, UNO_QUERY);
+ if (xIface.is())
+ return xIface->getTimestamp(columnIndex);
+ return css::util::DateTime();
+}
+
+Reference< css::io::XInputStream > SAL_CALL SbaXFormAdapter::getBinaryStream(sal_Int32 columnIndex)
+{
+ Reference< css::sdbc::XRow > xIface(m_xMainForm, UNO_QUERY);
+ if (xIface.is())
+ return xIface->getBinaryStream(columnIndex);
+ return Reference< css::io::XInputStream > ();
+}
+
+Reference< css::io::XInputStream > SAL_CALL SbaXFormAdapter::getCharacterStream(sal_Int32 columnIndex)
+{
+ Reference< css::sdbc::XRow > xIface(m_xMainForm, UNO_QUERY);
+ if (xIface.is())
+ return xIface->getCharacterStream(columnIndex);
+ return Reference< css::io::XInputStream > ();
+}
+
+Any SAL_CALL SbaXFormAdapter::getObject(sal_Int32 columnIndex, const Reference< css::container::XNameAccess >& typeMap)
+{
+ Reference< css::sdbc::XRow > xIface(m_xMainForm, UNO_QUERY);
+ if (xIface.is())
+ return xIface->getObject(columnIndex, typeMap);
+ return Any();
+}
+
+Reference< css::sdbc::XRef > SAL_CALL SbaXFormAdapter::getRef(sal_Int32 columnIndex)
+{
+ Reference< css::sdbc::XRow > xIface(m_xMainForm, UNO_QUERY);
+ if (xIface.is())
+ return xIface->getRef(columnIndex);
+ return Reference< css::sdbc::XRef > ();
+}
+
+Reference< css::sdbc::XBlob > SAL_CALL SbaXFormAdapter::getBlob(sal_Int32 columnIndex)
+{
+ Reference< css::sdbc::XRow > xIface(m_xMainForm, UNO_QUERY);
+ if (xIface.is())
+ return xIface->getBlob(columnIndex);
+ return Reference< css::sdbc::XBlob > ();
+}
+
+Reference< css::sdbc::XClob > SAL_CALL SbaXFormAdapter::getClob(sal_Int32 columnIndex)
+{
+ Reference< css::sdbc::XRow > xIface(m_xMainForm, UNO_QUERY);
+ if (xIface.is())
+ return xIface->getClob(columnIndex);
+ return Reference< css::sdbc::XClob > ();
+}
+
+Reference< css::sdbc::XArray > SAL_CALL SbaXFormAdapter::getArray(sal_Int32 columnIndex)
+{
+ Reference< css::sdbc::XRow > xIface(m_xMainForm, UNO_QUERY);
+ if (xIface.is())
+ return xIface->getArray(columnIndex);
+ return Reference< css::sdbc::XArray > ();
+}
+
+// css::sdbcx::XRowLocate
+Any SAL_CALL SbaXFormAdapter::getBookmark()
+{
+ Reference< css::sdbcx::XRowLocate > xIface(m_xMainForm, UNO_QUERY);
+ if (xIface.is())
+ return xIface->getBookmark();
+ return Any();
+}
+
+sal_Bool SAL_CALL SbaXFormAdapter::moveToBookmark(const Any& bookmark)
+{
+ Reference< css::sdbcx::XRowLocate > xIface(m_xMainForm, UNO_QUERY);
+ if (xIface.is())
+ return xIface->moveToBookmark(bookmark);
+ return false;
+}
+
+sal_Bool SAL_CALL SbaXFormAdapter::moveRelativeToBookmark(const Any& bookmark, sal_Int32 rows)
+{
+ Reference< css::sdbcx::XRowLocate > xIface(m_xMainForm, UNO_QUERY);
+ if (xIface.is())
+ return xIface->moveRelativeToBookmark(bookmark,rows);
+ return false;
+}
+
+sal_Int32 SAL_CALL SbaXFormAdapter::compareBookmarks(const Any& _first, const Any& _second)
+{
+ Reference< css::sdbcx::XRowLocate > xIface(m_xMainForm, UNO_QUERY);
+ if (xIface.is())
+ return xIface->compareBookmarks(_first, _second);
+ return 0;
+}
+
+sal_Bool SAL_CALL SbaXFormAdapter::hasOrderedBookmarks()
+{
+ Reference< css::sdbcx::XRowLocate > xIface(m_xMainForm, UNO_QUERY);
+ if (xIface.is())
+ return xIface->hasOrderedBookmarks();
+ return false;
+}
+
+sal_Int32 SAL_CALL SbaXFormAdapter::hashBookmark(const Any& bookmark)
+{
+ Reference< css::sdbcx::XRowLocate > xIface(m_xMainForm, UNO_QUERY);
+ if (xIface.is())
+ return xIface->hashBookmark(bookmark);
+ return 0;
+}
+
+// css::sdbc::XRowUpdate
+void SAL_CALL SbaXFormAdapter::updateNull(sal_Int32 columnIndex)
+{
+ Reference< css::sdbc::XRowUpdate > xIface(m_xMainForm, UNO_QUERY);
+ if (xIface.is())
+ xIface->updateNull(columnIndex);
+}
+
+void SAL_CALL SbaXFormAdapter::updateBoolean(sal_Int32 columnIndex, sal_Bool x)
+{
+ Reference< css::sdbc::XRowUpdate > xIface(m_xMainForm, UNO_QUERY);
+ if (xIface.is())
+ xIface->updateBoolean(columnIndex, x);
+}
+
+void SAL_CALL SbaXFormAdapter::updateByte(sal_Int32 columnIndex, sal_Int8 x)
+{
+ Reference< css::sdbc::XRowUpdate > xIface(m_xMainForm, UNO_QUERY);
+ if (xIface.is())
+ xIface->updateByte(columnIndex, x);
+}
+
+void SAL_CALL SbaXFormAdapter::updateShort(sal_Int32 columnIndex, sal_Int16 x)
+{
+ Reference< css::sdbc::XRowUpdate > xIface(m_xMainForm, UNO_QUERY);
+ if (xIface.is())
+ xIface->updateShort(columnIndex, x);
+}
+
+void SAL_CALL SbaXFormAdapter::updateInt(sal_Int32 columnIndex, sal_Int32 x)
+{
+ Reference< css::sdbc::XRowUpdate > xIface(m_xMainForm, UNO_QUERY);
+ if (xIface.is())
+ xIface->updateInt(columnIndex, x);
+}
+
+void SAL_CALL SbaXFormAdapter::updateLong(sal_Int32 columnIndex, sal_Int64 x)
+{
+ Reference< css::sdbc::XRowUpdate > xIface(m_xMainForm, UNO_QUERY);
+ if (xIface.is())
+ xIface->updateLong(columnIndex, x);
+}
+
+void SAL_CALL SbaXFormAdapter::updateFloat(sal_Int32 columnIndex, float x)
+{
+ Reference< css::sdbc::XRowUpdate > xIface(m_xMainForm, UNO_QUERY);
+ if (xIface.is())
+ xIface->updateFloat(columnIndex, x);
+}
+
+void SAL_CALL SbaXFormAdapter::updateDouble(sal_Int32 columnIndex, double x)
+{
+ Reference< css::sdbc::XRowUpdate > xIface(m_xMainForm, UNO_QUERY);
+ if (xIface.is())
+ xIface->updateDouble(columnIndex, x);
+}
+
+void SAL_CALL SbaXFormAdapter::updateString(sal_Int32 columnIndex, const OUString& x)
+{
+ Reference< css::sdbc::XRowUpdate > xIface(m_xMainForm, UNO_QUERY);
+ if (xIface.is())
+ xIface->updateString(columnIndex, x);
+}
+
+void SAL_CALL SbaXFormAdapter::updateBytes(sal_Int32 columnIndex, const Sequence< sal_Int8 >& x)
+{
+ Reference< css::sdbc::XRowUpdate > xIface(m_xMainForm, UNO_QUERY);
+ if (xIface.is())
+ xIface->updateBytes(columnIndex, x);
+}
+
+void SAL_CALL SbaXFormAdapter::updateDate(sal_Int32 columnIndex, const css::util::Date& x)
+{
+ Reference< css::sdbc::XRowUpdate > xIface(m_xMainForm, UNO_QUERY);
+ if (xIface.is())
+ xIface->updateDate(columnIndex, x);
+}
+
+void SAL_CALL SbaXFormAdapter::updateTime(sal_Int32 columnIndex, const css::util::Time& x)
+{
+ Reference< css::sdbc::XRowUpdate > xIface(m_xMainForm, UNO_QUERY);
+ if (xIface.is())
+ xIface->updateTime(columnIndex, x);
+}
+
+void SAL_CALL SbaXFormAdapter::updateTimestamp(sal_Int32 columnIndex, const css::util::DateTime& x)
+{
+ Reference< css::sdbc::XRowUpdate > xIface(m_xMainForm, UNO_QUERY);
+ if (xIface.is())
+ xIface->updateTimestamp(columnIndex, x);
+}
+
+void SAL_CALL SbaXFormAdapter::updateBinaryStream(sal_Int32 columnIndex, const Reference< css::io::XInputStream >& x, sal_Int32 length)
+{
+ Reference< css::sdbc::XRowUpdate > xIface(m_xMainForm, UNO_QUERY);
+ if (xIface.is())
+ xIface->updateBinaryStream(columnIndex, x, length);
+}
+
+void SAL_CALL SbaXFormAdapter::updateCharacterStream(sal_Int32 columnIndex, const Reference< css::io::XInputStream >& x, sal_Int32 length)
+{
+ Reference< css::sdbc::XRowUpdate > xIface(m_xMainForm, UNO_QUERY);
+ if (xIface.is())
+ xIface->updateCharacterStream(columnIndex, x, length);
+}
+
+void SAL_CALL SbaXFormAdapter::updateObject(sal_Int32 columnIndex, const Any& x)
+{
+ Reference< css::sdbc::XRowUpdate > xIface(m_xMainForm, UNO_QUERY);
+ if (xIface.is())
+ xIface->updateObject(columnIndex, x);
+}
+
+void SAL_CALL SbaXFormAdapter::updateNumericObject(sal_Int32 columnIndex, const Any& x, sal_Int32 scale)
+{
+ Reference< css::sdbc::XRowUpdate > xIface(m_xMainForm, UNO_QUERY);
+ if (xIface.is())
+ xIface->updateNumericObject(columnIndex, x, scale);
+}
+
+// css::sdbc::XResultSet
+sal_Bool SAL_CALL SbaXFormAdapter::next()
+{
+ if (m_xMainForm.is())
+ return m_xMainForm->next();
+ return false;
+}
+
+sal_Bool SAL_CALL SbaXFormAdapter::isBeforeFirst()
+{
+ if (m_xMainForm.is())
+ return m_xMainForm->isBeforeFirst();
+ return false;
+}
+
+sal_Bool SAL_CALL SbaXFormAdapter::isAfterLast()
+{
+ if (m_xMainForm.is())
+ return m_xMainForm->isAfterLast();
+ return false;
+}
+
+sal_Bool SAL_CALL SbaXFormAdapter::isFirst()
+{
+ if (m_xMainForm.is())
+ return m_xMainForm->isFirst();
+ return false;
+}
+
+sal_Bool SAL_CALL SbaXFormAdapter::isLast()
+{
+ if (m_xMainForm.is())
+ return m_xMainForm->isLast();
+ return false;
+}
+
+void SAL_CALL SbaXFormAdapter::beforeFirst()
+{
+ if (m_xMainForm.is())
+ m_xMainForm->beforeFirst();
+}
+
+void SAL_CALL SbaXFormAdapter::afterLast()
+{
+ if (m_xMainForm.is())
+ m_xMainForm->afterLast();
+}
+
+sal_Bool SAL_CALL SbaXFormAdapter::first()
+{
+ if (m_xMainForm.is())
+ return m_xMainForm->first();
+ return false;
+}
+
+sal_Bool SAL_CALL SbaXFormAdapter::last()
+{
+ if (m_xMainForm.is())
+ return m_xMainForm->last();
+ return false;
+}
+
+sal_Int32 SAL_CALL SbaXFormAdapter::getRow()
+{
+ if (m_xMainForm.is())
+ return m_xMainForm->getRow();
+ return 0;
+}
+
+sal_Bool SAL_CALL SbaXFormAdapter::absolute(sal_Int32 row)
+{
+ if (m_xMainForm.is())
+ return m_xMainForm->absolute(row);
+ return false;
+}
+
+sal_Bool SAL_CALL SbaXFormAdapter::relative(sal_Int32 rows)
+{
+ if (m_xMainForm.is())
+ return m_xMainForm->relative(rows);
+ return false;
+}
+
+sal_Bool SAL_CALL SbaXFormAdapter::previous()
+{
+ if (m_xMainForm.is())
+ return m_xMainForm->previous();
+ return false;
+}
+
+void SAL_CALL SbaXFormAdapter::refreshRow()
+{
+ if (m_xMainForm.is())
+ m_xMainForm->refreshRow();
+}
+
+sal_Bool SAL_CALL SbaXFormAdapter::rowUpdated()
+{
+ if (m_xMainForm.is())
+ return m_xMainForm->rowUpdated();
+ return false;
+}
+
+sal_Bool SAL_CALL SbaXFormAdapter::rowInserted()
+{
+ if (m_xMainForm.is())
+ return m_xMainForm->rowInserted();
+ return false;
+}
+
+sal_Bool SAL_CALL SbaXFormAdapter::rowDeleted()
+{
+ if (m_xMainForm.is())
+ return m_xMainForm->rowDeleted();
+ return false;
+}
+
+Reference< XInterface > SAL_CALL SbaXFormAdapter::getStatement()
+{
+ if (m_xMainForm.is())
+ return m_xMainForm->getStatement();
+ return nullptr;
+}
+
+// css::sdbc::XResultSetUpdate
+void SAL_CALL SbaXFormAdapter::insertRow()
+{
+ Reference< css::sdbc::XResultSetUpdate > xIface(m_xMainForm, UNO_QUERY);
+ if (xIface.is())
+ xIface->insertRow();
+}
+
+void SAL_CALL SbaXFormAdapter::updateRow()
+{
+ Reference< css::sdbc::XResultSetUpdate > xIface(m_xMainForm, UNO_QUERY);
+ if (xIface.is())
+ xIface->updateRow();
+}
+
+void SAL_CALL SbaXFormAdapter::deleteRow()
+{
+ Reference< css::sdbc::XResultSetUpdate > xIface(m_xMainForm, UNO_QUERY);
+ if (xIface.is())
+ xIface->deleteRow();
+}
+
+void SAL_CALL SbaXFormAdapter::cancelRowUpdates()
+{
+ Reference< css::sdbc::XResultSetUpdate > xIface(m_xMainForm, UNO_QUERY);
+ if (xIface.is())
+ xIface->cancelRowUpdates();
+}
+
+void SAL_CALL SbaXFormAdapter::moveToInsertRow()
+{
+ Reference< css::sdbc::XResultSetUpdate > xIface(m_xMainForm, UNO_QUERY);
+ if (xIface.is())
+ xIface->moveToInsertRow();
+}
+
+void SAL_CALL SbaXFormAdapter::moveToCurrentRow()
+{
+ Reference< css::sdbc::XResultSetUpdate > xIface(m_xMainForm, UNO_QUERY);
+ if (xIface.is())
+ xIface->moveToCurrentRow();
+}
+
+// css::sdbc::XRowSet
+void SAL_CALL SbaXFormAdapter::execute()
+{
+ if (m_xMainForm.is())
+ m_xMainForm->execute();
+}
+
+void SAL_CALL SbaXFormAdapter::addRowSetListener(const css::uno::Reference< css::sdbc::XRowSetListener >& l)
+{
+ m_aRowSetListeners.addInterface(l);
+ if (m_aRowSetListeners.getLength() == 1)
+ {
+ css::uno::Reference< css::sdbc::XRowSet > xBroadcaster(m_xMainForm, css::uno::UNO_QUERY);
+ if (xBroadcaster.is())
+ xBroadcaster->addRowSetListener(&m_aRowSetListeners);
+ }
+}
+void SAL_CALL SbaXFormAdapter::removeRowSetListener(const css::uno::Reference< css::sdbc::XRowSetListener >& l)
+{
+ if (m_aRowSetListeners.getLength() == 1)
+ {
+ css::uno::Reference< css::sdbc::XRowSet > xBroadcaster(m_xMainForm, css::uno::UNO_QUERY);
+ if (xBroadcaster.is())
+ xBroadcaster->removeRowSetListener(&m_aRowSetListeners);
+ }
+ m_aRowSetListeners.removeInterface(l);
+}
+
+// css::sdbcx::XDeleteRows
+Sequence<sal_Int32> SAL_CALL SbaXFormAdapter::deleteRows(const Sequence< Any >& rows)
+{
+ Reference< css::sdbcx::XDeleteRows > xIface(m_xMainForm, UNO_QUERY);
+ if (xIface.is())
+ return xIface->deleteRows(rows);
+ return Sequence<sal_Int32>();
+}
+
+// css::sdbc::XWarningsSupplier
+Any SAL_CALL SbaXFormAdapter::getWarnings()
+{
+ Reference< css::sdbc::XWarningsSupplier > xIface(m_xMainForm, UNO_QUERY);
+ if (xIface.is())
+ return xIface->getWarnings();
+ return Any();
+}
+
+void SAL_CALL SbaXFormAdapter::clearWarnings()
+{
+ Reference< css::sdbc::XWarningsSupplier > xIface(m_xMainForm, UNO_QUERY);
+ if (xIface.is())
+ xIface->clearWarnings();
+}
+
+// css::sdb::XRowSetApproveBroadcaster
+void SAL_CALL SbaXFormAdapter::addRowSetApproveListener(const css::uno::Reference< css::sdb::XRowSetApproveListener >& l)
+{
+ m_aRowSetApproveListeners.addInterface(l);
+ if (m_aRowSetApproveListeners.getLength() == 1)
+ {
+ css::uno::Reference< css::sdb::XRowSetApproveBroadcaster > xBroadcaster(m_xMainForm, css::uno::UNO_QUERY);
+ if (xBroadcaster.is())
+ xBroadcaster->addRowSetApproveListener(&m_aRowSetApproveListeners);
+ }
+}
+void SAL_CALL SbaXFormAdapter::removeRowSetApproveListener(const css::uno::Reference< css::sdb::XRowSetApproveListener >& l)
+{
+ if (m_aRowSetApproveListeners.getLength() == 1)
+ {
+ css::uno::Reference< css::sdb::XRowSetApproveBroadcaster > xBroadcaster(m_xMainForm, css::uno::UNO_QUERY);
+ if (xBroadcaster.is())
+ xBroadcaster->removeRowSetApproveListener(&m_aRowSetApproveListeners);
+ }
+ m_aRowSetApproveListeners.removeInterface(l);
+}
+
+// css::sdbc::XSQLErrorBroadcaster
+void SAL_CALL SbaXFormAdapter::addSQLErrorListener(const css::uno::Reference< css::sdb::XSQLErrorListener >& l)
+{
+ m_aErrorListeners.addInterface(l);
+ if (m_aErrorListeners.getLength() == 1)
+ {
+ css::uno::Reference< css::sdb::XSQLErrorBroadcaster > xBroadcaster(m_xMainForm, css::uno::UNO_QUERY);
+ if (xBroadcaster.is())
+ xBroadcaster->addSQLErrorListener(&m_aErrorListeners);
+ }
+}
+void SAL_CALL SbaXFormAdapter::removeSQLErrorListener(const css::uno::Reference< css::sdb::XSQLErrorListener >& l)
+{
+ if (m_aErrorListeners.getLength() == 1)
+ {
+ css::uno::Reference< css::sdb::XSQLErrorBroadcaster > xBroadcaster(m_xMainForm, css::uno::UNO_QUERY);
+ if (xBroadcaster.is())
+ xBroadcaster->removeSQLErrorListener(&m_aErrorListeners);
+ }
+ m_aErrorListeners.removeInterface(l);
+}
+
+// css::sdb::XResultSetAccess
+Reference< css::sdbc::XResultSet > SAL_CALL SbaXFormAdapter::createResultSet()
+{
+ Reference< css::sdb::XResultSetAccess > xIface(m_xMainForm, UNO_QUERY);
+ if (xIface.is())
+ return xIface->createResultSet();
+ return Reference< css::sdbc::XResultSet > ();
+}
+
+// css::form::XLoadable
+void SAL_CALL SbaXFormAdapter::load()
+{
+ Reference< css::form::XLoadable > xIface(m_xMainForm, UNO_QUERY);
+ if (xIface.is())
+ xIface->load();
+}
+
+void SAL_CALL SbaXFormAdapter::unload()
+{
+ Reference< css::form::XLoadable > xIface(m_xMainForm, UNO_QUERY);
+ if (xIface.is())
+ xIface->unload();
+}
+
+void SAL_CALL SbaXFormAdapter::reload()
+{
+ Reference< css::form::XLoadable > xIface(m_xMainForm, UNO_QUERY);
+ if (xIface.is())
+ xIface->reload();
+}
+
+sal_Bool SAL_CALL SbaXFormAdapter::isLoaded()
+{
+ Reference< css::form::XLoadable > xIface(m_xMainForm, UNO_QUERY);
+ if (xIface.is())
+ return xIface->isLoaded();
+ return false;
+}
+
+void SAL_CALL SbaXFormAdapter::addLoadListener(const css::uno::Reference< css::form::XLoadListener>& l)
+{
+ m_aLoadListeners.addInterface(l);
+ if (m_aLoadListeners.getLength() == 1)
+ {
+ css::uno::Reference< css::form::XLoadable > xBroadcaster(m_xMainForm, css::uno::UNO_QUERY);
+ if (xBroadcaster.is())
+ xBroadcaster->addLoadListener(&m_aLoadListeners);
+ }
+}
+void SAL_CALL SbaXFormAdapter::removeLoadListener(const css::uno::Reference< css::form::XLoadListener >& l)
+{
+ if (m_aLoadListeners.getLength() == 1)
+ {
+ css::uno::Reference< css::form::XLoadable > xBroadcaster(m_xMainForm, css::uno::UNO_QUERY);
+ if (xBroadcaster.is())
+ xBroadcaster->removeLoadListener(&m_aLoadListeners);
+ }
+ m_aLoadListeners.removeInterface(l);
+}
+
+// css::sdbc::XParameters
+void SAL_CALL SbaXFormAdapter::setNull(sal_Int32 parameterIndex, sal_Int32 sqlType)
+{
+ Reference< css::sdbc::XParameters > xIface(m_xMainForm, UNO_QUERY);
+ if (xIface.is())
+ xIface->setNull(parameterIndex, sqlType);
+}
+
+void SAL_CALL SbaXFormAdapter::setObjectNull(sal_Int32 parameterIndex, sal_Int32 sqlType, const OUString& typeName)
+{
+ Reference< css::sdbc::XParameters > xIface(m_xMainForm, UNO_QUERY);
+ if (xIface.is())
+ xIface->setObjectNull(parameterIndex, sqlType, typeName);
+}
+
+void SAL_CALL SbaXFormAdapter::setBoolean(sal_Int32 parameterIndex, sal_Bool x)
+{
+ Reference< css::sdbc::XParameters > xIface(m_xMainForm, UNO_QUERY);
+ if (xIface.is())
+ xIface->setBoolean(parameterIndex, x);
+}
+
+void SAL_CALL SbaXFormAdapter::setByte(sal_Int32 parameterIndex, sal_Int8 x)
+{
+ Reference< css::sdbc::XParameters > xIface(m_xMainForm, UNO_QUERY);
+ if (xIface.is())
+ xIface->setByte(parameterIndex, x);
+}
+
+void SAL_CALL SbaXFormAdapter::setShort(sal_Int32 parameterIndex, sal_Int16 x)
+{
+ Reference< css::sdbc::XParameters > xIface(m_xMainForm, UNO_QUERY);
+ if (xIface.is())
+ xIface->setShort(parameterIndex, x);
+}
+
+void SAL_CALL SbaXFormAdapter::setInt(sal_Int32 parameterIndex, sal_Int32 x)
+{
+ Reference< css::sdbc::XParameters > xIface(m_xMainForm, UNO_QUERY);
+ if (xIface.is())
+ xIface->setInt(parameterIndex, x);
+}
+
+void SAL_CALL SbaXFormAdapter::setLong(sal_Int32 parameterIndex, sal_Int64 x)
+{
+ Reference< css::sdbc::XParameters > xIface(m_xMainForm, UNO_QUERY);
+ if (xIface.is())
+ xIface->setLong(parameterIndex, x);
+}
+
+void SAL_CALL SbaXFormAdapter::setFloat(sal_Int32 parameterIndex, float x)
+{
+ Reference< css::sdbc::XParameters > xIface(m_xMainForm, UNO_QUERY);
+ if (xIface.is())
+ xIface->setFloat(parameterIndex, x);
+}
+
+void SAL_CALL SbaXFormAdapter::setDouble(sal_Int32 parameterIndex, double x)
+{
+ Reference< css::sdbc::XParameters > xIface(m_xMainForm, UNO_QUERY);
+ if (xIface.is())
+ xIface->setDouble(parameterIndex, x);
+}
+
+void SAL_CALL SbaXFormAdapter::setString(sal_Int32 parameterIndex, const OUString& x)
+{
+ Reference< css::sdbc::XParameters > xIface(m_xMainForm, UNO_QUERY);
+ if (xIface.is())
+ xIface->setString(parameterIndex, x);
+}
+
+void SAL_CALL SbaXFormAdapter::setBytes(sal_Int32 parameterIndex, const Sequence< sal_Int8 >& x)
+{
+ Reference< css::sdbc::XParameters > xIface(m_xMainForm, UNO_QUERY);
+ if (xIface.is())
+ xIface->setBytes(parameterIndex, x);
+}
+
+void SAL_CALL SbaXFormAdapter::setDate(sal_Int32 parameterIndex, const css::util::Date& x)
+{
+ Reference< css::sdbc::XParameters > xIface(m_xMainForm, UNO_QUERY);
+ if (xIface.is())
+ xIface->setDate(parameterIndex, x);
+}
+
+void SAL_CALL SbaXFormAdapter::setTime(sal_Int32 parameterIndex, const css::util::Time& x)
+{
+ Reference< css::sdbc::XParameters > xIface(m_xMainForm, UNO_QUERY);
+ if (xIface.is())
+ xIface->setTime(parameterIndex, x);
+}
+
+void SAL_CALL SbaXFormAdapter::setTimestamp(sal_Int32 parameterIndex, const css::util::DateTime& x)
+{
+ Reference< css::sdbc::XParameters > xIface(m_xMainForm, UNO_QUERY);
+ if (xIface.is())
+ xIface->setTimestamp(parameterIndex, x);
+}
+
+void SAL_CALL SbaXFormAdapter::setBinaryStream(sal_Int32 parameterIndex, const Reference< css::io::XInputStream >& x, sal_Int32 length)
+{
+ Reference< css::sdbc::XParameters > xIface(m_xMainForm, UNO_QUERY);
+ if (xIface.is())
+ xIface->setBinaryStream(parameterIndex, x, length);
+}
+
+void SAL_CALL SbaXFormAdapter::setCharacterStream(sal_Int32 parameterIndex, const Reference< css::io::XInputStream >& x, sal_Int32 length)
+{
+ Reference< css::sdbc::XParameters > xIface(m_xMainForm, UNO_QUERY);
+ if (xIface.is())
+ xIface->setCharacterStream(parameterIndex, x, length);
+}
+
+void SAL_CALL SbaXFormAdapter::setObject(sal_Int32 parameterIndex, const Any& x)
+{
+ Reference< css::sdbc::XParameters > xIface(m_xMainForm, UNO_QUERY);
+ if (xIface.is())
+ xIface->setObject(parameterIndex, x);
+}
+
+void SAL_CALL SbaXFormAdapter::setObjectWithInfo(sal_Int32 parameterIndex, const Any& x, sal_Int32 targetSqlType, sal_Int32 scale)
+{
+ Reference< css::sdbc::XParameters > xIface(m_xMainForm, UNO_QUERY);
+ if (xIface.is())
+ xIface->setObjectWithInfo(parameterIndex, x, targetSqlType, scale);
+}
+
+void SAL_CALL SbaXFormAdapter::setRef(sal_Int32 parameterIndex, const Reference< css::sdbc::XRef >& x)
+{
+ Reference< css::sdbc::XParameters > xIface(m_xMainForm, UNO_QUERY);
+ if (xIface.is())
+ xIface->setRef(parameterIndex, x);
+}
+
+void SAL_CALL SbaXFormAdapter::setBlob(sal_Int32 parameterIndex, const Reference< css::sdbc::XBlob >& x)
+{
+ Reference< css::sdbc::XParameters > xIface(m_xMainForm, UNO_QUERY);
+ if (xIface.is())
+ xIface->setBlob(parameterIndex, x);
+}
+
+void SAL_CALL SbaXFormAdapter::setClob(sal_Int32 parameterIndex, const Reference< css::sdbc::XClob >& x)
+{
+ Reference< css::sdbc::XParameters > xIface(m_xMainForm, UNO_QUERY);
+ if (xIface.is())
+ xIface->setClob(parameterIndex, x);
+}
+
+void SAL_CALL SbaXFormAdapter::setArray(sal_Int32 parameterIndex, const Reference< css::sdbc::XArray >& x)
+{
+ Reference< css::sdbc::XParameters > xIface(m_xMainForm, UNO_QUERY);
+ if (xIface.is())
+ xIface->setArray(parameterIndex, x);
+}
+
+void SAL_CALL SbaXFormAdapter::clearParameters()
+{
+ Reference< css::sdbc::XParameters > xIface(m_xMainForm, UNO_QUERY);
+ if (xIface.is())
+ xIface->clearParameters();
+}
+
+// css::form::XDatabaseParameterBroadcaster
+void SAL_CALL SbaXFormAdapter::addParameterListener(const Reference< css::form::XDatabaseParameterListener >& aListener)
+{
+ m_aParameterListeners.addInterface(aListener);
+ if (m_aParameterListeners.getLength() == 1)
+ {
+ Reference< css::form::XDatabaseParameterBroadcaster > xBroadcaster(m_xMainForm, UNO_QUERY);
+ if (xBroadcaster.is())
+ xBroadcaster->addParameterListener(&m_aParameterListeners);
+ }
+}
+
+void SAL_CALL SbaXFormAdapter::removeParameterListener(const Reference< css::form::XDatabaseParameterListener >& aListener)
+{
+ if (m_aParameterListeners.getLength() == 1)
+ {
+ Reference< css::form::XDatabaseParameterBroadcaster > xBroadcaster(m_xMainForm, UNO_QUERY);
+ if (xBroadcaster.is())
+ xBroadcaster->removeParameterListener(&m_aParameterListeners);
+ }
+ m_aParameterListeners.removeInterface(aListener);
+}
+
+// css::container::XChild
+Reference< XInterface > SAL_CALL SbaXFormAdapter::getParent()
+{
+ return m_xParent;
+}
+
+void SAL_CALL SbaXFormAdapter::setParent(const Reference< XInterface >& Parent)
+{
+ m_xParent = Parent;
+}
+
+// css::form::XSubmit
+void SAL_CALL SbaXFormAdapter::submit(const Reference< css::awt::XControl >& aControl, const css::awt::MouseEvent& aMouseEvt)
+{
+ Reference< css::form::XSubmit > xSubmit(m_xMainForm, UNO_QUERY);
+ if (xSubmit.is())
+ xSubmit->submit(aControl, aMouseEvt);
+}
+
+void SAL_CALL SbaXFormAdapter::addSubmitListener(const css::uno::Reference< css::form::XSubmitListener >& l)
+{
+ m_aSubmitListeners.addInterface(l);
+ if (m_aSubmitListeners.getLength() == 1)
+ {
+ css::uno::Reference< css::form::XSubmit > xBroadcaster(m_xMainForm, css::uno::UNO_QUERY);
+ if (xBroadcaster.is())
+ xBroadcaster->addSubmitListener(&m_aSubmitListeners);
+ }
+}
+void SAL_CALL SbaXFormAdapter::removeSubmitListener(const css::uno::Reference< css::form::XSubmitListener >& l)
+{
+ if (m_aSubmitListeners.getLength() == 1)
+ {
+ css::uno::Reference< css::form::XSubmit > xBroadcaster(m_xMainForm, css::uno::UNO_QUERY);
+ if (xBroadcaster.is())
+ xBroadcaster->removeSubmitListener(&m_aSubmitListeners);
+ }
+ m_aSubmitListeners.removeInterface(l);
+}
+
+// css::awt::XTabControllerModel
+sal_Bool SAL_CALL SbaXFormAdapter::getGroupControl()
+{
+ OSL_FAIL("SAL_CALL SbaXFormAdapter::getGroupControl : not supported !");
+ return false;
+}
+
+void SAL_CALL SbaXFormAdapter::setGroupControl(sal_Bool /*GroupControl*/)
+{
+ OSL_FAIL("SAL_CALL SbaXFormAdapter::setGroupControl : not supported !");
+}
+
+void SAL_CALL SbaXFormAdapter::setControlModels(const Sequence< Reference< css::awt::XControlModel > >& /*Controls*/)
+{
+ OSL_FAIL("SAL_CALL SbaXFormAdapter::setControlModels : not supported !");
+}
+
+Sequence< Reference< css::awt::XControlModel > > SAL_CALL SbaXFormAdapter::getControlModels()
+{
+ OSL_FAIL("SAL_CALL SbaXFormAdapter::getControlModels : not supported !");
+ return Sequence< Reference< css::awt::XControlModel > >();
+}
+
+void SAL_CALL SbaXFormAdapter::setGroup(const Sequence< Reference< css::awt::XControlModel > >& /*_rGroup*/, const OUString& /*GroupName*/)
+{
+ OSL_FAIL("SAL_CALL SbaXFormAdapter::setGroup : not supported !");
+}
+
+sal_Int32 SAL_CALL SbaXFormAdapter::getGroupCount()
+{
+ OSL_FAIL("SAL_CALL SbaXFormAdapter::getGroupCount : not supported !");
+ return 0;
+}
+
+void SAL_CALL SbaXFormAdapter::getGroup(sal_Int32 /*nGroup*/, Sequence< Reference< css::awt::XControlModel > >& /*_rGroup*/, OUString& /*Name*/)
+{
+ OSL_FAIL("SAL_CALL SbaXFormAdapter::getGroup : not supported !");
+}
+
+void SAL_CALL SbaXFormAdapter::getGroupByName(const OUString& /*Name*/, Sequence< Reference< css::awt::XControlModel > >& /*_rGroup*/)
+{
+ OSL_FAIL("SAL_CALL SbaXFormAdapter::getGroupByName : not supported !");
+}
+
+// css::lang::XComponent
+void SAL_CALL SbaXFormAdapter::dispose()
+{
+ // log off all multiplexers
+ if (m_xMainForm.is())
+ StopListening();
+
+ css::lang::EventObject aEvt(*this);
+ m_aLoadListeners.disposeAndClear(aEvt);
+ m_aRowSetListeners.disposeAndClear(aEvt);
+ m_aRowSetApproveListeners.disposeAndClear(aEvt);
+ m_aErrorListeners.disposeAndClear(aEvt);
+ m_aParameterListeners.disposeAndClear(aEvt);
+ m_aSubmitListeners.disposeAndClear(aEvt);
+ m_aResetListeners.disposeAndClear(aEvt);
+
+ m_aVetoablePropertyChangeListeners.disposeAndClear();
+ m_aPropertyChangeListeners.disposeAndClear();
+ m_aPropertiesChangeListeners.disposeAndClear(aEvt);
+
+ m_aDisposeListeners.disposeAndClear(aEvt);
+ m_aContainerListeners.disposeAndClear(aEvt);
+
+ // dispose all children
+ for (auto const& child : m_aChildren)
+ {
+ Reference< css::beans::XPropertySet > xSet(child, UNO_QUERY);
+ if (xSet.is())
+ xSet->removePropertyChangeListener(PROPERTY_NAME, static_cast<css::beans::XPropertyChangeListener*>(this));
+
+ Reference< css::container::XChild > xChild(child, UNO_QUERY);
+ if (xChild.is())
+ xChild->setParent(Reference< XInterface > ());
+
+ Reference< css::lang::XComponent > xComp(child, UNO_QUERY);
+ if (xComp.is())
+ xComp->dispose();
+ }
+ m_aChildren.clear();
+}
+
+void SAL_CALL SbaXFormAdapter::addEventListener(const Reference< css::lang::XEventListener >& xListener)
+{
+ m_aDisposeListeners.addInterface(xListener);
+}
+
+void SAL_CALL SbaXFormAdapter::removeEventListener(const Reference< css::lang::XEventListener >& aListener)
+{
+ m_aDisposeListeners.removeInterface(aListener);
+}
+
+// css::beans::XFastPropertySet
+void SAL_CALL SbaXFormAdapter::setFastPropertyValue(sal_Int32 nHandle, const Any& aValue)
+{
+ Reference< css::beans::XFastPropertySet > xSet(m_xMainForm, UNO_QUERY);
+ OSL_ENSURE(xSet.is(), "SAL_CALL SbaXFormAdapter::setFastPropertyValue : have no master form !");
+
+ if (m_nNamePropHandle == nHandle)
+ {
+ if (aValue.getValueType().getTypeClass() != TypeClass_STRING)
+ {
+ throw css::lang::IllegalArgumentException();
+ }
+
+ // for notifying property listeners
+ css::beans::PropertyChangeEvent aEvt;
+ aEvt.Source = *this;
+ aEvt.PropertyName = PROPERTY_NAME;
+ aEvt.PropertyHandle = m_nNamePropHandle;
+ aEvt.OldValue <<= m_sName;
+ aEvt.NewValue = aValue;
+
+ aValue >>= m_sName;
+
+ m_aPropertyChangeListeners.getContainer(PROPERTY_NAME)->notifyEach(
+ &XPropertyChangeListener::propertyChange, aEvt );
+
+ return;
+ }
+
+ xSet->setFastPropertyValue(nHandle, aValue);
+}
+
+Any SAL_CALL SbaXFormAdapter::getFastPropertyValue(sal_Int32 nHandle)
+{
+ Reference< css::beans::XFastPropertySet > xSet(m_xMainForm, UNO_QUERY);
+ OSL_ENSURE(xSet.is(), "SAL_CALL SbaXFormAdapter::getFastPropertyValue : have no master form !");
+
+ if (m_nNamePropHandle == nHandle)
+ return Any(m_sName);
+
+ return xSet->getFastPropertyValue(nHandle);
+}
+
+// css::container::XNamed
+OUString SAL_CALL SbaXFormAdapter::getName()
+{
+ return ::comphelper::getString(getPropertyValue(PROPERTY_NAME));
+}
+
+void SAL_CALL SbaXFormAdapter::setName(const OUString& aName)
+{
+ setPropertyValue(PROPERTY_NAME, Any(aName));
+}
+
+// css::io::XPersistObject
+OUString SAL_CALL SbaXFormAdapter::getServiceName()
+{
+ Reference< css::io::XPersistObject > xPersist(m_xMainForm, UNO_QUERY);
+ if (xPersist.is())
+ return xPersist->getServiceName();
+ return OUString();
+}
+
+void SAL_CALL SbaXFormAdapter::write(const Reference< css::io::XObjectOutputStream >& _rxOutStream)
+{
+ Reference< css::io::XPersistObject > xPersist(m_xMainForm, UNO_QUERY);
+ if (xPersist.is())
+ xPersist->write(_rxOutStream);
+}
+
+void SAL_CALL SbaXFormAdapter::read(const Reference< css::io::XObjectInputStream >& _rxInStream)
+{
+ Reference< css::io::XPersistObject > xPersist(m_xMainForm, UNO_QUERY);
+ if (xPersist.is())
+ xPersist->read(_rxInStream);
+}
+
+// css::beans::XMultiPropertySet
+Reference< css::beans::XPropertySetInfo > SAL_CALL SbaXFormAdapter::getPropertySetInfo()
+{
+ Reference< css::beans::XMultiPropertySet > xSet(m_xMainForm, UNO_QUERY);
+ if (!xSet.is())
+ return Reference< css::beans::XPropertySetInfo > ();
+
+ Reference< css::beans::XPropertySetInfo > xReturn = xSet->getPropertySetInfo();
+ if (-1 == m_nNamePropHandle)
+ {
+ // we need to determine the handle for the NAME property
+ const Sequence<css::beans::Property> aProps = xReturn->getProperties();
+ for (const css::beans::Property& rProp : aProps)
+ {
+ if (rProp.Name == PROPERTY_NAME)
+ {
+ m_nNamePropHandle = rProp.Handle;
+ break;
+ }
+ }
+ }
+ return xReturn;
+}
+
+void SAL_CALL SbaXFormAdapter::setPropertyValues(const Sequence< OUString >& PropertyNames, const Sequence< Any >& Values)
+{
+ Reference< css::beans::XMultiPropertySet > xSet(m_xMainForm, UNO_QUERY);
+ if (xSet.is())
+ xSet->setPropertyValues(PropertyNames, Values);
+}
+
+Sequence< Any > SAL_CALL SbaXFormAdapter::getPropertyValues(const Sequence< OUString >& aPropertyNames)
+{
+ Reference< css::beans::XMultiPropertySet > xSet(m_xMainForm, UNO_QUERY);
+ if (!xSet.is())
+ return Sequence< Any>(aPropertyNames.getLength());
+
+ Sequence< Any> aReturn = xSet->getPropertyValues(aPropertyNames);
+ auto aReturnRange = asNonConstRange(aReturn);
+
+ // search for (and fake) the NAME property
+ OSL_ENSURE(aReturn.getLength() == aPropertyNames.getLength(), "SAL_CALL SbaXFormAdapter::getPropertyValues : the main form returned an invalid-length sequence !");
+ for (sal_Int32 i=0; i<aPropertyNames.getLength(); ++i)
+ if (aPropertyNames[i] == PROPERTY_NAME)
+ {
+ aReturnRange[i] <<= m_sName;
+ break;
+ }
+
+ return aReturn;
+}
+
+void SAL_CALL SbaXFormAdapter::addPropertiesChangeListener(const Sequence< OUString>& /*aPropertyNames*/, const Reference< css::beans::XPropertiesChangeListener >& xListener)
+{
+ // we completely ignore the property names, _all_ changes of _all_ properties will be forwarded to _all_ listeners
+ m_aPropertiesChangeListeners.addInterface(xListener);
+ if (m_aPropertiesChangeListeners.getLength() == 1)
+ {
+ Reference< css::beans::XMultiPropertySet > xBroadcaster(m_xMainForm, UNO_QUERY);
+ if (xBroadcaster.is())
+ xBroadcaster->addPropertiesChangeListener(Sequence< OUString>{""}, &m_aPropertiesChangeListeners);
+ }
+}
+
+void SAL_CALL SbaXFormAdapter::removePropertiesChangeListener(const Reference< css::beans::XPropertiesChangeListener >& Listener)
+{
+ if (m_aPropertiesChangeListeners.getLength() == 1)
+ {
+ Reference< css::beans::XMultiPropertySet > xBroadcaster(m_xMainForm, UNO_QUERY);
+ if (xBroadcaster.is())
+ xBroadcaster->removePropertiesChangeListener(&m_aPropertiesChangeListeners);
+ }
+ m_aPropertiesChangeListeners.removeInterface(Listener);
+}
+
+void SAL_CALL SbaXFormAdapter::firePropertiesChangeEvent(const Sequence< OUString >& aPropertyNames, const Reference< css::beans::XPropertiesChangeListener >& xListener)
+{
+ Reference< css::beans::XMultiPropertySet > xSet(m_xMainForm, UNO_QUERY);
+ if (xSet.is())
+ xSet->firePropertiesChangeEvent(aPropertyNames, xListener);
+}
+
+// css::beans::XPropertySet
+void SAL_CALL SbaXFormAdapter::setPropertyValue(const OUString& aPropertyName, const Any& aValue)
+{
+ Reference< css::beans::XPropertySet > xSet(m_xMainForm, UNO_QUERY);
+ if (!xSet.is())
+ return;
+
+ // special handling for the "name" property
+ if (aPropertyName == PROPERTY_NAME)
+ setFastPropertyValue(m_nNamePropHandle, aValue);
+
+ xSet->setPropertyValue(aPropertyName, aValue);
+}
+
+Any SAL_CALL SbaXFormAdapter::getPropertyValue(const OUString& PropertyName)
+{
+ Reference< css::beans::XPropertySet > xSet(m_xMainForm, UNO_QUERY);
+ if (!xSet.is())
+ return Any();
+
+ // special handling for the "name" property
+ if (PropertyName == PROPERTY_NAME)
+ return getFastPropertyValue(m_nNamePropHandle);
+
+ return xSet->getPropertyValue(PropertyName);
+}
+
+void SAL_CALL SbaXFormAdapter::addPropertyChangeListener(const OUString& rName, const css::uno::Reference< css::beans::XPropertyChangeListener>& l )
+{
+ m_aPropertyChangeListeners.addInterface(rName, l);
+ if (m_aPropertyChangeListeners.getOverallLen() == 1)
+ {
+ css::uno::Reference< css::beans::XPropertySet > xBroadcaster(m_xMainForm, css::uno::UNO_QUERY);
+ if (xBroadcaster.is())
+ xBroadcaster->addPropertyChangeListener(OUString(), &m_aPropertyChangeListeners);
+ }
+}
+void SAL_CALL SbaXFormAdapter::removePropertyChangeListener(const OUString& rName, const css::uno::Reference< css::beans::XPropertyChangeListener>& l )
+{
+ if (m_aPropertyChangeListeners.getOverallLen() == 1)
+ {
+ css::uno::Reference< css::beans::XPropertySet > xBroadcaster(m_xMainForm, css::uno::UNO_QUERY);
+ if (xBroadcaster.is())
+ xBroadcaster->removePropertyChangeListener(OUString(), &m_aPropertyChangeListeners);
+ }
+ m_aPropertyChangeListeners.removeInterface(rName, l);
+}
+
+void SAL_CALL SbaXFormAdapter::addVetoableChangeListener(const OUString& rName, const css::uno::Reference< css::beans::XVetoableChangeListener>& l )
+{
+ m_aVetoablePropertyChangeListeners.addInterface(rName, l);
+ if (m_aVetoablePropertyChangeListeners.getOverallLen() == 1)
+ {
+ css::uno::Reference< css::beans::XPropertySet > xBroadcaster(m_xMainForm, css::uno::UNO_QUERY);
+ if (xBroadcaster.is())
+ xBroadcaster->addVetoableChangeListener(OUString(), &m_aVetoablePropertyChangeListeners);
+ }
+}
+void SAL_CALL SbaXFormAdapter::removeVetoableChangeListener(const OUString& rName, const css::uno::Reference< css::beans::XVetoableChangeListener>& l )
+{
+ if (m_aVetoablePropertyChangeListeners.getOverallLen() == 1)
+ {
+ css::uno::Reference< css::beans::XPropertySet > xBroadcaster(m_xMainForm, css::uno::UNO_QUERY);
+ if (xBroadcaster.is())
+ xBroadcaster->removeVetoableChangeListener(OUString(), &m_aVetoablePropertyChangeListeners);
+ }
+ m_aVetoablePropertyChangeListeners.removeInterface(rName, l);
+}
+
+
+// css::util::XCancellable
+void SAL_CALL SbaXFormAdapter::cancel()
+{
+ Reference< css::util::XCancellable > xCancel(m_xMainForm, UNO_QUERY);
+ if (!xCancel.is())
+ return;
+ xCancel->cancel();
+}
+
+// css::beans::XPropertyState
+css::beans::PropertyState SAL_CALL SbaXFormAdapter::getPropertyState(const OUString& PropertyName)
+{
+ Reference< css::beans::XPropertyState > xState(m_xMainForm, UNO_QUERY);
+ if (xState.is())
+ return xState->getPropertyState(PropertyName);
+ return css::beans::PropertyState_DEFAULT_VALUE;
+}
+
+Sequence< css::beans::PropertyState> SAL_CALL SbaXFormAdapter::getPropertyStates(const Sequence< OUString >& aPropertyName)
+{
+ Reference< css::beans::XPropertyState > xState(m_xMainForm, UNO_QUERY);
+ if (xState.is())
+ return xState->getPropertyStates(aPropertyName);
+
+ // set them all to DEFAULT
+ Sequence< css::beans::PropertyState> aReturn(aPropertyName.getLength());
+ for (css::beans::PropertyState& rState : asNonConstRange(aReturn))
+ rState = css::beans::PropertyState_DEFAULT_VALUE;
+ return aReturn;
+}
+
+void SAL_CALL SbaXFormAdapter::setPropertyToDefault(const OUString& PropertyName)
+{
+ Reference< css::beans::XPropertyState > xState(m_xMainForm, UNO_QUERY);
+ if (xState.is())
+ xState->setPropertyToDefault(PropertyName);
+}
+
+Any SAL_CALL SbaXFormAdapter::getPropertyDefault(const OUString& aPropertyName)
+{
+ Reference< css::beans::XPropertyState > xState(m_xMainForm, UNO_QUERY);
+ if (xState.is())
+ return xState->getPropertyDefault(aPropertyName);
+ return Any();
+}
+
+// css::form::XReset
+void SAL_CALL SbaXFormAdapter::reset()
+{
+ Reference< css::form::XReset > xReset(m_xMainForm, UNO_QUERY);
+ if (xReset.is())
+ xReset->reset();
+}
+
+void SAL_CALL SbaXFormAdapter::addResetListener(const css::uno::Reference< css::form::XResetListener >& l)
+{
+ m_aResetListeners.addInterface(l);
+ if (m_aResetListeners.getLength() == 1)
+ {
+ css::uno::Reference< css::form::XReset > xBroadcaster(m_xMainForm, css::uno::UNO_QUERY);
+ if (xBroadcaster.is())
+ xBroadcaster->addResetListener(&m_aResetListeners);
+ }
+}
+void SAL_CALL SbaXFormAdapter::removeResetListener(const css::uno::Reference< css::form::XResetListener >& l)
+{
+ if (m_aResetListeners.getLength() == 1)
+ {
+ css::uno::Reference< css::form::XReset > xBroadcaster(m_xMainForm, css::uno::UNO_QUERY);
+ if (xBroadcaster.is())
+ xBroadcaster->removeResetListener(&m_aResetListeners);
+ }
+ m_aResetListeners.removeInterface(l);
+}
+
+// css::container::XNameContainer
+void SbaXFormAdapter::implInsert(const Any& aElement, sal_Int32 nIndex, const OUString* pNewElName)
+{
+ // extract the form component
+ if (aElement.getValueType().getTypeClass() != TypeClass_INTERFACE)
+ {
+ throw css::lang::IllegalArgumentException();
+ }
+
+ Reference< css::form::XFormComponent > xElement(aElement, UNO_QUERY);
+ if (!xElement.is())
+ {
+ throw css::lang::IllegalArgumentException();
+ }
+
+ // for the name we need the propset
+ Reference< css::beans::XPropertySet > xElementSet(xElement, UNO_QUERY);
+ if (!xElementSet.is())
+ {
+ throw css::lang::IllegalArgumentException();
+ }
+ OUString sName;
+ try
+ {
+ if (pNewElName)
+ xElementSet->setPropertyValue(PROPERTY_NAME, Any(*pNewElName));
+
+ xElementSet->getPropertyValue(PROPERTY_NAME) >>= sName;
+ }
+ catch(Exception&)
+ {
+ // the set didn't support the name prop
+ throw css::lang::IllegalArgumentException();
+ }
+
+ // check the index
+ OSL_ASSERT(nIndex >= 0);
+ if (sal::static_int_cast< sal_uInt32 >(nIndex) > m_aChildren.size())
+ nIndex = m_aChildren.size();
+
+ OSL_ENSURE(m_aChildren.size() == m_aChildNames.size(), "SAL_CALL SbaXFormAdapter::implInsert : inconsistent container state !");
+ m_aChildren.insert(m_aChildren.begin() + nIndex, xElement);
+ m_aChildNames.insert(m_aChildNames.begin() + nIndex, sName);
+
+ // listen for a change of the name
+ xElementSet->addPropertyChangeListener(PROPERTY_NAME, static_cast<css::beans::XPropertyChangeListener*>(this));
+
+ // we are now the parent of the new element
+ xElement->setParent(static_cast<css::container::XContainer*>(this));
+
+ // notify the container listeners
+ css::container::ContainerEvent aEvt;
+ aEvt.Source = *this;
+ aEvt.Accessor <<= nIndex;
+ aEvt.Element <<= xElement;
+ m_aContainerListeners.notifyEach( &XContainerListener::elementInserted, aEvt );
+}
+
+sal_Int32 SbaXFormAdapter::implGetPos(const OUString& rName)
+{
+ std::vector< OUString>::const_iterator aIter = std::find( m_aChildNames.begin(),
+ m_aChildNames.end(),
+ rName);
+
+ if(aIter != m_aChildNames.end())
+ return aIter - m_aChildNames.begin();
+
+ return -1;
+}
+
+void SAL_CALL SbaXFormAdapter::insertByName(const OUString& aName, const Any& aElement)
+{
+ implInsert(aElement, m_aChildren.size(), &aName);
+}
+
+void SAL_CALL SbaXFormAdapter::removeByName(const OUString& Name)
+{
+ sal_Int32 nPos = implGetPos(Name);
+ if (-1 == nPos)
+ {
+ throw css::container::NoSuchElementException();
+ }
+ removeByIndex(nPos);
+}
+
+// css::container::XNameReplace
+void SAL_CALL SbaXFormAdapter::replaceByName(const OUString& aName, const Any& aElement)
+{
+ sal_Int32 nPos = implGetPos(aName);
+ if (-1 == nPos)
+ {
+ throw css::container::NoSuchElementException();
+ }
+ replaceByIndex(nPos, aElement);
+}
+
+// css::container::XNameAccess
+Any SAL_CALL SbaXFormAdapter::getByName(const OUString& aName)
+{
+ sal_Int32 nPos = implGetPos(aName);
+ if (-1 == nPos)
+ {
+ throw css::container::NoSuchElementException();
+ }
+ return Any(m_aChildren[nPos]);
+}
+
+Sequence< OUString > SAL_CALL SbaXFormAdapter::getElementNames()
+{
+ return Sequence< OUString >(m_aChildNames.data(), m_aChildNames.size());
+}
+
+sal_Bool SAL_CALL SbaXFormAdapter::hasByName(const OUString& aName)
+{
+ return (-1 != implGetPos(aName));
+}
+
+// css::container::XElementAccess
+Type SAL_CALL SbaXFormAdapter::getElementType()
+{
+ return cppu::UnoType<css::form::XFormComponent>::get();
+}
+
+sal_Bool SAL_CALL SbaXFormAdapter::hasElements()
+{
+ return !m_aChildren.empty();
+}
+
+// css::container::XIndexContainer
+void SAL_CALL SbaXFormAdapter::insertByIndex(sal_Int32 _rIndex, const Any& Element)
+{
+ if ( ( _rIndex < 0 ) || ( o3tl::make_unsigned(_rIndex) >= m_aChildren.size() ) )
+ throw css::lang::IndexOutOfBoundsException();
+ implInsert(Element, _rIndex);
+}
+
+void SAL_CALL SbaXFormAdapter::removeByIndex(sal_Int32 _rIndex)
+{
+ if ( ( _rIndex < 0 ) || ( o3tl::make_unsigned(_rIndex) >= m_aChildren.size() ) )
+ throw css::lang::IndexOutOfBoundsException();
+
+ Reference< css::form::XFormComponent > xAffected = *(m_aChildren.begin() + _rIndex);
+
+ OSL_ENSURE(m_aChildren.size() == m_aChildNames.size(), "SAL_CALL SbaXFormAdapter::removeByIndex : inconsistent container state !");
+ m_aChildren.erase(m_aChildren.begin() + _rIndex);
+ m_aChildNames.erase(m_aChildNames.begin() + _rIndex);
+
+ // no need to listen anymore
+ Reference< css::beans::XPropertySet > xAffectedSet(xAffected, UNO_QUERY);
+ xAffectedSet->removePropertyChangeListener(PROPERTY_NAME, static_cast<css::beans::XPropertyChangeListener*>(this));
+
+ // we are no longer the parent
+ xAffected->setParent(Reference< XInterface > ());
+
+ // notify container listeners
+ css::container::ContainerEvent aEvt;
+ aEvt.Source = *this;
+ aEvt.Element <<= xAffected;
+ m_aContainerListeners.notifyEach( &XContainerListener::elementRemoved, aEvt );
+}
+
+// css::container::XIndexReplace
+void SAL_CALL SbaXFormAdapter::replaceByIndex(sal_Int32 _rIndex, const Any& Element)
+{
+ if ( ( _rIndex < 0 ) || ( o3tl::make_unsigned(_rIndex) >= m_aChildren.size() ) )
+ throw css::lang::IndexOutOfBoundsException();
+
+ // extract the form component
+ if (Element.getValueType().getTypeClass() != TypeClass_INTERFACE)
+ {
+ throw css::lang::IllegalArgumentException();
+ }
+
+ Reference< css::form::XFormComponent > xElement(Element, UNO_QUERY);
+ if (!xElement.is())
+ {
+ throw css::lang::IllegalArgumentException();
+ }
+
+ // for the name we need the propset
+ Reference< css::beans::XPropertySet > xElementSet(xElement, UNO_QUERY);
+ if (!xElementSet.is())
+ {
+ throw css::lang::IllegalArgumentException();
+ }
+ OUString sName;
+ try
+ {
+ xElementSet->getPropertyValue(PROPERTY_NAME) >>= sName;
+ }
+ catch(Exception&)
+ {
+ // the set didn't support the name prop
+ throw css::lang::IllegalArgumentException();
+ }
+
+ Reference< css::form::XFormComponent > xOld = *(m_aChildren.begin() + _rIndex);
+
+ OSL_ENSURE(m_aChildren.size() == m_aChildNames.size(), "SAL_CALL SbaXFormAdapter::replaceByIndex : inconsistent container state !");
+ *(m_aChildren.begin() + _rIndex) = xElement;
+ *(m_aChildNames.begin() + _rIndex) = sName;
+
+ // correct property change listening
+ Reference< css::beans::XPropertySet > xOldSet(xOld, UNO_QUERY);
+ xOldSet->removePropertyChangeListener(PROPERTY_NAME, static_cast<css::beans::XPropertyChangeListener*>(this));
+ xElementSet->addPropertyChangeListener(PROPERTY_NAME, static_cast<css::beans::XPropertyChangeListener*>(this));
+
+ // parent reset
+ xOld->setParent(Reference< XInterface > ());
+ xElement->setParent(static_cast<css::container::XContainer*>(this));
+
+ // notify container listeners
+ css::container::ContainerEvent aEvt;
+ aEvt.Source = *this;
+ aEvt.Accessor <<= _rIndex;
+ aEvt.Element <<= xElement;
+ aEvt.ReplacedElement <<= xOld;
+
+ m_aContainerListeners.notifyEach( &XContainerListener::elementReplaced, aEvt );
+}
+
+// css::container::XIndexAccess
+sal_Int32 SAL_CALL SbaXFormAdapter::getCount()
+{
+ return m_aChildren.size();
+}
+
+Any SAL_CALL SbaXFormAdapter::getByIndex(sal_Int32 _rIndex)
+{
+ if ( ( _rIndex < 0 ) || ( o3tl::make_unsigned(_rIndex) >= m_aChildren.size() ) )
+ throw css::lang::IndexOutOfBoundsException();
+
+ Reference< css::form::XFormComponent > xElement = *(m_aChildren.begin() + _rIndex);
+ return Any(xElement);
+}
+
+// css::container::XContainer
+void SAL_CALL SbaXFormAdapter::addContainerListener(const Reference< css::container::XContainerListener >& xListener)
+{
+ m_aContainerListeners.addInterface(xListener);
+}
+
+void SAL_CALL SbaXFormAdapter::removeContainerListener(const Reference< css::container::XContainerListener >& xListener)
+{
+ m_aContainerListeners.removeInterface(xListener);
+}
+
+// css::container::XEnumerationAccess
+Reference< css::container::XEnumeration > SAL_CALL SbaXFormAdapter::createEnumeration()
+{
+ return new ::comphelper::OEnumerationByName(this);
+}
+
+// css::beans::XPropertyChangeListener
+void SAL_CALL SbaXFormAdapter::propertyChange(const css::beans::PropertyChangeEvent& evt)
+{
+ if (evt.PropertyName != PROPERTY_NAME)
+ return;
+
+ std::vector< css::uno::Reference< css::form::XFormComponent > >::const_iterator aIter = std::find_if( m_aChildren.begin(),
+ m_aChildren.end(),
+ [&evt](css::uno::Reference< css::uno::XInterface > const & x) { return x == evt.Source; });
+
+ if(aIter != m_aChildren.end())
+ {
+ sal_Int32 nPos = aIter - m_aChildren.begin();
+ OSL_ENSURE(*(m_aChildNames.begin() + nPos) == ::comphelper::getString(evt.OldValue), "SAL_CALL SbaXFormAdapter::propertyChange : object has a wrong name !");
+ *(m_aChildNames.begin() + nPos) = ::comphelper::getString(evt.NewValue);
+ }
+}
+
+// css::lang::XEventListener
+void SAL_CALL SbaXFormAdapter::disposing(const css::lang::EventObject& Source)
+{
+ // was it our main form ?
+ if (Source.Source == m_xMainForm)
+ dispose();
+
+ std::vector< css::uno::Reference< css::form::XFormComponent > >::const_iterator aIter = std::find_if( m_aChildren.begin(),
+ m_aChildren.end(),
+ [&Source](css::uno::Reference< css::uno::XInterface > const & x) { return x == Source.Source; });
+ if(aIter != m_aChildren.end())
+ removeByIndex(aIter - m_aChildren.begin());
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/browser/genericcontroller.cxx b/dbaccess/source/ui/browser/genericcontroller.cxx
new file mode 100644
index 000000000..a4b3936b1
--- /dev/null
+++ b/dbaccess/source/ui/browser/genericcontroller.cxx
@@ -0,0 +1,1217 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <dbaccess/genericcontroller.hxx>
+#include <browserids.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/weld.hxx>
+#include <toolkit/helper/vclunohelper.hxx>
+#include <dbaccess/dataview.hxx>
+#include <tools/diagnose_ex.h>
+#include <osl/diagnose.h>
+#include <vcl/stdtext.hxx>
+#include <framework/titlehelper.hxx>
+#include <connectivity/dbtools.hxx>
+#include <comphelper/sequence.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <com/sun/star/sdbc/XDataSource.hpp>
+#include <com/sun/star/sdb/DatabaseContext.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/util/URLTransformer.hpp>
+#include <com/sun/star/util/XCloseable.hpp>
+
+#include <com/sun/star/ui/XSidebarProvider.hpp>
+#include <sfx2/userinputinterception.hxx>
+
+#include <datasourceconnector.hxx>
+#include <com/sun/star/frame/FrameSearchFlag.hpp>
+#include <com/sun/star/frame/status/Visibility.hpp>
+#include <com/sun/star/frame/XUntitledNumbers.hpp>
+#include <com/sun/star/util/XModifiable.hpp>
+#include <rtl/ustring.hxx>
+#include <sal/log.hxx>
+#include <limits>
+#include <unordered_map>
+#include <set>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::frame;
+using namespace ::com::sun::star::frame::status;
+using namespace ::com::sun::star::util;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::sdb;
+using namespace ::com::sun::star::task;
+using namespace ::com::sun::star::awt;
+using namespace ::com::sun::star::ui;
+using namespace ::dbtools;
+using namespace ::comphelper;
+
+#define ALL_FEATURES -1
+
+typedef std::unordered_map< sal_Int16, sal_Int16 > CommandHashMap;
+
+namespace dbaui
+{
+
+namespace {
+
+// UserDefinedFeatures
+class UserDefinedFeatures
+{
+public:
+ explicit UserDefinedFeatures( const Reference< XController >& _rxController );
+
+ void execute( const URL& _rFeatureURL, const Sequence< PropertyValue>& _rArgs );
+
+private:
+ css::uno::WeakReference< XController > m_aController;
+};
+
+}
+
+UserDefinedFeatures::UserDefinedFeatures( const Reference< XController >& _rxController )
+ :m_aController( _rxController )
+{
+}
+
+void UserDefinedFeatures::execute( const URL& _rFeatureURL, const Sequence< PropertyValue>& _rArgs )
+{
+ try
+ {
+ Reference< XController > xController( Reference< XController >(m_aController), UNO_SET_THROW );
+ Reference< XDispatchProvider > xDispatchProvider( xController->getFrame(), UNO_QUERY_THROW );
+ Reference< XDispatch > xDispatch( xDispatchProvider->queryDispatch(
+ _rFeatureURL,
+ "_self",
+ FrameSearchFlag::AUTO
+ ) );
+
+ if ( xDispatch == xController )
+ {
+ SAL_WARN("dbaccess.ui", "UserDefinedFeatures::execute: the controller shouldn't be the dispatcher here!" );
+ xDispatch.clear();
+ }
+
+ if ( xDispatch.is() )
+ xDispatch->dispatch( _rFeatureURL, _rArgs );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+}
+
+// OGenericUnoController_Data
+struct OGenericUnoController_Data
+{
+ ::sfx2::UserInputInterception m_aUserInputInterception;
+ UserDefinedFeatures m_aUserDefinedFeatures;
+
+ OGenericUnoController_Data( OGenericUnoController& _rController, ::osl::Mutex& _rMutex )
+ :m_aUserInputInterception( _rController, _rMutex )
+ ,m_aUserDefinedFeatures( _rController.getXController() )
+ {
+ }
+};
+
+// OGenericUnoController
+OGenericUnoController::OGenericUnoController(const Reference< XComponentContext >& _rM)
+ :OGenericUnoController_Base( getMutex() )
+ ,m_pView(nullptr)
+#ifdef DBG_UTIL
+ ,m_bDescribingSupportedFeatures( false )
+#endif
+ ,m_aAsyncInvalidateAll(LINK(this, OGenericUnoController, OnAsyncInvalidateAll))
+ ,m_aAsyncCloseTask(LINK(this, OGenericUnoController, OnAsyncCloseTask))
+ ,m_xContext(_rM)
+ ,m_aCurrentFrame( *this )
+ ,m_bPreview(false)
+ ,m_bReadOnly(false)
+ ,m_bCurrentlyModified(false)
+ ,m_bExternalTitle(false)
+{
+ osl_atomic_increment( &m_refCount );
+ {
+ m_pData.reset( new OGenericUnoController_Data( *this, getMutex() ) );
+ }
+ osl_atomic_decrement( &m_refCount );
+
+
+ try
+ {
+ m_xUrlTransformer = URLTransformer::create(_rM);
+ }
+ catch(Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+}
+
+OGenericUnoController::~OGenericUnoController()
+{
+
+}
+
+bool OGenericUnoController::Construct(vcl::Window* /*pParent*/)
+{
+ OSL_ENSURE( getView(), "the view is NULL!" );
+
+ if ( getView() )
+ {
+ getView()->Construct();
+ getView()->Show();
+ }
+
+ m_aSupportedFeatures.clear();
+ fillSupportedFeatures();
+
+ // create the database context
+ OSL_ENSURE(getORB().is(), "OGenericUnoController::Construct need a service factory!");
+ try
+ {
+ m_xDatabaseContext = DatabaseContext::create(getORB());
+ }
+ catch(const Exception&)
+ {
+ SAL_WARN("dbaccess.ui","OGenericUnoController::Construct: could not create (or start listening at) the database context!");
+ // at least notify the user. Though the whole component does not make any sense without the database context ...
+ ShowServiceNotAvailableError(getFrameWeld(), u"com.sun.star.sdb.DatabaseContext", true);
+ }
+
+ return true;
+}
+
+IMPL_LINK_NOARG(OGenericUnoController, OnAsyncInvalidateAll, void*, void)
+{
+ if ( !OGenericUnoController_Base::rBHelper.bInDispose && !OGenericUnoController_Base::rBHelper.bDisposed )
+ InvalidateFeature_Impl();
+}
+
+void OGenericUnoController::impl_initialize()
+{
+}
+
+void SAL_CALL OGenericUnoController::initialize( const Sequence< Any >& aArguments )
+{
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( getMutex() );
+
+ Reference< XFrame > xFrame;
+
+ PropertyValue aValue;
+ const Any* pIter = aArguments.getConstArray();
+ const Any* pEnd = pIter + aArguments.getLength();
+
+ for ( ; pIter != pEnd; ++pIter )
+ {
+ if ( ( *pIter >>= aValue ) && aValue.Name == "Frame" )
+ {
+ xFrame.set(aValue.Value,UNO_QUERY_THROW);
+ }
+ else if ( ( *pIter >>= aValue ) && aValue.Name == "Preview" )
+ {
+ aValue.Value >>= m_bPreview;
+ m_bReadOnly = true;
+ }
+ }
+ try
+ {
+ if ( !xFrame.is() )
+ throw IllegalArgumentException("need a frame", *this, 1 );
+
+ Reference<XWindow> xParent = xFrame->getContainerWindow();
+ VclPtr<vcl::Window> pParentWin = VCLUnoHelper::GetWindow(xParent);
+ if (!pParentWin)
+ {
+ throw IllegalArgumentException("Parent window is null", *this, 1 );
+ }
+
+ m_aInitParameters.assign( aArguments );
+ Construct( pParentWin );
+
+ ODataView* pView = getView();
+ if ( !pView )
+ throw RuntimeException("unable to create a view", *this );
+
+ if ( m_bReadOnly || m_bPreview )
+ pView->EnableInput( false );
+
+ impl_initialize();
+ }
+ catch(Exception&)
+ {
+ // no one clears my view if I won't
+ m_pView = nullptr;
+ throw;
+ }
+}
+
+void SAL_CALL OGenericUnoController::acquire( ) noexcept
+{
+ OGenericUnoController_Base::acquire();
+}
+
+void SAL_CALL OGenericUnoController::release( ) noexcept
+{
+ OGenericUnoController_Base::release();
+}
+
+void OGenericUnoController::startFrameListening( const Reference< XFrame >& _rxFrame )
+{
+ if ( _rxFrame.is() )
+ _rxFrame->addFrameActionListener( this );
+}
+
+void OGenericUnoController::stopFrameListening( const Reference< XFrame >& _rxFrame )
+{
+ if ( _rxFrame.is() )
+ _rxFrame->removeFrameActionListener( this );
+}
+
+void OGenericUnoController::disposing(const EventObject& Source)
+{
+ // our frame ?
+ if ( Source.Source == getFrame() )
+ stopFrameListening( getFrame() );
+}
+
+void OGenericUnoController::modified(const EventObject& aEvent)
+{
+ ::osl::MutexGuard aGuard( getMutex() );
+ if ( !isDataSourceReadOnly() )
+ {
+ Reference<XModifiable> xModi(aEvent.Source,UNO_QUERY);
+ if ( xModi.is() )
+ m_bCurrentlyModified = xModi->isModified(); // can only be reset by save
+ else
+ m_bCurrentlyModified = true;
+ }
+ InvalidateFeature(ID_BROWSER_SAVEDOC);
+ InvalidateFeature(ID_BROWSER_UNDO);
+}
+
+Reference< XWindow > SAL_CALL OGenericUnoController::getComponentWindow()
+{
+ SolarMutexGuard g;
+ return VCLUnoHelper::GetInterface( getView() );
+}
+
+Reference<XSidebarProvider> SAL_CALL OGenericUnoController::getSidebar()
+{
+ return nullptr;
+}
+
+OUString SAL_CALL OGenericUnoController::getViewControllerName()
+{
+ return "Default";
+}
+
+Sequence< PropertyValue > SAL_CALL OGenericUnoController::getCreationArguments()
+{
+ // currently we do not support any creation args, so anything passed to XModel2::createViewController would be
+ // lost, so we can equally return an empty sequence here
+ return Sequence< PropertyValue >();
+}
+
+void OGenericUnoController::attachFrame( const Reference< XFrame >& _rxFrame )
+{
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( getMutex() );
+
+ stopFrameListening( m_aCurrentFrame.getFrame() );
+ Reference< XFrame > xFrame = m_aCurrentFrame.attachFrame( _rxFrame );
+ startFrameListening( xFrame );
+
+ loadMenu( xFrame );
+
+ if ( getView() )
+ getView()->attachFrame( xFrame );
+}
+
+namespace
+{
+ typedef std::vector< Any > States;
+
+ void lcl_notifyMultipleStates( XStatusListener& _rListener, FeatureStateEvent& _rEvent, const States& _rStates )
+ {
+ for (auto const& elem : _rStates)
+ {
+ _rEvent.State = elem;
+ _rListener.statusChanged( _rEvent );
+ }
+ }
+
+ void lcl_collectStates( const FeatureState& _rFeatureState, States& _out_rStates )
+ {
+ // order matters, due to a bug in framework which resets the check state when any non-boolean event
+ // arrives
+ // #i68215# is the bug to (re-)introduce this "ordered" notification here
+ // #i67882# is the bug which was caused by the real fix which we did in framework
+ // #i68216# is the bug which requests to fix the code in Draw which relies on
+ // framework's implementation details
+ if ( !!_rFeatureState.sTitle )
+ _out_rStates.push_back( Any( *_rFeatureState.sTitle ) );
+ if ( !!_rFeatureState.bChecked )
+ _out_rStates.push_back( Any( *_rFeatureState.bChecked ) );
+ if ( !!_rFeatureState.bInvisible )
+ _out_rStates.push_back( Any( Visibility( !*_rFeatureState.bInvisible ) ) );
+ if ( _rFeatureState.aValue.hasValue() )
+ _out_rStates.push_back( _rFeatureState.aValue );
+ if ( _out_rStates.empty() )
+ _out_rStates.emplace_back( );
+ }
+}
+
+void OGenericUnoController::ImplBroadcastFeatureState(const OUString& _rFeature, const Reference< XStatusListener > & xListener, bool _bIgnoreCache)
+{
+ sal_uInt16 nFeat = m_aSupportedFeatures[ _rFeature ].nFeatureId;
+ FeatureState aFeatState( GetState( nFeat ) );
+
+ FeatureState& rCachedState = m_aStateCache[nFeat]; // creates if necessary
+ if ( !_bIgnoreCache )
+ {
+ // check if we really need to notify the listeners : this method may be called much more often than needed, so check
+ // the cached state of the feature
+ bool bAlreadyCached = ( m_aStateCache.find(nFeat) != m_aStateCache.end() );
+ if ( bAlreadyCached )
+ if ( ( rCachedState.bEnabled == aFeatState.bEnabled )
+ && ( rCachedState.bChecked == aFeatState.bChecked )
+ && ( rCachedState.bInvisible == aFeatState.bInvisible )
+ && ( rCachedState.sTitle == aFeatState.sTitle )
+ )
+ return;
+ }
+ rCachedState = aFeatState;
+
+ FeatureStateEvent aEvent;
+ aEvent.FeatureURL.Complete = _rFeature;
+ if (m_xUrlTransformer.is())
+ m_xUrlTransformer->parseStrict(aEvent.FeatureURL);
+ aEvent.Source = static_cast<XDispatch*>(this);
+ aEvent.IsEnabled = aFeatState.bEnabled;
+
+ // collect all states to be notified
+ States aStates;
+ lcl_collectStates( aFeatState, aStates );
+
+ // a special listener ?
+ if ( xListener.is() )
+ lcl_notifyMultipleStates( *xListener, aEvent, aStates );
+ else
+ { // no -> iterate through all listeners responsible for the URL
+ std::set<OUString> aFeatureCommands;
+ for( const auto& rFeature : m_aSupportedFeatures )
+ {
+ if( rFeature.second.nFeatureId == nFeat )
+ aFeatureCommands.insert( rFeature.first );
+ }
+
+ // it is possible that listeners are registered or revoked while
+ // we are notifying them, so we must use a copy of m_arrStatusListener, not
+ // m_arrStatusListener itself
+ Dispatch aNotifyLoop( m_arrStatusListener );
+
+ for (auto const& elem : aNotifyLoop)
+ {
+ if ( aFeatureCommands.find( elem.aURL.Complete ) != aFeatureCommands.end() )
+ {
+ aEvent.FeatureURL = elem.aURL;
+ lcl_notifyMultipleStates( *elem.xListener, aEvent, aStates );
+ }
+ }
+ }
+
+}
+
+bool OGenericUnoController::isFeatureSupported( sal_Int32 _nId )
+{
+ SupportedFeatures::const_iterator aFeaturePos = std::find_if(
+ m_aSupportedFeatures.begin(),
+ m_aSupportedFeatures.end(),
+ CompareFeatureById(_nId)
+ );
+
+ return ( m_aSupportedFeatures.end() != aFeaturePos && !aFeaturePos->first.isEmpty());
+}
+
+void OGenericUnoController::InvalidateFeature_Impl()
+{
+ bool bEmpty = true;
+ FeatureListener aNextFeature;
+ {
+ ::osl::MutexGuard aGuard( m_aFeatureMutex);
+ bEmpty = m_aFeaturesToInvalidate.empty();
+ if (!bEmpty)
+ aNextFeature = m_aFeaturesToInvalidate.front();
+ }
+ while(!bEmpty)
+ {
+ if ( ALL_FEATURES == aNextFeature.nId )
+ {
+ InvalidateAll_Impl();
+ break;
+ }
+ else
+ {
+ SupportedFeatures::const_iterator aFeaturePos = std::find_if(
+ m_aSupportedFeatures.begin(),
+ m_aSupportedFeatures.end(),
+ CompareFeatureById( aNextFeature.nId )
+ );
+
+#if OSL_DEBUG_LEVEL > 0
+ if ( m_aSupportedFeatures.end() == aFeaturePos )
+ {
+ SAL_WARN( "dbaccess.ui", "OGenericUnoController::InvalidateFeature_Impl: feature id "
+ << aNextFeature.nId
+ << " has been invalidated, but is not supported!" );
+ }
+#endif
+ if ( m_aSupportedFeatures.end() != aFeaturePos )
+ // we really know this feature
+ ImplBroadcastFeatureState( aFeaturePos->first, aNextFeature.xListener, aNextFeature.bForceBroadcast );
+ }
+
+ ::osl::MutexGuard aGuard( m_aFeatureMutex);
+ m_aFeaturesToInvalidate.pop_front();
+ bEmpty = m_aFeaturesToInvalidate.empty();
+ if (!bEmpty)
+ aNextFeature = m_aFeaturesToInvalidate.front();
+ }
+}
+
+void OGenericUnoController::ImplInvalidateFeature( sal_Int32 _nId, const Reference< XStatusListener >& _xListener, bool _bForceBroadcast )
+{
+#if OSL_DEBUG_LEVEL > 0
+ if ( _nId != -1 )
+ {
+ auto isSupportedFeature = std::any_of(
+ m_aSupportedFeatures.begin(),
+ m_aSupportedFeatures.end(),
+ CompareFeatureById( _nId )
+ );
+ OSL_ENSURE( isSupportedFeature, "OGenericUnoController::ImplInvalidateFeature: invalidating an unsupported feature is suspicious, at least!" );
+ }
+#endif
+
+ FeatureListener aListener;
+ aListener.nId = _nId;
+ aListener.xListener = _xListener;
+ aListener.bForceBroadcast = _bForceBroadcast;
+
+ bool bWasEmpty;
+ {
+ ::osl::MutexGuard aGuard( m_aFeatureMutex );
+ bWasEmpty = m_aFeaturesToInvalidate.empty();
+ m_aFeaturesToInvalidate.push_back( aListener );
+ }
+
+ if ( bWasEmpty )
+ m_aAsyncInvalidateAll.Call();
+}
+
+void OGenericUnoController::InvalidateFeature(sal_uInt16 _nId, const Reference< XStatusListener > & _xListener, bool _bForceBroadcast)
+{
+ ImplInvalidateFeature( _nId, _xListener, _bForceBroadcast );
+}
+
+void OGenericUnoController::InvalidateAll()
+{
+ ImplInvalidateFeature( ALL_FEATURES, nullptr, true );
+}
+
+void OGenericUnoController::InvalidateAll_Impl()
+{
+ // invalidate all supported features
+ for (auto const& supportedFeature : m_aSupportedFeatures)
+ ImplBroadcastFeatureState( supportedFeature.first, nullptr, true );
+
+ {
+ ::osl::MutexGuard aGuard( m_aFeatureMutex);
+ OSL_ENSURE(m_aFeaturesToInvalidate.size(), "OGenericUnoController::InvalidateAll_Impl: to be called from within InvalidateFeature_Impl only!");
+ m_aFeaturesToInvalidate.pop_front();
+ if(!m_aFeaturesToInvalidate.empty())
+ m_aAsyncInvalidateAll.Call();
+ }
+}
+
+Reference< XDispatch > OGenericUnoController::queryDispatch(const URL& aURL, const OUString& aTargetFrameName, sal_Int32 nSearchFlags)
+{
+ Reference< XDispatch > xReturn;
+
+ OSL_PRECOND( !m_aSupportedFeatures.empty(), "OGenericUnoController::queryDispatch: shouldn't this be filled at construction time?" );
+ if ( m_aSupportedFeatures.empty() )
+ fillSupportedFeatures();
+
+ // URL's we can handle ourself?
+ if ( aURL.Complete == ".uno:FormSlots/ConfirmDeletion"
+ || ( ( m_aSupportedFeatures.find( aURL.Complete ) != m_aSupportedFeatures.end() )
+ && !isUserDefinedFeature( aURL.Complete )
+ )
+ )
+ {
+ xReturn = this;
+ }
+ // no? -> ask the slave dispatcher
+ else if ( m_xSlaveDispatcher.is() )
+ {
+ xReturn = m_xSlaveDispatcher->queryDispatch(aURL, aTargetFrameName, nSearchFlags);
+ }
+
+ // outta here
+ return xReturn;
+}
+
+Sequence< Reference< XDispatch > > OGenericUnoController::queryDispatches(const Sequence< DispatchDescriptor >& aDescripts)
+{
+ Sequence< Reference< XDispatch > > aReturn;
+ sal_Int32 nLen = aDescripts.getLength();
+ if ( nLen )
+ {
+ aReturn.realloc( nLen );
+ Reference< XDispatch >* pReturn = aReturn.getArray();
+ const Reference< XDispatch >* pReturnEnd = aReturn.getArray() + nLen;
+ const DispatchDescriptor* pDescripts = aDescripts.getConstArray();
+
+ for ( ; pReturn != pReturnEnd; ++ pReturn, ++pDescripts )
+ {
+ *pReturn = queryDispatch( pDescripts->FeatureURL, pDescripts->FrameName, pDescripts->SearchFlags );
+ }
+ }
+
+ return aReturn;
+}
+
+Reference< XDispatchProvider > OGenericUnoController::getSlaveDispatchProvider()
+{
+ return m_xSlaveDispatcher;
+}
+
+void OGenericUnoController::setSlaveDispatchProvider(const Reference< XDispatchProvider > & _xNewProvider)
+{
+ m_xSlaveDispatcher = _xNewProvider;
+}
+
+Reference< XDispatchProvider > OGenericUnoController::getMasterDispatchProvider()
+{
+ return m_xMasterDispatcher;
+}
+
+void OGenericUnoController::setMasterDispatchProvider(const Reference< XDispatchProvider > & _xNewProvider)
+{
+ m_xMasterDispatcher = _xNewProvider;
+}
+
+void OGenericUnoController::dispatch(const URL& _aURL, const Sequence< PropertyValue >& aArgs)
+{
+ SolarMutexGuard aSolarGuard;
+ // The SolarMutex is not locked anymore when the framework calls into
+ // here. So, lock it ourself. The real solution would be to lock it only in the places
+ // where it's needed, but a) this might turn out difficult, since we then also need to care
+ // for locking in the proper order (SolarMutex and m_aMutex), and b) this would be too many places
+ // for the time frame of the fix.
+ // #i52602#
+ executeChecked(_aURL,aArgs);
+}
+
+void OGenericUnoController::addStatusListener(const Reference< XStatusListener > & aListener, const URL& _rURL)
+{
+ // parse the URL now and here, this saves later parsing in each notification round
+ URL aParsedURL( _rURL );
+ if ( m_xUrlTransformer.is() )
+ m_xUrlTransformer->parseStrict( aParsedURL );
+
+ // remember the listener together with the URL
+ m_arrStatusListener.insert( m_arrStatusListener.end(), DispatchTarget( aParsedURL, aListener ) );
+
+ // initially broadcast the state
+ ImplBroadcastFeatureState( aParsedURL.Complete, aListener, true );
+ // force the new state to be broadcast to the new listener
+}
+
+void OGenericUnoController::removeStatusListener(const Reference< XStatusListener > & aListener, const URL& _rURL)
+{
+ if (_rURL.Complete.isEmpty())
+ {
+ m_arrStatusListener.erase(std::remove_if(m_arrStatusListener.begin(), m_arrStatusListener.end(),
+ [&aListener](const DispatchTarget& rCurrent) { return rCurrent.xListener == aListener; }),
+ m_arrStatusListener.end());
+ }
+ else
+ {
+ // remove the listener only for the given URL
+ Dispatch::iterator iterSearch = std::find_if(m_arrStatusListener.begin(), m_arrStatusListener.end(),
+ [&aListener, &_rURL](const DispatchTarget& rCurrent) {
+ return (rCurrent.xListener == aListener) && (rCurrent.aURL.Complete == _rURL.Complete); });
+ if (iterSearch != m_arrStatusListener.end())
+ m_arrStatusListener.erase(iterSearch);
+ }
+
+ OSL_PRECOND( !m_aSupportedFeatures.empty(), "OGenericUnoController::removeStatusListener: shouldn't this be filled at construction time?" );
+ if ( m_aSupportedFeatures.empty() )
+ fillSupportedFeatures();
+
+ SupportedFeatures::const_iterator aIter = m_aSupportedFeatures.find(_rURL.Complete);
+ if (aIter != m_aSupportedFeatures.end())
+ { // clear the cache for that feature
+ StateCache::const_iterator aCachePos = m_aStateCache.find( aIter->second.nFeatureId );
+ if ( aCachePos != m_aStateCache.end() )
+ m_aStateCache.erase( aCachePos );
+ }
+
+ // now remove the listener from the deque
+ ::osl::MutexGuard aGuard( m_aFeatureMutex );
+ m_aFeaturesToInvalidate.erase(
+ std::remove_if( m_aFeaturesToInvalidate.begin(),
+ m_aFeaturesToInvalidate.end(),
+ FindFeatureListener(aListener))
+ ,m_aFeaturesToInvalidate.end());
+}
+
+void OGenericUnoController::releaseNumberForComponent()
+{
+ try
+ {
+ Reference< XUntitledNumbers > xUntitledProvider(getPrivateModel(), UNO_QUERY );
+ if ( xUntitledProvider.is() )
+ xUntitledProvider->releaseNumberForComponent(static_cast<XWeak*>(this));
+ }
+ catch( const Exception& )
+ {
+ // NII
+ }
+}
+
+void OGenericUnoController::disposing()
+{
+ {
+ EventObject aDisposeEvent;
+ aDisposeEvent.Source = static_cast<XWeak*>(this);
+ Dispatch aStatusListener = m_arrStatusListener;
+ for (auto const& statusListener : aStatusListener)
+ {
+ statusListener.xListener->disposing(aDisposeEvent);
+ }
+ m_arrStatusListener.clear();
+ }
+
+ m_xDatabaseContext = nullptr;
+ {
+ ::osl::MutexGuard aGuard( m_aFeatureMutex);
+ m_aAsyncInvalidateAll.CancelCall();
+ m_aFeaturesToInvalidate.clear();
+ }
+
+ releaseNumberForComponent();
+
+ // check out from all the objects we are listening
+ // the frame
+ stopFrameListening( m_aCurrentFrame.getFrame() );
+ m_aCurrentFrame.attachFrame( nullptr );
+
+ m_xMasterDispatcher = nullptr;
+ m_xSlaveDispatcher = nullptr;
+ m_xTitleHelper.clear();
+ m_xUrlTransformer.clear();
+ m_aInitParameters.clear();
+}
+
+void SAL_CALL OGenericUnoController::addEventListener( const Reference< XEventListener >& xListener )
+{
+ // disambiguate
+ OGenericUnoController_Base::WeakComponentImplHelperBase::addEventListener( xListener );
+}
+
+void SAL_CALL OGenericUnoController::removeEventListener( const Reference< XEventListener >& xListener )
+{
+ // disambiguate
+ OGenericUnoController_Base::WeakComponentImplHelperBase::removeEventListener( xListener );
+}
+
+void OGenericUnoController::frameAction(const FrameActionEvent& aEvent)
+{
+ ::osl::MutexGuard aGuard( getMutex() );
+ if ( aEvent.Frame == m_aCurrentFrame.getFrame() )
+ m_aCurrentFrame.frameAction( aEvent.Action );
+}
+
+void OGenericUnoController::implDescribeSupportedFeature( const OUString& _rCommandURL,
+ sal_uInt16 _nFeatureId, sal_Int16 _nCommandGroup )
+{
+#ifdef DBG_UTIL
+ OSL_ENSURE( m_bDescribingSupportedFeatures, "OGenericUnoController::implDescribeSupportedFeature: bad timing for this call!" );
+#endif
+ OSL_PRECOND( _nFeatureId < ( std::numeric_limits< sal_uInt16 >::max() - 1000 ), // FIRST_USER_DEFINED_FEATURE
+ "OGenericUnoController::implDescribeSupportedFeature: invalid feature id!" );
+
+ ControllerFeature aFeature;
+ aFeature.Command = _rCommandURL;
+ aFeature.nFeatureId = _nFeatureId;
+ aFeature.GroupId = _nCommandGroup;
+
+#if OSL_DEBUG_LEVEL > 0
+ OSL_ENSURE( m_aSupportedFeatures.find( aFeature.Command ) == m_aSupportedFeatures.end(),
+ "OGenericUnoController::implDescribeSupportedFeature: this feature is already there!" );
+#endif
+ m_aSupportedFeatures[ aFeature.Command ] = aFeature;
+}
+
+void OGenericUnoController::describeSupportedFeatures()
+{
+ // add all supported features
+ implDescribeSupportedFeature( ".uno:Copy", ID_BROWSER_COPY, CommandGroup::EDIT );
+ implDescribeSupportedFeature( ".uno:Cut", ID_BROWSER_CUT, CommandGroup::EDIT );
+ implDescribeSupportedFeature( ".uno:Paste", ID_BROWSER_PASTE, CommandGroup::EDIT );
+ implDescribeSupportedFeature( ".uno:ClipboardFormatItems", ID_BROWSER_CLIPBOARD_FORMAT_ITEMS );
+ implDescribeSupportedFeature( ".uno:DSBEditDoc", ID_BROWSER_EDITDOC, CommandGroup::DOCUMENT );
+}
+
+FeatureState OGenericUnoController::GetState( sal_uInt16 _nId ) const
+{
+ FeatureState aReturn;
+ // (disabled automatically)
+
+ switch ( _nId )
+ {
+ case ID_BROWSER_UNDO:
+ case ID_BROWSER_SAVEDOC:
+ aReturn.bEnabled = true;
+ break;
+ default:
+ // for now, enable all the time
+ // TODO: we should ask the dispatcher. However, this is laborious, since you cannot ask a dispatcher
+ // directly, but need to add a status listener.
+ aReturn.bEnabled = true;
+ break;
+ }
+
+ return aReturn;
+}
+
+void OGenericUnoController::Execute( sal_uInt16 _nId, const Sequence< PropertyValue>& _rArgs )
+{
+ OSL_ENSURE( isUserDefinedFeature( _nId ),
+ "OGenericUnoController::Execute: responsible for user defined features only!" );
+
+ // user defined features can be handled by dispatch interceptors resp. protocol handlers only.
+ // So, we need to do a queryDispatch, and dispatch the URL
+ m_pData->m_aUserDefinedFeatures.execute( getURLForId( _nId ), _rArgs );
+}
+
+URL OGenericUnoController::getURLForId(sal_Int32 _nId) const
+{
+ URL aReturn;
+ if ( m_xUrlTransformer.is() )
+ {
+ SupportedFeatures::const_iterator aIter = std::find_if(
+ m_aSupportedFeatures.begin(),
+ m_aSupportedFeatures.end(),
+ CompareFeatureById( _nId )
+ );
+
+ if ( m_aSupportedFeatures.end() != aIter && !aIter->first.isEmpty() )
+ {
+ aReturn.Complete = aIter->first;
+ m_xUrlTransformer->parseStrict( aReturn );
+ }
+ }
+ return aReturn;
+}
+
+bool OGenericUnoController::isUserDefinedFeature( const sal_uInt16 _nFeatureId )
+{
+ return
+ (_nFeatureId >= ( std::numeric_limits< sal_uInt16 >::max() - 1000 )) // test if >= FIRST_USER_DEFINED_FEATURE
+ &&
+ ( _nFeatureId < (std::numeric_limits< sal_uInt16 >::max())) // test if < LAST_USER_DEFINED_FEATURE
+ ;
+}
+
+bool OGenericUnoController::isUserDefinedFeature( const OUString& _rFeatureURL ) const
+{
+ SupportedFeatures::const_iterator pos = m_aSupportedFeatures.find( _rFeatureURL );
+ OSL_PRECOND( pos != m_aSupportedFeatures.end(),
+ "OGenericUnoController::isUserDefinedFeature: this is no supported feature at all!" );
+
+ return ( pos != m_aSupportedFeatures.end() ) && isUserDefinedFeature( pos->second.nFeatureId );
+}
+
+sal_Bool SAL_CALL OGenericUnoController::supportsService(const OUString& ServiceName)
+{
+ return cppu::supportsService(this, ServiceName);
+}
+
+void OGenericUnoController::startConnectionListening(const Reference< XConnection >& _rxConnection)
+{
+ // we have to remove ourself before disposing the connection
+ Reference< XComponent > xComponent(_rxConnection, UNO_QUERY);
+ if (xComponent.is())
+ xComponent->addEventListener(static_cast<XFrameActionListener*>(this));
+}
+
+void OGenericUnoController::stopConnectionListening(const Reference< XConnection >& _rxConnection)
+{
+ // we have to remove ourself before disposing the connection
+ Reference< XComponent > xComponent(_rxConnection, UNO_QUERY);
+ if (xComponent.is())
+ xComponent->removeEventListener(static_cast<XFrameActionListener*>(this));
+}
+
+Reference< XConnection > OGenericUnoController::connect( const Reference< XDataSource>& _xDataSource )
+{
+ weld::WaitObject aWaitCursor(getFrameWeld());
+
+ ODatasourceConnector aConnector( getORB(), getFrameWeld(), OUString() );
+ Reference< XConnection > xConnection = aConnector.connect( _xDataSource, nullptr );
+ startConnectionListening( xConnection );
+
+ return xConnection;
+}
+
+Reference< XConnection > OGenericUnoController::connect( const OUString& _rDataSourceName,
+ const OUString& _rContextInformation, ::dbtools::SQLExceptionInfo* _pErrorInfo )
+{
+ weld::WaitObject aWaitCursor(getFrameWeld());
+
+ ODatasourceConnector aConnector( getORB(), getFrameWeld(), _rContextInformation );
+ Reference<XConnection> xConnection = aConnector.connect( _rDataSourceName, _pErrorInfo );
+ startConnectionListening( xConnection );
+
+ return xConnection;
+}
+
+void OGenericUnoController::setView( const VclPtr<ODataView> &i_rView )
+{
+ m_pView = i_rView;
+}
+
+void OGenericUnoController::clearView()
+{
+ m_pView = nullptr;
+}
+
+void OGenericUnoController::showError(const SQLExceptionInfo& _rInfo)
+{
+ ::dbtools::showError(_rInfo,VCLUnoHelper::GetInterface(getView()),getORB());
+}
+
+Reference< XLayoutManager > OGenericUnoController::getLayoutManager(const Reference< XFrame >& _xFrame)
+{
+ Reference< XPropertySet > xPropSet( _xFrame, UNO_QUERY );
+ Reference< XLayoutManager > xLayoutManager;
+ if ( xPropSet.is() )
+ {
+ try
+ {
+ xLayoutManager.set(xPropSet->getPropertyValue("LayoutManager"),UNO_QUERY);
+ }
+ catch ( Exception& )
+ {
+ }
+ }
+ return xLayoutManager;
+}
+
+void OGenericUnoController::loadMenu(const Reference< XFrame >& _xFrame)
+{
+ Reference< XLayoutManager > xLayoutManager = getLayoutManager(_xFrame);
+ if ( xLayoutManager.is() )
+ {
+ xLayoutManager->lock();
+ xLayoutManager->createElement( "private:resource/menubar/menubar" );
+ xLayoutManager->createElement( "private:resource/toolbar/toolbar" );
+ xLayoutManager->unlock();
+ xLayoutManager->doLayout();
+ }
+
+ onLoadedMenu( xLayoutManager );
+}
+
+void OGenericUnoController::onLoadedMenu(const Reference< XLayoutManager >& /*_xLayoutManager*/)
+{
+ // not interested in
+}
+
+void OGenericUnoController::closeTask()
+{
+ m_aAsyncCloseTask.Call();
+}
+
+IMPL_LINK_NOARG(OGenericUnoController, OnAsyncCloseTask, void*, void)
+{
+ if ( !OGenericUnoController_Base::rBHelper.bInDispose )
+ {
+ try
+ {
+ Reference< util::XCloseable > xCloseable( m_aCurrentFrame.getFrame(), UNO_QUERY_THROW );
+ xCloseable->close( false ); // false - holds the owner ship for this frame inside this object!
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+}
+
+Any SAL_CALL OGenericUnoController::getViewData()
+{
+ return Any();
+}
+
+void SAL_CALL OGenericUnoController::restoreViewData(const Any& /*Data*/)
+{
+}
+
+Reference< XModel > SAL_CALL OGenericUnoController::getModel()
+{
+ return Reference< XModel >();
+}
+
+Reference< XFrame > SAL_CALL OGenericUnoController::getFrame()
+{
+ ::osl::MutexGuard aGuard( getMutex() );
+ return m_aCurrentFrame.getFrame();
+}
+
+sal_Bool SAL_CALL OGenericUnoController::attachModel(const Reference< XModel > & /*xModel*/)
+{
+ SAL_WARN("dbaccess.ui", "OGenericUnoController::attachModel: not supported!" );
+ return false;
+}
+
+void OGenericUnoController::executeUnChecked(sal_uInt16 _nCommandId, const Sequence< PropertyValue >& aArgs)
+{
+ Execute(_nCommandId, aArgs);
+}
+
+void OGenericUnoController::executeUnChecked(const util::URL& _rCommand, const Sequence< PropertyValue >& aArgs)
+{
+ OSL_PRECOND( !m_aSupportedFeatures.empty(), "OGenericUnoController::executeUnChecked: shouldn't this be filled at construction time?" );
+ if ( m_aSupportedFeatures.empty() )
+ fillSupportedFeatures();
+
+ SupportedFeatures::const_iterator aIter = m_aSupportedFeatures.find( _rCommand.Complete );
+ if (aIter != m_aSupportedFeatures.end())
+ Execute( aIter->second.nFeatureId, aArgs );
+}
+
+void OGenericUnoController::executeChecked(const util::URL& _rCommand, const Sequence< PropertyValue >& aArgs)
+{
+ OSL_PRECOND( !m_aSupportedFeatures.empty(), "OGenericUnoController::executeChecked: shouldn't this be filled at construction time?" );
+ if ( m_aSupportedFeatures.empty() )
+ fillSupportedFeatures();
+
+ SupportedFeatures::const_iterator aIter = m_aSupportedFeatures.find( _rCommand.Complete );
+ if ( aIter != m_aSupportedFeatures.end() )
+ {
+ sal_uInt16 nFeatureId = aIter->second.nFeatureId;
+ if ( GetState( nFeatureId ).bEnabled )
+ Execute( nFeatureId, aArgs );
+ }
+}
+
+Reference< awt::XWindow> OGenericUnoController::getTopMostContainerWindow() const
+{
+ Reference< css::awt::XWindow> xWindow;
+
+ // get the top most window
+ Reference< XFrame > xFrame( m_aCurrentFrame.getFrame() );
+ if ( xFrame.is() )
+ {
+ xWindow = xFrame->getContainerWindow();
+
+ while ( xFrame.is() && !xFrame->isTop() )
+ {
+ xFrame = xFrame->getCreator();
+ }
+ if ( xFrame.is() )
+ xWindow = xFrame->getContainerWindow();
+ }
+ return xWindow;
+}
+
+Reference< XTitle > OGenericUnoController::impl_getTitleHelper_throw(bool bCreateIfNecessary)
+{
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( getMutex() );
+
+ if (!m_xTitleHelper.is() && bCreateIfNecessary)
+ {
+ Reference< XUntitledNumbers > xUntitledProvider(getPrivateModel(), UNO_QUERY );
+
+ m_xTitleHelper = new ::framework::TitleHelper( m_xContext, Reference< XController >(this), xUntitledProvider );
+ }
+
+ return m_xTitleHelper;
+}
+
+// XTitle
+OUString SAL_CALL OGenericUnoController::getTitle()
+{
+ ::osl::MutexGuard aGuard( getMutex() );
+ if ( m_bExternalTitle )
+ return impl_getTitleHelper_throw()->getTitle ();
+ return getPrivateTitle() + impl_getTitleHelper_throw()->getTitle ();
+}
+
+// XTitle
+void SAL_CALL OGenericUnoController::setTitle(const OUString& sTitle)
+{
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( getMutex() );
+ m_bExternalTitle = true;
+ impl_getTitleHelper_throw()->setTitle (sTitle);
+}
+
+// XTitleChangeBroadcaster
+void SAL_CALL OGenericUnoController::addTitleChangeListener(const Reference< XTitleChangeListener >& xListener)
+{
+ Reference< XTitleChangeBroadcaster > xBroadcaster(impl_getTitleHelper_throw(), UNO_QUERY);
+ if (xBroadcaster.is ())
+ xBroadcaster->addTitleChangeListener (xListener);
+}
+
+void SAL_CALL OGenericUnoController::removeTitleChangeListener(const Reference< XTitleChangeListener >& xListener)
+{
+ Reference< XTitleChangeBroadcaster > xBroadcaster(impl_getTitleHelper_throw(false), UNO_QUERY);
+ if (xBroadcaster.is ())
+ xBroadcaster->removeTitleChangeListener (xListener);
+}
+
+// XUserInputInterception
+void SAL_CALL OGenericUnoController::addKeyHandler( const Reference< XKeyHandler >& _rxHandler )
+{
+ if ( _rxHandler.is() )
+ m_pData->m_aUserInputInterception.addKeyHandler( _rxHandler );
+}
+
+void SAL_CALL OGenericUnoController::removeKeyHandler( const Reference< XKeyHandler >& _rxHandler )
+{
+ m_pData->m_aUserInputInterception.removeKeyHandler( _rxHandler );
+}
+
+void SAL_CALL OGenericUnoController::addMouseClickHandler( const Reference< XMouseClickHandler >& _rxHandler )
+{
+ if ( _rxHandler.is() )
+ m_pData->m_aUserInputInterception.addMouseClickHandler( _rxHandler );
+}
+
+void SAL_CALL OGenericUnoController::removeMouseClickHandler( const Reference< XMouseClickHandler >& _rxHandler )
+{
+ m_pData->m_aUserInputInterception.removeMouseClickHandler( _rxHandler );
+}
+
+void OGenericUnoController::executeChecked(sal_uInt16 _nCommandId, const Sequence< PropertyValue >& aArgs)
+{
+ if ( isCommandEnabled(_nCommandId) )
+ Execute(_nCommandId, aArgs);
+}
+
+bool OGenericUnoController::isCommandEnabled(sal_uInt16 _nCommandId) const
+{
+ return GetState( _nCommandId ).bEnabled;
+}
+
+bool OGenericUnoController::isDataSourceReadOnly() const
+{
+ return false;
+}
+
+Reference< XController > OGenericUnoController::getXController()
+{
+ return this;
+}
+
+bool OGenericUnoController::interceptUserInput( const NotifyEvent& _rEvent )
+{
+ return m_pData->m_aUserInputInterception.handleNotifyEvent( _rEvent );
+}
+
+bool OGenericUnoController::isCommandChecked(sal_uInt16 _nCommandId) const
+{
+ FeatureState aState = GetState( _nCommandId );
+
+ return aState.bChecked && *aState.bChecked;
+}
+
+bool OGenericUnoController::isCommandEnabled( const OUString& _rCompleteCommandURL ) const
+{
+ OSL_ENSURE( !_rCompleteCommandURL.isEmpty(), "OGenericUnoController::isCommandEnabled: Empty command url!" );
+
+ bool bIsEnabled = false;
+ SupportedFeatures::const_iterator aIter = m_aSupportedFeatures.find( _rCompleteCommandURL );
+ if ( aIter != m_aSupportedFeatures.end() )
+ bIsEnabled = isCommandEnabled( aIter->second.nFeatureId );
+
+ return bIsEnabled;
+}
+
+Sequence< ::sal_Int16 > SAL_CALL OGenericUnoController::getSupportedCommandGroups()
+{
+ CommandHashMap aCmdHashMap;
+ for (auto const& supportedFeature : m_aSupportedFeatures)
+ if ( supportedFeature.second.GroupId != CommandGroup::INTERNAL )
+ aCmdHashMap.emplace( supportedFeature.second.GroupId, 0 );
+
+ return comphelper::mapKeysToSequence( aCmdHashMap );
+}
+
+Sequence< DispatchInformation > SAL_CALL OGenericUnoController::getConfigurableDispatchInformation( ::sal_Int16 CommandGroup )
+{
+ std::vector< DispatchInformation > aInformationVector;
+ for (auto const& supportedFeature : m_aSupportedFeatures)
+ {
+ if ( sal_Int16( supportedFeature.second.GroupId ) == CommandGroup )
+ {
+ aInformationVector.push_back( supportedFeature.second );
+ }
+ }
+
+ return comphelper::containerToSequence( aInformationVector );
+}
+
+void OGenericUnoController::fillSupportedFeatures()
+{
+#ifdef DBG_UTIL
+ m_bDescribingSupportedFeatures = true;
+#endif
+ describeSupportedFeatures();
+#ifdef DBG_UTIL
+ m_bDescribingSupportedFeatures = false;
+#endif
+}
+
+void SAL_CALL OGenericUnoController::dispose()
+{
+ SolarMutexGuard aSolarGuard;
+ OGenericUnoController_Base::dispose();
+}
+
+weld::Window* OGenericUnoController::getFrameWeld() const
+{
+ return m_pView ? m_pView->GetFrameWeld() : nullptr;
+}
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/browser/sbagrid.cxx b/dbaccess/source/ui/browser/sbagrid.cxx
new file mode 100644
index 000000000..d1adbea01
--- /dev/null
+++ b/dbaccess/source/ui/browser/sbagrid.cxx
@@ -0,0 +1,1364 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <core_resource.hxx>
+
+#include <sot/exchange.hxx>
+
+#include <svx/dbaexchange.hxx>
+#include <com/sun/star/ui/dialogs/XExecutableDialog.hpp>
+
+#include <sbagrid.hxx>
+#include <dlgsize.hxx>
+#include <com/sun/star/beans/XPropertyState.hpp>
+#include <com/sun/star/form/XForm.hpp>
+#include <com/sun/star/container/XIndexContainer.hpp>
+
+#include <com/sun/star/view/XSelectionSupplier.hpp>
+#include <com/sun/star/awt/XTextComponent.hpp>
+#include <com/sun/star/sdbc/XResultSetUpdate.hpp>
+#include <tools/diagnose_ex.h>
+
+#include <svl/numuno.hxx>
+#include <toolkit/helper/vclunohelper.hxx>
+
+#include <vcl/svapp.hxx>
+
+#include <cppuhelper/queryinterface.hxx>
+#include <connectivity/dbtools.hxx>
+#include <comphelper/propertyvalue.hxx>
+#include <comphelper/types.hxx>
+#include <com/sun/star/sdbc/DataType.hpp>
+#include <com/sun/star/sdbc/SQLException.hpp>
+#include <strings.hrc>
+#include <strings.hxx>
+#include <dbexchange.hxx>
+#include <svtools/stringtransfer.hxx>
+#include <UITools.hxx>
+#include <TokenWriter.hxx>
+#include <osl/diagnose.h>
+#include <algorithm>
+
+using namespace ::com::sun::star::ui::dialogs;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::sdb;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::sdbcx;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::datatransfer;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::view;
+using namespace ::com::sun::star::form;
+using namespace ::com::sun::star::frame;
+using namespace ::com::sun::star::util;
+using namespace ::dbaui;
+using namespace ::dbtools;
+using namespace ::svx;
+using namespace ::svt;
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+com_sun_star_comp_dbu_SbaXGridControl_get_implementation(
+ css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const& )
+{
+ return cppu::acquire(new SbaXGridControl(context));
+}
+
+css::uno::Sequence<OUString> SAL_CALL SbaXGridControl::getSupportedServiceNames()
+{
+ return { "com.sun.star.form.control.InteractionGridControl", "com.sun.star.form.control.GridControl",
+ "com.sun.star.awt.UnoControl" };
+}
+
+
+// SbaXGridControl
+
+OUString SAL_CALL SbaXGridControl::getImplementationName()
+{
+ return "com.sun.star.comp.dbu.SbaXGridControl";
+}
+
+SbaXGridControl::SbaXGridControl(const Reference< XComponentContext >& _rM)
+ : FmXGridControl(_rM)
+{
+}
+
+SbaXGridControl::~SbaXGridControl()
+{
+}
+
+rtl::Reference<FmXGridPeer> SbaXGridControl::imp_CreatePeer(vcl::Window* pParent)
+{
+ rtl::Reference<FmXGridPeer> pReturn = new SbaXGridPeer(m_xContext);
+
+ // translate properties into WinBits
+ WinBits nStyle = WB_TABSTOP;
+ Reference< XPropertySet > xModelSet(getModel(), UNO_QUERY);
+ if (xModelSet.is())
+ {
+ try
+ {
+ if (::comphelper::getINT16(xModelSet->getPropertyValue(PROPERTY_BORDER)))
+ nStyle |= WB_BORDER;
+ }
+ catch(Exception&)
+ {
+ }
+
+ }
+
+ pReturn->Create(pParent, nStyle);
+ return pReturn;
+}
+
+Any SAL_CALL SbaXGridControl::queryInterface(const Type& _rType)
+{
+ Any aRet = FmXGridControl::queryInterface(_rType);
+ return aRet.hasValue() ? aRet : ::cppu::queryInterface(_rType,static_cast<css::frame::XDispatch*>(this));
+}
+
+Sequence< Type > SAL_CALL SbaXGridControl::getTypes( )
+{
+ return comphelper::concatSequences(
+ FmXGridControl::getTypes(),
+ Sequence { cppu::UnoType<css::frame::XDispatch>::get() });
+}
+
+Sequence< sal_Int8 > SAL_CALL SbaXGridControl::getImplementationId( )
+{
+ return css::uno::Sequence<sal_Int8>();
+}
+
+void SAL_CALL SbaXGridControl::createPeer(const Reference< css::awt::XToolkit > & rToolkit, const Reference< css::awt::XWindowPeer > & rParentPeer)
+{
+ FmXGridControl::createPeer(rToolkit, rParentPeer);
+
+ OSL_ENSURE(!mbCreatingPeer, "FmXGridControl::createPeer : recursion!");
+ // see the base class' createPeer for a comment on this
+
+ // TODO: why the hell this whole class does not use any mutex?
+
+ Reference< css::frame::XDispatch > xDisp(getPeer(), UNO_QUERY);
+ for (auto const& elem : m_aStatusMultiplexer)
+ {
+ if (elem.second.is() && elem.second->getLength())
+ xDisp->addStatusListener(elem.second, elem.first);
+ }
+}
+
+void SAL_CALL SbaXGridControl::dispatch(const css::util::URL& aURL, const Sequence< PropertyValue >& aArgs)
+{
+ Reference< css::frame::XDispatch > xDisp(getPeer(), UNO_QUERY);
+ if (xDisp.is())
+ xDisp->dispatch(aURL, aArgs);
+}
+
+void SAL_CALL SbaXGridControl::addStatusListener( const Reference< XStatusListener > & _rxListener, const URL& _rURL )
+{
+ ::osl::MutexGuard aGuard( GetMutex() );
+ if ( !_rxListener.is() )
+ return;
+
+ rtl::Reference<SbaXStatusMultiplexer>& xMultiplexer = m_aStatusMultiplexer[ _rURL ];
+ if ( !xMultiplexer.is() )
+ {
+ xMultiplexer = new SbaXStatusMultiplexer( *this, GetMutex() );
+ }
+
+ xMultiplexer->addInterface( _rxListener );
+ if ( getPeer().is() )
+ {
+ if ( 1 == xMultiplexer->getLength() )
+ { // the first external listener for this URL
+ Reference< XDispatch > xDisp( getPeer(), UNO_QUERY );
+ xDisp->addStatusListener( xMultiplexer, _rURL );
+ }
+ else
+ { // already have other listeners for this URL
+ _rxListener->statusChanged( xMultiplexer->getLastEvent() );
+ }
+ }
+}
+
+void SAL_CALL SbaXGridControl::removeStatusListener(const Reference< css::frame::XStatusListener > & _rxListener, const css::util::URL& _rURL)
+{
+ ::osl::MutexGuard aGuard( GetMutex() );
+
+ rtl::Reference<SbaXStatusMultiplexer>& xMultiplexer = m_aStatusMultiplexer[_rURL];
+ if (!xMultiplexer.is())
+ {
+ xMultiplexer = new SbaXStatusMultiplexer(*this,GetMutex());
+ }
+
+ if (getPeer().is() && xMultiplexer->getLength() == 1)
+ {
+ Reference< css::frame::XDispatch > xDisp(getPeer(), UNO_QUERY);
+ xDisp->removeStatusListener(xMultiplexer, _rURL);
+ }
+ xMultiplexer->removeInterface( _rxListener );
+}
+
+void SAL_CALL SbaXGridControl::dispose()
+{
+ SolarMutexGuard aGuard;
+
+ EventObject aEvt;
+ aEvt.Source = *this;
+
+ for (auto & elem : m_aStatusMultiplexer)
+ {
+ if (elem.second.is())
+ {
+ elem.second->disposeAndClear(aEvt);
+ elem.second.clear();
+ }
+ }
+ StatusMultiplexerArray().swap(m_aStatusMultiplexer);
+
+ FmXGridControl::dispose();
+}
+
+// SbaXGridPeer
+SbaXGridPeer::SbaXGridPeer(const Reference< XComponentContext >& _rM)
+: FmXGridPeer(_rM)
+,m_aStatusListeners(m_aMutex)
+{
+}
+
+SbaXGridPeer::~SbaXGridPeer()
+{
+}
+
+void SAL_CALL SbaXGridPeer::dispose()
+{
+ EventObject aEvt(*this);
+
+ m_aStatusListeners.disposeAndClear(aEvt);
+
+ FmXGridPeer::dispose();
+}
+
+void SbaXGridPeer::NotifyStatusChanged(const css::util::URL& _rUrl, const Reference< css::frame::XStatusListener > & xControl)
+{
+ VclPtr< SbaGridControl > pGrid = GetAs< SbaGridControl >();
+ if (!pGrid)
+ return;
+
+ css::frame::FeatureStateEvent aEvt;
+ aEvt.Source = *this;
+ aEvt.IsEnabled = !pGrid->IsReadOnlyDB();
+ aEvt.FeatureURL = _rUrl;
+
+ MapDispatchToBool::const_iterator aURLStatePos = m_aDispatchStates.find( classifyDispatchURL( _rUrl ) );
+ if ( m_aDispatchStates.end() != aURLStatePos )
+ aEvt.State <<= aURLStatePos->second;
+ else
+ aEvt.State <<= false;
+
+ if (xControl.is())
+ xControl->statusChanged(aEvt);
+ else
+ {
+ ::comphelper::OInterfaceContainerHelper3<css::frame::XStatusListener> * pIter
+ = m_aStatusListeners.getContainer(_rUrl);
+
+ if (pIter)
+ {
+ pIter->notifyEach( &XStatusListener::statusChanged, aEvt );
+ }
+ }
+}
+
+Any SAL_CALL SbaXGridPeer::queryInterface(const Type& _rType)
+{
+ Any aRet = ::cppu::queryInterface(_rType,static_cast<css::frame::XDispatch*>(this));
+ if(aRet.hasValue())
+ return aRet;
+ return FmXGridPeer::queryInterface(_rType);
+}
+
+Reference< css::frame::XDispatch > SAL_CALL SbaXGridPeer::queryDispatch(const css::util::URL& aURL, const OUString& aTargetFrameName, sal_Int32 nSearchFlags)
+{
+ if ( ( aURL.Complete == ".uno:GridSlots/BrowserAttribs" ) || ( aURL.Complete == ".uno:GridSlots/RowHeight" )
+ || ( aURL.Complete == ".uno:GridSlots/ColumnAttribs" ) || ( aURL.Complete == ".uno:GridSlots/ColumnWidth" )
+ )
+ {
+ return static_cast<css::frame::XDispatch*>(this);
+ }
+
+ return FmXGridPeer::queryDispatch(aURL, aTargetFrameName, nSearchFlags);
+}
+
+IMPL_LINK_NOARG( SbaXGridPeer, OnDispatchEvent, void*, void )
+{
+ VclPtr< SbaGridControl > pGrid = GetAs< SbaGridControl >();
+ if ( !pGrid ) // if this fails, we were disposing before arriving here
+ return;
+
+ if ( !Application::IsMainThread() )
+ {
+ // still not in the main thread (see SbaXGridPeer::dispatch). post an event, again
+ // without moving the special even to the back of the queue
+ pGrid->PostUserEvent( LINK( this, SbaXGridPeer, OnDispatchEvent ) );
+ }
+ else
+ {
+ DispatchArgs aArgs = m_aDispatchArgs.front();
+ m_aDispatchArgs.pop();
+
+ SbaXGridPeer::dispatch( aArgs.aURL, aArgs.aArgs );
+ }
+}
+
+SbaXGridPeer::DispatchType SbaXGridPeer::classifyDispatchURL( const URL& _rURL )
+{
+ DispatchType eURLType = dtUnknown;
+ if ( _rURL.Complete == ".uno:GridSlots/BrowserAttribs" )
+ eURLType = dtBrowserAttribs;
+ else if ( _rURL.Complete == ".uno:GridSlots/RowHeight" )
+ eURLType = dtRowHeight;
+ else if ( _rURL.Complete == ".uno:GridSlots/ColumnAttribs" )
+ eURLType = dtColumnAttribs;
+ else if ( _rURL.Complete == ".uno:GridSlots/ColumnWidth" )
+ eURLType = dtColumnWidth;
+ return eURLType;
+}
+
+void SAL_CALL SbaXGridPeer::dispatch(const URL& aURL, const Sequence< PropertyValue >& aArgs)
+{
+ VclPtr< SbaGridControl > pGrid = GetAs< SbaGridControl >();
+ if (!pGrid)
+ return;
+
+ if ( !Application::IsMainThread() )
+ {
+ // we're not in the main thread. This is bad, as we want to raise windows here,
+ // and VCL does not like windows to be opened in non-main threads (at least on Win32).
+ // Okay, do this async. No problem with this, as XDispatch::dispatch is defined to be
+ // a one-way method.
+
+ // save the args
+ DispatchArgs aDispatchArgs;
+ aDispatchArgs.aURL = aURL;
+ aDispatchArgs.aArgs = aArgs;
+ m_aDispatchArgs.push( aDispatchArgs );
+
+ // post an event
+ // we use the Window::PostUserEvent here, instead of the application::PostUserEvent
+ // this saves us from keeping track of these events - as soon as the window dies,
+ // the events are deleted automatically. For the application way, we would need to
+ // do this ourself.
+ // As we use our grid as window, and the grid dies before we die, this should be no problem.
+ pGrid->PostUserEvent( LINK( this, SbaXGridPeer, OnDispatchEvent ) );
+ return;
+ }
+
+ SolarMutexGuard aGuard;
+ sal_Int16 nColId = -1;
+ for (const PropertyValue& rArg : aArgs)
+ {
+ if (rArg.Name == "ColumnViewPos")
+ {
+ nColId = pGrid->GetColumnIdFromViewPos(::comphelper::getINT16(rArg.Value));
+ break;
+ }
+ if (rArg.Name == "ColumnModelPos")
+ {
+ nColId = pGrid->GetColumnIdFromModelPos(::comphelper::getINT16(rArg.Value));
+ break;
+ }
+ if (rArg.Name == "ColumnId")
+ {
+ nColId = ::comphelper::getINT16(rArg.Value);
+ break;
+ }
+ }
+
+ DispatchType eURLType = classifyDispatchURL( aURL );
+
+ if ( dtUnknown == eURLType )
+ return;
+
+ // notify any status listeners that the dialog is now active (well, about to be active)
+ MapDispatchToBool::const_iterator aThisURLState = m_aDispatchStates.emplace( eURLType, true ).first;
+ NotifyStatusChanged( aURL, nullptr );
+
+ // execute the dialog
+ switch ( eURLType )
+ {
+ case dtBrowserAttribs:
+ pGrid->SetBrowserAttrs();
+ break;
+
+ case dtRowHeight:
+ pGrid->SetRowHeight();
+ break;
+
+ case dtColumnAttribs:
+ {
+ OSL_ENSURE(nColId != -1, "SbaXGridPeer::dispatch : invalid parameter !");
+ if (nColId != -1)
+ break;
+ pGrid->SetColAttrs(nColId);
+ }
+ break;
+
+ case dtColumnWidth:
+ {
+ OSL_ENSURE(nColId != -1, "SbaXGridPeer::dispatch : invalid parameter !");
+ if (nColId != -1)
+ break;
+ pGrid->SetColWidth(nColId);
+ }
+ break;
+
+ case dtUnknown:
+ break;
+ }
+
+ // notify any status listeners that the dialog vanished
+ m_aDispatchStates.erase( aThisURLState );
+ NotifyStatusChanged( aURL, nullptr );
+}
+
+void SAL_CALL SbaXGridPeer::addStatusListener(const Reference< css::frame::XStatusListener > & xControl, const css::util::URL& aURL)
+{
+ ::comphelper::OInterfaceContainerHelper3< css::frame::XStatusListener >* pCont
+ = m_aStatusListeners.getContainer(aURL);
+ if (!pCont)
+ m_aStatusListeners.addInterface(aURL,xControl);
+ else
+ pCont->addInterface(xControl);
+ NotifyStatusChanged(aURL, xControl);
+}
+
+void SAL_CALL SbaXGridPeer::removeStatusListener(const Reference< css::frame::XStatusListener > & xControl, const css::util::URL& aURL)
+{
+ ::comphelper::OInterfaceContainerHelper3< css::frame::XStatusListener >* pCont = m_aStatusListeners.getContainer(aURL);
+ if ( pCont )
+ pCont->removeInterface(xControl);
+}
+
+Sequence< Type > SAL_CALL SbaXGridPeer::getTypes()
+{
+ return comphelper::concatSequences(
+ FmXGridPeer::getTypes(),
+ Sequence { cppu::UnoType<css::frame::XDispatch>::get() });
+}
+
+UNO3_GETIMPLEMENTATION2_IMPL(SbaXGridPeer, FmXGridPeer);
+
+VclPtr<FmGridControl> SbaXGridPeer::imp_CreateControl(vcl::Window* pParent, WinBits nStyle)
+{
+ return VclPtr<SbaGridControl>::Create( m_xContext, pParent, this, nStyle);
+}
+
+// SbaGridHeader
+
+SbaGridHeader::SbaGridHeader(BrowseBox* pParent)
+ :FmGridHeader(pParent, WB_STDHEADERBAR | WB_DRAG)
+ ,DragSourceHelper(this)
+{
+}
+
+SbaGridHeader::~SbaGridHeader()
+{
+ disposeOnce();
+}
+
+void SbaGridHeader::dispose()
+{
+ DragSourceHelper::dispose();
+ FmGridHeader::dispose();
+}
+
+void SbaGridHeader::StartDrag( sal_Int8 _nAction, const Point& _rPosPixel )
+{
+ SolarMutexGuard aGuard;
+ // in the new DnD API, the solar mutex is not locked when StartDrag is called
+
+ ImplStartColumnDrag( _nAction, _rPosPixel );
+}
+
+void SbaGridHeader::MouseButtonDown( const MouseEvent& _rMEvt )
+{
+ if (_rMEvt.IsLeft())
+ if (_rMEvt.GetClicks() != 2)
+ {
+ // the base class will start a column move here, which we don't want to allow
+ // (at the moment. If we store relative positions with the columns, we can allow column moves...)
+
+ }
+
+ FmGridHeader::MouseButtonDown(_rMEvt);
+}
+
+void SbaGridHeader::ImplStartColumnDrag(sal_Int8 _nAction, const Point& _rMousePos)
+{
+ sal_uInt16 nId = GetItemId(_rMousePos);
+ bool bResizingCol = false;
+ if (HEADERBAR_ITEM_NOTFOUND != nId)
+ {
+ tools::Rectangle aColRect = GetItemRect(nId);
+ aColRect.AdjustLeft(nId ? 3 : 0 ); // the handle col (nId == 0) does not have a left margin for resizing
+ aColRect.AdjustRight( -3 );
+ bResizingCol = !aColRect.Contains(_rMousePos);
+ }
+ if (bResizingCol)
+ return;
+
+ // force the base class to end its drag mode
+ EndTracking(TrackingEventFlags::Cancel | TrackingEventFlags::End);
+
+ // because we have 3d-buttons the select handler is called from MouseButtonUp, but StartDrag
+ // occurs earlier (while the mouse button is down)
+ // so for optical reasons we select the column before really starting the drag operation.
+ notifyColumnSelect(nId);
+
+ static_cast<SbaGridControl*>(GetParent())->StartDrag(_nAction,
+ Point(
+ _rMousePos.X() + GetPosPixel().X(), // we aren't left-justified with our parent, in contrast to the data window
+ _rMousePos.Y() - GetSizePixel().Height()
+ )
+ );
+}
+
+void SbaGridHeader::PreExecuteColumnContextMenu(sal_uInt16 nColId, weld::Menu& rMenu,
+ weld::Menu& rInsertMenu, weld::Menu& rChangeMenu,
+ weld::Menu& rShowMenu)
+{
+ FmGridHeader::PreExecuteColumnContextMenu(nColId, rMenu, rInsertMenu, rChangeMenu, rShowMenu);
+
+ // some items are valid only if the db isn't readonly
+ bool bDBIsReadOnly = static_cast<SbaGridControl*>(GetParent())->IsReadOnlyDB();
+
+ if (bDBIsReadOnly)
+ {
+ rMenu.set_visible("hide", false);
+ rMenu.set_sensitive("hide", false);
+ rMenu.set_visible("show", false);
+ rMenu.set_sensitive("show", false);
+ }
+
+ // prepend some new items
+ bool bColAttrs = (nColId != sal_uInt16(-1)) && (nColId != 0);
+ if ( !bColAttrs || bDBIsReadOnly)
+ return;
+
+ sal_uInt16 nPos = 0;
+ sal_uInt16 nModelPos = static_cast<SbaGridControl*>(GetParent())->GetModelColumnPos(nColId);
+ Reference< XPropertySet > xField = static_cast<SbaGridControl*>(GetParent())->getField(nModelPos);
+
+ if ( xField.is() )
+ {
+ switch( ::comphelper::getINT32(xField->getPropertyValue(PROPERTY_TYPE)) )
+ {
+ case DataType::BINARY:
+ case DataType::VARBINARY:
+ case DataType::LONGVARBINARY:
+ case DataType::SQLNULL:
+ case DataType::OBJECT:
+ case DataType::BLOB:
+ case DataType::CLOB:
+ case DataType::REF:
+ break;
+ default:
+ rMenu.insert(nPos++, "colattrset", DBA_RES(RID_STR_COLUMN_FORMAT),
+ nullptr, nullptr, nullptr, TRISTATE_INDET);
+ rMenu.insert_separator(nPos++, "separator1");
+ }
+ }
+
+ rMenu.insert(nPos++, "colwidth", DBA_RES(RID_STR_COLUMN_WIDTH),
+ nullptr, nullptr, nullptr, TRISTATE_INDET);
+ rMenu.insert_separator(nPos++, "separator2");
+}
+
+void SbaGridHeader::PostExecuteColumnContextMenu(sal_uInt16 nColId, const weld::Menu& rMenu, const OString& rExecutionResult)
+{
+ if (rExecutionResult == "colwidth")
+ static_cast<SbaGridControl*>(GetParent())->SetColWidth(nColId);
+ else if (rExecutionResult == "colattrset")
+ static_cast<SbaGridControl*>(GetParent())->SetColAttrs(nColId);
+ else
+ FmGridHeader::PostExecuteColumnContextMenu(nColId, rMenu, rExecutionResult);
+}
+
+// SbaGridControl
+SbaGridControl::SbaGridControl(Reference< XComponentContext > const & _rM,
+ vcl::Window* pParent, FmXGridPeer* _pPeer, WinBits nBits)
+ :FmGridControl(_rM,pParent, _pPeer, nBits)
+ ,m_pMasterListener(nullptr)
+ ,m_nAsyncDropEvent(nullptr)
+ ,m_bActivatingForDrop(false)
+{
+}
+
+SbaGridControl::~SbaGridControl()
+{
+ disposeOnce();
+}
+
+void SbaGridControl::dispose()
+{
+ if (m_nAsyncDropEvent)
+ Application::RemoveUserEvent(m_nAsyncDropEvent);
+ m_nAsyncDropEvent = nullptr;
+ FmGridControl::dispose();
+}
+
+VclPtr<BrowserHeader> SbaGridControl::imp_CreateHeaderBar(BrowseBox* pParent)
+{
+ return VclPtr<SbaGridHeader>::Create(pParent);
+}
+
+CellController* SbaGridControl::GetController(sal_Int32 nRow, sal_uInt16 nCol)
+{
+ if ( m_bActivatingForDrop )
+ return nullptr;
+
+ return FmGridControl::GetController(nRow, nCol);
+}
+
+void SbaGridControl::PreExecuteRowContextMenu(weld::Menu& rMenu)
+{
+ FmGridControl::PreExecuteRowContextMenu(rMenu);
+
+ sal_uInt16 nPos = 0;
+
+ if (!IsReadOnlyDB())
+ {
+ rMenu.insert(nPos++, "tableattr", DBA_RES(RID_STR_TABLE_FORMAT),
+ nullptr, nullptr, nullptr, TRISTATE_INDET);
+ rMenu.insert(nPos++, "rowheight", DBA_RES(RID_STR_ROW_HEIGHT),
+ nullptr, nullptr, nullptr, TRISTATE_INDET);
+ rMenu.insert_separator(nPos++, "separator1");
+ }
+
+ if ( GetSelectRowCount() > 0 )
+ {
+ rMenu.insert(nPos++, "copy", DBA_RES(RID_STR_COPY),
+ nullptr, nullptr, nullptr, TRISTATE_INDET);
+ rMenu.insert_separator(nPos++, "separator2");
+ }
+}
+
+SvNumberFormatter* SbaGridControl::GetDatasourceFormatter()
+{
+ Reference< css::util::XNumberFormatsSupplier > xSupplier = ::dbtools::getNumberFormats(::dbtools::getConnection(Reference< XRowSet > (getDataSource(),UNO_QUERY)), true, getContext());
+
+ SvNumberFormatsSupplierObj* pSupplierImpl = comphelper::getFromUnoTunnel<SvNumberFormatsSupplierObj>( xSupplier );
+ if ( !pSupplierImpl )
+ return nullptr;
+
+ SvNumberFormatter* pFormatter = pSupplierImpl->GetNumberFormatter();
+ return pFormatter;
+}
+
+void SbaGridControl::SetColWidth(sal_uInt16 nColId)
+{
+ // get the (UNO) column model
+ sal_uInt16 nModelPos = GetModelColumnPos(nColId);
+ Reference< XIndexAccess > xCols = GetPeer()->getColumns();
+ Reference< XPropertySet > xAffectedCol;
+ if (xCols.is() && (nModelPos != sal_uInt16(-1)))
+ xAffectedCol.set(xCols->getByIndex(nModelPos), css::uno::UNO_QUERY);
+
+ if (!xAffectedCol.is())
+ return;
+
+ Any aWidth = xAffectedCol->getPropertyValue(PROPERTY_WIDTH);
+ sal_Int32 nCurWidth = aWidth.hasValue() ? ::comphelper::getINT32(aWidth) : -1;
+
+ DlgSize aDlgColWidth(GetFrameWeld(), nCurWidth, false);
+ if (aDlgColWidth.run() != RET_OK)
+ return;
+
+ sal_Int32 nValue = aDlgColWidth.GetValue();
+ Any aNewWidth;
+ if (-1 == nValue)
+ { // set to default
+ Reference< XPropertyState > xPropState(xAffectedCol, UNO_QUERY);
+ if (xPropState.is())
+ {
+ try { aNewWidth = xPropState->getPropertyDefault(PROPERTY_WIDTH); } catch(Exception&) { } ;
+ }
+ }
+ else
+ aNewWidth <<= nValue;
+ try { xAffectedCol->setPropertyValue(PROPERTY_WIDTH, aNewWidth); } catch(Exception&) { } ;
+}
+
+void SbaGridControl::SetRowHeight()
+{
+ Reference< XPropertySet > xCols(GetPeer()->getColumns(), UNO_QUERY);
+ if (!xCols.is())
+ return;
+
+ Any aHeight = xCols->getPropertyValue(PROPERTY_ROW_HEIGHT);
+ sal_Int32 nCurHeight = aHeight.hasValue() ? ::comphelper::getINT32(aHeight) : -1;
+
+ DlgSize aDlgRowHeight(GetFrameWeld(), nCurHeight, true);
+ if (aDlgRowHeight.run() != RET_OK)
+ return;
+
+ sal_Int32 nValue = aDlgRowHeight.GetValue();
+ Any aNewHeight;
+ if (sal_Int16(-1) == nValue)
+ { // set to default
+ Reference< XPropertyState > xPropState(xCols, UNO_QUERY);
+ if (xPropState.is())
+ {
+ try
+ {
+ aNewHeight = xPropState->getPropertyDefault(PROPERTY_ROW_HEIGHT);
+ }
+ catch(Exception&)
+ { }
+ }
+ }
+ else
+ aNewHeight <<= nValue;
+ try
+ {
+ xCols->setPropertyValue(PROPERTY_ROW_HEIGHT, aNewHeight);
+ }
+ catch(Exception&)
+ {
+ TOOLS_WARN_EXCEPTION( "dbaccess", "setPropertyValue: PROPERTY_ROW_HEIGHT throws an exception");
+ }
+}
+
+void SbaGridControl::SetColAttrs(sal_uInt16 nColId)
+{
+ SvNumberFormatter* pFormatter = GetDatasourceFormatter();
+ if (!pFormatter)
+ return;
+
+ sal_uInt16 nModelPos = GetModelColumnPos(nColId);
+
+ // get the (UNO) column model
+ Reference< XIndexAccess > xCols = GetPeer()->getColumns();
+ Reference< XPropertySet > xAffectedCol;
+ if (xCols.is() && (nModelPos != sal_uInt16(-1)))
+ xAffectedCol.set(xCols->getByIndex(nModelPos), css::uno::UNO_QUERY);
+
+ // get the field the column is bound to
+ Reference< XPropertySet > xField = getField(nModelPos);
+ ::dbaui::callColumnFormatDialog(xAffectedCol,xField,pFormatter,GetFrameWeld());
+}
+
+void SbaGridControl::SetBrowserAttrs()
+{
+ Reference< XPropertySet > xGridModel(GetPeer()->getColumns(), UNO_QUERY);
+ if (!xGridModel.is())
+ return;
+
+ try
+ {
+ Reference< XComponentContext > xContext = getContext();
+ css::uno::Sequence<css::uno::Any> aArguments{
+ Any(comphelper::makePropertyValue("IntrospectedObject", xGridModel)),
+ Any(comphelper::makePropertyValue("ParentWindow", VCLUnoHelper::GetInterface(this)))
+ };
+ Reference<XExecutableDialog> xExecute(xContext->getServiceManager()->createInstanceWithArgumentsAndContext("com.sun.star.form.ControlFontDialog",
+ aArguments, xContext), css::uno::UNO_QUERY_THROW);
+ xExecute->execute();
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+}
+
+void SbaGridControl::PostExecuteRowContextMenu(const OString& rExecutionResult)
+{
+ if (rExecutionResult == "tableattr")
+ SetBrowserAttrs();
+ else if (rExecutionResult == "rowheight")
+ SetRowHeight();
+ else if (rExecutionResult == "copy")
+ CopySelectedRowsToClipboard();
+ else
+ FmGridControl::PostExecuteRowContextMenu(rExecutionResult);
+}
+
+void SbaGridControl::Select()
+{
+ // Some selection has changed ...
+ FmGridControl::Select();
+
+ if (m_pMasterListener)
+ m_pMasterListener->SelectionChanged();
+}
+
+void SbaGridControl::ActivateCell(sal_Int32 nRow, sal_uInt16 nCol, bool bSetCellFocus /*= sal_True*/ )
+{
+ FmGridControl::ActivateCell(nRow, nCol, bSetCellFocus);
+ if (m_pMasterListener)
+ m_pMasterListener->CellActivated();
+}
+
+void SbaGridControl::DeactivateCell(bool bUpdate /*= sal_True*/)
+{
+ FmGridControl::DeactivateCell(bUpdate);
+ if (m_pMasterListener)
+ m_pMasterListener->CellDeactivated();
+}
+
+void SbaGridControl::onRowChange()
+{
+ if ( m_pMasterListener )
+ m_pMasterListener->RowChanged();
+}
+
+void SbaGridControl::onColumnChange()
+{
+ if ( m_pMasterListener )
+ m_pMasterListener->ColumnChanged();
+}
+
+Reference< XPropertySet > SbaGridControl::getField(sal_uInt16 nModelPos)
+{
+ Reference< XPropertySet > xEmptyReturn;
+ try
+ {
+ // first get the name of the column
+ Reference< XIndexAccess > xCols = GetPeer()->getColumns();
+ if ( xCols.is() && xCols->getCount() > nModelPos )
+ {
+ Reference< XPropertySet > xCol(xCols->getByIndex(nModelPos),UNO_QUERY);
+ if ( xCol.is() )
+ xEmptyReturn.set(xCol->getPropertyValue(PROPERTY_BOUNDFIELD),UNO_QUERY);
+ }
+ else
+ OSL_FAIL("SbaGridControl::getField getColumns returns NULL or ModelPos is > than count!");
+ }
+ catch (const Exception&)
+ {
+ TOOLS_WARN_EXCEPTION("dbaccess", "SbaGridControl::getField Exception occurred");
+ }
+
+ return xEmptyReturn;
+}
+
+bool SbaGridControl::IsReadOnlyDB() const
+{
+ // assume yes if anything fails
+ bool bDBIsReadOnly = true;
+
+ try
+ {
+ // the db is the implemented by the parent of the grid control's model ...
+ Reference< XChild > xColumns(GetPeer()->getColumns(), UNO_QUERY);
+ if (xColumns.is())
+ {
+ Reference< XRowSet > xDataSource(xColumns->getParent(), UNO_QUERY);
+ ::dbtools::ensureRowSetConnection( xDataSource, getContext(), nullptr );
+ Reference< XChild > xConn(::dbtools::getConnection(xDataSource),UNO_QUERY);
+ if (xConn.is())
+ {
+ // ... and the RO-flag simply is implemented by a property
+ Reference< XPropertySet > xDbProps(xConn->getParent(), UNO_QUERY);
+ if (xDbProps.is())
+ {
+ Reference< XPropertySetInfo > xInfo = xDbProps->getPropertySetInfo();
+ if (xInfo->hasPropertyByName(PROPERTY_ISREADONLY))
+ bDBIsReadOnly = ::comphelper::getBOOL(xDbProps->getPropertyValue(PROPERTY_ISREADONLY));
+ }
+ }
+ }
+ }
+ catch (const Exception&)
+ {
+ TOOLS_WARN_EXCEPTION("dbaccess", "SbaGridControl::IsReadOnlyDB Exception occurred");
+ }
+
+ return bDBIsReadOnly;
+}
+
+void SbaGridControl::MouseButtonDown( const BrowserMouseEvent& rMEvt)
+{
+ sal_Int32 nRow = GetRowAtYPosPixel(rMEvt.GetPosPixel().Y());
+ sal_uInt16 nColPos = GetColumnAtXPosPixel(rMEvt.GetPosPixel().X());
+ sal_uInt16 nViewPos = (nColPos == BROWSER_INVALIDID) ? sal_uInt16(-1) : nColPos-1;
+ // 'the handle column' and 'no valid column' will both result in a view position of -1 !
+
+ bool bHitEmptySpace = (nRow > GetRowCount()) || (nViewPos == sal_uInt16(-1));
+
+ if (bHitEmptySpace && (rMEvt.GetClicks() == 2) && rMEvt.IsMod1())
+ Control::MouseButtonDown(rMEvt);
+ else
+ FmGridControl::MouseButtonDown(rMEvt);
+}
+
+void SbaGridControl::StartDrag( sal_Int8 _nAction, const Point& _rPosPixel )
+{
+ SolarMutexGuard aGuard;
+ // in the new DnD API, the solar mutex is not locked when StartDrag is called
+
+ bool bHandled = false;
+
+ do
+ {
+ // determine if dragging is allowed
+ // (Yes, this is controller (not view) functionality. But collecting and evaluating all the
+ // information necessary via UNO would be quite difficult (if not impossible) so
+ // my laziness says 'do it here'...)
+ sal_Int32 nRow = GetRowAtYPosPixel(_rPosPixel.Y());
+ sal_uInt16 nColPos = GetColumnAtXPosPixel(_rPosPixel.X());
+ sal_uInt16 nViewPos = (nColPos == BROWSER_INVALIDID) ? sal_uInt16(-1) : nColPos-1;
+ // 'the handle column' and 'no valid column' will both result in a view position of -1 !
+
+ bool bCurrentRowVirtual = IsCurrentAppending() && IsModified();
+ // the current row doesn't really exist: the user's appending a new one and already has entered some data,
+ // so the row contains data which has no counter part within the data source
+
+ sal_Int32 nCorrectRowCount = GetRowCount();
+ if (GetOptions() & DbGridControlOptions::Insert)
+ --nCorrectRowCount; // there is an empty row for inserting records
+ if (bCurrentRowVirtual)
+ --nCorrectRowCount;
+
+ if ((nColPos == BROWSER_INVALIDID) || (nRow >= nCorrectRowCount))
+ break;
+
+ bool bHitHandle = (nColPos == 0);
+
+ // check which kind of dragging has to be initiated
+ if ( bHitHandle // the handle column
+ // AND
+ && ( GetSelectRowCount() // at least one row is selected
+ // OR
+ || ( (nRow >= 0) // a row below the header
+ && !bCurrentRowVirtual // we aren't appending a new record
+ && (nRow != GetCurrentPos()) // a row which is not the current one
+ ) // OR
+ || ( (0 == GetSelectRowCount()) // no rows selected
+ && (-1 == nRow) // hit the header
+ )
+ )
+ )
+ { // => start dragging the row
+ if (GetDataWindow().IsMouseCaptured())
+ GetDataWindow().ReleaseMouse();
+
+ if (0 == GetSelectRowCount())
+ // no rows selected, but here in this branch
+ // -> the user started dragging the upper left corner, which symbolizes the whole table
+ SelectAll();
+
+ getMouseEvent().Clear();
+ implTransferSelectedRows(static_cast<sal_Int16>(nRow), false);
+
+ bHandled = true;
+ }
+ else if ( (nRow < 0) // the header
+ && (!bHitHandle) // non-handle column
+ && (nViewPos < GetViewColCount()) // valid (existing) column
+ )
+ { // => start dragging the column
+ if (GetDataWindow().IsMouseCaptured())
+ GetDataWindow().ReleaseMouse();
+
+ getMouseEvent().Clear();
+ DoColumnDrag(nViewPos);
+
+ bHandled = true;
+ }
+ else if ( !bHitHandle // non-handle column
+ && (nRow >= 0) // non-header row
+ )
+ { // => start dragging the field content
+ if (GetDataWindow().IsMouseCaptured())
+ GetDataWindow().ReleaseMouse();
+
+ getMouseEvent().Clear();
+ DoFieldDrag(nViewPos, static_cast<sal_Int16>(nRow));
+
+ bHandled = true;
+ }
+ }
+ while (false);
+
+ if (!bHandled)
+ FmGridControl::StartDrag(_nAction, _rPosPixel);
+}
+
+void SbaGridControl::DoColumnDrag(sal_uInt16 nColumnPos)
+{
+ Reference< XPropertySet > xDataSource = getDataSource();
+ OSL_ENSURE(xDataSource.is(), "SbaGridControl::DoColumnDrag : invalid data source !");
+ ::dbtools::ensureRowSetConnection(Reference< XRowSet >(getDataSource(),UNO_QUERY), getContext(), nullptr);
+
+ Reference< XPropertySet > xAffectedCol;
+ Reference< XPropertySet > xAffectedField;
+ Reference< XConnection > xActiveConnection;
+
+ // determine the field to drag
+ OUString sField;
+ try
+ {
+ xActiveConnection = ::dbtools::getConnection(Reference< XRowSet >(getDataSource(),UNO_QUERY));
+
+ sal_uInt16 nModelPos = GetModelColumnPos(GetColumnIdFromViewPos(nColumnPos));
+ Reference< XIndexContainer > xCols = GetPeer()->getColumns();
+ xAffectedCol.set(xCols->getByIndex(nModelPos),UNO_QUERY);
+ if (xAffectedCol.is())
+ {
+ xAffectedCol->getPropertyValue(PROPERTY_CONTROLSOURCE) >>= sField;
+ xAffectedField.set(xAffectedCol->getPropertyValue(PROPERTY_BOUNDFIELD),UNO_QUERY);
+ }
+ }
+ catch(Exception&)
+ {
+ OSL_FAIL("SbaGridControl::DoColumnDrag : something went wrong while getting the column");
+ }
+ if (sField.isEmpty())
+ return;
+
+ rtl::Reference<OColumnTransferable> pDataTransfer = new OColumnTransferable(xDataSource, sField, xAffectedField, xActiveConnection, ColumnTransferFormatFlags::FIELD_DESCRIPTOR | ColumnTransferFormatFlags::COLUMN_DESCRIPTOR);
+ pDataTransfer->StartDrag(this, DND_ACTION_COPY | DND_ACTION_LINK);
+}
+
+void SbaGridControl::CopySelectedRowsToClipboard()
+{
+ OSL_ENSURE( GetSelectRowCount() > 0, "SbaGridControl::CopySelectedRowsToClipboard: invalid call!" );
+ implTransferSelectedRows( static_cast<sal_Int16>(FirstSelectedRow()), true );
+}
+
+void SbaGridControl::implTransferSelectedRows( sal_Int16 nRowPos, bool _bTrueIfClipboardFalseIfDrag )
+{
+ Reference< XPropertySet > xForm = getDataSource();
+ OSL_ENSURE( xForm.is(), "SbaGridControl::implTransferSelectedRows: invalid form!" );
+
+ // build the sequence of numbers of selected rows
+ Sequence< Any > aSelectedRows;
+ bool bSelectionBookmarks = true;
+
+ // collect the affected rows
+ if ((GetSelectRowCount() == 0) && (nRowPos >= 0))
+ {
+ aSelectedRows = { Any(static_cast<sal_Int32>(nRowPos + 1)) };
+ bSelectionBookmarks = false;
+ }
+ else if ( !IsAllSelected() && GetSelectRowCount() )
+ {
+ aSelectedRows = getSelectionBookmarks();
+ bSelectionBookmarks = true;
+ }
+
+ try
+ {
+ rtl::Reference<ODataClipboard> pTransfer = new ODataClipboard( xForm, aSelectedRows, bSelectionBookmarks, getContext() );
+
+ if ( _bTrueIfClipboardFalseIfDrag )
+ pTransfer->CopyToClipboard( this );
+ else
+ pTransfer->StartDrag(this, DND_ACTION_COPY | DND_ACTION_LINK);
+ }
+ catch(Exception&)
+ {
+ }
+}
+
+void SbaGridControl::DoFieldDrag(sal_uInt16 nColumnPos, sal_Int16 nRowPos)
+{
+ // the only thing to do here is dragging the pure cell text
+ // the old implementation copied a SBA_FIELDDATAEXCHANGE_FORMAT, too, (which was rather expensive to obtain),
+ // but we have no client for this DnD format anymore (the mail part of SO 5.2 was the only client)
+
+ try
+ {
+ OUString sCellText;
+ Reference< XGridFieldDataSupplier > xFieldData(GetPeer());
+ Sequence<sal_Bool> aSupportingText = xFieldData->queryFieldDataType(cppu::UnoType<decltype(sCellText)>::get());
+ if (aSupportingText.getConstArray()[nColumnPos])
+ {
+ Sequence< Any> aCellContents = xFieldData->queryFieldData(nRowPos, cppu::UnoType<decltype(sCellText)>::get());
+ sCellText = ::comphelper::getString(aCellContents.getConstArray()[nColumnPos]);
+ ::svt::OStringTransfer::StartStringDrag(sCellText, this, DND_ACTION_COPY);
+ }
+ }
+ catch(Exception&)
+ {
+ OSL_FAIL("SbaGridControl::DoFieldDrag : could not retrieve the cell's contents !");
+ return;
+ }
+
+}
+
+ namespace {
+
+/// unary_function Functor object for class ZZ returntype is void
+ struct SbaGridControlPrec
+ {
+ bool operator()(const DataFlavorExVector::value_type& _aType)
+ {
+ switch (_aType.mnSotId)
+ {
+ case SotClipboardFormatId::DBACCESS_TABLE: // table descriptor
+ case SotClipboardFormatId::DBACCESS_QUERY: // query descriptor
+ case SotClipboardFormatId::DBACCESS_COMMAND: // SQL command
+ return true;
+ default: break;
+ }
+ return false;
+ }
+ };
+
+ }
+
+sal_Int8 SbaGridControl::AcceptDrop( const BrowserAcceptDropEvent& rEvt )
+{
+ sal_Int8 nAction = DND_ACTION_NONE;
+
+ // we need a valid connection
+ if (!::dbtools::getConnection(Reference< XRowSet > (getDataSource(),UNO_QUERY)).is())
+ return nAction;
+
+ if ( IsDropFormatSupported( SotClipboardFormatId::STRING ) )
+ do
+ { // odd construction, but spares us a lot of (explicit ;) goto's
+
+ if (!GetEmptyRow().is())
+ // without an empty row we're not in update mode
+ break;
+
+ const sal_Int32 nRow = GetRowAtYPosPixel(rEvt.maPosPixel.Y(), false);
+ const sal_uInt16 nCol = GetColumnId(GetColumnAtXPosPixel(rEvt.maPosPixel.X()));
+
+ sal_Int32 nCorrectRowCount = GetRowCount();
+ if (GetOptions() & DbGridControlOptions::Insert)
+ --nCorrectRowCount; // there is an empty row for inserting records
+ if (IsCurrentAppending())
+ --nCorrectRowCount; // the current data record doesn't really exist, we are appending a new one
+
+ if ( (nCol == BROWSER_INVALIDID) || (nRow >= nCorrectRowCount) || (nCol == 0) )
+ // no valid cell under the mouse cursor
+ break;
+
+ tools::Rectangle aRect = GetCellRect(nRow, nCol, false);
+ if (!aRect.Contains(rEvt.maPosPixel))
+ // not dropped within a cell (a cell isn't as wide as the column - the are small spaces)
+ break;
+
+ if ((IsModified() || (GetCurrentRow().is() && GetCurrentRow()->IsModified())) && (GetCurrentPos() != nRow))
+ // there is a current and modified row or cell and he text is to be dropped into another one
+ break;
+
+ CellControllerRef xCurrentController = Controller();
+ if (xCurrentController.is() && xCurrentController->IsValueChangedFromSaved() && ((nRow != GetCurRow()) || (nCol != GetCurColumnId())))
+ // the current controller is modified and the user wants to drop in another cell -> no chance
+ // (when leaving the modified cell an error may occur - this is deadly while dragging)
+ break;
+
+ Reference< XPropertySet > xField = getField(GetModelColumnPos(nCol));
+ if (!xField.is())
+ // the column is not valid bound (for instance a binary field)
+ break;
+
+ try
+ {
+ if (::comphelper::getBOOL(xField->getPropertyValue(PROPERTY_ISREADONLY)))
+ break;
+ }
+ catch (const Exception& )
+ {
+ // assume RO
+ break;
+ }
+
+ try
+ {
+ // assume that text can be dropped into a field if the column has a css::awt::XTextComponent interface
+ Reference< XIndexAccess > xColumnControls(GetPeer());
+ if (xColumnControls.is())
+ {
+ Reference< css::awt::XTextComponent > xColControl(
+ xColumnControls->getByIndex(GetViewColumnPos(nCol)),
+ css::uno::UNO_QUERY);
+ if (xColControl.is())
+ {
+ m_bActivatingForDrop = true;
+ GoToRowColumnId(nRow, nCol);
+ m_bActivatingForDrop = false;
+
+ nAction = DND_ACTION_COPY;
+ }
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+
+ } while (false);
+
+ if(nAction != DND_ACTION_COPY && GetEmptyRow().is())
+ {
+ const DataFlavorExVector& _rFlavors = GetDataFlavors();
+ if(std::any_of(_rFlavors.begin(),_rFlavors.end(),SbaGridControlPrec()))
+ nAction = DND_ACTION_COPY;
+ }
+
+ return (DND_ACTION_NONE != nAction) ? nAction : FmGridControl::AcceptDrop(rEvt);
+}
+
+sal_Int8 SbaGridControl::ExecuteDrop( const BrowserExecuteDropEvent& rEvt )
+{
+ // we need some properties of our data source
+ Reference< XPropertySet > xDataSource = getDataSource();
+ if (!xDataSource.is())
+ return DND_ACTION_NONE;
+
+ // we need a valid connection
+ if (!::dbtools::getConnection(Reference< XRowSet > (xDataSource,UNO_QUERY)).is())
+ return DND_ACTION_NONE;
+
+ if ( IsDropFormatSupported( SotClipboardFormatId::STRING ) )
+ {
+ sal_Int32 nRow = GetRowAtYPosPixel(rEvt.maPosPixel.Y(), false);
+ sal_uInt16 nCol = GetColumnAtXPosPixel(rEvt.maPosPixel.X());
+
+ sal_Int32 nCorrectRowCount = GetRowCount();
+ if (GetOptions() & DbGridControlOptions::Insert)
+ --nCorrectRowCount; // there is an empty row for inserting records
+ if (IsCurrentAppending())
+ --nCorrectRowCount; // the current data record doesn't really exist, we are appending a new one
+
+ OSL_ENSURE((nCol != BROWSER_INVALIDID) && (nRow < nCorrectRowCount), "SbaGridControl::Drop : dropped on an invalid position !");
+ // AcceptDrop should have caught this
+
+ // from now we work with ids instead of positions
+ nCol = GetColumnId(nCol);
+
+ GoToRowColumnId(nRow, nCol);
+ if (!IsEditing())
+ ActivateCell();
+
+ CellControllerRef xCurrentController = Controller();
+ EditCellController* pController = dynamic_cast<EditCellController*>(xCurrentController.get());
+ if (!pController)
+ return DND_ACTION_NONE;
+
+ // get the dropped string
+ TransferableDataHelper aDropped( rEvt.maDropEvent.Transferable );
+ OUString sDropped;
+ if ( !aDropped.GetString( SotClipboardFormatId::STRING, sDropped ) )
+ return DND_ACTION_NONE;
+
+ IEditImplementation* pEditImplementation = pController->GetEditImplementation();
+ pEditImplementation->SetText(sDropped);
+ // SetText itself doesn't call a Modify as it isn't a user interaction
+ pController->Modify();
+
+ return DND_ACTION_COPY;
+ }
+
+ if(GetEmptyRow().is())
+ {
+ const DataFlavorExVector& _rFlavors = GetDataFlavors();
+ if( std::any_of(_rFlavors.begin(),_rFlavors.end(), SbaGridControlPrec()) )
+ {
+ TransferableDataHelper aDropped( rEvt.maDropEvent.Transferable );
+ m_aDataDescriptor = ODataAccessObjectTransferable::extractObjectDescriptor(aDropped);
+ if (m_nAsyncDropEvent)
+ Application::RemoveUserEvent(m_nAsyncDropEvent);
+ m_nAsyncDropEvent = Application::PostUserEvent(LINK(this, SbaGridControl, AsynchDropEvent), nullptr, true);
+ return DND_ACTION_COPY;
+ }
+ }
+
+ return DND_ACTION_NONE;
+}
+
+Reference< XPropertySet > SbaGridControl::getDataSource() const
+{
+ Reference< XPropertySet > xReturn;
+
+ Reference< XChild > xColumns(GetPeer()->getColumns(), UNO_QUERY);
+ if (xColumns.is())
+ xReturn.set(xColumns->getParent(), UNO_QUERY);
+
+ return xReturn;
+}
+
+IMPL_LINK_NOARG(SbaGridControl, AsynchDropEvent, void*, void)
+{
+ m_nAsyncDropEvent = nullptr;
+
+ Reference< XPropertySet > xDataSource = getDataSource();
+ if ( xDataSource.is() )
+ {
+ bool bCountFinal = false;
+ xDataSource->getPropertyValue(PROPERTY_ISROWCOUNTFINAL) >>= bCountFinal;
+ if ( !bCountFinal )
+ setDataSource(nullptr); // detach from grid control
+ Reference< XResultSetUpdate > xResultSetUpdate(xDataSource,UNO_QUERY);
+ rtl::Reference<ODatabaseImportExport> pImExport = new ORowSetImportExport(GetFrameWeld(),xResultSetUpdate,m_aDataDescriptor, getContext());
+ Hide();
+ try
+ {
+ pImExport->initialize(m_aDataDescriptor);
+ if (m_pMasterListener)
+ m_pMasterListener->BeforeDrop();
+ if(!pImExport->Read())
+ {
+ OUString sError = DBA_RES(STR_NO_COLUMNNAME_MATCHING);
+ throwGenericSQLException(sError,nullptr);
+ }
+ if (m_pMasterListener)
+ m_pMasterListener->AfterDrop();
+ Show();
+ }
+ catch(const SQLException& e)
+ {
+ if (m_pMasterListener)
+ m_pMasterListener->AfterDrop();
+ Show();
+ ::dbtools::showError( ::dbtools::SQLExceptionInfo(e), VCLUnoHelper::GetInterface(this), getContext() );
+ }
+ catch(const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ if (m_pMasterListener)
+ m_pMasterListener->AfterDrop();
+ Show();
+ }
+ if ( !bCountFinal )
+ setDataSource(Reference< XRowSet >(xDataSource,UNO_QUERY));
+ }
+ m_aDataDescriptor.clear();
+}
+
+OUString SbaGridControl::GetAccessibleObjectDescription( AccessibleBrowseBoxObjType eObjType,sal_Int32 _nPosition) const
+{
+ OUString sRet;
+ if ( AccessibleBrowseBoxObjType::BrowseBox == eObjType )
+ {
+ SolarMutexGuard aGuard;
+ sRet = DBA_RES(STR_DATASOURCE_GRIDCONTROL_DESC);
+ }
+ else
+ sRet = FmGridControl::GetAccessibleObjectDescription( eObjType,_nPosition);
+ return sRet;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/browser/sbamultiplex.cxx b/dbaccess/source/ui/browser/sbamultiplex.cxx
new file mode 100644
index 000000000..8bf7ed747
--- /dev/null
+++ b/dbaccess/source/ui/browser/sbamultiplex.cxx
@@ -0,0 +1,528 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sbamultiplex.hxx>
+#include <cppuhelper/queryinterface.hxx>
+
+using namespace dbaui;
+
+// the listener multiplexers
+
+// XStatusListener
+SbaXStatusMultiplexer::SbaXStatusMultiplexer(::cppu::OWeakObject& rSource, ::osl::Mutex& _rMutex)
+ :OSbaWeakSubObject(rSource)
+ ,OInterfaceContainerHelper3(_rMutex)
+{
+}
+
+css::uno::Any SAL_CALL SbaXStatusMultiplexer::queryInterface(const css::uno::Type& _rType)
+{
+ css::uno::Any aReturn = OSbaWeakSubObject::queryInterface(_rType);
+ if (!aReturn.hasValue())
+ aReturn = ::cppu::queryInterface(_rType,
+ static_cast< css::frame::XStatusListener* >(this),
+ static_cast< css::lang::XEventListener* >(static_cast< css::frame::XStatusListener* >(this))
+ );
+
+ return aReturn;
+}
+void SAL_CALL SbaXStatusMultiplexer::disposing(const css::lang::EventObject& )
+{
+}
+
+
+void SAL_CALL SbaXStatusMultiplexer::statusChanged(const css::frame::FeatureStateEvent& e)
+{
+ m_aLastKnownStatus = e;
+ m_aLastKnownStatus.Source = &m_rParent;
+ notifyEach( &XStatusListener::statusChanged, m_aLastKnownStatus );
+}
+
+// LoadListener
+SbaXLoadMultiplexer::SbaXLoadMultiplexer(::cppu::OWeakObject& rSource, ::osl::Mutex& _rMutex)
+ :OSbaWeakSubObject(rSource)
+ ,OInterfaceContainerHelper3(_rMutex)
+{
+}
+
+css::uno::Any SAL_CALL SbaXLoadMultiplexer::queryInterface(const css::uno::Type& _rType)
+{
+ css::uno::Any aReturn = OSbaWeakSubObject::queryInterface(_rType);
+ if (!aReturn.hasValue())
+ aReturn = ::cppu::queryInterface(_rType,
+ static_cast< css::form::XLoadListener* >(this),
+ static_cast< css::lang::XEventListener* >(static_cast< css::form::XLoadListener* >(this))
+ );
+
+ return aReturn;
+}
+void SAL_CALL SbaXLoadMultiplexer::disposing(const css::lang::EventObject& )
+{
+}
+
+void SAL_CALL SbaXLoadMultiplexer::loaded(const css::lang::EventObject& e)
+{
+ css::lang::EventObject aMulti(e);
+ aMulti.Source = &m_rParent;
+ notifyEach( &XLoadListener::loaded, aMulti );
+}
+void SAL_CALL SbaXLoadMultiplexer::unloaded(const css::lang::EventObject& e)
+{
+ css::lang::EventObject aMulti(e);
+ aMulti.Source = &m_rParent;
+ notifyEach( &XLoadListener::unloaded, aMulti );
+}
+
+void SAL_CALL SbaXLoadMultiplexer::unloading(const css::lang::EventObject& e)
+{
+ css::lang::EventObject aMulti(e);
+ aMulti.Source = &m_rParent;
+ notifyEach( &XLoadListener::unloading, aMulti );
+}
+
+void SAL_CALL SbaXLoadMultiplexer::reloading(const css::lang::EventObject& e)
+{
+ css::lang::EventObject aMulti(e);
+ aMulti.Source = &m_rParent;
+ notifyEach( &XLoadListener::reloading, aMulti );
+}
+
+void SAL_CALL SbaXLoadMultiplexer::reloaded(const css::lang::EventObject& e)
+{
+ css::lang::EventObject aMulti(e);
+ aMulti.Source = &m_rParent;
+ notifyEach( &XLoadListener::reloaded, aMulti );
+}
+
+
+// css::sdbc::XRowSetListener
+SbaXRowSetMultiplexer::SbaXRowSetMultiplexer(::cppu::OWeakObject& rSource, ::osl::Mutex& _rMutex)
+ :OSbaWeakSubObject(rSource)
+ ,OInterfaceContainerHelper3(_rMutex)
+{
+}
+
+css::uno::Any SAL_CALL SbaXRowSetMultiplexer::queryInterface(const css::uno::Type& _rType)
+{
+ css::uno::Any aReturn = OSbaWeakSubObject::queryInterface(_rType);
+ if (!aReturn.hasValue())
+ aReturn = ::cppu::queryInterface(_rType,
+ static_cast< css::sdbc::XRowSetListener* >(this),
+ static_cast< css::lang::XEventListener* >(static_cast< css::sdbc::XRowSetListener* >(this))
+ );
+
+ return aReturn;
+}
+void SAL_CALL SbaXRowSetMultiplexer::disposing(const css::lang::EventObject& )
+{
+}
+
+void SAL_CALL SbaXRowSetMultiplexer::cursorMoved(const css::lang::EventObject& e)
+{
+ css::lang::EventObject aMulti(e);
+ aMulti.Source = &m_rParent;
+ notifyEach( &XRowSetListener::cursorMoved, aMulti );
+}
+
+void SAL_CALL SbaXRowSetMultiplexer::rowChanged(const css::lang::EventObject& e)
+{
+ css::lang::EventObject aMulti(e);
+ aMulti.Source = &m_rParent;
+ notifyEach( &XRowSetListener::rowChanged, aMulti );
+}
+
+void SAL_CALL SbaXRowSetMultiplexer::rowSetChanged(const css::lang::EventObject& e)
+{
+ css::lang::EventObject aMulti(e);
+ aMulti.Source = &m_rParent;
+ notifyEach( &XRowSetListener::rowSetChanged, aMulti );
+}
+
+// css::sdb::XRowSetApproveListener
+SbaXRowSetApproveMultiplexer::SbaXRowSetApproveMultiplexer(::cppu::OWeakObject& rSource, ::osl::Mutex& _rMutex)
+ :OSbaWeakSubObject(rSource)
+ ,OInterfaceContainerHelper3(_rMutex)
+{
+}
+
+css::uno::Any SAL_CALL SbaXRowSetApproveMultiplexer::queryInterface(const css::uno::Type& _rType)
+{
+ css::uno::Any aReturn = OSbaWeakSubObject::queryInterface(_rType);
+ if (!aReturn.hasValue())
+ aReturn = ::cppu::queryInterface(_rType,
+ static_cast< css::sdb::XRowSetApproveListener* >(this),
+ static_cast< css::lang::XEventListener* >(static_cast< css::sdb::XRowSetApproveListener* >(this))
+ );
+
+ return aReturn;
+}
+void SAL_CALL SbaXRowSetApproveMultiplexer::disposing(const css::lang::EventObject& )
+{
+}
+
+sal_Bool SAL_CALL SbaXRowSetApproveMultiplexer::approveCursorMove(const css::lang::EventObject& e)
+{
+ css::lang::EventObject aMulti(e);
+ aMulti.Source = &m_rParent;
+ ::comphelper::OInterfaceIteratorHelper3 aIt(*this);
+ bool bResult = true;
+ while (bResult && aIt.hasMoreElements())
+ bResult = aIt.next()->approveCursorMove(aMulti);
+ return bResult;
+}
+
+sal_Bool SAL_CALL SbaXRowSetApproveMultiplexer::approveRowChange(const css::sdb::RowChangeEvent& e)
+{
+ css::sdb::RowChangeEvent aMulti(e);
+ aMulti.Source = &m_rParent;
+ ::comphelper::OInterfaceIteratorHelper3 aIt(*this);
+ bool bResult = true;
+ while (bResult && aIt.hasMoreElements())
+ bResult = aIt.next()->approveRowChange(aMulti);
+ return bResult;
+}
+
+sal_Bool SAL_CALL SbaXRowSetApproveMultiplexer::approveRowSetChange(const css::lang::EventObject& e)
+{
+ css::lang::EventObject aMulti(e);
+ aMulti.Source = &m_rParent;
+ ::comphelper::OInterfaceIteratorHelper3 aIt(*this);
+ bool bResult = true;
+ while (bResult && aIt.hasMoreElements())
+ bResult = aIt.next()->approveRowSetChange(aMulti);
+ return bResult;
+}
+
+// css::sdb::XSQLErrorListener
+SbaXSQLErrorMultiplexer::SbaXSQLErrorMultiplexer(::cppu::OWeakObject& rSource, ::osl::Mutex& _rMutex)
+ :OSbaWeakSubObject(rSource)
+ ,OInterfaceContainerHelper3(_rMutex)
+{
+}
+
+css::uno::Any SAL_CALL SbaXSQLErrorMultiplexer::queryInterface(const css::uno::Type& _rType)
+{
+ css::uno::Any aReturn = OSbaWeakSubObject::queryInterface(_rType);
+ if (!aReturn.hasValue())
+ aReturn = ::cppu::queryInterface(_rType,
+ static_cast< css::sdb::XSQLErrorListener* >(this),
+ static_cast< css::lang::XEventListener* >(static_cast< css::sdb::XSQLErrorListener* >(this))
+ );
+
+ return aReturn;
+}
+void SAL_CALL SbaXSQLErrorMultiplexer::disposing(const css::lang::EventObject& )
+{
+}
+
+void SAL_CALL SbaXSQLErrorMultiplexer::errorOccured(const css::sdb::SQLErrorEvent& e)
+{
+ css::sdb::SQLErrorEvent aMulti(e);
+ aMulti.Source = &m_rParent;
+ notifyEach( &XSQLErrorListener::errorOccured, aMulti );
+}
+
+// css::form::XDatabaseParameterListener
+SbaXParameterMultiplexer::SbaXParameterMultiplexer(::cppu::OWeakObject& rSource, ::osl::Mutex& _rMutex)
+ :OSbaWeakSubObject(rSource)
+ ,OInterfaceContainerHelper3(_rMutex)
+{
+}
+
+css::uno::Any SAL_CALL SbaXParameterMultiplexer::queryInterface(const css::uno::Type& _rType)
+{
+ css::uno::Any aReturn = OSbaWeakSubObject::queryInterface(_rType);
+ if (!aReturn.hasValue())
+ aReturn = ::cppu::queryInterface(_rType,
+ static_cast< css::form::XDatabaseParameterListener* >(this),
+ static_cast< css::lang::XEventListener* >(static_cast< css::form::XDatabaseParameterListener* >(this))
+ );
+
+ return aReturn;
+}
+void SAL_CALL SbaXParameterMultiplexer::disposing(const css::lang::EventObject& )
+{
+}
+
+sal_Bool SAL_CALL SbaXParameterMultiplexer::approveParameter(const css::form::DatabaseParameterEvent& e)
+{
+ css::form::DatabaseParameterEvent aMulti(e);
+ aMulti.Source = &m_rParent;
+ ::comphelper::OInterfaceIteratorHelper3 aIt(*this);
+ bool bResult = true;
+ while (bResult && aIt.hasMoreElements())
+ bResult = aIt.next()->approveParameter(aMulti);
+ return bResult;
+}
+
+// css::form::XSubmitListener
+SbaXSubmitMultiplexer::SbaXSubmitMultiplexer(::cppu::OWeakObject& rSource, ::osl::Mutex& _rMutex)
+ :OSbaWeakSubObject(rSource)
+ ,OInterfaceContainerHelper3(_rMutex)
+{
+}
+
+css::uno::Any SAL_CALL SbaXSubmitMultiplexer::queryInterface(const css::uno::Type& _rType)
+{
+ css::uno::Any aReturn = OSbaWeakSubObject::queryInterface(_rType);
+ if (!aReturn.hasValue())
+ aReturn = ::cppu::queryInterface(_rType,
+ static_cast< css::form::XSubmitListener* >(this),
+ static_cast< css::lang::XEventListener* >(static_cast< css::form::XSubmitListener* >(this))
+ );
+
+ return aReturn;
+}
+void SAL_CALL SbaXSubmitMultiplexer::disposing(const css::lang::EventObject& )
+{
+}
+
+
+
+sal_Bool SAL_CALL SbaXSubmitMultiplexer::approveSubmit(const css::lang::EventObject& e)
+{
+ css::lang::EventObject aMulti(e);
+ aMulti.Source = &m_rParent;
+ ::comphelper::OInterfaceIteratorHelper3 aIt(*this);
+ bool bResult = true;
+ while (bResult && aIt.hasMoreElements())
+ bResult = aIt.next()->approveSubmit(aMulti);
+ return bResult;
+}
+
+// css::form::XResetListener
+SbaXResetMultiplexer::SbaXResetMultiplexer(::cppu::OWeakObject& rSource, ::osl::Mutex& _rMutex)
+ :OSbaWeakSubObject(rSource)
+ ,OInterfaceContainerHelper3(_rMutex)
+{
+}
+
+css::uno::Any SAL_CALL SbaXResetMultiplexer::queryInterface(const css::uno::Type& _rType)
+{
+ css::uno::Any aReturn = OSbaWeakSubObject::queryInterface(_rType);
+ if (!aReturn.hasValue())
+ aReturn = ::cppu::queryInterface(_rType,
+ static_cast< css::form::XResetListener* >(this),
+ static_cast< css::lang::XEventListener* >(static_cast< css::form::XResetListener* >(this))
+ );
+
+ return aReturn;
+}
+void SAL_CALL SbaXResetMultiplexer::disposing(const css::lang::EventObject& )
+{
+}
+
+
+sal_Bool SAL_CALL SbaXResetMultiplexer::approveReset(const css::lang::EventObject& e)
+{
+ css::lang::EventObject aMulti(e);
+ aMulti.Source = &m_rParent;
+ ::comphelper::OInterfaceIteratorHelper3 aIt(*this);
+ bool bResult = true;
+ while (bResult && aIt.hasMoreElements())
+ bResult = aIt.next()->approveReset(aMulti);
+ return bResult;
+}
+
+void SAL_CALL SbaXResetMultiplexer::resetted(const css::lang::EventObject& e)
+{
+ css::lang::EventObject aMulti(e);
+ aMulti.Source = &m_rParent;
+ notifyEach( &XResetListener::resetted, aMulti );
+}
+
+// css::beans::XPropertyChangeListener
+SbaXPropertyChangeMultiplexer::SbaXPropertyChangeMultiplexer(::cppu::OWeakObject& rSource, ::osl::Mutex& rMutex)
+ :OSbaWeakSubObject(rSource)
+ ,m_aListeners(rMutex)
+{
+}
+
+css::uno::Any SAL_CALL SbaXPropertyChangeMultiplexer::queryInterface(const css::uno::Type& _rType)
+{
+ css::uno::Any aReturn = OSbaWeakSubObject::queryInterface(_rType);
+ if (!aReturn.hasValue())
+ aReturn = ::cppu::queryInterface(_rType,
+ static_cast< css::beans::XPropertyChangeListener* >(this),
+ static_cast< css::lang::XEventListener* >(static_cast< css::beans::XPropertyChangeListener* >(this))
+ );
+
+ return aReturn;
+}
+void SAL_CALL SbaXPropertyChangeMultiplexer::disposing(const css::lang::EventObject& )
+{
+}
+void SAL_CALL SbaXPropertyChangeMultiplexer::propertyChange(const css::beans::PropertyChangeEvent& e)
+{
+ ::comphelper::OInterfaceContainerHelper3<XPropertyChangeListener>* pListeners = m_aListeners.getContainer(e.PropertyName);
+ if (pListeners)
+ Notify(*pListeners, e);
+
+ /* do the notification for the unspecialized listeners, too */
+ pListeners = m_aListeners.getContainer(OUString());
+ if (pListeners)
+ Notify(*pListeners, e);
+}
+
+void SbaXPropertyChangeMultiplexer::addInterface(const OUString& rName,
+ const css::uno::Reference< css::beans::XPropertyChangeListener > & rListener)
+{
+ m_aListeners.addInterface(rName, rListener);
+}
+
+void SbaXPropertyChangeMultiplexer::removeInterface(const OUString& rName,
+ const css::uno::Reference< css::beans::XPropertyChangeListener > & rListener)
+{
+ m_aListeners.removeInterface(rName, rListener);
+}
+
+void SbaXPropertyChangeMultiplexer::disposeAndClear()
+{
+ css::lang::EventObject aEvt(m_rParent);
+ m_aListeners.disposeAndClear(aEvt);
+}
+
+sal_Int32 SbaXPropertyChangeMultiplexer::getOverallLen() const
+{
+ sal_Int32 nLen = 0;
+ const std::vector< OUString > aContained = m_aListeners.getContainedTypes();
+ for ( OUString const & s : aContained)
+ {
+ ::comphelper::OInterfaceContainerHelper3<XPropertyChangeListener>* pListeners = m_aListeners.getContainer(s);
+ if (!pListeners)
+ continue;
+ nLen += pListeners->getLength();
+ }
+ return nLen;
+}
+
+void SbaXPropertyChangeMultiplexer::Notify(::comphelper::OInterfaceContainerHelper3<XPropertyChangeListener>& rListeners, const css::beans::PropertyChangeEvent& e)
+{
+ css::beans::PropertyChangeEvent aMulti(e);
+ aMulti.Source = &m_rParent;
+ rListeners.notifyEach( &XPropertyChangeListener::propertyChange, aMulti );
+}
+
+// css::beans::XVetoableChangeListener
+SbaXVetoableChangeMultiplexer::SbaXVetoableChangeMultiplexer(::cppu::OWeakObject& rSource, ::osl::Mutex& rMutex)
+ :OSbaWeakSubObject(rSource)
+ ,m_aListeners(rMutex)
+{
+}
+
+css::uno::Any SAL_CALL SbaXVetoableChangeMultiplexer::queryInterface(const css::uno::Type& _rType)
+{
+ css::uno::Any aReturn = OSbaWeakSubObject::queryInterface(_rType);
+ if (!aReturn.hasValue())
+ aReturn = ::cppu::queryInterface(_rType,
+ static_cast< css::beans::XVetoableChangeListener* >(this),
+ static_cast< css::lang::XEventListener* >(static_cast< css::beans::XVetoableChangeListener* >(this))
+ );
+
+ return aReturn;
+}
+void SAL_CALL SbaXVetoableChangeMultiplexer::disposing(const css::lang::EventObject& )
+{
+}
+void SAL_CALL SbaXVetoableChangeMultiplexer::vetoableChange(const css::beans::PropertyChangeEvent& e)
+{
+ ::comphelper::OInterfaceContainerHelper3<css::beans::XVetoableChangeListener>* pListeners = m_aListeners.getContainer(e.PropertyName);
+ if (pListeners)
+ Notify(*pListeners, e);
+
+ /* do the notification for the unspecialized listeners, too */
+ pListeners = m_aListeners.getContainer(OUString());
+ if (pListeners)
+ Notify(*pListeners, e);
+}
+
+void SbaXVetoableChangeMultiplexer::addInterface(const OUString& rName,
+ const css::uno::Reference< css::beans::XVetoableChangeListener > & rListener)
+{
+ m_aListeners.addInterface(rName, rListener);
+}
+
+void SbaXVetoableChangeMultiplexer::removeInterface(const OUString& rName,
+ const css::uno::Reference< css::beans::XVetoableChangeListener > & rListener)
+{
+ m_aListeners.removeInterface(rName, rListener);
+}
+
+void SbaXVetoableChangeMultiplexer::disposeAndClear()
+{
+ css::lang::EventObject aEvt(m_rParent);
+ m_aListeners.disposeAndClear(aEvt);
+}
+
+sal_Int32 SbaXVetoableChangeMultiplexer::getOverallLen() const
+{
+ sal_Int32 nLen = 0;
+ const std::vector< OUString > aContained = m_aListeners.getContainedTypes();
+ for ( OUString const & s : aContained)
+ {
+ ::comphelper::OInterfaceContainerHelper3<XVetoableChangeListener>* pListeners = m_aListeners.getContainer(s);
+ if (!pListeners)
+ continue;
+ nLen += pListeners->getLength();
+ }
+ return nLen;
+}
+
+void SbaXVetoableChangeMultiplexer::Notify(::comphelper::OInterfaceContainerHelper3<XVetoableChangeListener>& rListeners, const css::beans::PropertyChangeEvent& e)
+{
+ css::beans::PropertyChangeEvent aMulti(e);
+ aMulti.Source = &m_rParent;
+ rListeners.notifyEach( &XVetoableChangeListener::vetoableChange, aMulti );
+}
+
+// css::beans::XPropertiesChangeListener
+SbaXPropertiesChangeMultiplexer::SbaXPropertiesChangeMultiplexer(::cppu::OWeakObject& rSource, ::osl::Mutex& _rMutex)
+ :OSbaWeakSubObject(rSource)
+ ,OInterfaceContainerHelper3(_rMutex)
+{
+}
+
+css::uno::Any SAL_CALL SbaXPropertiesChangeMultiplexer::queryInterface(const css::uno::Type& _rType)
+{
+ css::uno::Any aReturn = OSbaWeakSubObject::queryInterface(_rType);
+ if (!aReturn.hasValue())
+ aReturn = ::cppu::queryInterface(_rType,
+ static_cast< css::beans::XPropertiesChangeListener* >(this),
+ static_cast< css::lang::XEventListener* >(static_cast< css::beans::XPropertiesChangeListener* >(this))
+ );
+
+ return aReturn;
+}
+void SAL_CALL SbaXPropertiesChangeMultiplexer::disposing(const css::lang::EventObject& )
+{
+}
+
+void SbaXPropertiesChangeMultiplexer::propertiesChange(const css::uno::Sequence< css::beans::PropertyChangeEvent>& aEvts)
+{
+ // the SbaXPropertiesChangeMultiplexer doesn't care about the property names a listener logs on for, it simply
+ // forwards _all_ changes to _all_ listeners
+
+ css::uno::Sequence< css::beans::PropertyChangeEvent> aMulti(aEvts);
+ for (css::beans::PropertyChangeEvent & rEvent : asNonConstRange(aMulti))
+ rEvent.Source = &m_rParent;
+
+ notifyEach( &css::beans::XPropertiesChangeListener::propertiesChange, aMulti );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/browser/unodatbr.cxx b/dbaccess/source/ui/browser/unodatbr.cxx
new file mode 100644
index 000000000..b993fac97
--- /dev/null
+++ b/dbaccess/source/ui/browser/unodatbr.cxx
@@ -0,0 +1,3819 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <browserids.hxx>
+#include <core_resource.hxx>
+#include <helpids.h>
+#include <dbtreelistbox.hxx>
+#include "dbtreemodel.hxx"
+#include <strings.hrc>
+#include <imageprovider.hxx>
+#include <sbagrid.hxx>
+#include <strings.hxx>
+#include <UITools.hxx>
+#include <unodatbr.hxx>
+
+#include <com/sun/star/awt/MouseWheelBehavior.hpp>
+#include <com/sun/star/awt/TextAlign.hpp>
+#include <com/sun/star/awt/VisualEffect.hpp>
+#include <com/sun/star/beans/NamedValue.hpp>
+#include <com/sun/star/beans/PropertyValue.hpp>
+#include <com/sun/star/beans/XMultiPropertySet.hpp>
+#include <com/sun/star/container/XNameContainer.hpp>
+#include <com/sun/star/form/XGridColumnFactory.hpp>
+#include <com/sun/star/form/XLoadable.hpp>
+#include <com/sun/star/form/XReset.hpp>
+#include <com/sun/star/frame/Desktop.hpp>
+#include <com/sun/star/frame/FrameSearchFlag.hpp>
+#include <com/sun/star/frame/XLayoutManager.hpp>
+#include <com/sun/star/lang/DisposedException.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/i18n/Collator.hpp>
+#include <com/sun/star/sdb/CommandType.hpp>
+#include <com/sun/star/sdb/SQLContext.hpp>
+#include <com/sun/star/sdb/XDatabaseContext.hpp>
+#include <com/sun/star/sdb/XDatabaseRegistrations.hpp>
+#include <com/sun/star/sdb/XDocumentDataSource.hpp>
+#include <com/sun/star/sdb/XParametersSupplier.hpp>
+#include <com/sun/star/sdb/XQueriesSupplier.hpp>
+#include <com/sun/star/sdb/XQueryDefinitionsSupplier.hpp>
+#include <com/sun/star/sdb/XResultSetAccess.hpp>
+#include <com/sun/star/sdb/XSingleSelectQueryComposer.hpp>
+#include <com/sun/star/sdb/application/NamedDatabaseObject.hpp>
+#include <com/sun/star/sdbc/ColumnValue.hpp>
+#include <com/sun/star/sdbc/DataType.hpp>
+#include <com/sun/star/sdbc/FetchDirection.hpp>
+#include <com/sun/star/sdbc/SQLWarning.hpp>
+#include <com/sun/star/sdbc/XDataSource.hpp>
+#include <com/sun/star/sdbc/XWarningsSupplier.hpp>
+#include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
+#include <com/sun/star/sdbcx/XTablesSupplier.hpp>
+#include <com/sun/star/sdbcx/XViewsSupplier.hpp>
+#include <com/sun/star/task/InteractionHandler.hpp>
+#include <com/sun/star/util/XFlushable.hpp>
+#include <com/sun/star/util/XNumberFormatter.hpp>
+#include <com/sun/star/util/XURLTransformer.hpp>
+#include <com/sun/star/document/MacroExecMode.hpp>
+#include <com/sun/star/ui/XContextMenuInterceptor.hpp>
+
+#include <comphelper/extract.hxx>
+#include <comphelper/sequence.hxx>
+#include <comphelper/types.hxx>
+#include <connectivity/dbexception.hxx>
+#include <cppuhelper/exc_hlp.hxx>
+#include <i18nlangtag/languagetag.hxx>
+#include <svl/filenotation.hxx>
+#include <svx/dataaccessdescriptor.hxx>
+#include <svx/databaseregistrationui.hxx>
+#include <toolkit/helper/vclunohelper.hxx>
+#include <tools/diagnose_ex.h>
+#include <osl/diagnose.h>
+#include <sal/log.hxx>
+#include <tools/multisel.hxx>
+#include <tools/urlobj.hxx>
+#include <unotools/confignode.hxx>
+#include <vcl/split.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/toolbox.hxx>
+#include <vcl/settings.hxx>
+#include <vcl/weld.hxx>
+
+#include <memory>
+
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::awt;
+using namespace ::com::sun::star::sdb;
+using namespace ::com::sun::star::sdb::application;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::sdbcx;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::util;
+using namespace ::com::sun::star::frame;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::ui::dialogs;
+using namespace ::com::sun::star::task;
+using namespace ::com::sun::star::form;
+using namespace ::com::sun::star::io;
+using namespace ::com::sun::star::i18n;
+using namespace ::com::sun::star::view;
+using namespace ::com::sun::star::datatransfer;
+using namespace ::com::sun::star::document;
+using namespace ::com::sun::star::ui;
+using namespace ::dbtools;
+using namespace ::comphelper;
+using namespace ::svx;
+
+// SbaTableQueryBrowser
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+org_openoffice_comp_dbu_ODatasourceBrowser_get_implementation(
+ css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const& )
+{
+ SolarMutexGuard aGuard;
+ return cppu::acquire(new ::dbaui::SbaTableQueryBrowser(context));
+}
+
+namespace dbaui
+{
+
+namespace DatabaseObject = css::sdb::application::DatabaseObject;
+namespace DatabaseObjectContainer = css::sdb::application::DatabaseObjectContainer;
+
+static void SafeAddPropertyListener(const Reference< XPropertySet > & xSet, const OUString& rPropName, XPropertyChangeListener* pListener)
+{
+ Reference< XPropertySetInfo > xInfo = xSet->getPropertySetInfo();
+ if (xInfo->hasPropertyByName(rPropName))
+ xSet->addPropertyChangeListener(rPropName, pListener);
+}
+
+static void SafeRemovePropertyListener(const Reference< XPropertySet > & xSet, const OUString& rPropName, XPropertyChangeListener* pListener)
+{
+ Reference< XPropertySetInfo > xInfo = xSet->getPropertySetInfo();
+ if (xInfo->hasPropertyByName(rPropName))
+ xSet->removePropertyChangeListener(rPropName, pListener);
+}
+
+OUString SAL_CALL SbaTableQueryBrowser::getImplementationName()
+{
+ return "org.openoffice.comp.dbu.ODatasourceBrowser";
+}
+
+css::uno::Sequence<OUString> SAL_CALL SbaTableQueryBrowser::getSupportedServiceNames()
+{
+ return { "com.sun.star.sdb.DataSourceBrowser" };
+}
+
+SbaTableQueryBrowser::SbaTableQueryBrowser(const Reference< XComponentContext >& _rM)
+ :SbaXDataBrowserController(_rM)
+ ,m_aSelectionListeners( getMutex() )
+ ,m_aContextMenuInterceptors( getMutex() )
+ ,m_aTableCopyHelper(this)
+ ,m_pTreeView(nullptr)
+ ,m_pSplitter(nullptr)
+ ,m_nAsyncDrop(nullptr)
+ ,m_bQueryEscapeProcessing( false )
+ ,m_bShowMenu(false)
+ ,m_bInSuspend(false)
+ ,m_bEnableBrowser(true)
+{
+}
+
+SbaTableQueryBrowser::~SbaTableQueryBrowser()
+{
+ if ( !rBHelper.bDisposed && !rBHelper.bInDispose )
+ {
+ SAL_WARN("dbaccess.ui", "Please check who doesn't dispose this component!");
+ // increment ref count to prevent double call of Dtor
+ osl_atomic_increment( &m_refCount );
+ dispose();
+ }
+ SolarMutexGuard g;
+ m_pTreeView.reset();
+ m_pSplitter.reset();
+}
+
+Any SAL_CALL SbaTableQueryBrowser::queryInterface(const Type& _rType)
+{
+ if ( _rType.equals( cppu::UnoType<XScriptInvocationContext>::get() ) )
+ {
+ OSL_PRECOND( !!m_aDocScriptSupport, "SbaTableQueryBrowser::queryInterface: did not initialize this, yet!" );
+ if ( !!m_aDocScriptSupport && *m_aDocScriptSupport )
+ return Any( Reference< XScriptInvocationContext >( this ) );
+ return Any();
+ }
+
+ Any aReturn = SbaXDataBrowserController::queryInterface(_rType);
+ if (!aReturn.hasValue())
+ aReturn = SbaTableQueryBrowser_Base::queryInterface(_rType);
+ return aReturn;
+}
+
+Sequence< Type > SAL_CALL SbaTableQueryBrowser::getTypes( )
+{
+ Sequence< Type > aTypes( ::comphelper::concatSequences(
+ SbaXDataBrowserController::getTypes(),
+ SbaTableQueryBrowser_Base::getTypes()
+ ) );
+
+ OSL_PRECOND( !!m_aDocScriptSupport, "SbaTableQueryBrowser::getTypes: did not initialize this, yet!" );
+ if ( !m_aDocScriptSupport || !*m_aDocScriptSupport )
+ {
+ auto [begin, end] = asNonConstRange(aTypes);
+ auto newEnd = std::remove_if( begin, end,
+ [](const Type& type)
+ { return type == cppu::UnoType<XScriptInvocationContext>::get(); } );
+ aTypes.realloc( std::distance(begin, newEnd) );
+ }
+ return aTypes;
+}
+
+Sequence< sal_Int8 > SAL_CALL SbaTableQueryBrowser::getImplementationId( )
+{
+ return css::uno::Sequence<sal_Int8>();
+}
+
+void SAL_CALL SbaTableQueryBrowser::disposing()
+{
+ SolarMutexGuard aGuard;
+ // doin' a lot of VCL stuff here -> lock the SolarMutex
+
+ // kiss our listeners goodbye
+ css::lang::EventObject aEvt(*this);
+ m_aSelectionListeners.disposeAndClear(aEvt);
+ m_aContextMenuInterceptors.disposeAndClear(aEvt);
+
+ if (getBrowserView())
+ {
+ // Need to do some cleanup of the data pointed to the tree view entries before we remove the treeview
+ clearTreeModel();
+ m_pTreeView = nullptr;
+ getBrowserView()->setTreeView(nullptr);
+ }
+
+ // remove ourself as status listener
+ implRemoveStatusListeners();
+
+ // check out from all the objects we are listening
+ // the frame
+ if (m_xCurrentFrameParent.is())
+ m_xCurrentFrameParent->removeFrameActionListener(static_cast<css::frame::XFrameActionListener*>(this));
+
+ // remove the container listener from the database context
+ try
+ {
+ Reference< XDatabaseRegistrations > xDatabaseRegistrations( m_xDatabaseContext, UNO_QUERY_THROW );
+ xDatabaseRegistrations->removeDatabaseRegistrationsListener( this );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+
+ SbaXDataBrowserController::disposing();
+}
+
+bool SbaTableQueryBrowser::Construct(vcl::Window* pParent)
+{
+ if ( !SbaXDataBrowserController::Construct( pParent ) )
+ return false;
+
+ try
+ {
+ Reference< XDatabaseRegistrations > xDatabaseRegistrations( m_xDatabaseContext, UNO_QUERY_THROW );
+ xDatabaseRegistrations->addDatabaseRegistrationsListener( this );
+
+ // the collator for the string compares
+ m_xCollator = Collator::create( getORB() );
+ m_xCollator->loadDefaultCollator( Application::GetSettings().GetLanguageTag().getLocale(), 0 );
+ }
+ catch(const Exception&)
+ {
+ SAL_WARN("dbaccess.ui", "SbaTableQueryBrowser::Construct: could not create (or start listening at) the database context!");
+ }
+
+ // some help ids
+ if (!getBrowserView() || !getBrowserView()->getVclControl())
+ return true;
+
+ // create controls and set sizes
+ const tools::Long nFrameWidth = getBrowserView()->LogicToPixel(::Size(3, 0), MapMode(MapUnit::MapAppFont)).Width();
+
+ m_pSplitter = VclPtr<Splitter>::Create(getBrowserView(),WB_HSCROLL);
+ m_pSplitter->SetPosSizePixel( ::Point(0,0), ::Size(nFrameWidth,0) );
+ m_pSplitter->SetBackground( Wallpaper( Application::GetSettings().GetStyleSettings().GetDialogColor() ) );
+
+ m_pTreeView = VclPtr<InterimDBTreeListBox>::Create(getBrowserView());
+
+ weld::TreeView& rTreeView = m_pTreeView->GetWidget();
+ rTreeView.connect_expanding(LINK(this, SbaTableQueryBrowser, OnExpandEntry));
+
+ m_pTreeView->setCopyHandler(LINK(this, SbaTableQueryBrowser, OnCopyEntry));
+
+ m_pTreeView->setContextMenuProvider( this );
+ m_pTreeView->setControlActionListener( this );
+ m_pTreeView->SetHelpId(HID_CTL_TREEVIEW);
+
+ // a default pos for the splitter, so that the listbox is about 80 (logical) pixels wide
+ m_pSplitter->SetSplitPosPixel(getBrowserView()->LogicToPixel(::Size(80, 0), MapMode(MapUnit::MapAppFont)).Width());
+
+ getBrowserView()->setSplitter(m_pSplitter);
+ getBrowserView()->setTreeView(m_pTreeView);
+
+ // fill view with data
+ rTreeView.set_sort_order(true);
+ rTreeView.set_sort_func([this](const weld::TreeIter& rLeft, const weld::TreeIter& rRight){
+ return OnTreeEntryCompare(rLeft, rRight);
+ });
+ rTreeView.make_sorted();
+ m_pTreeView->SetSelChangeHdl(LINK(this, SbaTableQueryBrowser, OnSelectionChange));
+ m_pTreeView->show_container();
+
+ // TODO
+ getBrowserView()->getVclControl()->SetHelpId(HID_CTL_TABBROWSER);
+ if (getBrowserView()->getVclControl()->GetHeaderBar())
+ getBrowserView()->getVclControl()->GetHeaderBar()->SetHelpId(HID_DATABROWSE_HEADER);
+ InvalidateFeature(ID_BROWSER_EXPLORER);
+
+ return true;
+}
+
+namespace
+{
+ struct SelectValueByName
+ {
+ const Any& operator()( OUString const& i_name ) const
+ {
+ return m_rCollection.get( i_name );
+ }
+
+ explicit SelectValueByName( ::comphelper::NamedValueCollection const& i_collection )
+ :m_rCollection( i_collection )
+ {
+ }
+
+ ::comphelper::NamedValueCollection const& m_rCollection;
+ };
+}
+
+void SbaTableQueryBrowser::impl_sanitizeRowSetClauses_nothrow()
+{
+ try
+ {
+ Reference< XPropertySet > xRowSetProps( getRowSet(), UNO_QUERY_THROW );
+ bool bEscapeProcessing = false;
+ OSL_VERIFY( xRowSetProps->getPropertyValue( PROPERTY_ESCAPE_PROCESSING ) >>= bEscapeProcessing );
+ if ( !bEscapeProcessing )
+ // don't touch or interpret anything if escape processing is disabled
+ return;
+
+ Reference< XSingleSelectQueryComposer > xComposer( createParser_nothrow() );
+ if ( !xComposer.is() )
+ // can't do anything. Already reported via assertion in createParser_nothrow.
+ return;
+
+ // the tables participating in the statement
+ const Reference< XTablesSupplier > xSuppTables( xComposer, UNO_QUERY_THROW );
+ const Reference< XNameAccess > xTableNames( xSuppTables->getTables(), UNO_SET_THROW );
+
+ // the columns participating in the statement
+ const Reference< XColumnsSupplier > xSuppColumns( xComposer, UNO_QUERY_THROW );
+ const Reference< XNameAccess > xColumnNames( xSuppColumns->getColumns(), UNO_SET_THROW );
+
+ // check if the order columns apply to tables which really exist in the statement
+ const Reference< XIndexAccess > xOrderColumns( xComposer->getOrderColumns(), UNO_SET_THROW );
+ const sal_Int32 nOrderColumns( xOrderColumns->getCount() );
+ bool invalidColumn = nOrderColumns == 0;
+ for ( sal_Int32 c=0; ( c < nOrderColumns ) && !invalidColumn; ++c )
+ {
+ const Reference< XPropertySet > xOrderColumn( xOrderColumns->getByIndex(c), UNO_QUERY_THROW );
+ OUString sTableName;
+ OSL_VERIFY( xOrderColumn->getPropertyValue( PROPERTY_TABLENAME ) >>= sTableName );
+ OUString sColumnName;
+ OSL_VERIFY( xOrderColumn->getPropertyValue( PROPERTY_NAME ) >>= sColumnName );
+
+ if ( sTableName.isEmpty() )
+ {
+ if ( !xColumnNames->hasByName( sColumnName ) )
+ {
+ invalidColumn = true;
+ break;
+ }
+ }
+ else
+ {
+ if ( !xTableNames->hasByName( sTableName ) )
+ {
+ invalidColumn = true;
+ break;
+ }
+
+ const Reference< XColumnsSupplier > xSuppTableColumns( xTableNames->getByName( sTableName ), UNO_QUERY_THROW );
+ const Reference< XNameAccess > xTableColumnNames( xSuppTableColumns->getColumns(), UNO_SET_THROW );
+ if ( !xTableColumnNames->hasByName( sColumnName ) )
+ {
+ invalidColumn = true;
+ break;
+ }
+ }
+ }
+
+ if ( invalidColumn )
+ {
+ // reset the complete order statement at both the row set and the parser
+ xRowSetProps->setPropertyValue( PROPERTY_ORDER, Any( OUString() ) );
+ xComposer->setOrder( "" );
+ }
+
+ // check if the columns participating in the filter refer to existing tables
+ // TODO: there's no API at all for this. The method which comes nearest to what we need is
+ // "getStructuredFilter", but it returns pure column names only. That is, for a statement like
+ // "SELECT * FROM <table> WHERE <other_table>.<column> = <value>", it will return "<column>". But
+ // there's no API at all to retrieve the information about "<other_table>" - which is what would
+ // be needed here.
+ // That'd be a chance to replace getStructuredFilter with something more reasonable.
+ // So, what really would be handy, is some
+ // XNormalizedFilter getNormalizedFilter();
+ // with
+ // interface XDisjunctiveFilterExpression
+ // {
+ // XConjunctiveFilterTerm getTerm( int index );
+ // }
+ // interface XConjunctiveFilterTerm
+ // {
+ // ComparisonPredicate getPredicate( int index );
+ // }
+ // struct ComparisonPredicate
+ // {
+ // XComparisonOperand Lhs;
+ // SQLFilterOperator Operator;
+ // XComparisonOperand Rhs;
+ // }
+ // interface XComparisonOperand
+ // {
+ // SQLFilterOperand Type;
+ // XPropertySet getColumn();
+ // string getLiteral();
+ // ...
+ // }
+ // enum SQLFilterOperand { Column, Literal, ... }
+ // ... or something like this...
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+}
+
+bool SbaTableQueryBrowser::InitializeForm( const Reference< XPropertySet > & i_formProperties )
+{
+ if (!m_xCurrentlyDisplayed)
+ return true;
+
+ // this method set all format settings from the original table or query
+ try
+ {
+ weld::TreeView& rTreeView = m_pTreeView->GetWidget();
+ DBTreeListUserData* pData = weld::fromId<DBTreeListUserData*>(rTreeView.get_id(*m_xCurrentlyDisplayed));
+ ENSURE_OR_RETURN_FALSE( pData, "SbaTableQueryBrowser::InitializeForm: No user data set at the currently displayed entry!" );
+ ENSURE_OR_RETURN_FALSE( pData->xObjectProperties.is(), "SbaTableQueryBrowser::InitializeForm: No table available!" );
+
+ Reference< XPropertySetInfo > xPSI( pData->xObjectProperties->getPropertySetInfo(), UNO_SET_THROW );
+
+ ::comphelper::NamedValueCollection aPropertyValues;
+
+ const OUString aTransferProperties[] =
+ {
+ OUString(PROPERTY_APPLYFILTER),
+ OUString(PROPERTY_FILTER),
+ OUString(PROPERTY_HAVING_CLAUSE),
+ OUString(PROPERTY_ORDER)
+ };
+ for (const auto & aTransferProperty : aTransferProperties)
+ {
+ if ( !xPSI->hasPropertyByName( aTransferProperty ) )
+ continue;
+ aPropertyValues.put( aTransferProperty, pData->xObjectProperties->getPropertyValue( aTransferProperty ) );
+ }
+
+ std::vector< OUString > aNames( aPropertyValues.getNames() );
+ std::sort(aNames.begin(), aNames.end());
+ Sequence< OUString > aPropNames( comphelper::containerToSequence(aNames) );
+
+ Sequence< Any > aPropValues( aNames.size() );
+ std::transform( aNames.begin(), aNames.end(), aPropValues.getArray(), SelectValueByName( aPropertyValues ) );
+
+ Reference< XMultiPropertySet > xFormMultiSet( i_formProperties, UNO_QUERY_THROW );
+ xFormMultiSet->setPropertyValues( aPropNames, aPropValues );
+
+ impl_sanitizeRowSetClauses_nothrow();
+ }
+ catch ( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ return false;
+ }
+
+ return true;
+}
+
+void SbaTableQueryBrowser::initializePreviewMode()
+{
+ if ( getBrowserView() && getBrowserView()->getVclControl() )
+ {
+ getBrowserView()->getVclControl()->AlwaysEnableInput( false );
+ getBrowserView()->getVclControl()->EnableInput( false );
+ getBrowserView()->getVclControl()->ForceHideScrollbars();
+ }
+ Reference< XPropertySet > xDataSourceSet(getRowSet(), UNO_QUERY);
+ if ( xDataSourceSet.is() )
+ {
+ xDataSourceSet->setPropertyValue("AllowInserts",Any(false));
+ xDataSourceSet->setPropertyValue("AllowUpdates",Any(false));
+ xDataSourceSet->setPropertyValue("AllowDeletes",Any(false));
+ }
+}
+
+void SbaTableQueryBrowser::InitializeGridModel(const Reference< css::form::XFormComponent > & xGrid)
+{
+ try
+ {
+ Reference< css::form::XGridColumnFactory > xColFactory(xGrid, UNO_QUERY);
+ Reference< XNameContainer > xColContainer(xGrid, UNO_QUERY);
+ clearGridColumns( xColContainer );
+
+ Reference< XLoadable > xFormAsLoadable;
+ if (xGrid.is())
+ xFormAsLoadable.set(xGrid->getParent(), css::uno::UNO_QUERY);
+ if (xFormAsLoadable.is() && xFormAsLoadable->isLoaded())
+ {
+ // set the formats from the table
+ if (m_xCurrentlyDisplayed)
+ {
+ Sequence< OUString> aProperties(6 + ( m_bPreview ? 5 : 0 ));
+ Sequence< Any> aValues(7 + ( m_bPreview ? 5 : 0 ));
+
+ weld::TreeView& rTreeView = m_pTreeView->GetWidget();
+ DBTreeListUserData* pData = weld::fromId<DBTreeListUserData*>(rTreeView.get_id(*m_xCurrentlyDisplayed));
+ OSL_ENSURE( pData->xObjectProperties.is(), "SbaTableQueryBrowser::InitializeGridModel: No table available!" );
+ if ( !pData->xObjectProperties.is() )
+ return;
+
+ OUString* pStringIter = aProperties.getArray();
+ Any* pValueIter = aValues.getArray();
+ if ( m_bPreview )
+ {
+ *pStringIter++ = "AlwaysShowCursor";
+ *pValueIter++ <<= false;
+ *pStringIter++ = PROPERTY_BORDER;
+ *pValueIter++ <<= sal_Int16(0);
+ }
+
+ *pStringIter++ = PROPERTY_FONT;
+ *pValueIter++ = pData->xObjectProperties->getPropertyValue(PROPERTY_FONT);
+ *pStringIter++ = PROPERTY_TEXTEMPHASIS;
+ *pValueIter++ = pData->xObjectProperties->getPropertyValue(PROPERTY_TEXTEMPHASIS);
+ *pStringIter++ = PROPERTY_TEXTRELIEF;
+ *pValueIter++ = pData->xObjectProperties->getPropertyValue(PROPERTY_TEXTRELIEF);
+ if ( m_bPreview )
+ {
+ *pStringIter++ = "HasNavigationBar";
+ *pValueIter++ <<= false;
+ *pStringIter++ = "HasRecordMarker";
+ *pValueIter++ <<= false;
+ }
+ *pStringIter++ = PROPERTY_ROW_HEIGHT;
+ *pValueIter++ = pData->xObjectProperties->getPropertyValue(PROPERTY_ROW_HEIGHT);
+ if ( m_bPreview )
+ {
+ *pStringIter++ = "Tabstop";
+ *pValueIter++ <<= false;
+ }
+ *pStringIter++ = PROPERTY_TEXTCOLOR;
+ *pValueIter++ = pData->xObjectProperties->getPropertyValue(PROPERTY_TEXTCOLOR);
+ *pStringIter++ = PROPERTY_TEXTLINECOLOR;
+ *pValueIter++ = pData->xObjectProperties->getPropertyValue(PROPERTY_TEXTLINECOLOR);
+
+ Reference< XMultiPropertySet > xFormMultiSet(xGrid, UNO_QUERY);
+ xFormMultiSet->setPropertyValues(aProperties, aValues);
+ }
+
+ // get the formats supplier of the database we're working with
+ Reference< css::util::XNumberFormatsSupplier > xSupplier = getNumberFormatter()->getNumberFormatsSupplier();
+
+ Reference<XConnection> xConnection;
+ Reference<XPropertySet> xRowSetProps(getRowSet(),UNO_QUERY);
+ xRowSetProps->getPropertyValue( PROPERTY_ACTIVE_CONNECTION ) >>= xConnection;
+ OSL_ENSURE(xConnection.is(),"A ActiveConnection should normally exists!");
+
+ Reference<XChild> xChild(xConnection,UNO_QUERY);
+ Reference<XPropertySet> xDataSourceProp(xChild->getParent(),UNO_QUERY);
+ bool bSuppressVersionCol = false;
+ OSL_VERIFY( xDataSourceProp->getPropertyValue( PROPERTY_SUPPRESSVERSIONCL ) >>= bSuppressVersionCol );
+
+ // insert the column into the gridcontrol so that we see something :-)
+ OUString aCurrentModelType;
+ Reference<XColumnsSupplier> xSupCols(getRowSet(),UNO_QUERY);
+ Reference<XNameAccess> xColumns = xSupCols->getColumns();
+
+ OUString sDefaultProperty;
+ Reference< XPropertySet > xColumn;
+ Reference< XPropertySetInfo > xColPSI;
+ const Sequence<OUString> aColNames = xColumns->getElementNames();
+ for (const OUString& rName : aColNames)
+ {
+ xColumn.set( xColumns->getByName( rName ), UNO_QUERY_THROW );
+ xColPSI.set( xColumn->getPropertySetInfo(), UNO_SET_THROW );
+
+ // ignore the column when it is a rowversion one
+ if ( bSuppressVersionCol
+ && xColPSI->hasPropertyByName( PROPERTY_ISROWVERSION )
+ && ::cppu::any2bool( xColumn->getPropertyValue( PROPERTY_ISROWVERSION ) )
+ )
+ continue;
+
+ // use the result set column's type to determine the type of grid column to create
+ bool bFormattedIsNumeric = true;
+ sal_Int32 nType = ::comphelper::getINT32( xColumn->getPropertyValue( PROPERTY_TYPE ) );
+
+ std::vector< NamedValue > aInitialValues;
+ std::vector< OUString > aCopyProperties;
+ Any aDefault;
+
+ switch(nType)
+ {
+ case DataType::BIT:
+ case DataType::BOOLEAN:
+ {
+ aCurrentModelType = "CheckBox";
+ aInitialValues.emplace_back( "VisualEffect", Any( VisualEffect::FLAT ) );
+ sDefaultProperty = PROPERTY_DEFAULTSTATE;
+
+ sal_Int32 nNullable = ColumnValue::NULLABLE_UNKNOWN;
+ OSL_VERIFY( xColumn->getPropertyValue( PROPERTY_ISNULLABLE ) >>= nNullable );
+ aInitialValues.emplace_back(
+ "TriState",
+ Any( ColumnValue::NO_NULLS != nNullable )
+ );
+ if ( ColumnValue::NO_NULLS == nNullable )
+ aDefault <<= sal_Int16(TRISTATE_FALSE);
+ }
+ break;
+
+ case DataType::LONGVARCHAR:
+ case DataType::CLOB:
+ aInitialValues.emplace_back( "MultiLine", Any( true ) );
+ [[fallthrough]];
+ case DataType::BINARY:
+ case DataType::VARBINARY:
+ case DataType::LONGVARBINARY:
+ aCurrentModelType = "TextField";
+ sDefaultProperty = PROPERTY_DEFAULTTEXT;
+ break;
+
+ case DataType::VARCHAR:
+ case DataType::CHAR:
+ bFormattedIsNumeric = false;
+ [[fallthrough]];
+ default:
+ aCurrentModelType = "FormattedField";
+ sDefaultProperty = PROPERTY_EFFECTIVEDEFAULT;
+
+ if ( xSupplier.is() )
+ aInitialValues.emplace_back( "FormatsSupplier", Any( xSupplier ) );
+ aInitialValues.emplace_back( "TreatAsNumber", Any( bFormattedIsNumeric ) );
+ aCopyProperties.emplace_back(PROPERTY_FORMATKEY );
+ break;
+ }
+
+ aInitialValues.emplace_back( PROPERTY_CONTROLSOURCE, Any( rName ) );
+ OUString sLabel;
+ xColumn->getPropertyValue(PROPERTY_LABEL) >>= sLabel;
+ if ( !sLabel.isEmpty() )
+ aInitialValues.emplace_back( PROPERTY_LABEL, Any( sLabel ) );
+ else
+ aInitialValues.emplace_back( PROPERTY_LABEL, Any( rName ) );
+
+ Reference< XPropertySet > xGridCol( xColFactory->createColumn( aCurrentModelType ), UNO_SET_THROW );
+ Reference< XPropertySetInfo > xGridColPSI( xGridCol->getPropertySetInfo(), UNO_SET_THROW );
+
+ // calculate the default
+ if ( xGridColPSI->hasPropertyByName( PROPERTY_CONTROLDEFAULT ) )
+ {
+ aDefault = xColumn->getPropertyValue( PROPERTY_CONTROLDEFAULT );
+ // default value
+ if ( nType == DataType::BIT || nType == DataType::BOOLEAN )
+ {
+ if ( aDefault.hasValue() )
+ aDefault <<= (comphelper::getString(aDefault).toInt32() == 0) ? sal_Int16(TRISTATE_FALSE) : sal_Int16(TRISTATE_TRUE);
+ else
+ aDefault <<= sal_Int16(TRISTATE_INDET);
+ }
+ }
+
+ if ( aDefault.hasValue() )
+ aInitialValues.emplace_back( sDefaultProperty, aDefault );
+
+ // transfer properties from the definition to the UNO-model :
+ aCopyProperties.emplace_back(PROPERTY_HIDDEN );
+ aCopyProperties.emplace_back(PROPERTY_WIDTH );
+
+ // help text to display for the column
+ Any aDescription;
+ if ( xColPSI->hasPropertyByName( PROPERTY_HELPTEXT ) )
+ aDescription = xColumn->getPropertyValue( PROPERTY_HELPTEXT );
+ OUString sTemp;
+ aDescription >>= sTemp;
+ if ( sTemp.isEmpty() )
+ xColumn->getPropertyValue( PROPERTY_DESCRIPTION ) >>= sTemp;
+
+ aDescription <<= sTemp;
+ aInitialValues.emplace_back( PROPERTY_HELPTEXT, aDescription );
+
+ // ... horizontal justify
+ Any aAlign; aAlign <<= sal_Int16( 0 );
+ Any aColAlign( xColumn->getPropertyValue( PROPERTY_ALIGN ) );
+ if ( aColAlign.hasValue() )
+ aAlign <<= sal_Int16( ::comphelper::getINT32( aColAlign ) );
+ aInitialValues.emplace_back( PROPERTY_ALIGN, aAlign );
+
+ // don't allow the mouse to scroll in the cells
+ if ( xGridColPSI->hasPropertyByName( PROPERTY_MOUSE_WHEEL_BEHAVIOR ) )
+ aInitialValues.emplace_back( PROPERTY_MOUSE_WHEEL_BEHAVIOR, Any( MouseWheelBehavior::SCROLL_DISABLED ) );
+
+ // now set all those values
+ for (auto const& property : aInitialValues)
+ {
+ xGridCol->setPropertyValue( property.Name, property.Value );
+ }
+ for (auto const& copyPropertyName : aCopyProperties)
+ xGridCol->setPropertyValue( copyPropertyName, xColumn->getPropertyValue(copyPropertyName) );
+
+ xColContainer->insertByName(rName, Any(xGridCol));
+ }
+ }
+ }
+ catch(const Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+}
+
+static Reference<XPropertySet> getColumnHelper(const weld::TreeView& rTreeView,
+ const weld::TreeIter* pCurrentlyDisplayed,
+ const Reference<XPropertySet>& rxSource)
+{
+ Reference<XPropertySet> xRet;
+ if (pCurrentlyDisplayed)
+ {
+ DBTreeListUserData* pData = weld::fromId<DBTreeListUserData*>(rTreeView.get_id(*pCurrentlyDisplayed));
+ Reference<XColumnsSupplier> xColumnsSup(pData->xObjectProperties,UNO_QUERY);
+ Reference<XNameAccess> xNames = xColumnsSup->getColumns();
+ OUString aName;
+ rxSource->getPropertyValue(PROPERTY_NAME) >>= aName;
+ if(xNames.is() && xNames->hasByName(aName))
+ xRet.set(xNames->getByName(aName),UNO_QUERY);
+ }
+ return xRet;
+}
+
+void SbaTableQueryBrowser::transferChangedControlProperty(const OUString& _rProperty, const Any& _rNewValue)
+{
+ if (m_xCurrentlyDisplayed)
+ {
+ weld::TreeView& rTreeView = m_pTreeView->GetWidget();
+ DBTreeListUserData* pData = weld::fromId<DBTreeListUserData*>(rTreeView.get_id(*m_xCurrentlyDisplayed));
+ Reference< XPropertySet > xObjectProps = pData->xObjectProperties;
+ OSL_ENSURE(xObjectProps.is(),"SbaTableQueryBrowser::transferChangedControlProperty: no table/query object!");
+ if (xObjectProps.is())
+ xObjectProps->setPropertyValue(_rProperty, _rNewValue);
+ }
+}
+
+void SbaTableQueryBrowser::propertyChange(const PropertyChangeEvent& evt)
+{
+ SbaXDataBrowserController::propertyChange(evt);
+
+ weld::TreeView& rTreeView = m_pTreeView->GetWidget();
+
+ try
+ {
+ Reference< XPropertySet > xSource(evt.Source, UNO_QUERY);
+ if (!xSource.is())
+ return;
+ // one of the many properties which require us to update the definition ?
+ // a column's width ?
+ else if (evt.PropertyName == PROPERTY_WIDTH)
+ { // a column width has changed -> update the model
+ // (the update of the view is done elsewhere)
+ Reference<XPropertySet> xProp = getColumnHelper(rTreeView, m_xCurrentlyDisplayed.get(), xSource);
+ if(xProp.is())
+ {
+ if(!evt.NewValue.hasValue())
+ xProp->setPropertyValue(PROPERTY_WIDTH,Any(sal_Int32(227)));
+ else
+ xProp->setPropertyValue(PROPERTY_WIDTH,evt.NewValue);
+ }
+ }
+
+ // a column's 'visible' state ?
+ else if (evt.PropertyName == PROPERTY_HIDDEN)
+ {
+ Reference<XPropertySet> xProp = getColumnHelper(rTreeView, m_xCurrentlyDisplayed.get(), xSource);
+ if(xProp.is())
+ xProp->setPropertyValue(PROPERTY_HIDDEN,evt.NewValue);
+ }
+
+ // a columns alignment ?
+ else if (evt.PropertyName == PROPERTY_ALIGN)
+ {
+ Reference<XPropertySet> xProp = getColumnHelper(rTreeView, m_xCurrentlyDisplayed.get(), xSource);
+ try
+ {
+ if(xProp.is())
+ {
+ if(evt.NewValue.hasValue())
+ {
+ sal_Int16 nAlign = 0;
+ if(evt.NewValue >>= nAlign)
+ xProp->setPropertyValue(PROPERTY_ALIGN,Any(sal_Int32(nAlign)));
+ else
+ xProp->setPropertyValue(PROPERTY_ALIGN,evt.NewValue);
+ }
+ else
+ xProp->setPropertyValue(PROPERTY_ALIGN,Any(css::awt::TextAlign::LEFT));
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+
+ // a column's format ?
+ else if ( evt.PropertyName == PROPERTY_FORMATKEY
+ && (TypeClass_LONG == evt.NewValue.getValueTypeClass())
+ )
+ {
+ // update the model (means the definition object)
+ Reference<XPropertySet> xProp = getColumnHelper(rTreeView, m_xCurrentlyDisplayed.get(), xSource);
+ if(xProp.is())
+ xProp->setPropertyValue(PROPERTY_FORMATKEY,evt.NewValue);
+ }
+
+ // some table definition properties ?
+ // the height of the rows in the grid ?
+ else if (evt.PropertyName == PROPERTY_ROW_HEIGHT)
+ {
+ if (m_xCurrentlyDisplayed)
+ {
+ DBTreeListUserData* pData = weld::fromId<DBTreeListUserData*>(rTreeView.get_id(*m_xCurrentlyDisplayed));
+ OSL_ENSURE( pData->xObjectProperties.is(), "No table available!" );
+
+ bool bDefault = !evt.NewValue.hasValue();
+ if (bDefault)
+ pData->xObjectProperties->setPropertyValue(PROPERTY_ROW_HEIGHT,Any(sal_Int32(45)));
+ else
+ pData->xObjectProperties->setPropertyValue(PROPERTY_ROW_HEIGHT,evt.NewValue);
+ }
+ }
+
+ else if ( evt.PropertyName == PROPERTY_FONT // the font ?
+ || evt.PropertyName == PROPERTY_TEXTCOLOR // the text color ?
+ || evt.PropertyName == PROPERTY_FILTER // the filter ?
+ || evt.PropertyName == PROPERTY_HAVING_CLAUSE // the having clause ?
+ || evt.PropertyName == PROPERTY_ORDER // the sort ?
+ || evt.PropertyName == PROPERTY_APPLYFILTER // the appliance of the filter ?
+ || evt.PropertyName == PROPERTY_TEXTLINECOLOR // the text line color ?
+ || evt.PropertyName == PROPERTY_TEXTEMPHASIS // the text emphasis ?
+ || evt.PropertyName == PROPERTY_TEXTRELIEF // the text relief ?
+ )
+ {
+ transferChangedControlProperty(evt.PropertyName, evt.NewValue);
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+}
+
+sal_Bool SbaTableQueryBrowser::suspend(sal_Bool bSuspend)
+{
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( getMutex() );
+ if ( getView() && getView()->IsInModalMode() )
+ return false;
+ bool bRet = false;
+ if ( !m_bInSuspend )
+ {
+ m_bInSuspend = true;
+ if ( rBHelper.bDisposed )
+ throw DisposedException( OUString(), *this );
+
+ bRet = SbaXDataBrowserController::suspend(bSuspend);
+ if ( bRet && getView() )
+ getView()->Hide();
+
+ m_bInSuspend = false;
+ }
+
+ return bRet;
+}
+
+void SAL_CALL SbaTableQueryBrowser::statusChanged( const FeatureStateEvent& _rEvent )
+{
+ // search the external dispatcher causing this call
+ Reference< XDispatch > xSource(_rEvent.Source, UNO_QUERY);
+ bool bFound = false;
+ for (auto & externalFeature : m_aExternalFeatures)
+ {
+ if ( _rEvent.FeatureURL.Complete == externalFeature.second.aURL.Complete)
+ {
+ bFound = true;
+ OSL_ENSURE( xSource.get() == externalFeature.second.xDispatcher.get(), "SbaTableQueryBrowser::statusChanged: inconsistent!" );
+ // update the enabled state
+ externalFeature.second.bEnabled = _rEvent.IsEnabled;
+
+ switch ( externalFeature.first )
+ {
+ case ID_BROWSER_DOCUMENT_DATASOURCE:
+ {
+ // if it's the slot for the document data source, remember the state
+ Sequence< PropertyValue > aDescriptor;
+ bool bProperFormat = _rEvent.State >>= aDescriptor;
+ OSL_ENSURE(bProperFormat, "SbaTableQueryBrowser::statusChanged: need a data access descriptor here!");
+ m_aDocumentDataSource.initializeFrom(aDescriptor);
+
+ OSL_ENSURE( ( m_aDocumentDataSource.has(DataAccessDescriptorProperty::DataSource)
+ || m_aDocumentDataSource.has(DataAccessDescriptorProperty::DatabaseLocation)
+ )
+ && m_aDocumentDataSource.has(DataAccessDescriptorProperty::Command)
+ && m_aDocumentDataSource.has(DataAccessDescriptorProperty::CommandType),
+ "SbaTableQueryBrowser::statusChanged: incomplete descriptor!");
+
+ // check if we know the object which is set as document data source
+ checkDocumentDataSource();
+ }
+ break;
+
+ default:
+ // update the toolbox
+ implCheckExternalSlot( externalFeature.first );
+ break;
+ }
+ break;
+ }
+ }
+
+ OSL_ENSURE(bFound, "SbaTableQueryBrowser::statusChanged: don't know who sent this!");
+}
+
+void SbaTableQueryBrowser::checkDocumentDataSource()
+{
+ std::unique_ptr<weld::TreeIter> xDataSourceEntry;
+ std::unique_ptr<weld::TreeIter> xContainerEntry;
+ std::unique_ptr<weld::TreeIter> xObjectEntry = getObjectEntry(m_aDocumentDataSource, &xDataSourceEntry, &xContainerEntry);
+ bool bKnownDocDataSource = static_cast<bool>(xObjectEntry);
+ if (!bKnownDocDataSource)
+ {
+ if (xDataSourceEntry)
+ {
+ // at least the data source is known
+ if (xContainerEntry)
+ {
+ bKnownDocDataSource = true; // assume we know it.
+ // TODO: should we expand the object container? This may be too expensive just for checking...
+ }
+ else
+ {
+ if (m_aDocumentDataSource.has(DataAccessDescriptorProperty::CommandType)
+ && m_aDocumentDataSource.has(DataAccessDescriptorProperty::Command))
+ { // maybe we have a command to be displayed ?
+ sal_Int32 nCommandType = CommandType::TABLE;
+ m_aDocumentDataSource[DataAccessDescriptorProperty::CommandType] >>= nCommandType;
+
+ OUString sCommand;
+ m_aDocumentDataSource[DataAccessDescriptorProperty::Command] >>= sCommand;
+
+ bKnownDocDataSource = (CommandType::COMMAND == nCommandType) && (!sCommand.isEmpty());
+ }
+ }
+ }
+ }
+
+ if ( !bKnownDocDataSource )
+ m_aExternalFeatures[ ID_BROWSER_DOCUMENT_DATASOURCE ].bEnabled = false;
+
+ // update the toolbox
+ implCheckExternalSlot(ID_BROWSER_DOCUMENT_DATASOURCE);
+}
+
+void SbaTableQueryBrowser::extractDescriptorProps(const svx::ODataAccessDescriptor& _rDescriptor, OUString& _rDataSource, OUString& _rCommand, sal_Int32& _rCommandType, bool& _rEscapeProcessing)
+{
+ _rDataSource = _rDescriptor.getDataSource();
+ if ( _rDescriptor.has(DataAccessDescriptorProperty::Command) )
+ _rDescriptor[DataAccessDescriptorProperty::Command] >>= _rCommand;
+ if ( _rDescriptor.has(DataAccessDescriptorProperty::CommandType) )
+ _rDescriptor[DataAccessDescriptorProperty::CommandType] >>= _rCommandType;
+
+ // escape processing is the only one allowed not to be present
+ _rEscapeProcessing = true;
+ if (_rDescriptor.has(DataAccessDescriptorProperty::EscapeProcessing))
+ _rEscapeProcessing = ::cppu::any2bool(_rDescriptor[DataAccessDescriptorProperty::EscapeProcessing]);
+}
+
+namespace
+{
+ bool getDataSourceDisplayName_isURL( const OUString& _rDS, OUString& _rDisplayName, OUString& _rUniqueId )
+ {
+ INetURLObject aURL( _rDS );
+ if ( aURL.GetProtocol() != INetProtocol::NotValid )
+ {
+ _rDisplayName = aURL.getBase(INetURLObject::LAST_SEGMENT,true,INetURLObject::DecodeMechanism::WithCharset);
+ _rUniqueId = aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE );
+ return true;
+ }
+ _rDisplayName = _rDS;
+ _rUniqueId.clear();
+ return false;
+ }
+
+ struct FilterByEntryDataId : public IEntryFilter
+ {
+ OUString sId;
+ explicit FilterByEntryDataId( const OUString& _rId ) : sId( _rId ) { }
+
+ virtual ~FilterByEntryDataId() {}
+
+ virtual bool includeEntry(const void* pEntry) const override;
+ };
+
+ bool FilterByEntryDataId::includeEntry(const void* pUserData) const
+ {
+ const DBTreeListUserData* pData = static_cast<const DBTreeListUserData*>(pUserData);
+ return ( !pData || ( pData->sAccessor == sId ) );
+ }
+}
+
+OUString SbaTableQueryBrowser::getDataSourceAccessor(const weld::TreeIter& rDataSourceEntry) const
+{
+ weld::TreeView& rTreeView = m_pTreeView->GetWidget();
+ DBTreeListUserData* pData = weld::fromId<DBTreeListUserData*>(rTreeView.get_id(rDataSourceEntry));
+ OSL_ENSURE( pData, "SbaTableQueryBrowser::getDataSourceAccessor: invalid entry data!" );
+ OSL_ENSURE( pData->eType == etDatasource, "SbaTableQueryBrowser::getDataSourceAccessor: entry does not denote a data source!" );
+ return !pData->sAccessor.isEmpty() ? pData->sAccessor : GetEntryText(rDataSourceEntry);
+}
+
+std::unique_ptr<weld::TreeIter> SbaTableQueryBrowser::getObjectEntry(const OUString& _rDataSource, const OUString& _rCommand, sal_Int32 nCommandType,
+ std::unique_ptr<weld::TreeIter>* ppDataSourceEntry, std::unique_ptr<weld::TreeIter>* ppContainerEntry, bool bExpandAncestors,
+ const SharedConnection& _rxConnection )
+{
+ if (ppDataSourceEntry)
+ ppDataSourceEntry->reset();
+ if (ppContainerEntry)
+ ppContainerEntry->reset();
+
+ std::unique_ptr<weld::TreeIter> xObject;
+ if ( m_pTreeView )
+ {
+ // look for the data source entry
+ OUString sDisplayName, sDataSourceId;
+ bool bIsDataSourceURL = getDataSourceDisplayName_isURL( _rDataSource, sDisplayName, sDataSourceId );
+ // the display name may differ from the URL for readability reasons
+ // #i33699#
+
+ FilterByEntryDataId aFilter( sDataSourceId );
+ std::unique_ptr<weld::TreeIter> xDataSource = m_pTreeView->GetEntryPosByName( sDisplayName, nullptr, &aFilter );
+ if (!xDataSource) // check if the data source name is a file location
+ {
+ if ( bIsDataSourceURL )
+ {
+ // special case, the data source is a URL
+ // add new entries to the list box model
+ implAddDatasource( _rDataSource, _rxConnection );
+ xDataSource = m_pTreeView->GetEntryPosByName( sDisplayName, nullptr, &aFilter );
+ OSL_ENSURE( xDataSource, "SbaTableQueryBrowser::getObjectEntry: hmm - did not find it again!" );
+ }
+ }
+
+ weld::TreeView& rTreeView = m_pTreeView->GetWidget();
+
+ if (xDataSource)
+ {
+ if (ppDataSourceEntry)
+ {
+ // (caller wants to have it...)
+ *ppDataSourceEntry = rTreeView.make_iterator(xDataSource.get());
+ }
+
+ // expand if required so
+ if (bExpandAncestors)
+ rTreeView.expand_row(*xDataSource);
+
+ // look for the object container
+ std::unique_ptr<weld::TreeIter> xCommandType;
+ if (nCommandType == CommandType::QUERY || nCommandType == CommandType::TABLE)
+ {
+ xCommandType = rTreeView.make_iterator(xDataSource.get());
+ if (!rTreeView.iter_children(*xCommandType))
+ xCommandType.reset();
+ else
+ {
+ // 1st child is queries, so we're already done if looking for CommandType::QUERY
+
+ // 2nd child is tables
+ if (nCommandType == CommandType::TABLE && !rTreeView.iter_next_sibling(*xCommandType))
+ xCommandType.reset();
+ }
+ }
+
+ if (xCommandType)
+ {
+ if (ppContainerEntry)
+ {
+ // (caller wants to have it...)
+ *ppContainerEntry = rTreeView.make_iterator(xCommandType.get());
+ }
+
+ rTreeView.make_unsorted();
+
+ // expand if required so
+ if (bExpandAncestors)
+ {
+ rTreeView.expand_row(*xCommandType);
+ }
+
+ // look for the object
+ sal_Int32 nIndex = 0;
+ do
+ {
+ OUString sPath;
+ switch (nCommandType)
+ {
+ case CommandType::TABLE:
+ sPath = _rCommand;
+ nIndex = -1;
+ break;
+
+ case CommandType::QUERY:
+ sPath = _rCommand.getToken( 0, '/', nIndex );
+ break;
+
+ default:
+ assert(false);
+ }
+ xObject = m_pTreeView->GetEntryPosByName(sPath, xCommandType.get());
+ if (xObject)
+ rTreeView.copy_iterator(*xObject, *xCommandType);
+ else
+ xCommandType.reset();
+ if ( nIndex >= 0 )
+ {
+ if (ensureEntryObject(*xObject))
+ {
+ DBTreeListUserData* pParentData = weld::fromId<DBTreeListUserData*>(rTreeView.get_id(*xObject));
+ Reference< XNameAccess > xCollection( pParentData->xContainer, UNO_QUERY );
+ sal_Int32 nIndex2 = nIndex;
+ sPath = _rCommand.getToken( 0, '/', nIndex2 );
+ try
+ {
+ if ( xCollection->hasByName(sPath) )
+ {
+ if(!m_pTreeView->GetEntryPosByName(sPath, xObject.get()))
+ {
+ Reference<XNameAccess> xChild(xCollection->getByName(sPath),UNO_QUERY);
+ DBTreeListUserData* pEntryData = new DBTreeListUserData;
+ pEntryData->eType = etQuery;
+ if ( xChild.is() )
+ {
+ pEntryData->eType = etQueryContainer;
+ }
+ implAppendEntry(xObject.get(), sPath, pEntryData);
+ }
+ }
+ }
+ catch(const Exception&)
+ {
+ SAL_WARN("dbaccess.ui", "SbaTableQueryBrowser::populateTree: could not fill the tree");
+ }
+ }
+ }
+ }
+ while ( nIndex >= 0 );
+
+ rTreeView.make_sorted();
+ }
+ }
+ }
+ return xObject;
+}
+
+std::unique_ptr<weld::TreeIter> SbaTableQueryBrowser::getObjectEntry(const svx::ODataAccessDescriptor& rDescriptor,
+ std::unique_ptr<weld::TreeIter>* ppDataSourceEntry, std::unique_ptr<weld::TreeIter>* ppContainerEntry)
+{
+ // extract the props from the descriptor
+ OUString sDataSource;
+ OUString sCommand;
+ sal_Int32 nCommandType = CommandType::COMMAND;
+ bool bEscapeProcessing = true;
+ extractDescriptorProps(rDescriptor, sDataSource, sCommand, nCommandType, bEscapeProcessing);
+
+ return getObjectEntry(sDataSource, sCommand, nCommandType, ppDataSourceEntry, ppContainerEntry, false /*bExpandAncestors*/);
+}
+
+void SbaTableQueryBrowser::connectExternalDispatches()
+{
+ Reference< XDispatchProvider > xProvider( getFrame(), UNO_QUERY );
+ OSL_ENSURE(xProvider.is(), "SbaTableQueryBrowser::connectExternalDispatches: no DispatchProvider !");
+ if (!xProvider.is())
+ return;
+
+ if ( m_aExternalFeatures.empty() )
+ {
+ const char* pURLs[] = {
+ ".uno:DataSourceBrowser/DocumentDataSource",
+ ".uno:DataSourceBrowser/FormLetter",
+ ".uno:DataSourceBrowser/InsertColumns",
+ ".uno:DataSourceBrowser/InsertContent",
+ };
+ const sal_uInt16 nIds[] = {
+ ID_BROWSER_DOCUMENT_DATASOURCE,
+ ID_BROWSER_FORMLETTER,
+ ID_BROWSER_INSERTCOLUMNS,
+ ID_BROWSER_INSERTCONTENT
+ };
+
+ for ( size_t i=0; i < SAL_N_ELEMENTS( pURLs ); ++i )
+ {
+ URL aURL;
+ aURL.Complete = OUString::createFromAscii( pURLs[i] );
+ if ( m_xUrlTransformer.is() )
+ m_xUrlTransformer->parseStrict( aURL );
+ m_aExternalFeatures[ nIds[ i ] ] = ExternalFeature( aURL );
+ }
+ }
+
+ for (auto & externalFeature : m_aExternalFeatures)
+ {
+ externalFeature.second.xDispatcher = xProvider->queryDispatch(
+ externalFeature.second.aURL, "_parent", FrameSearchFlag::PARENT
+ );
+
+ if ( externalFeature.second.xDispatcher.get() == static_cast< XDispatch* >( this ) )
+ {
+ SAL_WARN("dbaccess.ui", "SbaTableQueryBrowser::connectExternalDispatches: this should not happen anymore!" );
+ // (nowadays, the URLs aren't in our SupportedFeatures list anymore, so we should
+ // not supply a dispatcher for this)
+ externalFeature.second.xDispatcher.clear();
+ }
+
+ if ( externalFeature.second.xDispatcher.is() )
+ {
+ try
+ {
+ externalFeature.second.xDispatcher->addStatusListener( this, externalFeature.second.aURL );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+
+ implCheckExternalSlot( externalFeature.first );
+ }
+}
+
+void SbaTableQueryBrowser::implCheckExternalSlot( sal_uInt16 _nId )
+{
+ if ( !m_xMainToolbar.is() )
+ return;
+
+ VclPtr<vcl::Window> pToolboxWindow = VCLUnoHelper::GetWindow( m_xMainToolbar );
+ ToolBox* pToolbox = dynamic_cast< ToolBox* >( pToolboxWindow.get() );
+ OSL_ENSURE( pToolbox, "SbaTableQueryBrowser::implCheckExternalSlot: cannot obtain the toolbox window!" );
+
+ // check if we have to hide this item from the toolbox
+ if ( pToolbox )
+ {
+ bool bHaveDispatcher = m_aExternalFeatures[ _nId ].xDispatcher.is();
+ if ( bHaveDispatcher != pToolbox->IsItemVisible( ToolBoxItemId(_nId) ) )
+ bHaveDispatcher ? pToolbox->ShowItem( ToolBoxItemId(_nId) ) : pToolbox->HideItem( ToolBoxItemId(_nId) );
+ }
+
+ // and invalidate this feature in general
+ InvalidateFeature( _nId );
+}
+
+void SAL_CALL SbaTableQueryBrowser::disposing( const css::lang::EventObject& _rSource )
+{
+ // our frame ?
+ Reference< css::frame::XFrame > xSourceFrame(_rSource.Source, UNO_QUERY);
+ if (m_xCurrentFrameParent.is() && (xSourceFrame == m_xCurrentFrameParent))
+ m_xCurrentFrameParent->removeFrameActionListener(static_cast<css::frame::XFrameActionListener*>(this));
+ else
+ {
+ // search the external dispatcher causing this call in our map
+ Reference< XDispatch > xSource(_rSource.Source, UNO_QUERY);
+ if(xSource.is())
+ {
+ ExternalFeaturesMap::const_iterator aLoop = m_aExternalFeatures.begin();
+ ExternalFeaturesMap::const_iterator aEnd = m_aExternalFeatures.end();
+ while (aLoop != aEnd)
+ {
+ if ( aLoop->second.xDispatcher.get() == xSource.get() )
+ {
+ sal_uInt16 nSlot = aLoop->first;
+
+ // remove it
+ aLoop = m_aExternalFeatures.erase(aLoop);
+
+ // maybe update the UI
+ implCheckExternalSlot(nSlot);
+
+ // continue, the same XDispatch may be responsible for more than one URL
+ }
+ ++aLoop;
+ }
+ }
+ else
+ {
+ Reference<XConnection> xCon(_rSource.Source, UNO_QUERY);
+ if ( xCon.is() && m_pTreeView )
+ {
+ // our connection is in dispose so we have to find the entry equal with this connection
+ // and close it what means to collapse the entry
+ // get the top-level representing the removed data source
+ weld::TreeView& rTreeView = m_pTreeView->GetWidget();
+ std::unique_ptr<weld::TreeIter> xDSLoop(rTreeView.make_iterator());
+ if (rTreeView.get_iter_first(*xDSLoop))
+ {
+ do
+ {
+ DBTreeListUserData* pData = weld::fromId<DBTreeListUserData*>(rTreeView.get_id(*xDSLoop));
+ if ( pData && pData->xConnection == xCon )
+ {
+ // we set the connection to null to avoid a second disposing of the connection
+ pData->xConnection.clear();
+ closeConnection(*xDSLoop, false);
+ break;
+ }
+ }
+ while (rTreeView.iter_next_sibling(*xDSLoop));
+ }
+ }
+ else
+ SbaXDataBrowserController::disposing(_rSource);
+ }
+ }
+}
+
+void SbaTableQueryBrowser::implRemoveStatusListeners()
+{
+ // clear all old dispatches
+ for (auto const& externalFeature : m_aExternalFeatures)
+ {
+ if ( externalFeature.second.xDispatcher.is() )
+ {
+ try
+ {
+ externalFeature.second.xDispatcher->removeStatusListener( this, externalFeature.second.aURL );
+ }
+ catch (Exception&)
+ {
+ SAL_WARN("dbaccess.ui", "SbaTableQueryBrowser::implRemoveStatusListeners: could not remove a status listener!");
+ }
+ }
+ }
+ m_aExternalFeatures.clear();
+}
+
+sal_Bool SAL_CALL SbaTableQueryBrowser::select( const Any& _rSelection )
+{
+ SolarMutexGuard aGuard;
+ // doin' a lot of VCL stuff here -> lock the SolarMutex
+
+ Sequence< PropertyValue > aDescriptorSequence;
+ if (!(_rSelection >>= aDescriptorSequence))
+ throw IllegalArgumentException(OUString(), *this, 1);
+ // TODO: error message
+
+ ODataAccessDescriptor aDescriptor;
+ try
+ {
+ aDescriptor = ODataAccessDescriptor(aDescriptorSequence);
+ }
+ catch(const Exception&)
+ {
+ SAL_WARN("dbaccess.ui", "SbaTableQueryBrowser::select: could not extract the descriptor!");
+ }
+
+ // check the presence of the props we need
+ if ( !(aDescriptor.has(DataAccessDescriptorProperty::DataSource) || aDescriptor.has(DataAccessDescriptorProperty::DatabaseLocation)) || !aDescriptor.has(DataAccessDescriptorProperty::Command) || !aDescriptor.has(DataAccessDescriptorProperty::CommandType))
+ throw IllegalArgumentException(OUString(), *this, 1);
+ // TODO: error message
+
+ return implSelect(aDescriptor,true);
+}
+
+Any SAL_CALL SbaTableQueryBrowser::getSelection( )
+{
+ Any aReturn;
+
+ try
+ {
+ Reference< XLoadable > xLoadable(getRowSet(), UNO_QUERY);
+ if (xLoadable.is() && xLoadable->isLoaded())
+ {
+ Reference< XPropertySet > aFormProps(getRowSet(), UNO_QUERY);
+ ODataAccessDescriptor aDescriptor(aFormProps);
+ // remove properties which are not part of our "selection"
+ aDescriptor.erase(DataAccessDescriptorProperty::Connection);
+ aDescriptor.erase(DataAccessDescriptorProperty::Cursor);
+
+ aReturn <<= aDescriptor.createPropertyValueSequence();
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+
+ return aReturn;
+}
+
+void SAL_CALL SbaTableQueryBrowser::addSelectionChangeListener( const Reference< XSelectionChangeListener >& _rxListener )
+{
+ m_aSelectionListeners.addInterface(_rxListener);
+}
+
+void SAL_CALL SbaTableQueryBrowser::removeSelectionChangeListener( const Reference< XSelectionChangeListener >& _rxListener )
+{
+ m_aSelectionListeners.removeInterface(_rxListener);
+}
+
+void SbaTableQueryBrowser::attachFrame(const Reference< css::frame::XFrame > & _xFrame)
+{
+ implRemoveStatusListeners();
+
+ if (m_xCurrentFrameParent.is())
+ m_xCurrentFrameParent->removeFrameActionListener(static_cast<css::frame::XFrameActionListener*>(this));
+
+ SbaXDataBrowserController::attachFrame(_xFrame);
+
+ Reference< XFrame > xCurrentFrame( getFrame() );
+ if ( xCurrentFrame.is() )
+ {
+ m_xCurrentFrameParent = xCurrentFrame->findFrame("_parent",FrameSearchFlag::PARENT);
+ if ( m_xCurrentFrameParent.is() )
+ m_xCurrentFrameParent->addFrameActionListener(static_cast<css::frame::XFrameActionListener*>(this));
+
+ // obtain our toolbox
+ try
+ {
+ Reference< XPropertySet > xFrameProps( m_aCurrentFrame.getFrame(), UNO_QUERY_THROW );
+ Reference< XLayoutManager > xLayouter(
+ xFrameProps->getPropertyValue("LayoutManager"),
+ UNO_QUERY );
+
+ if ( xLayouter.is() )
+ {
+ Reference< XUIElement > xUI(
+ xLayouter->getElement( "private:resource/toolbar/toolbar" ),
+ UNO_SET_THROW );
+ m_xMainToolbar.set(xUI->getRealInterface(), css::uno::UNO_QUERY);
+ OSL_ENSURE( m_xMainToolbar.is(), "SbaTableQueryBrowser::attachFrame: where's my toolbox?" );
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+
+ // get the dispatchers for the external slots
+ connectExternalDispatches();
+}
+
+void SbaTableQueryBrowser::addModelListeners(const Reference< css::awt::XControlModel > & _xGridControlModel)
+{
+ SbaXDataBrowserController::addModelListeners(_xGridControlModel);
+ Reference< XPropertySet > xSourceSet(_xGridControlModel, UNO_QUERY);
+ if (xSourceSet.is())
+ {
+ xSourceSet->addPropertyChangeListener(PROPERTY_ROW_HEIGHT, static_cast<XPropertyChangeListener*>(this));
+ xSourceSet->addPropertyChangeListener(PROPERTY_FONT, static_cast<XPropertyChangeListener*>(this));
+ xSourceSet->addPropertyChangeListener(PROPERTY_TEXTCOLOR, static_cast<XPropertyChangeListener*>(this));
+ xSourceSet->addPropertyChangeListener(PROPERTY_TEXTLINECOLOR, static_cast<XPropertyChangeListener*>(this));
+ xSourceSet->addPropertyChangeListener(PROPERTY_TEXTEMPHASIS, static_cast<XPropertyChangeListener*>(this));
+ xSourceSet->addPropertyChangeListener(PROPERTY_TEXTRELIEF, static_cast<XPropertyChangeListener*>(this));
+ }
+
+}
+
+void SbaTableQueryBrowser::removeModelListeners(const Reference< css::awt::XControlModel > & _xGridControlModel)
+{
+ SbaXDataBrowserController::removeModelListeners(_xGridControlModel);
+ Reference< XPropertySet > xSourceSet(_xGridControlModel, UNO_QUERY);
+ if (xSourceSet.is())
+ {
+ xSourceSet->removePropertyChangeListener(PROPERTY_ROW_HEIGHT, static_cast<XPropertyChangeListener*>(this));
+ xSourceSet->removePropertyChangeListener(PROPERTY_FONT, static_cast<XPropertyChangeListener*>(this));
+ xSourceSet->removePropertyChangeListener(PROPERTY_TEXTCOLOR, static_cast<XPropertyChangeListener*>(this));
+ xSourceSet->removePropertyChangeListener(PROPERTY_TEXTLINECOLOR, static_cast<XPropertyChangeListener*>(this));
+ xSourceSet->removePropertyChangeListener(PROPERTY_TEXTEMPHASIS, static_cast<XPropertyChangeListener*>(this));
+ xSourceSet->removePropertyChangeListener(PROPERTY_TEXTRELIEF, static_cast<XPropertyChangeListener*>(this));
+ }
+}
+
+void SbaTableQueryBrowser::RowChanged()
+{
+ if(getBrowserView())
+ {
+ SbaGridControl* pControl = getBrowserView()->getVclControl();
+ if (!pControl->IsEditing())
+ InvalidateFeature(ID_BROWSER_COPY);
+ }
+ SbaXDataBrowserController::RowChanged();
+}
+
+void SbaTableQueryBrowser::ColumnChanged()
+{
+ if(getBrowserView())
+ {
+ SbaGridControl* pControl = getBrowserView()->getVclControl();
+ if (!pControl->IsEditing())
+ InvalidateFeature(ID_BROWSER_COPY);
+ }
+ SbaXDataBrowserController::ColumnChanged();
+}
+
+void SbaTableQueryBrowser::AddColumnListener(const Reference< XPropertySet > & xCol)
+{
+ SbaXDataBrowserController::AddColumnListener(xCol);
+ SafeAddPropertyListener(xCol, PROPERTY_WIDTH, static_cast<XPropertyChangeListener*>(this));
+ SafeAddPropertyListener(xCol, PROPERTY_HIDDEN, static_cast<XPropertyChangeListener*>(this));
+ SafeAddPropertyListener(xCol, PROPERTY_ALIGN, static_cast<XPropertyChangeListener*>(this));
+ SafeAddPropertyListener(xCol, PROPERTY_FORMATKEY, static_cast<XPropertyChangeListener*>(this));
+}
+
+void SbaTableQueryBrowser::RemoveColumnListener(const Reference< XPropertySet > & xCol)
+{
+ SbaXDataBrowserController::RemoveColumnListener(xCol);
+ SafeRemovePropertyListener(xCol, PROPERTY_WIDTH, static_cast<XPropertyChangeListener*>(this));
+ SafeRemovePropertyListener(xCol, PROPERTY_HIDDEN, static_cast<XPropertyChangeListener*>(this));
+ SafeRemovePropertyListener(xCol, PROPERTY_ALIGN, static_cast<XPropertyChangeListener*>(this));
+ SafeRemovePropertyListener(xCol, PROPERTY_FORMATKEY, static_cast<XPropertyChangeListener*>(this));
+}
+
+void SbaTableQueryBrowser::criticalFail()
+{
+ SbaXDataBrowserController::criticalFail();
+ unloadAndCleanup( false );
+}
+
+void SbaTableQueryBrowser::LoadFinished(bool _bWasSynch)
+{
+ SbaXDataBrowserController::LoadFinished(_bWasSynch);
+
+ m_sQueryCommand.clear();
+ m_bQueryEscapeProcessing = false;
+
+ if (isValid() && !loadingCancelled())
+ {
+ // did we load a query?
+ bool bTemporary; // needed because we m_bQueryEscapeProcessing is only one bit wide (and we want to pass it by reference)
+ if ( implGetQuerySignature( m_sQueryCommand, bTemporary ) )
+ m_bQueryEscapeProcessing = bTemporary;
+ }
+
+ // if the form has been loaded, this means that our "selection" has changed
+ css::lang::EventObject aEvent( *this );
+ m_aSelectionListeners.notifyEach( &XSelectionChangeListener::selectionChanged, aEvent );
+}
+
+bool SbaTableQueryBrowser::getExternalSlotState( sal_uInt16 _nId ) const
+{
+ bool bEnabled = false;
+ ExternalFeaturesMap::const_iterator aPos = m_aExternalFeatures.find( _nId );
+ if ( ( m_aExternalFeatures.end() != aPos ) && aPos->second.xDispatcher.is() )
+ bEnabled = aPos->second.bEnabled;
+ return bEnabled;
+}
+
+FeatureState SbaTableQueryBrowser::GetState(sal_uInt16 nId) const
+{
+ FeatureState aReturn;
+ // (disabled automatically)
+
+ // no chance without a view
+ if (!getBrowserView() || !getBrowserView()->getVclControl())
+ return aReturn;
+
+ switch ( nId )
+ {
+ case ID_TREE_ADMINISTRATE:
+ aReturn.bEnabled = true;
+ return aReturn;
+
+ case ID_BROWSER_CLOSE:
+ // the close button should always be enabled
+ aReturn.bEnabled = !m_bEnableBrowser;
+ return aReturn;
+
+ // "toggle explorer" is always enabled (if we have an explorer)
+ case ID_BROWSER_EXPLORER:
+ aReturn.bEnabled = m_bEnableBrowser;
+ aReturn.bChecked = haveExplorer();
+ return aReturn;
+
+ case ID_BROWSER_REMOVEFILTER:
+ return SbaXDataBrowserController::GetState( nId );
+
+ case ID_BROWSER_COPY:
+ if ( !m_pTreeView->HasChildPathFocus() )
+ // handled below
+ break;
+ [[fallthrough]];
+ case ID_TREE_CLOSE_CONN:
+ case ID_TREE_EDIT_DATABASE:
+ {
+ weld::TreeView& rTreeView = m_pTreeView->GetWidget();
+ std::unique_ptr<weld::TreeIter> xCurrentEntry(rTreeView.make_iterator());
+ if (!rTreeView.get_cursor(xCurrentEntry.get()))
+ return aReturn;
+
+ EntryType eType = getEntryType(*xCurrentEntry);
+ if ( eType == etUnknown )
+ return aReturn;
+
+ std::unique_ptr<weld::TreeIter> xDataSourceEntry = m_pTreeView->GetRootLevelParent(xCurrentEntry.get());
+ DBTreeListUserData* pDSData
+ = xDataSourceEntry
+ ? weld::fromId<DBTreeListUserData*>(rTreeView.get_id(*xDataSourceEntry))
+ : nullptr;
+
+ if ( nId == ID_TREE_CLOSE_CONN )
+ {
+ aReturn.bEnabled = ( pDSData != nullptr ) && pDSData->xConnection.is();
+ }
+ else if ( nId == ID_TREE_EDIT_DATABASE )
+ {
+ ::utl::OConfigurationTreeRoot aConfig( ::utl::OConfigurationTreeRoot::createWithComponentContext( getORB(),
+ "/org.openoffice.Office.DataAccess/Policies/Features/Common" ) );
+ bool bHaveEditDatabase( true );
+ OSL_VERIFY( aConfig.getNodeValue( "EditDatabaseFromDataSourceView" ) >>= bHaveEditDatabase );
+ aReturn.bEnabled = getORB().is() && xDataSourceEntry && bHaveEditDatabase;
+ }
+ else if ( nId == ID_BROWSER_COPY )
+ {
+ aReturn.bEnabled = isEntryCopyAllowed(*xCurrentEntry);
+ }
+
+ return aReturn;
+ }
+ }
+
+ // all slots not handled above are not available if no form is loaded
+ if (!isLoaded())
+ return aReturn;
+
+ try
+ {
+ bool bHandled = false;
+ switch (nId)
+ {
+ case ID_BROWSER_DOCUMENT_DATASOURCE:
+ // the slot is enabled if we have an external dispatcher able to handle it,
+ // and the dispatcher must have enabled the slot in general
+ aReturn.bEnabled = getExternalSlotState( ID_BROWSER_DOCUMENT_DATASOURCE );
+ bHandled = true;
+ break;
+ case ID_BROWSER_REFRESH:
+ aReturn.bEnabled = true;
+ bHandled = true;
+ break;
+ }
+
+ if (bHandled)
+ return aReturn;
+
+ // no chance without valid models
+ if (isValid() && !isValidCursor() && nId != ID_BROWSER_CLOSE)
+ return aReturn;
+
+ switch (nId)
+ {
+ case ID_BROWSER_INSERTCOLUMNS:
+ case ID_BROWSER_INSERTCONTENT:
+ case ID_BROWSER_FORMLETTER:
+ {
+ // the slot is enabled if we have an external dispatcher able to handle it,
+ // and the dispatcher must have enabled the slot in general
+ aReturn.bEnabled = getExternalSlotState( nId );
+
+ // for the Insert* slots, we need at least one selected row
+ if (ID_BROWSER_FORMLETTER != nId)
+ aReturn.bEnabled = aReturn.bEnabled && getBrowserView()->getVclControl()->GetSelectRowCount();
+
+ // disabled for native queries which are not saved within the database
+ Reference< XPropertySet > xDataSource(getRowSet(), UNO_QUERY);
+ try
+ {
+ aReturn.bEnabled = aReturn.bEnabled && xDataSource.is();
+
+ if (xDataSource.is())
+ {
+ sal_Int32 nType = ::comphelper::getINT32(xDataSource->getPropertyValue(PROPERTY_COMMAND_TYPE));
+ aReturn.bEnabled = aReturn.bEnabled &&
+ ( ::comphelper::getBOOL(xDataSource->getPropertyValue(PROPERTY_ESCAPE_PROCESSING)) ||
+ (nType == css::sdb::CommandType::QUERY) );
+ }
+ }
+ catch(DisposedException&)
+ {
+ SAL_WARN("dbaccess.ui", "SbaTableQueryBrowser::GetState: object already disposed!");
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+ break;
+
+ case ID_BROWSER_TITLE:
+ {
+ Reference<XPropertySet> xProp(getRowSet(),UNO_QUERY);
+ sal_Int32 nCommandType = CommandType::TABLE;
+ xProp->getPropertyValue(PROPERTY_COMMAND_TYPE) >>= nCommandType;
+ OUString sTitle;
+ switch (nCommandType)
+ {
+ case CommandType::TABLE:
+ sTitle = DBA_RES(STR_TBL_TITLE); break;
+ case CommandType::QUERY:
+ case CommandType::COMMAND:
+ sTitle = DBA_RES(STR_QRY_TITLE); break;
+ default:
+ SAL_WARN("dbaccess.ui", "SbaTableQueryBrowser::GetState: unknown command type!");
+ }
+ OUString aName;
+ xProp->getPropertyValue(PROPERTY_COMMAND) >>= aName;
+ OUString sObject(aName);
+
+ aReturn.sTitle = sTitle.replaceFirst("#", sObject);
+ aReturn.bEnabled = true;
+ }
+ break;
+ case ID_BROWSER_TABLEATTR:
+ case ID_BROWSER_ROWHEIGHT:
+ case ID_BROWSER_COLATTRSET:
+ case ID_BROWSER_COLWIDTH:
+ aReturn.bEnabled = getBrowserView()->getVclControl() && isValid() && isValidCursor();
+ // aReturn.bEnabled &= getDefinition() && !getDefinition()->GetDatabase()->IsReadOnly();
+ break;
+
+ case ID_BROWSER_COPY:
+ OSL_ENSURE( !m_pTreeView->HasChildPathFocus(), "SbaTableQueryBrowser::GetState( ID_BROWSER_COPY ): this should have been handled above!" );
+ if (getBrowserView()->getVclControl() && !getBrowserView()->getVclControl()->IsEditing())
+ {
+ SbaGridControl* pControl = getBrowserView()->getVclControl();
+ if ( pControl->GetSelectRowCount() )
+ {
+ aReturn.bEnabled = m_aCurrentFrame.isActive();
+ break;
+ }
+ else
+ aReturn.bEnabled = pControl->canCopyCellText(pControl->GetCurRow(), pControl->GetCurColumnId());
+ break;
+ }
+ [[fallthrough]];
+ default:
+ return SbaXDataBrowserController::GetState(nId);
+ }
+ }
+ catch(const Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+
+ return aReturn;
+
+}
+
+void SbaTableQueryBrowser::Execute(sal_uInt16 nId, const Sequence< PropertyValue >& aArgs)
+{
+ switch (nId)
+ {
+ default:
+ SbaXDataBrowserController::Execute(nId,aArgs);
+ break;
+
+ case ID_TREE_EDIT_DATABASE:
+ {
+ weld::TreeView& rTreeView = m_pTreeView->GetWidget();
+ std::unique_ptr<weld::TreeIter> xIter(rTreeView.make_iterator());
+ if (rTreeView.get_cursor(xIter.get()))
+ implAdministrate(*xIter);
+ break;
+ }
+ case ID_TREE_CLOSE_CONN:
+ {
+ weld::TreeView& rTreeView = m_pTreeView->GetWidget();
+ std::unique_ptr<weld::TreeIter> xIter(rTreeView.make_iterator());
+ if (rTreeView.get_cursor(xIter.get()))
+ {
+ xIter = m_pTreeView->GetRootLevelParent(xIter.get());
+ closeConnection(*xIter);
+ }
+ break;
+ }
+ case ID_TREE_ADMINISTRATE:
+ svx::administrateDatabaseRegistration( getFrameWeld() );
+ break;
+
+ case ID_BROWSER_REFRESH:
+ {
+ if ( !SaveModified( ) )
+ // nothing to do
+ break;
+
+ bool bFullReinit = false;
+ // check if the query signature (if the form is based on a query) has changed
+ if ( !m_sQueryCommand.isEmpty() )
+ {
+ OUString sNewQueryCommand;
+ bool bNewQueryEP;
+
+ bool bIsQuery =
+ implGetQuerySignature( sNewQueryCommand, bNewQueryEP );
+ OSL_ENSURE( bIsQuery, "SbaTableQueryBrowser::Execute: was a query before, but is not anymore?" );
+
+ bFullReinit = ( sNewQueryCommand != m_sQueryCommand ) || ( m_bQueryEscapeProcessing != bNewQueryEP );
+ }
+ if ( !bFullReinit )
+ {
+ // let the base class do a simple reload
+ SbaXDataBrowserController::Execute(nId,aArgs);
+ break;
+ }
+ [[fallthrough]];
+ }
+
+ case ID_BROWSER_REFRESH_REBUILD:
+ {
+ if ( !SaveModified() )
+ // nothing to do
+ break;
+
+ weld::TreeView& rTreeView = m_pTreeView->GetWidget();
+ std::unique_ptr<weld::TreeIter> xSelected = m_xCurrentlyDisplayed ?
+ rTreeView.make_iterator(m_xCurrentlyDisplayed.get()) : nullptr;
+
+ // unload
+ unloadAndCleanup( false );
+
+ // reselect the entry
+ if ( xSelected )
+ {
+ implSelect(xSelected.get());
+ }
+ else
+ {
+ Reference<XPropertySet> xProp(getRowSet(),UNO_QUERY);
+ implSelect(svx::ODataAccessDescriptor(xProp));
+ }
+ }
+ break;
+
+ case ID_BROWSER_EXPLORER:
+ toggleExplorer();
+ break;
+
+ case ID_BROWSER_DOCUMENT_DATASOURCE:
+ implSelect(m_aDocumentDataSource);
+ break;
+
+ case ID_BROWSER_INSERTCOLUMNS:
+ case ID_BROWSER_INSERTCONTENT:
+ case ID_BROWSER_FORMLETTER:
+ if (getBrowserView() && isValidCursor())
+ {
+ // the URL the slot id is assigned to
+ OSL_ENSURE( m_aExternalFeatures.find( nId ) != m_aExternalFeatures.end(),
+ "SbaTableQueryBrowser::Execute( ID_BROWSER_?): how could this ever be enabled?" );
+ URL aParentUrl = m_aExternalFeatures[ nId ].aURL;
+
+ // let the dispatcher execute the slot
+ Reference< XDispatch > xDispatch( m_aExternalFeatures[ nId ].xDispatcher );
+ if (xDispatch.is())
+ {
+ // set the properties for the dispatch
+
+ // first fill the selection
+ SbaGridControl* pGrid = getBrowserView()->getVclControl();
+ MultiSelection* pSelection = const_cast<MultiSelection*>(pGrid->GetSelection());
+ Sequence< Any > aSelection;
+ if ( !pGrid->IsAllSelected() )
+ { // transfer the selected rows only if not all rows are selected
+ // (all rows means the whole table)
+ // #i3832#
+ if (pSelection != nullptr)
+ {
+ aSelection.realloc(pSelection->GetSelectCount());
+ tools::Long nIdx = pSelection->FirstSelected();
+ Any* pSelectionNos = aSelection.getArray();
+ while (nIdx != SFX_ENDOFSELECTION)
+ {
+ *pSelectionNos++ <<= static_cast<sal_Int32>(nIdx + 1);
+ nIdx = pSelection->NextSelected();
+ }
+ }
+ }
+
+ Reference< XResultSet > xCursorClone;
+ try
+ {
+ Reference< XResultSetAccess > xResultSetAccess(getRowSet(),UNO_QUERY);
+ if (xResultSetAccess.is())
+ xCursorClone = xResultSetAccess->createResultSet();
+ }
+ catch(DisposedException&)
+ {
+ SAL_WARN("dbaccess.ui", "Object already disposed!");
+ }
+ catch(const Exception&)
+ {
+ SAL_WARN("dbaccess.ui", "SbaTableQueryBrowser::Execute(ID_BROWSER_?): could not clone the cursor!");
+ }
+
+ Reference<XPropertySet> xProp(getRowSet(),UNO_QUERY);
+
+ try
+ {
+ ODataAccessDescriptor aDescriptor;
+ OUString sDataSourceName;
+ xProp->getPropertyValue(PROPERTY_DATASOURCENAME) >>= sDataSourceName;
+
+ aDescriptor.setDataSource(sDataSourceName);
+ aDescriptor[DataAccessDescriptorProperty::Command] = xProp->getPropertyValue(PROPERTY_COMMAND);
+ aDescriptor[DataAccessDescriptorProperty::CommandType] = xProp->getPropertyValue(PROPERTY_COMMAND_TYPE);
+ aDescriptor[DataAccessDescriptorProperty::Connection] = xProp->getPropertyValue(PROPERTY_ACTIVE_CONNECTION);
+ aDescriptor[DataAccessDescriptorProperty::Cursor] <<= xCursorClone;
+ if ( aSelection.hasElements() )
+ {
+ aDescriptor[DataAccessDescriptorProperty::Selection] <<= aSelection;
+ aDescriptor[DataAccessDescriptorProperty::BookmarkSelection] <<= false;
+ // these are selection indices
+ // before we change this, all clients have to be adjusted
+ // so that they recognize the new BookmarkSelection property!
+ }
+
+ xDispatch->dispatch(aParentUrl, aDescriptor.createPropertyValueSequence());
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+ }
+ break;
+
+ case ID_BROWSER_CLOSE:
+ closeTask();
+ // if it's not 0, such an async close is already pending
+ break;
+
+ case ID_BROWSER_COPY:
+ if(m_pTreeView->HasChildPathFocus())
+ {
+ weld::TreeView& rTreeView = m_pTreeView->GetWidget();
+ std::unique_ptr<weld::TreeIter> xCursor(rTreeView.make_iterator());
+ if (rTreeView.get_cursor(xCursor.get()))
+ copyEntry(*xCursor);
+ }
+ else if (getBrowserView() && getBrowserView()->getVclControl() && !getBrowserView()->getVclControl()->IsEditing() && getBrowserView()->getVclControl()->GetSelectRowCount() < 1)
+ {
+ SbaGridControl* pControl = getBrowserView()->getVclControl();
+ pControl->copyCellText(pControl->GetCurRow(), pControl->GetCurColumnId());
+ }
+ else
+ SbaXDataBrowserController::Execute(nId,aArgs);
+ break;
+ }
+}
+
+void SbaTableQueryBrowser::implAddDatasource( const OUString& _rDataSourceName, const SharedConnection& _rxConnection )
+{
+ OUString a, b, c, d, e;
+ implAddDatasource( _rDataSourceName, a, d, b, e, c, _rxConnection );
+}
+
+void SbaTableQueryBrowser::implAddDatasource(const OUString& _rDbName, OUString& _rDbImage,
+ OUString& _rQueryName, OUString& _rQueryImage, OUString& _rTableName, OUString& _rTableImage,
+ const SharedConnection& _rxConnection)
+{
+ SolarMutexGuard aGuard;
+ // initialize the names/images if necessary
+ if (_rQueryName.isEmpty())
+ _rQueryName = DBA_RES(RID_STR_QUERIES_CONTAINER);
+ if (_rTableName.isEmpty())
+ _rTableName = DBA_RES(RID_STR_TABLES_CONTAINER);
+
+ if (_rQueryImage.isEmpty())
+ _rQueryImage = ImageProvider::getFolderImageId(DatabaseObject::QUERY);
+ if (_rTableImage.isEmpty())
+ _rTableImage = ImageProvider::getFolderImageId(DatabaseObject::TABLE);
+
+ if (_rDbImage.isEmpty())
+ _rDbImage = ImageProvider::getDatabaseImage();
+
+ // add the entry for the data source
+ // special handling for data sources denoted by URLs - we do not want to display this ugly URL, do we?
+ // #i33699#
+ OUString sDSDisplayName, sDataSourceId;
+ getDataSourceDisplayName_isURL( _rDbName, sDSDisplayName, sDataSourceId );
+
+ weld::TreeView& rTreeView = m_pTreeView->GetWidget();
+ DBTreeListUserData* pDSData = new DBTreeListUserData;
+ pDSData->eType = etDatasource;
+ pDSData->sAccessor = sDataSourceId;
+ pDSData->xConnection = _rxConnection;
+ OUString sId(weld::toId(pDSData));
+
+ std::unique_ptr<weld::TreeIter> xDatasourceEntry(rTreeView.make_iterator());
+ rTreeView.insert(nullptr, -1, &sDSDisplayName, &sId, nullptr, nullptr, false, xDatasourceEntry.get());
+ rTreeView.set_image(*xDatasourceEntry, _rDbImage);
+ rTreeView.set_text_emphasis(*xDatasourceEntry, false, 0);
+
+ // the child for the queries container
+ {
+ DBTreeListUserData* pQueriesData = new DBTreeListUserData;
+ pQueriesData->eType = etQueryContainer;
+ sId = weld::toId(pQueriesData);
+
+ std::unique_ptr<weld::TreeIter> xRet(rTreeView.make_iterator());
+ rTreeView.insert(xDatasourceEntry.get(), -1, &_rQueryName, &sId,
+ nullptr, nullptr, true /*ChildrenOnDemand*/, xRet.get());
+ rTreeView.set_image(*xRet, _rQueryImage);
+ rTreeView.set_text_emphasis(*xRet, false, 0);
+ }
+
+ // the child for the tables container
+ {
+ DBTreeListUserData* pTablesData = new DBTreeListUserData;
+ pTablesData->eType = etTableContainer;
+ sId = weld::toId(pTablesData);
+
+ std::unique_ptr<weld::TreeIter> xRet(rTreeView.make_iterator());
+ rTreeView.insert(xDatasourceEntry.get(), -1, &_rTableName, &sId,
+ nullptr, nullptr, true /*ChildrenOnDemand*/, xRet.get());
+ rTreeView.set_image(*xRet, _rTableImage);
+ rTreeView.set_text_emphasis(*xRet, false, 0);
+ }
+}
+
+void SbaTableQueryBrowser::initializeTreeModel()
+{
+ if (m_xDatabaseContext.is())
+ {
+ OUString aDBImage, aQueriesImage, aTablesImage;
+ OUString sQueriesName, sTablesName;
+
+ // fill the model with the names of the registered datasources
+ const Sequence<OUString> aDatasourceNames = m_xDatabaseContext->getElementNames();
+ for (const OUString& rDatasource : aDatasourceNames)
+ implAddDatasource( rDatasource, aDBImage, sQueriesName, aQueriesImage, sTablesName, aTablesImage, SharedConnection() );
+ }
+}
+
+void SbaTableQueryBrowser::populateTree(const Reference<XNameAccess>& _xNameAccess,
+ const weld::TreeIter& rParent,
+ EntryType eEntryType)
+{
+ weld::TreeView& rTreeView = m_pTreeView->GetWidget();
+ rTreeView.make_unsorted();
+
+ DBTreeListUserData* pData = weld::fromId<DBTreeListUserData*>(rTreeView.get_id(rParent));
+ if (pData) // don't ask if the nameaccess is already set see OnExpandEntry views and tables
+ pData->xContainer = _xNameAccess;
+
+ try
+ {
+ const Sequence<OUString> aNames = _xNameAccess->getElementNames();
+ for (const OUString& rName : aNames)
+ {
+ if( !m_pTreeView->GetEntryPosByName(rName, &rParent))
+ {
+ DBTreeListUserData* pEntryData = new DBTreeListUserData;
+ pEntryData->eType = eEntryType;
+ if ( eEntryType == etQuery )
+ {
+ Reference<XNameAccess> xChild(_xNameAccess->getByName(rName),UNO_QUERY);
+ if ( xChild.is() )
+ pEntryData->eType = etQueryContainer;
+ }
+ implAppendEntry(&rParent, rName, pEntryData);
+ }
+ }
+ }
+ catch(const Exception&)
+ {
+ SAL_WARN("dbaccess.ui", "SbaTableQueryBrowser::populateTree: could not fill the tree");
+ }
+
+ rTreeView.make_sorted();
+}
+
+std::unique_ptr<weld::TreeIter> SbaTableQueryBrowser::implAppendEntry(const weld::TreeIter* pParent, const OUString& rName, const DBTreeListUserData* pUserData)
+{
+ EntryType eEntryType = pUserData->eType;
+
+ std::unique_ptr<ImageProvider> xImageProvider(getImageProviderFor(pParent));
+
+ OUString aImage = xImageProvider->getImageId(rName, getDatabaseObjectType(eEntryType));
+
+ OUString sId(weld::toId(pUserData));
+ weld::TreeView& rTreeView = m_pTreeView->GetWidget();
+ std::unique_ptr<weld::TreeIter> xNewEntry(rTreeView.make_iterator());
+ rTreeView.insert(pParent, -1, &rName, &sId, nullptr, nullptr, eEntryType == etQueryContainer, xNewEntry.get());
+ rTreeView.set_image(*xNewEntry, aImage);
+ rTreeView.set_text_emphasis(*xNewEntry, false, 0);
+
+ return xNewEntry;
+}
+
+IMPL_LINK(SbaTableQueryBrowser, OnExpandEntry, const weld::TreeIter&, rParent, bool)
+{
+ weld::TreeView& rTreeView = m_pTreeView->GetWidget();
+ if (rTreeView.iter_has_child(rParent))
+ {
+ // nothing to do...
+ return true;
+ }
+
+ std::unique_ptr<weld::TreeIter> xFirstParent = m_pTreeView->GetRootLevelParent(&rParent);
+ OSL_ENSURE(xFirstParent,"SbaTableQueryBrowser::OnExpandEntry: No rootlevelparent!");
+
+ DBTreeListUserData* pData = weld::fromId<DBTreeListUserData*>(rTreeView.get_id(rParent));
+ assert(pData && "SbaTableQueryBrowser::OnExpandEntry: No user data!");
+
+ if (etTableContainer == pData->eType)
+ {
+ weld::WaitObject aWaitCursor(getFrameWeld());
+
+ // it could be that we already have a connection
+ SharedConnection xConnection;
+ ensureConnection(xFirstParent.get(), xConnection);
+
+ if ( xConnection.is() )
+ {
+ SQLExceptionInfo aInfo;
+ try
+ {
+ Reference< XWarningsSupplier > xWarnings(xConnection, UNO_QUERY);
+ if (xWarnings.is())
+ xWarnings->clearWarnings();
+
+ // first insert the views because the tables can also include
+ // views but that time the bitmap is the wrong one
+ // the nameaccess will be overwritten in populateTree
+ Reference<XViewsSupplier> xViewSup(xConnection,UNO_QUERY);
+ if(xViewSup.is())
+ populateTree( xViewSup->getViews(), rParent, etTableOrView );
+
+ Reference<XTablesSupplier> xTabSup(xConnection,UNO_QUERY);
+ if(xTabSup.is())
+ {
+ populateTree( xTabSup->getTables(), rParent, etTableOrView );
+ Reference<XContainer> xCont(xTabSup->getTables(),UNO_QUERY);
+ if(xCont.is())
+ // add as listener to know when elements are inserted or removed
+ xCont->addContainerListener(this);
+ }
+
+ if (xWarnings.is())
+ {
+#if 0
+ SQLExceptionInfo aWarnings(xWarnings->getWarnings());
+// Obviously this if test is always false. So to avoid a Clang warning
+// "use of logical '&&' with constant operand" I put this in #if
+// 0. Yeah, I know it is fairly likely nobody will ever read this
+// comment and make a decision what to do here, so I could as well
+// have just binned this...
+ if (aWarnings.isValid() && sal_False)
+ {
+ SQLContext aContext;
+ aContext.Message = DBA_RES(STR_OPENTABLES_WARNINGS);
+ aContext.Details = DBA_RES(STR_OPENTABLES_WARNINGS_DETAILS);
+ aContext.NextException = aWarnings.get();
+ aWarnings = aContext;
+ showError(aWarnings);
+ }
+#endif
+ // TODO: we need a better concept for these warnings:
+ // something like "don't show any warnings for this datasource, again" would be nice
+ // But this requires an extension of the InteractionHandler and an additional property on the data source
+ }
+ }
+ catch(const SQLContext& e) { aInfo = e; }
+ catch(const SQLWarning& e) { aInfo = e; }
+ catch(const SQLException& e) { aInfo = e; }
+ catch(const WrappedTargetException& e)
+ {
+ SQLException aSql;
+ if(e.TargetException >>= aSql)
+ aInfo = aSql;
+ else
+ SAL_WARN("dbaccess.ui", "SbaTableQueryBrowser::OnExpandEntry: something strange happened!");
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ if (aInfo.isValid())
+ showError(aInfo);
+ }
+ else
+ return false;
+ // 0 indicates that an error occurred
+ }
+ else
+ {
+ // we have to expand the queries or bookmarks
+ if (ensureEntryObject(rParent))
+ {
+ DBTreeListUserData* pParentData = weld::fromId<DBTreeListUserData*>(rTreeView.get_id(rParent));
+ Reference< XNameAccess > xCollection( pParentData->xContainer, UNO_QUERY );
+ populateTree(xCollection, rParent, etQuery);
+ }
+ }
+ return true;
+}
+
+bool SbaTableQueryBrowser::ensureEntryObject(const weld::TreeIter& rEntry)
+{
+ EntryType eType = getEntryType(rEntry);
+
+ // the user data of the entry
+ weld::TreeView& rTreeView = m_pTreeView->GetWidget();
+ DBTreeListUserData* pEntryData = weld::fromId<DBTreeListUserData*>(rTreeView.get_id(rEntry));
+ OSL_ENSURE(pEntryData,"ensureEntryObject: user data should already be set!");
+
+ std::unique_ptr<weld::TreeIter> xDataSourceEntry = m_pTreeView->GetRootLevelParent(&rEntry);
+
+ bool bSuccess = false;
+ switch (eType)
+ {
+ case etQueryContainer:
+ {
+ if ( pEntryData->xContainer.is() )
+ {
+ // nothing to do
+ bSuccess = true;
+ break;
+ }
+
+ std::unique_ptr<weld::TreeIter> xParent(rTreeView.make_iterator(&rEntry));
+ if (rTreeView.iter_parent(*xParent))
+ {
+ if (rTreeView.iter_compare(*xParent, *xDataSourceEntry) != 0)
+ {
+ OUString aName(rTreeView.get_text(rEntry));
+ DBTreeListUserData* pData = weld::fromId<DBTreeListUserData*>(rTreeView.get_id(*xParent));
+ try
+ {
+ Reference< XNameAccess > xNameAccess(pData->xContainer,UNO_QUERY);
+ if ( xNameAccess.is() )
+ pEntryData->xContainer.set(xNameAccess->getByName(aName),UNO_QUERY);
+ }
+ catch(const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+
+ bSuccess = pEntryData->xContainer.is();
+ }
+ else
+ {
+ try
+ {
+ Reference< XQueryDefinitionsSupplier > xQuerySup;
+ m_xDatabaseContext->getByName(getDataSourceAccessor(*xDataSourceEntry)) >>= xQuerySup;
+ if (xQuerySup.is())
+ {
+ Reference< XNameAccess > xQueryDefs = xQuerySup->getQueryDefinitions();
+ Reference< XContainer > xCont(xQueryDefs, UNO_QUERY);
+ if (xCont.is())
+ // add as listener to get notified if elements are inserted or removed
+ xCont->addContainerListener(this);
+
+ pEntryData->xContainer = xQueryDefs;
+ bSuccess = pEntryData->xContainer.is();
+ }
+ else {
+ SAL_WARN("dbaccess.ui", "SbaTableQueryBrowser::ensureEntryObject: no XQueryDefinitionsSupplier interface!");
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+ }
+ break;
+ }
+ default:
+ SAL_WARN("dbaccess.ui", "SbaTableQueryBrowser::ensureEntryObject: ooops ... missing some implementation here!");
+ // TODO ...
+ break;
+ }
+ return bSuccess;
+}
+
+bool SbaTableQueryBrowser::implSelect(const svx::ODataAccessDescriptor& _rDescriptor, bool _bSelectDirect)
+{
+ // extract the props
+ OUString sDataSource;
+ OUString sCommand;
+ sal_Int32 nCommandType = CommandType::COMMAND;
+ bool bEscapeProcessing = true;
+ extractDescriptorProps(_rDescriptor, sDataSource, sCommand, nCommandType, bEscapeProcessing);
+
+ // select it
+ return implSelect( sDataSource, sCommand, nCommandType, bEscapeProcessing, SharedConnection(), _bSelectDirect );
+}
+
+bool SbaTableQueryBrowser::implLoadAnything(const OUString& _rDataSourceName, const OUString& _rCommand,
+ const sal_Int32 nCommandType, const bool _bEscapeProcessing, const SharedConnection& _rxConnection)
+{
+ try
+ {
+ Reference<XPropertySet> xProp( getRowSet(), UNO_QUERY_THROW );
+ Reference< XLoadable > xLoadable( xProp, UNO_QUERY_THROW );
+ // the values allowing the RowSet to re-execute
+ xProp->setPropertyValue(PROPERTY_DATASOURCENAME, Any(_rDataSourceName));
+ if(_rxConnection.is())
+ xProp->setPropertyValue( PROPERTY_ACTIVE_CONNECTION, Any( _rxConnection.getTyped() ) );
+
+ // set this _before_ setting the connection, else the rowset would rebuild it ...
+ xProp->setPropertyValue(PROPERTY_COMMAND_TYPE, Any(nCommandType));
+ xProp->setPropertyValue(PROPERTY_COMMAND, Any(_rCommand));
+ xProp->setPropertyValue(PROPERTY_ESCAPE_PROCESSING, css::uno::Any(_bEscapeProcessing));
+ if ( m_bPreview )
+ {
+ xProp->setPropertyValue(PROPERTY_FETCHDIRECTION, Any(FetchDirection::FORWARD));
+ }
+
+ // the formatter depends on the data source we're working on, so rebuild it here ...
+ initFormatter();
+
+ // switch the grid to design mode while loading
+ getBrowserView()->getGridControl()->setDesignMode(true);
+ InitializeForm( xProp );
+
+ bool bSuccess = true;
+
+ {
+ {
+ Reference< XNameContainer > xColContainer(getFormComponent(), UNO_QUERY);
+ // first we have to clear the grid
+ clearGridColumns(xColContainer);
+ }
+ FormErrorHelper aHelper(this);
+ // load the form
+ bSuccess = reloadForm(xLoadable);
+
+ // initialize the model
+ InitializeGridModel(getFormComponent());
+
+ Any aVal = xProp->getPropertyValue(PROPERTY_ISNEW);
+ if (aVal.hasValue() && ::comphelper::getBOOL(aVal))
+ {
+ // then set the default values and the parameters given from the parent
+ Reference< XReset> xReset(xProp, UNO_QUERY);
+ xReset->reset();
+ }
+
+ if ( m_bPreview )
+ initializePreviewMode();
+
+ LoadFinished(true);
+ }
+
+ InvalidateAll();
+ return bSuccess;
+ }
+ catch( const SQLException& )
+ {
+ Any aException( ::cppu::getCaughtException() );
+ showError( SQLExceptionInfo( aException ) );
+ }
+ catch( const WrappedTargetException& e )
+ {
+ if ( e.TargetException.isExtractableTo( ::cppu::UnoType< SQLException >::get() ) )
+ showError( SQLExceptionInfo( e.TargetException ) );
+ else
+ {
+ TOOLS_WARN_EXCEPTION("dbaccess", "");
+ }
+ }
+ catch(const Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+
+ InvalidateAll();
+ return false;
+}
+
+bool SbaTableQueryBrowser::implSelect(const OUString& _rDataSourceName, const OUString& _rCommand,
+ const sal_Int32 nCommandType, const bool _bEscapeProcessing,
+ const SharedConnection& _rxConnection,
+ bool _bSelectDirect)
+{
+ if (!_rDataSourceName.getLength() || !_rCommand.getLength() || (-1 == nCommandType))
+ return false;
+
+ std::unique_ptr<weld::TreeIter> xDataSource;
+ std::unique_ptr<weld::TreeIter> xCommandType;
+ std::unique_ptr<weld::TreeIter> xCommand = getObjectEntry( _rDataSourceName, _rCommand, nCommandType, &xDataSource, &xCommandType, true, _rxConnection );
+
+ if (xCommand)
+ {
+ weld::TreeView& rTreeView = m_pTreeView->GetWidget();
+
+ bool bSuccess = true;
+ if ( _bSelectDirect )
+ {
+ bSuccess = implSelect(xCommand.get());
+ }
+ else
+ {
+ rTreeView.select(*xCommand);
+ }
+
+ if ( bSuccess )
+ {
+ rTreeView.scroll_to_row(*xCommand);
+ rTreeView.set_cursor(*xCommand);
+ }
+ }
+ else if (!xCommandType)
+ {
+ if (m_xCurrentlyDisplayed)
+ {
+ // tell the old entry (if any) it has been deselected
+ selectPath(m_xCurrentlyDisplayed.get(), false);
+ m_xCurrentlyDisplayed.reset();
+ }
+
+ // we have a command and need to display this in the rowset
+ return implLoadAnything(_rDataSourceName, _rCommand, nCommandType, _bEscapeProcessing, _rxConnection);
+ }
+ return false;
+}
+
+IMPL_LINK_NOARG(SbaTableQueryBrowser, OnSelectionChange, LinkParamNone*, void)
+{
+ weld::TreeView& rTreeView = m_pTreeView->GetWidget();
+ std::unique_ptr<weld::TreeIter> xSelection(rTreeView.make_iterator());
+ if (!rTreeView.get_selected(xSelection.get()))
+ xSelection.reset();
+ implSelect(xSelection.get());
+}
+
+std::unique_ptr<weld::TreeIter> SbaTableQueryBrowser::implGetConnectionEntry(const weld::TreeIter& rEntry) const
+{
+ weld::TreeView& rTreeView = m_pTreeView->GetWidget();
+ std::unique_ptr<weld::TreeIter> xCurrentEntry(rTreeView.make_iterator(&rEntry));
+ DBTreeListUserData* pEntryData = weld::fromId<DBTreeListUserData*>(rTreeView.get_id(*xCurrentEntry));
+ while (pEntryData->eType != etDatasource)
+ {
+ rTreeView.iter_parent(*xCurrentEntry);
+ pEntryData = weld::fromId<DBTreeListUserData*>(rTreeView.get_id(*xCurrentEntry));
+ }
+ return xCurrentEntry;
+}
+
+bool SbaTableQueryBrowser::implSelect(const weld::TreeIter* pEntry)
+{
+ if ( !pEntry )
+ return false;
+
+ weld::TreeView& rTreeView = m_pTreeView->GetWidget();
+ DBTreeListUserData* pEntryData = weld::fromId<DBTreeListUserData*>(rTreeView.get_id(*pEntry));
+ switch (pEntryData->eType)
+ {
+ case etTableOrView:
+ case etQuery:
+ break;
+ default:
+ // nothing to do
+ return false;
+ }
+
+ OSL_ENSURE(rTreeView.get_iter_depth(*pEntry) >= 2, "SbaTableQueryBrowser::implSelect: invalid entry!");
+
+ // get the entry for the tables or queries
+ std::unique_ptr<weld::TreeIter> xContainer = rTreeView.make_iterator(pEntry);
+ rTreeView.iter_parent(*xContainer);
+ DBTreeListUserData* pContainerData = weld::fromId<DBTreeListUserData*>(rTreeView.get_id(*xContainer));
+
+ // get the entry for the datasource
+ std::unique_ptr<weld::TreeIter> xConnection = implGetConnectionEntry(*xContainer);
+ DBTreeListUserData* pConData = weld::fromId<DBTreeListUserData*>(rTreeView.get_id(*xConnection));
+
+ // reinitialize the rowset
+ // but first check if it is necessary
+ // get all old properties
+ Reference<XPropertySet> xRowSetProps(getRowSet(),UNO_QUERY);
+ OUString aOldName;
+ xRowSetProps->getPropertyValue(PROPERTY_COMMAND) >>= aOldName;
+ sal_Int32 nOldType = 0;
+ xRowSetProps->getPropertyValue(PROPERTY_COMMAND_TYPE) >>= nOldType;
+ Reference<XConnection> xOldConnection(xRowSetProps->getPropertyValue(PROPERTY_ACTIVE_CONNECTION),UNO_QUERY);
+
+ // the name of the table or query
+ const OUString sSimpleName = rTreeView.get_text(*pEntry);
+ OUStringBuffer sNameBuffer(sSimpleName);
+ if ( etQueryContainer == pContainerData->eType )
+ {
+ std::unique_ptr<weld::TreeIter> xTemp = rTreeView.make_iterator(xContainer.get());
+ std::unique_ptr<weld::TreeIter> xNextTemp = rTreeView.make_iterator(xTemp.get());
+ if (rTreeView.iter_parent(*xNextTemp))
+ {
+ while (rTreeView.iter_compare(*xNextTemp, *xConnection) != 0)
+ {
+ sNameBuffer.insert(0,'/');
+ sNameBuffer.insert(0, rTreeView.get_text(*xTemp));
+ rTreeView.copy_iterator(*xNextTemp, *xTemp);
+ if (!rTreeView.iter_parent(*xNextTemp))
+ break;
+ }
+ }
+ }
+ OUString aName = sNameBuffer.makeStringAndClear();
+
+ sal_Int32 nCommandType = ( etTableContainer == pContainerData->eType)
+ ? CommandType::TABLE
+ : CommandType::QUERY;
+
+ // check if need to rebuild the rowset
+ bool bRebuild = ( xOldConnection != pConData->xConnection )
+ || ( nOldType != nCommandType )
+ || ( aName != aOldName );
+
+ Reference< css::form::XLoadable > xLoadable = getLoadable();
+ bRebuild |= !xLoadable->isLoaded();
+ bool bSuccess = true;
+ if ( bRebuild )
+ {
+ try
+ {
+ weld::WaitObject aWaitCursor(getFrameWeld());
+
+ // tell the old entry it has been deselected
+ selectPath(m_xCurrentlyDisplayed.get(), false);
+ m_xCurrentlyDisplayed.reset();
+
+ // not really loaded
+ m_xCurrentlyDisplayed = rTreeView.make_iterator(pEntry);
+ // tell the new entry it has been selected
+ selectPath(m_xCurrentlyDisplayed.get());
+
+ // get the name of the data source currently selected
+ ensureConnection(m_xCurrentlyDisplayed.get(), pConData->xConnection);
+
+ if ( !pConData->xConnection.is() )
+ {
+ unloadAndCleanup( false );
+ return false;
+ }
+
+ Reference<XNameAccess> xNameAccess;
+ switch(nCommandType)
+ {
+ case CommandType::TABLE:
+ {
+ // only for tables
+ if ( !pContainerData->xContainer.is() )
+ {
+ Reference<XTablesSupplier> xSup( pConData->xConnection, UNO_QUERY );
+ if(xSup.is())
+ xNameAccess = xSup->getTables();
+
+ pContainerData->xContainer = xNameAccess;
+ }
+ else
+ xNameAccess.set( pContainerData->xContainer, UNO_QUERY );
+ }
+ break;
+ case CommandType::QUERY:
+ {
+ if ( pContainerData->xContainer.is() )
+ xNameAccess.set( pContainerData->xContainer, UNO_QUERY );
+ else
+ {
+ Reference<XQueriesSupplier> xSup( pConData->xConnection, UNO_QUERY );
+ if(xSup.is())
+ xNameAccess = xSup->getQueries();
+ }
+ }
+ break;
+ }
+ OUString sStatus(DBA_RES(CommandType::TABLE == nCommandType ? STR_LOADING_TABLE : STR_LOADING_QUERY));
+ sStatus = sStatus.replaceFirst("$name$", aName);
+ BrowserViewStatusDisplay aShowStatus(static_cast<UnoDataBrowserView*>(getView()), sStatus);
+
+ bool bEscapeProcessing = true;
+ if(xNameAccess.is() && xNameAccess->hasByName(sSimpleName))
+ {
+ DBTreeListUserData* pData = weld::fromId<DBTreeListUserData*>(rTreeView.get_id(*pEntry));
+ if ( !pData->xObjectProperties.is() )
+ {
+ Reference<XInterface> xObject;
+ if(xNameAccess->getByName(sSimpleName) >>= xObject) // remember the table or query object
+ {
+ pData->xObjectProperties.set(xObject, css::uno::UNO_QUERY);
+ // if the query contains a parameterized statement and preview is enabled we won't get any data.
+ if ( nCommandType == CommandType::QUERY && xObject.is() )
+ {
+ Reference<XPropertySet> xObjectProps(xObject,UNO_QUERY);
+ xObjectProps->getPropertyValue(PROPERTY_ESCAPE_PROCESSING) >>= bEscapeProcessing;
+ if ( m_bPreview )
+ {
+ OUString sSql;
+ xObjectProps->getPropertyValue(PROPERTY_COMMAND) >>= sSql;
+ Reference< XMultiServiceFactory > xFactory( pConData->xConnection, UNO_QUERY );
+ if (xFactory.is())
+ {
+ try
+ {
+ Reference<XSingleSelectQueryAnalyzer> xAnalyzer(xFactory->createInstance(SERVICE_NAME_SINGLESELECTQUERYCOMPOSER),UNO_QUERY);
+ if ( xAnalyzer.is() )
+ {
+ xAnalyzer->setQuery(sSql);
+ Reference<XParametersSupplier> xParSup(xAnalyzer,UNO_QUERY);
+ if ( xParSup->getParameters()->getCount() > 0 )
+ {
+ OUString sFilter = " WHERE " + xAnalyzer->getFilter();
+ OUString sReplace = sSql.replaceFirst(sFilter, "");
+ xAnalyzer->setQuery(sReplace);
+ Reference<XSingleSelectQueryComposer> xComposer(xAnalyzer,UNO_QUERY);
+ xComposer->setFilter("0=1");
+ aName = xAnalyzer->getQuery();
+ nCommandType = CommandType::COMMAND;
+ }
+ }
+ }
+ catch (Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ OUString sDataSourceName(getDataSourceAccessor(*xConnection));
+ bSuccess = implLoadAnything( sDataSourceName, aName, nCommandType, bEscapeProcessing, pConData->xConnection );
+ if ( !bSuccess )
+ { // clean up
+ criticalFail();
+ }
+ }
+ catch(const SQLException& e)
+ {
+ showError(SQLExceptionInfo(e));
+ // reset the values
+ xRowSetProps->setPropertyValue(PROPERTY_DATASOURCENAME,Any());
+ xRowSetProps->setPropertyValue(PROPERTY_ACTIVE_CONNECTION,Any());
+ bSuccess = false;
+ }
+ catch(WrappedTargetException& e)
+ {
+ SQLException aSql;
+ if(e.TargetException >>= aSql)
+ showError(SQLExceptionInfo(aSql));
+ else
+ SAL_WARN("dbaccess.ui", "SbaTableQueryBrowser::implSelect: something strange happened!");
+ // reset the values
+ xRowSetProps->setPropertyValue(PROPERTY_DATASOURCENAME,Any());
+ xRowSetProps->setPropertyValue(PROPERTY_ACTIVE_CONNECTION,Any());
+ bSuccess = false;
+ }
+ catch(const Exception&)
+ {
+ // reset the values
+ xRowSetProps->setPropertyValue(PROPERTY_DATASOURCENAME,Any());
+ xRowSetProps->setPropertyValue(PROPERTY_ACTIVE_CONNECTION,Any());
+ bSuccess = false;
+ }
+ }
+ return bSuccess;
+}
+
+std::unique_ptr<weld::TreeIter> SbaTableQueryBrowser::getEntryFromContainer(const Reference<XNameAccess>& rxNameAccess)
+{
+ std::unique_ptr<weld::TreeIter> xContainer;
+
+ weld::TreeView& rTreeView = m_pTreeView->GetWidget();
+ std::unique_ptr<weld::TreeIter> xDSLoop(rTreeView.make_iterator(xContainer.get()));
+ if (rTreeView.get_iter_first(*xDSLoop))
+ {
+ do
+ {
+ xContainer = rTreeView.make_iterator(xDSLoop.get());
+ if (rTreeView.iter_children(*xContainer))
+ {
+ // 1st child is queries
+ DBTreeListUserData* pQueriesData = weld::fromId<DBTreeListUserData*>(rTreeView.get_id(*xContainer));
+ if (pQueriesData && pQueriesData->xContainer == rxNameAccess)
+ break;
+
+ if (rTreeView.iter_next_sibling(*xContainer))
+ {
+ // 2nd child is tables
+ DBTreeListUserData* pTablesData = weld::fromId<DBTreeListUserData*>(rTreeView.get_id(*xContainer));
+ if (pTablesData && pTablesData->xContainer == rxNameAccess)
+ break;
+ }
+ }
+ xContainer.reset();
+ }
+ while (rTreeView.iter_next_sibling(*xDSLoop));
+ }
+
+ return xContainer;
+}
+
+void SAL_CALL SbaTableQueryBrowser::elementInserted(const ContainerEvent& rEvent)
+{
+ SolarMutexGuard aSolarGuard;
+
+ Reference< XNameAccess > xNames(rEvent.Source, UNO_QUERY);
+ // first search for a definition container where we can insert this element
+
+ std::unique_ptr<weld::TreeIter> xEntry = getEntryFromContainer(xNames);
+ if (xEntry) // found one
+ {
+ weld::TreeView& rTreeView = m_pTreeView->GetWidget();
+ rTreeView.make_unsorted();
+
+ // insert the new entry into the tree
+ DBTreeListUserData* pContainerData = weld::fromId<DBTreeListUserData*>(rTreeView.get_id(*xEntry));
+ OSL_ENSURE(pContainerData, "elementInserted: There must be user data for this type!");
+
+ DBTreeListUserData* pNewData = new DBTreeListUserData;
+ bool bIsTable = etTableContainer == pContainerData->eType;
+ if ( bIsTable )
+ {
+ rEvent.Element >>= pNewData->xObjectProperties;// remember the new element
+ pNewData->eType = etTableOrView;
+ }
+ else
+ {
+ if (rTreeView.iter_n_children(*xEntry) < xNames->getElementNames().getLength() - 1)
+ {
+ // the item inserts its children on demand, but it has not been expanded yet. So ensure here and
+ // now that it has all items
+ populateTree(xNames, *xEntry, etQuery);
+ }
+ pNewData->eType = etQuery;
+ }
+ implAppendEntry(xEntry.get(), ::comphelper::getString(rEvent.Accessor), pNewData);
+
+ rTreeView.make_sorted();
+ }
+ else
+ SbaXDataBrowserController::elementInserted(rEvent);
+}
+
+bool SbaTableQueryBrowser::isCurrentlyDisplayedChanged(std::u16string_view rName, const weld::TreeIter& rContainer)
+{
+ if (!m_xCurrentlyDisplayed)
+ return false;
+ weld::TreeView& rTreeView = m_pTreeView->GetWidget();
+ if (getEntryType(*m_xCurrentlyDisplayed) != getChildType(rContainer))
+ return false;
+ if (rTreeView.get_text(*m_xCurrentlyDisplayed) != rName)
+ return false;
+ std::unique_ptr<weld::TreeIter> xParent = rTreeView.make_iterator(m_xCurrentlyDisplayed.get());
+ return rTreeView.iter_parent(*xParent) && rTreeView.iter_compare(*xParent, rContainer) == 0;
+}
+
+void SAL_CALL SbaTableQueryBrowser::elementRemoved( const ContainerEvent& _rEvent )
+{
+ SolarMutexGuard aSolarGuard;
+
+ Reference< XNameAccess > xNames(_rEvent.Source, UNO_QUERY);
+ // get the top-level representing the removed data source
+ // and search for the queries and tables
+ std::unique_ptr<weld::TreeIter> xContainer = getEntryFromContainer(xNames);
+ if (xContainer)
+ {
+ // a query or table has been removed
+ OUString aName = ::comphelper::getString(_rEvent.Accessor);
+
+ weld::TreeView& rTreeView = m_pTreeView->GetWidget();
+ if (isCurrentlyDisplayedChanged(aName, *xContainer))
+ {
+ // the element displayed currently has been replaced
+
+ // we need to remember the old value
+ std::unique_ptr<weld::TreeIter> xTemp = rTreeView.make_iterator(m_xCurrentlyDisplayed.get());
+
+ // unload
+ unloadAndCleanup( false ); // don't dispose the connection
+
+ DBTreeListUserData* pData = weld::fromId<DBTreeListUserData*>(rTreeView.get_id(*xTemp));
+ rTreeView.set_id(*xTemp, OUString());
+ delete pData; // the data could be null because we have a table which isn't correct
+ rTreeView.remove(*xTemp);
+ }
+ else
+ {
+ // remove the entry from the model
+ std::unique_ptr<weld::TreeIter> xChild(rTreeView.make_iterator(xContainer.get()));
+ if (rTreeView.get_iter_first(*xChild))
+ {
+ do
+ {
+ if (rTreeView.get_text(*xChild) == aName)
+ {
+ DBTreeListUserData* pData = weld::fromId<DBTreeListUserData*>(rTreeView.get_id(*xChild));
+ rTreeView.set_id(*xChild, OUString());
+ delete pData;
+ rTreeView.remove(*xChild);
+ break;
+ }
+ } while (rTreeView.iter_next_sibling(*xChild));
+ }
+ }
+
+ // maybe the object which is part of the document data source has been removed
+ checkDocumentDataSource();
+ }
+ else
+ SbaXDataBrowserController::elementRemoved(_rEvent);
+}
+
+void SAL_CALL SbaTableQueryBrowser::elementReplaced( const ContainerEvent& _rEvent )
+{
+ SolarMutexGuard aSolarGuard;
+
+ Reference< XNameAccess > xNames(_rEvent.Source, UNO_QUERY);
+ std::unique_ptr<weld::TreeIter> xContainer = getEntryFromContainer(xNames);
+ if (xContainer)
+ {
+ // a table or query as been replaced
+ OUString aName = ::comphelper::getString(_rEvent.Accessor);
+
+ weld::TreeView& rTreeView = m_pTreeView->GetWidget();
+ if (isCurrentlyDisplayedChanged(aName, *xContainer))
+ { // the element displayed currently has been replaced
+
+ // we need to remember the old value
+ std::unique_ptr<weld::TreeIter> xTemp = rTreeView.make_iterator(m_xCurrentlyDisplayed.get());
+ unloadAndCleanup( false ); // don't dispose the connection
+
+ DBTreeListUserData* pData = weld::fromId<DBTreeListUserData*>(rTreeView.get_id(*xTemp));
+ if (pData)
+ {
+ if ( etTableOrView == pData->eType )
+ {
+ // only insert userdata when we have a table because the query is only a commanddefinition object and not a query
+ _rEvent.Element >>= pData->xObjectProperties; // remember the new element
+ }
+ else
+ {
+ rTreeView.set_id(*xTemp, OUString());
+ delete pData;
+ }
+ }
+ }
+ else
+ {
+ // find the entry for this name
+ std::unique_ptr<weld::TreeIter> xChild(rTreeView.make_iterator(xContainer.get()));
+ if (rTreeView.get_iter_first(*xChild))
+ {
+ do
+ {
+ if (rTreeView.get_text(*xChild) == aName)
+ {
+ DBTreeListUserData* pData = weld::fromId<DBTreeListUserData*>(rTreeView.get_id(*xChild));
+ if (pData)
+ {
+ if ( etTableOrView == pData->eType )
+ {
+ // only insert userdata when we have a table because the query is only a commanddefinition object and not a query
+ _rEvent.Element >>= pData->xObjectProperties; // remember the new element
+ }
+ else
+ {
+ rTreeView.set_id(*xChild, OUString());
+ delete pData;
+ }
+ }
+ break;
+ }
+ } while (rTreeView.iter_next_sibling(*xChild));
+ }
+ }
+
+ // maybe the object which is part of the document data source has been removed
+ checkDocumentDataSource();
+ }
+ else if (xNames.get() == m_xDatabaseContext.get())
+ { // a datasource has been replaced in the context
+ SAL_WARN("dbaccess.ui", "SbaTableQueryBrowser::elementReplaced: no support for replaced data sources!");
+ // very suspicious: the database context should not allow to replace data source, only to register
+ // and revoke them
+ }
+ else
+ SbaXDataBrowserController::elementReplaced(_rEvent);
+}
+
+void SbaTableQueryBrowser::impl_releaseConnection( SharedConnection& _rxConnection )
+{
+ // remove as event listener
+ Reference< XComponent > xComponent( _rxConnection, UNO_QUERY );
+ if ( xComponent.is() )
+ {
+ Reference< XEventListener > xListener( static_cast< ::cppu::OWeakObject* >( this ), UNO_QUERY );
+ xComponent->removeEventListener( xListener );
+ }
+
+ try
+ {
+ // temporary (hopefully!) hack for #i55274#
+ Reference< XFlushable > xFlush( _rxConnection, UNO_QUERY );
+ if ( xFlush.is() )
+ xFlush->flush();
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+
+ // clear
+ _rxConnection.clear();
+ // will implicitly dispose if we have the ownership, since xConnection is a SharedConnection
+}
+
+void SbaTableQueryBrowser::disposeConnection(const weld::TreeIter* pDSEntry)
+{
+ OSL_ENSURE( pDSEntry, "SbaTableQueryBrowser::disposeConnection: invalid entry (NULL)!" );
+ OSL_ENSURE( impl_isDataSourceEntry( pDSEntry ), "SbaTableQueryBrowser::disposeConnection: invalid entry (not top-level)!" );
+
+ if (pDSEntry)
+ {
+ weld::TreeView& rTreeView = m_pTreeView->GetWidget();
+ DBTreeListUserData* pTreeListData = weld::fromId<DBTreeListUserData*>(rTreeView.get_id(*pDSEntry));
+ if (pTreeListData)
+ impl_releaseConnection(pTreeListData->xConnection);
+ }
+}
+
+void SbaTableQueryBrowser::closeConnection(const weld::TreeIter& rDSEntry, bool _bDisposeConnection)
+{
+ OSL_ENSURE(impl_isDataSourceEntry(&rDSEntry), "SbaTableQueryBrowser::closeConnection: invalid entry (not top-level)!");
+
+ weld::TreeView& rTreeView = m_pTreeView->GetWidget();
+
+ // if one of the entries of the given DS is displayed currently, unload the form
+ if (m_xCurrentlyDisplayed)
+ {
+ std::unique_ptr<weld::TreeIter> xRoot = m_pTreeView->GetRootLevelParent(m_xCurrentlyDisplayed.get());
+ if (rTreeView.iter_compare(*xRoot, rDSEntry) == 0)
+ unloadAndCleanup(_bDisposeConnection);
+ }
+
+ // collapse the query/table container
+ std::unique_ptr<weld::TreeIter> xContainers(rTreeView.make_iterator(&rDSEntry));
+ if (rTreeView.iter_children(*xContainers))
+ {
+ do
+ {
+ std::unique_ptr<weld::TreeIter> xElements(rTreeView.make_iterator(xContainers.get()));
+ if (rTreeView.iter_children(*xElements))
+ {
+ rTreeView.collapse_row(*xContainers);
+ // and delete their children (they are connection-relative)
+ bool bElements = true;
+ while (bElements)
+ {
+ std::unique_ptr<weld::TreeIter> xRemove(rTreeView.make_iterator(xElements.get()));
+ bElements = rTreeView.iter_next_sibling(*xElements);
+ DBTreeListUserData* pData = weld::fromId<DBTreeListUserData*>(rTreeView.get_id(*xRemove));
+ rTreeView.set_id(*xRemove, OUString());
+ delete pData;
+ rTreeView.remove(*xRemove);
+ }
+ }
+ }
+ while (rTreeView.iter_next_sibling(*xContainers));
+ }
+
+ // collapse the entry itself
+ rTreeView.collapse_row(rDSEntry);
+
+ // dispose/reset the connection
+ if ( _bDisposeConnection )
+ disposeConnection(&rDSEntry);
+}
+
+void SbaTableQueryBrowser::unloadAndCleanup( bool _bDisposeConnection )
+{
+ if (!m_xCurrentlyDisplayed)
+ // nothing to do
+ return;
+
+ std::unique_ptr<weld::TreeIter> xDSEntry = m_pTreeView->GetRootLevelParent(m_xCurrentlyDisplayed.get());
+
+ // de-select the path for the currently displayed table/query
+ selectPath(m_xCurrentlyDisplayed.get(), false);
+ m_xCurrentlyDisplayed.reset();
+
+ try
+ {
+ // get the active connection. We need to dispose it.
+
+ // unload the form
+ Reference< XLoadable > xLoadable = getLoadable();
+ if (xLoadable->isLoaded())
+ xLoadable->unload();
+
+ // clear the grid control
+ Reference< XNameContainer > xConta(getControlModel(),UNO_QUERY);
+ clearGridColumns(xConta);
+
+ // dispose the connection
+ if(_bDisposeConnection)
+ disposeConnection(xDSEntry.get());
+ }
+ catch(SQLException& e)
+ {
+ showError(SQLExceptionInfo(e));
+ }
+ catch(WrappedTargetException& e)
+ {
+ SQLException aSql;
+ if(e.TargetException >>= aSql)
+ showError(SQLExceptionInfo(aSql));
+ else
+ SAL_WARN("dbaccess.ui", "SbaTableQueryBrowser::unloadAndCleanup: something strange happened!");
+ }
+ catch(const Exception&)
+ {
+ SAL_WARN("dbaccess.ui", "SbaTableQueryBrowser::unloadAndCleanup: could not reset the form");
+ }
+}
+
+namespace
+{
+ Reference< XInterface > lcl_getDataSource( const Reference< XDatabaseContext >& _rxDatabaseContext,
+ const OUString& _rDataSourceName, const Reference< XConnection >& _rxConnection )
+ {
+ Reference< XDataSource > xDataSource;
+ try
+ {
+ if ( !_rDataSourceName.isEmpty() && _rxDatabaseContext->hasByName( _rDataSourceName ) )
+ xDataSource.set( _rxDatabaseContext->getByName( _rDataSourceName ), UNO_QUERY_THROW );
+
+ if ( !xDataSource.is() )
+ {
+ Reference< XChild > xConnAsChild( _rxConnection, UNO_QUERY );
+ if ( xConnAsChild.is() )
+ xDataSource.set( xConnAsChild->getParent(), UNO_QUERY_THROW );
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ return xDataSource;
+ }
+}
+
+void SbaTableQueryBrowser::impl_initialize()
+{
+ SolarMutexGuard aGuard;
+ // doin' a lot of VCL stuff here -> lock the SolarMutex
+
+ // first initialize the parent
+ SbaXDataBrowserController::impl_initialize();
+
+ Reference<XConnection> xForeignConnection;
+ Reference< XFrame > xFrame;
+
+ OUString aTableName, aCatalogName, aSchemaName;
+
+ bool bEscapeProcessing = true;
+ sal_Int32 nInitialDisplayCommandType = CommandType::COMMAND;
+ OUString sInitialDataSourceName;
+ OUString sInitialCommand;
+
+ const NamedValueCollection& rArguments( getInitParams() );
+
+ rArguments.get_ensureType( PROPERTY_DATASOURCENAME, sInitialDataSourceName );
+ rArguments.get_ensureType( PROPERTY_COMMAND_TYPE, nInitialDisplayCommandType );
+ rArguments.get_ensureType( PROPERTY_COMMAND, sInitialCommand );
+ rArguments.get_ensureType( PROPERTY_ACTIVE_CONNECTION, xForeignConnection );
+ rArguments.get_ensureType( PROPERTY_UPDATE_CATALOGNAME, aCatalogName );
+ rArguments.get_ensureType( PROPERTY_UPDATE_SCHEMANAME, aSchemaName );
+ rArguments.get_ensureType( PROPERTY_UPDATE_TABLENAME, aTableName );
+ rArguments.get_ensureType( PROPERTY_ESCAPE_PROCESSING, bEscapeProcessing );
+ rArguments.get_ensureType( "Frame", xFrame );
+ rArguments.get_ensureType( PROPERTY_SHOWMENU, m_bShowMenu );
+
+ // disable the browser if either of ShowTreeViewButton (compatibility name) or EnableBrowser
+ // is present and set to FALSE
+ bool bDisableBrowser = !rArguments.getOrDefault( "ShowTreeViewButton", true ) // compatibility name
+ || !rArguments.getOrDefault( PROPERTY_ENABLE_BROWSER, true );
+ OSL_ENSURE( !rArguments.has( "ShowTreeViewButton" ),
+ "SbaTableQueryBrowser::impl_initialize: ShowTreeViewButton is superseded by EnableBrowser!" );
+ m_bEnableBrowser = !bDisableBrowser;
+
+ // hide the tree view it is disabled in general, or if the settings tell to hide it initially
+ bool bHideTreeView = ( !m_bEnableBrowser )
+ || !rArguments.getOrDefault( "ShowTreeView", true ) // compatibility name
+ || !rArguments.getOrDefault( PROPERTY_SHOW_BROWSER, true );
+ OSL_ENSURE( !rArguments.has( "ShowTreeView" ),
+ "SbaTableQueryBrowser::impl_initialize: ShowTreeView is superseded by ShowBrowser!" );
+
+ if ( bHideTreeView )
+ hideExplorer();
+ else
+ showExplorer();
+
+ if ( m_bPreview )
+ {
+ try
+ {
+ Sequence< OUString> aProperties
+ {
+ "AlwaysShowCursor", PROPERTY_BORDER, "HasNavigationBar", "HasRecordMarker", "Tabstop"
+ };
+ Sequence< Any> aValues
+ {
+ Any(false), Any(sal_Int16(0)), Any(false), Any(false), Any(false)
+ };
+ Reference< XMultiPropertySet > xFormMultiSet(getFormComponent(), UNO_QUERY);
+ if ( xFormMultiSet.is() )
+ xFormMultiSet->setPropertyValues(aProperties, aValues);
+ }
+ catch(const Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+
+ // are we loaded into a (sub)frame of an embedded document (i.e. a form belonging to a database
+ // document)?
+ bool bSubFrameOfEmbeddedDocument = false;
+ if ( xFrame.is() )
+ {
+ Reference<XFramesSupplier> xSup = xFrame->getCreator();
+ Reference<XController> xCont = xSup.is() ? xSup->getController() : Reference<XController>();
+
+ bSubFrameOfEmbeddedDocument = xCont.is() && ::dbtools::isEmbeddedInDatabase( xCont->getModel(), xForeignConnection );
+ }
+
+ // if we have a connection at this point, it was either passed from outside, our
+ // determined from an outer DB document. In both cases, do not dispose it later on.
+ SharedConnection xConnection( xForeignConnection, SharedConnection::NoTakeOwnership );
+
+ // should we display all registered databases in the left hand side tree?
+ // or only *one* special?
+ bool bLimitedTreeEntries = false;
+ // if we're part of a frame which is a secondary frame of a database document, then only
+ // display the database for this document, not all registered ones
+ bLimitedTreeEntries |= bSubFrameOfEmbeddedDocument;
+ // if the tree view is not to be displayed at all, then only display the data source
+ // which was given as initial selection
+ bLimitedTreeEntries |= !m_bEnableBrowser;
+
+ weld::TreeView& rTreeView = m_pTreeView->GetWidget();
+ rTreeView.make_unsorted();
+
+ if ( bLimitedTreeEntries )
+ {
+ if ( xConnection.is() )
+ {
+ startConnectionListening( xConnection );
+
+ // if no initial name was given, try to obtain one from the data source
+ if ( sInitialDataSourceName.isEmpty() )
+ {
+ Reference< XChild > xChild( xConnection, UNO_QUERY );
+ Reference< XPropertySet > xDataSourceProperties;
+ if ( xChild.is() )
+ xDataSourceProperties.set(xChild->getParent(), css::uno::UNO_QUERY);
+ if ( xDataSourceProperties.is() )
+ {
+ try
+ {
+ OSL_VERIFY( xDataSourceProperties->getPropertyValue( PROPERTY_NAME ) >>= sInitialDataSourceName );
+ }
+ catch( const Exception& )
+ {
+ SAL_WARN("dbaccess.ui", "SbaTableQueryBrowser::impl_initialize: a connection parent which does not have a 'Name'!??" );
+ }
+ }
+ }
+ }
+
+ implAddDatasource( sInitialDataSourceName, xConnection );
+
+ std::unique_ptr<weld::TreeIter> xFirst(rTreeView.make_iterator());
+ if (rTreeView.get_iter_first(*xFirst))
+ rTreeView.expand_row(*xFirst);
+ }
+ else
+ initializeTreeModel();
+
+ rTreeView.make_sorted();
+
+ if ( m_bEnableBrowser )
+ {
+ m_aDocScriptSupport = ::std::optional< bool >( false );
+ }
+ else
+ {
+ // we are not used as "browser", but as mere view for a single table/query/command. In particular,
+ // there is a specific database document which we belong to.
+ Reference< XOfficeDatabaseDocument > xDocument( getDataSourceOrModel(
+ lcl_getDataSource( m_xDatabaseContext, sInitialDataSourceName, xConnection ) ), UNO_QUERY );
+ m_aDocScriptSupport = ::std::optional< bool >( Reference< XEmbeddedScripts >( xDocument, UNO_QUERY ).is() );
+ }
+
+ if ( implSelect( sInitialDataSourceName, sInitialCommand, nInitialDisplayCommandType, bEscapeProcessing, xConnection, true ) )
+ {
+ try
+ {
+ Reference< XPropertySet > xRowSetProps(getRowSet(), UNO_QUERY);
+ xRowSetProps->setPropertyValue(PROPERTY_UPDATE_CATALOGNAME,Any(aCatalogName));
+ xRowSetProps->setPropertyValue(PROPERTY_UPDATE_SCHEMANAME,Any(aSchemaName));
+ xRowSetProps->setPropertyValue(PROPERTY_UPDATE_TABLENAME,Any(aTableName));
+
+ }
+ catch(const Exception&)
+ {
+ SAL_WARN("dbaccess.ui", "SbaTableQueryBrowser::impl_initialize: could not set the update related names!");
+ }
+ }
+
+ InvalidateAll();
+}
+
+bool SbaTableQueryBrowser::haveExplorer() const
+{
+ return m_pTreeView && m_pTreeView->IsVisible();
+}
+
+void SbaTableQueryBrowser::hideExplorer()
+{
+ if (!haveExplorer())
+ return;
+ if (!getBrowserView())
+ return;
+
+ m_pTreeView->Hide();
+ m_pSplitter->Hide();
+ getBrowserView()->Resize();
+
+ InvalidateFeature(ID_BROWSER_EXPLORER);
+}
+
+void SbaTableQueryBrowser::showExplorer()
+{
+ if (haveExplorer())
+ return;
+
+ if (!getBrowserView())
+ return;
+
+ m_pTreeView->Show();
+ m_pSplitter->Show();
+ getBrowserView()->Resize();
+
+ InvalidateFeature(ID_BROWSER_EXPLORER);
+}
+
+bool SbaTableQueryBrowser::ensureConnection(const weld::TreeIter* pAnyEntry, SharedConnection& rConnection)
+{
+ std::unique_ptr<weld::TreeIter> xDSEntry = m_pTreeView->GetRootLevelParent(pAnyEntry);
+ weld::TreeView& rTreeView = m_pTreeView->GetWidget();
+ DBTreeListUserData* pDSData =
+ xDSEntry
+ ? weld::fromId<DBTreeListUserData*>(rTreeView.get_id(*xDSEntry))
+ : nullptr;
+
+ return ensureConnection(xDSEntry.get(), pDSData, rConnection);
+}
+
+std::unique_ptr< ImageProvider > SbaTableQueryBrowser::getImageProviderFor(const weld::TreeIter* pAnyEntry)
+{
+ std::unique_ptr<ImageProvider> xImageProvider(new ImageProvider);
+ SharedConnection xConnection;
+ if (getExistentConnectionFor(pAnyEntry, xConnection))
+ xImageProvider.reset(new ImageProvider(xConnection));
+ return xImageProvider;
+}
+
+bool SbaTableQueryBrowser::getExistentConnectionFor(const weld::TreeIter* pAnyEntry, SharedConnection& rConnection)
+{
+ std::unique_ptr<weld::TreeIter> xDSEntry = m_pTreeView->GetRootLevelParent(pAnyEntry);
+ weld::TreeView& rTreeView = m_pTreeView->GetWidget();
+ DBTreeListUserData* pDSData =
+ xDSEntry
+ ? weld::fromId<DBTreeListUserData*>(rTreeView.get_id(*xDSEntry))
+ : nullptr;
+ if (pDSData)
+ rConnection = pDSData->xConnection;
+ return rConnection.is();
+}
+
+bool SbaTableQueryBrowser::impl_isDataSourceEntry(const weld::TreeIter* pEntry) const
+{
+ if (!pEntry)
+ return false;
+ std::unique_ptr<weld::TreeIter> xRoot(m_pTreeView->GetRootLevelParent(pEntry));
+ weld::TreeView& rTreeView = m_pTreeView->GetWidget();
+ return rTreeView.iter_compare(*xRoot, *pEntry) == 0;
+}
+
+bool SbaTableQueryBrowser::ensureConnection(const weld::TreeIter* pDSEntry, void* pDSData, SharedConnection& rConnection)
+{
+ OSL_ENSURE( impl_isDataSourceEntry( pDSEntry ), "SbaTableQueryBrowser::ensureConnection: this entry does not denote a data source!" );
+ if (pDSEntry)
+ {
+ weld::TreeView& rTreeView = m_pTreeView->GetWidget();
+ OUString aDSName = rTreeView.get_text(*pDSEntry);
+
+ DBTreeListUserData* pTreeListData = static_cast<DBTreeListUserData*>(pDSData);
+ if ( pTreeListData )
+ rConnection = pTreeListData->xConnection;
+
+ if ( !rConnection.is() && pTreeListData )
+ {
+ // show the "connecting to ..." status
+ OUString sConnecting(DBA_RES(STR_CONNECTING_DATASOURCE));
+ sConnecting = sConnecting.replaceFirst("$name$", aDSName);
+ BrowserViewStatusDisplay aShowStatus(static_cast<UnoDataBrowserView*>(getView()), sConnecting);
+
+ // build a string showing context information in case of error
+ OUString sConnectingContext(DBA_RES(STR_COULDNOTCONNECT_DATASOURCE));
+ sConnectingContext = sConnectingContext.replaceFirst("$name$", aDSName);
+
+ // connect
+ rConnection.reset(
+ connect(getDataSourceAccessor(*pDSEntry), sConnectingContext, nullptr),
+ SharedConnection::TakeOwnership);
+
+ // remember the connection
+ pTreeListData->xConnection = rConnection;
+ }
+ }
+ return rConnection.is();
+}
+
+int SbaTableQueryBrowser::OnTreeEntryCompare(const weld::TreeIter& rLHS, const weld::TreeIter& rRHS)
+{
+ weld::TreeView& rTreeView = m_pTreeView->GetWidget();
+
+ // we want the table entry and the end so we have to do a check
+ if (isContainer(rRHS))
+ {
+ // don't use getEntryType (directly or indirectly) for the LHS:
+ // LHS is currently being inserted, so it is not "completely valid" at the moment
+
+ const EntryType eRight = getEntryType(rRHS);
+ if (etTableContainer == eRight)
+ // every other container should be placed _before_ the bookmark container
+ return -1;
+
+ const OUString sLeft = rTreeView.get_text(rLHS);
+
+ EntryType eLeft = etTableContainer;
+ if (DBA_RES(RID_STR_TABLES_CONTAINER) == sLeft)
+ eLeft = etTableContainer;
+ else if (DBA_RES(RID_STR_QUERIES_CONTAINER) == sLeft)
+ eLeft = etQueryContainer;
+
+ if ( eLeft == eRight )
+ return 0;
+
+ if ( ( eLeft == etTableContainer ) && ( eRight == etQueryContainer ) )
+ return 1;
+
+ if ( ( eLeft == etQueryContainer ) && ( eRight == etTableContainer ) )
+ return -1;
+
+ SAL_WARN("dbaccess.ui", "SbaTableQueryBrowser::OnTreeEntryCompare: unexpected case!" );
+ return 0;
+ }
+
+ OUString sLeftText = rTreeView.get_text(rLHS);
+ OUString sRightText = rTreeView.get_text(rRHS);
+
+ sal_Int32 nCompareResult = 0; // equal by default
+
+ if (m_xCollator.is())
+ {
+ try
+ {
+ nCompareResult = m_xCollator->compareString(sLeftText, sRightText);
+ }
+ catch(const Exception&)
+ {
+ }
+ }
+ else
+ // default behaviour if we do not have a collator -> do the simple string compare
+ nCompareResult = sLeftText.compareTo(sRightText);
+
+ return nCompareResult;
+}
+
+void SbaTableQueryBrowser::implAdministrate(const weld::TreeIter& rApplyTo)
+{
+ try
+ {
+ // get the desktop object
+ Reference< XDesktop2 > xFrameLoader = Desktop::create( getORB() );
+
+ // the initial selection
+ weld::TreeView& rTreeView = m_pTreeView->GetWidget();
+ std::unique_ptr<weld::TreeIter> xTopLevelSelected(rTreeView.make_iterator(&rApplyTo));
+
+ while (rTreeView.get_iter_depth(*xTopLevelSelected))
+ rTreeView.iter_parent(*xTopLevelSelected);
+
+ OUString sInitialSelection = getDataSourceAccessor(*xTopLevelSelected);
+
+ Reference< XDataSource > xDataSource( getDataSourceByName( sInitialSelection, getFrameWeld(), getORB(), nullptr ) );
+ Reference< XModel > xDocumentModel( getDataSourceOrModel( xDataSource ), UNO_QUERY );
+
+ if ( xDocumentModel.is() )
+ {
+ Reference< XInteractionHandler2 > xInteractionHandler(
+ InteractionHandler::createWithParent(getORB(), nullptr) );
+
+ ::comphelper::NamedValueCollection aLoadArgs;
+ aLoadArgs.put( "Model", xDocumentModel );
+ aLoadArgs.put( "InteractionHandler", xInteractionHandler );
+ aLoadArgs.put( "MacroExecutionMode", MacroExecMode::USE_CONFIG );
+
+ Sequence< PropertyValue > aLoadArgPV;
+ aLoadArgs >>= aLoadArgPV;
+
+ xFrameLoader->loadComponentFromURL(
+ xDocumentModel->getURL(),
+ "_default",
+ FrameSearchFlag::ALL | FrameSearchFlag::GLOBAL,
+ aLoadArgPV
+ );
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+}
+
+bool SbaTableQueryBrowser::requestQuickHelp(const void* pUserData, OUString& rText) const
+{
+ const DBTreeListUserData* pData = static_cast<const DBTreeListUserData*>(pUserData);
+ if (pData->eType == etDatasource && !pData->sAccessor.isEmpty())
+ {
+ rText = ::svt::OFileNotation(pData->sAccessor).get( ::svt::OFileNotation::N_SYSTEM);
+ return true;
+ }
+ return false;
+}
+
+OUString SbaTableQueryBrowser::getContextMenuResourceName() const
+{
+ return "explorer";
+}
+
+IController& SbaTableQueryBrowser::getCommandController()
+{
+ return *this;
+}
+
+::comphelper::OInterfaceContainerHelper2* SbaTableQueryBrowser::getContextMenuInterceptors()
+{
+ return &m_aContextMenuInterceptors;
+}
+
+Any SbaTableQueryBrowser::getCurrentSelection(weld::TreeView& rControl) const
+{
+ weld::TreeView& rTreeView = m_pTreeView->GetWidget();
+
+ OSL_PRECOND( &rTreeView == &rControl,
+ "SbaTableQueryBrowser::getCurrentSelection: where does this come from?" );
+
+ if (&rTreeView != &rControl)
+ return Any();
+
+ std::unique_ptr<weld::TreeIter> xSelected(rTreeView.make_iterator());
+ if (!rTreeView.get_selected(xSelected.get()))
+ return Any();
+
+ NamedDatabaseObject aSelectedObject;
+ DBTreeListUserData* pData = weld::fromId<DBTreeListUserData*>(rTreeView.get_id(*xSelected));
+ aSelectedObject.Type = static_cast< sal_Int32 >( pData->eType );
+
+ switch ( aSelectedObject.Type )
+ {
+ case DatabaseObject::QUERY:
+ case DatabaseObject::TABLE:
+ aSelectedObject.Name = rTreeView.get_text(*xSelected);
+ break;
+
+ case DatabaseObjectContainer::DATA_SOURCE:
+ case DatabaseObjectContainer::QUERIES:
+ case DatabaseObjectContainer::TABLES:
+ aSelectedObject.Name = getDataSourceAccessor(*xSelected);
+ break;
+
+ default:
+ SAL_WARN("dbaccess.ui", "SbaTableQueryBrowser::getCurrentSelection: invalid (unexpected) object type!" );
+ break;
+ }
+
+ return Any( aSelectedObject );
+}
+
+vcl::Window* SbaTableQueryBrowser::getMenuParent() const
+{
+ return m_pTreeView;
+}
+
+void SbaTableQueryBrowser::adjustMenuPosition(const weld::TreeView&, ::Point&) const
+{
+}
+
+bool SbaTableQueryBrowser::implGetQuerySignature( OUString& _rCommand, bool& _bEscapeProcessing )
+{
+ _rCommand.clear();
+ _bEscapeProcessing = false;
+
+ try
+ {
+ // contain the dss (data source signature) of the form
+ OUString sDataSourceName;
+ OUString sCommand;
+ sal_Int32 nCommandType = CommandType::COMMAND;
+ Reference< XPropertySet > xRowsetProps( getRowSet(), UNO_QUERY );
+ ODataAccessDescriptor aDesc( xRowsetProps );
+ sDataSourceName = aDesc.getDataSource();
+ aDesc[ DataAccessDescriptorProperty::Command ] >>= sCommand;
+ aDesc[ DataAccessDescriptorProperty::CommandType ] >>= nCommandType;
+
+ // do we need to do anything?
+ if ( CommandType::QUERY != nCommandType )
+ return false;
+
+ // get the query object
+ Reference< XQueryDefinitionsSupplier > xSuppQueries;
+ Reference< XNameAccess > xQueries;
+ Reference< XPropertySet > xQuery;
+ m_xDatabaseContext->getByName( sDataSourceName ) >>= xSuppQueries;
+ if ( xSuppQueries.is() )
+ xQueries = xSuppQueries->getQueryDefinitions();
+ if ( xQueries.is() )
+ xQueries->getByName( sCommand ) >>= xQuery;
+ OSL_ENSURE( xQuery.is(), "SbaTableQueryBrowser::implGetQuerySignature: could not retrieve the query object!" );
+
+ // get the two properties we need
+ if ( xQuery.is() )
+ {
+ xQuery->getPropertyValue( PROPERTY_COMMAND ) >>= _rCommand;
+ _bEscapeProcessing = ::cppu::any2bool( xQuery->getPropertyValue( PROPERTY_ESCAPE_PROCESSING ) );
+ return true;
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+
+ return false;
+}
+
+void SbaTableQueryBrowser::frameAction(const css::frame::FrameActionEvent& aEvent)
+{
+ if (aEvent.Frame == m_xCurrentFrameParent)
+ {
+ if(aEvent.Action == FrameAction_COMPONENT_DETACHING)
+ implRemoveStatusListeners();
+ else if (aEvent.Action == FrameAction_COMPONENT_REATTACHED)
+ connectExternalDispatches();
+ }
+ else
+ SbaXDataBrowserController::frameAction(aEvent);
+
+}
+
+void SbaTableQueryBrowser::clearGridColumns(const Reference< XNameContainer >& _xColContainer)
+{
+ // first we have to clear the grid
+ Reference< XInterface > xColumn;
+ const Sequence<OUString> aColNames = _xColContainer->getElementNames();
+ for (const OUString& rName : aColNames)
+ {
+ _xColContainer->getByName(rName) >>= xColumn;
+ _xColContainer->removeByName(rName);
+ ::comphelper::disposeComponent(xColumn);
+ }
+}
+
+void SbaTableQueryBrowser::loadMenu(const Reference< XFrame >& _xFrame)
+{
+ if ( m_bShowMenu )
+ {
+ OGenericUnoController::loadMenu(_xFrame);
+ }
+ else if ( !m_bPreview )
+ {
+ Reference< css::frame::XLayoutManager > xLayoutManager = getLayoutManager(_xFrame);
+
+ if ( xLayoutManager.is() )
+ {
+ xLayoutManager->lock();
+ xLayoutManager->createElement( "private:resource/toolbar/toolbar" );
+ xLayoutManager->unlock();
+ xLayoutManager->doLayout();
+ }
+ onLoadedMenu( xLayoutManager );
+ }
+}
+
+OUString SbaTableQueryBrowser::getPrivateTitle() const
+{
+ OUString sTitle;
+ if (m_xCurrentlyDisplayed)
+ {
+ weld::TreeView& rTreeView = m_pTreeView->GetWidget();
+ std::unique_ptr<weld::TreeIter> xContainer = rTreeView.make_iterator(m_xCurrentlyDisplayed.get());
+ if (!rTreeView.iter_parent(*xContainer))
+ return OUString();
+ // get the entry for the datasource
+ std::unique_ptr<weld::TreeIter> xConnection = implGetConnectionEntry(*xContainer);
+ OUString sName = rTreeView.get_text(*m_xCurrentlyDisplayed);
+ sTitle = GetEntryText(*xConnection);
+ INetURLObject aURL(sTitle);
+ if ( aURL.GetProtocol() != INetProtocol::NotValid )
+ sTitle = aURL.getBase(INetURLObject::LAST_SEGMENT,true,INetURLObject::DecodeMechanism::WithCharset);
+ if ( !sName.isEmpty() )
+ {
+ sName += " - " + sTitle;
+ sTitle = sName;
+ }
+ }
+
+ return sTitle;
+}
+
+bool SbaTableQueryBrowser::preReloadForm()
+{
+ bool bIni = false;
+ if (!m_xCurrentlyDisplayed)
+ {
+ // switch the grid to design mode while loading
+ getBrowserView()->getGridControl()->setDesignMode(true);
+ // we had an invalid statement so we need to connect the column models
+ Reference<XPropertySet> xRowSetProps(getRowSet(),UNO_QUERY);
+ svx::ODataAccessDescriptor aDesc(xRowSetProps);
+ // extract the props
+ OUString sDataSource;
+ OUString sCommand;
+ sal_Int32 nCommandType = CommandType::COMMAND;
+ bool bEscapeProcessing = true;
+ extractDescriptorProps(aDesc, sDataSource, sCommand, nCommandType, bEscapeProcessing);
+ if ( !sDataSource.isEmpty() && !sCommand.isEmpty() && (-1 != nCommandType) )
+ {
+ m_xCurrentlyDisplayed = getObjectEntry(sDataSource, sCommand, nCommandType, nullptr, nullptr);
+ bIni = true;
+ }
+ }
+ return bIni;
+}
+
+void SbaTableQueryBrowser::postReloadForm()
+{
+ InitializeGridModel(getFormComponent());
+ LoadFinished(true);
+}
+
+Reference< XEmbeddedScripts > SAL_CALL SbaTableQueryBrowser::getScriptContainer()
+{
+ // update our database document
+ Reference< XModel > xDocument;
+ try
+ {
+ Reference< XPropertySet > xCursorProps( getRowSet(), UNO_QUERY_THROW );
+ Reference< XConnection > xConnection( xCursorProps->getPropertyValue( PROPERTY_ACTIVE_CONNECTION ), UNO_QUERY );
+ if ( xConnection.is() )
+ {
+ Reference< XChild > xChild( xConnection, UNO_QUERY_THROW );
+ Reference< XDocumentDataSource > xDataSource( xChild->getParent(), UNO_QUERY_THROW );
+ xDocument.set( xDataSource->getDatabaseDocument(), UNO_QUERY_THROW );
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ Reference< XEmbeddedScripts > xScripts( xDocument, UNO_QUERY );
+ OSL_ENSURE( xScripts.is() || !xDocument.is(),
+ "SbaTableQueryBrowser::getScriptContainer: invalid database document!" );
+ return xScripts;
+}
+
+void SAL_CALL SbaTableQueryBrowser::registerContextMenuInterceptor( const Reference< XContextMenuInterceptor >& Interceptor )
+{
+ if ( Interceptor.is() )
+ m_aContextMenuInterceptors.addInterface( Interceptor );
+}
+
+void SAL_CALL SbaTableQueryBrowser::releaseContextMenuInterceptor( const Reference< XContextMenuInterceptor >& Interceptor )
+{
+ if ( Interceptor.is() )
+ m_aContextMenuInterceptors.removeInterface( Interceptor );
+}
+
+void SAL_CALL SbaTableQueryBrowser::registeredDatabaseLocation( const DatabaseRegistrationEvent& Event )
+{
+ SolarMutexGuard aGuard;
+ implAddDatasource( Event.Name, SharedConnection() );
+}
+
+void SbaTableQueryBrowser::impl_cleanupDataSourceEntry(std::u16string_view rDataSourceName)
+{
+ // get the top-level representing the removed data source
+ weld::TreeView& rTreeView = m_pTreeView->GetWidget();
+ std::unique_ptr<weld::TreeIter> xDataSourceEntry(rTreeView.make_iterator());
+ bool bDataSourceEntry = rTreeView.get_iter_first(*xDataSourceEntry);
+ while (bDataSourceEntry)
+ {
+ if (rTreeView.get_text(*xDataSourceEntry) == rDataSourceName)
+ break;
+ bDataSourceEntry = rTreeView.iter_next_sibling(*xDataSourceEntry);
+ }
+
+ OSL_ENSURE( bDataSourceEntry, "SbaTableQueryBrowser::impl_cleanupDataSourceEntry: do not know this data source!" );
+ if (!bDataSourceEntry)
+ return;
+
+ if (isSelected(*xDataSourceEntry))
+ {
+ // a table or query belonging to the deleted data source is currently being displayed.
+ unloadAndCleanup();
+ }
+
+ std::unique_ptr<weld::TreeIter> xChild(rTreeView.make_iterator(xDataSourceEntry.get()));
+ if (rTreeView.iter_children(*xChild))
+ {
+ do
+ {
+ // delete any user data of the child entries of the to-be-removed entry
+ const DBTreeListUserData* pData = weld::fromId<const DBTreeListUserData*>(rTreeView.get_id(*xChild));
+ rTreeView.set_id(*xChild, OUString());
+ delete pData;
+ } while (rTreeView.iter_next_sibling(*xChild));
+ }
+
+ // remove the entry
+ DBTreeListUserData* pData = weld::fromId<DBTreeListUserData*>(rTreeView.get_id(*xDataSourceEntry));
+ rTreeView.set_id(*xDataSourceEntry, OUString());
+ delete pData;
+ rTreeView.remove(*xDataSourceEntry);
+}
+
+void SAL_CALL SbaTableQueryBrowser::revokedDatabaseLocation( const DatabaseRegistrationEvent& Event )
+{
+ SolarMutexGuard aGuard;
+
+ impl_cleanupDataSourceEntry( Event.Name );
+
+ // maybe the object which is part of the document data source has been removed
+ checkDocumentDataSource();
+}
+
+void SAL_CALL SbaTableQueryBrowser::changedDatabaseLocation( const DatabaseRegistrationEvent& Event )
+{
+ SolarMutexGuard aGuard;
+
+ // in case the data source was expanded, and connected, we need to clean it up
+ // for simplicity, just do as if the data source were completely removed and re-added
+ impl_cleanupDataSourceEntry( Event.Name );
+ implAddDatasource( Event.Name, SharedConnection() );
+}
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/control/ColumnControlWindow.cxx b/dbaccess/source/ui/control/ColumnControlWindow.cxx
new file mode 100644
index 000000000..f9f786f22
--- /dev/null
+++ b/dbaccess/source/ui/control/ColumnControlWindow.cxx
@@ -0,0 +1,182 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <ColumnControlWindow.hxx>
+#include <unotools/syslocale.hxx>
+#include <i18nlangtag/languagetag.hxx>
+#include <connectivity/dbtools.hxx>
+#include <o3tl/safeint.hxx>
+#include <UITools.hxx>
+#include <core_resource.hxx>
+#include <strings.hrc>
+#include <com/sun/star/util/NumberFormatter.hpp>
+
+using namespace ::dbaui;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::util;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::lang;
+
+OColumnControlTopLevel::OColumnControlTopLevel(vcl::Window* pParent,
+ const Reference<XComponentContext>& _rxContext)
+ : InterimItemWindow(pParent, "dbaccess/ui/colcontrolbox.ui", "ColControlBox")
+ , m_xControl(new OColumnControlWindow(m_xContainer.get(), _rxContext))
+{
+}
+
+void OColumnControlTopLevel::dispose()
+{
+ m_xControl.reset();
+ InterimItemWindow::dispose();
+}
+
+void OColumnControlTopLevel::GetFocus()
+{
+ m_xControl->GrabFocus();
+}
+
+// OColumnControlWindow
+OColumnControlWindow::OColumnControlWindow(weld::Container* pParent,
+ const Reference<XComponentContext>& _rxContext)
+ : OFieldDescControl(pParent, nullptr)
+ , m_xContext(_rxContext)
+ , m_sTypeNames(DBA_RES(STR_TABLEDESIGN_DBFIELDTYPES))
+ , m_bAutoIncrementEnabled(true)
+{
+ m_aLocale = SvtSysLocale().GetLanguageTag().getLocale();
+}
+
+void OColumnControlWindow::ActivateAggregate( EControlType eType )
+{
+ switch(eType )
+ {
+ case tpFormat:
+ case tpDefault:
+ case tpColumnName:
+ break;
+ default:
+ OFieldDescControl::ActivateAggregate( eType );
+ }
+}
+
+void OColumnControlWindow::DeactivateAggregate( EControlType eType )
+{
+ switch(eType )
+ {
+ case tpFormat:
+ case tpDefault:
+ case tpColumnName:
+ break;
+ default:
+ OFieldDescControl::DeactivateAggregate( eType );
+ }
+}
+
+void OColumnControlWindow::CellModified(sal_Int32 /*nRow*/, sal_uInt16 /*nColId*/ )
+{
+ saveCurrentFieldDescData();
+}
+
+css::lang::Locale OColumnControlWindow::GetLocale() const
+{
+ return m_aLocale;
+}
+
+Reference< XNumberFormatter > OColumnControlWindow::GetFormatter() const
+{
+ if ( !m_xFormatter.is() )
+ try
+ {
+ Reference< XNumberFormatsSupplier > xSupplier(::dbtools::getNumberFormats(m_xConnection, true, m_xContext));
+
+ if ( xSupplier.is() )
+ {
+ // create a new formatter
+ m_xFormatter.set( NumberFormatter::create(m_xContext), UNO_QUERY_THROW);
+ m_xFormatter->attachNumberFormatsSupplier(xSupplier);
+ }
+ }
+ catch(Exception&)
+ {
+ }
+ return m_xFormatter;
+}
+
+TOTypeInfoSP OColumnControlWindow::getTypeInfo(sal_Int32 _nPos)
+{
+ return ( _nPos >= 0 && o3tl::make_unsigned(_nPos) < m_aDestTypeInfoIndex.size()) ? m_aDestTypeInfoIndex[_nPos]->second : TOTypeInfoSP();
+}
+
+const OTypeInfoMap* OColumnControlWindow::getTypeInfo() const
+{
+ return &m_aDestTypeInfo;
+}
+
+Reference< XDatabaseMetaData> OColumnControlWindow::getMetaData()
+{
+ if ( m_xConnection.is() )
+ return m_xConnection->getMetaData();
+ return Reference< XDatabaseMetaData>();
+}
+
+Reference< XConnection> OColumnControlWindow::getConnection()
+{
+ return m_xConnection;
+}
+
+void OColumnControlWindow::setConnection(const Reference< XConnection>& _xCon)
+{
+ m_xConnection = _xCon;
+ m_xFormatter = nullptr;
+ m_aDestTypeInfoIndex.clear();
+ m_aDestTypeInfo.clear();
+
+ if ( m_xConnection.is() )
+ {
+ Init();
+
+ ::dbaui::fillTypeInfo(m_xConnection,m_sTypeNames,m_aDestTypeInfo,m_aDestTypeInfoIndex);
+ // read autoincrement value set in the datasource
+ ::dbaui::fillAutoIncrementValue(m_xConnection,m_bAutoIncrementEnabled,m_sAutoIncrementValue);
+ }
+}
+
+bool OColumnControlWindow::isAutoIncrementValueEnabled() const
+{
+ return m_bAutoIncrementEnabled;
+}
+
+OUString OColumnControlWindow::getAutoIncrementValue() const
+{
+ return m_sAutoIncrementValue;
+}
+
+TOTypeInfoSP const & OColumnControlWindow::getDefaultTyp() const
+{
+ if ( !m_pTypeInfo )
+ {
+ m_pTypeInfo = std::make_shared<OTypeInfo>();
+ m_pTypeInfo->aUIName = m_sTypeNames.getToken(TYPE_OTHER, ';');
+ }
+ return m_pTypeInfo;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/control/FieldControls.cxx b/dbaccess/source/ui/control/FieldControls.cxx
new file mode 100644
index 000000000..3f3553d56
--- /dev/null
+++ b/dbaccess/source/ui/control/FieldControls.cxx
@@ -0,0 +1,60 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <FieldControls.hxx>
+#include <SqlNameEdit.hxx>
+#include <core_resource.hxx>
+
+namespace dbaui {
+
+OPropColumnEditCtrl::OPropColumnEditCtrl(std::unique_ptr<weld::Entry> xEntry,
+ OUString const & _rAllowedChars,
+ TranslateId pHelpId,
+ short nPosition)
+ : OSQLNameEntry(std::move(xEntry), _rAllowedChars)
+ , m_nPos(nPosition)
+{
+ m_strHelpText = DBA_RES(pHelpId);
+}
+
+OPropEditCtrl::OPropEditCtrl(std::unique_ptr<weld::Entry> xEntry, TranslateId pHelpId, short nPosition)
+ : OWidgetBase(xEntry.get())
+ , m_xEntry(std::move(xEntry))
+ , m_nPos(nPosition)
+{
+ m_strHelpText = DBA_RES(pHelpId);
+}
+
+OPropNumericEditCtrl::OPropNumericEditCtrl(std::unique_ptr<weld::SpinButton> xSpinButton, TranslateId pHelpId, short nPosition)
+ : OWidgetBase(xSpinButton.get())
+ , m_xSpinButton(std::move(xSpinButton))
+ , m_nPos(nPosition)
+{
+ m_strHelpText = DBA_RES(pHelpId);
+}
+
+OPropListBoxCtrl::OPropListBoxCtrl(std::unique_ptr<weld::ComboBox> xComboBox, TranslateId pHelpId, short nPosition)
+ : OWidgetBase(xComboBox.get())
+ , m_xComboBox(std::move(xComboBox))
+ , m_nPos(nPosition)
+{
+ m_strHelpText = DBA_RES(pHelpId);
+}
+
+} // end namespace dbaui
diff --git a/dbaccess/source/ui/control/FieldDescControl.cxx b/dbaccess/source/ui/control/FieldDescControl.cxx
new file mode 100644
index 000000000..331fbc5cb
--- /dev/null
+++ b/dbaccess/source/ui/control/FieldDescControl.cxx
@@ -0,0 +1,1384 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <core_resource.hxx>
+#include <FieldDescControl.hxx>
+#include <FieldControls.hxx>
+#include <tools/diagnose_ex.h>
+#include <TableDesignHelpBar.hxx>
+#include <vcl/svapp.hxx>
+#include <FieldDescriptions.hxx>
+#include <svl/numuno.hxx>
+#include <vcl/transfer.hxx>
+#include <com/sun/star/sdbc/ColumnValue.hpp>
+#include <com/sun/star/util/NumberFormat.hpp>
+#include <com/sun/star/util/XNumberFormatPreviewer.hpp>
+#include <com/sun/star/util/XNumberFormatTypes.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <QEnumTypes.hxx>
+#include <helpids.h>
+#include <connectivity/dbtools.hxx>
+#include <connectivity/dbconversion.hxx>
+#include <comphelper/numbers.hxx>
+#include <comphelper/types.hxx>
+#include <UITools.hxx>
+#include <strings.hrc>
+#include <osl/diagnose.h>
+
+using namespace dbaui;
+using namespace dbtools;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::util;
+
+namespace
+{
+ template< typename T1, typename T2> void lcl_HideAndDeleteControl(short& _nPos,std::unique_ptr<T1>& _pControl, std::unique_ptr<T2>& _pControlText)
+ {
+ if ( _pControl )
+ {
+ --_nPos;
+ _pControl->hide();
+ _pControlText->hide();
+ _pControl.reset();
+ _pControlText.reset();
+ }
+ }
+}
+
+OFieldDescControl::OFieldDescControl(weld::Container* pPage, OTableDesignHelpBar* pHelpBar)
+ : m_xBuilder(Application::CreateBuilder(pPage, "dbaccess/ui/fielddescpage.ui"))
+ , m_xContainer(m_xBuilder->weld_container("FieldDescPage"))
+ , m_pHelp( pHelpBar )
+ , m_pLastFocusWindow(nullptr)
+ , m_pActFocusWindow(nullptr)
+ , m_nPos(-1)
+ , aYes(DBA_RES(STR_VALUE_YES))
+ , aNo(DBA_RES(STR_VALUE_NO))
+ , m_nEditWidth(50)
+ , pActFieldDescr(nullptr)
+{
+ if (m_pHelp)
+ m_pHelp->connect_focus_out(LINK(this, OFieldDescControl, HelpFocusOut));
+}
+
+OFieldDescControl::~OFieldDescControl()
+{
+ dispose();
+}
+
+void OFieldDescControl::dispose()
+{
+ // Destroy children
+ DeactivateAggregate( tpDefault );
+ DeactivateAggregate( tpRequired );
+ DeactivateAggregate( tpTextLen );
+ DeactivateAggregate( tpNumType );
+ DeactivateAggregate( tpScale );
+ DeactivateAggregate( tpLength );
+ DeactivateAggregate( tpFormat );
+ DeactivateAggregate( tpAutoIncrement );
+ DeactivateAggregate( tpBoolDefault );
+ DeactivateAggregate( tpColumnName );
+ DeactivateAggregate( tpType );
+ DeactivateAggregate( tpAutoIncrementValue );
+ m_pHelp = nullptr;
+ m_pLastFocusWindow = nullptr;
+ m_pActFocusWindow = nullptr;
+ m_xDefaultText.reset();
+ m_xRequiredText.reset();
+ m_xAutoIncrementText.reset();
+ m_xTextLenText.reset();
+ m_xNumTypeText.reset();
+ m_xLengthText.reset();
+ m_xScaleText.reset();
+ m_xFormatText.reset();
+ m_xBoolDefaultText.reset();
+ m_xColumnNameText.reset();
+ m_xTypeText.reset();
+ m_xAutoIncrementValueText.reset();
+ m_xRequired.reset();
+ m_xNumType.reset();
+ m_xAutoIncrement.reset();
+ m_xDefault.reset();
+ m_xTextLen.reset();
+ m_xLength.reset();
+ m_xScale.reset();
+ m_xFormatSample.reset();
+ m_xBoolDefault.reset();
+ m_xColumnName.reset();
+ m_xType.reset();
+ m_xAutoIncrementValue.reset();
+ m_xFormat.reset();
+ m_xContainer.reset();
+ m_xBuilder.reset();
+}
+
+OUString OFieldDescControl::BoolStringPersistent(std::u16string_view rUIString) const
+{
+ if (rUIString == aNo)
+ return OUString('0');
+ if (rUIString == aYes)
+ return OUString('1');
+ return OUString();
+}
+
+OUString OFieldDescControl::BoolStringUI(const OUString& rPersistentString) const
+{
+ // Older versions may store a language dependent string as a default
+ if (rPersistentString == aYes || rPersistentString == aNo)
+ return rPersistentString;
+
+ if (rPersistentString == "0")
+ return aNo;
+ if (rPersistentString == "1")
+ return aYes;
+
+ return DBA_RES(STR_VALUE_NONE);
+}
+
+void OFieldDescControl::Init()
+{
+ Reference< css::util::XNumberFormatter > xFormatter = GetFormatter();
+ ::dbaui::setEvalDateFormatForFormatter(xFormatter);
+}
+
+void OFieldDescControl::SetReadOnly( bool bReadOnly )
+{
+ // Enable/disable Controls
+ OWidgetBase* ppAggregates[] = { m_xRequired.get(), m_xNumType.get()
+ , m_xAutoIncrement.get(), m_xDefault.get()
+ , m_xTextLen.get(), m_xLength.get()
+ , m_xScale.get(), m_xColumnName.get()
+ , m_xType.get(), m_xAutoIncrementValue.get()
+ };
+ weld::Widget* ppAggregatesText[] = { m_xRequiredText.get(), m_xNumTypeText.get()
+ , m_xAutoIncrementText.get(), m_xDefaultText.get()
+ , m_xTextLenText.get(), m_xLengthText.get()
+ , m_xScaleText.get(), m_xColumnNameText.get()
+ , m_xTypeText.get(), m_xAutoIncrementValueText.get()
+ };
+
+ OSL_ENSURE(SAL_N_ELEMENTS(ppAggregates) == SAL_N_ELEMENTS(ppAggregatesText),"Lists are not identical!");
+
+ for (size_t i=0; i<SAL_N_ELEMENTS(ppAggregates); ++i)
+ {
+ if ( ppAggregatesText[i] )
+ ppAggregatesText[i]->set_sensitive( !bReadOnly );
+ if ( ppAggregates[i] )
+ ppAggregates[i]->set_sensitive( !bReadOnly );
+ }
+
+ if (m_xFormat)
+ {
+ assert(m_xFormatText);
+ m_xFormat->set_sensitive(!bReadOnly);
+ m_xFormatText->set_sensitive(!bReadOnly);
+ }
+}
+
+void OFieldDescControl::SetControlText( sal_uInt16 nControlId, const OUString& rText )
+{
+ // Set the Controls' texts
+ switch( nControlId )
+ {
+ case FIELD_PROPERTY_BOOL_DEFAULT:
+ if (m_xBoolDefault)
+ {
+ OUString sOld = m_xBoolDefault->get_active_text();
+ m_xBoolDefault->set_active_text(rText);
+ if (sOld != rText)
+ ChangeHdl(m_xBoolDefault->GetComboBox());
+ }
+ break;
+ case FIELD_PROPERTY_DEFAULT:
+ if (m_xDefault)
+ {
+ m_xDefault->set_text(rText);
+ UpdateFormatSample(pActFieldDescr);
+ }
+ break;
+
+ case FIELD_PROPERTY_REQUIRED:
+ if (m_xRequired)
+ m_xRequired->set_active_text(rText);
+ break;
+
+ case FIELD_PROPERTY_TEXTLEN:
+ if (m_xTextLen)
+ m_xTextLen->set_text(rText);
+ break;
+
+ case FIELD_PROPERTY_NUMTYPE:
+ if (m_xNumType)
+ m_xNumType->set_active_text(rText);
+ break;
+
+ case FIELD_PROPERTY_AUTOINC:
+ if (m_xAutoIncrement)
+ {
+ OUString sOld = m_xAutoIncrement->get_active_text();
+ m_xAutoIncrement->set_active_text(rText);
+ if (sOld != rText)
+ ChangeHdl(m_xAutoIncrement->GetComboBox());
+ }
+ break;
+
+ case FIELD_PROPERTY_LENGTH:
+ if (m_xLength)
+ m_xLength->set_text(rText);
+ break;
+
+ case FIELD_PROPERTY_SCALE:
+ if (m_xScale)
+ m_xScale->set_text(rText);
+ break;
+
+ case FIELD_PROPERTY_FORMAT:
+ if (pActFieldDescr)
+ UpdateFormatSample(pActFieldDescr);
+ break;
+ case FIELD_PROPERTY_COLUMNNAME:
+ if (m_xColumnName)
+ m_xColumnName->set_text(rText);
+ break;
+ case FIELD_PROPERTY_TYPE:
+ if (m_xType)
+ m_xType->set_active_text(rText);
+ break;
+ case FIELD_PROPERTY_AUTOINCREMENT:
+ if (m_xAutoIncrementValue)
+ m_xAutoIncrementValue->set_text(rText);
+ break;
+ }
+}
+
+IMPL_LINK_NOARG(OFieldDescControl, FormatClickHdl, weld::Button&, void)
+{
+ // Create temporary Column, which is used for data exchange with Dialog
+ if( !pActFieldDescr )
+ return;
+
+ sal_Int32 nOldFormatKey(pActFieldDescr->GetFormatKey());
+ SvxCellHorJustify rOldJustify = pActFieldDescr->GetHorJustify();
+ Reference< XNumberFormatsSupplier > xSupplier = GetFormatter()->getNumberFormatsSupplier();
+ SvNumberFormatsSupplierObj* pSupplierImpl = comphelper::getFromUnoTunnel<SvNumberFormatsSupplierObj>( xSupplier );
+ if (!pSupplierImpl)
+ return;
+
+ SvNumberFormatter* pFormatter = pSupplierImpl->GetNumberFormatter();
+ if(!::dbaui::callColumnFormatDialog(m_xContainer.get(),pFormatter,pActFieldDescr->GetType(),nOldFormatKey,rOldJustify,true))
+ return;
+
+ bool bModified = false;
+ if(nOldFormatKey != pActFieldDescr->GetFormatKey())
+ {
+ pActFieldDescr->SetFormatKey( nOldFormatKey );
+ bModified = true;
+ }
+ if(rOldJustify != pActFieldDescr->GetHorJustify())
+ {
+ pActFieldDescr->SetHorJustify( rOldJustify );
+ bModified = true;
+ }
+
+ if(bModified)
+ {
+ SetModified(true);
+ UpdateFormatSample(pActFieldDescr);
+ }
+}
+
+void OFieldDescControl::SetModified(bool /*bModified*/)
+{
+}
+
+IMPL_LINK(OFieldDescControl, ChangeHdl, weld::ComboBox&, rListBox, void)
+{
+ if (!pActFieldDescr)
+ return;
+
+ if (rListBox.get_value_changed_from_saved())
+ SetModified(true);
+
+ // Special treatment for Bool fields
+ if (m_xRequired && &rListBox == m_xRequired->GetWidget() && m_xBoolDefault)
+ {
+ // If m_xRequired = sal_True then the sal_Bool field must NOT contain <<none>>
+ OUString sDef = BoolStringUI(::comphelper::getString(pActFieldDescr->GetControlDefault()));
+
+ if (m_xRequired->get_active() == 0) // Yes
+ {
+ m_xBoolDefault->remove_text(DBA_RES(STR_VALUE_NONE));
+ if (sDef != aYes && sDef != aNo)
+ m_xBoolDefault->set_active(1); // No as a default
+ else
+ m_xBoolDefault->set_active_text(sDef);
+ }
+ else if (m_xBoolDefault->get_count() < 3)
+ {
+ m_xBoolDefault->append_text(DBA_RES(STR_VALUE_NONE));
+ m_xBoolDefault->set_active_text(sDef);
+ }
+ }
+
+ // A special treatment only for AutoIncrement
+ if (m_xAutoIncrement && &rListBox == m_xAutoIncrement->GetWidget())
+ {
+ if (rListBox.get_active() == 1)
+ { // no
+ DeactivateAggregate( tpAutoIncrementValue );
+ if(pActFieldDescr->IsPrimaryKey())
+ DeactivateAggregate( tpRequired );
+ else if( pActFieldDescr->getTypeInfo()->bNullable )
+ {
+ ActivateAggregate( tpRequired );
+ if (m_xRequired)
+ {
+ if( pActFieldDescr->IsNullable() )
+ m_xRequired->set_active(1); // no
+ else
+ m_xRequired->set_active(0); // yes
+ }
+ }
+ ActivateAggregate( tpDefault );
+ }
+ else
+ {
+ DeactivateAggregate( tpRequired );
+ DeactivateAggregate( tpDefault );
+ ActivateAggregate( tpAutoIncrementValue );
+ }
+ }
+
+ if (m_xType && &rListBox == m_xType->GetWidget())
+ {
+ TOTypeInfoSP pTypeInfo = getTypeInfo(m_xType->get_active());
+ pActFieldDescr->FillFromTypeInfo(pTypeInfo,true,false); // SetType(pTypeInfo);
+
+ DisplayData(pActFieldDescr);
+ CellModified(-1, m_xType->GetPos());
+ }
+}
+
+void OFieldDescControl::ActivateAggregate( EControlType eType )
+{
+ // Create Controls
+ switch( eType )
+ {
+ case tpDefault:
+ if (m_xDefault)
+ return;
+ m_nPos++;
+ m_xDefaultText = m_xBuilder->weld_label("DefaultValueText");
+ m_xDefaultText->show();
+ m_xDefault = std::make_unique<OPropEditCtrl>(
+ m_xBuilder->weld_entry("DefaultValue"), STR_HELP_DEFAULT_VALUE, FIELD_PROPERTY_DEFAULT);
+ InitializeControl(m_xDefault->GetWidget(),HID_TAB_ENT_DEFAULT);
+ m_xDefault->show();
+ break;
+ case tpAutoIncrementValue:
+ if (m_xAutoIncrementValue || !isAutoIncrementValueEnabled())
+ return;
+ m_nPos++;
+ m_xAutoIncrementValueText = m_xBuilder->weld_label("AutoIncrementValueText");
+ m_xAutoIncrementValueText->show();
+ m_xAutoIncrementValue = std::make_unique<OPropEditCtrl>(
+ m_xBuilder->weld_spin_button("AutoIncrementValue"), STR_HELP_AUTOINCREMENT_VALUE,
+ FIELD_PROPERTY_AUTOINCREMENT);
+ m_xAutoIncrementValue->set_text( getAutoIncrementValue() );
+ InitializeControl(m_xAutoIncrementValue->GetWidget(),HID_TAB_AUTOINCREMENTVALUE);
+ m_xAutoIncrementValue->show();
+ break;
+
+ case tpRequired:
+ {
+ if (m_xRequired)
+ return;
+ Reference< XDatabaseMetaData> xMetaData = getMetaData();
+
+ if(xMetaData.is() && xMetaData->supportsNonNullableColumns())
+ {
+ m_nPos++;
+ m_xRequiredText = m_xBuilder->weld_label("RequiredText");
+ m_xRequiredText->show();
+ m_xRequired = std::make_unique<OPropListBoxCtrl>(
+ m_xBuilder->weld_combo_box("Required"), STR_HELP_AUTOINCREMENT_VALUE,
+ FIELD_PROPERTY_AUTOINCREMENT);
+ m_xRequired->append_text(aYes);
+ m_xRequired->append_text(aNo);
+ m_xRequired->set_active(1);
+
+ InitializeControl(m_xRequired.get(),HID_TAB_ENT_REQUIRED, true);
+ m_xRequired->show();
+ }
+ }
+ break;
+ case tpAutoIncrement:
+ {
+ if (m_xAutoIncrement)
+ return;
+ m_nPos++;
+ m_xAutoIncrementText = m_xBuilder->weld_label("AutoIncrementText");
+ m_xAutoIncrementText->show();
+ m_xAutoIncrement = std::make_unique<OPropListBoxCtrl>(
+ m_xBuilder->weld_combo_box("AutoIncrement"), STR_HELP_AUTOINCREMENT,
+ FIELD_PROPERTY_AUTOINC);
+ m_xAutoIncrement->append_text(aYes);
+ m_xAutoIncrement->append_text(aNo);
+ m_xAutoIncrement->set_active(0);
+ InitializeControl(m_xAutoIncrement.get(),HID_TAB_ENT_AUTOINCREMENT, true);
+ m_xAutoIncrement->show();
+ }
+ break;
+ case tpTextLen:
+ if (m_xTextLen)
+ return;
+ m_nPos++;
+ m_xTextLenText = m_xBuilder->weld_label("TextLengthText");
+ m_xTextLenText->show();
+ m_xTextLen = CreateNumericControl("TextLength", STR_HELP_TEXT_LENGTH, FIELD_PROPERTY_TEXTLEN,HID_TAB_ENT_TEXT_LEN);
+ break;
+
+ case tpType:
+ if (m_xType)
+ return;
+ m_nPos++;
+ m_xTypeText = m_xBuilder->weld_label("TypeText");
+ m_xTypeText->show();
+ m_xType = std::make_unique<OPropListBoxCtrl>(
+ m_xBuilder->weld_combo_box("Type"), STR_HELP_AUTOINCREMENT, FIELD_PROPERTY_TYPE);
+ {
+ const OTypeInfoMap* pTypeInfo = getTypeInfo();
+ for (auto const& elem : *pTypeInfo)
+ m_xType->append_text(elem.second->aUIName);
+ }
+ m_xType->set_active(0);
+ InitializeControl(m_xType.get(),HID_TAB_ENT_TYPE, true);
+ m_xType->show();
+ break;
+ case tpColumnName:
+ if (m_xColumnName)
+ return;
+ m_nPos++;
+ {
+ sal_Int32 nMax(0);
+ OUString aTmpString;
+ try
+ {
+ Reference< XDatabaseMetaData> xMetaData = getMetaData();
+ if ( xMetaData.is() )
+ {
+ nMax = xMetaData->getMaxColumnNameLength();
+ aTmpString = xMetaData->getExtraNameCharacters();
+ }
+ }
+ catch (const Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ m_xColumnNameText = m_xBuilder->weld_label("ColumnNameText");
+ m_xColumnNameText->show();
+ m_xColumnName = std::make_unique<OPropColumnEditCtrl>(
+ m_xBuilder->weld_entry("ColumnName"), aTmpString,
+ STR_HELP_DEFAULT_VALUE, FIELD_PROPERTY_COLUMNNAME);
+ m_xColumnName->set_max_length(nMax);
+ m_xColumnName->setCheck( isSQL92CheckEnabled(getConnection()) );
+ }
+
+ InitializeControl(m_xColumnName->GetWidget(),HID_TAB_ENT_COLUMNNAME);
+ m_xColumnName->show();
+ break;
+ case tpNumType:
+ if (m_xNumType)
+ return;
+ m_nPos++;
+ m_xNumTypeText = m_xBuilder->weld_label("NumTypeText");
+ m_xNumTypeText->show();
+ m_xNumType = std::make_unique<OPropListBoxCtrl>(
+ m_xBuilder->weld_combo_box("NumType"), STR_HELP_NUMERIC_TYPE, FIELD_PROPERTY_NUMTYPE);
+ m_xNumType->append_text("Byte");
+ m_xNumType->append_text("SmallInt");
+ m_xNumType->append_text("Integer");
+ m_xNumType->append_text("Single");
+ m_xNumType->append_text("Double");
+ m_xNumType->set_active(2);
+ InitializeControl(m_xNumType.get(),HID_TAB_ENT_NUMTYP, true);
+ m_xNumType->show();
+ break;
+
+ case tpLength:
+ if (m_xLength)
+ return;
+ m_nPos++;
+ m_xLengthText = m_xBuilder->weld_label("LengthText");
+ m_xLengthText->show();
+ m_xLength = CreateNumericControl("Length", STR_HELP_LENGTH, FIELD_PROPERTY_LENGTH,HID_TAB_ENT_LEN);
+ break;
+
+ case tpScale:
+ if (m_xScale)
+ return;
+ m_nPos++;
+ m_xScaleText = m_xBuilder->weld_label("ScaleText");
+ m_xScaleText->show();
+ m_xScale = CreateNumericControl("Scale", STR_HELP_SCALE, FIELD_PROPERTY_SCALE,HID_TAB_ENT_SCALE);
+ break;
+
+ case tpFormat:
+ if (!m_xFormat)
+ {
+ m_nPos++;
+ m_xFormatText = m_xBuilder->weld_label("FormatTextText");
+ m_xFormatText->show();
+
+ m_xFormatSample = std::make_unique<OPropEditCtrl>(
+ m_xBuilder->weld_entry("FormatText"), STR_HELP_FORMAT_CODE, -1);
+ m_xFormatSample->set_editable(false);
+ m_xFormatSample->set_sensitive(false);
+ InitializeControl(m_xFormatSample->GetWidget(),HID_TAB_ENT_FORMAT_SAMPLE);
+ m_xFormatSample->show();
+
+ m_xFormat = m_xBuilder->weld_button("FormatButton");
+ m_xFormat->connect_clicked( LINK( this, OFieldDescControl, FormatClickHdl ) );
+ InitializeControl(m_xFormat.get(),HID_TAB_ENT_FORMAT);
+ m_xFormat->show();
+ }
+
+ UpdateFormatSample(pActFieldDescr);
+ break;
+ case tpBoolDefault:
+ if (m_xBoolDefault)
+ return;
+
+ m_nPos++;
+ m_xBoolDefaultText = m_xBuilder->weld_label("BoolDefaultText");
+ m_xBoolDefaultText->show();
+ m_xBoolDefault = std::make_unique<OPropListBoxCtrl>(
+ m_xBuilder->weld_combo_box("BoolDefault"), STR_HELP_BOOL_DEFAULT,
+ FIELD_PROPERTY_BOOL_DEFAULT);
+ m_xBoolDefault->append_text(DBA_RES(STR_VALUE_NONE));
+ m_xBoolDefault->append_text(aYes);
+ m_xBoolDefault->append_text(aNo);
+ InitializeControl(m_xBoolDefault->GetWidget(),HID_TAB_ENT_BOOL_DEFAULT);
+ m_xBoolDefault->show();
+ break;
+ }
+}
+
+void OFieldDescControl::InitializeControl(OPropListBoxCtrl* _pControl,const OString& _sHelpId,bool _bAddChangeHandler)
+{
+ if ( _bAddChangeHandler )
+ _pControl->GetComboBox().connect_changed(LINK(this,OFieldDescControl,ChangeHdl));
+
+ InitializeControl(_pControl->GetWidget(), _sHelpId);
+}
+
+void OFieldDescControl::InitializeControl(weld::Widget* pControl,const OString& _sHelpId)
+{
+ pControl->set_help_id(_sHelpId);
+ pControl->connect_focus_in(LINK(this, OFieldDescControl, OnControlFocusGot));
+ pControl->connect_focus_out(LINK(this, OFieldDescControl, OnControlFocusLost));
+
+ if (dynamic_cast<weld::Entry*>(pControl))
+ {
+ int nWidthRequest = Application::GetDefaultDevice()->LogicToPixel(Size(m_nEditWidth, 0), MapMode(MapUnit::MapAppFont)).Width();
+ pControl->set_size_request(nWidthRequest, -1);
+ }
+}
+
+std::unique_ptr<OPropNumericEditCtrl> OFieldDescControl::CreateNumericControl(const OString& rId, TranslateId pHelpId, short _nProperty, const OString& _sHelpId)
+{
+ auto xControl = std::make_unique<OPropNumericEditCtrl>(
+ m_xBuilder->weld_spin_button(rId), pHelpId, _nProperty);
+ xControl->set_digits(0);
+ xControl->set_range(0, 0x7FFFFFFF); // Should be changed outside, if needed
+ xControl->show();
+
+ InitializeControl(xControl->GetWidget(),_sHelpId);
+
+ return xControl;
+}
+
+void OFieldDescControl::DeactivateAggregate( EControlType eType )
+{
+ m_pLastFocusWindow = nullptr;
+ // Destroy Controls
+ switch( eType )
+ {
+ case tpDefault:
+ lcl_HideAndDeleteControl(m_nPos,m_xDefault,m_xDefaultText);
+ break;
+
+ case tpAutoIncrementValue:
+ lcl_HideAndDeleteControl(m_nPos,m_xAutoIncrementValue,m_xAutoIncrementValueText);
+ break;
+
+ case tpColumnName:
+ lcl_HideAndDeleteControl(m_nPos,m_xColumnName,m_xColumnNameText);
+ break;
+
+ case tpType:
+ lcl_HideAndDeleteControl(m_nPos,m_xType,m_xTypeText);
+ break;
+
+ case tpAutoIncrement:
+ lcl_HideAndDeleteControl(m_nPos,m_xAutoIncrement,m_xAutoIncrementText);
+ break;
+
+ case tpRequired:
+ lcl_HideAndDeleteControl(m_nPos,m_xRequired,m_xRequiredText);
+ break;
+
+ case tpTextLen:
+ lcl_HideAndDeleteControl(m_nPos,m_xTextLen,m_xTextLenText);
+ break;
+
+ case tpNumType:
+ lcl_HideAndDeleteControl(m_nPos,m_xNumType,m_xNumTypeText);
+ break;
+
+ case tpLength:
+ lcl_HideAndDeleteControl(m_nPos,m_xLength,m_xLengthText);
+ break;
+
+ case tpScale:
+ lcl_HideAndDeleteControl(m_nPos,m_xScale,m_xScaleText);
+ break;
+
+ case tpFormat:
+ // TODO: we have to check if we have to increment m_nPos again
+ lcl_HideAndDeleteControl(m_nPos,m_xFormat,m_xFormatText);
+ if (m_xFormatSample)
+ {
+ m_xFormatSample->hide();
+ m_xFormatSample.reset();
+ }
+ break;
+ case tpBoolDefault:
+ lcl_HideAndDeleteControl(m_nPos,m_xBoolDefault,m_xBoolDefaultText);
+ break;
+ }
+}
+
+void OFieldDescControl::DisplayData(OFieldDescription* pFieldDescr )
+{
+ pActFieldDescr = pFieldDescr;
+ if(!pFieldDescr)
+ {
+ if (m_pHelp)
+ m_pHelp->SetHelpText( OUString() );
+ DeactivateAggregate( tpDefault );
+ DeactivateAggregate( tpRequired );
+ DeactivateAggregate( tpTextLen );
+ DeactivateAggregate( tpNumType );
+ DeactivateAggregate( tpScale );
+ DeactivateAggregate( tpLength );
+ DeactivateAggregate( tpFormat );
+ DeactivateAggregate( tpAutoIncrement );
+ DeactivateAggregate( tpBoolDefault );
+ DeactivateAggregate( tpColumnName );
+ DeactivateAggregate( tpType );
+ DeactivateAggregate( tpAutoIncrementValue );
+ m_pPreviousType = TOTypeInfoSP();
+ // Reset the saved focus' pointer
+ m_pLastFocusWindow = nullptr;
+ return;
+ }
+
+ TOTypeInfoSP pFieldType(pFieldDescr->getTypeInfo());
+
+ ActivateAggregate( tpColumnName );
+ ActivateAggregate( tpType );
+
+ OSL_ENSURE(pFieldType,"We need a type information here!");
+ // If the type has changed, substitute Controls
+ if( m_pPreviousType != pFieldType )
+ {
+ // Reset the saved focus' pointer
+ m_pLastFocusWindow = nullptr;
+
+ // Controls, which must NOT be displayed again
+ DeactivateAggregate( tpNumType );
+
+ // determine which controls we should show and which not
+
+ // 1. the required control
+ if ( pFieldType->bNullable )
+ ActivateAggregate( tpRequired );
+ else
+ DeactivateAggregate( tpRequired );
+
+ // 2. the autoincrement
+ if ( pFieldType->bAutoIncrement )
+ {
+ DeactivateAggregate( tpRequired );
+ DeactivateAggregate( tpDefault );
+ ActivateAggregate( tpAutoIncrement );
+ ActivateAggregate( tpAutoIncrementValue );
+ }
+ else
+ {
+ DeactivateAggregate( tpAutoIncrement );
+ DeactivateAggregate( tpAutoIncrementValue );
+ if(pFieldType->bNullable)
+ ActivateAggregate( tpRequired );
+ else
+ DeactivateAggregate( tpRequired );
+ ActivateAggregate( tpDefault );
+ }
+ // 3. the scale and precision
+ if (pFieldType->nPrecision)
+ {
+ ActivateAggregate( tpLength );
+ m_xLength->set_max(std::max<sal_Int32>(pFieldType->nPrecision,pFieldDescr->GetPrecision()));
+ m_xLength->set_editable(!pFieldType->aCreateParams.isEmpty());
+ }
+ else
+ DeactivateAggregate( tpLength );
+
+ if (pFieldType->nMaximumScale)
+ {
+ ActivateAggregate( tpScale );
+ m_xScale->set_range(pFieldType->nMinimumScale,
+ std::max<sal_Int32>(pFieldType->nMaximumScale,pFieldDescr->GetScale()));
+ m_xScale->set_editable(!pFieldType->aCreateParams.isEmpty() && pFieldType->aCreateParams != "PRECISION");
+ }
+ else
+ DeactivateAggregate( tpScale );
+
+ // and now look for type specific things
+ switch( pFieldType->nType )
+ {
+ case DataType::CHAR:
+ case DataType::VARCHAR:
+ case DataType::LONGVARCHAR:
+ DeactivateAggregate( tpLength );
+ DeactivateAggregate( tpBoolDefault );
+
+ ActivateAggregate( tpDefault );
+ ActivateAggregate( tpFormat );
+ if (pFieldType->nPrecision)
+ {
+ ActivateAggregate( tpTextLen );
+ m_xTextLen->set_max(std::max<sal_Int32>(pFieldType->nPrecision,pFieldDescr->GetPrecision()));
+ m_xTextLen->set_editable(!pFieldType->aCreateParams.isEmpty());
+ }
+ else
+ DeactivateAggregate( tpTextLen );
+ break;
+ case DataType::DATE:
+ case DataType::TIME:
+ case DataType::TIMESTAMP:
+ DeactivateAggregate( tpLength ); // we don't need a length for date types
+ DeactivateAggregate( tpTextLen );
+ DeactivateAggregate( tpBoolDefault );
+
+ ActivateAggregate( tpDefault );
+ ActivateAggregate( tpFormat );
+ break;
+ case DataType::BIT:
+ if ( !pFieldType->aCreateParams.isEmpty() )
+ {
+ DeactivateAggregate( tpFormat );
+ DeactivateAggregate( tpTextLen );
+ DeactivateAggregate( tpBoolDefault );
+ break;
+ }
+ [[fallthrough]];
+ case DataType::BOOLEAN:
+ DeactivateAggregate( tpTextLen );
+ DeactivateAggregate( tpFormat );
+ DeactivateAggregate( tpDefault );
+
+ ActivateAggregate( tpBoolDefault );
+ break;
+ case DataType::DECIMAL:
+ case DataType::NUMERIC:
+ case DataType::BIGINT:
+ case DataType::FLOAT:
+ case DataType::DOUBLE:
+ case DataType::TINYINT:
+ case DataType::SMALLINT:
+ case DataType::INTEGER:
+ case DataType::REAL:
+ DeactivateAggregate( tpTextLen );
+ DeactivateAggregate( tpBoolDefault );
+
+ ActivateAggregate( tpFormat );
+ break;
+ case DataType::BINARY:
+ case DataType::VARBINARY:
+ DeactivateAggregate( tpDefault );
+ DeactivateAggregate( tpRequired );
+ DeactivateAggregate( tpTextLen );
+ DeactivateAggregate( tpBoolDefault );
+
+ ActivateAggregate( tpFormat );
+ break;
+ case DataType::LONGVARBINARY:
+ case DataType::SQLNULL:
+ case DataType::OBJECT:
+ case DataType::DISTINCT:
+ case DataType::STRUCT:
+ case DataType::ARRAY:
+ case DataType::BLOB:
+ case DataType::CLOB:
+ case DataType::REF:
+ case DataType::OTHER:
+ DeactivateAggregate( tpFormat );
+ DeactivateAggregate( tpTextLen );
+ DeactivateAggregate( tpBoolDefault );
+
+ break;
+ default:
+ OSL_FAIL("Unknown type");
+ }
+ m_pPreviousType = pFieldType;
+ }
+
+ if (pFieldDescr->IsPrimaryKey())
+ {
+ DeactivateAggregate(tpRequired);
+ }
+ else if (!m_xAutoIncrement && pFieldType)
+ {
+ if (pFieldType->bNullable)
+ ActivateAggregate(tpRequired);
+ else
+ DeactivateAggregate(tpRequired);
+ }
+ // Initialize Controls
+ if (m_xAutoIncrement)
+ {
+ if ( pFieldDescr->IsAutoIncrement() )
+ {
+ m_xAutoIncrement->set_active(0); // yes
+ ActivateAggregate( tpAutoIncrementValue );
+ if (m_xAutoIncrementValue)
+ m_xAutoIncrementValue->set_text(pFieldDescr->GetAutoIncrementValue());
+ DeactivateAggregate( tpRequired );
+ DeactivateAggregate( tpDefault );
+ }
+ else
+ {
+ // disable autoincrement value because it should only be visible when autoincrement is to true
+ DeactivateAggregate( tpAutoIncrementValue );
+ m_xAutoIncrement->set_active(1); // no
+ ActivateAggregate( tpDefault );
+ // Affects pRequired
+ if(!pFieldDescr->IsPrimaryKey())
+ ActivateAggregate( tpRequired );
+ }
+ }
+
+ if (m_xDefault)
+ {
+ m_xDefault->set_text(getControlDefault(pFieldDescr));
+ m_xDefault->save_value();
+ }
+
+ if (m_xBoolDefault)
+ {
+ // If m_xRequired = sal_True then the sal_Bool field must NOT contain <<none>>
+ OUString sValue;
+ pFieldDescr->GetControlDefault() >>= sValue;
+ OUString sDef = BoolStringUI(sValue);
+
+ // Make sure that <<none>> is only present if the field can be NULL
+ if ( ( pFieldType && !pFieldType->bNullable ) || !pFieldDescr->IsNullable() )
+ {
+ pFieldDescr->SetIsNullable(ColumnValue::NO_NULLS); // The type says so
+
+ m_xBoolDefault->remove_text(DBA_RES(STR_VALUE_NONE));
+ if ( sDef != aYes && sDef != aNo )
+ m_xBoolDefault->set_active(1); // No as a default
+ else
+ m_xBoolDefault->set_active_text(sDef);
+
+ pFieldDescr->SetControlDefault(Any(BoolStringPersistent(m_xBoolDefault->get_active_text())));
+ }
+ else if (m_xBoolDefault->get_count() < 3)
+ {
+ m_xBoolDefault->append_text(DBA_RES(STR_VALUE_NONE));
+ m_xBoolDefault->set_active_text(sDef);
+ }
+ else
+ m_xBoolDefault->set_active_text(sDef);
+ }
+
+ if (m_xRequired)
+ {
+ if( pFieldDescr->IsNullable() )
+ m_xRequired->set_active(1); // no
+ else
+ m_xRequired->set_active(0); // yes
+ }
+
+ if (m_xTextLen)
+ {
+ m_xTextLen->set_text(OUString::number(pFieldDescr->GetPrecision()));
+ m_xTextLen->save_value();
+ }
+
+ if( m_xNumType )
+ {
+ OSL_FAIL("OFieldDescControl::DisplayData: invalid num type!");
+ }
+
+ if (m_xLength)
+ m_xLength->set_text(OUString::number(pFieldDescr->GetPrecision()));
+
+ if (m_xScale)
+ m_xScale->set_text(OUString::number(pFieldDescr->GetScale()));
+
+ if (m_xFormat)
+ UpdateFormatSample(pFieldDescr);
+
+ if (m_xColumnName)
+ m_xColumnName->set_text(pFieldDescr->GetName());
+
+ if (m_xType)
+ {
+ sal_Int32 nPos = pFieldType ? m_xType->find_text(pFieldDescr->getTypeInfo()->aUIName) : -1;
+ if (nPos == -1)
+ {
+ const OTypeInfoMap* pMap = getTypeInfo();
+ OTypeInfoMap::const_iterator aIter = pMap->find(pFieldType ? pFieldDescr->getTypeInfo()->nType : pFieldDescr->GetType());
+ if(aIter == pMap->end() && !pMap->empty())
+ {
+ aIter = pMap->begin();
+ if(pFieldDescr->GetPrecision() > aIter->second->nPrecision)
+ pFieldDescr->SetPrecision(aIter->second->nPrecision);
+ if(pFieldDescr->GetScale() > aIter->second->nMaximumScale)
+ pFieldDescr->SetScale(0);
+ if(!aIter->second->bNullable && pFieldDescr->IsNullable())
+ pFieldDescr->SetIsNullable(ColumnValue::NO_NULLS);
+ if(!aIter->second->bAutoIncrement && pFieldDescr->IsAutoIncrement())
+ pFieldDescr->SetAutoIncrement(false);
+ }
+ if ( aIter != pMap->end() )
+ {
+ pFieldDescr->SetType(aIter->second);
+ }
+ }
+ m_xType->set_active_text(pFieldDescr->getTypeInfo()->aUIName);
+ }
+
+ // Enable/disable Controls
+ bool bRead(IsReadOnly());
+
+ SetReadOnly( bRead );
+}
+
+IMPL_LINK(OFieldDescControl, OnControlFocusGot, weld::Widget&, rControl, void )
+{
+ OUString strHelpText;
+
+ if (m_xTextLen && &rControl == m_xTextLen->GetWidget())
+ {
+ m_xTextLen->save_value();
+ strHelpText = m_xTextLen->GetHelp();
+ }
+ else if (m_xLength && &rControl == m_xLength->GetWidget())
+ {
+ m_xLength->save_value();
+ strHelpText = m_xLength->GetHelp();
+ }
+ else if (m_xScale && &rControl == m_xScale->GetWidget())
+ {
+ m_xScale->save_value();
+ strHelpText = m_xScale->GetHelp();
+ }
+ else if (m_xColumnName && &rControl == m_xColumnName->GetWidget())
+ {
+ m_xColumnName->save_value();
+ strHelpText = m_xColumnName->GetHelp();
+ }
+ else if (m_xDefault && &rControl == m_xDefault->GetWidget())
+ {
+ m_xDefault->save_value();
+ strHelpText = m_xDefault->GetHelp();
+ }
+ else if (m_xFormatSample && &rControl == m_xFormatSample->GetWidget())
+ {
+ m_xFormatSample->save_value();
+ strHelpText = m_xFormatSample->GetHelp();
+ }
+ else if (m_xAutoIncrementValue && &rControl == m_xAutoIncrementValue->GetWidget())
+ {
+ m_xAutoIncrementValue->save_value();
+ strHelpText = m_xAutoIncrementValue->GetHelp();
+ }
+ else if (m_xRequired && &rControl == m_xRequired->GetWidget())
+ {
+ m_xRequired->save_value();
+ strHelpText = m_xRequired->GetHelp();
+ }
+ else if (m_xNumType && &rControl == m_xNumType->GetWidget())
+ {
+ m_xNumType->save_value();
+ strHelpText = m_xNumType->GetHelp();
+ }
+ else if (m_xAutoIncrement && &rControl == m_xAutoIncrement->GetWidget())
+ {
+ m_xAutoIncrement->save_value();
+ strHelpText = m_xAutoIncrement->GetHelp();
+ }
+ else if (m_xBoolDefault && &rControl == m_xBoolDefault->GetWidget())
+ {
+ m_xBoolDefault->save_value();
+ strHelpText = m_xBoolDefault->GetHelp();
+ }
+ else if (m_xType && &rControl == m_xType->GetWidget())
+ {
+ m_xType->save_value();
+ strHelpText = m_xType->GetHelp();
+ }
+ else if (m_xFormat && &rControl == m_xFormat.get())
+ strHelpText = DBA_RES(STR_HELP_FORMAT_BUTTON);
+
+ if (!strHelpText.isEmpty() && m_pHelp)
+ m_pHelp->SetHelpText(strHelpText);
+
+ m_pActFocusWindow = &rControl;
+
+ m_aControlFocusIn.Call(rControl);
+}
+
+IMPL_LINK(OFieldDescControl, OnControlFocusLost, weld::Widget&, rControl, void )
+{
+ if (m_xLength && &rControl == m_xLength->GetWidget() && m_xLength->get_value_changed_from_saved())
+ CellModified(-1, m_xLength->GetPos());
+ else if (m_xTextLen && &rControl == m_xTextLen->GetWidget() && m_xTextLen->get_value_changed_from_saved())
+ CellModified(-1, m_xTextLen->GetPos());
+ else if (m_xScale && &rControl == m_xScale->GetWidget() && m_xScale->get_value_changed_from_saved())
+ CellModified(-1, m_xScale->GetPos());
+ else if (m_xColumnName && &rControl == m_xColumnName->GetWidget() && m_xColumnName->get_value_changed_from_saved())
+ CellModified(-1, m_xColumnName->GetPos());
+ else if (m_xDefault && &rControl == m_xDefault->GetWidget() && m_xDefault->get_value_changed_from_saved())
+ CellModified(-1, m_xDefault->GetPos());
+ else if (m_xFormatSample && &rControl == m_xFormatSample->GetWidget() && m_xFormatSample->get_value_changed_from_saved())
+ CellModified(-1, m_xFormatSample->GetPos());
+ else if (m_xAutoIncrementValue && &rControl == m_xAutoIncrementValue->GetWidget() && m_xAutoIncrementValue->get_value_changed_from_saved())
+ CellModified(-1, m_xAutoIncrementValue->GetPos());
+ else if (m_xRequired && &rControl == m_xRequired->GetWidget() && m_xRequired->get_value_changed_from_saved())
+ CellModified(-1, m_xRequired->GetPos());
+ else if (m_xNumType && &rControl == m_xNumType->GetWidget() && m_xNumType->get_value_changed_from_saved())
+ CellModified(-1, m_xNumType->GetPos());
+ else if (m_xAutoIncrement && &rControl == m_xAutoIncrement->GetWidget() && m_xAutoIncrement->get_value_changed_from_saved())
+ CellModified(-1, m_xAutoIncrement->GetPos());
+ else if (m_xBoolDefault && &rControl == m_xBoolDefault->GetWidget() && m_xBoolDefault->get_value_changed_from_saved())
+ CellModified(-1, m_xBoolDefault->GetPos());
+ else if (m_xType && &rControl == m_xType->GetWidget() && m_xType->get_value_changed_from_saved())
+ CellModified(-1, m_xType->GetPos());
+ else if (m_xDefault && &rControl == m_xDefault->GetWidget())
+ UpdateFormatSample(pActFieldDescr);
+
+ implFocusLost(&rControl);
+}
+
+void OFieldDescControl::SaveData( OFieldDescription* pFieldDescr )
+{
+ if( !pFieldDescr )
+ return;
+
+ // Read out Controls
+ OUString sDefault;
+ if (m_xDefault)
+ {
+ // tdf#138409 take the control default in the UI Locale format, e.g. 12,34 and return a string
+ // suitable as the database default, e.g. 12.34
+ sDefault = CanonicalizeToControlDefault(pFieldDescr, m_xDefault->get_text());
+ }
+ else if (m_xBoolDefault)
+ {
+ sDefault = BoolStringPersistent(m_xBoolDefault->get_active_text());
+ }
+
+ if ( !sDefault.isEmpty() )
+ pFieldDescr->SetControlDefault(Any(sDefault));
+ else
+ pFieldDescr->SetControlDefault(Any());
+
+ if((m_xRequired && m_xRequired->get_active() == 0) || pFieldDescr->IsPrimaryKey() || (m_xBoolDefault && m_xBoolDefault->get_count() == 2)) // yes
+ pFieldDescr->SetIsNullable( ColumnValue::NO_NULLS );
+ else
+ pFieldDescr->SetIsNullable( ColumnValue::NULLABLE );
+
+ if (m_xAutoIncrement)
+ pFieldDescr->SetAutoIncrement(m_xAutoIncrement->get_active() == 0);
+
+ if( m_xTextLen )
+ pFieldDescr->SetPrecision( static_cast<sal_Int32>(m_xTextLen->get_value()) );
+ else if (m_xLength)
+ pFieldDescr->SetPrecision( static_cast<sal_Int32>(m_xLength->get_value()) );
+ if (m_xScale)
+ pFieldDescr->SetScale( static_cast<sal_Int32>(m_xScale->get_value()) );
+
+ if (m_xColumnName)
+ pFieldDescr->SetName(m_xColumnName->get_text());
+
+ if (m_xAutoIncrementValue && isAutoIncrementValueEnabled())
+ pFieldDescr->SetAutoIncrementValue(m_xAutoIncrementValue->get_text());
+}
+
+void OFieldDescControl::UpdateFormatSample(OFieldDescription const * pFieldDescr)
+{
+ if (pFieldDescr && m_xFormatSample)
+ m_xFormatSample->set_text(getControlDefault(pFieldDescr,false));
+}
+
+void OFieldDescControl::GrabFocus()
+{
+ m_xContainer->grab_focus();
+
+ // Set the Focus to the Control that has been active last
+ if (m_pLastFocusWindow)
+ {
+ m_pLastFocusWindow->grab_focus();
+ m_pLastFocusWindow = nullptr;
+ }
+}
+
+void OFieldDescControl::implFocusLost(weld::Widget* _pWhich)
+{
+ // Remember the active Control
+ if (!m_pLastFocusWindow)
+ m_pLastFocusWindow = _pWhich;
+
+ // Reset HelpText
+ if (m_pHelp && !m_pHelp->HasFocus())
+ m_pHelp->SetHelpText( OUString() );
+}
+
+IMPL_LINK_NOARG(OFieldDescControl, HelpFocusOut, weld::Widget&, void)
+{
+ m_pHelp->SetHelpText(OUString());
+}
+
+bool OFieldDescControl::IsFocusInEditableWidget() const
+{
+ if (m_xDefault && m_pActFocusWindow == m_xDefault->GetWidget())
+ return true;
+ if (m_xFormatSample && m_pActFocusWindow == m_xFormatSample->GetWidget())
+ return true;
+ if (m_xTextLen && m_pActFocusWindow == m_xTextLen->GetWidget())
+ return true;
+ if (m_xLength && m_pActFocusWindow == m_xLength->GetWidget())
+ return true;
+ if (m_xScale && m_pActFocusWindow == m_xScale->GetWidget())
+ return true;
+ if (m_xColumnName && m_pActFocusWindow == m_xColumnName->GetWidget())
+ return true;
+ if (m_xAutoIncrementValue && m_pActFocusWindow == m_xAutoIncrementValue->GetWidget())
+ return true;
+ return false;
+}
+
+bool OFieldDescControl::HasChildPathFocus() const
+{
+ return m_xContainer && m_xContainer->has_child_focus();
+}
+
+bool OFieldDescControl::isCopyAllowed()
+{
+ int nStartPos, nEndPos;
+ bool bAllowed = (m_pActFocusWindow != nullptr) && IsFocusInEditableWidget() &&
+ dynamic_cast<weld::Entry&>(*m_pActFocusWindow).get_selection_bounds(nStartPos, nEndPos);
+ return bAllowed;
+}
+
+bool OFieldDescControl::isCutAllowed()
+{
+ int nStartPos, nEndPos;
+ bool bAllowed = (m_pActFocusWindow != nullptr) && IsFocusInEditableWidget() &&
+ dynamic_cast<weld::Entry&>(*m_pActFocusWindow).get_selection_bounds(nStartPos, nEndPos);
+ return bAllowed;
+}
+
+bool OFieldDescControl::isPasteAllowed()
+{
+ bool bAllowed = (m_pActFocusWindow != nullptr) && IsFocusInEditableWidget();
+ if ( bAllowed )
+ {
+ TransferableDataHelper aTransferData(TransferableDataHelper::CreateFromClipboard(m_pActFocusWindow->get_clipboard()));
+ bAllowed = aTransferData.HasFormat(SotClipboardFormatId::STRING);
+ }
+ return bAllowed;
+}
+
+void OFieldDescControl::cut()
+{
+ if (isCutAllowed())
+ dynamic_cast<weld::Entry&>(*m_pActFocusWindow).cut_clipboard();
+}
+
+void OFieldDescControl::copy()
+{
+ if (isCopyAllowed()) // this only checks if the focus window is valid
+ dynamic_cast<weld::Entry&>(*m_pActFocusWindow).copy_clipboard();
+}
+
+void OFieldDescControl::paste()
+{
+ if (m_pActFocusWindow) // this only checks if the focus window is valid
+ dynamic_cast<weld::Entry&>(*m_pActFocusWindow).paste_clipboard();
+}
+
+bool OFieldDescControl::isTextFormat(const OFieldDescription* _pFieldDescr, sal_uInt32& _nFormatKey) const
+{
+ _nFormatKey = _pFieldDescr->GetFormatKey();
+ bool bTextFormat = true;
+
+ try
+ {
+ if (!_nFormatKey)
+ {
+ Reference< css::util::XNumberFormatTypes> xNumberTypes(GetFormatter()->getNumberFormatsSupplier()->getNumberFormats(),UNO_QUERY);
+ OSL_ENSURE(xNumberTypes.is(),"XNumberFormatTypes is null!");
+
+ _nFormatKey = ::dbtools::getDefaultNumberFormat( _pFieldDescr->GetType(),
+ _pFieldDescr->GetScale(),
+ _pFieldDescr->IsCurrency(),
+ xNumberTypes,
+ GetLocale());
+ }
+ sal_Int32 nNumberFormat = ::comphelper::getNumberFormatType(GetFormatter(),_nFormatKey);
+ bTextFormat = (nNumberFormat == css::util::NumberFormat::TEXT);
+ }
+ catch(const Exception&)
+ {
+
+ }
+
+ return bTextFormat;
+}
+
+OUString OFieldDescControl::getControlDefault( const OFieldDescription* _pFieldDescr, bool _bCheck) const
+{
+ OUString sDefault;
+ bool bCheck = !_bCheck || _pFieldDescr->GetControlDefault().hasValue();
+ if ( bCheck )
+ {
+ try
+ {
+ double nValue = 0.0;
+ sal_uInt32 nFormatKey;
+ bool bTextFormat = isTextFormat(_pFieldDescr,nFormatKey);
+ if ( _pFieldDescr->GetControlDefault() >>= sDefault )
+ {
+ if ( !bTextFormat )
+ {
+ if ( !sDefault.isEmpty() )
+ {
+ try
+ {
+ nValue = GetFormatter()->convertStringToNumber(nFormatKey,sDefault);
+ }
+ catch(const Exception&)
+ {
+ return OUString(); // return empty string for format example
+ }
+ }
+ }
+ }
+ else
+ _pFieldDescr->GetControlDefault() >>= nValue;
+
+ Reference< css::util::XNumberFormatter> xNumberFormatter = GetFormatter();
+ Reference<XPropertySet> xFormSet = xNumberFormatter->getNumberFormatsSupplier()->getNumberFormats()->getByKey(nFormatKey);
+ OSL_ENSURE(xFormSet.is(),"XPropertySet is null!");
+ OUString sFormat;
+ xFormSet->getPropertyValue("FormatString") >>= sFormat;
+
+ if ( !bTextFormat )
+ {
+ Locale aLocale;
+ ::comphelper::getNumberFormatProperty(xNumberFormatter,nFormatKey,"Locale") >>= aLocale;
+
+ sal_Int32 nNumberFormat = ::comphelper::getNumberFormatType(xNumberFormatter,nFormatKey);
+ if( (nNumberFormat & css::util::NumberFormat::DATE) == css::util::NumberFormat::DATE
+ || (nNumberFormat & css::util::NumberFormat::DATETIME) == css::util::NumberFormat::DATETIME )
+ {
+ nValue = DBTypeConversion::toNullDate(DBTypeConversion::getNULLDate(xNumberFormatter->getNumberFormatsSupplier()),nValue);
+ }
+
+ Reference< css::util::XNumberFormatPreviewer> xPreviewer(xNumberFormatter,UNO_QUERY);
+ OSL_ENSURE(xPreviewer.is(),"XNumberFormatPreviewer is null!");
+ sDefault = xPreviewer->convertNumberToPreviewString(sFormat,nValue,aLocale,true);
+ }
+ else if ( !(_bCheck && sDefault.isEmpty()) )
+ sDefault = xNumberFormatter->formatString(nFormatKey, sDefault.isEmpty() ? sFormat : sDefault);
+ }
+ catch(const Exception&)
+ {
+
+ }
+ }
+
+ return sDefault;
+}
+
+// tdf#138409 intended to be effectively the reverse of getControlDefault to
+// turn a user's possibly 12,34 format into 12.34 format for numerical types
+OUString OFieldDescControl::CanonicalizeToControlDefault(const OFieldDescription* pFieldDescr, const OUString& rDefault) const
+{
+ if (rDefault.isEmpty())
+ return rDefault;
+
+ bool bIsNumericalType = false;
+ switch (pFieldDescr->GetType())
+ {
+ case DataType::TINYINT:
+ case DataType::SMALLINT:
+ case DataType::INTEGER:
+ case DataType::BIGINT:
+ case DataType::FLOAT:
+ case DataType::REAL:
+ case DataType::DOUBLE:
+ case DataType::NUMERIC:
+ case DataType::DECIMAL:
+ bIsNumericalType = true;
+ break;
+ }
+
+ if (!bIsNumericalType)
+ return rDefault;
+
+ try
+ {
+ sal_uInt32 nFormatKey;
+ bool bTextFormat = isTextFormat(pFieldDescr, nFormatKey);
+ if (bTextFormat)
+ return rDefault;
+ double nValue = GetFormatter()->convertStringToNumber(nFormatKey, rDefault);
+ return OUString::number(nValue);
+ }
+ catch(const Exception&)
+ {
+ }
+
+ return rDefault;
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/control/RelationControl.cxx b/dbaccess/source/ui/control/RelationControl.cxx
new file mode 100644
index 000000000..fc8bca178
--- /dev/null
+++ b/dbaccess/source/ui/control/RelationControl.cxx
@@ -0,0 +1,695 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <RelationControl.hxx>
+
+#include <svtools/editbrowsebox.hxx>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <tools/diagnose_ex.h>
+#include <toolkit/helper/vclunohelper.hxx>
+#include <TableConnectionData.hxx>
+#include <TableConnection.hxx>
+#include <TableWindow.hxx>
+#include <com/sun/star/awt/XWindow.hpp>
+#include <com/sun/star/container/XNameAccess.hpp>
+#include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
+#include <RelControliFace.hxx>
+#include <helpids.h>
+#include <o3tl/safeint.hxx>
+#include <osl/diagnose.h>
+
+#include <vector>
+#include <utility>
+using std::pair;
+using std::make_pair;
+
+#define SOURCE_COLUMN 1
+#define DEST_COLUMN 2
+
+namespace dbaui
+{
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::beans;
+ using namespace ::com::sun::star::sdbc;
+ using namespace ::com::sun::star::sdbcx;
+ using namespace ::com::sun::star::container;
+ using namespace svt;
+
+ typedef ::svt::EditBrowseBox ORelationControl_Base;
+ class ORelationControl : public ORelationControl_Base
+ {
+ friend class OTableListBoxControl;
+
+ VclPtr< ::svt::ListBoxControl> m_pListCell;
+ TTableConnectionData::value_type m_pConnData;
+ OTableListBoxControl* m_pBoxControl;
+ tools::Long m_nDataPos;
+ Reference< XPropertySet> m_xSourceDef;
+ Reference< XPropertySet> m_xDestDef;
+ enum opcode { DELETE, INSERT, MODIFY };
+ typedef std::vector< pair < opcode, pair < OConnectionLineDataVec::size_type, OConnectionLineDataVec::size_type> > > ops_type;
+ ops_type m_ops;
+
+ void fillListBox(const Reference< XPropertySet>& _xDest);
+ /** returns the column id for the editbrowsebox
+ @param _nColId
+ the column id SOURCE_COLUMN or DEST_COLUMN
+
+ @return the current column id either SOURCE_COLUMN or DEST_COLUMN depends on the connection data
+ */
+ sal_uInt16 getColumnIdent( sal_uInt16 _nColId ) const;
+ public:
+ explicit ORelationControl(const css::uno::Reference<css::awt::XWindow>& rParent);
+ void SetController(OTableListBoxControl* pController)
+ {
+ m_pBoxControl = pController;
+ }
+
+ /** searches for a connection between these two tables
+ @param _pSource
+ the left table
+ @param _pDest
+ the right window
+ */
+ void setWindowTables(const OTableWindow* _pSource,const OTableWindow* _pDest);
+
+ /** allows to access the connection data from outside
+
+ @return the connection data
+ */
+ const TTableConnectionData::value_type& getData() const { return m_pConnData; }
+
+ void lateInit();
+
+ protected:
+ virtual ~ORelationControl() override { disposeOnce(); }
+ virtual void dispose() override { m_pListCell.disposeAndClear(); ORelationControl_Base::dispose(); }
+ virtual void Resize() override;
+ virtual Size GetOptimalSize() const override;
+ virtual bool PreNotify(NotifyEvent& rNEvt ) override;
+
+ virtual bool IsTabAllowed(bool bForward) const override;
+
+ void Init(const TTableConnectionData::value_type& _pConnData);
+ using ORelationControl_Base::Init;
+ virtual void InitController( ::svt::CellControllerRef& rController, sal_Int32 nRow, sal_uInt16 nCol ) override;
+ virtual ::svt::CellController* GetController( sal_Int32 nRow, sal_uInt16 nCol ) override;
+ virtual void PaintCell( OutputDevice& rDev, const tools::Rectangle& rRect, sal_uInt16 nColId ) const override;
+ virtual bool SeekRow( sal_Int32 nRow ) override;
+ virtual bool SaveModified() override;
+ virtual OUString GetCellText( sal_Int32 nRow, sal_uInt16 nColId ) const override;
+
+ virtual void CellModified() override;
+
+ DECL_LINK( AsynchDeactivate, void*, void );
+ private:
+
+ DECL_LINK( AsynchActivate, void*, void );
+
+ };
+
+ ORelationControl::ORelationControl(const css::uno::Reference<css::awt::XWindow>& rParent)
+ : EditBrowseBox(VCLUnoHelper::GetWindow(rParent),
+ EditBrowseBoxFlags::SMART_TAB_TRAVEL | EditBrowseBoxFlags::NO_HANDLE_COLUMN_CONTENT,
+ WB_TABSTOP | WB_BORDER,
+ BrowserMode::AUTOSIZE_LASTCOL)
+ , m_pBoxControl(nullptr)
+ , m_nDataPos(0)
+ {
+ }
+
+ void ORelationControl::Init(const TTableConnectionData::value_type& _pConnData)
+ {
+
+ m_pConnData = _pConnData;
+ OSL_ENSURE(m_pConnData, "No data supplied!");
+
+ m_pConnData->normalizeLines();
+ }
+
+ void ORelationControl::lateInit()
+ {
+ if ( !m_pConnData )
+ return;
+ m_xSourceDef = m_pConnData->getReferencingTable()->getTable();
+ m_xDestDef = m_pConnData->getReferencedTable()->getTable();
+
+ if ( ColCount() == 0 )
+ {
+ InsertDataColumn( SOURCE_COLUMN, m_pConnData->getReferencingTable()->GetWinName(), 100);
+ InsertDataColumn( DEST_COLUMN, m_pConnData->getReferencedTable()->GetWinName(), 100);
+ // If the Defs do not yet exits, we need to set them with SetSource-/-DestDef
+
+ m_pListCell.reset( VclPtr<ListBoxControl>::Create( &GetDataWindow() ) );
+
+ // set browse mode
+ SetMode( BrowserMode::COLUMNSELECTION |
+ BrowserMode::HLINES |
+ BrowserMode::VLINES |
+ BrowserMode::HIDECURSOR |
+ BrowserMode::HIDESELECT |
+ BrowserMode::AUTO_HSCROLL |
+ BrowserMode::AUTO_VSCROLL);
+ }
+ else
+ // not the first call
+ RowRemoved(0, GetRowCount());
+
+ RowInserted(0, m_pConnData->GetConnLineDataList().size() + 1); // add one extra row
+ }
+
+ void ORelationControl::Resize()
+ {
+ EditBrowseBox::Resize();
+ tools::Long nOutputWidth = GetOutputSizePixel().Width() - 1;
+ SetColumnWidth(1, (nOutputWidth / 2));
+ SetColumnWidth(2, (nOutputWidth / 2));
+ }
+
+ bool ORelationControl::PreNotify(NotifyEvent& rNEvt)
+ {
+ if (rNEvt.GetType() == MouseNotifyEvent::LOSEFOCUS && !HasChildPathFocus() && !ControlHasFocus())
+ PostUserEvent(LINK(this, ORelationControl, AsynchDeactivate), nullptr, true);
+ else if (rNEvt.GetType() == MouseNotifyEvent::GETFOCUS)
+ PostUserEvent(LINK(this, ORelationControl, AsynchActivate), nullptr, true);
+
+ return EditBrowseBox::PreNotify(rNEvt);
+ }
+
+ IMPL_LINK_NOARG(ORelationControl, AsynchActivate, void*, void)
+ {
+ ActivateCell();
+ }
+
+ IMPL_LINK_NOARG(ORelationControl, AsynchDeactivate, void*, void)
+ {
+ DeactivateCell();
+ }
+
+ bool ORelationControl::IsTabAllowed(bool bForward) const
+ {
+ sal_Int32 nRow = GetCurRow();
+ sal_uInt16 nCol = GetCurColumnId();
+
+ bool bRet = !( ( bForward && (nCol == DEST_COLUMN) && (nRow == GetRowCount() - 1))
+ || (!bForward && (nCol == SOURCE_COLUMN) && (nRow == 0)));
+
+ return bRet && EditBrowseBox::IsTabAllowed(bForward);
+ }
+
+ bool ORelationControl::SaveModified()
+ {
+ sal_Int32 nRow = GetCurRow();
+ if ( nRow != BROWSER_ENDOFSELECTION )
+ {
+ weld::ComboBox& rListBox = m_pListCell->get_widget();
+ OUString sFieldName(rListBox.get_active_text());
+ OConnectionLineDataVec& rLines = m_pConnData->GetConnLineDataList();
+ if ( rLines.size() <= o3tl::make_unsigned(nRow) )
+ {
+ rLines.push_back(new OConnectionLineData());
+ nRow = rLines.size() - 1;
+ // add new past-rLines row
+ m_ops.emplace_back(INSERT, make_pair(nRow+1, nRow+2));
+ }
+
+ OConnectionLineDataRef pConnLineData = rLines[nRow];
+
+ switch( getColumnIdent( GetCurColumnId() ) )
+ {
+ case SOURCE_COLUMN:
+ pConnLineData->SetSourceFieldName( sFieldName );
+ break;
+ case DEST_COLUMN:
+ pConnLineData->SetDestFieldName( sFieldName );
+ break;
+ }
+ // the modification we just did does *not* need to be registered in m_ops;
+ // it is already taken into account (by the codepath that called us)
+ //m_ops.push_back(make_pair(MODIFY, make_pair(nRow, nRow+1)));
+ }
+
+ const OConnectionLineDataVec::size_type oldSize = m_pConnData->GetConnLineDataList().size();
+ OConnectionLineDataVec::size_type line = m_pConnData->normalizeLines();
+ const OConnectionLineDataVec::size_type newSize = m_pConnData->GetConnLineDataList().size();
+ assert(newSize <= oldSize);
+ m_ops.emplace_back(MODIFY, make_pair(line, newSize));
+ m_ops.emplace_back(DELETE, make_pair(newSize, oldSize));
+
+ return true;
+ }
+
+ sal_uInt16 ORelationControl::getColumnIdent( sal_uInt16 _nColId ) const
+ {
+ sal_uInt16 nId = _nColId;
+ if ( m_pConnData->getReferencingTable() != m_pBoxControl->getReferencingTable() )
+ nId = ( _nColId == SOURCE_COLUMN) ? DEST_COLUMN : SOURCE_COLUMN;
+ return nId;
+ }
+
+ OUString ORelationControl::GetCellText( sal_Int32 nRow, sal_uInt16 nColId ) const
+ {
+ OUString sText;
+ if ( m_pConnData->GetConnLineDataList().size() > o3tl::make_unsigned(nRow) )
+ {
+ OConnectionLineDataRef pConnLineData = m_pConnData->GetConnLineDataList()[nRow];
+ switch( getColumnIdent( nColId ) )
+ {
+ case SOURCE_COLUMN:
+ sText = pConnLineData->GetSourceFieldName();
+ break;
+ case DEST_COLUMN:
+ sText = pConnLineData->GetDestFieldName();
+ break;
+ }
+ }
+ return sText;
+ }
+
+ void ORelationControl::InitController( CellControllerRef& /*rController*/, sal_Int32 nRow, sal_uInt16 nColumnId )
+ {
+
+ OString sHelpId( HID_RELATIONDIALOG_LEFTFIELDCELL );
+
+ Reference< XPropertySet> xDef;
+ switch ( getColumnIdent(nColumnId) )
+ {
+ case SOURCE_COLUMN:
+ xDef = m_xSourceDef;
+ sHelpId = HID_RELATIONDIALOG_LEFTFIELDCELL;
+ break;
+ case DEST_COLUMN:
+ xDef = m_xDestDef;
+ sHelpId = HID_RELATIONDIALOG_RIGHTFIELDCELL;
+ break;
+ default:
+ // ?????????
+ break;
+ }
+
+ if ( !xDef.is() )
+ return;
+
+ fillListBox(xDef);
+ OUString sName = GetCellText( nRow, nColumnId );
+ weld::ComboBox& rList = m_pListCell->get_widget();
+ rList.set_active_text(sName);
+ if (rList.get_active_text() != sName)
+ {
+ rList.append_text(sName);
+ rList.set_active_text(sName);
+ }
+
+ rList.set_help_id(sHelpId);
+ }
+
+ CellController* ORelationControl::GetController( sal_Int32 /*nRow*/, sal_uInt16 /*nColumnId*/ )
+ {
+ return new ListBoxCellController( m_pListCell.get() );
+ }
+
+ bool ORelationControl::SeekRow( sal_Int32 nRow )
+ {
+ m_nDataPos = nRow;
+ return true;
+ }
+
+ void ORelationControl::PaintCell( OutputDevice& rDev, const tools::Rectangle& rRect, sal_uInt16 nColumnId ) const
+ {
+ OUString aText = GetCellText( m_nDataPos, nColumnId );
+
+ Point aPos( rRect.TopLeft() );
+ Size aTextSize( GetDataWindow().GetTextWidth( aText ), GetDataWindow().GetTextHeight() );
+
+ if( aPos.X() < rRect.Left() || aPos.X() + aTextSize.Width() > rRect.Right() ||
+ aPos.Y() < rRect.Top() || aPos.Y() + aTextSize.Height() > rRect.Bottom() )
+ {
+ rDev.SetClipRegion(vcl::Region(rRect));
+ }
+
+ rDev.DrawText( aPos, aText );
+
+ if( rDev.IsClipRegion() )
+ rDev.SetClipRegion();
+ }
+ void ORelationControl::fillListBox(const Reference< XPropertySet>& _xDest)
+ {
+ weld::ComboBox& rList = m_pListCell->get_widget();
+ rList.clear();
+ try
+ {
+ if ( _xDest.is() )
+ {
+ //sal_Int32 nRows = GetRowCount();
+ Reference<XColumnsSupplier> xSup(_xDest,UNO_QUERY);
+ Reference<XNameAccess> xColumns = xSup->getColumns();
+ Sequence< OUString> aNames = xColumns->getElementNames();
+ const OUString* pIter = aNames.getConstArray();
+ const OUString* pEnd = pIter + aNames.getLength();
+ for(;pIter != pEnd;++pIter)
+ {
+ rList.append_text(*pIter);
+ }
+ rList.insert_text(0, OUString());
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+ void ORelationControl::setWindowTables(const OTableWindow* _pSource,const OTableWindow* _pDest)
+ {
+ // If I edit here, hide
+ bool bWasEditing = IsEditing();
+ if ( bWasEditing )
+ DeactivateCell();
+
+ if ( _pSource && _pDest )
+ {
+ m_xSourceDef = _pSource->GetTable();
+ SetColumnTitle(1, _pSource->GetName());
+
+ m_xDestDef = _pDest->GetTable();
+ SetColumnTitle(2, _pDest->GetName());
+
+ const OJoinTableView* pView = _pSource->getTableView();
+ OTableConnection* pConn = pView->GetTabConn(_pSource,_pDest);
+ if ( pConn && !m_pConnData->GetConnLineDataList().empty() )
+ {
+ m_pConnData->CopyFrom(*pConn->GetData());
+ m_pBoxControl->getContainer()->notifyConnectionChange();
+ }
+ else
+ {
+ // no connection found so we clear our data
+ OConnectionLineDataVec& rLines = m_pConnData->GetConnLineDataList();
+ for( const auto& rLine : rLines )
+ {
+ rLine->Reset();
+ }
+
+ m_pConnData->setReferencingTable(_pSource->GetData());
+ m_pConnData->setReferencedTable(_pDest->GetData());
+ }
+ m_pConnData->normalizeLines();
+
+ }
+ // Repaint
+ Invalidate();
+
+ if ( bWasEditing )
+ {
+ GoToRow(0);
+ ActivateCell();
+ }
+ }
+
+ void ORelationControl::CellModified()
+ {
+ EditBrowseBox::CellModified();
+ SaveModified();
+ assert(m_pBoxControl);
+ m_pBoxControl->NotifyCellChange();
+ }
+
+ Size ORelationControl::GetOptimalSize() const
+ {
+ return LogicToPixel(Size(140, 80), MapMode(MapUnit::MapAppFont));
+ }
+
+ OTableListBoxControl::OTableListBoxControl(weld::Builder* _pParent,
+ const OJoinTableView::OTableWindowMap* _pTableMap,
+ IRelationControlInterface* _pParentDialog)
+ : m_xLeftTable(_pParent->weld_combo_box("table1"))
+ , m_xRightTable(_pParent->weld_combo_box("table2"))
+ , m_xTable(_pParent->weld_container("relations"))
+ , m_xTableCtrlParent(m_xTable->CreateChildFrame())
+ , m_xRC_Tables(VclPtr<ORelationControl>::Create(m_xTableCtrlParent))
+ , m_pTableMap(_pTableMap)
+ , m_pParentDialog(_pParentDialog)
+ {
+ Size aPrefSize = m_xRC_Tables->GetOptimalSize();
+ m_xTable->set_size_request(aPrefSize.Width(), aPrefSize.Height());
+
+ m_xRC_Tables->SetController(this);
+ m_xRC_Tables->Init();
+
+ lateUIInit();
+
+ Link<weld::ComboBox&,void> aLink(LINK(this, OTableListBoxControl, OnTableChanged));
+ m_xLeftTable->connect_changed(aLink);
+ m_xRightTable->connect_changed(aLink);
+ }
+
+ OTableListBoxControl::~OTableListBoxControl()
+ {
+ m_xRC_Tables.disposeAndClear();
+ m_xTableCtrlParent->dispose();
+ m_xTableCtrlParent.clear();
+ }
+
+ void OTableListBoxControl::fillListBoxes()
+ {
+ OSL_ENSURE( !m_pTableMap->empty(), "OTableListBoxControl::fillListBoxes: no table window!");
+ OTableWindow* pInitialLeft = nullptr;
+ OTableWindow* pInitialRight = nullptr;
+
+ // Collect the names of all TabWins
+ for (auto const& elem : *m_pTableMap)
+ {
+ m_xLeftTable->append_text(elem.first);
+ m_xRightTable->append_text(elem.first);
+
+ if (!pInitialLeft)
+ {
+ pInitialLeft = elem.second;
+ m_strCurrentLeft = elem.first;
+ }
+ else if (!pInitialRight)
+ {
+ pInitialRight = elem.second;
+ m_strCurrentRight = elem.first;
+ }
+ }
+
+ if ( !pInitialRight )
+ {
+ pInitialRight = pInitialLeft;
+ m_strCurrentRight = m_strCurrentLeft;
+ }
+
+ // The corresponding Defs for my Controls
+ m_xRC_Tables->setWindowTables(pInitialLeft,pInitialRight);
+
+ // The table selected in a ComboBox must not be available in the other
+
+ if ( m_pTableMap->size() > 2 )
+ {
+ m_xLeftTable->remove_text(m_strCurrentRight);
+ m_xRightTable->remove_text(m_strCurrentLeft);
+ }
+
+ // Select the first one on the left side and on the right side,
+ // select the second one
+ m_xLeftTable->set_active_text(m_strCurrentLeft);
+ m_xRightTable->set_active_text(m_strCurrentRight);
+
+ m_xLeftTable->grab_focus();
+ }
+
+ IMPL_LINK(OTableListBoxControl, OnTableChanged, weld::ComboBox&, rListBox, void)
+ {
+ OUString strSelected(rListBox.get_active_text());
+ OTableWindow* pLeft = nullptr;
+ OTableWindow* pRight = nullptr;
+
+ // Special treatment: If there are only two tables, we need to switch the other one too when changing in a LB
+ if ( m_pTableMap->size() == 2 )
+ {
+ weld::ComboBox* pOther;
+ if (&rListBox == m_xLeftTable.get())
+ pOther = m_xRightTable.get();
+ else
+ pOther = m_xLeftTable.get();
+ pOther->set_active(1 - pOther->get_active());
+
+ OJoinTableView::OTableWindowMap::const_iterator aIter = m_pTableMap->begin();
+ OTableWindow* pFirst = aIter->second;
+ ++aIter;
+ OTableWindow* pSecond = aIter->second;
+
+ if (m_xLeftTable->get_active_text() == pFirst->GetName())
+ {
+ pLeft = pFirst;
+ pRight = pSecond;
+ }
+ else
+ {
+ pLeft = pSecond;
+ pRight = pFirst;
+ }
+ }
+ else
+ {
+ // First we need the TableDef to the Table and with it the TabWin
+ OJoinTableView::OTableWindowMap::const_iterator aFind = m_pTableMap->find(strSelected);
+ OTableWindow* pLoop = nullptr;
+ if( aFind != m_pTableMap->end() )
+ pLoop = aFind->second;
+ OSL_ENSURE(pLoop != nullptr, "ORelationDialog::OnTableChanged: invalid ListBox entry!");
+ // We need to find strSelect, because we filled the ListBoxes with the table names with which we compare now
+ if (&rListBox == m_xLeftTable.get())
+ {
+ // Insert the previously selected Entry on the left side on the right side
+ m_xRightTable->append_text(m_strCurrentLeft);
+ // Remove the currently selected Entry
+ m_xRightTable->remove_text(strSelected);
+ m_strCurrentLeft = strSelected;
+
+ pLeft = pLoop;
+
+ OJoinTableView::OTableWindowMap::const_iterator aIter = m_pTableMap->find(m_xRightTable->get_active_text());
+ OSL_ENSURE( aIter != m_pTableMap->end(), "Invalid name");
+ if ( aIter != m_pTableMap->end() )
+ pRight = aIter->second;
+
+ m_xLeftTable->grab_focus();
+ }
+ else
+ {
+ // Insert the previously selected Entry on the right side on the left side
+ m_xLeftTable->append_text(m_strCurrentRight);
+ // Remove the currently selected Entry
+ m_xLeftTable->remove_text(strSelected);
+ m_strCurrentRight = strSelected;
+
+ pRight = pLoop;
+ OJoinTableView::OTableWindowMap::const_iterator aIter = m_pTableMap->find(m_xLeftTable->get_active_text());
+ OSL_ENSURE( aIter != m_pTableMap->end(), "Invalid name");
+ if ( aIter != m_pTableMap->end() )
+ pLeft = aIter->second;
+ }
+ }
+
+ rListBox.grab_focus();
+
+ m_xRC_Tables->setWindowTables(pLeft,pRight);
+
+ NotifyCellChange();
+ }
+
+ void OTableListBoxControl::NotifyCellChange()
+ {
+ // Enable/disable the OK button, depending on having a valid situation
+ TTableConnectionData::value_type pConnData = m_xRC_Tables->getData();
+ const OConnectionLineDataVec& rLines = pConnData->GetConnLineDataList();
+ bool bValid = !rLines.empty();
+ if (bValid)
+ {
+ for (auto const& line : rLines)
+ {
+ bValid = ! (line->GetSourceFieldName().isEmpty() || line->GetDestFieldName().isEmpty());
+ if (!bValid)
+ break;
+ }
+ }
+ m_pParentDialog->setValid(bValid);
+
+ m_xRC_Tables->DeactivateCell();
+ for (auto const& elem : m_xRC_Tables->m_ops)
+ {
+ switch(elem.first)
+ {
+ case ORelationControl::DELETE:
+ m_xRC_Tables->RowRemoved(elem.second.first, elem.second.second - elem.second.first);
+ break;
+ case ORelationControl::INSERT:
+ m_xRC_Tables->RowInserted(elem.second.first, elem.second.second - elem.second.first);
+ break;
+ case ORelationControl::MODIFY:
+ for(OConnectionLineDataVec::size_type j = elem.second.first; j < elem.second.second; ++j)
+ m_xRC_Tables->RowModified(j);
+ break;
+ }
+ }
+ m_xRC_Tables->ActivateCell();
+ m_xRC_Tables->m_ops.clear();
+ }
+
+ static void fillEntryAndDisable(weld::ComboBox& _rListBox,const OUString& _sEntry)
+ {
+ _rListBox.append_text(_sEntry);
+ _rListBox.set_active(0);
+ _rListBox.set_sensitive(false);
+ }
+
+ void OTableListBoxControl::fillAndDisable(const TTableConnectionData::value_type& _pConnectionData)
+ {
+ fillEntryAndDisable(*m_xLeftTable, _pConnectionData->getReferencingTable()->GetWinName());
+ fillEntryAndDisable(*m_xRightTable, _pConnectionData->getReferencedTable()->GetWinName());
+ }
+
+ void OTableListBoxControl::Init(const TTableConnectionData::value_type& _pConnData)
+ {
+ m_xRC_Tables->Init(_pConnData);
+ }
+
+ void OTableListBoxControl::lateUIInit()
+ {
+ m_xRC_Tables->Show();
+ lateInit();
+ }
+
+ void OTableListBoxControl::lateInit()
+ {
+ m_xRC_Tables->lateInit();
+ }
+
+ void OTableListBoxControl::Disable()
+ {
+ m_xLeftTable->set_sensitive(false);
+ m_xRightTable->set_sensitive(false);
+ m_xRC_Tables->Disable();
+ }
+
+ void OTableListBoxControl::Invalidate()
+ {
+ m_xRC_Tables->Invalidate();
+ }
+
+ void OTableListBoxControl::SaveModified()
+ {
+ m_xRC_Tables->SaveModified();
+ }
+
+ TTableWindowData::value_type const & OTableListBoxControl::getReferencingTable() const
+ {
+ return m_xRC_Tables->getData()->getReferencingTable();
+ }
+
+ void OTableListBoxControl::enableRelation(bool _bEnable)
+ {
+ if ( !_bEnable )
+ m_xRC_Tables->PostUserEvent(LINK(m_xRC_Tables, ORelationControl, AsynchDeactivate));
+ m_xRC_Tables->Enable(_bEnable);
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/control/SqlNameEdit.cxx b/dbaccess/source/ui/control/SqlNameEdit.cxx
new file mode 100644
index 000000000..9d968a0fd
--- /dev/null
+++ b/dbaccess/source/ui/control/SqlNameEdit.cxx
@@ -0,0 +1,85 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <SqlNameEdit.hxx>
+
+namespace dbaui
+{
+ static bool isCharOk(sal_Unicode _cChar,bool _bFirstChar, std::u16string_view _sAllowedChars)
+ {
+ return (
+ (_cChar >= 'A' && _cChar <= 'Z') ||
+ _cChar == '_' ||
+ _sAllowedChars.find(_cChar) != std::u16string_view::npos ||
+ (!_bFirstChar && (_cChar >= '0' && _cChar <= '9')) ||
+ (_cChar >= 'a' && _cChar <= 'z')
+ );
+ }
+ bool OSQLNameChecker::checkString(const OUString& _sToCheck,
+ OUString& _rsCorrected)
+ {
+ bool bCorrected = false;
+ if ( m_bCheck )
+ {
+ sal_Int32 nMatch = 0;
+ for (sal_Int32 i = nMatch; i < _sToCheck.getLength(); ++i)
+ {
+ if ( !isCharOk( _sToCheck[i], i == 0, m_sAllowedChars ) )
+ {
+ _rsCorrected += _sToCheck.subView(nMatch, i - nMatch);
+ bCorrected = true;
+ nMatch = i + 1;
+ }
+ }
+ _rsCorrected += _sToCheck.subView( nMatch );
+ }
+ return bCorrected;
+ }
+
+ namespace
+ {
+ void checkName(OSQLNameChecker& rChecker, weld::Entry& rEntry)
+ {
+ OUString sCorrected;
+ if (rChecker.checkString(rEntry.get_text(), sCorrected))
+ {
+ int nStartPos, nEndPos;
+ rEntry.get_selection_bounds(nStartPos, nEndPos);
+ int nMin = std::min(nStartPos, nEndPos);
+ rEntry.set_text(sCorrected);
+ rEntry.select_region(nMin, nMin);
+
+ rEntry.save_value();
+ }
+ }
+ }
+
+ IMPL_LINK(OSQLNameEditControl, ModifyHdl, weld::Entry&, rEntry, void)
+ {
+ checkName(*this, rEntry);
+ m_ChainChangedHdl.Call(rEntry);
+ }
+
+ IMPL_LINK(OSQLNameEntry, ModifyHdl, weld::Entry&, rEntry, void)
+ {
+ checkName(*this, rEntry);
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/control/TableGrantCtrl.cxx b/dbaccess/source/ui/control/TableGrantCtrl.cxx
new file mode 100644
index 000000000..f4826e96d
--- /dev/null
+++ b/dbaccess/source/ui/control/TableGrantCtrl.cxx
@@ -0,0 +1,476 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <TableGrantCtrl.hxx>
+#include <core_resource.hxx>
+#include <com/sun/star/sdbc/SQLException.hpp>
+#include <com/sun/star/sdbcx/XTablesSupplier.hpp>
+#include <com/sun/star/sdbcx/Privilege.hpp>
+#include <com/sun/star/sdbcx/PrivilegeObject.hpp>
+#include <com/sun/star/sdbcx/XUsersSupplier.hpp>
+#include <com/sun/star/sdbcx/XAuthorizable.hpp>
+#include <connectivity/dbtools.hxx>
+#include <toolkit/helper/vclunohelper.hxx>
+#include <vcl/svapp.hxx>
+#include <osl/diagnose.h>
+#include <strings.hrc>
+
+using namespace ::com::sun::star::accessibility;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::sdbcx;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::uno;
+using namespace ::dbaui;
+using namespace ::svt;
+
+const sal_uInt16 COL_TABLE_NAME = 1;
+const sal_uInt16 COL_SELECT = 2;
+const sal_uInt16 COL_INSERT = 3;
+const sal_uInt16 COL_DELETE = 4;
+const sal_uInt16 COL_UPDATE = 5;
+const sal_uInt16 COL_ALTER = 6;
+const sal_uInt16 COL_REF = 7;
+const sal_uInt16 COL_DROP = 8;
+
+
+// OTableGrantControl
+OTableGrantControl::OTableGrantControl(const css::uno::Reference<css::awt::XWindow> &rParent)
+ :EditBrowseBox(VCLUnoHelper::GetWindow(rParent), EditBrowseBoxFlags::SMART_TAB_TRAVEL | EditBrowseBoxFlags::NO_HANDLE_COLUMN_CONTENT, WB_TABSTOP)
+ ,m_pCheckCell( nullptr )
+ ,m_pEdit( nullptr )
+ ,m_nDataPos( 0 )
+ ,m_nDeactivateEvent(nullptr)
+{
+ // insert columns
+ sal_uInt16 i=1;
+ InsertDataColumn( i, DBA_RES(STR_TABLE_PRIV_NAME), 75);
+ FreezeColumn(i++);
+ InsertDataColumn( i++, DBA_RES(STR_TABLE_PRIV_SELECT), 75);
+ InsertDataColumn( i++, DBA_RES(STR_TABLE_PRIV_INSERT), 75);
+ InsertDataColumn( i++, DBA_RES(STR_TABLE_PRIV_DELETE), 75);
+ InsertDataColumn( i++, DBA_RES(STR_TABLE_PRIV_UPDATE), 75);
+ InsertDataColumn( i++, DBA_RES(STR_TABLE_PRIV_ALTER), 75);
+ InsertDataColumn( i++, DBA_RES(STR_TABLE_PRIV_REFERENCE), 75);
+ InsertDataColumn( i++, DBA_RES(STR_TABLE_PRIV_DROP), 75);
+
+ while(--i)
+ SetColumnWidth(i,GetAutoColumnWidth(i));
+}
+
+OTableGrantControl::~OTableGrantControl()
+{
+ disposeOnce();
+}
+
+void OTableGrantControl::dispose()
+{
+ if (m_nDeactivateEvent)
+ {
+ Application::RemoveUserEvent(m_nDeactivateEvent);
+ m_nDeactivateEvent = nullptr;
+ }
+
+ m_pCheckCell.disposeAndClear();
+ m_pEdit.disposeAndClear();
+
+ m_xTables = nullptr;
+ ::svt::EditBrowseBox::dispose();
+}
+
+void OTableGrantControl::setTablesSupplier(const Reference< XTablesSupplier >& _xTablesSup)
+{
+ // first we need the users
+ Reference< XUsersSupplier> xUserSup(_xTablesSup,UNO_QUERY);
+ if(xUserSup.is())
+ m_xUsers = xUserSup->getUsers();
+
+ // second we need the tables to determine which privileges the user has
+ if(_xTablesSup.is())
+ m_xTables = _xTablesSup->getTables();
+
+ if(m_xTables.is())
+ m_aTableNames = m_xTables->getElementNames();
+
+ OSL_ENSURE(m_xUsers.is(),"No user access supported!");
+ OSL_ENSURE(m_xTables.is(),"No tables supported!");
+}
+
+void OTableGrantControl::setComponentContext(const Reference< css::uno::XComponentContext>& _rxContext)
+{
+ m_xContext = _rxContext;
+}
+
+void OTableGrantControl::UpdateTables()
+{
+ RemoveRows();
+
+ if(m_xTables.is())
+ RowInserted(0, m_aTableNames.getLength());
+ // m_bEnable = m_xDb->GetUser() != ((OUserAdmin*)GetParent())->GetUser();
+}
+
+void OTableGrantControl::Init()
+{
+ EditBrowseBox::Init();
+
+ // instantiate ComboBox
+ if(!m_pCheckCell)
+ {
+ m_pCheckCell = VclPtr<CheckBoxControl>::Create( &GetDataWindow() );
+ m_pCheckCell->EnableTriState(false);
+
+ m_pEdit = VclPtr<EditControl>::Create(&GetDataWindow());
+ weld::Entry& rEntry = m_pEdit->get_widget();
+ rEntry.set_editable(false);
+ rEntry.set_sensitive(false);
+ }
+
+ UpdateTables();
+ // set browser mode
+ BrowserMode const nMode = BrowserMode::COLUMNSELECTION | BrowserMode::HLINES | BrowserMode::VLINES |
+ BrowserMode::HIDECURSOR | BrowserMode::HIDESELECT;
+
+ SetMode(nMode);
+}
+
+bool OTableGrantControl::PreNotify(NotifyEvent& rNEvt)
+{
+ if (rNEvt.GetType() == MouseNotifyEvent::LOSEFOCUS)
+ if (!HasChildPathFocus())
+ {
+ if (m_nDeactivateEvent)
+ Application::RemoveUserEvent(m_nDeactivateEvent);
+ m_nDeactivateEvent = Application::PostUserEvent(LINK(this, OTableGrantControl, AsynchDeactivate), nullptr, true);
+ }
+ if (rNEvt.GetType() == MouseNotifyEvent::GETFOCUS)
+ {
+ if (m_nDeactivateEvent)
+ Application::RemoveUserEvent(m_nDeactivateEvent);
+ m_nDeactivateEvent = Application::PostUserEvent(LINK(this, OTableGrantControl, AsynchActivate), nullptr, true);
+ }
+ return EditBrowseBox::PreNotify(rNEvt);
+}
+
+IMPL_LINK_NOARG(OTableGrantControl, AsynchActivate, void*, void)
+{
+ m_nDeactivateEvent = nullptr;
+ ActivateCell();
+}
+
+IMPL_LINK_NOARG(OTableGrantControl, AsynchDeactivate, void*, void)
+{
+ m_nDeactivateEvent = nullptr;
+ DeactivateCell();
+}
+
+bool OTableGrantControl::IsTabAllowed(bool bForward) const
+{
+ sal_Int32 nRow = GetCurRow();
+ sal_uInt16 nCol = GetCurColumnId();
+
+ if (bForward && (nCol == 2) && (nRow == GetRowCount() - 1))
+ return false;
+
+ if (!bForward && (nCol == 1) && (nRow == 0))
+ return false;
+
+ return EditBrowseBox::IsTabAllowed(bForward);
+}
+
+bool OTableGrantControl::SaveModified()
+{
+
+ sal_Int32 nRow = GetCurRow();
+ if(nRow == -1 || nRow >= m_aTableNames.getLength())
+ return false;
+
+ OUString sTableName = m_aTableNames[nRow];
+ bool bErg = true;
+ try
+ {
+
+ if ( m_xUsers->hasByName(m_sUserName) )
+ {
+ Reference<XAuthorizable> xAuth(m_xUsers->getByName(m_sUserName),UNO_QUERY);
+ if ( xAuth.is() )
+ {
+ switch( GetCurColumnId() )
+ {
+ case COL_INSERT:
+ if (m_pCheckCell->GetBox().get_active())
+ xAuth->grantPrivileges(sTableName,PrivilegeObject::TABLE,Privilege::INSERT);
+ else
+ xAuth->revokePrivileges(sTableName,PrivilegeObject::TABLE,Privilege::INSERT);
+ break;
+ case COL_DELETE:
+ if (m_pCheckCell->GetBox().get_active())
+ xAuth->grantPrivileges(sTableName,PrivilegeObject::TABLE,Privilege::DELETE);
+ else
+ xAuth->revokePrivileges(sTableName,PrivilegeObject::TABLE,Privilege::DELETE);
+ break;
+ case COL_UPDATE:
+ if (m_pCheckCell->GetBox().get_active())
+ xAuth->grantPrivileges(sTableName,PrivilegeObject::TABLE,Privilege::UPDATE);
+ else
+ xAuth->revokePrivileges(sTableName,PrivilegeObject::TABLE,Privilege::UPDATE);
+ break;
+ case COL_ALTER:
+ if (m_pCheckCell->GetBox().get_active())
+ xAuth->grantPrivileges(sTableName,PrivilegeObject::TABLE,Privilege::ALTER);
+ else
+ xAuth->revokePrivileges(sTableName,PrivilegeObject::TABLE,Privilege::ALTER);
+ break;
+ case COL_SELECT:
+ if (m_pCheckCell->GetBox().get_active())
+ xAuth->grantPrivileges(sTableName,PrivilegeObject::TABLE,Privilege::SELECT);
+ else
+ xAuth->revokePrivileges(sTableName,PrivilegeObject::TABLE,Privilege::SELECT);
+ break;
+ case COL_REF:
+ if (m_pCheckCell->GetBox().get_active())
+ xAuth->grantPrivileges(sTableName,PrivilegeObject::TABLE,Privilege::REFERENCE);
+ else
+ xAuth->revokePrivileges(sTableName,PrivilegeObject::TABLE,Privilege::REFERENCE);
+ break;
+ case COL_DROP:
+ if (m_pCheckCell->GetBox().get_active())
+ xAuth->grantPrivileges(sTableName,PrivilegeObject::TABLE,Privilege::DROP);
+ else
+ xAuth->revokePrivileges(sTableName,PrivilegeObject::TABLE,Privilege::DROP);
+ break;
+ }
+ fillPrivilege(nRow);
+ }
+ }
+ }
+ catch(SQLException& e)
+ {
+ bErg = false;
+ ::dbtools::showError(::dbtools::SQLExceptionInfo(e),VCLUnoHelper::GetInterface(GetParent()),m_xContext);
+ }
+ if(bErg && Controller().is())
+ Controller()->SaveValue();
+ if(!bErg)
+ UpdateTables();
+
+ return bErg;
+}
+
+OUString OTableGrantControl::GetCellText( sal_Int32 nRow, sal_uInt16 nColId ) const
+{
+ if(COL_TABLE_NAME == nColId)
+ return m_aTableNames[nRow];
+
+ sal_Int32 nPriv = 0;
+ TTablePrivilegeMap::const_iterator aFind = findPrivilege(nRow);
+ if(aFind != m_aPrivMap.end())
+ nPriv = aFind->second.nRights;
+
+ return OUString::number(isAllowed(nColId,nPriv) ? 1 :0);
+}
+
+void OTableGrantControl::InitController( CellControllerRef& /*rController*/, sal_Int32 nRow, sal_uInt16 nColumnId )
+{
+ OUString sTablename = m_aTableNames[nRow];
+ // special case for tablename
+ if (nColumnId == COL_TABLE_NAME)
+ m_pEdit->get_widget().set_text(sTablename);
+ else
+ {
+ // get the privileges from the user
+ TTablePrivilegeMap::const_iterator aFind = findPrivilege(nRow);
+ m_pCheckCell->GetBox().set_active(aFind != m_aPrivMap.end() && isAllowed(nColumnId,aFind->second.nRights));
+ }
+}
+
+void OTableGrantControl::fillPrivilege(sal_Int32 _nRow) const
+{
+
+ if ( !m_xUsers->hasByName(m_sUserName) )
+ return;
+
+ try
+ {
+ Reference<XAuthorizable> xAuth(m_xUsers->getByName(m_sUserName),UNO_QUERY);
+ if ( xAuth.is() )
+ {
+ // get the privileges
+ TPrivileges nRights;
+ nRights.nRights = xAuth->getPrivileges(m_aTableNames[_nRow],PrivilegeObject::TABLE);
+ if(m_xGrantUser.is())
+ nRights.nWithGrant = m_xGrantUser->getGrantablePrivileges(m_aTableNames[_nRow],PrivilegeObject::TABLE);
+ else
+ nRights.nWithGrant = 0;
+
+ m_aPrivMap[m_aTableNames[_nRow]] = nRights;
+ }
+ }
+ catch(SQLException& e)
+ {
+ ::dbtools::showError(::dbtools::SQLExceptionInfo(e),VCLUnoHelper::GetInterface(GetParent()),m_xContext);
+ }
+ catch(Exception& )
+ {
+ }
+}
+
+bool OTableGrantControl::isAllowed(sal_uInt16 _nColumnId,sal_Int32 _nPrivilege)
+{
+ bool bAllowed = false;
+ switch (_nColumnId)
+ {
+ case COL_INSERT:
+ bAllowed = (Privilege::INSERT & _nPrivilege) == Privilege::INSERT;
+ break;
+ case COL_DELETE:
+ bAllowed = (Privilege::DELETE & _nPrivilege) == Privilege::DELETE;
+ break;
+ case COL_UPDATE:
+ bAllowed = (Privilege::UPDATE & _nPrivilege) == Privilege::UPDATE;
+ break;
+ case COL_ALTER:
+ bAllowed = (Privilege::ALTER & _nPrivilege) == Privilege::ALTER;
+ break;
+ case COL_SELECT:
+ bAllowed = (Privilege::SELECT & _nPrivilege) == Privilege::SELECT;
+ break;
+ case COL_REF:
+ bAllowed = (Privilege::REFERENCE & _nPrivilege) == Privilege::REFERENCE;
+ break;
+ case COL_DROP:
+ bAllowed = (Privilege::DROP & _nPrivilege) == Privilege::DROP;
+ break;
+ }
+ return bAllowed;
+}
+
+void OTableGrantControl::setUserName(const OUString& _sUserName)
+{
+ m_sUserName = _sUserName;
+ m_aPrivMap = TTablePrivilegeMap();
+}
+
+void OTableGrantControl::setGrantUser(const Reference< XAuthorizable>& _xGrantUser)
+{
+ OSL_ENSURE(_xGrantUser.is(),"OTableGrantControl::setGrantUser: GrantUser is null!");
+ m_xGrantUser = _xGrantUser;
+}
+
+CellController* OTableGrantControl::GetController( sal_Int32 nRow, sal_uInt16 nColumnId )
+{
+
+ CellController* pController = nullptr;
+ switch( nColumnId )
+ {
+ case COL_TABLE_NAME:
+ break;
+ case COL_INSERT:
+ case COL_DELETE:
+ case COL_UPDATE:
+ case COL_ALTER:
+ case COL_SELECT:
+ case COL_REF:
+ case COL_DROP:
+ {
+ TTablePrivilegeMap::const_iterator aFind = findPrivilege(nRow);
+ if(aFind != m_aPrivMap.end() && isAllowed(nColumnId,aFind->second.nWithGrant))
+ pController = new CheckBoxCellController( m_pCheckCell );
+ }
+ break;
+ default:
+ ;
+ }
+ return pController;
+}
+
+bool OTableGrantControl::SeekRow( sal_Int32 nRow )
+{
+ m_nDataPos = nRow;
+
+ return (nRow <= m_aTableNames.getLength());
+}
+
+void OTableGrantControl::PaintCell( OutputDevice& rDev, const tools::Rectangle& rRect, sal_uInt16 nColumnId ) const
+{
+
+ if(nColumnId != COL_TABLE_NAME)
+ {
+ TTablePrivilegeMap::const_iterator aFind = findPrivilege(m_nDataPos);
+ if(aFind != m_aPrivMap.end())
+ PaintTristate(rRect, isAllowed(nColumnId,aFind->second.nRights) ? TRISTATE_TRUE : TRISTATE_FALSE,isAllowed(nColumnId,aFind->second.nWithGrant));
+ else
+ PaintTristate(rRect, TRISTATE_FALSE, false);
+ }
+ else
+ {
+ OUString aText(GetCellText( m_nDataPos, nColumnId ));
+ Point aPos( rRect.TopLeft() );
+ sal_Int32 nWidth = GetDataWindow().GetTextWidth( aText );
+ sal_Int32 nHeight = GetDataWindow().GetTextHeight();
+
+ if( aPos.X() < rRect.Left() || aPos.X() + nWidth > rRect.Right() ||
+ aPos.Y() < rRect.Top() || aPos.Y() + nHeight > rRect.Bottom() )
+ {
+ rDev.SetClipRegion(vcl::Region(rRect));
+ }
+
+ rDev.DrawText( aPos, aText );
+ }
+
+ if( rDev.IsClipRegion() )
+ rDev.SetClipRegion();
+}
+
+void OTableGrantControl::CellModified()
+{
+ EditBrowseBox::CellModified();
+ SaveModified();
+}
+
+OTableGrantControl::TTablePrivilegeMap::const_iterator OTableGrantControl::findPrivilege(sal_Int32 _nRow) const
+{
+ TTablePrivilegeMap::const_iterator aFind = m_aPrivMap.find(m_aTableNames[_nRow]);
+ if(aFind == m_aPrivMap.end())
+ {
+ fillPrivilege(_nRow);
+ aFind = m_aPrivMap.find(m_aTableNames[_nRow]);
+ }
+ return aFind;
+}
+
+Reference< XAccessible > OTableGrantControl::CreateAccessibleCell( sal_Int32 _nRow, sal_uInt16 _nColumnPos )
+{
+ sal_uInt16 nColumnId = GetColumnId( _nColumnPos );
+ if(nColumnId != COL_TABLE_NAME)
+ {
+ TriState eState = TRISTATE_FALSE;
+ TTablePrivilegeMap::const_iterator aFind = findPrivilege(_nRow);
+ if(aFind != m_aPrivMap.end())
+ {
+ eState = isAllowed(nColumnId,aFind->second.nRights) ? TRISTATE_TRUE : TRISTATE_FALSE;
+ }
+ else
+ eState = TRISTATE_FALSE;
+
+ return EditBrowseBox::CreateAccessibleCheckBoxCell( _nRow, _nColumnPos,eState );
+ }
+ return EditBrowseBox::CreateAccessibleCell( _nRow, _nColumnPos );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/control/charsetlistbox.cxx b/dbaccess/source/ui/control/charsetlistbox.cxx
new file mode 100644
index 000000000..8915b65c9
--- /dev/null
+++ b/dbaccess/source/ui/control/charsetlistbox.cxx
@@ -0,0 +1,69 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <charsetlistbox.hxx>
+
+#include <svl/itemset.hxx>
+#include <svl/stritem.hxx>
+#include <osl/diagnose.h>
+
+namespace dbaui
+{
+ CharSetListBox::CharSetListBox(std::unique_ptr<weld::ComboBox> xControl)
+ : m_xControl(std::move(xControl))
+ {
+ for (auto const& charset : m_aCharSets)
+ {
+ m_xControl->append_text(charset.getDisplayName());
+ }
+ }
+
+ void CharSetListBox::SelectEntryByIanaName( const OUString& _rIanaName )
+ {
+ OCharsetDisplay::const_iterator aFind = m_aCharSets.findIanaName( _rIanaName );
+ if (aFind == m_aCharSets.end())
+ {
+ OSL_FAIL( "CharSetListBox::SelectEntryByIanaName: unknown charset falling back to system language!" );
+ aFind = m_aCharSets.findEncoding( RTL_TEXTENCODING_DONTKNOW );
+ }
+
+ if (aFind == m_aCharSets.end())
+ m_xControl->set_active(-1);
+ else
+ m_xControl->set_active_text((*aFind).getDisplayName());
+ }
+
+ bool CharSetListBox::StoreSelectedCharSet( SfxItemSet& _rSet, const sal_uInt16 _nItemId )
+ {
+ bool bChangedSomething = false;
+ if (m_xControl->get_value_changed_from_saved())
+ {
+ OCharsetDisplay::const_iterator aFind = m_aCharSets.findDisplayName(m_xControl->get_active_text());
+ OSL_ENSURE( aFind != m_aCharSets.end(), "CharSetListBox::StoreSelectedCharSet: could not translate the selected character set!" );
+ if ( aFind != m_aCharSets.end() )
+ {
+ _rSet.Put( SfxStringItem( _nItemId, (*aFind).getIanaName() ) );
+ bChangedSomething = true;
+ }
+ }
+ return bChangedSomething;
+ }
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/control/curledit.cxx b/dbaccess/source/ui/control/curledit.cxx
new file mode 100644
index 000000000..9cccde370
--- /dev/null
+++ b/dbaccess/source/ui/control/curledit.cxx
@@ -0,0 +1,89 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <curledit.hxx>
+
+namespace dbaui
+{
+
+OConnectionURLEdit::OConnectionURLEdit(std::unique_ptr<weld::Entry> xEntry, std::unique_ptr<weld::Label> xForcedPrefix)
+ : m_pTypeCollection(nullptr)
+ , m_bShowPrefix(false)
+ , m_xEntry(std::move(xEntry))
+ , m_xForcedPrefix(std::move(xForcedPrefix))
+{
+}
+
+OConnectionURLEdit::~OConnectionURLEdit()
+{
+}
+
+void OConnectionURLEdit::SetTextNoPrefix(const OUString& _rText)
+{
+ m_xEntry->set_text(_rText);
+}
+
+OUString OConnectionURLEdit::GetTextNoPrefix() const
+{
+ return m_xEntry->get_text();
+}
+
+void OConnectionURLEdit::SetText(const OUString& _rStr)
+{
+ Selection aNoSelection(0,0);
+ SetText(_rStr, aNoSelection);
+}
+
+void OConnectionURLEdit::SetText(const OUString& _rStr, const Selection& /*_rNewSelection*/)
+{
+ m_xForcedPrefix->set_visible(m_bShowPrefix);
+
+ bool bIsEmpty = _rStr.isEmpty();
+ // calc the prefix
+ OUString sPrefix;
+ if (!bIsEmpty)
+ {
+ // determine the type of the new URL described by the new text
+ sPrefix = m_pTypeCollection->getPrefix(_rStr);
+ }
+
+ // the fixed text gets the prefix
+ m_xForcedPrefix->set_label(sPrefix);
+
+ // do the real SetText
+ OUString sNewText( _rStr );
+ if ( !bIsEmpty )
+ sNewText = m_pTypeCollection->cutPrefix( _rStr );
+ m_xEntry->set_text(sNewText);
+}
+
+OUString OConnectionURLEdit::GetText() const
+{
+ return m_xForcedPrefix->strip_mnemonic(m_xForcedPrefix->get_label()) + m_xEntry->get_text();
+}
+
+void OConnectionURLEdit::ShowPrefix(bool _bShowPrefix)
+{
+ m_bShowPrefix = _bShowPrefix;
+ m_xForcedPrefix->set_visible(m_bShowPrefix);
+}
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/control/dbtreelistbox.cxx b/dbaccess/source/ui/control/dbtreelistbox.cxx
new file mode 100644
index 000000000..eb89e1fdb
--- /dev/null
+++ b/dbaccess/source/ui/control/dbtreelistbox.cxx
@@ -0,0 +1,512 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <dbtreelistbox.hxx>
+#include <dbexchange.hxx>
+#include <callbacks.hxx>
+
+#include <com/sun/star/awt/PopupMenuDirection.hpp>
+#include <com/sun/star/ui/XContextMenuInterceptor.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <com/sun/star/frame/XController.hpp>
+#include <com/sun/star/frame/XPopupMenuController.hpp>
+#include <com/sun/star/lang/IllegalArgumentException.hpp>
+#include <cppuhelper/implbase.hxx>
+#include <comphelper/interfacecontainer2.hxx>
+#include <comphelper/processfactory.hxx>
+#include <comphelper/propertyvalue.hxx>
+#include <dbaccess/IController.hxx>
+#include <framework/actiontriggerhelper.hxx>
+#include <toolkit/awt/vclxmenu.hxx>
+#include <toolkit/helper/vclunohelper.hxx>
+#include <svx/dbaobjectex.hxx>
+#include <vcl/commandevent.hxx>
+#include <vcl/event.hxx>
+#include <vcl/svapp.hxx>
+
+#include <memory>
+
+namespace dbaui
+{
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::datatransfer;
+using namespace ::com::sun::star::ui;
+using namespace ::com::sun::star::view;
+
+InterimDBTreeListBox::InterimDBTreeListBox(vcl::Window* pParent)
+ : InterimItemWindow(pParent, "dbaccess/ui/dbtreelist.ui", "DBTreeList")
+ , TreeListBox(m_xBuilder->weld_tree_view("treeview"), true)
+ , m_xStatusBar(m_xBuilder->weld_label("statusbar"))
+{
+ InitControlBase(&GetWidget());
+}
+
+InterimDBTreeListBox::~InterimDBTreeListBox()
+{
+ disposeOnce();
+}
+
+void InterimDBTreeListBox::dispose()
+{
+ implStopSelectionTimer();
+ m_xStatusBar.reset();
+ m_xTreeView.reset();
+ InterimItemWindow::dispose();
+}
+
+bool InterimDBTreeListBox::DoChildKeyInput(const KeyEvent& rKEvt)
+{
+ return ChildKeyInput(rKEvt);
+}
+
+TreeListBoxDropTarget::TreeListBoxDropTarget(TreeListBox& rTreeView)
+ : DropTargetHelper(rTreeView.GetWidget().get_drop_target())
+ , m_rTreeView(rTreeView)
+{
+}
+
+sal_Int8 TreeListBoxDropTarget::AcceptDrop(const AcceptDropEvent& rEvt)
+{
+ sal_Int8 nAccept = m_rTreeView.AcceptDrop(rEvt);
+
+ if (nAccept != DND_ACTION_NONE)
+ {
+ // to enable the autoscroll when we're close to the edges
+ weld::TreeView& rWidget = m_rTreeView.GetWidget();
+ rWidget.get_dest_row_at_pos(rEvt.maPosPixel, nullptr, true);
+ }
+
+ return nAccept;
+}
+
+sal_Int8 TreeListBoxDropTarget::ExecuteDrop(const ExecuteDropEvent& rEvt)
+{
+ return m_rTreeView.ExecuteDrop(rEvt);
+}
+
+TreeListBox::TreeListBox(std::unique_ptr<weld::TreeView> xTreeView, bool bSQLType)
+ : m_xTreeView(std::move(xTreeView))
+ , m_aDropTargetHelper(*this)
+ , m_pActionListener(nullptr)
+ , m_pContextMenuProvider(nullptr)
+ , m_aTimer("dbaccess TreeListBox m_aTimer")
+{
+ m_xTreeView->connect_key_press(LINK(this, TreeListBox, KeyInputHdl));
+ m_xTreeView->connect_changed(LINK(this, TreeListBox, SelectHdl));
+ m_xTreeView->connect_query_tooltip(LINK(this, TreeListBox, QueryTooltipHdl));
+ m_xTreeView->connect_popup_menu(LINK(this, TreeListBox, CommandHdl));
+
+ if (bSQLType)
+ m_xHelper.set(new ODataClipboard);
+ else
+ m_xHelper.set(new svx::OComponentTransferable);
+ m_xTreeView->enable_drag_source(m_xHelper, DND_ACTION_COPY);
+ m_xTreeView->connect_drag_begin(LINK(this, TreeListBox, DragBeginHdl));
+
+ m_aTimer.SetTimeout(900);
+ m_aTimer.SetInvokeHandler(LINK(this, TreeListBox, OnTimeOut));
+}
+
+bool TreeListBox::DoChildKeyInput(const KeyEvent& /*rKEvt*/)
+{
+ // nothing by default
+ return false;
+}
+
+IMPL_LINK(TreeListBox, KeyInputHdl, const KeyEvent&, rKEvt, bool)
+{
+ KeyFuncType eFunc = rKEvt.GetKeyCode().GetFunction();
+ bool bHandled = false;
+
+ switch (eFunc)
+ {
+ case KeyFuncType::COPY:
+ bHandled = m_aCopyHandler.IsSet() && !m_xTreeView->get_selected(nullptr);
+ if (bHandled)
+ m_aCopyHandler.Call(nullptr);
+ break;
+ case KeyFuncType::PASTE:
+ bHandled = m_aPasteHandler.IsSet() && !m_xTreeView->get_selected(nullptr);
+ if (bHandled)
+ m_aPasteHandler.Call(nullptr);
+ break;
+ case KeyFuncType::DELETE:
+ bHandled = m_aDeleteHandler.IsSet() && !m_xTreeView->get_selected(nullptr);
+ if (bHandled)
+ m_aDeleteHandler.Call(nullptr);
+ break;
+ default:
+ break;
+ }
+
+ return bHandled || DoChildKeyInput(rKEvt);
+}
+
+void TreeListBox::implStopSelectionTimer()
+{
+ if ( m_aTimer.IsActive() )
+ m_aTimer.Stop();
+}
+
+void TreeListBox::implStartSelectionTimer()
+{
+ implStopSelectionTimer();
+ m_aTimer.Start();
+}
+
+IMPL_LINK_NOARG(TreeListBox, SelectHdl, weld::TreeView&, void)
+{
+ implStartSelectionTimer();
+}
+
+TreeListBox::~TreeListBox()
+{
+}
+
+std::unique_ptr<weld::TreeIter> TreeListBox::GetEntryPosByName(std::u16string_view aName, const weld::TreeIter* pStart, const IEntryFilter* _pFilter) const
+{
+ auto xEntry(m_xTreeView->make_iterator(pStart));
+ if (pStart)
+ {
+ if (!m_xTreeView->iter_children(*xEntry))
+ return nullptr;
+ }
+ else
+ {
+ if (!m_xTreeView->get_iter_first(*xEntry))
+ return nullptr;
+ }
+
+ do
+ {
+ if (m_xTreeView->get_text(*xEntry) == aName)
+ {
+ if (!_pFilter || _pFilter->includeEntry(weld::fromId<void*>(m_xTreeView->get_id(*xEntry))))
+ {
+ // found
+ return xEntry;
+ }
+ }
+ } while (m_xTreeView->iter_next_sibling(*xEntry));
+
+ return nullptr;
+}
+
+IMPL_LINK(TreeListBox, DragBeginHdl, bool&, rUnsetDragIcon, bool)
+{
+ rUnsetDragIcon = false;
+
+ if (m_pActionListener)
+ {
+ m_xDragedEntry = m_xTreeView->make_iterator();
+ if (!m_xTreeView->get_selected(m_xDragedEntry.get()))
+ m_xDragedEntry.reset();
+ if (m_xDragedEntry && m_pActionListener->requestDrag(*m_xDragedEntry))
+ {
+ // if the (asynchronous) drag started, stop the selection timer
+ implStopSelectionTimer();
+ return false;
+ }
+ }
+
+ return true;
+}
+
+sal_Int8 TreeListBox::AcceptDrop(const AcceptDropEvent& rEvt)
+{
+ sal_Int8 nDropOption = DND_ACTION_NONE;
+ if ( m_pActionListener )
+ {
+ ::Point aDropPos = rEvt.maPosPixel;
+ std::unique_ptr<weld::TreeIter> xDropTarget(m_xTreeView->make_iterator());
+ if (!m_xTreeView->get_dest_row_at_pos(aDropPos, xDropTarget.get(), true))
+ xDropTarget.reset();
+
+ // check if drag is on child entry, which is not allowed
+ std::unique_ptr<weld::TreeIter> xParent;
+ if (rEvt.mnAction & DND_ACTION_MOVE)
+ {
+ if (!m_xDragedEntry) // no entry to move
+ return m_pActionListener->queryDrop(rEvt, m_aDropTargetHelper.GetDataFlavorExVector());
+
+ if (xDropTarget)
+ {
+ xParent = m_xTreeView->make_iterator(xDropTarget.get());
+ if (!m_xTreeView->iter_parent(*xParent))
+ xParent.reset();
+ }
+ while (xParent && m_xTreeView->iter_compare(*xParent, *m_xDragedEntry) != 0)
+ {
+ if (!m_xTreeView->iter_parent(*xParent))
+ xParent.reset();
+ }
+ }
+
+ if (!xParent)
+ {
+ nDropOption = m_pActionListener->queryDrop(rEvt, m_aDropTargetHelper.GetDataFlavorExVector());
+ // check if move is allowed
+ if ( nDropOption & DND_ACTION_MOVE )
+ {
+ if (!m_xDragedEntry || !xDropTarget ||
+ m_xTreeView->iter_compare(*m_xDragedEntry, *xDropTarget) == 0 ||
+ GetEntryPosByName(m_xTreeView->get_text(*m_xDragedEntry), xDropTarget.get()))
+ {
+ nDropOption = nDropOption & ~DND_ACTION_MOVE;//DND_ACTION_NONE;
+ }
+ }
+ }
+ }
+
+ return nDropOption;
+}
+
+sal_Int8 TreeListBox::ExecuteDrop(const ExecuteDropEvent& rEvt)
+{
+ if (m_pActionListener)
+ m_pActionListener->executeDrop(rEvt);
+ m_xTreeView->unset_drag_dest_row();
+ return DND_ACTION_NONE;
+}
+
+IMPL_LINK(TreeListBox, QueryTooltipHdl, const weld::TreeIter&, rIter, OUString)
+{
+ OUString sQuickHelpText;
+ if (m_pActionListener &&
+ m_pActionListener->requestQuickHelp(weld::fromId<void*>(m_xTreeView->get_id(rIter)), sQuickHelpText))
+ {
+ return sQuickHelpText;
+ }
+ return m_xTreeView->get_tooltip_text();
+}
+
+namespace
+{
+ // SelectionSupplier
+ typedef ::cppu::WeakImplHelper< XSelectionSupplier
+ > SelectionSupplier_Base;
+ class SelectionSupplier : public SelectionSupplier_Base
+ {
+ public:
+ explicit SelectionSupplier( const Any& _rSelection )
+ :m_aSelection( _rSelection )
+ {
+ }
+
+ virtual sal_Bool SAL_CALL select( const Any& xSelection ) override;
+ virtual Any SAL_CALL getSelection( ) override;
+ virtual void SAL_CALL addSelectionChangeListener( const Reference< XSelectionChangeListener >& xListener ) override;
+ virtual void SAL_CALL removeSelectionChangeListener( const Reference< XSelectionChangeListener >& xListener ) override;
+
+ protected:
+ virtual ~SelectionSupplier() override
+ {
+ }
+
+ private:
+ Any m_aSelection;
+ };
+
+ sal_Bool SAL_CALL SelectionSupplier::select( const Any& /*_Selection*/ )
+ {
+ throw IllegalArgumentException();
+ // API bug: this should be a NoSupportException
+ }
+
+ Any SAL_CALL SelectionSupplier::getSelection( )
+ {
+ return m_aSelection;
+ }
+
+ void SAL_CALL SelectionSupplier::addSelectionChangeListener( const Reference< XSelectionChangeListener >& /*_Listener*/ )
+ {
+ OSL_FAIL( "SelectionSupplier::removeSelectionChangeListener: no support!" );
+ // API bug: this should be a NoSupportException
+ }
+
+ void SAL_CALL SelectionSupplier::removeSelectionChangeListener( const Reference< XSelectionChangeListener >& /*_Listener*/ )
+ {
+ OSL_FAIL( "SelectionSupplier::removeSelectionChangeListener: no support!" );
+ // API bug: this should be a NoSupportException
+ }
+}
+
+IMPL_LINK(TreeListBox, CommandHdl, const CommandEvent&, rCEvt, bool)
+{
+ if (rCEvt.GetCommand() != CommandEventId::ContextMenu)
+ return false;
+
+ ::Point aPos = rCEvt.GetMousePosPixel();
+
+ std::unique_ptr<weld::TreeIter> xIter(m_xTreeView->make_iterator());
+ if (m_xTreeView->get_dest_row_at_pos(aPos, xIter.get(), false) && !m_xTreeView->is_selected(*xIter))
+ {
+ m_xTreeView->unselect_all();
+ m_xTreeView->set_cursor(*xIter);
+ m_xTreeView->select(*xIter);
+ SelectHdl(*m_xTreeView);
+ }
+
+ if (!m_pContextMenuProvider)
+ return false;
+
+ OUString aResourceName(m_pContextMenuProvider->getContextMenuResourceName());
+ if (aResourceName.isEmpty())
+ return false;
+
+ css::uno::Sequence< css::uno::Any > aArgs{
+ css::uno::Any(comphelper::makePropertyValue( "Value", aResourceName )),
+ css::uno::Any(comphelper::makePropertyValue( "Frame", m_pContextMenuProvider->getCommandController().getXController()->getFrame() )),
+ css::uno::Any(comphelper::makePropertyValue( "IsContextMenu", true ))
+ };
+
+ css::uno::Reference< css::uno::XComponentContext > xContext = comphelper::getProcessComponentContext();
+ css::uno::Reference<css::frame::XPopupMenuController> xMenuController
+ (xContext->getServiceManager()->createInstanceWithArgumentsAndContext(
+ "com.sun.star.comp.framework.ResourceMenuController", aArgs, xContext), css::uno::UNO_QUERY);
+
+ if (!xMenuController.is())
+ return false;
+
+ VclPtr<vcl::Window> xMenuParent = m_pContextMenuProvider->getMenuParent();
+
+ css::uno::Reference< css::awt::XWindow> xSourceWindow = VCLUnoHelper::GetInterface(xMenuParent);
+
+ rtl::Reference xPopupMenu( new VCLXPopupMenu );
+ xMenuController->setPopupMenu( xPopupMenu );
+
+ // allow context menu interception
+ ::comphelper::OInterfaceContainerHelper2* pInterceptors = m_pContextMenuProvider->getContextMenuInterceptors();
+ if (pInterceptors && pInterceptors->getLength())
+ {
+ OUString aMenuIdentifier( "private:resource/popupmenu/" + aResourceName );
+
+ ContextMenuExecuteEvent aEvent;
+ aEvent.SourceWindow = xSourceWindow;
+ aEvent.ExecutePosition.X = -1;
+ aEvent.ExecutePosition.Y = -1;
+ aEvent.ActionTriggerContainer = ::framework::ActionTriggerHelper::CreateActionTriggerContainerFromMenu(
+ xPopupMenu, &aMenuIdentifier );
+ aEvent.Selection = new SelectionSupplier(m_pContextMenuProvider->getCurrentSelection(*m_xTreeView));
+
+ ::comphelper::OInterfaceIteratorHelper2 aIter( *pInterceptors );
+ bool bModifiedMenu = false;
+ bool bAskInterceptors = true;
+ while ( aIter.hasMoreElements() && bAskInterceptors )
+ {
+ Reference< XContextMenuInterceptor > xInterceptor( aIter.next(), UNO_QUERY );
+ if ( !xInterceptor.is() )
+ continue;
+
+ try
+ {
+ ContextMenuInterceptorAction eAction = xInterceptor->notifyContextMenuExecute( aEvent );
+ switch ( eAction )
+ {
+ case ContextMenuInterceptorAction_CANCELLED:
+ return false;
+
+ case ContextMenuInterceptorAction_EXECUTE_MODIFIED:
+ bModifiedMenu = true;
+ bAskInterceptors = false;
+ break;
+
+ case ContextMenuInterceptorAction_CONTINUE_MODIFIED:
+ bModifiedMenu = true;
+ bAskInterceptors = true;
+ break;
+
+ default:
+ OSL_FAIL( "DBTreeListBox::CreateContextMenu: unexpected return value of the interceptor call!" );
+ [[fallthrough]];
+ case ContextMenuInterceptorAction_IGNORED:
+ break;
+ }
+ }
+ catch( const DisposedException& e )
+ {
+ if ( e.Context == xInterceptor )
+ aIter.remove();
+ }
+ }
+
+ if ( bModifiedMenu )
+ {
+ xPopupMenu->clear();
+ ::framework::ActionTriggerHelper::CreateMenuFromActionTriggerContainer(
+ xPopupMenu, aEvent.ActionTriggerContainer );
+ aEvent.ActionTriggerContainer.clear();
+ }
+ }
+
+ // adjust pos relative to m_xTreeView to relative to xMenuParent
+ m_pContextMenuProvider->adjustMenuPosition(*m_xTreeView, aPos);
+
+ // do action for selected entry in popup menu
+ css::uno::Reference<css::awt::XWindowPeer> xParent(xSourceWindow, css::uno::UNO_QUERY);
+ xPopupMenu->execute(xParent, css::awt::Rectangle(aPos.X(), aPos.Y(), 1, 1), css::awt::PopupMenuDirection::EXECUTE_DOWN);
+
+ css::uno::Reference<css::lang::XComponent> xComponent(xMenuController, css::uno::UNO_QUERY);
+ if (xComponent.is())
+ xComponent->dispose();
+ xMenuController.clear();
+
+ return true;
+}
+
+IMPL_LINK_NOARG(TreeListBox, OnTimeOut, Timer*, void)
+{
+ implStopSelectionTimer();
+
+ m_aSelChangeHdl.Call( nullptr );
+}
+
+std::unique_ptr<weld::TreeIter> TreeListBox::GetRootLevelParent(const weld::TreeIter* pEntry) const
+{
+ if (!pEntry)
+ return nullptr;
+ std::unique_ptr<weld::TreeIter> xEntry(m_xTreeView->make_iterator(pEntry));
+ while (m_xTreeView->get_iter_depth(*xEntry))
+ m_xTreeView->iter_parent(*xEntry);
+ return xEntry;
+}
+
+DBTreeViewBase::DBTreeViewBase(weld::Container* pContainer)
+ : m_xBuilder(Application::CreateBuilder(pContainer, "dbaccess/ui/dbtreelist.ui"))
+ , m_xContainer(m_xBuilder->weld_container("DBTreeList"))
+{
+}
+
+DBTreeViewBase::~DBTreeViewBase()
+{
+}
+
+DBTreeView::DBTreeView(weld::Container* pContainer, bool bSQLType)
+ : DBTreeViewBase(pContainer)
+{
+ m_xTreeListBox.reset(new TreeListBox(m_xBuilder->weld_tree_view("treeview"), bSQLType));
+}
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/control/opendoccontrols.cxx b/dbaccess/source/ui/control/opendoccontrols.cxx
new file mode 100644
index 000000000..2fb86bdca
--- /dev/null
+++ b/dbaccess/source/ui/control/opendoccontrols.cxx
@@ -0,0 +1,194 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <opendoccontrols.hxx>
+
+#include <com/sun/star/uno/Sequence.hxx>
+#include <com/sun/star/beans/PropertyValue.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/container/XNameAccess.hpp>
+#include <com/sun/star/ui/theModuleUIConfigurationManagerSupplier.hpp>
+#include <com/sun/star/ui/XUIConfigurationManager.hpp>
+#include <com/sun/star/graphic/XGraphic.hpp>
+#include <com/sun/star/ui/XImageManager.hpp>
+
+#include <comphelper/processfactory.hxx>
+#include <vcl/commandinfoprovider.hxx>
+#include <unotools/historyoptions.hxx>
+#include <comphelper/sequenceashashmap.hxx>
+#include <tools/urlobj.hxx>
+#include <osl/diagnose.h>
+
+namespace dbaui
+{
+
+ namespace
+ {
+ using ::com::sun::star::uno::Reference;
+ using ::com::sun::star::uno::Exception;
+ using ::com::sun::star::uno::Sequence;
+ using ::com::sun::star::uno::XComponentContext;
+ using ::com::sun::star::container::XNameAccess;
+ using ::com::sun::star::beans::PropertyValue;
+ using ::com::sun::star::ui::theModuleUIConfigurationManagerSupplier;
+ using ::com::sun::star::ui::XModuleUIConfigurationManagerSupplier;
+ using ::com::sun::star::ui::XUIConfigurationManager;
+ using ::com::sun::star::ui::XImageManager;
+ using ::com::sun::star::graphic::XGraphic;
+
+ Reference< XGraphic> GetCommandIcon( const char* _pCommandURL, const OUString& _rModuleName )
+ {
+ if ( !_pCommandURL || !*_pCommandURL )
+ return nullptr;
+
+ OUString sCommandURL = OUString::createFromAscii( _pCommandURL );
+ try
+ {
+ do
+ {
+ // Retrieve popup menu labels
+ Reference< css::uno::XComponentContext > xContext( ::comphelper::getProcessComponentContext() );
+ if ( !xContext.is() )
+ break;
+
+ Reference< XModuleUIConfigurationManagerSupplier > xSupplier(
+ theModuleUIConfigurationManagerSupplier::get(xContext) );
+
+ Reference< XUIConfigurationManager > xManager( xSupplier->getUIConfigurationManager( _rModuleName ) );
+ Reference< XImageManager > xImageManager;
+ if ( xManager.is() )
+ xImageManager.set(xManager->getImageManager(), css::uno::UNO_QUERY);
+ if ( !xImageManager.is() )
+ break;
+
+ Sequence< OUString > aCommandList( &sCommandURL, 1 );
+ Sequence<Reference< XGraphic> > xIconList( xImageManager->getImages( 0, aCommandList ) );
+ if ( !xIconList.hasElements() )
+ break;
+
+ return xIconList[0];
+ }
+ while ( false );
+ }
+ catch ( Exception& ) {}
+
+ return nullptr;
+ }
+ }
+
+ // OpenButton
+
+ OpenDocumentButton::OpenDocumentButton(std::unique_ptr<weld::Button> xControl, const char* _pAsciiModuleName)
+ : m_xControl(std::move(xControl))
+ {
+ impl_init( _pAsciiModuleName );
+ }
+
+ void OpenDocumentButton::impl_init( const char* _pAsciiModuleName )
+ {
+ OSL_ENSURE( _pAsciiModuleName, "OpenDocumentButton::impl_init: invalid module name!" );
+ m_sModule = OUString::createFromAscii( _pAsciiModuleName );
+
+ // our label should equal the UI text of the "Open" command
+ auto aProperties = vcl::CommandInfoProvider::GetCommandProperties(".uno:Open", m_sModule);
+ OUString sLabel(vcl::CommandInfoProvider::GetLabelForCommand(aProperties));
+ m_xControl->set_label(" " + sLabel.replaceAll("~", ""));
+
+ // Place icon left of text and both centered in the button.
+ m_xControl->set_image(GetCommandIcon(".uno:Open", m_sModule));
+ }
+
+ // OpenDocumentListBox
+
+ OpenDocumentListBox::OpenDocumentListBox(std::unique_ptr<weld::ComboBox> xControl, const char* _pAsciiModuleName )
+ : m_xControl(std::move(xControl))
+ {
+ // we need to limit the max auto width feature of the filter box
+ int nWidth = m_xControl->get_approximate_digit_width() * 50;
+ m_xControl->set_size_request(nWidth, -1);
+
+ impl_init( _pAsciiModuleName );
+ }
+
+ void OpenDocumentListBox::impl_init( const char* _pAsciiModuleName )
+ {
+ OSL_ENSURE( _pAsciiModuleName, "OpenDocumentListBox::impl_init: invalid module name!" );
+
+ std::vector< SvtHistoryOptions::HistoryItem > aHistory = SvtHistoryOptions::GetList( EHistoryType::PickList );
+ Reference< XNameAccess > xFilterFactory;
+ xFilterFactory.set(::comphelper::getProcessServiceFactory()->createInstance(
+ "com.sun.star.document.FilterFactory" ), css::uno::UNO_QUERY);
+
+ for ( const SvtHistoryOptions::HistoryItem& rHistoryItem : aHistory )
+ {
+ try
+ {
+ // Get the current history item's properties.
+ OUString sURL = rHistoryItem.sURL;
+ OUString sFilter = rHistoryItem.sFilter;
+ OUString sTitle = rHistoryItem.sTitle;
+ OUString sPassword = rHistoryItem.sPassword;
+
+ // If the entry is a Base file then insert it into the
+ // history list and the list box.
+ Sequence< PropertyValue > aProps;
+ xFilterFactory->getByName( sFilter ) >>= aProps;
+
+ ::comphelper::SequenceAsHashMap aFilterProperties( aProps );
+ OUString sDocumentService = aFilterProperties.getUnpackedValueOrDefault(
+ "DocumentService", OUString() );
+ if ( sDocumentService.equalsAscii( _pAsciiModuleName ) )
+ {
+ // yes, it's a Base document
+ INetURLObject aURL;
+ aURL.SetSmartURL( sURL );
+ // The password is set only when it is not empty.
+ if ( !sPassword.isEmpty() )
+ aURL.SetPass( sPassword );
+
+ if ( sTitle.isEmpty() )
+ sTitle = aURL.getBase( INetURLObject::LAST_SEGMENT, true, INetURLObject::DecodeMechanism::Unambiguous );
+
+ OUString sDecodedURL = aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE );
+
+ m_xControl->append_text(sTitle);
+ m_aURLs.emplace_back(sDecodedURL, sFilter);
+ }
+ }
+ catch( Exception& ) {}
+ }
+ }
+
+ OUString OpenDocumentListBox::GetSelectedDocumentURL() const
+ {
+ OUString sURL;
+ sal_Int32 nSelected = m_xControl->get_active();
+ if (nSelected != -1)
+ sURL = impl_getDocumentAtIndex( nSelected ).first;
+ return sURL;
+ }
+
+ const OpenDocumentListBox::StringPair & OpenDocumentListBox::impl_getDocumentAtIndex( sal_uInt16 _nListIndex ) const
+ {
+ return m_aURLs[_nListIndex];
+ }
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/control/sqledit.cxx b/dbaccess/source/ui/control/sqledit.cxx
new file mode 100644
index 000000000..49758289e
--- /dev/null
+++ b/dbaccess/source/ui/control/sqledit.cxx
@@ -0,0 +1,515 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+
+#include <cassert>
+
+#include <com/sun/star/beans/XMultiPropertySet.hpp>
+#include <com/sun/star/beans/XPropertiesChangeListener.hpp>
+#include <com/sun/star/container/XHierarchicalNameAccess.hpp>
+#include <officecfg/Office/Common.hxx>
+#include <editeng/eeitem.hxx>
+#include <editeng/colritem.hxx>
+#include <editeng/fhgtitem.hxx>
+#include <editeng/fontitem.hxx>
+#include <editeng/wghtitem.hxx>
+#include <sqledit.hxx>
+#include <cppuhelper/implbase.hxx>
+#include <i18nlangtag/languagetag.hxx>
+#include <svl/itempool.hxx>
+#include <svl/itemset.hxx>
+#include <vcl/commandevent.hxx>
+#include <vcl/event.hxx>
+#include <vcl/settings.hxx>
+#include <vcl/specialchars.hxx>
+#include <vcl/svapp.hxx>
+
+using namespace dbaui;
+
+class SQLEditView::ChangesListener:
+ public cppu::WeakImplHelper< css::beans::XPropertiesChangeListener >
+{
+public:
+ explicit ChangesListener(SQLEditView& editor): editor_(editor) {}
+
+private:
+ virtual ~ChangesListener() override {}
+
+ virtual void SAL_CALL disposing(css::lang::EventObject const &) override
+ {
+ osl::MutexGuard g(editor_.m_mutex);
+ editor_.m_notifier.clear();
+ }
+
+ virtual void SAL_CALL propertiesChange(
+ css::uno::Sequence< css::beans::PropertyChangeEvent > const &) override
+ {
+ SolarMutexGuard g;
+ editor_.ImplSetFont();
+ }
+
+ SQLEditView& editor_;
+};
+
+SQLEditView::SQLEditView(std::unique_ptr<weld::ScrolledWindow> xScrolledWindow)
+ : m_xScrolledWindow(std::move(xScrolledWindow))
+ , m_aUpdateDataTimer("dbaccess SQLEditView m_aUpdateDataTimer")
+ , m_aHighlighter(HighlighterLanguage::SQL)
+ , m_bInUpdate(false)
+ , m_bDisableInternalUndo(false)
+{
+ m_xScrolledWindow->connect_vadjustment_changed(LINK(this, SQLEditView, ScrollHdl));
+}
+
+void SQLEditView::DisableInternalUndo()
+{
+ GetEditEngine()->EnableUndo(false);
+ m_bDisableInternalUndo = true;
+}
+
+void SQLEditView::SetItemPoolFont(SfxItemPool* pItemPool)
+{
+ OUString sFontName(officecfg::Office::Common::Font::SourceViewFont::FontName::get().value_or(OUString()));
+ if (sFontName.isEmpty())
+ {
+ vcl::Font aTmpFont(OutputDevice::GetDefaultFont(DefaultFontType::FIXED, Application::GetSettings().GetUILanguageTag().getLanguageType(), GetDefaultFontFlags::OnlyOne));
+ sFontName = aTmpFont.GetFamilyName();
+ }
+
+ Size aFontSize(0, officecfg::Office::Common::Font::SourceViewFont::FontHeight::get());
+ vcl::Font aAppFont(sFontName, aFontSize);
+
+ pItemPool->SetPoolDefaultItem(SvxFontItem(aAppFont.GetFamilyType(), aAppFont.GetFamilyName(),
+ "", PITCH_DONTKNOW, RTL_TEXTENCODING_DONTKNOW,
+ EE_CHAR_FONTINFO));
+ pItemPool->SetPoolDefaultItem(SvxFontItem(aAppFont.GetFamilyType(), aAppFont.GetFamilyName(),
+ "", PITCH_DONTKNOW, RTL_TEXTENCODING_DONTKNOW,
+ EE_CHAR_FONTINFO_CJK));
+ pItemPool->SetPoolDefaultItem(SvxFontItem(aAppFont.GetFamilyType(), aAppFont.GetFamilyName(),
+ "", PITCH_DONTKNOW, RTL_TEXTENCODING_DONTKNOW,
+ EE_CHAR_FONTINFO_CTL));
+
+ pItemPool->SetPoolDefaultItem(
+ SvxFontHeightItem(aAppFont.GetFontHeight() * 20, 100, EE_CHAR_FONTHEIGHT));
+ pItemPool->SetPoolDefaultItem(
+ SvxFontHeightItem(aAppFont.GetFontHeight() * 20, 100, EE_CHAR_FONTHEIGHT_CJK));
+ pItemPool->SetPoolDefaultItem(
+ SvxFontHeightItem(aAppFont.GetFontHeight() * 20, 100, EE_CHAR_FONTHEIGHT_CTL));
+}
+
+void SQLEditView::makeEditEngine()
+{
+ assert(!m_pItemPool);
+ m_pItemPool = EditEngine::CreatePool();
+ SetItemPoolFont(m_pItemPool.get());
+ m_xEditEngine.reset(new EditEngine(m_pItemPool.get()));
+}
+
+void SQLEditView::SetDrawingArea(weld::DrawingArea* pDrawingArea)
+{
+ WeldEditView::SetDrawingArea(pDrawingArea);
+
+ EditEngine& rEditEngine = *GetEditEngine();
+
+ rEditEngine.SetDefaultHorizontalTextDirection(EEHorizontalTextDirection::L2R);
+ rEditEngine.SetModifyHdl(LINK(this, SQLEditView, ModifyHdl));
+ rEditEngine.SetStatusEventHdl(LINK(this, SQLEditView, EditStatusHdl));
+
+ m_aUpdateDataTimer.SetTimeout(150);
+ m_aUpdateDataTimer.SetInvokeHandler(LINK(this, SQLEditView, ImplUpdateDataHdl));
+
+ ImplSetFont();
+
+ // Listen for change of Font and Color Settings:
+ // Using "this" in ctor is a little fishy, but should work here at least as
+ // long as there are no derivations:
+ m_listener = new ChangesListener(*this);
+ css::uno::Reference< css::beans::XMultiPropertySet > n(
+ officecfg::Office::Common::Font::SourceViewFont::get(),
+ css::uno::UNO_QUERY_THROW);
+ {
+ osl::MutexGuard g(m_mutex);
+ m_notifier = n;
+ }
+ css::uno::Sequence< OUString > s { "FontHeight", "FontName" };
+ n->addPropertiesChangeListener(s, m_listener);
+ m_ColorConfig.AddListener(this);
+}
+
+SQLEditView::~SQLEditView()
+{
+ css::uno::Reference< css::beans::XMultiPropertySet > n;
+ {
+ osl::MutexGuard g(m_mutex);
+ n = m_notifier;
+ }
+ if (n.is()) {
+ n->removePropertiesChangeListener(m_listener);
+ }
+ m_ColorConfig.RemoveListener(this);
+}
+
+void SQLEditView::SetTextAndUpdate(const OUString& rNewText)
+{
+ SetText(rNewText);
+ UpdateData();
+}
+
+IMPL_LINK_NOARG(SQLEditView, ModifyHdl, LinkParamNone*, void)
+{
+ if (m_bInUpdate)
+ return;
+ m_aUpdateDataTimer.Start();
+}
+
+IMPL_LINK_NOARG(SQLEditView, ImplUpdateDataHdl, Timer*, void)
+{
+ UpdateData();
+}
+
+Color SQLEditView::GetColorValue(TokenType aToken)
+{
+ return GetSyntaxHighlightColor(m_aColorConfig, m_aHighlighter.GetLanguage(), aToken);
+}
+
+void SQLEditView::UpdateData()
+{
+ m_bInUpdate = true;
+ EditEngine& rEditEngine = *GetEditEngine();
+
+ bool bModified = rEditEngine.IsModified();
+ bool bUndoEnabled = rEditEngine.IsUndoEnabled();
+ rEditEngine.EnableUndo(false);
+
+ // syntax highlighting
+ for (sal_Int32 nLine=0; nLine < rEditEngine.GetParagraphCount(); ++nLine)
+ {
+ OUString aLine( rEditEngine.GetText( nLine ) );
+
+ ESelection aAllLine(nLine, 0, nLine, EE_TEXTPOS_ALL);
+ rEditEngine.RemoveAttribs(aAllLine, false, EE_CHAR_COLOR);
+ rEditEngine.RemoveAttribs(aAllLine, false, EE_CHAR_WEIGHT);
+ rEditEngine.RemoveAttribs(aAllLine, false, EE_CHAR_WEIGHT_CJK);
+ rEditEngine.RemoveAttribs(aAllLine, false, EE_CHAR_WEIGHT_CTL);
+
+ std::vector<HighlightPortion> aPortions;
+ m_aHighlighter.getHighlightPortions( aLine, aPortions );
+ for (auto const& portion : aPortions)
+ {
+ SfxItemSet aSet(rEditEngine.GetEmptyItemSet());
+ aSet.Put(SvxColorItem(GetColorValue(portion.tokenType), EE_CHAR_COLOR));
+ rEditEngine.QuickSetAttribs(aSet, ESelection(nLine, portion.nBegin, nLine, portion.nEnd));
+ }
+ }
+
+ rEditEngine.ClearModifyFlag();
+
+ m_bInUpdate = false;
+
+ rEditEngine.EnableUndo(bUndoEnabled);
+
+ if (bModified)
+ m_aModifyLink.Call(nullptr);
+
+ Invalidate();
+}
+
+void SQLEditView::DoBracketHilight(sal_uInt16 nKey)
+{
+ ESelection aCurrentPos = m_xEditView->GetSelection();
+ sal_Int32 nStartPos = aCurrentPos.nStartPos;
+ const sal_uInt32 nStartPara = aCurrentPos.nStartPara;
+ sal_uInt16 nCount = 0;
+ int nChar = -1;
+
+ switch (nKey)
+ {
+ case '\'': // no break
+ case '"':
+ {
+ nChar = nKey;
+ break;
+ }
+ case '}' :
+ {
+ nChar = '{';
+ break;
+ }
+ case ')':
+ {
+ nChar = '(';
+ break;
+ }
+ case ']':
+ {
+ nChar = '[';
+ break;
+ }
+ }
+
+ if (nChar == -1)
+ return;
+
+ bool bUndoEnabled = m_xEditEngine->IsUndoEnabled();
+ m_xEditEngine->EnableUndo(false);
+
+ sal_uInt32 nPara = nStartPara;
+ do
+ {
+ if (nPara == nStartPara && nStartPos == 0)
+ continue;
+
+ OUString aLine( m_xEditEngine->GetText( nPara ) );
+
+ if (aLine.isEmpty())
+ continue;
+
+ for (sal_Int32 i = (nPara==nStartPara) ? nStartPos-1 : aLine.getLength()-1; i>0; --i)
+ {
+ if (aLine[i] == nChar)
+ {
+ if (!nCount)
+ {
+ SfxItemSet aSet(m_xEditEngine->GetEmptyItemSet());
+ aSet.Put(SvxColorItem(Color(0,0,0), EE_CHAR_COLOR));
+ aSet.Put(SvxWeightItem(WEIGHT_ULTRABOLD, EE_CHAR_WEIGHT));
+ aSet.Put(SvxWeightItem(WEIGHT_ULTRABOLD, EE_CHAR_WEIGHT_CJK));
+ aSet.Put(SvxWeightItem(WEIGHT_ULTRABOLD, EE_CHAR_WEIGHT_CTL));
+
+ m_xEditEngine->QuickSetAttribs(aSet, ESelection(nPara, i, nPara, i + 1));
+ m_xEditEngine->QuickSetAttribs(aSet, ESelection(nStartPara, nStartPos, nStartPara, nStartPos));
+ return;
+ }
+ else
+ --nCount;
+ }
+ if (aLine[i] == nKey)
+ ++nCount;
+ }
+ } while (nPara--);
+
+ m_xEditEngine->EnableUndo(bUndoEnabled);
+}
+
+Color SQLEditView::GetSyntaxHighlightColor(const svtools::ColorConfig& rColorConfig, HighlighterLanguage eLanguage, TokenType aToken)
+{
+ Color aColor;
+ switch (eLanguage)
+ {
+ case HighlighterLanguage::SQL:
+ {
+ switch (aToken)
+ {
+ case TokenType::Identifier: aColor = rColorConfig.GetColorValue(svtools::SQLIDENTIFIER).nColor; break;
+ case TokenType::Number: aColor = rColorConfig.GetColorValue(svtools::SQLNUMBER).nColor; break;
+ case TokenType::String: aColor = rColorConfig.GetColorValue(svtools::SQLSTRING).nColor; break;
+ case TokenType::Operator: aColor = rColorConfig.GetColorValue(svtools::SQLOPERATOR).nColor; break;
+ case TokenType::Keywords: aColor = rColorConfig.GetColorValue(svtools::SQLKEYWORD).nColor; break;
+ case TokenType::Parameter: aColor = rColorConfig.GetColorValue(svtools::SQLPARAMETER).nColor; break;
+ case TokenType::Comment: aColor = rColorConfig.GetColorValue(svtools::SQLCOMMENT).nColor; break;
+ default: aColor = Color(0,0,0);
+ }
+ break;
+ }
+ case HighlighterLanguage::Basic:
+ {
+ switch (aToken)
+ {
+ case TokenType::Identifier: aColor = Color(255,0,0); break;
+ case TokenType::Comment: aColor = Color(0,0,45); break;
+ case TokenType::Number: aColor = Color(204,102,204); break;
+ case TokenType::String: aColor = Color(0,255,45); break;
+ case TokenType::Operator: aColor = Color(0,0,100); break;
+ case TokenType::Keywords: aColor = Color(0,0,255); break;
+ case TokenType::Error : aColor = Color(0,255,255); break;
+ default: aColor = Color(0,0,0);
+ }
+ break;
+ }
+ default: aColor = Color(0,0,0);
+
+ }
+ return aColor;
+}
+
+bool SQLEditView::KeyInput(const KeyEvent& rKEvt)
+{
+ DoBracketHilight(rKEvt.GetCharCode());
+
+ if (m_bDisableInternalUndo)
+ {
+ KeyFuncType eFunc = rKEvt.GetKeyCode().GetFunction();
+ if (eFunc == KeyFuncType::UNDO || eFunc == KeyFuncType::REDO)
+ return false;
+ }
+
+ return WeldEditView::KeyInput(rKEvt);
+}
+
+bool SQLEditView::Command(const CommandEvent& rCEvt)
+{
+ if (rCEvt.GetCommand() == CommandEventId::ContextMenu)
+ {
+ ::tools::Rectangle aRect(rCEvt.GetMousePosPixel(), Size(1, 1));
+ weld::Widget* pPopupParent = GetDrawingArea();
+ std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(pPopupParent, "vcl/ui/editmenu.ui"));
+ std::unique_ptr<weld::Menu> xContextMenu(xBuilder->weld_menu("menu"));
+
+ bool bEnableCut = true;
+ bool bEnableCopy = true;
+ bool bEnableDelete = true;
+ bool bEnablePaste = true;
+ bool bEnableSpecialChar = true;
+
+ EditView* pEditView = GetEditView();
+
+ if (!pEditView->HasSelection())
+ {
+ bEnableCut = false;
+ bEnableCopy = false;
+ bEnableDelete = false;
+ }
+
+ if (pEditView->IsReadOnly())
+ {
+ bEnableCut = false;
+ bEnablePaste = false;
+ bEnableDelete = false;
+ bEnableSpecialChar = false;
+ }
+
+ xContextMenu->set_sensitive("cut", bEnableCut);
+ xContextMenu->set_sensitive("copy", bEnableCopy);
+ xContextMenu->set_sensitive("delete", bEnableDelete);
+ xContextMenu->set_sensitive("paste", bEnablePaste);
+ xContextMenu->set_sensitive("specialchar", bEnableSpecialChar);
+ xContextMenu->set_visible("undo", false);
+ xContextMenu->set_visible("specialchar", vcl::GetGetSpecialCharsFunction() != nullptr);
+
+ OString sCommand = xContextMenu->popup_at_rect(pPopupParent, aRect);
+
+ if (sCommand == "cut")
+ pEditView->Cut();
+ else if (sCommand == "copy")
+ pEditView->Copy();
+ else if (sCommand == "paste")
+ pEditView->Paste();
+ else if (sCommand == "delete")
+ pEditView->DeleteSelected();
+ else if (sCommand == "selectall")
+ {
+ sal_Int32 nPar = m_xEditEngine->GetParagraphCount();
+ if (nPar)
+ {
+ sal_Int32 nLen = m_xEditEngine->GetTextLen(nPar - 1);
+ pEditView->SetSelection(ESelection(0, 0, nPar - 1, nLen));
+ }
+ }
+ else if (sCommand == "specialchar")
+ {
+ OUString aChars = vcl::GetGetSpecialCharsFunction()(pPopupParent, m_xEditEngine->GetStandardFont(0));
+ if (!aChars.isEmpty())
+ {
+ pEditView->InsertText(aChars);
+ }
+ }
+
+ return true;
+ }
+ return WeldEditView::Command(rCEvt);
+}
+
+void SQLEditView::EditViewScrollStateChange()
+{
+ // editengine height has changed or editview scroll pos has changed
+ SetScrollBarRange();
+}
+
+void SQLEditView::SetScrollBarRange()
+{
+ EditEngine *pEditEngine = GetEditEngine();
+ if (!pEditEngine)
+ return;
+ if (!m_xScrolledWindow)
+ return;
+ EditView* pEditView = GetEditView();
+ if (!pEditView)
+ return;
+
+ int nVUpper = pEditEngine->GetTextHeight();
+ int nVCurrentDocPos = pEditView->GetVisArea().Top();
+ const Size aOut(pEditView->GetOutputArea().GetSize());
+ int nVStepIncrement = aOut.Height() * 2 / 10;
+ int nVPageIncrement = aOut.Height() * 8 / 10;
+ int nVPageSize = aOut.Height();
+
+ /* limit the page size to below nUpper because gtk's gtk_scrolled_window_start_deceleration has
+ effectively...
+
+ lower = gtk_adjustment_get_lower
+ upper = gtk_adjustment_get_upper - gtk_adjustment_get_page_size
+
+ and requires that upper > lower or the deceleration animation never ends
+ */
+ nVPageSize = std::min(nVPageSize, nVUpper);
+
+ m_xScrolledWindow->vadjustment_configure(nVCurrentDocPos, 0, nVUpper,
+ nVStepIncrement, nVPageIncrement, nVPageSize);
+}
+
+IMPL_LINK_NOARG(SQLEditView, ScrollHdl, weld::ScrolledWindow&, void)
+{
+ DoScroll();
+}
+
+IMPL_LINK_NOARG(SQLEditView, EditStatusHdl, EditStatus&, void)
+{
+ Resize();
+}
+
+void SQLEditView::DoScroll()
+{
+ if (m_xEditView)
+ {
+ auto currentDocPos = m_xEditView->GetVisArea().Top();
+ auto nDiff = currentDocPos - m_xScrolledWindow->vadjustment_get_value();
+ // we expect SetScrollBarRange callback to be triggered by Scroll
+ // to set where we ended up
+ m_xEditView->Scroll(0, nDiff);
+ }
+}
+
+void SQLEditView::ConfigurationChanged(utl::ConfigurationBroadcaster*, ConfigurationHints)
+{
+ UpdateData();
+}
+
+void SQLEditView::ImplSetFont()
+{
+ // see SmEditWindow::DataChanged for a similar case
+ SetItemPoolFont(m_pItemPool.get()); // change default font
+ // re-create with the new font
+ EditEngine& rEditEngine = *GetEditEngine();
+ OUString aTxt(rEditEngine.GetText());
+ rEditEngine.Clear();
+ SetTextAndUpdate(aTxt);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/control/tabletree.cxx b/dbaccess/source/ui/control/tabletree.cxx
new file mode 100644
index 000000000..2c3f0976f
--- /dev/null
+++ b/dbaccess/source/ui/control/tabletree.cxx
@@ -0,0 +1,707 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <core_resource.hxx>
+#include <tabletree.hxx>
+#include <imageprovider.hxx>
+#include <strings.hrc>
+#include <connectivity/dbtools.hxx>
+#include <com/sun/star/sdb/application/DatabaseObject.hpp>
+#include <com/sun/star/sdb/application/DatabaseObjectContainer.hpp>
+#include <com/sun/star/sdbcx/XViewsSupplier.hpp>
+#include <com/sun/star/sdbcx/XTablesSupplier.hpp>
+#include <com/sun/star/sdbc/SQLException.hpp>
+#include <com/sun/star/sdbc/XRow.hpp>
+#include <tools/diagnose_ex.h>
+#include <osl/diagnose.h>
+#include <connectivity/dbmetadata.hxx>
+
+#include <algorithm>
+
+namespace dbaui
+{
+
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::sdb;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::sdbcx;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::sdb::application;
+
+using namespace ::dbtools;
+using namespace ::comphelper;
+
+namespace DatabaseObject = ::com::sun::star::sdb::application::DatabaseObject;
+namespace DatabaseObjectContainer = ::com::sun::star::sdb::application::DatabaseObjectContainer;
+
+// OTableTreeListBox
+OTableTreeListBox::OTableTreeListBox(std::unique_ptr<weld::TreeView> xTreeView, bool bShowToggles)
+ : TreeListBox(std::move(xTreeView), true)
+ , m_xImageProvider(new ImageProvider)
+ , m_bVirtualRoot(false)
+ , m_bNoEmptyFolders(false)
+ , m_bShowToggles(bShowToggles)
+{
+ if (m_bShowToggles)
+ m_xTreeView->enable_toggle_buttons(weld::ColumnToggleType::Check);
+}
+
+bool OTableTreeListBox::isFolderEntry(const weld::TreeIter& rEntry) const
+{
+ sal_Int32 nEntryType = m_xTreeView->get_id(rEntry).toInt32();
+ return ( nEntryType == DatabaseObjectContainer::TABLES )
+ || ( nEntryType == DatabaseObjectContainer::CATALOG )
+ || ( nEntryType == DatabaseObjectContainer::SCHEMA );
+}
+
+void OTableTreeListBox::implOnNewConnection( const Reference< XConnection >& _rxConnection )
+{
+ m_xConnection = _rxConnection;
+ m_xImageProvider.reset( new ImageProvider( m_xConnection ) );
+}
+
+void OTableTreeListBox::UpdateTableList( const Reference< XConnection >& _rxConnection )
+{
+ Sequence< OUString > sTables, sViews;
+
+ OUString sCurrentActionError;
+ try
+ {
+ Reference< XTablesSupplier > xTableSupp( _rxConnection, UNO_QUERY_THROW );
+ sCurrentActionError = DBA_RES(STR_NOTABLEINFO);
+
+ Reference< XNameAccess > xTables,xViews;
+
+ Reference< XViewsSupplier > xViewSupp( _rxConnection, UNO_QUERY );
+ if ( xViewSupp.is() )
+ {
+ xViews = xViewSupp->getViews();
+ if (xViews.is())
+ sViews = xViews->getElementNames();
+ }
+
+ xTables = xTableSupp->getTables();
+ if (xTables.is())
+ sTables = xTables->getElementNames();
+ }
+ catch(RuntimeException&)
+ {
+ TOOLS_WARN_EXCEPTION( "dbaccess", "OTableTreeListBox::UpdateTableList");
+ }
+ catch ( const SQLException& )
+ {
+ throw;
+ }
+ catch(Exception&)
+ {
+ css::uno::Any anyEx = cppu::getCaughtException();
+ // a non-SQLException exception occurred ... simply throw an SQLException
+ throw SQLException(sCurrentActionError, nullptr, "", 0, anyEx);
+ }
+
+ UpdateTableList( _rxConnection, sTables, sViews );
+}
+
+namespace
+{
+ struct OViewSetter
+ {
+ const Sequence< OUString> m_aViews;
+ ::comphelper::UStringMixEqual m_aEqualFunctor;
+
+ OViewSetter(const Sequence< OUString>& _rViews,bool _bCase) : m_aViews(_rViews),m_aEqualFunctor(_bCase){}
+ OTableTreeListBox::TNames::value_type operator() (const OUString& name)
+ {
+ OTableTreeListBox::TNames::value_type aRet;
+ aRet.first = name;
+ aRet.second = std::any_of(m_aViews.begin(), m_aViews.end(),
+ [this, &name](const OUString& lhs)
+ { return m_aEqualFunctor(lhs, name); } );
+
+ return aRet;
+ }
+ };
+
+}
+
+void OTableTreeListBox::UpdateTableList(
+ const Reference< XConnection >& _rxConnection,
+ const Sequence< OUString>& _rTables,
+ const Sequence< OUString>& _rViews
+ )
+{
+ TNames aTables;
+ aTables.resize(_rTables.getLength());
+ try
+ {
+ Reference< XDatabaseMetaData > xMeta( _rxConnection->getMetaData(), UNO_SET_THROW );
+ std::transform( _rTables.begin(), _rTables.end(),
+ aTables.begin(), OViewSetter( _rViews, xMeta->supportsMixedCaseQuotedIdentifiers() ) );
+ }
+ catch(Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ UpdateTableList( _rxConnection, aTables );
+}
+
+namespace
+{
+ std::vector< OUString > lcl_getMetaDataStrings_throw( const Reference< XResultSet >& _rxMetaDataResult, sal_Int32 _nColumnIndex )
+ {
+ std::vector< OUString > aStrings;
+ Reference< XRow > xRow( _rxMetaDataResult, UNO_QUERY_THROW );
+ while ( _rxMetaDataResult->next() )
+ aStrings.push_back( xRow->getString( _nColumnIndex ) );
+ return aStrings;
+ }
+
+ bool lcl_shouldDisplayEmptySchemasAndCatalogs( const Reference< XConnection >& _rxConnection )
+ {
+ ::dbtools::DatabaseMetaData aMetaData( _rxConnection );
+ return aMetaData.displayEmptyTableFolders();
+ }
+}
+
+void OTableTreeListBox::UpdateTableList( const Reference< XConnection >& _rxConnection, const TNames& _rTables )
+{
+ implOnNewConnection( _rxConnection );
+
+ // throw away all the old stuff
+ m_xTreeView->clear();
+ m_xTreeView->make_unsorted();
+
+ try
+ {
+ if (haveVirtualRoot())
+ {
+ OUString sRootEntryText;
+ if ( std::none_of(_rTables.begin(),_rTables.end(),
+ [] (const TNames::value_type& name) { return !name.second; }) )
+ sRootEntryText = DBA_RES(STR_ALL_TABLES);
+ else if ( std::none_of(_rTables.begin(),_rTables.end(),
+ [] (const TNames::value_type& name) { return name.second; }) )
+ sRootEntryText = DBA_RES(STR_ALL_VIEWS);
+ else
+ sRootEntryText = DBA_RES(STR_ALL_TABLES_AND_VIEWS);
+ OUString sId(OUString::number(DatabaseObjectContainer::TABLES));
+ OUString sImageId = ImageProvider::getFolderImageId(DatabaseObject::TABLE);
+ std::unique_ptr<weld::TreeIter> xRet(m_xTreeView->make_iterator());
+ m_xTreeView->insert(nullptr, -1, nullptr, &sId, nullptr, nullptr, false, xRet.get());
+ m_xTreeView->set_image(*xRet, sImageId, -1);
+ if (m_bShowToggles)
+ m_xTreeView->set_toggle(*xRet, TRISTATE_FALSE);
+ m_xTreeView->set_text(*xRet, sRootEntryText, 0);
+ m_xTreeView->set_text_emphasis(*xRet, false, 0);
+ }
+
+ if ( _rTables.empty() )
+ // nothing to do (besides inserting the root entry)
+ return;
+
+ // get the table/view names
+ Reference< XDatabaseMetaData > xMeta( _rxConnection->getMetaData(), UNO_SET_THROW );
+ for (auto const& table : _rTables)
+ {
+ // add the entry
+ implAddEntry(xMeta, table.first, false);
+ }
+
+ if ( !m_bNoEmptyFolders && lcl_shouldDisplayEmptySchemasAndCatalogs( _rxConnection ) )
+ {
+ bool bSupportsCatalogs = xMeta->supportsCatalogsInDataManipulation();
+ bool bSupportsSchemas = xMeta->supportsSchemasInDataManipulation();
+
+ if ( bSupportsCatalogs || bSupportsSchemas )
+ {
+ // we display empty catalogs if the DB supports catalogs, and they're noted at the beginning of a
+ // composed name. Otherwise, we display empty schematas. (also see the tree structure explained in
+ // implAddEntry)
+ bool bCatalogs = bSupportsCatalogs && xMeta->isCatalogAtStart();
+
+ std::vector< OUString > aFolderNames( lcl_getMetaDataStrings_throw(
+ bCatalogs ? xMeta->getCatalogs() : xMeta->getSchemas(), 1 ) );
+ sal_Int32 nFolderType = bCatalogs ? DatabaseObjectContainer::CATALOG : DatabaseObjectContainer::SCHEMA;
+
+ OUString sImageId = ImageProvider::getFolderImageId(DatabaseObject::TABLE);
+
+ std::unique_ptr<weld::TreeIter> xRootEntry(getAllObjectsEntry());
+ std::unique_ptr<weld::TreeIter> xRet(m_xTreeView->make_iterator());
+ for (auto const& folderName : aFolderNames)
+ {
+ std::unique_ptr<weld::TreeIter> xFolder(GetEntryPosByName(folderName, xRootEntry.get()));
+ if (!xFolder)
+ {
+ OUString sId(OUString::number(nFolderType));
+ m_xTreeView->insert(xRootEntry.get(), -1, nullptr, &sId, nullptr, nullptr, false, xRet.get());
+ m_xTreeView->set_image(*xRet, sImageId, -1);
+ if (m_bShowToggles)
+ m_xTreeView->set_toggle(*xRet, TRISTATE_FALSE);
+ m_xTreeView->set_text(*xRet, folderName, 0);
+ m_xTreeView->set_text_emphasis(*xRet, false, 0);
+ }
+ }
+ }
+ }
+ }
+ catch ( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+
+ m_xTreeView->make_sorted();
+}
+
+bool OTableTreeListBox::isWildcardChecked(const weld::TreeIter& rEntry)
+{
+ return m_xTreeView->get_text_emphasis(rEntry, 0);
+}
+
+void OTableTreeListBox::checkWildcard(const weld::TreeIter& rEntry)
+{
+ if (!m_bShowToggles)
+ return;
+ m_xTreeView->set_toggle(rEntry, TRISTATE_TRUE);
+ checkedButton_noBroadcast(rEntry);
+}
+
+std::unique_ptr<weld::TreeIter> OTableTreeListBox::getAllObjectsEntry() const
+{
+ if (!haveVirtualRoot())
+ return nullptr;
+ auto xRet = m_xTreeView->make_iterator();
+ if (!m_xTreeView->get_iter_first(*xRet))
+ return nullptr;
+ return xRet;
+}
+
+void OTableTreeListBox::checkedButton_noBroadcast(const weld::TreeIter& rEntry)
+{
+ if (!m_bShowToggles)
+ return;
+ TriState eState = m_xTreeView->get_toggle(rEntry);
+ OSL_ENSURE(TRISTATE_INDET != eState, "OTableTreeListBox::CheckButtonHdl: user action which lead to TRISTATE?");
+
+ if (m_xTreeView->iter_has_child(rEntry)) // if it has children, check those too
+ {
+ std::unique_ptr<weld::TreeIter> xChildEntry(m_xTreeView->make_iterator(&rEntry));
+ std::unique_ptr<weld::TreeIter> xSiblingEntry(m_xTreeView->make_iterator(&rEntry));
+ bool bChildEntry = m_xTreeView->iter_next(*xChildEntry);
+ bool bSiblingEntry = m_xTreeView->iter_next_sibling(*xSiblingEntry);
+ while (bChildEntry && (!bSiblingEntry || !xChildEntry->equal(*xSiblingEntry)))
+ {
+ m_xTreeView->set_toggle(*xChildEntry, eState);
+ bChildEntry = m_xTreeView->iter_next(*xChildEntry);
+ }
+ }
+
+ if (m_xTreeView->is_selected(rEntry))
+ {
+ m_xTreeView->selected_foreach([this, eState](weld::TreeIter& rSelected){
+ m_xTreeView->set_toggle(rSelected, eState);
+ if (m_xTreeView->iter_has_child(rSelected)) // if it has children, check those too
+ {
+ std::unique_ptr<weld::TreeIter> xChildEntry(m_xTreeView->make_iterator(&rSelected));
+ std::unique_ptr<weld::TreeIter> xSiblingEntry(m_xTreeView->make_iterator(&rSelected));
+ bool bChildEntry = m_xTreeView->iter_next(*xChildEntry);
+ bool bSiblingEntry = m_xTreeView->iter_next_sibling(*xSiblingEntry);
+ while (bChildEntry && (!bSiblingEntry || !xChildEntry->equal(*xSiblingEntry)))
+ {
+ m_xTreeView->set_toggle(*xChildEntry, eState);
+ bChildEntry = m_xTreeView->iter_next(*xChildEntry);
+ }
+ }
+ return false;
+ });
+ }
+
+ CheckButtons();
+
+ // if an entry has children, it makes a difference if the entry is checked
+ // because all children are checked or if the user checked it explicitly.
+ // So we track explicit (un)checking
+ implEmphasize(rEntry, eState == TRISTATE_TRUE);
+}
+
+void OTableTreeListBox::implEmphasize(const weld::TreeIter& rEntry, bool _bChecked, bool _bUpdateDescendants, bool _bUpdateAncestors)
+{
+ // special emphasizing handling for the "all objects" entry
+ bool bAllObjectsEntryAffected = haveVirtualRoot() && (getAllObjectsEntry()->equal(rEntry));
+ if ( m_xTreeView->iter_has_child(rEntry) // the entry has children
+ || bAllObjectsEntryAffected // or it is the "all objects" entry
+ )
+ {
+ m_xTreeView->set_text_emphasis(rEntry, _bChecked, 0);
+ }
+
+ if (_bUpdateDescendants)
+ {
+ std::unique_ptr<weld::TreeIter> xChild(m_xTreeView->make_iterator(&rEntry));
+ // remove the mark for all children of the checked entry
+ bool bChildLoop = m_xTreeView->iter_children(*xChild);
+ while (bChildLoop)
+ {
+ if (m_xTreeView->iter_has_child(*xChild))
+ implEmphasize(*xChild, false, true, false);
+ bChildLoop = m_xTreeView->iter_next_sibling(*xChild);
+ }
+ }
+
+ if (_bUpdateAncestors)
+ {
+ std::unique_ptr<weld::TreeIter> xParent(m_xTreeView->make_iterator(&rEntry));
+ // remove the mark for all ancestors of the entry
+ if (m_xTreeView->iter_parent(*xParent))
+ implEmphasize(*xParent, false, false);
+ }
+}
+
+std::unique_ptr<weld::TreeIter> OTableTreeListBox::implAddEntry(
+ const Reference< XDatabaseMetaData >& _rxMeta,
+ const OUString& _rTableName,
+ bool _bCheckName
+ )
+{
+ OSL_PRECOND( _rxMeta.is(), "OTableTreeListBox::implAddEntry: invalid meta data!" );
+ if ( !_rxMeta.is() )
+ return nullptr;
+
+ // split the complete name into its components
+ OUString sCatalog, sSchema, sName;
+ qualifiedNameComponents( _rxMeta, _rTableName, sCatalog, sSchema, sName, ::dbtools::EComposeRule::InDataManipulation );
+
+ std::unique_ptr<weld::TreeIter> xParentEntry(getAllObjectsEntry());
+
+ // if the DB uses catalog at the start of identifiers, then our hierarchy is
+ // catalog
+ // +- schema
+ // +- table
+ // else it is
+ // schema
+ // +- catalog
+ // +- table
+ bool bCatalogAtStart = _rxMeta->isCatalogAtStart();
+ const OUString& rFirstName = bCatalogAtStart ? sCatalog : sSchema;
+ const sal_Int32 nFirstFolderType = bCatalogAtStart ? DatabaseObjectContainer::CATALOG : DatabaseObjectContainer::SCHEMA;
+ const OUString& rSecondName = bCatalogAtStart ? sSchema : sCatalog;
+ const sal_Int32 nSecondFolderType = bCatalogAtStart ? DatabaseObjectContainer::SCHEMA : DatabaseObjectContainer::CATALOG;
+
+ if ( !rFirstName.isEmpty() )
+ {
+ std::unique_ptr<weld::TreeIter> xFolder(GetEntryPosByName(rFirstName, xParentEntry.get()));
+ if (!xFolder)
+ {
+ xFolder = m_xTreeView->make_iterator();
+ OUString sId(OUString::number(nFirstFolderType));
+ OUString sImageId = ImageProvider::getFolderImageId(DatabaseObject::TABLE);
+ m_xTreeView->insert(xParentEntry.get(), -1, nullptr, &sId, nullptr, nullptr, false, xFolder.get());
+ m_xTreeView->set_image(*xFolder, sImageId, -1);
+ if (m_bShowToggles)
+ m_xTreeView->set_toggle(*xFolder, TRISTATE_FALSE);
+ m_xTreeView->set_text(*xFolder, rFirstName, 0);
+ m_xTreeView->set_text_emphasis(*xFolder, false, 0);
+ }
+ xParentEntry = std::move(xFolder);
+ }
+
+ if ( !rSecondName.isEmpty() )
+ {
+ std::unique_ptr<weld::TreeIter> xFolder(GetEntryPosByName(rSecondName, xParentEntry.get()));
+ if (!xFolder)
+ {
+ xFolder = m_xTreeView->make_iterator();
+ OUString sId(OUString::number(nSecondFolderType));
+ OUString sImageId = ImageProvider::getFolderImageId(DatabaseObject::TABLE);
+ m_xTreeView->insert(xParentEntry.get(), -1, nullptr, &sId, nullptr, nullptr, false, xFolder.get());
+ m_xTreeView->set_image(*xFolder, sImageId, -1);
+ if (m_bShowToggles)
+ m_xTreeView->set_toggle(*xFolder, TRISTATE_FALSE);
+ m_xTreeView->set_text(*xFolder, rSecondName, 0);
+ m_xTreeView->set_text_emphasis(*xFolder, false, 0);
+ }
+ xParentEntry = std::move(xFolder);
+ }
+
+ if (!_bCheckName || !GetEntryPosByName(sName, xParentEntry.get()))
+ {
+ std::unique_ptr<weld::TreeIter> xEntry = m_xTreeView->make_iterator();
+ m_xTreeView->insert(xParentEntry.get(), -1, nullptr, nullptr, nullptr, nullptr, false, xEntry.get());
+
+ auto xGraphic = m_xImageProvider->getXGraphic(_rTableName, DatabaseObject::TABLE);
+ if (xGraphic.is())
+ m_xTreeView->set_image(*xEntry, xGraphic, -1);
+ else
+ {
+ OUString sImageId(m_xImageProvider->getImageId(_rTableName, DatabaseObject::TABLE));
+ m_xTreeView->set_image(*xEntry, sImageId, -1);
+ }
+ if (m_bShowToggles)
+ m_xTreeView->set_toggle(*xEntry, TRISTATE_FALSE);
+ m_xTreeView->set_text(*xEntry, sName, 0);
+ m_xTreeView->set_text_emphasis(*xEntry, false, 0);
+
+ return xEntry;
+ }
+
+ return nullptr;
+}
+
+NamedDatabaseObject OTableTreeListBox::describeObject(const weld::TreeIter& rEntry)
+{
+ NamedDatabaseObject aObject;
+
+ sal_Int32 nEntryType = m_xTreeView->get_id(rEntry).toInt32();
+
+ if ( nEntryType == DatabaseObjectContainer::TABLES )
+ {
+ aObject.Type = DatabaseObjectContainer::TABLES;
+ }
+ else if ( ( nEntryType == DatabaseObjectContainer::CATALOG )
+ || ( nEntryType == DatabaseObjectContainer::SCHEMA )
+ )
+ {
+ // nothing useful to be done
+ }
+ else
+ {
+ aObject.Type = DatabaseObject::TABLE;
+ aObject.Name = getQualifiedTableName(rEntry);
+ }
+
+ return aObject;
+}
+
+std::unique_ptr<weld::TreeIter> OTableTreeListBox::addedTable(const OUString& rName)
+{
+ try
+ {
+ Reference< XDatabaseMetaData > xMeta;
+ if ( impl_getAndAssertMetaData( xMeta ) )
+ return implAddEntry( xMeta, rName );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ return nullptr;
+}
+
+bool OTableTreeListBox::impl_getAndAssertMetaData( Reference< XDatabaseMetaData >& _out_rMetaData ) const
+{
+ if ( m_xConnection.is() )
+ _out_rMetaData = m_xConnection->getMetaData();
+ OSL_PRECOND( _out_rMetaData.is(), "OTableTreeListBox::impl_getAndAssertMetaData: invalid current connection!" );
+ return _out_rMetaData.is();
+}
+
+OUString OTableTreeListBox::getQualifiedTableName(const weld::TreeIter& rEntry) const
+{
+ OSL_PRECOND( !isFolderEntry(rEntry), "OTableTreeListBox::getQualifiedTableName: folder entries not allowed here!" );
+
+ try
+ {
+ Reference< XDatabaseMetaData > xMeta;
+ if ( !impl_getAndAssertMetaData( xMeta ) )
+ return OUString();
+
+ OUString sCatalog;
+ OUString sSchema;
+ OUString sTable;
+
+ std::unique_ptr<weld::TreeIter> xSchema(m_xTreeView->make_iterator(&rEntry));
+ bool bSchema = m_xTreeView->iter_parent(*xSchema);
+ if (bSchema)
+ {
+ std::unique_ptr<weld::TreeIter> xCatalog(m_xTreeView->make_iterator(xSchema.get()));
+ bool bCatalog = m_xTreeView->iter_parent(*xCatalog);
+ if ( bCatalog
+ || ( xMeta->supportsCatalogsInDataManipulation()
+ && !xMeta->supportsSchemasInDataManipulation()
+ ) // here we support catalog but no schema
+ )
+ {
+ if (!bCatalog)
+ {
+ xCatalog = std::move(xSchema);
+ bSchema = false;
+ }
+ sCatalog = m_xTreeView->get_text(*xCatalog);
+ }
+ if (bSchema)
+ sSchema = m_xTreeView->get_text(*xSchema);
+ }
+ sTable = m_xTreeView->get_text(rEntry);
+
+ return ::dbtools::composeTableName( xMeta, sCatalog, sSchema, sTable, false, ::dbtools::EComposeRule::InDataManipulation );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ return OUString();
+}
+
+std::unique_ptr<weld::TreeIter> OTableTreeListBox::getEntryByQualifiedName(const OUString& rName)
+{
+ try
+ {
+ Reference< XDatabaseMetaData > xMeta;
+ if ( !impl_getAndAssertMetaData( xMeta ) )
+ return nullptr;
+
+ // split the complete name into its components
+ OUString sCatalog, sSchema, sName;
+ qualifiedNameComponents(xMeta, rName, sCatalog, sSchema, sName,::dbtools::EComposeRule::InDataManipulation);
+
+ std::unique_ptr<weld::TreeIter> xParent(getAllObjectsEntry());
+ std::unique_ptr<weld::TreeIter> xCat;
+ std::unique_ptr<weld::TreeIter> xSchema;
+ if (!sCatalog.isEmpty())
+ {
+ xCat = GetEntryPosByName(sCatalog);
+ if (xCat)
+ xParent = std::move(xCat);
+ }
+
+ if (!sSchema.isEmpty())
+ {
+ xSchema = GetEntryPosByName(sSchema, xParent.get());
+ if (xSchema)
+ xParent = std::move(xSchema);
+ }
+
+ return GetEntryPosByName(sName, xParent.get());
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ return nullptr;
+}
+
+void OTableTreeListBox::removedTable(const OUString& rName)
+{
+ try
+ {
+ std::unique_ptr<weld::TreeIter> xEntry = getEntryByQualifiedName(rName);
+ if (xEntry)
+ m_xTreeView->remove(*xEntry);
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+}
+
+void OTableTreeListBox::CheckButtons()
+{
+ if (!m_bShowToggles)
+ return;
+
+ auto xEntry(m_xTreeView->make_iterator());
+ if (!m_xTreeView->get_iter_first(*xEntry))
+ return;
+
+ do
+ {
+ implDetermineState(*xEntry);
+ } while (m_xTreeView->iter_next_sibling(*xEntry));
+}
+
+TriState OTableTreeListBox::implDetermineState(const weld::TreeIter& rEntry)
+{
+ if (!m_bShowToggles)
+ return TRISTATE_FALSE;
+
+ TriState eState = m_xTreeView->get_toggle(rEntry);
+ if (!m_xTreeView->iter_has_child(rEntry))
+ // nothing to do in this bottom-up routine if there are no children ...
+ return eState;
+
+ // loop through the children and check their states
+ sal_uInt16 nCheckedChildren = 0;
+ sal_uInt16 nChildrenOverall = 0;
+
+ std::unique_ptr<weld::TreeIter> xChild(m_xTreeView->make_iterator(&rEntry));
+ bool bChildLoop = m_xTreeView->iter_children(*xChild);
+ while (bChildLoop)
+ {
+ TriState eChildState = implDetermineState(*xChild);
+ if (eChildState == TRISTATE_INDET)
+ break;
+ if (eChildState == TRISTATE_TRUE)
+ ++nCheckedChildren;
+ ++nChildrenOverall;
+ bChildLoop = m_xTreeView->iter_next_sibling(*xChild);
+ }
+
+ if (bChildLoop)
+ {
+ // we did not finish the loop because at least one of the children is in tristate
+ eState = TRISTATE_INDET;
+
+ // but this means that we did not finish all the siblings of pChildLoop,
+ // so their checking may be incorrect at the moment
+ // -> correct this
+ while (bChildLoop)
+ {
+ implDetermineState(*xChild);
+ bChildLoop = m_xTreeView->iter_next_sibling(*xChild);
+ }
+ }
+ else
+ {
+ // none if the children are in tristate
+ if (nCheckedChildren)
+ {
+ // we have at least one child checked
+ if (nCheckedChildren != nChildrenOverall)
+ {
+ // not all children are checked
+ eState = TRISTATE_INDET;
+ }
+ else
+ {
+ // all children are checked
+ eState = TRISTATE_TRUE;
+ }
+ }
+ else
+ {
+ // no children are checked
+ eState = TRISTATE_FALSE;
+ }
+ }
+
+ // finally set the entry to the state we just determined
+ m_xTreeView->set_toggle(rEntry, eState);
+
+ return eState;
+}
+
+DBTableTreeView::DBTableTreeView(weld::Container* pContainer)
+ : DBTreeViewBase(pContainer)
+{
+ m_xTreeListBox.reset(new OTableTreeListBox(m_xBuilder->weld_tree_view("treeview"), /*bShowToggles*/false));
+}
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/control/undosqledit.cxx b/dbaccess/source/ui/control/undosqledit.cxx
new file mode 100644
index 000000000..00a5fd407
--- /dev/null
+++ b/dbaccess/source/ui/control/undosqledit.cxx
@@ -0,0 +1,34 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <undosqledit.hxx>
+#include <QueryTextView.hxx>
+
+namespace dbaui
+{
+void OSqlEditUndoAct::ToggleText()
+{
+ OUString strNext = m_rOwner.GetSQLText();
+ m_rOwner.SetSQLText(m_strNextText);
+ m_strNextText = strNext;
+}
+
+} // namespace
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/dlg/CollectionView.cxx b/dbaccess/source/ui/dlg/CollectionView.cxx
new file mode 100644
index 000000000..2e02fda50
--- /dev/null
+++ b/dbaccess/source/ui/dlg/CollectionView.cxx
@@ -0,0 +1,316 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <CollectionView.hxx>
+#include <tools/diagnose_ex.h>
+#include <core_resource.hxx>
+#include <strings.hrc>
+#include <comphelper/interaction.hxx>
+#include <comphelper/propertysequence.hxx>
+#include <cppuhelper/exc_hlp.hxx>
+#include <com/sun/star/container/XChild.hpp>
+#include <com/sun/star/container/XNameContainer.hpp>
+#include <o3tl/safeint.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/weld.hxx>
+#include <UITools.hxx>
+#include <com/sun/star/container/XHierarchicalNameContainer.hpp>
+#include <com/sun/star/ucb/InteractiveAugmentedIOException.hpp>
+#include <com/sun/star/ucb/IOErrorCode.hpp>
+#include <com/sun/star/ucb/XDynamicResultSet.hpp>
+#include <com/sun/star/sdbc/XRow.hpp>
+#include <com/sun/star/task/InteractionHandler.hpp>
+#include <com/sun/star/task/InteractionClassification.hpp>
+#include <com/sun/star/sdbc/SQLException.hpp>
+#include <comphelper/processfactory.hxx>
+#include <ucbhelper/commandenvironment.hxx>
+#include <ucbhelper/content.hxx>
+#include <connectivity/dbexception.hxx>
+
+namespace dbaui
+{
+
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::ucb;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::task;
+using namespace ::com::sun::star::sdbc;
+using namespace comphelper;
+
+OCollectionView::OCollectionView(weld::Window* pParent,
+ const Reference< XContent>& _xContent,
+ const OUString& _sDefaultName,
+ const css::uno::Reference< css::uno::XComponentContext >& _rxContext)
+ : GenericDialogController(pParent, "dbaccess/ui/collectionviewdialog.ui", "CollectionView")
+ , m_xContent(_xContent)
+ , m_xContext(_rxContext)
+ , m_bCreateForm(true)
+ , m_xFTCurrentPath(m_xBuilder->weld_label("currentPathLabel"))
+ , m_xNewFolder(m_xBuilder->weld_button("newFolderButton"))
+ , m_xUp(m_xBuilder->weld_button("upButton"))
+ , m_xView(m_xBuilder->weld_tree_view("viewTreeview"))
+ , m_xName(m_xBuilder->weld_entry("fileNameEntry"))
+ , m_xPB_OK(m_xBuilder->weld_button("ok"))
+{
+ Reference<XInteractionHandler2> xHandler(
+ InteractionHandler::createWithParent(m_xContext, m_xDialog->GetXWindow()));
+ m_xCmdEnv = new ::ucbhelper::CommandEnvironment(xHandler, nullptr);
+
+ OSL_ENSURE(m_xContent.is(),"No valid content!");
+ m_xView->set_size_request(m_xView->get_approximate_digit_width() * 60, m_xView->get_height_rows(8));
+ m_xView->make_sorted();
+ Initialize();
+ initCurrentPath();
+
+ m_xName->set_text(_sDefaultName);
+ m_xName->grab_focus();
+
+ m_xView->connect_row_activated( LINK( this, OCollectionView, Dbl_Click_FileView ) );
+ m_xUp->connect_clicked( LINK( this, OCollectionView, Up_Click ) );
+ m_xNewFolder->connect_clicked( LINK( this, OCollectionView, NewFolder_Click ) );
+ m_xPB_OK->connect_clicked( LINK( this, OCollectionView, Save_Click ) );
+}
+
+OCollectionView::~OCollectionView()
+{
+}
+
+IMPL_LINK_NOARG(OCollectionView, Save_Click, weld::Button&, void)
+{
+ OUString sName = m_xName->get_text();
+ if (sName.isEmpty())
+ return;
+ try
+ {
+ sal_Int32 nIndex = sName.lastIndexOf('/') + 1;
+ if ( nIndex )
+ {
+ if ( nIndex == 1 ) // special handling for root
+ {
+ Reference<XChild> xChild(m_xContent,UNO_QUERY);
+ Reference<XNameAccess> xNameAccess(xChild,UNO_QUERY);
+ while( xNameAccess.is() )
+ {
+ xNameAccess.set(xChild->getParent(),UNO_QUERY);
+ if ( xNameAccess.is() )
+ {
+ m_xContent.set(xNameAccess,UNO_QUERY);
+ xChild.set(m_xContent,UNO_QUERY);
+ }
+ }
+ Initialize();
+ initCurrentPath();
+ }
+ OUString sSubFolder = sName.copy(0,nIndex-1);
+ sName = sName.copy(nIndex);
+ Reference<XHierarchicalNameContainer> xHier(m_xContent,UNO_QUERY);
+ OSL_ENSURE(xHier.is(),"XHierarchicalNameContainer not supported!");
+ if ( !sSubFolder.isEmpty() && xHier.is() )
+ {
+ if ( xHier->hasByHierarchicalName(sSubFolder) )
+ {
+ m_xContent.set(xHier->getByHierarchicalName(sSubFolder),UNO_QUERY);
+ }
+ else // sub folder doesn't exist
+ {
+ Sequence<Any> aValues(comphelper::InitAnyPropertySequence(
+ {
+ {"ResourceName", Any(sSubFolder)},
+ {"ResourceType", Any(OUString("folder"))}
+ }));
+ InteractiveAugmentedIOException aException(OUString(),Reference<XInterface>(),
+ InteractionClassification_ERROR,
+ IOErrorCode_NOT_EXISTING_PATH,aValues);
+
+ Reference<XInteractionHandler2> xHandler(
+ InteractionHandler::createWithParent(m_xContext, m_xDialog->GetXWindow()));
+ rtl::Reference<OInteractionRequest> pRequest = new OInteractionRequest(Any(aException));
+
+ rtl::Reference<OInteractionApprove> pApprove = new OInteractionApprove;
+ pRequest->addContinuation(pApprove);
+ xHandler->handle(pRequest);
+
+ return;
+ }
+ }
+ }
+ Reference<XNameContainer> xNameContainer(m_xContent,UNO_QUERY);
+ if ( xNameContainer.is() )
+ {
+ if ( xNameContainer->hasByName(sName) )
+ {
+ std::unique_ptr<weld::MessageDialog> xQueryBox(Application::CreateMessageDialog(m_xDialog.get(),
+ VclMessageType::Question, VclButtonsType::YesNo,
+ DBA_RES(STR_ALREADYEXISTOVERWRITE)));
+ if (xQueryBox->run() != RET_YES)
+ return;
+ }
+ m_xName->set_text(sName);
+ m_xDialog->response(RET_OK);
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+}
+
+IMPL_LINK_NOARG(OCollectionView, NewFolder_Click, weld::Button&, void)
+{
+ try
+ {
+ Reference<XHierarchicalNameContainer> xNameContainer(m_xContent,UNO_QUERY);
+ if ( dbaui::insertHierarchyElement(m_xDialog.get(),m_xContext,xNameContainer,OUString(),m_bCreateForm) )
+ Initialize();
+ }
+ catch( const SQLException& )
+ {
+ showError(::dbtools::SQLExceptionInfo(::cppu::getCaughtException()), m_xDialog->GetXWindow(), m_xContext);
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+}
+
+IMPL_LINK_NOARG(OCollectionView, Up_Click, weld::Button&, void)
+{
+ try
+ {
+ Reference<XChild> xChild(m_xContent,UNO_QUERY);
+ if ( xChild.is() )
+ {
+ Reference<XNameAccess> xNameAccess(xChild->getParent(),UNO_QUERY);
+ if ( xNameAccess.is() )
+ {
+ m_xContent.set(xNameAccess,UNO_QUERY);
+ Initialize();
+ initCurrentPath();
+ }
+ else
+ m_xUp->set_sensitive(false);
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+}
+
+IMPL_LINK_NOARG(OCollectionView, Dbl_Click_FileView, weld::TreeView&, bool)
+{
+ try
+ {
+ Reference<XNameAccess> xNameAccess(m_xContent,UNO_QUERY);
+ if ( xNameAccess.is() )
+ {
+ OUString sSubFolder = m_xView->get_selected_text();
+ if (!sSubFolder.isEmpty())
+ {
+ Reference< XContent> xContent;
+ if ( xNameAccess->hasByName(sSubFolder) )
+ xContent.set(xNameAccess->getByName(sSubFolder),UNO_QUERY);
+ if ( xContent.is() )
+ {
+ m_xContent = xContent;
+ Initialize();
+ initCurrentPath();
+ }
+ }
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+
+ return true;
+}
+
+void OCollectionView::initCurrentPath()
+{
+ bool bEnable = false;
+ try
+ {
+ if ( m_xContent.is() )
+ {
+ const OUString sCID = m_xContent->getIdentifier()->getContentIdentifier();
+ static const char s_sFormsCID[] = "private:forms";
+ static const char s_sReportsCID[] = "private:reports";
+ m_bCreateForm = s_sFormsCID == sCID;
+ OUString sPath("/");
+ if ( m_bCreateForm && o3tl::make_unsigned(sCID.getLength()) != strlen(s_sFormsCID))
+ sPath = sCID.copy(strlen(s_sFormsCID));
+ else if ( !m_bCreateForm && o3tl::make_unsigned(sCID.getLength()) != strlen(s_sReportsCID) )
+ sPath = sCID.copy(strlen(s_sReportsCID) - 2);
+
+ m_xFTCurrentPath->set_label(sPath);
+ Reference<XChild> xChild(m_xContent,UNO_QUERY);
+ bEnable = xChild.is() && Reference<XNameAccess>(xChild->getParent(),UNO_QUERY).is();
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ m_xUp->set_sensitive(bEnable);
+}
+
+OUString OCollectionView::getName() const
+{
+ return m_xName->get_text();
+}
+
+#define ROW_TITLE 1
+#define ROW_IS_FOLDER 2
+
+void OCollectionView::Initialize()
+{
+ weld::WaitObject aWaitCursor(m_xDialog.get());
+
+ m_xView->clear();
+
+ try
+ {
+ ::ucbhelper::Content aContent(m_xContent, m_xCmdEnv, comphelper::getProcessComponentContext());
+ Sequence<OUString> aProps { "Title", "IsFolder" };
+ auto xDynResultSet = aContent.createDynamicCursor(aProps, ucbhelper::INCLUDE_FOLDERS_ONLY);
+ if (!xDynResultSet.is())
+ return;
+
+ Reference<XResultSet> xResultSet = xDynResultSet->getStaticResultSet();
+ Reference<XRow> xRow(xResultSet, UNO_QUERY);
+ while (xResultSet->next())
+ {
+ if (!xRow->getBoolean(ROW_IS_FOLDER))
+ continue;
+ m_xView->append_text(xRow->getString(ROW_TITLE));
+ }
+ }
+ catch (const Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+}
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/dlg/ConnectionHelper.cxx b/dbaccess/source/ui/dlg/ConnectionHelper.cxx
new file mode 100644
index 000000000..6642d2895
--- /dev/null
+++ b/dbaccess/source/ui/dlg/ConnectionHelper.cxx
@@ -0,0 +1,720 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <core_resource.hxx>
+#include "dsnItem.hxx"
+#include "ConnectionHelper.hxx"
+#include <IItemSetHelper.hxx>
+#include <strings.hrc>
+#include <svl/itemset.hxx>
+#include <unotools/moduleoptions.hxx>
+#include <unotools/pathoptions.hxx>
+#include <svl/stritem.hxx>
+#include <dsitems.hxx>
+#include <osl/diagnose.h>
+#include <vcl/svapp.hxx>
+#include <vcl/weld.hxx>
+#include <sfx2/filedlghelper.hxx>
+#include <vcl/stdtext.hxx>
+#include <sqlmessage.hxx>
+#include "dsselect.hxx"
+#include <svl/filenotation.hxx>
+#include <com/sun/star/awt/XSystemDependentWindowPeer.hpp>
+#include <com/sun/star/ui/dialogs/XFolderPicker2.hpp>
+#include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
+#include <com/sun/star/lang/SystemDependent.hpp>
+#include <com/sun/star/mozilla/MozillaBootstrap.hpp>
+#include <com/sun/star/task/InteractionHandler.hpp>
+#include <com/sun/star/ucb/XProgressHandler.hpp>
+#include <ucbhelper/commandenvironment.hxx>
+#include <ucbhelper/content.hxx>
+#include "finteraction.hxx"
+#include <tools/urlobj.hxx>
+#include <tools/diagnose_ex.h>
+
+#if defined _WIN32
+#include <rtl/process.h>
+#include <vcl/sysdata.hxx>
+#include "adodatalinks.hxx"
+#endif
+
+#include <com/sun/star/mozilla/XMozillaBootstrap.hpp>
+#include <comphelper/processfactory.hxx>
+#include <comphelper/string.hxx>
+
+namespace dbaui
+{
+ using namespace ::com::sun::star;
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::ucb;
+ using namespace ::com::sun::star::ui::dialogs;
+ using namespace ::com::sun::star::sdbc;
+ using namespace ::com::sun::star::beans;
+ using namespace ::com::sun::star::lang;
+ using namespace ::com::sun::star::container;
+ using namespace ::com::sun::star::mozilla;
+ using namespace ::dbtools;
+ using namespace ::svt;
+
+ OConnectionHelper::OConnectionHelper(weld::Container* pPage, weld::DialogController* pController, const OUString& _rUIXMLDescription, const OString& _rId, const SfxItemSet& _rCoreAttrs)
+ : OGenericAdministrationPage(pPage, pController, _rUIXMLDescription, _rId, _rCoreAttrs)
+ , m_bUserGrabFocus(false)
+ , m_pCollection(nullptr)
+ , m_xFT_Connection(m_xBuilder->weld_label("browseurllabel"))
+ , m_xPB_Connection(m_xBuilder->weld_button("browse"))
+ , m_xPB_CreateDB(m_xBuilder->weld_button("create"))
+ , m_xConnectionURL(new OConnectionURLEdit(m_xBuilder->weld_entry("browseurl"), m_xBuilder->weld_label("browselabel")))
+ {
+ // extract the datasource type collection from the item set
+ const DbuTypeCollectionItem* pCollectionItem = dynamic_cast<const DbuTypeCollectionItem*>( _rCoreAttrs.GetItem(DSID_TYPECOLLECTION) );
+ if (pCollectionItem)
+ m_pCollection = pCollectionItem->getCollection();
+ m_xPB_Connection->connect_clicked(LINK(this, OConnectionHelper, OnBrowseConnections));
+ m_xPB_CreateDB->connect_clicked(LINK(this, OConnectionHelper, OnCreateDatabase));
+ OSL_ENSURE(m_pCollection, "OConnectionHelper::OConnectionHelper : really need a DSN type collection !");
+ m_xConnectionURL->SetTypeCollection(m_pCollection);
+
+ m_xConnectionURL->connect_focus_in(LINK(this, OConnectionHelper, GetFocusHdl));
+ m_xConnectionURL->connect_focus_out(LINK(this, OConnectionHelper, LoseFocusHdl));
+ }
+
+ OConnectionHelper::~OConnectionHelper()
+ {
+ m_xConnectionURL.reset();
+ }
+
+ void OConnectionHelper::implInitControls(const SfxItemSet& _rSet, bool _bSaveValue)
+ {
+ // check whether or not the selection is invalid or readonly (invalid implies readonly, but not vice versa)
+ bool bValid, bReadonly;
+ getFlags(_rSet, bValid, bReadonly);
+
+ m_xFT_Connection->show();
+ m_xConnectionURL->show();
+ m_xConnectionURL->ShowPrefix( ::dbaccess::DST_JDBC == m_pCollection->determineType(m_eType) );
+
+ bool bEnableBrowseButton = m_pCollection->supportsBrowsing( m_eType );
+ m_xPB_Connection->set_visible( bEnableBrowseButton );
+
+ bool bEnableCreateButton = m_pCollection->supportsDBCreation( m_eType );
+ m_xPB_CreateDB->set_visible( bEnableCreateButton );
+
+ const SfxStringItem* pUrlItem = _rSet.GetItem<SfxStringItem>(DSID_CONNECTURL);
+
+ // forward the values to the controls
+ if ( bValid )
+ {
+ OUString sUrl = pUrlItem->GetValue();
+ setURL( sUrl );
+
+ checkTestConnection();
+ m_xConnectionURL->save_value();
+ }
+
+ OGenericAdministrationPage::implInitControls(_rSet, _bSaveValue);
+ }
+
+ void OConnectionHelper::implUpdateURLDependentStates() const
+ {
+ OSL_PRECOND( m_pAdminDialog && m_pCollection, "OConnectionHelper::implUpdateURLDependentStates: no admin dialog!" );
+ if ( !m_pAdminDialog || !m_pCollection )
+ return;
+
+ if ( m_pCollection->isFileSystemBased(m_eType) )
+ m_pAdminDialog->enableConfirmSettings( !getURLNoPrefix().isEmpty() );
+ }
+
+ IMPL_LINK_NOARG(OConnectionHelper, OnBrowseConnections, weld::Button&, void)
+ {
+ OSL_ENSURE(m_pAdminDialog,"No Admin dialog set! ->GPF");
+ const ::dbaccess::DATASOURCE_TYPE eType = m_pCollection->determineType(m_eType);
+ switch ( eType )
+ {
+ case ::dbaccess::DST_DBASE:
+ case ::dbaccess::DST_FLAT:
+ {
+ try
+ {
+ Reference< XFolderPicker2 > xFolderPicker = sfx2::createFolderPicker(m_xORB, GetFrameWeld());
+
+ bool bDoBrowse = false;
+ OUString sOldPath = getURLNoPrefix();
+ do
+ {
+ if (!sOldPath.isEmpty())
+ xFolderPicker->setDisplayDirectory(sOldPath);
+ if (0 == xFolderPicker->execute())
+ // cancelled by the user
+ return;
+
+ sOldPath = xFolderPicker->getDirectory();
+ switch (checkPathExistence(sOldPath))
+ {
+ case RET_RETRY:
+ bDoBrowse = true;
+ break;
+ case RET_CANCEL:
+ return;
+ default:
+ break;
+ }
+ }
+ while (bDoBrowse);
+
+ OUString sSelectedDirectory = xFolderPicker->getDirectory();
+ INetURLObject aSelectedDirectory( sSelectedDirectory, INetURLObject::EncodeMechanism::WasEncoded, RTL_TEXTENCODING_UTF8 );
+
+ // for UI purpose, we don't want to have the path encoded
+ sSelectedDirectory = aSelectedDirectory.GetMainURL( INetURLObject::DecodeMechanism::WithCharset );
+
+ setURLNoPrefix( sSelectedDirectory );
+ SetRoadmapStateValue(true);
+ callModifiedHdl();
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+ break;
+ case ::dbaccess::DST_CALC:
+ {
+ SvtModuleOptions aModule;
+ ::sfx2::FileDialogHelper aFileDlg(
+ ui::dialogs::TemplateDescription::FILEOPEN_READONLY_VERSION,
+ FileDialogFlags::NONE,
+ aModule.GetFactoryEmptyDocumentURL(SvtModuleOptions::EFactory::CALC)
+ ,SfxFilterFlags::IMPORT, SfxFilterFlags::NONE, GetFrameWeld());
+ askForFileName(aFileDlg);
+ }
+ break;
+ case ::dbaccess::DST_WRITER:
+ {
+ SvtModuleOptions aModule;
+ ::sfx2::FileDialogHelper aFileDlg(
+ ui::dialogs::TemplateDescription::FILEOPEN_READONLY_VERSION,
+ FileDialogFlags::NONE,
+ aModule.GetFactoryEmptyDocumentURL(SvtModuleOptions::EFactory::WRITER),
+ SfxFilterFlags::IMPORT, SfxFilterFlags::NONE, GetFrameWeld());
+ askForFileName(aFileDlg);
+ }
+ break;
+ case ::dbaccess::DST_MSACCESS:
+ {
+ OUString sFilterName(DBA_RES (STR_MSACCESS_FILTERNAME));
+ ::sfx2::FileDialogHelper aFileDlg(
+ ui::dialogs::TemplateDescription::FILEOPEN_READONLY_VERSION,
+ FileDialogFlags::NONE, GetFrameWeld());
+ aFileDlg.AddFilter(sFilterName,"*.mdb;*.mde");
+ aFileDlg.SetCurrentFilter(sFilterName);
+ askForFileName(aFileDlg);
+ }
+ break;
+ case ::dbaccess::DST_MSACCESS_2007:
+ {
+ OUString sFilterName2(DBA_RES (STR_MSACCESS_2007_FILTERNAME));
+ ::sfx2::FileDialogHelper aFileDlg(
+ ui::dialogs::TemplateDescription::FILEOPEN_READONLY_VERSION,
+ FileDialogFlags::NONE, GetFrameWeld());
+ aFileDlg.AddFilter(sFilterName2,"*.accdb;*.accde");
+ aFileDlg.SetCurrentFilter(sFilterName2);
+ askForFileName(aFileDlg);
+ }
+ break;
+ case ::dbaccess::DST_MYSQL_ODBC:
+ case ::dbaccess::DST_ODBC:
+ {
+ // collect all ODBC data source names
+ OUString sCurrDatasource = getURLNoPrefix();
+ OUString sDataSource;
+ if ( getSelectedDataSource(sDataSource,sCurrDatasource) && !sDataSource.isEmpty() )
+ {
+ setURLNoPrefix(sDataSource);
+ SetRoadmapStateValue(true);
+ callModifiedHdl();
+ }
+ else
+ return;
+ }
+ break;
+#if defined _WIN32
+ case ::dbaccess::DST_ADO:
+ {
+ OUString sOldDataSource=getURLNoPrefix();
+ OUString sNewDataSource;
+ HWND hWnd = nullptr;
+
+ weld::Window* pDialog = GetFrameWeld();
+ css::uno::Reference<css::awt::XSystemDependentWindowPeer> xSysDepWin(pDialog->GetXWindow(), css::uno::UNO_QUERY);
+ if (xSysDepWin.is())
+ {
+ css::uno::Sequence<sal_Int8> aProcessIdent(16);
+ rtl_getGlobalProcessId(reinterpret_cast<sal_uInt8*>(aProcessIdent.getArray()));
+ css::uno::Any aAny = xSysDepWin->getWindowHandle(aProcessIdent, css::lang::SystemDependent::SYSTEM_WIN32);
+ sal_Int64 tmp(0);
+ aAny >>= tmp;
+ hWnd = reinterpret_cast<HWND>(tmp);
+ }
+
+ sNewDataSource = getAdoDatalink(reinterpret_cast<sal_IntPtr>(hWnd),sOldDataSource);
+ if ( !sNewDataSource.isEmpty() )
+ {
+ setURLNoPrefix(sNewDataSource);
+ SetRoadmapStateValue(true);
+ callModifiedHdl();
+ }
+ }
+ break;
+#endif
+ case ::dbaccess::DST_MOZILLA:
+ case ::dbaccess::DST_THUNDERBIRD:
+ {
+ MozillaProductType profileType = MozillaProductType_Mozilla;
+ if (eType == ::dbaccess::DST_THUNDERBIRD)
+ profileType = MozillaProductType_Thunderbird;
+
+ Reference<XComponentContext> xContext = ::comphelper::getProcessComponentContext();
+ Reference<XMozillaBootstrap> xMozillaBootstrap = MozillaBootstrap::create(xContext);
+
+ // collect all Mozilla Profiles
+ css::uno::Sequence< OUString > list;
+
+ xMozillaBootstrap->getProfileList( profileType, list );
+ const OUString * pArray = list.getConstArray();
+
+ sal_Int32 count = list.getLength();
+
+ std::set<OUString> aProfiles;
+ for (sal_Int32 index=0; index < count; index++)
+ aProfiles.insert(pArray[index]);
+
+ // execute the select dialog
+ ODatasourceSelectDialog aSelector(GetFrameWeld(), aProfiles);
+ OUString sOldProfile=getURLNoPrefix();
+
+ if (!sOldProfile.isEmpty())
+ aSelector.Select(sOldProfile);
+ else
+ aSelector.Select(xMozillaBootstrap->getDefaultProfile(profileType));
+
+ if (RET_OK == aSelector.run())
+ setURLNoPrefix(aSelector.GetSelected());
+ break;
+ }
+ case ::dbaccess::DST_FIREBIRD:
+ {
+ OUString sFilterName(DBA_RES (STR_FIREBIRD_FILTERNAME));
+ ::sfx2::FileDialogHelper aFileDlg(
+ ui::dialogs::TemplateDescription::FILEOPEN_SIMPLE,
+ FileDialogFlags::NONE, GetFrameWeld());
+ aFileDlg.AddFilter(sFilterName,"*.fdb");
+ aFileDlg.SetCurrentFilter(sFilterName);
+ askForFileName(aFileDlg);
+ break;
+ }
+ default:
+ break;
+ }
+
+ checkTestConnection();
+ }
+
+ IMPL_LINK_NOARG(OConnectionHelper, OnCreateDatabase, weld::Button&, void)
+ {
+ OSL_ENSURE(m_pAdminDialog,"No Admin dialog set! ->GPF");
+ const ::dbaccess::DATASOURCE_TYPE eType = m_pCollection->determineType(m_eType);
+ switch ( eType )
+ {
+ case ::dbaccess::DST_FIREBIRD:
+ {
+ OUString sFilterName(DBA_RES (STR_FIREBIRD_FILTERNAME));
+ ::sfx2::FileDialogHelper aFileDlg(
+ ui::dialogs::TemplateDescription::FILESAVE_AUTOEXTENSION,
+ FileDialogFlags::NONE, GetFrameWeld());
+ aFileDlg.AddFilter(sFilterName,"*.fdb");
+ aFileDlg.SetCurrentFilter(sFilterName);
+ askForFileName(aFileDlg);
+ break;
+ }
+ default:
+ break;
+ }
+
+ checkTestConnection();
+ }
+
+ bool OConnectionHelper::checkTestConnection()
+ {
+ return true;
+ }
+
+ void OConnectionHelper::impl_setURL( std::u16string_view _rURL, bool _bPrefix )
+ {
+ OUString sURL( comphelper::string::stripEnd(_rURL, '*') );
+ OSL_ENSURE( m_pCollection, "OConnectionHelper::impl_setURL: have no interpreter for the URLs!" );
+
+ if ( m_pCollection && !sURL.isEmpty() )
+ {
+ if ( m_pCollection->isFileSystemBased( m_eType ) )
+ {
+ // get the two parts: prefix and file URL
+ OUString sTypePrefix, sFileURLEncoded;
+ if ( _bPrefix )
+ {
+ sTypePrefix = m_pCollection->getPrefix( m_eType );
+ sFileURLEncoded = m_pCollection->cutPrefix( sURL );
+ }
+ else
+ {
+ sFileURLEncoded = sURL;
+ }
+
+ // substitute any variables
+ sFileURLEncoded = SvtPathOptions().SubstituteVariable( sFileURLEncoded );
+
+ // decode the URL
+ sURL = sTypePrefix;
+ if ( !sFileURLEncoded.isEmpty() )
+ {
+ OFileNotation aFileNotation(sFileURLEncoded);
+ // set this decoded URL as text
+ sURL += aFileNotation.get(OFileNotation::N_SYSTEM);
+ }
+ }
+ }
+
+ if ( _bPrefix )
+ m_xConnectionURL->SetText( sURL );
+ else
+ m_xConnectionURL->SetTextNoPrefix( sURL );
+
+ implUpdateURLDependentStates();
+ }
+
+ OUString OConnectionHelper::impl_getURL() const
+ {
+ // get the pure text
+ OUString sURL = m_xConnectionURL->GetTextNoPrefix();
+
+ OSL_ENSURE( m_pCollection, "OConnectionHelper::impl_getURL: have no interpreter for the URLs!" );
+
+ if ( m_pCollection && !sURL.isEmpty() )
+ {
+ if ( m_pCollection->isFileSystemBased( m_eType ) )
+ {
+ // get the two parts: prefix and file URL
+ OUString sFileURLDecoded = sURL;
+
+ sURL = OUString();
+ if ( !sFileURLDecoded.isEmpty() )
+ {
+ OFileNotation aFileNotation( sFileURLDecoded, OFileNotation::N_SYSTEM );
+ sURL += aFileNotation.get( OFileNotation::N_URL );
+ }
+
+ // encode the URL
+ INetURLObject aFileURL( sFileURLDecoded, INetURLObject::EncodeMechanism::All, RTL_TEXTENCODING_UTF8 );
+ sFileURLDecoded = aFileURL.GetMainURL( INetURLObject::DecodeMechanism::NONE );
+ }
+ }
+ return sURL;
+ }
+
+ void OConnectionHelper::setURL( std::u16string_view _rURL )
+ {
+ impl_setURL( _rURL, true );
+ }
+
+ OUString OConnectionHelper::getURLNoPrefix( ) const
+ {
+ return impl_getURL();
+ }
+
+ void OConnectionHelper::setURLNoPrefix( std::u16string_view _rURL )
+ {
+ impl_setURL( _rURL, false );
+ }
+
+ sal_Int32 OConnectionHelper::checkPathExistence(const OUString& _rURL)
+ {
+ IS_PATH_EXIST e_exists = pathExists(_rURL, false);
+ if (!m_pCollection->supportsDBCreation(m_eType) &&
+ (( e_exists == PATH_NOT_EXIST) || ( e_exists == PATH_NOT_KNOWN)))
+ {
+ OUString sQuery(DBA_RES(STR_ASK_FOR_DIRECTORY_CREATION));
+ OFileNotation aTransformer(_rURL);
+ sQuery = sQuery.replaceFirst("$path$", aTransformer.get(OFileNotation::N_SYSTEM));
+
+ m_bUserGrabFocus = false;
+ std::unique_ptr<weld::MessageDialog> xQueryBox(Application::CreateMessageDialog(GetFrameWeld(),
+ VclMessageType::Question, VclButtonsType::YesNo,
+ sQuery));
+ xQueryBox->set_default_response(RET_YES);
+ sal_Int32 nQueryResult = xQueryBox->run();
+ m_bUserGrabFocus = true;
+
+ switch (nQueryResult)
+ {
+ case RET_YES:
+ {
+ bool bTryCreate = false;
+ do
+ {
+ if ( !createDirectoryDeep(_rURL) )
+ { // could not create the directory
+ sQuery = DBA_RES(STR_COULD_NOT_CREATE_DIRECTORY);
+ sQuery = sQuery.replaceFirst("$name$", aTransformer.get(OFileNotation::N_SYSTEM));
+
+ m_bUserGrabFocus = false;
+
+ std::unique_ptr<weld::MessageDialog> xWhatToDo(Application::CreateMessageDialog(GetFrameWeld(),
+ VclMessageType::Question, VclButtonsType::NONE,
+ sQuery));
+ xWhatToDo->add_button(GetStandardText(StandardButtonType::Retry), RET_RETRY);
+ xWhatToDo->add_button(GetStandardText(StandardButtonType::Cancel), RET_CANCEL);
+ xWhatToDo->set_default_response(RET_RETRY);
+ nQueryResult = xWhatToDo->run();
+ m_bUserGrabFocus = true;
+
+ if (RET_RETRY == nQueryResult)
+ bTryCreate = true;
+ else
+ {
+ SetRoadmapStateValue(false);
+ callModifiedHdl();
+ return RET_RETRY;
+ }
+ }
+ }
+ while (bTryCreate);
+ }
+ break;
+
+ case RET_NO:
+ callModifiedHdl();
+ return RET_OK;
+
+ default:
+ // cancelled
+ SetRoadmapStateValue(false);
+ callModifiedHdl();
+ return RET_CANCEL;
+ }
+ }
+/* else
+ {
+ // TODO: error msg
+ return RET_CANCEL;
+ } */
+ SetRoadmapStateValue(true);
+ callModifiedHdl();
+ return RET_OK;
+ }
+
+ IS_PATH_EXIST OConnectionHelper::pathExists(const OUString& _rURL, bool bIsFile) const
+ {
+ ::ucbhelper::Content aCheckExistence;
+ IS_PATH_EXIST eExists = PATH_NOT_EXIST;
+ Reference< css::task::XInteractionHandler > xInteractionHandler =
+ task::InteractionHandler::createWithParent(m_xORB, nullptr);
+ rtl::Reference<OFilePickerInteractionHandler> pHandler = new OFilePickerInteractionHandler(xInteractionHandler);
+ xInteractionHandler = pHandler;
+
+ Reference< XCommandEnvironment > xCmdEnv = new ::ucbhelper::CommandEnvironment( xInteractionHandler, Reference< XProgressHandler >() );
+ try
+ {
+ aCheckExistence = ::ucbhelper::Content(_rURL, xCmdEnv, comphelper::getProcessComponentContext());
+ const bool bExists = bIsFile? aCheckExistence.isDocument(): aCheckExistence.isFolder();
+ eExists = bExists? PATH_EXIST: PATH_NOT_EXIST;
+ }
+ catch (const Exception&)
+ {
+ eExists = pHandler->isDoesNotExist() ? PATH_NOT_EXIST : (bIsFile ? PATH_NOT_EXIST : PATH_NOT_KNOWN);
+ }
+ return eExists;
+ }
+
+ IMPL_LINK_NOARG(OConnectionHelper, GetFocusHdl, weld::Widget&, void)
+ {
+ if (!m_pCollection->isFileSystemBased(m_eType))
+ return;
+ if (!m_bUserGrabFocus)
+ return;
+ // URL edit field got the focus
+ m_xConnectionURL->SaveValueNoPrefix();
+ }
+
+ IMPL_LINK_NOARG(OConnectionHelper, LoseFocusHdl, weld::Widget&, void)
+ {
+ if (!m_pCollection->isFileSystemBased(m_eType))
+ return;
+ if (!m_bUserGrabFocus)
+ return;
+ // URL edit field lost the focus
+ commitURL();
+ }
+
+ bool OConnectionHelper::createDirectoryDeep(std::u16string_view _rPathURL)
+ {
+ // get a URL object analyzing the URL for us ...
+ INetURLObject aParser;
+ aParser.SetURL(_rPathURL);
+
+ INetProtocol eProtocol = aParser.GetProtocol();
+
+ std::vector< OUString > aToBeCreated; // the to-be-created levels
+
+ // search a level which exists
+ IS_PATH_EXIST eParentExists = PATH_NOT_EXIST;
+ while ( eParentExists == PATH_NOT_EXIST && aParser.getSegmentCount())
+ {
+ aToBeCreated.push_back(aParser.getName()); // remember the local name for creation
+ aParser.removeSegment(); // cut the local name
+ eParentExists = pathExists(aParser.GetMainURL(INetURLObject::DecodeMechanism::NONE), false);
+ }
+
+ if (!aParser.getSegmentCount())
+ return false;
+
+ // create all the missing levels
+ try
+ {
+ // the parent content
+ Reference< XCommandEnvironment > xEmptyEnv;
+ ::ucbhelper::Content aParent(aParser.GetMainURL(INetURLObject::DecodeMechanism::NONE), xEmptyEnv, comphelper::getProcessComponentContext());
+
+ OUString sContentType;
+ if ( INetProtocol::File == eProtocol )
+ {
+ sContentType = "application/vnd.sun.staroffice.fsys-folder";
+ // the file UCP currently does not support the ContentType property
+ }
+ else
+ {
+ Any aContentType = aParent.getPropertyValue("ContentType");
+ aContentType >>= sContentType;
+ }
+
+ // the properties which need to be set on the new content
+ Sequence< OUString > aNewDirectoryProperties { "Title" };
+
+ // loop
+ for ( std::vector< OUString >::const_reverse_iterator aLocalName = aToBeCreated.rbegin();
+ aLocalName != aToBeCreated.rend();
+ ++aLocalName
+ )
+ {
+ // the values to be set
+ Sequence< Any > aNewDirectoryAttributes{ Any(* aLocalName) };
+ if (!aParent.insertNewContent(sContentType, aNewDirectoryProperties, aNewDirectoryAttributes, aParent))
+ return false;
+ }
+ }
+ catch ( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ return false;
+ }
+
+ return true;
+ }
+
+ void OConnectionHelper::fillWindows(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList)
+ {
+ _rControlList.emplace_back(new ODisableWidgetWrapper<weld::Label>(m_xFT_Connection.get()));
+ _rControlList.emplace_back(new ODisableWidgetWrapper<weld::Button>(m_xPB_Connection.get()));
+ _rControlList.emplace_back(new ODisableWidgetWrapper<weld::Button>(m_xPB_CreateDB.get()));
+ }
+
+ void OConnectionHelper::fillControls(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList)
+ {
+ _rControlList.emplace_back( new OSaveValueWidgetWrapper<OConnectionURLEdit>( m_xConnectionURL.get() ) );
+ }
+
+ bool OConnectionHelper::commitURL()
+ {
+ OUString sOldPath = m_xConnectionURL->GetSavedValueNoPrefix();
+ OUString sURL = m_xConnectionURL->GetTextNoPrefix();
+
+ if ( m_pCollection->isFileSystemBased(m_eType) )
+ {
+ if ( ( sURL != sOldPath ) && !sURL.isEmpty() )
+ { // the text changed since entering the control
+
+ // the path may be in system notation...
+ OFileNotation aTransformer(sURL);
+ sURL = aTransformer.get(OFileNotation::N_URL);
+
+ const ::dbaccess::DATASOURCE_TYPE eType = m_pCollection->determineType(m_eType);
+
+ if ( ( ::dbaccess::DST_CALC == eType) || ( ::dbaccess::DST_WRITER == eType) || ( ::dbaccess::DST_MSACCESS == eType) || ( ::dbaccess::DST_MSACCESS_2007 == eType) )
+ {
+ if( pathExists(sURL, true) == PATH_NOT_EXIST )
+ {
+ OUString sFile = DBA_RES( STR_FILE_DOES_NOT_EXIST );
+ sFile = sFile.replaceFirst("$file$", aTransformer.get(OFileNotation::N_SYSTEM));
+ OSQLWarningBox aWarning(GetFrameWeld(), sFile);
+ aWarning.run();
+ setURLNoPrefix(sOldPath);
+ SetRoadmapStateValue(false);
+ callModifiedHdl();
+ return false;
+ }
+ }
+ else
+ {
+ switch (checkPathExistence(sURL))
+ {
+ case RET_RETRY:
+ m_bUserGrabFocus = false;
+ m_xConnectionURL->grab_focus();
+ m_bUserGrabFocus = true;
+ return false;
+
+ case RET_CANCEL:
+ setURLNoPrefix(sOldPath);
+ return false;
+ }
+ }
+ }
+ }
+
+ setURLNoPrefix(sURL);
+ m_xConnectionURL->SaveValueNoPrefix();
+ return true;
+ }
+
+ void OConnectionHelper::askForFileName(::sfx2::FileDialogHelper& _aFileOpen)
+ {
+ OUString sOldPath = getURLNoPrefix();
+ if ( !sOldPath.isEmpty() )
+ _aFileOpen.SetDisplayDirectory(sOldPath);
+ else
+ _aFileOpen.SetDisplayDirectory( SvtPathOptions().GetWorkPath() );
+ if (ERRCODE_NONE == _aFileOpen.Execute())
+ {
+ setURLNoPrefix(_aFileOpen.GetPath());
+ SetRoadmapStateValue(checkTestConnection());
+ callModifiedHdl();
+ }
+ }
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/dlg/ConnectionHelper.hxx b/dbaccess/source/ui/dlg/ConnectionHelper.hxx
new file mode 100644
index 000000000..b4c00548f
--- /dev/null
+++ b/dbaccess/source/ui/dlg/ConnectionHelper.hxx
@@ -0,0 +1,103 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include "adminpages.hxx"
+#include <curledit.hxx>
+#include <sfx2/filedlghelper.hxx>
+
+namespace dbaui
+{
+
+ enum IS_PATH_EXIST
+ {
+ PATH_NOT_EXIST = 0,
+ PATH_EXIST,
+ PATH_NOT_KNOWN
+ };
+
+ class OConnectionHelper : public OGenericAdministrationPage
+ {
+ bool m_bUserGrabFocus;
+
+ public:
+ OConnectionHelper(weld::Container* pPage, weld::DialogController* pController, const OUString& _rUIXMLDescription, const OString& _rId, const SfxItemSet& _rCoreAttrs);
+ virtual ~OConnectionHelper() override;
+
+ OUString m_eType; // the type can't be changed in this class, so we hold it as member.
+ // setting/retrieving the current connection URL
+ // necessary because for some types, the URL must be decoded for display purposes
+ ::dbaccess::ODsnTypeCollection* m_pCollection; /// the DSN type collection instance
+
+ std::unique_ptr<weld::Label> m_xFT_Connection;
+ std::unique_ptr<weld::Button> m_xPB_Connection;
+ std::unique_ptr<weld::Button> m_xPB_CreateDB;
+ std::unique_ptr<OConnectionURLEdit> m_xConnectionURL;
+
+ public:
+
+ // <method>OGenericAdministrationPage::fillControls</method>
+ virtual void fillControls(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) override;
+ // <method>OGenericAdministrationPage::fillWindows</method>
+ virtual void fillWindows(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) override;
+ virtual void implInitControls(const SfxItemSet& _rSet, bool _bSaveValue) override;
+
+ // setting/retrieving the current connection URL
+ // necessary because for some types, the URL must be decoded for display purposes
+ //String getURL( OConnectionURLEdit* _m_pConnection ) const;
+ //void setURL( const OUString& _rURL, OConnectionURLEdit* _m_pConnection );
+
+ OUString getURLNoPrefix( ) const;
+ void setURLNoPrefix( std::u16string_view _rURL );
+
+ /** checks if the path is existence
+ @param _rURL
+ The URL to check.
+ */
+ sal_Int32 checkPathExistence(const OUString& _rURL);
+
+ IS_PATH_EXIST pathExists(const OUString& _rURL, bool bIsFile) const;
+ bool createDirectoryDeep(std::u16string_view _rPathNormalized);
+ bool commitURL();
+
+ /** opens the FileOpen dialog and asks for a FileName
+ @param _aFileOpen
+ Executes the file open dialog, which must be filled from caller.
+ */
+ void askForFileName(::sfx2::FileDialogHelper& _aFileOpen);
+
+ protected:
+ void setURL( std::u16string_view _rURL );
+ virtual bool checkTestConnection();
+
+ private:
+ DECL_LINK(OnBrowseConnections, weld::Button&, void);
+ DECL_LINK(OnCreateDatabase, weld::Button&, void);
+ DECL_LINK(GetFocusHdl, weld::Widget&, void);
+ DECL_LINK(LoseFocusHdl, weld::Widget&, void);
+ OUString impl_getURL() const;
+ void impl_setURL( std::u16string_view _rURL, bool _bPrefix );
+ void implUpdateURLDependentStates() const;
+ };
+
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/dlg/ConnectionPage.cxx b/dbaccess/source/ui/dlg/ConnectionPage.cxx
new file mode 100644
index 000000000..7ff32140e
--- /dev/null
+++ b/dbaccess/source/ui/dlg/ConnectionPage.cxx
@@ -0,0 +1,284 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <config_java.h>
+#include "ConnectionPage.hxx"
+#include <core_resource.hxx>
+#include <IItemSetHelper.hxx>
+#include <strings.hrc>
+#include <dsmeta.hxx>
+#if HAVE_FEATURE_JAVA
+#include <jvmaccess/virtualmachine.hxx>
+#endif
+#include <svl/itemset.hxx>
+#include <svl/stritem.hxx>
+#include <svl/eitem.hxx>
+#include <dsitems.hxx>
+#include <helpids.h>
+#include <sqlmessage.hxx>
+#include <svl/filenotation.hxx>
+#include <com/sun/star/ucb/XProgressHandler.hpp>
+#include <connectivity/CommonTools.hxx>
+#include <o3tl/string_view.hxx>
+
+namespace dbaui
+{
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::ucb;
+ using namespace ::com::sun::star::ui::dialogs;
+ using namespace ::com::sun::star::sdbc;
+ using namespace ::com::sun::star::beans;
+ using namespace ::com::sun::star::lang;
+ using namespace ::com::sun::star::container;
+ using namespace ::dbtools;
+ using namespace ::svt;
+
+ std::unique_ptr<SfxTabPage> OConnectionTabPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* _rAttrSet)
+ {
+ return std::make_unique<OConnectionTabPage>(pPage, pController, *_rAttrSet);
+ }
+
+ // OConnectionTabPage
+ OConnectionTabPage::OConnectionTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& _rCoreAttrs)
+ : OConnectionHelper(pPage, pController, "dbaccess/ui/connectionpage.ui", "ConnectionPage", _rCoreAttrs)
+ , m_xFL2(m_xBuilder->weld_label("userlabel"))
+ , m_xUserNameLabel(m_xBuilder->weld_label("userNameLabel"))
+ , m_xUserName(m_xBuilder->weld_entry("userNameEntry"))
+ , m_xPasswordRequired(m_xBuilder->weld_check_button("passCheckbutton"))
+ , m_xFL3(m_xBuilder->weld_label("JDBCLabel"))
+ , m_xJavaDriverLabel(m_xBuilder->weld_label("javaDriverLabel"))
+ , m_xJavaDriver(m_xBuilder->weld_entry("driverEntry"))
+ , m_xTestJavaDriver(m_xBuilder->weld_button("driverButton"))
+ , m_xTestConnection(m_xBuilder->weld_button("connectionButton"))
+ {
+ m_xConnectionURL->connect_changed(LINK(this, OConnectionTabPage, OnEditModified));
+ m_xJavaDriver->connect_changed(LINK(this, OConnectionTabPage, OnEditModified));
+ m_xUserName->connect_changed(LINK(this, OGenericAdministrationPage, OnControlEntryModifyHdl));
+ m_xPasswordRequired->connect_toggled(LINK(this, OGenericAdministrationPage, OnControlModifiedButtonClick));
+
+ m_xTestConnection->connect_clicked(LINK(this,OGenericAdministrationPage,OnTestConnectionButtonClickHdl));
+ m_xTestJavaDriver->connect_clicked(LINK(this,OConnectionTabPage,OnTestJavaClickHdl));
+ }
+
+ OConnectionTabPage::~OConnectionTabPage()
+ {
+ }
+
+ void OConnectionTabPage::implInitControls(const SfxItemSet& _rSet, bool _bSaveValue)
+ {
+ // check whether or not the selection is invalid or readonly (invalid implies readonly, but not vice versa)
+ bool bValid, bReadonly;
+ getFlags(_rSet, bValid, bReadonly);
+
+ m_eType = m_pAdminDialog->getDatasourceType(_rSet);
+ OConnectionHelper::implInitControls( _rSet, _bSaveValue);
+
+ ::dbaccess::DATASOURCE_TYPE eType = m_pCollection->determineType(m_eType);
+ switch( eType )
+ {
+ case ::dbaccess::DST_DBASE:
+ m_xFT_Connection->set_label(DBA_RES(STR_DBASE_PATH_OR_FILE));
+ m_xConnectionURL->set_help_id(HID_DSADMIN_DBASE_PATH);
+ break;
+ case ::dbaccess::DST_FLAT:
+ m_xFT_Connection->set_label(DBA_RES(STR_FLAT_PATH_OR_FILE));
+ m_xConnectionURL->set_help_id(HID_DSADMIN_FLAT_PATH);
+ break;
+ case ::dbaccess::DST_CALC:
+ m_xFT_Connection->set_label(DBA_RES(STR_CALC_PATH_OR_FILE));
+ m_xConnectionURL->set_help_id(HID_DSADMIN_CALC_PATH);
+ break;
+ case ::dbaccess::DST_WRITER:
+ m_xFT_Connection->set_label(DBA_RES(STR_WRITER_PATH_OR_FILE));
+ m_xConnectionURL->set_help_id(HID_DSADMIN_WRITER_PATH);
+ break;
+ case ::dbaccess::DST_ADO:
+ m_xFT_Connection->set_label(DBA_RES(STR_COMMONURL));
+ break;
+ case ::dbaccess::DST_MSACCESS:
+ case ::dbaccess::DST_MSACCESS_2007:
+ m_xFT_Connection->set_label(DBA_RES(STR_MSACCESS_MDB_FILE));
+ m_xConnectionURL->set_help_id(HID_DSADMIN_MSACCESS_MDB_FILE);
+ break;
+ case ::dbaccess::DST_MYSQL_NATIVE:
+ case ::dbaccess::DST_MYSQL_JDBC:
+ m_xFT_Connection->set_label(DBA_RES(STR_MYSQL_DATABASE_NAME));
+ m_xConnectionURL->set_help_id( HID_DSADMIN_MYSQL_DATABASE );
+ break;
+ case ::dbaccess::DST_ORACLE_JDBC:
+ m_xFT_Connection->set_label(DBA_RES(STR_ORACLE_DATABASE_NAME));
+ m_xConnectionURL->set_help_id(HID_DSADMIN_ORACLE_DATABASE);
+ break;
+ case ::dbaccess::DST_MYSQL_ODBC:
+ case ::dbaccess::DST_ODBC:
+ m_xFT_Connection->set_label(DBA_RES(STR_NAME_OF_ODBC_DATASOURCE));
+ m_xConnectionURL->set_help_id( eType == ::dbaccess::DST_MYSQL_ODBC ? OString(HID_DSADMIN_MYSQL_ODBC_DATASOURCE) : OString(HID_DSADMIN_ODBC_DATASOURCE));
+ break;
+ case ::dbaccess::DST_LDAP:
+ m_xFT_Connection->set_label(DBA_RES(STR_HOSTNAME));
+ m_xConnectionURL->set_help_id( HID_DSADMIN_LDAP_HOSTNAME );
+ break;
+ case ::dbaccess::DST_MOZILLA:
+ m_xFT_Connection->set_label(DBA_RES(STR_MOZILLA_PROFILE_NAME));
+ m_xConnectionURL->set_help_id( HID_DSADMIN_MOZILLA_PROFILE_NAME );
+ break;
+ case ::dbaccess::DST_THUNDERBIRD:
+ m_xFT_Connection->set_label(DBA_RES(STR_THUNDERBIRD_PROFILE_NAME));
+ m_xConnectionURL->set_help_id( HID_DSADMIN_THUNDERBIRD_PROFILE_NAME );
+ break;
+ case ::dbaccess::DST_OUTLOOK:
+ case ::dbaccess::DST_OUTLOOKEXP:
+ case ::dbaccess::DST_EVOLUTION:
+ case ::dbaccess::DST_EVOLUTION_GROUPWISE:
+ case ::dbaccess::DST_EVOLUTION_LDAP:
+ case ::dbaccess::DST_KAB:
+ case ::dbaccess::DST_MACAB:
+ m_xFT_Connection->set_label(DBA_RES(STR_NO_ADDITIONAL_SETTINGS));
+ {
+ OUString sText = m_xFT_Connection->get_label();
+ sText = sText.replaceAll("%test",m_xTestConnection->get_label());
+ sText = sText.replaceAll("~","");
+ m_xFT_Connection->set_label(sText);
+ }
+ m_xConnectionURL->hide();
+ break;
+ case ::dbaccess::DST_JDBC:
+ default:
+ m_xFT_Connection->set_label(DBA_RES(STR_COMMONURL));
+ break;
+ }
+
+ AuthenticationMode eAuthMode( DataSourceMetaData::getAuthentication( m_eType ) );
+ bool bShowUserAuthenfication = ( eAuthMode != AuthNone );
+ bool bShowUser = ( eAuthMode == AuthUserPwd );
+
+ m_xPB_Connection->set_help_id(HID_DSADMIN_BROWSECONN);
+ m_xFL2->set_visible( bShowUserAuthenfication );
+ m_xUserNameLabel->set_visible( bShowUser && bShowUserAuthenfication );
+ m_xUserName->set_visible( bShowUser && bShowUserAuthenfication );
+ m_xPasswordRequired->set_visible( bShowUserAuthenfication );
+
+ // collect the items
+ const SfxStringItem* pUidItem = _rSet.GetItem<SfxStringItem>(DSID_USER);
+
+ const SfxStringItem* pJdbcDrvItem = _rSet.GetItem<SfxStringItem>(DSID_JDBCDRIVERCLASS);
+ const SfxStringItem* pUrlItem = _rSet.GetItem<SfxStringItem>(DSID_CONNECTURL);
+ const SfxBoolItem* pAllowEmptyPwd = _rSet.GetItem<SfxBoolItem>(DSID_PASSWORDREQUIRED);
+
+ // forward the values to the controls
+ if ( !bValid )
+ return;
+
+ m_xUserName->set_text(pUidItem->GetValue());
+ m_xPasswordRequired->set_active(pAllowEmptyPwd->GetValue());
+
+ const OUString& sUrl = pUrlItem->GetValue();
+ setURL( sUrl );
+
+ const bool bEnableJDBC = m_pCollection->determineType(m_eType) == ::dbaccess::DST_JDBC;
+ if ( !pJdbcDrvItem->GetValue().getLength() )
+ {
+ OUString sDefaultJdbcDriverName = m_pCollection->getJavaDriverClass(m_eType);
+ if ( !sDefaultJdbcDriverName.isEmpty() )
+ m_xJavaDriver->set_text(sDefaultJdbcDriverName);
+ }
+ else
+ m_xJavaDriver->set_text(pJdbcDrvItem->GetValue());
+
+ m_xJavaDriverLabel->set_visible(bEnableJDBC);
+ m_xJavaDriver->set_visible(bEnableJDBC);
+ m_xTestJavaDriver->set_visible(bEnableJDBC);
+ m_xTestJavaDriver->set_sensitive( !m_xJavaDriver->get_text().trim().isEmpty() );
+ m_xFL3->set_visible(bEnableJDBC);
+
+ checkTestConnection();
+
+ m_xUserName->save_value();
+ m_xConnectionURL->save_value();
+ m_xJavaDriver->save_value();
+ m_xPasswordRequired->save_state();
+ }
+
+ bool OConnectionTabPage::FillItemSet(SfxItemSet* _rSet)
+ {
+ bool bChangedSomething = false;
+
+ if (m_xUserName->get_value_changed_from_saved())
+ {
+ _rSet->Put(SfxStringItem(DSID_USER, m_xUserName->get_text()));
+ _rSet->Put(SfxStringItem(DSID_PASSWORD, OUString()));
+ bChangedSomething = true;
+ }
+
+ fillBool(*_rSet,m_xPasswordRequired.get(),DSID_PASSWORDREQUIRED,false, bChangedSomething);
+
+ if ( m_pCollection->determineType(m_eType) == ::dbaccess::DST_JDBC )
+ {
+ fillString(*_rSet,m_xJavaDriver.get(), DSID_JDBCDRIVERCLASS, bChangedSomething);
+ }
+
+ fillString(*_rSet,m_xConnectionURL.get(), DSID_CONNECTURL, bChangedSomething);
+
+ return bChangedSomething;
+ }
+ IMPL_LINK_NOARG(OConnectionTabPage, OnTestJavaClickHdl, weld::Button&, void)
+ {
+ OSL_ENSURE(m_pAdminDialog,"No Admin dialog set! ->GPF");
+ bool bSuccess = false;
+#if HAVE_FEATURE_JAVA
+ try
+ {
+ if ( !m_xJavaDriver->get_text().trim().isEmpty() )
+ {
+ ::rtl::Reference< jvmaccess::VirtualMachine > xJVM = ::connectivity::getJavaVM( m_pAdminDialog->getORB() );
+ m_xJavaDriver->set_text(m_xJavaDriver->get_text().trim()); // fdo#68341
+ bSuccess = ::connectivity::existsJavaClassByName(xJVM, o3tl::trim(m_xJavaDriver->get_text()));
+ }
+ }
+ catch(Exception&)
+ {
+ }
+#endif
+
+ TranslateId pMessage = bSuccess ? STR_JDBCDRIVER_SUCCESS : STR_JDBCDRIVER_NO_SUCCESS;
+ const MessageType mt = bSuccess ? MessageType::Info : MessageType::Error;
+ OSQLMessageBox aMsg(GetFrameWeld(), DBA_RES(pMessage), OUString(), MessBoxStyle::Ok | MessBoxStyle::DefaultOk, mt);
+ aMsg.run();
+ }
+ bool OConnectionTabPage::checkTestConnection()
+ {
+ OSL_ENSURE(m_pAdminDialog,"No Admin dialog set! ->GPF");
+ bool bEnableTestConnection = !m_xConnectionURL->get_visible() || !m_xConnectionURL->GetTextNoPrefix().isEmpty();
+ if ( m_pCollection->determineType(m_eType) == ::dbaccess::DST_JDBC )
+ bEnableTestConnection = bEnableTestConnection && (!m_xJavaDriver->get_text().trim().isEmpty());
+ m_xTestConnection->set_sensitive(bEnableTestConnection);
+ return true;
+ }
+ IMPL_LINK(OConnectionTabPage, OnEditModified, weld::Entry&, rEdit, void)
+ {
+ if (&rEdit == m_xJavaDriver.get())
+ m_xTestJavaDriver->set_sensitive( !m_xJavaDriver->get_text().trim().isEmpty() );
+
+ checkTestConnection();
+ // tell the listener we were modified
+ callModifiedHdl();
+ }
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/dlg/ConnectionPage.hxx b/dbaccess/source/ui/dlg/ConnectionPage.hxx
new file mode 100644
index 000000000..19e769462
--- /dev/null
+++ b/dbaccess/source/ui/dlg/ConnectionPage.hxx
@@ -0,0 +1,72 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include "ConnectionHelper.hxx"
+
+namespace dbaui
+{
+
+ // OConnectionTabPage
+
+ /** implements the connection page of the data source properties dialog.
+ */
+ class OConnectionTabPage final : public OConnectionHelper
+ {
+ private:
+ // user authentication
+ std::unique_ptr<weld::Label> m_xFL2;
+ std::unique_ptr<weld::Label> m_xUserNameLabel;
+ std::unique_ptr<weld::Entry> m_xUserName;
+ std::unique_ptr<weld::CheckButton> m_xPasswordRequired;
+
+ // jdbc driver
+ std::unique_ptr<weld::Label> m_xFL3;
+ std::unique_ptr<weld::Label> m_xJavaDriverLabel;
+ std::unique_ptr<weld::Entry> m_xJavaDriver;
+ std::unique_ptr<weld::Button> m_xTestJavaDriver;
+
+ // connection test
+ std::unique_ptr<weld::Button> m_xTestConnection;
+
+ // called when the test connection button was clicked
+ DECL_LINK(OnTestJavaClickHdl, weld::Button&, void);
+ DECL_LINK(OnEditModified, weld::Entry&, void);
+
+ public:
+ OConnectionTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& _rCoreAttrs);
+ static std::unique_ptr<SfxTabPage> Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* _rAttrSet);
+ virtual ~OConnectionTabPage() override;
+ virtual bool FillItemSet (SfxItemSet* _rCoreAttrs) override;
+
+ virtual void implInitControls(const SfxItemSet& _rSet, bool _bSaveValue) override;
+
+ /** changes the connection URL.
+ <p>The new URL must be of the type which is currently selected, only the parts which do not
+ affect the type may be changed (compared to the previous URL).</p>
+ */
+ private:
+ /** enables the test connection button, if allowed
+ */
+ virtual bool checkTestConnection() override;
+ };
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/dlg/ConnectionPageSetup.cxx b/dbaccess/source/ui/dlg/ConnectionPageSetup.cxx
new file mode 100644
index 000000000..8f57c24f9
--- /dev/null
+++ b/dbaccess/source/ui/dlg/ConnectionPageSetup.cxx
@@ -0,0 +1,153 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "ConnectionPageSetup.hxx"
+#include <strings.hrc>
+#include <core_resource.hxx>
+#include <IItemSetHelper.hxx>
+#include <svl/itemset.hxx>
+#include <dsitems.hxx>
+#include <svl/filenotation.hxx>
+#include <com/sun/star/ucb/XProgressHandler.hpp>
+
+namespace dbaui
+{
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::ucb;
+ using namespace ::com::sun::star::ui::dialogs;
+ using namespace ::com::sun::star::beans;
+ using namespace ::com::sun::star::lang;
+ using namespace ::com::sun::star::container;
+ using namespace ::svt;
+
+ std::unique_ptr<OGenericAdministrationPage> OConnectionTabPageSetup::CreateDbaseTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& _rAttrSet)
+ {
+ return std::make_unique<OConnectionTabPageSetup>( pPage, pController, "dbaccess/ui/dbwizconnectionpage.ui", "ConnectionPage", _rAttrSet, STR_DBASE_HELPTEXT, STR_DBASE_HEADERTEXT, STR_DBASE_PATH_OR_FILE );
+ }
+
+ std::unique_ptr<OGenericAdministrationPage> OConnectionTabPageSetup::CreateMSAccessTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& _rAttrSet)
+ {
+ return std::make_unique<OConnectionTabPageSetup>( pPage, pController, "dbaccess/ui/dbwizconnectionpage.ui", "ConnectionPage", _rAttrSet, STR_MSACCESS_HELPTEXT, STR_MSACCESS_HEADERTEXT, STR_MSACCESS_MDB_FILE );
+ }
+
+ std::unique_ptr<OGenericAdministrationPage> OConnectionTabPageSetup::CreateADOTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& _rAttrSet)
+ {
+ return std::make_unique<OConnectionTabPageSetup>( pPage, pController, "dbaccess/ui/dbwizconnectionpage.ui", "ConnectionPage", _rAttrSet, STR_ADO_HELPTEXT, STR_ADO_HEADERTEXT, STR_COMMONURL );
+ }
+
+ std::unique_ptr<OGenericAdministrationPage> OConnectionTabPageSetup::CreateODBCTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& _rAttrSet)
+ {
+ return std::make_unique<OConnectionTabPageSetup>( pPage, pController, "dbaccess/ui/dbwizconnectionpage.ui", "ConnectionPage", _rAttrSet, STR_ODBC_HELPTEXT, STR_ODBC_HEADERTEXT, STR_NAME_OF_ODBC_DATASOURCE );
+ }
+
+ std::unique_ptr<OGenericAdministrationPage> OConnectionTabPageSetup::CreateUserDefinedTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& _rAttrSet)
+ {
+ return std::make_unique<OConnectionTabPageSetup>(pPage, pController, "dbaccess/ui/dbwizconnectionpage.ui", "ConnectionPage", _rAttrSet, TranslateId(), TranslateId(), STR_COMMONURL);
+ }
+
+ OConnectionTabPageSetup::OConnectionTabPageSetup(weld::Container* pPage, weld::DialogController* pController, const OUString& _rUIXMLDescription, const OString& _rId, const SfxItemSet& _rCoreAttrs, TranslateId pHelpTextResId, TranslateId pHeaderResId, TranslateId pUrlResId)
+ : OConnectionHelper(pPage, pController, _rUIXMLDescription, _rId, _rCoreAttrs)
+ , m_xHelpText(m_xBuilder->weld_label("helptext"))
+ , m_xHeaderText(m_xBuilder->weld_label("header"))
+ {
+
+ if (pHelpTextResId)
+ {
+ OUString sHelpText = DBA_RES(pHelpTextResId);
+ m_xHelpText->set_label(sHelpText);
+ }
+ else
+ m_xHelpText->hide();
+
+ if (pHeaderResId)
+ m_xHeaderText->set_label(DBA_RES(pHeaderResId));
+
+ if (pUrlResId)
+ {
+ OUString sLabelText = DBA_RES(pUrlResId);
+ m_xFT_Connection->set_label(sLabelText);
+ }
+ else
+ m_xFT_Connection->hide();
+
+ m_xConnectionURL->connect_changed(LINK(this, OConnectionTabPageSetup, OnEditModified));
+
+ SetRoadmapStateValue(false);
+ }
+
+ OConnectionTabPageSetup::~OConnectionTabPageSetup()
+ {
+ }
+
+ void OConnectionTabPageSetup::implInitControls(const SfxItemSet& _rSet, bool _bSaveValue)
+ {
+ m_eType = m_pAdminDialog->getDatasourceType(_rSet);
+ // special handling for oracle, this can only happen
+ // if the user enters the same url as used for Oracle and we are on the JDBC path
+ //! TODO
+ //if ( ::dbaccess::DST_ORACLE_JDBC == m_eType )
+ // m_eType = ::dbaccess::DST_JDBC;
+ if(m_pCollection->determineType(m_eType) == ::dbaccess::DST_POSTGRES){
+ SetRoadmapStateValue(true);
+ }
+
+ OConnectionHelper::implInitControls(_rSet, _bSaveValue);
+
+ //! TODO
+ //if ( m_eType >= ::dbaccess::DST_USERDEFINE1 )
+ //{
+ // OUString sDisplayName = m_pCollection->getTypeDisplayName(m_eType);
+ // FixedText* ppTextControls[] ={&m_aFT_Connection};
+ // for (size_t i = 0; i < sizeof(ppTextControls)/sizeof(ppTextControls[0]); ++i)
+ // {
+ // ppTextControls[i]->SetText(sDisplayName);
+ // }
+ //}
+
+ callModifiedHdl();
+ }
+
+ bool OConnectionTabPageSetup::commitPage( ::vcl::WizardTypes::CommitPageReason /*_eReason*/ )
+ {
+ return commitURL();
+ }
+
+ bool OConnectionTabPageSetup::FillItemSet(SfxItemSet* _rSet)
+ {
+ bool bChangedSomething = false;
+ fillString(*_rSet,m_xConnectionURL.get(), DSID_CONNECTURL, bChangedSomething);
+ return bChangedSomething;
+ }
+
+ bool OConnectionTabPageSetup::checkTestConnection()
+ {
+ if ( m_pCollection->determineType(m_eType) == ::dbaccess::DST_POSTGRES )
+ return true;
+ return !m_xConnectionURL->get_visible() || !m_xConnectionURL->GetTextNoPrefix().isEmpty();
+ }
+
+ IMPL_LINK_NOARG(OConnectionTabPageSetup, OnEditModified, weld::Entry&, void)
+ {
+ SetRoadmapStateValue(checkTestConnection());
+ callModifiedHdl();
+ }
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/dlg/ConnectionPageSetup.hxx b/dbaccess/source/ui/dlg/ConnectionPageSetup.hxx
new file mode 100644
index 000000000..0039a7160
--- /dev/null
+++ b/dbaccess/source/ui/dlg/ConnectionPageSetup.hxx
@@ -0,0 +1,63 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include "ConnectionHelper.hxx"
+#include "adminpages.hxx"
+#include <unotools/resmgr.hxx>
+
+namespace dbaui
+{
+
+ // OConnectionTabPageSetup
+
+ /** implements the connection page of the data source properties dialog.
+ */
+ class OConnectionTabPageSetup : public OConnectionHelper
+ {
+ std::unique_ptr<weld::Label> m_xHelpText;
+ std::unique_ptr<weld::Label> m_xHeaderText;
+
+ // called when the test connection button was clicked
+ DECL_LINK(OnEditModified, weld::Entry&, void);
+
+ public:
+ OConnectionTabPageSetup(weld::Container* pPage, weld::DialogController* pController, const OUString& _rUIXMLDescription, const OString& _rId, const SfxItemSet& _rCoreAttrs, TranslateId pHelpTextResId, TranslateId pHeaderResId, TranslateId pUrlResId);
+ virtual ~OConnectionTabPageSetup() override;
+
+ static std::unique_ptr<OGenericAdministrationPage> CreateDbaseTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& _rAttrSet);
+ static std::unique_ptr<OGenericAdministrationPage> CreateMSAccessTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& _rAttrSet);
+ static std::unique_ptr<OGenericAdministrationPage> CreateADOTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& _rAttrSet);
+ static std::unique_ptr<OGenericAdministrationPage> CreateODBCTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& _rAttrSet);
+ static std::unique_ptr<OGenericAdministrationPage> CreateUserDefinedTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& _rAttrSet);
+
+ virtual bool FillItemSet (SfxItemSet* _rCoreAttrs) override;
+
+ virtual void implInitControls(const SfxItemSet& _rSet, bool _bSaveValue) override;
+ virtual bool commitPage( ::vcl::WizardTypes::CommitPageReason _eReason ) override;
+
+ protected:
+ virtual bool checkTestConnection() override;
+ };
+
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/dlg/DBSetupConnectionPages.cxx b/dbaccess/source/ui/dlg/DBSetupConnectionPages.cxx
new file mode 100644
index 000000000..ffbde972f
--- /dev/null
+++ b/dbaccess/source/ui/dlg/DBSetupConnectionPages.cxx
@@ -0,0 +1,786 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <config_java.h>
+
+#include "DBSetupConnectionPages.hxx"
+#include <core_resource.hxx>
+#include <sqlmessage.hxx>
+#include <strings.hrc>
+#include <svl/itemset.hxx>
+#include <svl/stritem.hxx>
+#include <svl/eitem.hxx>
+#include <svl/intitem.hxx>
+#include <dsitems.hxx>
+#include "dsnItem.hxx"
+
+#if HAVE_FEATURE_JAVA
+ #include <jvmaccess/virtualmachine.hxx>
+#endif
+
+#include <connectivity/CommonTools.hxx>
+#include <dbwizsetup.hxx>
+#include "TextConnectionHelper.hxx"
+#include <osl/diagnose.h>
+
+namespace dbaui
+{
+using namespace ::com::sun::star;
+
+ std::unique_ptr<OGenericAdministrationPage> OTextConnectionPageSetup::CreateTextTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& _rAttrSet)
+ {
+ return std::make_unique<OTextConnectionPageSetup>(pPage, pController, _rAttrSet);
+ }
+
+ // OTextConnectionPageSetup
+ OTextConnectionPageSetup::OTextConnectionPageSetup(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rCoreAttrs)
+ : OConnectionTabPageSetup(pPage, pController, "dbaccess/ui/dbwiztextpage.ui", "DBWizTextPage",
+ rCoreAttrs, STR_TEXT_HELPTEXT, STR_TEXT_HEADERTEXT, STR_TEXT_PATH_OR_FILE)
+ , m_xSubContainer(m_xBuilder->weld_widget("TextPageContainer"))
+ , m_xTextConnectionHelper(new OTextConnectionHelper(m_xSubContainer.get(), TC_EXTENSION | TC_SEPARATORS))
+ {
+ m_xTextConnectionHelper->SetClickHandler(LINK( this, OTextConnectionPageSetup, ImplGetExtensionHdl ) );
+ }
+
+ OTextConnectionPageSetup::~OTextConnectionPageSetup()
+ {
+ m_xTextConnectionHelper.reset();
+ }
+
+ IMPL_LINK_NOARG(OTextConnectionPageSetup, ImplGetExtensionHdl, OTextConnectionHelper*, void)
+ {
+ SetRoadmapStateValue(!m_xTextConnectionHelper->GetExtension().isEmpty() && OConnectionTabPageSetup::checkTestConnection());
+ callModifiedHdl();
+ }
+
+ bool OTextConnectionPageSetup::checkTestConnection()
+ {
+ bool bDoEnable = OConnectionTabPageSetup::checkTestConnection();
+ bDoEnable = !m_xTextConnectionHelper->GetExtension().isEmpty() && bDoEnable;
+ return bDoEnable;
+ }
+
+ void OTextConnectionPageSetup::fillControls(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList)
+ {
+ OConnectionTabPageSetup::fillControls(_rControlList);
+ m_xTextConnectionHelper->fillControls(_rControlList);
+ }
+
+ void OTextConnectionPageSetup::fillWindows(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList)
+ {
+ OConnectionTabPageSetup::fillWindows(_rControlList);
+ m_xTextConnectionHelper->fillWindows(_rControlList);
+ }
+
+ void OTextConnectionPageSetup::implInitControls(const SfxItemSet& _rSet, bool _bSaveValue)
+ {
+ // first check whether or not the selection is invalid or readonly (invalid implies readonly, but not vice versa)
+ bool bValid, bReadonly;
+ getFlags(_rSet, bValid, bReadonly);
+ OConnectionTabPageSetup::implInitControls( _rSet, _bSaveValue);
+ m_xTextConnectionHelper->implInitControls(_rSet, bValid);
+ }
+
+ bool OTextConnectionPageSetup::FillItemSet( SfxItemSet* _rSet )
+ {
+ bool bChangedSomething = OConnectionTabPageSetup::FillItemSet(_rSet);
+ bChangedSomething = m_xTextConnectionHelper->FillItemSet(*_rSet, bChangedSomething);
+ return bChangedSomething;
+ }
+
+ bool OTextConnectionPageSetup::prepareLeave()
+ {
+ return m_xTextConnectionHelper->prepareLeave();
+ }
+
+ std::unique_ptr<OGenericAdministrationPage> OLDAPConnectionPageSetup::CreateLDAPTabPage( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& _rAttrSet )
+ {
+ return std::make_unique<OLDAPConnectionPageSetup>(pPage, pController, _rAttrSet);
+ }
+
+ // OLDAPPageSetup
+ OLDAPConnectionPageSetup::OLDAPConnectionPageSetup( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& _rCoreAttrs )
+ : OGenericAdministrationPage(pPage, pController, "dbaccess/ui/ldapconnectionpage.ui", "LDAPConnectionPage", _rCoreAttrs)
+ , m_xFTHelpText(m_xBuilder->weld_label("helpLabel"))
+ , m_xFTHostServer(m_xBuilder->weld_label("hostNameLabel"))
+ , m_xETHostServer(m_xBuilder->weld_entry("hostNameEntry"))
+ , m_xFTBaseDN(m_xBuilder->weld_label("baseDNLabel"))
+ , m_xETBaseDN(m_xBuilder->weld_entry("baseDNEntry"))
+ , m_xFTPortNumber(m_xBuilder->weld_label("portNumLabel"))
+ , m_xNFPortNumber(m_xBuilder->weld_spin_button("portNumEntry"))
+ , m_xFTDefaultPortNumber(m_xBuilder->weld_label("portNumDefLabel"))
+ , m_xCBUseSSL(m_xBuilder->weld_check_button("useSSLCheckbutton"))
+ {
+ m_xETHostServer->connect_changed(LINK(this, OGenericAdministrationPage, OnControlEntryModifyHdl));
+ m_xETBaseDN->connect_changed(LINK(this, OGenericAdministrationPage, OnControlEntryModifyHdl));
+ m_xNFPortNumber->connect_value_changed(LINK(this, OGenericAdministrationPage, OnControlSpinButtonModifyHdl));
+ m_xCBUseSSL->connect_toggled( LINK(this, OGenericAdministrationPage, OnControlModifiedButtonClick) );
+ SetRoadmapStateValue(false);
+ }
+
+ OLDAPConnectionPageSetup::~OLDAPConnectionPageSetup()
+ {
+ }
+
+ bool OLDAPConnectionPageSetup::FillItemSet( SfxItemSet* _rSet )
+ {
+ bool bChangedSomething = false;
+ fillString(*_rSet,m_xETBaseDN.get(),DSID_CONN_LDAP_BASEDN, bChangedSomething);
+ fillInt32(*_rSet,m_xNFPortNumber.get(),DSID_CONN_LDAP_PORTNUMBER,bChangedSomething);
+
+ if ( m_xETHostServer->get_value_changed_from_saved() )
+ {
+ const DbuTypeCollectionItem* pCollectionItem = dynamic_cast<const DbuTypeCollectionItem*>( _rSet->GetItem(DSID_TYPECOLLECTION) );
+ ::dbaccess::ODsnTypeCollection* pCollection = nullptr;
+ if (pCollectionItem)
+ pCollection = pCollectionItem->getCollection();
+ OSL_ENSURE(pCollection, "OLDAPConnectionPageSetup::FillItemSet : really need a DSN type collection !");
+ if (pCollection)
+ {
+ OUString sUrl = pCollection->getPrefix( "sdbc:address:ldap:") + m_xETHostServer->get_text();
+ _rSet->Put(SfxStringItem(DSID_CONNECTURL, sUrl));
+ bChangedSomething = true;
+ }
+ }
+
+ fillBool(*_rSet,m_xCBUseSSL.get(),DSID_CONN_LDAP_USESSL,false,bChangedSomething);
+ return bChangedSomething;
+ }
+ void OLDAPConnectionPageSetup::fillControls(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList)
+ {
+ _rControlList.emplace_back(new OSaveValueWidgetWrapper<weld::Entry>(m_xETHostServer.get()));
+ _rControlList.emplace_back(new OSaveValueWidgetWrapper<weld::Entry>(m_xETBaseDN.get()));
+ _rControlList.emplace_back(new OSaveValueWidgetWrapper<weld::SpinButton>(m_xNFPortNumber.get()));
+ _rControlList.emplace_back(new OSaveValueWidgetWrapper<weld::Toggleable>(m_xCBUseSSL.get()));
+ }
+ void OLDAPConnectionPageSetup::fillWindows(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList)
+ {
+ _rControlList.emplace_back(new ODisableWidgetWrapper<weld::Label>(m_xFTHelpText.get()));
+ _rControlList.emplace_back(new ODisableWidgetWrapper<weld::Label>(m_xFTHostServer.get()));
+ _rControlList.emplace_back(new ODisableWidgetWrapper<weld::Label>(m_xFTBaseDN.get()));
+ _rControlList.emplace_back(new ODisableWidgetWrapper<weld::Label>(m_xFTPortNumber.get()));
+ _rControlList.emplace_back(new ODisableWidgetWrapper<weld::Label>(m_xFTDefaultPortNumber.get()));
+ }
+ void OLDAPConnectionPageSetup::implInitControls(const SfxItemSet& _rSet, bool _bSaveValue)
+ {
+ // check whether or not the selection is invalid or readonly (invalid implies readonly, but not vice versa)
+ bool bValid, bReadonly;
+ getFlags(_rSet, bValid, bReadonly);
+
+ const SfxStringItem* pBaseDN = _rSet.GetItem<SfxStringItem>(DSID_CONN_LDAP_BASEDN);
+ const SfxInt32Item* pPortNumber = _rSet.GetItem<SfxInt32Item>(DSID_CONN_LDAP_PORTNUMBER);
+
+ if ( bValid )
+ {
+ m_xETBaseDN->set_text(pBaseDN->GetValue());
+ m_xNFPortNumber->set_value(pPortNumber->GetValue());
+ }
+ OGenericAdministrationPage::implInitControls(_rSet, _bSaveValue);
+ callModifiedHdl();
+ }
+
+ void OLDAPConnectionPageSetup::callModifiedHdl(weld::Widget*)
+ {
+ bool bRoadmapState = ((!m_xETHostServer->get_text().isEmpty() ) && ( !m_xETBaseDN->get_text().isEmpty() ) && (!m_xFTPortNumber->get_label().isEmpty() ));
+ SetRoadmapStateValue(bRoadmapState);
+ OGenericAdministrationPage::callModifiedHdl();
+ }
+
+ std::unique_ptr<OMySQLIntroPageSetup> OMySQLIntroPageSetup::CreateMySQLIntroTabPage(weld::Container* pPage, ODbTypeWizDialogSetup* pController, const SfxItemSet& rAttrSet)
+ {
+ return std::make_unique<OMySQLIntroPageSetup>(pPage, pController, rAttrSet);
+ }
+
+ OMySQLIntroPageSetup::OMySQLIntroPageSetup(weld::Container* pPage, ODbTypeWizDialogSetup* pController, const SfxItemSet& _rCoreAttrs)
+ : OGenericAdministrationPage(pPage, pController, "dbaccess/ui/dbwizmysqlintropage.ui", "DBWizMysqlIntroPage", _rCoreAttrs)
+ , m_xODBCDatabase(m_xBuilder->weld_radio_button("odbc"))
+ , m_xJDBCDatabase(m_xBuilder->weld_radio_button("jdbc"))
+ , m_xNATIVEDatabase(m_xBuilder->weld_radio_button("directly"))
+ {
+ m_xODBCDatabase->connect_toggled(LINK(this, OMySQLIntroPageSetup, OnSetupModeSelected));
+ m_xJDBCDatabase->connect_toggled(LINK(this, OMySQLIntroPageSetup, OnSetupModeSelected));
+ m_xNATIVEDatabase->connect_toggled(LINK(this, OMySQLIntroPageSetup, OnSetupModeSelected));
+ pController->SetIntroPage(this);
+ }
+
+ OMySQLIntroPageSetup::~OMySQLIntroPageSetup()
+ {
+ }
+
+ IMPL_LINK_NOARG(OMySQLIntroPageSetup, OnSetupModeSelected, weld::Toggleable&, void)
+ {
+ maClickHdl.Call( this );
+ }
+
+ void OMySQLIntroPageSetup::implInitControls(const SfxItemSet& _rSet, bool /*_bSaveValue*/)
+ {
+ // show the "Connect directly" option only if the driver is installed
+ const DbuTypeCollectionItem* pCollectionItem = dynamic_cast<const DbuTypeCollectionItem*>( _rSet.GetItem(DSID_TYPECOLLECTION) );
+ bool bHasMySQLNative = ( pCollectionItem != nullptr ) && pCollectionItem->getCollection()->hasDriver( "sdbc:mysql:mysqlc:" );
+ if ( bHasMySQLNative )
+ m_xNATIVEDatabase->show();
+
+ // if any of the options is checked, then there's nothing to do
+ if ( m_xODBCDatabase->get_active() || m_xJDBCDatabase->get_active() || m_xNATIVEDatabase->get_active() )
+ return;
+
+ // prefer "native" or "JDBC"
+ if ( bHasMySQLNative )
+ m_xNATIVEDatabase->set_active(true);
+ else
+ m_xJDBCDatabase->set_active(true);
+ }
+
+ void OMySQLIntroPageSetup::fillControls(std::vector< std::unique_ptr<ISaveValueWrapper> >& /*_rControlList*/)
+ {
+ }
+
+ void OMySQLIntroPageSetup::fillWindows(std::vector< std::unique_ptr<ISaveValueWrapper> >& /*_rControlList*/)
+ {
+ }
+
+ bool OMySQLIntroPageSetup::FillItemSet(SfxItemSet* /*_rSet*/)
+ {
+ OSL_FAIL("Who called me?! Please ask oj for more information.");
+ return true;
+ }
+
+ OMySQLIntroPageSetup::ConnectionType OMySQLIntroPageSetup::getMySQLMode() const
+ {
+ if (m_xJDBCDatabase->get_active())
+ return VIA_JDBC;
+ else if (m_xNATIVEDatabase->get_active())
+ return VIA_NATIVE;
+ else
+ return VIA_ODBC;
+ }
+
+ // MySQLNativeSetupPage
+ MySQLNativeSetupPage::MySQLNativeSetupPage( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rCoreAttrs )
+ : OGenericAdministrationPage(pPage, pController, "dbaccess/ui/dbwizmysqlnativepage.ui", "DBWizMysqlNativePage", rCoreAttrs)
+ , m_xHelpText(m_xBuilder->weld_label("helptext"))
+ , m_xSettingsContainer(m_xBuilder->weld_container("MySQLSettingsContainer"))
+ , m_xMySQLSettings(new MySQLNativeSettings(m_xSettingsContainer.get(), LINK(this, OGenericAdministrationPage, OnControlModified)))
+ {
+ SetRoadmapStateValue(false);
+ }
+
+ MySQLNativeSetupPage::~MySQLNativeSetupPage()
+ {
+ m_xMySQLSettings.reset();
+ }
+
+ std::unique_ptr<OGenericAdministrationPage> MySQLNativeSetupPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rAttrSet)
+ {
+ return std::make_unique<MySQLNativeSetupPage>(pPage, pController, rAttrSet);
+ }
+
+ void MySQLNativeSetupPage::fillControls( std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList )
+ {
+ m_xMySQLSettings->fillControls( _rControlList );
+ }
+
+ void MySQLNativeSetupPage::fillWindows(std::vector<std::unique_ptr<ISaveValueWrapper>>& rControlList)
+ {
+ rControlList.emplace_back(new ODisableWidgetWrapper<weld::Label>(m_xHelpText.get()));
+ m_xMySQLSettings->fillWindows(rControlList);
+ }
+
+ bool MySQLNativeSetupPage::FillItemSet( SfxItemSet* _rSet )
+ {
+ return m_xMySQLSettings->FillItemSet( _rSet );
+ }
+
+ void MySQLNativeSetupPage::implInitControls( const SfxItemSet& _rSet, bool _bSaveValue )
+ {
+ m_xMySQLSettings->implInitControls( _rSet );
+
+ OGenericAdministrationPage::implInitControls( _rSet, _bSaveValue );
+
+ callModifiedHdl();
+ }
+
+ void MySQLNativeSetupPage::callModifiedHdl(weld::Widget*)
+ {
+ SetRoadmapStateValue( m_xMySQLSettings->canAdvance() );
+
+ OGenericAdministrationPage::callModifiedHdl();
+ }
+
+ // OMySQLJDBCConnectionPageSetup
+ OGeneralSpecialJDBCConnectionPageSetup::OGeneralSpecialJDBCConnectionPageSetup( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& _rCoreAttrs ,sal_uInt16 _nPortId, TranslateId pDefaultPortResId, TranslateId pHelpTextResId, TranslateId pHeaderTextResId, TranslateId pDriverClassId)
+ : OGenericAdministrationPage(pPage, pController, "dbaccess/ui/specialjdbcconnectionpage.ui", "SpecialJDBCConnectionPage", _rCoreAttrs)
+ , m_nPortId(_nPortId)
+ , m_xHeaderText(m_xBuilder->weld_label("header"))
+ , m_xFTHelpText(m_xBuilder->weld_label("helpLabel"))
+ , m_xFTDatabasename(m_xBuilder->weld_label("dbNameLabel"))
+ , m_xETDatabasename(m_xBuilder->weld_entry("dbNameEntry"))
+ , m_xFTHostname(m_xBuilder->weld_label("hostNameLabel"))
+ , m_xETHostname(m_xBuilder->weld_entry("hostNameEntry"))
+ , m_xFTPortNumber(m_xBuilder->weld_label("portNumLabel"))
+ , m_xFTDefaultPortNumber(m_xBuilder->weld_label("portNumDefLabel"))
+ , m_xNFPortNumber(m_xBuilder->weld_spin_button("portNumEntry"))
+ , m_xFTDriverClass(m_xBuilder->weld_label("jdbcDriverLabel"))
+ , m_xETDriverClass(m_xBuilder->weld_entry("jdbcDriverEntry"))
+ , m_xPBTestJavaDriver(m_xBuilder->weld_button("testDriverButton"))
+ {
+ m_xFTDriverClass->set_label(DBA_RES(pDriverClassId));
+
+ m_xFTDefaultPortNumber->set_label(DBA_RES(pDefaultPortResId));
+ OUString sHelpText = DBA_RES(pHelpTextResId);
+ m_xFTHelpText->set_label(sHelpText);
+ //TODO this code snippet is redundant
+ m_xHeaderText->set_label(DBA_RES(pHeaderTextResId));
+
+ m_xETDatabasename->connect_changed(LINK(this, OGenericAdministrationPage, OnControlEntryModifyHdl));
+ m_xETHostname->connect_changed(LINK(this, OGenericAdministrationPage, OnControlEntryModifyHdl));
+ m_xNFPortNumber->connect_value_changed(LINK(this, OGenericAdministrationPage, OnControlSpinButtonModifyHdl));
+
+ m_xETDriverClass->connect_changed(LINK(this, OGenericAdministrationPage, OnControlEntryModifyHdl));
+ m_xPBTestJavaDriver->connect_clicked(LINK(this,OGeneralSpecialJDBCConnectionPageSetup,OnTestJavaClickHdl));
+
+ const SfxStringItem* pUrlItem = _rCoreAttrs.GetItem<SfxStringItem>(DSID_CONNECTURL);
+ const DbuTypeCollectionItem* pTypesItem = _rCoreAttrs.GetItem<DbuTypeCollectionItem>(DSID_TYPECOLLECTION);
+ ::dbaccess::ODsnTypeCollection* pTypeCollection = pTypesItem ? pTypesItem->getCollection() : nullptr;
+ if (pTypeCollection && pUrlItem && pUrlItem->GetValue().getLength() )
+ {
+ m_sDefaultJdbcDriverName = pTypeCollection->getJavaDriverClass(pUrlItem->GetValue());
+ }
+
+ SetRoadmapStateValue(false);
+ }
+
+ OGeneralSpecialJDBCConnectionPageSetup::~OGeneralSpecialJDBCConnectionPageSetup()
+ {
+ }
+
+ std::unique_ptr<OGenericAdministrationPage> OGeneralSpecialJDBCConnectionPageSetup::CreateMySQLJDBCTabPage( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& _rAttrSet )
+ {
+ return std::make_unique<OGeneralSpecialJDBCConnectionPageSetup>(pPage, pController,
+ _rAttrSet,
+ DSID_MYSQL_PORTNUMBER ,
+ STR_MYSQL_DEFAULT,
+ STR_MYSQLJDBC_HELPTEXT,
+ STR_MYSQLJDBC_HEADERTEXT,
+ STR_MYSQL_DRIVERCLASSTEXT);
+ }
+
+ std::unique_ptr<OGenericAdministrationPage> OGeneralSpecialJDBCConnectionPageSetup::CreateOracleJDBCTabPage( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& _rAttrSet )
+ {
+ return std::make_unique<OGeneralSpecialJDBCConnectionPageSetup>(pPage, pController,
+ _rAttrSet,
+ DSID_ORACLE_PORTNUMBER,
+ STR_ORACLE_DEFAULT,
+ STR_ORACLE_HELPTEXT,
+ STR_ORACLE_HEADERTEXT,
+ STR_ORACLE_DRIVERCLASSTEXT);
+ }
+
+ void OGeneralSpecialJDBCConnectionPageSetup::fillControls(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList)
+ {
+ _rControlList.emplace_back(new OSaveValueWidgetWrapper<weld::Entry>(m_xETDatabasename.get()));
+ _rControlList.emplace_back(new OSaveValueWidgetWrapper<weld::Entry>(m_xETDriverClass.get()));
+ _rControlList.emplace_back(new OSaveValueWidgetWrapper<weld::Entry>(m_xETHostname.get()));
+ _rControlList.emplace_back(new OSaveValueWidgetWrapper<weld::SpinButton>(m_xNFPortNumber.get()));
+ }
+
+ void OGeneralSpecialJDBCConnectionPageSetup::fillWindows(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList)
+ {
+ _rControlList.emplace_back(new ODisableWidgetWrapper<weld::Label>(m_xFTHelpText.get()));
+ _rControlList.emplace_back(new ODisableWidgetWrapper<weld::Label>(m_xFTDatabasename.get()));
+ _rControlList.emplace_back(new ODisableWidgetWrapper<weld::Label>(m_xFTHostname.get()));
+ _rControlList.emplace_back(new ODisableWidgetWrapper<weld::Label>(m_xFTPortNumber.get()));
+ _rControlList.emplace_back(new ODisableWidgetWrapper<weld::Label>(m_xFTDefaultPortNumber.get()));
+ _rControlList.emplace_back(new ODisableWidgetWrapper<weld::Label>(m_xFTDriverClass.get()));
+ }
+
+ bool OGeneralSpecialJDBCConnectionPageSetup::FillItemSet( SfxItemSet* _rSet )
+ {
+ bool bChangedSomething = false;
+ fillString(*_rSet,m_xETDriverClass.get(),DSID_JDBCDRIVERCLASS,bChangedSomething);
+ fillString(*_rSet,m_xETHostname.get(),DSID_CONN_HOSTNAME,bChangedSomething);
+ fillString(*_rSet,m_xETDatabasename.get(),DSID_DATABASENAME,bChangedSomething);
+ fillInt32(*_rSet,m_xNFPortNumber.get(),m_nPortId,bChangedSomething );
+ return bChangedSomething;
+ }
+
+ void OGeneralSpecialJDBCConnectionPageSetup::implInitControls(const SfxItemSet& _rSet, bool _bSaveValue)
+ {
+ // check whether or not the selection is invalid or readonly (invalid implies readonly, but not vice versa)
+ bool bValid, bReadonly;
+ getFlags(_rSet, bValid, bReadonly);
+
+ const SfxStringItem* pDatabaseName = _rSet.GetItem<SfxStringItem>(DSID_DATABASENAME);
+ const SfxStringItem* pDrvItem = _rSet.GetItem<SfxStringItem>(DSID_JDBCDRIVERCLASS);
+ const SfxStringItem* pHostName = _rSet.GetItem<SfxStringItem>(DSID_CONN_HOSTNAME);
+ const SfxInt32Item* pPortNumber = _rSet.GetItem<SfxInt32Item>(m_nPortId);
+
+ if ( bValid )
+ {
+ m_xETDatabasename->set_text(pDatabaseName->GetValue());
+ m_xETDatabasename->save_value();
+
+ m_xETDriverClass->set_text(pDrvItem->GetValue());
+ m_xETDriverClass->save_value();
+
+ m_xETHostname->set_text(pHostName->GetValue());
+ m_xETHostname->save_value();
+
+ m_xNFPortNumber->set_value(pPortNumber->GetValue());
+ m_xNFPortNumber->save_value();
+ }
+ OGenericAdministrationPage::implInitControls(_rSet, _bSaveValue);
+
+ // to get the correct value when saveValue was called by base class
+ if ( m_xETDriverClass->get_text().trim().isEmpty() )
+ {
+ m_xETDriverClass->set_text(m_sDefaultJdbcDriverName);
+ m_xETDriverClass->save_value();
+ }
+ callModifiedHdl();
+
+ bool bRoadmapState = ((!m_xETDatabasename->get_text().isEmpty() ) && (!m_xETHostname->get_text().isEmpty()) && (!m_xNFPortNumber->get_text().isEmpty() ) && ( !m_xETDriverClass->get_text().isEmpty() ));
+ SetRoadmapStateValue(bRoadmapState);
+ }
+
+ IMPL_LINK_NOARG(OGeneralSpecialJDBCConnectionPageSetup, OnTestJavaClickHdl, weld::Button&, void)
+ {
+ OSL_ENSURE(m_pAdminDialog,"No Admin dialog set! ->GPF");
+
+ bool bSuccess = false;
+#if HAVE_FEATURE_JAVA
+ try
+ {
+ if ( !m_xETDriverClass->get_text().trim().isEmpty() )
+ {
+// TODO change jvmaccess
+ ::rtl::Reference< jvmaccess::VirtualMachine > xJVM = ::connectivity::getJavaVM( m_pAdminDialog->getORB() );
+ m_xETDriverClass->set_text(m_xETDriverClass->get_text().trim()); // fdo#68341
+ bSuccess = ::connectivity::existsJavaClassByName(xJVM,m_xETDriverClass->get_text());
+ }
+ }
+ catch(css::uno::Exception&)
+ {
+ }
+#endif
+ TranslateId pMessage = bSuccess ? STR_JDBCDRIVER_SUCCESS : STR_JDBCDRIVER_NO_SUCCESS;
+ const MessageType mt = bSuccess ? MessageType::Info : MessageType::Error;
+ OSQLMessageBox aMsg(GetFrameWeld(), DBA_RES(pMessage), OUString(), MessBoxStyle::Ok | MessBoxStyle::DefaultOk, mt);
+ aMsg.run();
+ }
+
+ void OGeneralSpecialJDBCConnectionPageSetup::callModifiedHdl(weld::Widget* pControl)
+ {
+ if (pControl == m_xETDriverClass.get())
+ m_xPBTestJavaDriver->set_sensitive( !m_xETDriverClass->get_text().trim().isEmpty() );
+ bool bRoadmapState = ((!m_xETDatabasename->get_text().isEmpty() ) && ( !m_xETHostname->get_text().isEmpty() ) && (!m_xNFPortNumber->get_text().isEmpty() ) && ( !m_xETDriverClass->get_text().trim().isEmpty() ));
+ SetRoadmapStateValue(bRoadmapState);
+ OGenericAdministrationPage::callModifiedHdl();
+ }
+
+ std::unique_ptr<OGenericAdministrationPage> OJDBCConnectionPageSetup::CreateJDBCTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& _rAttrSet)
+ {
+ return std::make_unique<OJDBCConnectionPageSetup>(pPage, pController, _rAttrSet);
+ }
+
+ // OMySQLJDBCConnectionPageSetup
+ OJDBCConnectionPageSetup::OJDBCConnectionPageSetup(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rCoreAttrs)
+ : OConnectionTabPageSetup(pPage, pController, "dbaccess/ui/jdbcconnectionpage.ui", "JDBCConnectionPage", rCoreAttrs,
+ STR_JDBC_HELPTEXT, STR_JDBC_HEADERTEXT, STR_COMMONURL)
+ , m_xFTDriverClass(m_xBuilder->weld_label("jdbcLabel"))
+ , m_xETDriverClass(m_xBuilder->weld_entry("jdbcEntry"))
+ , m_xPBTestJavaDriver(m_xBuilder->weld_button("jdbcButton"))
+ {
+ m_xETDriverClass->connect_changed(LINK(this, OJDBCConnectionPageSetup, OnEditModified));
+ m_xPBTestJavaDriver->connect_clicked(LINK(this,OJDBCConnectionPageSetup,OnTestJavaClickHdl));
+ }
+
+ OJDBCConnectionPageSetup::~OJDBCConnectionPageSetup()
+ {
+ }
+
+ void OJDBCConnectionPageSetup::fillControls(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList)
+ {
+ _rControlList.emplace_back(new OSaveValueWidgetWrapper<weld::Entry>(m_xETDriverClass.get()));
+ }
+
+ void OJDBCConnectionPageSetup::fillWindows(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList)
+ {
+ _rControlList.emplace_back(new ODisableWidgetWrapper<weld::Label>(m_xFTDriverClass.get()));
+ }
+
+ bool OJDBCConnectionPageSetup::FillItemSet( SfxItemSet* _rSet )
+ {
+ bool bChangedSomething = OConnectionTabPageSetup::FillItemSet(_rSet);
+ fillString(*_rSet,m_xETDriverClass.get(),DSID_JDBCDRIVERCLASS,bChangedSomething);
+ return bChangedSomething;
+ }
+
+ void OJDBCConnectionPageSetup::implInitControls(const SfxItemSet& _rSet, bool _bSaveValue)
+ {
+ // check whether or not the selection is invalid or readonly (invalid implies readonly, but not vice versa)
+ bool bValid, bReadonly;
+ getFlags(_rSet, bValid, bReadonly);
+
+ const SfxStringItem* pDrvItem = _rSet.GetItem<SfxStringItem>(DSID_JDBCDRIVERCLASS);
+
+ if ( bValid )
+ {
+ if ( !pDrvItem->GetValue().getLength() )
+ {
+ OUString sDefaultJdbcDriverName = m_pCollection->getJavaDriverClass(m_eType);
+ if ( !sDefaultJdbcDriverName.isEmpty() )
+ {
+ m_xETDriverClass->set_text(sDefaultJdbcDriverName);
+ m_xETDriverClass->save_value();
+ }
+ }
+ else
+ {
+ m_xETDriverClass->set_text(pDrvItem->GetValue());
+ m_xETDriverClass->save_value();
+ }
+ }
+ bool bEnable = pDrvItem->GetValue().getLength() != 0;
+ m_xPBTestJavaDriver->set_sensitive(bEnable);
+ OConnectionTabPageSetup::implInitControls(_rSet, _bSaveValue);
+
+ SetRoadmapStateValue(checkTestConnection());
+ }
+
+ bool OJDBCConnectionPageSetup::checkTestConnection()
+ {
+ OSL_ENSURE(m_pAdminDialog,"No Admin dialog set! ->GPF");
+ bool bEnableTestConnection = !m_xConnectionURL->get_visible() || !m_xConnectionURL->GetTextNoPrefix().isEmpty();
+ bEnableTestConnection = bEnableTestConnection && (!m_xETDriverClass->get_text().isEmpty());
+ return bEnableTestConnection;
+ }
+
+ IMPL_LINK_NOARG(OJDBCConnectionPageSetup, OnTestJavaClickHdl, weld::Button&, void)
+ {
+ OSL_ENSURE(m_pAdminDialog,"No Admin dialog set! ->GPF");
+ bool bSuccess = false;
+#if HAVE_FEATURE_JAVA
+ try
+ {
+ if ( !m_xETDriverClass->get_text().isEmpty() )
+ {
+// TODO change jvmaccess
+ ::rtl::Reference< jvmaccess::VirtualMachine > xJVM = ::connectivity::getJavaVM( m_pAdminDialog->getORB() );
+ m_xETDriverClass->set_text(m_xETDriverClass->get_text().trim()); // fdo#68341
+ bSuccess = xJVM.is() && ::connectivity::existsJavaClassByName(xJVM,m_xETDriverClass->get_text());
+ }
+ }
+ catch(css::uno::Exception&)
+ {
+ }
+#endif
+ TranslateId pMessage = bSuccess ? STR_JDBCDRIVER_SUCCESS : STR_JDBCDRIVER_NO_SUCCESS;
+ const MessageType mt = bSuccess ? MessageType::Info : MessageType::Error;
+ OSQLMessageBox aMsg(GetFrameWeld(), DBA_RES(pMessage), OUString(), MessBoxStyle::Ok | MessBoxStyle::DefaultOk, mt);
+ aMsg.run();
+ }
+
+ IMPL_LINK(OJDBCConnectionPageSetup, OnEditModified, weld::Entry&, rEdit, void)
+ {
+ if (&rEdit == m_xETDriverClass.get())
+ m_xPBTestJavaDriver->set_sensitive(!m_xETDriverClass->get_text().isEmpty());
+ SetRoadmapStateValue(checkTestConnection());
+ // tell the listener we were modified
+ callModifiedHdl();
+ }
+
+ std::unique_ptr<OGenericAdministrationPage> OSpreadSheetConnectionPageSetup::CreateDocumentOrSpreadSheetTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& _rAttrSet)
+ {
+ return std::make_unique<OSpreadSheetConnectionPageSetup>(pPage, pController, _rAttrSet);
+ }
+
+ OSpreadSheetConnectionPageSetup::OSpreadSheetConnectionPageSetup(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rCoreAttrs)
+ : OConnectionTabPageSetup(pPage, pController, "dbaccess/ui/dbwizspreadsheetpage.ui", "DBWizSpreadsheetPage",
+ rCoreAttrs, STR_SPREADSHEET_HELPTEXT, STR_SPREADSHEET_HEADERTEXT, STR_SPREADSHEETPATH)
+ , m_xPasswordrequired(m_xBuilder->weld_check_button("passwordrequired"))
+ {
+ m_xPasswordrequired->connect_toggled(LINK(this, OGenericAdministrationPage, OnControlModifiedButtonClick));
+ }
+
+ OSpreadSheetConnectionPageSetup::~OSpreadSheetConnectionPageSetup()
+ {
+ }
+
+ void OSpreadSheetConnectionPageSetup::fillWindows(std::vector< std::unique_ptr<ISaveValueWrapper> >& /*_rControlList*/)
+ {
+ }
+
+ void OSpreadSheetConnectionPageSetup::fillControls(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList)
+ {
+ OConnectionTabPageSetup::fillControls(_rControlList);
+ _rControlList.emplace_back(new OSaveValueWidgetWrapper<weld::Toggleable>(m_xPasswordrequired.get()));
+
+ }
+
+ bool OSpreadSheetConnectionPageSetup::FillItemSet( SfxItemSet* _rSet )
+ {
+ bool bChangedSomething = OConnectionTabPageSetup::FillItemSet(_rSet);
+ fillBool(*_rSet,m_xPasswordrequired.get(),DSID_PASSWORDREQUIRED,false,bChangedSomething);
+ return bChangedSomething;
+ }
+
+ std::unique_ptr<OGenericAdministrationPage> OAuthentificationPageSetup::CreateAuthentificationTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& _rAttrSet)
+ {
+ return std::make_unique<OAuthentificationPageSetup>(pPage, pController, _rAttrSet);
+ }
+
+ OAuthentificationPageSetup::OAuthentificationPageSetup(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& _rCoreAttrs)
+ : OGenericAdministrationPage(pPage, pController, "dbaccess/ui/authentificationpage.ui", "AuthentificationPage", _rCoreAttrs)
+ , m_xFTHelpText(m_xBuilder->weld_label("helptext"))
+ , m_xFTUserName(m_xBuilder->weld_label("generalUserNameLabel"))
+ , m_xETUserName(m_xBuilder->weld_entry("generalUserNameEntry"))
+ , m_xCBPasswordRequired(m_xBuilder->weld_check_button("passRequiredCheckbutton"))
+ , m_xPBTestConnection(m_xBuilder->weld_button("testConnectionButton"))
+ {
+ m_xETUserName->connect_changed(LINK(this,OGenericAdministrationPage,OnControlEntryModifyHdl));
+ m_xCBPasswordRequired->connect_toggled(LINK(this,OGenericAdministrationPage,OnControlModifiedButtonClick));
+ m_xPBTestConnection->connect_clicked(LINK(this,OGenericAdministrationPage,OnTestConnectionButtonClickHdl));
+ }
+
+ OAuthentificationPageSetup::~OAuthentificationPageSetup()
+ {
+ }
+
+ void OAuthentificationPageSetup::fillWindows(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList)
+ {
+ _rControlList.emplace_back(new ODisableWidgetWrapper<weld::Label>(m_xFTHelpText.get()));
+ _rControlList.emplace_back(new ODisableWidgetWrapper<weld::Label>(m_xFTUserName.get()));
+ _rControlList.emplace_back(new ODisableWidgetWrapper<weld::Button>(m_xPBTestConnection.get()));
+ }
+
+ void OAuthentificationPageSetup::fillControls(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList)
+ {
+ _rControlList.emplace_back(new OSaveValueWidgetWrapper<weld::Entry>(m_xETUserName.get()));
+ _rControlList.emplace_back(new OSaveValueWidgetWrapper<weld::Toggleable>(m_xCBPasswordRequired.get()));
+ }
+
+ void OAuthentificationPageSetup::implInitControls(const SfxItemSet& _rSet, bool /*_bSaveValue*/)
+ {
+ // check whether or not the selection is invalid or readonly (invalid implies readonly, but not vice versa)
+ bool bValid, bReadonly;
+ getFlags(_rSet, bValid, bReadonly);
+ const SfxStringItem* pUidItem = _rSet.GetItem<SfxStringItem>(DSID_USER);
+ const SfxBoolItem* pAllowEmptyPwd = _rSet.GetItem<SfxBoolItem>(DSID_PASSWORDREQUIRED);
+
+ m_xETUserName->set_text(pUidItem->GetValue());
+ m_xCBPasswordRequired->set_active(pAllowEmptyPwd->GetValue());
+
+ m_xETUserName->save_value();
+ }
+
+ bool OAuthentificationPageSetup::FillItemSet( SfxItemSet* _rSet )
+ {
+ bool bChangedSomething = false;
+
+ if (m_xETUserName->get_value_changed_from_saved())
+ {
+ _rSet->Put(SfxStringItem(DSID_USER, m_xETUserName->get_text()));
+ _rSet->Put(SfxStringItem(DSID_PASSWORD, OUString()));
+ bChangedSomething = true;
+ }
+ fillBool(*_rSet, m_xCBPasswordRequired.get(), DSID_PASSWORDREQUIRED, false, bChangedSomething);
+ return bChangedSomething;
+ }
+
+ std::unique_ptr<OGenericAdministrationPage> OFinalDBPageSetup::CreateFinalDBTabPageSetup(weld::Container* pPage, ODbTypeWizDialogSetup* pController, const SfxItemSet& _rAttrSet)
+ {
+ return std::make_unique<OFinalDBPageSetup>(pPage, pController, _rAttrSet);
+ }
+
+ OFinalDBPageSetup::OFinalDBPageSetup(weld::Container* pPage, ODbTypeWizDialogSetup* pController, const SfxItemSet& _rCoreAttrs)
+ : OGenericAdministrationPage(pPage, pController, "dbaccess/ui/finalpagewizard.ui", "PageFinal", _rCoreAttrs)
+ , m_xFTFinalHeader(m_xBuilder->weld_label("headerText"))
+ , m_xFTFinalHelpText(m_xBuilder->weld_label("helpText"))
+ , m_xRBRegisterDataSource(m_xBuilder->weld_radio_button("yesregister"))
+ , m_xRBDontregisterDataSource(m_xBuilder->weld_radio_button("noregister"))
+ , m_xFTAdditionalSettings(m_xBuilder->weld_label("additionalText"))
+ , m_xCBOpenAfterwards(m_xBuilder->weld_check_button("openediting"))
+ , m_xCBStartTableWizard(m_xBuilder->weld_check_button("usewizard"))
+ , m_xFTFinalText(m_xBuilder->weld_label("finishText"))
+ {
+ m_xCBOpenAfterwards->connect_toggled(LINK(this, OFinalDBPageSetup, OnOpenSelected));
+ m_xRBRegisterDataSource->set_active(true);
+ pController->SetFinalPage(this);
+ }
+
+ OFinalDBPageSetup::~OFinalDBPageSetup()
+ {
+ }
+
+ bool OFinalDBPageSetup::IsDatabaseDocumentToBeRegistered() const
+ {
+ return m_xRBRegisterDataSource->get_active() && m_xRBRegisterDataSource->get_sensitive();
+ }
+
+ bool OFinalDBPageSetup::IsDatabaseDocumentToBeOpened() const
+ {
+ return m_xCBOpenAfterwards->get_active() && m_xCBOpenAfterwards->get_sensitive();
+ }
+
+ bool OFinalDBPageSetup::IsTableWizardToBeStarted() const
+ {
+ return m_xCBStartTableWizard->get_active() && m_xCBStartTableWizard->get_sensitive();
+ }
+
+ void OFinalDBPageSetup::fillWindows(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList)
+ {
+ _rControlList.emplace_back(new ODisableWidgetWrapper<weld::Label>(m_xFTFinalHeader.get()));
+ _rControlList.emplace_back(new ODisableWidgetWrapper<weld::Label>(m_xFTFinalHelpText.get()));
+ _rControlList.emplace_back(new ODisableWidgetWrapper<weld::Label>(m_xFTAdditionalSettings.get()));
+ _rControlList.emplace_back(new ODisableWidgetWrapper<weld::Label>(m_xFTFinalText.get()));
+ }
+
+ void OFinalDBPageSetup::fillControls(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList)
+ {
+ _rControlList.emplace_back(new OSaveValueWidgetWrapper<weld::Toggleable>(m_xCBOpenAfterwards.get()));
+ _rControlList.emplace_back(new OSaveValueWidgetWrapper<weld::Toggleable>(m_xCBStartTableWizard.get()));
+ _rControlList.emplace_back(new OSaveValueWidgetWrapper<weld::Toggleable>(m_xRBRegisterDataSource.get()));
+ _rControlList.emplace_back(new OSaveValueWidgetWrapper<weld::Toggleable>(m_xRBDontregisterDataSource.get()));
+ }
+
+ void OFinalDBPageSetup::implInitControls(const SfxItemSet& /*_rSet*/, bool /*_bSaveValue*/)
+ {
+ m_xCBOpenAfterwards->set_active(true);
+ }
+
+ void OFinalDBPageSetup::enableTableWizardCheckBox( bool _bSupportsTableCreation)
+ {
+ m_xCBStartTableWizard->set_sensitive(_bSupportsTableCreation);
+ }
+
+ bool OFinalDBPageSetup::FillItemSet( SfxItemSet* /*_rSet*/ )
+ {
+ return true;
+ }
+
+ IMPL_LINK(OFinalDBPageSetup, OnOpenSelected, weld::Toggleable&, rBox, void)
+ {
+ m_xCBStartTableWizard->set_sensitive(rBox.get_sensitive() && rBox.get_active());
+ }
+}
+
+// namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/dlg/DBSetupConnectionPages.hxx b/dbaccess/source/ui/dlg/DBSetupConnectionPages.hxx
new file mode 100644
index 000000000..8bc367602
--- /dev/null
+++ b/dbaccess/source/ui/dlg/DBSetupConnectionPages.hxx
@@ -0,0 +1,270 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include "ConnectionPageSetup.hxx"
+
+#include "adminpages.hxx"
+#include "admincontrols.hxx"
+#include "TextConnectionHelper.hxx"
+
+namespace dbaui
+{
+ class ODbTypeWizDialogSetup;
+
+ // OSpreadSheetConnectionPageSetup
+ class OSpreadSheetConnectionPageSetup final : public OConnectionTabPageSetup
+ {
+ public:
+ virtual bool FillItemSet ( SfxItemSet* _rCoreAttrs ) override;
+ static std::unique_ptr<OGenericAdministrationPage> CreateDocumentOrSpreadSheetTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& _rAttrSet);
+ OSpreadSheetConnectionPageSetup(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& _rCoreAttrs);
+ virtual ~OSpreadSheetConnectionPageSetup() override;
+
+ private:
+ std::unique_ptr<weld::CheckButton> m_xPasswordrequired;
+
+ virtual void fillControls(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) override;
+ virtual void fillWindows(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) override;
+ };
+
+ // OTextConnectionPage
+ class OTextConnectionPageSetup : public OConnectionTabPageSetup
+ {
+ public:
+ virtual bool FillItemSet ( SfxItemSet* _rCoreAttrs ) override;
+ static std::unique_ptr<OGenericAdministrationPage> CreateTextTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& _rAttrSet );
+ OTextConnectionPageSetup(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& _rCoreAttrs);
+ virtual ~OTextConnectionPageSetup() override;
+ protected:
+ virtual bool prepareLeave() override;
+ virtual void implInitControls(const SfxItemSet& _rSet, bool _bSaveValue) override;
+ virtual void fillControls(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) override;
+ virtual void fillWindows(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) override;
+ bool checkTestConnection() override;
+ private:
+ DECL_LINK(ImplGetExtensionHdl, OTextConnectionHelper*, void);
+ std::unique_ptr<weld::Widget> m_xSubContainer;
+ std::unique_ptr<OTextConnectionHelper> m_xTextConnectionHelper;
+ };
+
+ // OLDAPConnectionPageSetup
+ class OLDAPConnectionPageSetup : public OGenericAdministrationPage
+ {
+ public:
+ virtual bool FillItemSet ( SfxItemSet* _rCoreAttrs ) override;
+ static std::unique_ptr<OGenericAdministrationPage> CreateLDAPTabPage( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& _rAttrSet );
+ OLDAPConnectionPageSetup( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& _rCoreAttrs );
+ virtual ~OLDAPConnectionPageSetup() override;
+ virtual void callModifiedHdl(weld::Widget* pControl = nullptr) override;
+
+ protected:
+ virtual void implInitControls(const SfxItemSet& _rSet, bool _bSaveValue) override;
+ virtual void fillControls(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) override;
+ virtual void fillWindows(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) override;
+
+ private:
+ std::unique_ptr<weld::Label> m_xFTHelpText;
+ std::unique_ptr<weld::Label> m_xFTHostServer;
+ std::unique_ptr<weld::Entry> m_xETHostServer;
+ std::unique_ptr<weld::Label> m_xFTBaseDN;
+ std::unique_ptr<weld::Entry> m_xETBaseDN;
+ std::unique_ptr<weld::Label> m_xFTPortNumber;
+ std::unique_ptr<weld::SpinButton> m_xNFPortNumber;
+ std::unique_ptr<weld::Label> m_xFTDefaultPortNumber;
+ std::unique_ptr<weld::CheckButton> m_xCBUseSSL;
+ };
+
+ // MySQLNativeSetupPage
+ class MySQLNativeSetupPage : public OGenericAdministrationPage
+ {
+ private:
+ std::unique_ptr<weld::Label> m_xHelpText;
+ std::unique_ptr<weld::Container> m_xSettingsContainer;
+ std::unique_ptr<MySQLNativeSettings> m_xMySQLSettings;
+
+ public:
+ MySQLNativeSetupPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rCoreAttrs);
+ virtual ~MySQLNativeSetupPage() override;
+
+ static std::unique_ptr<OGenericAdministrationPage> Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rAttrSet);
+
+ protected:
+ virtual void fillControls( std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList ) override;
+ virtual void fillWindows( std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList ) override;
+
+ virtual bool FillItemSet( SfxItemSet* _rCoreAttrs ) override;
+ virtual void implInitControls(const SfxItemSet& _rSet, bool _bSaveValue) override;
+
+ virtual void callModifiedHdl(weld::Widget* pControl = nullptr) override;
+ };
+
+ // OGeneralSpecialJDBCConnectionPageSetup
+ class OGeneralSpecialJDBCConnectionPageSetup final : public OGenericAdministrationPage
+ {
+ public:
+ OGeneralSpecialJDBCConnectionPageSetup(weld::Container* pPage, weld::DialogController* pController
+ , const SfxItemSet& _rCoreAttrs
+ , sal_uInt16 _nPortId
+ , TranslateId pDefaultPortResId
+ , TranslateId pHelpTextResId
+ , TranslateId pHeaderTextResId
+ , TranslateId pDriverClassId );
+ virtual ~OGeneralSpecialJDBCConnectionPageSetup() override;
+ static std::unique_ptr<OGenericAdministrationPage> CreateMySQLJDBCTabPage( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& _rAttrSet );
+ static std::unique_ptr<OGenericAdministrationPage> CreateOracleJDBCTabPage( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& _rAttrSet );
+
+ private:
+ virtual bool FillItemSet( SfxItemSet* _rCoreAttrs ) override;
+ virtual void implInitControls(const SfxItemSet& _rSet, bool _bSaveValue) override;
+ virtual void fillControls(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) override;
+ virtual void fillWindows(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) override;
+ virtual void callModifiedHdl(weld::Widget* pControl = nullptr) override;
+
+ DECL_LINK(OnTestJavaClickHdl, weld::Button&, void);
+
+ OUString m_sDefaultJdbcDriverName;
+ sal_uInt16 m_nPortId;
+
+ std::unique_ptr<weld::Label> m_xHeaderText;
+ std::unique_ptr<weld::Label> m_xFTHelpText;
+ std::unique_ptr<weld::Label> m_xFTDatabasename;
+ std::unique_ptr<weld::Entry> m_xETDatabasename;
+ std::unique_ptr<weld::Label> m_xFTHostname;
+ std::unique_ptr<weld::Entry> m_xETHostname;
+ std::unique_ptr<weld::Label> m_xFTPortNumber;
+ std::unique_ptr<weld::Label> m_xFTDefaultPortNumber;
+ std::unique_ptr<weld::SpinButton> m_xNFPortNumber;
+
+ std::unique_ptr<weld::Label> m_xFTDriverClass;
+ std::unique_ptr<weld::Entry> m_xETDriverClass;
+ std::unique_ptr<weld::Button> m_xPBTestJavaDriver;
+ };
+
+ // OJDBCConnectionPageSetup
+ class OJDBCConnectionPageSetup final : public OConnectionTabPageSetup
+ {
+ public:
+ OJDBCConnectionPageSetup(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& _rCoreAttrs);
+ virtual ~OJDBCConnectionPageSetup() override;
+ static std::unique_ptr<OGenericAdministrationPage> CreateJDBCTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rAttrSet);
+
+ private:
+ virtual bool checkTestConnection() override;
+
+ virtual bool FillItemSet( SfxItemSet* _rCoreAttrs ) override;
+ virtual void implInitControls(const SfxItemSet& _rSet, bool _bSaveValue) override;
+ virtual void fillControls(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) override;
+ virtual void fillWindows(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) override;
+
+ DECL_LINK(OnTestJavaClickHdl, weld::Button&, void);
+ DECL_LINK(OnEditModified, weld::Entry&, void);
+ std::unique_ptr<weld::Label> m_xFTDriverClass;
+ std::unique_ptr<weld::Entry> m_xETDriverClass;
+ std::unique_ptr<weld::Button> m_xPBTestJavaDriver;
+ };
+
+ // OMySQLIntroPageSetup
+ class OMySQLIntroPageSetup : public OGenericAdministrationPage
+ {
+ public:
+ enum ConnectionType
+ {
+ VIA_ODBC,
+ VIA_JDBC,
+ VIA_NATIVE
+ };
+
+ OMySQLIntroPageSetup(weld::Container* pPage, ODbTypeWizDialogSetup* pController, const SfxItemSet& rCoreAttrs);
+ virtual ~OMySQLIntroPageSetup() override;
+
+ static std::unique_ptr<OMySQLIntroPageSetup> CreateMySQLIntroTabPage(weld::Container* pPage, ODbTypeWizDialogSetup* pController, const SfxItemSet& rAttrSet);
+ ConnectionType getMySQLMode() const;
+ void SetClickHdl( const Link<OMySQLIntroPageSetup *, void>& rLink ) { maClickHdl = rLink; }
+
+ protected:
+ virtual bool FillItemSet(SfxItemSet* _rSet) override;
+ virtual void implInitControls(const SfxItemSet& _rSet, bool _bSaveValue) override;
+ virtual void fillControls(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) override;
+ virtual void fillWindows(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) override;
+
+ private:
+ std::unique_ptr<weld::RadioButton> m_xODBCDatabase;
+ std::unique_ptr<weld::RadioButton> m_xJDBCDatabase;
+ std::unique_ptr<weld::RadioButton> m_xNATIVEDatabase;
+ Link<OMySQLIntroPageSetup *, void> maClickHdl;
+
+ DECL_LINK(OnSetupModeSelected, weld::Toggleable&, void);
+ };
+
+ // OAuthentificationPageSetup
+ class OAuthentificationPageSetup final : public OGenericAdministrationPage
+ {
+ public:
+ virtual bool FillItemSet ( SfxItemSet* _rCoreAttrs ) override;
+ static std::unique_ptr<OGenericAdministrationPage> CreateAuthentificationTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& _rAttrSet);
+ OAuthentificationPageSetup(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& _rCoreAttrs);
+ virtual ~OAuthentificationPageSetup() override;
+
+ private:
+ std::unique_ptr<weld::Label> m_xFTHelpText;
+ std::unique_ptr<weld::Label> m_xFTUserName;
+ std::unique_ptr<weld::Entry> m_xETUserName;
+ std::unique_ptr<weld::CheckButton> m_xCBPasswordRequired;
+ std::unique_ptr<weld::Button> m_xPBTestConnection;
+
+ virtual void implInitControls(const SfxItemSet& _rSet, bool _bSaveValue) override;
+ virtual void fillControls(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) override;
+ virtual void fillWindows(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) override;
+ };
+
+ // OFinalDBPageSetup
+ class OFinalDBPageSetup : public OGenericAdministrationPage
+ {
+ public:
+ virtual bool FillItemSet ( SfxItemSet* _rCoreAttrs ) override;
+ static std::unique_ptr<OGenericAdministrationPage> CreateFinalDBTabPageSetup(weld::Container* pPage, ODbTypeWizDialogSetup* pController, const SfxItemSet& _rAttrSet);
+
+ OFinalDBPageSetup(weld::Container* pPage, ODbTypeWizDialogSetup* pController, const SfxItemSet& _rCoreAttrs);
+ virtual ~OFinalDBPageSetup() override;
+ bool IsDatabaseDocumentToBeRegistered() const;
+ bool IsDatabaseDocumentToBeOpened() const;
+ bool IsTableWizardToBeStarted() const;
+ void enableTableWizardCheckBox( bool _bSupportsTableCreation);
+
+ DECL_LINK(OnOpenSelected, weld::Toggleable&, void);
+ protected:
+ virtual void implInitControls(const SfxItemSet& _rSet, bool _bSaveValue) override;
+ virtual void fillControls(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) override;
+ virtual void fillWindows(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) override;
+ private:
+ std::unique_ptr<weld::Label> m_xFTFinalHeader;
+ std::unique_ptr<weld::Label> m_xFTFinalHelpText;
+ std::unique_ptr<weld::RadioButton> m_xRBRegisterDataSource;
+ std::unique_ptr<weld::RadioButton> m_xRBDontregisterDataSource;
+ std::unique_ptr<weld::Label> m_xFTAdditionalSettings;
+ std::unique_ptr<weld::CheckButton> m_xCBOpenAfterwards;
+ std::unique_ptr<weld::CheckButton> m_xCBStartTableWizard;
+ std::unique_ptr<weld::Label> m_xFTFinalText;
+ };
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/dlg/DbAdminImpl.cxx b/dbaccess/source/ui/dlg/DbAdminImpl.cxx
new file mode 100644
index 000000000..ca20930ef
--- /dev/null
+++ b/dbaccess/source/ui/dlg/DbAdminImpl.cxx
@@ -0,0 +1,1074 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "DbAdminImpl.hxx"
+#include <dsmeta.hxx>
+
+#include <svl/poolitem.hxx>
+#include <svl/itempool.hxx>
+#include <svl/stritem.hxx>
+#include <svl/intitem.hxx>
+#include <svl/eitem.hxx>
+#include <IItemSetHelper.hxx>
+#include <UITools.hxx>
+#include <core_resource.hxx>
+#include <strings.hrc>
+#include <strings.hxx>
+#include <dsitems.hxx>
+#include "dsnItem.hxx"
+#include "optionalboolitem.hxx"
+#include <stringlistitem.hxx>
+#include <OAuthenticationContinuation.hxx>
+
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/frame/XStorable.hpp>
+#include <com/sun/star/sdb/DatabaseContext.hpp>
+#include <com/sun/star/sdb/SQLContext.hpp>
+#include <com/sun/star/sdbc/ConnectionPool.hpp>
+#include <com/sun/star/sdbc/XDriver.hpp>
+#include <com/sun/star/task/InteractionHandler.hpp>
+#include <com/sun/star/ucb/AuthenticationRequest.hpp>
+
+#include <comphelper/interaction.hxx>
+#include <comphelper/sequence.hxx>
+#include <connectivity/DriversConfig.hxx>
+#include <connectivity/dbexception.hxx>
+#include <osl/file.hxx>
+#include <tools/diagnose_ex.h>
+#include <osl/diagnose.h>
+#include <sal/log.hxx>
+#include <typelib/typedescription.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/stdtext.hxx>
+#include <vcl/weld.hxx>
+
+#include <algorithm>
+#include <iterator>
+#include <functional>
+#include <o3tl/functional.hxx>
+
+namespace dbaui
+{
+using namespace ::dbtools;
+using namespace com::sun::star::uno;
+using namespace com::sun::star;
+using namespace com::sun::star::ucb;
+using namespace com::sun::star::task;
+using namespace com::sun::star::sdbc;
+using namespace com::sun::star::sdb;
+using namespace com::sun::star::lang;
+using namespace com::sun::star::beans;
+using namespace com::sun::star::util;
+using namespace com::sun::star::container;
+using namespace com::sun::star::frame;
+
+namespace
+{
+ bool implCheckItemType( SfxItemSet const & _rSet, const sal_uInt16 _nId, const std::function<bool ( const SfxPoolItem* )>& isItemType )
+ {
+ bool bCorrectType = false;
+
+ SfxItemPool* pPool = _rSet.GetPool();
+ OSL_ENSURE( pPool, "implCheckItemType: invalid item pool!" );
+ if ( pPool )
+ {
+ const SfxPoolItem& rDefItem = pPool->GetDefaultItem( _nId );
+ bCorrectType = isItemType(&rDefItem);
+ }
+ return bCorrectType;
+ }
+
+ void lcl_putProperty(const Reference< XPropertySet >& _rxSet, const OUString& _rName, const Any& _rValue)
+ {
+ try
+ {
+ if ( _rxSet.is() )
+ _rxSet->setPropertyValue(_rName, _rValue);
+ }
+ catch(Exception&)
+ {
+ SAL_WARN("dbaccess", "ODbAdminDialog::implTranslateProperty: could not set the property "
+ << _rName);
+ }
+
+ }
+
+ OUString lcl_createHostWithPort(const SfxStringItem* _pHostName,const SfxInt32Item* _pPortNumber)
+ {
+ OUString sNewUrl;
+
+ if ( _pHostName && _pHostName->GetValue().getLength() )
+ sNewUrl = _pHostName->GetValue();
+
+ if ( _pPortNumber )
+ {
+ sNewUrl += ":" + OUString::number(_pPortNumber->GetValue());
+ }
+
+ return sNewUrl;
+ }
+}
+
+ // ODbDataSourceAdministrationHelper
+ODbDataSourceAdministrationHelper::ODbDataSourceAdministrationHelper(const Reference< XComponentContext >& _xORB, weld::Window* pParent, weld::Window* pTopParent, IItemSetHelper* _pItemSetHelper)
+ : m_xContext(_xORB)
+ , m_pParent(pParent)
+ , m_pItemSetHelper(_pItemSetHelper)
+{
+ /// initialize the property translation map
+ // direct properties of a data source
+ m_aDirectPropTranslator.emplace( DSID_CONNECTURL, PROPERTY_URL );
+ m_aDirectPropTranslator.emplace( DSID_NAME, PROPERTY_NAME );
+ m_aDirectPropTranslator.emplace( DSID_USER, PROPERTY_USER );
+ m_aDirectPropTranslator.emplace( DSID_PASSWORD, PROPERTY_PASSWORD );
+ m_aDirectPropTranslator.emplace( DSID_PASSWORDREQUIRED, PROPERTY_ISPASSWORDREQUIRED );
+ m_aDirectPropTranslator.emplace( DSID_TABLEFILTER, PROPERTY_TABLEFILTER );
+ m_aDirectPropTranslator.emplace( DSID_READONLY, PROPERTY_ISREADONLY );
+ m_aDirectPropTranslator.emplace( DSID_SUPPRESSVERSIONCL, PROPERTY_SUPPRESSVERSIONCL );
+
+ // implicit properties, to be found in the direct property "Info"
+ m_aIndirectPropTranslator.emplace( DSID_JDBCDRIVERCLASS, INFO_JDBCDRIVERCLASS );
+ m_aIndirectPropTranslator.emplace( DSID_TEXTFILEEXTENSION, INFO_TEXTFILEEXTENSION );
+ m_aIndirectPropTranslator.emplace( DSID_CHARSET, INFO_CHARSET );
+ m_aIndirectPropTranslator.emplace( DSID_TEXTFILEHEADER, INFO_TEXTFILEHEADER );
+ m_aIndirectPropTranslator.emplace( DSID_FIELDDELIMITER, INFO_FIELDDELIMITER );
+ m_aIndirectPropTranslator.emplace( DSID_TEXTDELIMITER, INFO_TEXTDELIMITER );
+ m_aIndirectPropTranslator.emplace( DSID_DECIMALDELIMITER, INFO_DECIMALDELIMITER );
+ m_aIndirectPropTranslator.emplace( DSID_THOUSANDSDELIMITER, INFO_THOUSANDSDELIMITER );
+ m_aIndirectPropTranslator.emplace( DSID_SHOWDELETEDROWS, INFO_SHOWDELETEDROWS );
+ m_aIndirectPropTranslator.emplace( DSID_ALLOWLONGTABLENAMES, INFO_ALLOWLONGTABLENAMES );
+ m_aIndirectPropTranslator.emplace( DSID_ADDITIONALOPTIONS, INFO_ADDITIONALOPTIONS );
+ m_aIndirectPropTranslator.emplace( DSID_SQL92CHECK, PROPERTY_ENABLESQL92CHECK );
+ m_aIndirectPropTranslator.emplace( DSID_AUTOINCREMENTVALUE, PROPERTY_AUTOINCREMENTCREATION );
+ m_aIndirectPropTranslator.emplace( DSID_AUTORETRIEVEVALUE, INFO_AUTORETRIEVEVALUE );
+ m_aIndirectPropTranslator.emplace( DSID_AUTORETRIEVEENABLED, INFO_AUTORETRIEVEENABLED );
+ m_aIndirectPropTranslator.emplace( DSID_APPEND_TABLE_ALIAS, INFO_APPEND_TABLE_ALIAS );
+ m_aIndirectPropTranslator.emplace( DSID_AS_BEFORE_CORRNAME, INFO_AS_BEFORE_CORRELATION_NAME );
+ m_aIndirectPropTranslator.emplace( DSID_CHECK_REQUIRED_FIELDS, INFO_FORMS_CHECK_REQUIRED_FIELDS );
+ m_aIndirectPropTranslator.emplace( DSID_ESCAPE_DATETIME, INFO_ESCAPE_DATETIME );
+ m_aIndirectPropTranslator.emplace( DSID_PRIMARY_KEY_SUPPORT, OUString("PrimaryKeySupport") );
+ m_aIndirectPropTranslator.emplace( DSID_PARAMETERNAMESUBST, INFO_PARAMETERNAMESUBST );
+ m_aIndirectPropTranslator.emplace( DSID_IGNOREDRIVER_PRIV, INFO_IGNOREDRIVER_PRIV );
+ m_aIndirectPropTranslator.emplace( DSID_BOOLEANCOMPARISON, PROPERTY_BOOLEANCOMPARISONMODE );
+ m_aIndirectPropTranslator.emplace( DSID_ENABLEOUTERJOIN, PROPERTY_ENABLEOUTERJOIN );
+ m_aIndirectPropTranslator.emplace( DSID_CATALOG, PROPERTY_USECATALOGINSELECT );
+ m_aIndirectPropTranslator.emplace( DSID_SCHEMA, PROPERTY_USESCHEMAINSELECT );
+ m_aIndirectPropTranslator.emplace( DSID_INDEXAPPENDIX, OUString("AddIndexAppendix") );
+ m_aIndirectPropTranslator.emplace( DSID_DOSLINEENDS, OUString("PreferDosLikeLineEnds") );
+ m_aIndirectPropTranslator.emplace( DSID_CONN_SOCKET, OUString("LocalSocket") );
+ m_aIndirectPropTranslator.emplace( DSID_NAMED_PIPE, OUString("NamedPipe") );
+ m_aIndirectPropTranslator.emplace( DSID_RESPECTRESULTSETTYPE, OUString("RespectDriverResultSetType") );
+ m_aIndirectPropTranslator.emplace( DSID_MAX_ROW_SCAN, OUString("MaxRowScan") );
+
+ // extra settings for ODBC
+ m_aIndirectPropTranslator.emplace( DSID_USECATALOG, INFO_USECATALOG );
+ // extra settings for an LDAP address book
+ m_aIndirectPropTranslator.emplace( DSID_CONN_LDAP_BASEDN, INFO_CONN_LDAP_BASEDN );
+ m_aIndirectPropTranslator.emplace( DSID_CONN_LDAP_ROWCOUNT, INFO_CONN_LDAP_ROWCOUNT );
+ m_aIndirectPropTranslator.emplace( DSID_CONN_LDAP_USESSL, OUString("UseSSL") );
+ m_aIndirectPropTranslator.emplace( DSID_DOCUMENT_URL, PROPERTY_URL );
+
+ // Oracle
+ m_aIndirectPropTranslator.emplace( DSID_IGNORECURRENCY, OUString("IgnoreCurrency") );
+
+ try
+ {
+ m_xDatabaseContext = DatabaseContext::create(m_xContext);
+ }
+ catch(const Exception&)
+ {
+ ShowServiceNotAvailableError(pTopParent, u"com.sun.star.sdb.DatabaseContext", true);
+ }
+}
+
+bool ODbDataSourceAdministrationHelper::getCurrentSettings(Sequence< PropertyValue >& _rDriverParam)
+{
+ OSL_ENSURE(m_pItemSetHelper->getOutputSet(), "ODbDataSourceAdministrationHelper::getCurrentSettings : not to be called without an example set!");
+ if (!m_pItemSetHelper->getOutputSet())
+ return false;
+
+ std::vector< PropertyValue > aReturn;
+ // collecting this in a vector because it has a push_back, in opposite to sequences
+
+ // user: DSID_USER -> "user"
+ const SfxStringItem* pUser = m_pItemSetHelper->getOutputSet()->GetItem<SfxStringItem>(DSID_USER);
+ if (pUser && pUser->GetValue().getLength())
+ aReturn.emplace_back( "user", 0,
+ Any(pUser->GetValue()), PropertyState_DIRECT_VALUE);
+
+ // check if the connection type requires a password
+ if (hasAuthentication(*m_pItemSetHelper->getOutputSet()))
+ {
+ // password: DSID_PASSWORD -> password
+ const SfxStringItem* pPassword = m_pItemSetHelper->getOutputSet()->GetItem<SfxStringItem>(DSID_PASSWORD);
+ OUString sPassword = pPassword ? pPassword->GetValue() : OUString();
+ const SfxBoolItem* pPasswordRequired = m_pItemSetHelper->getOutputSet()->GetItem<SfxBoolItem>(DSID_PASSWORDREQUIRED);
+ // if the set does not contain a password, but the item set says it requires one, ask the user
+ if ((!pPassword || !pPassword->GetValue().getLength()) && (pPasswordRequired && pPasswordRequired->GetValue()))
+ {
+ const SfxStringItem* pName = m_pItemSetHelper->getOutputSet()->GetItem<SfxStringItem>(DSID_NAME);
+
+ Reference< XModel > xModel( getDataSourceOrModel( m_xDatasource ), UNO_QUERY_THROW );
+ ::comphelper::NamedValueCollection aArgs( xModel->getArgs() );
+ Reference< XInteractionHandler > xHandler( aArgs.getOrDefault( "InteractionHandler", Reference< XInteractionHandler >() ) );
+
+ if ( !xHandler.is() )
+ {
+ // instantiate the default SDB interaction handler
+ xHandler = task::InteractionHandler::createWithParent(m_xContext, m_pParent->GetXWindow());
+ }
+
+ OUString sName = pName ? pName->GetValue() : OUString();
+ OUString sLoginRequest(DBA_RES(STR_ENTER_CONNECTION_PASSWORD));
+ OUString sTemp = sName;
+ sName = ::dbaui::getStrippedDatabaseName(nullptr,sTemp);
+ if ( !sName.isEmpty() )
+ sLoginRequest = sLoginRequest.replaceAll("$name$", sName);
+ else
+ {
+ sLoginRequest = sLoginRequest.replaceAll("\"$name$\"", "");
+ // ensure that in other languages the string will be deleted
+ sLoginRequest = sLoginRequest.replaceAll("$name$", "");
+ }
+
+ // the request
+ AuthenticationRequest aRequest;
+ aRequest.ServerName = sName;
+ aRequest.Diagnostic = sLoginRequest;
+ aRequest.HasRealm = false;
+ // aRequest.Realm
+ aRequest.HasUserName = pUser != nullptr;
+ aRequest.UserName = pUser ? pUser->GetValue() : OUString();
+ aRequest.HasPassword = true;
+ //aRequest.Password
+ aRequest.HasAccount = false;
+ // aRequest.Account
+
+ rtl::Reference<comphelper::OInteractionRequest> pRequest = new comphelper::OInteractionRequest(Any(aRequest));
+
+ // build an interaction request
+ // two continuations (Ok and Cancel)
+ ::rtl::Reference< comphelper::OInteractionAbort > pAbort = new comphelper::OInteractionAbort;
+ ::rtl::Reference< dbaccess::OAuthenticationContinuation > pAuthenticate = new dbaccess::OAuthenticationContinuation;
+ pAuthenticate->setCanChangeUserName( false );
+ pAuthenticate->setRememberPassword( RememberAuthentication_SESSION );
+
+ // some knittings
+ pRequest->addContinuation(pAbort);
+ pRequest->addContinuation(pAuthenticate);
+
+ // handle the request
+ try
+ {
+ SolarMutexGuard aSolarGuard;
+ // release the mutex when calling the handler, it may need to lock the SolarMutex
+ xHandler->handle(pRequest);
+ }
+ catch(Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ if (!pAuthenticate->wasSelected())
+ return false;
+
+ sPassword = pAuthenticate->getPassword();
+ if (pAuthenticate->getRememberPassword())
+ m_pItemSetHelper->getWriteOutputSet()->Put(SfxStringItem(DSID_PASSWORD, sPassword));
+ }
+
+ if (!sPassword.isEmpty())
+ aReturn.emplace_back( "password", 0,
+ Any(sPassword), PropertyState_DIRECT_VALUE);
+ }
+
+ if ( !aReturn.empty() )
+ _rDriverParam = comphelper::containerToSequence(aReturn);
+
+ // append all the other stuff (charset etc.)
+ fillDatasourceInfo(*m_pItemSetHelper->getOutputSet(), _rDriverParam);
+
+ return true;
+}
+
+void ODbDataSourceAdministrationHelper::successfullyConnected()
+{
+ OSL_ENSURE(m_pItemSetHelper->getOutputSet(), "ODbDataSourceAdministrationHelper::successfullyConnected: not to be called without an example set!");
+ if (!m_pItemSetHelper->getOutputSet())
+ return;
+
+ if (hasAuthentication(*m_pItemSetHelper->getOutputSet()))
+ {
+ const SfxStringItem* pPassword = m_pItemSetHelper->getOutputSet()->GetItem<SfxStringItem>(DSID_PASSWORD);
+ if (pPassword && (0 != pPassword->GetValue().getLength()))
+ {
+ OUString sPassword = pPassword->GetValue();
+
+ Reference< XPropertySet > xCurrentDatasource = getCurrentDataSource();
+ lcl_putProperty(xCurrentDatasource,m_aDirectPropTranslator[DSID_PASSWORD], Any(sPassword));
+ }
+ }
+}
+
+void ODbDataSourceAdministrationHelper::clearPassword()
+{
+ if (m_pItemSetHelper->getWriteOutputSet())
+ m_pItemSetHelper->getWriteOutputSet()->ClearItem(DSID_PASSWORD);
+}
+
+std::pair< Reference<XConnection>,bool> ODbDataSourceAdministrationHelper::createConnection()
+{
+ std::pair< Reference<XConnection>,bool> aRet;
+ aRet.second = false;
+ Sequence< PropertyValue > aConnectionParams;
+ if ( getCurrentSettings(aConnectionParams) )
+ {
+ // the current DSN
+ // fill the table list with this connection information
+ SQLExceptionInfo aErrorInfo;
+ try
+ {
+ weld::WaitObject aWaitCursor(m_pParent);
+ aRet.first = getDriver()->connect(getConnectionURL(), aConnectionParams);
+ aRet.second = true;
+ }
+ catch (const SQLContext& e) { aErrorInfo = SQLExceptionInfo(e); }
+ catch (const SQLWarning& e) { aErrorInfo = SQLExceptionInfo(e); }
+ catch (const SQLException& e) { aErrorInfo = SQLExceptionInfo(e); }
+
+ showError(aErrorInfo,m_pParent->GetXWindow(),getORB());
+ }
+ if ( aRet.first.is() )
+ successfullyConnected();// notify the admindlg to save the password
+
+ return aRet;
+}
+
+Reference< XDriver > ODbDataSourceAdministrationHelper::getDriver()
+{
+ return getDriver(getConnectionURL());
+}
+
+Reference< XDriver > ODbDataSourceAdministrationHelper::getDriver(const OUString& _sURL)
+{
+ // get the global DriverManager
+ Reference< XConnectionPool > xDriverManager;
+
+ OUString sCurrentActionError = DBA_RES(STR_COULDNOTCREATE_DRIVERMANAGER);
+ sCurrentActionError = sCurrentActionError.replaceFirst("#servicename#", "com.sun.star.sdbc.ConnectionPool");
+
+ try
+ {
+ xDriverManager.set( ConnectionPool::create( getORB() ) );
+ }
+ catch (const Exception&)
+ {
+ css::uno::Any anyEx = cppu::getCaughtException();
+ // wrap the exception into an SQLException
+ throw SQLException(sCurrentActionError, getORB(), "S1000", 0, anyEx);
+ }
+
+ Reference< XDriver > xDriver = xDriverManager->getDriverByURL(_sURL);
+ if (!xDriver.is())
+ {
+ sCurrentActionError = DBA_RES(STR_NOREGISTEREDDRIVER);
+ sCurrentActionError = sCurrentActionError.replaceFirst("#connurl#", _sURL);
+ // will be caught and translated into an SQLContext exception
+ throw SQLException(sCurrentActionError, getORB(), "S1000", 0, Any());
+ }
+ return xDriver;
+}
+
+Reference< XPropertySet > const & ODbDataSourceAdministrationHelper::getCurrentDataSource()
+{
+ if ( !m_xDatasource.is() )
+ {
+ Reference<XInterface> xIn(m_aDataSourceOrName,UNO_QUERY);
+ if ( !xIn.is() )
+ {
+ OUString sCurrentDatasource;
+ m_aDataSourceOrName >>= sCurrentDatasource;
+ OSL_ENSURE(!sCurrentDatasource.isEmpty(),"No datasource name given!");
+ try
+ {
+ if ( m_xDatabaseContext.is() )
+ m_xDatasource.set(m_xDatabaseContext->getByName(sCurrentDatasource),UNO_QUERY);
+ xIn = m_xDatasource;
+ }
+ catch(const Exception&)
+ {
+ }
+ }
+ m_xModel.set(getDataSourceOrModel(xIn),UNO_QUERY);
+ if ( m_xModel.is() )
+ m_xDatasource.set(xIn,UNO_QUERY);
+ else
+ {
+ m_xDatasource.set(getDataSourceOrModel(xIn),UNO_QUERY);
+ m_xModel.set(xIn,UNO_QUERY);
+ }
+ }
+
+ OSL_ENSURE(m_xDatasource.is(), "ODbDataSourceAdministrationHelper::getCurrentDataSource: no data source!");
+ return m_xDatasource;
+}
+
+OUString ODbDataSourceAdministrationHelper::getDatasourceType( const SfxItemSet& _rSet )
+{
+ const SfxStringItem* pConnectURL = _rSet.GetItem<SfxStringItem>(DSID_CONNECTURL);
+ OSL_ENSURE( pConnectURL , "ODbDataSourceAdministrationHelper::getDatasourceType: invalid items in the source set!" );
+ const DbuTypeCollectionItem* pTypeCollection = _rSet.GetItem<DbuTypeCollectionItem>(DSID_TYPECOLLECTION);
+ OSL_ENSURE(pTypeCollection, "ODbDataSourceAdministrationHelper::getDatasourceType: invalid items in the source set!");
+ ::dbaccess::ODsnTypeCollection* pCollection = pTypeCollection->getCollection();
+ return pCollection->getType(pConnectURL->GetValue());
+}
+
+bool ODbDataSourceAdministrationHelper::hasAuthentication(const SfxItemSet& _rSet)
+{
+ return DataSourceMetaData::getAuthentication( getDatasourceType( _rSet ) ) != AuthNone;
+}
+
+OUString ODbDataSourceAdministrationHelper::getConnectionURL() const
+{
+ OUString sNewUrl;
+
+ OUString eType = getDatasourceType(*m_pItemSetHelper->getOutputSet());
+
+ const SfxStringItem* pUrlItem = m_pItemSetHelper->getOutputSet()->GetItem<SfxStringItem>(DSID_CONNECTURL);
+ const DbuTypeCollectionItem* pTypeCollection = m_pItemSetHelper->getOutputSet()->GetItem<DbuTypeCollectionItem>(DSID_TYPECOLLECTION);
+
+ OSL_ENSURE(pUrlItem,"Connection URL is NULL. -> GPF!");
+ OSL_ENSURE(pTypeCollection, "ODbDataSourceAdministrationHelper::getDatasourceType: invalid items in the source set!");
+ ::dbaccess::ODsnTypeCollection* pCollection = pTypeCollection->getCollection();
+ OSL_ENSURE(pCollection, "ODbDataSourceAdministrationHelper::getDatasourceType: invalid type collection!");
+
+ switch( pCollection->determineType(eType) )
+ {
+ case ::dbaccess::DST_DBASE:
+ case ::dbaccess::DST_FLAT:
+ case ::dbaccess::DST_CALC:
+ case ::dbaccess::DST_WRITER:
+ break;
+ case ::dbaccess::DST_MSACCESS:
+ case ::dbaccess::DST_MSACCESS_2007:
+ {
+ OUString sFileName = pCollection->cutPrefix(pUrlItem->GetValue());
+ OUString sNewFileName;
+ if ( ::osl::FileBase::getSystemPathFromFileURL( sFileName, sNewFileName ) == ::osl::FileBase::E_None )
+ {
+ sNewUrl += sNewFileName;
+ }
+ }
+ break;
+ case ::dbaccess::DST_MYSQL_NATIVE:
+ case ::dbaccess::DST_MYSQL_JDBC:
+ {
+ const SfxStringItem* pHostName = m_pItemSetHelper->getOutputSet()->GetItem<SfxStringItem>(DSID_CONN_HOSTNAME);
+ const SfxInt32Item* pPortNumber = m_pItemSetHelper->getOutputSet()->GetItem<SfxInt32Item>(DSID_MYSQL_PORTNUMBER);
+ const SfxStringItem* pDatabaseName = m_pItemSetHelper->getOutputSet()->GetItem<SfxStringItem>(DSID_DATABASENAME);
+ sNewUrl = lcl_createHostWithPort(pHostName,pPortNumber);
+ OUString sDatabaseName = pDatabaseName ? pDatabaseName->GetValue() : OUString();
+ if ( !sDatabaseName.getLength() && pUrlItem )
+ sDatabaseName = pCollection->cutPrefix( pUrlItem->GetValue() );
+ // TODO: what's that? Why is the database name transported via the URL Item?
+ // Huh? Anybody there?
+ // OJ: It is needed when the connection properties are changed. There the URL is used for every type.
+
+ if ( !sDatabaseName.isEmpty() )
+ {
+ sNewUrl += "/" + sDatabaseName;
+ }
+ }
+ break;
+ case ::dbaccess::DST_ORACLE_JDBC:
+ {
+ const SfxStringItem* pHostName = m_pItemSetHelper->getOutputSet()->GetItem<SfxStringItem>(DSID_CONN_HOSTNAME);
+ const SfxInt32Item* pPortNumber = m_pItemSetHelper->getOutputSet()->GetItem<SfxInt32Item>(DSID_ORACLE_PORTNUMBER);
+ const SfxStringItem* pDatabaseName = m_pItemSetHelper->getOutputSet()->GetItem<SfxStringItem>(DSID_DATABASENAME);
+ if ( pHostName && pHostName->GetValue().getLength() )
+ {
+ sNewUrl = "@" + lcl_createHostWithPort(pHostName,pPortNumber);
+ OUString sDatabaseName = pDatabaseName ? pDatabaseName->GetValue() : OUString();
+ if ( sDatabaseName.isEmpty() && pUrlItem )
+ sDatabaseName = pCollection->cutPrefix( pUrlItem->GetValue() );
+ if ( !sDatabaseName.isEmpty() )
+ {
+ sNewUrl += ":" + sDatabaseName;
+ }
+ }
+ else
+ { // here someone entered a JDBC url which looks like oracle, so we have to use the url property
+
+ }
+ }
+ break;
+ case ::dbaccess::DST_LDAP:
+ {
+ const SfxInt32Item* pPortNumber = m_pItemSetHelper->getOutputSet()->GetItem<SfxInt32Item>(DSID_CONN_LDAP_PORTNUMBER);
+ sNewUrl = pCollection->cutPrefix(pUrlItem->GetValue()) + lcl_createHostWithPort(nullptr,pPortNumber);
+ }
+ break;
+ case ::dbaccess::DST_JDBC:
+ // run through
+ default:
+ break;
+ }
+ if ( !sNewUrl.isEmpty() )
+ sNewUrl = pCollection->getPrefix(eType) + sNewUrl;
+ else
+ sNewUrl = pUrlItem->GetValue();
+
+ return sNewUrl;
+}
+
+namespace {
+
+struct PropertyValueLess
+{
+ bool operator() (const PropertyValue& x, const PropertyValue& y) const
+ { return x.Name < y.Name; } // construct prevents a MSVC6 warning
+};
+
+}
+
+typedef std::set<PropertyValue, PropertyValueLess> PropertyValueSet;
+
+void ODbDataSourceAdministrationHelper::translateProperties(const Reference< XPropertySet >& _rxSource, SfxItemSet& _rDest)
+{
+ if (_rxSource.is())
+ {
+ for (auto const& elem : m_aDirectPropTranslator)
+ {
+ // get the property value
+ Any aValue;
+ try
+ {
+ aValue = _rxSource->getPropertyValue(elem.second);
+ }
+ catch(Exception&)
+ {
+ SAL_WARN("dbaccess", "ODbDataSourceAdministrationHelper::translateProperties: could not extract the property "
+ << elem.second);
+ }
+ // transfer it into an item
+ implTranslateProperty(_rDest, elem.first, aValue);
+ }
+
+ // get the additional information
+ Sequence< PropertyValue > aAdditionalInfo;
+ try
+ {
+ _rxSource->getPropertyValue(PROPERTY_INFO) >>= aAdditionalInfo;
+ }
+ catch(Exception&) { }
+
+ // collect the names of the additional settings
+ PropertyValueSet aInfos;
+ for (const PropertyValue& rAdditionalInfo : std::as_const(aAdditionalInfo))
+ {
+ if( rAdditionalInfo.Name == "JDBCDRV" )
+ { // compatibility
+ PropertyValue aCompatibility(rAdditionalInfo);
+ aCompatibility.Name = "JavaDriverClass";
+ aInfos.insert(aCompatibility);
+ }
+ else
+ aInfos.insert(rAdditionalInfo);
+ }
+
+ // go through all known translations and check if we have such a setting
+ if ( !aInfos.empty() )
+ {
+ PropertyValue aSearchFor;
+ for (auto const& elem : m_aIndirectPropTranslator)
+ {
+ aSearchFor.Name = elem.second;
+ PropertyValueSet::const_iterator aInfoPos = aInfos.find(aSearchFor);
+ if (aInfos.end() != aInfoPos)
+ // the property is contained in the info sequence
+ // -> transfer it into an item
+ implTranslateProperty(_rDest, elem.first, aInfoPos->Value);
+ }
+ }
+
+ convertUrl(_rDest);
+ }
+
+ try
+ {
+ Reference<XStorable> xStore(getDataSourceOrModel(_rxSource),UNO_QUERY);
+ _rDest.Put(SfxBoolItem(DSID_READONLY, !xStore.is() || xStore->isReadonly() ));
+ }
+ catch(Exception&)
+ {
+ TOOLS_WARN_EXCEPTION("dbaccess", "IsReadOnly throws");
+ }
+}
+
+void ODbDataSourceAdministrationHelper::translateProperties(const SfxItemSet& _rSource, const Reference< XPropertySet >& _rxDest)
+{
+ OSL_ENSURE(_rxDest.is(), "ODbDataSourceAdministrationHelper::translateProperties: invalid property set!");
+ if (!_rxDest.is())
+ return;
+
+ // the property set info
+ Reference< XPropertySetInfo > xInfo;
+ try { xInfo = _rxDest->getPropertySetInfo(); }
+ catch(Exception&) { }
+
+ static const OUStringLiteral sUrlProp(u"URL");
+ // transfer the direct properties
+ for (auto const& elem : m_aDirectPropTranslator)
+ {
+ const SfxPoolItem* pCurrentItem = _rSource.GetItem(static_cast<sal_uInt16>(elem.first));
+ if (pCurrentItem)
+ {
+ sal_Int16 nAttributes = PropertyAttribute::READONLY;
+ if (xInfo.is())
+ {
+ try { nAttributes = xInfo->getPropertyByName(elem.second).Attributes; }
+ catch(Exception&) { }
+ }
+ if ((nAttributes & PropertyAttribute::READONLY) == 0)
+ {
+ if ( sUrlProp == elem.second )
+ {
+ Any aValue(getConnectionURL());
+ // aValue <<= OUString();
+ lcl_putProperty(_rxDest, elem.second,aValue);
+ }
+ else
+ implTranslateProperty(_rxDest, elem.second, pCurrentItem);
+ }
+ }
+ }
+
+ // now for the indirect properties
+
+ Sequence< PropertyValue > aInfo;
+ // the original properties
+ try
+ {
+ _rxDest->getPropertyValue(PROPERTY_INFO) >>= aInfo;
+ }
+ catch(Exception&) { }
+
+ // overwrite and extend them
+ fillDatasourceInfo(_rSource, aInfo);
+ // and propagate the (newly composed) sequence to the set
+ lcl_putProperty(_rxDest,PROPERTY_INFO, Any(aInfo));
+}
+
+void ODbDataSourceAdministrationHelper::fillDatasourceInfo(const SfxItemSet& _rSource, Sequence< css::beans::PropertyValue >& _rInfo)
+{
+ // within the current "Info" sequence, replace the ones we can examine from the item set
+ // (we don't just fill a completely new sequence with our own items, but we preserve any properties unknown to
+ // us)
+
+ // first determine which of all the items are relevant for the data source (depends on the connection url)
+ const OUString eType = getDatasourceType(_rSource);
+ const ::connectivity::DriversConfig aDriverConfig(getORB());
+ const ::comphelper::NamedValueCollection& aProperties = aDriverConfig.getProperties(eType);
+
+ // collect the translated property values for the relevant items
+ PropertyValueSet aRelevantSettings;
+ MapInt2String::const_iterator aTranslation;
+ for (ItemID detailId = DSID_FIRST_ITEM_ID ; detailId <= DSID_LAST_ITEM_ID; ++detailId)
+ {
+ const SfxPoolItem* pCurrent = _rSource.GetItem(static_cast<sal_uInt16>(detailId));
+ aTranslation = m_aIndirectPropTranslator.find(detailId);
+ if ( pCurrent && (m_aIndirectPropTranslator.end() != aTranslation) &&
+ aProperties.has(aTranslation->second) )
+ {
+ if ( aTranslation->second == INFO_CHARSET )
+ {
+ OUString sCharSet;
+ implTranslateProperty(pCurrent) >>= sCharSet;
+ if ( !sCharSet.isEmpty() )
+ aRelevantSettings.insert(PropertyValue(aTranslation->second, 0, Any(sCharSet), PropertyState_DIRECT_VALUE));
+ }
+ else
+ aRelevantSettings.insert(PropertyValue(aTranslation->second, 0, implTranslateProperty(pCurrent), PropertyState_DIRECT_VALUE));
+ }
+ }
+
+ // settings to preserve
+ MapInt2String aPreservedSettings;
+
+ // now aRelevantSettings contains all the property values relevant for the current data source type,
+ // check the original sequence if it already contains any of these values (which have to be overwritten, then)
+ PropertyValue* pInfo = _rInfo.getArray();
+ PropertyValue aSearchFor;
+ sal_Int32 nObsoleteSetting = -1;
+ sal_Int32 nCount = _rInfo.getLength();
+ for (sal_Int32 i = 0; i < nCount; ++i, ++pInfo)
+ {
+ aSearchFor.Name = pInfo->Name;
+ PropertyValueSet::const_iterator aOverwrittenSetting = aRelevantSettings.find(aSearchFor);
+ if (aRelevantSettings.end() != aOverwrittenSetting)
+ { // the setting was present in the original sequence, and it is to be overwritten -> replace it
+ if ( pInfo->Value != aOverwrittenSetting->Value )
+ *pInfo = *aOverwrittenSetting;
+ aRelevantSettings.erase(aOverwrittenSetting);
+ }
+ else if( pInfo->Name == "JDBCDRV" )
+ { // this is a compatibility setting, remove it from the sequence (it's replaced by JavaDriverClass)
+ nObsoleteSetting = i;
+ }
+ else
+ aPreservedSettings[i] = pInfo->Name;
+ }
+ if (-1 != nObsoleteSetting)
+ ::comphelper::removeElementAt(_rInfo, nObsoleteSetting);
+
+ if ( !aPreservedSettings.empty() )
+ { // check if there are settings which
+ // * are known as indirect properties
+ // * but not relevant for the current data source type
+ // These settings have to be removed: If they're not relevant, we have no UI for changing them.
+
+ // for this, we need a string-controlled quick access to m_aIndirectPropTranslator
+ std::set<OUString> aIndirectProps;
+ std::transform(m_aIndirectPropTranslator.begin(),
+ m_aIndirectPropTranslator.end(),
+ std::inserter(aIndirectProps,aIndirectProps.begin()),
+ ::o3tl::select2nd< MapInt2String::value_type >());
+
+ // now check the to-be-preserved props
+ std::vector< sal_Int32 > aRemoveIndexes;
+ sal_Int32 nPositionCorrector = 0;
+ for (auto const& preservedSetting : aPreservedSettings)
+ {
+ if (aIndirectProps.end() != aIndirectProps.find(preservedSetting.second))
+ {
+ aRemoveIndexes.push_back(preservedSetting.first - nPositionCorrector);
+ ++nPositionCorrector;
+ }
+ }
+ // now finally remove all such props
+ for (auto const& removeIndex : aRemoveIndexes)
+ ::comphelper::removeElementAt(_rInfo, removeIndex);
+ }
+
+ Sequence< Any> aTypeSettings;
+ aTypeSettings = aProperties.getOrDefault("TypeInfoSettings",aTypeSettings);
+ // here we have a special entry for types from oracle
+ if ( aTypeSettings.hasElements() )
+ {
+ aRelevantSettings.insert(PropertyValue("TypeInfoSettings", 0, Any(aTypeSettings), PropertyState_DIRECT_VALUE));
+ }
+
+ // check which values are still left ('cause they were not present in the original sequence, but are to be set)
+ if ( aRelevantSettings.empty() )
+ return;
+
+ sal_Int32 nOldLength = _rInfo.getLength();
+ _rInfo.realloc(nOldLength + aRelevantSettings.size());
+ PropertyValue* pAppendValues = _rInfo.getArray() + nOldLength;
+ for (auto const& relevantSetting : aRelevantSettings)
+ {
+ if ( relevantSetting.Name == INFO_CHARSET )
+ {
+ OUString sCharSet;
+ relevantSetting.Value >>= sCharSet;
+ if ( !sCharSet.isEmpty() )
+ *pAppendValues = relevantSetting;
+ }
+ else
+ *pAppendValues = relevantSetting;
+ ++pAppendValues;
+ }
+}
+
+Any ODbDataSourceAdministrationHelper::implTranslateProperty(const SfxPoolItem* _pItem)
+{
+ // translate the SfxPoolItem
+ Any aValue;
+
+ const SfxStringItem* pStringItem = dynamic_cast<const SfxStringItem*>( _pItem );
+ const SfxBoolItem* pBoolItem = dynamic_cast<const SfxBoolItem*>( _pItem );
+ const OptionalBoolItem* pOptBoolItem = dynamic_cast<const OptionalBoolItem*>( _pItem );
+ const SfxInt32Item* pInt32Item = dynamic_cast< const SfxInt32Item* >( _pItem );
+ const OStringListItem* pStringListItem = dynamic_cast<const OStringListItem*>( _pItem );
+
+ if ( pStringItem )
+ {
+ aValue <<= pStringItem->GetValue();
+ }
+ else if ( pBoolItem )
+ {
+ aValue <<= pBoolItem->GetValue();
+ }
+ else if ( pOptBoolItem )
+ {
+ if ( !pOptBoolItem->HasValue() )
+ aValue.clear();
+ else
+ aValue <<= pOptBoolItem->GetValue();
+ }
+ else if ( pInt32Item )
+ {
+ aValue <<= pInt32Item->GetValue();
+ }
+ else if ( pStringListItem )
+ {
+ aValue <<= pStringListItem->getList();
+ }
+ else
+ {
+ OSL_FAIL("ODbDataSourceAdministrationHelper::implTranslateProperty: unsupported item type!");
+ return aValue;
+ }
+
+ return aValue;
+}
+
+void ODbDataSourceAdministrationHelper::implTranslateProperty(const Reference< XPropertySet >& _rxSet, const OUString& _rName, const SfxPoolItem* _pItem)
+{
+ Any aValue = implTranslateProperty(_pItem);
+ lcl_putProperty(_rxSet, _rName,aValue);
+}
+
+OString ODbDataSourceAdministrationHelper::translatePropertyId( sal_Int32 _nId )
+{
+ OUString aString;
+
+ MapInt2String::const_iterator aPos = m_aDirectPropTranslator.find( _nId );
+ if ( m_aDirectPropTranslator.end() != aPos )
+ {
+ aString = aPos->second;
+ }
+ else
+ {
+ MapInt2String::const_iterator indirectPos = m_aIndirectPropTranslator.find( _nId );
+ if ( m_aIndirectPropTranslator.end() != indirectPos )
+ aString = indirectPos->second;
+ }
+
+ OString aReturn( aString.getStr(), aString.getLength(), RTL_TEXTENCODING_ASCII_US );
+ return aReturn;
+}
+template<class T> static bool checkItemType(const SfxPoolItem* pItem){ return dynamic_cast<const T*>(pItem) != nullptr;}
+
+void ODbDataSourceAdministrationHelper::implTranslateProperty( SfxItemSet& _rSet, sal_Int32 _nId, const Any& _rValue )
+{
+ switch ( _rValue.getValueType().getTypeClass() )
+ {
+ case TypeClass_STRING:
+ if ( implCheckItemType( _rSet, _nId, checkItemType<SfxStringItem> ) )
+ {
+ OUString sValue;
+ _rValue >>= sValue;
+ _rSet.Put(SfxStringItem(_nId, sValue));
+ }
+ else {
+ SAL_WARN( "dbaccess", "ODbDataSourceAdministrationHelper::implTranslateProperty: invalid property value ("
+ << translatePropertyId(_nId) << " should be no string)!");
+ }
+ break;
+
+ case TypeClass_BOOLEAN:
+ if ( implCheckItemType( _rSet, _nId, checkItemType<SfxBoolItem> ) )
+ {
+ bool bVal = false;
+ _rValue >>= bVal;
+ _rSet.Put(SfxBoolItem(_nId, bVal));
+ }
+ else if ( implCheckItemType( _rSet, _nId, checkItemType<OptionalBoolItem> ) )
+ {
+ OptionalBoolItem aItem( _nId );
+ if ( _rValue.hasValue() )
+ {
+ bool bValue = false;
+ _rValue >>= bValue;
+ aItem.SetValue( bValue );
+ }
+ else
+ aItem.ClearValue();
+ _rSet.Put( aItem );
+ }
+ else {
+ SAL_WARN( "dbaccess", "ODbDataSourceAdministrationHelper::implTranslateProperty: invalid property value ("
+ << translatePropertyId(_nId)
+ << " should be no boolean)!");
+ }
+ break;
+
+ case TypeClass_LONG:
+ if ( implCheckItemType( _rSet, _nId, checkItemType<SfxInt32Item> ) )
+ {
+ sal_Int32 nValue = 0;
+ _rValue >>= nValue;
+ _rSet.Put( SfxInt32Item( _nId, nValue ) );
+ }
+ else {
+ SAL_WARN( "dbaccess", "ODbDataSourceAdministrationHelper::implTranslateProperty: invalid property value ("
+ << translatePropertyId(_nId)
+ << " should be no int)!");
+ }
+ break;
+
+ case TypeClass_SEQUENCE:
+ if ( implCheckItemType( _rSet, _nId, checkItemType<OStringListItem> ) )
+ {
+ // determine the element type
+ TypeDescription aTD(_rValue.getValueType());
+ typelib_IndirectTypeDescription* pSequenceTD =
+ reinterpret_cast< typelib_IndirectTypeDescription* >(aTD.get());
+ OSL_ENSURE(pSequenceTD && pSequenceTD->pType, "ODbDataSourceAdministrationHelper::implTranslateProperty: invalid sequence type!");
+
+ Type aElementType(pSequenceTD->pType);
+ switch (aElementType.getTypeClass())
+ {
+ case TypeClass_STRING:
+ {
+ Sequence< OUString > aStringList;
+ _rValue >>= aStringList;
+ _rSet.Put(OStringListItem(_nId, aStringList));
+ }
+ break;
+ default:
+ OSL_FAIL("ODbDataSourceAdministrationHelper::implTranslateProperty: unsupported property value type!");
+ }
+ }
+ else {
+ SAL_WARN( "dbaccess", "ODbDataSourceAdministrationHelper::implTranslateProperty: invalid property value ("
+ << translatePropertyId(_nId)
+ << " should be no string sequence)!");
+ }
+ break;
+
+ case TypeClass_VOID:
+ _rSet.ClearItem(_nId);
+ break;
+
+ default:
+ OSL_FAIL("ODbDataSourceAdministrationHelper::implTranslateProperty: unsupported property value type!");
+ }
+}
+
+OUString ODbDataSourceAdministrationHelper::getDocumentUrl(SfxItemSet const & _rDest)
+{
+ const SfxStringItem* pUrlItem = _rDest.GetItem<SfxStringItem>(DSID_DOCUMENT_URL);
+ OSL_ENSURE(pUrlItem,"Document URL is NULL. -> GPF!");
+ return pUrlItem->GetValue();
+}
+
+void ODbDataSourceAdministrationHelper::convertUrl(SfxItemSet& _rDest)
+{
+ OUString eType = getDatasourceType(_rDest);
+
+ const SfxStringItem* pUrlItem = _rDest.GetItem<SfxStringItem>(DSID_CONNECTURL);
+ const DbuTypeCollectionItem* pTypeCollection = _rDest.GetItem<DbuTypeCollectionItem>(DSID_TYPECOLLECTION);
+
+ OSL_ENSURE(pUrlItem,"Connection URL is NULL. -> GPF!");
+ OSL_ENSURE(pTypeCollection, "ODbAdminDialog::getDatasourceType: invalid items in the source set!");
+ ::dbaccess::ODsnTypeCollection* pCollection = pTypeCollection->getCollection();
+ OSL_ENSURE(pCollection, "ODbAdminDialog::getDatasourceType: invalid type collection!");
+
+ sal_uInt16 nPortNumberId = 0;
+ sal_Int32 nPortNumber = -1;
+ OUString sNewHostName;
+ OUString sUrlPart;
+
+ pCollection->extractHostNamePort(pUrlItem->GetValue(),sUrlPart,sNewHostName,nPortNumber);
+ const ::dbaccess::DATASOURCE_TYPE eTy = pCollection->determineType(eType);
+
+ switch( eTy )
+ {
+ case ::dbaccess::DST_MYSQL_NATIVE:
+ case ::dbaccess::DST_MYSQL_JDBC:
+ nPortNumberId = DSID_MYSQL_PORTNUMBER;
+ break;
+ case ::dbaccess::DST_ORACLE_JDBC:
+ nPortNumberId = DSID_ORACLE_PORTNUMBER;
+ break;
+ case ::dbaccess::DST_LDAP:
+ nPortNumberId = DSID_CONN_LDAP_PORTNUMBER;
+ break;
+ default:
+ break;
+ }
+
+ if ( !sUrlPart.isEmpty() )
+ {
+ if ( eTy == ::dbaccess::DST_MYSQL_NATIVE )
+ {
+ _rDest.Put( SfxStringItem( DSID_DATABASENAME, sUrlPart ) );
+ }
+ else
+ {
+ OUString sNewUrl = pCollection->getPrefix(eType) + sUrlPart;
+ _rDest.Put( SfxStringItem( DSID_CONNECTURL, sNewUrl ) );
+ }
+ }
+
+ if ( !sNewHostName.isEmpty() )
+ _rDest.Put(SfxStringItem(DSID_CONN_HOSTNAME, sNewHostName));
+
+ if ( nPortNumber != -1 && nPortNumberId != 0 )
+ _rDest.Put(SfxInt32Item(nPortNumberId, nPortNumber));
+
+}
+
+bool ODbDataSourceAdministrationHelper::saveChanges(const SfxItemSet& _rSource)
+{
+ // put the remembered settings into the property set
+ Reference<XPropertySet> xDatasource = getCurrentDataSource();
+ if ( !xDatasource.is() )
+ return false;
+
+ translateProperties(_rSource,xDatasource );
+
+ return true;
+}
+
+void ODbDataSourceAdministrationHelper::setDataSourceOrName( const Any& _rDataSourceOrName )
+{
+ OSL_ENSURE( !m_aDataSourceOrName.hasValue(), "ODbDataSourceAdministrationHelper::setDataSourceOrName: already have one!" );
+ // hmm. We could reset m_xDatasource/m_xModel, probably, and continue working
+ m_aDataSourceOrName = _rDataSourceOrName;
+}
+
+// DbuTypeCollectionItem
+DbuTypeCollectionItem::DbuTypeCollectionItem(sal_Int16 _nWhich, ::dbaccess::ODsnTypeCollection* _pCollection)
+ :SfxPoolItem(_nWhich)
+ ,m_pCollection(_pCollection)
+{
+}
+
+DbuTypeCollectionItem::DbuTypeCollectionItem(const DbuTypeCollectionItem& _rSource)
+ :SfxPoolItem(_rSource)
+ ,m_pCollection(_rSource.getCollection())
+{
+}
+
+bool DbuTypeCollectionItem::operator==(const SfxPoolItem& _rItem) const
+{
+ return SfxPoolItem::operator==(_rItem) &&
+ static_cast<const DbuTypeCollectionItem&>( _rItem ).getCollection() == getCollection();
+}
+
+DbuTypeCollectionItem* DbuTypeCollectionItem::Clone(SfxItemPool* /*_pPool*/) const
+{
+ return new DbuTypeCollectionItem(*this);
+}
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/dlg/DbAdminImpl.hxx b/dbaccess/source/ui/dlg/DbAdminImpl.hxx
new file mode 100644
index 000000000..22a61ecee
--- /dev/null
+++ b/dbaccess/source/ui/dlg/DbAdminImpl.hxx
@@ -0,0 +1,167 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <sal/config.h>
+
+#include <map>
+
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/beans/PropertyValue.hpp>
+#include <com/sun/star/sdb/XDatabaseContext.hpp>
+#include <com/sun/star/sdbc/XConnection.hpp>
+#include <com/sun/star/sdbc/XDriver.hpp>
+#include <dsntypes.hxx>
+#include <svl/itemset.hxx>
+#include <com/sun/star/frame/XModel.hpp>
+#include <svl/poolitem.hxx>
+#include <vcl/weld.hxx>
+
+namespace dbaui
+{
+ namespace DataSourceInfoConverter
+ {
+ void convert(const css::uno::Reference< css::uno::XComponentContext> & xContext,
+ const ::dbaccess::ODsnTypeCollection* _pCollection,
+ const OUString& _sOldURLPrefix,
+ const OUString& _sNewURLPrefix,
+ const css::uno::Reference< css::beans::XPropertySet >& _xDatasource);
+ };
+ class IItemSetHelper;
+ // ODbDataSourceAdministrationHelper
+ class ODbDataSourceAdministrationHelper final
+ {
+ public:
+ typedef std::map<sal_Int32, OUString> MapInt2String;
+
+ private:
+ css::uno::Reference< css::uno::XComponentContext >
+ m_xContext; /// service factory
+ css::uno::Reference< css::sdb::XDatabaseContext >
+ m_xDatabaseContext; /// database context we're working in
+ css::uno::Reference< css::beans::XPropertySet > m_xDatasource;
+ css::uno::Reference< css::frame::XModel > m_xModel;
+
+ css::uno::Any m_aDataSourceOrName;
+
+ MapInt2String m_aDirectPropTranslator; /// translating property id's into names (direct properties of a data source)
+ MapInt2String m_aIndirectPropTranslator; /// translating property id's into names (indirect properties of a data source)
+ weld::Window* m_pParent;
+ IItemSetHelper* m_pItemSetHelper;
+ public:
+
+ ODbDataSourceAdministrationHelper(const css::uno::Reference< css::uno::XComponentContext >& _xORB,
+ weld::Window* pParent, weld::Window* pTopParent,
+ IItemSetHelper* _pItemSetHelper);
+
+ /** translate the current dialog SfxItems into driver relevant PropertyValues
+ @see successfullyConnected
+ */
+ bool getCurrentSettings(css::uno::Sequence< css::beans::PropertyValue >& _rDriverParams);
+
+ /** to be called if the settings got from getCurrentSettings have been used for successfully connecting
+ @see getCurrentSettings
+ */
+ void successfullyConnected();
+
+ /// clear the password in the current data source's item set
+ void clearPassword();
+
+ const css::uno::Reference< css::uno::XComponentContext >& getORB() const { return m_xContext; }
+
+ /** creates a new connection. The caller is responsible to dispose it !!!!
+ */
+ std::pair< css::uno::Reference< css::sdbc::XConnection >,bool> createConnection();
+
+ /** return the corresponding driver for the selected URL
+ */
+ css::uno::Reference< css::sdbc::XDriver > getDriver();
+ css::uno::Reference< css::sdbc::XDriver > getDriver(const OUString& _sURL);
+
+ /** returns the data source the dialog is currently working with
+ */
+ css::uno::Reference< css::beans::XPropertySet > const & getCurrentDataSource();
+ // returns the Url of a database document
+ static OUString getDocumentUrl(SfxItemSet const & _rDest);
+
+ void setDataSourceOrName( const css::uno::Any& _rDataSourceOrName );
+
+ /** extracts the connection type from the given set<p/>
+ The connection type is determined by the value of the DSN item, analyzed by the TypeCollection item.
+ */
+ static OUString getDatasourceType( const SfxItemSet& _rSet );
+
+ /** returns the connection URL
+ @return
+ The connection URL
+ */
+ OUString getConnectionURL() const;
+
+ /// fill the necessary information from the url line
+ static void convertUrl(SfxItemSet& _rDest);
+
+ const MapInt2String& getIndirectProperties() const { return m_aIndirectPropTranslator; }
+
+ /** translates properties of a UNO data source into SfxItems
+ @param _rxSource
+ The data source
+ @param _rDest
+ The item set to fill.
+ */
+ void translateProperties(
+ const css::uno::Reference< css::beans::XPropertySet >& _rxSource,
+ SfxItemSet& _rDest);
+
+ /** translate SfxItems into properties of a UNO data source
+ @param _rSource
+ The item set to read from.
+ @param _rxDest
+ The data source to fill.
+ */
+ void translateProperties(
+ const SfxItemSet& _rSource,
+ const css::uno::Reference< css::beans::XPropertySet >& _rxDest);
+
+ bool saveChanges(const SfxItemSet& _rSource);
+ private:
+ /** fill a data source info array with the settings from a given item set
+ */
+ void fillDatasourceInfo(const SfxItemSet& _rSource, css::uno::Sequence< css::beans::PropertyValue >& _rInfo);
+
+ /// translate the given value into an SfxPoolItem, put this into the given set under the given id
+ void implTranslateProperty(SfxItemSet& _rSet, sal_Int32 _nId, const css::uno::Any& _rValue);
+
+ /// translate the given SfxPoolItem into an <type scope="com.sun.star.Any">uno</type>
+ static css::uno::Any implTranslateProperty(const SfxPoolItem* _pItem);
+
+ /// translate the given SfxPoolItem into an <type scope="com.sun.star.Any">uno</type>, set it (under the given name) on the given property set
+ static void implTranslateProperty(const css::uno::Reference< css::beans::XPropertySet >& _rxSet, const OUString& _rName, const SfxPoolItem* _pItem);
+
+ /** check if the data source described by the given set needs authentication<p/>
+ The return value depends on the data source type only.
+ */
+ static bool hasAuthentication(const SfxItemSet& _rSet);
+
+ OString translatePropertyId( sal_Int32 _nId );
+ };
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/dlg/DriverSettings.hxx b/dbaccess/source/ui/dlg/DriverSettings.hxx
new file mode 100644
index 000000000..72ce3d459
--- /dev/null
+++ b/dbaccess/source/ui/dlg/DriverSettings.hxx
@@ -0,0 +1,78 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <sfx2/tabdlg.hxx>
+
+class SfxTabPage;
+namespace dbaui
+{
+ /// a collection class for all details a driver needs
+ class ODriversSettings
+ {
+ public:
+
+ /** Creates the detail page for ado
+ */
+ static std::unique_ptr<SfxTabPage> CreateDbase( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* _rAttrSet );
+
+ /** Creates the detail page for ado
+ */
+ static std::unique_ptr<SfxTabPage> CreateAdo( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* _rAttrSet );
+
+ /** Creates the detail page for ODBC
+ */
+ static std::unique_ptr<SfxTabPage> CreateODBC( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* _rAttrSet );
+
+ /** Creates the detail page for user
+ */
+ static std::unique_ptr<SfxTabPage> CreateUser( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* _rAttrSet );
+
+ /** Creates the detail page for MySQLODBC
+ */
+ static std::unique_ptr<SfxTabPage> CreateMySQLODBC( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* _rAttrSet );
+
+ /** Creates the detail page for MySQLJDBC
+ */
+ static std::unique_ptr<SfxTabPage> CreateMySQLJDBC( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* _rAttrSet );
+
+ /** Creates the detail page for MySQLNATIVE
+ */
+ static std::unique_ptr<SfxTabPage> CreateMySQLNATIVE( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* _rAttrSet );
+
+ /** Creates the detail page for Oracle JDBC
+ */
+ static std::unique_ptr<SfxTabPage> CreateOracleJDBC( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* _rAttrSet );
+
+ /** Creates the detail page for LDAP
+ */
+ static std::unique_ptr<SfxTabPage> CreateLDAP( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* _rAttrSet );
+
+ /// Creates the detail page for Text
+ static std::unique_ptr<SfxTabPage> CreateText( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* _rAttrSet );
+
+ /// creates the GeneratedValues page
+ static std::unique_ptr<SfxTabPage> CreateGeneratedValuesPage( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* _rAttrSet );
+
+ /// creates the "Special Settings" page of the "Advanced Settings" dialog
+ static std::unique_ptr<SfxTabPage> CreateSpecialSettingsPage( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* _rAttrSet );
+ };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/dlg/QueryPropertiesDialog.cxx b/dbaccess/source/ui/dlg/QueryPropertiesDialog.cxx
new file mode 100644
index 000000000..df0d38e4b
--- /dev/null
+++ b/dbaccess/source/ui/dlg/QueryPropertiesDialog.cxx
@@ -0,0 +1,60 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <QueryPropertiesDialog.hxx>
+#include <strings.hrc>
+#include <core_resource.hxx>
+
+namespace dbaui
+{
+
+QueryPropertiesDialog::QueryPropertiesDialog(
+ weld::Window* pParent, const bool bDistinct, const sal_Int64 nLimit )
+ : GenericDialogController(pParent, "dbaccess/ui/querypropertiesdialog.ui", "QueryPropertiesDialog")
+ , m_xRB_Distinct(m_xBuilder->weld_radio_button("distinct"))
+ , m_xRB_NonDistinct(m_xBuilder->weld_radio_button("nondistinct"))
+ , m_xLB_Limit(m_xBuilder->weld_combo_box("limitbox"))
+{
+ m_xRB_Distinct->set_active(bDistinct);
+ m_xRB_NonDistinct->set_active(!bDistinct);
+
+ m_xLB_Limit->append(OUString::number(-1), DBA_RES(STR_QUERY_LIMIT_ALL)); // ALL_INT and ALL_STRING
+ /// Default values
+ sal_Int64 const aDefLimitAry[] =
+ {
+ 5,
+ 10,
+ 20,
+ 50
+ };
+ for (auto a : aDefLimitAry)
+ m_xLB_Limit->append(OUString::number(a), OUString::number(a));
+ OUString sInitial = OUString::number(nLimit);
+ auto nPos = m_xLB_Limit->find_id(sInitial);
+ if (nPos != -1)
+ m_xLB_Limit->set_active(nPos);
+ else
+ m_xLB_Limit->set_entry_text(OUString::number(nLimit));
+}
+
+sal_Int64 QueryPropertiesDialog::getLimit() const
+{
+ OUString sSelectedId = m_xLB_Limit->get_active_id();
+ if (!sSelectedId.isEmpty())
+ return sSelectedId.toInt64();
+ return m_xLB_Limit->get_active_text().toInt64();
+}
+
+QueryPropertiesDialog::~QueryPropertiesDialog()
+{
+}
+
+} ///dbaui namespace
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/dlg/RelationDlg.cxx b/dbaccess/source/ui/dlg/RelationDlg.cxx
new file mode 100644
index 000000000..cc449d9b7
--- /dev/null
+++ b/dbaccess/source/ui/dlg/RelationDlg.cxx
@@ -0,0 +1,215 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <RelationDlg.hxx>
+
+#include <com/sun/star/sdbc/KeyRule.hpp>
+#include <com/sun/star/sdbc/SQLException.hpp>
+
+#include <tools/diagnose_ex.h>
+#include <JoinDesignView.hxx>
+#include <JoinController.hxx>
+#include <connectivity/dbexception.hxx>
+#include <connectivity/dbtools.hxx>
+#include <RTableConnectionData.hxx>
+#include <RelationControl.hxx>
+#include <cppuhelper/exc_hlp.hxx>
+
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::beans;
+using namespace ::dbaui;
+using namespace ::dbtools;
+
+ORelationDialog::ORelationDialog( OJoinTableView* pParent,
+ const TTableConnectionData::value_type& pConnectionData,
+ bool bAllowTableSelect )
+ : GenericDialogController(pParent->GetFrameWeld(),
+ "dbaccess/ui/relationdialog.ui", "RelationDialog")
+ , m_pParent(pParent)
+ , m_pOrigConnData(pConnectionData)
+ , m_bTriedOneUpdate(false)
+ , m_xRB_NoCascUpd(m_xBuilder->weld_radio_button("addaction"))
+ , m_xRB_CascUpd(m_xBuilder->weld_radio_button("addcascade"))
+ , m_xRB_CascUpdNull(m_xBuilder->weld_radio_button("addnull"))
+ , m_xRB_CascUpdDefault(m_xBuilder->weld_radio_button("adddefault"))
+ , m_xRB_NoCascDel(m_xBuilder->weld_radio_button("delaction"))
+ , m_xRB_CascDel(m_xBuilder->weld_radio_button("delcascade"))
+ , m_xRB_CascDelNull(m_xBuilder->weld_radio_button("delnull"))
+ , m_xRB_CascDelDefault(m_xBuilder->weld_radio_button("deldefault"))
+ , m_xPB_OK(m_xBuilder->weld_button("ok"))
+{
+ // Copy connection
+ m_pConnData = pConnectionData->NewInstance();
+ m_pConnData->CopyFrom( *pConnectionData );
+
+ Init(m_pConnData);
+ m_xTableControl.reset(new OTableListBoxControl(m_xBuilder.get(), &pParent->GetTabWinMap(), this));
+
+ m_xPB_OK->connect_clicked(LINK(this, ORelationDialog, OKClickHdl));
+
+ m_xTableControl->Init( m_pConnData );
+ if ( bAllowTableSelect )
+ m_xTableControl->fillListBoxes();
+ else
+ m_xTableControl->fillAndDisable(pConnectionData);
+
+ m_xTableControl->lateInit();
+
+ m_xTableControl->NotifyCellChange();
+}
+
+ORelationDialog::~ORelationDialog()
+{
+}
+
+void ORelationDialog::Init(const TTableConnectionData::value_type& _pConnectionData)
+{
+ ORelationTableConnectionData* pConnData = static_cast<ORelationTableConnectionData*>(_pConnectionData.get());
+ // Update Rules
+ switch (pConnData->GetUpdateRules())
+ {
+ case KeyRule::NO_ACTION:
+ case KeyRule::RESTRICT:
+ m_xRB_NoCascUpd->set_active(true);
+ break;
+
+ case KeyRule::CASCADE:
+ m_xRB_CascUpd->set_active(true);
+ break;
+
+ case KeyRule::SET_NULL:
+ m_xRB_CascUpdNull->set_active(true);
+ break;
+ case KeyRule::SET_DEFAULT:
+ m_xRB_CascUpdDefault->set_active(true);
+ break;
+ }
+
+ // Delete Rules
+ switch (pConnData->GetDeleteRules())
+ {
+ case KeyRule::NO_ACTION:
+ case KeyRule::RESTRICT:
+ m_xRB_NoCascDel->set_active(true);
+ break;
+
+ case KeyRule::CASCADE:
+ m_xRB_CascDel->set_active(true);
+ break;
+
+ case KeyRule::SET_NULL:
+ m_xRB_CascDelNull->set_active(true);
+ break;
+ case KeyRule::SET_DEFAULT:
+ m_xRB_CascDelDefault->set_active(true);
+ break;
+ }
+}
+
+IMPL_LINK_NOARG(ORelationDialog, OKClickHdl, weld::Button&, void)
+{
+ // Read out RadioButtons
+ sal_uInt16 nAttrib = 0;
+
+ // Delete Rules
+ if( m_xRB_NoCascDel->get_active() )
+ nAttrib |= KeyRule::NO_ACTION;
+ if( m_xRB_CascDel->get_active() )
+ nAttrib |= KeyRule::CASCADE;
+ if( m_xRB_CascDelNull->get_active() )
+ nAttrib |= KeyRule::SET_NULL;
+ if( m_xRB_CascDelDefault->get_active() )
+ nAttrib |= KeyRule::SET_DEFAULT;
+
+ ORelationTableConnectionData* pConnData = static_cast<ORelationTableConnectionData*>(m_pConnData.get());
+ pConnData->SetDeleteRules( nAttrib );
+
+ // Update Rules
+ nAttrib = 0;
+ if( m_xRB_NoCascUpd->get_active() )
+ nAttrib |= KeyRule::NO_ACTION;
+ if( m_xRB_CascUpd->get_active() )
+ nAttrib |= KeyRule::CASCADE;
+ if( m_xRB_CascUpdNull->get_active() )
+ nAttrib |= KeyRule::SET_NULL;
+ if( m_xRB_CascUpdDefault->get_active() )
+ nAttrib |= KeyRule::SET_DEFAULT;
+ pConnData->SetUpdateRules( nAttrib );
+
+ m_xTableControl->SaveModified();
+
+ //// if the ComboBoxes for the table selection are enabled (constructor with bAllowTableSelect==sal_True),
+ //// then I must also put the table names into the connection
+ //m_pConnData->SetSourceWinName(m_xTableControl->getSourceWinName());
+ //m_pConnData->SetDestWinName(m_xTableControl->getDestWinName());
+
+ // try to create the relation
+ try
+ {
+ ORelationTableConnectionData* pOrigConnData = static_cast<ORelationTableConnectionData*>(m_pOrigConnData.get());
+ if ( *pConnData == *pOrigConnData || pConnData->Update())
+ {
+ m_pOrigConnData->CopyFrom( *m_pConnData );
+ m_xDialog->response(RET_OK);
+ return;
+ }
+ }
+ catch( const SQLException& )
+ {
+ ::dbtools::showError(SQLExceptionInfo(::cppu::getCaughtException()),
+ m_xDialog->GetXWindow(),
+ m_pParent->getDesignView()->getController().getORB());
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+
+ m_bTriedOneUpdate = true;
+ // this means that the original connection may be lost (if m_pConnData was not a newly created but an
+ // existent conn to be modified), which we reflect by returning RET_NO (see ::Execute)
+
+ // try again
+ Init(m_pConnData);
+ m_xTableControl->Init( m_pConnData );
+ m_xTableControl->lateInit();
+}
+
+short ORelationDialog::run()
+{
+ short nResult = GenericDialogController::run();
+ if ((nResult != RET_OK) && m_bTriedOneUpdate)
+ return RET_NO;
+
+ return nResult;
+}
+
+void ORelationDialog::setValid(bool _bValid)
+{
+ m_xPB_OK->set_sensitive(_bValid);
+}
+
+void ORelationDialog::notifyConnectionChange()
+{
+ Init(m_pConnData);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/dlg/TablesSingleDlg.cxx b/dbaccess/source/ui/dlg/TablesSingleDlg.cxx
new file mode 100644
index 000000000..bcf039c5e
--- /dev/null
+++ b/dbaccess/source/ui/dlg/TablesSingleDlg.cxx
@@ -0,0 +1,105 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <TablesSingleDlg.hxx>
+#include "DbAdminImpl.hxx"
+#include "tablespage.hxx"
+
+namespace dbaui
+{
+using namespace com::sun::star::uno;
+using namespace com::sun::star::sdbc;
+using namespace com::sun::star::lang;
+using namespace com::sun::star::beans;
+using namespace com::sun::star::container;
+
+ // OTableSubscriptionDialog
+OTableSubscriptionDialog::OTableSubscriptionDialog(weld::Window* pParent
+ ,const SfxItemSet* _pItems
+ ,const Reference< XComponentContext >& _rxORB
+ ,const css::uno::Any& _aDataSourceName)
+ : SfxSingleTabDialogController(pParent, _pItems,
+ "dbaccess/ui/tablesfilterdialog.ui", "TablesFilterDialog")
+ , m_pImpl(new ODbDataSourceAdministrationHelper(_rxORB, m_xDialog.get(), pParent, this))
+ , m_bStopExecution(false)
+{
+ m_pImpl->setDataSourceOrName(_aDataSourceName);
+ Reference< XPropertySet > xDatasource = m_pImpl->getCurrentDataSource();
+ m_pOutSet.reset(new SfxItemSet( *_pItems ));
+
+ m_pImpl->translateProperties(xDatasource, *m_pOutSet);
+ SetInputSet(m_pOutSet.get());
+
+ auto xTabPage = std::make_unique<OTableSubscriptionPage>(get_content_area(), this, *m_pOutSet);
+ xTabPage->SetServiceFactory(_rxORB);
+ SetTabPage(std::move(xTabPage));
+}
+
+OTableSubscriptionDialog::~OTableSubscriptionDialog()
+{
+}
+
+short OTableSubscriptionDialog::run()
+{
+ short nRet = RET_CANCEL;
+ if ( !m_bStopExecution )
+ {
+ nRet = SfxSingleTabDialogController::run();
+ if ( nRet == RET_OK )
+ {
+ m_pOutSet->Put(*GetOutputItemSet());
+ m_pImpl->saveChanges(*m_pOutSet);
+ }
+ }
+ return nRet;
+}
+
+bool OTableSubscriptionDialog::getCurrentSettings(Sequence< PropertyValue >& _rDriverParams)
+{
+ return m_pImpl->getCurrentSettings(_rDriverParams);
+}
+
+void OTableSubscriptionDialog::successfullyConnected()
+{
+ m_pImpl->successfullyConnected();
+}
+
+void OTableSubscriptionDialog::clearPassword()
+{
+ m_pImpl->clearPassword();
+}
+
+Reference< XPropertySet > const & OTableSubscriptionDialog::getCurrentDataSource()
+{
+ return m_pImpl->getCurrentDataSource();
+}
+
+const SfxItemSet* OTableSubscriptionDialog::getOutputSet() const
+{
+ return m_pOutSet.get();
+}
+
+SfxItemSet* OTableSubscriptionDialog::getWriteOutputSet()
+{
+ return m_pOutSet.get();
+}
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/dlg/TextConnectionHelper.cxx b/dbaccess/source/ui/dlg/TextConnectionHelper.cxx
new file mode 100644
index 000000000..15fa887f7
--- /dev/null
+++ b/dbaccess/source/ui/dlg/TextConnectionHelper.cxx
@@ -0,0 +1,392 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <core_resource.hxx>
+#include "TextConnectionHelper.hxx"
+#include <strings.hrc>
+#include <strings.hxx>
+#include <svl/itemset.hxx>
+#include <svl/stritem.hxx>
+#include <svl/eitem.hxx>
+#include <dsitems.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/weld.hxx>
+#include <vcl/mnemonic.hxx>
+#include <o3tl/string_view.hxx>
+
+namespace
+{
+
+OUString lcl_getListEntry(const OUString& rStr, sal_Int32& rIdx)
+{
+ const OUString sTkn {rStr.getToken( 0, '\t', rIdx )};
+ if (rIdx>=0)
+ {
+ rIdx = rStr.indexOf('\t', rIdx);
+ if (rIdx>=0 && ++rIdx>=rStr.getLength())
+ rIdx = -1;
+ }
+ return sTkn;
+}
+
+}
+
+namespace dbaui
+{
+
+ OTextConnectionHelper::OTextConnectionHelper(weld::Widget* pParent, const short _nAvailableSections)
+ : m_aFieldSeparatorList (DBA_RES(STR_AUTOFIELDSEPARATORLIST))
+ , m_aTextSeparatorList (STR_AUTOTEXTSEPARATORLIST)
+ , m_aTextNone (DBA_RES(STR_AUTOTEXT_FIELD_SEP_NONE))
+ , m_nAvailableSections( _nAvailableSections )
+ , m_xBuilder(Application::CreateBuilder(pParent, "dbaccess/ui/textpage.ui"))
+ , m_xContainer(m_xBuilder->weld_widget("TextPage"))
+ , m_xExtensionHeader(m_xBuilder->weld_widget("extensionframe"))
+ , m_xAccessTextFiles(m_xBuilder->weld_radio_button("textfile"))
+ , m_xAccessCSVFiles(m_xBuilder->weld_radio_button("csvfile"))
+ , m_xAccessOtherFiles(m_xBuilder->weld_radio_button("custom"))
+ , m_xOwnExtension(m_xBuilder->weld_entry("extension"))
+ , m_xExtensionExample(m_xBuilder->weld_label("example"))
+ , m_xFormatHeader(m_xBuilder->weld_widget("formatframe"))
+ , m_xFieldSeparatorLabel(m_xBuilder->weld_label("fieldlabel"))
+ , m_xFieldSeparator(m_xBuilder->weld_combo_box("fieldseparator"))
+ , m_xTextSeparatorLabel(m_xBuilder->weld_label("textlabel"))
+ , m_xTextSeparator(m_xBuilder->weld_combo_box("textseparator"))
+ , m_xDecimalSeparatorLabel(m_xBuilder->weld_label("decimallabel"))
+ , m_xDecimalSeparator(m_xBuilder->weld_combo_box("decimalseparator"))
+ , m_xThousandsSeparatorLabel(m_xBuilder->weld_label("thousandslabel"))
+ , m_xThousandsSeparator(m_xBuilder->weld_combo_box("thousandsseparator"))
+ , m_xRowHeader(m_xBuilder->weld_check_button("containsheaders"))
+ , m_xCharSetHeader(m_xBuilder->weld_widget("charsetframe"))
+ , m_xCharSetLabel(m_xBuilder->weld_label("charsetlabel"))
+ , m_xCharSet(new CharSetListBox(m_xBuilder->weld_combo_box("charset")))
+ {
+ for(sal_Int32 nIdx {0}; nIdx>=0;)
+ m_xFieldSeparator->append_text( lcl_getListEntry(m_aFieldSeparatorList, nIdx) );
+
+ for(sal_Int32 nIdx {0}; nIdx>=0;)
+ m_xTextSeparator->append_text( lcl_getListEntry(m_aTextSeparatorList, nIdx) );
+ m_xTextSeparator->append_text(m_aTextNone);
+
+ m_xOwnExtension->connect_changed(LINK(this, OTextConnectionHelper, OnEditModified));
+ m_xAccessTextFiles->connect_toggled(LINK(this, OTextConnectionHelper, OnSetExtensionHdl));
+ m_xAccessCSVFiles->connect_toggled(LINK(this, OTextConnectionHelper, OnSetExtensionHdl));
+ m_xAccessOtherFiles->connect_toggled(LINK(this, OTextConnectionHelper, OnSetExtensionHdl));
+ m_xAccessCSVFiles->set_active(true);
+
+ struct SectionDescriptor
+ {
+ short nFlag;
+ weld::Widget* pFrame;
+ } aSections[] = {
+ { TC_EXTENSION, m_xExtensionHeader.get() },
+ { TC_SEPARATORS, m_xFormatHeader.get() },
+ { TC_HEADER, m_xRowHeader.get() },
+ { TC_CHARSET, m_xCharSetHeader.get() },
+ { 0, nullptr }
+ };
+
+ for ( size_t section=0; section < SAL_N_ELEMENTS( aSections ) - 1; ++section )
+ {
+ if ( ( m_nAvailableSections & aSections[section].nFlag ) != 0 )
+ {
+ // the section is visible, no need to do anything here
+ continue;
+ }
+
+ // hide all elements from this section
+ aSections[section].pFrame->hide();
+ }
+
+ m_xContainer->show();
+ }
+
+ IMPL_LINK_NOARG(OTextConnectionHelper, OnEditModified, weld::Entry&, void)
+ {
+ m_aGetExtensionHandler.Call(this);
+ }
+
+ IMPL_LINK_NOARG(OTextConnectionHelper, OnSetExtensionHdl, weld::Toggleable&, void)
+ {
+ bool bDoEnable = m_xAccessOtherFiles->get_active();
+ m_xOwnExtension->set_sensitive(bDoEnable);
+ m_xExtensionExample->set_sensitive(bDoEnable);
+ m_aGetExtensionHandler.Call(this);
+ }
+
+ void OTextConnectionHelper::fillControls(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList)
+ {
+ _rControlList.emplace_back(new OSaveValueWidgetWrapper<weld::ComboBox>(m_xFieldSeparator.get()));
+ _rControlList.emplace_back(new OSaveValueWidgetWrapper<weld::ComboBox>(m_xTextSeparator.get()));
+ _rControlList.emplace_back(new OSaveValueWidgetWrapper<weld::ComboBox>(m_xDecimalSeparator.get()));
+ _rControlList.emplace_back(new OSaveValueWidgetWrapper<weld::ComboBox>(m_xThousandsSeparator.get()));
+ _rControlList.emplace_back(new OSaveValueWidgetWrapper<weld::Toggleable>(m_xRowHeader.get()));
+ _rControlList.emplace_back(new OSaveValueWidgetWrapper<weld::ComboBox>(m_xCharSet->get_widget()));
+ }
+
+ void OTextConnectionHelper::fillWindows(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList)
+ {
+ _rControlList.emplace_back(new ODisableWidgetWrapper<weld::Label>(m_xFieldSeparatorLabel.get()));
+ _rControlList.emplace_back(new ODisableWidgetWrapper<weld::Label>(m_xTextSeparatorLabel.get()));
+ _rControlList.emplace_back(new ODisableWidgetWrapper<weld::Label>(m_xDecimalSeparatorLabel.get()));
+ _rControlList.emplace_back(new ODisableWidgetWrapper<weld::Label>(m_xThousandsSeparatorLabel.get()));
+ _rControlList.emplace_back(new ODisableWidgetWrapper<weld::Widget>(m_xCharSetHeader.get()));
+ _rControlList.emplace_back(new ODisableWidgetWrapper<weld::Label>(m_xCharSetLabel.get()));
+ _rControlList.emplace_back(new ODisableWidgetWrapper<weld::ComboBox>(m_xCharSet->get_widget()));
+ }
+
+ void OTextConnectionHelper::implInitControls(const SfxItemSet& _rSet, bool _bValid)
+ {
+ if ( !_bValid )
+ return;
+
+ const SfxStringItem* pDelItem = _rSet.GetItem<SfxStringItem>(DSID_FIELDDELIMITER);
+ const SfxStringItem* pStrItem = _rSet.GetItem<SfxStringItem>(DSID_TEXTDELIMITER);
+ const SfxStringItem* pDecdelItem = _rSet.GetItem<SfxStringItem>(DSID_DECIMALDELIMITER);
+ const SfxStringItem* pThodelItem = _rSet.GetItem<SfxStringItem>(DSID_THOUSANDSDELIMITER);
+ const SfxStringItem* pExtensionItem = _rSet.GetItem<SfxStringItem>(DSID_TEXTFILEEXTENSION);
+ const SfxStringItem* pCharsetItem = _rSet.GetItem<SfxStringItem>(DSID_CHARSET);
+
+ if ( ( m_nAvailableSections & TC_EXTENSION ) != 0 )
+ {
+ m_aOldExtension = pExtensionItem->GetValue();
+ SetExtension( m_aOldExtension );
+ }
+
+ if ( ( m_nAvailableSections & TC_HEADER ) != 0 )
+ {
+ const SfxBoolItem* pHdrItem = _rSet.GetItem<SfxBoolItem>(DSID_TEXTFILEHEADER);
+ m_xRowHeader->set_active(pHdrItem->GetValue());
+ }
+
+ if ( ( m_nAvailableSections & TC_SEPARATORS ) != 0 )
+ {
+ SetSeparator(*m_xFieldSeparator, m_aFieldSeparatorList, pDelItem->GetValue());
+ SetSeparator(*m_xTextSeparator, m_aTextSeparatorList, pStrItem->GetValue());
+ m_xDecimalSeparator->set_entry_text( pDecdelItem->GetValue() );
+ m_xThousandsSeparator->set_entry_text( pThodelItem->GetValue() );
+ }
+
+ if ( ( m_nAvailableSections & TC_CHARSET ) != 0 )
+ {
+ m_xCharSet->SelectEntryByIanaName( pCharsetItem->GetValue() );
+ }
+ }
+
+ bool OTextConnectionHelper::prepareLeave()
+ {
+ OUString sExtension = GetExtension();
+ OUString aErrorText;
+ weld::Widget* pErrorWin = nullptr;
+ OUString aDelText(m_xFieldSeparator->get_active_text());
+ if(aDelText.isEmpty())
+ { // No FieldSeparator
+ aErrorText = DBA_RES(STR_AUTODELIMITER_MISSING);
+ aErrorText = aErrorText.replaceFirst("#1",m_xFieldSeparatorLabel->get_label());
+ pErrorWin = m_xFieldSeparator.get();
+ }
+ else if (m_xDecimalSeparator->get_active_text().isEmpty())
+ { // No DecimalSeparator
+ aErrorText = DBA_RES(STR_AUTODELIMITER_MISSING);
+ aErrorText = aErrorText.replaceFirst("#1",m_xDecimalSeparatorLabel->get_label());
+ pErrorWin = m_xDecimalSeparator.get();
+ }
+ else if (m_xTextSeparator->get_active_text() == m_xFieldSeparator->get_active_text())
+ { // Field and TextSeparator must not be the same
+ aErrorText = DBA_RES(STR_AUTODELIMITER_MUST_DIFFER);
+ aErrorText = aErrorText.replaceFirst("#1",m_xTextSeparatorLabel->get_label());
+ aErrorText = aErrorText.replaceFirst("#2",m_xFieldSeparatorLabel->get_label());
+ pErrorWin = m_xTextSeparator.get();
+ }
+ else if (m_xDecimalSeparator->get_active_text() == m_xThousandsSeparator->get_active_text())
+ { // Thousands and DecimalSeparator must not be the same
+ aErrorText = DBA_RES(STR_AUTODELIMITER_MUST_DIFFER);
+ aErrorText = aErrorText.replaceFirst("#1",m_xDecimalSeparatorLabel->get_label());
+ aErrorText = aErrorText.replaceFirst("#2",m_xThousandsSeparatorLabel->get_label());
+ pErrorWin = m_xDecimalSeparator.get();
+ }
+ else if (m_xFieldSeparator->get_active_text() == m_xThousandsSeparator->get_active_text())
+ { // Thousands and FieldSeparator must not be the same
+ aErrorText = DBA_RES(STR_AUTODELIMITER_MUST_DIFFER);
+ aErrorText = aErrorText.replaceFirst("#1",m_xFieldSeparatorLabel->get_label());
+ aErrorText = aErrorText.replaceFirst("#2",m_xThousandsSeparatorLabel->get_label());
+ pErrorWin = m_xFieldSeparator.get();
+ }
+ else if (m_xFieldSeparator->get_active_text() == m_xDecimalSeparator->get_active_text())
+ { // Tenner and FieldSeparator must not be the same
+ aErrorText = DBA_RES(STR_AUTODELIMITER_MUST_DIFFER);
+ aErrorText = aErrorText.replaceFirst("#1",m_xFieldSeparatorLabel->get_label());
+ aErrorText = aErrorText.replaceFirst("#2",m_xDecimalSeparatorLabel->get_label());
+ pErrorWin = m_xFieldSeparator.get();
+ }
+ else if (m_xTextSeparator->get_active_text() == m_xThousandsSeparator->get_active_text())
+ { // Thousands and TextSeparator must not be the same
+ aErrorText = DBA_RES(STR_AUTODELIMITER_MUST_DIFFER);
+ aErrorText = aErrorText.replaceFirst("#1",m_xTextSeparatorLabel->get_label());
+ aErrorText = aErrorText.replaceFirst("#2",m_xThousandsSeparatorLabel->get_label());
+ pErrorWin = m_xTextSeparator.get();
+ }
+ else if (m_xTextSeparator->get_active_text() == m_xDecimalSeparator->get_active_text())
+ { // Tenner and TextSeparator must not be the same
+ aErrorText = DBA_RES(STR_AUTODELIMITER_MUST_DIFFER);
+ aErrorText = aErrorText.replaceFirst("#1",m_xTextSeparatorLabel->get_label());
+ aErrorText = aErrorText.replaceFirst("#2",m_xDecimalSeparatorLabel->get_label());
+ pErrorWin = m_xTextSeparator.get();
+ }
+ else if ((sExtension.indexOf('*') != -1) || (sExtension.indexOf('?') != -1))
+ {
+ aErrorText = DBA_RES(STR_AUTONO_WILDCARDS);
+ aErrorText = aErrorText.replaceFirst("#1",sExtension);
+ pErrorWin = m_xOwnExtension.get();
+ }
+ else
+ return true;
+ std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(m_xContainer.get(),
+ VclMessageType::Warning, VclButtonsType::Ok,
+ MnemonicGenerator::EraseAllMnemonicChars(aErrorText)));
+ xBox->run();
+ pErrorWin->grab_focus();
+ return false;
+ }
+
+ bool OTextConnectionHelper::FillItemSet( SfxItemSet& rSet, const bool _bChangedSomething )
+ {
+ bool bChangedSomething = _bChangedSomething;
+
+ if ( ( m_nAvailableSections & TC_EXTENSION ) != 0 )
+ {
+ OUString sExtension = GetExtension();
+ if( m_aOldExtension != sExtension )
+ {
+ rSet.Put( SfxStringItem( DSID_TEXTFILEEXTENSION, sExtension ) );
+ bChangedSomething = true;
+ }
+ }
+
+ if ( ( m_nAvailableSections & TC_HEADER ) != 0 )
+ {
+ if (m_xRowHeader->get_state_changed_from_saved())
+ {
+ rSet.Put(SfxBoolItem(DSID_TEXTFILEHEADER, m_xRowHeader->get_active()));
+ bChangedSomething = true;
+ }
+ }
+
+ if ( ( m_nAvailableSections & TC_SEPARATORS ) != 0 )
+ {
+ if (m_xFieldSeparator->get_value_changed_from_saved())
+ {
+ rSet.Put( SfxStringItem(DSID_FIELDDELIMITER, GetSeparator( *m_xFieldSeparator, m_aFieldSeparatorList) ) );
+ bChangedSomething = true;
+ }
+ if (m_xTextSeparator->get_value_changed_from_saved())
+ {
+ rSet.Put( SfxStringItem(DSID_TEXTDELIMITER, GetSeparator( *m_xTextSeparator, m_aTextSeparatorList) ) );
+ bChangedSomething = true;
+ }
+
+ if (m_xDecimalSeparator->get_value_changed_from_saved())
+ {
+ rSet.Put( SfxStringItem(DSID_DECIMALDELIMITER, m_xDecimalSeparator->get_active_text().copy(0, 1) ) );
+ bChangedSomething = true;
+ }
+ if (m_xThousandsSeparator->get_value_changed_from_saved())
+ {
+ rSet.Put( SfxStringItem(DSID_THOUSANDSDELIMITER, m_xThousandsSeparator->get_active_text().copy(0,1) ) );
+ bChangedSomething = true;
+ }
+ }
+
+ if ( ( m_nAvailableSections & TC_CHARSET ) != 0 )
+ {
+ if ( m_xCharSet->StoreSelectedCharSet( rSet, DSID_CHARSET ) )
+ bChangedSomething = true;
+ }
+
+ return bChangedSomething;
+ }
+
+ void OTextConnectionHelper::SetExtension(const OUString& _rVal)
+ {
+ if (_rVal == "txt")
+ m_xAccessTextFiles->set_active(true);
+ else if (_rVal == "csv")
+ m_xAccessCSVFiles->set_active(true);
+ else
+ {
+ m_xAccessOtherFiles->set_active(true);
+ m_xExtensionExample->set_label(_rVal);
+ }
+ }
+
+ OUString OTextConnectionHelper::GetExtension() const
+ {
+ OUString sExtension;
+ if (m_xAccessTextFiles->get_active())
+ sExtension = "txt";
+ else if (m_xAccessCSVFiles->get_active())
+ sExtension = "csv";
+ else
+ {
+ sExtension = m_xOwnExtension->get_text();
+ if ( sExtension.startsWith("*.") )
+ sExtension = sExtension.copy(2);
+ }
+ return sExtension;
+ }
+
+ OUString OTextConnectionHelper::GetSeparator(const weld::ComboBox& rBox, std::u16string_view rList)
+ {
+ sal_Unicode const nTok = '\t';
+ int nPos(rBox.find_text(rBox.get_active_text()));
+
+ if (nPos == -1)
+ return rBox.get_active_text();
+
+ if ( m_xTextSeparator.get() != &rBox || nPos != (rBox.get_count()-1) )
+ return OUString(
+ static_cast< sal_Unicode >( o3tl::toInt32(o3tl::getToken(rList, (nPos*2)+1, nTok )) ));
+ // somewhat strange ... translates for instance an "32" into " "
+ return OUString();
+ }
+
+ void OTextConnectionHelper::SetSeparator( weld::ComboBox& rBox, std::u16string_view rList, const OUString& rVal )
+ {
+ if (rVal.getLength()==1)
+ {
+ const sal_Unicode nVal {rVal[0]};
+ for(sal_Int32 nIdx {0}; nIdx>=0;)
+ {
+ sal_Int32 nPrevIdx {nIdx};
+ if (static_cast<sal_Unicode>(o3tl::toInt32(o3tl::getToken(rList, 1, '\t', nIdx))) == nVal)
+ {
+ rBox.set_entry_text(OUString(o3tl::getToken(rList,0, '\t', nPrevIdx)));
+ return;
+ }
+ }
+ rBox.set_entry_text( rVal );
+ }
+ else if ( m_xTextSeparator.get() == &rBox && rVal.isEmpty() )
+ rBox.set_entry_text(m_aTextNone);
+ else
+ rBox.set_entry_text(rVal.copy(0, 1));
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/dlg/TextConnectionHelper.hxx b/dbaccess/source/ui/dlg/TextConnectionHelper.hxx
new file mode 100644
index 000000000..6755a4223
--- /dev/null
+++ b/dbaccess/source/ui/dlg/TextConnectionHelper.hxx
@@ -0,0 +1,89 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include "adminpages.hxx"
+#include <charsetlistbox.hxx>
+#include <rtl/ustring.hxx>
+
+namespace dbaui
+
+{
+
+ #define TC_EXTENSION (short(0x01)) // a section specifying the extension of the files to connect to
+ #define TC_SEPARATORS (short(0x02)) // a section specifying the various separators
+ #define TC_HEADER (short(0x04)) // a section containing the "Text contains header" check box only
+ #define TC_CHARSET (short(0x08)) // not yet implemented
+
+ class OTextConnectionHelper final
+ {
+ public:
+ OTextConnectionHelper(weld::Widget* pParent , const short _nAvailableSections);
+
+ private:
+ OUString m_aFieldSeparatorList;
+ OUString m_aTextSeparatorList;
+ OUString m_aTextNone;
+ OUString m_aOldExtension;
+ Link<OTextConnectionHelper*, void> m_aGetExtensionHandler; /// to be called if a new type is selected
+
+ short m_nAvailableSections;
+
+ std::unique_ptr<weld::Builder> m_xBuilder;
+ std::unique_ptr<weld::Widget> m_xContainer;
+ std::unique_ptr<weld::Widget> m_xExtensionHeader;
+ std::unique_ptr<weld::RadioButton> m_xAccessTextFiles;
+ std::unique_ptr<weld::RadioButton> m_xAccessCSVFiles;
+ std::unique_ptr<weld::RadioButton> m_xAccessOtherFiles;
+ std::unique_ptr<weld::Entry> m_xOwnExtension;
+ std::unique_ptr<weld::Label> m_xExtensionExample;
+ std::unique_ptr<weld::Widget> m_xFormatHeader;
+ std::unique_ptr<weld::Label> m_xFieldSeparatorLabel;
+ std::unique_ptr<weld::ComboBox> m_xFieldSeparator;
+ std::unique_ptr<weld::Label> m_xTextSeparatorLabel;
+ std::unique_ptr<weld::ComboBox> m_xTextSeparator;
+ std::unique_ptr<weld::Label> m_xDecimalSeparatorLabel;
+ std::unique_ptr<weld::ComboBox> m_xDecimalSeparator;
+ std::unique_ptr<weld::Label> m_xThousandsSeparatorLabel;
+ std::unique_ptr<weld::ComboBox> m_xThousandsSeparator;
+ std::unique_ptr<weld::CheckButton> m_xRowHeader;
+ std::unique_ptr<weld::Widget> m_xCharSetHeader;
+ std::unique_ptr<weld::Label> m_xCharSetLabel;
+ std::unique_ptr<CharSetListBox> m_xCharSet;
+
+ DECL_LINK(OnSetExtensionHdl, weld::Toggleable&, void);
+ DECL_LINK(OnEditModified, weld::Entry&, void);
+
+ OUString GetSeparator(const weld::ComboBox& rBox, std::u16string_view rList);
+ void SetSeparator(weld::ComboBox& rBox, std::u16string_view rList, const OUString& rVal);
+ void SetExtension(const OUString& _rVal);
+
+ public:
+ void implInitControls(const SfxItemSet& _rSet, bool _bValid);
+ void fillControls(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList);
+ void fillWindows(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList);
+ void SetClickHandler(const Link<OTextConnectionHelper*, void>& _rHandler) { m_aGetExtensionHandler = _rHandler; }
+ OUString GetExtension() const;
+ bool FillItemSet( SfxItemSet& rSet, const bool bChangedSomething );
+ bool prepareLeave();
+ };
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/dlg/UserAdmin.cxx b/dbaccess/source/ui/dlg/UserAdmin.cxx
new file mode 100644
index 000000000..b601c4939
--- /dev/null
+++ b/dbaccess/source/ui/dlg/UserAdmin.cxx
@@ -0,0 +1,316 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "UserAdmin.hxx"
+#include <com/sun/star/sdbc/SQLException.hpp>
+#include <com/sun/star/sdbc/XDatabaseMetaData.hpp>
+#include <com/sun/star/sdbc/XDriver.hpp>
+#include <com/sun/star/sdbcx/XDataDefinitionSupplier.hpp>
+#include <com/sun/star/sdbcx/XUsersSupplier.hpp>
+#include <com/sun/star/sdbcx/XDrop.hpp>
+#include <com/sun/star/sdbcx/XDataDescriptorFactory.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/sdbcx/XUser.hpp>
+#include <com/sun/star/sdbcx/XAppend.hpp>
+#include <IItemSetHelper.hxx>
+#include <strings.hrc>
+#include <strings.hxx>
+#include <core_resource.hxx>
+#include <connectivity/dbexception.hxx>
+#include <connectivity/dbtools.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/weld.hxx>
+#include <sfx2/passwd.hxx>
+
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::sdbcx;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::task;
+using namespace dbaui;
+using namespace comphelper;
+
+namespace {
+
+class OPasswordDialog : public weld::GenericDialogController
+{
+ std::unique_ptr<weld::Frame> m_xUser;
+ std::unique_ptr<weld::Entry> m_xEDOldPassword;
+ std::unique_ptr<weld::Entry> m_xEDPassword;
+ std::unique_ptr<weld::Entry> m_xEDPasswordRepeat;
+ std::unique_ptr<weld::Button> m_xOKBtn;
+
+ DECL_LINK(OKHdl_Impl, weld::Button&, void);
+ DECL_LINK(ModifiedHdl, weld::Entry&, void);
+
+public:
+ OPasswordDialog(weld::Window* pParent, std::u16string_view rUserName);
+
+ OUString GetOldPassword() const { return m_xEDOldPassword->get_text(); }
+ OUString GetNewPassword() const { return m_xEDPassword->get_text(); }
+};
+
+}
+
+OPasswordDialog::OPasswordDialog(weld::Window* _pParent, std::u16string_view rUserName)
+ : GenericDialogController(_pParent, "dbaccess/ui/password.ui", "PasswordDialog")
+ , m_xUser(m_xBuilder->weld_frame("userframe"))
+ , m_xEDOldPassword(m_xBuilder->weld_entry("oldpassword"))
+ , m_xEDPassword(m_xBuilder->weld_entry("newpassword"))
+ , m_xEDPasswordRepeat(m_xBuilder->weld_entry("confirmpassword"))
+ , m_xOKBtn(m_xBuilder->weld_button("ok"))
+{
+ OUString sUser = m_xUser->get_label();
+ sUser = sUser.replaceFirst("$name$: $", rUserName);
+ m_xUser->set_label(sUser);
+ m_xOKBtn->set_sensitive(false);
+
+ m_xOKBtn->connect_clicked( LINK( this, OPasswordDialog, OKHdl_Impl ) );
+ m_xEDOldPassword->connect_changed( LINK( this, OPasswordDialog, ModifiedHdl ) );
+}
+
+IMPL_LINK_NOARG(OPasswordDialog, OKHdl_Impl, weld::Button&, void)
+{
+ if (m_xEDPassword->get_text() == m_xEDPasswordRepeat->get_text())
+ m_xDialog->response(RET_OK);
+ else
+ {
+ OUString aErrorMsg( DBA_RES( STR_ERROR_PASSWORDS_NOT_IDENTICAL));
+ std::unique_ptr<weld::MessageDialog> xErrorBox(Application::CreateMessageDialog(m_xDialog.get(),
+ VclMessageType::Warning, VclButtonsType::Ok,
+ aErrorMsg));
+ xErrorBox->run();
+ m_xEDPassword->set_text(OUString());
+ m_xEDPasswordRepeat->set_text(OUString());
+ m_xEDPassword->grab_focus();
+ }
+}
+
+IMPL_LINK(OPasswordDialog, ModifiedHdl, weld::Entry&, rEdit, void)
+{
+ m_xOKBtn->set_sensitive(!rEdit.get_text().isEmpty());
+}
+
+// OUserAdmin
+OUserAdmin::OUserAdmin(weld::Container* pPage, weld::DialogController* pController,const SfxItemSet& _rAttrSet)
+ : OGenericAdministrationPage(pPage, pController, "dbaccess/ui/useradminpage.ui", "UserAdminPage", _rAttrSet)
+ , m_xUSER(m_xBuilder->weld_combo_box("user"))
+ , m_xNEWUSER(m_xBuilder->weld_button("add"))
+ , m_xCHANGEPWD(m_xBuilder->weld_button("changepass"))
+ , m_xDELETEUSER(m_xBuilder->weld_button("delete"))
+ , m_xTable(m_xBuilder->weld_container("table"))
+ , m_xTableCtrlParent(m_xTable->CreateChildFrame())
+ , m_xTableCtrl(VclPtr<OTableGrantControl>::Create(m_xTableCtrlParent))
+{
+ m_xTableCtrl->Show();
+
+ m_xUSER->connect_changed(LINK(this, OUserAdmin, ListDblClickHdl));
+ m_xNEWUSER->connect_clicked(LINK(this, OUserAdmin, UserHdl));
+ m_xCHANGEPWD->connect_clicked(LINK(this, OUserAdmin, UserHdl));
+ m_xDELETEUSER->connect_clicked(LINK(this, OUserAdmin, UserHdl));
+}
+
+OUserAdmin::~OUserAdmin()
+{
+ m_xConnection = nullptr;
+ m_xTableCtrl.disposeAndClear();
+ m_xTableCtrlParent->dispose();
+ m_xTableCtrlParent.clear();
+}
+
+void OUserAdmin::FillUserNames()
+{
+ if(m_xConnection.is())
+ {
+ m_xUSER->clear();
+
+ Reference<XDatabaseMetaData> xMetaData = m_xConnection->getMetaData();
+
+ if ( xMetaData.is() )
+ {
+ m_UserName = xMetaData->getUserName();
+
+ // first we need the users
+ if ( m_xUsers.is() )
+ {
+ m_xUSER->clear();
+
+ m_aUserNames = m_xUsers->getElementNames();
+ const OUString* pBegin = m_aUserNames.getConstArray();
+ const OUString* pEnd = pBegin + m_aUserNames.getLength();
+ for(;pBegin != pEnd;++pBegin)
+ m_xUSER->append_text(*pBegin);
+
+ m_xUSER->set_active(0);
+ if(m_xUsers->hasByName(m_UserName))
+ {
+ Reference<XAuthorizable> xAuth;
+ m_xUsers->getByName(m_UserName) >>= xAuth;
+ m_xTableCtrl->setGrantUser(xAuth);
+ }
+
+ m_xTableCtrl->setUserName(GetUser());
+ m_xTableCtrl->Init();
+ }
+ }
+ }
+
+ Reference<XAppend> xAppend(m_xUsers,UNO_QUERY);
+ m_xNEWUSER->set_sensitive(xAppend.is());
+ Reference<XDrop> xDrop(m_xUsers,UNO_QUERY);
+ m_xDELETEUSER->set_sensitive(xDrop.is());
+
+ m_xCHANGEPWD->set_sensitive(m_xUsers.is());
+ m_xTableCtrl->Enable(m_xUsers.is());
+}
+
+std::unique_ptr<SfxTabPage> OUserAdmin::Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* _rAttrSet )
+{
+ return std::make_unique<OUserAdmin>( pPage, pController, *_rAttrSet );
+}
+
+IMPL_LINK(OUserAdmin, UserHdl, weld::Button&, rButton, void)
+{
+ try
+ {
+ if (&rButton == m_xNEWUSER.get())
+ {
+ SfxPasswordDialog aPwdDlg(GetFrameWeld());
+ aPwdDlg.ShowExtras(SfxShowExtras::ALL);
+ if (aPwdDlg.run())
+ {
+ Reference<XDataDescriptorFactory> xUserFactory(m_xUsers,UNO_QUERY);
+ Reference<XPropertySet> xNewUser = xUserFactory->createDataDescriptor();
+ if(xNewUser.is())
+ {
+ xNewUser->setPropertyValue(PROPERTY_NAME,Any(aPwdDlg.GetUser()));
+ xNewUser->setPropertyValue(PROPERTY_PASSWORD,Any(aPwdDlg.GetPassword()));
+ Reference<XAppend> xAppend(m_xUsers,UNO_QUERY);
+ if(xAppend.is())
+ xAppend->appendByDescriptor(xNewUser);
+ }
+ }
+ }
+ else if (&rButton == m_xCHANGEPWD.get())
+ {
+ OUString sName = GetUser();
+
+ if(m_xUsers->hasByName(sName))
+ {
+ Reference<XUser> xUser;
+ m_xUsers->getByName(sName) >>= xUser;
+ if(xUser.is())
+ {
+ OPasswordDialog aDlg(GetFrameWeld(), sName);
+ if (aDlg.run() == RET_OK)
+ {
+ OUString sNewPassword,sOldPassword;
+ sNewPassword = aDlg.GetNewPassword();
+ sOldPassword = aDlg.GetOldPassword();
+
+ if(!sNewPassword.isEmpty())
+ xUser->changePassword(sOldPassword,sNewPassword);
+ }
+ }
+ }
+ }
+ else
+ {// delete user
+ if(m_xUsers.is() && m_xUsers->hasByName(GetUser()))
+ {
+ Reference<XDrop> xDrop(m_xUsers,UNO_QUERY);
+ if(xDrop.is())
+ {
+ std::unique_ptr<weld::MessageDialog> xQry(Application::CreateMessageDialog(GetFrameWeld(),
+ VclMessageType::Question, VclButtonsType::YesNo,
+ DBA_RES(STR_QUERY_USERADMIN_DELETE_USER)));
+ if (xQry->run() == RET_YES)
+ xDrop->dropByName(GetUser());
+ }
+ }
+ }
+ FillUserNames();
+ }
+ catch(const SQLException& e)
+ {
+ ::dbtools::showError(::dbtools::SQLExceptionInfo(e), GetDialogController()->getDialog()->GetXWindow(), m_xORB);
+ }
+ catch(Exception& )
+ {
+ }
+}
+
+IMPL_LINK_NOARG(OUserAdmin, ListDblClickHdl, weld::ComboBox&, void)
+{
+ m_xTableCtrl->setUserName(GetUser());
+ m_xTableCtrl->UpdateTables();
+ m_xTableCtrl->DeactivateCell();
+ m_xTableCtrl->ActivateCell(m_xTableCtrl->GetCurRow(),m_xTableCtrl->GetCurColumnId());
+}
+
+OUString OUserAdmin::GetUser() const
+{
+ return m_xUSER->get_active_text();
+}
+
+void OUserAdmin::fillControls(std::vector< std::unique_ptr<ISaveValueWrapper> >& /*_rControlList*/)
+{
+}
+
+void OUserAdmin::fillWindows(std::vector< std::unique_ptr<ISaveValueWrapper> >& /*_rControlList*/)
+{
+}
+
+void OUserAdmin::implInitControls(const SfxItemSet& _rSet, bool _bSaveValue)
+{
+ m_xTableCtrl->setComponentContext(m_xORB);
+ try
+ {
+ if ( !m_xConnection.is() && m_pAdminDialog )
+ {
+ m_xConnection = m_pAdminDialog->createConnection().first;
+ Reference< XTablesSupplier > xTablesSup(m_xConnection,UNO_QUERY);
+ Reference<XUsersSupplier> xUsersSup(xTablesSup,UNO_QUERY);
+ if ( !xUsersSup.is() )
+ {
+ Reference< XDataDefinitionSupplier > xDriver(m_pAdminDialog->getDriver(),UNO_QUERY);
+ if ( xDriver.is() )
+ {
+ xUsersSup.set(xDriver->getDataDefinitionByConnection(m_xConnection),UNO_QUERY);
+ xTablesSup.set(xUsersSup,UNO_QUERY);
+ }
+ }
+ if ( xUsersSup.is() )
+ {
+ m_xTableCtrl->setTablesSupplier(xTablesSup);
+ m_xUsers = xUsersSup->getUsers();
+ }
+ }
+ FillUserNames();
+ }
+ catch(const SQLException& e)
+ {
+ ::dbtools::showError(::dbtools::SQLExceptionInfo(e), GetDialogController()->getDialog()->GetXWindow(), m_xORB);
+ }
+
+ OGenericAdministrationPage::implInitControls(_rSet, _bSaveValue);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/dlg/UserAdmin.hxx b/dbaccess/source/ui/dlg/UserAdmin.hxx
new file mode 100644
index 000000000..e9c2a13e7
--- /dev/null
+++ b/dbaccess/source/ui/dlg/UserAdmin.hxx
@@ -0,0 +1,74 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <TableGrantCtrl.hxx>
+#include "adminpages.hxx"
+
+namespace com::sun::star {
+ namespace sdbc {
+ class XConnection;
+ }
+}
+
+namespace dbaui
+{
+
+class OUserAdmin final : public OGenericAdministrationPage
+{
+ std::unique_ptr<weld::ComboBox> m_xUSER;
+ std::unique_ptr<weld::Button> m_xNEWUSER;
+ std::unique_ptr<weld::Button> m_xCHANGEPWD;
+ std::unique_ptr<weld::Button> m_xDELETEUSER;
+ std::unique_ptr<weld::Container> m_xTable;
+ css::uno::Reference<css::awt::XWindow> m_xTableCtrlParent;
+ VclPtr<OTableGrantControl> m_xTableCtrl; // show the grant rights of one user
+
+ css::uno::Reference< css::sdbc::XConnection> m_xConnection;
+ css::uno::Reference< css::container::XNameAccess > m_xUsers;
+ css::uno::Sequence< OUString> m_aUserNames;
+
+ OUString m_UserName;
+
+ // methods
+ DECL_LINK(ListDblClickHdl, weld::ComboBox&, void);
+ DECL_LINK(UserHdl, weld::Button&, void);
+
+ void FillUserNames();
+
+public:
+ OUserAdmin(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& _rCoreAttrs);
+ static std::unique_ptr<SfxTabPage> Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet);
+ virtual ~OUserAdmin() override;
+
+ OUString GetUser() const;
+
+ // subclasses must override this, but it isn't pure virtual
+ virtual void implInitControls(const SfxItemSet& _rSet, bool _bSaveValue) override;
+
+ // <method>OGenericAdministrationPage::fillControls</method>
+ virtual void fillControls(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) override;
+
+ // <method>OGenericAdministrationPage::fillWindows</method>
+ virtual void fillWindows(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) override;
+};
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/dlg/UserAdminDlg.cxx b/dbaccess/source/ui/dlg/UserAdminDlg.cxx
new file mode 100644
index 000000000..ec44c3399
--- /dev/null
+++ b/dbaccess/source/ui/dlg/UserAdminDlg.cxx
@@ -0,0 +1,162 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <core_resource.hxx>
+#include "adminpages.hxx"
+#include "DbAdminImpl.hxx"
+#include <strings.hrc>
+#include "UserAdmin.hxx"
+#include <UserAdminDlg.hxx>
+
+#include <com/sun/star/sdbc/SQLException.hpp>
+
+#include <connectivity/dbexception.hxx>
+#include <connectivity/dbmetadata.hxx>
+#include <connectivity/dbtools.hxx>
+#include <comphelper/types.hxx>
+#include <cppuhelper/exc_hlp.hxx>
+#include <tools/diagnose_ex.h>
+
+namespace dbaui
+{
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::beans;
+ using namespace ::com::sun::star::lang;
+ using namespace ::com::sun::star::sdbc;
+ using namespace ::com::sun::star::sdbcx;
+
+ // OUserAdminDlg
+ OUserAdminDlg::OUserAdminDlg(weld::Window* pParent,
+ SfxItemSet* pItems,
+ const Reference< XComponentContext >& rxORB,
+ const css::uno::Any& rDataSourceName,
+ const Reference< XConnection >& xConnection)
+ : SfxTabDialogController(pParent, "dbaccess/ui/useradmindialog.ui", "UserAdminDialog", pItems)
+ , m_pParent(pParent)
+ , m_pItemSet(pItems)
+ , m_xConnection(xConnection)
+ , m_bOwnConnection(!xConnection.is())
+ {
+ m_pImpl.reset(new ODbDataSourceAdministrationHelper(rxORB, m_xDialog.get(), pParent, this));
+ m_pImpl->setDataSourceOrName(rDataSourceName);
+ Reference< XPropertySet > xDatasource = m_pImpl->getCurrentDataSource();
+ m_pImpl->translateProperties(xDatasource, *pItems);
+ SetInputSet(pItems);
+ // propagate this set as our new input set and reset the example set
+ m_xExampleSet.reset(new SfxItemSet(*GetInputSetImpl()));
+
+ AddTabPage("settings", OUserAdmin::Create, nullptr);
+
+ // remove the reset button - it's meaning is much too ambiguous in this dialog
+ RemoveResetButton();
+ }
+
+ OUserAdminDlg::~OUserAdminDlg()
+ {
+ if ( m_bOwnConnection )
+ {
+ try
+ {
+ ::comphelper::disposeComponent(m_xConnection);
+ }
+ catch(const Exception&)
+ {
+ }
+ }
+
+ SetInputSet(nullptr);
+ }
+
+ short OUserAdminDlg::run()
+ {
+ try
+ {
+ ::dbtools::DatabaseMetaData aMetaData( createConnection().first );
+ if ( !aMetaData.supportsUserAdministration( getORB() ) )
+ {
+ OUString sError(DBA_RES(STR_USERADMIN_NOT_AVAILABLE));
+ throw SQLException(sError, nullptr, "S1000", 0, Any());
+ }
+ }
+ catch(const SQLException&)
+ {
+ ::dbtools::showError(::dbtools::SQLExceptionInfo(::cppu::getCaughtException()), m_pParent->GetXWindow(), getORB());
+ return RET_CANCEL;
+ }
+ catch(const Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ short nRet = SfxTabDialogController::run();
+ if ( nRet == RET_OK )
+ m_pImpl->saveChanges(*GetOutputItemSet());
+ return nRet;
+ }
+ void OUserAdminDlg::PageCreated(const OString& rId, SfxTabPage& _rPage)
+ {
+ // register ourself as modified listener
+ static_cast<OGenericAdministrationPage&>(_rPage).SetServiceFactory( m_pImpl->getORB() );
+ static_cast<OGenericAdministrationPage&>(_rPage).SetAdminDialog(this,this);
+ SfxTabDialogController::PageCreated(rId, _rPage);
+ }
+ const SfxItemSet* OUserAdminDlg::getOutputSet() const
+ {
+ return m_pItemSet;
+ }
+ SfxItemSet* OUserAdminDlg::getWriteOutputSet()
+ {
+ return m_pItemSet;
+ }
+ std::pair< Reference<XConnection>,bool> OUserAdminDlg::createConnection()
+ {
+ if ( !m_xConnection.is() )
+ {
+ m_xConnection = m_pImpl->createConnection().first;
+ m_bOwnConnection = m_xConnection.is();
+ }
+ return std::pair< Reference<XConnection>,bool> (m_xConnection,false);
+ }
+ Reference< XComponentContext > OUserAdminDlg::getORB() const
+ {
+ return m_pImpl->getORB();
+ }
+ Reference< XDriver > OUserAdminDlg::getDriver()
+ {
+ return m_pImpl->getDriver();
+ }
+ OUString OUserAdminDlg::getDatasourceType(const SfxItemSet& _rSet) const
+ {
+ return dbaui::ODbDataSourceAdministrationHelper::getDatasourceType(_rSet);
+ }
+ void OUserAdminDlg::clearPassword()
+ {
+ m_pImpl->clearPassword();
+ }
+ void OUserAdminDlg::setTitle(const OUString& _sTitle)
+ {
+ m_xDialog->set_title(_sTitle);
+ }
+ void OUserAdminDlg::enableConfirmSettings( bool ) {}
+ void OUserAdminDlg::saveDatasource()
+ {
+ PrepareLeaveCurrentPage();
+ }
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/dlg/admincontrols.cxx b/dbaccess/source/ui/dlg/admincontrols.cxx
new file mode 100644
index 000000000..de515f9e3
--- /dev/null
+++ b/dbaccess/source/ui/dlg/admincontrols.cxx
@@ -0,0 +1,201 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "admincontrols.hxx"
+#include <dsitems.hxx>
+
+#include <svl/eitem.hxx>
+#include <svl/stritem.hxx>
+#include <svl/intitem.hxx>
+#include <vcl/svapp.hxx>
+
+namespace dbaui
+{
+
+ // MySQLNativeSettings
+ MySQLNativeSettings::MySQLNativeSettings(weld::Widget* pParent, const Link<weld::Widget*,void>& rControlModificationLink)
+ : m_xBuilder(Application::CreateBuilder(pParent, "dbaccess/ui/mysqlnativesettings.ui"))
+ , m_xContainer(m_xBuilder->weld_widget("MysqlNativeSettings"))
+ , m_xDatabaseNameLabel(m_xBuilder->weld_label("dbnamelabel"))
+ , m_xDatabaseName(m_xBuilder->weld_entry("dbname"))
+ , m_xHostPortRadio(m_xBuilder->weld_radio_button("hostport"))
+ , m_xSocketRadio(m_xBuilder->weld_radio_button("socketlabel"))
+ , m_xNamedPipeRadio(m_xBuilder->weld_radio_button("namedpipelabel"))
+ , m_xHostNameLabel(m_xBuilder->weld_label("serverlabel"))
+ , m_xHostName(m_xBuilder->weld_entry("server"))
+ , m_xPortLabel(m_xBuilder->weld_label("portlabel"))
+ , m_xPort(m_xBuilder->weld_spin_button("port"))
+ , m_xDefaultPort(m_xBuilder->weld_label("defaultport"))
+ , m_xSocket(m_xBuilder->weld_entry("socket"))
+ , m_xNamedPipe(m_xBuilder->weld_entry("namedpipe"))
+ , m_aControlModificationLink(rControlModificationLink)
+ {
+ m_xDatabaseName->connect_changed( LINK(this, MySQLNativeSettings, EditModifyHdl) );
+ m_xHostName->connect_changed( LINK(this, MySQLNativeSettings, EditModifyHdl) );
+ m_xPort->connect_value_changed( LINK(this, MySQLNativeSettings, SpinModifyHdl) );
+ m_xSocket->connect_changed( LINK(this, MySQLNativeSettings, EditModifyHdl) );
+ m_xNamedPipe->connect_changed( LINK(this, MySQLNativeSettings, EditModifyHdl) );
+ m_xSocketRadio->connect_toggled( LINK(this, MySQLNativeSettings, RadioToggleHdl) );
+ m_xNamedPipeRadio->connect_toggled( LINK(this, MySQLNativeSettings, RadioToggleHdl) );
+ m_xHostPortRadio->connect_toggled( LINK(this, MySQLNativeSettings, RadioToggleHdl) );
+
+ // sockets are available on Unix systems only, named pipes only on Windows
+#ifdef UNX
+ m_xNamedPipeRadio->hide();
+ m_xNamedPipe->hide();
+#else
+ m_xSocketRadio->hide();
+ m_xSocket->hide();
+#endif
+ m_xContainer->show();
+ }
+
+ IMPL_LINK(MySQLNativeSettings, RadioToggleHdl, weld::Toggleable&, rRadioButton, void)
+ {
+ m_aControlModificationLink.Call(&rRadioButton);
+
+ const bool bHostPortRadio = m_xHostPortRadio->get_active();
+ m_xHostNameLabel->set_sensitive(bHostPortRadio);
+ m_xHostName->set_sensitive(bHostPortRadio);
+ m_xPortLabel->set_sensitive(bHostPortRadio);
+ m_xPort->set_sensitive(bHostPortRadio);
+ m_xDefaultPort->set_sensitive(bHostPortRadio);
+
+ m_xSocket->set_sensitive(m_xSocketRadio->get_active());
+ m_xNamedPipe->set_sensitive(m_xNamedPipeRadio->get_active());
+ }
+
+ IMPL_LINK(MySQLNativeSettings, EditModifyHdl, weld::Entry&, rEdit, void)
+ {
+ m_aControlModificationLink.Call(&rEdit);
+ }
+
+ IMPL_LINK(MySQLNativeSettings, SpinModifyHdl, weld::SpinButton&, rEdit, void)
+ {
+ m_aControlModificationLink.Call(&rEdit);
+ }
+
+ void MySQLNativeSettings::fillControls( std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList )
+ {
+ _rControlList.emplace_back(new OSaveValueWidgetWrapper<weld::Entry>(m_xDatabaseName.get()));
+ _rControlList.emplace_back(new OSaveValueWidgetWrapper<weld::Entry>(m_xHostName.get()));
+ _rControlList.emplace_back(new OSaveValueWidgetWrapper<weld::Entry>(m_xPort.get()));
+ _rControlList.emplace_back(new OSaveValueWidgetWrapper<weld::Entry>(m_xSocket.get()));
+ _rControlList.emplace_back(new OSaveValueWidgetWrapper<weld::Entry>(m_xNamedPipe.get()));
+ }
+
+ void MySQLNativeSettings::fillWindows( std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList )
+ {
+ _rControlList.emplace_back( new ODisableWidgetWrapper<weld::Label>( m_xDatabaseNameLabel.get() ) );
+ _rControlList.emplace_back( new ODisableWidgetWrapper<weld::Label>( m_xHostNameLabel.get() ) );
+ _rControlList.emplace_back( new ODisableWidgetWrapper<weld::Label>( m_xPortLabel.get() ) );
+ _rControlList.emplace_back( new ODisableWidgetWrapper<weld::Label>( m_xDefaultPort.get() ) );
+ _rControlList.emplace_back( new ODisableWidgetWrapper<weld::RadioButton>( m_xSocketRadio.get() ) );
+ _rControlList.emplace_back( new ODisableWidgetWrapper<weld::RadioButton>( m_xNamedPipeRadio.get() ) );
+ }
+
+ bool MySQLNativeSettings::FillItemSet( SfxItemSet* _rSet )
+ {
+ bool bChangedSomething = false;
+
+ OGenericAdministrationPage::fillString( *_rSet, m_xHostName.get(), DSID_CONN_HOSTNAME, bChangedSomething );
+ OGenericAdministrationPage::fillString( *_rSet, m_xDatabaseName.get(), DSID_DATABASENAME, bChangedSomething );
+ OGenericAdministrationPage::fillInt32 ( *_rSet, m_xPort.get(), DSID_MYSQL_PORTNUMBER, bChangedSomething );
+#ifdef UNX
+ OGenericAdministrationPage::fillString( *_rSet, m_xSocket.get(), DSID_CONN_SOCKET, bChangedSomething );
+#else
+ OGenericAdministrationPage::fillString( *_rSet, m_xNamedPipe.get(), DSID_NAMED_PIPE, bChangedSomething );
+#endif
+
+ return bChangedSomething;
+ }
+
+ void MySQLNativeSettings::implInitControls(const SfxItemSet& _rSet )
+ {
+ const SfxBoolItem* pInvalid = _rSet.GetItem<SfxBoolItem>(DSID_INVALID_SELECTION);
+ bool bValid = !pInvalid || !pInvalid->GetValue();
+ if ( !bValid )
+ return;
+
+ const SfxStringItem* pDatabaseName = _rSet.GetItem<SfxStringItem>(DSID_DATABASENAME);
+ const SfxStringItem* pHostName = _rSet.GetItem<SfxStringItem>(DSID_CONN_HOSTNAME);
+ const SfxInt32Item* pPortNumber = _rSet.GetItem<SfxInt32Item>(DSID_MYSQL_PORTNUMBER);
+ const SfxStringItem* pSocket = _rSet.GetItem<SfxStringItem>(DSID_CONN_SOCKET);
+ const SfxStringItem* pNamedPipe = _rSet.GetItem<SfxStringItem>(DSID_NAMED_PIPE);
+
+ m_xDatabaseName->set_text( pDatabaseName->GetValue() );
+ m_xDatabaseName->save_value();
+
+ m_xHostName->set_text( pHostName->GetValue() );
+ m_xHostName->save_value();
+
+ m_xPort->set_value( pPortNumber->GetValue() );
+ m_xPort->save_value();
+
+ m_xSocket->set_text( pSocket->GetValue() );
+ m_xSocket->save_value();
+
+ m_xNamedPipe->set_text( pNamedPipe->GetValue() );
+ m_xNamedPipe->save_value();
+
+ // if a socket (on Unix) or a pipe name (on Windows) is given, this is preferred over
+ // the port
+#ifdef UNX
+ weld::RadioButton& rSocketPipeRadio = *m_xSocketRadio;
+ const SfxStringItem* pSocketPipeItem = pSocket;
+#else
+ weld::RadioButton& rSocketPipeRadio = *m_xNamedPipeRadio;
+ const SfxStringItem* pSocketPipeItem = pNamedPipe;
+#endif
+ const OUString& rSocketPipe( pSocketPipeItem->GetValue() );
+ if (!rSocketPipe.isEmpty())
+ rSocketPipeRadio.set_active(true);
+ else
+ m_xHostPortRadio->set_active(true);
+ }
+
+ bool MySQLNativeSettings::canAdvance() const
+ {
+ if (m_xDatabaseName->get_text().isEmpty())
+ return false;
+
+ if ( m_xHostPortRadio->get_active()
+ && ( ( m_xHostName->get_text().isEmpty() )
+ || ( m_xPort->get_text().isEmpty() )
+ )
+ )
+ return false;
+
+#ifdef UNX
+ if ( ( m_xSocketRadio->get_active() )
+ && ( m_xSocket->get_text().isEmpty() )
+ )
+#else
+ if ( ( m_xNamedPipeRadio->get_active() )
+ && ( m_xNamedPipe->get_text().isEmpty() )
+ )
+#endif
+ return false;
+
+ return true;
+ }
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/dlg/admincontrols.hxx b/dbaccess/source/ui/dlg/admincontrols.hxx
new file mode 100644
index 000000000..7bd1e5edf
--- /dev/null
+++ b/dbaccess/source/ui/dlg/admincontrols.hxx
@@ -0,0 +1,65 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include "adminpages.hxx"
+
+#include <vcl/weld.hxx>
+
+namespace dbaui
+{
+
+ // MySQLNativeSettings
+ class MySQLNativeSettings
+ {
+ private:
+ std::unique_ptr<weld::Builder> m_xBuilder;
+ std::unique_ptr<weld::Widget> m_xContainer;
+ std::unique_ptr<weld::Label> m_xDatabaseNameLabel;
+ std::unique_ptr<weld::Entry> m_xDatabaseName;
+ std::unique_ptr<weld::RadioButton> m_xHostPortRadio;
+ std::unique_ptr<weld::RadioButton> m_xSocketRadio;
+ std::unique_ptr<weld::RadioButton> m_xNamedPipeRadio;
+ std::unique_ptr<weld::Label> m_xHostNameLabel;
+ std::unique_ptr<weld::Entry> m_xHostName;
+ std::unique_ptr<weld::Label> m_xPortLabel;
+ std::unique_ptr<weld::SpinButton> m_xPort;
+ std::unique_ptr<weld::Label> m_xDefaultPort;
+ std::unique_ptr<weld::Entry> m_xSocket;
+ std::unique_ptr<weld::Entry> m_xNamedPipe;
+ Link<weld::Widget*,void> m_aControlModificationLink;
+ DECL_LINK(RadioToggleHdl, weld::Toggleable&, void);
+ DECL_LINK(SpinModifyHdl, weld::SpinButton&, void);
+ DECL_LINK(EditModifyHdl, weld::Entry&, void);
+
+ public:
+ MySQLNativeSettings(weld::Widget* pParent, const Link<weld::Widget*,void>& rControlModificationLink);
+ void fillControls( std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList );
+ void fillWindows( std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList );
+
+ bool FillItemSet( SfxItemSet* rCoreAttrs );
+ void implInitControls( const SfxItemSet& _rSet );
+
+ bool canAdvance() const;
+ };
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/dlg/adminpages.cxx b/dbaccess/source/ui/dlg/adminpages.cxx
new file mode 100644
index 000000000..5f0eedbb0
--- /dev/null
+++ b/dbaccess/source/ui/dlg/adminpages.cxx
@@ -0,0 +1,278 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "adminpages.hxx"
+#include <core_resource.hxx>
+#include <dbu_dlg.hxx>
+#include <IItemSetHelper.hxx>
+#include <strings.hrc>
+#include <svl/stritem.hxx>
+#include <svl/eitem.hxx>
+#include <svl/intitem.hxx>
+#include <dsitems.hxx>
+#include "dsselect.hxx"
+#include "odbcconfig.hxx"
+#include "optionalboolitem.hxx"
+#include <sqlmessage.hxx>
+#include <com/sun/star/sdbc/XConnection.hpp>
+#include <comphelper/types.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/weld.hxx>
+
+namespace dbaui
+{
+
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::sdbc;
+ using namespace ::com::sun::star::beans;
+ using namespace ::com::sun::star::lang;
+ using namespace ::dbtools;
+
+ ISaveValueWrapper::~ISaveValueWrapper()
+ {
+ }
+
+ OGenericAdministrationPage::OGenericAdministrationPage(weld::Container* pPage, weld::DialogController* pController, const OUString& rUIXMLDescription, const OString& rId, const SfxItemSet& rAttrSet)
+ : SfxTabPage(pPage, pController, rUIXMLDescription, rId, &rAttrSet)
+ , m_abEnableRoadmap(false)
+ , m_pAdminDialog(nullptr)
+ , m_pItemSetHelper(nullptr)
+ {
+ SetExchangeSupport();
+
+ m_xContainer->set_size_request(m_xContainer->get_approximate_digit_width() * WIZARD_PAGE_X,
+ m_xContainer->get_text_height() * WIZARD_PAGE_Y);
+ }
+
+ DeactivateRC OGenericAdministrationPage::DeactivatePage(SfxItemSet* _pSet)
+ {
+ if (_pSet)
+ {
+ if (!prepareLeave())
+ return DeactivateRC::KeepPage;
+ FillItemSet(_pSet);
+ }
+
+ return DeactivateRC::LeavePage;
+ }
+
+ void OGenericAdministrationPage::Reset(const SfxItemSet* _rCoreAttrs)
+ {
+ implInitControls(*_rCoreAttrs, false);
+ }
+
+ void OGenericAdministrationPage::Activate()
+ {
+ BuilderPage::Activate();
+ OSL_ENSURE(m_pItemSetHelper,"NO ItemSetHelper set!");
+ if ( m_pItemSetHelper )
+ ActivatePage(*m_pItemSetHelper->getOutputSet());
+ }
+
+ void OGenericAdministrationPage::ActivatePage(const SfxItemSet& _rSet)
+ {
+ implInitControls(_rSet, true);
+ }
+
+ void OGenericAdministrationPage::getFlags(const SfxItemSet& _rSet, bool& _rValid, bool& _rReadonly)
+ {
+ const SfxBoolItem* pInvalid = _rSet.GetItem<SfxBoolItem>(DSID_INVALID_SELECTION);
+ _rValid = !pInvalid || !pInvalid->GetValue();
+ const SfxBoolItem* pReadonly = _rSet.GetItem<SfxBoolItem>(DSID_READONLY);
+ _rReadonly = !_rValid || (pReadonly && pReadonly->GetValue());
+ }
+
+ IMPL_LINK(OGenericAdministrationPage, OnControlModified, weld::Widget*, pCtrl, void)
+ {
+ callModifiedHdl(pCtrl);
+ }
+
+ IMPL_LINK(OGenericAdministrationPage, OnControlModifiedButtonClick, weld::Toggleable&, rCtrl, void)
+ {
+ callModifiedHdl(&rCtrl);
+ }
+
+ IMPL_LINK(OGenericAdministrationPage, OnControlEntryModifyHdl, weld::Entry&, rCtrl, void)
+ {
+ callModifiedHdl(&rCtrl);
+ }
+
+ IMPL_LINK(OGenericAdministrationPage, OnControlSpinButtonModifyHdl, weld::SpinButton&, rCtrl, void)
+ {
+ callModifiedHdl(&rCtrl);
+ }
+
+ bool OGenericAdministrationPage::getSelectedDataSource(OUString& _sReturn, OUString const & _sCurr)
+ {
+ // collect all ODBC data source names
+ std::set<OUString> aOdbcDatasources;
+ OOdbcEnumeration aEnumeration;
+ if (!aEnumeration.isLoaded())
+ {
+ // show an error message
+ OUString sError(DBA_RES(STR_COULD_NOT_LOAD_ODBC_LIB));
+ sError = sError.replaceFirst("#lib#", aEnumeration.getLibraryName());
+ std::unique_ptr<weld::MessageDialog> xDialog(Application::CreateMessageDialog(GetFrameWeld(),
+ VclMessageType::Warning, VclButtonsType::Ok,
+ sError));
+ xDialog->run();
+ return false;
+ }
+ else
+ {
+ aEnumeration.getDatasourceNames(aOdbcDatasources);
+ // execute the select dialog
+ ODatasourceSelectDialog aSelector(GetFrameWeld(), aOdbcDatasources);
+ if (!_sCurr.isEmpty())
+ aSelector.Select(_sCurr);
+ if (RET_OK == aSelector.run())
+ _sReturn = aSelector.GetSelected();
+ }
+ return true;
+ }
+
+ void OGenericAdministrationPage::implInitControls(const SfxItemSet& _rSet, bool _bSaveValue)
+ {
+ // check whether or not the selection is invalid or readonly (invalid implies readonly, but not vice versa)
+ bool bValid, bReadonly;
+ getFlags(_rSet, bValid, bReadonly);
+
+ std::vector< std::unique_ptr<ISaveValueWrapper> > aControlList;
+ if ( _bSaveValue )
+ {
+ fillControls(aControlList);
+ for( const auto& pValueWrapper : aControlList )
+ {
+ pValueWrapper->SaveValue();
+ }
+ }
+
+ if ( bReadonly )
+ {
+ fillWindows(aControlList);
+ for( const auto& pValueWrapper : aControlList )
+ {
+ pValueWrapper->Disable();
+ }
+ }
+ }
+
+ void OGenericAdministrationPage::initializePage()
+ {
+ OSL_ENSURE(m_pItemSetHelper,"NO ItemSetHelper set!");
+ if ( m_pItemSetHelper )
+ Reset(m_pItemSetHelper->getOutputSet());
+ }
+ bool OGenericAdministrationPage::commitPage( ::vcl::WizardTypes::CommitPageReason )
+ {
+ return true;
+ }
+ bool OGenericAdministrationPage::canAdvance() const
+ {
+ return true;
+ }
+ void OGenericAdministrationPage::fillBool( SfxItemSet& _rSet, const weld::CheckButton* pCheckBox, sal_uInt16 _nID, bool bOptionalBool, bool& _bChangedSomething, bool _bRevertValue )
+ {
+ if (!(pCheckBox && pCheckBox->get_state_changed_from_saved()))
+ return;
+
+ bool bValue = pCheckBox->get_active();
+ if ( _bRevertValue )
+ bValue = !bValue;
+
+ if (bOptionalBool)
+ {
+ OptionalBoolItem aValue( _nID );
+ if ( pCheckBox->get_state() != TRISTATE_INDET )
+ aValue.SetValue( bValue );
+ _rSet.Put( aValue );
+ }
+ else
+ _rSet.Put( SfxBoolItem( _nID, bValue ) );
+
+ _bChangedSomething = true;
+ }
+ void OGenericAdministrationPage::fillInt32(SfxItemSet& _rSet, const weld::SpinButton* pEdit, sal_uInt16 _nID, bool& _bChangedSomething)
+ {
+ if (pEdit && pEdit->get_value_changed_from_saved())
+ {
+ _rSet.Put(SfxInt32Item(_nID, pEdit->get_value()));
+ _bChangedSomething = true;
+ }
+ }
+ void OGenericAdministrationPage::fillString(SfxItemSet& _rSet, const weld::Entry* pEdit, sal_uInt16 _nID, bool& _bChangedSomething)
+ {
+ if (pEdit && pEdit->get_value_changed_from_saved())
+ {
+ _rSet.Put(SfxStringItem(_nID, pEdit->get_text().trim()));
+ _bChangedSomething = true;
+ }
+ }
+ void OGenericAdministrationPage::fillString(SfxItemSet& _rSet, const dbaui::OConnectionURLEdit* pEdit, sal_uInt16 _nID, bool& _bChangedSomething)
+ {
+ if (pEdit && pEdit->get_value_changed_from_saved())
+ {
+ _rSet.Put(SfxStringItem(_nID, pEdit->GetText().trim()));
+ _bChangedSomething = true;
+ }
+ }
+
+ IMPL_LINK_NOARG(OGenericAdministrationPage, OnTestConnectionButtonClickHdl, weld::Button&, void)
+ {
+ OSL_ENSURE(m_pAdminDialog,"No Admin dialog set! ->GPF");
+ bool bSuccess = false;
+ if ( !m_pAdminDialog )
+ return;
+
+ m_pAdminDialog->saveDatasource();
+ OGenericAdministrationPage::implInitControls(*m_pItemSetHelper->getOutputSet(), true);
+ bool bShowMessage = true;
+ try
+ {
+ std::pair< Reference<XConnection>,bool> aConnectionPair = m_pAdminDialog->createConnection();
+ bShowMessage = aConnectionPair.second;
+ bSuccess = aConnectionPair.first.is();
+ ::comphelper::disposeComponent(aConnectionPair.first);
+ }
+ catch(Exception&)
+ {
+ }
+ if ( bShowMessage )
+ {
+ MessageType eImage = MessageType::Info;
+ OUString aMessage,sTitle;
+ sTitle = DBA_RES(STR_CONNECTION_TEST);
+ if ( bSuccess )
+ {
+ aMessage = DBA_RES(STR_CONNECTION_SUCCESS);
+ }
+ else
+ {
+ eImage = MessageType::Error;
+ aMessage = DBA_RES(STR_CONNECTION_NO_SUCCESS);
+ }
+ OSQLMessageBox aMsg(GetFrameWeld(), sTitle, aMessage, MessBoxStyle::Ok, eImage);
+ aMsg.run();
+ }
+ if ( !bSuccess )
+ m_pAdminDialog->clearPassword();
+ }
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/dlg/adminpages.hxx b/dbaccess/source/ui/dlg/adminpages.hxx
new file mode 100644
index 000000000..de8265751
--- /dev/null
+++ b/dbaccess/source/ui/dlg/adminpages.hxx
@@ -0,0 +1,233 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <sfx2/tabdlg.hxx>
+#include <vcl/wizardmachine.hxx>
+#include <curledit.hxx>
+
+namespace dbaui
+{
+ /// helper class to wrap the savevalue and disable call
+ class SAL_NO_VTABLE ISaveValueWrapper
+ {
+ public:
+ virtual ~ISaveValueWrapper() = 0;
+ virtual void SaveValue() = 0;
+ virtual void Disable() = 0;
+ };
+
+ template < class T > class OSaveValueWidgetWrapper : public ISaveValueWrapper
+ {
+ T* m_pSaveValue;
+ public:
+ explicit OSaveValueWidgetWrapper(T* _pSaveValue) : m_pSaveValue(_pSaveValue)
+ { OSL_ENSURE(m_pSaveValue,"Illegal argument!"); }
+
+ virtual void SaveValue() override { m_pSaveValue->save_value(); }
+ virtual void Disable() override { m_pSaveValue->set_sensitive(false); }
+ };
+
+ template <> class OSaveValueWidgetWrapper<weld::Toggleable> : public ISaveValueWrapper
+ {
+ weld::Toggleable* m_pSaveValue;
+ public:
+ explicit OSaveValueWidgetWrapper(weld::Toggleable* _pSaveValue) : m_pSaveValue(_pSaveValue)
+ { OSL_ENSURE(m_pSaveValue,"Illegal argument!"); }
+
+ virtual void SaveValue() override { m_pSaveValue->save_state(); }
+ virtual void Disable() override { m_pSaveValue->set_sensitive(false); }
+ };
+
+ template <> class OSaveValueWidgetWrapper<dbaui::OConnectionURLEdit> : public ISaveValueWrapper
+ {
+ dbaui::OConnectionURLEdit* m_pSaveValue;
+ public:
+ explicit OSaveValueWidgetWrapper(dbaui::OConnectionURLEdit* _pSaveValue) : m_pSaveValue(_pSaveValue)
+ { OSL_ENSURE(m_pSaveValue,"Illegal argument!"); }
+
+ virtual void SaveValue() override { m_pSaveValue->save_value(); }
+ virtual void Disable() override { m_pSaveValue->set_sensitive(false); }
+ };
+
+ template <class T> class ODisableWidgetWrapper : public ISaveValueWrapper
+ {
+ T* m_pSaveValue;
+ public:
+ explicit ODisableWidgetWrapper(T* _pSaveValue) : m_pSaveValue(_pSaveValue)
+ { OSL_ENSURE(m_pSaveValue,"Illegal argument!"); }
+
+ virtual void SaveValue() override {}
+ virtual void Disable() override { m_pSaveValue->set_sensitive(false); }
+ };
+
+ // OGenericAdministrationPage
+ class IDatabaseSettingsDialog;
+ class IItemSetHelper;
+ class OGenericAdministrationPage :public SfxTabPage
+ ,public ::vcl::IWizardPageController
+ {
+ private:
+ Link<OGenericAdministrationPage const *, void> m_aModifiedHandler; /// to be called if something on the page has been modified
+ bool m_abEnableRoadmap;
+ protected:
+ IDatabaseSettingsDialog* m_pAdminDialog;
+ IItemSetHelper* m_pItemSetHelper;
+
+ css::uno::Reference< css::uno::XComponentContext >
+ m_xORB;
+ public:
+ OGenericAdministrationPage(weld::Container* pPage, weld::DialogController* pController, const OUString& rUIXMLDescription, const OString& rId, const SfxItemSet& rAttrSet);
+ /// set a handler which gets called every time something on the page has been modified
+ void SetModifiedHandler(const Link<OGenericAdministrationPage const *, void>& _rHandler) { m_aModifiedHandler = _rHandler; }
+
+ /** Sets the ParentDialog
+ @param _pAdminDialog
+ the ParentDialog
+ @param _pItemSetHelper
+ the itemset helper
+ */
+ void SetAdminDialog(IDatabaseSettingsDialog* _pDialog,IItemSetHelper* _pItemSetHelper)
+ {
+ OSL_ENSURE(_pDialog && _pItemSetHelper,"Values are NULL!");
+ m_pAdminDialog = _pDialog;
+ m_pItemSetHelper = _pItemSetHelper;
+ }
+
+ /** Sets the ServiceFactory
+ @param _rxORB
+ The service factory.
+ */
+ void SetServiceFactory(const css::uno::Reference< css::uno::XComponentContext >& rxORB)
+ {
+ m_xORB = rxORB;
+ }
+
+ /** opens a dialog filled with all data sources available for this type and
+ returns the selected on.
+ @param _eType
+ The type for which the data source dialog should be opened.
+ @param _sReturn
+ <OUT/> contains the selected name.
+ @return
+ <FALSE/> if an error occurred, otherwise <TRUE/>
+ */
+ bool getSelectedDataSource(OUString& _sReturn, OUString const & _sCurr);
+
+ // svt::IWizardPageController
+ virtual void initializePage() override;
+ virtual bool commitPage( ::vcl::WizardTypes::CommitPageReason _eReason ) override;
+ virtual bool canAdvance() const override;
+
+ void SetRoadmapStateValue( bool _bDoEnable ) { m_abEnableRoadmap = _bDoEnable; }
+ bool GetRoadmapStateValue() const { return m_abEnableRoadmap; }
+
+ protected:
+ /// default implementation: call FillItemSet, call prepareLeave,
+ virtual DeactivateRC DeactivatePage(SfxItemSet* pSet) override;
+ /// default implementation: call implInitControls with the given item set and _bSaveValue = sal_False
+ virtual void Reset(const SfxItemSet* _rCoreAttrs) override;
+ /// default implementation: call implInitControls with the given item set and _bSaveValue = sal_True
+ virtual void ActivatePage(const SfxItemSet& _rSet) override;
+
+ // BuilderPage overridables
+ virtual void Activate() override;
+
+ protected:
+ virtual void callModifiedHdl(weld::Widget* /*pControl*/ = nullptr) { m_aModifiedHandler.Call(this); }
+
+ /// called from within DeactivatePage. The page is allowed to be deactivated if this method returns sal_True
+ virtual bool prepareLeave() { return true; }
+
+ /** called from within Reset and ActivatePage, use to initialize the controls with the items from the given set
+ @param _bSaveValue if set to sal_True, the implementation should call SaveValue on all relevant controls
+ */
+ virtual void implInitControls(const SfxItemSet& _rSet, bool _bSaveValue);
+
+ /// analyze the invalid and the readonly flag which may be present in the set
+ static void getFlags(const SfxItemSet& _rSet, bool& _rValid, bool& _rReadonly);
+
+ /** will be called inside <method>implInitControls</method> to save the value if necessary
+ @param _rControlList
+ The list must be filled with the controls.
+ It is not allowed to clear the list before pushing data into it.
+ */
+ virtual void fillControls(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) = 0;
+
+ /** will be called inside <method>implInitControls</method> to disable if necessary
+ @param _rControlList
+ The list must be filled with the controls.
+ It is not allowed to clear the list before pushing data into it.
+ */
+ virtual void fillWindows(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) = 0;
+
+ public:
+ /** fills the Boolean value into the item set when the value changed.
+ @param _rSet
+ The item set where to put the new value into.
+ @param _pCheckBox
+ The check box which is checked.
+ @param _nID
+ The id in the itemset to set with the new value.
+ @param _bChangedSomething
+ <TRUE/> if something changed otherwise <FALSE/>
+ @param _bRevertValue
+ set to <TRUE/> if the display value should be reverted before putting it into the set
+ */
+ static void fillBool(SfxItemSet& _rSet, const weld::CheckButton* pCheckBox, sal_uInt16 _nID, bool bOptionalBool, bool& _bChangedSomething, bool _bRevertValue = false);
+
+ /** fills the int value into the item set when the value changed.
+ @param _rSet
+ The item set where to put the new value into.
+ @param _pEdit
+ The check box which is checked.
+ @param _nID
+ The id in the itemset to set with the new value.
+ @param _bChangedSomething
+ <TRUE/> if something changed otherwise <FALSE/>
+ */
+ static void fillInt32(SfxItemSet& _rSet,const weld::SpinButton* pEdit,sal_uInt16 _nID, bool& _bChangedSomething);
+
+ /** fills the String value into the item set when the value changed.
+ @param _rSet
+ The item set where to put the new value into.
+ @param _pEdit
+ The check box which is checked.
+ @param _nID
+ The id in the itemset to set with the new value.
+ @param _bChangedSomething
+ <TRUE/> if something changed otherwise <FALSE/>
+ */
+ static void fillString(SfxItemSet& _rSet,const weld::Entry* pEdit,sal_uInt16 _nID, bool& _bChangedSomething);
+ static void fillString(SfxItemSet& _rSet,const dbaui::OConnectionURLEdit* pEdit,sal_uInt16 _nID, bool& _bChangedSomething);
+
+ protected:
+ /** This link be used for controls where the tabpage does not need to take any special action when the control
+ is modified. The implementation just calls callModifiedHdl.
+ */
+ DECL_LINK(OnControlModified, weld::Widget*, void);
+ DECL_LINK(OnControlEntryModifyHdl, weld::Entry&, void);
+ DECL_LINK(OnControlSpinButtonModifyHdl, weld::SpinButton&, void);
+ DECL_LINK(OnControlModifiedButtonClick, weld::Toggleable&, void);
+ DECL_LINK(OnTestConnectionButtonClickHdl, weld::Button&, void);
+ };
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/dlg/adodatalinks.cxx b/dbaccess/source/ui/dlg/adodatalinks.cxx
new file mode 100644
index 000000000..82af63688
--- /dev/null
+++ b/dbaccess/source/ui/dlg/adodatalinks.cxx
@@ -0,0 +1,141 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#if defined(_WIN32)
+// LO/windows.h conflict
+#undef WB_LEFT
+#undef WB_RIGHT
+#include <msdasc.h>
+
+#include <comphelper/scopeguard.hxx>
+#include <o3tl/char16_t2wchar_t.hxx>
+#include <systools/win32/comtools.hxx>
+#include <systools/win32/oleauto.hxx>
+
+#include <initguid.h>
+#include <adoid.h>
+#include <adoint.h>
+
+#include "adodatalinks.hxx"
+
+namespace {
+
+OUString PromptNew(sal_IntPtr hWnd)
+{
+ try
+ {
+ // Initialize COM
+ sal::systools::CoInitializeGuard aGuard(COINIT_APARTMENTTHREADED);
+
+ // Instantiate DataLinks object.
+ sal::systools::COMReference<IDataSourceLocator> dlPrompt;
+ dlPrompt.CoCreateInstance(CLSID_DataLinks, //clsid -- Data Links UI
+ nullptr, //pUnkOuter
+ CLSCTX_INPROC_SERVER); //dwClsContext
+
+ sal::systools::ThrowIfFailed(dlPrompt->put_hWnd(hWnd), "put_hWnd failed");
+
+ // Prompt for connection information.
+ sal::systools::COMReference<IDispatch> piDispatch;
+ sal::systools::ThrowIfFailed(dlPrompt->PromptNew(&piDispatch), "PromptNew failed");
+ sal::systools::COMReference<ADOConnection> piTmpConnection(piDispatch,
+ sal::systools::COM_QUERY_THROW);
+
+ sal::systools::BStr _result;
+ sal::systools::ThrowIfFailed(piTmpConnection->get_ConnectionString(&_result),
+ "get_ConnectionString failed");
+
+ return OUString(_result);
+ }
+ catch (const sal::systools::ComError&)
+ {
+ return OUString();
+ }
+}
+
+OUString PromptEdit(sal_IntPtr hWnd, OUString const & connstr)
+{
+ try
+ {
+ // Initialize COM
+ sal::systools::CoInitializeGuard aGuard(COINIT_APARTMENTTHREADED);
+
+ sal::systools::COMReference<ADOConnection> piTmpConnection;
+ piTmpConnection.CoCreateInstance(CLSID_CADOConnection, nullptr, CLSCTX_INPROC_SERVER);
+
+ sal::systools::ThrowIfFailed(
+ piTmpConnection->put_ConnectionString(sal::systools::BStr(connstr)),
+ "put_ConnectionString failed");
+
+ // Instantiate DataLinks object.
+ sal::systools::COMReference<IDataSourceLocator> dlPrompt;
+ dlPrompt.CoCreateInstance(CLSID_DataLinks, //clsid -- Data Links UI
+ nullptr, //pUnkOuter
+ CLSCTX_INPROC_SERVER); //dwClsContext
+
+ sal::systools::ThrowIfFailed(dlPrompt->put_hWnd(hWnd), "put_hWnd failed");
+
+ try
+ {
+ // Prompt for connection information.
+ IDispatch* piDispatch = piTmpConnection.get();
+ VARIANT_BOOL pbSuccess;
+ sal::systools::ThrowIfFailed(dlPrompt->PromptEdit(&piDispatch, &pbSuccess),
+ "PromptEdit failed");
+ if (!pbSuccess) //if user press cancel then sal_False == pbSuccess
+ return connstr;
+ }
+ catch (const sal::systools::ComError&)
+ {
+ // Prompt for new connection information.
+ sal::systools::COMReference<IDispatch> piDispatch;
+ sal::systools::ThrowIfFailed(dlPrompt->PromptNew(&piDispatch), "PromptNew failed");
+ piTmpConnection.set(piDispatch, sal::systools::COM_QUERY_THROW);
+ }
+
+ sal::systools::BStr _result;
+ sal::systools::ThrowIfFailed(piTmpConnection->get_ConnectionString(&_result),
+ "get_ConnectionString failed");
+
+ return OUString(_result);
+ }
+ catch (const sal::systools::ComError&)
+ {
+ return connstr;
+ }
+}
+
+}
+
+OUString getAdoDatalink(sal_IntPtr hWnd,OUString const & oldLink)
+{
+ OUString dataLink;
+ if (!oldLink.isEmpty())
+ {
+ dataLink=PromptEdit(hWnd,oldLink);
+ }
+ else
+ dataLink=PromptNew(hWnd);
+ return dataLink;
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/dlg/adodatalinks.hxx b/dbaccess/source/ui/dlg/adodatalinks.hxx
new file mode 100644
index 000000000..6b753f62e
--- /dev/null
+++ b/dbaccess/source/ui/dlg/adodatalinks.hxx
@@ -0,0 +1,26 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <rtl/ustring.hxx>
+#include <sal/types.h>
+
+OUString getAdoDatalink(sal_IntPtr hWnd, OUString const& oldLink);
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/dlg/adtabdlg.cxx b/dbaccess/source/ui/dlg/adtabdlg.cxx
new file mode 100644
index 000000000..809b483cd
--- /dev/null
+++ b/dbaccess/source/ui/dlg/adtabdlg.cxx
@@ -0,0 +1,467 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <adtabdlg.hxx>
+#include <tools/diagnose_ex.h>
+#include <core_resource.hxx>
+#include <strings.hrc>
+#include <connectivity/dbtools.hxx>
+#include <com/sun/star/container/XContainer.hpp>
+#include <com/sun/star/sdb/application/DatabaseObject.hpp>
+#include <com/sun/star/sdb/XQueriesSupplier.hpp>
+#include <com/sun/star/sdbcx/XViewsSupplier.hpp>
+#include <com/sun/star/sdbcx/XTablesSupplier.hpp>
+#include <com/sun/star/container/XNameAccess.hpp>
+#include <imageprovider.hxx>
+#include <comphelper/containermultiplexer.hxx>
+#include <cppuhelper/basemutex.hxx>
+#include <algorithm>
+
+// slot ids
+using namespace dbaui;
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::sdb;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::sdbcx;
+using namespace dbtools;
+
+TableObjectListFacade::~TableObjectListFacade()
+{
+}
+
+namespace {
+
+class TableListFacade : public ::cppu::BaseMutex
+ , public TableObjectListFacade
+ , public ::comphelper::OContainerListener
+{
+ OTableTreeListBox& m_rTableList;
+ Reference< XConnection > m_xConnection;
+ ::rtl::Reference< comphelper::OContainerListenerAdapter>
+ m_pContainerListener;
+ bool m_bAllowViews;
+
+public:
+ TableListFacade(OTableTreeListBox& _rTableList, const Reference< XConnection >& _rxConnection)
+ : ::comphelper::OContainerListener(m_aMutex)
+ ,m_rTableList( _rTableList )
+ ,m_xConnection( _rxConnection )
+ ,m_bAllowViews(true)
+ {
+ }
+ virtual ~TableListFacade() override;
+
+private:
+ virtual void updateTableObjectList( bool _bAllowViews ) override;
+ virtual OUString getSelectedName( OUString& _out_rAliasName ) const override;
+ virtual bool isLeafSelected() const override;
+ // OContainerListener
+ virtual void _elementInserted( const css::container::ContainerEvent& _rEvent ) override;
+ virtual void _elementRemoved( const css::container::ContainerEvent& _rEvent ) override;
+ virtual void _elementReplaced( const css::container::ContainerEvent& _rEvent ) override;
+};
+
+}
+
+TableListFacade::~TableListFacade()
+{
+ if ( m_pContainerListener.is() )
+ m_pContainerListener->dispose();
+}
+
+OUString TableListFacade::getSelectedName( OUString& _out_rAliasName ) const
+{
+ weld::TreeView& rTableList = m_rTableList.GetWidget();
+ std::unique_ptr<weld::TreeIter> xEntry(rTableList.make_iterator());
+
+ if (!rTableList.get_selected(xEntry.get()))
+ return OUString();
+
+ OUString aCatalog, aSchema, aTableName;
+ std::unique_ptr<weld::TreeIter> xSchema(rTableList.make_iterator(xEntry.get()));
+ if (rTableList.iter_parent(*xSchema))
+ {
+ auto xAll = m_rTableList.getAllObjectsEntry();
+ if (!xAll || !xSchema->equal(*xAll))
+ {
+ std::unique_ptr<weld::TreeIter> xCatalog(rTableList.make_iterator(xSchema.get()));
+ if (rTableList.iter_parent(*xCatalog))
+ {
+ if (!xAll || !xCatalog->equal(*xAll))
+ aCatalog = rTableList.get_text(*xCatalog, 0);
+ }
+ aSchema = rTableList.get_text(*xSchema, 0);
+ }
+ }
+ aTableName = rTableList.get_text(*xEntry, 0);
+
+ OUString aComposedName;
+ try
+ {
+ Reference< XDatabaseMetaData > xMeta( m_xConnection->getMetaData(), UNO_SET_THROW );
+ if ( aCatalog.isEmpty()
+ && !aSchema.isEmpty()
+ && xMeta->supportsCatalogsInDataManipulation()
+ && !xMeta->supportsSchemasInDataManipulation() )
+ {
+ aCatalog = aSchema;
+ aSchema.clear();
+ }
+
+ aComposedName = ::dbtools::composeTableName(
+ xMeta, aCatalog, aSchema, aTableName, false, ::dbtools::EComposeRule::InDataManipulation );
+ }
+ catch ( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+
+ _out_rAliasName = aTableName;
+ return aComposedName;
+}
+
+void TableListFacade::_elementInserted( const container::ContainerEvent& /*_rEvent*/ )
+{
+ updateTableObjectList(m_bAllowViews);
+}
+
+void TableListFacade::_elementRemoved( const container::ContainerEvent& /*_rEvent*/ )
+{
+ updateTableObjectList(m_bAllowViews);
+}
+
+void TableListFacade::_elementReplaced( const container::ContainerEvent& /*_rEvent*/ )
+{
+}
+
+void TableListFacade::updateTableObjectList( bool _bAllowViews )
+{
+ m_bAllowViews = _bAllowViews;
+ weld::TreeView& rTableList = m_rTableList.GetWidget();
+ rTableList.clear();
+ try
+ {
+ Reference< XTablesSupplier > xTableSupp( m_xConnection, UNO_QUERY_THROW );
+
+ Reference< XViewsSupplier > xViewSupp;
+ Reference< XNameAccess > xTables, xViews;
+ Sequence< OUString > sTables, sViews;
+
+ xTables = xTableSupp->getTables();
+ if ( xTables.is() )
+ {
+ if ( !m_pContainerListener.is() )
+ {
+ Reference< XContainer> xContainer(xTables,uno::UNO_QUERY);
+ if ( xContainer.is() )
+ m_pContainerListener = new ::comphelper::OContainerListenerAdapter(this,xContainer);
+ }
+ sTables = xTables->getElementNames();
+ }
+
+ xViewSupp.set( xTableSupp, UNO_QUERY );
+ if ( xViewSupp.is() )
+ {
+ xViews = xViewSupp->getViews();
+ if ( xViews.is() )
+ sViews = xViews->getElementNames();
+ }
+
+ // if no views are allowed remove the views also out the table name filter
+ if ( !_bAllowViews )
+ {
+ const OUString* pTableBegin = sTables.getConstArray();
+ const OUString* pTableEnd = pTableBegin + sTables.getLength();
+ std::vector< OUString > aTables(pTableBegin,pTableEnd);
+
+ const OUString* pViewBegin = sViews.getConstArray();
+ const OUString* pViewEnd = pViewBegin + sViews.getLength();
+ ::comphelper::UStringMixEqual aEqualFunctor;
+ for(;pViewBegin != pViewEnd;++pViewBegin)
+ aTables.erase(std::remove_if(aTables.begin(),aTables.end(),
+ [&aEqualFunctor, pViewBegin](const OUString& lhs)
+ { return aEqualFunctor(lhs, *pViewBegin); } )
+ , aTables.end());
+ sTables = Sequence< OUString>(aTables.data(), aTables.size());
+ sViews = Sequence< OUString>();
+ }
+
+ m_rTableList.UpdateTableList( m_xConnection, sTables, sViews );
+
+ std::unique_ptr<weld::TreeIter> xEntry(rTableList.make_iterator());
+ bool bEntry = rTableList.get_iter_first(*xEntry);
+ while (bEntry && rTableList.iter_has_child(*xEntry))
+ {
+ rTableList.expand_row(*xEntry);
+ bEntry = rTableList.iter_next(*xEntry);
+ }
+ if (bEntry)
+ rTableList.select(*xEntry);
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+}
+
+bool TableListFacade::isLeafSelected() const
+{
+ weld::TreeView& rTableList = m_rTableList.GetWidget();
+ std::unique_ptr<weld::TreeIter> xEntry(rTableList.make_iterator());
+ const bool bEntry = rTableList.get_selected(xEntry.get());
+ return bEntry && !rTableList.iter_has_child(*xEntry);
+}
+
+namespace {
+
+class QueryListFacade : public ::cppu::BaseMutex
+ , public TableObjectListFacade
+ , public ::comphelper::OContainerListener
+{
+ weld::TreeView& m_rQueryList;
+ Reference< XConnection > m_xConnection;
+ ::rtl::Reference< comphelper::OContainerListenerAdapter>
+ m_pContainerListener;
+
+public:
+ QueryListFacade( weld::TreeView& _rQueryList, const Reference< XConnection >& _rxConnection )
+ : ::comphelper::OContainerListener(m_aMutex)
+ ,m_rQueryList( _rQueryList )
+ ,m_xConnection( _rxConnection )
+ {
+ }
+ virtual ~QueryListFacade() override;
+
+private:
+ virtual void updateTableObjectList( bool _bAllowViews ) override;
+ virtual OUString getSelectedName( OUString& _out_rAliasName ) const override;
+ virtual bool isLeafSelected() const override;
+ // OContainerListener
+ virtual void _elementInserted( const css::container::ContainerEvent& _rEvent ) override;
+ virtual void _elementRemoved( const css::container::ContainerEvent& _rEvent ) override;
+ virtual void _elementReplaced( const css::container::ContainerEvent& _rEvent ) override;
+};
+
+}
+
+QueryListFacade::~QueryListFacade()
+{
+ if ( m_pContainerListener.is() )
+ m_pContainerListener->dispose();
+}
+
+void QueryListFacade::_elementInserted( const container::ContainerEvent& _rEvent )
+{
+ OUString sName;
+ if ( _rEvent.Accessor >>= sName )
+ {
+ OUString aQueryImage(ImageProvider::getDefaultImageResourceID(css::sdb::application::DatabaseObject::QUERY));
+ m_rQueryList.append("", sName, aQueryImage);
+ }
+}
+
+void QueryListFacade::_elementRemoved( const container::ContainerEvent& /*_rEvent*/ )
+{
+ updateTableObjectList(true);
+}
+
+void QueryListFacade::_elementReplaced( const container::ContainerEvent& /*_rEvent*/ )
+{
+}
+
+void QueryListFacade::updateTableObjectList( bool /*_bAllowViews*/ )
+{
+ m_rQueryList.clear();
+ try
+ {
+ OUString aQueryImage(ImageProvider::getDefaultImageResourceID(css::sdb::application::DatabaseObject::QUERY));
+
+ Reference< XQueriesSupplier > xSuppQueries( m_xConnection, UNO_QUERY_THROW );
+ Reference< XNameAccess > xQueries( xSuppQueries->getQueries(), UNO_SET_THROW );
+ if ( !m_pContainerListener.is() )
+ {
+ Reference< XContainer> xContainer(xQueries,UNO_QUERY_THROW);
+ m_pContainerListener = new ::comphelper::OContainerListenerAdapter(this,xContainer);
+ }
+ const Sequence< OUString > aQueryNames = xQueries->getElementNames();
+
+ for ( auto const & name : aQueryNames )
+ m_rQueryList.append("", name, aQueryImage);
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+}
+
+OUString QueryListFacade::getSelectedName( OUString& _out_rAliasName ) const
+{
+ OUString sSelected;
+ std::unique_ptr<weld::TreeIter> xEntry(m_rQueryList.make_iterator());
+ const bool bEntry = m_rQueryList.get_selected(xEntry.get());
+ if (bEntry)
+ sSelected = _out_rAliasName = m_rQueryList.get_text(*xEntry, 0);
+ return sSelected;
+}
+
+bool QueryListFacade::isLeafSelected() const
+{
+ std::unique_ptr<weld::TreeIter> xEntry(m_rQueryList.make_iterator());
+ const bool bEntry = m_rQueryList.get_selected(xEntry.get());
+ return bEntry && !m_rQueryList.iter_has_child(*xEntry);
+
+}
+
+OAddTableDlg::OAddTableDlg(weld::Window* pParent, IAddTableDialogContext& _rContext)
+ : GenericDialogController(pParent, "dbaccess/ui/tablesjoindialog.ui", "TablesJoinDialog")
+ , m_rContext(_rContext)
+ , m_xCaseTables(m_xBuilder->weld_radio_button("tables"))
+ , m_xCaseQueries(m_xBuilder->weld_radio_button("queries"))
+ // false means: do not show any buttons
+ , m_xTableList(new OTableTreeListBox(m_xBuilder->weld_tree_view("tablelist"), false))
+ , m_xQueryList(m_xBuilder->weld_tree_view("querylist"))
+ , m_xAddButton(m_xBuilder->weld_button("add"))
+ , m_xCloseButton(m_xBuilder->weld_button("close"))
+{
+ weld::TreeView& rTableList = m_xTableList->GetWidget();
+ Size aSize(rTableList.get_approximate_digit_width() * 23,
+ rTableList.get_height_rows(15));
+ rTableList.set_size_request(aSize.Width(), aSize.Height());
+ m_xQueryList->set_size_request(aSize.Width(), aSize.Height());
+
+ m_xCaseTables->connect_toggled(LINK(this, OAddTableDlg, OnTypeSelected));
+ m_xAddButton->connect_clicked( LINK( this, OAddTableDlg, AddClickHdl ) );
+ m_xCloseButton->connect_clicked( LINK( this, OAddTableDlg, CloseClickHdl ) );
+ rTableList.connect_row_activated( LINK( this, OAddTableDlg, TableListDoubleClickHdl ) );
+ rTableList.connect_changed( LINK( this, OAddTableDlg, TableListSelectHdl ) );
+ m_xQueryList->connect_row_activated( LINK( this, OAddTableDlg, TableListDoubleClickHdl ) );
+ m_xQueryList->connect_changed( LINK( this, OAddTableDlg, TableListSelectHdl ) );
+
+ rTableList.set_selection_mode(SelectionMode::Single);
+ m_xTableList->SuppressEmptyFolders();
+
+ m_xQueryList->set_selection_mode(SelectionMode::Single);
+
+ if ( !m_rContext.allowQueries() )
+ {
+ m_xCaseTables->hide();
+ m_xCaseQueries->hide();
+ }
+
+ m_xDialog->set_title(getDialogTitleForContext(m_rContext));
+}
+
+OAddTableDlg::~OAddTableDlg()
+{
+}
+
+void OAddTableDlg::impl_switchTo( ObjectList _eList )
+{
+ switch ( _eList )
+ {
+ case Tables:
+ m_xTableList->GetWidget().show(); m_xCaseTables->set_active(true);
+ m_xQueryList->hide(); m_xCaseQueries->set_active(false);
+ m_xCurrentList.reset( new TableListFacade( *m_xTableList, m_rContext.getConnection() ) );
+ m_xTableList->GetWidget().grab_focus();
+ break;
+
+ case Queries:
+ m_xTableList->GetWidget().hide(); m_xCaseTables->set_active(false);
+ m_xQueryList->show(); m_xCaseQueries->set_active(true);
+ m_xCurrentList.reset( new QueryListFacade( *m_xQueryList, m_rContext.getConnection() ) );
+ m_xQueryList->grab_focus();
+ break;
+ }
+ m_xCurrentList->updateTableObjectList( m_rContext.allowViews() );
+}
+
+void OAddTableDlg::Update()
+{
+ if (!m_xCurrentList)
+ impl_switchTo( Tables );
+ else
+ m_xCurrentList->updateTableObjectList( m_rContext.allowViews() );
+}
+
+IMPL_LINK_NOARG( OAddTableDlg, AddClickHdl, weld::Button&, void )
+{
+ TableListDoubleClickHdl(m_xTableList->GetWidget());
+}
+
+IMPL_LINK_NOARG(OAddTableDlg, TableListDoubleClickHdl, weld::TreeView&, bool)
+{
+ if ( impl_isAddAllowed() )
+ {
+ if ( m_xCurrentList->isLeafSelected() )
+ {
+ OUString sSelectedName, sAliasName;
+ sSelectedName = m_xCurrentList->getSelectedName( sAliasName );
+
+ m_rContext.addTableWindow( sSelectedName, sAliasName );
+ }
+ if ( !impl_isAddAllowed() )
+ m_xDialog->response(RET_CLOSE);
+ }
+ return true;
+}
+
+IMPL_LINK_NOARG( OAddTableDlg, TableListSelectHdl, weld::TreeView&, void )
+{
+ m_xAddButton->set_sensitive( m_xCurrentList->isLeafSelected() );
+}
+
+IMPL_LINK_NOARG( OAddTableDlg, CloseClickHdl, weld::Button&, void )
+{
+ m_xDialog->response(RET_CLOSE);
+}
+
+IMPL_LINK_NOARG(OAddTableDlg, OnTypeSelected, weld::Toggleable&, void)
+{
+ if ( m_xCaseTables->get_active() )
+ impl_switchTo( Tables );
+ else
+ impl_switchTo( Queries );
+}
+
+void OAddTableDlg::OnClose()
+{
+ m_rContext.onWindowClosing();
+}
+
+bool OAddTableDlg::impl_isAddAllowed()
+{
+ return m_rContext.allowAddition();
+}
+
+OUString OAddTableDlg::getDialogTitleForContext( IAddTableDialogContext const & _rContext )
+{
+ OUString sTitle;
+
+ if ( _rContext.allowQueries() )
+ sTitle = DBA_RES( STR_ADD_TABLE_OR_QUERY );
+ else
+ sTitle = DBA_RES( STR_ADD_TABLES );
+
+ return sTitle;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/dlg/advancedsettings.cxx b/dbaccess/source/ui/dlg/advancedsettings.cxx
new file mode 100644
index 000000000..40964305a
--- /dev/null
+++ b/dbaccess/source/ui/dlg/advancedsettings.cxx
@@ -0,0 +1,472 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+
+#include <memory>
+
+#include "advancedsettings.hxx"
+#include <advancedsettingsdlg.hxx>
+#include <dsitems.hxx>
+#include "DbAdminImpl.hxx"
+#include "DriverSettings.hxx"
+#include "optionalboolitem.hxx"
+
+#include <svl/eitem.hxx>
+#include <svl/intitem.hxx>
+#include <svl/stritem.hxx>
+
+namespace dbaui
+{
+
+ using ::com::sun::star::uno::Reference;
+ using ::com::sun::star::uno::Any;
+ using ::com::sun::star::uno::XComponentContext;
+ using ::com::sun::star::beans::XPropertySet;
+ using ::com::sun::star::sdbc::XConnection;
+ using ::com::sun::star::sdbc::XDriver;
+
+ // SpecialSettingsPage
+ struct BooleanSettingDesc
+ {
+ std::unique_ptr<weld::CheckButton>& xControl; // the dialog's control which displays this setting
+ OString sControlId; // the widget name of the control in the .ui
+ sal_uInt16 nItemId; // the ID of the item (in an SfxItemSet) which corresponds to this setting
+ bool bInvertedDisplay; // true if and only if the checkbox is checked when the item is sal_False, and vice versa
+ bool bOptionalBool; // type is OptionalBool
+ };
+
+ // SpecialSettingsPage
+ SpecialSettingsPage::SpecialSettingsPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& _rCoreAttrs, const DataSourceMetaData& _rDSMeta)
+ : OGenericAdministrationPage(pPage, pController, "dbaccess/ui/specialsettingspage.ui", "SpecialSettingsPage", _rCoreAttrs)
+ , m_aBooleanSettings {
+ { m_xIsSQL92Check, "usesql92", DSID_SQL92CHECK, false, false },
+ { m_xAppendTableAlias, "append", DSID_APPEND_TABLE_ALIAS, false, false },
+ { m_xAsBeforeCorrelationName, "useas", DSID_AS_BEFORE_CORRNAME, false, false },
+ { m_xEnableOuterJoin, "useoj", DSID_ENABLEOUTERJOIN, false, false },
+ { m_xIgnoreDriverPrivileges, "ignoreprivs", DSID_IGNOREDRIVER_PRIV, false, false },
+ { m_xParameterSubstitution, "replaceparams", DSID_PARAMETERNAMESUBST, false, false },
+ { m_xSuppressVersionColumn, "displayver", DSID_SUPPRESSVERSIONCL, true, false },
+ { m_xCatalog, "usecatalogname", DSID_CATALOG, false, false },
+ { m_xSchema, "useschemaname", DSID_SCHEMA, false, false },
+ { m_xIndexAppendix, "createindex", DSID_INDEXAPPENDIX, false, false },
+ { m_xDosLineEnds, "eol", DSID_DOSLINEENDS, false, false },
+ { m_xCheckRequiredFields, "inputchecks", DSID_CHECK_REQUIRED_FIELDS, false, false },
+ { m_xIgnoreCurrency, "ignorecurrency", DSID_IGNORECURRENCY, false, false },
+ { m_xEscapeDateTime, "useodbcliterals", DSID_ESCAPE_DATETIME, false, false },
+ { m_xPrimaryKeySupport, "primarykeys", DSID_PRIMARY_KEY_SUPPORT, false, false },
+ { m_xRespectDriverResultSetType, "resulttype", DSID_RESPECTRESULTSETTYPE, false, false } }
+ , m_bHasBooleanComparisonMode( _rDSMeta.getFeatureSet().has( DSID_BOOLEANCOMPARISON ) )
+ , m_bHasMaxRowScan( _rDSMeta.getFeatureSet().has( DSID_MAX_ROW_SCAN ) )
+ {
+ const FeatureSet& rFeatures( _rDSMeta.getFeatureSet() );
+ // create all the check boxes for the boolean settings
+ for (auto & booleanSetting : m_aBooleanSettings)
+ {
+ sal_uInt16 nItemId = booleanSetting.nItemId;
+ if ( rFeatures.has( nItemId ) )
+ {
+ // check whether this must be a tristate check box
+ const SfxPoolItem& rItem = _rCoreAttrs.Get(nItemId);
+ booleanSetting.bOptionalBool = dynamic_cast<const OptionalBoolItem*>(&rItem) != nullptr;
+ booleanSetting.xControl = m_xBuilder->weld_check_button(booleanSetting.sControlId);
+ if (booleanSetting.bOptionalBool)
+ booleanSetting.xControl->connect_toggled(LINK(this, SpecialSettingsPage, OnTriStateToggleHdl));
+ else
+ booleanSetting.xControl->connect_toggled(LINK(this, SpecialSettingsPage, OnToggleHdl));
+ booleanSetting.xControl->show();
+ }
+ }
+
+ // create the controls for the boolean comparison mode
+ if ( m_bHasBooleanComparisonMode )
+ {
+ m_xBooleanComparisonModeLabel = m_xBuilder->weld_label("comparisonft");
+ m_xBooleanComparisonMode = m_xBuilder->weld_combo_box("comparison");
+ m_xBooleanComparisonMode->connect_changed(LINK(this, SpecialSettingsPage, BooleanComparisonSelectHdl));
+ m_xBooleanComparisonModeLabel->show();
+ m_xBooleanComparisonMode->show();
+ }
+ // create the controls for the max row scan
+ if ( m_bHasMaxRowScan )
+ {
+ m_xMaxRowScanLabel = m_xBuilder->weld_label("rowsft");
+ m_xMaxRowScan = m_xBuilder->weld_spin_button("rows");
+ m_xMaxRowScan->connect_value_changed(LINK(this, OGenericAdministrationPage, OnControlSpinButtonModifyHdl));
+ m_xMaxRowScanLabel->show();
+ m_xMaxRowScan->show();
+ }
+ }
+
+ IMPL_LINK(SpecialSettingsPage, OnTriStateToggleHdl, weld::Toggleable&, rToggle, void)
+ {
+ auto eOldState = m_aTriStates[&rToggle];
+ switch (eOldState)
+ {
+ case TRISTATE_INDET:
+ rToggle.set_state(TRISTATE_FALSE);
+ break;
+ case TRISTATE_TRUE:
+ rToggle.set_state(TRISTATE_INDET);
+ break;
+ case TRISTATE_FALSE:
+ rToggle.set_state(TRISTATE_TRUE);
+ break;
+ }
+ m_aTriStates[&rToggle] = rToggle.get_state();
+ OnToggleHdl(rToggle);
+ }
+
+ IMPL_LINK(SpecialSettingsPage, OnToggleHdl, weld::Toggleable&, rBtn, void)
+ {
+ if (&rBtn == m_xAppendTableAlias.get() && m_xAsBeforeCorrelationName)
+ {
+ // make m_xAsBeforeCorrelationName depend on m_xAppendTableAlias
+ m_xAsBeforeCorrelationName->set_sensitive(m_xAppendTableAlias->get_active());
+ }
+ OnControlModifiedButtonClick(rBtn);
+ }
+
+ IMPL_LINK(SpecialSettingsPage, BooleanComparisonSelectHdl, weld::ComboBox&, rControl, void)
+ {
+ callModifiedHdl(&rControl);
+ }
+
+ SpecialSettingsPage::~SpecialSettingsPage()
+ {
+ }
+
+ void SpecialSettingsPage::fillWindows( std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList )
+ {
+ if ( m_bHasBooleanComparisonMode )
+ {
+ _rControlList.emplace_back(new ODisableWidgetWrapper<weld::Label>(m_xBooleanComparisonModeLabel.get()));
+ }
+ if ( m_bHasMaxRowScan )
+ {
+ _rControlList.emplace_back(new ODisableWidgetWrapper<weld::Label>(m_xMaxRowScanLabel.get()));
+ }
+ }
+
+ void SpecialSettingsPage::fillControls(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList)
+ {
+ for (auto const& booleanSetting : m_aBooleanSettings)
+ {
+ if (booleanSetting.xControl)
+ {
+ _rControlList.emplace_back(new OSaveValueWidgetWrapper<weld::Toggleable>(booleanSetting.xControl.get()));
+ }
+ }
+
+ if ( m_bHasBooleanComparisonMode )
+ _rControlList.emplace_back(new OSaveValueWidgetWrapper<weld::ComboBox>(m_xBooleanComparisonMode.get()));
+ if ( m_bHasMaxRowScan )
+ _rControlList.emplace_back(new OSaveValueWidgetWrapper<weld::SpinButton>(m_xMaxRowScan.get()));
+ }
+
+ void SpecialSettingsPage::implInitControls(const SfxItemSet& _rSet, bool _bSaveValue)
+ {
+ // check whether or not the selection is invalid or readonly (invalid implies readonly, but not vice versa)
+ bool bValid, bReadonly;
+ getFlags( _rSet, bValid, bReadonly );
+
+ if ( !bValid )
+ {
+ OGenericAdministrationPage::implInitControls(_rSet, _bSaveValue);
+ return;
+ }
+
+ m_aTriStates.clear();
+
+ // the boolean items
+ for (auto const& booleanSetting : m_aBooleanSettings)
+ {
+ if (!booleanSetting.xControl)
+ continue;
+
+ bool bTriState = false;
+
+ std::optional<bool> aValue;
+
+ const SfxPoolItem* pItem = _rSet.GetItem<SfxPoolItem>(booleanSetting.nItemId);
+ if (const SfxBoolItem *pBoolItem = dynamic_cast<const SfxBoolItem*>( pItem) )
+ {
+ aValue = pBoolItem->GetValue();
+ }
+ else if (const OptionalBoolItem *pOptionalItem = dynamic_cast<const OptionalBoolItem*>( pItem) )
+ {
+ aValue = pOptionalItem->GetFullValue();
+ bTriState = true;
+ }
+ else
+ OSL_FAIL( "SpecialSettingsPage::implInitControls: unknown boolean item type!" );
+
+ if ( !aValue )
+ {
+ booleanSetting.xControl->set_state(TRISTATE_INDET);
+ }
+ else
+ {
+ bool bValue = *aValue;
+ if ( booleanSetting.bInvertedDisplay )
+ bValue = !bValue;
+ booleanSetting.xControl->set_active(bValue);
+ }
+ if (bTriState)
+ m_aTriStates[booleanSetting.xControl.get()] = booleanSetting.xControl->get_state();
+ }
+
+ if (m_xAppendTableAlias && m_xAsBeforeCorrelationName)
+ {
+ // make m_xAsBeforeCorrelationName depend on m_xAppendTableAlias
+ m_xAsBeforeCorrelationName->set_sensitive(m_xAppendTableAlias->get_active());
+ }
+
+ // the non-boolean items
+ if ( m_bHasBooleanComparisonMode )
+ {
+ const SfxInt32Item* pBooleanComparison = _rSet.GetItem<SfxInt32Item>(DSID_BOOLEANCOMPARISON);
+ m_xBooleanComparisonMode->set_active(static_cast<sal_uInt16>(pBooleanComparison->GetValue()));
+ }
+
+ if ( m_bHasMaxRowScan )
+ {
+ const SfxInt32Item* pMaxRowScan = _rSet.GetItem<SfxInt32Item>(DSID_MAX_ROW_SCAN);
+ m_xMaxRowScan->set_value(pMaxRowScan->GetValue());
+ }
+
+ OGenericAdministrationPage::implInitControls(_rSet, _bSaveValue);
+ }
+
+ bool SpecialSettingsPage::FillItemSet( SfxItemSet* _rSet )
+ {
+ bool bChangedSomething = false;
+
+ // the boolean items
+ for (auto const& booleanSetting : m_aBooleanSettings)
+ {
+ if (!booleanSetting.xControl)
+ continue;
+ fillBool(*_rSet, booleanSetting.xControl.get(), booleanSetting.nItemId, booleanSetting.bOptionalBool, bChangedSomething, booleanSetting.bInvertedDisplay);
+ }
+
+ // the non-boolean items
+ if ( m_bHasBooleanComparisonMode )
+ {
+ if (m_xBooleanComparisonMode->get_value_changed_from_saved())
+ {
+ _rSet->Put(SfxInt32Item(DSID_BOOLEANCOMPARISON, m_xBooleanComparisonMode->get_active()));
+ bChangedSomething = true;
+ }
+ }
+ if ( m_bHasMaxRowScan )
+ {
+ fillInt32(*_rSet,m_xMaxRowScan.get(),DSID_MAX_ROW_SCAN,bChangedSomething);
+ }
+ return bChangedSomething;
+ }
+
+ // GeneratedValuesPage
+ GeneratedValuesPage::GeneratedValuesPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& _rCoreAttrs)
+ : OGenericAdministrationPage(pPage, pController, "dbaccess/ui/generatedvaluespage.ui", "GeneratedValuesPage", _rCoreAttrs)
+ , m_xAutoRetrievingEnabled(m_xBuilder->weld_check_button("autoretrieve"))
+ , m_xGrid(m_xBuilder->weld_widget("grid"))
+ , m_xAutoIncrementLabel(m_xBuilder->weld_label("statementft"))
+ , m_xAutoIncrement(m_xBuilder->weld_entry("statement"))
+ , m_xAutoRetrievingLabel(m_xBuilder->weld_label("queryft"))
+ , m_xAutoRetrieving(m_xBuilder->weld_entry("query"))
+ {
+ m_xAutoRetrievingEnabled->connect_toggled(LINK(this, GeneratedValuesPage, OnAutoToggleHdl));
+ m_xAutoIncrement->connect_changed(LINK(this, OGenericAdministrationPage, OnControlEntryModifyHdl));
+ m_xAutoRetrieving->connect_changed(LINK(this, OGenericAdministrationPage, OnControlEntryModifyHdl));
+ }
+
+ IMPL_LINK(GeneratedValuesPage, OnAutoToggleHdl, weld::Toggleable&, rBtn, void)
+ {
+ m_xGrid->set_sensitive(rBtn.get_active());
+ OnControlModifiedButtonClick(rBtn);
+ }
+
+ GeneratedValuesPage::~GeneratedValuesPage()
+ {
+ }
+
+ void GeneratedValuesPage::fillWindows( std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList )
+ {
+ _rControlList.emplace_back(new ODisableWidgetWrapper<weld::Widget>(m_xContainer.get()));
+ }
+
+ void GeneratedValuesPage::fillControls( std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList )
+ {
+ _rControlList.emplace_back( new OSaveValueWidgetWrapper<weld::Toggleable>( m_xAutoRetrievingEnabled.get() ) );
+ _rControlList.emplace_back( new OSaveValueWidgetWrapper<weld::Entry>( m_xAutoIncrement.get() ) );
+ _rControlList.emplace_back( new OSaveValueWidgetWrapper<weld::Entry>( m_xAutoRetrieving.get() ) );
+ }
+
+ void GeneratedValuesPage::implInitControls( const SfxItemSet& _rSet, bool _bSaveValue )
+ {
+ // check whether or not the selection is invalid or readonly (invalid implies readonly, but not vice versa)
+ bool bValid, bReadonly;
+ getFlags(_rSet, bValid, bReadonly);
+
+ // collect the items
+ const SfxStringItem* pAutoIncrementItem = _rSet.GetItem<SfxStringItem>(DSID_AUTOINCREMENTVALUE);
+ const SfxStringItem* pAutoRetrieveValueItem = _rSet.GetItem<SfxStringItem>(DSID_AUTORETRIEVEVALUE);
+ const SfxBoolItem* pAutoRetrieveEnabledItem = _rSet.GetItem<SfxBoolItem>(DSID_AUTORETRIEVEENABLED);
+
+ // forward the values to the controls
+ if (bValid)
+ {
+ bool bEnabled = pAutoRetrieveEnabledItem->GetValue();
+ m_xAutoRetrievingEnabled->set_active(bEnabled);
+
+ m_xAutoIncrement->set_text(pAutoIncrementItem->GetValue());
+ m_xAutoIncrement->save_value();
+ m_xAutoRetrieving->set_text(pAutoRetrieveValueItem->GetValue());
+ m_xAutoRetrieving->save_value();
+ }
+ OGenericAdministrationPage::implInitControls( _rSet, _bSaveValue );
+ }
+
+ bool GeneratedValuesPage::FillItemSet(SfxItemSet* _rSet)
+ {
+ bool bChangedSomething = false;
+
+ fillString( *_rSet, m_xAutoIncrement.get(), DSID_AUTOINCREMENTVALUE, bChangedSomething );
+ fillBool( *_rSet, m_xAutoRetrievingEnabled.get(), DSID_AUTORETRIEVEENABLED, false, bChangedSomething );
+ fillString( *_rSet, m_xAutoRetrieving.get(), DSID_AUTORETRIEVEVALUE, bChangedSomething );
+
+ return bChangedSomething;
+ }
+
+ // AdvancedSettingsDialog
+ AdvancedSettingsDialog::AdvancedSettingsDialog(weld::Window* pParent, SfxItemSet* _pItems,
+ const Reference< XComponentContext >& _rxContext, const Any& _aDataSourceName )
+ : SfxTabDialogController(pParent, "dbaccess/ui/advancedsettingsdialog.ui", "AdvancedSettingsDialog", _pItems)
+ {
+ m_pImpl.reset(new ODbDataSourceAdministrationHelper(_rxContext, m_xDialog.get(), pParent, this));
+ m_pImpl->setDataSourceOrName(_aDataSourceName);
+ Reference< XPropertySet > xDatasource = m_pImpl->getCurrentDataSource();
+ m_pImpl->translateProperties(xDatasource, *_pItems);
+ SetInputSet(_pItems);
+ // propagate this set as our new input set and reset the example set
+ m_xExampleSet.reset(new SfxItemSet(*GetInputSetImpl()));
+
+ const OUString eType = dbaui::ODbDataSourceAdministrationHelper::getDatasourceType(*_pItems);
+
+ DataSourceMetaData aMeta( eType );
+ const FeatureSet& rFeatures( aMeta.getFeatureSet() );
+
+ // auto-generated values?
+ if (rFeatures.supportsGeneratedValues())
+ AddTabPage("generated", ODriversSettings::CreateGeneratedValuesPage, nullptr);
+ else
+ RemoveTabPage("generated");
+
+ // any "special settings"?
+ if (rFeatures.supportsAnySpecialSetting())
+ AddTabPage("special", ODriversSettings::CreateSpecialSettingsPage, nullptr);
+ else
+ RemoveTabPage("special");
+
+ // remove the reset button - it's meaning is much too ambiguous in this dialog
+ RemoveResetButton();
+ }
+
+ AdvancedSettingsDialog::~AdvancedSettingsDialog()
+ {
+ SetInputSet(nullptr);
+ }
+
+ bool AdvancedSettingsDialog::doesHaveAnyAdvancedSettings( const OUString& _sURL )
+ {
+ DataSourceMetaData aMeta( _sURL );
+ const FeatureSet& rFeatures( aMeta.getFeatureSet() );
+ return rFeatures.supportsGeneratedValues() || rFeatures.supportsAnySpecialSetting();
+ }
+
+ short AdvancedSettingsDialog::Ok()
+ {
+ short nRet = SfxTabDialogController::Ok();
+ if ( nRet == RET_OK )
+ {
+ m_xExampleSet->Put(*GetOutputItemSet());
+ m_pImpl->saveChanges(*m_xExampleSet);
+ }
+ return nRet;
+ }
+
+ void AdvancedSettingsDialog::PageCreated(const OString& rId, SfxTabPage& _rPage)
+ {
+ // register ourself as modified listener
+ static_cast<OGenericAdministrationPage&>(_rPage).SetServiceFactory( getORB() );
+ static_cast<OGenericAdministrationPage&>(_rPage).SetAdminDialog(this,this);
+ SfxTabDialogController::PageCreated(rId, _rPage);
+ }
+
+ const SfxItemSet* AdvancedSettingsDialog::getOutputSet() const
+ {
+ return m_xExampleSet.get();
+ }
+
+ SfxItemSet* AdvancedSettingsDialog::getWriteOutputSet()
+ {
+ return m_xExampleSet.get();
+ }
+
+ std::pair< Reference< XConnection >, bool > AdvancedSettingsDialog::createConnection()
+ {
+ return m_pImpl->createConnection();
+ }
+
+ Reference< XComponentContext > AdvancedSettingsDialog::getORB() const
+ {
+ return m_pImpl->getORB();
+ }
+
+ Reference< XDriver > AdvancedSettingsDialog::getDriver()
+ {
+ return m_pImpl->getDriver();
+ }
+
+ OUString AdvancedSettingsDialog::getDatasourceType(const SfxItemSet& _rSet) const
+ {
+ return dbaui::ODbDataSourceAdministrationHelper::getDatasourceType(_rSet);
+ }
+
+ void AdvancedSettingsDialog::clearPassword()
+ {
+ m_pImpl->clearPassword();
+ }
+
+ void AdvancedSettingsDialog::setTitle(const OUString& _sTitle)
+ {
+ m_xDialog->set_title(_sTitle);
+ }
+
+ void AdvancedSettingsDialog::enableConfirmSettings( bool ) {}
+
+ void AdvancedSettingsDialog::saveDatasource()
+ {
+ PrepareLeaveCurrentPage();
+ }
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/dlg/advancedsettings.hxx b/dbaccess/source/ui/dlg/advancedsettings.hxx
new file mode 100644
index 000000000..38f100612
--- /dev/null
+++ b/dbaccess/source/ui/dlg/advancedsettings.hxx
@@ -0,0 +1,116 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include "adminpages.hxx"
+#include <dsmeta.hxx>
+#include <vector>
+
+namespace dbaui
+{
+ struct BooleanSettingDesc;
+
+ // SpecialSettingsPage
+ // implements the "Special Settings" page of the advanced database settings
+ class SpecialSettingsPage final : public OGenericAdministrationPage
+ {
+ std::unique_ptr<weld::CheckButton> m_xIsSQL92Check;
+ std::unique_ptr<weld::CheckButton> m_xAppendTableAlias;
+ std::unique_ptr<weld::CheckButton> m_xAsBeforeCorrelationName;
+ std::unique_ptr<weld::CheckButton> m_xEnableOuterJoin;
+ std::unique_ptr<weld::CheckButton> m_xIgnoreDriverPrivileges;
+ std::unique_ptr<weld::CheckButton> m_xParameterSubstitution;
+ std::unique_ptr<weld::CheckButton> m_xSuppressVersionColumn;
+ std::unique_ptr<weld::CheckButton> m_xCatalog;
+ std::unique_ptr<weld::CheckButton> m_xSchema;
+ std::unique_ptr<weld::CheckButton> m_xIndexAppendix;
+ std::unique_ptr<weld::CheckButton> m_xDosLineEnds;
+ std::unique_ptr<weld::CheckButton> m_xCheckRequiredFields;
+ std::unique_ptr<weld::CheckButton> m_xIgnoreCurrency;
+ std::unique_ptr<weld::CheckButton> m_xEscapeDateTime;
+ std::unique_ptr<weld::CheckButton> m_xPrimaryKeySupport;
+ std::unique_ptr<weld::CheckButton> m_xRespectDriverResultSetType;
+
+ std::unique_ptr<weld::Label> m_xBooleanComparisonModeLabel;
+ std::unique_ptr<weld::ComboBox> m_xBooleanComparisonMode;
+
+ std::unique_ptr<weld::Label> m_xMaxRowScanLabel;
+ std::unique_ptr<weld::SpinButton> m_xMaxRowScan;
+
+ std::map<weld::Toggleable*, TriState> m_aTriStates;
+
+ std::vector< BooleanSettingDesc > m_aBooleanSettings;
+
+ bool m_bHasBooleanComparisonMode;
+ bool m_bHasMaxRowScan;
+
+ public:
+ DECL_LINK(OnToggleHdl, weld::Toggleable&, void);
+ DECL_LINK(OnTriStateToggleHdl, weld::Toggleable&, void);
+
+ virtual bool FillItemSet ( SfxItemSet* _rCoreAttrs ) override;
+
+ SpecialSettingsPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& _rCoreAttrs, const DataSourceMetaData& _rDSMeta);
+ virtual ~SpecialSettingsPage() override;
+
+ private:
+ // OGenericAdministrationPage overridables
+ virtual void implInitControls (const SfxItemSet& _rSet, bool _bSaveValue ) override;
+
+ // <method>OGenericAdministrationPage::fillControls</method>
+ virtual void fillControls(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) override;
+
+ // <method>OGenericAdministrationPage::fillWindows</method>
+ virtual void fillWindows(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) override;
+
+ DECL_LINK(BooleanComparisonSelectHdl, weld::ComboBox&, void);
+ };
+
+ // GeneratedValuesPage
+ class GeneratedValuesPage final : public OGenericAdministrationPage
+ {
+ std::unique_ptr<weld::CheckButton> m_xAutoRetrievingEnabled;
+ std::unique_ptr<weld::Widget> m_xGrid;
+ std::unique_ptr<weld::Label> m_xAutoIncrementLabel;
+ std::unique_ptr<weld::Entry> m_xAutoIncrement;
+ std::unique_ptr<weld::Label> m_xAutoRetrievingLabel;
+ std::unique_ptr<weld::Entry> m_xAutoRetrieving;
+
+ public:
+ virtual bool FillItemSet (SfxItemSet* _rCoreAttrs) override;
+
+ GeneratedValuesPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& _rCoreAttrs);
+ virtual ~GeneratedValuesPage() override;
+
+ private:
+ DECL_LINK(OnAutoToggleHdl, weld::Toggleable&, void);
+
+ // subclasses must override this, but it isn't pure virtual
+ virtual void implInitControls(const SfxItemSet& _rSet, bool _bSaveValue) override;
+
+ // <method>OGenericAdministrationPage::fillControls</method>
+ virtual void fillControls(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) override;
+
+ // <method>OGenericAdministrationPage::fillWindows</method>
+ virtual void fillWindows(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) override;
+ };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/dlg/dbadmin.cxx b/dbaccess/source/ui/dlg/dbadmin.cxx
new file mode 100644
index 000000000..c6ca46f75
--- /dev/null
+++ b/dbaccess/source/ui/dlg/dbadmin.cxx
@@ -0,0 +1,433 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "ConnectionPage.hxx"
+#include "DbAdminImpl.hxx"
+#include "DriverSettings.hxx"
+#include "adminpages.hxx"
+#include <dbadmin.hxx>
+#include <svl/stritem.hxx>
+#include <svl/eitem.hxx>
+#include <svl/intitem.hxx>
+#include <core_resource.hxx>
+#include <strings.hrc>
+#include <dsitems.hxx>
+#include "dsnItem.hxx"
+#include "optionalboolitem.hxx"
+#include <stringlistitem.hxx>
+
+#include <unotools/confignode.hxx>
+
+namespace dbaui
+{
+using namespace com::sun::star::uno;
+using namespace com::sun::star::sdbc;
+using namespace com::sun::star::lang;
+using namespace com::sun::star::util;
+using namespace com::sun::star::beans;
+using namespace com::sun::star::container;
+
+// ODbAdminDialog
+ODbAdminDialog::ODbAdminDialog(weld::Window* pParent,
+ SfxItemSet const * _pItems,
+ const Reference< XComponentContext >& _rxContext)
+ : SfxTabDialogController(pParent, "dbaccess/ui/admindialog.ui", "AdminDialog", _pItems)
+ , m_sMainPageID("advanced")
+{
+ m_pImpl.reset(new ODbDataSourceAdministrationHelper(_rxContext, m_xDialog.get(), pParent, this));
+
+ // add the initial tab page
+ AddTabPage(m_sMainPageID, OConnectionTabPage::Create, nullptr);
+
+ // remove the reset button - it's meaning is much too ambiguous in this dialog
+ RemoveResetButton();
+}
+
+ODbAdminDialog::~ODbAdminDialog()
+{
+ SetInputSet(nullptr);
+}
+
+short ODbAdminDialog::Ok()
+{
+ SfxTabDialogController::Ok();
+ return ( AR_LEAVE_MODIFIED == implApplyChanges() ) ? RET_OK : RET_CANCEL;
+ // TODO : AR_ERROR is not handled correctly, we always close the dialog here
+}
+
+void ODbAdminDialog::PageCreated(const OString& rId, SfxTabPage& _rPage)
+{
+ // register ourself as modified listener
+ static_cast<OGenericAdministrationPage&>(_rPage).SetServiceFactory( getORB() );
+ static_cast<OGenericAdministrationPage&>(_rPage).SetAdminDialog(this,this);
+
+ SfxTabDialogController::PageCreated(rId, _rPage);
+}
+
+void ODbAdminDialog::addDetailPage(const OString& rPageId, TranslateId pTextId, CreateTabPage pCreateFunc)
+{
+ AddTabPage(rPageId, DBA_RES(pTextId), pCreateFunc);
+}
+
+void ODbAdminDialog::impl_selectDataSource(const css::uno::Any& _aDataSourceName)
+{
+ m_pImpl->setDataSourceOrName(_aDataSourceName);
+ Reference< XPropertySet > xDatasource = m_pImpl->getCurrentDataSource();
+ impl_resetPages( xDatasource );
+
+ const DbuTypeCollectionItem* pCollectionItem = dynamic_cast<const DbuTypeCollectionItem*>(getOutputSet()->GetItem(DSID_TYPECOLLECTION));
+ assert(pCollectionItem && "must exist");
+ ::dbaccess::ODsnTypeCollection* pCollection = pCollectionItem->getCollection();
+ ::dbaccess::DATASOURCE_TYPE eType = pCollection->determineType(getDatasourceType(*getOutputSet()));
+
+ // and insert the new ones
+ switch ( eType )
+ {
+ case ::dbaccess::DST_DBASE:
+ addDetailPage("dbase", STR_PAGETITLE_ADVANCED, ODriversSettings::CreateDbase);
+ break;
+
+ case ::dbaccess::DST_ADO:
+ addDetailPage("ado", STR_PAGETITLE_ADVANCED, ODriversSettings::CreateAdo);
+ break;
+
+ case ::dbaccess::DST_FLAT:
+ addDetailPage("text", STR_PAGETITLE_ADVANCED, ODriversSettings::CreateText);
+ break;
+
+ case ::dbaccess::DST_ODBC:
+ addDetailPage("odbc", STR_PAGETITLE_ADVANCED, ODriversSettings::CreateODBC);
+ break;
+
+ case ::dbaccess::DST_MYSQL_ODBC:
+ addDetailPage("mysqlodbc", STR_PAGETITLE_ADVANCED, ODriversSettings::CreateMySQLODBC);
+ break;
+
+ case ::dbaccess::DST_MYSQL_JDBC:
+ addDetailPage("mysqljdbc", STR_PAGETITLE_ADVANCED, ODriversSettings::CreateMySQLJDBC);
+ break;
+
+ case ::dbaccess::DST_ORACLE_JDBC:
+ addDetailPage("oraclejdbc", STR_PAGETITLE_ADVANCED, ODriversSettings::CreateOracleJDBC);
+ break;
+
+ case ::dbaccess::DST_LDAP:
+ addDetailPage("ldap",STR_PAGETITLE_ADVANCED,ODriversSettings::CreateLDAP);
+ break;
+ case ::dbaccess::DST_USERDEFINE1: /// first user defined driver
+ case ::dbaccess::DST_USERDEFINE2:
+ case ::dbaccess::DST_USERDEFINE3:
+ case ::dbaccess::DST_USERDEFINE4:
+ case ::dbaccess::DST_USERDEFINE5:
+ case ::dbaccess::DST_USERDEFINE6:
+ case ::dbaccess::DST_USERDEFINE7:
+ case ::dbaccess::DST_USERDEFINE8:
+ case ::dbaccess::DST_USERDEFINE9:
+ case ::dbaccess::DST_USERDEFINE10:
+ {
+ OUString aTitle(DBA_RES(STR_PAGETITLE_ADVANCED));
+ AddTabPage("user" + OString::number(eType - dbaccess::DST_USERDEFINE1 + 1), aTitle, ODriversSettings::CreateUser);
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+void ODbAdminDialog::impl_resetPages(const Reference< XPropertySet >& _rxDatasource)
+{
+ // the selection is valid if and only if we have a datasource now
+ GetInputSetImpl()->Put(SfxBoolItem(DSID_INVALID_SELECTION, !_rxDatasource.is()));
+ // (sal_False tells the tab pages to disable and reset all their controls, which is different
+ // from "just set them to readonly")
+
+ // reset the pages
+
+ // prevent flicker
+ m_xDialog->freeze();
+
+ // remove all items which relate to indirect properties from the input set
+ // (without this, the following may happen: select an arbitrary data source where some indirect properties
+ // are set. Select another data source of the same type, where the indirect props are not set (yet). Then,
+ // the indirect property values of the first ds are shown in the second ds ...)
+ const ODbDataSourceAdministrationHelper::MapInt2String& rMap = m_pImpl->getIndirectProperties();
+ for (auto const& elem : rMap)
+ GetInputSetImpl()->ClearItem( static_cast<sal_uInt16>(elem.first) );
+
+ // extract all relevant data from the property set of the data source
+ m_pImpl->translateProperties(_rxDatasource, *GetInputSetImpl());
+
+ // reset the example set
+ m_xExampleSet.reset(new SfxItemSet(*GetInputSetImpl()));
+
+ // special case: MySQL Native does not have the generic "advanced" page
+
+ const DbuTypeCollectionItem* pCollectionItem = dynamic_cast<const DbuTypeCollectionItem*>(getOutputSet()->GetItem(DSID_TYPECOLLECTION));
+ assert(pCollectionItem && "must exist");
+ ::dbaccess::ODsnTypeCollection* pCollection = pCollectionItem->getCollection();
+ if ( pCollection->determineType(getDatasourceType( *m_xExampleSet )) == ::dbaccess::DST_MYSQL_NATIVE )
+ {
+ OString sMySqlNative("mysqlnative");
+ AddTabPage(sMySqlNative, DBA_RES(STR_PAGETITLE_CONNECTION), ODriversSettings::CreateMySQLNATIVE);
+ RemoveTabPage("advanced");
+ m_sMainPageID = sMySqlNative;
+ }
+
+ SetCurPageId(m_sMainPageID);
+ SfxTabPage* pConnectionPage = GetTabPage(m_sMainPageID);
+ if ( pConnectionPage )
+ pConnectionPage->Reset(GetInputSetImpl());
+ // if this is NULL, the page has not been created yet, which means we're called before the
+ // dialog was displayed (probably from inside the ctor)
+
+ m_xDialog->thaw();
+}
+
+void ODbAdminDialog::setTitle(const OUString& rTitle)
+{
+ m_xDialog->set_title(rTitle);
+}
+
+void ODbAdminDialog::enableConfirmSettings( bool ) {}
+
+void ODbAdminDialog::saveDatasource()
+{
+ PrepareLeaveCurrentPage();
+}
+
+ODbAdminDialog::ApplyResult ODbAdminDialog::implApplyChanges()
+{
+ if (!PrepareLeaveCurrentPage())
+ { // the page did not allow us to leave
+ return AR_KEEP;
+ }
+
+ if ( !m_pImpl->saveChanges(*m_xExampleSet) )
+ return AR_KEEP;
+
+ return AR_LEAVE_MODIFIED;
+}
+
+void ODbAdminDialog::selectDataSource(const css::uno::Any& _aDataSourceName)
+{
+ impl_selectDataSource(_aDataSourceName);
+}
+
+const SfxItemSet* ODbAdminDialog::getOutputSet() const
+{
+ return GetExampleSet();
+}
+
+SfxItemSet* ODbAdminDialog::getWriteOutputSet()
+{
+ return m_xExampleSet.get();
+}
+
+std::pair< Reference<XConnection>,bool> ODbAdminDialog::createConnection()
+{
+ return m_pImpl->createConnection();
+}
+
+Reference< XComponentContext > ODbAdminDialog::getORB() const
+{
+ return m_pImpl->getORB();
+}
+
+Reference< XDriver > ODbAdminDialog::getDriver()
+{
+ return m_pImpl->getDriver();
+}
+
+OUString ODbAdminDialog::getDatasourceType(const SfxItemSet& _rSet) const
+{
+ return dbaui::ODbDataSourceAdministrationHelper::getDatasourceType(_rSet);
+}
+
+void ODbAdminDialog::clearPassword()
+{
+ m_pImpl->clearPassword();
+}
+
+void ODbAdminDialog::createItemSet(std::unique_ptr<SfxItemSet>& _rpSet, rtl::Reference<SfxItemPool>& _rpPool, std::vector<SfxPoolItem*>*& _rpDefaults, ::dbaccess::ODsnTypeCollection* _pTypeCollection)
+{
+ // just to be sure...
+ _rpSet = nullptr;
+ _rpPool = nullptr;
+ _rpDefaults = nullptr;
+
+ const OUString sFilterAll( "%" );
+ // create and initialize the defaults
+ _rpDefaults = new std::vector<SfxPoolItem*>(DSID_LAST_ITEM_ID - DSID_FIRST_ITEM_ID + 1);
+ SfxPoolItem** pCounter = _rpDefaults->data(); // want to modify this without affecting the out param _rppDefaults
+ *pCounter++ = new SfxStringItem(DSID_NAME, OUString());
+ *pCounter++ = new SfxStringItem(DSID_ORIGINALNAME, OUString());
+ *pCounter++ = new SfxStringItem(DSID_CONNECTURL, OUString());
+ *pCounter++ = new OStringListItem(DSID_TABLEFILTER, Sequence< OUString >(&sFilterAll, 1));
+ *pCounter++ = new DbuTypeCollectionItem(DSID_TYPECOLLECTION, _pTypeCollection);
+ *pCounter++ = new SfxBoolItem(DSID_INVALID_SELECTION, false);
+ *pCounter++ = new SfxBoolItem(DSID_READONLY, false);
+ *pCounter++ = new SfxStringItem(DSID_USER, OUString());
+ *pCounter++ = new SfxStringItem(DSID_PASSWORD, OUString());
+ *pCounter++ = new SfxStringItem(DSID_ADDITIONALOPTIONS, OUString());
+ *pCounter++ = new SfxStringItem(DSID_CHARSET, OUString());
+ *pCounter++ = new SfxBoolItem(DSID_PASSWORDREQUIRED, false);
+ *pCounter++ = new SfxBoolItem(DSID_SHOWDELETEDROWS, false);
+ *pCounter++ = new SfxBoolItem(DSID_ALLOWLONGTABLENAMES, false);
+ *pCounter++ = new SfxStringItem(DSID_JDBCDRIVERCLASS, OUString());
+ *pCounter++ = new SfxStringItem(DSID_FIELDDELIMITER, OUString(','));
+ *pCounter++ = new SfxStringItem(DSID_TEXTDELIMITER, OUString('"'));
+ *pCounter++ = new SfxStringItem(DSID_DECIMALDELIMITER, OUString('.'));
+ *pCounter++ = new SfxStringItem(DSID_THOUSANDSDELIMITER, OUString());
+ *pCounter++ = new SfxStringItem(DSID_TEXTFILEEXTENSION, "txt");
+ *pCounter++ = new SfxBoolItem(DSID_TEXTFILEHEADER, true);
+ *pCounter++ = new SfxBoolItem(DSID_PARAMETERNAMESUBST, false);
+ *pCounter++ = new SfxInt32Item(DSID_CONN_PORTNUMBER, 8100);
+ *pCounter++ = new SfxBoolItem(DSID_SUPPRESSVERSIONCL, false);
+ *pCounter++ = new SfxBoolItem(DSID_CONN_SHUTSERVICE, false);
+ *pCounter++ = new SfxInt32Item(DSID_CONN_DATAINC, 20);
+ *pCounter++ = new SfxInt32Item(DSID_CONN_CACHESIZE, 20);
+ *pCounter++ = new SfxStringItem(DSID_CONN_CTRLUSER, OUString());
+ *pCounter++ = new SfxStringItem(DSID_CONN_CTRLPWD, OUString());
+ *pCounter++ = new SfxBoolItem(DSID_USECATALOG, false);
+ *pCounter++ = new SfxStringItem(DSID_CONN_HOSTNAME, OUString());
+ *pCounter++ = new SfxStringItem(DSID_CONN_LDAP_BASEDN, OUString());
+ *pCounter++ = new SfxInt32Item(DSID_CONN_LDAP_PORTNUMBER, 389);
+ *pCounter++ = new SfxInt32Item(DSID_CONN_LDAP_ROWCOUNT, 100);
+ *pCounter++ = new SfxBoolItem(DSID_SQL92CHECK, false);
+ *pCounter++ = new SfxStringItem(DSID_AUTOINCREMENTVALUE, OUString());
+ *pCounter++ = new SfxStringItem(DSID_AUTORETRIEVEVALUE, OUString());
+ *pCounter++ = new SfxBoolItem(DSID_AUTORETRIEVEENABLED, false);
+ *pCounter++ = new SfxBoolItem(DSID_APPEND_TABLE_ALIAS, false);
+ *pCounter++ = new SfxInt32Item(DSID_MYSQL_PORTNUMBER, 3306);
+ *pCounter++ = new SfxBoolItem(DSID_IGNOREDRIVER_PRIV, true);
+ *pCounter++ = new SfxInt32Item(DSID_BOOLEANCOMPARISON, 0);
+ *pCounter++ = new SfxInt32Item(DSID_ORACLE_PORTNUMBER, 1521);
+ *pCounter++ = new SfxBoolItem(DSID_ENABLEOUTERJOIN, true);
+ *pCounter++ = new SfxBoolItem(DSID_CATALOG, true);
+ *pCounter++ = new SfxBoolItem(DSID_SCHEMA, true);
+ *pCounter++ = new SfxBoolItem(DSID_INDEXAPPENDIX, true);
+ *pCounter++ = new SfxBoolItem(DSID_CONN_LDAP_USESSL, false);
+ *pCounter++ = new SfxStringItem(DSID_DOCUMENT_URL, OUString());
+ *pCounter++ = new SfxBoolItem(DSID_DOSLINEENDS, false);
+ *pCounter++ = new SfxStringItem(DSID_DATABASENAME, OUString());
+ *pCounter++ = new SfxBoolItem(DSID_AS_BEFORE_CORRNAME, false);
+ *pCounter++ = new SfxBoolItem(DSID_CHECK_REQUIRED_FIELDS, true);
+ *pCounter++ = new SfxBoolItem(DSID_IGNORECURRENCY, false);
+ *pCounter++ = new SfxStringItem(DSID_CONN_SOCKET, OUString());
+ *pCounter++ = new SfxBoolItem(DSID_ESCAPE_DATETIME, true);
+ *pCounter++ = new SfxStringItem(DSID_NAMED_PIPE, OUString());
+ *pCounter++ = new OptionalBoolItem( DSID_PRIMARY_KEY_SUPPORT );
+ *pCounter++ = new SfxInt32Item(DSID_MAX_ROW_SCAN, 100);
+ *pCounter++ = new SfxBoolItem( DSID_RESPECTRESULTSETTYPE,false );
+
+ // create the pool
+ static SfxItemInfo const aItemInfos[DSID_LAST_ITEM_ID - DSID_FIRST_ITEM_ID + 1] =
+ {
+ {0,false},
+ {0,false},
+ {0,false},
+ {0,false},
+ {0,false},
+ {0,false},
+ {0,false},
+ {0,false},
+ {0,false},
+ {0,false},
+ {0,false},
+ {0,false},
+ {0,false},
+ {0,false},
+ {0,false},
+ {0,false},
+ {0,false},
+ {0,false},
+ {0,false},
+ {0,false},
+ {0,false},
+ {0,false},
+ {0,false},
+ {0,false},
+ {0,false},
+ {0,false},
+ {0,false},
+ {0,false},
+ {0,false},
+ {0,false},
+ {0,false},
+ {0,false},
+ {0,false},
+ {0,false},
+ {0,false},
+ {0,false},
+ {0,false},
+ {0,false},
+ {0,false},
+ {0,false},
+ {0,false},
+ {0,false},
+ {0,false},
+ {0,false},
+ {0,false},
+ {0,false},
+ {0,false},
+ {0,false},
+ {0,false},
+ {0,false},
+ {0,false},
+ {0,false},
+ {0,false},
+ {0,false},
+ {0,false},
+ {0,false},
+ {0,false},
+ {0,false},
+ {0,false},
+ {0,false},
+ };
+
+ OSL_ENSURE(SAL_N_ELEMENTS(aItemInfos) == DSID_LAST_ITEM_ID,"Invalid Ids!");
+ _rpPool = new SfxItemPool("DSAItemPool", DSID_FIRST_ITEM_ID, DSID_LAST_ITEM_ID,
+ aItemInfos, _rpDefaults);
+ _rpPool->FreezeIdRanges();
+
+ // and, finally, the set
+ _rpSet.reset(new SfxItemSet(*_rpPool));
+}
+
+void ODbAdminDialog::destroyItemSet(std::unique_ptr<SfxItemSet>& _rpSet, rtl::Reference<SfxItemPool>& _rpPool, std::vector<SfxPoolItem*>*& _rpDefaults)
+{
+ // _first_ delete the set (referring the pool)
+ _rpSet.reset();
+
+ // delete the pool
+ if (_rpPool)
+ {
+ _rpPool->ReleaseDefaults(true);
+ // the "true" means delete the items, too
+ _rpPool = nullptr;
+ }
+
+ // reset the defaults ptr
+ _rpDefaults = nullptr;
+ // no need to explicitly delete the defaults, this has been done by the ReleaseDefaults
+}
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/dlg/dbfindex.cxx b/dbaccess/source/ui/dlg/dbfindex.cxx
new file mode 100644
index 000000000..89f74ab72
--- /dev/null
+++ b/dbaccess/source/ui/dlg/dbfindex.cxx
@@ -0,0 +1,430 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "dbfindex.hxx"
+#include <comphelper/processfactory.hxx>
+#include <osl/file.hxx>
+#include <osl/thread.hxx>
+#include <tools/config.hxx>
+#include <osl/diagnose.h>
+#include <unotools/localfilehelper.hxx>
+#include <tools/urlobj.hxx>
+#include <unotools/pathoptions.hxx>
+#include <ucbhelper/content.hxx>
+#include <svl/filenotation.hxx>
+#include <rtl/strbuf.hxx>
+
+namespace dbaui
+{
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::ucb;
+using namespace ::svt;
+
+constexpr OStringLiteral aGroupIdent("dBase III");
+
+
+ODbaseIndexDialog::ODbaseIndexDialog(weld::Window * pParent, const OUString& aDataSrcName)
+ : GenericDialogController(pParent, "dbaccess/ui/dbaseindexdialog.ui", "DBaseIndexDialog")
+ , m_aDSN(aDataSrcName)
+ , m_xPB_OK(m_xBuilder->weld_button("ok"))
+ , m_xCB_Tables(m_xBuilder->weld_combo_box("table"))
+ , m_xIndexes(m_xBuilder->weld_widget("frame"))
+ , m_xLB_TableIndexes(m_xBuilder->weld_tree_view("tableindex"))
+ , m_xLB_FreeIndexes(m_xBuilder->weld_tree_view("freeindex"))
+ , m_xAdd(m_xBuilder->weld_button("add"))
+ , m_xRemove(m_xBuilder->weld_button("remove"))
+ , m_xAddAll(m_xBuilder->weld_button("addall"))
+ , m_xRemoveAll(m_xBuilder->weld_button("removeall"))
+{
+ int nWidth = m_xLB_TableIndexes->get_approximate_digit_width() * 18;
+ int nHeight = m_xLB_TableIndexes->get_height_rows(10);
+ m_xLB_TableIndexes->set_size_request(nWidth, nHeight);
+ m_xLB_FreeIndexes->set_size_request(nWidth, nHeight);
+
+ m_xCB_Tables->connect_changed( LINK(this, ODbaseIndexDialog, TableSelectHdl) );
+ m_xAdd->connect_clicked( LINK(this, ODbaseIndexDialog, AddClickHdl) );
+ m_xRemove->connect_clicked( LINK(this, ODbaseIndexDialog, RemoveClickHdl) );
+ m_xAddAll->connect_clicked( LINK(this, ODbaseIndexDialog, AddAllClickHdl) );
+ m_xRemoveAll->connect_clicked( LINK(this, ODbaseIndexDialog, RemoveAllClickHdl) );
+ m_xPB_OK->connect_clicked( LINK(this, ODbaseIndexDialog, OKClickHdl) );
+
+ m_xLB_FreeIndexes->connect_changed( LINK(this, ODbaseIndexDialog, OnListEntrySelected) );
+ m_xLB_TableIndexes->connect_changed( LINK(this, ODbaseIndexDialog, OnListEntrySelected) );
+
+ Init();
+ SetCtrls();
+}
+
+ODbaseIndexDialog::~ODbaseIndexDialog()
+{
+}
+
+void ODbaseIndexDialog::checkButtons()
+{
+ m_xAdd->set_sensitive(0 != m_xLB_FreeIndexes->count_selected_rows());
+ m_xAddAll->set_sensitive(0 != m_xLB_FreeIndexes->n_children());
+
+ m_xRemove->set_sensitive(0 != m_xLB_TableIndexes->count_selected_rows());
+ m_xRemoveAll->set_sensitive(0 != m_xLB_TableIndexes->n_children());
+}
+
+OTableIndex ODbaseIndexDialog::implRemoveIndex(const OUString& _rName, TableIndexList& _rList, weld::TreeView& _rDisplay, bool _bMustExist)
+{
+ OTableIndex aReturn;
+
+ TableIndexList::iterator aSearch = std::find_if(_rList.begin(), _rList.end(),
+ [&_rName](const OTableIndex& rIndex) { return rIndex.GetIndexFileName() == _rName; });
+ if (aSearch != _rList.end())
+ {
+ sal_Int32 nPos = static_cast<sal_Int32>(std::distance(_rList.begin(), aSearch));
+
+ aReturn = *aSearch;
+
+ _rList.erase(aSearch);
+ _rDisplay.remove_text(_rName);
+
+ // adjust selection if necessary
+ if (static_cast<sal_uInt32>(nPos) == _rList.size())
+ _rDisplay.select(static_cast<sal_uInt16>(nPos)-1);
+ else
+ _rDisplay.select(static_cast<sal_uInt16>(nPos));
+ }
+ OSL_ENSURE(!_bMustExist || !aReturn.GetIndexFileName().isEmpty(), "ODbaseIndexDialog::implRemoveIndex : did not find the index!");
+ return aReturn;
+}
+
+void ODbaseIndexDialog::implInsertIndex(const OTableIndex& _rIndex, TableIndexList& _rList, weld::TreeView& _rDisplay)
+{
+ _rList.push_front(_rIndex);
+ _rDisplay.append_text(_rIndex.GetIndexFileName());
+ _rDisplay.select(0);
+}
+
+OTableIndex ODbaseIndexDialog::RemoveTableIndex( std::u16string_view _rTableName, const OUString& _rIndexName )
+{
+ OTableIndex aReturn;
+
+ // does the table exist ?
+ TableInfoList::iterator aTablePos = std::find_if(m_aTableInfoList.begin(), m_aTableInfoList.end(),
+ [&] (const OTableInfo& arg) { return arg.aTableName == _rTableName; });
+
+ if (aTablePos == m_aTableInfoList.end())
+ return aReturn;
+
+ return implRemoveIndex(_rIndexName, aTablePos->aIndexList, *m_xLB_TableIndexes, true/*_bMustExist*/);
+}
+
+void ODbaseIndexDialog::InsertTableIndex( std::u16string_view _rTableName, const OTableIndex& _rIndex)
+{
+ TableInfoList::iterator aTablePos = std::find_if(m_aTableInfoList.begin(), m_aTableInfoList.end(),
+ [&] (const OTableInfo& arg) { return arg.aTableName == _rTableName; });
+
+ if (aTablePos == m_aTableInfoList.end())
+ return;
+
+ implInsertIndex(_rIndex, aTablePos->aIndexList, *m_xLB_TableIndexes);
+}
+
+IMPL_LINK_NOARG(ODbaseIndexDialog, OKClickHdl, weld::Button&, void)
+{
+ // let all tables write their INF file
+
+ for (auto const& tableInfo : m_aTableInfoList)
+ tableInfo.WriteInfFile(m_aDSN);
+
+ m_xDialog->response(RET_OK);
+}
+
+IMPL_LINK_NOARG(ODbaseIndexDialog, AddClickHdl, weld::Button&, void)
+{
+ OUString aSelection = m_xLB_FreeIndexes->get_selected_text();
+ OUString aTableName = m_xCB_Tables->get_active_text();
+ OTableIndex aIndex = RemoveFreeIndex( aSelection, true );
+ InsertTableIndex( aTableName, aIndex );
+
+ checkButtons();
+}
+
+IMPL_LINK_NOARG(ODbaseIndexDialog, RemoveClickHdl, weld::Button&, void)
+{
+ OUString aSelection = m_xLB_TableIndexes->get_selected_text();
+ OUString aTableName = m_xCB_Tables->get_active_text();
+ OTableIndex aIndex = RemoveTableIndex( aTableName, aSelection );
+ InsertFreeIndex( aIndex );
+
+ checkButtons();
+}
+
+IMPL_LINK_NOARG(ODbaseIndexDialog, AddAllClickHdl, weld::Button&, void)
+{
+ const sal_Int32 nCnt = m_xLB_FreeIndexes->n_children();
+ OUString aTableName = m_xCB_Tables->get_active_text();
+
+ for (sal_Int32 nPos = 0; nPos < nCnt; ++nPos)
+ InsertTableIndex(aTableName, RemoveFreeIndex(m_xLB_FreeIndexes->get_text(0), true));
+
+ checkButtons();
+}
+
+IMPL_LINK_NOARG(ODbaseIndexDialog, RemoveAllClickHdl, weld::Button&, void)
+{
+ const sal_Int32 nCnt = m_xLB_TableIndexes->n_children();
+ OUString aTableName = m_xCB_Tables->get_active_text();
+
+ for (sal_Int32 nPos = 0; nPos < nCnt; ++nPos)
+ InsertFreeIndex(RemoveTableIndex(aTableName, m_xLB_TableIndexes->get_text(0)));
+
+ checkButtons();
+}
+
+IMPL_LINK_NOARG(ODbaseIndexDialog, OnListEntrySelected, weld::TreeView&, void)
+{
+ checkButtons();
+}
+
+IMPL_LINK(ODbaseIndexDialog, TableSelectHdl, weld::ComboBox&, rComboBox, void)
+{
+ // search the table
+ TableInfoList::iterator aTablePos = std::find_if(m_aTableInfoList.begin(), m_aTableInfoList.end(),
+ [&] (const OTableInfo& arg) { return arg.aTableName == rComboBox.get_active_text() ; });
+
+ if (aTablePos == m_aTableInfoList.end())
+ return;
+
+ // fill the listbox for the indexes
+ m_xLB_TableIndexes->clear();
+ for (auto const& index : aTablePos->aIndexList)
+ m_xLB_TableIndexes->append_text(index.GetIndexFileName());
+
+ if (!aTablePos->aIndexList.empty())
+ m_xLB_TableIndexes->select(0);
+
+ checkButtons();
+}
+
+void ODbaseIndexDialog::Init()
+{
+ m_xPB_OK->set_sensitive(false);
+ m_xIndexes->set_sensitive(false);
+
+ // All indices are first added to a list of free indices.
+ // Afterwards, check the index of each table in the Inf-file.
+ // These indices are removed from the list of free indices and
+ // entered in the indexlist of the table.
+
+ // if the string does not contain a path, cut the string
+ INetURLObject aURL;
+ aURL.SetSmartProtocol(INetProtocol::File);
+ {
+ SvtPathOptions aPathOptions;
+ m_aDSN = aPathOptions.SubstituteVariable(m_aDSN);
+ }
+ aURL.SetSmartURL(m_aDSN);
+
+ // String aFileName = aURL.PathToFileName();
+ m_aDSN = aURL.GetMainURL(INetURLObject::DecodeMechanism::NONE);
+ ::ucbhelper::Content aFile;
+ bool bFolder=true;
+ try
+ {
+ aFile = ::ucbhelper::Content(m_aDSN,Reference< css::ucb::XCommandEnvironment >(), comphelper::getProcessComponentContext());
+ bFolder = aFile.isFolder();
+ }
+ catch(Exception&)
+ {
+ return;
+ }
+
+ // first assume for all indexes they're free
+
+ OUString const aIndexExt("ndx");
+ OUString const aTableExt("dbf");
+
+ std::vector< OUString > aUsedIndexes;
+
+ aURL.SetSmartProtocol(INetProtocol::File);
+ const Sequence<OUString> aFolderUrls = ::utl::LocalFileHelper::GetFolderContents(m_aDSN, bFolder);
+ for(const OUString& rURL : aFolderUrls)
+ {
+ OUString aName;
+ osl::FileBase::getSystemPathFromFileURL(rURL,aName);
+ aURL.SetSmartURL(aName);
+ OUString aExt = aURL.getExtension();
+ if (aExt == aIndexExt)
+ {
+ m_aFreeIndexList.emplace_back(aURL.getName() );
+ }
+ else if (aExt == aTableExt)
+ {
+ m_aTableInfoList.emplace_back(aURL.getName() );
+ OTableInfo& rTabInfo = m_aTableInfoList.back();
+
+ // open the INF file
+ aURL.setExtension(u"inf");
+ OFileNotation aTransformer(aURL.GetURLNoPass(), OFileNotation::N_URL);
+ Config aInfFile( aTransformer.get(OFileNotation::N_SYSTEM) );
+ aInfFile.SetGroup( aGroupIdent );
+
+ // fill the indexes list
+ OString aNDX;
+ sal_uInt16 nKeyCnt = aInfFile.GetKeyCount();
+ OString aKeyName;
+ OUString aEntry;
+
+ for( sal_uInt16 nKey = 0; nKey < nKeyCnt; nKey++ )
+ {
+ // does the key point to an index file ?
+ aKeyName = aInfFile.GetKeyName( nKey );
+ aNDX = aKeyName.copy(0,3);
+
+ // yes -> add to the tables index list
+ if (aNDX == "NDX")
+ {
+ aEntry = OStringToOUString(aInfFile.ReadKey(aKeyName), osl_getThreadTextEncoding());
+ rTabInfo.aIndexList.emplace_back( aEntry );
+
+ // and remove it from the free index list
+ aUsedIndexes.push_back(aEntry);
+ // do this later below. We may not have encountered the index file, yet, thus we may not
+ // know the index as being free, yet
+ }
+ }
+ }
+ }
+
+ for (auto const& usedIndex : aUsedIndexes)
+ RemoveFreeIndex( usedIndex, false );
+
+ if (!m_aTableInfoList.empty())
+ {
+ m_xPB_OK->set_sensitive(true);
+ m_xIndexes->set_sensitive(true);
+ }
+
+ checkButtons();
+}
+
+void ODbaseIndexDialog::SetCtrls()
+{
+ // ComboBox tables
+ for (auto const& tableInfo : m_aTableInfoList)
+ m_xCB_Tables->append_text(tableInfo.aTableName);
+
+ // put the first dataset into Edit
+ if (!m_aTableInfoList.empty())
+ {
+ const OTableInfo& rTabInfo = m_aTableInfoList.front();
+ m_xCB_Tables->set_entry_text(rTabInfo.aTableName);
+
+ // build ListBox of the table indices
+ for (auto const& index : rTabInfo.aIndexList)
+ m_xLB_TableIndexes->append_text(index.GetIndexFileName());
+
+ if (!rTabInfo.aIndexList.empty())
+ m_xLB_TableIndexes->select(0);
+ }
+
+ // ListBox of the free indices
+ for (auto const& freeIndex : m_aFreeIndexList)
+ m_xLB_FreeIndexes->append_text(freeIndex.GetIndexFileName());
+
+ if (!m_aFreeIndexList.empty())
+ m_xLB_FreeIndexes->select(0);
+
+ TableSelectHdl(*m_xCB_Tables);
+ checkButtons();
+}
+
+void OTableInfo::WriteInfFile( const OUString& rDSN ) const
+{
+ // open INF file
+ INetURLObject aURL;
+ aURL.SetSmartProtocol(INetProtocol::File);
+ OUString aDsn = rDSN;
+ {
+ SvtPathOptions aPathOptions;
+ aDsn = aPathOptions.SubstituteVariable(aDsn);
+ }
+ aURL.SetSmartURL(aDsn);
+ aURL.Append(aTableName);
+ aURL.setExtension(u"inf");
+
+ OFileNotation aTransformer(aURL.GetURLNoPass(), OFileNotation::N_URL);
+ Config aInfFile( aTransformer.get(OFileNotation::N_SYSTEM) );
+ aInfFile.SetGroup( aGroupIdent );
+
+ // first, delete all table indices
+ OString aNDX;
+ sal_uInt16 nKeyCnt = aInfFile.GetKeyCount();
+ sal_uInt16 nKey = 0;
+
+ while( nKey < nKeyCnt )
+ {
+ // Does the key point to an index file?...
+ OString aKeyName = aInfFile.GetKeyName( nKey );
+ aNDX = aKeyName.copy(0,3);
+
+ //...if yes, delete index file, nKey is at subsequent key
+ if (aNDX == "NDX")
+ {
+ aInfFile.DeleteKey(aKeyName);
+ nKeyCnt--;
+ }
+ else
+ nKey++;
+
+ }
+
+ // now add all saved indices
+ sal_uInt16 nPos = 0;
+ for (auto const& index : aIndexList)
+ {
+ OStringBuffer aKeyName("NDX");
+ if( nPos > 0 ) // first index contains no number
+ aKeyName.append(static_cast<sal_Int32>(nPos));
+ aInfFile.WriteKey(
+ aKeyName.makeStringAndClear(),
+ OUStringToOString(index.GetIndexFileName(),
+ osl_getThreadTextEncoding()));
+ ++nPos;
+ }
+
+ aInfFile.Flush();
+
+ // if only [dbase] is left in INF-file, delete file
+ if(nPos)
+ return;
+
+ try
+ {
+ ::ucbhelper::Content aContent(aURL.GetURLNoPass(),Reference<XCommandEnvironment>(), comphelper::getProcessComponentContext());
+ aContent.executeCommand( "delete", Any( true ) );
+ }
+ catch (const Exception& )
+ {
+ // simply silent this. The strange algorithm here does a lot of
+ // things even if no files at all were created or accessed, so it's
+ // possible that the file we're trying to delete does not even
+ // exist, and this is a valid condition.
+ }
+}
+
+} // namespace
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/dlg/dbfindex.hxx b/dbaccess/source/ui/dlg/dbfindex.hxx
new file mode 100644
index 000000000..53b75640e
--- /dev/null
+++ b/dbaccess/source/ui/dlg/dbfindex.hxx
@@ -0,0 +1,110 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <vcl/weld.hxx>
+#include <deque>
+
+namespace dbaui
+{
+
+// OTableIndex
+/// represents a single dbf index
+class OTableIndex
+{
+private:
+ OUString aIndexFileName;
+
+public:
+ OTableIndex() { }
+ explicit OTableIndex( const OUString& rFileName ) : aIndexFileName( rFileName ) { }
+
+ const OUString& GetIndexFileName() const { return aIndexFileName; }
+};
+
+typedef std::deque< OTableIndex > TableIndexList;
+
+// OTableInfo
+class ODbaseIndexDialog;
+/** holds the INF file of a table
+*/
+class OTableInfo
+{
+ friend class ODbaseIndexDialog;
+private:
+ OUString aTableName;
+ TableIndexList aIndexList;
+
+public:
+ explicit OTableInfo( const OUString& rName ) : aTableName(rName) { }
+
+ void WriteInfFile( const OUString& rDSN ) const;
+};
+
+typedef std::deque< OTableInfo > TableInfoList;
+
+// IndexDialog
+class ODbaseIndexDialog : public weld::GenericDialogController
+{
+protected:
+ OUString m_aDSN;
+ TableInfoList m_aTableInfoList;
+ TableIndexList m_aFreeIndexList;
+
+ std::unique_ptr<weld::Button> m_xPB_OK;
+ std::unique_ptr<weld::ComboBox> m_xCB_Tables;
+ std::unique_ptr<weld::Widget> m_xIndexes;
+ std::unique_ptr<weld::TreeView> m_xLB_TableIndexes;
+ std::unique_ptr<weld::TreeView> m_xLB_FreeIndexes;
+
+ std::unique_ptr<weld::Button> m_xAdd;
+ std::unique_ptr<weld::Button> m_xRemove;
+ std::unique_ptr<weld::Button> m_xAddAll;
+ std::unique_ptr<weld::Button> m_xRemoveAll;
+
+ DECL_LINK( TableSelectHdl, weld::ComboBox&, void );
+ DECL_LINK( AddClickHdl, weld::Button&, void );
+ DECL_LINK( RemoveClickHdl, weld::Button&, void );
+ DECL_LINK( AddAllClickHdl, weld::Button&, void );
+ DECL_LINK( RemoveAllClickHdl, weld::Button&, void );
+ DECL_LINK( OKClickHdl, weld::Button&, void );
+ DECL_LINK( OnListEntrySelected, weld::TreeView&, void );
+
+ void Init();
+ void SetCtrls();
+
+ static OTableIndex implRemoveIndex(const OUString& _rName, TableIndexList& _rList, weld::TreeView& _rDisplay, bool _bMustExist);
+ static void implInsertIndex(const OTableIndex& _rIndex, TableIndexList& _rList, weld::TreeView& _rDisplay);
+
+ OTableIndex RemoveFreeIndex( const OUString& _rName, bool _bMustExist ) { return implRemoveIndex(_rName, m_aFreeIndexList, *m_xLB_FreeIndexes, _bMustExist); }
+ void InsertFreeIndex( const OTableIndex& _rIndex ) { implInsertIndex(_rIndex, m_aFreeIndexList, *m_xLB_FreeIndexes); }
+ OTableIndex RemoveTableIndex( std::u16string_view _rTableName, const OUString& _rIndexName );
+ void InsertTableIndex( std::u16string_view _rTableName, const OTableIndex& _rIndex );
+
+ void checkButtons();
+
+public:
+ ODbaseIndexDialog(weld::Window * pParent, const OUString& rDataSrcName);
+ virtual ~ODbaseIndexDialog() override;
+};
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/dlg/dbwiz.cxx b/dbaccess/source/ui/dlg/dbwiz.cxx
new file mode 100644
index 000000000..fa0653502
--- /dev/null
+++ b/dbaccess/source/ui/dlg/dbwiz.cxx
@@ -0,0 +1,336 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <core_resource.hxx>
+#include <dbwiz.hxx>
+#include <strings.hrc>
+#include <strings.hxx>
+#include <dsitems.hxx>
+#include "dsnItem.hxx"
+#include "adminpages.hxx"
+#include "generalpage.hxx"
+#include <unotools/confignode.hxx>
+#include "ConnectionPage.hxx"
+#include "DriverSettings.hxx"
+#include "DbAdminImpl.hxx"
+#include <helpids.h>
+
+namespace dbaui
+{
+using namespace com::sun::star::uno;
+using namespace com::sun::star::sdbc;
+using namespace com::sun::star::lang;
+using namespace com::sun::star::util;
+using namespace com::sun::star::beans;
+using namespace com::sun::star::container;
+
+#define START_PAGE 0
+#define CONNECTION_PAGE 1
+#define ADDITIONAL_PAGE_DBASE 2
+#define ADDITIONAL_PAGE_FLAT 3
+#define ADDITIONAL_PAGE_LDAP 4
+//5 was ADDITIONAL_PAGE_ADABAS
+#define ADDITIONAL_PAGE_MYSQL_JDBC 6
+#define ADDITIONAL_PAGE_MYSQL_ODBC 7
+#define ADDITIONAL_PAGE_ORACLE_JDBC 8
+#define ADDITIONAL_PAGE_ADO 9
+#define ADDITIONAL_PAGE_ODBC 10
+#define ADDITIONAL_USERDEFINED 11
+#define ADDITIONAL_PAGE_MYSQL_NATIVE 12
+
+// ODbTypeWizDialog
+ODbTypeWizDialog::ODbTypeWizDialog(weld::Window* _pParent, SfxItemSet const * _pItems,
+ const Reference< XComponentContext >& _rxORB, const css::uno::Any& _aDataSourceName)
+ : WizardMachine(_pParent, WizardButtonFlags::NEXT | WizardButtonFlags::PREVIOUS | WizardButtonFlags::FINISH | WizardButtonFlags::CANCEL | WizardButtonFlags::HELP )
+{
+ m_pImpl.reset(new ODbDataSourceAdministrationHelper(_rxORB, m_xAssistant.get(), _pParent, this));
+ m_pImpl->setDataSourceOrName(_aDataSourceName);
+ Reference< XPropertySet > xDatasource = m_pImpl->getCurrentDataSource();
+ m_pOutSet.reset(new SfxItemSet( *_pItems->GetPool(), _pItems->GetRanges() ));
+
+ m_pImpl->translateProperties(xDatasource, *m_pOutSet);
+ m_eType = dbaui::ODbDataSourceAdministrationHelper::getDatasourceType(*m_pOutSet);
+
+ defaultButton(WizardButtonFlags::NEXT);
+ enableButtons(WizardButtonFlags::FINISH, false);
+ enableAutomaticNextButtonState();
+
+ m_xPrevPage->set_help_id(HID_DBWIZ_PREVIOUS);
+ m_xNextPage->set_help_id(HID_DBWIZ_NEXT);
+ m_xCancel->set_help_id(HID_DBWIZ_CANCEL);
+ m_xFinish->set_help_id(HID_DBWIZ_FINISH);
+ // no local resources needed anymore
+
+ const DbuTypeCollectionItem* pCollectionItem = dynamic_cast<const DbuTypeCollectionItem*>(_pItems->GetItem(DSID_TYPECOLLECTION));
+ assert(pCollectionItem && "must exist");
+ m_pCollection = pCollectionItem->getCollection();
+
+ ActivatePage();
+ setTitleBase(DBA_RES(STR_DATABASE_TYPE_CHANGE));
+
+ m_xAssistant->set_current_page(0);
+}
+
+ODbTypeWizDialog::~ODbTypeWizDialog()
+{
+}
+
+IMPL_LINK(ODbTypeWizDialog, OnTypeSelected, OGeneralPage&, _rTabPage, void)
+{
+ m_eType = _rTabPage.GetSelectedType();
+ const bool bURLRequired = m_pCollection->isConnectionUrlRequired(m_eType);
+ enableButtons(WizardButtonFlags::NEXT,bURLRequired);
+ enableButtons(WizardButtonFlags::FINISH,!bURLRequired);
+}
+
+WizardState ODbTypeWizDialog::determineNextState( WizardState _nCurrentState ) const
+{
+ WizardState nNextState = WZS_INVALID_STATE;
+ switch(_nCurrentState)
+ {
+ case START_PAGE:
+ switch(m_pCollection->determineType(m_eType))
+ {
+ case ::dbaccess::DST_MOZILLA:
+ case ::dbaccess::DST_OUTLOOK:
+ case ::dbaccess::DST_OUTLOOKEXP:
+ case ::dbaccess::DST_EVOLUTION:
+ case ::dbaccess::DST_EVOLUTION_GROUPWISE:
+ case ::dbaccess::DST_EVOLUTION_LDAP:
+ case ::dbaccess::DST_KAB:
+ case ::dbaccess::DST_MACAB:
+ nNextState = WZS_INVALID_STATE;
+ break;
+ case ::dbaccess::DST_MYSQL_NATIVE:
+ nNextState = ADDITIONAL_PAGE_MYSQL_NATIVE;
+ break;
+ default:
+ nNextState = CONNECTION_PAGE;
+ break;
+ }
+ break;
+ case CONNECTION_PAGE:
+ switch(m_pCollection->determineType(m_eType))
+ {
+ case ::dbaccess::DST_MOZILLA:
+ case ::dbaccess::DST_THUNDERBIRD:
+ case ::dbaccess::DST_OUTLOOK:
+ case ::dbaccess::DST_OUTLOOKEXP:
+ case ::dbaccess::DST_EVOLUTION:
+ case ::dbaccess::DST_EVOLUTION_GROUPWISE:
+ case ::dbaccess::DST_EVOLUTION_LDAP:
+ case ::dbaccess::DST_KAB:
+ case ::dbaccess::DST_MACAB:
+ case ::dbaccess::DST_MSACCESS:
+ case ::dbaccess::DST_MSACCESS_2007:
+ case ::dbaccess::DST_JDBC:
+ case ::dbaccess::DST_CALC:
+ case ::dbaccess::DST_WRITER:
+ nNextState = WZS_INVALID_STATE;
+ break;
+ case ::dbaccess::DST_DBASE:
+ nNextState = ADDITIONAL_PAGE_DBASE;
+ break;
+ case ::dbaccess::DST_FLAT:
+ nNextState = ADDITIONAL_PAGE_FLAT;
+ break;
+ case ::dbaccess::DST_LDAP:
+ nNextState = ADDITIONAL_PAGE_LDAP;
+ break;
+ case ::dbaccess::DST_MYSQL_JDBC:
+ nNextState = ADDITIONAL_PAGE_MYSQL_JDBC;
+ break;
+ case ::dbaccess::DST_MYSQL_ODBC:
+ nNextState = ADDITIONAL_PAGE_MYSQL_ODBC;
+ break;
+ case ::dbaccess::DST_ORACLE_JDBC:
+ nNextState = ADDITIONAL_PAGE_ORACLE_JDBC;
+ break;
+ case ::dbaccess::DST_ADO:
+ nNextState = ADDITIONAL_PAGE_ADO;
+ break;
+ case ::dbaccess::DST_ODBC:
+ nNextState = ADDITIONAL_PAGE_ODBC;
+ break;
+ default:
+ nNextState = WZS_INVALID_STATE;
+ break;
+ }
+ break;
+ }
+
+ return nNextState;
+}
+
+const SfxItemSet* ODbTypeWizDialog::getOutputSet() const
+{
+ return m_pOutSet.get();
+}
+
+SfxItemSet* ODbTypeWizDialog::getWriteOutputSet()
+{
+ return m_pOutSet.get();
+}
+
+std::pair< Reference<XConnection>,bool> ODbTypeWizDialog::createConnection()
+{
+ return m_pImpl->createConnection();
+}
+
+Reference< XComponentContext > ODbTypeWizDialog::getORB() const
+{
+ return m_pImpl->getORB();
+}
+
+Reference< XDriver > ODbTypeWizDialog::getDriver()
+{
+ return m_pImpl->getDriver();
+}
+
+OUString ODbTypeWizDialog::getDatasourceType(const SfxItemSet& _rSet) const
+{
+ return dbaui::ODbDataSourceAdministrationHelper::getDatasourceType(_rSet);
+}
+
+void ODbTypeWizDialog::clearPassword()
+{
+ m_pImpl->clearPassword();
+}
+
+std::unique_ptr<BuilderPage> ODbTypeWizDialog::createPage(WizardState _nState)
+{
+ TranslateId pStringId = STR_PAGETITLE_ADVANCED;
+ std::unique_ptr<BuilderPage> xPage;
+
+ OString sIdent(OString::number(_nState));
+ weld::Container* pPageContainer = m_xAssistant->append_page(sIdent);
+
+ switch(_nState)
+ {
+ case START_PAGE: // start state
+ {
+ xPage = std::make_unique<OGeneralPageDialog>(pPageContainer, this, *m_pOutSet);
+ OGeneralPage* pGeneralPage = static_cast<OGeneralPage*>(xPage.get());
+ pGeneralPage->SetTypeSelectHandler( LINK( this, ODbTypeWizDialog, OnTypeSelected));
+ pStringId = STR_PAGETITLE_GENERAL;
+ }
+ break;
+ case CONNECTION_PAGE:
+ xPage = OConnectionTabPage::Create(pPageContainer, this, m_pOutSet.get());
+ pStringId = STR_PAGETITLE_CONNECTION;
+ break;
+
+ case ADDITIONAL_PAGE_DBASE:
+ xPage = ODriversSettings::CreateDbase(pPageContainer, this, m_pOutSet.get());
+ break;
+ case ADDITIONAL_PAGE_FLAT:
+ xPage = ODriversSettings::CreateText(pPageContainer, this, m_pOutSet.get());
+ break;
+ case ADDITIONAL_PAGE_LDAP:
+ xPage = ODriversSettings::CreateLDAP(pPageContainer, this, m_pOutSet.get());
+ break;
+ case ADDITIONAL_PAGE_MYSQL_JDBC:
+ xPage = ODriversSettings::CreateMySQLJDBC(pPageContainer, this, m_pOutSet.get());
+ break;
+ case ADDITIONAL_PAGE_MYSQL_NATIVE:
+ xPage = ODriversSettings::CreateMySQLNATIVE(pPageContainer, this, m_pOutSet.get());
+ break;
+ case ADDITIONAL_PAGE_MYSQL_ODBC:
+ xPage = ODriversSettings::CreateMySQLODBC(pPageContainer, this, m_pOutSet.get());
+ break;
+ case ADDITIONAL_PAGE_ORACLE_JDBC:
+ xPage = ODriversSettings::CreateOracleJDBC(pPageContainer, this, m_pOutSet.get());
+ break;
+ case ADDITIONAL_PAGE_ADO:
+ xPage = ODriversSettings::CreateAdo(pPageContainer, this, m_pOutSet.get());
+ break;
+ case ADDITIONAL_PAGE_ODBC:
+ xPage = ODriversSettings::CreateODBC(pPageContainer, this, m_pOutSet.get());
+ break;
+ case ADDITIONAL_USERDEFINED:
+ xPage = ODriversSettings::CreateUser(pPageContainer, this, m_pOutSet.get());
+ break;
+ default:
+ OSL_FAIL("Wrong state!");
+ break;
+ }
+
+ // register ourself as modified listener
+ if ( xPage )
+ {
+ static_cast<OGenericAdministrationPage*>(xPage.get())->SetServiceFactory( m_pImpl->getORB() );
+ static_cast<OGenericAdministrationPage*>(xPage.get())->SetAdminDialog(this,this);
+ m_xAssistant->set_page_title(sIdent, DBA_RES(pStringId));
+ defaultButton( _nState == START_PAGE ? WizardButtonFlags::NEXT : WizardButtonFlags::FINISH );
+ enableButtons( WizardButtonFlags::FINISH, _nState != START_PAGE);
+ }
+ return xPage;
+}
+
+bool ODbTypeWizDialog::leaveState(WizardState _nState)
+{
+ SfxTabPage* pPage = static_cast<SfxTabPage*>(WizardMachine::GetPage(_nState));
+ if ( pPage )
+ pPage->FillItemSet(m_pOutSet.get());
+ return true;
+}
+
+void ODbTypeWizDialog::setTitle(const OUString& _sTitle)
+{
+ m_xAssistant->set_title(_sTitle);
+}
+
+void ODbTypeWizDialog::enableConfirmSettings( bool _bEnable )
+{
+ enableButtons( WizardButtonFlags::FINISH, _bEnable );
+ // TODO:
+ // this is hacky. At the moment, this method is used in only one case.
+ // As soon as it is to be used more wide-spread, we should find a proper concept
+ // for enabling both the Next and Finish buttons, depending on the current page state.
+ // Plus, the concept must also care for the case where those pages are embedded into
+ // a normal tab dialog.
+}
+
+void ODbTypeWizDialog::saveDatasource()
+{
+ SfxTabPage* pPage = static_cast<SfxTabPage*>(WizardMachine::GetPage(getCurrentState()));
+ if ( pPage )
+ pPage->FillItemSet(m_pOutSet.get());
+
+ OUString sOldURL;
+ if ( m_pImpl->getCurrentDataSource().is() )
+ m_pImpl->getCurrentDataSource()->getPropertyValue(PROPERTY_URL) >>= sOldURL;
+ DataSourceInfoConverter::convert( getORB(), m_pCollection,sOldURL,m_eType,m_pImpl->getCurrentDataSource());
+}
+
+vcl::IWizardPageController* ODbTypeWizDialog::getPageController(BuilderPage* pCurrentPage) const
+{
+ OGenericAdministrationPage* pPage = static_cast<OGenericAdministrationPage*>(pCurrentPage);
+ return pPage;
+}
+
+bool ODbTypeWizDialog::onFinish()
+{
+ saveDatasource();
+ return m_pImpl->saveChanges(*m_pOutSet) && WizardMachine::onFinish();
+}
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/dlg/dbwizsetup.cxx b/dbaccess/source/ui/dlg/dbwizsetup.cxx
new file mode 100644
index 000000000..f687740dd
--- /dev/null
+++ b/dbaccess/source/ui/dlg/dbwizsetup.cxx
@@ -0,0 +1,994 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <core_resource.hxx>
+#include <dbwizsetup.hxx>
+#include <dsmeta.hxx>
+#include "DBSetupConnectionPages.hxx"
+#include <strings.hrc>
+#include <strings.hxx>
+#include <dsitems.hxx>
+#include "dsnItem.hxx"
+
+#include <unotools/pathoptions.hxx>
+#include <svl/stritem.hxx>
+#include "adminpages.hxx"
+#include <sfx2/docfilt.hxx>
+#include <unotools/ucbhelper.hxx>
+#include "generalpage.hxx"
+#include <unotools/confignode.hxx>
+#include "DbAdminImpl.hxx"
+#include <helpids.h>
+#include "ConnectionPageSetup.hxx"
+#include <UITools.hxx>
+#include <dbaccess/AsynchronousLink.hxx>
+#include <sfx2/filedlghelper.hxx>
+#include <cppuhelper/exc_hlp.hxx>
+#include <cppuhelper/implbase.hxx>
+#include <com/sun/star/frame/TerminationVetoException.hpp>
+#include <com/sun/star/frame/XStorable.hpp>
+#include <com/sun/star/sdb/DatabaseContext.hpp>
+#include <com/sun/star/frame/Desktop.hpp>
+#include <com/sun/star/frame/FrameSearchFlag.hpp>
+#include <com/sun/star/frame/XComponentLoader.hpp>
+#include <com/sun/star/frame/XModel.hpp>
+#include <com/sun/star/ucb/SimpleFileAccess.hpp>
+#include <com/sun/star/ucb/InteractiveIOException.hpp>
+#include <com/sun/star/io/IOException.hpp>
+#include <com/sun/star/frame/XTerminateListener.hpp>
+#include <com/sun/star/document/MacroExecMode.hpp>
+#include <com/sun/star/ucb/IOErrorCode.hpp>
+#include <com/sun/star/task/InteractionHandler.hpp>
+#include <com/sun/star/task/XInteractionHandler2.hpp>
+#include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
+
+#include <comphelper/interaction.hxx>
+#include <comphelper/namedvaluecollection.hxx>
+#include <tools/diagnose_ex.h>
+#include <osl/diagnose.h>
+#include <connectivity/DriversConfig.hxx>
+
+namespace dbaui
+{
+using namespace dbtools;
+using namespace vcl;
+using namespace com::sun::star;
+using namespace com::sun::star::uno;
+using namespace com::sun::star::sdbc;
+using namespace com::sun::star::sdbcx;
+using namespace com::sun::star::task;
+using namespace com::sun::star::lang;
+using namespace com::sun::star::io;
+using namespace com::sun::star::util;
+using namespace com::sun::star::beans;
+using namespace com::sun::star::container;
+using namespace com::sun::star::frame;
+using namespace com::sun::star::ucb;
+using namespace ::com::sun::star::sdb;
+using namespace ::com::sun::star::document;
+using namespace ::comphelper;
+using namespace ::cppu;
+
+using vcl::RoadmapWizardTypes::WizardPath;
+
+// ODbTypeWizDialogSetup
+ODbTypeWizDialogSetup::ODbTypeWizDialogSetup(weld::Window* _pParent
+ ,SfxItemSet const * _pItems
+ ,const Reference< XComponentContext >& _rxORB
+ ,const css::uno::Any& _aDataSourceName
+ )
+ : vcl::RoadmapWizardMachine( _pParent )
+
+ , m_bIsConnectable( false)
+ , m_sRM_IntroText( DBA_RES( STR_PAGETITLE_INTROPAGE ) )
+ , m_sRM_dBaseText( DBA_RES( STR_PAGETITLE_DBASE ) )
+ , m_sRM_TextText( DBA_RES( STR_PAGETITLE_TEXT ) )
+ , m_sRM_MSAccessText( DBA_RES( STR_PAGETITLE_MSACCESS ) )
+ , m_sRM_LDAPText( DBA_RES( STR_PAGETITLE_LDAP ) )
+ , m_sRM_ADOText( DBA_RES( STR_PAGETITLE_ADO ) )
+ , m_sRM_JDBCText( DBA_RES( STR_PAGETITLE_JDBC ) )
+ , m_sRM_MySQLNativePageTitle( DBA_RES( STR_PAGETITLE_MYSQL_NATIVE ) )
+ , m_sRM_OracleText( DBA_RES( STR_PAGETITLE_ORACLE ) )
+ , m_sRM_MySQLText( DBA_RES( STR_PAGETITLE_MYSQL ) )
+ , m_sRM_ODBCText( DBA_RES( STR_PAGETITLE_ODBC ) )
+ , m_sRM_DocumentOrSpreadSheetText( DBA_RES( STR_PAGETITLE_DOCUMENT_OR_SPREADSHEET ) )
+ , m_sRM_AuthentificationText( DBA_RES( STR_PAGETITLE_AUTHENTIFICATION ) )
+ , m_sRM_FinalText( DBA_RES( STR_PAGETITLE_FINAL ) )
+ , m_sWorkPath( SvtPathOptions().GetWorkPath() )
+ , m_pGeneralPage( nullptr )
+ , m_pMySQLIntroPage( nullptr )
+ , m_pFinalPage( nullptr )
+{
+ // no local resources needed anymore
+ // extract the datasource type collection from the item set
+ const DbuTypeCollectionItem* pCollectionItem = dynamic_cast<const DbuTypeCollectionItem*>(_pItems->GetItem(DSID_TYPECOLLECTION));
+ assert(pCollectionItem && "must exist");
+ m_pCollection = pCollectionItem->getCollection();
+
+ assert(m_pCollection && "ODbTypeWizDialogSetup::ODbTypeWizDialogSetup : really need a DSN type collection !");
+
+ m_pImpl.reset(new ODbDataSourceAdministrationHelper(_rxORB, m_xAssistant.get(), _pParent, this));
+ m_pImpl->setDataSourceOrName(_aDataSourceName);
+ Reference< XPropertySet > xDatasource = m_pImpl->getCurrentDataSource();
+ m_pOutSet.reset( new SfxItemSet( *_pItems->GetPool(), _pItems->GetRanges() ) );
+
+ m_pImpl->translateProperties(xDatasource, *m_pOutSet);
+
+ defaultButton(WizardButtonFlags::NEXT);
+ enableButtons(WizardButtonFlags::FINISH, true);
+ enableAutomaticNextButtonState();
+
+ ::dbaccess::ODsnTypeCollection::TypeIterator aIter = m_pCollection->begin();
+ ::dbaccess::ODsnTypeCollection::TypeIterator aEnd = m_pCollection->end();
+ for(PathId i = 1;aIter != aEnd;++aIter,++i)
+ {
+ const OUString& sURLPrefix = aIter.getURLPrefix();
+ WizardPath aPath;
+ aPath.push_back(PAGE_DBSETUPWIZARD_INTRO);
+ m_pCollection->fillPageIds(sURLPrefix,aPath);
+ aPath.push_back(PAGE_DBSETUPWIZARD_AUTHENTIFICATION);
+ aPath.push_back(PAGE_DBSETUPWIZARD_FINAL);
+
+ declareAuthDepPath(sURLPrefix,i,aPath);
+ }
+
+ WizardPath aPath;
+ aPath.push_back(PAGE_DBSETUPWIZARD_INTRO);
+ declarePath( static_cast<PathId>(m_pCollection->size()+1), aPath);
+
+ m_xPrevPage->set_help_id(HID_DBWIZ_PREVIOUS);
+ m_xNextPage->set_help_id(HID_DBWIZ_NEXT);
+ m_xCancel->set_help_id(HID_DBWIZ_CANCEL);
+ m_xFinish->set_help_id(HID_DBWIZ_FINISH);
+ ActivatePage();
+ setTitleBase(DBA_RES(STR_DBWIZARDTITLE));
+ m_xAssistant->set_current_page(0);
+}
+
+void ODbTypeWizDialogSetup::declareAuthDepPath( const OUString& _sURL, PathId _nPathId, const WizardPath& _rPaths)
+{
+ bool bHasAuthentication = DataSourceMetaData::getAuthentication( _sURL ) != AuthNone;
+
+ // collect the elements of the path
+ WizardPath aPath;
+
+ for (auto const& path : _rPaths)
+ {
+ if ( bHasAuthentication || ( path != PAGE_DBSETUPWIZARD_AUTHENTIFICATION ) )
+ aPath.push_back(path);
+ }
+
+ // call base method
+ ::vcl::RoadmapWizardMachine::declarePath( _nPathId, aPath );
+}
+
+OUString ODbTypeWizDialogSetup::getStateDisplayName(WizardState _nState) const
+{
+ OUString sRoadmapItem;
+ switch( _nState )
+ {
+ case PAGE_DBSETUPWIZARD_INTRO:
+ sRoadmapItem = m_sRM_IntroText;
+ break;
+
+ case PAGE_DBSETUPWIZARD_DBASE:
+ sRoadmapItem = m_sRM_dBaseText;
+ break;
+ case PAGE_DBSETUPWIZARD_ADO:
+ sRoadmapItem = m_sRM_ADOText;
+ break;
+ case PAGE_DBSETUPWIZARD_TEXT:
+ sRoadmapItem = m_sRM_TextText;
+ break;
+ case PAGE_DBSETUPWIZARD_MSACCESS:
+ sRoadmapItem = m_sRM_MSAccessText;
+ break;
+ case PAGE_DBSETUPWIZARD_LDAP:
+ sRoadmapItem = m_sRM_LDAPText;
+ break;
+ case PAGE_DBSETUPWIZARD_JDBC:
+ sRoadmapItem = m_sRM_JDBCText;
+ break;
+ case PAGE_DBSETUPWIZARD_ORACLE:
+ sRoadmapItem = m_sRM_OracleText;
+ break;
+ case PAGE_DBSETUPWIZARD_MYSQL_INTRO:
+ sRoadmapItem = m_sRM_MySQLText;
+ break;
+ case PAGE_DBSETUPWIZARD_MYSQL_JDBC:
+ sRoadmapItem = m_sRM_JDBCText;
+ break;
+ case PAGE_DBSETUPWIZARD_MYSQL_NATIVE:
+ sRoadmapItem = m_sRM_MySQLNativePageTitle;
+ break;
+ case PAGE_DBSETUPWIZARD_MYSQL_ODBC:
+ sRoadmapItem = m_sRM_ODBCText;
+ break;
+ case PAGE_DBSETUPWIZARD_ODBC:
+ sRoadmapItem = m_sRM_ODBCText;
+ break;
+ case PAGE_DBSETUPWIZARD_DOCUMENT_OR_SPREADSHEET:
+ sRoadmapItem = m_sRM_DocumentOrSpreadSheetText;
+ break;
+ case PAGE_DBSETUPWIZARD_AUTHENTIFICATION:
+ sRoadmapItem = m_sRM_AuthentificationText;
+ break;
+ case PAGE_DBSETUPWIZARD_USERDEFINED:
+ sRoadmapItem = DBA_RES(STR_PAGETITLE_CONNECTION);
+ break;
+ case PAGE_DBSETUPWIZARD_FINAL:
+ sRoadmapItem = m_sRM_FinalText;
+ break;
+ default:
+ break;
+ }
+ return sRoadmapItem;
+}
+
+ODbTypeWizDialogSetup::~ODbTypeWizDialogSetup()
+{
+}
+
+IMPL_LINK_NOARG(ODbTypeWizDialogSetup, OnTypeSelected, OGeneralPage&, void)
+{
+ activateDatabasePath();
+}
+
+static void lcl_removeUnused(const ::comphelper::NamedValueCollection& _aOld,const ::comphelper::NamedValueCollection& _aNew,::comphelper::NamedValueCollection& _rDSInfo)
+{
+ _rDSInfo.merge(_aNew,true);
+ uno::Sequence< beans::NamedValue > aOldValues = _aOld.getNamedValues();
+ const beans::NamedValue* pIter = aOldValues.getConstArray();
+ const beans::NamedValue* pEnd = pIter + aOldValues.getLength();
+ for(;pIter != pEnd;++pIter)
+ {
+ if ( !_aNew.has(pIter->Name) )
+ {
+ _rDSInfo.remove(pIter->Name);
+ }
+ }
+}
+
+void DataSourceInfoConverter::convert(const Reference<XComponentContext> & xContext, const ::dbaccess::ODsnTypeCollection* _pCollection,const OUString& _sOldURLPrefix,const OUString& _sNewURLPrefix,const css::uno::Reference< css::beans::XPropertySet >& _xDatasource)
+{
+ if ( _pCollection->getPrefix(_sOldURLPrefix) == _pCollection->getPrefix(_sNewURLPrefix) )
+ return ;
+ uno::Sequence< beans::PropertyValue> aInfo;
+ _xDatasource->getPropertyValue(PROPERTY_INFO) >>= aInfo;
+ ::comphelper::NamedValueCollection aDS(aInfo);
+
+ ::connectivity::DriversConfig aDriverConfig(xContext);
+
+ const ::comphelper::NamedValueCollection& aOldProperties = aDriverConfig.getProperties(_sOldURLPrefix);
+ const ::comphelper::NamedValueCollection& aNewProperties = aDriverConfig.getProperties(_sNewURLPrefix);
+ lcl_removeUnused(aOldProperties,aNewProperties,aDS);
+
+ aDS >>= aInfo;
+ _xDatasource->setPropertyValue(PROPERTY_INFO,uno::Any(aInfo));
+}
+
+void ODbTypeWizDialogSetup::activateDatabasePath()
+{
+ switch ( m_pGeneralPage->GetDatabaseCreationMode() )
+ {
+ case OGeneralPageWizard::eCreateNew:
+ {
+ sal_Int32 nCreateNewDBIndex = m_pCollection->getIndexOf( m_pGeneralPage->GetSelectedType() );
+ if ( nCreateNewDBIndex == -1 )
+ nCreateNewDBIndex = m_pCollection->getIndexOf( u"sdbc:dbase:" );
+ OSL_ENSURE( nCreateNewDBIndex != -1, "ODbTypeWizDialogSetup::activateDatabasePath: the GeneralPage should have prevented this!" );
+ activatePath( static_cast< PathId >( nCreateNewDBIndex + 1 ), true );
+
+ enableState(PAGE_DBSETUPWIZARD_FINAL );
+ enableButtons( WizardButtonFlags::FINISH, true);
+ }
+ break;
+ case OGeneralPageWizard::eConnectExternal:
+ {
+ OUString sOld = m_sURL;
+ m_sURL = m_pGeneralPage->GetSelectedType();
+ DataSourceInfoConverter::convert(getORB(), m_pCollection,sOld,m_sURL,m_pImpl->getCurrentDataSource());
+ ::dbaccess::DATASOURCE_TYPE eType = VerifyDataSourceType(m_pCollection->determineType(m_sURL));
+ if (eType == ::dbaccess::DST_UNKNOWN)
+ m_pCollection->determineType(m_sOldURL);
+
+ activatePath( static_cast<PathId>(m_pCollection->getIndexOf(m_sURL) + 1), true);
+ updateTypeDependentStates();
+ }
+ break;
+ case OGeneralPageWizard::eOpenExisting:
+ {
+ activatePath( static_cast<PathId>(m_pCollection->size() + 1), true );
+ enableButtons( WizardButtonFlags::FINISH, !m_pGeneralPage->GetSelectedDocumentURL().isEmpty() );
+ }
+ break;
+ default:
+ OSL_FAIL( "ODbTypeWizDialogSetup::activateDatabasePath: unknown creation mode!" );
+ }
+
+ enableButtons( WizardButtonFlags::NEXT, m_pGeneralPage->GetDatabaseCreationMode() != OGeneralPageWizard::eOpenExisting );
+ // TODO: this should go into the base class. Point is, we activate a path whose *last*
+ // step is also the current one. The base class should automatically disable
+ // the Next button in such a case. However, not for this patch ...
+}
+
+void ODbTypeWizDialogSetup::updateTypeDependentStates()
+{
+ bool bDoEnable = false;
+ bool bIsConnectionRequired = m_pCollection->isConnectionUrlRequired(m_sURL);
+ if (!bIsConnectionRequired)
+ {
+ bDoEnable = true;
+ }
+ else if ( m_sURL == m_sOldURL )
+ {
+ bDoEnable = m_bIsConnectable;
+ }
+ enableState(PAGE_DBSETUPWIZARD_AUTHENTIFICATION, bDoEnable);
+ enableState(PAGE_DBSETUPWIZARD_FINAL, bDoEnable );
+ enableButtons( WizardButtonFlags::FINISH, bDoEnable);
+}
+
+void ODbTypeWizDialogSetup::resetPages(const Reference< XPropertySet >& _rxDatasource)
+{
+ // remove all items which relate to indirect properties from the input set
+ // (without this, the following may happen: select an arbitrary data source where some indirect properties
+ // are set. Select another data source of the same type, where the indirect props are not set (yet). Then,
+ // the indirect property values of the first ds are shown in the second ds ...)
+ const ODbDataSourceAdministrationHelper::MapInt2String& rMap = m_pImpl->getIndirectProperties();
+ for (auto const& elem : rMap)
+ getWriteOutputSet()->ClearItem( static_cast<sal_uInt16>(elem.first) );
+
+ // extract all relevant data from the property set of the data source
+ m_pImpl->translateProperties(_rxDatasource, *getWriteOutputSet());
+}
+
+const SfxItemSet* ODbTypeWizDialogSetup::getOutputSet() const
+{
+ return m_pOutSet.get();
+}
+
+SfxItemSet* ODbTypeWizDialogSetup::getWriteOutputSet()
+{
+ return m_pOutSet.get();
+}
+
+std::pair< Reference<XConnection>,bool> ODbTypeWizDialogSetup::createConnection()
+{
+ return m_pImpl->createConnection();
+}
+
+Reference< XComponentContext > ODbTypeWizDialogSetup::getORB() const
+{
+ return m_pImpl->getORB();
+}
+
+Reference< XDriver > ODbTypeWizDialogSetup::getDriver()
+{
+ return m_pImpl->getDriver();
+}
+
+::dbaccess::DATASOURCE_TYPE ODbTypeWizDialogSetup::VerifyDataSourceType(const ::dbaccess::DATASOURCE_TYPE DatabaseType) const
+{
+ ::dbaccess::DATASOURCE_TYPE LocDatabaseType = DatabaseType;
+ if ((LocDatabaseType == ::dbaccess::DST_MYSQL_JDBC) || (LocDatabaseType == ::dbaccess::DST_MYSQL_ODBC) || (LocDatabaseType == ::dbaccess::DST_MYSQL_NATIVE))
+ {
+ if (m_pMySQLIntroPage != nullptr)
+ {
+ switch( m_pMySQLIntroPage->getMySQLMode() )
+ {
+ case OMySQLIntroPageSetup::VIA_JDBC:
+ return ::dbaccess::DST_MYSQL_JDBC;
+ case OMySQLIntroPageSetup::VIA_NATIVE:
+ return ::dbaccess::DST_MYSQL_NATIVE;
+ case OMySQLIntroPageSetup::VIA_ODBC:
+ return ::dbaccess::DST_MYSQL_ODBC;
+ }
+ }
+ }
+ return LocDatabaseType;
+}
+
+OUString ODbTypeWizDialogSetup::getDatasourceType(const SfxItemSet& _rSet) const
+{
+ OUString sRet = dbaui::ODbDataSourceAdministrationHelper::getDatasourceType(_rSet);
+ if (m_pMySQLIntroPage && m_pMySQLIntroPage->IsVisible())
+ {
+ switch( m_pMySQLIntroPage->getMySQLMode() )
+ {
+ case OMySQLIntroPageSetup::VIA_JDBC:
+ sRet = "sdbc:mysql:jdbc:";
+ break;
+ case OMySQLIntroPageSetup::VIA_NATIVE:
+ sRet = "sdbc:mysql:mysqlc:";
+ break;
+ case OMySQLIntroPageSetup::VIA_ODBC:
+ sRet = "sdbc:mysql:odbc:";
+ break;
+ }
+ }
+ return sRet;
+}
+
+void ODbTypeWizDialogSetup::clearPassword()
+{
+ m_pImpl->clearPassword();
+}
+
+void ODbTypeWizDialogSetup::SetIntroPage(OMySQLIntroPageSetup* pPage)
+{
+ m_pMySQLIntroPage = pPage;
+ m_pMySQLIntroPage->SetClickHdl(LINK( this, ODbTypeWizDialogSetup, ImplClickHdl ) );
+}
+
+void ODbTypeWizDialogSetup::SetGeneralPage(OGeneralPageWizard* pPage)
+{
+ m_pGeneralPage = pPage;
+ m_pGeneralPage->SetTypeSelectHandler(LINK(this, ODbTypeWizDialogSetup, OnTypeSelected));
+ m_pGeneralPage->SetCreationModeHandler(LINK( this, ODbTypeWizDialogSetup, OnChangeCreationMode ) );
+ m_pGeneralPage->SetDocumentSelectionHandler(LINK( this, ODbTypeWizDialogSetup, OnRecentDocumentSelected ) );
+ m_pGeneralPage->SetChooseDocumentHandler(LINK( this, ODbTypeWizDialogSetup, OnSingleDocumentChosen ) );
+}
+
+void ODbTypeWizDialogSetup::SetFinalPage(OFinalDBPageSetup* pPage)
+{
+ m_pFinalPage = pPage;
+}
+
+std::unique_ptr<BuilderPage> ODbTypeWizDialogSetup::createPage(WizardState _nState)
+{
+ std::unique_ptr<OGenericAdministrationPage> xPage;
+
+ OString sIdent(OString::number(_nState));
+ weld::Container* pPageContainer = m_xAssistant->append_page(sIdent);
+
+ switch(_nState)
+ {
+ case PAGE_DBSETUPWIZARD_INTRO:
+ xPage = std::make_unique<OGeneralPageWizard>(pPageContainer,this,*m_pOutSet);
+ break;
+
+ case PAGE_DBSETUPWIZARD_DBASE:
+ xPage = OConnectionTabPageSetup::CreateDbaseTabPage(pPageContainer, this, *m_pOutSet);
+ break;
+
+ case PAGE_DBSETUPWIZARD_ADO:
+ xPage = OConnectionTabPageSetup::CreateADOTabPage(pPageContainer, this, *m_pOutSet);
+ break;
+
+ case PAGE_DBSETUPWIZARD_TEXT:
+ xPage = OTextConnectionPageSetup::CreateTextTabPage(pPageContainer, this, *m_pOutSet);
+ break;
+
+ case PAGE_DBSETUPWIZARD_ODBC:
+ xPage = OConnectionTabPageSetup::CreateODBCTabPage(pPageContainer, this, *m_pOutSet);
+ break;
+
+ case PAGE_DBSETUPWIZARD_JDBC:
+ xPage = OJDBCConnectionPageSetup::CreateJDBCTabPage(pPageContainer, this, *m_pOutSet);
+ break;
+
+ case PAGE_DBSETUPWIZARD_MYSQL_ODBC:
+ m_pOutSet->Put(SfxStringItem(DSID_CONNECTURL, m_pCollection->getPrefix("sdbc:mysql:odbc:")));
+ xPage = OConnectionTabPageSetup::CreateODBCTabPage(pPageContainer, this, *m_pOutSet);
+ break;
+
+ case PAGE_DBSETUPWIZARD_MYSQL_JDBC:
+ m_pOutSet->Put(SfxStringItem(DSID_CONNECTURL, m_pCollection->getPrefix("sdbc:mysql:jdbc:")));
+ xPage = OGeneralSpecialJDBCConnectionPageSetup::CreateMySQLJDBCTabPage(pPageContainer, this, *m_pOutSet);
+ break;
+ case PAGE_DBSETUPWIZARD_MYSQL_NATIVE:
+ m_pOutSet->Put(SfxStringItem(DSID_CONNECTURL, m_pCollection->getPrefix("sdbc:mysql:mysqlc:")));
+ xPage = MySQLNativeSetupPage::Create(pPageContainer, this, *m_pOutSet);
+ break;
+
+ case PAGE_DBSETUPWIZARD_ORACLE:
+ xPage = OGeneralSpecialJDBCConnectionPageSetup::CreateOracleJDBCTabPage(pPageContainer, this, *m_pOutSet);
+ break;
+
+ case PAGE_DBSETUPWIZARD_LDAP:
+ xPage = OLDAPConnectionPageSetup::CreateLDAPTabPage(pPageContainer, this, *m_pOutSet);
+ break;
+
+ case PAGE_DBSETUPWIZARD_DOCUMENT_OR_SPREADSHEET:
+ xPage = OSpreadSheetConnectionPageSetup::CreateDocumentOrSpreadSheetTabPage(pPageContainer, this, *m_pOutSet);
+ break;
+
+ case PAGE_DBSETUPWIZARD_MSACCESS:
+ xPage = OConnectionTabPageSetup::CreateMSAccessTabPage(pPageContainer, this, *m_pOutSet);
+ break;
+ case PAGE_DBSETUPWIZARD_MYSQL_INTRO:
+ xPage = OMySQLIntroPageSetup::CreateMySQLIntroTabPage(pPageContainer, this, *m_pOutSet);
+ break;
+
+ case PAGE_DBSETUPWIZARD_AUTHENTIFICATION:
+ xPage = OAuthentificationPageSetup::CreateAuthentificationTabPage(pPageContainer, this, *m_pOutSet);
+ break;
+
+ case PAGE_DBSETUPWIZARD_USERDEFINED:
+ xPage = OConnectionTabPageSetup::CreateUserDefinedTabPage(pPageContainer, this, *m_pOutSet);
+ break;
+
+ case PAGE_DBSETUPWIZARD_FINAL:
+ xPage = OFinalDBPageSetup::CreateFinalDBTabPageSetup(pPageContainer, this, *m_pOutSet);
+ break;
+ }
+
+ if ( xPage )
+ {
+ if ((_nState != PAGE_DBSETUPWIZARD_INTRO) && (_nState != PAGE_DBSETUPWIZARD_AUTHENTIFICATION))
+ {
+ xPage->SetModifiedHandler(LINK( this, ODbTypeWizDialogSetup, ImplModifiedHdl ) );
+ }
+
+ xPage->SetServiceFactory( m_pImpl->getORB() );
+ xPage->SetAdminDialog(this, this);
+
+ defaultButton( _nState == PAGE_DBSETUPWIZARD_FINAL ? WizardButtonFlags::FINISH : WizardButtonFlags::NEXT );
+ enableButtons( WizardButtonFlags::FINISH, _nState == PAGE_DBSETUPWIZARD_FINAL );
+ enableButtons( WizardButtonFlags::NEXT, _nState != PAGE_DBSETUPWIZARD_FINAL );
+
+ m_xAssistant->set_page_title(sIdent, getStateDisplayName(_nState));
+ }
+ return xPage;
+}
+
+IMPL_LINK(ODbTypeWizDialogSetup, ImplModifiedHdl, OGenericAdministrationPage const *, _pConnectionPageSetup, void)
+{
+ m_bIsConnectable = _pConnectionPageSetup->GetRoadmapStateValue( );
+ enableState(PAGE_DBSETUPWIZARD_FINAL, m_bIsConnectable);
+ enableState(PAGE_DBSETUPWIZARD_AUTHENTIFICATION, m_bIsConnectable);
+ if (getCurrentState() == PAGE_DBSETUPWIZARD_FINAL)
+ enableButtons( WizardButtonFlags::FINISH, true);
+ else
+ enableButtons( WizardButtonFlags::FINISH, m_bIsConnectable);
+ enableButtons( WizardButtonFlags::NEXT, m_bIsConnectable && (getCurrentState() != PAGE_DBSETUPWIZARD_FINAL));
+}
+
+IMPL_LINK(ODbTypeWizDialogSetup, ImplClickHdl, OMySQLIntroPageSetup*, _pMySQLIntroPageSetup, void)
+{
+ OUString sURLPrefix;
+ switch( _pMySQLIntroPageSetup->getMySQLMode() )
+ {
+ case OMySQLIntroPageSetup::VIA_ODBC:
+ sURLPrefix = "sdbc:mysql:odbc:";
+ break;
+ case OMySQLIntroPageSetup::VIA_JDBC:
+ sURLPrefix = "sdbc:mysql:jdbc:";
+ break;
+ case OMySQLIntroPageSetup::VIA_NATIVE:
+ sURLPrefix = "sdbc:mysql:mysqlc:";
+ break;
+ }
+ activatePath( static_cast<PathId>(m_pCollection->getIndexOf(sURLPrefix) + 1), true);
+}
+
+IMPL_LINK_NOARG(ODbTypeWizDialogSetup, OnChangeCreationMode, OGeneralPageWizard&, void)
+{
+ activateDatabasePath();
+}
+
+IMPL_LINK_NOARG(ODbTypeWizDialogSetup, OnRecentDocumentSelected, OGeneralPageWizard&, void)
+{
+ enableButtons( WizardButtonFlags::FINISH, !m_pGeneralPage->GetSelectedDocumentURL().isEmpty() );
+}
+
+IMPL_LINK_NOARG(ODbTypeWizDialogSetup, OnSingleDocumentChosen, OGeneralPageWizard&, void)
+{
+ if (prepareLeaveCurrentState(WizardTypes::eFinish))
+ onFinish();
+}
+
+void ODbTypeWizDialogSetup::enterState(WizardState _nState)
+{
+ m_sURL = dbaui::ODbDataSourceAdministrationHelper::getDatasourceType(*m_pOutSet);
+ RoadmapWizardMachine::enterState(_nState);
+ switch(_nState)
+ {
+ case PAGE_DBSETUPWIZARD_INTRO:
+ m_sOldURL = m_sURL;
+ break;
+ case PAGE_DBSETUPWIZARD_FINAL:
+ enableButtons( WizardButtonFlags::FINISH, true);
+ if ( m_pFinalPage )
+ m_pFinalPage->enableTableWizardCheckBox(m_pCollection->supportsTableCreation(m_sURL));
+ break;
+ }
+}
+
+void ODbTypeWizDialogSetup::saveDatasource()
+{
+ SfxTabPage* pPage = static_cast<SfxTabPage*>(GetPage(getCurrentState()));
+ if ( pPage )
+ pPage->FillItemSet(m_pOutSet.get());
+}
+
+bool ODbTypeWizDialogSetup::leaveState(WizardState _nState)
+{
+ if (_nState == PAGE_DBSETUPWIZARD_MYSQL_INTRO)
+ return true;
+ if ( _nState == PAGE_DBSETUPWIZARD_INTRO && m_sURL != m_sOldURL )
+ {
+ resetPages(m_pImpl->getCurrentDataSource());
+ }
+ SfxTabPage* pPage = static_cast<SfxTabPage*>(GetPage(_nState));
+ return pPage && pPage->DeactivatePage(m_pOutSet.get()) != DeactivateRC::KeepPage;
+}
+
+void ODbTypeWizDialogSetup::setTitle(const OUString& _sTitle)
+{
+ m_xAssistant->set_title(_sTitle);
+}
+
+void ODbTypeWizDialogSetup::enableConfirmSettings( bool /*_bEnable*/ )
+{
+}
+
+namespace
+{
+ bool lcl_handle( const Reference< XInteractionHandler2 >& _rxHandler, const Any& _rRequest )
+ {
+ rtl::Reference<OInteractionRequest> pRequest = new OInteractionRequest( _rRequest );
+ rtl::Reference<OInteractionAbort> pAbort = new OInteractionAbort;
+ pRequest->addContinuation( pAbort );
+
+ return _rxHandler->handleInteractionRequest( pRequest );
+ }
+}
+
+bool ODbTypeWizDialogSetup::SaveDatabaseDocument()
+{
+ Reference< XInteractionHandler2 > xHandler( InteractionHandler::createWithParent(getORB(), nullptr) );
+ try
+ {
+ if (callSaveAsDialog())
+ {
+ m_pImpl->saveChanges(*m_pOutSet);
+ Reference< XPropertySet > xDatasource = m_pImpl->getCurrentDataSource();
+ Reference< XModel > xModel( getDataSourceOrModel( xDatasource ), UNO_QUERY_THROW );
+ Reference< XStorable > xStore( xModel, UNO_QUERY_THROW );
+
+ if ( m_pGeneralPage->GetDatabaseCreationMode() == OGeneralPageWizard::eCreateNew )
+ CreateDatabase();
+
+ ::comphelper::NamedValueCollection aArgs( xModel->getArgs() );
+ aArgs.put( "Overwrite", true );
+ aArgs.put( "InteractionHandler", xHandler );
+ aArgs.put( "MacroExecutionMode", MacroExecMode::USE_CONFIG );
+ aArgs.put( "IgnoreFirebirdMigration", true );
+
+ OUString sPath = ODbDataSourceAdministrationHelper::getDocumentUrl( *m_pOutSet );
+ xStore->storeAsURL( sPath, aArgs.getPropertyValues() );
+
+ if ( !m_pFinalPage || m_pFinalPage->IsDatabaseDocumentToBeRegistered() )
+ RegisterDataSourceByLocation( sPath );
+
+ return true;
+ }
+ }
+ catch ( const Exception& e )
+ {
+ Any aError = ::cppu::getCaughtException();
+ if ( xHandler.is() )
+ {
+ if ( !lcl_handle( xHandler, aError ) )
+ {
+ InteractiveIOException aRequest;
+ aRequest.Classification = InteractionClassification_ERROR;
+ if ( aError.isExtractableTo( ::cppu::UnoType< IOException >::get() ) )
+ // assume saving the document failed
+ aRequest.Code = IOErrorCode_CANT_WRITE;
+ else
+ aRequest.Code = IOErrorCode_GENERAL;
+ aRequest.Message = e.Message;
+ aRequest.Context = e.Context;
+ lcl_handle( xHandler, Any( aRequest ) );
+ }
+ }
+ }
+ return false;
+}
+
+ bool ODbTypeWizDialogSetup::IsDatabaseDocumentToBeOpened() const
+ {
+ if ( m_pGeneralPage->GetDatabaseCreationMode() == OGeneralPageWizard::eOpenExisting )
+ return true;
+
+ if ( m_pFinalPage != nullptr )
+ return m_pFinalPage->IsDatabaseDocumentToBeOpened();
+
+ return true;
+ }
+
+ bool ODbTypeWizDialogSetup::IsTableWizardToBeStarted() const
+ {
+ if ( m_pGeneralPage->GetDatabaseCreationMode() == OGeneralPageWizard::eOpenExisting )
+ return false;
+
+ if ( m_pFinalPage != nullptr )
+ return m_pFinalPage->IsTableWizardToBeStarted();
+
+ return false;
+ }
+
+ void ODbTypeWizDialogSetup::CreateDatabase()
+ {
+ OUString sUrl;
+ const OUString eType = m_pGeneralPage->GetSelectedType();
+ if ( dbaccess::ODsnTypeCollection::isEmbeddedDatabase(eType) )
+ {
+ sUrl = eType;
+ Reference< XPropertySet > xDatasource = m_pImpl->getCurrentDataSource();
+ OSL_ENSURE(xDatasource.is(),"DataSource is null!");
+ if ( xDatasource.is() )
+ xDatasource->setPropertyValue( PROPERTY_INFO, Any( m_pCollection->getDefaultDBSettings( eType ) ) );
+ m_pImpl->translateProperties(xDatasource,*m_pOutSet);
+ }
+ else if ( m_pCollection->isFileSystemBased(eType) )
+ {
+ Reference< XSimpleFileAccess3 > xSimpleFileAccess(ucb::SimpleFileAccess::create(getORB()));
+ INetURLObject aDBPathURL(m_sWorkPath);
+ aDBPathURL.Append(m_aDocURL.getBase());
+ createUniqueFolderName(&aDBPathURL);
+ sUrl = aDBPathURL.GetMainURL( INetURLObject::DecodeMechanism::NONE);
+ xSimpleFileAccess->createFolder(sUrl);
+ sUrl = eType + sUrl;
+ }
+ m_pOutSet->Put(SfxStringItem(DSID_CONNECTURL, sUrl));
+ m_pImpl->saveChanges(*m_pOutSet);
+ }
+
+ void ODbTypeWizDialogSetup::RegisterDataSourceByLocation(std::u16string_view _sPath)
+ {
+ Reference< XPropertySet > xDatasource = m_pImpl->getCurrentDataSource();
+ Reference< XDatabaseContext > xDatabaseContext( DatabaseContext::create(getORB()) );
+ INetURLObject aURL( _sPath );
+ OUString sFilename = aURL.getBase( INetURLObject::LAST_SEGMENT, true, INetURLObject::DecodeMechanism::WithCharset );
+ OUString sDatabaseName = ::dbtools::createUniqueName(xDatabaseContext, sFilename, false);
+ xDatabaseContext->registerObject(sDatabaseName, xDatasource);
+ }
+
+ bool ODbTypeWizDialogSetup::callSaveAsDialog()
+ {
+ bool bRet = false;
+ ::sfx2::FileDialogHelper aFileDlg(
+ ui::dialogs::TemplateDescription::FILESAVE_AUTOEXTENSION,
+ FileDialogFlags::NONE, m_xAssistant.get());
+ aFileDlg.SetContext(sfx2::FileDialogHelper::BaseSaveAs);
+ std::shared_ptr<const SfxFilter> pFilter = getStandardDatabaseFilter();
+ if ( pFilter )
+ {
+ OUString sDefaultName = DBA_RES( STR_DATABASEDEFAULTNAME );
+ OUString sExtension = pFilter->GetDefaultExtension();
+ sDefaultName += sExtension.replaceAt( 0, 1, u"" );
+ INetURLObject aWorkURL( m_sWorkPath );
+ aWorkURL.Append( sDefaultName );
+ sDefaultName = createUniqueFileName( aWorkURL );
+ aFileDlg.SetFileName( sDefaultName );
+
+ aFileDlg.AddFilter(pFilter->GetUIName(),pFilter->GetDefaultExtension());
+ aFileDlg.SetCurrentFilter(pFilter->GetUIName());
+ }
+ if ( aFileDlg.Execute() == ERRCODE_NONE )
+ {
+ m_aDocURL = INetURLObject(aFileDlg.GetPath());
+
+ if( m_aDocURL.GetProtocol() != INetProtocol::NotValid )
+ {
+ OUString sFileName = m_aDocURL.GetMainURL( INetURLObject::DecodeMechanism::NONE );
+ if ( ::utl::UCBContentHelper::IsDocument(sFileName) )
+ ::utl::UCBContentHelper::Kill(sFileName);
+ m_pOutSet->Put(SfxStringItem(DSID_DOCUMENT_URL, sFileName));
+ bRet = true;
+ }
+ }
+ return bRet;
+ }
+
+ void ODbTypeWizDialogSetup::createUniqueFolderName(INetURLObject* pURL)
+ {
+ Reference< XSimpleFileAccess3 > xSimpleFileAccess(ucb::SimpleFileAccess::create(getORB()));
+ OUString sLastSegmentName = pURL->getName();
+ bool bFolderExists = true;
+ sal_Int32 i = 1;
+ while (bFolderExists)
+ {
+ bFolderExists = xSimpleFileAccess->isFolder(pURL->GetMainURL( INetURLObject::DecodeMechanism::NONE ));
+ if (bFolderExists)
+ {
+ i++;
+ pURL->setName(OUStringConcatenation(sLastSegmentName + OUString::number(i)));
+ }
+ }
+ }
+
+ OUString ODbTypeWizDialogSetup::createUniqueFileName(const INetURLObject& _rURL)
+ {
+ Reference< XSimpleFileAccess3 > xSimpleFileAccess(ucb::SimpleFileAccess::create(getORB()));
+ OUString BaseName = _rURL.getBase();
+
+ bool bElementExists = true;
+
+ INetURLObject aExistenceCheck( _rURL );
+ for ( sal_Int32 i = 1; bElementExists; )
+ {
+ bElementExists = xSimpleFileAccess->exists( aExistenceCheck.GetMainURL( INetURLObject::DecodeMechanism::NONE ) );
+ if ( bElementExists )
+ {
+ aExistenceCheck.setBase( OUStringConcatenation(BaseName + OUString::number( i ) ));
+ ++i;
+ }
+ }
+ return aExistenceCheck.getName( INetURLObject::LAST_SEGMENT, true, INetURLObject::DecodeMechanism::WithCharset );
+ }
+
+ vcl::IWizardPageController* ODbTypeWizDialogSetup::getPageController(BuilderPage* pCurrentPage) const
+ {
+ OGenericAdministrationPage* pPage = static_cast<OGenericAdministrationPage*>(pCurrentPage);
+ return pPage;
+ }
+
+ namespace
+ {
+ typedef ::cppu::WeakImplHelper< XTerminateListener
+ > AsyncLoader_Base;
+ class AsyncLoader : public AsyncLoader_Base
+ {
+ private:
+ Reference< XComponentLoader > m_xFrameLoader;
+ Reference< XDesktop2 > m_xDesktop;
+ Reference< XInteractionHandler2 > m_xInteractionHandler;
+ OUString m_sURL;
+ OAsynchronousLink m_aAsyncCaller;
+
+ public:
+ AsyncLoader( const Reference< XComponentContext >& _rxORB, const OUString& _rURL );
+
+ void doLoadAsync();
+
+ // XTerminateListener
+ virtual void SAL_CALL queryTermination( const css::lang::EventObject& Event ) override;
+ virtual void SAL_CALL notifyTermination( const css::lang::EventObject& Event ) override;
+ // XEventListener
+ virtual void SAL_CALL disposing( const css::lang::EventObject& Source ) override;
+
+ private:
+ DECL_LINK( OnOpenDocument, void*, void );
+ };
+
+ AsyncLoader::AsyncLoader( const Reference< XComponentContext >& _rxORB, const OUString& _rURL )
+ :m_sURL( _rURL )
+ ,m_aAsyncCaller( LINK( this, AsyncLoader, OnOpenDocument ) )
+ {
+ try
+ {
+ m_xDesktop.set( Desktop::create(_rxORB) );
+ m_xFrameLoader.set( m_xDesktop, UNO_QUERY_THROW );
+ m_xInteractionHandler = InteractionHandler::createWithParent(_rxORB, nullptr);
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+
+ void AsyncLoader::doLoadAsync()
+ {
+ OSL_ENSURE( !m_aAsyncCaller.IsRunning(), "AsyncLoader:doLoadAsync: already running!" );
+
+ acquire();
+ try
+ {
+ if ( m_xDesktop.is() )
+ m_xDesktop->addTerminateListener( this );
+ }
+ catch( const Exception& ) { DBG_UNHANDLED_EXCEPTION("dbaccess"); }
+
+ m_aAsyncCaller.Call();
+ }
+
+ IMPL_LINK_NOARG( AsyncLoader, OnOpenDocument, void*, void )
+ {
+ try
+ {
+ if ( m_xFrameLoader.is() )
+ {
+ ::comphelper::NamedValueCollection aLoadArgs;
+ aLoadArgs.put( "InteractionHandler", m_xInteractionHandler );
+ aLoadArgs.put( "MacroExecutionMode", MacroExecMode::USE_CONFIG );
+
+ Sequence< PropertyValue > aLoadArgPV;
+ aLoadArgs >>= aLoadArgPV;
+
+ m_xFrameLoader->loadComponentFromURL( m_sURL,
+ "_default",
+ FrameSearchFlag::ALL,
+ aLoadArgPV
+ );
+ }
+ }
+ catch( const Exception& )
+ {
+ // do not assert.
+ // Such an exception happens for instance of the to-be-loaded document does not exist anymore.
+ }
+
+ try
+ {
+ if ( m_xDesktop.is() )
+ m_xDesktop->removeTerminateListener( this );
+ }
+ catch( const Exception& ) { DBG_UNHANDLED_EXCEPTION("dbaccess"); }
+
+ release();
+ }
+
+ void SAL_CALL AsyncLoader::queryTermination( const css::lang::EventObject& /*Event*/ )
+ {
+ throw TerminationVetoException();
+ }
+
+ void SAL_CALL AsyncLoader::notifyTermination( const css::lang::EventObject& /*Event*/ )
+ {
+ }
+ void SAL_CALL AsyncLoader::disposing( const css::lang::EventObject& /*Source*/ )
+ {
+ }
+ }
+
+ bool ODbTypeWizDialogSetup::onFinish()
+ {
+ if ( m_pGeneralPage->GetDatabaseCreationMode() == OGeneralPageWizard::eOpenExisting )
+ {
+ // we're not going to re-use the XModel we have - since the document the user
+ // wants us to load could be a non-database document. Instead, we asynchronously
+ // open the selected document. Thus, the wizard's return value is RET_CANCEL,
+ // which means to not continue loading the database document
+ if ( !WizardMachine::Finish() )
+ return false;
+
+ try
+ {
+ rtl::Reference<AsyncLoader> pAsyncLoader = new AsyncLoader( getORB(), m_pGeneralPage->GetSelectedDocumentURL() );
+ pAsyncLoader->doLoadAsync();
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+
+ return true;
+ }
+
+ if (getCurrentState() != PAGE_DBSETUPWIZARD_FINAL)
+ {
+ skipUntil(PAGE_DBSETUPWIZARD_FINAL);
+ }
+ if (getCurrentState() == PAGE_DBSETUPWIZARD_FINAL)
+ return SaveDatabaseDocument() && WizardMachine::onFinish();
+ else
+ {
+ enableButtons( WizardButtonFlags::FINISH, false );
+ return false;
+ }
+ }
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/dlg/detailpages.cxx b/dbaccess/source/ui/dlg/detailpages.cxx
new file mode 100644
index 000000000..8a06d7de1
--- /dev/null
+++ b/dbaccess/source/ui/dlg/detailpages.cxx
@@ -0,0 +1,717 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <config_java.h>
+#include <core_resource.hxx>
+#include "detailpages.hxx"
+#include <sqlmessage.hxx>
+#include <dsmeta.hxx>
+#include "advancedsettings.hxx"
+#include "DbAdminImpl.hxx"
+#include <dsitems.hxx>
+#include "dbfindex.hxx"
+#include "dsnItem.hxx"
+
+#include <IItemSetHelper.hxx>
+#include <strings.hrc>
+
+#include <svl/itemset.hxx>
+#include <svl/stritem.hxx>
+#include <svl/eitem.hxx>
+#include <svl/intitem.hxx>
+#if HAVE_FEATURE_JAVA
+#include <jvmaccess/virtualmachine.hxx>
+#endif
+#include <connectivity/CommonTools.hxx>
+#include "DriverSettings.hxx"
+
+namespace dbaui
+{
+
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::sdbc;
+ using namespace ::com::sun::star::beans;
+ using namespace ::com::sun::star::lang;
+ using namespace ::com::sun::star::container;
+ using namespace ::dbtools;
+
+ OCommonBehaviourTabPage::OCommonBehaviourTabPage(weld::Container* pPage, weld::DialogController* pController,
+ const OUString& rUIXMLDescription, const OString& rId, const SfxItemSet& rCoreAttrs,
+ OCommonBehaviourTabPageFlags nControlFlags)
+ : OGenericAdministrationPage(pPage, pController, rUIXMLDescription, rId, rCoreAttrs)
+ , m_nControlFlags(nControlFlags)
+ {
+ if (m_nControlFlags & OCommonBehaviourTabPageFlags::UseOptions)
+ {
+ m_xOptionsLabel = m_xBuilder->weld_label("optionslabel");
+ m_xOptionsLabel->show();
+ m_xOptions = m_xBuilder->weld_entry("options");
+ m_xOptions->show();
+ m_xOptions->connect_changed(LINK(this,OGenericAdministrationPage,OnControlEntryModifyHdl));
+ }
+
+ if (m_nControlFlags & OCommonBehaviourTabPageFlags::UseCharset)
+ {
+ m_xDataConvertLabel = m_xBuilder->weld_label("charsetheader");
+ m_xDataConvertLabel->show();
+ m_xCharsetLabel = m_xBuilder->weld_label("charsetlabel");
+ m_xCharsetLabel->show();
+ m_xCharset.reset(new CharSetListBox(m_xBuilder->weld_combo_box("charset")));
+ m_xCharset->show();
+ m_xCharset->connect_changed(LINK(this, OCommonBehaviourTabPage, CharsetSelectHdl));
+ }
+ }
+
+ IMPL_LINK_NOARG(OCommonBehaviourTabPage, CharsetSelectHdl, weld::ComboBox&, void)
+ {
+ callModifiedHdl();
+ }
+
+ OCommonBehaviourTabPage::~OCommonBehaviourTabPage()
+ {
+ m_xCharset.reset();
+ }
+
+ void OCommonBehaviourTabPage::fillWindows(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList)
+ {
+ if (m_nControlFlags & OCommonBehaviourTabPageFlags::UseOptions)
+ {
+ _rControlList.emplace_back(new ODisableWidgetWrapper<weld::Label>(m_xOptionsLabel.get()));
+ }
+
+ if (m_nControlFlags & OCommonBehaviourTabPageFlags::UseCharset)
+ {
+ _rControlList.emplace_back(new ODisableWidgetWrapper<weld::Label>(m_xCharsetLabel.get()));
+ }
+ }
+
+ void OCommonBehaviourTabPage::fillControls(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList)
+ {
+ if (m_nControlFlags & OCommonBehaviourTabPageFlags::UseOptions)
+ _rControlList.emplace_back(new OSaveValueWidgetWrapper<weld::Entry>(m_xOptions.get()));
+
+ if (m_nControlFlags & OCommonBehaviourTabPageFlags::UseCharset)
+ _rControlList.emplace_back(new OSaveValueWidgetWrapper<weld::ComboBox>(m_xCharset->get_widget()));
+ }
+
+ void OCommonBehaviourTabPage::implInitControls(const SfxItemSet& _rSet, bool _bSaveValue)
+ {
+ // check whether or not the selection is invalid or readonly (invalid implies readonly, but not vice versa)
+ bool bValid, bReadonly;
+ getFlags(_rSet, bValid, bReadonly);
+
+ // collect the items
+ const SfxStringItem* pOptionsItem = _rSet.GetItem<SfxStringItem>(DSID_ADDITIONALOPTIONS);
+ const SfxStringItem* pCharsetItem = _rSet.GetItem<SfxStringItem>(DSID_CHARSET);
+
+ // forward the values to the controls
+ if (bValid)
+ {
+ if (m_nControlFlags & OCommonBehaviourTabPageFlags::UseOptions)
+ {
+ m_xOptions->set_text(pOptionsItem->GetValue());
+ m_xOptions->save_value();
+ }
+
+ if (m_nControlFlags & OCommonBehaviourTabPageFlags::UseCharset)
+ {
+ m_xCharset->SelectEntryByIanaName( pCharsetItem->GetValue() );
+ }
+ }
+ OGenericAdministrationPage::implInitControls(_rSet, _bSaveValue);
+ }
+
+ bool OCommonBehaviourTabPage::FillItemSet(SfxItemSet* _rSet)
+ {
+ bool bChangedSomething = false;
+
+ if (m_nControlFlags & OCommonBehaviourTabPageFlags::UseOptions)
+ {
+ fillString(*_rSet,m_xOptions.get(),DSID_ADDITIONALOPTIONS,bChangedSomething);
+ }
+
+ if (m_nControlFlags & OCommonBehaviourTabPageFlags::UseCharset)
+ {
+ if ( m_xCharset->StoreSelectedCharSet( *_rSet, DSID_CHARSET ) )
+ bChangedSomething = true;
+ }
+
+ return bChangedSomething;
+ }
+
+ // ODbaseDetailsPage
+ ODbaseDetailsPage::ODbaseDetailsPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& _rCoreAttrs)
+ : OCommonBehaviourTabPage(pPage, pController, "dbaccess/ui/dbasepage.ui", "DbasePage",
+ _rCoreAttrs, OCommonBehaviourTabPageFlags::UseCharset)
+ , m_xShowDeleted(m_xBuilder->weld_check_button("showDelRowsCheckbutton"))
+ , m_xFT_Message(m_xBuilder->weld_label("specMessageLabel"))
+ , m_xIndexes(m_xBuilder->weld_button("indiciesButton"))
+ {
+ m_xIndexes->connect_clicked(LINK(this, ODbaseDetailsPage, OnButtonClicked));
+ m_xShowDeleted->connect_toggled(LINK(this, ODbaseDetailsPage, OnButtonToggled));
+ }
+
+ ODbaseDetailsPage::~ODbaseDetailsPage()
+ {
+ }
+
+ std::unique_ptr<SfxTabPage> ODriversSettings::CreateDbase(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* _rAttrSet)
+ {
+ return std::make_unique<ODbaseDetailsPage>(pPage, pController, *_rAttrSet);
+ }
+
+ void ODbaseDetailsPage::implInitControls(const SfxItemSet& _rSet, bool _bSaveValue)
+ {
+ // check whether or not the selection is invalid or readonly (invalid implies readonly, but not vice versa)
+ bool bValid, bReadonly;
+ getFlags(_rSet, bValid, bReadonly);
+
+ // get the DSN string (needed for the index dialog)
+ const SfxStringItem* pUrlItem = _rSet.GetItem<SfxStringItem>(DSID_CONNECTURL);
+ const DbuTypeCollectionItem* pTypesItem = _rSet.GetItem<DbuTypeCollectionItem>(DSID_TYPECOLLECTION);
+ ::dbaccess::ODsnTypeCollection* pTypeCollection = pTypesItem ? pTypesItem->getCollection() : nullptr;
+ if (pTypeCollection && pUrlItem && pUrlItem->GetValue().getLength())
+ m_sDsn = pTypeCollection->cutPrefix(pUrlItem->GetValue());
+
+ // get the other relevant items
+ const SfxBoolItem* pDeletedItem = _rSet.GetItem<SfxBoolItem>(DSID_SHOWDELETEDROWS);
+
+ if ( bValid )
+ {
+ m_xShowDeleted->set_active(pDeletedItem->GetValue());
+ m_xFT_Message->set_visible(m_xShowDeleted->get_active());
+ }
+
+ OCommonBehaviourTabPage::implInitControls(_rSet, _bSaveValue);
+ }
+
+ bool ODbaseDetailsPage::FillItemSet( SfxItemSet* _rSet )
+ {
+ bool bChangedSomething = OCommonBehaviourTabPage::FillItemSet(_rSet);
+
+ fillBool(*_rSet, m_xShowDeleted.get(), DSID_SHOWDELETEDROWS, false, bChangedSomething);
+ return bChangedSomething;
+ }
+
+ IMPL_LINK_NOARG(ODbaseDetailsPage, OnButtonClicked, weld::Button&, void)
+ {
+ ODbaseIndexDialog aIndexDialog(GetFrameWeld(), m_sDsn);
+ aIndexDialog.run();
+ }
+
+ IMPL_LINK_NOARG(ODbaseDetailsPage, OnButtonToggled, weld::Toggleable&, void)
+ {
+ m_xFT_Message->set_visible(m_xShowDeleted->get_active());
+ // it was the checkbox -> we count as modified from now on
+ callModifiedHdl();
+ }
+
+
+ // OAdoDetailsPage
+ OAdoDetailsPage::OAdoDetailsPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rCoreAttrs)
+ : OCommonBehaviourTabPage(pPage, pController, "dbaccess/ui/autocharsetpage.ui", "AutoCharset",
+ rCoreAttrs, OCommonBehaviourTabPageFlags::UseCharset )
+ {
+
+ }
+
+ std::unique_ptr<SfxTabPage> ODriversSettings::CreateAdo(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet)
+ {
+ return std::make_unique<OAdoDetailsPage>(pPage, pController, *rAttrSet);
+ }
+
+ // OOdbcDetailsPage
+ OOdbcDetailsPage::OOdbcDetailsPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rCoreAttrs)
+ : OCommonBehaviourTabPage(pPage, pController, "dbaccess/ui/odbcpage.ui", "ODBC", rCoreAttrs,
+ OCommonBehaviourTabPageFlags::UseCharset | OCommonBehaviourTabPageFlags::UseOptions)
+ , m_xUseCatalog(m_xBuilder->weld_check_button("useCatalogCheckbutton"))
+ {
+ m_xUseCatalog->connect_toggled(LINK(this, OGenericAdministrationPage, OnControlModifiedButtonClick));
+ }
+
+ OOdbcDetailsPage::~OOdbcDetailsPage()
+ {
+ }
+
+ std::unique_ptr<SfxTabPage> ODriversSettings::CreateODBC(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* pAttrSet)
+ {
+ return std::make_unique<OOdbcDetailsPage>(pPage, pController, *pAttrSet);
+ }
+
+ bool OOdbcDetailsPage::FillItemSet( SfxItemSet* _rSet )
+ {
+ bool bChangedSomething = OCommonBehaviourTabPage::FillItemSet(_rSet);
+ fillBool(*_rSet,m_xUseCatalog.get(),DSID_USECATALOG,false,bChangedSomething);
+ return bChangedSomething;
+ }
+ void OOdbcDetailsPage::implInitControls(const SfxItemSet& _rSet, bool _bSaveValue)
+ {
+ // check whether or not the selection is invalid or readonly (invalid implies readonly, but not vice versa)
+ bool bValid, bReadonly;
+ getFlags(_rSet, bValid, bReadonly);
+
+ const SfxBoolItem* pUseCatalogItem = _rSet.GetItem<SfxBoolItem>(DSID_USECATALOG);
+
+ if ( bValid )
+ m_xUseCatalog->set_active(pUseCatalogItem->GetValue());
+
+ OCommonBehaviourTabPage::implInitControls(_rSet, _bSaveValue);
+ }
+ // OOdbcDetailsPage
+ OUserDriverDetailsPage::OUserDriverDetailsPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rCoreAttrs)
+ : OCommonBehaviourTabPage(pPage, pController, "dbaccess/ui/userdetailspage.ui", "UserDetailsPage",
+ rCoreAttrs, OCommonBehaviourTabPageFlags::UseCharset | OCommonBehaviourTabPageFlags::UseOptions)
+ , m_xFTHostname(m_xBuilder->weld_label("hostnameft"))
+ , m_xEDHostname(m_xBuilder->weld_entry("hostname"))
+ , m_xPortNumber(m_xBuilder->weld_label("portnumberft"))
+ , m_xNFPortNumber(m_xBuilder->weld_spin_button("portnumber"))
+ , m_xUseCatalog(m_xBuilder->weld_check_button("usecatalog"))
+ {
+ m_xUseCatalog->connect_toggled(LINK(this, OGenericAdministrationPage, OnControlModifiedButtonClick));
+ }
+
+ OUserDriverDetailsPage::~OUserDriverDetailsPage()
+ {
+ }
+
+ std::unique_ptr<SfxTabPage> ODriversSettings::CreateUser(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* pAttrSet)
+ {
+ return std::make_unique<OUserDriverDetailsPage>(pPage, pController, *pAttrSet);
+ }
+
+ bool OUserDriverDetailsPage::FillItemSet( SfxItemSet* _rSet )
+ {
+ bool bChangedSomething = OCommonBehaviourTabPage::FillItemSet(_rSet);
+
+ fillInt32(*_rSet,m_xNFPortNumber.get(),DSID_CONN_PORTNUMBER,bChangedSomething);
+ fillString(*_rSet,m_xEDHostname.get(),DSID_CONN_HOSTNAME,bChangedSomething);
+ fillBool(*_rSet,m_xUseCatalog.get(),DSID_USECATALOG,false,bChangedSomething);
+
+ return bChangedSomething;
+ }
+ void OUserDriverDetailsPage::fillControls(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList)
+ {
+ OCommonBehaviourTabPage::fillControls(_rControlList);
+ _rControlList.emplace_back(new OSaveValueWidgetWrapper<weld::Entry>(m_xEDHostname.get()));
+ _rControlList.emplace_back(new OSaveValueWidgetWrapper<weld::Toggleable>(m_xUseCatalog.get()));
+ _rControlList.emplace_back(new OSaveValueWidgetWrapper<weld::SpinButton>(m_xNFPortNumber.get()));
+ }
+ void OUserDriverDetailsPage::fillWindows(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList)
+ {
+ OCommonBehaviourTabPage::fillWindows(_rControlList);
+ _rControlList.emplace_back(new ODisableWidgetWrapper<weld::Label>(m_xFTHostname.get()));
+ _rControlList.emplace_back(new ODisableWidgetWrapper<weld::Label>(m_xPortNumber.get()));
+ }
+ void OUserDriverDetailsPage::implInitControls(const SfxItemSet& _rSet, bool _bSaveValue)
+ {
+ // check whether or not the selection is invalid or readonly (invalid implies readonly, but not vice versa)
+ bool bValid, bReadonly;
+ getFlags(_rSet, bValid, bReadonly);
+
+ const SfxBoolItem* pUseCatalogItem = _rSet.GetItem<SfxBoolItem>(DSID_USECATALOG);
+ const SfxStringItem* pHostName = _rSet.GetItem<SfxStringItem>(DSID_CONN_HOSTNAME);
+ const SfxInt32Item* pPortNumber = _rSet.GetItem<SfxInt32Item>(DSID_CONN_PORTNUMBER);
+
+ if ( bValid )
+ {
+ m_xEDHostname->set_text(pHostName->GetValue());
+ m_xEDHostname->save_value();
+
+ m_xNFPortNumber->set_value(pPortNumber->GetValue());
+ m_xNFPortNumber->save_value();
+
+ m_xUseCatalog->set_active(pUseCatalogItem->GetValue());
+ }
+
+ OCommonBehaviourTabPage::implInitControls(_rSet, _bSaveValue);
+ }
+ // OMySQLODBCDetailsPage
+ OMySQLODBCDetailsPage::OMySQLODBCDetailsPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rCoreAttrs)
+ : OCommonBehaviourTabPage(pPage, pController, "dbaccess/ui/autocharsetpage.ui", "AutoCharset",
+ rCoreAttrs, OCommonBehaviourTabPageFlags::UseCharset )
+ {
+ }
+
+ std::unique_ptr<SfxTabPage> ODriversSettings::CreateMySQLODBC(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* pAttrSet)
+ {
+ return std::make_unique<OMySQLODBCDetailsPage>(pPage, pController, *pAttrSet);
+ }
+
+ // OMySQLJDBCDetailsPage
+ OGeneralSpecialJDBCDetailsPage::OGeneralSpecialJDBCDetailsPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rCoreAttrs ,sal_uInt16 _nPortId, bool bShowSocket)
+ : OCommonBehaviourTabPage(pPage, pController, "dbaccess/ui/generalspecialjdbcdetailspage.ui", "GeneralSpecialJDBCDetails",
+ rCoreAttrs, OCommonBehaviourTabPageFlags::UseCharset)
+ , m_nPortId(_nPortId)
+ , m_bUseClass(true)
+ , m_xEDHostname(m_xBuilder->weld_entry("hostNameEntry"))
+ , m_xNFPortNumber(m_xBuilder->weld_spin_button("portNumberSpinbutton"))
+ , m_xFTSocket(m_xBuilder->weld_label("socketLabel"))
+ , m_xEDSocket(m_xBuilder->weld_entry("socketEntry"))
+ , m_xFTDriverClass(m_xBuilder->weld_label("driverClassLabel"))
+ , m_xEDDriverClass(m_xBuilder->weld_entry("jdbcDriverClassEntry"))
+ , m_xTestJavaDriver(m_xBuilder->weld_button("testDriverClassButton"))
+ {
+ const SfxStringItem* pUrlItem = rCoreAttrs.GetItem<SfxStringItem>(DSID_CONNECTURL);
+ const DbuTypeCollectionItem* pTypesItem = rCoreAttrs.GetItem<DbuTypeCollectionItem>(DSID_TYPECOLLECTION);
+ ::dbaccess::ODsnTypeCollection* pTypeCollection = pTypesItem ? pTypesItem->getCollection() : nullptr;
+ if (pTypeCollection && pUrlItem && pUrlItem->GetValue().getLength() )
+ {
+ m_sDefaultJdbcDriverName = pTypeCollection->getJavaDriverClass(pUrlItem->GetValue());
+ }
+ if ( m_sDefaultJdbcDriverName.getLength() )
+ {
+ m_xEDDriverClass->connect_changed(LINK(this,OGenericAdministrationPage,OnControlEntryModifyHdl));
+ m_xTestJavaDriver->connect_clicked(LINK(this,OGeneralSpecialJDBCDetailsPage,OnTestJavaClickHdl));
+ }
+ else
+ {
+ m_bUseClass = false;
+ m_xFTDriverClass->hide();
+ m_xEDDriverClass->hide();
+ m_xTestJavaDriver->hide();
+ }
+
+ m_xFTSocket->set_visible(bShowSocket && !m_bUseClass);
+ m_xEDSocket->set_visible(bShowSocket && !m_bUseClass);
+
+ m_xEDHostname->connect_changed(LINK(this,OGenericAdministrationPage,OnControlEntryModifyHdl));
+ m_xNFPortNumber->connect_value_changed(LINK(this,OGenericAdministrationPage,OnControlSpinButtonModifyHdl));
+ m_xEDSocket->connect_changed(LINK(this,OGenericAdministrationPage,OnControlEntryModifyHdl));
+ }
+
+ OGeneralSpecialJDBCDetailsPage::~OGeneralSpecialJDBCDetailsPage()
+ {
+ }
+
+ bool OGeneralSpecialJDBCDetailsPage::FillItemSet( SfxItemSet* _rSet )
+ {
+ bool bChangedSomething = OCommonBehaviourTabPage::FillItemSet(_rSet);
+ if ( m_bUseClass )
+ fillString(*_rSet,m_xEDDriverClass.get(),DSID_JDBCDRIVERCLASS,bChangedSomething);
+ fillString(*_rSet,m_xEDHostname.get(),DSID_CONN_HOSTNAME,bChangedSomething);
+ fillString(*_rSet,m_xEDSocket.get(),DSID_CONN_SOCKET,bChangedSomething);
+ fillInt32(*_rSet,m_xNFPortNumber.get(),m_nPortId,bChangedSomething );
+
+ return bChangedSomething;
+ }
+ void OGeneralSpecialJDBCDetailsPage::implInitControls(const SfxItemSet& _rSet, bool _bSaveValue)
+ {
+ // check whether or not the selection is invalid or readonly (invalid implies readonly, but not vice versa)
+ bool bValid, bReadonly;
+ getFlags(_rSet, bValid, bReadonly);
+
+ const SfxStringItem* pDrvItem = _rSet.GetItem<SfxStringItem>(DSID_JDBCDRIVERCLASS);
+ const SfxStringItem* pHostName = _rSet.GetItem<SfxStringItem>(DSID_CONN_HOSTNAME);
+ const SfxInt32Item* pPortNumber = _rSet.GetItem<SfxInt32Item>(m_nPortId);
+ const SfxStringItem* pSocket = _rSet.GetItem<SfxStringItem>(DSID_CONN_SOCKET);
+
+ if ( bValid )
+ {
+ if ( m_bUseClass )
+ {
+ m_xEDDriverClass->set_text(pDrvItem->GetValue());
+ m_xEDDriverClass->save_value();
+ }
+
+ m_xEDHostname->set_text(pHostName->GetValue());
+ m_xEDHostname->save_value();
+
+ m_xNFPortNumber->set_value(pPortNumber->GetValue());
+ m_xNFPortNumber->save_value();
+
+ m_xEDSocket->set_text(pSocket->GetValue());
+ m_xEDSocket->save_value();
+ }
+
+ OCommonBehaviourTabPage::implInitControls(_rSet, _bSaveValue);
+
+ // to get the correct value when saveValue was called by base class
+ if ( m_bUseClass && m_xEDDriverClass->get_text().trim().isEmpty() )
+ {
+ m_xEDDriverClass->set_text(m_sDefaultJdbcDriverName);
+ m_xEDDriverClass->save_value();
+ }
+ }
+ IMPL_LINK_NOARG(OGeneralSpecialJDBCDetailsPage, OnTestJavaClickHdl, weld::Button&, void)
+ {
+ OSL_ENSURE(m_pAdminDialog,"No Admin dialog set! ->GPF");
+ OSL_ENSURE(m_bUseClass,"Who called me?");
+
+ bool bSuccess = false;
+#if HAVE_FEATURE_JAVA
+ try
+ {
+ if (!m_xEDDriverClass->get_text().trim().isEmpty())
+ {
+// TODO change jvmaccess
+ ::rtl::Reference< jvmaccess::VirtualMachine > xJVM = ::connectivity::getJavaVM( m_pAdminDialog->getORB() );
+ m_xEDDriverClass->set_text(m_xEDDriverClass->get_text().trim()); // fdo#68341
+ bSuccess = ::connectivity::existsJavaClassByName(xJVM,m_xEDDriverClass->get_text());
+ }
+ }
+ catch(Exception&)
+ {
+ }
+#endif
+ TranslateId pMessage = bSuccess ? STR_JDBCDRIVER_SUCCESS : STR_JDBCDRIVER_NO_SUCCESS;
+ const MessageType mt = bSuccess ? MessageType::Info : MessageType::Error;
+ OSQLMessageBox aMsg(GetFrameWeld(), DBA_RES(pMessage), OUString(), MessBoxStyle::Ok | MessBoxStyle::DefaultOk, mt);
+ aMsg.run();
+ }
+
+ void OGeneralSpecialJDBCDetailsPage::callModifiedHdl(weld::Widget* pControl)
+ {
+ if (m_bUseClass && pControl == m_xEDDriverClass.get())
+ m_xTestJavaDriver->set_sensitive(!m_xEDDriverClass->get_text().trim().isEmpty());
+
+ // tell the listener we were modified
+ OGenericAdministrationPage::callModifiedHdl();
+ }
+
+ // MySQLNativePage
+ MySQLNativePage::MySQLNativePage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rCoreAttrs)
+ : OCommonBehaviourTabPage(pPage, pController, "dbaccess/ui/mysqlnativepage.ui", "MysqlNativePage", rCoreAttrs, OCommonBehaviourTabPageFlags::UseCharset)
+ , m_xMySQLSettingsContainer(m_xBuilder->weld_widget("MySQLSettingsContainer"))
+ , m_xMySQLSettings(new MySQLNativeSettings(m_xMySQLSettingsContainer.get(), LINK(this,OGenericAdministrationPage,OnControlModified)))
+ , m_xSeparator1(m_xBuilder->weld_label("connectionheader"))
+ , m_xSeparator2(m_xBuilder->weld_label("userheader"))
+ , m_xUserNameLabel(m_xBuilder->weld_label("usernamelabel"))
+ , m_xUserName(m_xBuilder->weld_entry("username"))
+ , m_xPasswordRequired(m_xBuilder->weld_check_button("passwordrequired"))
+ {
+ m_xUserName->connect_changed(LINK(this,OGenericAdministrationPage,OnControlEntryModifyHdl));
+ }
+
+ MySQLNativePage::~MySQLNativePage()
+ {
+ m_xMySQLSettings.reset();
+ }
+
+ void MySQLNativePage::fillControls(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList)
+ {
+ OCommonBehaviourTabPage::fillControls( _rControlList );
+ m_xMySQLSettings->fillControls( _rControlList );
+
+ _rControlList.emplace_back(new OSaveValueWidgetWrapper<weld::Entry>(m_xUserName.get()));
+ _rControlList.emplace_back(new OSaveValueWidgetWrapper<weld::Toggleable>(m_xPasswordRequired.get()));
+ }
+
+ void MySQLNativePage::fillWindows(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList)
+ {
+ OCommonBehaviourTabPage::fillWindows( _rControlList );
+ m_xMySQLSettings->fillWindows( _rControlList);
+
+ _rControlList.emplace_back(new ODisableWidgetWrapper<weld::Label>(m_xSeparator1.get()));
+ _rControlList.emplace_back(new ODisableWidgetWrapper<weld::Label>(m_xSeparator2.get()));
+ _rControlList.emplace_back(new ODisableWidgetWrapper<weld::Label>(m_xUserNameLabel.get()));
+ }
+
+ bool MySQLNativePage::FillItemSet( SfxItemSet* _rSet )
+ {
+ bool bChangedSomething = OCommonBehaviourTabPage::FillItemSet( _rSet );
+
+ bChangedSomething |= m_xMySQLSettings->FillItemSet( _rSet );
+
+ if (m_xUserName->get_value_changed_from_saved())
+ {
+ _rSet->Put( SfxStringItem( DSID_USER, m_xUserName->get_text() ) );
+ _rSet->Put( SfxStringItem( DSID_PASSWORD, OUString()));
+ bChangedSomething = true;
+ }
+ fillBool(*_rSet,m_xPasswordRequired.get(),DSID_PASSWORDREQUIRED,false,bChangedSomething);
+
+ return bChangedSomething;
+ }
+ void MySQLNativePage::implInitControls(const SfxItemSet& _rSet, bool _bSaveValue)
+ {
+ // check whether or not the selection is invalid or readonly (invalid implies readonly, but not vice versa)
+ bool bValid, bReadonly;
+ getFlags(_rSet, bValid, bReadonly);
+
+ m_xMySQLSettings->implInitControls( _rSet );
+
+ const SfxStringItem* pUidItem = _rSet.GetItem<SfxStringItem>(DSID_USER);
+ const SfxBoolItem* pAllowEmptyPwd = _rSet.GetItem<SfxBoolItem>(DSID_PASSWORDREQUIRED);
+
+ if ( bValid )
+ {
+ m_xUserName->set_text(pUidItem->GetValue());
+ m_xUserName->save_value();
+ m_xPasswordRequired->set_active(pAllowEmptyPwd->GetValue());
+ }
+
+ OCommonBehaviourTabPage::implInitControls(_rSet, _bSaveValue);
+ }
+
+ std::unique_ptr<SfxTabPage> ODriversSettings::CreateMySQLJDBC( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* _rAttrSet )
+ {
+ return std::make_unique<OGeneralSpecialJDBCDetailsPage>(pPage, pController, *_rAttrSet,DSID_MYSQL_PORTNUMBER);
+ }
+
+ std::unique_ptr<SfxTabPage> ODriversSettings::CreateMySQLNATIVE(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* pAttrSet)
+ {
+ return std::make_unique<MySQLNativePage>(pPage, pController, *pAttrSet);
+ }
+
+ std::unique_ptr<SfxTabPage> ODriversSettings::CreateOracleJDBC(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* _rAttrSet)
+ {
+ return std::make_unique<OGeneralSpecialJDBCDetailsPage>(pPage, pController, *_rAttrSet,DSID_ORACLE_PORTNUMBER, false);
+ }
+
+ // OLDAPDetailsPage
+ OLDAPDetailsPage::OLDAPDetailsPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rCoreAttrs)
+ : OCommonBehaviourTabPage(pPage, pController, "dbaccess/ui/ldappage.ui", "LDAP",
+ rCoreAttrs, OCommonBehaviourTabPageFlags::NONE)
+ , m_xETBaseDN(m_xBuilder->weld_entry("baseDNEntry"))
+ , m_xCBUseSSL(m_xBuilder->weld_check_button("useSSLCheckbutton"))
+ , m_xNFPortNumber(m_xBuilder->weld_spin_button("portNumberSpinbutton"))
+ , m_xNFRowCount(m_xBuilder->weld_spin_button("LDAPRowCountspinbutton"))
+ {
+ m_xETBaseDN->connect_changed(LINK(this,OGenericAdministrationPage,OnControlEntryModifyHdl));
+ m_xNFPortNumber->connect_value_changed(LINK(this,OGenericAdministrationPage,OnControlSpinButtonModifyHdl));
+ m_xNFRowCount->connect_value_changed(LINK(this,OGenericAdministrationPage,OnControlSpinButtonModifyHdl));
+
+ m_iNormalPort = 389;
+ m_iSSLPort = 636;
+ m_xCBUseSSL->connect_toggled(LINK(this, OLDAPDetailsPage, OnCheckBoxClick));
+ }
+
+ OLDAPDetailsPage::~OLDAPDetailsPage()
+ {
+ }
+
+ std::unique_ptr<SfxTabPage> ODriversSettings::CreateLDAP(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* _rAttrSet)
+ {
+ return std::make_unique<OLDAPDetailsPage>(pPage, pController, *_rAttrSet);
+ }
+
+ bool OLDAPDetailsPage::FillItemSet( SfxItemSet* _rSet )
+ {
+ bool bChangedSomething = OCommonBehaviourTabPage::FillItemSet(_rSet);
+
+ fillString(*_rSet,m_xETBaseDN.get(),DSID_CONN_LDAP_BASEDN,bChangedSomething);
+ fillInt32(*_rSet,m_xNFPortNumber.get(),DSID_CONN_LDAP_PORTNUMBER,bChangedSomething);
+ fillInt32(*_rSet,m_xNFRowCount.get(),DSID_CONN_LDAP_ROWCOUNT,bChangedSomething);
+ fillBool(*_rSet,m_xCBUseSSL.get(),DSID_CONN_LDAP_USESSL,false,bChangedSomething);
+ return bChangedSomething;
+ }
+
+ IMPL_LINK(OLDAPDetailsPage, OnCheckBoxClick, weld::Toggleable&, rCheckBox, void)
+ {
+ OnControlModifiedButtonClick(rCheckBox);
+ callModifiedHdl();
+ if (m_xCBUseSSL->get_active())
+ {
+ m_iNormalPort = m_xNFPortNumber->get_value();
+ m_xNFPortNumber->set_value(m_iSSLPort);
+ }
+ else
+ {
+ m_iSSLPort = m_xNFPortNumber->get_value();
+ m_xNFPortNumber->set_value(m_iNormalPort);
+ }
+ }
+
+ void OLDAPDetailsPage::implInitControls(const SfxItemSet& _rSet, bool _bSaveValue)
+ {
+ // check whether or not the selection is invalid or readonly (invalid implies readonly, but not vice versa)
+ bool bValid, bReadonly;
+ getFlags(_rSet, bValid, bReadonly);
+
+ const SfxStringItem* pBaseDN = _rSet.GetItem<SfxStringItem>(DSID_CONN_LDAP_BASEDN);
+ const SfxBoolItem* pUseSSL = _rSet.GetItem<SfxBoolItem>(DSID_CONN_LDAP_USESSL);
+ const SfxInt32Item* pPortNumber = _rSet.GetItem<SfxInt32Item>(DSID_CONN_LDAP_PORTNUMBER);
+ const SfxInt32Item* pRowCount = _rSet.GetItem<SfxInt32Item>(DSID_CONN_LDAP_ROWCOUNT);
+
+ if ( bValid )
+ {
+ m_xETBaseDN->set_text(pBaseDN->GetValue());
+ m_xNFPortNumber->set_value(pPortNumber->GetValue());
+ m_xNFRowCount->set_value(pRowCount->GetValue());
+ m_xCBUseSSL->set_active(pUseSSL->GetValue());
+ }
+
+ OCommonBehaviourTabPage::implInitControls(_rSet, _bSaveValue);
+ }
+
+ // OTextDetailsPage
+ OTextDetailsPage::OTextDetailsPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rCoreAttrs)
+ : OCommonBehaviourTabPage(pPage, pController, "dbaccess/ui/emptypage.ui", "EmptyPage", rCoreAttrs, OCommonBehaviourTabPageFlags::NONE)
+ , m_xTextConnectionHelper(new OTextConnectionHelper(m_xContainer.get(), TC_EXTENSION | TC_HEADER | TC_SEPARATORS | TC_CHARSET))
+ {
+ }
+
+ OTextDetailsPage::~OTextDetailsPage()
+ {
+ m_xTextConnectionHelper.reset();
+ }
+
+ std::unique_ptr<SfxTabPage> ODriversSettings::CreateText(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* pAttrSet)
+ {
+ return std::make_unique<OTextDetailsPage>(pPage, pController, *pAttrSet);
+ }
+
+ void OTextDetailsPage::fillControls(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList)
+ {
+ OCommonBehaviourTabPage::fillControls(_rControlList);
+ m_xTextConnectionHelper->fillControls(_rControlList);
+
+ }
+ void OTextDetailsPage::fillWindows(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList)
+ {
+ OCommonBehaviourTabPage::fillWindows(_rControlList);
+ m_xTextConnectionHelper->fillWindows(_rControlList);
+
+ }
+ void OTextDetailsPage::implInitControls(const SfxItemSet& _rSet, bool _bSaveValue)
+ {
+ // first check whether or not the selection is invalid or readonly (invalid implies readonly, but not vice versa)
+ bool bValid, bReadonly;
+ getFlags(_rSet, bValid, bReadonly);
+
+ m_xTextConnectionHelper->implInitControls(_rSet, bValid);
+ OCommonBehaviourTabPage::implInitControls(_rSet, _bSaveValue);
+ }
+
+ bool OTextDetailsPage::FillItemSet( SfxItemSet* rSet )
+ {
+ bool bChangedSomething = OCommonBehaviourTabPage::FillItemSet(rSet);
+ bChangedSomething = m_xTextConnectionHelper->FillItemSet(*rSet, bChangedSomething);
+ return bChangedSomething;
+ }
+
+ bool OTextDetailsPage::prepareLeave()
+ {
+ return m_xTextConnectionHelper->prepareLeave();
+ }
+
+ std::unique_ptr<SfxTabPage> ODriversSettings::CreateGeneratedValuesPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* _rAttrSet)
+ {
+ return std::make_unique<GeneratedValuesPage>(pPage, pController, *_rAttrSet);
+ }
+
+ std::unique_ptr<SfxTabPage> ODriversSettings::CreateSpecialSettingsPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* _rAttrSet)
+ {
+ OUString eType = ODbDataSourceAdministrationHelper::getDatasourceType( *_rAttrSet );
+ DataSourceMetaData aMetaData( eType );
+ return std::make_unique<SpecialSettingsPage>(pPage, pController, *_rAttrSet, aMetaData);
+ }
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/dlg/detailpages.hxx b/dbaccess/source/ui/dlg/detailpages.hxx
new file mode 100644
index 000000000..2952f42e6
--- /dev/null
+++ b/dbaccess/source/ui/dlg/detailpages.hxx
@@ -0,0 +1,253 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include "adminpages.hxx"
+#include <charsetlistbox.hxx>
+#include "TextConnectionHelper.hxx"
+#include "admincontrols.hxx"
+
+#include <o3tl/typed_flags_set.hxx>
+
+enum class OCommonBehaviourTabPageFlags {
+ NONE = 0x0000,
+ UseCharset = 0x0002,
+ UseOptions = 0x0004,
+};
+namespace o3tl {
+ template<> struct typed_flags<OCommonBehaviourTabPageFlags> : is_typed_flags<OCommonBehaviourTabPageFlags, 0x0006> {};
+}
+
+namespace dbaui
+{
+ /** eases the implementation of tab pages handling user/password and/or character
+ set and/or generic options input
+ <BR>
+ The controls to be used have to be defined within the resource, as usual, but
+ this class does all the handling necessary.
+ */
+ class OCommonBehaviourTabPage : public OGenericAdministrationPage
+ {
+ OCommonBehaviourTabPageFlags m_nControlFlags;
+
+ std::unique_ptr<weld::Label> m_xOptionsLabel;
+ std::unique_ptr<weld::Entry> m_xOptions;
+
+ std::unique_ptr<weld::Label> m_xDataConvertLabel;
+ std::unique_ptr<weld::Label> m_xCharsetLabel;
+ std::unique_ptr<CharSetListBox> m_xCharset;
+
+ std::unique_ptr<weld::CheckButton> m_xAutoRetrievingEnabled;
+ std::unique_ptr<weld::Label> m_xAutoIncrementLabel;
+ std::unique_ptr<weld::Entry> m_xAutoIncrement;
+ std::unique_ptr<weld::Label> m_xAutoRetrievingLabel;
+ std::unique_ptr<weld::Entry> m_xAutoRetrieving;
+
+ public:
+ virtual bool FillItemSet (SfxItemSet* _rCoreAttrs) override;
+
+ OCommonBehaviourTabPage(weld::Container* pPage, weld::DialogController* pController, const OUString& rUIXMLDescription, const OString& rId, const SfxItemSet& _rCoreAttrs, OCommonBehaviourTabPageFlags nControlFlags);
+ protected:
+
+ virtual ~OCommonBehaviourTabPage() override;
+
+ // subclasses must override this, but it isn't pure virtual
+ virtual void implInitControls(const SfxItemSet& _rSet, bool _bSaveValue) override;
+
+ // <method>OGenericAdministrationPage::fillControls</method>
+ virtual void fillControls(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) override;
+
+ // <method>OGenericAdministrationPage::fillWindows</method>
+ virtual void fillWindows(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) override;
+ private:
+ DECL_LINK(CharsetSelectHdl, weld::ComboBox&, void);
+ };
+
+
+ // ODbaseDetailsPage
+ class ODbaseDetailsPage : public OCommonBehaviourTabPage
+ {
+ public:
+ virtual bool FillItemSet ( SfxItemSet* _rCoreAttrs ) override;
+
+ ODbaseDetailsPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& _rCoreAttrs);
+ virtual ~ODbaseDetailsPage() override;
+ private:
+ OUString m_sDsn;
+
+ std::unique_ptr<weld::CheckButton> m_xShowDeleted;
+ std::unique_ptr<weld::Label> m_xFT_Message;
+ std::unique_ptr<weld::Button> m_xIndexes;
+
+ protected:
+ virtual void implInitControls(const SfxItemSet& _rSet, bool _bSaveValue) override;
+
+ private:
+ DECL_LINK(OnButtonClicked, weld::Button&, void);
+ DECL_LINK(OnButtonToggled, weld::Toggleable&, void);
+ };
+
+ // OAdoDetailsPage
+ class OAdoDetailsPage : public OCommonBehaviourTabPage
+ {
+ public:
+ OAdoDetailsPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rCoreAttrs);
+ };
+
+ // OOdbcDetailsPage
+ class OOdbcDetailsPage : public OCommonBehaviourTabPage
+ {
+ public:
+ virtual bool FillItemSet ( SfxItemSet* _rCoreAttrs ) override;
+
+ OOdbcDetailsPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rCoreAttrs);
+ virtual ~OOdbcDetailsPage() override;
+ protected:
+ virtual void implInitControls(const SfxItemSet& _rSet, bool _bSaveValue) override;
+ private:
+ std::unique_ptr<weld::CheckButton> m_xUseCatalog;
+ };
+
+ // OUserDriverDetailsPage
+ class OUserDriverDetailsPage : public OCommonBehaviourTabPage
+ {
+ public:
+ virtual bool FillItemSet ( SfxItemSet* _rCoreAttrs ) override;
+
+ OUserDriverDetailsPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& _rCoreAttrs);
+ virtual ~OUserDriverDetailsPage() override;
+ protected:
+ virtual void implInitControls(const SfxItemSet& _rSet, bool _bSaveValue) override;
+ virtual void fillControls(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) override;
+ virtual void fillWindows(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) override;
+ private:
+ std::unique_ptr<weld::Label> m_xFTHostname;
+ std::unique_ptr<weld::Entry> m_xEDHostname;
+ std::unique_ptr<weld::Label> m_xPortNumber;
+ std::unique_ptr<weld::SpinButton> m_xNFPortNumber;
+ std::unique_ptr<weld::CheckButton> m_xUseCatalog;
+ };
+
+ // OMySQLODBCDetailsPage
+ class OMySQLODBCDetailsPage : public OCommonBehaviourTabPage
+ {
+ public:
+ OMySQLODBCDetailsPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rCoreAttrs);
+ };
+
+ // OGeneralSpecialJDBCDetailsPage
+ class OGeneralSpecialJDBCDetailsPage final : public OCommonBehaviourTabPage
+ {
+ public:
+ OGeneralSpecialJDBCDetailsPage(weld::Container* pPage, weld::DialogController* pController,
+ const SfxItemSet& _rCoreAttrs,
+ sal_uInt16 _nPortId,
+ bool bShowSocket = true);
+ virtual ~OGeneralSpecialJDBCDetailsPage() override;
+
+ private:
+
+ virtual bool FillItemSet( SfxItemSet* _rCoreAttrs ) override;
+ virtual void implInitControls(const SfxItemSet& _rSet, bool _bSaveValue) override;
+ virtual void callModifiedHdl(weld::Widget* pControl = nullptr) override;
+
+ DECL_LINK(OnTestJavaClickHdl, weld::Button&, void);
+
+ OUString m_sDefaultJdbcDriverName;
+ sal_uInt16 m_nPortId;
+ bool m_bUseClass;
+
+ std::unique_ptr<weld::Entry> m_xEDHostname;
+ std::unique_ptr<weld::SpinButton> m_xNFPortNumber;
+ std::unique_ptr<weld::Label> m_xFTSocket;
+ std::unique_ptr<weld::Entry> m_xEDSocket;
+ std::unique_ptr<weld::Label> m_xFTDriverClass;
+ std::unique_ptr<weld::Entry> m_xEDDriverClass;
+ std::unique_ptr<weld::Button> m_xTestJavaDriver;
+ };
+
+ // MySQLNativePage
+ class MySQLNativePage : public OCommonBehaviourTabPage
+ {
+ public:
+ MySQLNativePage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rCoreAttrs);
+ virtual ~MySQLNativePage() override;
+
+ private:
+ std::unique_ptr<weld::Widget> m_xMySQLSettingsContainer;
+ std::unique_ptr<MySQLNativeSettings> m_xMySQLSettings;
+ std::unique_ptr<weld::Label> m_xSeparator1;
+ std::unique_ptr<weld::Label> m_xSeparator2;
+ std::unique_ptr<weld::Label> m_xUserNameLabel;
+ std::unique_ptr<weld::Entry> m_xUserName;
+ std::unique_ptr<weld::CheckButton> m_xPasswordRequired;
+
+ protected:
+ virtual bool FillItemSet( SfxItemSet* _rCoreAttrs ) override;
+ virtual void implInitControls(const SfxItemSet& _rSet, bool _bSaveValue) override;
+ virtual void fillControls(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) override;
+ virtual void fillWindows(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) override;
+ };
+
+ // OOdbcDetailsPage
+ class OLDAPDetailsPage : public OCommonBehaviourTabPage
+ {
+ public:
+ virtual bool FillItemSet ( SfxItemSet* _rCoreAttrs ) override;
+
+ OLDAPDetailsPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rCoreAttrs);
+ virtual ~OLDAPDetailsPage() override;
+ protected:
+ virtual void implInitControls(const SfxItemSet& _rSet, bool _bSaveValue) override;
+ private:
+ sal_Int32 m_iSSLPort;
+ sal_Int32 m_iNormalPort;
+
+ std::unique_ptr<weld::Entry> m_xETBaseDN;
+ std::unique_ptr<weld::CheckButton> m_xCBUseSSL;
+ std::unique_ptr<weld::SpinButton> m_xNFPortNumber;
+ std::unique_ptr<weld::SpinButton> m_xNFRowCount;
+
+ DECL_LINK(OnCheckBoxClick, weld::Toggleable&, void);
+ };
+
+ // OTextDetailsPage
+ class OTextDetailsPage : public OCommonBehaviourTabPage
+ {
+ public:
+ virtual bool FillItemSet ( SfxItemSet* _rCoreAttrs ) override;
+
+ OTextDetailsPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rCoreAttrs);
+ virtual ~OTextDetailsPage() override;
+
+ protected:
+ virtual bool prepareLeave() override;
+
+ virtual void implInitControls(const SfxItemSet& _rSet, bool _bSaveValue) override;
+ virtual void fillControls(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) override;
+ virtual void fillWindows(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) override;
+
+ private:
+ std::unique_ptr<OTextConnectionHelper> m_xTextConnectionHelper;
+ };
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/dlg/directsql.cxx b/dbaccess/source/ui/dlg/directsql.cxx
new file mode 100644
index 000000000..ba5d9d3be
--- /dev/null
+++ b/dbaccess/source/ui/dlg/directsql.cxx
@@ -0,0 +1,430 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <core_resource.hxx>
+#include <directsql.hxx>
+#include <sqledit.hxx>
+#include <strings.hxx>
+#include <strings.hrc>
+#include <comphelper/types.hxx>
+#include <osl/mutex.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <tools/diagnose_ex.h>
+#include <vcl/svapp.hxx>
+#include <vcl/weld.hxx>
+#include <com/sun/star/sdbc/SQLException.hpp>
+#include <com/sun/star/sdbc/XRow.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/sdbc/XMultipleResults.hpp>
+
+namespace dbaui
+{
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::sdbc;
+ using namespace ::com::sun::star::lang;
+
+ constexpr sal_Int32 g_nHistoryLimit = 20;
+
+ // DirectSQLDialog
+ DirectSQLDialog::DirectSQLDialog(weld::Window* _pParent, const Reference< XConnection >& _rxConn)
+ : GenericDialogController(_pParent, "dbaccess/ui/directsqldialog.ui", "DirectSQLDialog")
+ , m_xExecute(m_xBuilder->weld_button("execute"))
+ , m_xSQLHistory(m_xBuilder->weld_combo_box("sqlhistory"))
+ , m_xStatus(m_xBuilder->weld_text_view("status"))
+ , m_xDirectSQL(m_xBuilder->weld_check_button("directsql"))
+ , m_xShowOutput(m_xBuilder->weld_check_button("showoutput"))
+ , m_xOutput(m_xBuilder->weld_text_view("output"))
+ , m_xClose(m_xBuilder->weld_button("close"))
+ , m_xSQL(new SQLEditView(m_xBuilder->weld_scrolled_window("scrolledwindow", true)))
+ , m_xSQLEd(new weld::CustomWeld(*m_xBuilder, "sql", *m_xSQL))
+ , m_nStatusCount(1)
+ , m_xConnection(_rxConn)
+ , m_pClosingEvent(nullptr)
+ {
+ int nWidth = m_xStatus->get_approximate_digit_width() * 60;
+ int nHeight = m_xStatus->get_height_rows(7);
+
+ m_xSQLEd->set_size_request(nWidth, nHeight);
+ m_xStatus->set_size_request(-1, nHeight);
+ m_xOutput->set_size_request(-1, nHeight);
+
+ m_xSQL->GrabFocus();
+
+ m_xExecute->connect_clicked(LINK(this, DirectSQLDialog, OnExecute));
+ m_xClose->connect_clicked(LINK(this, DirectSQLDialog, OnCloseClick));
+ m_xSQLHistory->connect_changed(LINK(this, DirectSQLDialog, OnListEntrySelected));
+
+ // add a dispose listener to the connection
+ Reference< XComponent > xConnComp(m_xConnection, UNO_QUERY);
+ OSL_ENSURE(xConnComp.is(), "DirectSQLDialog::DirectSQLDialog: invalid connection!");
+ if (xConnComp.is())
+ startComponentListening(xConnComp);
+
+ m_xSQL->SetModifyHdl(LINK(this, DirectSQLDialog, OnStatementModified));
+ OnStatementModified(nullptr);
+ }
+
+ DirectSQLDialog::~DirectSQLDialog()
+ {
+ ::osl::MutexGuard aGuard(m_aMutex);
+ if (m_pClosingEvent)
+ Application::RemoveUserEvent(m_pClosingEvent);
+ stopAllComponentListening();
+ }
+
+ void DirectSQLDialog::_disposing( const EventObject& _rSource )
+ {
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard(m_aMutex);
+
+ assert(!m_pClosingEvent);
+
+ OSL_ENSURE(Reference< XConnection >(_rSource.Source, UNO_QUERY).get() == m_xConnection.get(),
+ "DirectSQLDialog::_disposing: where does this come from?");
+
+ {
+ OUString sMessage(DBA_RES(STR_DIRECTSQL_CONNECTIONLOST));
+ std::unique_ptr<weld::MessageDialog> xError(Application::CreateMessageDialog(m_xDialog.get(),
+ VclMessageType::Warning, VclButtonsType::Ok,
+ sMessage));
+ xError->run();
+ }
+
+ m_pClosingEvent = Application::PostUserEvent(LINK(this, DirectSQLDialog, OnClose));
+ }
+
+ sal_Int32 DirectSQLDialog::getHistorySize() const
+ {
+ #ifdef DBG_UTIL
+ {
+ const char* pError = impl_CheckInvariants();
+ if (pError)
+ SAL_WARN("dbaccess.ui", "DirectSQLDialog::getHistorySize: " << pError);
+ }
+ #endif
+ return m_aStatementHistory.size();
+ }
+
+ void DirectSQLDialog::implEnsureHistoryLimit()
+ {
+ #ifdef DBG_UTIL
+ {
+ const char* pError = impl_CheckInvariants();
+ if (pError)
+ SAL_WARN("dbaccess.ui", "DirectSQLDialog::implEnsureHistoryLimit: " << pError);
+ }
+ #endif
+
+ if (getHistorySize() <= g_nHistoryLimit)
+ // nothing to do
+ return;
+
+ sal_Int32 nRemoveEntries = getHistorySize() - g_nHistoryLimit;
+ while (nRemoveEntries--)
+ {
+ m_aStatementHistory.pop_front();
+ m_aNormalizedHistory.pop_front();
+ m_xSQLHistory->remove(0);
+ }
+ }
+
+ void DirectSQLDialog::implAddToStatementHistory(const OUString& _rStatement)
+ {
+ #ifdef DBG_UTIL
+ {
+ const char* pError = impl_CheckInvariants();
+ if (pError)
+ SAL_WARN("dbaccess.ui", "DirectSQLDialog::implAddToStatementHistor: " << pError);
+ }
+ #endif
+
+ // add the statement to the history
+ m_aStatementHistory.push_back(_rStatement);
+
+ // normalize the statement, and remember the normalized form, too
+ OUString sNormalized = _rStatement.replaceAll("\n", " ");
+ m_aNormalizedHistory.push_back(sNormalized);
+
+ // add the normalized version to the list box
+ m_xSQLHistory->append_text(sNormalized);
+
+ // ensure that we don't exceed the history limit
+ implEnsureHistoryLimit();
+ }
+
+#ifdef DBG_UTIL
+ const char* DirectSQLDialog::impl_CheckInvariants() const
+ {
+ if (m_aStatementHistory.size() != m_aNormalizedHistory.size())
+ return "statement history is inconsistent!";
+
+ if (!m_xSQLHistory)
+ return "invalid listbox!";
+
+ if (m_aStatementHistory.size() != static_cast<size_t>(m_xSQLHistory->get_count()))
+ return "invalid listbox entry count!";
+
+ if (!m_xConnection.is())
+ return "have no connection!";
+
+ return nullptr;
+ }
+#endif
+
+ void DirectSQLDialog::implExecuteStatement(const OUString& _rStatement)
+ {
+ #ifdef DBG_UTIL
+ {
+ const char* pError = impl_CheckInvariants();
+ if (pError)
+ SAL_WARN("dbaccess.ui", "DirectSQLDialog::implExecuteStatement: " << pError);
+ }
+ #endif
+
+ ::osl::MutexGuard aGuard(m_aMutex);
+
+ OUString sStatus;
+
+ // clear the output box
+ m_xOutput->set_text(OUString());
+ try
+ {
+ // create a statement
+ Reference< XStatement > xStatement = m_xConnection->createStatement();
+
+ if (m_xDirectSQL->get_active())
+ {
+ Reference< com::sun::star::beans::XPropertySet > xStatementProps(xStatement, UNO_QUERY_THROW);
+ try
+ {
+ xStatementProps->setPropertyValue(PROPERTY_ESCAPE_PROCESSING, Any(false));
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+
+ Reference<XDatabaseMetaData> xMeta = m_xConnection->getMetaData();
+ css::uno::Reference< css::sdbc::XMultipleResults > xMR ( xStatement, UNO_QUERY );
+
+ if (xMeta.is() && xMeta->supportsMultipleResultSets() && xMR.is())
+ {
+ bool hasRS = xStatement->execute(_rStatement);
+ if(hasRS)
+ {
+ css::uno::Reference< css::sdbc::XResultSet > xRS (xMR->getResultSet());
+ if (m_xShowOutput->get_active())
+ display(xRS);
+ }
+ else
+ addOutputText(
+ OUStringConcatenation(OUString::number(xMR->getUpdateCount()) + " rows updated\n"));
+ for (;;)
+ {
+ hasRS = xMR->getMoreResults();
+ if (!hasRS && xMR->getUpdateCount() == -1)
+ break;
+ if(hasRS)
+ {
+ css::uno::Reference< css::sdbc::XResultSet > xRS (xMR->getResultSet());
+ if (m_xShowOutput->get_active())
+ display(xRS);
+ }
+ }
+ }
+ else
+ {
+ const OUString upperStatement = _rStatement.toAsciiUpperCase();
+ if (upperStatement.startsWith("UPDATE"))
+ {
+ sal_Int32 resultCount = xStatement->executeUpdate(_rStatement);
+ addOutputText(OUStringConcatenation(OUString::number(resultCount) + " rows updated\n"));
+ }
+ else if (upperStatement.startsWith("INSERT"))
+ {
+ sal_Int32 resultCount = xStatement->executeUpdate(_rStatement);
+ addOutputText(OUStringConcatenation(OUString::number(resultCount) + " rows inserted\n"));
+ }
+ else if (upperStatement.startsWith("DELETE"))
+ {
+ sal_Int32 resultCount = xStatement->executeUpdate(_rStatement);
+ addOutputText(OUStringConcatenation(OUString::number(resultCount) + " rows deleted\n"));
+ }
+ else if (upperStatement.startsWith("CREATE"))
+ {
+ xStatement->executeUpdate(_rStatement);
+ addOutputText(u"Command executed\n");
+ }
+ else if (upperStatement.startsWith("SELECT") || m_xShowOutput->get_active())
+ {
+ css::uno::Reference< css::sdbc::XResultSet > xRS = xStatement->executeQuery(_rStatement);
+ if (m_xShowOutput->get_active())
+ display(xRS);
+ }
+ else
+ {
+ sal_Int32 resultCount = xStatement->executeUpdate(_rStatement);
+ addOutputText(OUStringConcatenation(OUString::number(resultCount) + " rows updated\n"));
+ }
+ }
+ // successful
+ sStatus = DBA_RES(STR_COMMAND_EXECUTED_SUCCESSFULLY);
+
+ // dispose the statement
+ ::comphelper::disposeComponent(xStatement);
+ }
+ catch(const SQLException& e)
+ {
+ sStatus = e.Message;
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+
+ // add the status text
+ addStatusText(sStatus);
+ }
+
+ void DirectSQLDialog::display(const css::uno::Reference< css::sdbc::XResultSet >& xRS)
+ {
+ // get a handle for the rows
+ css::uno::Reference< css::sdbc::XRow > xRow( xRS, css::uno::UNO_QUERY );
+ // work through each of the rows
+ while (xRS->next())
+ {
+ // initialise the output line for each row
+ OUStringBuffer out;
+ // work along the columns until that are none left
+ try
+ {
+ int i = 1;
+ for (;;)
+ {
+ // be dumb, treat everything as a string
+ out.append(xRow->getString(i) + ",");
+ i++;
+ }
+ }
+ // trap for when we fall off the end of the row
+ catch (const SQLException&)
+ {
+ }
+ // report the output
+ addOutputText(out);
+ }
+ }
+
+ void DirectSQLDialog::addStatusText(std::u16string_view _rMessage)
+ {
+ OUString sAppendMessage = OUString::number(m_nStatusCount++) + ": " + _rMessage + "\n\n";
+
+ OUString sCompleteMessage = m_xStatus->get_text() + sAppendMessage;
+ m_xStatus->set_text(sCompleteMessage);
+
+ m_xStatus->select_region(sCompleteMessage.getLength(), sCompleteMessage.getLength());
+ }
+
+ void DirectSQLDialog::addOutputText(std::u16string_view _rMessage)
+ {
+ OUString sAppendMessage = OUString::Concat(_rMessage) + "\n";
+
+ OUString sCompleteMessage = m_xOutput->get_text() + sAppendMessage;
+ m_xOutput->set_text(sCompleteMessage);
+ }
+
+ void DirectSQLDialog::executeCurrent()
+ {
+ #ifdef DBG_UTIL
+ {
+ const char* pError = impl_CheckInvariants();
+ if (pError)
+ SAL_WARN("dbaccess.ui", "DirectSQLDialog::executeCurrent: " << pError);
+ }
+ #endif
+
+ OUString sStatement = m_xSQL->GetText();
+
+ // execute
+ implExecuteStatement(sStatement);
+
+ // add the statement to the history
+ implAddToStatementHistory(sStatement);
+
+ m_xSQL->GrabFocus();
+ }
+
+ void DirectSQLDialog::switchToHistory(sal_Int32 _nHistoryPos)
+ {
+ #ifdef DBG_UTIL
+ {
+ const char* pError = impl_CheckInvariants();
+ if (pError)
+ SAL_WARN("dbaccess.ui", "DirectSQLDialog::switchToHistory: " << pError);
+ }
+ #endif
+
+ if ((_nHistoryPos >= 0) && (_nHistoryPos < getHistorySize()))
+ {
+ // set the text in the statement editor
+ OUString sStatement = m_aStatementHistory[_nHistoryPos];
+ m_xSQL->SetTextAndUpdate(sStatement);
+ OnStatementModified(nullptr);
+
+ m_xSQL->GrabFocus();
+ }
+ else
+ OSL_FAIL("DirectSQLDialog::switchToHistory: invalid position!");
+ }
+
+ IMPL_LINK_NOARG( DirectSQLDialog, OnStatementModified, LinkParamNone*, void )
+ {
+ m_xExecute->set_sensitive(!m_xSQL->GetText().isEmpty());
+ }
+
+ IMPL_LINK_NOARG( DirectSQLDialog, OnCloseClick, weld::Button&, void )
+ {
+ m_xDialog->response(RET_OK);
+ }
+
+ IMPL_LINK_NOARG( DirectSQLDialog, OnClose, void*, void )
+ {
+ assert(m_pClosingEvent);
+ Application::RemoveUserEvent(m_pClosingEvent);
+ m_pClosingEvent = nullptr;
+
+ m_xDialog->response(RET_OK);
+ }
+
+ IMPL_LINK_NOARG( DirectSQLDialog, OnExecute, weld::Button&, void )
+ {
+ executeCurrent();
+ }
+
+ IMPL_LINK_NOARG( DirectSQLDialog, OnListEntrySelected, weld::ComboBox&, void )
+ {
+ const sal_Int32 nSelected = m_xSQLHistory->get_active();
+ if (nSelected != -1)
+ switchToHistory(nSelected);
+ }
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/dlg/dlgattr.cxx b/dbaccess/source/ui/dlg/dlgattr.cxx
new file mode 100644
index 000000000..1df2acc20
--- /dev/null
+++ b/dbaccess/source/ui/dlg/dlgattr.cxx
@@ -0,0 +1,60 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <dlgattr.hxx>
+
+#include <sfx2/tabdlg.hxx>
+
+#include <svx/numinf.hxx>
+
+#include <svx/dialogs.hrc>
+#include <svl/itemset.hxx>
+#include <svx/svxids.hrc>
+
+using namespace dbaui;
+
+
+SbaSbAttrDlg::SbaSbAttrDlg(weld::Widget* pParent, const SfxItemSet* pCellAttrs,
+ SvNumberFormatter* pFormatter, bool bHasFormat)
+ : SfxTabDialogController(pParent, "dbaccess/ui/fielddialog.ui", "FieldDialog", pCellAttrs)
+{
+ pNumberInfoItem.reset( new SvxNumberInfoItem( pFormatter, SID_ATTR_NUMBERFORMAT_INFO ) );
+
+ if (bHasFormat)
+ AddTabPage("format", RID_SVXPAGE_NUMBERFORMAT);
+ else
+ RemoveTabPage("format");
+ AddTabPage("alignment", RID_SVXPAGE_ALIGNMENT);
+}
+
+SbaSbAttrDlg::~SbaSbAttrDlg()
+{
+}
+
+void SbaSbAttrDlg::PageCreated(const OString& rPageId, SfxTabPage& rTabPage)
+{
+ SfxAllItemSet aSet(*(GetInputSetImpl()->GetPool()));
+ if (rPageId == "format")
+ {
+ aSet.Put (SvxNumberInfoItem( pNumberInfoItem->GetNumberFormatter(), SID_ATTR_NUMBERFORMAT_INFO));
+ rTabPage.PageCreated(aSet);
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/dlg/dlgsave.cxx b/dbaccess/source/ui/dlg/dlgsave.cxx
new file mode 100644
index 000000000..ce5d16881
--- /dev/null
+++ b/dbaccess/source/ui/dlg/dlgsave.cxx
@@ -0,0 +1,351 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <dlgsave.hxx>
+#include <core_resource.hxx>
+#include <strings.hrc>
+#include <com/sun/star/sdb/CommandType.hpp>
+#include <com/sun/star/sdbc/XRow.hpp>
+#include <connectivity/dbtools.hxx>
+#include <UITools.hxx>
+#include <SqlNameEdit.hxx>
+#include <com/sun/star/sdbc/XDatabaseMetaData.hpp>
+#include <objectnamecheck.hxx>
+#include <tools/diagnose_ex.h>
+
+using namespace dbaui;
+using namespace dbtools;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::sdb;
+using namespace ::com::sun::star::sdbc;
+namespace dbaui
+{
+
+class OSaveAsDlgImpl
+{
+public:
+ OUString m_aQryLabel;
+ OUString m_sTblLabel;
+ OUString m_aName;
+ const IObjectNameCheck& m_rObjectNameCheck;
+ css::uno::Reference< css::sdbc::XDatabaseMetaData> m_xMetaData;
+ sal_Int32 m_nType;
+ SADFlags m_nFlags;
+
+ OSQLNameChecker m_aChecker;
+
+ std::unique_ptr<weld::Label> m_xDescription;
+ std::unique_ptr<weld::Label> m_xCatalogLbl;
+ std::unique_ptr<weld::ComboBox> m_xCatalog;
+ std::unique_ptr<weld::Label> m_xSchemaLbl;
+ std::unique_ptr<weld::ComboBox> m_xSchema;
+ std::unique_ptr<weld::Label> m_xLabel;
+ std::unique_ptr<weld::Entry> m_xTitle;
+ std::unique_ptr<weld::Button> m_xPB_OK;
+
+ DECL_LINK(TextFilterHdl, OUString&, bool);
+
+ OSaveAsDlgImpl( weld::Builder* pParent, sal_Int32 _rType,
+ const css::uno::Reference< css::sdbc::XConnection>& _xConnection,
+ const OUString& rDefault,
+ const IObjectNameCheck& _rObjectNameCheck,
+ SADFlags _nFlags);
+ OSaveAsDlgImpl( weld::Builder* pParent,
+ const OUString& rDefault,
+ const IObjectNameCheck& _rObjectNameCheck,
+ SADFlags _nFlags);
+};
+
+} // dbaui
+
+IMPL_LINK(OSaveAsDlgImpl, TextFilterHdl, OUString&, rTest, bool)
+{
+ OUString sCorrected;
+ if (m_aChecker.checkString(rTest, sCorrected))
+ rTest = sCorrected;
+ return true;
+}
+
+OSaveAsDlgImpl::OSaveAsDlgImpl(weld::Builder* pBuilder,
+ sal_Int32 _rType,
+ const Reference< XConnection>& _xConnection,
+ const OUString& rDefault,
+ const IObjectNameCheck& _rObjectNameCheck,
+ SADFlags _nFlags)
+ : m_aQryLabel(DBA_RES(STR_QRY_LABEL))
+ , m_sTblLabel(DBA_RES(STR_TBL_LABEL))
+ , m_aName(rDefault)
+ , m_rObjectNameCheck( _rObjectNameCheck )
+ , m_nType(_rType)
+ , m_nFlags(_nFlags)
+ , m_aChecker(OUString())
+ , m_xDescription(pBuilder->weld_label("descriptionft"))
+ , m_xCatalogLbl(pBuilder->weld_label("catalogft"))
+ , m_xCatalog(pBuilder->weld_combo_box("catalog"))
+ , m_xSchemaLbl(pBuilder->weld_label("schemaft"))
+ , m_xSchema(pBuilder->weld_combo_box("schema"))
+ , m_xLabel(pBuilder->weld_label("titleft"))
+ , m_xTitle(pBuilder->weld_entry("title"))
+ , m_xPB_OK(pBuilder->weld_button("ok"))
+{
+ if ( _xConnection.is() )
+ m_xMetaData = _xConnection->getMetaData();
+
+ if (m_xMetaData.is())
+ {
+ OUString sExtraNameChars(m_xMetaData->getExtraNameCharacters());
+ m_aChecker.setAllowedChars(sExtraNameChars);
+ }
+
+ m_xTitle->connect_insert_text(LINK(this, OSaveAsDlgImpl, TextFilterHdl));
+ m_xSchema->connect_entry_insert_text(LINK(this, OSaveAsDlgImpl, TextFilterHdl));
+ m_xCatalog->connect_entry_insert_text(LINK(this, OSaveAsDlgImpl, TextFilterHdl));
+}
+
+OSaveAsDlgImpl::OSaveAsDlgImpl(weld::Builder* pBuilder,
+ const OUString& rDefault,
+ const IObjectNameCheck& _rObjectNameCheck,
+ SADFlags _nFlags)
+ : m_aQryLabel(DBA_RES(STR_QRY_LABEL))
+ , m_sTblLabel(DBA_RES(STR_TBL_LABEL))
+ , m_aName(rDefault)
+ , m_rObjectNameCheck( _rObjectNameCheck )
+ , m_nType(CommandType::COMMAND)
+ , m_nFlags(_nFlags)
+ , m_aChecker(OUString())
+ , m_xDescription(pBuilder->weld_label("descriptionft"))
+ , m_xCatalogLbl(pBuilder->weld_label("catalogft"))
+ , m_xCatalog(pBuilder->weld_combo_box("catalog"))
+ , m_xSchemaLbl(pBuilder->weld_label("schemaft"))
+ , m_xSchema(pBuilder->weld_combo_box("schema"))
+ , m_xLabel(pBuilder->weld_label("titleft"))
+ , m_xTitle(pBuilder->weld_entry("title"))
+ , m_xPB_OK(pBuilder->weld_button("ok"))
+{
+ m_xTitle->connect_insert_text(LINK(this, OSaveAsDlgImpl, TextFilterHdl));
+ m_xSchema->connect_entry_insert_text(LINK(this, OSaveAsDlgImpl, TextFilterHdl));
+ m_xCatalog->connect_entry_insert_text(LINK(this, OSaveAsDlgImpl, TextFilterHdl));
+}
+
+using namespace ::com::sun::star::lang;
+
+namespace
+{
+typedef Reference< XResultSet > (SAL_CALL XDatabaseMetaData::*FGetMetaStrings)();
+
+void lcl_fillComboList( weld::ComboBox& _rList, const Reference< XConnection >& _rxConnection,
+ FGetMetaStrings GetAll, const OUString& _rCurrent )
+{
+ try {
+ Reference< XDatabaseMetaData > xMetaData( _rxConnection->getMetaData(), UNO_SET_THROW );
+
+ Reference< XResultSet > xRes = (xMetaData.get()->*GetAll)();
+ Reference< XRow > xRow( xRes, UNO_QUERY_THROW );
+ OUString sValue;
+ while ( xRes->next() ) {
+ sValue = xRow->getString( 1 );
+ if ( !xRow->wasNull() )
+ _rList.append_text( sValue );
+ }
+
+ int nPos = _rList.find_text( _rCurrent );
+ if (nPos != -1)
+ _rList.set_active( nPos );
+ else
+ _rList.set_active( 0 );
+ } catch( const Exception& ) {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+}
+}
+
+OSaveAsDlg::OSaveAsDlg( weld::Window * pParent,
+ sal_Int32 _rType,
+ const Reference< XComponentContext >& _rxContext,
+ const Reference< XConnection>& _xConnection,
+ const OUString& rDefault,
+ const IObjectNameCheck& _rObjectNameCheck,
+ SADFlags _nFlags)
+ : GenericDialogController(pParent, "dbaccess/ui/savedialog.ui", "SaveDialog")
+ , m_xContext( _rxContext )
+{
+ m_pImpl.reset( new OSaveAsDlgImpl(m_xBuilder.get(),_rType,_xConnection,rDefault,_rObjectNameCheck,_nFlags) );
+
+ switch (_rType) {
+ case CommandType::QUERY:
+ implInitOnlyTitle(m_pImpl->m_aQryLabel);
+ break;
+
+ case CommandType::TABLE:
+ OSL_ENSURE( m_pImpl->m_xMetaData.is(), "OSaveAsDlg::OSaveAsDlg: no meta data for entering table names: this will crash!" );
+ {
+ m_pImpl->m_xLabel->set_label(m_pImpl->m_sTblLabel);
+ if(m_pImpl->m_xMetaData.is() && !m_pImpl->m_xMetaData->supportsCatalogsInTableDefinitions()) {
+ m_pImpl->m_xCatalogLbl->hide();
+ m_pImpl->m_xCatalog->hide();
+ } else {
+ // now fill the catalogs
+ lcl_fillComboList( *m_pImpl->m_xCatalog, _xConnection,
+ &XDatabaseMetaData::getCatalogs, _xConnection->getCatalog() );
+ }
+
+ if ( !m_pImpl->m_xMetaData->supportsSchemasInTableDefinitions()) {
+ m_pImpl->m_xSchemaLbl->hide();
+ m_pImpl->m_xSchema->hide();
+ } else {
+ lcl_fillComboList( *m_pImpl->m_xSchema, _xConnection,
+ &XDatabaseMetaData::getSchemas, m_pImpl->m_xMetaData->getUserName() );
+ }
+
+ OSL_ENSURE(m_pImpl->m_xMetaData.is(),"The metadata can not be null!");
+ if(m_pImpl->m_aName.indexOf('.') != -1) {
+ OUString sCatalog,sSchema,sTable;
+ ::dbtools::qualifiedNameComponents(m_pImpl->m_xMetaData,
+ m_pImpl->m_aName,
+ sCatalog,
+ sSchema,
+ sTable,
+ ::dbtools::EComposeRule::InDataManipulation);
+
+ int nPos = m_pImpl->m_xCatalog->find_text(sCatalog);
+ if (nPos != -1)
+ m_pImpl->m_xCatalog->set_active(nPos);
+
+ if ( !sSchema.isEmpty() ) {
+ nPos = m_pImpl->m_xSchema->find_text(sSchema);
+ if (nPos != -1)
+ m_pImpl->m_xSchema->set_active(nPos);
+ }
+ m_pImpl->m_xTitle->set_text(sTable);
+ } else
+ m_pImpl->m_xTitle->set_text(m_pImpl->m_aName);
+ m_pImpl->m_xTitle->select_region(0, -1);
+
+ sal_Int32 nLength = m_pImpl->m_xMetaData.is() ? m_pImpl->m_xMetaData->getMaxTableNameLength() : 0;
+ if (nLength)
+ {
+ m_pImpl->m_xTitle->set_max_length(nLength);
+ m_pImpl->m_xSchema->set_entry_max_length(nLength);
+ m_pImpl->m_xCatalog->set_entry_max_length(nLength);
+ }
+
+ bool bCheck = _xConnection.is() && isSQL92CheckEnabled(_xConnection);
+ m_pImpl->m_aChecker.setCheck(bCheck); // enable non valid sql chars as well
+ }
+ break;
+
+ default:
+ OSL_FAIL( "OSaveAsDlg::OSaveAsDlg: Type not supported yet!" );
+ }
+
+ implInit();
+}
+
+OSaveAsDlg::OSaveAsDlg(weld::Window * pParent,
+ const Reference< XComponentContext >& _rxContext,
+ const OUString& rDefault,
+ const OUString& _sLabel,
+ const IObjectNameCheck& _rObjectNameCheck,
+ SADFlags _nFlags)
+ : GenericDialogController(pParent, "dbaccess/ui/savedialog.ui", "SaveDialog")
+ , m_xContext( _rxContext )
+{
+ m_pImpl.reset( new OSaveAsDlgImpl(m_xBuilder.get(),rDefault,_rObjectNameCheck,_nFlags) );
+ implInitOnlyTitle(_sLabel);
+ implInit();
+}
+
+OSaveAsDlg::~OSaveAsDlg()
+{
+}
+
+IMPL_LINK_NOARG(OSaveAsDlg, ButtonClickHdl, weld::Button&, void)
+{
+ m_pImpl->m_aName = m_pImpl->m_xTitle->get_text();
+
+ OUString sNameToCheck( m_pImpl->m_aName );
+
+ if ( m_pImpl->m_nType == CommandType::TABLE ) {
+ sNameToCheck = ::dbtools::composeTableName(
+ m_pImpl->m_xMetaData,
+ getCatalog(),
+ getSchema(),
+ sNameToCheck,
+ false, // no quoting
+ ::dbtools::EComposeRule::InDataManipulation
+ );
+ }
+
+ SQLExceptionInfo aNameError;
+ if ( m_pImpl->m_rObjectNameCheck.isNameValid( sNameToCheck, aNameError ) )
+ m_xDialog->response(RET_OK);
+
+ showError(aNameError, m_xDialog->GetXWindow(), m_xContext);
+ m_pImpl->m_xTitle->grab_focus();
+}
+
+IMPL_LINK_NOARG(OSaveAsDlg, EditModifyHdl, weld::Entry&, void)
+{
+ m_pImpl->m_xPB_OK->set_sensitive(!m_pImpl->m_xTitle->get_text().isEmpty());
+}
+
+void OSaveAsDlg::implInitOnlyTitle(const OUString& _rLabel)
+{
+ m_pImpl->m_xLabel->set_label(_rLabel);
+ m_pImpl->m_xCatalogLbl->hide();
+ m_pImpl->m_xCatalog->hide();
+ m_pImpl->m_xSchemaLbl->hide();
+ m_pImpl->m_xSchema->hide();
+
+ m_pImpl->m_xTitle->set_text(m_pImpl->m_aName);
+ m_pImpl->m_aChecker.setCheck(false); // enable non valid sql chars as well
+}
+
+void OSaveAsDlg::implInit()
+{
+ if ( !( m_pImpl->m_nFlags & SADFlags::AdditionalDescription ) ) {
+ // hide the description window
+ m_pImpl->m_xDescription->hide();
+ }
+
+ if ( SADFlags::TitlePasteAs == ( m_pImpl->m_nFlags & SADFlags::TitlePasteAs ) )
+ m_xDialog->set_title( DBA_RES( STR_TITLE_PASTE_AS ) );
+ else if ( SADFlags::TitleRename == ( m_pImpl->m_nFlags & SADFlags::TitleRename ) )
+ m_xDialog->set_title( DBA_RES( STR_TITLE_RENAME ) );
+
+ m_pImpl->m_xPB_OK->connect_clicked(LINK(this,OSaveAsDlg,ButtonClickHdl));
+ m_pImpl->m_xTitle->connect_changed(LINK(this,OSaveAsDlg,EditModifyHdl));
+ m_pImpl->m_xTitle->grab_focus();
+}
+
+const OUString& OSaveAsDlg::getName() const
+{
+ return m_pImpl->m_aName;
+}
+OUString OSaveAsDlg::getCatalog() const
+{
+ return m_pImpl->m_xCatalog->get_visible() ? m_pImpl->m_xCatalog->get_active_text() : OUString();
+}
+OUString OSaveAsDlg::getSchema() const
+{
+ return m_pImpl->m_xSchema->get_visible() ? m_pImpl->m_xSchema->get_active_text() : OUString();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/dlg/dlgsize.cxx b/dbaccess/source/ui/dlg/dlgsize.cxx
new file mode 100644
index 000000000..544d9577f
--- /dev/null
+++ b/dbaccess/source/ui/dlg/dlgsize.cxx
@@ -0,0 +1,83 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <dlgsize.hxx>
+
+namespace dbaui
+{
+
+#define DEF_ROW_HEIGHT 45
+#define DEF_COL_WIDTH 227
+
+DlgSize::DlgSize(weld::Window* pParent, sal_Int32 nVal, bool bRow, sal_Int32 _nAlternativeStandard )
+ : GenericDialogController(pParent, bRow ? OUString("dbaccess/ui/rowheightdialog.ui") : OUString("dbaccess/ui/colwidthdialog.ui"),
+ bRow ? OString("RowHeightDialog") : OString("ColWidthDialog"))
+ , m_nPrevValue(nVal)
+ , m_xMF_VALUE(m_xBuilder->weld_metric_spin_button("value", FieldUnit::CM))
+ , m_xCB_STANDARD(m_xBuilder->weld_check_button("automatic"))
+{
+ sal_Int32 nStandard(bRow ? DEF_ROW_HEIGHT : DEF_COL_WIDTH);
+ if ( _nAlternativeStandard > 0 )
+ nStandard = _nAlternativeStandard;
+ m_xCB_STANDARD->connect_toggled(LINK(this,DlgSize,CbClickHdl));
+
+ bool bDefault = -1 == nVal;
+ m_xCB_STANDARD->set_active(bDefault);
+ if (bDefault)
+ {
+ SetValue(nStandard);
+ m_nPrevValue = nStandard;
+ }
+ CbClickHdl(*m_xCB_STANDARD);
+}
+
+DlgSize::~DlgSize()
+{
+}
+
+void DlgSize::SetValue( sal_Int32 nVal )
+{
+ m_xMF_VALUE->set_value(nVal, FieldUnit::CM );
+}
+
+sal_Int32 DlgSize::GetValue() const
+{
+ if (m_xCB_STANDARD->get_active())
+ return -1;
+ return static_cast<sal_Int32>(m_xMF_VALUE->get_value( FieldUnit::CM ));
+}
+
+IMPL_LINK_NOARG(DlgSize, CbClickHdl, weld::Toggleable&, void)
+{
+ m_xMF_VALUE->set_sensitive(!m_xCB_STANDARD->get_active());
+ if (m_xCB_STANDARD->get_active())
+ {
+ // don't use getValue as this will use m_xCB_STANDARD->to determine if we're standard
+ m_nPrevValue = static_cast<sal_Int32>(m_xMF_VALUE->get_value(FieldUnit::CM));
+ m_xMF_VALUE->set_text("");
+ }
+ else
+ {
+ SetValue(m_nPrevValue);
+ }
+}
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/dlg/dsnItem.hxx b/dbaccess/source/ui/dlg/dsnItem.hxx
new file mode 100644
index 000000000..4ae414881
--- /dev/null
+++ b/dbaccess/source/ui/dlg/dsnItem.hxx
@@ -0,0 +1,48 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <svl/poolitem.hxx>
+
+namespace dbaccess
+{
+ class ODsnTypeCollection;
+}
+namespace dbaui
+{
+ // DbuTypeCollectionItem
+ /** allows an ODsnTypeCollection to be transported in an SfxItemSet
+ */
+ class DbuTypeCollectionItem : public SfxPoolItem
+ {
+ ::dbaccess::ODsnTypeCollection* m_pCollection;
+
+ public:
+ DbuTypeCollectionItem(sal_Int16 nWhich, ::dbaccess::ODsnTypeCollection* _pCollection);
+ DbuTypeCollectionItem(const DbuTypeCollectionItem& _rSource);
+
+ virtual bool operator==(const SfxPoolItem& _rItem) const override;
+ virtual DbuTypeCollectionItem* Clone(SfxItemPool* _pPool = nullptr) const override;
+
+ ::dbaccess::ODsnTypeCollection* getCollection() const { return m_pCollection; }
+ };
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/dlg/dsselect.cxx b/dbaccess/source/ui/dlg/dsselect.cxx
new file mode 100644
index 000000000..4c0b9a836
--- /dev/null
+++ b/dbaccess/source/ui/dlg/dsselect.cxx
@@ -0,0 +1,133 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "dsselect.hxx"
+
+#include <com/sun/star/sdbcx/XCreateCatalog.hpp>
+#include <com/sun/star/ui/dialogs/XExecutableDialog.hpp>
+
+namespace dbaui
+{
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::sdbcx;
+using namespace ::com::sun::star::ui::dialogs;
+
+ODatasourceSelectDialog::ODatasourceSelectDialog(weld::Window* _pParent, const std::set<OUString>& _rDatasources)
+ : GenericDialogController(_pParent, "dbaccess/ui/choosedatasourcedialog.ui", "ChooseDataSourceDialog")
+ , m_xDatasource(m_xBuilder->weld_tree_view("treeview"))
+ , m_xOk(m_xBuilder->weld_button("ok"))
+ , m_xCancel(m_xBuilder->weld_button("cancel"))
+ , m_xManageDatasources(m_xBuilder->weld_button("organize"))
+{
+ m_xDatasource->set_size_request(-1, m_xDatasource->get_height_rows(6));
+
+ fillListBox(_rDatasources);
+#ifdef HAVE_ODBC_ADMINISTRATION
+ // allow ODBC datasource management
+ m_xManageDatasources->show();
+ m_xManageDatasources->set_sensitive(true);
+ m_xManageDatasources->connect_clicked(LINK(this,ODatasourceSelectDialog,ManageClickHdl));
+#endif
+ m_xDatasource->connect_row_activated(LINK(this,ODatasourceSelectDialog,ListDblClickHdl));
+}
+
+ODatasourceSelectDialog::~ODatasourceSelectDialog()
+{
+}
+
+IMPL_LINK(ODatasourceSelectDialog, ListDblClickHdl, weld::TreeView&, rListBox, bool)
+{
+ if (rListBox.n_children())
+ m_xDialog->response(RET_OK);
+ return true;
+}
+
+short ODatasourceSelectDialog::run()
+{
+ short nRet = GenericDialogController::run();
+#ifdef HAVE_ODBC_ADMINISTRATION
+ if (m_xODBCManagement.get())
+ m_xODBCManagement->disableCallback();
+#endif
+ return nRet;
+}
+
+#ifdef HAVE_ODBC_ADMINISTRATION
+IMPL_LINK_NOARG(ODatasourceSelectDialog, ManageClickHdl, weld::Button&, void)
+{
+ if ( !m_xODBCManagement.get() )
+ m_xODBCManagement.reset( new OOdbcManagement( LINK( this, ODatasourceSelectDialog, ManageProcessFinished ) ) );
+
+ if ( !m_xODBCManagement->manageDataSources_async() )
+ {
+ // TODO: error message
+ m_xDatasource->grab_focus();
+ m_xManageDatasources->set_sensitive(false);
+ return;
+ }
+
+ m_xDatasource->set_sensitive(false);
+ m_xOk->set_sensitive(false);
+ m_xCancel->set_sensitive(false);
+ m_xManageDatasources->set_sensitive(false);
+
+ SAL_WARN_IF( !m_xODBCManagement->isRunning(), "dbaccess.ui", "ODatasourceSelectDialog::ManageClickHdl: success, but not running - you were *fast*!" );
+}
+
+IMPL_LINK_NOARG( ODatasourceSelectDialog, ManageProcessFinished, void*, void )
+{
+ m_xODBCManagement->receivedCallback();
+
+ std::set<OUString> aOdbcDatasources;
+ OOdbcEnumeration aEnumeration;
+ aEnumeration.getDatasourceNames( aOdbcDatasources );
+ fillListBox( aOdbcDatasources );
+
+ m_xDatasource->set_sensitive(true);
+ m_xOk->set_sensitive(true);
+ m_xCancel->set_sensitive(true);
+ m_xManageDatasources->set_sensitive(true);
+}
+
+#endif
+void ODatasourceSelectDialog::fillListBox(const std::set<OUString>& _rDatasources)
+{
+ OUString sSelected;
+ if (m_xDatasource->n_children())
+ sSelected = m_xDatasource->get_selected_text();
+ m_xDatasource->clear();
+ // fill the list
+ for (auto const& datasource : _rDatasources)
+ {
+ m_xDatasource->append_text(datasource);
+ }
+
+ if (m_xDatasource->n_children())
+ {
+ if (!sSelected.isEmpty())
+ m_xDatasource->select_text(sSelected);
+ else // select the first entry
+ m_xDatasource->select(0);
+ }
+}
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/dlg/dsselect.hxx b/dbaccess/source/ui/dlg/dsselect.hxx
new file mode 100644
index 000000000..87cdef17c
--- /dev/null
+++ b/dbaccess/source/ui/dlg/dsselect.hxx
@@ -0,0 +1,61 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <rtl/ustring.hxx>
+#include <vcl/weld.hxx>
+
+#include <memory>
+#include <set>
+
+class SfxItemSet;
+namespace dbaui
+{
+// ODatasourceSelector
+class ODatasourceSelectDialog final : public weld::GenericDialogController
+{
+ std::unique_ptr<weld::TreeView> m_xDatasource;
+ std::unique_ptr<weld::Button> m_xOk;
+ std::unique_ptr<weld::Button> m_xCancel;
+ std::unique_ptr<weld::Button> m_xManageDatasources;
+#ifdef HAVE_ODBC_ADMINISTRATION
+ std::unique_ptr<OOdbcManagement> m_xODBCManagement;
+#endif
+
+public:
+ ODatasourceSelectDialog(weld::Window* pParent, const std::set<OUString>& rDatasources);
+ virtual ~ODatasourceSelectDialog() override;
+ OUString GetSelected() const { return m_xDatasource->get_selected_text(); }
+ void Select(const OUString& _rEntry) { m_xDatasource->select_text(_rEntry); }
+
+ virtual short run() override;
+
+private:
+ DECL_LINK(ListDblClickHdl, weld::TreeView&, bool);
+#ifdef HAVE_ODBC_ADMINISTRATION
+ DECL_LINK(ManageClickHdl, weld::Button&, void);
+ DECL_LINK(ManageProcessFinished, void*, void);
+#endif
+ void fillListBox(const std::set<OUString>& _rDatasources);
+};
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/dlg/finteraction.cxx b/dbaccess/source/ui/dlg/finteraction.cxx
new file mode 100644
index 000000000..611119a0c
--- /dev/null
+++ b/dbaccess/source/ui/dlg/finteraction.cxx
@@ -0,0 +1,59 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "finteraction.hxx"
+#include <com/sun/star/ucb/InteractiveIOException.hpp>
+
+namespace dbaui
+{
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::task;
+ using namespace ::com::sun::star::ucb;
+
+ // OFilePickerInteractionHandler
+ OFilePickerInteractionHandler::OFilePickerInteractionHandler( const Reference< XInteractionHandler >& _rxMaster )
+ :m_xMaster( _rxMaster )
+ ,m_bDoesNotExist(false)
+ {
+ assert(m_xMaster.is());
+ }
+
+ OFilePickerInteractionHandler::~OFilePickerInteractionHandler( )
+ {
+ }
+
+ void SAL_CALL OFilePickerInteractionHandler::handle( const Reference< XInteractionRequest >& _rxRequest )
+ {
+ InteractiveIOException aIoException;
+ if ( _rxRequest->getRequest() >>= aIoException )
+ {
+ if ( IOErrorCode_NOT_EXISTING == aIoException.Code )
+ {
+ m_bDoesNotExist = true;
+ return;
+ }
+ }
+
+ if ( m_xMaster.is() )
+ m_xMaster->handle( _rxRequest );
+ }
+
+} // namespace svt
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/dlg/finteraction.hxx b/dbaccess/source/ui/dlg/finteraction.hxx
new file mode 100644
index 000000000..a487392a5
--- /dev/null
+++ b/dbaccess/source/ui/dlg/finteraction.hxx
@@ -0,0 +1,54 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <cppuhelper/implbase.hxx>
+#include <com/sun/star/task/XInteractionHandler.hpp>
+
+namespace dbaui
+{
+
+ // OFilePickerInteractionHandler
+ typedef ::cppu::WeakImplHelper< css::task::XInteractionHandler
+ > OFilePickerInteractionHandler_Base;
+
+ /** an InteractionHandler implementation which extends another handler with some customizability
+ */
+ class OFilePickerInteractionHandler final : public OFilePickerInteractionHandler_Base
+ {
+ css::uno::Reference< css::task::XInteractionHandler >
+ m_xMaster; // our master handler
+ bool m_bDoesNotExist;
+
+ public:
+ explicit OFilePickerInteractionHandler( const css::uno::Reference< css::task::XInteractionHandler >& _rxMaster );
+
+ bool isDoesNotExist() const { return m_bDoesNotExist; }
+
+ private:
+ // XInteractionHandler
+ virtual void SAL_CALL handle( const css::uno::Reference< css::task::XInteractionRequest >& _rxRequest ) override;
+
+ virtual ~OFilePickerInteractionHandler() override;
+ };
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/dlg/generalpage.cxx b/dbaccess/source/ui/dlg/generalpage.cxx
new file mode 100644
index 000000000..f7017187b
--- /dev/null
+++ b/dbaccess/source/ui/dlg/generalpage.cxx
@@ -0,0 +1,700 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <config_features.h>
+#include <core_resource.hxx>
+#include "dsnItem.hxx"
+#include "generalpage.hxx"
+#include <connectivity/dbexception.hxx>
+#include <strings.hrc>
+#include <dsitems.hxx>
+#include <sfx2/filedlghelper.hxx>
+#include <sfx2/docfilt.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/weld.hxx>
+#include <svl/stritem.hxx>
+#include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
+#include <UITools.hxx>
+#include <officecfg/Office/Common.hxx>
+#include <comphelper/processfactory.hxx>
+#include <unotools/confignode.hxx>
+#include <o3tl/safeint.hxx>
+#include <osl/diagnose.h>
+#include <sal/log.hxx>
+#include <dbwizsetup.hxx>
+
+namespace dbaui
+{
+ using namespace ::com::sun::star;
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::sdbc;
+ using namespace ::com::sun::star::beans;
+ using namespace ::com::sun::star::container;
+
+ // OGeneralPage
+ OGeneralPage::OGeneralPage(weld::Container* pPage, weld::DialogController* pController, const OUString& _rUIXMLDescription, const SfxItemSet& _rItems)
+ : OGenericAdministrationPage(pPage, pController, _rUIXMLDescription, "PageGeneral", _rItems)
+ , m_xSpecialMessage(m_xBuilder->weld_label("specialMessage"))
+ , m_eLastMessage(smNone)
+ , m_bInitTypeList(true)
+ , m_xDatasourceType(m_xBuilder->weld_combo_box("datasourceType"))
+ , m_pCollection(nullptr)
+ {
+ // extract the datasource type collection from the item set
+ const DbuTypeCollectionItem* pCollectionItem = dynamic_cast<const DbuTypeCollectionItem*>( _rItems.GetItem(DSID_TYPECOLLECTION) );
+ if (pCollectionItem)
+ m_pCollection = pCollectionItem->getCollection();
+ SAL_WARN_IF(!m_pCollection, "dbaccess.ui.generalpage", "OGeneralPage::OGeneralPage : really need a DSN type collection !");
+
+ // do some knittings
+ m_xDatasourceType->connect_changed(LINK(this, OGeneralPage, OnDatasourceTypeSelected));
+ }
+
+ OGeneralPage::~OGeneralPage()
+ {
+ }
+
+ namespace
+ {
+ struct DisplayedType
+ {
+ OUString eType;
+ OUString sDisplayName;
+
+ DisplayedType( const OUString& _eType, const OUString& _rDisplayName ) : eType( _eType ), sDisplayName( _rDisplayName ) { }
+ };
+ typedef std::vector< DisplayedType > DisplayedTypes;
+
+ struct DisplayedTypeLess
+ {
+ bool operator() ( const DisplayedType& _rLHS, const DisplayedType& _rRHS )
+ {
+ return _rLHS.eType < _rRHS.eType;
+ }
+ };
+ }
+
+ void OGeneralPage::initializeTypeList()
+ {
+ if ( !m_bInitTypeList )
+ return;
+
+ m_bInitTypeList = false;
+ m_xDatasourceType->clear();
+
+ if ( !m_pCollection )
+ return;
+
+ DisplayedTypes aDisplayedTypes;
+
+ ::dbaccess::ODsnTypeCollection::TypeIterator aEnd = m_pCollection->end();
+ for ( ::dbaccess::ODsnTypeCollection::TypeIterator aTypeLoop = m_pCollection->begin();
+ aTypeLoop != aEnd;
+ ++aTypeLoop
+ )
+ {
+ const OUString& sURLPrefix = aTypeLoop.getURLPrefix();
+ if ( !sURLPrefix.isEmpty() )
+ {
+ // skip mysql connection variations. It is handled in another window.
+ if(sURLPrefix.startsWith("sdbc:mysql:") && !sURLPrefix.startsWith("sdbc:mysql:jdbc:"))
+ continue;
+
+ OUString sDisplayName = aTypeLoop.getDisplayName();
+ if (m_xDatasourceType->find_text(sDisplayName) == -1 &&
+ approveDatasourceType(sURLPrefix, sDisplayName))
+ {
+ aDisplayedTypes.emplace_back( sURLPrefix, sDisplayName );
+ }
+ }
+ }
+ std::sort( aDisplayedTypes.begin(), aDisplayedTypes.end(), DisplayedTypeLess() );
+ for ( const auto& rDisplayedType : aDisplayedTypes )
+ insertDatasourceTypeEntryData( rDisplayedType.eType, rDisplayedType.sDisplayName );
+ }
+
+ void OGeneralPageWizard::initializeEmbeddedDBList()
+ {
+ if ( !m_bInitEmbeddedDBList )
+ return;
+
+ m_bInitEmbeddedDBList = false;
+ m_xEmbeddedDBType->clear();
+
+ if ( !m_pCollection )
+ return;
+
+ DisplayedTypes aDisplayedTypes;
+
+ ::dbaccess::ODsnTypeCollection::TypeIterator aEnd = m_pCollection->end();
+ for ( ::dbaccess::ODsnTypeCollection::TypeIterator aTypeLoop = m_pCollection->begin();
+ aTypeLoop != aEnd;
+ ++aTypeLoop
+ )
+ {
+ const OUString& sURLPrefix = aTypeLoop.getURLPrefix();
+ if ( !sURLPrefix.isEmpty() )
+ {
+ OUString sDisplayName = aTypeLoop.getDisplayName();
+ if (m_xEmbeddedDBType->find_text(sDisplayName) == -1 &&
+ dbaccess::ODsnTypeCollection::isEmbeddedDatabase(sURLPrefix))
+ {
+#if !HAVE_FEATURE_MACOSX_SANDBOX
+ if( !officecfg::Office::Common::Misc::ExperimentalMode::get()
+ && sURLPrefix.startsWith("sdbc:embedded:firebird") )
+ continue;
+#endif
+ aDisplayedTypes.emplace_back( sURLPrefix, sDisplayName );
+ m_bIsDisplayedTypesEmpty = false;
+ }
+ }
+ }
+ std::sort( aDisplayedTypes.begin(), aDisplayedTypes.end(), DisplayedTypeLess() );
+ for (auto const& displayedType : aDisplayedTypes)
+ insertEmbeddedDBTypeEntryData( displayedType.eType, displayedType.sDisplayName );
+ }
+
+ void OGeneralPage::setParentTitle(const OUString&)
+ {
+ }
+
+ void OGeneralPage::switchMessage(std::u16string_view _sURLPrefix)
+ {
+ SPECIAL_MESSAGE eMessage = smNone;
+ if ( _sURLPrefix.empty()/*_eType == m_eNotSupportedKnownType*/ )
+ {
+ eMessage = smUnsupportedType;
+ }
+
+ if ( eMessage != m_eLastMessage )
+ {
+ TranslateId pResId;
+ if ( smUnsupportedType == eMessage )
+ pResId = STR_UNSUPPORTED_DATASOURCE_TYPE;
+ OUString sMessage;
+ if ( pResId )
+ sMessage = DBA_RES(pResId);
+
+ m_xSpecialMessage->set_label( sMessage );
+ m_eLastMessage = eMessage;
+ }
+ }
+
+ void OGeneralPage::onTypeSelected(const OUString& _sURLPrefix)
+ {
+ // the new URL text as indicated by the selection history
+ implSetCurrentType( _sURLPrefix );
+
+ switchMessage(_sURLPrefix);
+
+ m_aTypeSelectHandler.Call(*this);
+ }
+
+ void OGeneralPage::implInitControls( const SfxItemSet& _rSet, bool _bSaveValue )
+ {
+ initializeTypeList();
+
+ m_xDatasourceType->set_active_text(getDatasourceName(_rSet));
+
+ // notify our listener that our type selection has changed (if so)
+ // FIXME: how to detect that it did not changed? (fdo#62937)
+ setParentTitle( m_eCurrentSelection );
+ onTypeSelected( m_eCurrentSelection );
+
+ // a special message for the current page state
+ switchMessage( m_eCurrentSelection );
+
+ OGenericAdministrationPage::implInitControls( _rSet, _bSaveValue );
+ }
+
+ OUString OGeneralPageWizard::getEmbeddedDBName( const SfxItemSet& _rSet )
+ {
+ // first check whether or not the selection is invalid or readonly (invalid implies readonly, but not vice versa)
+ bool bValid, bReadonly;
+ getFlags( _rSet, bValid, bReadonly );
+
+ // if the selection is invalid, disable everything
+
+ implSetCurrentType( OUString() );
+
+ // compare the DSN prefix with the registered ones
+ OUString sDisplayName;
+
+ if (m_pCollection && bValid)
+ {
+ implSetCurrentType( dbaccess::ODsnTypeCollection::getEmbeddedDatabase() );
+ sDisplayName = m_pCollection->getTypeDisplayName( m_eCurrentSelection );
+ onTypeSelected(m_eCurrentSelection);
+ }
+
+ // select the correct datasource type
+ if ( dbaccess::ODsnTypeCollection::isEmbeddedDatabase( m_eCurrentSelection )
+ && m_xEmbeddedDBType->find_text(sDisplayName) == -1 )
+ { // this indicates it's really a type which is known in general, but not supported on the current platform
+ // show a message saying so
+ // eSpecialMessage = smUnsupportedType;
+ insertEmbeddedDBTypeEntryData( m_eCurrentSelection, sDisplayName );
+ }
+
+ return sDisplayName;
+ }
+
+ OUString OGeneralPage::getDatasourceName( const SfxItemSet& _rSet )
+ {
+ // first check whether or not the selection is invalid or readonly (invalid implies readonly, but not vice versa)
+ bool bValid, bReadonly;
+ getFlags( _rSet, bValid, bReadonly );
+
+ // if the selection is invalid, disable everything
+ OUString sConnectURL;
+ if ( bValid )
+ {
+ // collect some items and some values
+ const SfxStringItem* pUrlItem = _rSet.GetItem<SfxStringItem>(DSID_CONNECTURL);
+ assert( pUrlItem );
+ sConnectURL = pUrlItem->GetValue();
+ }
+
+ implSetCurrentType( OUString() );
+
+ // compare the DSN prefix with the registered ones
+ OUString sDisplayName;
+
+ if (m_pCollection && bValid)
+ {
+ implSetCurrentType( m_pCollection->getPrefix( sConnectURL ) );
+ sDisplayName = m_pCollection->getTypeDisplayName( m_eCurrentSelection );
+ }
+
+ // select the correct datasource type
+ if ( approveDatasourceType( m_eCurrentSelection, sDisplayName )
+ && m_xDatasourceType->find_text(sDisplayName) == -1 )
+ { // this indicates it's really a type which is known in general, but not supported on the current platform
+ // show a message saying so
+ // eSpecialMessage = smUnsupportedType;
+ insertDatasourceTypeEntryData( m_eCurrentSelection, sDisplayName );
+ }
+
+ return sDisplayName;
+ }
+
+ // For the databaseWizard we only have one entry for the MySQL Database,
+ // because we have a separate tabpage to retrieve the respective datasource type
+ // ( ::dbaccess::DST_MYSQL_ODBC || ::dbaccess::DST_MYSQL_JDBC). Therefore we use ::dbaccess::DST_MYSQL_JDBC as a temporary
+ // representative for all MySQl databases)
+ // Also, embedded databases (embedded HSQL, at the moment), are not to appear in the list of
+ // databases to connect to.
+ bool OGeneralPage::approveDatasourceType( std::u16string_view _sURLPrefix, OUString& _inout_rDisplayName )
+ {
+ return approveDatasourceType( m_pCollection->determineType(_sURLPrefix), _inout_rDisplayName );
+ }
+
+ bool OGeneralPage::approveDatasourceType( ::dbaccess::DATASOURCE_TYPE eType, OUString& _inout_rDisplayName )
+ {
+ if ( eType == ::dbaccess::DST_MYSQL_NATIVE_DIRECT )
+ {
+ // do not display the Connector/OOo driver itself, it is always wrapped via the MySQL-Driver, if
+ // this driver is installed
+ if ( m_pCollection->hasDriver( "sdbc:mysql:mysqlc:" ) )
+ _inout_rDisplayName.clear();
+ }
+
+ if ( eType == ::dbaccess::DST_EMBEDDED_HSQLDB
+ || eType == ::dbaccess::DST_EMBEDDED_FIREBIRD )
+ _inout_rDisplayName.clear();
+
+ return _inout_rDisplayName.getLength() > 0;
+ }
+
+ void OGeneralPage::insertDatasourceTypeEntryData(const OUString& _sType, const OUString& sDisplayName)
+ {
+ // insert a (temporary) entry
+ m_xDatasourceType->append_text(sDisplayName);
+ m_aURLPrefixes.push_back(_sType);
+ }
+
+ void OGeneralPageWizard::insertEmbeddedDBTypeEntryData(const OUString& _sType, const OUString& sDisplayName)
+ {
+ // insert a (temporary) entry
+ m_xEmbeddedDBType->append_text(sDisplayName);
+ m_aEmbeddedURLPrefixes.push_back(_sType);
+ }
+
+ void OGeneralPage::fillWindows(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList)
+ {
+ _rControlList.emplace_back(new ODisableWidgetWrapper<weld::Label>(m_xSpecialMessage.get()));
+ }
+
+ void OGeneralPage::fillControls(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList)
+ {
+ _rControlList.emplace_back(new OSaveValueWidgetWrapper<weld::ComboBox>(m_xDatasourceType.get()));
+ }
+
+ void OGeneralPage::implSetCurrentType( const OUString& _eType )
+ {
+ if ( _eType == m_eCurrentSelection )
+ return;
+
+ m_eCurrentSelection = _eType;
+ }
+
+ void OGeneralPage::Reset(const SfxItemSet* _rCoreAttrs)
+ {
+ // reset all locale data
+ implSetCurrentType( OUString() );
+ // this ensures that our type selection link will be called, even if the new one is the same as the
+ // current one
+ OGenericAdministrationPage::Reset(_rCoreAttrs);
+ }
+
+ IMPL_LINK( OGeneralPageWizard, OnEmbeddedDBTypeSelected, weld::ComboBox&, _rBox, void )
+ {
+ // get the type from the entry data
+ const sal_Int32 nSelected = _rBox.get_active();
+ if (o3tl::make_unsigned(nSelected) >= m_aEmbeddedURLPrefixes.size() )
+ {
+ SAL_WARN("dbaccess.ui.generalpage", "Got out-of-range value '" << nSelected << "' from the DatasourceType selection ListBox's GetSelectedEntryPos(): no corresponding URL prefix");
+ return;
+ }
+ const OUString sURLPrefix = m_aEmbeddedURLPrefixes[ nSelected ];
+
+ setParentTitle( sURLPrefix );
+ // let the impl method do all the stuff
+ onTypeSelected( sURLPrefix );
+ // tell the listener we were modified
+ callModifiedHdl();
+ }
+
+ IMPL_LINK( OGeneralPage, OnDatasourceTypeSelected, weld::ComboBox&, _rBox, void )
+ {
+ // get the type from the entry data
+ const sal_Int32 nSelected = _rBox.get_active();
+ if (nSelected == -1)
+ return;
+ if (o3tl::make_unsigned(nSelected) >= m_aURLPrefixes.size() )
+ {
+ SAL_WARN("dbaccess.ui.generalpage", "Got out-of-range value '" << nSelected << "' from the DatasourceType selection ListBox's GetSelectedEntryPos(): no corresponding URL prefix");
+ return;
+ }
+ const OUString sURLPrefix = m_aURLPrefixes[ nSelected ];
+
+ setParentTitle( sURLPrefix );
+ // let the impl method do all the stuff
+ onTypeSelected( sURLPrefix );
+ // tell the listener we were modified
+ callModifiedHdl();
+ }
+
+ // OGeneralPageDialog
+ OGeneralPageDialog::OGeneralPageDialog(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& _rItems)
+ : OGeneralPage(pPage, pController, "dbaccess/ui/generalpagedialog.ui", _rItems)
+ {
+ }
+
+ void OGeneralPageDialog::setParentTitle( const OUString& _sURLPrefix )
+ {
+ const OUString sName = m_pCollection->getTypeDisplayName( _sURLPrefix );
+ if ( m_pAdminDialog )
+ {
+ OUString sMessage = DBA_RES(STR_PARENTTITLE_GENERAL);
+ m_pAdminDialog->setTitle( sMessage.replaceAll( "#", sName ) );
+ }
+ }
+
+ void OGeneralPageDialog::implInitControls( const SfxItemSet& _rSet, bool _bSaveValue )
+ {
+ OGeneralPage::implInitControls( _rSet, _bSaveValue );
+
+ // first check whether or not the selection is invalid or readonly (invalid implies readonly, but not vice versa)
+ bool bValid, bReadonly;
+ getFlags(_rSet, bValid, bReadonly );
+
+ m_xDatasourceType->set_sensitive( bValid );
+ }
+
+ bool OGeneralPageDialog::FillItemSet( SfxItemSet* _rCoreAttrs )
+ {
+ bool bChangedSomething = false;
+
+ const sal_Int32 nEntry = m_xDatasourceType->get_active();
+ OUString sURLPrefix = m_aURLPrefixes[ nEntry ];
+
+ if (m_xDatasourceType->get_value_changed_from_saved())
+ {
+ _rCoreAttrs->Put( SfxStringItem( DSID_CONNECTURL, sURLPrefix ) );
+ bChangedSomething = true;
+ }
+
+ return bChangedSomething;
+ }
+
+ // OGeneralPageWizard
+ OGeneralPageWizard::OGeneralPageWizard(weld::Container* pPage, ODbTypeWizDialogSetup* pController, const SfxItemSet& _rItems)
+ : OGeneralPage( pPage, pController, "dbaccess/ui/generalpagewizard.ui", _rItems )
+ , m_xRB_CreateDatabase(m_xBuilder->weld_radio_button("createDatabase"))
+ , m_xRB_OpenExistingDatabase(m_xBuilder->weld_radio_button("openExistingDatabase"))
+ , m_xRB_ConnectDatabase(m_xBuilder->weld_radio_button("connectDatabase"))
+ , m_xFT_EmbeddedDBLabel(m_xBuilder->weld_label("embeddeddbLabel"))
+ , m_xEmbeddedDBType(m_xBuilder->weld_combo_box("embeddeddbList"))
+ , m_xFT_DocListLabel(m_xBuilder->weld_label("docListLabel"))
+ , m_xFT_HelpText(m_xBuilder->weld_label("helpText"))
+ , m_xLB_DocumentList(new OpenDocumentListBox(m_xBuilder->weld_combo_box("documentList"), "com.sun.star.sdb.OfficeDatabaseDocument"))
+ , m_xPB_OpenDatabase(new OpenDocumentButton(m_xBuilder->weld_button("openDatabase"), "com.sun.star.sdb.OfficeDatabaseDocument"))
+ , m_xFT_NoEmbeddedDBLabel(m_xBuilder->weld_label("noembeddeddbLabel"))
+ , m_eOriginalCreationMode(eCreateNew)
+ , m_bInitEmbeddedDBList(true)
+ , m_bIsDisplayedTypesEmpty(true)
+ {
+ // If no driver for embedded DBs is installed, and no dBase driver, then hide the "Create new database" option
+ sal_Int32 nCreateNewDBIndex = m_pCollection->getIndexOf( dbaccess::ODsnTypeCollection::getEmbeddedDatabase() );
+ if ( nCreateNewDBIndex == -1 )
+ nCreateNewDBIndex = m_pCollection->getIndexOf( u"sdbc:dbase:" );
+ bool bHideCreateNew = ( nCreateNewDBIndex == -1 );
+
+ // also, if our application policies tell us to hide the option, do it
+ ::utl::OConfigurationTreeRoot aConfig( ::utl::OConfigurationTreeRoot::createWithComponentContext(
+ ::comphelper::getProcessComponentContext(),
+ "/org.openoffice.Office.DataAccess/Policies/Features/Base"
+ ) );
+ bool bAllowCreateLocalDatabase( true );
+ OSL_VERIFY( aConfig.getNodeValue( "CreateLocalDatabase" ) >>= bAllowCreateLocalDatabase );
+ if ( !bAllowCreateLocalDatabase )
+ bHideCreateNew = true;
+
+ if ( bHideCreateNew )
+ {
+ m_xRB_CreateDatabase->hide();
+ m_xRB_ConnectDatabase->set_active(true);
+ }
+ else
+ m_xRB_CreateDatabase->set_active(true);
+
+ // do some knittings
+ m_xEmbeddedDBType->connect_changed(LINK(this, OGeneralPageWizard, OnEmbeddedDBTypeSelected));
+ m_xRB_CreateDatabase->connect_toggled( LINK( this, OGeneralPageWizard, OnSetupModeSelected ) );
+ m_xRB_ConnectDatabase->connect_toggled( LINK( this, OGeneralPageWizard, OnSetupModeSelected ) );
+ m_xRB_OpenExistingDatabase->connect_toggled( LINK( this, OGeneralPageWizard, OnSetupModeSelected ) );
+ m_xLB_DocumentList->connect_changed( LINK( this, OGeneralPageWizard, OnDocumentSelected ) );
+ m_xPB_OpenDatabase->connect_clicked( LINK( this, OGeneralPageWizard, OnOpenDocument ) );
+ m_xFT_NoEmbeddedDBLabel->hide();
+
+ pController->SetGeneralPage(this);
+ }
+
+ OGeneralPageWizard::~OGeneralPageWizard()
+ {
+ }
+
+ OGeneralPageWizard::CreationMode OGeneralPageWizard::GetDatabaseCreationMode() const
+ {
+ if ( m_xRB_CreateDatabase->get_active() )
+ return eCreateNew;
+ if ( m_xRB_ConnectDatabase->get_active() )
+ return eConnectExternal;
+ return eOpenExisting;
+ }
+
+ void OGeneralPageWizard::implInitControls( const SfxItemSet& _rSet, bool _bSaveValue )
+ {
+ OGeneralPage::implInitControls( _rSet, _bSaveValue );
+
+ initializeEmbeddedDBList();
+ m_xEmbeddedDBType->set_active_text(getEmbeddedDBName(_rSet));
+
+ if(m_bIsDisplayedTypesEmpty)
+ {
+ m_xRB_CreateDatabase->set_sensitive(false);
+ m_xFT_EmbeddedDBLabel->hide();
+ m_xEmbeddedDBType->hide();
+ m_xFT_NoEmbeddedDBLabel->show();
+ m_xRB_OpenExistingDatabase->set_active(true);
+ }
+
+ // first check whether or not the selection is invalid or readonly (invalid implies readonly, but not vice versa)
+ bool bValid, bReadonly;
+ getFlags( _rSet, bValid, bReadonly );
+
+ SetPageTitle(OUString());
+
+ if ( !bValid || bReadonly )
+ {
+ m_xFT_EmbeddedDBLabel->set_sensitive( false );
+ m_xDatasourceType->set_sensitive( false );
+ m_xPB_OpenDatabase->set_sensitive( false );
+ m_xFT_DocListLabel->set_sensitive( false );
+ m_xLB_DocumentList->set_sensitive( false );
+ }
+
+ if (m_xLB_DocumentList->get_count())
+ m_xLB_DocumentList->set_active(0);
+
+ m_eOriginalCreationMode = GetDatabaseCreationMode();
+
+ SetupModeSelected();
+ }
+
+ OUString OGeneralPageWizard::getDatasourceName(const SfxItemSet& _rSet)
+ {
+ // Sets the default selected database on startup.
+ if (m_xRB_CreateDatabase->get_active() )
+ {
+ return m_pCollection->getTypeDisplayName( u"sdbc:firebird:" );
+ }
+
+ return OGeneralPage::getDatasourceName( _rSet );
+ }
+
+ bool OGeneralPageWizard::approveDatasourceType( ::dbaccess::DATASOURCE_TYPE eType, OUString& _inout_rDisplayName )
+ {
+ switch ( eType )
+ {
+ case ::dbaccess::DST_MYSQL_JDBC:
+ case ::dbaccess::DST_MYSQL_ODBC:
+ case ::dbaccess::DST_MYSQL_NATIVE:
+ _inout_rDisplayName = "MySQL/MariaDB";
+ break;
+ default:
+ break;
+ }
+
+ return OGeneralPage::approveDatasourceType( eType, _inout_rDisplayName );
+ }
+
+ bool OGeneralPageWizard::FillItemSet(SfxItemSet* _rCoreAttrs)
+ {
+ bool bChangedSomething = false;
+
+ bool bCommitTypeSelection = true;
+
+ if ( m_xRB_CreateDatabase->get_active() )
+ {
+ _rCoreAttrs->Put( SfxStringItem( DSID_CONNECTURL, "sdbc:dbase:" ) );
+ bChangedSomething = true;
+ bCommitTypeSelection = false;
+ }
+ else if ( m_xRB_OpenExistingDatabase->get_active() )
+ {
+ if ( m_xRB_OpenExistingDatabase->get_state_changed_from_saved() )
+ bChangedSomething = true;
+
+ // TODO
+ bCommitTypeSelection = false;
+ }
+
+ if ( bCommitTypeSelection )
+ {
+ const sal_Int32 nEntry = m_xDatasourceType->get_active();
+ OUString sURLPrefix = m_aURLPrefixes[nEntry];
+
+ if ( m_xDatasourceType->get_value_changed_from_saved()
+ || ( GetDatabaseCreationMode() != m_eOriginalCreationMode )
+ )
+ {
+ _rCoreAttrs->Put( SfxStringItem( DSID_CONNECTURL,sURLPrefix ) );
+ bChangedSomething = true;
+ }
+ else
+ implSetCurrentType( sURLPrefix );
+ }
+ return bChangedSomething;
+ }
+
+ OUString OGeneralPageWizard::GetSelectedDocumentURL() const
+ {
+ if ( !m_aBrowsedDocumentURL.isEmpty() )
+ return m_aBrowsedDocumentURL;
+ else
+ return m_xLB_DocumentList->GetSelectedDocumentURL();
+ }
+
+ void OGeneralPageWizard::EnableControls()
+ {
+ bool bValid, bReadonly;
+ getFlags( GetItemSet(), bValid, bReadonly );
+ if ( bValid && !bReadonly )
+ {
+ m_xEmbeddedDBType->set_sensitive(m_xRB_CreateDatabase->get_active());
+ m_xFT_EmbeddedDBLabel->set_sensitive(m_xRB_CreateDatabase->get_active());
+ m_xDatasourceType->set_sensitive(m_xRB_ConnectDatabase->get_active());
+ m_xPB_OpenDatabase->set_sensitive(m_xRB_OpenExistingDatabase->get_active());
+ m_xFT_DocListLabel->set_sensitive(m_xRB_OpenExistingDatabase->get_active());
+ m_xLB_DocumentList->set_sensitive(m_xRB_OpenExistingDatabase->get_active());
+ }
+ }
+
+ void OGeneralPageWizard::SetupModeSelected()
+ {
+ m_aCreationModeHandler.Call( *this );
+
+ if (m_xRB_CreateDatabase->get_active())
+ OnEmbeddedDBTypeSelected(*m_xEmbeddedDBType);
+ else
+ OnDatasourceTypeSelected(*m_xDatasourceType);
+
+ EnableControls();
+ }
+
+ IMPL_LINK(OGeneralPageWizard, OnSetupModeSelected, weld::Toggleable&, rButton, void)
+ {
+ if (!rButton.get_active())
+ return;
+ SetupModeSelected();
+ }
+
+ IMPL_LINK_NOARG( OGeneralPageWizard, OnDocumentSelected, weld::ComboBox&, void )
+ {
+ m_aDocumentSelectionHandler.Call( *this );
+ }
+
+ IMPL_LINK_NOARG( OGeneralPageWizard, OnOpenDocument, weld::Button&, void )
+ {
+ ::sfx2::FileDialogHelper aFileDlg(
+ ui::dialogs::TemplateDescription::FILEOPEN_READONLY_VERSION,
+ FileDialogFlags::NONE, "sdatabase", SfxFilterFlags::NONE, SfxFilterFlags::NONE, GetFrameWeld());
+ aFileDlg.SetContext(sfx2::FileDialogHelper::BaseDataSource);
+ std::shared_ptr<const SfxFilter> pFilter = getStandardDatabaseFilter();
+ if ( pFilter )
+ {
+ aFileDlg.SetCurrentFilter(pFilter->GetUIName());
+ }
+ if ( aFileDlg.Execute() != ERRCODE_NONE )
+ return;
+
+ OUString sPath = aFileDlg.GetPath();
+ // check for aFileDlg.GetCurrentFilter used to be here but current fpicker filter
+ // can be set to anything, see tdf#125267 how this breaks if other value
+ // than 'ODF Database' is selected. Let's therefore check only if wildcard matches
+ if ( !pFilter->GetWildcard().Matches(sPath) )
+ {
+ OUString sMessage(DBA_RES(STR_ERR_USE_CONNECT_TO));
+ std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(GetFrameWeld(),
+ VclMessageType::Info, VclButtonsType::Ok,
+ sMessage));
+ xInfoBox->run();
+ m_xRB_ConnectDatabase->set_active(true);
+ OnSetupModeSelected( *m_xRB_ConnectDatabase );
+ return;
+ }
+ m_aBrowsedDocumentURL = sPath;
+ m_aChooseDocumentHandler.Call( *this );
+ }
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/dlg/generalpage.hxx b/dbaccess/source/ui/dlg/generalpage.hxx
new file mode 100644
index 000000000..1abda980e
--- /dev/null
+++ b/dbaccess/source/ui/dlg/generalpage.hxx
@@ -0,0 +1,189 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include "adminpages.hxx"
+#include <opendoccontrols.hxx>
+
+namespace dbaui
+{
+ class ODbTypeWizDialogSetup;
+
+ // OGeneralPage
+ class OGeneralPage : public OGenericAdministrationPage
+ {
+ protected:
+ OGeneralPage(weld::Container* pPage, weld::DialogController* pController, const OUString& _rUIXMLDescription, const SfxItemSet& _rItems);
+
+ OUString m_eCurrentSelection; /// currently selected type
+
+ private:
+ std::unique_ptr<weld::Label> m_xSpecialMessage;
+
+ enum SPECIAL_MESSAGE
+ {
+ smNone,
+ smUnsupportedType
+ };
+ SPECIAL_MESSAGE m_eLastMessage;
+
+ Link<OGeneralPage&,void> m_aTypeSelectHandler; /// to be called if a new type is selected
+ bool m_bInitTypeList : 1;
+ bool approveDatasourceType( std::u16string_view _sURLPrefix, OUString& _inout_rDisplayName );
+ void insertDatasourceTypeEntryData( const OUString& _sType, const OUString& sDisplayName );
+
+ protected:
+ std::unique_ptr<weld::ComboBox> m_xDatasourceType;
+
+ ::dbaccess::ODsnTypeCollection*
+ m_pCollection; /// the DSN type collection instance
+
+ std::vector< OUString>
+ m_aURLPrefixes;
+
+ public:
+ virtual ~OGeneralPage() override;
+
+ /// set a handler which gets called every time the user selects a new type
+ void SetTypeSelectHandler( const Link<OGeneralPage&,void>& _rHandler ) { m_aTypeSelectHandler = _rHandler; }
+
+ /// get the currently selected datasource type
+ const OUString& GetSelectedType() const { return m_eCurrentSelection; }
+
+ protected:
+ // SfxTabPage overridables
+ virtual void Reset( const SfxItemSet* _rCoreAttrs ) override;
+
+ virtual void implInitControls( const SfxItemSet& _rSet, bool _bSaveValue ) override;
+ virtual OUString getDatasourceName( const SfxItemSet& _rSet );
+ virtual bool approveDatasourceType( ::dbaccess::DATASOURCE_TYPE eType, OUString& _inout_rDisplayName );
+
+ // <method>OGenericAdministrationPage::fillControls</method>
+ virtual void fillControls(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) override;
+ // <method>OGenericAdministrationPage::fillWindows</method>
+ virtual void fillWindows(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) override;
+
+ void onTypeSelected(const OUString& _sURLPrefix);
+
+ /**
+ * Initializes the listbox, which contains entries each representing a
+ * connection to an existing database.
+ */
+ void initializeTypeList();
+
+ void implSetCurrentType( const OUString& _eType );
+
+ void switchMessage(std::u16string_view _sURLPrefix);
+
+ /// sets the title of the parent dialog
+ virtual void setParentTitle( const OUString& _sURLPrefix );
+
+ DECL_LINK(OnDatasourceTypeSelected, weld::ComboBox&, void);
+ };
+
+ // OGeneralPageDialog
+ class OGeneralPageDialog : public OGeneralPage
+ {
+ public:
+ OGeneralPageDialog(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& _rItems);
+
+ protected:
+ virtual bool FillItemSet( SfxItemSet* _rCoreAttrs ) override;
+
+ virtual void implInitControls( const SfxItemSet& _rSet, bool _bSaveValue ) override;
+ virtual void setParentTitle( const OUString& _sURLPrefix ) override;
+ };
+
+ // OGeneralPageWizard
+ class OGeneralPageWizard final : public OGeneralPage
+ {
+ public:
+ OGeneralPageWizard( weld::Container* pPage, ODbTypeWizDialogSetup* pController, const SfxItemSet& _rItems );
+ virtual ~OGeneralPageWizard() override;
+
+ enum CreationMode
+ {
+ eCreateNew,
+ eConnectExternal,
+ eOpenExisting
+ };
+
+ private:
+ // dialog controls
+ std::unique_ptr<weld::RadioButton> m_xRB_CreateDatabase;
+ std::unique_ptr<weld::RadioButton> m_xRB_OpenExistingDatabase;
+ std::unique_ptr<weld::RadioButton> m_xRB_ConnectDatabase;
+
+ std::unique_ptr<weld::Label> m_xFT_EmbeddedDBLabel;
+ std::unique_ptr<weld::ComboBox> m_xEmbeddedDBType;
+
+ std::unique_ptr<weld::Label> m_xFT_DocListLabel;
+ std::unique_ptr<weld::Label> m_xFT_HelpText;
+ std::unique_ptr<OpenDocumentListBox> m_xLB_DocumentList;
+ std::unique_ptr<OpenDocumentButton> m_xPB_OpenDatabase;
+
+ std::unique_ptr<weld::Label> m_xFT_NoEmbeddedDBLabel;
+
+ // state
+ OUString m_aBrowsedDocumentURL;
+ CreationMode m_eOriginalCreationMode;
+
+ Link<OGeneralPageWizard&,void> m_aCreationModeHandler; /// to be called if a new type is selected
+ Link<OGeneralPageWizard&,void> m_aDocumentSelectionHandler; /// to be called when a document in the RecentDoc list is selected
+ Link<OGeneralPageWizard&,void> m_aChooseDocumentHandler; /// to be called when a recent document has been definitely chosen
+
+ bool m_bInitEmbeddedDBList : 1;
+ bool m_bIsDisplayedTypesEmpty : 1;
+ void insertEmbeddedDBTypeEntryData( const OUString& _sType, const OUString& sDisplayName );
+
+ void EnableControls();
+
+ public:
+ void SetCreationModeHandler( const Link<OGeneralPageWizard&,void>& _rHandler ) { m_aCreationModeHandler = _rHandler; }
+ CreationMode GetDatabaseCreationMode() const;
+
+ void SetDocumentSelectionHandler( const Link<OGeneralPageWizard&,void>& _rHandler) { m_aDocumentSelectionHandler = _rHandler; }
+ void SetChooseDocumentHandler( const Link<OGeneralPageWizard&,void>& _rHandler) { m_aChooseDocumentHandler = _rHandler; }
+ OUString GetSelectedDocumentURL() const;
+
+ private:
+ virtual bool FillItemSet( SfxItemSet* _rCoreAttrs ) override;
+
+ virtual void implInitControls( const SfxItemSet& _rSet, bool _bSaveValue ) override;
+ virtual OUString getDatasourceName( const SfxItemSet& _rSet ) override;
+ virtual bool approveDatasourceType( ::dbaccess::DATASOURCE_TYPE eType, OUString& _inout_rDisplayName ) override;
+
+ std::vector< OUString>
+ m_aEmbeddedURLPrefixes;
+
+ OUString getEmbeddedDBName( const SfxItemSet& _rSet );
+ void initializeEmbeddedDBList();
+
+ void SetupModeSelected();
+
+ DECL_LINK( OnEmbeddedDBTypeSelected, weld::ComboBox&, void );
+ DECL_LINK( OnSetupModeSelected, weld::Toggleable&, void );
+ DECL_LINK( OnDocumentSelected, weld::ComboBox&, void );
+ DECL_LINK( OnOpenDocument, weld::Button&, void );
+ };
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/dlg/indexdialog.cxx b/dbaccess/source/ui/dlg/indexdialog.cxx
new file mode 100644
index 000000000..4c9312848
--- /dev/null
+++ b/dbaccess/source/ui/dlg/indexdialog.cxx
@@ -0,0 +1,707 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+
+#include <set>
+
+#include <core_resource.hxx>
+#include <indexdialog.hxx>
+#include <strings.hrc>
+#include <bitmaps.hlst>
+#include <indexfieldscontrol.hxx>
+#include <indexcollection.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/weld.hxx>
+#include <com/sun/star/sdb/SQLContext.hpp>
+#include <connectivity/dbtools.hxx>
+#include <osl/diagnose.h>
+
+namespace dbaui
+{
+
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::container;
+ using namespace ::com::sun::star::sdbc;
+ using namespace ::com::sun::star::sdb;
+ using namespace ::com::sun::star::lang;
+ using namespace ::dbtools;
+
+ // helper
+ static bool operator ==(const OIndexField& _rLHS, const OIndexField& _rRHS)
+ {
+ return (_rLHS.sFieldName == _rRHS.sFieldName)
+ && (_rLHS.bSortAscending == _rRHS.bSortAscending);
+ }
+
+ static bool operator ==(const IndexFields& _rLHS, const IndexFields& _rRHS)
+ {
+ return std::equal(_rLHS.begin(), _rLHS.end(), _rRHS.begin(), _rRHS.end());
+ }
+
+ static bool operator !=(const IndexFields& _rLHS, const IndexFields& _rRHS)
+ {
+ return !(_rLHS == _rRHS);
+ }
+
+ // DbaIndexDialog
+ DbaIndexDialog::DbaIndexDialog(weld::Window* pParent, const Sequence< OUString >& _rFieldNames,
+ const Reference< XNameAccess >& _rxIndexes,
+ const Reference< XConnection >& _rxConnection,
+ const Reference< XComponentContext >& _rxContext)
+ : GenericDialogController(pParent, "dbaccess/ui/indexdesigndialog.ui", "IndexDesignDialog")
+ , m_xConnection(_rxConnection)
+ , m_bEditingActive(false)
+ , m_bEditAgain(false)
+ , m_bNoHandlerCall(false)
+ , m_xContext(_rxContext)
+ , m_xActions(m_xBuilder->weld_toolbar("ACTIONS"))
+ , m_xIndexList(m_xBuilder->weld_tree_view("INDEX_LIST"))
+ , m_xIndexDetails(m_xBuilder->weld_label("INDEX_DETAILS"))
+ , m_xDescriptionLabel(m_xBuilder->weld_label("DESC_LABEL"))
+ , m_xDescription(m_xBuilder->weld_label("DESCRIPTION"))
+ , m_xUnique(m_xBuilder->weld_check_button("UNIQUE"))
+ , m_xFieldsLabel(m_xBuilder->weld_label("FIELDS_LABEL"))
+ , m_xClose(m_xBuilder->weld_button("close"))
+ , m_xTable(m_xBuilder->weld_container("FIELDS"))
+ , m_xTableCtrlParent(m_xTable->CreateChildFrame())
+ , m_xFields(VclPtr<IndexFieldsControl>::Create(m_xTableCtrlParent))
+ {
+ m_xIndexList->set_size_request(m_xIndexList->get_approximate_digit_width() * 17,
+ m_xIndexList->get_height_rows(12));
+
+ int nWidth = m_xIndexList->get_approximate_digit_width() * 60;
+ int nHeight = m_xIndexList->get_height_rows(8);
+ m_xTable->set_size_request(nWidth, nHeight);
+
+ m_xActions->connect_clicked(LINK(this, DbaIndexDialog, OnIndexAction));
+
+ m_xIndexList->connect_changed(LINK(this, DbaIndexDialog, OnIndexSelected));
+ m_xIndexList->connect_editing(LINK(this, DbaIndexDialog, OnEntryEditing),
+ LINK(this, DbaIndexDialog, OnEntryEdited));
+
+ m_xFields->SetSizePixel(Size(nWidth, 100));
+ m_xFields->Init(_rFieldNames, ::dbtools::getBooleanDataSourceSetting( m_xConnection, "AddIndexAppendix" ));
+ m_xFields->Show();
+
+ m_xIndexes.reset(new OIndexCollection());
+ try
+ {
+ m_xIndexes->attach(_rxIndexes);
+ }
+ catch(SQLException& e)
+ {
+ ::dbtools::showError(SQLExceptionInfo(e), pParent->GetXWindow(), _rxContext);
+ }
+ catch(Exception&)
+ {
+ OSL_FAIL("DbaIndexDialog::DbaIndexDialog: could not retrieve basic information from the UNO collection!");
+ }
+
+ fillIndexList();
+
+ m_xUnique->connect_toggled(LINK(this, DbaIndexDialog, OnModifiedClick));
+ m_xFields->SetModifyHdl(LINK(this, DbaIndexDialog, OnModified));
+
+ m_xClose->connect_clicked(LINK(this, DbaIndexDialog, OnCloseDialog));
+
+ // if all of the indexes have an empty description, we're not interested in displaying it
+ bool bFound = false;
+ for (auto const& check : *m_xIndexes)
+ {
+ if (!check.sDescription.isEmpty())
+ {
+ bFound = true;
+ break;
+ }
+ }
+ if (!bFound)
+ {
+ // hide the controls which are necessary for the description
+ m_xDescription->hide();
+ m_xDescriptionLabel->hide();
+ }
+ }
+
+ void DbaIndexDialog::updateToolbox()
+ {
+ m_xActions->set_item_sensitive("ID_INDEX_NEW", !m_bEditingActive);
+
+ int nSelected = m_xIndexList->get_selected_index();
+ bool bSelectedAnything = nSelected != -1;
+ if (bSelectedAnything)
+ {
+ // is the current entry modified?
+ Indexes::const_iterator aSelectedPos = m_xIndexes->begin() + m_xIndexList->get_id(nSelected).toUInt32();
+ m_xActions->set_item_sensitive("ID_INDEX_SAVE", aSelectedPos->isModified() || aSelectedPos->isNew());
+ m_xActions->set_item_sensitive("ID_INDEX_RESET", aSelectedPos->isModified() || aSelectedPos->isNew());
+ bSelectedAnything = !aSelectedPos->bPrimaryKey;
+ }
+ else
+ {
+ m_xActions->set_item_sensitive("ID_INDEX_SAVE", false);
+ m_xActions->set_item_sensitive("ID_INDEX_RESET", false);
+ }
+ m_xActions->set_item_sensitive("ID_INDEX_DROP", bSelectedAnything);
+ m_xActions->set_item_sensitive("ID_INDEX_RENAME", bSelectedAnything);
+ }
+
+ void DbaIndexDialog::fillIndexList()
+ {
+ OUString aPKeyIcon(BMP_PKEYICON);
+ // fill the list with the index names
+ m_xIndexList->clear();
+ sal_uInt32 nPos = 0;
+ for (auto const& indexLoop : *m_xIndexes)
+ {
+ m_xIndexList->append(OUString::number(nPos), indexLoop.sName);
+ if (indexLoop.bPrimaryKey)
+ m_xIndexList->set_image(nPos, aPKeyIcon);
+ ++nPos;
+ }
+
+ if (nPos)
+ m_xIndexList->select(0);
+
+ IndexSelected();
+ }
+
+ DbaIndexDialog::~DbaIndexDialog( )
+ {
+ m_xIndexes.reset();
+ m_xFields.disposeAndClear();
+ m_xTableCtrlParent->dispose();
+ m_xTableCtrlParent.clear();
+ }
+
+ bool DbaIndexDialog::implCommit(const weld::TreeIter* pEntry)
+ {
+ assert(pEntry && "DbaIndexDialog::implCommit: invalid entry!");
+
+ Indexes::iterator aCommitPos = m_xIndexes->begin() + m_xIndexList->get_id(*pEntry).toUInt32();
+
+ // if it's not a new index, remove it
+ // (we can't modify indexes, only drop'n'insert)
+ if (!aCommitPos->isNew())
+ if (!implDropIndex(pEntry, false))
+ return false;
+
+ // create the new index
+ SQLExceptionInfo aExceptionInfo;
+ try
+ {
+ m_xIndexes->commitNewIndex(aCommitPos);
+ }
+ catch(SQLContext& e) { aExceptionInfo = SQLExceptionInfo(e); }
+ catch(SQLWarning& e) { aExceptionInfo = SQLExceptionInfo(e); }
+ catch(SQLException& e) { aExceptionInfo = SQLExceptionInfo(e); }
+
+ // reflect the new selection in the toolbox
+ updateToolbox();
+
+ if (aExceptionInfo.isValid())
+ showError(aExceptionInfo, m_xDialog->GetXWindow(), m_xContext);
+ else
+ {
+ m_xUnique->save_state();
+ m_xFields->SaveValue();
+ }
+
+ return !aExceptionInfo.isValid();
+ }
+
+ void DbaIndexDialog::OnNewIndex()
+ {
+ // commit the current entry, if necessary
+ if (!implCommitPreviouslySelected())
+ return;
+
+ // get a new unique name for the new index
+ OUString sNewIndexName;
+ const OUString sNewIndexNameBase(DBA_RES(STR_LOGICAL_INDEX_NAME));
+ sal_Int32 i;
+
+ for ( i = 1; i < 0x7FFFFFFF; ++i )
+ {
+ sNewIndexName = sNewIndexNameBase + OUString::number(i);
+ if (m_xIndexes->end() == m_xIndexes->find(sNewIndexName))
+ break;
+ }
+ if (i == 0x7FFFFFFF)
+ {
+ OSL_FAIL("DbaIndexDialog::OnNewIndex: no free index name found!");
+ // can't do anything ... of course we try another base, but this could end with the same result ...
+ return;
+ }
+
+ std::unique_ptr<weld::TreeIter> xNewEntry(m_xIndexList->make_iterator());
+ m_xIndexList->insert(nullptr, -1, &sNewIndexName, nullptr, nullptr, nullptr, false, xNewEntry.get());
+ m_xIndexes->insert(sNewIndexName);
+
+ // update the user data on the entries in the list box:
+ // they're iterators of the index collection, and thus they have changed when removing the index
+ m_xIndexList->all_foreach([this](weld::TreeIter& rEntry){
+ Indexes::const_iterator aAfterInsertPos = m_xIndexes->find(m_xIndexList->get_text(rEntry));
+ OSL_ENSURE(aAfterInsertPos != m_xIndexes->end(), "DbaIndexDialog::OnNewIndex: problems with one of the entries!");
+ m_xIndexList->set_id(rEntry, OUString::number(aAfterInsertPos - m_xIndexes->begin()));
+ return false;
+ });
+
+ // select the entry and start in-place editing
+ m_bNoHandlerCall = true;
+ m_xIndexList->select(*xNewEntry);
+ m_bNoHandlerCall = false;
+ IndexSelected();
+ m_xIndexList->grab_focus();
+ m_xIndexList->start_editing(*xNewEntry);
+ updateToolbox();
+ }
+
+ void DbaIndexDialog::OnDropIndex(bool _bConfirm)
+ {
+ std::unique_ptr<weld::TreeIter> xSelected(m_xIndexList->make_iterator());
+ // the selected index
+ if (!m_xIndexList->get_selected(xSelected.get()))
+ return;
+
+ // let the user confirm the drop
+ if (_bConfirm)
+ {
+ OUString sConfirm(DBA_RES(STR_CONFIRM_DROP_INDEX));
+ sConfirm = sConfirm.replaceFirst("$name$", m_xIndexList->get_text(*xSelected));
+ std::unique_ptr<weld::MessageDialog> xConfirm(Application::CreateMessageDialog(m_xDialog.get(),
+ VclMessageType::Question, VclButtonsType::YesNo,
+ sConfirm));
+ if (RET_YES != xConfirm->run())
+ return;
+ }
+
+ // do the drop
+ implDropIndex(xSelected.get(), true);
+
+ // reflect the new selection in the toolbox
+ updateToolbox();
+ }
+
+ bool DbaIndexDialog::implDropIndex(const weld::TreeIter* pEntry, bool _bRemoveFromCollection)
+ {
+ // do the drop
+ Indexes::iterator aDropPos = m_xIndexes->begin() + m_xIndexList->get_id(*pEntry).toUInt32();
+ OSL_ENSURE(aDropPos != m_xIndexes->end(), "DbaIndexDialog::OnDropIndex: did not find the index in my collection!");
+
+ SQLExceptionInfo aExceptionInfo;
+ bool bSuccess = false;
+ try
+ {
+ if (_bRemoveFromCollection)
+ bSuccess = m_xIndexes->drop(aDropPos);
+ else
+ bSuccess = m_xIndexes->dropNoRemove(aDropPos);
+ }
+ catch(SQLContext& e) { aExceptionInfo = SQLExceptionInfo(e); }
+ catch(SQLWarning& e) { aExceptionInfo = SQLExceptionInfo(e); }
+ catch(SQLException& e) { aExceptionInfo = SQLExceptionInfo(e); }
+
+ if (aExceptionInfo.isValid())
+ showError(aExceptionInfo, m_xDialog->GetXWindow(), m_xContext);
+ else if (bSuccess && _bRemoveFromCollection)
+ {
+ m_bNoHandlerCall = true;
+
+ // if the entry to remove is the selected on...
+ if (m_xPreviousSelection && m_xPreviousSelection->equal(*pEntry))
+ m_xPreviousSelection.reset();
+ m_xIndexList->remove(*pEntry);
+
+ m_bNoHandlerCall = false;
+
+ // update the user data on the entries in the list box:
+ // they're iterators of the index collection, and thus they have changed when removing the index
+ m_xIndexList->all_foreach([this](weld::TreeIter& rEntry){
+ Indexes::const_iterator aAfterDropPos = m_xIndexes->find(m_xIndexList->get_text(rEntry));
+ OSL_ENSURE(aAfterDropPos != m_xIndexes->end(), "DbaIndexDialog::OnDropIndex: problems with one of the remaining entries!");
+ m_xIndexList->set_id(rEntry, OUString::number(aAfterDropPos - m_xIndexes->begin()));
+ return false;
+ });
+
+ // the Remove automatically selected another entry (if possible), but we disabled the calling of the handler
+ // to prevent that we missed something... call the handler directly
+ IndexSelected();
+ }
+
+ return !aExceptionInfo.isValid();
+ }
+
+ void DbaIndexDialog::OnRenameIndex()
+ {
+ // the selected iterator
+ std::unique_ptr<weld::TreeIter> xSelected(m_xIndexList->make_iterator());
+ if (!m_xIndexList->get_selected(xSelected.get()))
+ return;
+
+ // save the changes made 'til here
+ // Upon leaving the edit mode, the control will be re-initialized with the
+ // settings from the current entry
+ implSaveModified(false);
+
+ m_xIndexList->grab_focus();
+ m_xIndexList->start_editing(*xSelected);
+ updateToolbox();
+ }
+
+ void DbaIndexDialog::OnSaveIndex()
+ {
+ // the selected index
+ implCommitPreviouslySelected();
+ updateToolbox();
+ }
+
+ void DbaIndexDialog::OnResetIndex()
+ {
+ // the selected index
+ std::unique_ptr<weld::TreeIter> xSelected(m_xIndexList->make_iterator());
+ // the selected index
+ if (!m_xIndexList->get_selected(xSelected.get()))
+ xSelected.reset();
+ OSL_ENSURE(xSelected, "DbaIndexDialog::OnResetIndex: invalid call!");
+ if (!xSelected)
+ return;
+
+ Indexes::iterator aResetPos = m_xIndexes->begin() + m_xIndexList->get_id(*xSelected).toUInt32();
+
+ if (aResetPos->isNew())
+ {
+ OnDropIndex(false);
+ return;
+ }
+
+ SQLExceptionInfo aExceptionInfo;
+ try
+ {
+ m_xIndexes->resetIndex(aResetPos);
+ }
+ catch(SQLContext& e) { aExceptionInfo = SQLExceptionInfo(e); }
+ catch(SQLWarning& e) { aExceptionInfo = SQLExceptionInfo(e); }
+ catch(SQLException& e) { aExceptionInfo = SQLExceptionInfo(e); }
+
+ if (aExceptionInfo.isValid())
+ showError(aExceptionInfo, m_xDialog->GetXWindow(), m_xContext);
+ else
+ m_xIndexList->set_text(*xSelected, aResetPos->sName);
+
+ updateControls(xSelected.get());
+ updateToolbox();
+ }
+
+ IMPL_LINK(DbaIndexDialog, OnIndexAction, const OString&, rClicked, void)
+ {
+ if (rClicked == "ID_INDEX_NEW")
+ OnNewIndex();
+ else if (rClicked == "ID_INDEX_DROP")
+ OnDropIndex();
+ else if (rClicked == "ID_INDEX_RENAME")
+ OnRenameIndex();
+ else if (rClicked == "ID_INDEX_SAVE")
+ OnSaveIndex();
+ else if (rClicked == "ID_INDEX_RESET")
+ OnResetIndex();
+ }
+
+ IMPL_LINK_NOARG(DbaIndexDialog, OnCloseDialog, weld::Button&, void)
+ {
+ if (m_bEditingActive)
+ {
+ OSL_ENSURE(!m_bEditAgain, "DbaIndexDialog::OnCloseDialog: somebody was faster than hell!");
+ // this means somebody entered a new name, which was invalid, which cause us to posted us an event,
+ // and before the event arrived the user clicked onto "close". VERY fast, this user...
+ m_xIndexList->end_editing();
+ if (m_bEditAgain)
+ // could not commit the new name (started a new - asynchronous - edit trial)
+ return;
+ }
+
+ // the currently selected entry
+ std::unique_ptr<weld::TreeIter> xSelected(m_xIndexList->make_iterator());
+ // the selected index
+ if (!m_xIndexList->get_selected(xSelected.get()))
+ xSelected.reset();
+
+ OSL_ENSURE(xSelected && m_xPreviousSelection && xSelected->equal(*m_xPreviousSelection), "DbaIndexDialog::OnCloseDialog: inconsistence!");
+
+ sal_Int32 nResponse = RET_NO;
+ if (xSelected)
+ {
+ // the descriptor
+ Indexes::const_iterator aSelected = m_xIndexes->begin() + m_xIndexList->get_id(*xSelected).toUInt32();
+ if (aSelected->isModified() || aSelected->isNew())
+ {
+ std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(m_xDialog.get(), "dbaccess/ui/saveindexdialog.ui"));
+ std::unique_ptr<weld::MessageDialog> xQuery(xBuilder->weld_message_dialog("SaveIndexDialog"));
+ nResponse = xQuery->run();
+ }
+ }
+
+ switch (nResponse)
+ {
+ case RET_YES:
+ if (!implCommitPreviouslySelected())
+ return;
+ break;
+ case RET_NO:
+ break;
+ default:
+ return;
+ }
+
+ m_xDialog->response(RET_OK);
+ }
+
+ IMPL_LINK(DbaIndexDialog, OnEditIndexAgain, void*, p, void)
+ {
+ weld::TreeIter* pEntry = static_cast<weld::TreeIter*>(p);
+ m_bEditAgain = false;
+ m_xIndexList->grab_focus();
+ m_xIndexList->start_editing(*pEntry);
+ delete pEntry;
+ }
+
+ IMPL_LINK_NOARG(DbaIndexDialog, OnEntryEditing, const weld::TreeIter&, bool)
+ {
+ m_bEditingActive = true;
+ return true;
+ }
+
+ IMPL_LINK(DbaIndexDialog, OnEntryEdited, const IterString&, rIterString, bool)
+ {
+ m_bEditingActive = false;
+
+ const weld::TreeIter& rEntry = rIterString.first;
+ OUString sNewName = rIterString.second;
+
+ Indexes::iterator aPosition = m_xIndexes->begin() + m_xIndexList->get_id(rEntry).toUInt32();
+
+ OSL_ENSURE(aPosition >= m_xIndexes->begin() && aPosition < m_xIndexes->end(),
+ "DbaIndexDialog::OnEntryEdited: invalid entry!");
+
+ Indexes::const_iterator aSameName = m_xIndexes->find(sNewName);
+ if (aSameName != aPosition && m_xIndexes->end() != aSameName)
+ {
+ OUString sError(DBA_RES(STR_INDEX_NAME_ALREADY_USED));
+ sError = sError.replaceFirst("$name$", sNewName);
+ std::unique_ptr<weld::MessageDialog> xError(Application::CreateMessageDialog(m_xDialog.get(),
+ VclMessageType::Warning, VclButtonsType::Ok,
+ sError));
+ xError->run();
+
+ updateToolbox();
+ m_bEditAgain = true;
+ std::unique_ptr<weld::TreeIter> xEntry(m_xIndexList->make_iterator(&rEntry));
+ Application::PostUserEvent(LINK(this, DbaIndexDialog, OnEditIndexAgain), xEntry.release());
+ return false;
+ }
+
+ aPosition->sName = sNewName;
+
+ // rename can be done by a drop/insert combination only
+ if (aPosition->isNew())
+ {
+ updateToolbox();
+ // no commitment needed here...
+ return true;
+ }
+
+ if (aPosition->sName != aPosition->getOriginalName())
+ {
+ aPosition->setModified(true);
+ updateToolbox();
+ }
+
+ return true;
+ }
+
+ bool DbaIndexDialog::implSaveModified(bool _bPlausibility)
+ {
+ if (!m_xPreviousSelection)
+ return true;
+
+ // try to commit the previously selected index
+ if (m_xFields->IsModified() && !m_xFields->SaveModified())
+ return false;
+
+ Indexes::iterator aPreviouslySelected = m_xIndexes->begin() + m_xIndexList->get_id(*m_xPreviousSelection).toUInt32();
+
+ // the unique flag
+ aPreviouslySelected->bUnique = m_xUnique->get_active();
+ if (m_xUnique->get_state_changed_from_saved())
+ aPreviouslySelected->setModified(true);
+
+ // the fields
+ m_xFields->commitTo(aPreviouslySelected->aFields);
+ if (m_xFields->GetSavedValue() != aPreviouslySelected->aFields)
+ aPreviouslySelected->setModified(true);
+
+ // plausibility checks
+ if (_bPlausibility && !implCheckPlausibility(aPreviouslySelected))
+ return false;
+
+ return true;
+ }
+
+ bool DbaIndexDialog::implCheckPlausibility(const Indexes::const_iterator& _rPos)
+ {
+ // need at least one field
+ if (_rPos->aFields.empty())
+ {
+ std::unique_ptr<weld::MessageDialog> xError(Application::CreateMessageDialog(m_xDialog.get(),
+ VclMessageType::Warning, VclButtonsType::Ok,
+ DBA_RES(STR_NEED_INDEX_FIELDS)));
+ xError->run();
+ m_xFields->GrabFocus();
+ return false;
+ }
+
+ // no double fields
+ std::set< OUString > aExistentFields;
+ for (auto const& fieldCheck : _rPos->aFields)
+ {
+ if (aExistentFields.end() != aExistentFields.find(fieldCheck.sFieldName))
+ {
+ // a column is specified twice ... won't work anyway, so prevent this here and now
+ OUString sMessage(DBA_RES(STR_INDEXDESIGN_DOUBLE_COLUMN_NAME));
+ sMessage = sMessage.replaceFirst("$name$", fieldCheck.sFieldName);
+ std::unique_ptr<weld::MessageDialog> xError(Application::CreateMessageDialog(m_xDialog.get(),
+ VclMessageType::Warning, VclButtonsType::Ok,
+ sMessage));
+ xError->run();
+ m_xFields->GrabFocus();
+ return false;
+ }
+ aExistentFields.insert(fieldCheck.sFieldName);
+ }
+
+ return true;
+ }
+
+ bool DbaIndexDialog::implCommitPreviouslySelected()
+ {
+ if (m_xPreviousSelection)
+ {
+ Indexes::const_iterator aPreviouslySelected = m_xIndexes->begin() + m_xIndexList->get_id(*m_xPreviousSelection).toUInt32();
+
+ if (!implSaveModified())
+ return false;
+
+ // commit the index (if necessary)
+ if (aPreviouslySelected->isModified() && !implCommit(m_xPreviousSelection.get()))
+ return false;
+ }
+
+ return true;
+ }
+
+ IMPL_LINK_NOARG(DbaIndexDialog, OnModifiedClick, weld::Toggleable&, void)
+ {
+ OnModified(*m_xFields);
+ }
+
+ IMPL_LINK_NOARG( DbaIndexDialog, OnModified, IndexFieldsControl&, void )
+ {
+ assert(m_xPreviousSelection && "DbaIndexDialog, OnModified: invalid call!");
+ Indexes::iterator aPosition = m_xIndexes->begin() + m_xIndexList->get_id(*m_xPreviousSelection).toUInt32();
+
+ aPosition->setModified(true);
+ updateToolbox();
+ }
+
+ void DbaIndexDialog::updateControls(const weld::TreeIter* pEntry)
+ {
+ if (pEntry)
+ {
+ // the descriptor of the selected index
+ Indexes::const_iterator aSelectedIndex = m_xIndexes->begin() + m_xIndexList->get_id(*pEntry).toUInt32();
+
+ // fill the controls
+ m_xUnique->set_active(aSelectedIndex->bUnique);
+ m_xUnique->set_sensitive(!aSelectedIndex->bPrimaryKey);
+ m_xUnique->save_state();
+
+ m_xFields->initializeFrom(std::vector(aSelectedIndex->aFields));
+ m_xFields->Enable(!aSelectedIndex->bPrimaryKey);
+ m_xFields->SaveValue();
+
+ m_xDescription->set_label(aSelectedIndex->sDescription);
+ m_xDescription->set_sensitive(!aSelectedIndex->bPrimaryKey);
+
+ m_xDescriptionLabel->set_sensitive(!aSelectedIndex->bPrimaryKey);
+ }
+ else
+ {
+ m_xUnique->set_active(false);
+ m_xFields->initializeFrom(IndexFields());
+ m_xDescription->set_label(OUString());
+ }
+ }
+
+ void DbaIndexDialog::IndexSelected()
+ {
+ if (m_bEditingActive)
+ m_xIndexList->end_editing();
+
+ std::unique_ptr<weld::TreeIter> xSelected(m_xIndexList->make_iterator());
+ if (!m_xIndexList->get_selected(xSelected.get()))
+ xSelected.reset();
+
+ // commit the old data
+ if (m_xPreviousSelection && (!xSelected || !m_xPreviousSelection->equal(*xSelected)))
+ {
+ // (this call may happen in case somebody ended an in-place edit with 'return', so we need to check this before committing)
+ if (!implCommitPreviouslySelected())
+ {
+ m_bNoHandlerCall = true;
+ m_xIndexList->select(*m_xPreviousSelection);
+ m_bNoHandlerCall = false;
+ return;
+ }
+ }
+
+ // disable/enable the detail controls
+ m_xIndexDetails->set_sensitive(xSelected != nullptr);
+ m_xUnique->set_sensitive(xSelected != nullptr);
+ m_xDescriptionLabel->set_sensitive(xSelected != nullptr);
+ m_xFieldsLabel->set_sensitive(xSelected != nullptr);
+ m_xFields->Enable(xSelected != nullptr);
+
+ updateControls(xSelected.get());
+ if (xSelected)
+ m_xIndexList->grab_focus();
+
+ m_xPreviousSelection = std::move(xSelected);
+
+ updateToolbox();
+ }
+
+ IMPL_LINK_NOARG(DbaIndexDialog, OnIndexSelected, weld::TreeView&, void)
+ {
+ if (m_bNoHandlerCall)
+ return;
+ IndexSelected();
+ }
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/dlg/indexfieldscontrol.cxx b/dbaccess/source/ui/dlg/indexfieldscontrol.cxx
new file mode 100644
index 000000000..35b0e3f02
--- /dev/null
+++ b/dbaccess/source/ui/dlg/indexfieldscontrol.cxx
@@ -0,0 +1,447 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <core_resource.hxx>
+#include <indexfieldscontrol.hxx>
+#include <strings.hrc>
+#include <o3tl/safeint.hxx>
+#include <osl/diagnose.h>
+#include <helpids.h>
+#include <toolkit/helper/vclunohelper.hxx>
+#include <vcl/settings.hxx>
+#include <vcl/svapp.hxx>
+
+namespace dbaui
+{
+
+constexpr auto BROWSER_STANDARD_FLAGS = BrowserMode::COLUMNSELECTION | BrowserMode::HLINES | BrowserMode::VLINES |
+ BrowserMode::HIDECURSOR | BrowserMode::HIDESELECT | BrowserMode::AUTO_HSCROLL | BrowserMode::AUTO_VSCROLL;
+
+#define COLUMN_ID_FIELDNAME 1
+#define COLUMN_ID_ORDER 2
+
+ using namespace ::com::sun::star::uno;
+ using namespace ::svt;
+
+ // DbaMouseDownListBoxController
+ class DbaMouseDownListBoxController : public ListBoxCellController
+ {
+ protected:
+ Link<DbaMouseDownListBoxController&,void> m_aAdditionalModifyHdl;
+
+ public:
+ explicit DbaMouseDownListBoxController(ListBoxControl* _pParent)
+ :ListBoxCellController(_pParent)
+ {
+ }
+
+ void SetAdditionalModifyHdl(const Link<DbaMouseDownListBoxController&,void>& _rHdl);
+
+ protected:
+ virtual void callModifyHdl() override;
+ };
+
+ void DbaMouseDownListBoxController::SetAdditionalModifyHdl(const Link<DbaMouseDownListBoxController&,void>& _rHdl)
+ {
+ m_aAdditionalModifyHdl = _rHdl;
+ }
+
+ void DbaMouseDownListBoxController::callModifyHdl()
+ {
+ m_aAdditionalModifyHdl.Call(*this);
+ ListBoxCellController::callModifyHdl();
+ }
+
+ // IndexFieldsControl
+ IndexFieldsControl::IndexFieldsControl(const css::uno::Reference<css::awt::XWindow> &rParent)
+ : EditBrowseBox(VCLUnoHelper::GetWindow(rParent), EditBrowseBoxFlags::SMART_TAB_TRAVEL | EditBrowseBoxFlags::ACTIVATE_ON_BUTTONDOWN, WB_TABSTOP | WB_BORDER, BROWSER_STANDARD_FLAGS)
+ , m_aSeekRow(m_aFields.end())
+ , m_pSortingCell(nullptr)
+ , m_pFieldNameCell(nullptr)
+ , m_bAddIndexAppendix(false)
+ {
+ }
+
+ IndexFieldsControl::~IndexFieldsControl()
+ {
+ disposeOnce();
+ }
+
+ void IndexFieldsControl::dispose()
+ {
+ m_pSortingCell.disposeAndClear();
+ m_pFieldNameCell.disposeAndClear();
+ ::svt::EditBrowseBox::dispose();
+ }
+
+ bool IndexFieldsControl::SeekRow(sal_Int32 nRow)
+ {
+ if (!EditBrowseBox::SeekRow(nRow))
+ return false;
+
+ if (nRow < 0)
+ {
+ m_aSeekRow = m_aFields.end();
+ }
+ else
+ {
+ m_aSeekRow = m_aFields.begin() + nRow;
+ OSL_ENSURE(m_aSeekRow <= m_aFields.end(), "IndexFieldsControl::SeekRow: invalid row!");
+ }
+
+ return true;
+ }
+
+ void IndexFieldsControl::PaintCell( OutputDevice& _rDev, const tools::Rectangle& _rRect, sal_uInt16 _nColumnId ) const
+ {
+ Point aPos(_rRect.TopLeft());
+ aPos.AdjustX(1 );
+
+ OUString aText = GetRowCellText(m_aSeekRow,_nColumnId);
+ Size TxtSize(GetDataWindow().GetTextWidth(aText), GetDataWindow().GetTextHeight());
+
+ // clipping
+ if (aPos.X() < _rRect.Right() || aPos.X() + TxtSize.Width() > _rRect.Right() ||
+ aPos.Y() < _rRect.Top() || aPos.Y() + TxtSize.Height() > _rRect.Bottom())
+ _rDev.SetClipRegion(vcl::Region(_rRect));
+
+ // allow for a disabled control ...
+ bool bEnabled = IsEnabled();
+ Color aOriginalColor = _rDev.GetTextColor();
+ if (!bEnabled)
+ _rDev.SetTextColor(GetSettings().GetStyleSettings().GetDisableColor());
+
+ // draw the text
+ _rDev.DrawText(aPos, aText);
+
+ // reset the color (if necessary)
+ if (!bEnabled)
+ _rDev.SetTextColor(aOriginalColor);
+
+ if (_rDev.IsClipRegion())
+ _rDev.SetClipRegion();
+ }
+
+ void IndexFieldsControl::initializeFrom(IndexFields&& _rFields)
+ {
+ // copy the field descriptions
+ m_aFields = std::move(_rFields);
+ m_aSeekRow = m_aFields.end();
+
+ SetUpdateMode(false);
+ // remove all rows
+ RowRemoved(1, GetRowCount());
+ // insert rows for the fields
+ RowInserted(GetRowCount(), m_aFields.size(), false);
+ // insert an additional row for a new field for that index
+ RowInserted(GetRowCount(), 1, false);
+ SetUpdateMode(true);
+
+ GoToRowColumnId(0, COLUMN_ID_FIELDNAME);
+ }
+
+ void IndexFieldsControl::commitTo(IndexFields& _rFields)
+ {
+ // do not just copy the array, we may have empty field names (which should not be copied)
+ _rFields.resize(m_aFields.size());
+ IndexFields::iterator aDest = std::copy_if(m_aFields.begin(), m_aFields.end(), _rFields.begin(),
+ [](const OIndexField& source) { return !source.sFieldName.isEmpty(); });
+
+ _rFields.resize(aDest - _rFields.begin());
+ }
+
+ sal_uInt32 IndexFieldsControl::GetTotalCellWidth(sal_Int32 _nRow, sal_uInt16 _nColId)
+ {
+ if (COLUMN_ID_ORDER == _nColId)
+ {
+ sal_Int32 nWidthAsc = GetTextWidth(m_sAscendingText) + GetSettings().GetStyleSettings().GetScrollBarSize();
+ sal_Int32 nWidthDesc = GetTextWidth(m_sDescendingText) + GetSettings().GetStyleSettings().GetScrollBarSize();
+ // maximum plus some additional space
+ return std::max(nWidthAsc, nWidthDesc) + GetTextWidth(OUString('0')) * 2;
+ }
+ return EditBrowseBox::GetTotalCellWidth(_nRow, _nColId);
+ }
+
+ void IndexFieldsControl::Init(const Sequence< OUString >& _rAvailableFields, bool _bAddIndexAppendix)
+ {
+ m_bAddIndexAppendix = _bAddIndexAppendix;
+
+ RemoveColumns();
+
+ // for the width: both columns together should be somewhat smaller than the whole window (without the scrollbar)
+ sal_Int32 nFieldNameWidth = GetSizePixel().Width();
+
+ if ( m_bAddIndexAppendix )
+ {
+ m_sAscendingText = DBA_RES(STR_ORDER_ASCENDING);
+ m_sDescendingText = DBA_RES(STR_ORDER_DESCENDING);
+
+ // the "sort order" column
+ OUString sColumnName = DBA_RES(STR_TAB_INDEX_SORTORDER);
+ // the width of the order column is the maximum widths of the texts used
+ // (the title of the column)
+ sal_Int32 nSortOrderColumnWidth = GetTextWidth(sColumnName);
+ // ("ascending" + scrollbar width)
+ sal_Int32 nOther = GetTextWidth(m_sAscendingText) + GetSettings().GetStyleSettings().GetScrollBarSize();
+ nSortOrderColumnWidth = std::max(nSortOrderColumnWidth, nOther);
+ // ("descending" + scrollbar width)
+ nOther = GetTextWidth(m_sDescendingText) + GetSettings().GetStyleSettings().GetScrollBarSize();
+ nSortOrderColumnWidth = std::max(nSortOrderColumnWidth, nOther);
+ // (plus some additional space)
+ nSortOrderColumnWidth += GetTextWidth(OUString('0')) * 2;
+ InsertDataColumn(COLUMN_ID_ORDER, sColumnName, nSortOrderColumnWidth, HeaderBarItemBits::STDSTYLE, 1);
+
+ m_pSortingCell = VclPtr<ListBoxControl>::Create(&GetDataWindow());
+ weld::ComboBox& rSortingListBox = m_pSortingCell->get_widget();
+ rSortingListBox.append_text(m_sAscendingText);
+ rSortingListBox.append_text(m_sDescendingText);
+ rSortingListBox.set_help_id(HID_DLGINDEX_INDEXDETAILS_SORTORDER);
+
+ nFieldNameWidth -= nSortOrderColumnWidth;
+ }
+ StyleSettings aSystemStyle = Application::GetSettings().GetStyleSettings();
+ nFieldNameWidth -= aSystemStyle.GetScrollBarSize();
+ nFieldNameWidth -= 8;
+ // the "field name" column
+ OUString sColumnName = DBA_RES(STR_TAB_INDEX_FIELD);
+ InsertDataColumn(COLUMN_ID_FIELDNAME, sColumnName, nFieldNameWidth, HeaderBarItemBits::STDSTYLE, 0);
+
+ // create the cell controllers
+ // for the field name cell
+ m_pFieldNameCell = VclPtr<ListBoxControl>::Create(&GetDataWindow());
+ weld::ComboBox& rNameListBox = m_pFieldNameCell->get_widget();
+ rNameListBox.append_text(OUString());
+ rNameListBox.set_help_id(HID_DLGINDEX_INDEXDETAILS_FIELD);
+ const OUString* pFields = _rAvailableFields.getConstArray();
+ const OUString* pFieldsEnd = pFields + _rAvailableFields.getLength();
+ for (;pFields < pFieldsEnd; ++pFields)
+ rNameListBox.append_text(*pFields);
+ }
+
+ CellController* IndexFieldsControl::GetController(sal_Int32 _nRow, sal_uInt16 _nColumnId)
+ {
+ if (!IsEnabled())
+ return nullptr;
+
+ IndexFields::const_iterator aRow;
+ bool bNewField = !implGetFieldDesc(_nRow, aRow);
+
+ DbaMouseDownListBoxController* pReturn = nullptr;
+ switch (_nColumnId)
+ {
+ case COLUMN_ID_ORDER:
+ if (!bNewField && m_pSortingCell && !aRow->sFieldName.isEmpty())
+ pReturn = new DbaMouseDownListBoxController(m_pSortingCell);
+ break;
+
+ case COLUMN_ID_FIELDNAME:
+ pReturn = new DbaMouseDownListBoxController(m_pFieldNameCell);
+ break;
+
+ default:
+ OSL_FAIL("IndexFieldsControl::GetController: invalid column id!");
+ }
+
+ if (pReturn)
+ pReturn->SetAdditionalModifyHdl(LINK(this, IndexFieldsControl, OnListEntrySelected));
+
+ return pReturn;
+ }
+
+ bool IndexFieldsControl::implGetFieldDesc(sal_Int32 _nRow, IndexFields::const_iterator& _rPos)
+ {
+ _rPos = m_aFields.end();
+ if ((_nRow < 0) || (o3tl::make_unsigned(_nRow) >= m_aFields.size()))
+ return false;
+ _rPos = m_aFields.begin() + _nRow;
+ return true;
+ }
+
+ bool IndexFieldsControl::SaveModified()
+ {
+ if (!IsModified())
+ return true;
+
+ switch (GetCurColumnId())
+ {
+ case COLUMN_ID_FIELDNAME:
+ {
+ weld::ComboBox& rNameListBox = m_pFieldNameCell->get_widget();
+ OUString sFieldSelected = rNameListBox.get_active_text();
+ bool bEmptySelected = sFieldSelected.isEmpty();
+ if (isNewField())
+ {
+ if (!bEmptySelected)
+ {
+ // add a new field to the collection
+ OIndexField aNewField;
+ aNewField.sFieldName = sFieldSelected;
+ m_aFields.push_back(aNewField);
+ RowInserted(GetRowCount());
+ }
+ }
+ else
+ {
+ sal_Int32 nRow = GetCurRow();
+ OSL_ENSURE(nRow < static_cast<sal_Int32>(m_aFields.size()), "IndexFieldsControl::SaveModified: invalid current row!");
+ if (nRow >= 0) // may be -1 in case the control was empty
+ {
+ // remove the field from the selection
+ IndexFields::iterator aPos = m_aFields.begin() + nRow;
+
+ if (bEmptySelected)
+ {
+ aPos->sFieldName.clear();
+
+ // invalidate the row to force repaint
+ Invalidate(GetRowRectPixel(nRow));
+ return true;
+ }
+
+ if (sFieldSelected == aPos->sFieldName)
+ // nothing changed
+ return true;
+
+ aPos->sFieldName = sFieldSelected;
+ }
+ }
+
+ Invalidate(GetRowRectPixel(GetCurRow()));
+ }
+ break;
+ case COLUMN_ID_ORDER:
+ {
+ OSL_ENSURE(!isNewField(), "IndexFieldsControl::SaveModified: why the hell ...!!!");
+ // selected entry
+ weld::ComboBox& rSortingListBox = m_pSortingCell->get_widget();
+ sal_Int32 nPos = rSortingListBox.get_active();
+ OSL_ENSURE(nPos != -1, "IndexFieldsControl::SaveModified: how did you get this selection??");
+ // adjust the sort flag in the index field description
+ OIndexField& rCurrentField = m_aFields[GetCurRow()];
+ rCurrentField.bSortAscending = (0 == nPos);
+
+ }
+ break;
+ default:
+ OSL_FAIL("IndexFieldsControl::SaveModified: invalid column id!");
+ }
+ return true;
+ }
+
+ void IndexFieldsControl::InitController(CellControllerRef& /*_rController*/, sal_Int32 _nRow, sal_uInt16 _nColumnId)
+ {
+ IndexFields::const_iterator aFieldDescription;
+ bool bNewField = !implGetFieldDesc(_nRow, aFieldDescription);
+
+ switch (_nColumnId)
+ {
+ case COLUMN_ID_FIELDNAME:
+ {
+ weld::ComboBox& rNameListBox = m_pFieldNameCell->get_widget();
+ rNameListBox.set_active_text(bNewField ? OUString() : aFieldDescription->sFieldName);
+ rNameListBox.save_value();
+ break;
+ }
+
+ case COLUMN_ID_ORDER:
+ {
+ weld::ComboBox& rSortingListBox = m_pSortingCell->get_widget();
+ rSortingListBox.set_active_text(aFieldDescription->bSortAscending ? m_sAscendingText : m_sDescendingText);
+ rSortingListBox.save_value();
+ break;
+ }
+
+ default:
+ OSL_FAIL("IndexFieldsControl::InitController: invalid column id!");
+ }
+ }
+
+ IMPL_LINK( IndexFieldsControl, OnListEntrySelected, DbaMouseDownListBoxController&, rController, void )
+ {
+ weld::ComboBox& rListBox = rController.GetListBox();
+ if (!rListBox.get_popup_shown())
+ m_aModifyHdl.Call(*this);
+
+ if (&rListBox != &m_pFieldNameCell->get_widget())
+ return;
+
+// a field has been selected
+ if (GetCurRow() >= GetRowCount() - 2)
+ { // and we're in one of the last two rows
+ OUString sSelectedEntry = rListBox.get_active_text();
+ sal_Int32 nCurrentRow = GetCurRow();
+ sal_Int32 rowCount = GetRowCount();
+
+ OSL_ENSURE((static_cast<sal_Int32>(m_aFields.size() + 1)) == rowCount, "IndexFieldsControl::OnListEntrySelected: inconsistence!");
+
+ if (!sSelectedEntry.isEmpty() && (nCurrentRow == rowCount - 1) /*&& (!m_nMaxColumnsInIndex || rowCount < m_nMaxColumnsInIndex )*/ )
+ { // in the last row, a non-empty string has been selected
+ // -> insert a new row
+ m_aFields.emplace_back();
+ RowInserted(GetRowCount());
+ Invalidate(GetRowRectPixel(nCurrentRow));
+ }
+ else if (sSelectedEntry.isEmpty() && (nCurrentRow == rowCount - 2))
+ { // in the (last-1)th row, an empty entry has been selected
+ // -> remove the last row
+ m_aFields.pop_back();
+ RowRemoved(GetRowCount() - 1);
+ Invalidate(GetRowRectPixel(nCurrentRow));
+ }
+ }
+
+ SaveModified();
+ }
+ OUString IndexFieldsControl::GetCellText(sal_Int32 _nRow,sal_uInt16 nColId) const
+ {
+ IndexFields::const_iterator aRow = m_aFields.end();
+ if ( _nRow >= 0 )
+ {
+ aRow = m_aFields.begin() + _nRow;
+ OSL_ENSURE(aRow <= m_aFields.end(), "IndexFieldsControl::SeekRow: invalid row!");
+ }
+ return GetRowCellText(aRow,nColId);
+ }
+ OUString IndexFieldsControl::GetRowCellText(const IndexFields::const_iterator& _rRow,sal_uInt16 nColId) const
+ {
+ if (_rRow < m_aFields.end())
+ {
+ switch (nColId)
+ {
+ case COLUMN_ID_FIELDNAME:
+ return _rRow->sFieldName;
+ case COLUMN_ID_ORDER:
+ if (_rRow->sFieldName.isEmpty())
+ return OUString();
+ else
+ return _rRow->bSortAscending ? m_sAscendingText : m_sDescendingText;
+ default:
+ OSL_FAIL("IndexFieldsControl::GetCurrentRowCellText: invalid column id!");
+ }
+ }
+ return OUString();
+ }
+ bool IndexFieldsControl::IsTabAllowed(bool /*bForward*/) const
+ {
+ return false;
+ }
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/dlg/odbcconfig.cxx b/dbaccess/source/ui/dlg/odbcconfig.cxx
new file mode 100644
index 000000000..b2f3a45ff
--- /dev/null
+++ b/dbaccess/source/ui/dlg/odbcconfig.cxx
@@ -0,0 +1,325 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <config_folders.h>
+#include "odbcconfig.hxx"
+
+#include <rtl/bootstrap.hxx>
+#include <rtl/ustring.hxx>
+#include <osl/diagnose.h>
+#include <osl/process.h>
+#include <osl/thread.hxx>
+#include <vcl/svapp.hxx>
+
+#ifdef HAVE_ODBC_SUPPORT
+
+#if defined(_WIN32)
+#define ODBC_LIBRARY "ODBC32.DLL"
+#endif
+#ifdef UNX
+#ifdef MACOSX
+#define ODBC_LIBRARY "libiodbc.dylib"
+#else
+#define ODBC_LIBRARY_PLAIN "libodbc.so"
+#define ODBC_LIBRARY_1 "libodbc.so.1"
+#define ODBC_LIBRARY "libodbc.so.2"
+#endif
+#endif
+
+#include <connectivity/odbc.hxx>
+
+#else
+
+#define ODBC_LIBRARY ""
+
+#endif // HAVE_ODBC_SUPPORT
+
+namespace dbaui
+{
+
+#ifdef HAVE_ODBC_SUPPORT
+typedef SQLRETURN (SQL_API* TSQLManageDataSource) (SQLHWND hwndParent);
+typedef SQLRETURN (SQL_API* TSQLAllocHandle) (SQLSMALLINT HandleType, SQLHANDLE InputHandle, SQLHANDLE* OutputHandlePtr);
+typedef SQLRETURN (SQL_API* TSQLFreeHandle) (SQLSMALLINT HandleType, SQLHANDLE Handle);
+typedef SQLRETURN (SQL_API* TSQLSetEnvAttr) (SQLHENV EnvironmentHandle, SQLINTEGER Attribute, SQLPOINTER ValuePtr, SQLINTEGER StringLength);
+typedef SQLRETURN (SQL_API* TSQLDataSources) (SQLHENV EnvironmentHandle, SQLUSMALLINT Direction, SQLCHAR* ServerName,
+ SQLSMALLINT BufferLength1, SQLSMALLINT* NameLength1Ptr, SQLCHAR* Description, SQLSMALLINT BufferLength2, SQLSMALLINT* NameLength2Ptr);
+
+#endif
+
+// OOdbcLibWrapper
+
+bool OOdbcEnumeration::load(const char* _pLibPath)
+{
+ m_sLibPath = OUString::createFromAscii(_pLibPath);
+#if defined(HAVE_ODBC_SUPPORT) && !defined(DISABLE_DYNLOADING)
+ // load the module
+ m_pOdbcLib = osl_loadModule(m_sLibPath.pData, SAL_LOADMODULE_NOW);
+ return (nullptr != m_pOdbcLib);
+#else
+ return sal_False;
+#endif
+}
+
+void OOdbcEnumeration::unload()
+{
+#if defined(HAVE_ODBC_SUPPORT) && !defined(DISABLE_DYNLOADING)
+ if (isLoaded())
+ {
+ osl_unloadModule(m_pOdbcLib);
+ m_pOdbcLib = nullptr;
+ }
+#endif
+}
+
+oslGenericFunction OOdbcEnumeration::loadSymbol(const char* _pFunctionName)
+{
+ return osl_getFunctionSymbol(m_pOdbcLib, OUString::createFromAscii(_pFunctionName).pData);
+}
+
+
+struct OdbcTypesImpl
+{
+#ifdef HAVE_ODBC_SUPPORT
+ SQLHANDLE hEnvironment;
+ OdbcTypesImpl() : hEnvironment(nullptr) { }
+#else
+ void* pDummy;
+#endif
+};
+
+OOdbcEnumeration::OOdbcEnumeration()
+ :m_pOdbcLib(nullptr)
+#ifdef HAVE_ODBC_SUPPORT
+ ,m_pAllocHandle(nullptr)
+ ,m_pFreeHandle(nullptr)
+ ,m_pSetEnvAttr(nullptr)
+ ,m_pDataSources(nullptr)
+ ,m_pImpl(new OdbcTypesImpl)
+#endif
+{
+ bool bLoaded = load(ODBC_LIBRARY);
+#ifdef ODBC_LIBRARY_1
+ if ( !bLoaded )
+ bLoaded = load(ODBC_LIBRARY_1);
+#endif
+#ifdef ODBC_LIBRARY_PLAIN
+ if ( !bLoaded )
+ bLoaded = load(ODBC_LIBRARY_PLAIN);
+#endif
+
+ if ( !bLoaded )
+ return;
+
+#ifdef HAVE_ODBC_SUPPORT
+ // load the generic functions
+ m_pAllocHandle = loadSymbol("SQLAllocHandle");
+ m_pFreeHandle = loadSymbol("SQLFreeHandle");
+ m_pSetEnvAttr = loadSymbol("SQLSetEnvAttr");
+ m_pDataSources = loadSymbol("SQLDataSources");
+
+ // all or nothing
+ if (!m_pAllocHandle || !m_pSetEnvAttr || !m_pDataSources || !m_pFreeHandle)
+ {
+ unload();
+ m_pAllocHandle = m_pFreeHandle = m_pSetEnvAttr = m_pDataSources = nullptr;
+ }
+#endif
+}
+
+OOdbcEnumeration::~OOdbcEnumeration()
+{
+ freeEnv();
+ unload();
+}
+
+// OOdbcEnumeration
+bool OOdbcEnumeration::allocEnv()
+{
+ OSL_ENSURE(isLoaded(), "OOdbcEnumeration::allocEnv: not loaded!");
+ if (!isLoaded())
+ return false;
+
+#ifdef HAVE_ODBC_SUPPORT
+ if (m_pImpl->hEnvironment)
+ // nothing to do
+ return true;
+ SQLRETURN nResult = (*reinterpret_cast<TSQLAllocHandle>(m_pAllocHandle))(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &m_pImpl->hEnvironment);
+ if (SQL_SUCCESS != nResult)
+ // can't do anything without environment
+ return false;
+
+ (*reinterpret_cast<TSQLSetEnvAttr>(m_pSetEnvAttr))(m_pImpl->hEnvironment, SQL_ATTR_ODBC_VERSION, reinterpret_cast<SQLPOINTER>(SQL_OV_ODBC3),SQL_IS_INTEGER);
+ return true;
+#else
+ return sal_False;
+#endif
+}
+
+void OOdbcEnumeration::freeEnv()
+{
+#ifdef HAVE_ODBC_SUPPORT
+ if (m_pImpl->hEnvironment)
+ (*reinterpret_cast<TSQLFreeHandle>(m_pFreeHandle))(SQL_HANDLE_ENV, m_pImpl->hEnvironment);
+ m_pImpl->hEnvironment = nullptr;
+#endif
+}
+
+void OOdbcEnumeration::getDatasourceNames(std::set<OUString>& _rNames)
+{
+ OSL_ENSURE(isLoaded(), "OOdbcEnumeration::getDatasourceNames: not loaded!");
+ if (!isLoaded())
+ return;
+
+ if (!allocEnv())
+ {
+ OSL_FAIL("OOdbcEnumeration::getDatasourceNames: could not allocate an ODBC environment!");
+ return;
+ }
+
+#ifdef HAVE_ODBC_SUPPORT
+ // now that we have an environment collect the data source names
+ UCHAR szDSN[SQL_MAX_DSN_LENGTH+1];
+ SWORD pcbDSN;
+ UCHAR szDescription[1024+1];
+ SWORD pcbDescription;
+ SQLRETURN nResult = SQL_SUCCESS;
+ rtl_TextEncoding nTextEncoding = osl_getThreadTextEncoding();
+
+ for ( nResult = (*reinterpret_cast<TSQLDataSources>(m_pDataSources))(m_pImpl->hEnvironment, SQL_FETCH_FIRST, szDSN,
+ sizeof(szDSN), &pcbDSN, szDescription, sizeof(szDescription)-1, &pcbDescription);
+ ;
+ nResult = (*reinterpret_cast<TSQLDataSources>(m_pDataSources))(m_pImpl->hEnvironment, SQL_FETCH_NEXT, szDSN,
+ sizeof(szDSN), &pcbDSN, szDescription, sizeof(szDescription)-1, &pcbDescription)
+ )
+ {
+ if (nResult != SQL_SUCCESS)
+ // no further error handling
+ break;
+ else
+ {
+ OUString aCurrentDsn(reinterpret_cast<const char*>(szDSN),pcbDSN, nTextEncoding);
+ _rNames.insert(aCurrentDsn);
+ }
+ }
+#else
+ (void) _rNames;
+#endif
+}
+
+#ifdef HAVE_ODBC_ADMINISTRATION
+
+// ProcessTerminationWait
+class ProcessTerminationWait : public ::osl::Thread
+{
+ oslProcess m_hProcessHandle;
+ Link<void*,void> m_aFinishHdl;
+ ImplSVEvent* m_nEventId;
+
+public:
+ ProcessTerminationWait( oslProcess _hProcessHandle, const Link<void*,void>& _rFinishHdl )
+ : m_hProcessHandle( _hProcessHandle )
+ , m_aFinishHdl( _rFinishHdl )
+ , m_nEventId(nullptr)
+ {
+ }
+
+ void disableCallback()
+ {
+ // if finished event not posted yet, disable by turning it to a no-op Link
+ m_aFinishHdl = Link<void*, void>();
+ if (m_nEventId)
+ {
+ // already posted, remove it
+ Application::RemoveUserEvent(m_nEventId);
+ m_nEventId = nullptr;
+ }
+ }
+
+ void receivedCallback()
+ {
+ m_nEventId = nullptr;
+ }
+
+protected:
+ virtual void SAL_CALL run() override
+ {
+ osl_setThreadName("dbaui::ProcessTerminationWait");
+
+ osl_joinProcess( m_hProcessHandle );
+ osl_freeProcessHandle( m_hProcessHandle );
+ m_nEventId = Application::PostUserEvent( m_aFinishHdl );
+ }
+};
+
+// OOdbcManagement
+OOdbcManagement::OOdbcManagement(const Link<void*,void>& rAsyncFinishCallback)
+ : m_aAsyncFinishCallback(rAsyncFinishCallback)
+{
+}
+
+OOdbcManagement::~OOdbcManagement()
+{
+ // wait for our thread to be finished
+ if ( m_pProcessWait )
+ m_pProcessWait->join();
+}
+
+bool OOdbcManagement::manageDataSources_async()
+{
+ OSL_PRECOND( !isRunning(), "OOdbcManagement::manageDataSources_async: still running from the previous call!" );
+ if ( isRunning() )
+ return false;
+
+ // this is done in an external process, due to #i78733#
+ // (and note this whole functionality is supported on Windows only, ATM)
+ OUString sExecutableName( "$BRAND_BASE_DIR/" LIBO_LIBEXEC_FOLDER "/odbcconfig.exe" );
+ ::rtl::Bootstrap::expandMacros( sExecutableName ); //TODO: detect failure
+ oslProcess hProcessHandle(nullptr);
+ oslProcessError eError = osl_executeProcess( sExecutableName.pData, nullptr, 0, 0, nullptr, nullptr, nullptr, 0, &hProcessHandle );
+ if ( eError != osl_Process_E_None )
+ return false;
+
+ m_pProcessWait.reset( new ProcessTerminationWait( hProcessHandle, m_aAsyncFinishCallback ) );
+ m_pProcessWait->create();
+ return true;
+}
+
+void OOdbcManagement::disableCallback()
+{
+ if (m_pProcessWait)
+ m_pProcessWait->disableCallback();
+}
+
+void OOdbcManagement::receivedCallback()
+{
+ if (m_pProcessWait)
+ m_pProcessWait->receivedCallback();
+}
+
+bool OOdbcManagement::isRunning() const
+{
+ return ( m_pProcessWait && m_pProcessWait->isRunning() );
+}
+
+#endif // HAVE_ODBC_ADMINISTRATION
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/dlg/odbcconfig.hxx b/dbaccess/source/ui/dlg/odbcconfig.hxx
new file mode 100644
index 000000000..16177ad8a
--- /dev/null
+++ b/dbaccess/source/ui/dlg/odbcconfig.hxx
@@ -0,0 +1,106 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#if defined(_WIN32) || (defined (UNX) && !defined(ANDROID) && !defined(IOS))
+#define HAVE_ODBC_SUPPORT
+#endif
+
+#if defined(_WIN32) && defined(HAVE_ODBC_SUPPORT)
+#define HAVE_ODBC_ADMINISTRATION
+#endif
+
+#include <rtl/ustring.hxx>
+#include <tools/link.hxx>
+#include <osl/module.h>
+
+#include <memory>
+#include <set>
+
+namespace dbaui
+{
+
+// OOdbcEnumeration
+struct OdbcTypesImpl;
+class OOdbcEnumeration final
+{
+ oslModule m_pOdbcLib; // the library handle
+ OUString m_sLibPath; // the path to the library
+
+#ifdef HAVE_ODBC_SUPPORT
+ // entry points for ODBC administration
+ oslGenericFunction m_pAllocHandle;
+ oslGenericFunction m_pFreeHandle;
+ oslGenericFunction m_pSetEnvAttr;
+ oslGenericFunction m_pDataSources;
+
+#endif
+ std::unique_ptr<OdbcTypesImpl> m_pImpl;
+ // needed because we can't have a member of type SQLHANDLE: this would require us to include the respective
+ // ODBC file, which would lead to a lot of conflicts with other includes
+
+public:
+ OOdbcEnumeration();
+ ~OOdbcEnumeration();
+
+#ifdef HAVE_ODBC_SUPPORT
+ bool isLoaded() const { return nullptr != m_pOdbcLib; }
+#else
+ bool isLoaded() const { return false; }
+#endif
+ const OUString& getLibraryName() const { return m_sLibPath; }
+
+ void getDatasourceNames(std::set<OUString>& _rNames);
+
+private:
+ oslGenericFunction loadSymbol(const char* _pFunctionName);
+
+ /// load the lib
+ bool load(const char* _pLibPath);
+ /// unload the lib
+ void unload();
+ /// ensure that an ODBC environment is allocated
+ bool allocEnv();
+ /// free any allocated ODBC environment
+ void freeEnv();
+};
+
+// OOdbcManagement
+#ifdef HAVE_ODBC_ADMINISTRATION
+class ProcessTerminationWait;
+class OOdbcManagement
+{
+ std::unique_ptr< ProcessTerminationWait > m_pProcessWait;
+ Link<void*,void> m_aAsyncFinishCallback;
+
+public:
+ explicit OOdbcManagement( const Link<void*,void>& _rAsyncFinishCallback );
+ ~OOdbcManagement();
+
+ bool manageDataSources_async();
+ bool isRunning() const;
+ void disableCallback();
+ void receivedCallback();
+};
+#endif
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/dlg/optionalboolitem.cxx b/dbaccess/source/ui/dlg/optionalboolitem.cxx
new file mode 100644
index 000000000..30d176391
--- /dev/null
+++ b/dbaccess/source/ui/dlg/optionalboolitem.cxx
@@ -0,0 +1,44 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "optionalboolitem.hxx"
+
+namespace dbaui
+{
+
+ // OptionalBoolItem
+ OptionalBoolItem::OptionalBoolItem( sal_uInt16 _nWhich )
+ :SfxPoolItem( _nWhich )
+ {
+ }
+
+ bool OptionalBoolItem::operator==( const SfxPoolItem& _rItem ) const
+ {
+ return SfxPoolItem::operator==(_rItem) &&
+ static_cast<const OptionalBoolItem&>( _rItem ).m_aValue == m_aValue;
+ }
+
+ OptionalBoolItem* OptionalBoolItem::Clone( SfxItemPool* /*_pPool*/ ) const
+ {
+ return new OptionalBoolItem( *this );
+ }
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/dlg/optionalboolitem.hxx b/dbaccess/source/ui/dlg/optionalboolitem.hxx
new file mode 100644
index 000000000..c500dfa2a
--- /dev/null
+++ b/dbaccess/source/ui/dlg/optionalboolitem.hxx
@@ -0,0 +1,51 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <svl/poolitem.hxx>
+
+#include <optional>
+
+namespace dbaui
+{
+
+ // OptionalBoolItem
+ class OptionalBoolItem : public SfxPoolItem
+ {
+ ::std::optional< bool > m_aValue;
+
+ public:
+ explicit OptionalBoolItem( sal_uInt16 nWhich );
+
+ virtual bool operator==( const SfxPoolItem& _rItem ) const override;
+ virtual OptionalBoolItem* Clone( SfxItemPool* _pPool = nullptr ) const override;
+
+ bool HasValue() const { return !!m_aValue; }
+ void ClearValue() { m_aValue.reset(); }
+ bool GetValue() const { return *m_aValue; }
+ void SetValue(bool _bValue) { m_aValue = _bValue; }
+
+ const ::std::optional< bool >&
+ GetFullValue() const { return m_aValue; }
+ };
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/dlg/paramdialog.cxx b/dbaccess/source/ui/dlg/paramdialog.cxx
new file mode 100644
index 000000000..de3347682
--- /dev/null
+++ b/dbaccess/source/ui/dlg/paramdialog.cxx
@@ -0,0 +1,334 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <core_resource.hxx>
+#include <paramdialog.hxx>
+#include <strings.hrc>
+#include <strings.hxx>
+#include <com/sun/star/util/NumberFormatter.hpp>
+#include <comphelper/types.hxx>
+#include <connectivity/dbtools.hxx>
+#include <vcl/weld.hxx>
+#include <o3tl/safeint.hxx>
+#include <osl/diagnose.h>
+#include <tools/diagnose_ex.h>
+
+namespace dbaui
+{
+
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::lang;
+ using namespace ::com::sun::star::beans;
+ using namespace ::com::sun::star::container;
+ using namespace ::com::sun::star::sdbc;
+ using namespace ::com::sun::star::util;
+ using namespace ::connectivity;
+
+ // OParameterDialog
+
+
+ OParameterDialog::OParameterDialog(
+ weld::Window* pParent, const Reference< XIndexAccess > & rParamContainer,
+ const Reference< XConnection > & _rxConnection, const Reference< XComponentContext >& rxContext)
+ : GenericDialogController(pParent, "dbaccess/ui/parametersdialog.ui", "Parameters")
+ , m_nCurrentlySelected(-1)
+ , m_xConnection(_rxConnection)
+ , m_aPredicateInput( rxContext, _rxConnection, getParseContext() )
+ , m_aResetVisitFlag("dbaccess OParameterDialog m_aResetVisitFlag")
+ , m_xAllParams(m_xBuilder->weld_tree_view("allParamTreeview"))
+ , m_xParam(m_xBuilder->weld_entry("paramEntry"))
+ , m_xTravelNext(m_xBuilder->weld_button("next"))
+ , m_xOKBtn(m_xBuilder->weld_button("ok"))
+ , m_xCancelBtn(m_xBuilder->weld_button("cancel"))
+ {
+ m_xAllParams->set_size_request(-1, m_xAllParams->get_height_rows(10));
+
+ if (rxContext.is())
+ m_xFormatter.set( NumberFormatter::create( rxContext ), UNO_QUERY_THROW);
+ else {
+ OSL_FAIL("OParameterDialog::OParameterDialog: need a service factory!");
+ }
+
+ Reference< XNumberFormatsSupplier > xNumberFormats = ::dbtools::getNumberFormats(m_xConnection, true);
+ if (!xNumberFormats.is())
+ ::comphelper::disposeComponent(m_xFormatter);
+ else
+ m_xFormatter->attachNumberFormatsSupplier(xNumberFormats);
+ try
+ {
+ OSL_ENSURE(rParamContainer->getCount(), "OParameterDialog::OParameterDialog : can't handle empty containers !");
+
+ m_aFinalValues.realloc(rParamContainer->getCount());
+ PropertyValue* pValues = m_aFinalValues.getArray();
+
+ for (sal_Int32 i = 0, nCount = rParamContainer->getCount(); i<nCount; ++i, ++pValues)
+ {
+ Reference< XPropertySet > xParamAsSet;
+ rParamContainer->getByIndex(i) >>= xParamAsSet;
+ OSL_ENSURE(xParamAsSet.is(),"Parameter is null!");
+ if(!xParamAsSet.is())
+ continue;
+ pValues->Name = ::comphelper::getString(xParamAsSet->getPropertyValue(PROPERTY_NAME));
+ m_xAllParams->append_text(pValues->Name);
+
+ m_aVisitedParams.push_back(VisitFlags::NONE);
+ // not visited, not dirty
+ }
+
+ m_xParams = rParamContainer;
+ }
+ catch(Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+
+ Construct();
+
+ m_aResetVisitFlag.SetInvokeHandler(LINK(this, OParameterDialog, OnVisitedTimeout));
+ }
+
+ OParameterDialog::~OParameterDialog()
+ {
+ if (m_aResetVisitFlag.IsActive())
+ m_aResetVisitFlag.Stop();
+ }
+
+ void OParameterDialog::Construct()
+ {
+ m_xAllParams->connect_changed(LINK(this, OParameterDialog, OnEntryListBoxSelected));
+ m_xParam->connect_focus_out(LINK(this, OParameterDialog, OnValueLoseFocusHdl));
+ m_xParam->connect_changed(LINK(this, OParameterDialog, OnValueModified));
+ m_xTravelNext->connect_clicked(LINK(this, OParameterDialog, OnButtonClicked));
+ m_xOKBtn->connect_clicked(LINK(this, OParameterDialog, OnButtonClicked));
+ m_xCancelBtn->connect_clicked(LINK(this, OParameterDialog, OnButtonClicked));
+
+ if (m_xAllParams->n_children())
+ {
+ m_xAllParams->select(0);
+ OnEntrySelected();
+
+ if (m_xAllParams->n_children() == 1)
+ m_xTravelNext->set_sensitive(false);
+
+ if (m_xAllParams->n_children() > 1)
+ m_xDialog->change_default_widget(m_xOKBtn.get(), m_xTravelNext.get());
+ }
+
+ m_xParam->grab_focus();
+ }
+
+ IMPL_LINK_NOARG(OParameterDialog, OnValueLoseFocusHdl, weld::Widget&, void)
+ {
+ CheckValueForError();
+ }
+
+ bool OParameterDialog::CheckValueForError()
+ {
+ if (m_nCurrentlySelected != -1)
+ {
+ if ( !( m_aVisitedParams[ m_nCurrentlySelected ] & VisitFlags::Dirty ) )
+ // nothing to do, the value isn't dirty
+ return false;
+ }
+
+ bool bRet = false;
+
+ Reference< XPropertySet > xParamAsSet;
+ m_xParams->getByIndex(m_nCurrentlySelected) >>= xParamAsSet;
+ if (xParamAsSet.is())
+ {
+ if (m_xConnection.is() && m_xFormatter.is())
+ {
+ OUString sParamValue(m_xParam->get_text());
+ bool bValid = m_aPredicateInput.normalizePredicateString( sParamValue, xParamAsSet );
+ m_xParam->set_text(sParamValue);
+ m_xParam->set_message_type(bValid ? weld::EntryMessageType::Normal : weld::EntryMessageType::Error);
+ OUString sToolTip;
+ if ( bValid )
+ {
+ // with this the value isn't dirty anymore
+ if (m_nCurrentlySelected != -1)
+ m_aVisitedParams[m_nCurrentlySelected] &= ~VisitFlags::Dirty;
+ }
+ else
+ {
+ OUString sName;
+ try
+ {
+ sName = ::comphelper::getString(xParamAsSet->getPropertyValue(PROPERTY_NAME));
+ }
+ catch(Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+
+ OUString sMessage(DBA_RES(STR_COULD_NOT_CONVERT_PARAM));
+ sToolTip = sMessage.replaceAll( "$name$", sName );
+ m_xParam->grab_focus();
+ bRet = true;
+ }
+ m_xParam->set_tooltip_text(sToolTip);
+ m_xOKBtn->set_sensitive(bValid);
+ }
+ }
+
+ return bRet;
+ }
+
+ IMPL_LINK(OParameterDialog, OnButtonClicked, weld::Button&, rButton, void)
+ {
+ if (m_xCancelBtn.get() == &rButton)
+ {
+ // no interpreting of the given values anymore...
+ m_xParam->connect_focus_out(Link<weld::Widget&, void>()); // no direct call from the control anymore ...
+ m_xDialog->response(RET_CANCEL);
+ }
+ else if (m_xOKBtn.get() == &rButton)
+ {
+ // transfer the current values into the Any
+ if (OnEntrySelected())
+ { // there was an error interpreting the current text
+ return;
+ }
+
+ if (m_xParams.is())
+ {
+ // write the parameters
+ try
+ {
+ PropertyValue* pValues = m_aFinalValues.getArray();
+ for (sal_Int32 i = 0, nCount = m_xParams->getCount(); i<nCount; ++i, ++pValues)
+ {
+ Reference< XPropertySet > xParamAsSet;
+ m_xParams->getByIndex(i) >>= xParamAsSet;
+
+ OUString sValue;
+ pValues->Value >>= sValue;
+ pValues->Value = m_aPredicateInput.getPredicateValue( sValue, xParamAsSet );
+ }
+ }
+ catch(Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+
+ }
+ m_xDialog->response(RET_OK);
+ }
+ else if (m_xTravelNext.get() == &rButton)
+ {
+ if (sal_Int32 nCount = m_xAllParams->n_children())
+ {
+ sal_Int32 nCurrent = m_xAllParams->get_selected_index();
+ OSL_ENSURE(static_cast<size_t>(nCount) == m_aVisitedParams.size(), "OParameterDialog::OnButtonClicked : inconsistent lists !");
+
+ // search the next entry in list we haven't visited yet
+ sal_Int32 nNext = (nCurrent + 1) % nCount;
+ while ((nNext != nCurrent) && ( m_aVisitedParams[nNext] & VisitFlags::Visited ))
+ nNext = (nNext + 1) % nCount;
+
+ if ( m_aVisitedParams[nNext] & VisitFlags::Visited )
+ // there is no such "not visited yet" entry -> simply take the next one
+ nNext = (nCurrent + 1) % nCount;
+
+ m_xAllParams->select(nNext);
+ OnEntrySelected();
+ }
+ }
+ }
+
+ IMPL_LINK_NOARG(OParameterDialog, OnEntryListBoxSelected, weld::TreeView&, void)
+ {
+ OnEntrySelected();
+ }
+
+ bool OParameterDialog::OnEntrySelected()
+ {
+ if (m_aResetVisitFlag.IsActive())
+ {
+ LINK(this, OParameterDialog, OnVisitedTimeout).Call(&m_aResetVisitFlag);
+ m_aResetVisitFlag.Stop();
+ }
+ // save the old values
+ if (m_nCurrentlySelected != -1)
+ {
+ // do the transformation of the current text
+ if (CheckValueForError())
+ { // there was an error interpreting the text
+ m_xAllParams->select(m_nCurrentlySelected);
+ return true;
+ }
+
+ m_aFinalValues.getArray()[m_nCurrentlySelected].Value <<= m_xParam->get_text();
+ }
+
+ // initialize the controls with the new values
+ sal_Int32 nSelected = m_xAllParams->get_selected_index();
+ OSL_ENSURE(nSelected != -1, "OParameterDialog::OnEntrySelected : no current entry !");
+
+ m_xParam->set_text(::comphelper::getString(m_aFinalValues[nSelected].Value));
+ m_nCurrentlySelected = nSelected;
+
+ // with this the value isn't dirty
+ OSL_ENSURE(o3tl::make_unsigned(m_nCurrentlySelected) < m_aVisitedParams.size(), "OParameterDialog::OnEntrySelected : invalid current entry !");
+ m_aVisitedParams[m_nCurrentlySelected] &= ~VisitFlags::Dirty;
+
+ m_aResetVisitFlag.SetTimeout(1000);
+ m_aResetVisitFlag.Start();
+
+ return false;
+ }
+
+ IMPL_LINK_NOARG(OParameterDialog, OnVisitedTimeout, Timer*, void)
+ {
+ OSL_ENSURE(m_nCurrentlySelected != -1, "OParameterDialog::OnVisitedTimeout : invalid call !");
+
+ // mark the currently selected entry as visited
+ OSL_ENSURE(o3tl::make_unsigned(m_nCurrentlySelected) < m_aVisitedParams.size(), "OParameterDialog::OnVisitedTimeout : invalid entry !");
+ m_aVisitedParams[m_nCurrentlySelected] |= VisitFlags::Visited;
+
+ // was it the last "not visited yet" entry ?
+ bool bVisited = false;
+ for (auto const& visitedParam : m_aVisitedParams)
+ {
+ if (!(visitedParam & VisitFlags::Visited))
+ {
+ bVisited = true;
+ break;
+ }
+ }
+
+ if (!bVisited)
+ {
+ // yes, there isn't another one -> change the "default button"
+ m_xDialog->change_default_widget(m_xTravelNext.get(), m_xOKBtn.get());
+ }
+ }
+
+ IMPL_LINK(OParameterDialog, OnValueModified, weld::Entry&, rEdit, void)
+ {
+ // mark the currently selected entry as dirty
+ OSL_ENSURE(o3tl::make_unsigned(m_nCurrentlySelected) < m_aVisitedParams.size(), "OParameterDialog::OnValueModified : invalid entry !");
+ m_aVisitedParams[m_nCurrentlySelected] |= VisitFlags::Dirty;
+ rEdit.set_message_type(weld::EntryMessageType::Normal);
+ }
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/dlg/queryfilter.cxx b/dbaccess/source/ui/dlg/queryfilter.cxx
new file mode 100644
index 000000000..2735acee5
--- /dev/null
+++ b/dbaccess/source/ui/dlg/queryfilter.cxx
@@ -0,0 +1,748 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <queryfilter.hxx>
+#include <com/sun/star/sdbc/DataType.hpp>
+#include <com/sun/star/util/Date.hpp>
+#include <com/sun/star/sdbc/ColumnSearch.hpp>
+#include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
+#include <com/sun/star/sdb/SQLFilterOperator.hpp>
+#include <com/sun/star/sdbc/XConnection.hpp>
+#include <comphelper/string.hxx>
+#include <tools/diagnose_ex.h>
+#include <osl/diagnose.h>
+#include <connectivity/dbtools.hxx>
+#include <strings.hxx>
+#include <com/sun/star/sdb/XSingleSelectQueryComposer.hpp>
+
+using namespace dbaui;
+using namespace connectivity;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::util;
+using namespace ::com::sun::star::sdb;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::sdbcx;
+using namespace ::com::sun::star::beans;
+
+static void Replace_OS_PlaceHolder(OUString& aString)
+{
+ aString = aString.replaceAll( "*", "%" );
+ aString = aString.replaceAll( "?", "_" );
+}
+
+static void Replace_SQL_PlaceHolder(OUString& aString)
+{
+ aString = aString.replaceAll( "%", "*" );
+ aString = aString.replaceAll( "_", "?" );
+}
+
+DlgFilterCrit::DlgFilterCrit(weld::Window * pParent,
+ const Reference< XComponentContext >& rxContext,
+ const Reference< XConnection>& _rxConnection,
+ const Reference< XSingleSelectQueryComposer >& _rxComposer,
+ const Reference< XNameAccess>& _rxCols)
+ : GenericDialogController(pParent, "dbaccess/ui/queryfilterdialog.ui", "QueryFilterDialog")
+ , m_xQueryComposer(_rxComposer)
+ , m_xColumns( _rxCols )
+ , m_xConnection( _rxConnection )
+ , m_xMetaData( _rxConnection->getMetaData() )
+ , m_aPredicateInput( rxContext, _rxConnection, getParseContext() )
+ , m_xLB_WHEREFIELD1(m_xBuilder->weld_combo_box("field1"))
+ , m_xLB_WHERECOMP1(m_xBuilder->weld_combo_box("cond1"))
+ , m_xET_WHEREVALUE1(m_xBuilder->weld_entry("value1"))
+ , m_xLB_WHERECOND2(m_xBuilder->weld_combo_box("op2"))
+ , m_xLB_WHEREFIELD2(m_xBuilder->weld_combo_box("field2"))
+ , m_xLB_WHERECOMP2(m_xBuilder->weld_combo_box("cond2"))
+ , m_xET_WHEREVALUE2(m_xBuilder->weld_entry("value2"))
+ , m_xLB_WHERECOND3(m_xBuilder->weld_combo_box("op3"))
+ , m_xLB_WHEREFIELD3(m_xBuilder->weld_combo_box("field3"))
+ , m_xLB_WHERECOMP3(m_xBuilder->weld_combo_box("cond3"))
+ , m_xET_WHEREVALUE3(m_xBuilder->weld_entry("value3"))
+{
+ //set all condition preferred width to max width
+ //if all entries exist
+ Size aSize(m_xLB_WHERECOMP1->get_preferred_size());
+ m_xLB_WHERECOMP1->set_size_request(aSize.Width(), -1);
+ m_xLB_WHERECOMP2->set_size_request(aSize.Width(), -1);
+ m_xLB_WHERECOMP3->set_size_request(aSize.Width(), -1);
+ const sal_Int32 nEntryCount = m_xLB_WHERECOMP1->get_count();
+ m_aSTR_COMPARE_OPERATORS.resize(nEntryCount);
+ for (sal_Int32 i = 0; i < nEntryCount; ++i)
+ {
+ m_aSTR_COMPARE_OPERATORS[i] = m_xLB_WHERECOMP1->get_text(i);
+ }
+ m_xLB_WHERECOMP1->clear();
+
+ // ... also write it into the remaining fields
+ Sequence< OUString> aNames = m_xColumns->getElementNames();
+ const OUString* pIter = aNames.getConstArray();
+ const OUString* pEnd = pIter + aNames.getLength();
+ Reference<XPropertySet> xColumn;
+ for(;pIter != pEnd;++pIter)
+ {
+ try
+ {
+ xColumn.set( m_xColumns->getByName( *pIter ), UNO_QUERY_THROW );
+
+ sal_Int32 nDataType( 0 );
+ OSL_VERIFY( xColumn->getPropertyValue( PROPERTY_TYPE ) >>= nDataType );
+ sal_Int32 eColumnSearch = ::dbtools::getSearchColumnFlag( m_xConnection, nDataType );
+ if ( eColumnSearch == ColumnSearch::NONE )
+ continue;
+
+ bool bIsSearchable( true );
+ OSL_VERIFY( xColumn->getPropertyValue( PROPERTY_ISSEARCHABLE ) >>= bIsSearchable );
+ if ( !bIsSearchable )
+ continue;
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ m_xLB_WHEREFIELD1->append_text( *pIter );
+ m_xLB_WHEREFIELD2->append_text( *pIter );
+ m_xLB_WHEREFIELD3->append_text( *pIter );
+ }
+
+ Reference<XNameAccess> xSelectColumns = Reference<XColumnsSupplier>(m_xQueryComposer,UNO_QUERY_THROW)->getColumns();
+ aNames = xSelectColumns->getElementNames();
+ pIter = aNames.getConstArray();
+ pEnd = pIter + aNames.getLength();
+ for(;pIter != pEnd;++pIter)
+ {
+ // don't insert a column name twice
+ if ( !m_xColumns->hasByName(*pIter) )
+ {
+ xColumn.set(xSelectColumns->getByName(*pIter),UNO_QUERY);
+ OSL_ENSURE(xColumn.is(),"DlgFilterCrit::DlgFilterCrit: Column is null!");
+ sal_Int32 nDataType(0);
+ xColumn->getPropertyValue(PROPERTY_TYPE) >>= nDataType;
+ sal_Int32 eColumnSearch = dbtools::getSearchColumnFlag(m_xConnection,nDataType);
+ // TODO
+ // !pColumn->IsFunction()
+ if(eColumnSearch != ColumnSearch::NONE)
+ {
+ m_xLB_WHEREFIELD1->append_text( *pIter );
+ m_xLB_WHEREFIELD2->append_text( *pIter );
+ m_xLB_WHEREFIELD3->append_text( *pIter );
+ }
+ }
+ }
+ // initialize the listboxes with noEntry
+ m_xLB_WHEREFIELD1->set_active(0);
+ m_xLB_WHEREFIELD2->set_active(0);
+ m_xLB_WHEREFIELD3->set_active(0);
+
+ // insert the criteria into the dialog
+ Sequence<Sequence<PropertyValue > > aValues = m_xQueryComposer->getStructuredFilter();
+ int i(0);
+ fillLines(i, aValues);
+ aValues = m_xQueryComposer->getStructuredHavingClause();
+ fillLines(i, aValues);
+
+ EnableLines();
+
+ m_xLB_WHEREFIELD1->connect_changed(LINK(this,DlgFilterCrit,ListSelectHdl));
+ m_xLB_WHEREFIELD2->connect_changed(LINK(this,DlgFilterCrit,ListSelectHdl));
+ m_xLB_WHEREFIELD3->connect_changed(LINK(this,DlgFilterCrit,ListSelectHdl));
+
+ m_xLB_WHERECOMP1->connect_changed(LINK(this,DlgFilterCrit,ListSelectCompHdl));
+ m_xLB_WHERECOMP2->connect_changed(LINK(this,DlgFilterCrit,ListSelectCompHdl));
+ m_xLB_WHERECOMP3->connect_changed(LINK(this,DlgFilterCrit,ListSelectCompHdl));
+
+ m_xET_WHEREVALUE1->connect_focus_out( LINK( this, DlgFilterCrit, PredicateLoseFocus ) );
+ m_xET_WHEREVALUE2->connect_focus_out( LINK( this, DlgFilterCrit, PredicateLoseFocus ) );
+ m_xET_WHEREVALUE3->connect_focus_out( LINK( this, DlgFilterCrit, PredicateLoseFocus ) );
+
+ if (m_xET_WHEREVALUE1->get_sensitive())
+ m_xET_WHEREVALUE1->grab_focus();
+}
+
+DlgFilterCrit::~DlgFilterCrit()
+{
+}
+
+sal_Int32 DlgFilterCrit::GetOSQLPredicateType( std::u16string_view _rSelectedPredicate ) const
+{
+ sal_Int32 nPredicateIndex = -1;
+ for ( size_t i=0; i < m_aSTR_COMPARE_OPERATORS.size(); ++i)
+ if ( m_aSTR_COMPARE_OPERATORS[i] == _rSelectedPredicate )
+ {
+ nPredicateIndex = i;
+ break;
+ }
+
+ sal_Int32 nPredicateType = SQLFilterOperator::NOT_SQLNULL;
+ switch ( nPredicateIndex )
+ {
+ case 0:
+ nPredicateType = SQLFilterOperator::EQUAL;
+ break;
+ case 1:
+ nPredicateType = SQLFilterOperator::NOT_EQUAL;
+ break;
+ case 2:
+ nPredicateType = SQLFilterOperator::LESS;
+ break;
+ case 3:
+ nPredicateType = SQLFilterOperator::LESS_EQUAL;
+ break;
+ case 4:
+ nPredicateType = SQLFilterOperator::GREATER;
+ break;
+ case 5:
+ nPredicateType = SQLFilterOperator::GREATER_EQUAL;
+ break;
+ case 6:
+ nPredicateType = SQLFilterOperator::LIKE;
+ break;
+ case 7:
+ nPredicateType = SQLFilterOperator::NOT_LIKE;
+ break;
+ case 8:
+ nPredicateType = SQLFilterOperator::SQLNULL;
+ break;
+ case 9:
+ nPredicateType = SQLFilterOperator::NOT_SQLNULL;
+ break;
+ default:
+ OSL_FAIL( "DlgFilterCrit::GetOSQLPredicateType: unknown predicate string!" );
+ break;
+ }
+
+ return nPredicateType;
+}
+
+sal_Int32 DlgFilterCrit::GetSelectionPos(sal_Int32 eType, const weld::ComboBox& rListBox)
+{
+ sal_Int32 nPos;
+ switch(eType)
+ {
+ case SQLFilterOperator::EQUAL:
+ nPos = 0;
+ break;
+ case SQLFilterOperator::NOT_EQUAL:
+ nPos = 1;
+ break;
+ case SQLFilterOperator::LESS:
+ nPos = 2;
+ break;
+ case SQLFilterOperator::LESS_EQUAL:
+ nPos = 3;
+ break;
+ case SQLFilterOperator::GREATER:
+ nPos = 4;
+ break;
+ case SQLFilterOperator::GREATER_EQUAL:
+ nPos = 5;
+ break;
+ case SQLFilterOperator::NOT_LIKE:
+ nPos = rListBox.get_count() > 2 ? rListBox.get_count()-3 : 0;
+ break;
+ case SQLFilterOperator::LIKE:
+ nPos = rListBox.get_count() > 2 ? rListBox.get_count()-4 : 1;
+ break;
+ case SQLFilterOperator::SQLNULL:
+ nPos = rListBox.get_count()-2;
+ break;
+ case SQLFilterOperator::NOT_SQLNULL:
+ nPos = rListBox.get_count()-1;
+ break;
+ default:
+ // TODO What value should this be?
+ nPos = 0;
+ break;
+ }
+ return nPos;
+}
+
+bool DlgFilterCrit::getCondition(const weld::ComboBox& _rField,const weld::ComboBox& _rComp,const weld::Entry& _rValue,PropertyValue& _rFilter) const
+{
+ bool bHaving = false;
+ try
+ {
+ _rFilter.Name = _rField.get_active_text();
+ Reference< XPropertySet > xColumn = getQueryColumn(_rFilter.Name);
+ if ( xColumn.is() )
+ {
+ bool bFunction = false;
+ OUString sTableName;
+ Reference< XPropertySetInfo > xInfo = xColumn->getPropertySetInfo();
+ if ( xInfo->hasPropertyByName(PROPERTY_REALNAME) )
+ {
+ if ( xInfo->hasPropertyByName(PROPERTY_TABLENAME) )
+ {
+ xColumn->getPropertyValue(PROPERTY_TABLENAME) >>= sTableName;
+ if ( !sTableName.isEmpty() )
+ {
+ // properly quote all parts of the table name, so
+ // e.g. <schema>.<table> becomes "<schema>"."<table>"
+ OUString aCatlog,aSchema,aTable;
+ ::dbtools::qualifiedNameComponents( m_xMetaData, sTableName, aCatlog, aSchema, aTable, ::dbtools::EComposeRule::InDataManipulation );
+ sTableName = ::dbtools::composeTableName( m_xMetaData, aCatlog, aSchema, aTable, true, ::dbtools::EComposeRule::InDataManipulation );
+ }
+ }
+ xColumn->getPropertyValue(PROPERTY_REALNAME) >>= _rFilter.Name;
+ static constexpr OUStringLiteral sAgg = u"AggregateFunction";
+ if ( xInfo->hasPropertyByName(sAgg) )
+ xColumn->getPropertyValue(sAgg) >>= bHaving;
+ static constexpr OUStringLiteral sFunction = u"Function";
+ if ( xInfo->hasPropertyByName(sFunction) )
+ xColumn->getPropertyValue(sFunction) >>= bFunction;
+ }
+ if ( !bFunction )
+ {
+ const OUString aQuote = m_xMetaData.is() ? m_xMetaData->getIdentifierQuoteString() : OUString();
+ _rFilter.Name = ::dbtools::quoteName(aQuote,_rFilter.Name);
+ if ( !sTableName.isEmpty() )
+ {
+ sTableName += "." + _rFilter.Name;
+ _rFilter.Name = sTableName;
+ }
+ }
+ }
+ }
+ catch(const Exception&)
+ {
+ }
+
+ _rFilter.Handle = GetOSQLPredicateType( _rComp.get_active_text() );
+ if ( SQLFilterOperator::SQLNULL != _rFilter.Handle && _rFilter.Handle != SQLFilterOperator::NOT_SQLNULL )
+ {
+ OUString sPredicateValue;
+ m_aPredicateInput.getPredicateValue( _rValue.get_text(), getMatchingColumn( _rValue ) ) >>= sPredicateValue;
+ if ( _rFilter.Handle == SQLFilterOperator::LIKE ||
+ _rFilter.Handle == SQLFilterOperator::NOT_LIKE )
+ ::Replace_OS_PlaceHolder( sPredicateValue );
+ _rFilter.Value <<= sPredicateValue;
+ }
+ return bHaving;
+}
+
+Reference< XPropertySet > DlgFilterCrit::getColumn( const OUString& _rFieldName ) const
+{
+ Reference< XPropertySet > xColumn;
+ try
+ {
+ if ( m_xColumns.is() && m_xColumns->hasByName( _rFieldName ) )
+ m_xColumns->getByName( _rFieldName ) >>= xColumn;
+
+ Reference< XNameAccess> xColumns = Reference< XColumnsSupplier >(m_xQueryComposer,UNO_QUERY_THROW)->getColumns();
+ if ( xColumns.is() && !xColumn.is() )
+ {
+ Sequence< OUString> aSeq = xColumns->getElementNames();
+ const OUString* pIter = aSeq.getConstArray();
+ const OUString* pEnd = pIter + aSeq.getLength();
+ for(;pIter != pEnd;++pIter)
+ {
+ Reference<XPropertySet> xProp(xColumns->getByName(*pIter),UNO_QUERY);
+ if ( xProp.is() && xProp->getPropertySetInfo()->hasPropertyByName(PROPERTY_REALNAME) )
+ {
+ OUString sRealName;
+ xProp->getPropertyValue(PROPERTY_REALNAME) >>= sRealName;
+ if ( sRealName == _rFieldName )
+ {
+ if ( m_xColumns.is() && m_xColumns->hasByName( *pIter ) )
+ m_xColumns->getByName( *pIter ) >>= xColumn;
+ break;
+ }
+ }
+ }
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+
+ return xColumn;
+}
+
+Reference< XPropertySet > DlgFilterCrit::getQueryColumn( const OUString& _rFieldName ) const
+{
+ Reference< XPropertySet > xColumn;
+ try
+ {
+ Reference< XNameAccess> xColumns = Reference< XColumnsSupplier >(m_xQueryComposer,UNO_QUERY_THROW)->getColumns();
+ if ( xColumns.is() && xColumns->hasByName( _rFieldName ) )
+ xColumns->getByName( _rFieldName ) >>= xColumn;
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+
+ return xColumn;
+}
+
+Reference< XPropertySet > DlgFilterCrit::getMatchingColumn( const weld::Entry& _rValueInput ) const
+{
+ // the name
+ OUString sField;
+ if ( &_rValueInput == m_xET_WHEREVALUE1.get() )
+ {
+ sField = m_xLB_WHEREFIELD1->get_active_text();
+ }
+ else if ( &_rValueInput == m_xET_WHEREVALUE2.get() )
+ {
+ sField = m_xLB_WHEREFIELD2->get_active_text();
+ }
+ else if ( &_rValueInput == m_xET_WHEREVALUE3.get() )
+ {
+ sField = m_xLB_WHEREFIELD3->get_active_text();
+ }
+ else {
+ OSL_FAIL( "DlgFilterCrit::getMatchingColumn: invalid event source!" );
+ }
+
+ // the field itself
+ return getColumn( sField );
+}
+
+IMPL_LINK( DlgFilterCrit, PredicateLoseFocus, weld::Widget&, rControl, void )
+{
+ weld::Entry& rField = dynamic_cast<weld::Entry&>(rControl);
+ // retrieve the field affected
+ Reference< XPropertySet> xColumn(getMatchingColumn(rField));
+ // and normalize its content
+ if ( xColumn.is() )
+ {
+ OUString sText(rField.get_text());
+ m_aPredicateInput.normalizePredicateString(sText, xColumn);
+ rField.set_text(sText);
+ }
+}
+
+void DlgFilterCrit::SetLine( int nIdx, const PropertyValue& _rItem, bool _bOr )
+{
+ OUString aStr;
+ _rItem.Value >>= aStr;
+ if ( _rItem.Handle == SQLFilterOperator::LIKE ||
+ _rItem.Handle == SQLFilterOperator::NOT_LIKE )
+ ::Replace_SQL_PlaceHolder(aStr);
+ aStr = comphelper::string::stripEnd(aStr, ' ');
+
+ Reference< XPropertySet > xColumn = getColumn( _rItem.Name );
+
+ // to make sure that we only set first three
+ weld::ComboBox* pColumnListControl = nullptr;
+ weld::ComboBox* pPredicateListControl = nullptr;
+ weld::Entry* pPredicateValueControl = nullptr;
+ switch( nIdx )
+ {
+ case 0:
+ pColumnListControl = m_xLB_WHEREFIELD1.get();
+ pPredicateListControl = m_xLB_WHERECOMP1.get();
+ pPredicateValueControl = m_xET_WHEREVALUE1.get();
+ break;
+ case 1:
+ m_xLB_WHERECOND2->set_active( _bOr ? 1 : 0 );
+
+ pColumnListControl = m_xLB_WHEREFIELD2.get();
+ pPredicateListControl = m_xLB_WHERECOMP2.get();
+ pPredicateValueControl = m_xET_WHEREVALUE2.get();
+ break;
+ case 2:
+ m_xLB_WHERECOND3->set_active( _bOr ? 1 : 0 );
+
+ pColumnListControl = m_xLB_WHEREFIELD3.get();
+ pPredicateListControl = m_xLB_WHERECOMP3.get();
+ pPredicateValueControl = m_xET_WHEREVALUE3.get();
+ break;
+ }
+
+ if ( !(pColumnListControl && pPredicateListControl && pPredicateValueControl) )
+ return;
+
+ OUString sName;
+ if ( xColumn.is() )
+ xColumn->getPropertyValue(PROPERTY_NAME) >>= sName;
+ else
+ sName = _rItem.Name;
+ // select the appropriate field name
+ SelectField( *pColumnListControl, sName );
+ ListSelectHdl( *pColumnListControl );
+
+ // select the appropriate condition
+ pPredicateListControl->set_active( GetSelectionPos( _rItem.Handle, *pPredicateListControl ) );
+
+ // initially normalize this value
+ OUString aString( aStr );
+ m_aPredicateInput.normalizePredicateString( aString, xColumn );
+ pPredicateValueControl->set_text( aString );
+}
+
+void DlgFilterCrit::SelectField(weld::ComboBox& rBox, std::u16string_view rField)
+{
+ const sal_Int32 nCnt = rBox.get_count();
+
+ for( sal_Int32 i=0 ; i<nCnt ; i++ )
+ {
+ if (rBox.get_text(i) == rField)
+ {
+ rBox.set_active(i);
+ return;
+ }
+ }
+
+ rBox.set_active(0);
+}
+
+void DlgFilterCrit::EnableLines()
+{
+ // enabling/disabling of whole lines
+ if( m_xLB_WHEREFIELD1->get_active() == 0 )
+ {
+ m_xLB_WHEREFIELD2->set_sensitive(false);
+ m_xLB_WHERECOND2->set_sensitive(false);
+ m_xLB_WHERECOMP2->set_sensitive(false);
+ m_xET_WHEREVALUE2->set_sensitive(false);
+
+ m_xLB_WHEREFIELD3->set_sensitive(false);
+ m_xLB_WHERECOND3->set_sensitive(false);
+ m_xLB_WHERECOMP3->set_sensitive(false);
+ m_xET_WHEREVALUE3->set_sensitive(false);
+ }
+ else
+ {
+ m_xLB_WHEREFIELD2->set_sensitive(true);
+ m_xLB_WHERECOND2->set_sensitive(true);
+ m_xLB_WHERECOMP2->set_sensitive(true);
+ m_xET_WHEREVALUE2->set_sensitive(true);
+
+ m_xLB_WHEREFIELD3->set_sensitive(true);
+ m_xLB_WHERECOND3->set_sensitive(true);
+ m_xLB_WHERECOMP3->set_sensitive(true);
+ m_xET_WHEREVALUE3->set_sensitive(true);
+ }
+
+ if( m_xLB_WHEREFIELD2->get_active() == 0 )
+ {
+ m_xLB_WHEREFIELD3->set_sensitive(false);
+ m_xLB_WHERECOND3->set_sensitive(false);
+ m_xLB_WHERECOMP3->set_sensitive(false);
+ m_xET_WHEREVALUE3->set_sensitive(false);
+ }
+ else
+ {
+ m_xLB_WHEREFIELD3->set_sensitive(true);
+ m_xLB_WHERECOND3->set_sensitive(true);
+ m_xLB_WHERECOMP3->set_sensitive(true);
+ m_xET_WHEREVALUE3->set_sensitive(true);
+ }
+
+ // comparison field equal to NOENTRY
+ if( m_xLB_WHEREFIELD1->get_active() == 0 )
+ {
+ m_xLB_WHERECOMP1->set_sensitive(false);
+ m_xET_WHEREVALUE1->set_sensitive(false);
+ }
+ else
+ {
+ m_xLB_WHEREFIELD1->set_sensitive(true);
+ m_xLB_WHERECOMP1->set_sensitive(true);
+ m_xET_WHEREVALUE1->set_sensitive(true);
+ }
+
+ if( m_xLB_WHEREFIELD2->get_active() == 0 )
+ {
+ m_xLB_WHERECOND2->set_sensitive(false);
+ m_xLB_WHERECOMP2->set_sensitive(false);
+ m_xET_WHEREVALUE2->set_sensitive(false);
+ }
+ else
+ {
+ m_xLB_WHERECOND2->set_sensitive(true);
+ m_xLB_WHEREFIELD2->set_sensitive(true);
+ m_xLB_WHERECOMP2->set_sensitive(true);
+ m_xET_WHEREVALUE2->set_sensitive(true);
+ }
+
+ if( m_xLB_WHEREFIELD3->get_active() == 0 )
+ {
+ m_xLB_WHERECOND3->set_sensitive(false);
+ m_xLB_WHERECOMP3->set_sensitive(false);
+ m_xET_WHEREVALUE3->set_sensitive(false);
+ }
+ else
+ {
+ m_xLB_WHERECOND3->set_sensitive(true);
+ m_xLB_WHERECOND3->set_sensitive(true);
+ m_xLB_WHEREFIELD3->set_sensitive(true);
+ m_xLB_WHERECOMP3->set_sensitive(true);
+ m_xET_WHEREVALUE3->set_sensitive(true);
+ }
+
+ // comparison operator equal to ISNULL or ISNOTNULL
+ if(m_xLB_WHERECOMP1->get_count() > 2 &&
+ ((m_xLB_WHERECOMP1->get_active() == m_xLB_WHERECOMP1->get_count()-1) ||
+ (m_xLB_WHERECOMP1->get_active() == m_xLB_WHERECOMP1->get_count()-2)) )
+ m_xET_WHEREVALUE1->set_sensitive(false);
+
+ if(m_xLB_WHERECOMP2->get_count() > 2 &&
+ ((m_xLB_WHERECOMP2->get_active() == m_xLB_WHERECOMP2->get_count()-1) ||
+ (m_xLB_WHERECOMP2->get_active() == m_xLB_WHERECOMP2->get_count()-2)) )
+ m_xET_WHEREVALUE2->set_sensitive(false);
+
+ if(m_xLB_WHERECOMP3->get_count() > 2 &&
+ ((m_xLB_WHERECOMP3->get_active() == m_xLB_WHERECOMP3->get_count()-1) ||
+ (m_xLB_WHERECOMP3->get_active() == m_xLB_WHERECOMP3->get_count()-2)) )
+ m_xET_WHEREVALUE3->set_sensitive(false);
+}
+
+IMPL_LINK( DlgFilterCrit, ListSelectHdl, weld::ComboBox&, rListBox, void )
+{
+ OUString aName;
+ weld::ComboBox* pComp;
+ if(&rListBox == m_xLB_WHEREFIELD1.get())
+ {
+ aName = m_xLB_WHEREFIELD1->get_active_text();
+ pComp = m_xLB_WHERECOMP1.get();
+ }
+ else if(&rListBox == m_xLB_WHEREFIELD2.get())
+ {
+ aName = m_xLB_WHEREFIELD2->get_active_text();
+ pComp = m_xLB_WHERECOMP2.get();
+ }
+ else
+ {
+ aName = m_xLB_WHEREFIELD3->get_active_text();
+ pComp = m_xLB_WHERECOMP3.get();
+ }
+
+ pComp->clear();
+
+ Reference<XPropertySet> xColumn = getColumn(aName);
+ if ( xColumn.is() )
+ {
+ sal_Int32 nDataType = 0;
+ xColumn->getPropertyValue(PROPERTY_TYPE) >>= nDataType;
+ sal_Int32 eColumnSearch = dbtools::getSearchColumnFlag(m_xConnection,nDataType);
+
+ if(eColumnSearch == ColumnSearch::FULL)
+ {
+ for(size_t i=0;i < m_aSTR_COMPARE_OPERATORS.size(); i++)
+ pComp->append_text(m_aSTR_COMPARE_OPERATORS[i]);
+ }
+ else if(eColumnSearch == ColumnSearch::CHAR)
+ {
+ for(sal_Int32 i=6; i<10; i++)
+ pComp->append_text(m_aSTR_COMPARE_OPERATORS[i]);
+ }
+ else if(eColumnSearch == ColumnSearch::BASIC)
+ {
+ size_t i;
+ for( i = 0; i < 6; i++ )
+ pComp->append_text(m_aSTR_COMPARE_OPERATORS[i]);
+ for(i=8; i < m_aSTR_COMPARE_OPERATORS.size(); ++i)
+ pComp->append_text(m_aSTR_COMPARE_OPERATORS[i]);
+ }
+ else
+ {
+ OSL_FAIL("DlgFilterCrit::ListSelectHdl: This column should not exist at all.");
+ }
+ }
+ pComp->set_active(0);
+
+ EnableLines();
+}
+
+IMPL_LINK_NOARG(DlgFilterCrit, ListSelectCompHdl, weld::ComboBox&, void)
+{
+ EnableLines();
+}
+
+void DlgFilterCrit::BuildWherePart()
+{
+ Sequence<Sequence<PropertyValue> > aFilter(1),aHaving(1);
+
+ if( m_xLB_WHEREFIELD1->get_active() != 0 )
+ {
+ PropertyValue aValue;
+ if ( getCondition(*m_xLB_WHEREFIELD1,*m_xLB_WHERECOMP1,*m_xET_WHEREVALUE1,aValue) )
+ {
+ aHaving = { { aValue } };
+ }
+ else
+ {
+ aFilter = { { aValue} };
+ }
+ }
+
+ if( m_xLB_WHEREFIELD2->get_active() != 0 )
+ {
+ PropertyValue aValue;
+ Sequence<Sequence<PropertyValue> >& _rValues = aFilter;
+ if ( getCondition(*m_xLB_WHEREFIELD2,*m_xLB_WHERECOMP2,*m_xET_WHEREVALUE2,aValue) )
+ _rValues = aHaving;
+ if ( m_xLB_WHERECOND2->get_active() )
+ _rValues.realloc( _rValues.getLength() + 1);
+ sal_Int32 nPos = _rValues.getLength() - 1;
+ sal_Int32 nAndPos = _rValues[nPos].getLength();
+ auto pValues = _rValues.getArray();
+ pValues[nPos].realloc( _rValues[nPos].getLength() + 1);
+ pValues[nPos].getArray()[nAndPos] = aValue;
+ }
+
+ if( m_xLB_WHEREFIELD3->get_active() != 0 )
+ {
+ PropertyValue aValue;
+ Sequence<Sequence<PropertyValue> >& _rValues = aFilter;
+ if ( getCondition(*m_xLB_WHEREFIELD3,*m_xLB_WHERECOMP3,*m_xET_WHEREVALUE3,aValue) )
+ _rValues = aHaving;
+ if (m_xLB_WHERECOND3->get_active())
+ _rValues.realloc( _rValues.getLength() + 1);
+ sal_Int32 nPos = _rValues.getLength() - 1;
+ sal_Int32 nAndPos = _rValues[nPos].getLength();
+ auto pValues = _rValues.getArray();
+ pValues[nPos].realloc( _rValues[nPos].getLength() + 1);
+ pValues[nPos].getArray()[nAndPos] = aValue;
+ }
+ try
+ {
+ m_xQueryComposer->setStructuredFilter(aFilter);
+ m_xQueryComposer->setStructuredHavingClause(aHaving);
+ }
+ catch(const Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+}
+
+void DlgFilterCrit::fillLines(int &i, const Sequence< Sequence< PropertyValue > >& _aValues)
+{
+ const Sequence<PropertyValue >* pOrIter = _aValues.getConstArray();
+ const Sequence<PropertyValue >* pOrEnd = pOrIter + _aValues.getLength();
+ bool bOr(i != 0); // WHERE clause and HAVING clause are always ANDed, nor ORed
+ for(; pOrIter != pOrEnd; ++pOrIter)
+ {
+ const PropertyValue* pAndIter = pOrIter->getConstArray();
+ const PropertyValue* pAndEnd = pAndIter + pOrIter->getLength();
+ for(;pAndIter != pAndEnd; ++pAndIter)
+ {
+ SetLine( i++,*pAndIter,bOr);
+ bOr = false;
+ }
+ bOr=true;
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/dlg/queryorder.cxx b/dbaccess/source/ui/dlg/queryorder.cxx
new file mode 100644
index 000000000..40b25cdd3
--- /dev/null
+++ b/dbaccess/source/ui/dlg/queryorder.cxx
@@ -0,0 +1,218 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <strings.hrc>
+#include <strings.hxx>
+#include <core_resource.hxx>
+#include <queryorder.hxx>
+#include <com/sun/star/sdb/XSingleSelectQueryComposer.hpp>
+#include <com/sun/star/sdbc/ColumnSearch.hpp>
+#include <com/sun/star/sdbc/XConnection.hpp>
+#include <com/sun/star/container/XNameAccess.hpp>
+#include <connectivity/dbtools.hxx>
+#include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
+#include <tools/diagnose_ex.h>
+
+using namespace dbaui;
+using namespace connectivity;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::util;
+using namespace ::com::sun::star::sdb;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::sdbcx;
+using namespace ::com::sun::star::beans;
+
+
+DlgOrderCrit::DlgOrderCrit(weld::Window * pParent,
+ const Reference< XConnection>& _rxConnection,
+ const Reference< XSingleSelectQueryComposer >& _rxComposer,
+ const Reference< XNameAccess>& _rxCols)
+ : GenericDialogController(pParent, "dbaccess/ui/sortdialog.ui", "SortDialog")
+ , m_xQueryComposer(_rxComposer)
+ , m_xColumns(_rxCols)
+ , m_xConnection(_rxConnection)
+ , m_xLB_ORDERFIELD1(m_xBuilder->weld_combo_box("field1"))
+ , m_xLB_ORDERVALUE1(m_xBuilder->weld_combo_box("value1"))
+ , m_xLB_ORDERFIELD2(m_xBuilder->weld_combo_box("field2"))
+ , m_xLB_ORDERVALUE2(m_xBuilder->weld_combo_box("value2"))
+ , m_xLB_ORDERFIELD3(m_xBuilder->weld_combo_box("field3"))
+ , m_xLB_ORDERVALUE3(m_xBuilder->weld_combo_box("value3"))
+{
+ m_aColumnList[0] = m_xLB_ORDERFIELD1.get();
+ m_aColumnList[1] = m_xLB_ORDERFIELD2.get();
+ m_aColumnList[2] = m_xLB_ORDERFIELD3.get();
+
+ m_aValueList[0] = m_xLB_ORDERVALUE1.get();
+ m_aValueList[1] = m_xLB_ORDERVALUE2.get();
+ m_aValueList[2] = m_xLB_ORDERVALUE3.get();
+
+ OUString aSTR_NOENTRY(DBA_RES(STR_VALUE_NONE));
+ for (auto j : m_aColumnList)
+ {
+ j->append_text(aSTR_NOENTRY);
+ }
+
+ for (int j=0; j < DOG_ROWS; ++j)
+ {
+ m_aColumnList[j]->set_active(0);
+ m_aValueList[j]->set_active(0);
+ }
+ try
+ {
+ // ... also the remaining fields
+ Sequence< OUString> aNames = m_xColumns->getElementNames();
+ const OUString* pIter = aNames.getConstArray();
+ const OUString* pEnd = pIter + aNames.getLength();
+ Reference<XPropertySet> xColumn;
+ for(;pIter != pEnd;++pIter)
+ {
+ xColumn.set(m_xColumns->getByName(*pIter),UNO_QUERY);
+ OSL_ENSURE(xColumn.is(),"Column is null!");
+ if ( xColumn.is() )
+ {
+ sal_Int32 nDataType = 0;
+ xColumn->getPropertyValue(PROPERTY_TYPE) >>= nDataType;
+ sal_Int32 eColumnSearch = dbtools::getSearchColumnFlag(m_xConnection,nDataType);
+ if(eColumnSearch != ColumnSearch::NONE)
+ {
+ for (auto j : m_aColumnList)
+ {
+ j->append_text(*pIter);
+ }
+ }
+ }
+ }
+
+ m_sOrgOrder = m_xQueryComposer->getOrder();
+ impl_initializeOrderList_nothrow();
+ }
+ catch(const Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ EnableLines();
+
+ m_xLB_ORDERFIELD1->connect_changed(LINK(this,DlgOrderCrit,FieldListSelectHdl));
+ m_xLB_ORDERFIELD2->connect_changed(LINK(this,DlgOrderCrit,FieldListSelectHdl));
+}
+
+DlgOrderCrit::~DlgOrderCrit()
+{
+}
+
+IMPL_LINK_NOARG( DlgOrderCrit, FieldListSelectHdl, weld::ComboBox&, void )
+{
+ EnableLines();
+}
+
+void DlgOrderCrit::impl_initializeOrderList_nothrow()
+{
+ try
+ {
+ static const OUStringLiteral sNameProperty = u"Name";
+ static const OUStringLiteral sAscendingProperty = u"IsAscending";
+
+ Reference< XIndexAccess > xOrderColumns( m_xQueryComposer->getOrderColumns(), UNO_SET_THROW );
+ sal_Int32 nColumns = xOrderColumns->getCount();
+ if ( nColumns > DOG_ROWS )
+ nColumns = DOG_ROWS;
+
+ for ( sal_Int32 i = 0; i < nColumns; ++i )
+ {
+ Reference< XPropertySet > xColumn( xOrderColumns->getByIndex( i ), UNO_QUERY_THROW );
+
+ OUString sColumnName;
+ bool bIsAscending( true );
+
+ xColumn->getPropertyValue( sNameProperty ) >>= sColumnName;
+ xColumn->getPropertyValue( sAscendingProperty ) >>= bIsAscending;
+
+ m_aColumnList[i]->set_active_text(sColumnName);
+ m_aValueList[i]->set_active(bIsAscending ? 0 : 1);
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+}
+
+void DlgOrderCrit::EnableLines()
+{
+
+ if ( m_xLB_ORDERFIELD1->get_active() == 0 )
+ {
+ m_xLB_ORDERFIELD2->set_sensitive(false);
+ m_xLB_ORDERVALUE2->set_sensitive(false);
+
+ m_xLB_ORDERFIELD2->set_active( 0 );
+ m_xLB_ORDERVALUE2->set_active( 0 );
+ }
+ else
+ {
+ m_xLB_ORDERFIELD2->set_sensitive(true);
+ m_xLB_ORDERVALUE2->set_sensitive(true);
+ }
+
+ if ( m_xLB_ORDERFIELD2->get_active() == 0 )
+ {
+ m_xLB_ORDERFIELD3->set_sensitive(false);
+ m_xLB_ORDERVALUE3->set_sensitive(false);
+
+ m_xLB_ORDERFIELD3->set_active( 0 );
+ m_xLB_ORDERVALUE3->set_active( 0 );
+ }
+ else
+ {
+ m_xLB_ORDERFIELD3->set_sensitive(true);
+ m_xLB_ORDERVALUE3->set_sensitive(true);
+ }
+}
+
+OUString DlgOrderCrit::GetOrderList( ) const
+{
+ Reference<XDatabaseMetaData> xMetaData = m_xConnection->getMetaData();
+ OUString sQuote = xMetaData.is() ? xMetaData->getIdentifierQuoteString() : OUString();
+
+ OUStringBuffer sOrder;
+ for( sal_uInt16 i=0 ; i<DOG_ROWS; i++ )
+ {
+ if (m_aColumnList[i]->get_active() != 0)
+ {
+ if(!sOrder.isEmpty())
+ sOrder.append(",");
+
+ OUString sName = m_aColumnList[i]->get_active_text();
+ sOrder.append(::dbtools::quoteName(sQuote,sName));
+ if (m_aValueList[i]->get_active())
+ sOrder.append(" DESC ");
+ else
+ sOrder.append(" ASC ");
+ }
+ }
+ return sOrder.makeStringAndClear();
+}
+
+void DlgOrderCrit::BuildOrderPart()
+{
+ m_xQueryComposer->setOrder(GetOrderList());
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/dlg/sqlmessage.cxx b/dbaccess/source/ui/dlg/sqlmessage.cxx
new file mode 100644
index 000000000..eacc59083
--- /dev/null
+++ b/dbaccess/source/ui/dlg/sqlmessage.cxx
@@ -0,0 +1,604 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <core_resource.hxx>
+#include <sqlmessage.hxx>
+#include <strings.hrc>
+#include <com/sun/star/sdbc/SQLException.hpp>
+#include <com/sun/star/sdb/SQLContext.hpp>
+#include <vcl/stdtext.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/weld.hxx>
+#include <osl/diagnose.h>
+#include <connectivity/dbexception.hxx>
+#include <connectivity/sqlerror.hxx>
+#include <unotools/configmgr.hxx>
+
+#include <tools/urlobj.hxx>
+
+#define RET_MORE RET_RETRY + 1
+
+using namespace dbtools;
+using namespace com::sun::star::uno;
+using namespace com::sun::star::sdb;
+using namespace com::sun::star::sdbc;
+
+namespace dbaui
+{
+
+namespace
+{
+ class ImageProvider
+ {
+ private:
+ OUString m_defaultImageID;
+
+ public:
+ explicit ImageProvider(const OUString& defaultImageID)
+ : m_defaultImageID(defaultImageID)
+ {
+ }
+
+ const OUString& getImage() const
+ {
+ return m_defaultImageID;
+ }
+ };
+
+ class LabelProvider
+ {
+ private:
+ OUString m_label;
+ public:
+ explicit LabelProvider(TranslateId labelResourceID)
+ : m_label(DBA_RES(labelResourceID))
+ {
+ }
+
+ const OUString& getLabel() const
+ {
+ return m_label;
+ }
+ };
+
+ class ProviderFactory
+ {
+ private:
+ mutable std::shared_ptr< ImageProvider > m_pErrorImage;
+ mutable std::shared_ptr< ImageProvider > m_pWarningsImage;
+ mutable std::shared_ptr< ImageProvider > m_pInfoImage;
+ mutable std::shared_ptr< LabelProvider > m_pErrorLabel;
+ mutable std::shared_ptr< LabelProvider > m_pWarningsLabel;
+ mutable std::shared_ptr< LabelProvider > m_pInfoLabel;
+
+ public:
+ ProviderFactory()
+ {
+ }
+
+ std::shared_ptr< ImageProvider > const & getImageProvider( SQLExceptionInfo::TYPE _eType ) const
+ {
+ std::shared_ptr< ImageProvider >* ppProvider( &m_pErrorImage );
+ OUString sNormalImageID("dialog-error");
+
+ switch ( _eType )
+ {
+ case SQLExceptionInfo::TYPE::SQLWarning:
+ ppProvider = &m_pWarningsImage;
+ sNormalImageID = "dialog-warning";
+ break;
+
+ case SQLExceptionInfo::TYPE::SQLContext:
+ ppProvider = &m_pInfoImage;
+ sNormalImageID = "dialog-information";
+ break;
+
+ default:
+ break;
+ }
+
+ if ( !ppProvider->get() )
+ (*ppProvider) = std::make_shared<ImageProvider>(sNormalImageID);
+ return *ppProvider;
+ }
+
+ std::shared_ptr< LabelProvider > const & getLabelProvider( SQLExceptionInfo::TYPE _eType, bool _bSubLabel ) const
+ {
+ std::shared_ptr< LabelProvider >* ppProvider( &m_pErrorLabel );
+ TranslateId pLabelID( STR_EXCEPTION_ERROR );
+
+ switch ( _eType )
+ {
+ case SQLExceptionInfo::TYPE::SQLWarning:
+ ppProvider = &m_pWarningsLabel;
+ pLabelID = STR_EXCEPTION_WARNING;
+ break;
+
+ case SQLExceptionInfo::TYPE::SQLContext:
+ ppProvider = &m_pInfoLabel;
+ pLabelID = _bSubLabel ? STR_EXCEPTION_DETAILS : STR_EXCEPTION_INFO;
+ break;
+ default:
+ break;
+ }
+
+ if ( !ppProvider->get() )
+ (*ppProvider) = std::make_shared<LabelProvider>( pLabelID );
+ return *ppProvider;
+ }
+
+ };
+
+ /// a stripped version of the SQLException, packed for displaying
+ struct ExceptionDisplayInfo
+ {
+ SQLExceptionInfo::TYPE eType;
+
+ std::shared_ptr< ImageProvider > pImageProvider;
+ std::shared_ptr< LabelProvider > pLabelProvider;
+
+ bool bSubEntry;
+
+ OUString sMessage;
+ OUString sSQLState;
+ OUString sErrorCode;
+
+ ExceptionDisplayInfo() : eType( SQLExceptionInfo::TYPE::Undefined ), bSubEntry( false ) { }
+ explicit ExceptionDisplayInfo( SQLExceptionInfo::TYPE _eType ) : eType( _eType ), bSubEntry( false ) { }
+ };
+
+ bool lcl_hasDetails( const ExceptionDisplayInfo& _displayInfo )
+ {
+ return ( !_displayInfo.sErrorCode.isEmpty() )
+ || ( !_displayInfo.sSQLState.isEmpty()
+ && _displayInfo.sSQLState != "S1000"
+ );
+ }
+
+ typedef std::vector< ExceptionDisplayInfo > ExceptionDisplayChain;
+
+ /// strips the [OOoBase] vendor identifier from the given error message, if applicable
+ OUString lcl_stripOOoBaseVendor( const OUString& _rErrorMessage )
+ {
+ OUString sErrorMessage( _rErrorMessage );
+
+ const OUString sVendorIdentifier( ::connectivity::SQLError::getMessagePrefix() );
+ if ( sErrorMessage.startsWith( sVendorIdentifier ) )
+ {
+ // characters to strip
+ sal_Int32 nStripLen( sVendorIdentifier.getLength() );
+ // usually, there should be a whitespace between the vendor and the real message
+ while ( ( sErrorMessage.getLength() > nStripLen )
+ && ( sErrorMessage[nStripLen] == ' ' )
+ )
+ ++nStripLen;
+ sErrorMessage = sErrorMessage.copy( nStripLen );
+ }
+
+ return sErrorMessage;
+ }
+
+ void lcl_buildExceptionChain( const SQLExceptionInfo& _rErrorInfo, const ProviderFactory& _rFactory, ExceptionDisplayChain& _out_rChain )
+ {
+ ExceptionDisplayChain().swap(_out_rChain);
+
+ SQLExceptionIteratorHelper iter( _rErrorInfo );
+ while ( iter.hasMoreElements() )
+ {
+ // current chain element
+ SQLExceptionInfo aCurrentElement;
+ iter.next( aCurrentElement );
+
+ const SQLException* pCurrentError = aCurrentElement;
+ OSL_ENSURE( pCurrentError, "lcl_buildExceptionChain: iterator failure!" );
+ // hasMoreElements should not have returned <TRUE/> in this case
+
+ ExceptionDisplayInfo aDisplayInfo( aCurrentElement.getType() );
+
+ aDisplayInfo.sMessage = pCurrentError->Message.trim();
+ aDisplayInfo.sSQLState = pCurrentError->SQLState;
+ if ( pCurrentError->ErrorCode )
+ aDisplayInfo.sErrorCode = OUString::number( pCurrentError->ErrorCode );
+
+ if ( aDisplayInfo.sMessage.isEmpty()
+ && !lcl_hasDetails( aDisplayInfo )
+ )
+ {
+ OSL_FAIL( "lcl_buildExceptionChain: useless exception: no state, no error code, no message!" );
+ continue;
+ }
+
+ aDisplayInfo.pImageProvider = _rFactory.getImageProvider( aCurrentElement.getType() );
+ aDisplayInfo.pLabelProvider = _rFactory.getLabelProvider( aCurrentElement.getType(), false );
+
+ _out_rChain.push_back( aDisplayInfo );
+
+ if ( aCurrentElement.getType() == SQLExceptionInfo::TYPE::SQLContext )
+ {
+ const SQLContext* pContext = aCurrentElement;
+ if ( !pContext->Details.isEmpty() )
+ {
+ ExceptionDisplayInfo aSubInfo( aCurrentElement.getType() );
+
+ aSubInfo.sMessage = pContext->Details;
+ aSubInfo.pImageProvider = _rFactory.getImageProvider( aCurrentElement.getType() );
+ aSubInfo.pLabelProvider = _rFactory.getLabelProvider( aCurrentElement.getType(), true );
+ aSubInfo.bSubEntry = true;
+
+ _out_rChain.push_back( aSubInfo );
+ }
+ }
+ }
+ }
+
+ void lcl_insertExceptionEntry(weld::TreeView& rList, size_t nElementPos, const ExceptionDisplayInfo& rEntry)
+ {
+ rList.append(OUString::number(nElementPos), rEntry.pLabelProvider->getLabel(), rEntry.pImageProvider->getImage());
+ }
+}
+
+namespace {
+
+class OExceptionChainDialog : public weld::GenericDialogController
+{
+ std::unique_ptr<weld::TreeView> m_xExceptionList;
+ std::unique_ptr<weld::TextView> m_xExceptionText;
+
+ OUString m_sStatusLabel;
+ OUString m_sErrorCodeLabel;
+
+ ExceptionDisplayChain m_aExceptions;
+
+public:
+ OExceptionChainDialog(weld::Window* pParent, ExceptionDisplayChain&& rExceptions);
+
+protected:
+ DECL_LINK(OnExceptionSelected, weld::TreeView&, void);
+};
+
+}
+
+OExceptionChainDialog::OExceptionChainDialog(weld::Window* pParent, ExceptionDisplayChain&& rExceptions)
+ : GenericDialogController(pParent, "dbaccess/ui/sqlexception.ui", "SQLExceptionDialog")
+ , m_xExceptionList(m_xBuilder->weld_tree_view("list"))
+ , m_xExceptionText(m_xBuilder->weld_text_view("description"))
+ , m_aExceptions(std::move(rExceptions))
+{
+ int nListWidth = m_xExceptionText->get_approximate_digit_width() * 28;
+ int nTextWidth = m_xExceptionText->get_approximate_digit_width() * 42;
+ int nHeight = m_xExceptionList->get_height_rows(6);
+ m_xExceptionList->set_size_request(nListWidth, nHeight);
+ m_xExceptionText->set_size_request(nTextWidth, nHeight);
+
+ m_sStatusLabel = DBA_RES( STR_EXCEPTION_STATUS );
+ m_sErrorCodeLabel = DBA_RES( STR_EXCEPTION_ERRORCODE );
+
+ m_xExceptionList->connect_changed(LINK(this, OExceptionChainDialog, OnExceptionSelected));
+
+ bool bHave22018 = false;
+ size_t elementPos = 0;
+
+ for (auto const& elem : m_aExceptions)
+ {
+ lcl_insertExceptionEntry(*m_xExceptionList, elementPos, elem);
+ bHave22018 = elem.sSQLState == "22018";
+ ++elementPos;
+ }
+
+ // if the error has the code 22018, then add an additional explanation
+ // #i24021#
+ if ( bHave22018 )
+ {
+ ProviderFactory aProviderFactory;
+
+ ExceptionDisplayInfo aInfo22018;
+ aInfo22018.sMessage = DBA_RES( STR_EXPLAN_STRINGCONVERSION_ERROR );
+ aInfo22018.pLabelProvider = aProviderFactory.getLabelProvider( SQLExceptionInfo::TYPE::SQLContext, false );
+ aInfo22018.pImageProvider = aProviderFactory.getImageProvider( SQLExceptionInfo::TYPE::SQLContext );
+ m_aExceptions.push_back( aInfo22018 );
+
+ lcl_insertExceptionEntry(*m_xExceptionList, m_aExceptions.size() - 1, aInfo22018);
+ }
+
+ if (m_xExceptionList->n_children())
+ {
+ m_xExceptionList->select(0);
+ OnExceptionSelected(*m_xExceptionList);
+ }
+}
+
+IMPL_LINK_NOARG(OExceptionChainDialog, OnExceptionSelected, weld::TreeView&, void)
+{
+ OUString sText;
+
+ OUString sId(m_xExceptionList->get_selected_id());
+ if (!sId.isEmpty())
+ {
+ const ExceptionDisplayInfo& aExceptionInfo(m_aExceptions[sId.toUInt32()]);
+
+ if ( !aExceptionInfo.sSQLState.isEmpty() )
+ {
+ sText += m_sStatusLabel + ": " + aExceptionInfo.sSQLState + "\n";
+ }
+
+ if ( !aExceptionInfo.sErrorCode.isEmpty() )
+ {
+ sText += m_sErrorCodeLabel + ": " + aExceptionInfo.sErrorCode + "\n";
+ }
+
+ if ( !sText.isEmpty() )
+ sText += "\n";
+
+ sText += aExceptionInfo.sMessage;
+ }
+
+ m_xExceptionText->set_text(sText);
+}
+
+// SQLMessageBox_Impl
+struct SQLMessageBox_Impl
+{
+ ExceptionDisplayChain aDisplayInfo;
+
+ explicit SQLMessageBox_Impl( const SQLExceptionInfo& _rExceptionInfo )
+ {
+ // transform the exception chain to a form more suitable for displaying it here
+ ProviderFactory aProviderFactory;
+ lcl_buildExceptionChain( _rExceptionInfo, aProviderFactory, aDisplayInfo );
+ }
+};
+
+namespace
+{
+ void lcl_addButton(weld::MessageDialog* pDialog, StandardButtonType eType, bool bDefault)
+ {
+ sal_uInt16 nButtonID = 0;
+ switch (eType)
+ {
+ case StandardButtonType::Yes:
+ nButtonID = RET_YES;
+ pDialog->add_button(GetStandardText(StandardButtonType::Yes), nButtonID);
+ break;
+ case StandardButtonType::No:
+ nButtonID = RET_NO;
+ pDialog->add_button(GetStandardText(StandardButtonType::No), nButtonID);
+ break;
+ case StandardButtonType::OK:
+ nButtonID = RET_OK;
+ pDialog->add_button(GetStandardText(StandardButtonType::OK), nButtonID);
+ break;
+ case StandardButtonType::Cancel:
+ nButtonID = RET_CANCEL;
+ pDialog->add_button(GetStandardText(StandardButtonType::Cancel), nButtonID);
+ break;
+ case StandardButtonType::Retry:
+ nButtonID = RET_RETRY;
+ pDialog->add_button(GetStandardText(StandardButtonType::Retry), nButtonID);
+ break;
+ case StandardButtonType::Help:
+ nButtonID = RET_HELP;
+ pDialog->add_button(GetStandardText(StandardButtonType::Help), nButtonID);
+ break;
+ default:
+ OSL_FAIL( "lcl_addButton: invalid button id!" );
+ break;
+ }
+ if (bDefault)
+ pDialog->set_default_response(nButtonID);
+ }
+}
+
+void OSQLMessageBox::impl_fillMessages()
+{
+ OSL_PRECOND( !m_pImpl->aDisplayInfo.empty(), "OSQLMessageBox::impl_fillMessages: nothing to display at all?" );
+
+ if ( m_pImpl->aDisplayInfo.empty() )
+ return;
+ const ExceptionDisplayInfo* pSecondInfo = nullptr;
+
+ const ExceptionDisplayInfo& rFirstInfo = *m_pImpl->aDisplayInfo.begin();
+ if ( m_pImpl->aDisplayInfo.size() > 1 )
+ pSecondInfo = &m_pImpl->aDisplayInfo[1];
+ OUString sPrimary, sSecondary;
+ sPrimary = rFirstInfo.sMessage;
+ // one or two texts to display?
+ if ( pSecondInfo )
+ {
+ // we show two elements in the main dialog if and only if one of
+ // - the first element in the chain is an SQLContext, and the second
+ // element denotes its sub entry
+ // - the first and the second element are both independent (i.e. the second
+ // is no sub entry), and none of them is a context.
+ bool bFirstElementIsContext = ( rFirstInfo.eType == SQLExceptionInfo::TYPE::SQLContext );
+ bool bSecondElementIsContext = ( pSecondInfo->eType == SQLExceptionInfo::TYPE::SQLContext );
+
+ if ( bFirstElementIsContext && pSecondInfo->bSubEntry )
+ sSecondary = pSecondInfo->sMessage;
+ if ( !bFirstElementIsContext && !bSecondElementIsContext )
+ sSecondary = pSecondInfo->sMessage;
+ }
+
+ // primary text
+ m_xDialog->set_primary_text(lcl_stripOOoBaseVendor(sPrimary));
+
+ // secondary text (if applicable)
+ m_xDialog->set_secondary_text(lcl_stripOOoBaseVendor(sSecondary));
+}
+
+void OSQLMessageBox::impl_createStandardButtons( MessBoxStyle _nStyle )
+{
+ if ( _nStyle & MessBoxStyle::YesNoCancel )
+ {
+ lcl_addButton(m_xDialog.get(), StandardButtonType::Yes, bool(_nStyle & MessBoxStyle::DefaultYes));
+ lcl_addButton(m_xDialog.get(), StandardButtonType::No, bool(_nStyle & MessBoxStyle::DefaultNo));
+ lcl_addButton(m_xDialog.get(), StandardButtonType::Cancel, bool(_nStyle & MessBoxStyle::DefaultCancel));
+ }
+ else if ( _nStyle & MessBoxStyle::OkCancel )
+ {
+ lcl_addButton(m_xDialog.get(), StandardButtonType::OK, bool(_nStyle & MessBoxStyle::DefaultOk));
+ lcl_addButton(m_xDialog.get(), StandardButtonType::Cancel, bool(_nStyle & MessBoxStyle::DefaultCancel));
+ }
+ else if ( _nStyle & MessBoxStyle::YesNo )
+ {
+ lcl_addButton(m_xDialog.get(), StandardButtonType::Yes, bool(_nStyle & MessBoxStyle::DefaultYes));
+ lcl_addButton(m_xDialog.get(), StandardButtonType::No, bool(_nStyle & MessBoxStyle::DefaultNo));
+ }
+ else if ( _nStyle & MessBoxStyle::RetryCancel )
+ {
+ lcl_addButton(m_xDialog.get(), StandardButtonType::Retry, bool(_nStyle & MessBoxStyle::DefaultRetry));
+ lcl_addButton(m_xDialog.get(), StandardButtonType::Cancel, bool(_nStyle & MessBoxStyle::DefaultCancel));
+ }
+ else if ( _nStyle & MessBoxStyle::Ok )
+ {
+ lcl_addButton(m_xDialog.get(), StandardButtonType::OK, true);
+ }
+
+ if ( m_sHelpURL.isEmpty() )
+ return;
+
+ lcl_addButton(m_xDialog.get(), StandardButtonType::Help, false);
+
+ OUString aTmp;
+ INetURLObject aHID( m_sHelpURL );
+ if ( aHID.GetProtocol() == INetProtocol::Hid )
+ aTmp = aHID.GetURLPath();
+ else
+ aTmp = m_sHelpURL;
+
+ m_xDialog->set_help_id(OUStringToOString(aTmp, RTL_TEXTENCODING_UTF8));
+}
+
+void OSQLMessageBox::impl_addDetailsButton()
+{
+ size_t nFirstPageVisible = m_xDialog->get_secondary_text().isEmpty() ? 1 : 2;
+
+ bool bMoreDetailsAvailable = m_pImpl->aDisplayInfo.size() > nFirstPageVisible;
+ if ( !bMoreDetailsAvailable )
+ {
+ // even if the text fits into what we can display, we might need to details button
+ // if there is more non-trivial information in the errors than the mere messages
+ for (auto const& error : m_pImpl->aDisplayInfo)
+ {
+ if ( lcl_hasDetails(error) )
+ {
+ bMoreDetailsAvailable = true;
+ break;
+ }
+ }
+ }
+
+ if ( bMoreDetailsAvailable )
+ {
+ m_xDialog->add_button(GetStandardText(StandardButtonType::More), RET_MORE);
+ m_xMoreButton.reset(m_xDialog->weld_widget_for_response(RET_MORE));
+ m_xMoreButton->connect_clicked(LINK(this, OSQLMessageBox, ButtonClickHdl));
+ }
+}
+
+void OSQLMessageBox::Construct(weld::Window* pParent, MessBoxStyle _nStyle, MessageType _eImage)
+{
+ // init the image
+ MessageType eType( _eImage );
+ if ( eType == AUTO )
+ {
+ switch ( m_pImpl->aDisplayInfo[0].eType )
+ {
+ case SQLExceptionInfo::TYPE::SQLException: eType = Error; break;
+ case SQLExceptionInfo::TYPE::SQLWarning: eType = Warning; break;
+ case SQLExceptionInfo::TYPE::SQLContext: eType = Info; break;
+ default: OSL_FAIL( "OSQLMessageBox::Construct: invalid type!" );
+ }
+ }
+ VclMessageType eMessageType;
+ switch (eType)
+ {
+ default:
+ OSL_FAIL( "OSQLMessageBox::impl_initImage: unsupported image type!" );
+ [[fallthrough]];
+ case Info:
+ eMessageType = VclMessageType::Info;
+ break;
+ case Warning:
+ eMessageType = VclMessageType::Warning;
+ break;
+ case Error:
+ eMessageType = VclMessageType::Error;
+ break;
+ case Query:
+ eMessageType = VclMessageType::Question;
+ break;
+ }
+
+ m_xDialog.reset(Application::CreateMessageDialog(pParent, eMessageType, VclButtonsType::NONE, ""));
+ m_xDialog->set_title(utl::ConfigManager::getProductName() + " Base");
+
+ impl_fillMessages();
+
+ // create buttons
+ impl_createStandardButtons( _nStyle );
+ impl_addDetailsButton();
+}
+
+OSQLMessageBox::OSQLMessageBox(weld::Window* pParent, const SQLExceptionInfo& rException, MessBoxStyle nStyle, const OUString& rHelpURL)
+ : m_pImpl(new SQLMessageBox_Impl(rException))
+ , m_sHelpURL(rHelpURL)
+{
+ Construct(pParent, nStyle, AUTO);
+}
+
+OSQLMessageBox::OSQLMessageBox(weld::Window* pParent, const OUString& rTitle, const OUString& rMessage, MessBoxStyle nStyle, MessageType eType, const ::dbtools::SQLExceptionInfo* pAdditionalErrorInfo )
+{
+ SQLContext aError;
+ aError.Message = rTitle;
+ aError.Details = rMessage;
+ if (pAdditionalErrorInfo)
+ aError.NextException = pAdditionalErrorInfo->get();
+
+ m_pImpl.reset(new SQLMessageBox_Impl(SQLExceptionInfo(aError)));
+
+ Construct(pParent, nStyle, eType);
+}
+
+OSQLMessageBox::~OSQLMessageBox()
+{
+}
+
+IMPL_LINK_NOARG(OSQLMessageBox, ButtonClickHdl, weld::Button&, void)
+{
+ OExceptionChainDialog aDlg(m_xDialog.get(), std::vector(m_pImpl->aDisplayInfo));
+ aDlg.run();
+}
+
+// OSQLWarningBox
+OSQLWarningBox::OSQLWarningBox(weld::Window* pParent, const OUString& rMessage, MessBoxStyle nStyle,
+ const ::dbtools::SQLExceptionInfo* pAdditionalErrorInfo )
+ : OSQLMessageBox(pParent, DBA_RES(STR_EXCEPTION_WARNING), rMessage, nStyle, MessageType::Warning, pAdditionalErrorInfo)
+{
+}
+
+// OSQLErrorBox
+OSQLErrorBox::OSQLErrorBox(weld::Window* pParent, const OUString& rMessage)
+ : OSQLMessageBox(pParent, DBA_RES(STR_EXCEPTION_ERROR), rMessage, MessBoxStyle::Ok | MessBoxStyle::DefaultOk,
+ MessageType::Error, nullptr)
+{
+}
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/dlg/tablespage.cxx b/dbaccess/source/ui/dlg/tablespage.cxx
new file mode 100644
index 000000000..6094f84e7
--- /dev/null
+++ b/dbaccess/source/ui/dlg/tablespage.cxx
@@ -0,0 +1,488 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "tablespage.hxx"
+#include <dsitems.hxx>
+#include <datasourceconnector.hxx>
+#include <comphelper/types.hxx>
+#include <connectivity/dbtools.hxx>
+#include <connectivity/dbexception.hxx>
+#include <stringlistitem.hxx>
+#include <svl/stritem.hxx>
+#include <strings.hxx>
+#include <com/sun/star/sdbc/SQLException.hpp>
+#include <com/sun/star/util/XModifiable.hpp>
+#include <sqlmessage.hxx>
+#include <UITools.hxx>
+#include <osl/diagnose.h>
+#include <TablesSingleDlg.hxx>
+#include <tools/diagnose_ex.h>
+#include <cppuhelper/exc_hlp.hxx>
+
+namespace dbaui
+{
+
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::sdbc;
+ using namespace ::com::sun::star::sdbcx;
+ using namespace ::com::sun::star::sdb;
+ using namespace ::com::sun::star::beans;
+ using namespace ::com::sun::star::lang;
+ using namespace ::com::sun::star::container;
+ using namespace ::com::sun::star::util;
+ using namespace ::dbtools;
+ using namespace ::comphelper;
+
+ // OTableSubscriptionPage
+ OTableSubscriptionPage::OTableSubscriptionPage(weld::Container* pPage, OTableSubscriptionDialog* pTablesDlg, const SfxItemSet& _rCoreAttrs)
+ : OGenericAdministrationPage(pPage, pTablesDlg, "dbaccess/ui/tablesfilterpage.ui", "TablesFilterPage", _rCoreAttrs)
+ , m_bCatalogAtStart(true)
+ , m_pTablesDlg(pTablesDlg)
+ , m_xTables(m_xBuilder->weld_widget("TablesFilterPage"))
+ , m_xTablesList(new OTableTreeListBox(m_xBuilder->weld_tree_view("treeview"), true))
+ {
+ m_xTablesList->init();
+
+ weld::TreeView& rWidget = m_xTablesList->GetWidget();
+
+ rWidget.set_size_request(rWidget.get_approximate_digit_width() * 48,
+ rWidget.get_height_rows(12));
+
+ // initialize the TabListBox
+ rWidget.set_selection_mode(SelectionMode::Multiple);
+
+ rWidget.connect_toggled(LINK(this, OTableSubscriptionPage, OnTreeEntryChecked));
+ }
+
+ OTableSubscriptionPage::~OTableSubscriptionPage()
+ {
+ // just to make sure that our connection will be removed
+ try
+ {
+ ::comphelper::disposeComponent(m_xCurrentConnection);
+ }
+ catch (RuntimeException&) { }
+ }
+
+ void OTableSubscriptionPage::implCheckTables(const Sequence< OUString >& _rTables)
+ {
+ // the meta data for the current connection, used for splitting up table names
+ Reference< XDatabaseMetaData > xMeta;
+ try
+ {
+ if (m_xCurrentConnection.is())
+ xMeta = m_xCurrentConnection->getMetaData();
+ }
+ catch(SQLException&)
+ {
+ OSL_FAIL("OTableSubscriptionPage::implCheckTables : could not retrieve the current connection's meta data!");
+ }
+
+ // uncheck all
+ CheckAll(false);
+
+ // check the ones which are in the list
+ OUString sCatalog, sSchema, sName;
+
+ std::unique_ptr<weld::TreeIter> xRootEntry(m_xTablesList->getAllObjectsEntry());
+
+ for (const OUString& rIncludeTable : _rTables)
+ {
+ if (xMeta.is())
+ qualifiedNameComponents(xMeta, rIncludeTable, sCatalog, sSchema, sName,::dbtools::EComposeRule::InDataManipulation);
+ else
+ sName = rIncludeTable;
+
+ bool bAllTables = (1 == sName.getLength()) && ('%' == sName[0]);
+ bool bAllSchemas = (1 == sSchema.getLength()) && ('%' == sSchema[0]);
+
+ // the catalog entry
+ std::unique_ptr<weld::TreeIter> xCatalog(m_xTablesList->GetEntryPosByName(sCatalog, xRootEntry.get()));
+ if (!(xCatalog || sCatalog.isEmpty()))
+ // the table (resp. its catalog) referred in this filter entry does not exist anymore
+ continue;
+
+ if (bAllSchemas && xCatalog)
+ {
+ m_xTablesList->checkWildcard(*xCatalog);
+ continue;
+ }
+
+ // the schema entry
+ std::unique_ptr<weld::TreeIter> xSchema = m_xTablesList->GetEntryPosByName(sSchema, (xCatalog ? xCatalog.get() : xRootEntry.get()));
+ if (!(xSchema || sSchema.isEmpty()))
+ // the table (resp. its schema) referred in this filter entry does not exist anymore
+ continue;
+
+ if (bAllTables && xSchema)
+ {
+ m_xTablesList->checkWildcard(*xSchema);
+ continue;
+ }
+
+ std::unique_ptr<weld::TreeIter> xEntry(m_xTablesList->GetEntryPosByName(sName, xSchema ? xSchema.get() : (xCatalog ? xCatalog.get() : xRootEntry.get())));
+ if (xEntry)
+ m_xTablesList->GetWidget().set_toggle(*xEntry, TRISTATE_TRUE);
+ }
+ m_xTablesList->CheckButtons();
+ }
+
+ void OTableSubscriptionPage::implCompleteTablesCheck( const css::uno::Sequence< OUString >& _rTableFilter )
+ {
+ if (!_rTableFilter.hasElements())
+ { // no tables visible
+ CheckAll(false);
+ }
+ else
+ {
+ if ((1 == _rTableFilter.getLength()) && _rTableFilter[0] == "%")
+ { // all tables visible
+ CheckAll();
+ }
+ else
+ implCheckTables( _rTableFilter );
+ }
+ }
+
+ void OTableSubscriptionPage::implInitControls(const SfxItemSet& _rSet, bool _bSaveValue)
+ {
+ // check whether or not the selection is invalid or readonly (invalid implies readonly, but not vice versa)
+ bool bValid, bReadonly;
+ getFlags(_rSet, bValid, bReadonly);
+
+ // get the name of the data source we're working for
+ const SfxStringItem* pNameItem = _rSet.GetItem<SfxStringItem>(DSID_NAME);
+ OSL_ENSURE(pNameItem, "OTableSubscriptionPage::implInitControls: missing the name attribute!");
+ OUString sDSName = pNameItem->GetValue();
+
+ if (bValid && !sDSName.isEmpty() && !m_xCurrentConnection.is() )
+ { // get the current table list from the connection for the current settings
+
+ // the PropertyValues for the current dialog settings
+ Sequence< PropertyValue > aConnectionParams;
+ OSL_ENSURE(m_pTablesDlg, "OTableSubscriptionPage::implInitControls: need a parent dialog doing the translation!");
+ if ( m_pTablesDlg )
+ {
+ if (!m_pTablesDlg->getCurrentSettings(aConnectionParams))
+ {
+ m_xTablesList->GetWidget().clear();
+ m_pTablesDlg->endExecution();
+ return;
+ }
+ }
+
+ // fill the table list with this connection information
+ SQLExceptionInfo aErrorInfo;
+
+ try
+ {
+ weld::WaitObject aWaitCursor(GetFrameWeld());
+
+ Reference<XPropertySet> xProp = m_pTablesDlg->getCurrentDataSource();
+ OSL_ENSURE(xProp.is(),"No data source set!");
+ if ( xProp.is() )
+ {
+ Any aTableFilter = xProp->getPropertyValue(PROPERTY_TABLEFILTER);
+ Any aTableTypeFilter = xProp->getPropertyValue(PROPERTY_TABLETYPEFILTER);
+
+ Reference<XModifiable> xModi(getDataSourceOrModel(xProp),UNO_QUERY);
+ bool bModified = ( xModi.is() && xModi->isModified() );
+
+ Sequence< OUString > aNewTableFilter { "%" };
+ xProp->setPropertyValue(PROPERTY_TABLEFILTER,Any(aNewTableFilter));
+
+ xProp->setPropertyValue( PROPERTY_TABLETYPEFILTER, Any( Sequence< OUString >() ) );
+ Reference< css::lang::XEventListener> xEvt;
+ aErrorInfo = ::dbaui::createConnection(xProp, m_xORB, xEvt, m_xCurrentConnection);
+
+ xProp->setPropertyValue(PROPERTY_TABLEFILTER,aTableFilter);
+ xProp->setPropertyValue(PROPERTY_TABLETYPEFILTER,aTableTypeFilter);
+
+ if ( xModi.is() && !bModified )
+ xModi->setModified(false);
+
+ }
+
+ if ( m_xCurrentConnection.is() )
+ {
+ m_xTablesList->UpdateTableList( m_xCurrentConnection );
+ if (m_pTablesDlg)
+ m_pTablesDlg->successfullyConnected();
+ }
+ }
+ catch (const SQLException&)
+ {
+ aErrorInfo = ::cppu::getCaughtException();
+ }
+
+ if (aErrorInfo.isValid())
+ {
+ // establishing the connection failed. Show an error window and exit.
+ OSQLMessageBox aMessageBox(GetFrameWeld(), aErrorInfo);
+ aMessageBox.run();
+ m_xTables->set_sensitive(false);
+ m_xTablesList->GetWidget().clear();
+
+ if ( m_pTablesDlg )
+ {
+ m_pTablesDlg->clearPassword();
+ m_pTablesDlg->endExecution();
+ }
+ }
+ else
+ {
+ // in addition, we need some infos about the connection used
+ m_sCatalogSeparator = "."; // (default)
+ m_bCatalogAtStart = true; // (default)
+ try
+ {
+ Reference< XDatabaseMetaData > xMeta;
+ if (m_xCurrentConnection.is())
+ xMeta = m_xCurrentConnection->getMetaData();
+ if (xMeta.is() && xMeta->supportsCatalogsInDataManipulation())
+ {
+ m_sCatalogSeparator = xMeta->getCatalogSeparator();
+ m_bCatalogAtStart = xMeta->isCatalogAtStart();
+ }
+ }
+ catch(Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+ }
+
+ // get the current table filter
+ const OStringListItem* pTableFilter = _rSet.GetItem<OStringListItem>(DSID_TABLEFILTER);
+ Sequence< OUString > aTableFilter;
+ if (pTableFilter)
+ aTableFilter = pTableFilter->getList();
+
+ implCompleteTablesCheck( aTableFilter );
+
+ // expand the first entry by default
+ std::unique_ptr<weld::TreeIter> xExpand = m_xTablesList->getAllObjectsEntry();
+ while (xExpand)
+ {
+ m_xTablesList->GetWidget().expand_row(*xExpand);
+ if (!m_xTablesList->GetWidget().iter_children(*xExpand))
+ break;
+ std::unique_ptr<weld::TreeIter> xSibling(m_xTablesList->GetWidget().make_iterator(xExpand.get()));
+ if (m_xTablesList->GetWidget().iter_next_sibling(*xSibling))
+ xExpand.reset();
+ }
+
+ // update the toolbox according the current selection and check state
+ OGenericAdministrationPage::implInitControls(_rSet, _bSaveValue);
+ }
+
+ void OTableSubscriptionPage::CheckAll( bool _bCheck )
+ {
+ std::unique_ptr<weld::TreeIter> xEntry(m_xTablesList->GetWidget().make_iterator());
+ if (m_xTablesList->GetWidget().get_iter_first(*xEntry))
+ {
+ do
+ {
+ m_xTablesList->GetWidget().set_toggle(*xEntry, _bCheck ? TRISTATE_TRUE : TRISTATE_FALSE);
+ }
+ while (m_xTablesList->GetWidget().iter_next(*xEntry));
+ }
+
+ if (_bCheck)
+ {
+ auto xRoot = m_xTablesList->getAllObjectsEntry();
+ if (xRoot)
+ m_xTablesList->checkWildcard(*xRoot);
+ }
+ }
+
+ DeactivateRC OTableSubscriptionPage::DeactivatePage(SfxItemSet* _pSet)
+ {
+ DeactivateRC nResult = OGenericAdministrationPage::DeactivatePage(_pSet);
+
+ // dispose the connection, we don't need it anymore, so we're not wasting resources
+ try
+ {
+ ::comphelper::disposeComponent(m_xCurrentConnection);
+ }
+ catch (RuntimeException&) { }
+
+ return nResult;
+ }
+
+ IMPL_LINK(OTableSubscriptionPage, OnTreeEntryChecked, const weld::TreeView::iter_col&, rRowCol, void)
+ {
+ m_xTablesList->checkedButton_noBroadcast(rRowCol.first);
+ callModifiedHdl();
+ }
+
+ Sequence< OUString > OTableSubscriptionPage::collectDetailedSelection() const
+ {
+ Sequence< OUString > aTableFilter;
+ constexpr OUStringLiteral sWildcard = u"%";
+
+ std::unique_ptr<weld::TreeIter> xAllObjectsEntry(m_xTablesList->getAllObjectsEntry());
+ if (!xAllObjectsEntry)
+ return aTableFilter;
+ std::unique_ptr<weld::TreeIter> xEntry(m_xTablesList->GetWidget().make_iterator(xAllObjectsEntry.get()));
+ if (!m_xTablesList->GetWidget().iter_next(*xEntry))
+ xEntry.reset();
+ while (xEntry)
+ {
+ bool bCatalogWildcard = false;
+ bool bSchemaWildcard = false;
+ std::unique_ptr<weld::TreeIter> xSchema;
+ std::unique_ptr<weld::TreeIter> xCatalog;
+
+ if (m_xTablesList->GetWidget().get_toggle(*xEntry) == TRISTATE_TRUE && !m_xTablesList->GetWidget().iter_has_child(*xEntry))
+ { // checked and a leaf, which means it's no catalog, no schema, but a real table
+ OUStringBuffer sComposedName;
+ OUString sCatalog;
+ if (m_xTablesList->GetWidget().get_iter_depth(*xEntry))
+ {
+ xSchema = m_xTablesList->GetWidget().make_iterator(xEntry.get());
+ m_xTablesList->GetWidget().iter_parent(*xSchema);
+ if (xAllObjectsEntry->equal(*xSchema))
+ {
+ // do not want to have the root entry
+ xSchema.reset();
+ }
+
+ if (xSchema)
+ { // it's a real schema entry, not the "all objects" root
+ if (m_xTablesList->GetWidget().get_iter_depth(*xSchema))
+ {
+ xCatalog = m_xTablesList->GetWidget().make_iterator(xSchema.get());
+ m_xTablesList->GetWidget().iter_parent(*xCatalog);
+ if (xAllObjectsEntry->equal(*xCatalog))
+ {
+ // do not want to have the root entry
+ xCatalog.reset();
+ }
+
+ if (xCatalog)
+ { // it's a real catalog entry, not the "all objects" root
+ bCatalogWildcard = m_xTablesList->isWildcardChecked(*xCatalog);
+ if (m_bCatalogAtStart)
+ {
+ sComposedName.append(m_xTablesList->GetWidget().get_text(*xCatalog) + m_sCatalogSeparator);
+ if (bCatalogWildcard)
+ sComposedName.append(sWildcard);
+ }
+ else
+ {
+ if (bCatalogWildcard)
+ sCatalog = sWildcard;
+ else
+ sCatalog.clear();
+ sCatalog += m_sCatalogSeparator + m_xTablesList->GetWidget().get_text(*xCatalog) ;
+ }
+ }
+ }
+ bSchemaWildcard = m_xTablesList->isWildcardChecked(*xSchema);
+ sComposedName.append(m_xTablesList->GetWidget().get_text(*xSchema) + ".");
+ }
+
+ if (bSchemaWildcard)
+ sComposedName.append(sWildcard);
+ }
+ if (!bSchemaWildcard && !bCatalogWildcard)
+ sComposedName.append(m_xTablesList->GetWidget().get_text(*xEntry));
+
+ if (!m_bCatalogAtStart && !bCatalogWildcard)
+ sComposedName.append(sCatalog);
+
+ // need some space
+ sal_Int32 nOldLen = aTableFilter.getLength();
+ aTableFilter.realloc(nOldLen + 1);
+ // add the new name
+ aTableFilter.getArray()[nOldLen] = sComposedName.makeStringAndClear();
+ }
+
+ if (bCatalogWildcard)
+ xEntry = implNextSibling(xCatalog.get());
+ else if (bSchemaWildcard)
+ xEntry = implNextSibling(xSchema.get());
+ else
+ {
+ if (!m_xTablesList->GetWidget().iter_next(*xEntry))
+ xEntry.reset();
+ }
+ }
+
+ return aTableFilter;
+ }
+
+ std::unique_ptr<weld::TreeIter> OTableSubscriptionPage::implNextSibling(const weld::TreeIter* pEntry) const
+ {
+ std::unique_ptr<weld::TreeIter> xReturn;
+ if (pEntry)
+ {
+ xReturn = m_xTablesList->GetWidget().make_iterator(pEntry);
+ if (!m_xTablesList->GetWidget().iter_next_sibling(*xReturn))
+ {
+ std::unique_ptr<weld::TreeIter> xParent = m_xTablesList->GetWidget().make_iterator(pEntry);
+ if (m_xTablesList->GetWidget().iter_parent(*xParent))
+ xReturn = implNextSibling(xParent.get());
+ else
+ xReturn.reset();
+ }
+ }
+ return xReturn;
+ }
+
+ bool OTableSubscriptionPage::FillItemSet( SfxItemSet* _rCoreAttrs )
+ {
+ bool bValid, bReadonly;
+ getFlags(*_rCoreAttrs, bValid, bReadonly);
+
+ if (!bValid || bReadonly)
+ // don't store anything if the data we're working with is invalid or readonly
+ return true;
+
+ // create the output string which contains all the table names
+ if ( m_xCurrentConnection.is() )
+ { // collect the table filter data only if we have a connection - else no tables are displayed at all
+ Sequence< OUString > aTableFilter;
+ auto xRoot = m_xTablesList->getAllObjectsEntry();
+ if (xRoot && m_xTablesList->isWildcardChecked(*xRoot))
+ {
+ aTableFilter = { "%" };
+ }
+ else
+ {
+ aTableFilter = collectDetailedSelection();
+ }
+ _rCoreAttrs->Put( OStringListItem(DSID_TABLEFILTER, aTableFilter) );
+ }
+
+ return true;
+ }
+
+ void OTableSubscriptionPage::fillControls(std::vector< std::unique_ptr<ISaveValueWrapper> >& /*_rControlList*/)
+ {
+ }
+
+ void OTableSubscriptionPage::fillWindows(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList)
+ {
+ _rControlList.emplace_back(new ODisableWidgetWrapper<weld::Widget>(m_xTables.get()));
+ }
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/dlg/tablespage.hxx b/dbaccess/source/ui/dlg/tablespage.hxx
new file mode 100644
index 000000000..483518b2a
--- /dev/null
+++ b/dbaccess/source/ui/dlg/tablespage.hxx
@@ -0,0 +1,81 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include "adminpages.hxx"
+#include <tabletree.hxx>
+#include <com/sun/star/sdbc/XConnection.hpp>
+
+namespace dbaui
+{
+
+ // OTableSubscriptionPage
+ class OTableSubscriptionDialog;
+ class OTableSubscriptionPage final
+ :public OGenericAdministrationPage
+ {
+ private:
+ OUString m_sCatalogSeparator;
+ bool m_bCatalogAtStart : 1;
+
+ css::uno::Reference< css::sdbc::XConnection >
+ m_xCurrentConnection; /// valid as long as the page is active
+ OTableSubscriptionDialog* m_pTablesDlg;
+
+ std::unique_ptr<weld::Widget> m_xTables;
+ std::unique_ptr<OTableTreeListBox> m_xTablesList;
+
+ public:
+ virtual bool FillItemSet(SfxItemSet* _rCoreAttrs) override;
+ virtual DeactivateRC DeactivatePage(SfxItemSet* _pSet) override;
+
+ OTableSubscriptionPage(weld::Container* pPage, OTableSubscriptionDialog* pController, const SfxItemSet& _rCoreAttrs);
+ virtual ~OTableSubscriptionPage() override;
+
+ private:
+ virtual void fillControls(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) override;
+ virtual void fillWindows(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) override;
+
+ DECL_LINK(OnTreeEntryChecked, const weld::TreeView::iter_col&, void);
+
+ /** check the tables in <member>m_aTablesList</member> according to <arg>_rTables</arg>
+ */
+ void implCheckTables(const css::uno::Sequence< OUString >& _rTables);
+
+ /// returns the next sibling, if not available, the next sibling of the parent, a.s.o.
+ std::unique_ptr<weld::TreeIter> implNextSibling(const weld::TreeIter* pEntry) const;
+
+ /** return the current selection in <member>m_aTablesList</member>
+ */
+ css::uno::Sequence< OUString > collectDetailedSelection() const;
+
+ /// (un)check all entries
+ void CheckAll( bool bCheck = true );
+
+ virtual void implInitControls(const SfxItemSet& _rSet, bool _bSaveValue) override;
+
+ // checks the tables according to the filter given
+ // in opposite to implCheckTables, this method handles the case of an empty sequence, too ...
+ void implCompleteTablesCheck( const css::uno::Sequence< OUString >& _rTableFilter );
+ };
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/dlg/textconnectionsettings.cxx b/dbaccess/source/ui/dlg/textconnectionsettings.cxx
new file mode 100644
index 000000000..5076b3d32
--- /dev/null
+++ b/dbaccess/source/ui/dlg/textconnectionsettings.cxx
@@ -0,0 +1,69 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <textconnectionsettings.hxx>
+#include "TextConnectionHelper.hxx"
+#include <dsitems.hxx>
+#include <stringconstants.hxx>
+
+namespace dbaui
+{
+ // TextConnectionSettingsDialog
+ TextConnectionSettingsDialog::TextConnectionSettingsDialog(weld::Window* pParent, SfxItemSet& rItems)
+ : GenericDialogController(pParent, "dbaccess/ui/textconnectionsettings.ui", "TextConnectionSettingsDialog")
+ , m_rItems(rItems)
+ , m_xContainer(m_xBuilder->weld_widget("TextPageContainer"))
+ , m_xOK(m_xBuilder->weld_button("ok"))
+ , m_xTextConnectionHelper(new OTextConnectionHelper(m_xContainer.get(), TC_HEADER | TC_SEPARATORS | TC_CHARSET))
+ {
+ m_xOK->connect_clicked(LINK(this, TextConnectionSettingsDialog, OnOK));
+ }
+
+ TextConnectionSettingsDialog::~TextConnectionSettingsDialog()
+ {
+ }
+
+ void TextConnectionSettingsDialog::bindItemStorages( SfxItemSet& _rSet, PropertyValues& _rValues )
+ {
+ _rValues[ PROPERTY_ID_HEADER_LINE ] = std::make_shared<SetItemPropertyStorage>( _rSet, DSID_TEXTFILEHEADER );
+ _rValues[ PROPERTY_ID_FIELD_DELIMITER ] = std::make_shared<SetItemPropertyStorage>( _rSet, DSID_FIELDDELIMITER );
+ _rValues[ PROPERTY_ID_STRING_DELIMITER ] = std::make_shared<SetItemPropertyStorage>( _rSet, DSID_TEXTDELIMITER );
+ _rValues[ PROPERTY_ID_DECIMAL_DELIMITER ] = std::make_shared<SetItemPropertyStorage>( _rSet, DSID_DECIMALDELIMITER );
+ _rValues[ PROPERTY_ID_THOUSAND_DELIMITER ] = std::make_shared<SetItemPropertyStorage>( _rSet, DSID_THOUSANDSDELIMITER );
+ _rValues[ PROPERTY_ID_ENCODING ] = std::make_shared<SetItemPropertyStorage>( _rSet, DSID_CHARSET );
+ }
+
+ short TextConnectionSettingsDialog::run()
+ {
+ m_xTextConnectionHelper->implInitControls(m_rItems, true);
+ return GenericDialogController::run();
+ }
+
+ IMPL_LINK_NOARG(TextConnectionSettingsDialog, OnOK, weld::Button&, void)
+ {
+ if (m_xTextConnectionHelper->prepareLeave())
+ {
+ m_xTextConnectionHelper->FillItemSet( m_rItems, false/*bUnused*/ );
+ m_xDialog->response(RET_OK);
+ }
+ }
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/AppElementType.hxx b/dbaccess/source/ui/inc/AppElementType.hxx
new file mode 100644
index 000000000..59105cf22
--- /dev/null
+++ b/dbaccess/source/ui/inc/AppElementType.hxx
@@ -0,0 +1,53 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <com/sun/star/sdb/application/DatabaseObject.hpp>
+
+namespace dbaui
+{
+
+ enum ElementType
+ {
+ E_TABLE = css::sdb::application::DatabaseObject::TABLE,
+ E_QUERY = css::sdb::application::DatabaseObject::QUERY,
+ E_FORM = css::sdb::application::DatabaseObject::FORM,
+ E_REPORT = css::sdb::application::DatabaseObject::REPORT,
+
+ E_NONE = 4,
+ E_ELEMENT_TYPE_COUNT = E_NONE
+ };
+
+ enum PreviewMode
+ {
+ E_PREVIEWNONE = 0,
+ E_DOCUMENT = 1,
+ E_DOCUMENTINFO = 2
+ };
+
+ enum ElementOpenMode
+ {
+ E_OPEN_NORMAL,
+ E_OPEN_DESIGN,
+ E_OPEN_FOR_MAIL
+ };
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/ChildWindow.hxx b/dbaccess/source/ui/inc/ChildWindow.hxx
new file mode 100644
index 000000000..8da6c8570
--- /dev/null
+++ b/dbaccess/source/ui/inc/ChildWindow.hxx
@@ -0,0 +1,38 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+#include <vcl/weld.hxx>
+
+namespace dbaui
+{
+class OChildWindow
+{
+protected:
+ OChildWindow(weld::Container* pParent, const OUString& rUIXMLDescription, const OString& rID);
+ std::unique_ptr<weld::Builder> m_xBuilder;
+ std::unique_ptr<weld::Container> m_xContainer;
+
+public:
+ virtual ~OChildWindow();
+
+ virtual void GrabFocus() = 0;
+
+ virtual bool HasChildPathFocus() const = 0;
+
+ void Enable(bool bEnable) { m_xContainer->set_sensitive(bEnable); }
+
+ void SetHelpId(const OString& rHelpId) { m_xContainer->set_help_id(rHelpId); }
+
+ void Show() { m_xContainer->show(); }
+};
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/dbaccess/source/ui/inc/CollectionView.hxx b/dbaccess/source/ui/inc/CollectionView.hxx
new file mode 100644
index 000000000..c80e98f5e
--- /dev/null
+++ b/dbaccess/source/ui/inc/CollectionView.hxx
@@ -0,0 +1,65 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <vcl/weld.hxx>
+#include <com/sun/star/ucb/XContent.hpp>
+#include <com/sun/star/ucb/XCommandEnvironment.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+
+namespace dbaui
+{
+ /* this class allows to browse through the collection of forms and reports
+ */
+ class OCollectionView : public weld::GenericDialogController
+ {
+ css::uno::Reference< css::ucb::XContent> m_xContent;
+ css::uno::Reference< css::uno::XComponentContext > m_xContext;
+ css::uno::Reference< css::ucb::XCommandEnvironment > m_xCmdEnv;
+ bool m_bCreateForm;
+
+ std::unique_ptr<weld::Label> m_xFTCurrentPath;
+ std::unique_ptr<weld::Button> m_xNewFolder;
+ std::unique_ptr<weld::Button> m_xUp;
+ std::unique_ptr<weld::TreeView> m_xView;
+ std::unique_ptr<weld::Entry> m_xName;
+ std::unique_ptr<weld::Button> m_xPB_OK;
+
+ DECL_LINK(Up_Click, weld::Button&, void);
+ DECL_LINK(NewFolder_Click, weld::Button&, void);
+ DECL_LINK(Save_Click, weld::Button&, void);
+ DECL_LINK(Dbl_Click_FileView, weld::TreeView&, bool);
+
+ /// sets the fixedtext to the right content
+ void initCurrentPath();
+
+ void Initialize();
+ public:
+ OCollectionView(weld::Window * pParent,
+ const css::uno::Reference< css::ucb::XContent>& _xContent,
+ const OUString& _sDefaultName,
+ const css::uno::Reference< css::uno::XComponentContext >& _rxContext);
+ virtual ~OCollectionView() override;
+ const css::uno::Reference< css::ucb::XContent>& getSelectedFolder() const { return m_xContent;}
+ OUString getName() const;
+ };
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/ColumnControlWindow.hxx b/dbaccess/source/ui/inc/ColumnControlWindow.hxx
new file mode 100644
index 000000000..e68b99067
--- /dev/null
+++ b/dbaccess/source/ui/inc/ColumnControlWindow.hxx
@@ -0,0 +1,82 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "FieldDescControl.hxx"
+#include "TypeInfo.hxx"
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <com/sun/star/util/XNumberFormatter.hpp>
+#include <vcl/InterimItemWindow.hxx>
+
+namespace dbaui
+{
+ // OColumnControlWindow
+ class OColumnControlWindow : public OFieldDescControl
+ {
+ css::lang::Locale m_aLocale;
+ css::uno::Reference< css::uno::XComponentContext> m_xContext;
+ css::uno::Reference< css::sdbc::XConnection> m_xConnection;
+ mutable css::uno::Reference< css::util::XNumberFormatter > m_xFormatter; // a number formatter working with the connection's NumberFormatsSupplier
+
+ OTypeInfoMap m_aDestTypeInfo;
+ std::vector<OTypeInfoMap::iterator> m_aDestTypeInfoIndex;
+
+ mutable TOTypeInfoSP m_pTypeInfo; // default type
+ OUString m_sTypeNames; // these type names are the ones out of the resource file
+ OUString m_sAutoIncrementValue;
+ bool m_bAutoIncrementEnabled;
+ protected:
+ virtual void ActivateAggregate( EControlType eType ) override;
+ virtual void DeactivateAggregate( EControlType eType ) override;
+
+ virtual css::lang::Locale GetLocale() const override;
+ virtual css::uno::Reference< css::util::XNumberFormatter > GetFormatter() const override;
+ virtual TOTypeInfoSP getTypeInfo(sal_Int32 _nPos) override;
+ virtual bool isAutoIncrementValueEnabled() const override;
+ virtual OUString getAutoIncrementValue() const override;
+ virtual void CellModified(sal_Int32 nRow, sal_uInt16 nColId ) override;
+
+ public:
+ OColumnControlWindow(weld::Container* pParent,
+ const css::uno::Reference< css::uno::XComponentContext>& _rxContext);
+
+ void setConnection(const css::uno::Reference< css::sdbc::XConnection>& _xCon);
+
+ virtual css::uno::Reference< css::sdbc::XDatabaseMetaData> getMetaData() override;
+ virtual css::uno::Reference< css::sdbc::XConnection> getConnection() override;
+ virtual const OTypeInfoMap* getTypeInfo() const override;
+ TOTypeInfoSP const & getDefaultTyp() const;
+ };
+
+ class OColumnControlTopLevel final : public InterimItemWindow
+ {
+ std::unique_ptr<OColumnControlWindow> m_xControl;
+ public:
+ OColumnControlTopLevel(vcl::Window* pParent,
+ const css::uno::Reference< css::uno::XComponentContext>& _rxContext);
+ virtual void dispose() override;
+
+ OColumnControlWindow& GetControl() { return *m_xControl; }
+
+ virtual void GetFocus() override;
+ };
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/ConnectionLine.hxx b/dbaccess/source/ui/inc/ConnectionLine.hxx
new file mode 100644
index 000000000..954c7e02d
--- /dev/null
+++ b/dbaccess/source/ui/inc/ConnectionLine.hxx
@@ -0,0 +1,71 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <tools/gen.hxx>
+#include "ConnectionLineData.hxx"
+#include <vcl/vclptr.hxx>
+
+class OutputDevice;
+namespace dbaui
+{
+
+ // ConnData ---------->* ConnLineData
+ // ^1 ^1
+ // | |
+ // Conn ---------->* ConnLine
+
+ /*
+ the class OConnectionLine represents the graphical line between the to two windows
+ **/
+ class OTableConnection;
+ class OConnectionLine final
+ {
+ VclPtr<OTableConnection> m_pTabConn;
+ OConnectionLineDataRef m_pData;
+
+ Point m_aSourceConnPos,
+ m_aDestConnPos;
+ Point m_aSourceDescrLinePos,
+ m_aDestDescrLinePos;
+ public:
+ OConnectionLine( OTableConnection* pConn, OConnectionLineDataRef const & pLineData );
+ OConnectionLine( const OConnectionLine& rLine );
+ ~OConnectionLine();
+
+ OConnectionLine& operator=( const OConnectionLine& rLine );
+
+ tools::Rectangle GetBoundingRect() const;
+ bool RecalcLine();
+ void Draw( OutputDevice* pOutDev );
+ bool CheckHit( const Point& rMousePos ) const;
+
+ bool IsValid() const;
+
+ tools::Rectangle GetSourceTextPos() const;
+ tools::Rectangle GetDestTextPos() const;
+
+ const OConnectionLineDataRef& GetData() const { return m_pData; }
+
+ Point getMidPoint() const;
+ };
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/ConnectionLineAccess.hxx b/dbaccess/source/ui/inc/ConnectionLineAccess.hxx
new file mode 100644
index 000000000..1652b8b0b
--- /dev/null
+++ b/dbaccess/source/ui/inc/ConnectionLineAccess.hxx
@@ -0,0 +1,91 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "TableConnection.hxx"
+#include <com/sun/star/accessibility/XAccessibleRelationSet.hpp>
+#include <cppuhelper/implbase2.hxx>
+#include <toolkit/awt/vclxaccessiblecomponent.hxx>
+#include <vcl/vclptr.hxx>
+
+namespace dbaui
+{
+ typedef ::cppu::ImplHelper2< css::accessibility::XAccessibleRelationSet,
+ css::accessibility::XAccessible
+ > OConnectionLineAccess_BASE;
+ class OTableConnection;
+ /** the class OConnectionLineAccess represents the accessible object for the connection between two table windows
+ like they are used in the QueryDesign and the RelationDesign
+ */
+ class OConnectionLineAccess : public VCLXAccessibleComponent
+ , public OConnectionLineAccess_BASE
+ {
+ VclPtr<const OTableConnection> m_pLine; // the window which I should give accessibility to
+ protected:
+ /** this function is called upon disposing the component
+ */
+ virtual void SAL_CALL disposing() override;
+
+ public:
+ OConnectionLineAccess(OTableConnection* _pLine);
+
+ // XInterface
+ virtual css::uno::Any SAL_CALL queryInterface( const css::uno::Type& aType ) override;
+ virtual void SAL_CALL acquire( ) noexcept override
+ { // here inline is allowed because we do not use this class outside this dll
+ VCLXAccessibleComponent::acquire( );
+ }
+ virtual void SAL_CALL release( ) noexcept override
+ { // here inline is allowed because we do not use this class outside this dll
+ VCLXAccessibleComponent::release( );
+ }
+
+ // XTypeProvider
+ virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes( ) override;
+
+ // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() override;
+
+ // XAccessible
+ virtual css::uno::Reference< css::accessibility::XAccessibleContext > SAL_CALL getAccessibleContext( ) override;
+
+ // XAccessibleContext
+ virtual sal_Int32 SAL_CALL getAccessibleChildCount( ) override;
+ virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL getAccessibleChild( sal_Int32 i ) override;
+ virtual sal_Int32 SAL_CALL getAccessibleIndexInParent( ) override;
+ virtual sal_Int16 SAL_CALL getAccessibleRole( ) override;
+ virtual OUString SAL_CALL getAccessibleDescription( ) override;
+ virtual css::uno::Reference< css::accessibility::XAccessibleRelationSet > SAL_CALL getAccessibleRelationSet( ) override;
+
+ // XAccessibleComponent
+ virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL getAccessibleAtPoint( const css::awt::Point& aPoint ) override;
+ virtual css::awt::Rectangle SAL_CALL getBounds( ) override;
+ virtual css::awt::Point SAL_CALL getLocation( ) override;
+ virtual css::awt::Point SAL_CALL getLocationOnScreen( ) override;
+ virtual css::awt::Size SAL_CALL getSize( ) override;
+
+ // XAccessibleRelationSet
+ virtual sal_Int32 SAL_CALL getRelationCount( ) override;
+ virtual css::accessibility::AccessibleRelation SAL_CALL getRelation( sal_Int32 nIndex ) override;
+ virtual sal_Bool SAL_CALL containsRelation( sal_Int16 aRelationType ) override;
+ virtual css::accessibility::AccessibleRelation SAL_CALL getRelationByType( sal_Int16 aRelationType ) override;
+ };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/ConnectionLineData.hxx b/dbaccess/source/ui/inc/ConnectionLineData.hxx
new file mode 100644
index 000000000..10ad0bfdd
--- /dev/null
+++ b/dbaccess/source/ui/inc/ConnectionLineData.hxx
@@ -0,0 +1,80 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "QEnumTypes.hxx"
+#include <vector>
+
+#include <rtl/ref.hxx>
+#include <salhelper/simplereferenceobject.hxx>
+#include <rtl/ustring.hxx>
+
+namespace dbaui
+{
+
+ // ConnData ---------->* ConnLineData
+ // ^1 ^1
+ // | |
+ // Conn ---------->* ConnLine
+
+ /**
+ the class OConnectionLineData contains the data of a connection
+ e.g. the source and the destination field
+ **/
+ class OConnectionLineData : public ::salhelper::SimpleReferenceObject
+ {
+ OUString m_aSourceFieldName;
+ OUString m_aDestFieldName;
+
+ friend bool operator==(const OConnectionLineData& lhs, const OConnectionLineData& rhs);
+ friend bool operator!=(const OConnectionLineData& lhs, const OConnectionLineData& rhs) { return !(lhs == rhs); }
+ protected:
+ virtual ~OConnectionLineData() override;
+ public:
+ OConnectionLineData();
+ OConnectionLineData( const OUString& rSourceFieldName, const OUString& rDestFieldName );
+ OConnectionLineData( const OConnectionLineData& rConnLineData );
+ // provide a copy of own instance (this is somehow more acceptable for me compared to a virtual assignment operator
+ void CopyFrom(const OConnectionLineData& rSource);
+
+ // member access (write)
+ void SetFieldName(EConnectionSide nWhich, const OUString& strFieldName)
+ {
+ if (nWhich==JTCS_FROM)
+ m_aSourceFieldName = strFieldName;
+ else
+ m_aDestFieldName = strFieldName;
+ }
+ void SetSourceFieldName( const OUString& rSourceFieldName){ SetFieldName(JTCS_FROM, rSourceFieldName); }
+ void SetDestFieldName( const OUString& rDestFieldName ){ SetFieldName(JTCS_TO, rDestFieldName); }
+
+ // member access (read)
+ const OUString& GetFieldName(EConnectionSide nWhich) const { return (nWhich == JTCS_FROM) ? m_aSourceFieldName : m_aDestFieldName; }
+ OUString const & GetSourceFieldName() const { return GetFieldName(JTCS_FROM); }
+ OUString const & GetDestFieldName() const { return GetFieldName(JTCS_TO); }
+
+ void Reset();
+ OConnectionLineData& operator=( const OConnectionLineData& rConnLineData );
+ };
+
+ typedef ::rtl::Reference< OConnectionLineData > OConnectionLineDataRef;
+ typedef std::vector< OConnectionLineDataRef > OConnectionLineDataVec;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/DExport.hxx b/dbaccess/source/ui/inc/DExport.hxx
new file mode 100644
index 000000000..ab7c85811
--- /dev/null
+++ b/dbaccess/source/ui/inc/DExport.hxx
@@ -0,0 +1,162 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <sal/config.h>
+
+#include <com/sun/star/sdbc/SQLException.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/util/XNumberFormatter.hpp>
+#include <com/sun/star/container/XNameAccess.hpp>
+#include <com/sun/star/lang/Locale.hpp>
+#include <com/sun/star/util/Date.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <map>
+#include <vector>
+#include <comphelper/stl_types.hxx>
+#include "TypeInfo.hxx"
+#include "WTypeSelect.hxx"
+#include "commontypes.hxx"
+#include "IUpdateHelper.hxx"
+
+namespace com::sun::star {
+ namespace awt{
+ struct FontDescriptor;
+ }
+ namespace sdbc{
+ class XPreparedStatement;
+ class XDatabaseMetaData;
+ }
+}
+
+#define COLUMN_POSITION_NOT_FOUND (sal_Int32(-1))
+
+class SvNumberFormatter;
+namespace dbaui
+{
+ class OFieldDescription;
+ class ODatabaseExport
+ {
+ public:
+ typedef std::map<OUString, OFieldDescription*, ::comphelper::UStringMixLess> TColumns;
+ typedef std::vector<TColumns::const_iterator> TColumnVector;
+ typedef std::vector< std::pair<sal_Int32,sal_Int32> > TPositions;
+
+ protected:
+ TPositions m_vColumnPositions; ///< columns to be used
+ std::vector<sal_Int32> m_vColumnTypes; ///< ColumnTypes for faster access
+ std::vector<sal_Int32> m_vColumnSize;
+ std::vector<sal_Int16> m_vNumberFormat;
+ css::lang::Locale m_aLocale;
+
+ TColumns m_aDestColumns; ///< container for new created columns
+ TColumnVector m_vDestVector;
+
+ css::uno::Reference< css::beans::XPropertySet > m_xTable; ///< dest table
+ css::uno::Reference< css::container::XNameAccess> m_xTables; ///< container
+ SharedConnection m_xConnection; ///< dest conn
+
+ std::shared_ptr<IUpdateHelper> m_pUpdateHelper;
+ css::uno::Reference< css::util::XNumberFormatter > m_xFormatter; ///< a number formatter working with the connection's NumberFormatsSupplier
+ css::uno::Reference< css::uno::XComponentContext> m_xContext;
+ css::util::Date m_aNullDate;
+
+ SvNumberFormatter* m_pFormatter;
+ SvStream& m_rInputStream;
+ /// for saving the selected tablename
+ OUString m_sDefaultTableName;
+
+ OUString m_sTextToken; ///< cell content
+ OUString m_sNumToken; ///< SDNUM value
+ TOTypeInfoSP m_pTypeInfo; ///< contains the default type
+ const TColumnVector* m_pColumnList;
+ const OTypeInfoMap* m_pInfoMap;
+ sal_Int32 m_nColumnPos; ///< current column position
+ sal_Int32 m_nRows; ///< number of rows to be searched
+ sal_Int32 m_nRowCount; ///< current count of rows
+ bool m_bError; ///< error and termination code
+ bool m_bInTbl; ///< true, if parser is in RTF table
+ bool m_bHead; ///< true, if the header hasn't been read yet
+ bool m_bDontAskAgain;///< if there is an error when pasting, don't show it again
+ bool m_bIsAutoIncrement; ///< if PKey is set by user
+ bool m_bFoundTable; ///< set to true when a table was found
+ bool m_bCheckOnly;
+ bool m_bAppendFirstLine;
+
+
+ virtual TypeSelectionPageFactory
+ getTypeSelectionPageFactory() = 0;
+
+ void CreateDefaultColumn(const OUString& _rColumnName);
+ sal_Int16 CheckString(const OUString& aToken, sal_Int16 _nOldNumberFormat);
+ void adjustFormat();
+ void eraseTokens();
+ void insertValueIntoColumn();
+ void createRowSet();
+ void showErrorDialog(const css::sdbc::SQLException& e);
+ void ensureFormatter();
+
+ /** executeWizard calls a wizard to create/append data
+
+ @param _sTableName the tablename
+ @param _aTextColor the text color of the new created table
+ @param _rFont the font of the new table
+
+ @return true when an error occurs
+ */
+ bool executeWizard( const OUString& _sTableName,
+ const css::uno::Any& _aTextColor,
+ const css::awt::FontDescriptor& _rFont);
+
+ virtual ~ODatabaseExport();
+
+ public:
+ ODatabaseExport(
+ const SharedConnection& _rxConnection,
+ const css::uno::Reference< css::util::XNumberFormatter >& _rxNumberF,
+ const css::uno::Reference< css::uno::XComponentContext >& _rxContext,
+ SvStream& _rInputStream
+ );
+
+ // required for automatic type recognition
+ ODatabaseExport(
+ sal_Int32 nRows,
+ TPositions&& _rColumnPositions,
+ const css::uno::Reference< css::util::XNumberFormatter >& _rxNumberF,
+ const css::uno::Reference< css::uno::XComponentContext >& _rxContext,
+ const TColumnVector* rList,
+ const OTypeInfoMap* _pInfoMap,
+ bool _bAutoIncrementEnabled,
+ SvStream& _rInputStream
+ );
+
+ void SetColumnTypes(const TColumnVector* rList,const OTypeInfoMap* _pInfoMap);
+
+ void SetTableName(const OUString &_sTableName){ m_sDefaultTableName = _sTableName ; }
+
+ void enableCheckOnly() { m_bCheckOnly = true; }
+ bool isCheckEnabled() const { return m_bCheckOnly; }
+
+ static css::uno::Reference< css::sdbc::XPreparedStatement > createPreparedStatment( const css::uno::Reference< css::sdbc::XDatabaseMetaData>& _xMetaData
+ ,const css::uno::Reference< css::beans::XPropertySet>& _xDestTable
+ ,const TPositions& _rvColumnPositions);
+ };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/FieldControls.hxx b/dbaccess/source/ui/inc/FieldControls.hxx
new file mode 100644
index 000000000..7eb88ec4e
--- /dev/null
+++ b/dbaccess/source/ui/inc/FieldControls.hxx
@@ -0,0 +1,120 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "SqlNameEdit.hxx"
+#include <unotools/resmgr.hxx>
+
+namespace dbaui
+{
+
+ class OPropColumnEditCtrl : public OSQLNameEntry
+ {
+ short m_nPos;
+ OUString m_strHelpText;
+ public:
+ OPropColumnEditCtrl(std::unique_ptr<weld::Entry> xEntry, OUString const & _rAllowedChars, TranslateId pHelpId, short nPosition);
+
+ short GetPos() const { return m_nPos; }
+ const OUString& GetHelp() const { return m_strHelpText; }
+ };
+
+ class OPropEditCtrl : public OWidgetBase
+ {
+ std::unique_ptr<weld::Entry> m_xEntry;
+ short m_nPos;
+ OUString m_strHelpText;
+
+ public:
+ OPropEditCtrl(std::unique_ptr<weld::Entry> xEntry, TranslateId pHelpId, short nPosition);
+
+ void set_text(const OUString& rText) { m_xEntry->set_text(rText); }
+ OUString get_text() const { return m_xEntry->get_text(); }
+ void set_editable(bool bEditable) { m_xEntry->set_editable(bEditable); }
+
+ virtual void save_value() override { m_xEntry->save_value(); }
+ virtual bool get_value_changed_from_saved() const override { return m_xEntry->get_value_changed_from_saved(); }
+
+ short GetPos() const { return m_nPos; }
+ const OUString& GetHelp() const { return m_strHelpText; }
+ };
+
+ class OPropNumericEditCtrl : public OWidgetBase
+ {
+ std::unique_ptr<weld::SpinButton> m_xSpinButton;
+ short m_nPos;
+ OUString m_strHelpText;
+
+ public:
+ OPropNumericEditCtrl(std::unique_ptr<weld::SpinButton> xSpinButton, TranslateId pHelpId, short nPosition);
+
+ void set_text(const OUString& rText) { m_xSpinButton->set_text(rText); }
+ OUString get_text() const { return m_xSpinButton->get_text(); }
+
+ virtual void save_value() override { m_xSpinButton->save_value(); }
+ virtual bool get_value_changed_from_saved() const override { return m_xSpinButton->get_value_changed_from_saved(); }
+ void set_digits(int nLen) { m_xSpinButton->set_digits(nLen); }
+ void set_min(int nMin) { m_xSpinButton->set_min(nMin); }
+ void set_max(int nMax) { m_xSpinButton->set_max(nMax); }
+ void set_range(int nMin, int nMax) { m_xSpinButton->set_range(nMin, nMax); }
+ int get_value() const { return m_xSpinButton->get_value(); }
+
+ short GetPos() const { return m_nPos; }
+ const OUString& GetHelp() const { return m_strHelpText; }
+
+ void set_editable(bool bEditable) { m_xSpinButton->set_editable(bEditable); }
+ };
+
+ class OPropListBoxCtrl : public OWidgetBase
+ {
+ std::unique_ptr<weld::ComboBox> m_xComboBox;
+ short m_nPos;
+ OUString m_strHelpText;
+
+ public:
+ OPropListBoxCtrl(std::unique_ptr<weld::ComboBox> xComboBox, TranslateId pHelpId, short nPosition);
+ virtual ~OPropListBoxCtrl() override
+ {
+ m_xComboBox->clear();
+ }
+
+ virtual void save_value() override { m_xComboBox->save_value(); }
+ virtual bool get_value_changed_from_saved() const override { return m_xComboBox->get_value_changed_from_saved(); }
+
+ weld::ComboBox& GetComboBox() { return *m_xComboBox; }
+
+ OUString get_active_text() const { return m_xComboBox->get_active_text(); }
+ void set_active_text(const OUString &rText) { m_xComboBox->set_active_text(rText); }
+
+ int get_active() const { return m_xComboBox->get_active(); }
+ void set_active(int nPos) { m_xComboBox->set_active(nPos); }
+
+ int get_count() const { return m_xComboBox->get_count(); }
+
+ void append_text(const OUString &rText) { m_xComboBox->append_text(rText); }
+ void remove_text(const OUString &rText) { m_xComboBox->remove_text(rText); }
+ int find_text(const OUString &rText) const { return m_xComboBox->find_text(rText); }
+
+ short GetPos() const { return m_nPos; }
+ const OUString& GetHelp() const { return m_strHelpText; }
+ };
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/FieldDescControl.hxx b/dbaccess/source/ui/inc/FieldDescControl.hxx
new file mode 100644
index 000000000..478a41070
--- /dev/null
+++ b/dbaccess/source/ui/inc/FieldDescControl.hxx
@@ -0,0 +1,201 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <vcl/weld.hxx>
+#include "IClipBoardTest.hxx"
+#include "QEnumTypes.hxx"
+#include <com/sun/star/sdbc/XDatabaseMetaData.hpp>
+#include <com/sun/star/util/XNumberFormatter.hpp>
+#include "TypeInfo.hxx"
+#include <unotools/resmgr.hxx>
+
+// field description columns of a table
+#define FIELD_NAME 1
+#define FIELD_TYPE 2
+#define HELP_TEXT 3
+#define COLUMN_DESCRIPTION 4
+
+#define FIELD_FIRST_VIRTUAL_COLUMN 5
+
+#define FIELD_PROPERTY_REQUIRED 5
+#define FIELD_PROPERTY_NUMTYPE 6
+#define FIELD_PROPERTY_AUTOINC 7
+#define FIELD_PROPERTY_DEFAULT 8
+#define FIELD_PROPERTY_TEXTLEN 9
+#define FIELD_PROPERTY_LENGTH 10
+#define FIELD_PROPERTY_SCALE 11
+#define FIELD_PROPERTY_BOOL_DEFAULT 12
+#define FIELD_PROPERTY_FORMAT 13
+#define FIELD_PROPERTY_COLUMNNAME 14
+#define FIELD_PROPERTY_TYPE 15
+#define FIELD_PROPERTY_AUTOINCREMENT 16
+
+namespace dbaui
+{
+ class OTableDesignHelpBar;
+ class OPropListBoxCtrl;
+ class OPropEditCtrl;
+ class OPropNumericEditCtrl;
+ class OFieldDescription;
+ class OPropColumnEditCtrl;
+
+ class OFieldDescControl : public IClipboardTest
+ {
+ private:
+ std::unique_ptr<weld::Builder> m_xBuilder;
+ std::unique_ptr<weld::Container> m_xContainer;
+
+ OTableDesignHelpBar* m_pHelp;
+ weld::Widget* m_pLastFocusWindow;
+ weld::Widget* m_pActFocusWindow;
+
+ std::unique_ptr<weld::Label> m_xDefaultText;
+ std::unique_ptr<weld::Label> m_xRequiredText;
+ std::unique_ptr<weld::Label> m_xAutoIncrementText;
+ std::unique_ptr<weld::Label> m_xTextLenText;
+ std::unique_ptr<weld::Label> m_xNumTypeText;
+ std::unique_ptr<weld::Label> m_xLengthText;
+ std::unique_ptr<weld::Label> m_xScaleText;
+ std::unique_ptr<weld::Label> m_xFormatText;
+ std::unique_ptr<weld::Label> m_xBoolDefaultText;
+ std::unique_ptr<weld::Label> m_xColumnNameText;
+ std::unique_ptr<weld::Label> m_xTypeText;
+ std::unique_ptr<weld::Label> m_xAutoIncrementValueText;
+
+ std::unique_ptr<OPropListBoxCtrl> m_xRequired;
+ std::unique_ptr<OPropListBoxCtrl> m_xNumType;
+ std::unique_ptr<OPropListBoxCtrl> m_xAutoIncrement;
+ std::unique_ptr<OPropEditCtrl> m_xDefault;
+ std::unique_ptr<OPropNumericEditCtrl> m_xTextLen;
+ std::unique_ptr<OPropNumericEditCtrl> m_xLength;
+ std::unique_ptr<OPropNumericEditCtrl> m_xScale;
+ std::unique_ptr<OPropEditCtrl> m_xFormatSample;
+ std::unique_ptr<OPropListBoxCtrl> m_xBoolDefault;
+ std::unique_ptr<OPropColumnEditCtrl> m_xColumnName;
+ std::unique_ptr<OPropListBoxCtrl> m_xType;
+ std::unique_ptr<OPropEditCtrl> m_xAutoIncrementValue;
+
+ std::unique_ptr<weld::Button> m_xFormat;
+
+ Link<weld::Widget&, void> m_aControlFocusIn;
+
+ TOTypeInfoSP m_pPreviousType;
+ short m_nPos;
+ OUString aYes;
+ OUString aNo;
+
+ sal_Int32 m_nEditWidth;
+
+ OFieldDescription* pActFieldDescr;
+
+ DECL_LINK(FormatClickHdl, weld::Button&, void);
+ DECL_LINK(ChangeHdl, weld::ComboBox&, void);
+
+ // used by ActivatePropertyField
+ DECL_LINK( OnControlFocusLost, weld::Widget&, void );
+ DECL_LINK( OnControlFocusGot, weld::Widget&, void );
+
+ DECL_LINK( HelpFocusOut, weld::Widget&, void );
+
+ void UpdateFormatSample(OFieldDescription const * pFieldDescr);
+
+ bool isTextFormat(const OFieldDescription* _pFieldDescr,sal_uInt32& _nFormatKey) const;
+ std::unique_ptr<OPropNumericEditCtrl> CreateNumericControl(const OString& rId, TranslateId pHelpId, short _nProperty, const OString& _sHelpId);
+ void InitializeControl(weld::Widget* _pControl,const OString& _sHelpId);
+ void InitializeControl(OPropListBoxCtrl* _pControl,const OString& _sHelpId,bool _bAddChangeHandler);
+
+ bool IsFocusInEditableWidget() const;
+
+ void dispose();
+ protected:
+ void saveCurrentFieldDescData() { SaveData( pActFieldDescr ); }
+ OFieldDescription* getCurrentFieldDescData() { return pActFieldDescr; }
+ void setCurrentFieldDescData( OFieldDescription* _pDesc ) { pActFieldDescr = _pDesc; }
+
+ virtual void ActivateAggregate( EControlType eType );
+ virtual void DeactivateAggregate( EControlType eType );
+ virtual bool IsReadOnly() { return false; };
+
+ virtual css::uno::Reference< css::util::XNumberFormatter > GetFormatter() const = 0;
+
+ virtual css::lang::Locale GetLocale() const = 0;
+
+ virtual void CellModified(sal_Int32 nRow, sal_uInt16 nColId ) = 0;
+ virtual void SetModified(bool bModified); // base implementation is empty
+
+ virtual TOTypeInfoSP getTypeInfo(sal_Int32 _nPos) = 0;
+ virtual const OTypeInfoMap* getTypeInfo() const = 0;
+
+ virtual bool isAutoIncrementValueEnabled() const = 0;
+ virtual OUString getAutoIncrementValue() const = 0;
+
+ OUString BoolStringPersistent(std::u16string_view rUIString) const;
+ OUString BoolStringUI(const OUString& rPersistentString) const;
+
+ const OPropColumnEditCtrl* getColumnCtrl() const { return m_xColumnName.get(); }
+
+ void implFocusLost(weld::Widget* _pWhich);
+
+ public:
+ OFieldDescControl(weld::Container* pPage, OTableDesignHelpBar* pHelpBar);
+ virtual ~OFieldDescControl();
+
+ void DisplayData(OFieldDescription* pFieldDescr );
+
+ void SaveData( OFieldDescription* pFieldDescr );
+
+ void SetControlText( sal_uInt16 nControlId, const OUString& rText );
+ void SetReadOnly( bool bReadOnly );
+
+ void Enable(bool bEnable) { m_xContainer->set_sensitive(bEnable); }
+ void SetHelpId(const OString& rId) { m_xContainer->set_help_id(rId); }
+
+ virtual bool isCutAllowed() override;
+ virtual bool isCopyAllowed() override;
+ virtual bool isPasteAllowed() override;
+
+ virtual void cut() override;
+ virtual void copy() override;
+ virtual void paste() override;
+
+ void connect_focus_in(const Link<weld::Widget&, void>& rLink)
+ {
+ m_aControlFocusIn = rLink;
+ }
+
+ void Init();
+
+ void GrabFocus();
+
+ bool HasChildPathFocus() const;
+
+ virtual css::uno::Reference< css::sdbc::XDatabaseMetaData> getMetaData() = 0;
+ virtual css::uno::Reference< css::sdbc::XConnection> getConnection() = 0;
+
+ OUString getControlDefault( const OFieldDescription* pFieldDescr, bool _bCheck = true) const;
+ // tdf#138409 take the control default in the UI Locale format, e.g. 12,34 and return a string
+ // suitable as the database default, e.g. 12.34
+ OUString CanonicalizeToControlDefault(const OFieldDescription* pFieldDescr, const OUString& rUserText) const;
+
+ void setEditWidth(sal_Int32 _nWidth) { m_nEditWidth = _nWidth; }
+ };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/FieldDescriptions.hxx b/dbaccess/source/ui/inc/FieldDescriptions.hxx
new file mode 100644
index 000000000..5eccd7430
--- /dev/null
+++ b/dbaccess/source/ui/inc/FieldDescriptions.hxx
@@ -0,0 +1,111 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <editeng/svxenum.hxx>
+#include "TypeInfo.hxx"
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/beans/XPropertySetInfo.hpp>
+
+namespace dbaui
+{
+ class OFieldDescription
+ {
+ private:
+ css::uno::Any m_aControlDefault; // the value which the control inserts as default
+ css::uno::Any m_aWidth; // sal_Int32 or void
+ css::uno::Any m_aRelativePosition; // sal_Int32 or void
+
+ TOTypeInfoSP m_pType;
+
+ css::uno::Reference< css::beans::XPropertySet > m_xDest;
+ css::uno::Reference< css::beans::XPropertySetInfo > m_xDestInfo;
+
+ OUString m_sName;
+ OUString m_sTypeName;
+ OUString m_sDescription;
+ OUString m_sHelpText;
+
+ OUString m_sAutoIncrementValue;
+ sal_Int32 m_nType; // only used when m_pType is null
+ sal_Int32 m_nPrecision;
+ sal_Int32 m_nScale;
+ sal_Int32 m_nIsNullable;
+ sal_Int32 m_nFormatKey;
+ SvxCellHorJustify m_eHorJustify;
+ bool m_bIsAutoIncrement;
+ bool m_bIsPrimaryKey;
+ bool m_bIsCurrency;
+ bool m_bHidden;
+
+ public:
+ OFieldDescription();
+ OFieldDescription( const OFieldDescription& rDescr );
+ OFieldDescription(const css::uno::Reference< css::beans::XPropertySet >& _xAffectedCol
+ ,bool _bUseAsDest = false);
+ ~OFieldDescription();
+
+ void SetName(const OUString& _rName);
+ void SetDescription(const OUString& _rDescription);
+ void SetHelpText(const OUString& _sHelptext);
+ void SetDefaultValue(const css::uno::Any& _rDefaultValue);
+ void SetControlDefault(const css::uno::Any& _rControlDefault);
+ void SetAutoIncrementValue(const OUString& _sAutoIncValue);
+ void SetType(const TOTypeInfoSP& _pType);
+ void SetTypeValue(sal_Int32 _nType);
+ void SetTypeName(const OUString& _sTypeName);
+ void SetPrecision(sal_Int32 _rPrecision);
+ void SetScale(sal_Int32 _rScale);
+ void SetIsNullable(sal_Int32 _rIsNullable);
+ void SetFormatKey(sal_Int32 _rFormatKey);
+ void SetHorJustify(const SvxCellHorJustify& _rHorJustify);
+ void SetAutoIncrement(bool _bAuto);
+ void SetPrimaryKey(bool _bPKey);
+ void SetCurrency(bool _bIsCurrency);
+
+ /** copies the content of the field description into the column
+ @param _rxColumn the dest
+ */
+ void copyColumnSettingsTo(const css::uno::Reference< css::beans::XPropertySet >& _rxColumn);
+
+ void FillFromTypeInfo(const TOTypeInfoSP& _pType,bool _bForce,bool _bReset);
+
+ OUString GetName() const;
+ OUString GetDescription() const;
+ OUString GetHelpText() const;
+ css::uno::Any GetControlDefault() const;
+ OUString GetAutoIncrementValue() const;
+ sal_Int32 GetType() const;
+ OUString GetTypeName() const;
+ sal_Int32 GetPrecision() const;
+ sal_Int32 GetScale() const;
+ sal_Int32 GetIsNullable() const;
+ sal_Int32 GetFormatKey() const;
+ SvxCellHorJustify GetHorJustify() const;
+ const TOTypeInfoSP& getTypeInfo() const { return m_pType;}
+ TOTypeInfoSP getSpecialTypeInfo() const;
+ bool IsAutoIncrement() const;
+ bool IsPrimaryKey() const { return m_bIsPrimaryKey;}
+ bool IsCurrency() const { return m_bIsCurrency;}
+ bool IsNullable() const;
+ };
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/GeneralUndo.hxx b/dbaccess/source/ui/inc/GeneralUndo.hxx
new file mode 100644
index 000000000..1bbb593e3
--- /dev/null
+++ b/dbaccess/source/ui/inc/GeneralUndo.hxx
@@ -0,0 +1,40 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <svl/undo.hxx>
+#include <core_resource.hxx>
+
+namespace dbaui
+{
+ // SbaCommentUndoAction - Undo base class for actions whose GetComment provides
+ // a string loaded from a Sba resource
+
+ class OCommentUndoAction : public SfxUndoAction
+ {
+ OUString m_strComment; // undo, redo comment
+
+ public:
+ OCommentUndoAction(TranslateId pCommentID) { m_strComment = DBA_RES(pCommentID); }
+
+ virtual OUString GetComment() const override { return m_strComment; }
+ };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/HtmlReader.hxx b/dbaccess/source/ui/inc/HtmlReader.hxx
new file mode 100644
index 000000000..5c4ddde13
--- /dev/null
+++ b/dbaccess/source/ui/inc/HtmlReader.hxx
@@ -0,0 +1,68 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "DExport.hxx"
+#include <svtools/parhtml.hxx>
+#include <editeng/svxenum.hxx>
+#include <com/sun/star/awt/FontDescriptor.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+
+class SvStream;
+
+namespace dbaui
+{
+ class OHTMLReader final : public HTMLParser, public ODatabaseExport
+ {
+ OUString m_sCurrent;
+ sal_Int32 m_nTableCount;
+ sal_Int16 m_nColumnWidth; ///< maximum column width
+
+ virtual void NextToken( HtmlTokenId nToken ) override; // base class
+ bool CreateTable( HtmlTokenId nToken );
+ virtual TypeSelectionPageFactory
+ getTypeSelectionPageFactory() override;
+
+ void TableDataOn(SvxCellHorJustify& eVal);
+ void TableFontOn(css::awt::FontDescriptor& _rFont, Color &_rTextColor);
+ sal_Int16 GetWidthPixel( const HTMLOption& rOption );
+ void setTextEncoding();
+ void fetchOptions();
+ virtual ~OHTMLReader() override;
+
+ public:
+ OHTMLReader(SvStream& rIn,
+ const SharedConnection& _rxConnection,
+ const css::uno::Reference< css::util::XNumberFormatter >& _rxNumberF,
+ const css::uno::Reference< css::uno::XComponentContext >& _rxContext);
+ // required for automatic type recognition
+ OHTMLReader(SvStream& rIn,
+ sal_Int32 nRows,
+ TPositions&& _rColumnPositions,
+ const css::uno::Reference< css::util::XNumberFormatter >& _rxNumberF,
+ const css::uno::Reference< css::uno::XComponentContext >& _rxContext,
+ const TColumnVector* rList,
+ const OTypeInfoMap* _pInfoMap,
+ bool _bAutoIncrementEnabled);
+
+ virtual SvParserState CallParser() override;// base class
+ };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/IClipBoardTest.hxx b/dbaccess/source/ui/inc/IClipBoardTest.hxx
new file mode 100644
index 000000000..e3eb04962
--- /dev/null
+++ b/dbaccess/source/ui/inc/IClipBoardTest.hxx
@@ -0,0 +1,40 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+#include <sal/types.h>
+
+namespace dbaui
+{
+ class SAL_NO_VTABLE IClipboardTest
+ {
+ public:
+ virtual bool isCutAllowed() = 0;
+ virtual bool isCopyAllowed() = 0;
+ virtual bool isPasteAllowed() = 0;
+
+ virtual void copy() = 0;
+ virtual void cut() = 0;
+ virtual void paste() = 0;
+
+ protected:
+ ~IClipboardTest() {}
+ };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/IItemSetHelper.hxx b/dbaccess/source/ui/inc/IItemSetHelper.hxx
new file mode 100644
index 000000000..cdc1026ea
--- /dev/null
+++ b/dbaccess/source/ui/inc/IItemSetHelper.hxx
@@ -0,0 +1,72 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <sal/types.h>
+#include <com/sun/star/uno/Reference.hxx>
+#include <com/sun/star/uno/XComponentContext.hpp>
+
+namespace com::sun::star {
+ namespace sdbc {
+ class XConnection;
+ class XDriver;
+ }
+ namespace lang {
+ class XMultiServiceFactory;
+ }
+}
+
+class SfxItemSet;
+namespace dbaui
+{
+ class SAL_NO_VTABLE IItemSetHelper
+ {
+ public:
+ virtual const SfxItemSet* getOutputSet() const = 0;
+ virtual SfxItemSet* getWriteOutputSet() = 0;
+
+ protected:
+ ~IItemSetHelper() {}
+ };
+
+ class SAL_NO_VTABLE IDatabaseSettingsDialog
+ {
+ public:
+ virtual css::uno::Reference< css::uno::XComponentContext > getORB() const = 0;
+ virtual std::pair< css::uno::Reference< css::sdbc::XConnection >,bool> createConnection() = 0;
+ virtual css::uno::Reference< css::sdbc::XDriver > getDriver() = 0;
+ virtual OUString getDatasourceType(const SfxItemSet& _rSet) const = 0;
+ virtual void clearPassword() = 0;
+ virtual void saveDatasource() = 0;
+ virtual void setTitle(const OUString& _sTitle) = 0;
+
+ /** enables or disables the user's possibility to confirm the settings
+
+ In a wizard, disabling this will usually disable the "Finish" button.
+ In a normal tab dialog, this will usually disable the "OK" button.
+ */
+ virtual void enableConfirmSettings( bool _bEnable ) = 0;
+
+ protected:
+ ~IDatabaseSettingsDialog() {}
+ };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/IUpdateHelper.hxx b/dbaccess/source/ui/inc/IUpdateHelper.hxx
new file mode 100644
index 000000000..e6ef24a96
--- /dev/null
+++ b/dbaccess/source/ui/inc/IUpdateHelper.hxx
@@ -0,0 +1,44 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <com/sun/star/util/Date.hpp>
+#include <com/sun/star/util/DateTime.hpp>
+#include <com/sun/star/util/Time.hpp>
+
+namespace dbaui
+{
+ class SAL_NO_VTABLE IUpdateHelper
+ {
+ public:
+ virtual void updateString(sal_Int32 _nPos, const OUString& _sValue) = 0;
+ virtual void updateDouble(sal_Int32 _nPos,const double& _nValue) = 0;
+ virtual void updateInt(sal_Int32 _nPos, sal_Int32 _nValue) = 0;
+ virtual void updateNull(sal_Int32 _nPos, ::sal_Int32 sqlType) = 0;
+ virtual void updateDate(sal_Int32 _nPos,const css::util::Date& _nValue) = 0;
+ virtual void updateTime(sal_Int32 _nPos,const css::util::Time& _nValue) = 0;
+ virtual void updateTimestamp(sal_Int32 _nPos,const css::util::DateTime& _nValue) = 0;
+ virtual void insertRow() = 0;
+
+ protected:
+ ~IUpdateHelper() {}
+ };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/JAccess.hxx b/dbaccess/source/ui/inc/JAccess.hxx
new file mode 100644
index 000000000..3a630faa2
--- /dev/null
+++ b/dbaccess/source/ui/inc/JAccess.hxx
@@ -0,0 +1,70 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "JoinTableView.hxx"
+#include <toolkit/awt/vclxaccessiblecomponent.hxx>
+#include <cppuhelper/implbase1.hxx>
+#include <vcl/vclptr.hxx>
+
+namespace dbaui
+{
+ class OJoinTableView;
+ typedef ::cppu::ImplHelper1< css::accessibility::XAccessible
+ > OJoinDesignViewAccess_BASE;
+ /** the class OJoinDesignViewAccess represents the accessible object for join views
+ like the QueryDesign and the RelationDesign
+ */
+ class OJoinDesignViewAccess : public VCLXAccessibleComponent, public OJoinDesignViewAccess_BASE
+ {
+ VclPtr<OJoinTableView> m_pTableView; // the window which I should give accessibility to
+
+ public:
+ /** OJoinDesignViewAccess needs a valid view
+ */
+ OJoinDesignViewAccess( OJoinTableView* _pTableView);
+
+ // XInterface
+ DECLARE_XINTERFACE( )
+ DECLARE_XTYPEPROVIDER( )
+
+ virtual OUString SAL_CALL getImplementationName() override;
+
+ // XAccessible
+ virtual css::uno::Reference< css::accessibility::XAccessibleContext > SAL_CALL getAccessibleContext( ) override;
+
+ // XAccessibleContext
+ virtual sal_Int32 SAL_CALL getAccessibleChildCount( ) override;
+ virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL getAccessibleChild( sal_Int32 i ) override;
+ virtual sal_Int16 SAL_CALL getAccessibleRole( ) override;
+
+ void notifyAccessibleEvent(
+ const sal_Int16 _nEventId,
+ const css::uno::Any& _rOldValue,
+ const css::uno::Any& _rNewValue
+ )
+ {
+ NotifyAccessibleEvent(_nEventId,_rOldValue,_rNewValue);
+ }
+
+ void clearTableView();
+ };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/JoinController.hxx b/dbaccess/source/ui/inc/JoinController.hxx
new file mode 100644
index 000000000..941082322
--- /dev/null
+++ b/dbaccess/source/ui/inc/JoinController.hxx
@@ -0,0 +1,154 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "singledoccontroller.hxx"
+#include "JoinTableView.hxx"
+#include "JoinDesignView.hxx"
+#include "TableConnectionData.hxx"
+#include "TableWindowData.hxx"
+#include <memory>
+
+namespace comphelper
+{
+ class NamedValueCollection;
+}
+
+namespace dbaui
+{
+ class OAddTableDlg;
+ class AddTableDialogContext;
+ class OTableWindow;
+ typedef OSingleDocumentController OJoinController_BASE;
+
+ class OJoinController : public OJoinController_BASE
+ {
+ protected:
+ TTableConnectionData m_vTableConnectionData;
+ TTableWindowData m_vTableData;
+
+ ::dbtools::SQLExceptionInfo m_aExceptionInfo;
+
+ std::shared_ptr<OAddTableDlg> m_xAddTableDialog;
+ std::unique_ptr< AddTableDialogContext > m_pDialogContext;
+ Point m_aMinimumTableViewSize;
+
+ // state of a feature. 'feature' may be the handle of a css::util::URL somebody requested a dispatch interface for OR a toolbar slot.
+ virtual FeatureState GetState(sal_uInt16 nId) const override;
+ // execute a feature
+ virtual void Execute(sal_uInt16 nId, const css::uno::Sequence< css::beans::PropertyValue>& aArgs) override;
+
+ /** loads the information for the windows.
+ @param i_rViewSettings
+ The properties which comes from the layout information.
+ */
+ void loadTableWindows( const ::comphelper::NamedValueCollection& i_rViewSettings );
+
+ /** loads the information for one window.
+ @param _rTable
+ The properties which comes from the layout information.
+ */
+ void loadTableWindow( const ::comphelper::NamedValueCollection& i_rTableWindowSettings );
+
+ /** saves the TableWindows structure in a sequence of property values
+ @param _rViewProps
+ Contains the new sequence.
+ */
+ void saveTableWindows( ::comphelper::NamedValueCollection& o_rViewSettings ) const;
+
+ virtual ~OJoinController() override;
+ public:
+ OJoinController(const css::uno::Reference< css::uno::XComponentContext >& _rM);
+
+ // attribute access
+ TTableWindowData& getTableWindowData() { return m_vTableData; }
+ TTableConnectionData& getTableConnectionData() { return m_vTableConnectionData;}
+ OAddTableDlg* getAddTableDialog()const { return m_xAddTableDialog.get(); }
+
+ // OSingleDocumentController overridables
+ virtual void reconnect( bool _bUI ) override;
+ virtual void impl_onModifyChanged() override;
+
+ // own overridables
+ /** determines whether or not it's allowed for database views to participate in the game
+ */
+ virtual bool allowViews() const = 0;
+
+ /** determines whether or not it's allowed for queries to participate in the game
+ */
+ virtual bool allowQueries() const = 0;
+
+ /** provides access to the OJoinDesignView belonging to the controller, which might
+ or might not be the direct view (getView)
+ */
+ virtual OJoinDesignView* getJoinView();
+
+ /** erase the data in the data vector
+ @param _pData
+ the data which should be erased
+ */
+ void removeConnectionData(const TTableConnectionData::value_type& _pData);
+
+ void SaveTabWinsPosSize( OJoinTableView::OTableWindowMap* pTabWinList, tools::Long nOffsetX, tools::Long nOffsetY );
+
+ static void SaveTabWinPosSize(OTableWindow const * pTabWin, tools::Long nOffsetX, tools::Long nOffsetY);
+
+ // UNO interface overridables
+ // XEventListener
+ using OJoinController_BASE::disposing;
+
+ // css::lang::XComponent
+ virtual void SAL_CALL disposing() override;
+ // css::frame::XController
+ virtual sal_Bool SAL_CALL suspend(sal_Bool bSuspend) override;
+
+ // misc
+ /** only defines a method to save a SQLException in d&d methods to show the error at a later state
+ set the internal member m_aExceptionInfo to _rInfo
+ */
+ void setErrorOccurred(const ::dbtools::SQLExceptionInfo& _rInfo)
+ {
+ m_aExceptionInfo = _rInfo;
+ }
+ /**
+ just returns the internal member and clears it
+ */
+ ::dbtools::SQLExceptionInfo clearOccurredError()
+ {
+ ::dbtools::SQLExceptionInfo aInfo = m_aExceptionInfo;
+ m_aExceptionInfo = ::dbtools::SQLExceptionInfo();
+ return aInfo;
+ }
+
+ // show the dialog
+ void runDialogAsync();
+
+ protected:
+ TTableWindowData::value_type createTableWindowData(const OUString& _sComposedName,const OUString& _sTableName,const OUString& _sWindowName);
+ // ask the user if the design should be saved when it is modified
+ virtual short saveModified() = 0;
+ // called when the original state should be reset (first time load)
+ virtual void reset() = 0;
+ virtual void describeSupportedFeatures() override;
+
+ AddTableDialogContext& impl_getDialogContext() const;
+ };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/JoinDesignView.hxx b/dbaccess/source/ui/inc/JoinDesignView.hxx
new file mode 100644
index 000000000..f4871e9df
--- /dev/null
+++ b/dbaccess/source/ui/inc/JoinDesignView.hxx
@@ -0,0 +1,68 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <dbaccess/dataview.hxx>
+
+class Splitter;
+
+namespace dbaui
+{
+ class OJoinController;
+ class OScrollWindowHelper;
+ class OJoinTableView;
+ class OTableWindow;
+
+ class OJoinDesignView : public ODataView
+ {
+ protected:
+ VclPtr<OScrollWindowHelper> m_pScrollWindow; // contains only the scrollbars
+ VclPtr<OJoinTableView> m_pTableView; // presents the upper window
+ OJoinController& m_rController;
+
+ public:
+ OJoinDesignView(vcl::Window* pParent,
+ OJoinController& _rController,
+ const css::uno::Reference< css::uno::XComponentContext >& );
+ virtual ~OJoinDesignView() override;
+ virtual void dispose() override;
+
+ // set the view readonly or not
+ virtual void setReadOnly(bool _bReadOnly);
+ // set the statement for representation
+ /// late construction
+ virtual void Construct() override;
+ virtual void initialize() override;
+ virtual void KeyInput( const KeyEvent& rEvt ) override;
+
+ void SaveTabWinUIConfig(OTableWindow const * pWin);
+ OJoinController& getController() const { return m_rController; }
+ // called when fields are deleted
+
+ OJoinTableView* getTableView() const { return m_pTableView; }
+ OScrollWindowHelper* getScrollHelper() const { return m_pScrollWindow; }
+ protected:
+ // return the Rectangle where I can paint myself
+ virtual void resizeDocumentView(tools::Rectangle& rRect) override;
+ };
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/JoinExchange.hxx b/dbaccess/source/ui/inc/JoinExchange.hxx
new file mode 100644
index 000000000..7401ec886
--- /dev/null
+++ b/dbaccess/source/ui/inc/JoinExchange.hxx
@@ -0,0 +1,62 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "TableWindowListBox.hxx"
+
+#include <vcl/transfer.hxx>
+#include <com/sun/star/lang/XUnoTunnel.hpp>
+#include <cppuhelper/implbase1.hxx>
+
+namespace dbaui
+{
+ // OJoinExchObj: Additional data to create Joins in the JoinShell
+
+ typedef ::cppu::ImplHelper1< css::lang::XUnoTunnel > OJoinExchObj_Base;
+ class OJoinExchObj final : public TransferDataContainer, public OJoinExchObj_Base
+ {
+ bool m_bFirstEntry;
+
+ OJoinExchangeData m_jxdSourceDescription;
+
+ virtual ~OJoinExchObj() override;
+
+ public:
+ OJoinExchObj();
+ void setDescriptors(const OJoinExchangeData& jxdSource, bool _bFirstEntry);
+
+ // XInterface
+ virtual css::uno::Any SAL_CALL queryInterface( const css::uno::Type& aType ) override;
+ virtual void SAL_CALL acquire( ) noexcept override;
+ virtual void SAL_CALL release( ) noexcept override;
+
+ // XUnoTunnel
+ static const css::uno::Sequence< sal_Int8 > & getUnoTunnelId();
+ virtual sal_Int64 SAL_CALL getSomething( const css::uno::Sequence< sal_Int8 >& _rIdentifier ) override;
+
+ static OJoinExchangeData GetSourceDescription(const css::uno::Reference< css::datatransfer::XTransferable >& _rxObject);
+ static bool isFormatAvailable( const DataFlavorExVector& _rFormats ,SotClipboardFormatId _nSlotID=SotClipboardFormatId::SBA_JOIN);
+
+ private:
+ virtual void AddSupportedFormats() override;
+ virtual bool GetData( const css::datatransfer::DataFlavor& rFlavor, const OUString& rDestDoc ) override;
+ };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/JoinTableView.hxx b/dbaccess/source/ui/inc/JoinTableView.hxx
new file mode 100644
index 000000000..80de958ea
--- /dev/null
+++ b/dbaccess/source/ui/inc/JoinTableView.hxx
@@ -0,0 +1,325 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <vcl/window.hxx>
+#include <vcl/timer.hxx>
+#include <vcl/idle.hxx>
+#include <vcl/scrbar.hxx>
+#include <vcl/vclptr.hxx>
+#include <vcl/transfer.hxx>
+
+#include "callbacks.hxx"
+#include "TableConnectionData.hxx"
+#include "TableWindowData.hxx"
+
+#include <map>
+#include <vector>
+
+struct AcceptDropEvent;
+struct ExecuteDropEvent;
+class SfxUndoAction;
+
+namespace dbaui
+{
+ class OTableConnection;
+ class OTableWindow;
+ struct OJoinExchangeData;
+ class OJoinDesignView;
+ class OTableWindowData;
+ class OJoinDesignViewAccess;
+
+ // this class contains only the scrollbars to avoid that
+ // the tablewindows clip the scrollbars
+ class OJoinTableView;
+ class OScrollWindowHelper : public vcl::Window
+ {
+ VclPtr<ScrollBar> m_aHScrollBar;
+ VclPtr<ScrollBar> m_aVScrollBar;
+ VclPtr<vcl::Window> m_pCornerWindow;
+ VclPtr<OJoinTableView> m_pTableView;
+
+ protected:
+ virtual void Resize() override;
+
+ public:
+ OScrollWindowHelper( vcl::Window* pParent);
+ virtual ~OScrollWindowHelper() override;
+ virtual void dispose() override;
+
+ void setTableView(OJoinTableView* _pTableView);
+
+ void resetRange(const Point& _aSize);
+
+ // own methods
+ ScrollBar& GetHScrollBar() { return *m_aHScrollBar; }
+ ScrollBar& GetVScrollBar() { return *m_aVScrollBar; }
+ };
+
+
+ class OJoinTableView : public vcl::Window,
+ public IDragTransferableListener,
+ public DropTargetHelper
+ {
+ friend class OJoinMoveTabWinUndoAct;
+
+ public:
+ typedef std::map<OUString, VclPtr<OTableWindow> > OTableWindowMap;
+
+ private:
+ OTableWindowMap m_aTableMap;
+ std::vector<VclPtr<OTableConnection> > m_vTableConnection;
+
+ Idle m_aDragScrollIdle;
+ tools::Rectangle m_aDragRect;
+ tools::Rectangle m_aSizingRect;
+ Point m_aDragOffset;
+ Point m_aScrollOffset;
+ Point m_ptPrevDraggingPos;
+ Size m_aOutputSize;
+
+
+ VclPtr<OTableWindow> m_pDragWin;
+ VclPtr<OTableWindow> m_pSizingWin;
+ VclPtr<OTableConnection> m_pSelectedConn;
+
+
+ DECL_LINK(OnDragScrollTimer, Timer*, void);
+
+ protected:
+ VclPtr<OTableWindow> m_pLastFocusTabWin;
+ VclPtr<OJoinDesignView> m_pView;
+ rtl::Reference<OJoinDesignViewAccess> m_pAccessible;
+
+ public:
+ OJoinTableView( vcl::Window* pParent, OJoinDesignView* pView );
+ virtual ~OJoinTableView() override;
+ virtual void dispose() override;
+
+ // window override
+ virtual void StateChanged( StateChangedType nStateChange ) override;
+ virtual void GetFocus() override;
+ virtual void LoseFocus() override;
+ virtual void KeyInput( const KeyEvent& rEvt ) override;
+ // Accessibility
+ virtual css::uno::Reference< css::accessibility::XAccessible > CreateAccessible() override;
+
+ // own methods
+ ScrollBar& GetHScrollBar() { return static_cast<OScrollWindowHelper*>(GetParent())->GetHScrollBar(); }
+ ScrollBar& GetVScrollBar() { return static_cast<OScrollWindowHelper*>(GetParent())->GetVScrollBar(); }
+ DECL_LINK( ScrollHdl, ScrollBar*, void );
+
+ void DrawConnections(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect);
+ void InvalidateConnections();
+
+ void BeginChildMove( OTableWindow* pTabWin, const Point& rMousePos );
+ void BeginChildSizing( OTableWindow* pTabWin, PointerStyle nPointer );
+
+ void NotifyTitleClicked( OTableWindow* pTabWin, const Point& rMousePos );
+
+ virtual void AddTabWin(const OUString& _rComposedName, const OUString& rWinName, bool bNewTable = false);
+ virtual void RemoveTabWin( OTableWindow* pTabWin );
+
+ // hide all TabWins (does NOT delete them; they are put in an UNDO action)
+ void HideTabWins();
+
+ virtual void AddConnection(const OJoinExchangeData& jxdSource, const OJoinExchangeData& jxdDest) = 0;
+
+ /** RemoveConnection allows to remove connections from join table view
+
+ it implies that the same as addConnection
+
+ @param rConnection the connection which should be removed
+ @param bDelete when true then the connection will be deleted
+
+ @return an iterator to next valid connection, so it can be used in any loop
+ */
+ virtual bool RemoveConnection(VclPtr<OTableConnection>& rConnection, bool bDelete);
+
+ /** allows to add new connections to join table view
+
+ it implies an invalidation of the features ID_BROWSER_ADDTABLE and
+ SID_RELATION_ADD_RELATION also the modified flag will be set to true
+
+ @param _pConnection the connection which should be added
+ @param _bAddData when true then the data should also be appended
+ */
+ void addConnection(OTableConnection* _pConnection,bool _bAddData = true);
+
+ bool ScrollPane( tools::Long nDelta, bool bHoriz, bool bPaintScrollBars );
+ sal_uLong GetTabWinCount() const;
+ const Point& GetScrollOffset() const { return m_aScrollOffset; }
+
+ OJoinDesignView* getDesignView() const { return m_pView; }
+ OTableWindow* GetTabWindow( const OUString& rName );
+
+ VclPtr<OTableConnection>& GetSelectedConn() { return m_pSelectedConn; }
+ /** @note NULL is explicitly allowed (then no-op) */
+ void DeselectConn(OTableConnection* pConn);
+ void SelectConn(OTableConnection* pConn);
+
+ OTableWindowMap& GetTabWinMap() { return m_aTableMap; }
+
+ /** gives a read only access to the connection vector
+ */
+ const std::vector<VclPtr<OTableConnection> >& getTableConnections() const { return m_vTableConnection; }
+
+ bool ExistsAConn(const OTableWindow* pFromWin) const;
+
+ /** search for all connections of a table
+
+ @param _pFromWin the table for which connections should be found
+ @return an iterator which can be used to travel all connections of the table
+ */
+ std::vector<VclPtr<OTableConnection> >::const_iterator getTableConnections(const OTableWindow* _pFromWin) const;
+
+ /** how many connection belongs to single table
+
+ @param _pFromWin the table for which connections should be found
+ @return the count of connections which belongs to this table
+ */
+ sal_Int32 getConnectionCount(const OTableWindow* _pFromWin) const;
+
+ OTableConnection* GetTabConn(const OTableWindow* pLhs,const OTableWindow* pRhs,bool _bSuppressCrossOrNaturalJoin = false) const;
+
+ /** clear the window map and connection vector without destroying it
+
+ that means that the data of the windows and connection will be
+ untouched
+ */
+ void clearLayoutInformation();
+
+ /** set the focus to that tab win which most recently had it
+ (or to the first available one) **/
+ void GrabTabWinFocus();
+
+ /** take all WinData and ConnData from the document and create the
+ corresponding Wins and Conns */
+ virtual void ReSync() { }
+
+ /** Hard deletion
+
+ That means that all Conns and Wins are deleted from their respective
+ lists and the corresponding Data removed from the document */
+ virtual void ClearAll();
+
+ /** @note used by AddTabDlg to see if more tables can be added */
+ virtual bool IsAddAllowed();
+ virtual bool PreNotify(NotifyEvent& rNEvt) override;
+
+ // DnD stuff
+ virtual sal_Int8 AcceptDrop( const AcceptDropEvent& rEvt ) override;
+ virtual sal_Int8 ExecuteDrop( const ExecuteDropEvent& rEvt ) override;
+
+ /** @note can be used for special ui handling after d&d */
+ virtual void lookForUiActivities();
+
+ /** Hook that is called after moving/resizing TabWins
+
+ The position is 'virtual': the container has a virtual area of
+ which only a part - changeable by scroll bar - is visible.
+ Therefore: ptOldPosition is always positive, even if it represents
+ a point with a negative physical ordinate above the visible area
+
+ @note The standard implementation just passes the new data to the
+ Wins
+ */
+ void TabWinMoved(OTableWindow* ptWhich, const Point& ptOldPosition);
+
+ void TabWinSized(OTableWindow* ptWhich, const Point& ptOldPosition, const Size& szOldSize);
+
+ void modified();
+
+ /** check if the given window is visible.
+
+ @param _rPoint The Point to check
+ @param _rSize The Size to be check as well
+ @return true if the area is visible, false otherwise
+ */
+ bool isMovementAllowed(const Point& _rPoint,const Size& _rSize);
+
+ const Size& getRealOutputSize() const { return m_aOutputSize; }
+
+ virtual void EnsureVisible(const OTableWindow* _pWin);
+ void EnsureVisible(const Point& _rPoint,const Size& _rSize);
+
+ TTableWindowData::value_type createTableWindowData(const OUString& _rComposedName
+ ,const OUString& _sTableName
+ ,const OUString& _rWinName);
+
+ protected:
+ virtual void MouseButtonUp( const MouseEvent& rEvt ) override;
+ virtual void MouseButtonDown( const MouseEvent& rEvt ) override;
+ virtual void Tracking( const TrackingEvent& rTEvt ) override;
+ virtual void Paint( vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect ) override;
+ virtual void ConnDoubleClicked(VclPtr<OTableConnection>& rConnection);
+ void SetDefaultTabWinPosSize( OTableWindow* pTabWin );
+ virtual void DataChanged( const DataChangedEvent& rDCEvt ) override;
+
+ virtual void Resize() override;
+
+ virtual void dragFinished( ) override;
+ /// @note here the physical position (that can be changed while
+ /// resizing) is used, as no scrolling can take place while resizing
+ virtual void Command(const CommandEvent& rEvt) override;
+
+ virtual std::shared_ptr<OTableWindowData> CreateImpl(const OUString& _rComposedName
+ ,const OUString& _sTableName
+ ,const OUString& _rWinName);
+
+ /** factory method to create table windows
+
+ @param _pData The data corresponding to the window.
+ @return The new TableWindow
+ */
+ virtual VclPtr<OTableWindow> createWindow(const TTableWindowData::value_type& _pData) = 0;
+
+ /** determines whether the classes Init method should accept a query
+ name, or only table names */
+ virtual bool allowQueries() const;
+
+ /** called when init fails at the tablewindowdata because the m_xTable
+ object could not provide columns, but no exception was thrown.
+ Expected to throw. */
+ virtual void onNoColumns_throw();
+
+ virtual bool suppressCrossNaturalJoin(const TTableConnectionData::value_type& _pData) const;
+
+ private:
+ void InitColors();
+ void ScrollWhileDragging();
+
+ /** opens the context menu to delete a connection
+ @param _aPos the position where the popup menu should appear
+ @param _pSelConnection the connection which should be deleted
+ */
+ void executePopup(const Point& _aPos, VclPtr<OTableConnection>& rSelConnection);
+
+ /** invalidates this window without children and set the controller
+ modified
+ @param _pAction a possible undo action to add at the controller
+ */
+ void invalidateAndModify(std::unique_ptr<SfxUndoAction> _pAction);
+
+ private:
+ using Window::Scroll;
+ };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/QEnumTypes.hxx b/dbaccess/source/ui/inc/QEnumTypes.hxx
new file mode 100644
index 000000000..b889870c9
--- /dev/null
+++ b/dbaccess/source/ui/inc/QEnumTypes.hxx
@@ -0,0 +1,79 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+namespace dbaui
+{
+ enum EOrderDir
+ {
+ ORDER_NONE=0,
+ ORDER_ASC,
+ ORDER_DESC
+ };
+
+ enum EFunctionType
+ {
+ FKT_NONE =0x00000000,
+ FKT_OTHER =0x00000001,
+ FKT_AGGREGATE =0x00000002,
+ FKT_CONDITION =0x00000004,
+ FKT_NUMERIC =0x00000008
+ // if this function type is set, it is either EXISTS or UNIQUE,
+ // the FieldName contains the complete statement
+ };
+
+ enum EConnectionSide
+ {
+ JTCS_FROM=0,
+ JTCS_TO
+ };
+
+ enum ETableFieldType
+ {
+ TAB_NORMAL_FIELD=0,
+ TAB_PRIMARY_FIELD
+ };
+
+ enum EJoinType
+ {
+ FULL_JOIN=0,
+ LEFT_JOIN,
+ RIGHT_JOIN,
+ CROSS_JOIN,
+ INNER_JOIN
+ };
+
+ enum EControlType
+ {
+ tpDefault = 0,
+ tpRequired,
+ tpTextLen,
+ tpNumType,
+ tpLength,
+ tpScale,
+ tpFormat,
+ tpAutoIncrement,
+ tpBoolDefault,
+ tpColumnName,
+ tpType,
+ tpAutoIncrementValue
+ };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/QueryDesignView.hxx b/dbaccess/source/ui/inc/QueryDesignView.hxx
new file mode 100644
index 000000000..efef444e8
--- /dev/null
+++ b/dbaccess/source/ui/inc/QueryDesignView.hxx
@@ -0,0 +1,154 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "JoinDesignView.hxx"
+#include <vcl/split.hxx>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include "querycontroller.hxx"
+
+namespace connectivity
+{
+ class OSQLParseNode;
+}
+namespace weld
+{
+ class ComboBox;
+}
+namespace dbaui
+{
+ enum SqlParseError
+ {
+ eIllegalJoin,
+ eStatementTooLong,
+ eNoConnection,
+ eNoSelectStatement,
+ eStatementTooComplex,
+ eNoColumnInLike,
+ eColumnNotFound,
+ eNativeMode,
+ eTooManyTables,
+ eTooManyColumns,
+ eIllegalJoinCondition,
+ eOk
+ };
+
+ class OSelectionBrowseBox;
+ class OQueryContainerWindow;
+ class OQueryController;
+
+ class OQueryDesignView : public OJoinDesignView
+ {
+ enum ChildFocusState
+ {
+ SELECTION,
+ TABLEVIEW,
+ NONE
+ };
+
+ VclPtr<Splitter> m_aSplitter;
+
+ css::lang::Locale m_aLocale;
+ OUString m_sDecimalSep;
+
+ VclPtr<OSelectionBrowseBox> m_pSelectionBox; // presents the lower window
+ ChildFocusState m_eChildFocus;
+ bool m_bInSplitHandler;
+
+ public:
+ OQueryDesignView(OQueryContainerWindow* pParent, OQueryController& _rController, const css::uno::Reference< css::uno::XComponentContext >& );
+ virtual ~OQueryDesignView() override;
+ virtual void dispose() override;
+
+ bool isCutAllowed() const;
+ bool isPasteAllowed() const;
+ bool isCopyAllowed() const;
+ void copy();
+ void cut();
+ void paste();
+ // clears the whole query
+ void clear();
+ // set the view readonly or not
+ virtual void setReadOnly(bool _bReadOnly) override;
+ // check if the statement is correct when not returning false
+ bool checkStatement();
+ // returns the current sql statement
+ OUString getStatement();
+ /// late construction
+ virtual void Construct() override;
+ virtual void initialize() override;
+ // Window overrides
+ virtual bool PreNotify( NotifyEvent& rNEvt ) override;
+ virtual void GetFocus() override;
+
+ bool isSlotEnabled(sal_Int32 _nSlotId);
+ void setSlotEnabled(sal_Int32 _nSlotId, bool _bEnable);
+ void setNoneVisibleRow(sal_Int32 _nRows);
+
+ const css::lang::Locale& getLocale() const { return m_aLocale;}
+ const OUString& getDecimalSeparator() const { return m_sDecimalSep;}
+
+ SqlParseError InsertField( const OTableFieldDescRef& rInfo, bool bActivate = true);
+ bool HasFieldByAliasName(std::u16string_view rFieldName, OTableFieldDescRef const & rInfo) const;
+ // called when a table from tabview was deleted
+ void TableDeleted(const OUString& rAliasName);
+
+ sal_Int32 getColWidth( sal_uInt16 _nColPos) const;
+ void fillValidFields(std::u16string_view strTableName, weld::ComboBox& rFieldList);
+
+ void SaveUIConfig();
+ void stopTimer();
+ void startTimer();
+ void reset();
+
+ /** initializes the view from the current parser / parse iterator of the controller
+
+ @param _pErrorInfo
+ When not <NULL/>, the instance pointed to by this parameter takes the error
+ which happened during the initialization.
+ If it is not <NULL/>, then any such error will be displayed, using the controller's
+ showError method.
+
+ @return <TRUE/> if and only if the initialization was successful
+ */
+ bool initByParseIterator( ::dbtools::SQLExceptionInfo* _pErrorInfo );
+
+ void initByFieldDescriptions(
+ const css::uno::Sequence< css::beans::PropertyValue >& i_rFieldDescriptions
+ );
+
+ std::unique_ptr<::connectivity::OSQLParseNode> getPredicateTreeFromEntry( const OTableFieldDescRef& pEntry,
+ const OUString& _sCriteria,
+ OUString& _rsErrorMessage,
+ css::uno::Reference< css::beans::XPropertySet>& _rxColumn) const;
+
+ void fillFunctionInfo( const ::connectivity::OSQLParseNode* pNode
+ ,const OUString& sFunctionTerm
+ ,OTableFieldDescRef& aInfo);
+ protected:
+ // return the Rectangle where I can paint myself
+ virtual void resizeDocumentView(tools::Rectangle& rRect) override;
+ DECL_LINK( SplitHdl, Splitter*, void );
+
+ private:
+ using OJoinDesignView::SaveTabWinUIConfig;
+ };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/QueryPropertiesDialog.hxx b/dbaccess/source/ui/inc/QueryPropertiesDialog.hxx
new file mode 100644
index 000000000..2d8bb80dc
--- /dev/null
+++ b/dbaccess/source/ui/inc/QueryPropertiesDialog.hxx
@@ -0,0 +1,45 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+#include <vcl/weld.hxx>
+
+namespace dbaui
+{
+
+/**
+ * Dialog to set such properties of a query as distinct values and limit
+ * It can be opened from Edit menu in Query Design View
+ */
+class QueryPropertiesDialog : public weld::GenericDialogController
+{
+
+public:
+
+ QueryPropertiesDialog(
+ weld::Window* pParent, const bool bDistinct, const sal_Int64 nLimit );
+ virtual ~QueryPropertiesDialog() override;
+ bool getDistinct() const
+ {
+ return m_xRB_Distinct->get_active();
+ }
+
+ sal_Int64 getLimit() const;
+
+private:
+
+ std::unique_ptr<weld::RadioButton> m_xRB_Distinct;
+ std::unique_ptr<weld::RadioButton> m_xRB_NonDistinct;
+ std::unique_ptr<weld::ComboBox> m_xLB_Limit;
+};
+
+} ///dbaui namespace
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/QueryTableView.hxx b/dbaccess/source/ui/inc/QueryTableView.hxx
new file mode 100644
index 000000000..26133d2cc
--- /dev/null
+++ b/dbaccess/source/ui/inc/QueryTableView.hxx
@@ -0,0 +1,116 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "JoinTableView.hxx"
+#include "TableFieldDescription.hxx"
+
+namespace dbaui
+{
+ class OQueryTabWinUndoAct;
+ class OQueryTableConnection;
+ class OQueryTableWindow;
+ class OQueryDesignView;
+
+ class OQueryTableView : public OJoinTableView
+ {
+ protected:
+ virtual void ConnDoubleClicked(VclPtr<OTableConnection>& rConnection) override;
+
+ virtual VclPtr<OTableWindow> createWindow(const TTableWindowData::value_type& _pData) override;
+
+ /** called when init fails at the tablewindowdata because the m_xTable
+ object could not provide columns, but no exception was thrown.
+ Expected to throw. */
+ virtual void onNoColumns_throw() override;
+
+ virtual bool suppressCrossNaturalJoin(const TTableConnectionData::value_type& _pData) const override;
+
+ public:
+ OQueryTableView(vcl::Window* pParent,OQueryDesignView* pView);
+
+ /// base class overwritten: create and delete windows
+ /// (not really delete, as it becomes an UndoAction)
+ bool ContainsTabWin(const OTableWindow& rTabWin); // #i122589# Allow to check if OTableWindow is registered
+ virtual void AddTabWin( const OUString& _rTableName, const OUString& _rAliasName, bool bNewTable = false ) override;
+ virtual void RemoveTabWin(OTableWindow* pTabWin) override;
+
+ /// AddTabWin, setting an alias
+ void AddTabWin(const OUString& strDatabase, const OUString& strTableName, const OUString& strAlias, bool bNewTable);
+ /// search TabWin
+ OQueryTableWindow* FindTable(const OUString& rAliasName);
+ bool FindTableFromField(const OUString& rFieldName, OTableFieldDescRef const & rInfo, sal_uInt16& rCnt);
+
+ /// base class overwritten: create and delete Connections
+ virtual void AddConnection(const OJoinExchangeData& jxdSource, const OJoinExchangeData& jxdDest) override;
+
+ virtual bool RemoveConnection(VclPtr<OTableConnection>& rConn, bool bDelete) override;
+
+ // transfer of connections from and to UndoAction
+
+ /// Inserting a Connection the structure
+ void GetConnection(OQueryTableConnection* pConn);
+ /** Removing a Connection from the structure
+
+ This results effectively in complete reset of request form, as all
+ windows are hidden, as are all Connections to these windows and all
+ request columns based on those tables */
+ void DropConnection(VclPtr<OQueryTableConnection> const & rConn);
+
+ // show and hide TabWin (NOT create or delete)
+ bool ShowTabWin(OQueryTableWindow* pTabWin, OQueryTabWinUndoAct* pUndoAction, bool _bAppend);
+ void HideTabWin(OQueryTableWindow* pTabWin, OQueryTabWinUndoAct* pUndoAction);
+
+ /// ensure visibility of TabWins (+ and invalidate connections)
+ virtual void EnsureVisible(const OTableWindow* _pWin) override;
+
+ /// how many tables with a certain alias do I already have?
+ sal_Int32 CountTableAlias(const OUString& rName, sal_Int32& rMax);
+
+ /// insert field (simply passed to parents)
+ void InsertField(const OTableFieldDescRef& rInfo);
+
+ /// rebuild everything (TabWins, Connections)
+ /// (PRECONDITION: ClearAll was called previously)
+ virtual void ReSync() override;
+
+ /// delete everything hard (TabWins, Connections), without any notifications
+ virtual void ClearAll() override;
+
+ // used by AddTabDlg to see if tables can still be added
+ //virtual sal_Bool IsAddAllowed();
+
+ /// announce new Connection and insert it, if not existing yet
+ void NotifyTabConnection(const OQueryTableConnection& rNewConn, bool _bCreateUndoAction = true);
+
+ bool ExistsAVisitedConn(const OQueryTableWindow* pFrom) const;
+
+ virtual std::shared_ptr<OTableWindowData> CreateImpl(const OUString& _rComposedName
+ ,const OUString& _sTableName
+ ,const OUString& _rWinName) override;
+
+ /** opens the join dialog and allows to create a new join connection */
+ void createNewConnection();
+
+ private:
+ using OJoinTableView::EnsureVisible;
+ };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/QueryTextView.hxx b/dbaccess/source/ui/inc/QueryTextView.hxx
new file mode 100644
index 000000000..33f66342b
--- /dev/null
+++ b/dbaccess/source/ui/inc/QueryTextView.hxx
@@ -0,0 +1,69 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <vcl/InterimItemWindow.hxx>
+#include "querycontainerwindow.hxx"
+#include "sqledit.hxx"
+
+namespace dbaui
+{
+ class OQueryTextView final : public InterimItemWindow
+ {
+ friend class OQueryViewSwitch;
+
+ OQueryController& m_rController;
+ std::unique_ptr<SQLEditView> m_xSQL;
+ std::unique_ptr<weld::CustomWeld> m_xSQLEd;
+
+ Timer m_timerUndoActionCreation;
+ OUString m_strOrigText; // is restored on undo
+ Timer m_timerInvalidate;
+ bool m_bStopTimer;
+
+ DECL_LINK(OnUndoActionTimer, Timer*, void);
+ DECL_LINK(OnInvalidateTimer, Timer*, void);
+ DECL_LINK(ModifyHdl, LinkParamNone*, void);
+
+ public:
+ OQueryTextView(OQueryContainerWindow* pParent, OQueryController& rController);
+ virtual ~OQueryTextView() override;
+ virtual void dispose() override;
+
+ void SetSQLText(const OUString& rNewText);
+ OUString GetSQLText() const;
+
+ virtual void GetFocus() override;
+
+ bool isCutAllowed() const;
+ void copy();
+ void cut();
+ void paste();
+ // clears the whole query
+ void clear();
+ // set the statement for representation
+ void setStatement(const OUString& _rsStatement);
+ OUString getStatement() const;
+
+ void stopTimer();
+ void startTimer();
+ };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/QueryViewSwitch.hxx b/dbaccess/source/ui/inc/QueryViewSwitch.hxx
new file mode 100644
index 000000000..0f17d40bd
--- /dev/null
+++ b/dbaccess/source/ui/inc/QueryViewSwitch.hxx
@@ -0,0 +1,94 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <tools/gen.hxx>
+#include <vcl/vclptr.hxx>
+
+namespace dbtools
+{
+ class SQLExceptionInfo;
+}
+
+namespace dbaui
+{
+ class OQueryDesignView;
+ class OQueryTextView;
+ class OAddTableDlg;
+ class OQueryContainerWindow;
+ class OQueryController;
+
+ class OQueryViewSwitch final
+ {
+ VclPtr<OQueryDesignView> m_pDesignView;
+ VclPtr<OQueryTextView> m_pTextView;
+ bool m_bAddTableDialogWasVisible; // true if so
+ public:
+ OQueryViewSwitch(OQueryContainerWindow* pParent, OQueryController& _rController,const css::uno::Reference< css::uno::XComponentContext >& );
+ ~OQueryViewSwitch();
+
+ bool isCutAllowed() const;
+ bool isPasteAllowed() const;
+ bool isCopyAllowed() const;
+ void copy();
+ void cut();
+ void paste();
+ // clears the whole query
+ void clear();
+ // check if the statement is correct when not returning false
+ bool checkStatement();
+ // set the statement for representation
+ void setStatement(const OUString& _rsStatement);
+ // returns the current sql statement
+ OUString getStatement();
+ /// late construction
+ void Construct();
+ void initialize();
+ /** show the text or the design view
+ @return
+ <TRUE/> if and only if the view could be successfully, switched, <FALSE/> otherwise
+ (In the latter case, the controller will issue another switchView call to restore the
+ old state)
+ */
+ bool switchView( ::dbtools::SQLExceptionInfo* _pErrorInfo );
+ void forceInitialView();
+ bool isSlotEnabled(sal_Int32 _nSlotId);
+ void setSlotEnabled(sal_Int32 _nSlotId, bool _bEnable);
+ void setNoneVisibleRow(sal_Int32 _nRows);
+ void SaveUIConfig();
+ void reset();
+ void GrabFocus();
+
+ // returns the add table dialog from the design view
+ OAddTableDlg* getAddTableDialog();
+
+ OQueryDesignView* getDesignView() const { return m_pDesignView; }
+ OQueryContainerWindow* getContainer() const;
+
+ void SetPosSizePixel( Point _rPt,Size _rSize);
+ css::uno::Reference< css::uno::XComponentContext > const & getORB() const;
+
+ private:
+ void impl_forceSQLView();
+ bool impl_postViewSwitch( const bool i_bGraphicalDesign, const bool i_bSuccess );
+ };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/RTableConnectionData.hxx b/dbaccess/source/ui/inc/RTableConnectionData.hxx
new file mode 100644
index 000000000..0dd40e2fa
--- /dev/null
+++ b/dbaccess/source/ui/inc/RTableConnectionData.hxx
@@ -0,0 +1,79 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "TableConnectionData.hxx"
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include "QEnumTypes.hxx"
+
+namespace dbaui
+{
+ enum class Cardinality {
+ Undefined, OneMany, ManyOne, OneOne
+ };
+
+ class OConnectionLineData;
+ class ORelationTableConnectionData final : public OTableConnectionData
+ {
+ friend bool operator==(const ORelationTableConnectionData& lhs, const ORelationTableConnectionData& rhs);
+
+ ::osl::Mutex m_aMutex;
+
+ // @see com.sun.star.sdbc.KeyRule
+ sal_Int32 m_nUpdateRules;
+ sal_Int32 m_nDeleteRules;
+ Cardinality m_nCardinality;
+
+ bool checkPrimaryKey(const css::uno::Reference< css::beans::XPropertySet>& i_xTable, EConnectionSide _eEConnectionSide) const;
+ bool IsSourcePrimKey() const { return checkPrimaryKey(getReferencingTable()->getTable(),JTCS_FROM); }
+ bool IsDestPrimKey() const { return checkPrimaryKey(getReferencedTable()->getTable(),JTCS_TO); }
+
+ ORelationTableConnectionData& operator=( const ORelationTableConnectionData& rConnData );
+ public:
+ ORelationTableConnectionData();
+ ORelationTableConnectionData( const ORelationTableConnectionData& rConnData );
+ ORelationTableConnectionData( const TTableWindowData::value_type& _pReferencingTable,
+ const TTableWindowData::value_type& _pReferencedTable,
+ const OUString& rConnName = OUString() );
+ virtual ~ORelationTableConnectionData() override;
+
+ virtual void CopyFrom(const OTableConnectionData& rSource) override;
+ virtual std::shared_ptr<OTableConnectionData> NewInstance() const override { return std::make_shared<ORelationTableConnectionData>(); }
+
+ /** Update create a new relation
+
+ @return true if successful
+ */
+ virtual bool Update() override;
+
+ void SetCardinality();
+ void SetUpdateRules( sal_Int32 nAttr ){ m_nUpdateRules = nAttr; }
+ void SetDeleteRules( sal_Int32 nAttr ){ m_nDeleteRules = nAttr; }
+
+ sal_Int32 GetUpdateRules() const { return m_nUpdateRules; }
+ sal_Int32 GetDeleteRules() const { return m_nDeleteRules; }
+ Cardinality GetCardinality() const { return m_nCardinality; }
+
+ void IsConnectionPossible();
+ void ChangeOrientation();
+ void DropRelation();
+ };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/RelControliFace.hxx b/dbaccess/source/ui/inc/RelControliFace.hxx
new file mode 100644
index 000000000..65ef79db0
--- /dev/null
+++ b/dbaccess/source/ui/inc/RelControliFace.hxx
@@ -0,0 +1,40 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+namespace dbaui
+{
+ class IRelationControlInterface
+ {
+ public:
+ virtual ~IRelationControlInterface(){}
+
+ /** setValid set the valid inside, can be used for OK buttons
+ @param _bValid true when the using control allows an update
+ */
+ virtual void setValid(bool _bValid) = 0;
+
+ /** notifyConnectionChange is callback which is called when the table selection has changed and a new connection exists
+ @param _pConnectionData the connection which exists between the new tables
+ */
+ virtual void notifyConnectionChange() = 0;
+ };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/RelationControl.hxx b/dbaccess/source/ui/inc/RelationControl.hxx
new file mode 100644
index 000000000..5d4edee2a
--- /dev/null
+++ b/dbaccess/source/ui/inc/RelationControl.hxx
@@ -0,0 +1,91 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <vcl/weld.hxx>
+#include "JoinTableView.hxx"
+
+namespace dbaui
+{
+ class OTableListBoxControl;
+ class IRelationControlInterface;
+ class ORelationControl;
+
+ class OTableListBoxControl final
+ {
+ std::unique_ptr<weld::ComboBox> m_xLeftTable;
+ std::unique_ptr<weld::ComboBox> m_xRightTable;
+ std::unique_ptr<weld::Container> m_xTable;
+ css::uno::Reference<css::awt::XWindow> m_xTableCtrlParent;
+ VclPtr<ORelationControl> m_xRC_Tables;
+
+ const OJoinTableView::OTableWindowMap* m_pTableMap;
+ IRelationControlInterface* m_pParentDialog;
+ OUString m_strCurrentLeft;
+ OUString m_strCurrentRight;
+ DECL_LINK( OnTableChanged, weld::ComboBox&, void );
+ public:
+ OTableListBoxControl(weld::Builder* _pParent,
+ const OJoinTableView::OTableWindowMap* _pTableMap,
+ IRelationControlInterface* _pParentDialog);
+ ~OTableListBoxControl();
+
+ /** fillListBoxes fills the list boxes with the table windows
+ */
+ void fillListBoxes();
+
+ /** fillAndDisable fill the listboxes only with one entry and then disable them
+ @param _pConnectionData
+ contains the data which should be filled into the listboxes
+ */
+ void fillAndDisable(const TTableConnectionData::value_type& _pConnectionData);
+
+ /** enables the relation control
+ *
+ * \param _bEnable when sal_True enables it, otherwise disable it.
+ */
+ void enableRelation(bool _bEnable);
+
+ /** NotifyCellChange notifies the browse control that the connection data has changed
+ */
+ void NotifyCellChange();
+
+ /** Init is a call through to the control inside this one
+ @param _pConnData
+ the connection data which is used to init the control
+ */
+ void Init(const TTableConnectionData::value_type& _pConnData);
+ void lateUIInit();
+ void lateInit();
+
+ void Disable();
+ void Invalidate();
+
+ void SaveModified();
+
+ TTableWindowData::value_type const & getReferencingTable() const;
+
+ /** getContainer returns the container interface
+ @return the interface of the container
+ */
+ IRelationControlInterface* getContainer() const { return m_pParentDialog; }
+ };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/RelationController.hxx b/dbaccess/source/ui/inc/RelationController.hxx
new file mode 100644
index 000000000..a457f38b8
--- /dev/null
+++ b/dbaccess/source/ui/inc/RelationController.hxx
@@ -0,0 +1,79 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <memory>
+#include <string_view>
+
+#include "JoinController.hxx"
+
+namespace weld
+{
+ class WaitObject;
+}
+
+namespace dbaui
+{
+ class ORelationController : public OJoinController
+ {
+ css::uno::Reference< css::container::XNameAccess > m_xTables;
+ std::unique_ptr<weld::WaitObject> m_xWaitObject;
+ sal_uLong m_nThreadEvent;
+ bool m_bRelationsPossible;
+ protected:
+ // all the features which should be handled by this class
+ virtual void describeSupportedFeatures() override;
+ // state of a feature. 'feature' may be the handle of a css::util::URL somebody requested a dispatch interface for OR a toolbar slot.
+ virtual FeatureState GetState(sal_uInt16 nId) const override;
+ // execute a feature
+ virtual void Execute(sal_uInt16 nId, const css::uno::Sequence< css::beans::PropertyValue>& aArgs) override;
+
+ void loadData();
+ TTableWindowData::value_type existsTable(std::u16string_view _rComposedTableName) const;
+
+ // load the window positions out of the datasource
+ void loadLayoutInformation();
+ public:
+ ORelationController(const css::uno::Reference< css::uno::XComponentContext >& _rM);
+
+ virtual ~ORelationController() override;
+
+ void mergeData(const TTableConnectionData& _aConnectionData);
+
+ virtual bool Construct(vcl::Window* pParent) override;
+
+ // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual css::uno::Sequence< OUString> SAL_CALL getSupportedServiceNames() override;
+
+ // OJoinController overridables
+ virtual bool allowViews() const override;
+ virtual bool allowQueries() const override;
+
+ private:
+ // ask the user if the design should be saved when it is modified
+ virtual short saveModified() override;
+ virtual void reset() override;
+ virtual void impl_initialize() override;
+ virtual OUString getPrivateTitle( ) const override;
+ DECL_LINK( OnThreadFinished, void*, void );
+ };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/RelationDesignView.hxx b/dbaccess/source/ui/inc/RelationDesignView.hxx
new file mode 100644
index 000000000..2fba88be0
--- /dev/null
+++ b/dbaccess/source/ui/inc/RelationDesignView.hxx
@@ -0,0 +1,45 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include "JoinDesignView.hxx"
+
+namespace dbaui
+{
+ class ORelationController;
+
+ class ORelationDesignView : public OJoinDesignView
+ {
+ public:
+ ORelationDesignView(vcl::Window* pParent, ORelationController& _rController,const css::uno::Reference< css::uno::XComponentContext >& );
+
+ // set the statement for representation
+ /// late construction
+ virtual void Construct() override;
+ virtual void initialize() override;
+
+
+ virtual bool PreNotify( NotifyEvent& rNEvt ) override;
+ virtual void GetFocus() override;
+ };
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/RelationDlg.hxx b/dbaccess/source/ui/inc/RelationDlg.hxx
new file mode 100644
index 000000000..c4285f04a
--- /dev/null
+++ b/dbaccess/source/ui/inc/RelationDlg.hxx
@@ -0,0 +1,74 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <memory>
+#include <vcl/weld.hxx>
+#include "JoinTableView.hxx"
+#include "RelControliFace.hxx"
+#include "RelationControl.hxx"
+
+namespace dbaui
+{
+ class OJoinTableView;
+ class ORelationDialog final : public weld::GenericDialogController
+ , public IRelationControlInterface
+ {
+ VclPtr<OJoinTableView> m_pParent;
+ TTableConnectionData::value_type m_pConnData;
+ TTableConnectionData::value_type m_pOrigConnData;
+ bool m_bTriedOneUpdate;
+
+ std::unique_ptr<weld::RadioButton> m_xRB_NoCascUpd;
+ std::unique_ptr<weld::RadioButton> m_xRB_CascUpd;
+ std::unique_ptr<weld::RadioButton> m_xRB_CascUpdNull;
+ std::unique_ptr<weld::RadioButton> m_xRB_CascUpdDefault;
+ std::unique_ptr<weld::RadioButton> m_xRB_NoCascDel;
+ std::unique_ptr<weld::RadioButton> m_xRB_CascDel;
+ std::unique_ptr<weld::RadioButton> m_xRB_CascDelNull;
+ std::unique_ptr<weld::RadioButton> m_xRB_CascDelDefault;
+ std::unique_ptr<weld::Button> m_xPB_OK;
+
+ std::unique_ptr<OTableListBoxControl> m_xTableControl;
+
+ public:
+ ORelationDialog(OJoinTableView* pParent,
+ const TTableConnectionData::value_type& pConnectionData,
+ bool bAllowTableSelect = false );
+ virtual ~ORelationDialog() override;
+
+ virtual short run() override;
+
+ /** setValid set the valid inside, can be used for OK buttons
+ @param _bValid true when the using control allows an update
+ */
+ virtual void setValid(bool _bValid) override;
+
+ /** notifyConnectionChange is callback which is called when the table selection has changed and a new connection exists
+ @param _pConnectionData the connection which exists between the new tables
+ */
+ virtual void notifyConnectionChange() override;
+ private:
+ void Init(const TTableConnectionData::value_type& _pConnectionData);
+
+ DECL_LINK(OKClickHdl, weld::Button&, void);
+ };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/RelationTableView.hxx b/dbaccess/source/ui/inc/RelationTableView.hxx
new file mode 100644
index 000000000..6c178a3de
--- /dev/null
+++ b/dbaccess/source/ui/inc/RelationTableView.hxx
@@ -0,0 +1,74 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "JoinTableView.hxx"
+#include <comphelper/containermultiplexer.hxx>
+#include <cppuhelper/basemutex.hxx>
+#include <rtl/ref.hxx>
+
+namespace dbaui
+{
+ class ORelationDesignView;
+
+ class ORelationTableView : public ::cppu::BaseMutex,
+ public OJoinTableView,
+ public ::comphelper::OContainerListener
+ {
+ VclPtr<OTableConnection> m_pExistingConnection; ///< is set when a connection was dragged on an existing connection
+ TTableConnectionData::value_type m_pCurrentlyTabConnData; ///< set when we creating a connection with more than one keycolumn
+ ::rtl::Reference< comphelper::OContainerListenerAdapter> m_pContainerListener;
+ bool m_bInRemove;
+
+ virtual void ConnDoubleClicked(VclPtr<OTableConnection>& rConnection) override;
+ virtual void AddTabWin(const OUString& _rComposedName, const OUString& rWinName, bool bNewTable = false) override;
+
+ virtual VclPtr<OTableWindow> createWindow(const TTableWindowData::value_type& _pData) override;
+
+ /** determines whether the classes Init method should accept a query
+ name, or only table names */
+ virtual bool allowQueries() const override;
+
+ // OContainerListener
+ virtual void _elementInserted( const css::container::ContainerEvent& _rEvent ) override;
+ virtual void _elementRemoved( const css::container::ContainerEvent& _rEvent ) override;
+ virtual void _elementReplaced( const css::container::ContainerEvent& _rEvent ) override;
+
+ public:
+ ORelationTableView( vcl::Window* pParent, ORelationDesignView* pView );
+ virtual ~ORelationTableView() override;
+ virtual void dispose() override;
+
+ virtual void RemoveTabWin( OTableWindow* pTabWin ) override;
+ virtual void AddConnection(const OJoinExchangeData& jxdSource, const OJoinExchangeData& jxdDest) override;
+ virtual bool RemoveConnection(VclPtr<OTableConnection>& rConn, bool _bDelete) override;
+
+ virtual void ReSync() override;
+
+ /// Creates a dialogue for a completely new relation.
+ void AddNewRelation();
+
+ /// used by AddTabDlg to check if tables can be added
+ virtual bool IsAddAllowed() override;
+
+ virtual void lookForUiActivities() override;
+ };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/RtfReader.hxx b/dbaccess/source/ui/inc/RtfReader.hxx
new file mode 100644
index 000000000..58f6aa26b
--- /dev/null
+++ b/dbaccess/source/ui/inc/RtfReader.hxx
@@ -0,0 +1,59 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <vector>
+#include <svtools/parrtf.hxx>
+#include "DExport.hxx"
+
+class SvStream;
+
+namespace dbaui
+{
+ class ORTFReader final : public SvRTFParser , public ODatabaseExport
+ {
+ std::vector<Color> m_vecColor;
+
+ bool CreateTable(int nToken);
+ virtual void NextToken( int nToken ) override; // base class
+ virtual TypeSelectionPageFactory
+ getTypeSelectionPageFactory() override;
+
+ virtual ~ORTFReader() override;
+
+ public:
+ ORTFReader( SvStream& rIn,
+ const SharedConnection& _rxConnection,
+ const css::uno::Reference< css::util::XNumberFormatter >& _rxNumberF,
+ const css::uno::Reference< css::uno::XComponentContext >& _rxContext);
+ // required for automatic type recognition
+ ORTFReader( SvStream& rIn,
+ sal_Int32 nRows,
+ TPositions&& _rColumnPositions,
+ const css::uno::Reference< css::util::XNumberFormatter >& _rxNumberF,
+ const css::uno::Reference< css::uno::XComponentContext >& _rxContext,
+ const TColumnVector* rList,
+ const OTypeInfoMap* _pInfoMap,
+ bool _bAutoIncrementEnabled);
+
+ virtual SvParserState CallParser() override;// base class
+ };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/SqlNameEdit.hxx b/dbaccess/source/ui/inc/SqlNameEdit.hxx
new file mode 100644
index 000000000..257b18ebb
--- /dev/null
+++ b/dbaccess/source/ui/inc/SqlNameEdit.hxx
@@ -0,0 +1,121 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <svtools/editbrowsebox.hxx>
+#include <vcl/weld.hxx>
+
+namespace dbaui
+{
+ class OSQLNameChecker
+ {
+ OUString m_sAllowedChars;
+ bool m_bCheck; // true when we should check for invalid chars
+ public:
+ OSQLNameChecker(const OUString& _rAllowedChars)
+ :m_sAllowedChars(_rAllowedChars)
+ ,m_bCheck(true)
+ {
+ }
+
+ void setAllowedChars(const OUString& _rAllowedChars)
+ {
+ m_sAllowedChars = _rAllowedChars;
+ }
+ void setCheck(bool _bCheck)
+ {
+ m_bCheck = _bCheck;
+ }
+ bool checkString(const OUString& _sToCheck,OUString& _rsCorrected);
+ };
+
+ class OSQLNameEditControl : public svt::EditControl
+ , public OSQLNameChecker
+ {
+ public:
+ OSQLNameEditControl(BrowserDataWin* pParent, const OUString& rAllowedChars)
+ : svt::EditControl(pParent)
+ , OSQLNameChecker(rAllowedChars)
+ {
+ m_xWidget->connect_changed(LINK(this, OSQLNameEditControl, ModifyHdl));
+ }
+
+ virtual void connect_changed(const Link<weld::Entry&, void>& rLink) override
+ {
+ m_ChainChangedHdl = rLink;
+ }
+
+ private:
+ DECL_LINK(ModifyHdl, weld::Entry&, void);
+
+ Link<weld::Entry&,void> m_ChainChangedHdl;
+ };
+
+ class OWidgetBase
+ {
+ private:
+ weld::Widget* m_pWidget;
+ public:
+ OWidgetBase(weld::Widget *pWidget)
+ : m_pWidget(pWidget)
+ {
+ }
+
+ void hide() { m_pWidget->hide(); }
+ void show() { m_pWidget->show(); }
+ void set_sensitive(bool bSensitive) { m_pWidget->set_sensitive(bSensitive); }
+
+ weld::Widget* GetWidget() { return m_pWidget; }
+
+ virtual bool get_value_changed_from_saved() const = 0;
+ virtual void save_value() = 0;
+
+ virtual ~OWidgetBase() {}
+ };
+
+ class OSQLNameEntry : public OWidgetBase
+ , public OSQLNameChecker
+ {
+ private:
+ std::unique_ptr<weld::Entry> m_xEntry;
+
+ DECL_LINK(ModifyHdl, weld::Entry&, void);
+
+ public:
+ OSQLNameEntry(std::unique_ptr<weld::Entry> xEntry, const OUString& _rAllowedChars = OUString())
+ : OWidgetBase(xEntry.get())
+ , OSQLNameChecker(_rAllowedChars)
+ , m_xEntry(std::move(xEntry))
+ {
+ m_xEntry->connect_changed(LINK(this, OSQLNameEntry, ModifyHdl));
+ }
+
+ OUString get_text() const { return m_xEntry->get_text(); }
+ void set_text(const OUString& rText) { m_xEntry->set_text(rText); }
+ void set_max_length(int nLen) { m_xEntry->set_max_length(nLen); }
+ virtual void save_value() override { m_xEntry->save_value(); }
+ virtual bool get_value_changed_from_saved() const override
+ {
+ return m_xEntry->get_value_changed_from_saved();
+ }
+ };
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/TableConnection.hxx b/dbaccess/source/ui/inc/TableConnection.hxx
new file mode 100644
index 000000000..3c6ce0fdf
--- /dev/null
+++ b/dbaccess/source/ui/inc/TableConnection.hxx
@@ -0,0 +1,98 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <vector>
+#include <vcl/window.hxx>
+#include <com/sun/star/uno/Reference.h>
+#include "TableConnectionData.hxx"
+
+class Point;
+namespace tools { class Rectangle; }
+
+namespace dbaui
+{
+ class OTableConnectionData;
+ class OTableWindow;
+ class OJoinTableView;
+ class OConnectionLine;
+
+ class OTableConnection : public vcl::Window
+ {
+ std::vector<std::unique_ptr<OConnectionLine>> m_vConnLine;
+ TTableConnectionData::value_type
+ m_pData;
+ VclPtr<OJoinTableView> m_pParent;
+
+ bool m_bSelected;
+
+ void Init();
+ /** loops through the vector and deletes all lines */
+ void clearLineData();
+
+ public:
+ OTableConnection( OJoinTableView* pContainer, const TTableConnectionData::value_type& pTabConnData );
+ OTableConnection( const OTableConnection& rConn );
+ /** destructor
+
+ @attention Normally a pointer to OTableConnectionData is given but
+ here, however, one has to create an instance (with
+ OTableConnectionDate::NewInstance) which is never deleted
+ (same like in other cases). Thus, the caller is
+ responsible to check and save the data for deleting it
+ eventually.
+ */
+ virtual ~OTableConnection() override;
+ virtual void dispose() override;
+
+ OTableConnection& operator=( const OTableConnection& rConn );
+
+ void Select();
+ void Deselect();
+ bool IsSelected() const { return m_bSelected; }
+ bool CheckHit( const Point& rMousePos ) const;
+ void InvalidateConnection();
+ void UpdateLineList();
+
+ OTableWindow* GetSourceWin() const;
+ OTableWindow* GetDestWin() const;
+
+ void RecalcLines();
+ /** isTableConnection
+
+ @param _pTable the table where we should check if we belong to it
+ @return true when the source or the destination window are equal
+ */
+ bool isTableConnection(const OTableWindow* _pTable)
+ {
+ return (_pTable == GetSourceWin() || _pTable == GetDestWin());
+ }
+
+ tools::Rectangle GetBoundingRect() const;
+
+ const TTableConnectionData::value_type& GetData() const { return m_pData; }
+ const std::vector<std::unique_ptr<OConnectionLine>>& GetConnLineList() const { return m_vConnLine; }
+ OJoinTableView* GetParent() const { return m_pParent; }
+ virtual void Draw(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect);
+ using Window::Draw;
+ virtual css::uno::Reference< css::accessibility::XAccessible > CreateAccessible() override;
+ };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/TableConnectionData.hxx b/dbaccess/source/ui/inc/TableConnectionData.hxx
new file mode 100644
index 000000000..38de22894
--- /dev/null
+++ b/dbaccess/source/ui/inc/TableConnectionData.hxx
@@ -0,0 +1,101 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "ConnectionLineData.hxx"
+#include "TableWindowData.hxx"
+#include <vector>
+#include <memory>
+
+namespace dbaui
+{
+ //===========================================//
+ // ConnData ---------->* ConnLineData //
+ // ^1 ^1 //
+ // | | //
+ // Conn ---------->* ConnLine //
+ //===========================================//
+
+ /** Contains all connection data which exists between two windows */
+ class OTableConnectionData
+ {
+ protected:
+ TTableWindowData::value_type m_pReferencingTable;
+ TTableWindowData::value_type m_pReferencedTable;
+ OUString m_aConnName;
+
+ OConnectionLineDataVec m_vConnLineData;
+
+ void Init();
+
+ OTableConnectionData& operator=( const OTableConnectionData& rConnData );
+ public:
+ OTableConnectionData();
+ OTableConnectionData( const TTableWindowData::value_type& _pReferencingTable,
+ const TTableWindowData::value_type& _pReferencedTable );
+ OTableConnectionData( const OTableConnectionData& rConnData );
+ virtual ~OTableConnectionData();
+
+ /// initialise from a source (more comfortable than a virtual assignment operator)
+ virtual void CopyFrom(const OTableConnectionData& rSource);
+
+ /** deliver a new instance of my own type
+
+ derived classes have to deliver an instance of their own type
+
+ @note does NOT have to be initialised
+ */
+ virtual std::shared_ptr<OTableConnectionData> NewInstance() const;
+
+ void SetConnLine( sal_uInt16 nIndex, const OUString& rSourceFieldName, const OUString& rDestFieldName );
+ bool AppendConnLine( const OUString& rSourceFieldName, const OUString& rDestFieldName );
+ /** Deletes list of ConnLines
+ */
+ void ResetConnLines();
+
+ /** moves the empty lines to the back
+ removes duplicated empty lines
+
+ caller is responsible for repainting them
+
+ @return index of first changed line, or one-past-the-end if no change
+ */
+ OConnectionLineDataVec::size_type normalizeLines();
+
+ const OConnectionLineDataVec& GetConnLineDataList() const { return m_vConnLineData; }
+ OConnectionLineDataVec& GetConnLineDataList() { return m_vConnLineData; }
+
+ const TTableWindowData::value_type& getReferencingTable() const { return m_pReferencingTable; }
+ const TTableWindowData::value_type& getReferencedTable() const { return m_pReferencedTable; }
+
+ void setReferencingTable(const TTableWindowData::value_type& _pTable) { m_pReferencingTable = _pTable; }
+ void setReferencedTable(const TTableWindowData::value_type& _pTable) { m_pReferencedTable = _pTable; }
+
+ /** Update create a new connection
+
+ @return true if successful
+ */
+ virtual bool Update(){ return true; }
+ };
+
+ typedef std::vector< std::shared_ptr<OTableConnectionData> > TTableConnectionData;
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/TableController.hxx b/dbaccess/source/ui/inc/TableController.hxx
new file mode 100644
index 000000000..ce2017b58
--- /dev/null
+++ b/dbaccess/source/ui/inc/TableController.hxx
@@ -0,0 +1,129 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "singledoccontroller.hxx"
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include "TypeInfo.hxx"
+#include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
+#include <com/sun/star/sdbcx/XKeysSupplier.hpp>
+#include <com/sun/star/container/XNameAccess.hpp>
+
+namespace dbaui
+{
+ class OTableRow;
+ typedef OSingleDocumentController OTableController_BASE;
+ class OTableController final : public OTableController_BASE
+ {
+ private:
+ std::vector< std::shared_ptr<OTableRow> > m_vRowList;
+ OTypeInfoMap m_aTypeInfo;
+ std::vector<OTypeInfoMap::iterator> m_aTypeInfoIndex;
+
+ css::uno::Reference< css::beans::XPropertySet > m_xTable;
+
+ OUString m_sName; // table for update data
+ OUString m_sAutoIncrementValue; // the autoincrement value set in the datasource
+ OUString m_sTypeNames; // these type names are the ones out of the resource file
+ TOTypeInfoSP m_pTypeInfo; // fall back when type is unknown because database driver has a failure
+
+ bool m_bAllowAutoIncrementValue; // no : 1 NO BIT , is true when the datasource has an AutoIncrementValue property in their info property
+ bool m_bNew : 1; // is true when we create a new table
+
+
+ void reSyncRows();
+ void assignTable(); // set the table if a name is given
+ void loadData();
+ /// @throws css::sdbc::SQLException
+ /// @throws css::uno::RuntimeException
+ bool checkColumns(bool _bNew); // check if we have double column names
+ void appendColumns(css::uno::Reference< css::sdbcx::XColumnsSupplier> const & _rxColSup, bool _bNew, bool _bKeyColumns = false);
+ void appendPrimaryKey(css::uno::Reference< css::sdbcx::XKeysSupplier> const & _rxSup, bool _bNew);
+ void alterColumns();
+ void dropPrimaryKey();
+ css::uno::Reference< css::container::XNameAccess> getKeyColumns() const;
+ OUString createUniqueName(const OUString& _rName);
+
+ void reload();
+
+ // all the features which should be handled by this class
+ virtual void describeSupportedFeatures() override;
+ // state of a feature. 'feature' may be the handle of a css::util::URL somebody requested a dispatch interface for OR a toolbar slot.
+ virtual FeatureState GetState(sal_uInt16 nId) const override;
+ // execute a feature
+ virtual void Execute(sal_uInt16 nId, const css::uno::Sequence< css::beans::PropertyValue>& aArgs) override;
+
+ virtual void losingConnection( ) override;
+
+ virtual OUString getPrivateTitle( ) const override;
+
+ void doEditIndexes();
+ bool doSaveDoc(bool _bSaveAs);
+
+ virtual ~OTableController() override;
+ public:
+ OTableController(const css::uno::Reference< css::uno::XComponentContext >& _rM);
+
+ const css::uno::Reference< css::beans::XPropertySet >& getTable() const { return m_xTable;}
+
+ bool isAddAllowed() const;
+ bool isDropAllowed() const;
+ bool isAlterAllowed() const;
+ bool isAutoIncrementPrimaryKey() const;
+
+ bool isAutoIncrementValueEnabled() const { return m_bAllowAutoIncrementValue; }
+ const OUString& getAutoIncrementValue() const { return m_sAutoIncrementValue; }
+
+ virtual void impl_onModifyChanged() override;
+
+ std::vector< std::shared_ptr<OTableRow> >& getRows() { return m_vRowList; }
+
+ /// returns the position of the first empty row
+ sal_Int32 getFirstEmptyRowPosition();
+
+ const OTypeInfoMap& getTypeInfo() const { return m_aTypeInfo; }
+
+ TOTypeInfoSP const & getTypeInfo(sal_Int32 _nPos) const { return m_aTypeInfoIndex[_nPos]->second; }
+ TOTypeInfoSP getTypeInfoByType(sal_Int32 _nDataType) const;
+
+ const TOTypeInfoSP& getTypeInfoFallBack() const { return m_pTypeInfo; }
+
+ virtual bool Construct(vcl::Window* pParent) override;
+ // XEventListener
+ virtual void SAL_CALL disposing( const css::lang::EventObject& Source ) override;
+
+ // css::frame::XController
+ virtual sal_Bool SAL_CALL suspend(sal_Bool bSuspend) override;
+
+ // css::lang::XComponent
+ virtual void SAL_CALL disposing() override;
+
+ // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual css::uno::Sequence< OUString> SAL_CALL getSupportedServiceNames() override;
+
+ private:
+ void startTableListening();
+ void stopTableListening();
+ virtual void impl_initialize() override;
+ };
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/TableCopyHelper.hxx b/dbaccess/source/ui/inc/TableCopyHelper.hxx
new file mode 100644
index 000000000..b543dade8
--- /dev/null
+++ b/dbaccess/source/ui/inc/TableCopyHelper.hxx
@@ -0,0 +1,188 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "AppElementType.hxx"
+#include "commontypes.hxx"
+#include <svx/dataaccessdescriptor.hxx>
+#include <sot/storage.hxx>
+#include <vcl/transfer.hxx>
+#include <vcl/weld.hxx>
+#include <com/sun/star/sdbc/XConnection.hpp>
+#include <com/sun/star/sdbc/XResultSet.hpp>
+
+namespace dbaui
+{
+ class OGenericUnoController;
+ /// Functor object for class DataFlavorExVector::value_type returntype is bool
+ struct TAppSupportedSotFunctor
+ {
+ ElementType eEntryType;
+ TAppSupportedSotFunctor(const ElementType& _eEntryType)
+ : eEntryType(_eEntryType)
+ {
+ }
+
+ bool operator()(const DataFlavorExVector::value_type& _aType)
+ {
+ switch (_aType.mnSotId)
+ {
+ case SotClipboardFormatId::RTF: // RTF data descriptions
+ case SotClipboardFormatId::HTML: // HTML data descriptions
+ case SotClipboardFormatId::DBACCESS_TABLE: // table descriptor
+ return (E_TABLE == eEntryType);
+ case SotClipboardFormatId::DBACCESS_QUERY: // query descriptor
+ case SotClipboardFormatId::DBACCESS_COMMAND: // SQL command
+ return E_QUERY == eEntryType;
+ default: break;
+ }
+ return false;
+ }
+ };
+
+ class OTableCopyHelper
+ {
+ private:
+ OGenericUnoController* m_pController;
+ OUString m_sTableNameForAppend;
+
+ public:
+ // is needed to describe the drop target
+ struct DropDescriptor
+ {
+ svx::ODataAccessDescriptor aDroppedData;
+
+ //for transfor the tablename
+ OUString sDefaultTableName;
+
+ OUString aUrl;
+ tools::SvRef<SotTempStream> aHtmlRtfStorage;
+ ElementType nType;
+ std::unique_ptr<weld::TreeIter> xDroppedAt;
+ sal_Int8 nAction;
+ bool bHtml;
+ bool bError;
+
+ DropDescriptor()
+ : nType(E_TABLE)
+ , nAction(DND_ACTION_NONE)
+ , bHtml(false)
+ , bError(false)
+ { }
+ };
+
+ OTableCopyHelper(OGenericUnoController* _pController);
+
+ /** pastes a table into the data source
+ @param _rPasteData
+ The data helper.
+ @param _sDestDataSourceName
+ The name of the dest data source.
+ */
+ void pasteTable( const TransferableDataHelper& _rTransData
+ ,std::u16string_view _sDestDataSourceName
+ ,const SharedConnection& _xConnection);
+
+ /** pastes a table into the data source
+ @param _nFormatId
+ The format which should be copied.
+ @param _rPasteData
+ The data helper.
+ @param _sDestDataSourceName
+ The name of the dest data source.
+ */
+ void pasteTable( SotClipboardFormatId _nFormatId
+ ,const TransferableDataHelper& _rTransData
+ ,std::u16string_view _sDestDataSourceName
+ ,const SharedConnection& _xConnection);
+
+ /** copies a table which was constructed by tags like HTML or RTF
+ @param _rDesc
+ The Drop descriptor
+ @param _bCheck
+ If set to <TRUE/> than the controller checks only if a copy is possible.
+ @param _xConnection
+ The connection
+ */
+ bool copyTagTable( DropDescriptor const & _rDesc,
+ bool _bCheck,
+ const SharedConnection& _xConnection);
+
+ /** copies a table which was constructed by tags like HTML or RTF
+ @param _rDesc
+ The Drop descriptor
+ @param _bCheck
+ If set to <TRUE/> than the controller checks only if a copy is possible.
+ @param _xConnection
+ The connection
+ */
+ void asyncCopyTagTable( DropDescriptor& _rDesc
+ ,std::u16string_view _sDestDataSourceName
+ ,const SharedConnection& _xConnection);
+
+ /** copies a table which was constructed by tags like HTML or RTF
+ @param _aDroppedData
+ The dropped data
+ @param _rDesc
+ IN/OUT parameter
+ @param _xConnection
+ The connection
+ */
+ bool copyTagTable(const TransferableDataHelper& _aDroppedData,
+ DropDescriptor& _rAsyncDrop,
+ const SharedConnection& _xConnection);
+
+ /// returns <TRUE/> if the clipboard supports a table format, otherwise <FALSE/>.
+ static bool isTableFormat(const TransferableDataHelper& _rClipboard);
+
+ void SetTableNameForAppend( const OUString& _rDefaultTableName ) { m_sTableNameForAppend = _rDefaultTableName; }
+ void ResetTableNameForAppend() { SetTableNameForAppend( OUString() ); }
+ const OUString& GetTableNameForAppend() const { return m_sTableNameForAppend ;}
+
+ private:
+ /** pastes a table into the data source
+ @param _rPasteData
+ The data descriptor.
+ @param _sDestDataSourceName
+ The name of the dest data source.
+ */
+ void pasteTable(
+ const svx::ODataAccessDescriptor& _rPasteData,
+ std::u16string_view _sDestDataSourceName,
+ const SharedConnection& _xDestConnection
+ );
+
+ /** insert a table into the data source. The source can either be a table or a query
+ */
+ void insertTable(
+ std::u16string_view i_rSourceDataSource,
+ const css::uno::Reference< css::sdbc::XConnection>& i_rSourceConnection,
+ const OUString& i_rCommand,
+ const sal_Int32 i_nCommandType,
+ const css::uno::Reference< css::sdbc::XResultSet >& i_rSourceRows,
+ const css::uno::Sequence< css::uno::Any >& i_rSelection,
+ const bool i_bBookmarkSelection,
+ std::u16string_view i_rDestDataSource,
+ const css::uno::Reference< css::sdbc::XConnection>& i_rDestConnection
+ );
+
+ };
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/TableDesignControl.hxx b/dbaccess/source/ui/inc/TableDesignControl.hxx
new file mode 100644
index 000000000..89debc9e1
--- /dev/null
+++ b/dbaccess/source/ui/inc/TableDesignControl.hxx
@@ -0,0 +1,78 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <svtools/editbrowsebox.hxx>
+
+#include "IClipBoardTest.hxx"
+#include "TypeInfo.hxx"
+
+namespace dbaui
+{
+ class OTableDesignView;
+
+ class OTableRowView : public ::svt::EditBrowseBox, public IClipboardTest
+ {
+ friend class OTableDesignUndoAct;
+
+ protected:
+ tools::Long m_nDataPos; ///< currently needed row
+ tools::Long m_nCurrentPos; ///< current position of selected column
+
+ private:
+ sal_uInt16 m_nCurUndoActId;
+
+ public:
+ OTableRowView(vcl::Window* pParent);
+
+ virtual void SetCellData( sal_Int32 nRow, sal_uInt16 nColId, const TOTypeInfoSP& _pTypeInfo ) = 0;
+ virtual void SetCellData( sal_Int32 nRow, sal_uInt16 nColId, const css::uno::Any& _rNewData ) = 0;
+ virtual css::uno::Any GetCellData( sal_Int32 nRow, sal_uInt16 nColId ) = 0;
+ virtual void SetControlText( sal_Int32 nRow, sal_uInt16 nColId, const OUString& rText ) = 0;
+
+ virtual OTableDesignView* GetView() const = 0;
+
+ sal_uInt16 GetCurUndoActId() const { return m_nCurUndoActId; }
+
+ // IClipboardTest
+ virtual void cut() override;
+ virtual void copy() override;
+ virtual void paste() override;
+
+ protected:
+ void Paste( sal_Int32 nRow );
+
+ virtual void CopyRows() = 0;
+ virtual void DeleteRows() = 0;
+ virtual void InsertRows( sal_Int32 nRow ) = 0;
+ virtual void InsertNewRows( sal_Int32 nRow ) = 0;
+
+ virtual bool IsPrimaryKeyAllowed() = 0;
+ virtual bool IsInsertNewAllowed( sal_Int32 nRow ) = 0;
+ virtual bool IsDeleteAllowed() = 0;
+
+ virtual RowStatus GetRowStatus(sal_Int32 nRow) const override;
+ virtual void KeyInput(const KeyEvent& rEvt) override;
+ virtual void Command( const CommandEvent& rEvt ) override;
+
+ virtual void Init() override;
+ };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/TableDesignHelpBar.hxx b/dbaccess/source/ui/inc/TableDesignHelpBar.hxx
new file mode 100644
index 000000000..db4023d36
--- /dev/null
+++ b/dbaccess/source/ui/inc/TableDesignHelpBar.hxx
@@ -0,0 +1,59 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <vcl/weld.hxx>
+#include "IClipBoardTest.hxx"
+
+namespace dbaui
+{
+ class OTableDesignHelpBar final : public IClipboardTest
+ {
+ private:
+ std::unique_ptr<weld::TextView> m_xTextWin;
+
+ public:
+ OTableDesignHelpBar(std::unique_ptr<weld::TextView> xTextWin);
+
+ void SetHelpText( const OUString& rText );
+
+ bool HasFocus() const { return m_xTextWin->has_focus(); }
+
+ void connect_focus_in(const Link<weld::Widget&, void>& rLink)
+ {
+ m_xTextWin->connect_focus_in(rLink);
+ }
+
+ void connect_focus_out(const Link<weld::Widget&, void>& rLink)
+ {
+ m_xTextWin->connect_focus_out(rLink);
+ }
+
+ // IClipboardTest
+ virtual bool isCutAllowed() override;
+ virtual bool isCopyAllowed() override;
+ virtual bool isPasteAllowed() override;
+
+ virtual void copy() override;
+ virtual void cut() override;
+ virtual void paste() override;
+ };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/TableDesignView.hxx b/dbaccess/source/ui/inc/TableDesignView.hxx
new file mode 100644
index 000000000..077eb211e
--- /dev/null
+++ b/dbaccess/source/ui/inc/TableDesignView.hxx
@@ -0,0 +1,112 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <dbaccess/dataview.hxx>
+#include <com/sun/star/lang/Locale.hpp>
+#include <vcl/InterimItemWindow.hxx>
+#include <vcl/weld.hxx>
+#include "IClipBoardTest.hxx"
+
+namespace dbaui
+{
+ class OTableController;
+ class OTableDesignView;
+ class OTableFieldDescWin;
+ class OTableEditorCtrl;
+
+ class OTableBorderWindow final : public InterimItemWindow
+ {
+ std::unique_ptr<weld::Paned> m_xHorzSplitter;
+ std::unique_ptr<weld::Container> m_xEditorParent;
+ css::uno::Reference<css::awt::XWindow> m_xEditorParentWin;
+ VclPtr<OTableEditorCtrl> m_xEditorCtrl;
+ std::unique_ptr<weld::Container> m_xFieldDescParent;
+ std::unique_ptr<OTableFieldDescWin> m_xFieldDescWin;
+
+ public:
+ OTableBorderWindow(OTableDesignView* pParent);
+ virtual ~OTableBorderWindow() override;
+ // Window overrides
+ virtual void dispose() override;
+
+ virtual void GetFocus() override;
+ virtual void Layout() override;
+
+ OTableEditorCtrl* GetEditorCtrl() const { return m_xEditorCtrl.get(); }
+ OTableFieldDescWin* GetDescWin() const { return m_xFieldDescWin.get(); }
+ };
+
+ class OTableDesignView : public ODataView
+ , public IClipboardTest
+ {
+ enum ChildFocusState
+ {
+ DESCRIPTION,
+ EDITOR,
+ NONE
+ };
+ private:
+ css::lang::Locale m_aLocale;
+ VclPtr<OTableBorderWindow> m_pWin;
+ OTableController& m_rController;
+ ChildFocusState m_eChildFocus;
+
+ IClipboardTest* getActiveChild() const;
+
+ DECL_LINK( FieldDescFocusIn, weld::Widget&, void );
+ protected:
+
+ // return the Rectangle where I can paint myself
+ virtual void resizeDocumentView(tools::Rectangle& rRect) override;
+
+ public:
+ OTableDesignView( vcl::Window* pParent,
+ const css::uno::Reference< css::uno::XComponentContext >&,
+ OTableController& _rController);
+ virtual ~OTableDesignView() override;
+ virtual void dispose() override;
+
+ // Window overrides
+ virtual bool PreNotify( NotifyEvent& rNEvt ) override;
+ virtual void GetFocus() override;
+
+ OTableEditorCtrl* GetEditorCtrl() const { return m_pWin ? m_pWin->GetEditorCtrl() : nullptr; }
+ OTableFieldDescWin* GetDescWin() const { return m_pWin ? m_pWin->GetDescWin() : nullptr; }
+ OTableController& getController() const { return m_rController; }
+
+ const css::lang::Locale& getLocale() const { return m_aLocale;}
+
+ // IClipboardTest
+ virtual bool isCutAllowed() override;
+ virtual bool isCopyAllowed() override;
+ virtual bool isPasteAllowed() override;
+ virtual void copy() override;
+ virtual void cut() override;
+ virtual void paste() override;
+
+ // set the view readonly or not
+ void setReadOnly(bool _bReadOnly);
+
+ virtual void initialize() override;
+ void reSync(); // resync window data with realdata
+ };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/TableFieldDescription.hxx b/dbaccess/source/ui/inc/TableFieldDescription.hxx
new file mode 100644
index 000000000..d21ad953a
--- /dev/null
+++ b/dbaccess/source/ui/inc/TableFieldDescription.hxx
@@ -0,0 +1,150 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <vector>
+
+#include "QEnumTypes.hxx"
+#include <rtl/ustring.hxx>
+#include <com/sun/star/beans/PropertyValue.hpp>
+#include <rtl/ref.hxx>
+#include <vcl/vclptr.hxx>
+#include <vcl/window.hxx>
+
+#include <salhelper/simplereferenceobject.hxx>
+
+namespace comphelper
+{
+ class NamedValueCollection;
+}
+
+namespace vcl { class Window; }
+
+namespace dbaui
+{
+ class OTableFieldDesc : public ::salhelper::SimpleReferenceObject
+ {
+ private:
+ std::vector< OUString >
+ m_aCriteria;
+
+ OUString m_aTableName;
+ OUString m_aAliasName; ///< table range
+ OUString m_aFieldName; ///< column
+ OUString m_aFieldAlias; ///< column alias
+ OUString m_aFunctionName;///< contains the function name (only if m_eFunctionType != FKT_NONE)
+
+ VclPtr<vcl::Window> m_pTabWindow;
+
+ sal_Int32 m_eDataType;
+ sal_Int32 m_eFunctionType;
+ ETableFieldType m_eFieldType;
+ EOrderDir m_eOrderDir;
+ sal_Int32 m_nIndex;
+ sal_Int32 m_nColWidth;
+ sal_uInt16 m_nColumnId;
+ bool m_bGroupBy;
+ bool m_bVisible;
+
+ // when adding new fields, please take care of IsEmpty!
+
+ public:
+ OTableFieldDesc();
+ OTableFieldDesc(const OUString& rTable, const OUString& rField );
+ OTableFieldDesc(const OTableFieldDesc& rRS);
+ virtual ~OTableFieldDesc() override;
+
+ inline bool IsEmpty() const;
+
+ OTableFieldDesc& operator=( const OTableFieldDesc& _aField );
+
+ bool IsVisible() const { return m_bVisible;}
+ bool IsGroupBy() const { return m_bGroupBy;}
+
+ void SetVisible( bool bVis=true ) { m_bVisible = bVis; }
+ void SetGroupBy( bool bGb ) { m_bGroupBy = bGb; }
+ void SetTabWindow( vcl::Window* pWin ){ m_pTabWindow = pWin; }
+ void SetField( const OUString& rF ) { m_aFieldName = rF; }
+ void SetFieldAlias( const OUString& rF ) { m_aFieldAlias = rF; }
+ void SetTable( const OUString& rT ) { m_aTableName = rT; }
+ void SetAlias( const OUString& rT ) { m_aAliasName = rT; }
+ void SetFunction( const OUString& rT ) { m_aFunctionName = rT; }
+ void SetOrderDir( EOrderDir eDir ) { m_eOrderDir = eDir; }
+ void SetDataType( sal_Int32 eTyp ) { m_eDataType = eTyp; }
+ void SetFieldType( ETableFieldType eTyp ) { m_eFieldType = eTyp; }
+ void SetCriteria( sal_uInt16 nIdx, const OUString& rCrit );
+ void SetColWidth( sal_Int32 nWidth ) { m_nColWidth = nWidth; }
+ void SetFieldIndex( sal_Int32 nFieldIndex ) { m_nIndex = nFieldIndex; }
+ void SetFunctionType( sal_Int32 eTyp ) { m_eFunctionType = eTyp; }
+ void SetColumnId(sal_uInt16 _nColumnId) { m_nColumnId = _nColumnId; }
+
+ const OUString& GetField() const { return m_aFieldName;}
+ const OUString& GetFieldAlias() const { return m_aFieldAlias;}
+ const OUString& GetTable() const { return m_aTableName;}
+ const OUString& GetAlias() const { return m_aAliasName;}
+ const OUString& GetFunction() const { return m_aFunctionName;}
+ sal_Int32 GetDataType() const { return m_eDataType; }
+ ETableFieldType GetFieldType() const { return m_eFieldType; }
+ EOrderDir GetOrderDir() const { return m_eOrderDir; }
+ OUString GetCriteria( sal_uInt16 nIdx ) const;
+ sal_Int32 GetColWidth() const { return m_nColWidth; }
+ sal_Int32 GetFieldIndex() const { return m_nIndex; }
+ vcl::Window* GetTabWindow() const { return m_pTabWindow;}
+ sal_Int32 GetFunctionType() const { return m_eFunctionType; }
+ sal_uInt16 GetColumnId() const { return m_nColumnId;}
+
+ bool isAggregateFunction() const { return (m_eFunctionType & FKT_AGGREGATE) == FKT_AGGREGATE; }
+ bool isOtherFunction() const { return (m_eFunctionType & FKT_OTHER) == FKT_OTHER; }
+ bool isNumeric() const { return (m_eFunctionType & FKT_NUMERIC) == FKT_NUMERIC; }
+ bool isNoneFunction() const { return m_eFunctionType == FKT_NONE; }
+ bool isCondition() const { return (m_eFunctionType & FKT_CONDITION) == FKT_CONDITION; }
+ bool isNumericOrAggregateFunction() const { return isNumeric() || isAggregateFunction(); }
+
+ bool HasCriteria() const
+ {
+ for (auto const& criteria : m_aCriteria)
+ {
+ if(!criteria.isEmpty())
+ return true;
+ }
+ return false;
+ }
+
+ const std::vector< OUString>& GetCriteria() const { return m_aCriteria; }
+
+ void Load( const css::beans::PropertyValue& i_rSettings, const bool i_bIncludingCriteria );
+ void Save( ::comphelper::NamedValueCollection& o_rSettings, const bool i_bIncludingCriteria );
+ };
+
+ inline bool OTableFieldDesc::IsEmpty() const
+ {
+ bool bEmpty = (m_aTableName.isEmpty() &&
+ m_aAliasName.isEmpty() &&
+ m_aFieldName.isEmpty() &&
+ m_aFieldAlias.isEmpty() &&
+ m_aFunctionName.isEmpty() &&
+ !HasCriteria());
+ return bEmpty;
+ }
+
+ typedef ::rtl::Reference< OTableFieldDesc> OTableFieldDescRef;
+ typedef std::vector<OTableFieldDescRef> OTableFields;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/TableGrantCtrl.hxx b/dbaccess/source/ui/inc/TableGrantCtrl.hxx
new file mode 100644
index 000000000..74a9fd8b5
--- /dev/null
+++ b/dbaccess/source/ui/inc/TableGrantCtrl.hxx
@@ -0,0 +1,104 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <sal/config.h>
+
+#include <map>
+
+#include <svtools/editbrowsebox.hxx>
+#include <com/sun/star/awt/XWindow.hpp>
+#include <com/sun/star/sdbcx/XTablesSupplier.hpp>
+#include <com/sun/star/sdbcx/XAuthorizable.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+
+class Edit;
+namespace dbaui
+{
+
+class OTableGrantControl : public ::svt::EditBrowseBox
+{
+ typedef struct
+ {
+ sal_Int32 nRights;
+ sal_Int32 nWithGrant;
+ } TPrivileges;
+
+ typedef std::map<OUString, TPrivileges> TTablePrivilegeMap;
+
+ css::uno::Reference< css::container::XNameAccess > m_xUsers;
+ css::uno::Reference< css::container::XNameAccess > m_xTables;
+ css::uno::Reference< css::uno::XComponentContext> m_xContext;
+ css::uno::Reference< css::sdbcx::XAuthorizable> m_xGrantUser;
+ css::uno::Sequence< OUString> m_aTableNames;
+
+ mutable TTablePrivilegeMap m_aPrivMap;
+ OUString m_sUserName;
+ VclPtr<::svt::CheckBoxControl> m_pCheckCell;
+ VclPtr<::svt::EditControl> m_pEdit;
+ tools::Long m_nDataPos;
+ ImplSVEvent * m_nDeactivateEvent;
+
+public:
+ OTableGrantControl(const css::uno::Reference<css::awt::XWindow> &rParent);
+ virtual ~OTableGrantControl() override;
+ virtual void dispose() override;
+ void UpdateTables();
+ void setUserName(const OUString& _sUserName);
+ void setGrantUser(const css::uno::Reference< css::sdbcx::XAuthorizable>& _xGrantUser);
+
+ void setTablesSupplier(const css::uno::Reference< css::sdbcx::XTablesSupplier >& _xTablesSup);
+ void setComponentContext(const css::uno::Reference< css::uno::XComponentContext>& _rxContext);
+
+ virtual void Init() override;
+
+ // IAccessibleTableProvider
+ /** Creates the accessible object of a data table cell.
+ @param nRow The row index of the cell.
+ @param nColumnId The column ID of the cell.
+ @return The XAccessible interface of the specified cell. */
+ virtual css::uno::Reference<
+ css::accessibility::XAccessible >
+ CreateAccessibleCell( sal_Int32 nRow, sal_uInt16 nColumnId ) override;
+
+protected:
+ virtual bool PreNotify(NotifyEvent& rNEvt ) override;
+
+ virtual bool IsTabAllowed(bool bForward) const override;
+ virtual void InitController( ::svt::CellControllerRef& rController, sal_Int32 nRow, sal_uInt16 nCol ) override;
+ virtual ::svt::CellController* GetController( sal_Int32 nRow, sal_uInt16 nCol ) override;
+ virtual void PaintCell( OutputDevice& rDev, const tools::Rectangle& rRect, sal_uInt16 nColId ) const override;
+ virtual bool SeekRow( sal_Int32 nRow ) override;
+ virtual bool SaveModified() override;
+ virtual OUString GetCellText( sal_Int32 nRow, sal_uInt16 nColId ) const override;
+
+ virtual void CellModified() override;
+
+private:
+ DECL_LINK( AsynchActivate, void*, void );
+ DECL_LINK( AsynchDeactivate, void*, void );
+
+ static bool isAllowed(sal_uInt16 _nColumnId,sal_Int32 _nPrivilege);
+ void fillPrivilege(sal_Int32 _nRow) const;
+ TTablePrivilegeMap::const_iterator findPrivilege(sal_Int32 _nRow) const;
+};
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/TableRow.hxx b/dbaccess/source/ui/inc/TableRow.hxx
new file mode 100644
index 000000000..4f34a94bf
--- /dev/null
+++ b/dbaccess/source/ui/inc/TableRow.hxx
@@ -0,0 +1,76 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <tools/long.hxx>
+#include "TypeInfo.hxx"
+
+class SvStream;
+
+namespace dbaui
+{
+ class OFieldDescription;
+ class OTableRow
+ {
+ private:
+ OFieldDescription* m_pActFieldDescr;
+ sal_Int32 m_nPos;
+ bool m_bReadOnly;
+ bool m_bOwnsDescriptions;
+
+ protected:
+ public:
+ OTableRow();
+ OTableRow( const OTableRow& rRow, tools::Long nPosition = -1 );
+ ~OTableRow();
+
+ OFieldDescription* GetActFieldDescr() const { return m_pActFieldDescr; }
+ bool isValid() const { return GetActFieldDescr() != nullptr; }
+
+ void SetFieldType( const TOTypeInfoSP& _pType, bool _bForce = false );
+
+ void SetPrimaryKey( bool bSet );
+ bool IsPrimaryKey() const;
+
+ /** returns the current position in the table.
+ @return
+ the current position in the table
+ */
+ sal_Int32 GetPos() const { return m_nPos; }
+ void SetPos(sal_Int32 _nPos) { m_nPos = _nPos; }
+
+ /** set the row readonly
+ @param _bRead
+ if <TRUE/> then the row is readonly, otherwise not
+ */
+ void SetReadOnly( bool _bRead=true ){ m_bReadOnly = _bRead; }
+
+ /** returns if the row is readonly
+ @return
+ <TRUE/> if readonly, otherwise <FALSE/>
+ */
+ bool IsReadOnly() const { return m_bReadOnly; }
+
+ friend SvStream& WriteOTableRow( SvStream& rStr,const OTableRow& _rRow );
+ friend SvStream& ReadOTableRow( SvStream& rStr, OTableRow& _rRow );
+ };
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/TableRowExchange.hxx b/dbaccess/source/ui/inc/TableRowExchange.hxx
new file mode 100644
index 000000000..36e249795
--- /dev/null
+++ b/dbaccess/source/ui/inc/TableRowExchange.hxx
@@ -0,0 +1,40 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <vcl/transfer.hxx>
+#include <memory>
+
+namespace dbaui
+{
+ class OTableRow;
+ class OTableRowExchange : public TransferableHelper
+ {
+ std::vector< std::shared_ptr<OTableRow> > m_vTableRow;
+ public:
+ OTableRowExchange(std::vector< std::shared_ptr<OTableRow> >&& _rvTableRow);
+ protected:
+ virtual void AddSupportedFormats() override;
+ virtual bool GetData( const css::datatransfer::DataFlavor& rFlavor, const OUString& rDestDoc ) override;
+ virtual bool WriteObject( tools::SvRef<SotTempStream>& rxOStm, void* pUserObject, sal_uInt32 nUserObjectId, const css::datatransfer::DataFlavor& rFlavor ) override;
+ virtual void ObjectReleased() override;
+ };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/TableWindow.hxx b/dbaccess/source/ui/inc/TableWindow.hxx
new file mode 100644
index 000000000..c3bed06c7
--- /dev/null
+++ b/dbaccess/source/ui/inc/TableWindow.hxx
@@ -0,0 +1,183 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <com/sun/star/container/XNameAccess.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include "TableWindowTitle.hxx"
+#include <rtl/ref.hxx>
+#include "TableWindowData.hxx"
+#include "TableWindowListBox.hxx"
+#include <vector>
+#include <vcl/window.hxx>
+
+#include <comphelper/containermultiplexer.hxx>
+#include <cppuhelper/basemutex.hxx>
+#include <o3tl/typed_flags_set.hxx>
+
+// Flags for the size adjustment of SbaJoinTabWins
+enum class SizingFlags {
+ NONE = 0x0000,
+ Top = 0x0001,
+ Bottom = 0x0002,
+ Left = 0x0004,
+ Right = 0x0008,
+};
+namespace o3tl {
+ template<> struct typed_flags<SizingFlags> : is_typed_flags<SizingFlags, 0x0f> {};
+}
+
+
+namespace dbaui
+{
+ class OJoinDesignView;
+ class OJoinTableView;
+ class OTableWindowAccess;
+
+ class OTableWindow : public ::cppu::BaseMutex
+ ,public ::comphelper::OContainerListener
+ ,public vcl::Window
+ {
+ friend class OTableWindowTitle;
+ friend class OTableWindowListBox;
+ protected:
+ // and the table itself (needed for me as I want to lock it as long as the window is alive)
+ VclPtr<OTableWindowTitle> m_xTitle;
+ VclPtr<OTableWindowListBox> m_xListBox;
+
+ private:
+ TTableWindowData::value_type
+ m_pData;
+ ::rtl::Reference< comphelper::OContainerListenerAdapter>
+ m_pContainerListener;
+ sal_Int32 m_nMoveCount; // how often the arrow keys was pressed
+ sal_Int32 m_nMoveIncrement; // how many pixel we should move
+ SizingFlags m_nSizingFlags;
+
+ // OContainerListener
+ virtual void _elementInserted( const css::container::ContainerEvent& _rEvent ) override;
+ virtual void _elementRemoved( const css::container::ContainerEvent& _rEvent ) override;
+ virtual void _elementReplaced( const css::container::ContainerEvent& _rEvent ) override;
+
+ protected:
+ virtual void Resize() override;
+ virtual void Paint( vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect ) override;
+ virtual void MouseMove( const MouseEvent& rEvt ) override;
+ virtual void MouseButtonDown( const MouseEvent& rEvt ) override;
+ virtual void DataChanged( const DataChangedEvent& rDCEvt ) override;
+
+ // called at FIRST Init
+ void FillListBox();
+ // called at EACH Init
+
+ virtual void OnEntryDoubleClicked(weld::TreeIter& /*rEntry*/) { }
+ // called from the DoubleClickHdl of the ListBox
+
+ /** delete the user data with the equal type as created within createUserData
+ @param _pUserData
+ The user data store in the listbox entries. Created with a call to createUserData.
+ _pUserData may be <NULL/>. _pUserData will be set to <NULL/> after call.
+ */
+ virtual void deleteUserData(void*& _pUserData);
+
+ /** creates user information that will be append at the ListBoxentry
+ @param _xColumn
+ The corresponding column, can be <NULL/>.
+ @param _bPrimaryKey
+ <TRUE/> when the column belongs to the primary key
+ @return
+ the user data which will be append at the listbox entry, may be <NULL/>
+ */
+ virtual void* createUserData(const css::uno::Reference<
+ css::beans::XPropertySet>& _xColumn,
+ bool _bPrimaryKey);
+
+ /** updates image
+ */
+ void impl_updateImage();
+
+ OTableWindow( vcl::Window* pParent, const TTableWindowData::value_type& pTabWinData );
+
+ public:
+ virtual ~OTableWindow() override;
+ virtual void dispose() override;
+
+ // late Constructor, see also CreateListbox and FillListbox
+ virtual bool Init();
+
+ OJoinTableView* getTableView();
+ const OJoinTableView* getTableView() const;
+ OJoinDesignView* getDesignView();
+ void SetPosPixel( const Point& rNewPos ) override;
+ void SetSizePixel( const Size& rNewSize ) override;
+ void SetPosSizePixel( const Point& rNewPos, const Size& rNewSize ) override;
+
+ OUString getTitle() const;
+ void SetBoldTitle( bool bBold );
+ void setActive(bool _bActive = true);
+
+ void Remove();
+
+ OUString const & GetTableName() const { return m_pData->GetTableName(); }
+ OUString const & GetWinName() const { return m_pData->GetWinName(); }
+ OUString const & GetComposedName() const { return m_pData->GetComposedName(); }
+ const VclPtr<OTableWindowListBox>& GetListBox() const { return m_xListBox; }
+ const TTableWindowData::value_type& GetData() const { return m_pData; }
+ const VclPtr<OTableWindowTitle>& GetTitleCtrl() const { return m_xTitle; }
+
+ /** returns the name which should be used when displaying join or relations
+ @return
+ The composed name or the window name.
+ */
+ virtual OUString GetName() const = 0;
+
+ css::uno::Reference< css::container::XNameAccess > GetOriginalColumns() const { return m_pData->getColumns(); }
+ css::uno::Reference< css::beans::XPropertySet > GetTable() const { return m_pData->getTable(); }
+
+ /** set the sizing flag to the direction
+ @param _rPos
+ The EndPosition after resizing.
+ */
+ void setSizingFlag(const Point& _rPos);
+
+ /** returns the new sizing
+ */
+ tools::Rectangle getSizingRect(const Point& _rPos,const Size& _rOutputSize) const;
+
+ // window override
+ virtual void StateChanged( StateChangedType nStateChange ) override;
+ virtual void GetFocus() override;
+ virtual bool PreNotify( NotifyEvent& rNEvt ) override;
+ virtual void Command(const CommandEvent& rEvt) override;
+
+ // Accessibility
+ virtual css::uno::Reference< css::accessibility::XAccessible > CreateAccessible() override;
+
+ // do I have connections to the outside?
+ bool ExistsAConn() const;
+
+ void EnumValidFields(std::vector< OUString>& arrstrFields);
+
+ /** clears the listbox inside. Must be called be the dtor is called.
+ */
+ void clearListBox();
+ };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/TableWindowAccess.hxx b/dbaccess/source/ui/inc/TableWindowAccess.hxx
new file mode 100644
index 000000000..b51e4c80f
--- /dev/null
+++ b/dbaccess/source/ui/inc/TableWindowAccess.hxx
@@ -0,0 +1,94 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "TableWindow.hxx"
+#include <com/sun/star/accessibility/XAccessibleRelationSet.hpp>
+#include <cppuhelper/implbase2.hxx>
+#include <toolkit/awt/vclxaccessiblecomponent.hxx>
+#include <vcl/vclptr.hxx>
+
+namespace dbaui
+{
+ typedef ::cppu::ImplHelper2< css::accessibility::XAccessibleRelationSet,
+ css::accessibility::XAccessible
+ > OTableWindowAccess_BASE;
+ class OTableWindow;
+ /** the class OTableWindowAccess represents the accessible object for table windows
+ like they are used in the QueryDesign and the RelationDesign
+ */
+ class OTableWindowAccess : public VCLXAccessibleComponent
+ , public OTableWindowAccess_BASE
+ {
+ VclPtr<OTableWindow> m_pTable; // the window which I should give accessibility to
+
+ css::uno::Reference< css::accessibility::XAccessible > getParentChild(sal_Int32 _nIndex);
+ protected:
+ /** this function is called upon disposing the component
+ */
+ virtual void SAL_CALL disposing() override;
+
+ virtual void ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent ) override;
+ public:
+ OTableWindowAccess( OTableWindow* _pTable);
+
+ // XInterface
+ virtual css::uno::Any SAL_CALL queryInterface( const css::uno::Type& aType ) override;
+ virtual void SAL_CALL acquire( ) noexcept override
+ { // here inline is allowed because we do not use this class outside this dll
+ VCLXAccessibleComponent::acquire( );
+ }
+ virtual void SAL_CALL release( ) noexcept override
+ { // here inline is allowed because we do not use this class outside this dll
+ VCLXAccessibleComponent::release( );
+ }
+
+ // XTypeProvider
+ virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes( ) override;
+
+ // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+
+ // XAccessible
+ virtual css::uno::Reference< css::accessibility::XAccessibleContext > SAL_CALL getAccessibleContext( ) override;
+
+ // XAccessibleContext
+ virtual sal_Int32 SAL_CALL getAccessibleChildCount( ) override;
+ virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL getAccessibleChild( sal_Int32 i ) override;
+ virtual sal_Int32 SAL_CALL getAccessibleIndexInParent( ) override;
+ virtual sal_Int16 SAL_CALL getAccessibleRole( ) override;
+ virtual OUString SAL_CALL getAccessibleName( ) override;
+ virtual css::uno::Reference< css::accessibility::XAccessibleRelationSet > SAL_CALL getAccessibleRelationSet( ) override;
+
+ // XAccessibleComponent
+ virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL getAccessibleAtPoint( const css::awt::Point& aPoint ) override;
+
+ // XAccessibleExtendedComponent
+ virtual OUString SAL_CALL getTitledBorderText( ) override;
+
+ // XAccessibleRelationSet
+ virtual sal_Int32 SAL_CALL getRelationCount( ) override;
+ virtual css::accessibility::AccessibleRelation SAL_CALL getRelation( sal_Int32 nIndex ) override;
+ virtual sal_Bool SAL_CALL containsRelation( sal_Int16 aRelationType ) override;
+ virtual css::accessibility::AccessibleRelation SAL_CALL getRelationByType( sal_Int16 aRelationType ) override;
+ };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/TableWindowData.hxx b/dbaccess/source/ui/inc/TableWindowData.hxx
new file mode 100644
index 000000000..f7aea00b9
--- /dev/null
+++ b/dbaccess/source/ui/inc/TableWindowData.hxx
@@ -0,0 +1,95 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <tools/gen.hxx>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/container/XNameAccess.hpp>
+#include <com/sun/star/container/XIndexAccess.hpp>
+#include <com/sun/star/sdbc/XConnection.hpp>
+#include <unotools/eventlisteneradapter.hxx>
+#include <memory>
+#include <vector>
+
+namespace dbaui
+{
+ class OTableWindowData : public ::utl::OEventListenerAdapter
+ {
+ mutable ::osl::Mutex m_aMutex;
+
+ void listen();
+ protected:
+ // the columns of the table
+ css::uno::Reference< css::beans::XPropertySet > m_xTable; // can either be a table or a query
+ css::uno::Reference< css::container::XIndexAccess> m_xKeys;
+ css::uno::Reference< css::container::XNameAccess > m_xColumns;
+
+ OUString m_aTableName;
+ OUString m_aWinName;
+ OUString m_sComposedName;
+ Point m_aPosition;
+ Size m_aSize;
+ bool m_bShowAll;
+ bool m_bIsQuery;
+ bool m_bIsValid;
+
+ public:
+ explicit OTableWindowData( const css::uno::Reference< css::beans::XPropertySet>& _xTable
+ ,const OUString& _rComposedName
+ ,const OUString& strTableName
+ ,const OUString& rWinName );
+ virtual ~OTableWindowData() override;
+
+ /** late constructor
+ *
+ * \param _xConnection
+ * \param _bAllowQueries when true, queries are allowed
+ * \return false if the table was unaccessible otherwise true
+ */
+ bool init(const css::uno::Reference< css::sdbc::XConnection >& _xConnection
+ ,bool _bAllowQueries);
+
+ const OUString& GetComposedName() const { return m_sComposedName; }
+ const OUString& GetTableName() const { return m_aTableName; }
+ const OUString& GetWinName() const { return m_aWinName; }
+ const Point& GetPosition() const { return m_aPosition; }
+ const Size& GetSize() const { return m_aSize; }
+ bool IsShowAll() const { return m_bShowAll; }
+ bool isQuery() const { return m_bIsQuery; }
+ bool isValid() const { return m_bIsValid; } // it is either a table or query but it is known
+ bool HasPosition() const;
+ bool HasSize() const;
+
+ void SetWinName( const OUString& rWinName ) { m_aWinName = rWinName; }
+ void SetPosition( const Point& rPos ) { m_aPosition=rPos; }
+ void SetSize( const Size& rSize ) { m_aSize = rSize; }
+ void ShowAll( bool bAll ) { m_bShowAll = bAll; }
+
+ css::uno::Reference< css::beans::XPropertySet> getTable() const { ::osl::MutexGuard aGuard( m_aMutex ); return m_xTable; }
+ css::uno::Reference< css::container::XIndexAccess> getKeys() const { ::osl::MutexGuard aGuard( m_aMutex ); return m_xKeys; }
+ css::uno::Reference< css::container::XNameAccess > getColumns() const { ::osl::MutexGuard aGuard( m_aMutex ); return m_xColumns; }
+
+ // OEventListenerAdapter
+ virtual void _disposing( const css::lang::EventObject& _rSource ) override;
+ };
+
+ typedef std::vector< std::shared_ptr<OTableWindowData> > TTableWindowData;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/TableWindowListBox.hxx b/dbaccess/source/ui/inc/TableWindowListBox.hxx
new file mode 100644
index 000000000..cdad4947c
--- /dev/null
+++ b/dbaccess/source/ui/inc/TableWindowListBox.hxx
@@ -0,0 +1,121 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <vcl/transfer.hxx>
+#include <vcl/InterimItemWindow.hxx>
+#include "callbacks.hxx"
+
+struct AcceptDropEvent;
+struct ExecuteDropEvent;
+namespace dbaui
+{
+ class OTableWindowListBox;
+ struct OJoinExchangeData
+ {
+ public:
+ VclPtr<OTableWindowListBox> pListBox; // the ListBox inside the same (you can get the TabWin and the WinName out of it)
+ int nEntry; // the entry, which was dragged or to which was dropped on
+
+ OJoinExchangeData(OTableWindowListBox* pBox);
+ OJoinExchangeData() : pListBox(nullptr), nEntry(-1) { }
+ };
+
+ struct OJoinDropData
+ {
+ OJoinExchangeData aSource;
+ OJoinExchangeData aDest;
+ };
+
+ class OJoinExchObj;
+ class OTableWindow;
+ class TableWindowListBoxHelper;
+
+ class OTableWindowListBox
+ : public InterimItemWindow
+ , public IDragTransferableListener
+ {
+ std::unique_ptr<weld::TreeView> m_xTreeView;
+ std::unique_ptr<TableWindowListBoxHelper> m_xDragDropTargetHelper;
+
+ DECL_LINK( OnDoubleClick, weld::TreeView&, bool );
+ DECL_LINK(CommandHdl, const CommandEvent&, bool);
+ DECL_LINK( DropHdl, void*, void );
+ DECL_LINK( LookForUiHdl, void*, void );
+ DECL_LINK( DragBeginHdl, bool&, bool );
+ DECL_LINK( ScrollHdl, weld::TreeView&, void );
+
+ rtl::Reference<OJoinExchObj> m_xHelper;
+
+ VclPtr<OTableWindow> m_pTabWin;
+ ImplSVEvent * m_nDropEvent;
+ ImplSVEvent * m_nUiEvent;
+ OJoinDropData m_aDropInfo;
+
+ protected:
+ virtual void LoseFocus() override;
+ virtual void GetFocus() override;
+
+ virtual void dragFinished( ) override;
+
+ public:
+ OTableWindowListBox(OTableWindow* pParent);
+ virtual ~OTableWindowListBox() override;
+ virtual void dispose() override;
+
+ const weld::TreeView& get_widget() const { return *m_xTreeView; }
+ weld::TreeView& get_widget() { return *m_xTreeView; }
+
+ // DnD stuff
+ sal_Int8 AcceptDrop(const AcceptDropEvent& rEvt);
+ sal_Int8 ExecuteDrop(const ExecuteDropEvent& rEvt);
+
+ // window
+ virtual void Command(const CommandEvent& rEvt) override;
+
+ OTableWindow* GetTabWin(){ return m_pTabWin; }
+ int GetEntryFromText( std::u16string_view rEntryText );
+ };
+
+ class TableWindowListBoxHelper final : public DropTargetHelper
+ {
+ private:
+ OTableWindowListBox& m_rParent;
+
+ virtual sal_Int8 AcceptDrop(const AcceptDropEvent& rEvt) override
+ {
+ return m_rParent.AcceptDrop(rEvt);
+ }
+
+ virtual sal_Int8 ExecuteDrop(const ExecuteDropEvent& rEvt) override
+ {
+ return m_rParent.ExecuteDrop(rEvt);
+ }
+
+ public:
+ TableWindowListBoxHelper(OTableWindowListBox& rParent, const css::uno::Reference<css::datatransfer::dnd::XDropTarget>& rDropTarget)
+ : DropTargetHelper(rDropTarget)
+ , m_rParent(rParent)
+ {
+ }
+ };
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/TableWindowTitle.hxx b/dbaccess/source/ui/inc/TableWindowTitle.hxx
new file mode 100644
index 000000000..0a3779bd8
--- /dev/null
+++ b/dbaccess/source/ui/inc/TableWindowTitle.hxx
@@ -0,0 +1,44 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <vcl/InterimItemWindow.hxx>
+
+namespace dbaui
+{
+ class OTableWindow;
+ class OTableWindowTitle final : public InterimItemWindow
+ {
+ VclPtr<OTableWindow> m_pTabWin;
+ std::unique_ptr<weld::Label> m_xLabel;
+ std::unique_ptr<weld::Image> m_xImage;
+
+ DECL_LINK(MousePressHdl, const MouseEvent&, bool);
+
+ public:
+ OTableWindowTitle( OTableWindow* pParent );
+ virtual ~OTableWindowTitle() override;
+ virtual void dispose() override;
+
+ weld::Label& GetLabel() { return *m_xLabel; }
+ weld::Image& GetImage() { return *m_xImage; }
+ };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/TablesSingleDlg.hxx b/dbaccess/source/ui/inc/TablesSingleDlg.hxx
new file mode 100644
index 000000000..c75fa1eb3
--- /dev/null
+++ b/dbaccess/source/ui/inc/TablesSingleDlg.hxx
@@ -0,0 +1,71 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <sfx2/basedlgs.hxx>
+#include "IItemSetHelper.hxx"
+#include <com/sun/star/beans/PropertyValue.hpp>
+
+#include <memory>
+
+namespace com::sun::star {
+ namespace beans {
+ class XPropertySet;
+ }
+ namespace uno {
+ class XComponentContext;
+ }
+}
+
+namespace dbaui
+{
+class ODbDataSourceAdministrationHelper;
+ // OTableSubscriptionDialog
+ class OTableSubscriptionDialog : public SfxSingleTabDialogController, public IItemSetHelper
+ {
+ std::unique_ptr<ODbDataSourceAdministrationHelper> m_pImpl;
+ bool m_bStopExecution; // set when the dialog should not be executed
+
+ std::unique_ptr<SfxItemSet> m_pOutSet;
+ public:
+
+ OTableSubscriptionDialog(weld::Window* pParent
+ ,const SfxItemSet* _pItems
+ ,const css::uno::Reference< css::uno::XComponentContext >& _rxORB
+ ,const css::uno::Any& _aDataSourceName
+ );
+ virtual ~OTableSubscriptionDialog() override;
+
+ // forwards from ODbDataSourceAdministrationHelper
+ void successfullyConnected();
+ bool getCurrentSettings(css::uno::Sequence< css::beans::PropertyValue >& _rDriverParams);
+ void clearPassword();
+ css::uno::Reference< css::beans::XPropertySet > const & getCurrentDataSource();
+ void endExecution() { m_bStopExecution = true; }
+
+ virtual const SfxItemSet* getOutputSet() const override;
+ virtual SfxItemSet* getWriteOutputSet() override;
+
+ virtual short run() override;
+ };
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/TokenWriter.hxx b/dbaccess/source/ui/inc/TokenWriter.hxx
new file mode 100644
index 000000000..82e36240f
--- /dev/null
+++ b/dbaccess/source/ui/inc/TokenWriter.hxx
@@ -0,0 +1,206 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "commontypes.hxx"
+
+#include <com/sun/star/awt/FontDescriptor.hpp>
+#include <com/sun/star/sdbc/XResultSet.hpp>
+#include <com/sun/star/sdbc/XResultSetMetaData.hpp>
+#include <com/sun/star/sdbc/XResultSetUpdate.hpp>
+#include <com/sun/star/sdbc/XRow.hpp>
+#include <com/sun/star/lang/XEventListener.hpp>
+#include <com/sun/star/container/XIndexAccess.hpp>
+#include <com/sun/star/sdbcx/XRowLocate.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <com/sun/star/util/XNumberFormatter.hpp>
+
+#include <cppuhelper/implbase.hxx>
+#include <svx/dataaccessdescriptor.hxx>
+#include <vcl/weld.hxx>
+
+namespace com::sun::star {
+ namespace sdbc{
+ class XRowUpdate;
+ }
+}
+
+class SvStream;
+
+namespace dbaui
+{
+ // ODatabaseImportExport base class for import/export
+ class ODatabaseExport;
+ class ODatabaseImportExport : public ::cppu::WeakImplHelper< css::lang::XEventListener>
+ {
+ protected:
+ css::uno::Sequence< css::uno::Any> m_aSelection;
+ bool m_bBookmarkSelection;
+ SvStream* m_pStream;
+ css::awt::FontDescriptor m_aFont;
+ css::uno::Reference< css::beans::XPropertySet > m_xObject; // table/query
+ SharedConnection m_xConnection;
+ css::uno::Reference< css::sdbc::XResultSet > m_xResultSet;
+ css::uno::Reference< css::sdbc::XRow > m_xRow;
+ css::uno::Reference< css::sdbcx::XRowLocate > m_xRowLocate;
+ css::uno::Reference< css::sdbc::XResultSetMetaData > m_xResultSetMetaData;
+ css::uno::Reference< css::container::XIndexAccess > m_xRowSetColumns;
+ css::uno::Reference< css::util::XNumberFormatter > m_xFormatter; // a number formatter working with the connection's NumberFormatsSupplier
+ css::uno::Reference< css::uno::XComponentContext > m_xContext;
+
+ OUString m_sName;
+
+ //for transfor the tablename
+ OUString m_sDefaultTableName;
+
+ OUString m_sDataSourceName;
+ sal_Int32 m_nCommandType;
+ bool m_bNeedToReInitialize;
+
+ rtl_TextEncoding m_eDestEnc;
+ bool m_bInInitialize;
+ bool m_bCheckOnly;
+
+ // export data
+ ODatabaseImportExport( const svx::ODataAccessDescriptor& _aDataDescriptor,
+ const css::uno::Reference< css::uno::XComponentContext >& _rM,
+ const css::uno::Reference< css::util::XNumberFormatter >& _rxNumberF);
+
+ // import data
+ ODatabaseImportExport( const SharedConnection& _rxConnection,
+ const css::uno::Reference< css::util::XNumberFormatter >& _rxNumberF,
+ const css::uno::Reference< css::uno::XComponentContext >& _rM);
+
+ virtual ~ODatabaseImportExport() override;
+
+ virtual void initialize();
+ public:
+ void setStream(SvStream* _pStream){ m_pStream = _pStream; }
+
+ //for set the tablename
+ void setSTableName(const OUString &_sTableName){ m_sDefaultTableName = _sTableName; }
+
+ virtual bool Write(); // Export
+ virtual bool Read(); // Import
+
+ void initialize(const svx::ODataAccessDescriptor& _aDataDescriptor);
+ void dispose();
+
+ void enableCheckOnly() { m_bCheckOnly = true; }
+ bool isCheckEnabled() const { return m_bCheckOnly; }
+
+ private:
+ virtual void SAL_CALL disposing( const css::lang::EventObject& Source ) override;
+ void impl_initFromDescriptor( const svx::ODataAccessDescriptor& _aDataDescriptor, bool _bPlusDefaultInit );
+ };
+
+ // RTF Import and Export
+
+ class ORTFImportExport : public ODatabaseImportExport
+ {
+ void appendRow(OString const * pHorzChar,sal_Int32 _nColumnCount,sal_Int32& k,sal_Int32& kk);
+ public:
+ // export data
+ ORTFImportExport( const svx::ODataAccessDescriptor& _aDataDescriptor,
+ const css::uno::Reference< css::uno::XComponentContext >& _rM,
+ const css::uno::Reference< css::util::XNumberFormatter >& _rxNumberF)
+ : ODatabaseImportExport(_aDataDescriptor,_rM,_rxNumberF) {};
+
+ // import data
+ ORTFImportExport( const SharedConnection& _rxConnection,
+ const css::uno::Reference< css::util::XNumberFormatter >& _rxNumberF,
+ const css::uno::Reference< css::uno::XComponentContext >& _rM)
+ : ODatabaseImportExport(_rxConnection,_rxNumberF,_rM)
+ {}
+
+ virtual bool Write() override;
+ virtual bool Read() override;
+ };
+ // HTML Import and Export
+ #define SBA_HTML_FONTSIZES 7
+ const sal_Int16 nIndentMax = 23;
+ class OHTMLImportExport : public ODatabaseImportExport
+ {
+ static const sal_Int16 nCellSpacing;
+ static const char sIndentSource[];
+ char sIndent[nIndentMax+1];
+ sal_Int16 m_nIndent;
+ #if OSL_DEBUG_LEVEL > 0
+ bool m_bCheckFont;
+ #endif
+
+ void WriteHeader();
+ void WriteBody();
+ void WriteTables();
+ void WriteCell( sal_Int32 nFormat,sal_Int32 nWidthPixel,sal_Int32 nHeightPixel,const char* pChar,const OUString& rValue,const char* pHtmlTag);
+ void IncIndent( sal_Int16 nVal );
+ const char* GetIndentStr() const { return sIndent; }
+ void FontOn();
+ inline void FontOff();
+
+ public:
+ // export data
+ OHTMLImportExport( const svx::ODataAccessDescriptor& _aDataDescriptor,
+ const css::uno::Reference< css::uno::XComponentContext >& _rM,
+ const css::uno::Reference< css::util::XNumberFormatter >& _rxNumberF);
+ // import data
+ OHTMLImportExport( const SharedConnection& _rxConnection,
+ const css::uno::Reference< css::util::XNumberFormatter >& _rxNumberF,
+ const css::uno::Reference< css::uno::XComponentContext >& _rM)
+ : ODatabaseImportExport(_rxConnection,_rxNumberF,_rM)
+ , m_nIndent(0)
+ {}
+
+ virtual bool Write() override;
+ virtual bool Read() override;
+
+ };
+ // normal RowSet Import and Export
+
+ class ORowSetImportExport : public ODatabaseImportExport
+ {
+ std::vector<sal_Int32> m_aColumnMapping;
+ std::vector<sal_Int32> m_aColumnTypes;
+ css::uno::Reference< css::sdbc::XResultSetUpdate > m_xTargetResultSetUpdate;
+ css::uno::Reference< css::sdbc::XRowUpdate > m_xTargetRowUpdate;
+ css::uno::Reference< css::sdbc::XResultSetMetaData > m_xTargetResultSetMetaData;
+ weld::Window* m_pParent;
+ bool m_bAlreadyAsked;
+
+ bool insertNewRow();
+ protected:
+ virtual void initialize() override;
+
+ public:
+ // export data
+ ORowSetImportExport(weld::Window* pParent,
+ const css::uno::Reference< css::sdbc::XResultSetUpdate >& xResultSetUpdate,
+ const svx::ODataAccessDescriptor& aDataDescriptor,
+ const css::uno::Reference< css::uno::XComponentContext >& rM);
+
+ virtual bool Write() override;
+ virtual bool Read() override;
+
+ private:
+ using ODatabaseImportExport::initialize;
+ };
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/TypeInfo.hxx b/dbaccess/source/ui/inc/TypeInfo.hxx
new file mode 100644
index 000000000..e9958e8e8
--- /dev/null
+++ b/dbaccess/source/ui/inc/TypeInfo.hxx
@@ -0,0 +1,121 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <rtl/ustring.hxx>
+#include <com/sun/star/sdbc/DataType.hpp>
+#include <com/sun/star/sdbc/ColumnSearch.hpp>
+#include <map>
+#include <memory>
+
+namespace dbaui
+{
+// Based on these ids the language dependent OUString are fetched from the resource
+const sal_uInt16 TYPE_UNKNOWN = 0;
+const sal_uInt16 TYPE_TEXT = 1;
+const sal_uInt16 TYPE_NUMERIC = 2;
+const sal_uInt16 TYPE_DATETIME = 3;
+const sal_uInt16 TYPE_DATE = 4;
+const sal_uInt16 TYPE_TIME = 5;
+const sal_uInt16 TYPE_BOOL = 6;
+const sal_uInt16 TYPE_CURRENCY = 7;
+const sal_uInt16 TYPE_MEMO = 8;
+const sal_uInt16 TYPE_COUNTER = 9;
+const sal_uInt16 TYPE_IMAGE = 10;
+const sal_uInt16 TYPE_CHAR = 11;
+const sal_uInt16 TYPE_DECIMAL = 12;
+const sal_uInt16 TYPE_BINARY = 13;
+const sal_uInt16 TYPE_VARBINARY = 14;
+const sal_uInt16 TYPE_BIGINT = 15;
+const sal_uInt16 TYPE_DOUBLE = 16;
+const sal_uInt16 TYPE_FLOAT = 17;
+const sal_uInt16 TYPE_REAL = 18;
+const sal_uInt16 TYPE_INTEGER = 19;
+const sal_uInt16 TYPE_SMALLINT = 20;
+const sal_uInt16 TYPE_TINYINT = 21;
+const sal_uInt16 TYPE_SQLNULL = 22;
+const sal_uInt16 TYPE_OBJECT = 23;
+const sal_uInt16 TYPE_DISTINCT = 24;
+const sal_uInt16 TYPE_STRUCT = 25;
+const sal_uInt16 TYPE_ARRAY = 26;
+const sal_uInt16 TYPE_BLOB = 27;
+const sal_uInt16 TYPE_CLOB = 28;
+const sal_uInt16 TYPE_REF = 29;
+const sal_uInt16 TYPE_OTHER = 30;
+const sal_uInt16 TYPE_BIT = 31;
+
+ class OTypeInfo
+ {
+ public:
+ OUString aUIName; // the name which is the user see (a combination of resource text and aTypeName)
+ OUString aTypeName; // name of type in database
+ OUString aCreateParams; // parameter for creation
+ OUString aLocalTypeName;
+
+ sal_Int32 nPrecision; // length of type
+ sal_Int32 nNumPrecRadix; // indicating the radix, which is usually 2 or 10
+ sal_Int32 nType; // database type
+
+ sal_Int16 nMaximumScale; // decimal places after decimal point
+ sal_Int16 nMinimumScale; // min decimal places after decimal point
+
+ sal_Int16 nSearchType; // if it is possible to search for type
+
+ bool bCurrency : 1, // currency
+ bAutoIncrement : 1, // if automatic incrementing field
+ bNullable : 1; // if field can be NULL
+
+ OTypeInfo()
+ :nPrecision(0)
+ ,nNumPrecRadix(10)
+ ,nType(css::sdbc::DataType::OTHER)
+ ,nMaximumScale(0)
+ ,nMinimumScale(0)
+ ,nSearchType(css::sdbc::ColumnSearch::FULL)
+ ,bCurrency(false)
+ ,bAutoIncrement(false)
+ ,bNullable(true)
+ {}
+ const OUString& getDBName() const { return aTypeName; }
+
+ };
+
+ typedef std::shared_ptr<OTypeInfo> TOTypeInfoSP;
+ typedef std::multimap<sal_Int32,TOTypeInfoSP> OTypeInfoMap;
+ /** return the most suitable typeinfo for a requested type
+ @param _rTypeInfo contains a map of type to typeinfo
+ @param _nType the requested type
+ @param _sTypeName the typename
+ @param _sCreateParams the create params
+ @param _nPrecision the precision
+ @param _nScale the scale
+ @param _bAutoIncrement if it is an auto increment
+ @param _brForceToType true when type was found which has some differences
+ */
+ TOTypeInfoSP getTypeInfoFromType(const OTypeInfoMap& _rTypeInfo,
+ sal_Int32 _nType,
+ const OUString& _sTypeName,
+ const OUString& _sCreateParams,
+ sal_Int32 _nPrecision,
+ sal_Int32 _nScale,
+ bool _bAutoIncrement,
+ bool& _brForceToType);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/UITools.hxx b/dbaccess/source/ui/inc/UITools.hxx
new file mode 100644
index 000000000..c622c73f6
--- /dev/null
+++ b/dbaccess/source/ui/inc/UITools.hxx
@@ -0,0 +1,396 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <connectivity/dbexception.hxx>
+#include <comphelper/stl_types.hxx>
+#include "TypeInfo.hxx"
+#include <editeng/svxenum.hxx>
+#include <vcl/taskpanelist.hxx>
+#include <connectivity/dbtools.hxx>
+#include <unotools/resmgr.hxx>
+
+#include <memory>
+#include <string_view>
+
+#define RET_ALL 100
+
+// we only need forward decl here
+namespace com::sun::star {
+
+ namespace beans { class XPropertySet;}
+ namespace container
+ {
+ class XNameAccess;
+ class XHierarchicalNameContainer;
+ }
+ namespace lang
+ {
+ class XEventListener;
+ }
+ namespace awt
+ {
+ struct FontDescriptor;
+ class XWindow;
+ }
+ namespace sdbc
+ {
+ class XDatabaseMetaData;
+ class XConnection;
+ }
+ namespace util
+ {
+ struct URL;
+ class XNumberFormatter;
+ }
+ namespace ucb { class XContent; }
+ namespace uno { class XComponentContext; }
+}
+
+namespace svt
+{
+ class EditBrowseBox;
+}
+
+namespace vcl { class Window; }
+namespace weld {
+ class Widget;
+ class Window;
+}
+class ToolBox;
+namespace vcl { class Font; }
+class SvNumberFormatter;
+class SfxFilter;
+
+namespace dbaui
+{
+
+ /** creates a new connection and appends the eventlistener
+ @param _rsDataSourceName name of the datasource
+ @param _xDatabaseContext the database context
+ @param _rxContext the UNO component context
+ @param _rEvtLst the eventlistener which will be added to the new created connection
+ @param _rOUTConnection this parameter will be filled with the new created connection
+ @return SQLExceptionInfo contains a SQLException, SQLContext or a SQLWarning when they araised else .isValid() will return false
+ */
+ ::dbtools::SQLExceptionInfo createConnection(
+ const OUString& _rsDataSourceName,
+ const css::uno::Reference< css::container::XNameAccess >& _xDatabaseContext,
+ const css::uno::Reference< css::uno::XComponentContext >& _rxContext,
+ css::uno::Reference< css::lang::XEventListener> const & _rEvtLst,
+ css::uno::Reference< css::sdbc::XConnection>& _rOUTConnection );
+ /** creates a new connection and appends the eventlistener
+ @param _xDataSource the datasource
+ @param _rxContext the UNO component context
+ @param _rEvtLst the eventlistener which will be added to the new created connection
+ @param _rOUTConnection this parameter will be filled with the new created connection
+ @return SQLExceptionInfo contains a SQLException, SQLContext or a SQLWarning when they araised else .isValid() will return false
+ */
+ ::dbtools::SQLExceptionInfo createConnection(
+ const css::uno::Reference< css::beans::XPropertySet >& _xDataSource,
+ const css::uno::Reference< css::uno::XComponentContext >& _rxContext,
+ css::uno::Reference< css::lang::XEventListener> const & _rEvtLst,
+ css::uno::Reference< css::sdbc::XConnection>& _rOUTConnection );
+
+ /** fills a map and a vector with localized type names
+ @param _rxConnection the connection to access the metadata
+ @param _rsTypeNames a list of localized type names separated with ';'
+ @param _rTypeInfoMap the filled map with the type names
+ @param _rTypeInfoIters the vector filled with map iterators
+ */
+ void fillTypeInfo( const css::uno::Reference< css::sdbc::XConnection>& _rxConnection,
+ std::u16string_view _rsTypeNames,
+ OTypeInfoMap& _rTypeInfoMap,
+ std::vector<OTypeInfoMap::iterator>& _rTypeInfoIters);
+
+ /** fill a column with data of a field description
+ @param _rxColumn the column which should be filled
+ @param _pFieldDesc the source of the data
+ */
+ class OFieldDescription;
+ void setColumnProperties( const css::uno::Reference< css::beans::XPropertySet>& _rxColumn,
+ const OFieldDescription* _pFieldDesc);
+
+ OUString createDefaultName( const css::uno::Reference< css::sdbc::XDatabaseMetaData>& _xMetaData,
+ const css::uno::Reference< css::container::XNameAccess>& _xTables,
+ const OUString& _sName);
+
+ /** checks if the given name exists in the database context
+ */
+ bool checkDataSourceAvailable( const OUString& _sDataSourceName,
+ const css::uno::Reference< css::uno::XComponentContext >& _rxContext);
+
+ /** maps SvxCellHorJustify to css::awt::TextAlign
+ @param SvxCellHorJustify& _eAlignment
+ @return the corresponding css::awt::TextAlign
+ */
+ sal_Int32 mapTextAlign(const SvxCellHorJustify& _eAlignment);
+
+ /** retrieves a data source given by name or URL, and displays an error if this fails
+
+ Any <type scope="css::sdbc">SQLException</type>s which occur will be displayed.
+ Additionally, and Exceptions which indicate a data source name pointing to a non-existent database
+ URL will also be denoted. Yet more additionally, and other exceptions will be forwarded to
+ a <type scope="css::sdb">InteractionHandler</type>.
+
+ @param _rDataSourceName
+ the URL of the database document, or the name of a registered data source
+ @param _pErrorMessageParent
+ the window to use as parent for error messages
+ @param _rxContext
+ a service factory to use for components to be created
+ @param _pErrorInfo
+ takes the error info in case of failure. If <NULL/>, the error is displayed to the user.
+ */
+ css::uno::Reference< css::sdbc::XDataSource >
+ getDataSourceByName(
+ const OUString& _rDataSourceName,
+ weld::Window* _pErrorMessageParent,
+ const css::uno::Reference< css::uno::XComponentContext >& _rxContext,
+ ::dbtools::SQLExceptionInfo* _pErrorInfo
+ );
+
+ /** returns either the model when data source is given as parameter,
+ or returns a data source when a model is given.
+ @param _xObject Either a data source or a model.
+ */
+ css::uno::Reference< css::uno::XInterface > getDataSourceOrModel(const css::uno::Reference< css::uno::XInterface >& _xObject);
+
+ /** maps css::awt::TextAlign to SvxCellHorJustify
+ @param css::awt::TextAlign& _nAlignment
+ @return the corresponding SvxCellHorJustify
+ */
+ SvxCellHorJustify mapTextJustify(sal_Int32 _nAlignment);
+
+ /** call the format dialog and set the selected format at the column
+ @param _xAffectedCol Font to be converted
+ @param _xField Font to be converted
+ */
+ void callColumnFormatDialog(const css::uno::Reference< css::beans::XPropertySet>& _xAffectedCol,
+ const css::uno::Reference< css::beans::XPropertySet>& _xField,
+ SvNumberFormatter* _pFormatter,
+ weld::Widget* _pParent);
+
+ /** second variant of the function before
+ */
+ bool callColumnFormatDialog(weld::Widget* _pParent,
+ SvNumberFormatter* _pFormatter,
+ sal_Int32 _nDataType,
+ sal_Int32& _nFormatKey,
+ SvxCellHorJustify& _eJustify,
+ bool _bHasFormat);
+ /** append a name to tablefilter of a datasource
+ @param xConnection the connection is need to get the datasource
+ @param rName the name which should be appended
+ @param rxContext needed to check if datasource is available
+ @param pParent needed when an error must be shown
+ @return false when datsource is not available otherwise true
+ */
+ bool appendToFilter(const css::uno::Reference< css::sdbc::XConnection>& xConnection,
+ const OUString& rName,
+ const css::uno::Reference< css::uno::XComponentContext >& rxContext,
+ weld::Window* pParent);
+
+ /** notifySystemWindow adds or remove the given window _pToRegister at the Systemwindow found when search _pWindow.
+ @param _pWindow
+ The window which is used to search for the SystemWindow.
+ @param _pToRegister
+ The window which should be added or removed on the TaskPaneList.
+ @param _rMemFunc
+ The member function which should be called at the SystemWindow when found.
+ Possible values are:
+ ::comphelper::mem_fun(&TaskPaneList::AddWindow)
+ ::comphelper::mem_fun(&TaskPaneList::RemoveWindow)
+ */
+ void notifySystemWindow(vcl::Window const * _pWindow,
+ vcl::Window* _pToRegister,
+ const ::comphelper::mem_fun1_t<TaskPaneList,vcl::Window*>& _rMemFunc);
+
+ void adjustBrowseBoxColumnWidth( ::svt::EditBrowseBox* _pBox, sal_uInt16 _nColId );
+
+ /** check if SQL92 name checking is enabled
+ @param _xConnection
+ Used to get the datasource as parent from the connection.
+ @return
+ <TRUE/> if so otherwise <FALSE/>
+ */
+ bool isSQL92CheckEnabled(const css::uno::Reference< css::sdbc::XConnection>& _xConnection);
+
+ /** check if the alias name of the table should be added at select statements
+ @param _xConnection
+ Used to get the datasource as parent from the connection.
+ @return
+ <TRUE/> if so otherwise <FALSE/>
+ */
+ bool isAppendTableAliasEnabled(const css::uno::Reference< css::sdbc::XConnection>& _xConnection);
+
+ /** determines whether when generating SQL statements, AS should be placed before a table alias
+ */
+ bool generateAsBeforeTableAlias( const css::uno::Reference< css::sdbc::XConnection>& _rxConnection );
+
+ /** fills the bool and string value with information out of the datasource info property
+ @param _xDatasource
+ Asked for the properties.
+ @param _rAutoIncrementValueEnabled
+ <OUT/> Set to sal_True when the property was set in the datasource.
+ @param _rsAutoIncrementValue
+ <OUT/> Set to the value when the property was set in the datasource.
+ */
+ void fillAutoIncrementValue(const css::uno::Reference< css::beans::XPropertySet>& _xDatasource
+ ,bool& _rAutoIncrementValueEnabled
+ ,OUString& _rsAutoIncrementValue);
+
+ /** fills the bool and string value with information out of the datasource info property
+ @param _xConnection
+ Used to get the datasource as parent from the connection.
+ @param _rAutoIncrementValueEnabled
+ <OUT/> Set to sal_True when the property was set in the datasource.
+ @param _rsAutoIncrementValue
+ <OUT/> Set to the value when the property was set in the datasource.
+ */
+ void fillAutoIncrementValue(const css::uno::Reference< css::sdbc::XConnection>& _xConnection
+ ,bool& _rAutoIncrementValueEnabled
+ ,OUString& _rsAutoIncrementValue);
+
+ /** set the evaluation flag at the number formatter
+ @param _rxFormatter
+ */
+ void setEvalDateFormatForFormatter(css::uno::Reference< css::util::XNumberFormatter > const & _rxFormatter);
+
+ /** query for a type info which can be used to create a primary key column
+ @param _rTypeInfo
+ The map which contains all available types.
+ @return
+ The type info which can be used to create a primary key column.
+ */
+ TOTypeInfoSP queryPrimaryKeyType(const OTypeInfoMap& _rTypeInfo);
+
+ /** query for a specific type.
+ @param _nDataType
+ The type we are searching.
+ @param _rTypeInfo
+ The map which contains all available types.
+ @return
+ The type or <NULL/> if we can't find it.
+ */
+ TOTypeInfoSP queryTypeInfoByType(sal_Int32 _nDataType,const OTypeInfoMap& _rTypeInfo);
+
+ /** returns the configuration node name of user defined drivers.
+ @return
+ the configuration node name of user defined drivers.
+ */
+
+ /** returns the result of the user action when view the query dialog.
+ @param pParent
+ The parent of the dialog
+ @param pTitle
+ A string resource id for the text which will be displayed as title.
+ @param pText
+ A string resource id for the text which will be displayed above the buttons.
+ When the string contains a #1. This will be replaced by the name.
+ @param bAll
+ When set to <TRUE/>, the all button will be appended.
+ @param rName
+ The name of the object to ask for.
+ @return
+ RET_YES, RET_NO, RET_ALL
+ */
+ sal_Int32 askForUserAction(weld::Window* pParent, TranslateId pTitle, TranslateId pText, bool bAll, std::u16string_view rName);
+
+ /** creates a new view from a query or table
+ @param _sName
+ The name of the view to be created.
+ @param _xConnection
+ The source connection.
+ @param _xSourceObject
+ The object for which a view should be created.
+ @return
+ The created view.
+ */
+ css::uno::Reference< css::beans::XPropertySet> createView( const OUString& _sName
+ ,const css::uno::Reference< css::sdbc::XConnection >& _xConnection
+ ,const css::uno::Reference< css::beans::XPropertySet>& _xSourceObject);
+
+ /** creates a view with the given command
+ */
+ css::uno::Reference< css::beans::XPropertySet> createView(
+ const OUString& _rName,
+ const css::uno::Reference< css::sdbc::XConnection >& _xConnection,
+ const OUString& _rCommand
+ );
+
+ /** returns the stripped database name.
+ @param _xDataSource
+ The data source
+ @param _rsDatabaseName
+ Will be filled with the original data source if it is empty.
+ @return
+ The stripped database name either the registered name or if it is a file url the last segment.
+ */
+ OUString getStrippedDatabaseName(const css::uno::Reference< css::beans::XPropertySet>& _xDataSource
+ ,OUString& _rsDatabaseName);
+
+ /** returns the standard database filter
+ @return
+ the filter
+ */
+ std::shared_ptr<const SfxFilter> getStandardDatabaseFilter();
+
+ /** opens a save dialog to store a form or report folder in the current hierarchy.
+ @param _pParent
+ The parent of the dialog.
+ @param _rxContext
+ a multi service factory which can be used to instantiate usual global services
+ @param _xNames
+ Where to insert the new object.
+ @param _sParentFolder
+ The name of the parent folder.
+ @param _bForm
+ <TRUE/> if a form should be inserted
+ @param _bCollection
+ A folder should be inserted
+ @param _xContent
+ The content which should be copied.
+ @param _bMove
+ if <TRUE/> the name of the content must be inserted without any change, otherwise not.
+ @return
+ <TRUE/> if the insert operation was successful, otherwise <FALSE/>.
+ */
+ bool insertHierarchyElement(
+ weld::Window* pParent,
+ const css::uno::Reference< css::uno::XComponentContext >& _rxContext,
+ const css::uno::Reference< css::container::XHierarchicalNameContainer>& _xNames,
+ const OUString& _sParentFolder,
+ bool _bForm,
+ bool _bCollection = true,
+ const css::uno::Reference< css::ucb::XContent>& _xContent = nullptr,
+ bool _bMove = false
+ );
+
+ /** creates a number formatter
+ @param _rxConnection
+ The connection is needed to create the formatter
+ @param _rxContext
+ The multi service factory
+ */
+ css::uno::Reference< css::util::XNumberFormatter > getNumberFormatter(const css::uno::Reference< css::sdbc::XConnection >& _rxConnection,const css::uno::Reference< css::uno::XComponentContext >& _rxContext );
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/UserAdminDlg.hxx b/dbaccess/source/ui/inc/UserAdminDlg.hxx
new file mode 100644
index 000000000..941eab5fa
--- /dev/null
+++ b/dbaccess/source/ui/inc/UserAdminDlg.hxx
@@ -0,0 +1,76 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <sfx2/tabdlg.hxx>
+#include "IItemSetHelper.hxx"
+#include <memory>
+
+namespace com::sun::star {
+ namespace sdbc {
+ class XConnection;
+ }
+ namespace lang {
+ class XMultiServiceFactory;
+ }
+}
+
+namespace dbaui
+{
+ class ODbDataSourceAdministrationHelper;
+ // OUserAdminDlg
+
+ /** implements the user admin dialog
+ */
+ class OUserAdminDlg : public SfxTabDialogController, public IItemSetHelper, public IDatabaseSettingsDialog
+ {
+ weld::Window* m_pParent;
+ std::unique_ptr<ODbDataSourceAdministrationHelper> m_pImpl;
+ SfxItemSet* m_pItemSet;
+ css::uno::Reference< css::sdbc::XConnection> m_xConnection;
+ bool m_bOwnConnection;
+ protected:
+ virtual void PageCreated(const OString& rId, SfxTabPage& _rPage) override;
+ public:
+ OUserAdminDlg(weld::Window* pParent, SfxItemSet* pItems,
+ const css::uno::Reference< css::uno::XComponentContext >& rxORB,
+ const css::uno::Any& rDataSourceName,
+ const css::uno::Reference< css::sdbc::XConnection>& rConnection);
+
+ virtual ~OUserAdminDlg() override;
+
+ virtual const SfxItemSet* getOutputSet() const override;
+ virtual SfxItemSet* getWriteOutputSet() override;
+
+ virtual short run() override;
+
+ // forwards to ODbDataSourceAdministrationHelper
+ virtual css::uno::Reference< css::uno::XComponentContext > getORB() const override;
+ virtual std::pair< css::uno::Reference< css::sdbc::XConnection >,bool> createConnection() override;
+ virtual css::uno::Reference< css::sdbc::XDriver > getDriver() override;
+ virtual OUString getDatasourceType(const SfxItemSet& _rSet) const override;
+ virtual void clearPassword() override;
+ virtual void saveDatasource() override;
+ virtual void setTitle(const OUString& _sTitle) override;
+ virtual void enableConfirmSettings( bool _bEnable ) override;
+ };
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/WCPage.hxx b/dbaccess/source/ui/inc/WCPage.hxx
new file mode 100644
index 000000000..69dc96f14
--- /dev/null
+++ b/dbaccess/source/ui/inc/WCPage.hxx
@@ -0,0 +1,78 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "WTabPage.hxx"
+
+namespace dbaui
+{
+ class OWizColumnSelect;
+ class OWizNormalExtend;
+ class OCopyTable final : public OWizardPage
+ {
+ bool m_bPKeyAllowed;
+ bool m_bUseHeaderAllowed;
+ sal_Int16 m_nOldOperation;
+
+ std::unique_ptr<weld::Entry> m_xEdTableName;
+ std::unique_ptr<weld::RadioButton> m_xRB_DefData;
+ std::unique_ptr<weld::RadioButton> m_xRB_Def;
+ std::unique_ptr<weld::RadioButton> m_xRB_View;
+ std::unique_ptr<weld::RadioButton> m_xRB_AppendData;
+ std::unique_ptr<weld::CheckButton> m_xCB_UseHeaderLine;
+ std::unique_ptr<weld::CheckButton> m_xCB_PrimaryColumn;
+ std::unique_ptr<weld::Label> m_xFT_KeyName;
+ std::unique_ptr<weld::Entry> m_xEdKeyName;
+
+ DECL_LINK( RadioChangeHdl, weld::Toggleable&, void );
+ DECL_LINK( KeyClickHdl, weld::Toggleable&, void );
+
+ bool checkAppendData();
+ void SetAppendDataRadio();
+
+ public:
+ virtual void Reset() override;
+ virtual void Activate() override;
+ virtual bool LeavePage() override;
+ virtual OUString GetTitle() const override ;
+
+ OCopyTable(weld::Container* pParent, OCopyTableWizard* pWizard);
+ virtual ~OCopyTable() override;
+
+ bool IsOptionDefData() const { return m_xRB_DefData->get_active(); }
+ bool IsOptionDef() const { return m_xRB_Def->get_active(); }
+ bool IsOptionView() const { return m_xRB_View->get_active(); }
+ OUString GetKeyName() const { return m_xEdKeyName->get_text(); }
+
+ void setCreateStyleAction();
+ void disallowViews()
+ {
+ m_xRB_View->set_sensitive(false);
+ }
+ void disallowUseHeaderLine()
+ {
+ m_bUseHeaderAllowed = false;
+ m_xCB_UseHeaderLine->set_sensitive(false);
+ }
+
+ void setCreatePrimaryKey( bool _bDoCreate, const OUString& _rSuggestedName );
+ };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/WColumnSelect.hxx b/dbaccess/source/ui/inc/WColumnSelect.hxx
new file mode 100644
index 000000000..38b1317fd
--- /dev/null
+++ b/dbaccess/source/ui/inc/WColumnSelect.hxx
@@ -0,0 +1,82 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "WTabPage.hxx"
+#include "WCopyTable.hxx"
+
+#include <comphelper/stl_types.hxx>
+
+namespace dbaui
+{
+ class OFieldDescription;
+
+ // Wizard Page: OWizColumnSelect
+
+ class OWizColumnSelect : public OWizardPage
+ {
+ std::unique_ptr<weld::TreeView> m_xOrgColumnNames; // left side
+ std::unique_ptr<weld::Button> m_xColumn_RH;
+ std::unique_ptr<weld::Button> m_xColumns_RH;
+ std::unique_ptr<weld::Button> m_xColumn_LH;
+ std::unique_ptr<weld::Button> m_xColumns_LH;
+ std::unique_ptr<weld::TreeView> m_xNewColumnNames; // right side
+
+ DECL_LINK( ButtonClickHdl, weld::Button&, void );
+ DECL_LINK( ListDoubleClickHdl, weld::TreeView&, bool );
+
+ static void clearListBox(weld::TreeView& _rListBox);
+ static void fillColumns(weld::TreeView const * pRight,
+ std::vector< OUString> &_rRightColumns);
+
+ void createNewColumn( weld::TreeView* _pListbox,
+ OFieldDescription const * _pSrcField,
+ std::vector< OUString>& _rRightColumns,
+ const OUString& _sColumnName,
+ std::u16string_view _sExtraChars,
+ sal_Int32 _nMaxNameLen,
+ const ::comphelper::UStringMixEqual& _aCase);
+
+ void moveColumn( weld::TreeView* _pRight,
+ weld::TreeView const * _pLeft,
+ std::vector< OUString>& _rRightColumns,
+ const OUString& _sColumnName,
+ std::u16string_view _sExtraChars,
+ sal_Int32 _nMaxNameLen,
+ const ::comphelper::UStringMixEqual& _aCase);
+
+ void enableButtons();
+
+ sal_Int32 adjustColumnPosition(weld::TreeView const * _pLeft,
+ std::u16string_view _sColumnName,
+ ODatabaseExport::TColumnVector::size_type nCurrentPos,
+ const ::comphelper::UStringMixEqual& _aCase);
+
+ public:
+ virtual void Reset ( ) override;
+ virtual void Activate() override;
+ virtual bool LeavePage() override;
+ virtual OUString GetTitle() const override ;
+
+ OWizColumnSelect(weld::Container* pParent, OCopyTableWizard* pWizard);
+ virtual ~OWizColumnSelect() override;
+ };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/WCopyTable.hxx b/dbaccess/source/ui/inc/WCopyTable.hxx
new file mode 100644
index 000000000..613311283
--- /dev/null
+++ b/dbaccess/source/ui/inc/WCopyTable.hxx
@@ -0,0 +1,413 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <com/sun/star/container/XNameAccess.hpp>
+#include <com/sun/star/sdbc/XConnection.hpp>
+#include <com/sun/star/sdbc/XDatabaseMetaData.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <comphelper/stl_types.hxx>
+#include "TypeInfo.hxx"
+#include <vcl/roadmapwizard.hxx>
+#include "DExport.hxx"
+#include "WTabPage.hxx"
+#include "FieldDescriptions.hxx"
+#include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
+#include <com/sun/star/sdbcx/XKeysSupplier.hpp>
+#include <com/sun/star/task/XInteractionHandler.hpp>
+#include <map>
+#include <algorithm>
+
+namespace dbaui
+{
+
+ class TColumnFindFunctor
+ {
+ public:
+ virtual bool operator()(const OUString& _sColumnName) const = 0;
+
+ protected:
+ ~TColumnFindFunctor() {}
+ };
+
+ class TExportColumnFindFunctor : public TColumnFindFunctor
+ {
+ ODatabaseExport::TColumns* m_pColumns;
+ public:
+ TExportColumnFindFunctor(ODatabaseExport::TColumns* _pColumns)
+ {
+ m_pColumns = _pColumns;
+ }
+
+ virtual ~TExportColumnFindFunctor() {}
+
+ bool operator()(const OUString& _sColumnName) const override
+ {
+ return m_pColumns->find(_sColumnName) != m_pColumns->end();
+ }
+ };
+
+ class TMultiListBoxEntryFindFunctor : public TColumnFindFunctor
+ {
+ ::comphelper::UStringMixEqual m_aCase;
+ std::vector< OUString>* m_pVector;
+ public:
+ TMultiListBoxEntryFindFunctor(std::vector< OUString>* _pVector,
+ const ::comphelper::UStringMixEqual& _aCase)
+ :m_aCase(_aCase)
+ ,m_pVector(_pVector)
+ {
+ }
+
+ virtual ~TMultiListBoxEntryFindFunctor() {}
+
+ bool operator()(const OUString& _sColumnName) const override
+ {
+ return std::any_of(m_pVector->begin(),m_pVector->end(),
+ [this, &_sColumnName](const OUString& lhs)
+ { return m_aCase(lhs, _sColumnName); });
+ }
+ };
+
+ // ICopyTableSourceObject
+ /** interface to an object to copy to another DB, using the OCopyTableWizard
+
+ when the wizard is used to copy an object to another DB, it usually requires
+ a sdbcx-level or sdb-level object (a css.sdbcx.Table or css.sdb.Query, that is).
+
+ However, to also support copying tables from sdbc-level connections, we allow to
+ work with the object name only. This implies some less features (like copying the
+ UI settings of a table is not done), but still allows to copy definition and data.
+ */
+ class ICopyTableSourceObject
+ {
+ public:
+ /// retrieves the fully qualified name of the object to copy
+ virtual OUString getQualifiedObjectName() const = 0;
+ /// determines whether the object is a view
+ virtual bool isView() const = 0;
+ /** copies the UI settings of the object to the given target object. Might be
+ ignored by implementations which do not have Ui settings.
+ */
+ virtual void copyUISettingsTo( const css::uno::Reference< css::beans::XPropertySet >& _rxObject ) const = 0;
+ /// retrieves the column names of the to-be-copied object
+ virtual css::uno::Sequence< OUString >
+ getColumnNames() const = 0;
+ /// retrieves the names of the primary keys of the to-be-copied object
+ virtual css::uno::Sequence< OUString >
+ getPrimaryKeyColumnNames() const = 0;
+ /// creates a OFieldDescription for the given column of the to-be-copied object
+ virtual OFieldDescription* createFieldDescription( const OUString& _rColumnName ) const = 0;
+ /// returns the SELECT statement which can be used to retrieve the data of the to-be-copied object
+ virtual OUString getSelectStatement() const = 0;
+
+ /** copies the filter and sorting
+ *
+ * \return
+ */
+ virtual void copyFilterAndSortingTo(const css::uno::Reference< css::sdbc::XConnection >& _xConnection,const css::uno::Reference< css::beans::XPropertySet >& _rxObject ) const = 0;
+
+ /** returns the prepared statement which can be used to retrieve the data of the to-be-copied object
+
+ The default implementation of this method will simply prepare a statement with the return value
+ of ->getSelectStatement.
+ */
+ virtual ::utl::SharedUNOComponent< css::sdbc::XPreparedStatement >
+ getPreparedSelectStatement() const = 0;
+
+ virtual ~ICopyTableSourceObject();
+ };
+
+ // ObjectCopySource
+ class ObjectCopySource : public ICopyTableSourceObject
+ {
+ private:
+ css::uno::Reference< css::sdbc::XConnection > m_xConnection;
+ css::uno::Reference< css::sdbc::XDatabaseMetaData > m_xMetaData;
+ css::uno::Reference< css::beans::XPropertySet > m_xObject;
+ css::uno::Reference< css::beans::XPropertySetInfo > m_xObjectPSI;
+ css::uno::Reference< css::container::XNameAccess > m_xObjectColumns;
+
+ public:
+ ObjectCopySource(
+ const css::uno::Reference< css::sdbc::XConnection >& _rxConnection,
+ const css::uno::Reference< css::beans::XPropertySet >& _rxObject
+ );
+
+ // ICopyTableSourceObject overridables
+ virtual OUString getQualifiedObjectName() const override;
+ virtual bool isView() const override;
+ virtual void copyUISettingsTo( const css::uno::Reference< css::beans::XPropertySet >& _rxObject ) const override;
+ virtual void copyFilterAndSortingTo(const css::uno::Reference< css::sdbc::XConnection >& _xConnection, const css::uno::Reference< css::beans::XPropertySet >& _rxObject ) const override;
+ virtual css::uno::Sequence< OUString >
+ getColumnNames() const override;
+ virtual css::uno::Sequence< OUString >
+ getPrimaryKeyColumnNames() const override;
+ virtual OFieldDescription* createFieldDescription( const OUString& _rColumnName ) const override;
+ virtual OUString getSelectStatement() const override;
+ virtual ::utl::SharedUNOComponent< css::sdbc::XPreparedStatement >
+ getPreparedSelectStatement() const override;
+ };
+
+ // NamedTableCopySource
+ class NamedTableCopySource : public ICopyTableSourceObject
+ {
+ private:
+ css::uno::Reference< css::sdbc::XConnection > m_xConnection;
+ css::uno::Reference< css::sdbc::XDatabaseMetaData > m_xMetaData;
+ OUString m_sTableName;
+ OUString m_sTableCatalog;
+ OUString m_sTableSchema;
+ OUString m_sTableBareName;
+ std::vector< OFieldDescription > m_aColumnInfo;
+ ::utl::SharedUNOComponent< css::sdbc::XPreparedStatement > m_xStatement;
+
+ public:
+ NamedTableCopySource(
+ const css::uno::Reference< css::sdbc::XConnection >& _rxConnection,
+ const OUString& _rTableName
+ );
+
+ // ICopyTableSourceObject overridables
+ virtual OUString getQualifiedObjectName() const override;
+ virtual bool isView() const override;
+ virtual void copyUISettingsTo( const css::uno::Reference< css::beans::XPropertySet >& _rxObject ) const override;
+ virtual void copyFilterAndSortingTo(const css::uno::Reference< css::sdbc::XConnection >& _xConnection,const css::uno::Reference< css::beans::XPropertySet >& _rxObject ) const override;
+ virtual css::uno::Sequence< OUString >
+ getColumnNames() const override;
+ virtual css::uno::Sequence< OUString >
+ getPrimaryKeyColumnNames() const override;
+ virtual OFieldDescription* createFieldDescription( const OUString& _rColumnName ) const override;
+ virtual OUString getSelectStatement() const override;
+ virtual ::utl::SharedUNOComponent< css::sdbc::XPreparedStatement >
+ getPreparedSelectStatement() const override;
+
+ private:
+ void impl_ensureColumnInfo_throw();
+ ::utl::SharedUNOComponent< css::sdbc::XPreparedStatement > const &
+ impl_ensureStatement_throw();
+ };
+
+ // Wizard Dialog
+ class OCopyTableWizard : public vcl::RoadmapWizardMachine
+ {
+ friend class OWizColumnSelect;
+ friend class OWizTypeSelect;
+ friend class OWizTypeSelectControl;
+ friend class OCopyTable;
+ friend class OWizNameMatching;
+
+ public:
+ typedef std::map<OUString, OUString, ::comphelper::UStringMixLess> TNameMapping;
+
+ enum Wizard_Button_Style
+ {
+ WIZARD_NEXT,
+ WIZARD_PREV,
+ WIZARD_FINISH,
+
+ WIZARD_NONE
+ };
+
+ private:
+ ODatabaseExport::TColumns m_vDestColumns; // contains the columns
+ ODatabaseExport::TColumnVector m_aDestVec; // the order to insert the columns
+ ODatabaseExport::TColumns m_vSourceColumns;
+ ODatabaseExport::TColumnVector m_vSourceVec;
+
+ OTypeInfoMap m_aTypeInfo;
+ std::vector<OTypeInfoMap::iterator> m_aTypeInfoIndex;
+ OTypeInfoMap m_aDestTypeInfo;
+ std::vector<OTypeInfoMap::iterator> m_aDestTypeInfoIndex;
+ TNameMapping m_mNameMapping;
+
+ ODatabaseExport::TPositions m_vColumnPositions;
+ std::vector<sal_Int32> m_vColumnTypes;
+
+ css::uno::Reference< css::sdbc::XConnection > m_xDestConnection;
+
+ const ICopyTableSourceObject& m_rSourceObject;
+
+ css::uno::Reference< css::util::XNumberFormatter > m_xFormatter;
+ css::uno::Reference< css::uno::XComponentContext> m_xContext;
+ css::uno::Reference< css::task::XInteractionHandler> m_xInteractionHandler;
+
+ OUString m_sTypeNames; // these type names are the ones out of the resource file
+ sal_uInt32 m_nPageCount;
+ bool m_bDeleteSourceColumns;
+ bool m_bInterConnectionCopy; // are we copying between different connections?
+
+ css::lang::Locale m_aLocale;
+ OUString m_sName; // for a table the name is composed
+ OUString m_sSourceName;
+ OUString m_aKeyName;
+ TOTypeInfoSP m_pTypeInfo; // default type
+ bool m_bAddPKFirstTime;
+ sal_Int16 m_nOperation;
+ Wizard_Button_Style m_ePressed;
+ bool m_bCreatePrimaryKeyColumn;
+ bool m_bUseHeaderLine;
+
+ private:
+ DECL_LINK( ImplPrevHdl, weld::Button&, void );
+ DECL_LINK( ImplNextHdl, weld::Button&, void);
+ DECL_LINK( ImplOKHdl, weld::Button&, void );
+ bool CheckColumns(sal_Int32& _rnBreakPos);
+ void loadData( const ICopyTableSourceObject& _rSourceObject,
+ ODatabaseExport::TColumns& _rColumns,
+ ODatabaseExport::TColumnVector& _rColVector );
+ void construct();
+ // need for table creation
+ static void appendColumns( css::uno::Reference< css::sdbcx::XColumnsSupplier> const & _rxColSup, const ODatabaseExport::TColumnVector* _pVec, bool _bKeyColumns = false );
+ static void appendKey(css::uno::Reference< css::sdbcx::XKeysSupplier> const & _rxSup,const ODatabaseExport::TColumnVector* _pVec);
+ // checks if the type is supported in the destination database
+ bool supportsType(sal_Int32 _nDataType,sal_Int32& _rNewDataType);
+
+ virtual std::unique_ptr<BuilderPage> createPage(vcl::WizardTypes::WizardState /*nState*/) override
+ {
+ assert(false);
+ return nullptr;
+ }
+
+ virtual void ActivatePage() override;
+
+ sal_uInt16 GetCurLevel() const { return getCurrentState(); }
+
+ weld::Container* CreatePageContainer();
+
+ public:
+ // used for copy tables or queries
+ OCopyTableWizard(
+ weld::Window * pParent,
+ const OUString& _rDefaultName,
+ sal_Int16 _nOperation,
+ const ICopyTableSourceObject& _rSourceObject,
+ const css::uno::Reference< css::sdbc::XConnection >& _xSourceConnection,
+ const css::uno::Reference< css::sdbc::XConnection >& _xConnection,
+ const css::uno::Reference< css::uno::XComponentContext >& _rxContext,
+ const css::uno::Reference< css::task::XInteractionHandler>& _xInteractionHandler
+ );
+
+ // used for importing rtf/html sources
+ OCopyTableWizard(
+ weld::Window* pParent,
+ const OUString& _rDefaultName,
+ sal_Int16 _nOperation,
+ ODatabaseExport::TColumns&& _rDestColumns,
+ const ODatabaseExport::TColumnVector& _rSourceColVec,
+ const css::uno::Reference< css::sdbc::XConnection >& _xConnection,
+ const css::uno::Reference< css::util::XNumberFormatter >& _xFormatter,
+ TypeSelectionPageFactory _pTypeSelectionPageFactory,
+ SvStream& _rTypeSelectionPageArg,
+ const css::uno::Reference< css::uno::XComponentContext >& _rxContext
+ );
+
+ virtual ~OCopyTableWizard() override;
+
+ virtual bool DeactivatePage() override;
+ weld::Button& GetOKButton() { return *m_xFinish; }
+ Wizard_Button_Style GetPressedButton() const { return m_ePressed; }
+ void EnableNextButton(bool bEnable);
+ void AddWizardPage(std::unique_ptr<OWizardPage> xPage); // delete page from OCopyTableWizard
+ void CheckButtons(); // checks which button can be disabled, enabled
+
+ // returns a vector where the position of a column and if the column is in the selection
+ // when not the value is COLUMN_POSITION_NOT_FOUND.
+ const ODatabaseExport::TPositions& GetColumnPositions() const { return m_vColumnPositions; }
+ const std::vector<sal_Int32>& GetColumnTypes() const { return m_vColumnTypes; }
+ bool UseHeaderLine() const { return m_bUseHeaderLine; }
+ void setUseHeaderLine(bool _bUseHeaderLine) { m_bUseHeaderLine = _bUseHeaderLine; }
+
+ void insertColumn(sal_Int32 _nPos,OFieldDescription* _pField);
+
+ /** replaces a field description with another one. The name must not be known so far.
+ @param _nPos
+ The pos inside the vector, 0 based.
+ @param _pField
+ The field to set.
+ @param _sOldName
+ The name of column to be replaced.
+ */
+ void replaceColumn(sal_Int32 _nPos,OFieldDescription* _pField,const OUString& _sOldName);
+
+ /** returns whether a primary key should be created in the target database
+ */
+ bool shouldCreatePrimaryKey() const { return m_bCreatePrimaryKeyColumn;}
+ void setCreatePrimaryKey( bool _bDoCreate, const OUString& _rSuggestedName );
+
+ static bool supportsPrimaryKey( const css::uno::Reference< css::sdbc::XConnection >& _rxConnection );
+ bool supportsPrimaryKey() const { return supportsPrimaryKey( m_xDestConnection ); }
+
+ static bool supportsViews( const css::uno::Reference< css::sdbc::XConnection >& _rxConnection );
+ bool supportsViews() const { return supportsViews( m_xDestConnection ); }
+
+ /** returns the name of the primary key
+ @return
+ The name of the primary key.
+ */
+ const OUString& getPrimaryKeyName() const { return m_aKeyName; }
+
+ const OTypeInfoMap& getTypeInfo() const { return m_aTypeInfo; }
+
+ TOTypeInfoSP const & getDestTypeInfo(sal_Int32 _nPos) const { return m_aDestTypeInfoIndex[_nPos]->second; }
+ const OTypeInfoMap& getDestTypeInfo() const { return m_aDestTypeInfo; }
+
+ const css::lang::Locale& GetLocale() const { return m_aLocale; }
+ const css::uno::Reference< css::util::XNumberFormatter >& GetFormatter() const { return m_xFormatter; }
+ const css::uno::Reference< css::uno::XComponentContext>& GetComponentContext() const { return m_xContext; }
+
+ const ODatabaseExport::TColumns& getSourceColumns() const{ return m_vSourceColumns; }
+ const ODatabaseExport::TColumnVector& getSrcVector() const { return m_vSourceVec; }
+ ODatabaseExport::TColumns& getDestColumns() { return m_vDestColumns; }
+ const ODatabaseExport::TColumnVector& getDestVector() const { return m_aDestVec; }
+ const OUString& getName() const { return m_sName; }
+
+ /** clears the dest vectors
+ */
+ void clearDestColumns();
+
+ css::uno::Reference< css::beans::XPropertySet > returnTable();
+ css::uno::Reference< css::beans::XPropertySet > getTable() const;
+ css::uno::Reference< css::beans::XPropertySet > createTable();
+ css::uno::Reference< css::beans::XPropertySet > createView() const;
+ sal_Int32 getMaxColumnNameLength() const;
+
+ void setOperation( const sal_Int16 _nOperation );
+ sal_Int16 getOperation() const { return m_nOperation;}
+
+ OUString convertColumnName( const TColumnFindFunctor& _rCmpFunctor,
+ const OUString& _sColumnName,
+ std::u16string_view _sExtraChars,
+ sal_Int32 _nMaxNameLen);
+ TOTypeInfoSP convertType(const TOTypeInfoSP&_pType, bool& _bNotConvert);
+
+ OUString createUniqueName(const OUString& _sName);
+
+ // displays an error message that a column type is not supported
+ void showColumnTypeNotSupported(std::u16string_view _rColumnName);
+
+ void removeColumnNameFromNameMap(const OUString& _sName);
+ void showError(const OUString& _sErrorMessage);
+ void showError(const css::uno::Any& _aError);
+ };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/WExtendPages.hxx b/dbaccess/source/ui/inc/WExtendPages.hxx
new file mode 100644
index 000000000..7d75f2cc1
--- /dev/null
+++ b/dbaccess/source/ui/inc/WExtendPages.hxx
@@ -0,0 +1,69 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "WTypeSelect.hxx"
+
+class SvStream;
+namespace dbaui
+{
+ class OCopyTableWizard;
+
+ // Wizard Page: OWizHTMLExtend
+ class OWizHTMLExtend : public OWizTypeSelect
+ {
+ protected:
+ virtual void createReaderAndCallParser(sal_Int32 _nRows) override;
+ public:
+ OWizHTMLExtend(weld::Container* pPage, OCopyTableWizard* pWizard, SvStream& rStream)
+ : OWizTypeSelect(pPage, pWizard, &rStream)
+ {
+ }
+
+ static std::unique_ptr<OWizTypeSelect> Create(weld::Container* pPage, OCopyTableWizard* pWizard, SvStream& rInput ) { return std::make_unique<OWizHTMLExtend>(pPage, pWizard, rInput); }
+ };
+ // Wizard Page: OWizRTFExtend
+ class OWizRTFExtend : public OWizTypeSelect
+ {
+ protected:
+ virtual void createReaderAndCallParser(sal_Int32 _nRows) override;
+ public:
+ OWizRTFExtend(weld::Container* pPage, OCopyTableWizard* pWizard, SvStream& rStream)
+ : OWizTypeSelect(pPage, pWizard, &rStream)
+ {
+ }
+
+ static std::unique_ptr<OWizTypeSelect> Create(weld::Container* pPage, OCopyTableWizard* pWizard, SvStream& rInput) { return std::make_unique<OWizRTFExtend>(pPage, pWizard, rInput); }
+ };
+
+ // Wizard Page: OWizNormalExtend
+ class OWizNormalExtend : public OWizTypeSelect
+ {
+ protected:
+ virtual void createReaderAndCallParser(sal_Int32 _nRows) override;
+ public:
+ OWizNormalExtend(weld::Container* pPage, OCopyTableWizard* pWizard)
+ : OWizTypeSelect(pPage, pWizard)
+ {
+ EnableAuto(false);
+ }
+ };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/WNameMatch.hxx b/dbaccess/source/ui/inc/WNameMatch.hxx
new file mode 100644
index 000000000..d108c043c
--- /dev/null
+++ b/dbaccess/source/ui/inc/WNameMatch.hxx
@@ -0,0 +1,63 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "WTabPage.hxx"
+#include "DExport.hxx"
+#include "WCopyTable.hxx"
+
+namespace dbaui
+{
+ // Wizard Page: OWizNameMatching
+ // Name matching for data appending
+ class OWizNameMatching : public OWizardPage
+ {
+ std::unique_ptr<weld::Label> m_xTABLE_LEFT;
+ std::unique_ptr<weld::Label> m_xTABLE_RIGHT;
+ std::unique_ptr<weld::TreeView> m_xCTRL_LEFT; // left side
+ std::unique_ptr<weld::TreeView> m_xCTRL_RIGHT; // right side
+ std::unique_ptr<weld::Button> m_xColumn_up;
+ std::unique_ptr<weld::Button> m_xColumn_down;
+ std::unique_ptr<weld::Button> m_xColumn_up_right;
+ std::unique_ptr<weld::Button> m_xColumn_down_right;
+ std::unique_ptr<weld::Button> m_xAll;
+ std::unique_ptr<weld::Button> m_xNone;
+ OUString m_sSourceText;
+ OUString m_sDestText;
+
+ DECL_LINK( ButtonClickHdl, weld::Button&, void );
+ DECL_LINK( RightButtonClickHdl, weld::Button&, void );
+ DECL_LINK( AllNoneClickHdl, weld::Button&, void );
+ DECL_LINK( TableListClickHdl, weld::TreeView&, void );
+ DECL_LINK( TableListRightSelectHdl, weld::TreeView&, void );
+
+ static void FillListBox(weld::TreeView& rTreeView, const ODatabaseExport::TColumnVector& rList, bool bCheckButtons);
+
+ public:
+ virtual void Reset ( ) override;
+ virtual void Activate() override;
+ virtual bool LeavePage() override;
+ virtual OUString GetTitle() const override ;
+
+ OWizNameMatching(weld::Container* pPage, OCopyTableWizard* pWizard);
+ virtual ~OWizNameMatching() override;
+ };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/WTabPage.hxx b/dbaccess/source/ui/inc/WTabPage.hxx
new file mode 100644
index 000000000..cc7564cba
--- /dev/null
+++ b/dbaccess/source/ui/inc/WTabPage.hxx
@@ -0,0 +1,46 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <vcl/wizardmachine.hxx>
+
+namespace dbaui
+{
+ // Wizard Page
+ class OCopyTableWizard;
+ class OWizardPage : public ::vcl::OWizardPage
+ {
+ protected:
+ OCopyTableWizard* m_pParent;
+ bool m_bFirstTime; // Page is called the first time; should be set in the reset method
+
+ OWizardPage(weld::Container* pPage, OCopyTableWizard* pWizard, const OUString& rUIXMLDescription, const OString& rID);
+
+ public:
+ virtual ~OWizardPage() override;
+ virtual void Reset ( ) = 0;
+ virtual bool LeavePage() = 0;
+ virtual OUString GetTitle() const = 0;
+
+ bool IsFirstTime() const { return m_bFirstTime; }
+ };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/WTypeSelect.hxx b/dbaccess/source/ui/inc/WTypeSelect.hxx
new file mode 100644
index 000000000..8a953302a
--- /dev/null
+++ b/dbaccess/source/ui/inc/WTypeSelect.hxx
@@ -0,0 +1,139 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "FieldDescControl.hxx"
+#include "TypeInfo.hxx"
+#include "WTabPage.hxx"
+
+class SvStream;
+
+namespace dbaui
+{
+ class OWizTypeSelect;
+ class OTableDesignHelpBar;
+ // OWizTypeSelectControl
+ class OWizTypeSelectControl final : public OFieldDescControl
+ {
+ OWizTypeSelect* m_pParentTabPage;
+ virtual void ActivateAggregate( EControlType eType ) override;
+ virtual void DeactivateAggregate( EControlType eType ) override;
+
+ virtual void CellModified(sal_Int32 nRow, sal_uInt16 nColId ) override;
+
+ virtual css::lang::Locale GetLocale() const override;
+ virtual css::uno::Reference< css::util::XNumberFormatter > GetFormatter() const override;
+ virtual TOTypeInfoSP getTypeInfo(sal_Int32 _nPos) override;
+ virtual const OTypeInfoMap* getTypeInfo() const override;
+ virtual bool isAutoIncrementValueEnabled() const override;
+ virtual OUString getAutoIncrementValue() const override;
+
+ public:
+ OWizTypeSelectControl(weld::Container* pPage, OWizTypeSelect* pParentTabPage);
+ virtual ~OWizTypeSelectControl() override;
+
+ virtual css::uno::Reference< css::sdbc::XDatabaseMetaData> getMetaData() override;
+ virtual css::uno::Reference< css::sdbc::XConnection> getConnection() override;
+ };
+
+ // Wizard Page: OWizTypeSelectList
+ // just defines the css::ucb::Command for the Contextmenu
+ class OWizTypeSelectList
+ {
+ std::unique_ptr<weld::TreeView> m_xControl;
+ bool m_bPKey;
+ bool IsPrimaryKeyAllowed() const;
+ void setPrimaryKey( OFieldDescription* _pFieldDescr,
+ sal_uInt16 _nPos,
+ bool _bSet = false);
+
+ DECL_LINK(CommandHdl, const CommandEvent&, bool);
+
+ Link<weld::TreeView&, void> m_aChangeHdl;
+
+ public:
+ OWizTypeSelectList(std::unique_ptr<weld::TreeView> xControl);
+ void SetPKey(bool bPKey) { m_bPKey = bPKey; }
+ weld::TreeView* GetWidget() { return m_xControl.get(); }
+ OUString get_selected_id() const { return m_xControl->get_selected_id(); }
+ void clear() { m_xControl->clear(); }
+ void append(const OUString& rId, const OUString& rStr)
+ {
+ m_xControl->append(rId, rStr);
+ }
+ void set_image(int nRow, const OUString& rImage)
+ {
+ m_xControl->set_image(nRow, rImage);
+ }
+ void set_selection_mode(SelectionMode eMode) { m_xControl->set_selection_mode(eMode); }
+ int count_selected_rows() const { return m_xControl->count_selected_rows(); }
+ void select(int pos) { m_xControl->select(pos); }
+ void connect_changed(const Link<weld::TreeView&, void>& rLink)
+ {
+ m_aChangeHdl = rLink;
+ m_xControl->connect_changed(rLink);
+ }
+ };
+
+ // Wizard Page: OWizTypeSelect
+ // Serves as base class for different copy properties.
+ // Calls FillColumnList, when button AUTO is triggered
+ class OWizTypeSelect : public OWizardPage
+ {
+ friend class OWizTypeSelectControl;
+ friend class OWizTypeSelectList;
+
+ DECL_LINK( ColumnSelectHdl, weld::TreeView&, void );
+ DECL_LINK( ButtonClickHdl, weld::Button&, void );
+ protected:
+ std::unique_ptr<OWizTypeSelectList> m_xColumnNames;
+ std::unique_ptr<weld::Label> m_xColumns;
+ std::unique_ptr<weld::Container> m_xControlContainer;
+ std::unique_ptr<OWizTypeSelectControl> m_xTypeControl;
+ std::unique_ptr<weld::Label> m_xAutoType;
+ std::unique_ptr<weld::Label> m_xAutoFt;
+ std::unique_ptr<weld::SpinButton> m_xAutoEt;
+ std::unique_ptr<weld::Button> m_xAutoPb;
+
+ SvStream* m_pParserStream; // stream to read the tokens from or NULL
+ OUString m_sAutoIncrementValue;
+ sal_Int32 m_nDisplayRow;
+ bool m_bAutoIncrementEnabled;
+ bool m_bDuplicateName;
+
+ virtual void createReaderAndCallParser(sal_Int32 _nRows) = 0;
+
+ void EnableAuto(bool bEnable);
+ public:
+ virtual void Reset ( ) override;
+ virtual void Activate( ) override;
+ virtual bool LeavePage() override;
+ virtual OUString GetTitle() const override;
+
+ OWizTypeSelect(weld::Container* pParent, OCopyTableWizard* pWizard, SvStream* pStream = nullptr);
+ virtual ~OWizTypeSelect() override;
+
+ void setDisplayRow(sal_Int32 _nRow) { m_nDisplayRow = _nRow - 1; }
+ void setDuplicateName(bool _bDuplicateName) { m_bDuplicateName = _bDuplicateName; }
+ };
+
+ typedef std::unique_ptr<OWizTypeSelect> (*TypeSelectionPageFactory)(weld::Container*, OCopyTableWizard*, SvStream&);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/adtabdlg.hxx b/dbaccess/source/ui/inc/adtabdlg.hxx
new file mode 100644
index 000000000..5fe1d7c1d
--- /dev/null
+++ b/dbaccess/source/ui/inc/adtabdlg.hxx
@@ -0,0 +1,98 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <memory>
+#include <com/sun/star/sdbc/XConnection.hpp>
+#include <vcl/weld.hxx>
+#include "tabletree.hxx"
+
+namespace dbaui
+{
+ /** unifies the access to a list of table/query objects
+ */
+ class TableObjectListFacade
+ {
+ public:
+ virtual void updateTableObjectList( bool _bAllowViews ) = 0;
+ virtual OUString getSelectedName( OUString& _out_rAliasName ) const = 0;
+ virtual bool isLeafSelected() const = 0;
+
+ virtual ~TableObjectListFacade();
+ };
+
+ class IAddTableDialogContext
+ {
+ public:
+ virtual css::uno::Reference< css::sdbc::XConnection >
+ getConnection() const = 0;
+ virtual bool allowViews() const = 0;
+ virtual bool allowQueries() const = 0;
+ virtual bool allowAddition() const = 0;
+ virtual void addTableWindow( const OUString& _rQualifiedTableName, const OUString& _rAliasName ) = 0;
+ virtual void onWindowClosing() = 0;
+
+ protected:
+ ~IAddTableDialogContext() {}
+ };
+
+ class OAddTableDlg : public weld::GenericDialogController
+ {
+ IAddTableDialogContext& m_rContext;
+ std::unique_ptr< TableObjectListFacade > m_xCurrentList;
+
+ std::unique_ptr<weld::RadioButton> m_xCaseTables;
+ std::unique_ptr<weld::RadioButton> m_xCaseQueries;
+
+ std::unique_ptr<OTableTreeListBox> m_xTableList;
+ std::unique_ptr<weld::TreeView> m_xQueryList;
+
+ std::unique_ptr<weld::Button> m_xAddButton;
+ std::unique_ptr<weld::Button> m_xCloseButton;
+
+ DECL_LINK( AddClickHdl, weld::Button&, void );
+ DECL_LINK( CloseClickHdl, weld::Button&, void);
+ DECL_LINK( TableListDoubleClickHdl, weld::TreeView&, bool );
+ DECL_LINK( TableListSelectHdl, weld::TreeView&, void );
+ DECL_LINK( OnTypeSelected, weld::Toggleable&, void );
+
+ public:
+ OAddTableDlg(weld::Window* _pParent,
+ IAddTableDialogContext& _rContext);
+ virtual ~OAddTableDlg() override;
+
+ void Update();
+ void OnClose();
+
+ static OUString getDialogTitleForContext(
+ IAddTableDialogContext const & _rContext );
+
+ private:
+ bool impl_isAddAllowed();
+
+ enum ObjectList
+ {
+ Tables,
+ Queries
+ };
+ void impl_switchTo( ObjectList _eList );
+ };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/advancedsettingsdlg.hxx b/dbaccess/source/ui/inc/advancedsettingsdlg.hxx
new file mode 100644
index 000000000..b28fe5ce3
--- /dev/null
+++ b/dbaccess/source/ui/inc/advancedsettingsdlg.hxx
@@ -0,0 +1,70 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include "IItemSetHelper.hxx"
+#include <sfx2/tabdlg.hxx>
+#include <memory>
+
+namespace dbaui
+{
+
+ // AdvancedSettingsDialog
+ class ODbDataSourceAdministrationHelper;
+ /** implements the advanced page dlg of the data source properties.
+ */
+ class AdvancedSettingsDialog : public SfxTabDialogController
+ , public IItemSetHelper
+ , public IDatabaseSettingsDialog
+ {
+ std::unique_ptr<ODbDataSourceAdministrationHelper> m_pImpl;
+
+ protected:
+ virtual void PageCreated(const OString& rId, SfxTabPage& _rPage) override;
+ virtual short Ok() override;
+
+ public:
+ AdvancedSettingsDialog(weld::Window* pParent,
+ SfxItemSet* _pItems,
+ const css::uno::Reference< css::uno::XComponentContext >& _rxORB,
+ const css::uno::Any& _aDataSourceName);
+
+ virtual ~AdvancedSettingsDialog() override;
+
+ /// determines whether or not the given data source type has any advanced setting
+ static bool doesHaveAnyAdvancedSettings( const OUString& _sURL );
+
+ virtual const SfxItemSet* getOutputSet() const override;
+ virtual SfxItemSet* getWriteOutputSet() override;
+
+ // forwards to ODbDataSourceAdministrationHelper
+ virtual css::uno::Reference< css::uno::XComponentContext > getORB() const override;
+ virtual std::pair< css::uno::Reference< css::sdbc::XConnection >,bool> createConnection() override;
+ virtual css::uno::Reference< css::sdbc::XDriver > getDriver() override;
+ virtual OUString getDatasourceType(const SfxItemSet& _rSet) const override;
+ virtual void clearPassword() override;
+ virtual void saveDatasource() override;
+ virtual void setTitle(const OUString& _sTitle) override;
+ virtual void enableConfirmSettings( bool _bEnable ) override;
+ };
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/asyncmodaldialog.hxx b/dbaccess/source/ui/inc/asyncmodaldialog.hxx
new file mode 100644
index 000000000..483dfb7c1
--- /dev/null
+++ b/dbaccess/source/ui/inc/asyncmodaldialog.hxx
@@ -0,0 +1,47 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <com/sun/star/ui/dialogs/XExecutableDialog.hpp>
+
+namespace dbaui
+{
+
+ // AsyncDialogExecutor
+ /** helper class for executing (UNO) dialogs modal, but asynchronously
+ */
+ class AsyncDialogExecutor
+ {
+ public:
+ /** executes the given dialog asynchronously, but still modal
+
+ @throws IllegalArgumentException
+ if the given dialog is <NULL/>
+ @todo
+ allow for a callback for the result
+ */
+ static void executeModalDialogAsync(
+ const css::uno::Reference< css::ui::dialogs::XExecutableDialog >& _rxDialog
+ );
+ };
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/browserids.hxx b/dbaccess/source/ui/inc/browserids.hxx
new file mode 100644
index 000000000..0c510497d
--- /dev/null
+++ b/dbaccess/source/ui/inc/browserids.hxx
@@ -0,0 +1,98 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <svx/svxids.hrc>
+#include <dbaccess_slotid.hrc>
+
+#define ID_BROWSER_COPY SID_COPY
+#define ID_BROWSER_CUT SID_CUT
+#define ID_BROWSER_EDITDOC SID_EDITDOC
+#define ID_BROWSER_UNDORECORD SID_FM_RECORD_UNDO
+#define ID_BROWSER_SAVERECORD SID_FM_RECORD_SAVE
+#define ID_BROWSER_PASTE SID_PASTE
+#define ID_BROWSER_CLIPBOARD_FORMAT_ITEMS SID_CLIPBOARD_FORMAT_ITEMS
+#define ID_BROWSER_REDO SID_REDO
+#define ID_BROWSER_SAVEDOC SID_SAVEDOC
+#define ID_BROWSER_SAVEASDOC SID_SAVEASDOC
+#define ID_BROWSER_TITLE SID_DOCINFO_TITLE
+#define ID_BROWSER_UNDO SID_UNDO
+#define ID_BROWSER_INSERTCOLUMNS SID_SBA_BRW_INSERT
+#define ID_BROWSER_FORMLETTER SID_SBA_BRW_MERGE
+#define ID_BROWSER_INSERTCONTENT SID_SBA_BRW_UPDATE
+
+#define ID_BROWSER_SEARCH SID_FM_SEARCH
+#define ID_BROWSER_SORTUP SID_FM_SORTUP
+#define ID_BROWSER_SORTDOWN SID_FM_SORTDOWN
+#define ID_BROWSER_AUTOFILTER SID_FM_AUTOFILTER
+#define ID_BROWSER_FILTERCRIT SID_FM_FILTERCRIT
+#define ID_BROWSER_ORDERCRIT SID_FM_ORDERCRIT
+#define ID_BROWSER_REMOVEFILTER SID_FM_REMOVE_FILTER_SORT
+#define ID_BROWSER_FILTERED SID_FM_FORM_FILTERED
+#define ID_BROWSER_REFRESH SID_FM_REFRESH
+#define ID_BROWSER_COLATTRSET 10020 // column formatting
+#define ID_BROWSER_COLWIDTH 10021 // column width
+#define ID_BROWSER_TABLEATTR 10022 // table format attributes
+#define ID_BROWSER_ROWHEIGHT 10023 // row height
+#define ID_BROWSER_ADDTABLE SID_FM_ADDTABLE
+#define ID_BROWSER_EXPLORER SID_DSBROWSER_EXPLORER
+#define ID_BROWSER_DOCUMENT_DATASOURCE SID_DOCUMENT_DATA_SOURCE
+
+// The following ids are local to special components (e.g. menus), so they don't need to be unique
+// overall. Please have this in mind when changing anything
+#define ID_TREE_EDIT_DATABASE 1
+#define ID_TREE_CLOSE_CONN 2
+ // FREE
+#define ID_TREE_ADMINISTRATE 4
+
+#define ID_REPORT_NEW_TEXT 14
+#define ID_FORM_NEW_TEXT 15
+#define ID_FORM_NEW_CALC 16
+#define ID_FORM_NEW_IMPRESS 17
+#define ID_NEW_QUERY_DESIGN 20
+#define ID_EDIT_QUERY_DESIGN 21
+#define ID_NEW_QUERY_SQL 22
+#define ID_EDIT_QUERY_SQL 23
+#define ID_NEW_TABLE_DESIGN 25
+#define ID_NEW_VIEW_DESIGN 28
+#define ID_DIRECT_SQL 32
+#define ID_BROWSER_REFRESH_REBUILD 34
+#define ID_INDEX_NEW 36
+#define ID_INDEX_DROP 37
+#define ID_INDEX_RENAME 38
+#define ID_INDEX_SAVE 39
+#define ID_INDEX_RESET 40
+#define ID_DOCUMENT_CREATE_REPWIZ 41
+#define ID_BROWSER_SQL 42
+
+#define ID_APP_NEW_QUERY_AUTO_PILOT 44
+#define ID_NEW_TABLE_DESIGN_AUTO_PILOT 45
+#define ID_NEW_VIEW_DESIGN_AUTO_PILOT 46
+
+
+// other
+#define ID_BROWSER_QUERY_EXECUTE SID_FM_EXECUTE
+
+#define ID_BROWSER_CLOSE SID_CLOSEWIN
+#define ID_BROWSER_ESCAPEPROCESSING SID_FM_NATIVESQL
+
+#define ID_BROWSER_INSERT_ROW (SID_SBA_START + 46) // insert row
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/brwctrlr.hxx b/dbaccess/source/ui/inc/brwctrlr.hxx
new file mode 100644
index 000000000..e5e1db401
--- /dev/null
+++ b/dbaccess/source/ui/inc/brwctrlr.hxx
@@ -0,0 +1,332 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <dbaccess/genericcontroller.hxx>
+#include "brwview.hxx"
+#include "sbagrid.hxx"
+
+#include <com/sun/star/form/XLoadable.hpp>
+#include <com/sun/star/container/XContainerListener.hpp>
+#include <com/sun/star/sdb/XSQLErrorListener.hpp>
+#include <com/sun/star/sdbc/XRowSet.hpp>
+#include <com/sun/star/form/XResetListener.hpp>
+#include <com/sun/star/form/XDatabaseParameterListener.hpp>
+#include <com/sun/star/form/XConfirmDeleteListener.hpp>
+#include <com/sun/star/form/XFormComponent.hpp>
+#include <com/sun/star/awt/XFocusListener.hpp>
+#include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
+#include <com/sun/star/sdb/XSingleSelectQueryComposer.hpp>
+#include <com/sun/star/beans/XPropertyChangeListener.hpp>
+#include <com/sun/star/frame/XModule.hpp>
+
+#include <vcl/timer.hxx>
+#include <vcl/transfer.hxx>
+#include <cppuhelper/implbase.hxx>
+#include <svtools/cliplistener.hxx>
+
+struct FmFoundRecordInformation;
+struct FmSearchContext;
+
+namespace dbtools
+{
+ class SQLExceptionInfo;
+}
+
+namespace dbaui
+{
+
+ typedef ::cppu::ImplInheritanceHelper < OGenericUnoController
+ , css::sdb::XSQLErrorListener
+ , css::form::XDatabaseParameterListener
+ , css::form::XConfirmDeleteListener
+ , css::form::XLoadListener
+ , css::form::XResetListener
+ , css::awt::XFocusListener
+ , css::container::XContainerListener
+ , css::beans::XPropertyChangeListener
+ , css::frame::XModule
+ > SbaXDataBrowserController_Base;
+
+ class SbaXDataBrowserController :public SbaXDataBrowserController_Base
+ ,public SbaGridListener
+ {
+ // attributes
+ private:
+ // for implementing the XFormController
+ class FormControllerImpl;
+ friend class FormControllerImpl;
+
+ css::uno::Reference< css::sdbc::XRowSet > m_xRowSet; // our rowset
+ css::uno::Reference< css::sdbcx::XColumnsSupplier > m_xColumnsSupplier; // queried from the rowset member
+ css::uno::Reference< css::form::XLoadable > m_xLoadable; // queried from the rowset member as well
+ css::uno::Reference< css::form::XFormComponent > m_xGridModel; // the model of our grid
+ css::uno::Reference< css::util::XNumberFormatter > m_xFormatter; // a number formatter working with the connection's NumberFormatsSupplier
+ mutable css::uno::Reference< css::sdb::XSingleSelectQueryComposer >
+ m_xParser; // for sorting 'n filtering
+
+ sal_Int32 m_nRowSetPrivileges; // cached Privileges property of m_xRowSet
+
+ AutoTimer m_aInvalidateClipboard; // for testing the state of the CUT/COPY/PASTE-slots
+
+ TransferableDataHelper m_aSystemClipboard; // content of the clipboard
+ rtl::Reference<TransferableClipboardListener>
+ m_pClipboardNotifier; // notifier for changes in the clipboard
+
+ OAsynchronousLink m_aAsyncGetCellFocus;
+ OAsynchronousLink m_aAsyncDisplayError;
+ ::dbtools::SQLExceptionInfo m_aCurrentError;
+
+ OUString m_sStateSaveRecord;
+ OUString m_sStateUndoRecord;
+ OUString m_sModuleIdentifier;
+
+ // members for asynchronous load operations
+ rtl::Reference<FormControllerImpl> m_xFormControllerImpl; // implementing the XFormController
+
+ sal_uInt16 m_nFormActionNestingLevel; // see enter-/leaveFormAction
+
+ bool m_bLoadCanceled : 1; // the load was canceled somehow
+ bool m_bCannotSelectUnfiltered : 1; // received a DATA_CANNOT_SELECT_UNFILTERED error
+
+ protected:
+ class FormErrorHelper final
+ {
+ SbaXDataBrowserController* m_pOwner;
+ public:
+ FormErrorHelper(SbaXDataBrowserController* pOwner) : m_pOwner(pOwner) { m_pOwner->enterFormAction(); }
+ ~FormErrorHelper() { m_pOwner->leaveFormAction(); }
+ };
+ friend class FormErrorHelper;
+
+ // attribute access
+ protected:
+ const css::uno::Reference< css::sdbc::XRowSet >& getRowSet() const { return m_xRowSet; }
+ const css::uno::Reference< css::form::XLoadable >& getLoadable() const { return m_xLoadable; }
+
+ const css::uno::Reference< css::form::XFormComponent >& getFormComponent() const { return m_xGridModel; }
+ css::uno::Reference< css::awt::XControlModel > getControlModel() const { return css::uno::Reference< css::awt::XControlModel > (m_xGridModel, css::uno::UNO_QUERY); }
+ const css::uno::Reference< css::util::XNumberFormatter >& getNumberFormatter()const { return m_xFormatter; }
+
+ bool isValid() const { return m_xRowSet.is() && m_xGridModel.is(); }
+ bool isValidCursor() const; // checks the css::data::XDatabaseCursor-interface of m_xRowSet
+ bool isLoaded() const;
+ bool loadingCancelled() const { return m_bLoadCanceled; }
+ void onStartLoading( const css::uno::Reference< css::form::XLoadable >& _rxLoadable );
+ void setLoadingCancelled() { m_bLoadCanceled = true; }
+
+ public:
+ SbaXDataBrowserController(const css::uno::Reference< css::uno::XComponentContext >& _rM);
+
+ UnoDataBrowserView* getBrowserView() const { return static_cast< UnoDataBrowserView*>(getView()); }
+ // late construction
+ virtual bool Construct(vcl::Window* pParent) override;
+
+ // UNO
+ virtual css::uno::Any SAL_CALL queryInterface(const css::uno::Type& _rType) override;
+
+ // XTypeProvider
+ virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes( ) override;
+ virtual css::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId( ) override;
+
+ // css::lang::XEventListener
+ virtual void SAL_CALL disposing(const css::lang::EventObject& Source) override;
+
+ // css::util::XModifyListener
+ virtual void SAL_CALL modified(const css::lang::EventObject& aEvent) override;
+
+ // css::container::XContainerListener
+ virtual void SAL_CALL elementInserted(const css::container::ContainerEvent& Event) override;
+ virtual void SAL_CALL elementRemoved(const css::container::ContainerEvent& Event) override;
+ virtual void SAL_CALL elementReplaced(const css::container::ContainerEvent& Event) override;
+
+ // XPropertyChangeListener
+ virtual void SAL_CALL propertyChange( const css::beans::PropertyChangeEvent& evt ) override;
+
+ // XModule
+ virtual void SAL_CALL setIdentifier( const OUString& Identifier ) override;
+ virtual OUString SAL_CALL getIdentifier( ) override;
+
+ // css::awt::XFocusListener
+ virtual void SAL_CALL focusGained(const css::awt::FocusEvent& e) override;
+ virtual void SAL_CALL focusLost(const css::awt::FocusEvent& e) override;
+
+ // css::frame::XController
+ virtual sal_Bool SAL_CALL suspend(sal_Bool bSuspend) override;
+
+ // css::lang::XComponent
+ virtual void SAL_CALL disposing() override;
+
+ // css::frame::XFrameActionListener
+ virtual void SAL_CALL frameAction(const css::frame::FrameActionEvent& aEvent) override;
+
+ // css::sdb::XSQLErrorListener
+ virtual void SAL_CALL errorOccured(const css::sdb::SQLErrorEvent& aEvent) override;
+
+ // css::form::XDatabaseParameterListener
+ virtual sal_Bool SAL_CALL approveParameter(const css::form::DatabaseParameterEvent& aEvent) override;
+
+ // css::form::XConfirmDeleteListener
+ virtual sal_Bool SAL_CALL confirmDelete(const css::sdb::RowChangeEvent& aEvent) override;
+
+ // css::form::XLoadListener
+ virtual void SAL_CALL loaded(const css::lang::EventObject& aEvent) override;
+ virtual void SAL_CALL unloading(const css::lang::EventObject& aEvent) override;
+ virtual void SAL_CALL unloaded(const css::lang::EventObject& aEvent) override;
+ virtual void SAL_CALL reloading(const css::lang::EventObject& aEvent) override;
+ virtual void SAL_CALL reloaded(const css::lang::EventObject& aEvent) override;
+
+ // css::form::XResetListener
+ virtual sal_Bool SAL_CALL approveReset(const css::lang::EventObject& rEvent) override;
+ virtual void SAL_CALL resetted(const css::lang::EventObject& rEvent) override;
+
+ // SbaGridListener
+ virtual void RowChanged() override;
+ virtual void ColumnChanged() override;
+ virtual void SelectionChanged() override;
+ virtual void CellActivated() override;
+ virtual void CellDeactivated() override;
+ virtual void BeforeDrop() override;
+ virtual void AfterDrop() override;
+
+ public:
+
+ protected:
+ virtual ~SbaXDataBrowserController() override;
+
+ // all the features which should be handled by this class
+ virtual void describeSupportedFeatures() override;
+ // state of a feature. 'feature' may be the handle of a css::util::URL somebody requested a dispatch interface for OR a toolbar slot.
+ virtual FeatureState GetState(sal_uInt16 nId) const override;
+ // execute a feature
+ virtual void Execute(sal_uInt16 nId, const css::uno::Sequence< css::beans::PropertyValue>& aArgs) override;
+
+ virtual void startFrameListening( const css::uno::Reference< css::frame::XFrame >& _rxFrame ) override;
+ virtual void stopFrameListening( const css::uno::Reference< css::frame::XFrame >& _rxFrame ) override;
+
+ virtual css::uno::Reference< css::sdbc::XRowSet > CreateForm();
+ // our default implementation simply instantiates a stardiv.one.form.component.Form service
+ // (probably this needs not to be overridden, but you may return anything you want as long as it
+ // supports the css::form::DatabaseForm service. For instance you may want to create an adapter here which
+ // is synchronized with a foreign css::form::DatabaseForm you got elsewhere)
+ virtual bool InitializeForm(
+ const css::uno::Reference< css::beans::XPropertySet >& i_formProperties ) = 0;
+ // called immediately after a successful CreateForm
+ // do any initialization (data source etc.) here. the form should be fully functional after that.
+ // return sal_False if you didn't succeed (don't throw exceptions, they won't be caught)
+
+ css::uno::Reference< css::form::XFormComponent > CreateGridModel();
+ // our default implementation simply instantiates a stardiv.one.form.component.Grid service
+ // you most probably don't want to override this behavior
+
+ // the default implementation of disposing distributes the events to the following disposingXXX functions
+ void disposingFormModel(const css::lang::EventObject& Source);
+ void disposingColumnModel(const css::lang::EventObject& Source);
+
+ // want to be a listener to the grid control ? use this !
+ void addControlListeners(const css::uno::Reference< css::awt::XControl > & _xGridControl);
+ void removeControlListeners(const css::uno::Reference< css::awt::XControl > & _xGridControl);
+
+ // want to be a listener to the grid model ? use this !
+ virtual void addModelListeners(const css::uno::Reference< css::awt::XControlModel > & _xGridControlModel);
+ virtual void removeModelListeners(const css::uno::Reference< css::awt::XControlModel > & _xGridControlModel);
+
+ // want to be a listener grid columns ? use this !
+ virtual void AddColumnListener(const css::uno::Reference< css::beans::XPropertySet > & xCol);
+ virtual void RemoveColumnListener(const css::uno::Reference< css::beans::XPropertySet > & xCol);
+
+ // call after "major changes" (e.g. the completion of the async load).
+ // invalidates all toolbox slots and all supported features.
+
+ virtual bool LoadForm();
+ // load the form
+ // the default implementation does a direct load or starts a load thread, depending on the multithread capabilities
+ // of the data source.
+ // the default implementation also calls LoadFinished after a synchronous load, so be sure to do the same if you override
+ // this method and don't call the base class' method
+
+ virtual void LoadFinished(bool bWasSynch);
+ // called if the loading (the _complete_ loading process) is done (no matter if synchron or asynchron).
+
+ virtual void criticalFail();
+ // called whenever a reload operation on the rowset failed
+ // (an "operation" is not only a simple reload: if the user sets a filter, and reloading the form
+ // after setting this filter fails, the filter is reset and the form is reloaded, again. Only the
+ // whole process (_both_ XLoadable::reload calls _together_) form the "reload operation"
+
+ // empty the frame where our view resides
+ bool CommitCurrent();
+ // commit the current column (i.e. cell)
+ bool SaveModified(bool bAskFor = true);
+ // save the modified record
+
+ css::uno::Reference< css::beans::XPropertySet > getBoundField() const;
+ // a PropertySet corresponding to the cursor field a column is bound to.
+ // The field for the current column will be retrieved.
+
+ void enterFormAction();
+ void leaveFormAction();
+
+ // init the formatter if form changes
+ void initFormatter();
+
+ /// loads or reloads the form
+ bool reloadForm(const css::uno::Reference< css::form::XLoadable >& _rxLoadable);
+
+ virtual bool preReloadForm(){ return false; }
+ virtual void postReloadForm(){}
+
+ css::uno::Reference< css::sdb::XSingleSelectQueryComposer >
+ createParser_nothrow();
+
+ private:
+ void setCurrentModified( bool _bSet );
+
+ // execute the filter or sort slot
+ void ExecuteFilterSortCrit(bool bFilter);
+
+ // execute the search slot
+ void ExecuteSearch();
+
+ void initializeParser() const; // changes the mutable member m_xParser
+ void applyParserFilter(const OUString& _rOldFilter, bool _bOldFilterApplied,const ::OUString& _sOldHaving,const css::uno::Reference< css::sdb::XSingleSelectQueryComposer >& _xParser);
+ void applyParserOrder(const OUString& _rOldOrder,const css::uno::Reference< css::sdb::XSingleSelectQueryComposer >& _xParser);
+
+ sal_Int16 getCurrentColumnPosition() const;
+ void setCurrentColumnPosition( sal_Int16 _nPos );
+ void addColumnListeners(const css::uno::Reference< css::awt::XControlModel > & _xGridControlModel);
+
+ void impl_checkForCannotSelectUnfiltered( const ::dbtools::SQLExceptionInfo& _rError );
+
+ // time to check the CUT/COPY/PASTE-slot-states
+ DECL_LINK( OnInvalidateClipboard, Timer*, void );
+ DECL_LINK( OnClipboardChanged, TransferableDataHelper*, void );
+
+ // search callbacks
+ DECL_LINK(OnSearchContextRequest, FmSearchContext&, sal_uInt32);
+ DECL_LINK(OnFoundData, FmFoundRecordInformation&, void);
+ DECL_LINK(OnCanceledNotFound, FmFoundRecordInformation&, void);
+
+ DECL_LINK( OnAsyncGetCellFocus, void*, void );
+ DECL_LINK( OnAsyncDisplayError, void*, void );
+ };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/brwview.hxx b/dbaccess/source/ui/inc/brwview.hxx
new file mode 100644
index 000000000..0933861b8
--- /dev/null
+++ b/dbaccess/source/ui/inc/brwview.hxx
@@ -0,0 +1,96 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <vcl/window.hxx>
+
+#include <dbaccess/dataview.hxx>
+#include <unotools/eventlisteneradapter.hxx>
+#include "dbtreelistbox.hxx"
+
+namespace com::sun::star::awt {
+ class XControl;
+ class XControlContainer;
+ class XControlModel;
+}
+
+class Splitter;
+
+namespace dbaui
+{
+ class SbaGridControl;
+
+ class UnoDataBrowserView final : public ODataView, public ::utl::OEventListenerAdapter
+ {
+ css::uno::Reference< css::awt::XControl > m_xGrid; // our grid's UNO representation
+ css::uno::Reference< css::awt::XControlContainer > m_xMe; // our own UNO representation
+ VclPtr<InterimDBTreeListBox> m_pTreeView;
+ VclPtr<Splitter> m_pSplitter;
+ mutable VclPtr<SbaGridControl> m_pVclControl; // our grid's VCL representation
+
+ DECL_LINK( SplitHdl, Splitter*, void );
+ // attribute access
+ public:
+ const css::uno::Reference< css::awt::XControl >& getGridControl() const { return m_xGrid; }
+ SbaGridControl* getVclControl() const;
+
+ UnoDataBrowserView( vcl::Window* pParent,
+ IController& _rController,
+ const css::uno::Reference< css::uno::XComponentContext >& );
+ virtual ~UnoDataBrowserView() override;
+ virtual void dispose() override;
+
+ /// late construction
+ void Construct(const css::uno::Reference< css::awt::XControlModel >& xModel);
+
+ /** as columns may be hidden there is a difference between a columns model pos and its view pos
+ so we you may use these translation function
+ */
+ sal_uInt16 View2ModelPos(sal_uInt16 nPos) const;
+ /// for the same reason the view column count isn't the same as the model column count
+
+ void setSplitter(Splitter* pSplitter);
+ void setTreeView(InterimDBTreeListBox* pTreeView);
+
+ void showStatus( const OUString& _rStatus );
+ void hideStatus();
+
+ const css::uno::Reference< css::awt::XControlContainer >& getContainer() const { return m_xMe; }
+
+ private:
+ virtual bool PreNotify( NotifyEvent& rNEvt ) override;
+ virtual void GetFocus() override;
+ virtual void resizeDocumentView(tools::Rectangle& rRect) override;
+ virtual void _disposing( const css::lang::EventObject& _rSource ) override;
+
+ using ODataView::Construct;
+ };
+
+ class BrowserViewStatusDisplay final
+ {
+ VclPtr<UnoDataBrowserView> m_pView;
+
+ public:
+ BrowserViewStatusDisplay( UnoDataBrowserView* _pView, const OUString& _rStatus );
+ ~BrowserViewStatusDisplay( );
+ };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/callbacks.hxx b/dbaccess/source/ui/inc/callbacks.hxx
new file mode 100644
index 000000000..e380b2671
--- /dev/null
+++ b/dbaccess/source/ui/inc/callbacks.hxx
@@ -0,0 +1,123 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <sot/exchange.hxx>
+
+class Point;
+struct AcceptDropEvent;
+struct ExecuteDropEvent;
+
+namespace comphelper { class OInterfaceContainerHelper2; }
+
+namespace vcl
+{
+ class Window;
+}
+
+namespace weld
+{
+ class TreeIter;
+ class TreeView;
+}
+
+namespace dbaui
+{
+
+ class IController;
+ // IControlActionListener
+ class SAL_NO_VTABLE IControlActionListener
+ {
+ public:
+ /** requests a quick help text to display
+ @return <FALSE/> if the default quick help text should be used
+ */
+ virtual bool requestQuickHelp(const void* pUserData, OUString& rText) const = 0;
+
+ /** handler for StartDrag requests
+ @return <TRUE/> if a drag operation was started
+ */
+ virtual bool requestDrag(const weld::TreeIter& rEntry) = 0;
+
+ /** check whether or not a drop request should be accepted
+ */
+ virtual sal_Int8 queryDrop( const AcceptDropEvent& _rEvt, const DataFlavorExVector& _rFlavors ) = 0;
+
+ /** execute a drop request
+ */
+ virtual sal_Int8 executeDrop( const ExecuteDropEvent& _rEvt ) = 0;
+
+ protected:
+ ~IControlActionListener() {}
+ };
+
+ // IContextMenuProvider
+ class SAL_NO_VTABLE IContextMenuProvider
+ {
+ public:
+ /** returns the context menu resource name for the control
+
+ Supposed to be a valid name from uiconfig/<module>/popupmenu folder.
+ */
+ virtual OUString getContextMenuResourceName() const = 0;
+
+ /** returns the controller which is responsible for providing states of certain features,
+ and executing them.
+ */
+ virtual IController& getCommandController() = 0;
+
+ /** returns the container of registered context menu interceptors, or NULL if the implementation
+ does not support context menu interception
+ */
+ virtual ::comphelper::OInterfaceContainerHelper2*
+ getContextMenuInterceptors() = 0;
+
+ /** returns the current selection in the given control
+
+ This selection is used for filling a ContextMenuExecuteEvent event for the given
+ control.
+ */
+ virtual css::uno::Any getCurrentSelection(weld::TreeView& rControl) const = 0;
+
+ virtual vcl::Window* getMenuParent() const = 0;
+
+ /** adjust rPos which is initially relative to rControl to be relative to
+ the window of getMenuParent
+ */
+ virtual void adjustMenuPosition(const weld::TreeView& rControl, ::Point& rPos) const = 0;
+
+ protected:
+ ~IContextMenuProvider() {}
+ };
+
+ // IDragTransferableListener
+ class SAL_NO_VTABLE IDragTransferableListener
+ {
+ public:
+ /// called when a drag operation done with a Transferable has been finished
+ virtual void dragFinished( ) = 0;
+
+ protected:
+ ~IDragTransferableListener() {}
+ };
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/charsetlistbox.hxx b/dbaccess/source/ui/inc/charsetlistbox.hxx
new file mode 100644
index 000000000..aedfb6ec5
--- /dev/null
+++ b/dbaccess/source/ui/inc/charsetlistbox.hxx
@@ -0,0 +1,48 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <vcl/weld.hxx>
+#include "charsets.hxx"
+
+class SfxItemSet;
+
+namespace dbaui
+{
+ // CharSetListBox
+ class CharSetListBox
+ {
+ public:
+ CharSetListBox(std::unique_ptr<weld::ComboBox> xControl);
+
+ void SelectEntryByIanaName( const OUString& _rIanaName );
+ bool StoreSelectedCharSet( SfxItemSet& _rSet, const sal_uInt16 _nItemId );
+
+ weld::ComboBox* get_widget() { return m_xControl.get(); }
+ void connect_changed(const Link<weld::ComboBox&, void>& rLink) { m_xControl->connect_changed(rLink); }
+ void show() { m_xControl->show(); }
+
+ private:
+ OCharsetDisplay m_aCharSets;
+ std::unique_ptr<weld::ComboBox> m_xControl;
+ };
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/charsets.hxx b/dbaccess/source/ui/inc/charsets.hxx
new file mode 100644
index 000000000..ed1f88d7b
--- /dev/null
+++ b/dbaccess/source/ui/inc/charsets.hxx
@@ -0,0 +1,105 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <connectivity/dbcharset.hxx>
+#include <rtl/ustring.hxx>
+
+namespace dbaui
+{
+
+ // OCharsetDisplay
+ typedef ::dbtools::OCharsetMap OCharsetDisplay_Base;
+ class OCharsetDisplay final : protected OCharsetDisplay_Base
+ {
+ private:
+ OUString m_aSystemDisplayName;
+
+ public:
+ class ExtendedCharsetIterator;
+ friend class OCharsetDisplay::ExtendedCharsetIterator;
+
+ typedef ExtendedCharsetIterator iterator;
+ typedef ExtendedCharsetIterator const_iterator;
+
+ OCharsetDisplay();
+
+ // various find operations
+ const_iterator findEncoding(const rtl_TextEncoding _eEncoding) const;
+ const_iterator findIanaName(const OUString& _rIanaName) const;
+ const_iterator findDisplayName(const OUString& _rDisplayName) const;
+
+ /// get access to the first element of the charset collection
+ const_iterator begin() const;
+ /// get access to the (last + 1st) element of the charset collection
+ const_iterator end() const;
+
+ private:
+ virtual bool approveEncoding( const rtl_TextEncoding _eEncoding, const rtl_TextEncodingInfo& _rInfo ) const override;
+
+ using OCharsetDisplay_Base::find;
+ };
+
+ //- CharsetDisplayDerefHelper
+ typedef ::dbtools::CharsetIteratorDerefHelper CharsetDisplayDerefHelper_Base;
+ class CharsetDisplayDerefHelper final : protected CharsetDisplayDerefHelper_Base
+ {
+ friend class OCharsetDisplay::ExtendedCharsetIterator;
+
+ OUString m_sDisplayName;
+
+ public:
+ CharsetDisplayDerefHelper(const CharsetDisplayDerefHelper& _rSource);
+
+ OUString const & getIanaName() const { return CharsetDisplayDerefHelper_Base::getIanaName(); }
+ const OUString& getDisplayName() const { return m_sDisplayName; }
+
+ private:
+ CharsetDisplayDerefHelper(const ::dbtools::CharsetIteratorDerefHelper& _rBase, const OUString& _rDisplayName);
+ };
+
+ //- OCharsetDisplay::ExtendedCharsetIterator
+ class OCharsetDisplay::ExtendedCharsetIterator
+ {
+ friend class OCharsetDisplay;
+
+ friend bool operator==(const ExtendedCharsetIterator& lhs, const ExtendedCharsetIterator& rhs);
+ friend bool operator!=(const ExtendedCharsetIterator& lhs, const ExtendedCharsetIterator& rhs) { return !(lhs == rhs); }
+
+ typedef ::dbtools::OCharsetMap container;
+ typedef container::CharsetIterator base_iterator;
+
+ protected:
+ const OCharsetDisplay* m_pContainer;
+ base_iterator m_aPosition;
+
+ public:
+ CharsetDisplayDerefHelper operator*() const;
+
+ /// prefix increment
+ const ExtendedCharsetIterator& operator++();
+
+ protected:
+ ExtendedCharsetIterator( const OCharsetDisplay* _pContainer, const base_iterator& _rPosition );
+ };
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/commontypes.hxx b/dbaccess/source/ui/inc/commontypes.hxx
new file mode 100644
index 000000000..50c567010
--- /dev/null
+++ b/dbaccess/source/ui/inc/commontypes.hxx
@@ -0,0 +1,39 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <sal/config.h>
+
+#include <unotools/sharedunocomponent.hxx>
+
+namespace com::sun::star {
+ namespace sdbc {
+ class XConnection;
+ }
+}
+
+namespace dbaui
+{
+
+ typedef ::utl::SharedUNOComponent< css::sdbc::XConnection > SharedConnection;
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/curledit.hxx b/dbaccess/source/ui/inc/curledit.hxx
new file mode 100644
index 000000000..a99c2c3af
--- /dev/null
+++ b/dbaccess/source/ui/inc/curledit.hxx
@@ -0,0 +1,102 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <vcl/weld.hxx>
+#include <dsntypes.hxx>
+
+namespace dbaui
+{
+
+class OConnectionURLEdit
+{
+ OUString m_sSavedValue;
+
+ ::dbaccess::ODsnTypeCollection* m_pTypeCollection;
+ OUString m_sSaveValueNoPrefix;
+ bool m_bShowPrefix; // when <TRUE> the prefix will be visible, otherwise not
+
+ std::unique_ptr<weld::Entry> m_xEntry;
+ std::unique_ptr<weld::Label> m_xForcedPrefix;
+
+public:
+ OConnectionURLEdit(std::unique_ptr<weld::Entry> xEntry, std::unique_ptr<weld::Label> xForcedPrefix);
+ ~OConnectionURLEdit();
+
+public:
+ bool get_visible() const { return m_xEntry->get_visible(); }
+ void connect_changed(const Link<weld::Entry&, void>& rLink) { m_xEntry->connect_changed(rLink); }
+ void set_help_id(const OString& rName) { m_xEntry->set_help_id(rName); }
+ void hide()
+ {
+ m_xEntry->hide();
+ if (m_bShowPrefix)
+ m_xForcedPrefix->hide();
+ }
+ void show()
+ {
+ m_xEntry->show();
+ if (m_bShowPrefix)
+ m_xForcedPrefix->show();
+ }
+ void save_value() { m_sSavedValue = GetText(); }
+ bool get_value_changed_from_saved() const { return m_sSavedValue != GetText(); }
+ void grab_focus()
+ {
+ m_xEntry->grab_focus();
+ }
+ void set_sensitive(bool bSensitive)
+ {
+ m_xEntry->set_sensitive(bSensitive);
+ if (m_bShowPrefix)
+ m_xForcedPrefix->set_sensitive(bSensitive);
+ }
+ void connect_focus_in(const Link<weld::Widget&, void>& rLink)
+ {
+ m_xEntry->connect_focus_in(rLink);
+ }
+ void connect_focus_out(const Link<weld::Widget&, void>& rLink)
+ {
+ m_xEntry->connect_focus_out(rLink);
+ }
+
+ // Edit overridables
+ void SetText(const OUString& _rStr);
+ void SetText(const OUString& _rStr, const Selection& _rNewSelection);
+ OUString GetText() const;
+
+ /** Shows the Prefix
+ @param _bShowPrefix
+ If <TRUE/> than the prefix will be visible, otherwise not.
+ */
+ void ShowPrefix(bool _bShowPrefix);
+ /// get the currently set text, excluding the prefix indicating the type
+ OUString GetTextNoPrefix() const;
+ /// set a new text, leave the current prefix unchanged
+ void SetTextNoPrefix(const OUString& _rText);
+
+ void SaveValueNoPrefix() { m_sSaveValueNoPrefix = GetTextNoPrefix(); }
+ const OUString& GetSavedValueNoPrefix() const { return m_sSaveValueNoPrefix; }
+ void SetTypeCollection(::dbaccess::ODsnTypeCollection* _pTypeCollection) { m_pTypeCollection = _pTypeCollection; }
+};
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/databaseobjectview.hxx b/dbaccess/source/ui/inc/databaseobjectview.hxx
new file mode 100644
index 000000000..d6b23878a
--- /dev/null
+++ b/dbaccess/source/ui/inc/databaseobjectview.hxx
@@ -0,0 +1,230 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <rtl/ustring.hxx>
+#include <com/sun/star/sdbc/XConnection.hpp>
+#include <com/sun/star/sdbc/XDataSource.hpp>
+#include <com/sun/star/lang/XComponent.hpp>
+#include <com/sun/star/frame/XComponentLoader.hpp>
+#include <com/sun/star/frame/XFrame.hpp>
+#include <com/sun/star/sdb/application/XDatabaseDocumentUI.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <comphelper/namedvaluecollection.hxx>
+
+namespace dbaui
+{
+ /** encapsulates access to the view of a database object.
+
+ @todo
+ this is to be merged with the OLinkedDocumentAccess class
+ */
+ class DatabaseObjectView
+ {
+ private:
+ css::uno::Reference< css::uno::XComponentContext >
+ m_xORB;
+ css::uno::Reference< css::frame::XFrame >
+ m_xParentFrame;
+ css::uno::Reference< css::frame::XComponentLoader >
+ m_xFrameLoader;
+ css::uno::Reference< css::sdb::application::XDatabaseDocumentUI >
+ m_xApplication;
+ OUString m_sComponentURL;
+
+ private:
+ css::uno::Reference< css::lang::XComponent >
+ doDispatch(
+ const ::comphelper::NamedValueCollection& i_rDispatchArgs
+ );
+
+ protected:
+ /** creates the desired view
+
+ The default implementation will call <member>fillDispatchArgs</member>, followed
+ by <member>doDispatch</member>.
+
+ @param _rDataSource
+ the data source, as passed to the <member>createNew</member> or <member>openExisting</member> method.
+ @param _rObjectName
+ the name of the object for which the view is to be opened,
+ or an empty string if a view for a new object should be created.
+ @param _rCreationArgs
+ the arguments for the view's creation
+ */
+ virtual css::uno::Reference< css::lang::XComponent > doCreateView(
+ const css::uno::Any& _rDataSource,
+ const OUString& _rObjectName,
+ const ::comphelper::NamedValueCollection& i_rCreationArgs
+ );
+
+ virtual void fillDispatchArgs(
+ ::comphelper::NamedValueCollection& i_rDispatchArgs,
+ const css::uno::Any& _rDataSource,
+ const OUString& _rObjectName
+ );
+
+ const css::uno::Reference< css::sdb::application::XDatabaseDocumentUI >&
+ getApplicationUI() const { return m_xApplication; }
+ css::uno::Reference< css::sdbc::XConnection >
+ getConnection() const;
+
+ public:
+ DatabaseObjectView(
+ const css::uno::Reference< css::uno::XComponentContext >& _rxORB,
+ const css::uno::Reference< css::sdb::application::XDatabaseDocumentUI >& _rxApplication,
+ const css::uno::Reference< css::frame::XFrame >& _rxParentFrame,
+ const OUString& _rComponentURL
+ );
+ virtual ~DatabaseObjectView(){}
+
+ /** sets the target frame into which the view should be loaded.
+
+ By default, the view is loaded into a top-level frame not being part of the
+ Desktop.
+ */
+ void setTargetFrame( const css::uno::Reference< css::frame::XFrame >& _rxFrame )
+ {
+ m_xFrameLoader.set( _rxFrame, css::uno::UNO_QUERY );
+ }
+
+ /** opens a view for a to-be-created object
+
+ @param _xDataSource
+ the data source for which a new object is to be created
+ @return
+ the controller of the newly created document
+ */
+ css::uno::Reference< css::lang::XComponent >
+ createNew(
+ const css::uno::Reference< css::sdbc::XDataSource >& _xDataSource,
+ const ::comphelper::NamedValueCollection& i_rDispatchArgs = ::comphelper::NamedValueCollection()
+ );
+
+ /** opens a view for an existent object
+
+ @param _xDataSource
+ the data source for which a new object is to be created
+ @param _rObjectName
+ the name of the object to be edited
+ @param _rArgs
+ Additional settings which should be forwarded to the frame
+ @return
+ the frame into which the view has been loaded
+ */
+ css::uno::Reference< css::lang::XComponent >
+ openExisting(
+ const css::uno::Any& _aDataSource,
+ const OUString& _rName,
+ const ::comphelper::NamedValueCollection& i_rDispatchArgs
+ );
+ };
+
+ // QueryDesigner
+ class QueryDesigner final : public DatabaseObjectView
+ {
+ sal_Int32 m_nCommandType;
+
+ virtual void fillDispatchArgs(
+ ::comphelper::NamedValueCollection& i_rDispatchArgs,
+ const css::uno::Any& _aDataSource,
+ const OUString& _rObjectName
+ ) override;
+
+ public:
+ QueryDesigner(
+ const css::uno::Reference< css::uno::XComponentContext >& _rxORB,
+ const css::uno::Reference< css::sdb::application::XDatabaseDocumentUI >& _rxApplication,
+ const css::uno::Reference< css::frame::XFrame >& _rxParentFrame,
+ bool _bCreateView
+ );
+ };
+
+ // TableDesigner
+ class TableDesigner : public DatabaseObjectView
+ {
+ protected:
+ virtual void fillDispatchArgs(
+ ::comphelper::NamedValueCollection& i_rDispatchArgs,
+ const css::uno::Any& _aDataSource,
+ const OUString& _rObjectName
+ ) override;
+
+ virtual css::uno::Reference< css::lang::XComponent > doCreateView(
+ const css::uno::Any& _rDataSource,
+ const OUString& _rObjectName,
+ const ::comphelper::NamedValueCollection& i_rCreationArgs
+ ) override;
+
+ public:
+ TableDesigner(
+ const css::uno::Reference< css::uno::XComponentContext >& _rxORB,
+ const css::uno::Reference< css::sdb::application::XDatabaseDocumentUI >& _rxApplication,
+ const css::uno::Reference< css::frame::XFrame >& _rxParentFrame
+ );
+
+ private:
+ /** retrieves the table designer component as provided by the connection, if any
+ @param _rTableName
+ the name of the table for which a designer is to be obtained
+ @return
+ the designer component, as provided by the connection, or <NULL/>, if the connection
+ does not provide a specialized designer.
+ @see css::sdb::application::XTableUIProvider
+ */
+ css::uno::Reference< css::uno::XInterface >
+ impl_getConnectionProvidedDesigner_nothrow( const OUString& _rTableName );
+ };
+
+ // ResultSetBrowser
+ class ResultSetBrowser : public DatabaseObjectView
+ {
+ private:
+ bool m_bTable;
+
+ protected:
+ virtual void fillDispatchArgs(
+ ::comphelper::NamedValueCollection& i_rDispatchArgs,
+ const css::uno::Any& _aDataSource,
+ const OUString& _rQualifiedName
+ ) override;
+
+ public:
+ ResultSetBrowser(
+ const css::uno::Reference< css::uno::XComponentContext >& _rxORB,
+ const css::uno::Reference< css::sdb::application::XDatabaseDocumentUI >& _rxApplication,
+ const css::uno::Reference< css::frame::XFrame >& _rxParentFrame,
+ bool _bTable
+ );
+
+ };
+ // RelationDesigner
+ class RelationDesigner : public DatabaseObjectView
+ {
+ public:
+ RelationDesigner(
+ const css::uno::Reference< css::uno::XComponentContext >& _rxORB,
+ const css::uno::Reference< css::sdb::application::XDatabaseDocumentUI >& _rxApplication,
+ const css::uno::Reference< css::frame::XFrame >& _rxParentFrame
+ );
+ };
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/datasourceconnector.hxx b/dbaccess/source/ui/inc/datasourceconnector.hxx
new file mode 100644
index 000000000..541c49607
--- /dev/null
+++ b/dbaccess/source/ui/inc/datasourceconnector.hxx
@@ -0,0 +1,76 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <com/sun/star/sdbc/XConnection.hpp>
+#include <com/sun/star/sdbc/XDataSource.hpp>
+
+namespace dbtools
+{
+ class SQLExceptionInfo;
+}
+
+namespace weld { class Window; }
+namespace dbaui
+{
+
+ // ODatasourceConnector
+ class ODatasourceConnector final
+ {
+ weld::Window* m_pErrorMessageParent;
+ css::uno::Reference< css::uno::XComponentContext >
+ m_xContext;
+ OUString m_sContextInformation;
+
+ public:
+ ODatasourceConnector(
+ const css::uno::Reference< css::uno::XComponentContext >& _rxContext,
+ weld::Window* _pMessageParent
+ );
+ ODatasourceConnector(
+ const css::uno::Reference< css::uno::XComponentContext >& _rxContext,
+ weld::Window* _pMessageParent,
+ const OUString& _rContextInformation
+ );
+
+ /// returns <TRUE/> if the object is able to create data source connections
+ bool isValid() const { return m_xContext.is(); }
+
+ /** creates a connection to the data source, displays the possible error to the user, or returns it
+ */
+ css::uno::Reference< css::sdbc::XConnection >
+ connect(
+ const OUString& _rDataSourceName,
+ ::dbtools::SQLExceptionInfo* _pErrorInfo
+ ) const;
+
+ /** creates a connection to the data source, displays the possible error to the user, or returns it
+ */
+ css::uno::Reference< css::sdbc::XConnection >
+ connect(
+ const css::uno::Reference< css::sdbc::XDataSource>& _xDataSource,
+ ::dbtools::SQLExceptionInfo* _pErrorInfo
+ ) const;
+ };
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/dbadmin.hxx b/dbaccess/source/ui/inc/dbadmin.hxx
new file mode 100644
index 000000000..8caf3c129
--- /dev/null
+++ b/dbaccess/source/ui/inc/dbadmin.hxx
@@ -0,0 +1,114 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <sfx2/tabdlg.hxx>
+#include <dsntypes.hxx>
+#include "IItemSetHelper.hxx"
+#include <unotools/resmgr.hxx>
+#include <memory>
+
+namespace com::sun::star {
+ namespace beans {
+ class XPropertySet;
+ }
+ namespace sdbc {
+ class XConnection;
+ }
+ namespace lang {
+ class XMultiServiceFactory;
+ }
+}
+
+namespace dbaui
+{
+
+// ODbAdminDialog
+class ODbDataSourceAdministrationHelper;
+/** tab dialog for administrating the office wide registered data sources
+*/
+class ODbAdminDialog final : public SfxTabDialogController, public IItemSetHelper, public IDatabaseSettingsDialog
+{
+private:
+ std::unique_ptr<ODbDataSourceAdministrationHelper> m_pImpl;
+
+ OString m_sMainPageID;
+
+public:
+ /** ctor. The itemset given should have been created by <method>createItemSet</method> and should be destroyed
+ after the dialog has been destroyed
+ */
+ ODbAdminDialog(weld::Window* pParent, SfxItemSet const * _pItems,
+ const css::uno::Reference< css::uno::XComponentContext >& _rxORB);
+ virtual ~ODbAdminDialog() override;
+
+ /** create and return an item set for use with the dialog.
+ @param _pTypeCollection pointer to an <type>ODatasourceMap</type>. May be NULL, in this case
+ the pool will not contain a typecollection default.
+ */
+ static void createItemSet(std::unique_ptr<SfxItemSet>& _rpSet, rtl::Reference<SfxItemPool>& _rpPool, std::vector<SfxPoolItem*>*& _rpDefaults, ::dbaccess::ODsnTypeCollection* _pTypeCollection);
+ /** destroy and item set / item pool / pool defaults previously created by <method>createItemSet</method>
+ */
+ static void destroyItemSet(std::unique_ptr<SfxItemSet>& _rpSet, rtl::Reference<SfxItemPool>& _rpPool, std::vector<SfxPoolItem*>*& _rpDefaults);
+
+ /** selects the DataSource
+ @param _rName
+ The name of the data source
+ */
+ void selectDataSource(const css::uno::Any& _aDataSourceName);
+
+ virtual const SfxItemSet* getOutputSet() const override;
+ virtual SfxItemSet* getWriteOutputSet() override;
+
+ // forwards to ODbDataSourceAdministrationHelper
+ virtual css::uno::Reference< css::uno::XComponentContext > getORB() const override;
+ virtual std::pair< css::uno::Reference< css::sdbc::XConnection >,bool> createConnection() override;
+ virtual css::uno::Reference< css::sdbc::XDriver > getDriver() override;
+ virtual OUString getDatasourceType(const SfxItemSet& _rSet) const override;
+ virtual void clearPassword() override;
+ virtual void saveDatasource() override;
+ virtual void setTitle(const OUString& _sTitle) override;
+ virtual void enableConfirmSettings( bool _bEnable ) override;
+
+private:
+ // adds a new detail page and remove all the old ones
+ void addDetailPage(const OString& rPageId, TranslateId pTextId, CreateTabPage pCreateFunc);
+
+ virtual void PageCreated(const OString& rId, SfxTabPage& _rPage) override;
+ virtual short Ok() override;
+
+ /// select a datasource with a given name, adjust the item set accordingly, and everything like that ..
+ void impl_selectDataSource(const css::uno::Any& _aDataSourceName);
+ /// reset the tag pages according to m_sCurrentDatasource and <arg>_rxDatasource</arg>
+ void impl_resetPages(const css::uno::Reference< css::beans::XPropertySet >& _rxDatasource);
+
+ enum ApplyResult
+ {
+ AR_LEAVE_MODIFIED, // something was modified and has successfully been committed
+ AR_KEEP // don't leave the page (e.g. because an error occurred)
+ };
+ /** apply all changes made
+ */
+ ApplyResult implApplyChanges();
+};
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/dbexchange.hxx b/dbaccess/source/ui/inc/dbexchange.hxx
new file mode 100644
index 000000000..7fb0c6ee0
--- /dev/null
+++ b/dbaccess/source/ui/inc/dbexchange.hxx
@@ -0,0 +1,83 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "TokenWriter.hxx"
+#include <com/sun/star/util/XNumberFormatter.hpp>
+#include <com/sun/star/sdbc/XConnection.hpp>
+#include <svx/dbaexchange.hxx>
+
+#include <rtl/ref.hxx>
+
+namespace com::sun::star::uno {
+ class XComponentContext;
+}
+
+namespace dbaui
+{
+
+ class ORTFImportExport;
+ class OHTMLImportExport;
+
+ class ODataClipboard : public svx::ODataAccessObjectTransferable
+
+ {
+ ::rtl::Reference< OHTMLImportExport > m_pHtml;
+ ::rtl::Reference< ORTFImportExport > m_pRtf;
+
+ public:
+ ODataClipboard();
+
+ ODataClipboard(
+ const css::uno::Reference< css::beans::XPropertySet >& i_rAliveForm,
+ const css::uno::Sequence< css::uno::Any >& i_rSelectedRows,
+ const bool i_bBookmarkSelection,
+ const css::uno::Reference< css::uno::XComponentContext >& i_rORB
+ );
+
+ void Update(
+ const OUString& _rDatasource,
+ const sal_Int32 _nCommandType,
+ const OUString& _rCommand,
+ const css::uno::Reference< css::sdbc::XConnection >& _rxConnection,
+ const css::uno::Reference< css::util::XNumberFormatter >& _rxFormatter,
+ const css::uno::Reference< css::uno::XComponentContext >& _rxORB
+ );
+
+ void Update(
+ const OUString& _rDatasource,
+ const sal_Int32 _nCommandType,
+ const OUString& _rCommand,
+ const css::uno::Reference< css::util::XNumberFormatter >& _rxFormatter,
+ const css::uno::Reference< css::uno::XComponentContext >& _rxORB
+ );
+
+ // XEventListener
+ virtual void SAL_CALL disposing( const css::lang::EventObject& Source ) override;
+
+ protected:
+ virtual void AddSupportedFormats() override;
+ virtual bool GetData( const css::datatransfer::DataFlavor& rFlavor, const OUString& rDestDoc ) override;
+ virtual void ObjectReleased() override;
+ virtual bool WriteObject( tools::SvRef<SotTempStream>& rxOStm, void* pUserObject, sal_uInt32 nUserObjectId, const css::datatransfer::DataFlavor& rFlavor ) override;
+ };
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/dbtreelistbox.hxx b/dbaccess/source/ui/inc/dbtreelistbox.hxx
new file mode 100644
index 000000000..7682841a2
--- /dev/null
+++ b/dbaccess/source/ui/inc/dbtreelistbox.hxx
@@ -0,0 +1,164 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <vcl/InterimItemWindow.hxx>
+#include <vcl/transfer.hxx>
+#include <vcl/timer.hxx>
+#include <vcl/weld.hxx>
+
+#include <memory>
+
+namespace dbaui
+{
+ class IEntryFilter
+ {
+ public:
+ virtual bool includeEntry(const void* pUserData) const = 0;
+
+ protected:
+ ~IEntryFilter() {}
+ };
+
+ class IControlActionListener;
+ class IContextMenuProvider;
+
+ class TreeListBox;
+
+ class TreeListBoxDropTarget : public DropTargetHelper
+ {
+ private:
+ TreeListBox& m_rTreeView;
+
+ virtual sal_Int8 AcceptDrop( const AcceptDropEvent& rEvt ) override;
+ virtual sal_Int8 ExecuteDrop( const ExecuteDropEvent& rEvt ) override;
+
+ public:
+ TreeListBoxDropTarget(TreeListBox& rTreeView);
+ };
+
+ class TreeListBox
+ {
+ protected:
+ std::unique_ptr<weld::TreeView> m_xTreeView;
+ TreeListBoxDropTarget m_aDropTargetHelper;
+
+ std::unique_ptr<weld::TreeIter> m_xDragedEntry;
+ IControlActionListener* m_pActionListener;
+ IContextMenuProvider* m_pContextMenuProvider;
+
+ DECL_LINK(KeyInputHdl, const KeyEvent&, bool);
+ DECL_LINK(SelectHdl, weld::TreeView&, void);
+ DECL_LINK(QueryTooltipHdl, const weld::TreeIter&, OUString);
+ DECL_LINK(CommandHdl, const CommandEvent&, bool);
+ DECL_LINK(DragBeginHdl, bool&, bool);
+
+ private:
+ Timer m_aTimer; // is needed for table updates
+ rtl::Reference<TransferDataContainer> m_xHelper;
+
+ Link<LinkParamNone*,void> m_aSelChangeHdl; // handler to be called (asynchronously) when the selection changes in any way
+ Link<LinkParamNone*,void> m_aCopyHandler; // called when someone press CTRL+C
+ Link<LinkParamNone*,void> m_aPasteHandler; // called when someone press CTRL+V
+ Link<LinkParamNone*,void> m_aDeleteHandler; // called when someone press DELETE Key
+
+ DECL_LINK(OnTimeOut, Timer*, void);
+
+ protected:
+ void implStopSelectionTimer();
+ void implStartSelectionTimer();
+
+ virtual bool DoChildKeyInput(const KeyEvent& rKEvt);
+
+ public:
+ TreeListBox(std::unique_ptr<weld::TreeView> xTreeView, bool bSQLType);
+ virtual ~TreeListBox();
+
+ std::unique_ptr<weld::TreeIter> GetEntryPosByName(std::u16string_view rName,
+ const weld::TreeIter* pStart = nullptr,
+ const IEntryFilter* pFilter = nullptr) const;
+
+ std::unique_ptr<weld::TreeIter> GetRootLevelParent(const weld::TreeIter* pEntry) const;
+
+ void setControlActionListener(IControlActionListener* pListener) { m_pActionListener = pListener; }
+ void setContextMenuProvider(IContextMenuProvider* pContextMenuProvider) { m_pContextMenuProvider = pContextMenuProvider; }
+
+ weld::TreeView& GetWidget() { return *m_xTreeView; }
+ const weld::TreeView& GetWidget() const { return *m_xTreeView; }
+
+ TransferDataContainer& GetDataTransfer() { return *m_xHelper; }
+
+ sal_Int8 AcceptDrop(const AcceptDropEvent& rEvt);
+ sal_Int8 ExecuteDrop(const ExecuteDropEvent& rEvt);
+
+ void SetSelChangeHdl( const Link<LinkParamNone*,void>& _rHdl ) { m_aSelChangeHdl = _rHdl; }
+ void setCopyHandler(const Link<LinkParamNone*,void>& _rHdl) { m_aCopyHandler = _rHdl; }
+ void setPasteHandler(const Link<LinkParamNone*,void>& _rHdl) { m_aPasteHandler = _rHdl; }
+ void setDeleteHandler(const Link<LinkParamNone*,void>& _rHdl) { m_aDeleteHandler = _rHdl; }
+ };
+
+ class InterimDBTreeListBox : public InterimItemWindow
+ , public TreeListBox
+ {
+ private:
+ std::unique_ptr<weld::Label> m_xStatusBar;
+ public:
+ InterimDBTreeListBox(vcl::Window* pParent);
+ virtual void dispose() override;
+ weld::Label& GetStatusBar() { return *m_xStatusBar; }
+ virtual ~InterimDBTreeListBox() override;
+ void show_container() { m_xContainer->show(); }
+ protected:
+ virtual bool DoChildKeyInput(const KeyEvent& rKEvt) override;
+ };
+
+ class DBTreeViewBase
+ {
+ protected:
+ std::unique_ptr<weld::Builder> m_xBuilder;
+ std::unique_ptr<weld::Container> m_xContainer;
+ std::unique_ptr<TreeListBox> m_xTreeListBox;
+ public:
+ DBTreeViewBase(weld::Container* pContainer);
+ virtual ~DBTreeViewBase();
+
+ weld::TreeView& GetWidget() { return m_xTreeListBox->GetWidget(); }
+ const weld::TreeView& GetWidget() const { return m_xTreeListBox->GetWidget(); }
+
+ TreeListBox& getListBox() const { return *m_xTreeListBox; }
+
+ void hide() { m_xContainer->hide(); }
+ void show() { m_xContainer->show(); }
+ bool get_visible() const { return m_xContainer->get_visible(); }
+ };
+
+ class DBTreeView final : public DBTreeViewBase
+ {
+ public:
+ DBTreeView(weld::Container* pContainer, bool bSQLType);
+ };
+
+ class DBTableTreeView final : public DBTreeViewBase
+ {
+ public:
+ DBTableTreeView(weld::Container* pContainer);
+ };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/dbu_dlg.hxx b/dbaccess/source/ui/inc/dbu_dlg.hxx
new file mode 100644
index 000000000..ed97c4c93
--- /dev/null
+++ b/dbaccess/source/ui/inc/dbu_dlg.hxx
@@ -0,0 +1,24 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#define WIZARD_PAGE_X 56
+#define WIZARD_PAGE_Y 30
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/dbwiz.hxx b/dbaccess/source/ui/inc/dbwiz.hxx
new file mode 100644
index 000000000..0c51ab1a9
--- /dev/null
+++ b/dbaccess/source/ui/inc/dbwiz.hxx
@@ -0,0 +1,101 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <dsntypes.hxx>
+#include "IItemSetHelper.hxx"
+#include <vcl/wizardmachine.hxx>
+#include <memory>
+
+namespace com::sun::star {
+ namespace beans {
+ class XPropertySet;
+ }
+ namespace sdbc {
+ class XConnection;
+ }
+ namespace lang {
+ class XMultiServiceFactory;
+ }
+}
+
+using vcl::WizardTypes::WizardState;
+using vcl::WizardTypes::CommitPageReason;
+
+namespace dbaccess
+{
+ class ODsnTypeCollection;
+}
+namespace dbaui
+{
+
+// ODbTypeWizDialog
+class OGeneralPage;
+class ODbDataSourceAdministrationHelper;
+/** tab dialog for administrating the office wide registered data sources
+*/
+class ODbTypeWizDialog : public vcl::WizardMachine , public IItemSetHelper, public IDatabaseSettingsDialog
+{
+private:
+ std::unique_ptr<ODbDataSourceAdministrationHelper> m_pImpl;
+ std::unique_ptr<SfxItemSet> m_pOutSet;
+ ::dbaccess::ODsnTypeCollection*
+ m_pCollection; /// the DSN type collection instance
+ OUString m_eType;
+
+public:
+ /** ctor. The itemset given should have been created by <method>createItemSet</method> and should be destroyed
+ after the dialog has been destroyed
+ */
+ ODbTypeWizDialog(weld::Window* pParent
+ ,SfxItemSet const * _pItems
+ ,const css::uno::Reference< css::uno::XComponentContext >& _rxORB
+ ,const css::uno::Any& _aDataSourceName
+ );
+ virtual ~ODbTypeWizDialog() override;
+
+ virtual const SfxItemSet* getOutputSet() const override;
+ virtual SfxItemSet* getWriteOutputSet() override;
+
+ // forwards to ODbDataSourceAdministrationHelper
+ virtual css::uno::Reference< css::uno::XComponentContext > getORB() const override;
+ virtual std::pair< css::uno::Reference< css::sdbc::XConnection >,bool> createConnection() override;
+ virtual css::uno::Reference< css::sdbc::XDriver > getDriver() override;
+ virtual OUString getDatasourceType(const SfxItemSet& _rSet) const override;
+ virtual void clearPassword() override;
+ virtual void saveDatasource() override;
+ virtual void setTitle(const OUString& _sTitle) override;
+ virtual void enableConfirmSettings( bool _bEnable ) override;
+
+protected:
+ /// to override to create new pages
+ virtual std::unique_ptr<BuilderPage> createPage(WizardState _nState) override;
+ virtual WizardState determineNextState(WizardState _nCurrentState) const override;
+ virtual bool leaveState(WizardState _nState) override;
+ virtual ::vcl::IWizardPageController* getPageController(BuilderPage* pCurrentPage) const override;
+ virtual bool onFinish() override;
+
+private:
+ DECL_LINK(OnTypeSelected, OGeneralPage&, void);
+};
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/dbwizsetup.hxx b/dbaccess/source/ui/inc/dbwizsetup.hxx
new file mode 100644
index 000000000..0829b328d
--- /dev/null
+++ b/dbaccess/source/ui/inc/dbwizsetup.hxx
@@ -0,0 +1,170 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <dsntypes.hxx>
+#include "IItemSetHelper.hxx"
+#include <tools/urlobj.hxx>
+#include <memory>
+#include <vcl/roadmapwizard.hxx>
+
+namespace com::sun::star {
+ namespace beans {
+ class XPropertySet;
+ }
+ namespace sdbc {
+ class XConnection;
+ }
+ namespace lang {
+ class XMultiServiceFactory;
+ }
+}
+
+using vcl::WizardTypes::WizardState;
+using vcl::WizardTypes::CommitPageReason;
+using vcl::RoadmapWizardTypes::PathId;
+
+namespace dbaui
+{
+
+class OGenericAdministrationPage;
+
+// ODbTypeWizDialogSetup
+class OGeneralPage;
+class OGeneralPageWizard;
+class ODbDataSourceAdministrationHelper;
+/** tab dialog for administrating the office wide registered data sources
+*/
+class OMySQLIntroPageSetup;
+class OFinalDBPageSetup;
+
+class ODbTypeWizDialogSetup final : public vcl::RoadmapWizardMachine, public IItemSetHelper, public IDatabaseSettingsDialog
+{
+private:
+ std::unique_ptr<ODbDataSourceAdministrationHelper> m_pImpl;
+ std::unique_ptr<SfxItemSet> m_pOutSet;
+ OUString m_sURL;
+ OUString m_sOldURL;
+ bool m_bIsConnectable : 1;
+ OUString m_sRM_IntroText;
+ OUString m_sRM_dBaseText;
+ OUString m_sRM_TextText;
+ OUString m_sRM_MSAccessText;
+ OUString m_sRM_LDAPText;
+ OUString m_sRM_ADOText;
+ OUString m_sRM_JDBCText;
+ OUString m_sRM_MySQLNativePageTitle;
+ OUString m_sRM_OracleText;
+ OUString m_sRM_MySQLText;
+ OUString m_sRM_ODBCText;
+ OUString m_sRM_DocumentOrSpreadSheetText;
+ OUString m_sRM_AuthentificationText;
+ OUString m_sRM_FinalText;
+ INetURLObject m_aDocURL;
+ OUString m_sWorkPath;
+ OGeneralPageWizard* m_pGeneralPage;
+ OMySQLIntroPageSetup* m_pMySQLIntroPage;
+ OFinalDBPageSetup* m_pFinalPage;
+
+ ::dbaccess::ODsnTypeCollection*
+ m_pCollection; /// the DSN type collection instance
+
+public:
+ /** ctor. The itemset given should have been created by <method>createItemSet</method> and should be destroyed
+ after the dialog has been destroyed
+ */
+ ODbTypeWizDialogSetup(weld::Window* pParent
+ ,SfxItemSet const * _pItems
+ ,const css::uno::Reference< css::uno::XComponentContext >& _rxORB
+ ,const css::uno::Any& _aDataSourceName
+ );
+ virtual ~ODbTypeWizDialogSetup() override;
+
+ virtual const SfxItemSet* getOutputSet() const override;
+ virtual SfxItemSet* getWriteOutputSet() override;
+
+ // forwards to ODbDataSourceAdministrationHelper
+ virtual css::uno::Reference< css::uno::XComponentContext > getORB() const override;
+ virtual std::pair< css::uno::Reference< css::sdbc::XConnection >,bool> createConnection() override;
+ virtual css::uno::Reference< css::sdbc::XDriver > getDriver() override;
+ virtual OUString getDatasourceType(const SfxItemSet& _rSet) const override;
+ virtual void clearPassword() override;
+ virtual void setTitle(const OUString& _sTitle) override;
+ virtual void enableConfirmSettings( bool _bEnable ) override;
+ virtual void saveDatasource() override;
+ virtual OUString getStateDisplayName( WizardState _nState ) const override;
+
+ /** returns <TRUE/> if the database should be opened, otherwise <FALSE/>.
+ */
+ bool IsDatabaseDocumentToBeOpened() const;
+
+ /** returns <TRUE/> if the table wizard should be opened, otherwise <FALSE/>.
+ */
+ bool IsTableWizardToBeStarted() const;
+
+ void SetIntroPage(OMySQLIntroPageSetup* pPage);
+ void SetGeneralPage(OGeneralPageWizard* pPage);
+ void SetFinalPage(OFinalDBPageSetup* pPage);
+
+private:
+ /// to override to create new pages
+ virtual std::unique_ptr<BuilderPage> createPage(WizardState _nState) override;
+ virtual bool leaveState(WizardState _nState) override;
+ virtual void enterState(WizardState _nState) override;
+ virtual ::vcl::IWizardPageController* getPageController(BuilderPage* pCurrentPage) const override;
+ virtual bool onFinish() override;
+
+ void resetPages(const css::uno::Reference< css::beans::XPropertySet >& _rxDatasource);
+
+ /** declares a path with or without authentication, as indicated by the database type
+
+ @param _sURL
+ the data source type for which the path is declared. If this
+ data source type does not support authentication, the PAGE_DBSETUPWIZARD_AUTHENTIFICATION
+ state will be stripped from the sequence of states.
+ @param _nPathId
+ the ID of the path
+ @path
+ the first state in this path, following by an arbitrary number of others, as in
+ RoadmapWizard::declarePath.
+ */
+ void declareAuthDepPath( const OUString& _sURL, PathId _nPathId, const vcl::RoadmapWizardTypes::WizardPath& _rPaths);
+
+ void RegisterDataSourceByLocation(std::u16string_view sPath);
+ bool SaveDatabaseDocument();
+ void activateDatabasePath();
+ OUString createUniqueFileName(const INetURLObject& rURL);
+ void CreateDatabase();
+ void createUniqueFolderName(INetURLObject* pURL);
+ ::dbaccess::DATASOURCE_TYPE VerifyDataSourceType(const ::dbaccess::DATASOURCE_TYPE DatabaseType) const;
+
+ void updateTypeDependentStates();
+ bool callSaveAsDialog();
+ DECL_LINK(OnTypeSelected, OGeneralPage&, void);
+ DECL_LINK(OnChangeCreationMode, OGeneralPageWizard&, void);
+ DECL_LINK(OnRecentDocumentSelected, OGeneralPageWizard&, void);
+ DECL_LINK(OnSingleDocumentChosen, OGeneralPageWizard&, void);
+ DECL_LINK(ImplClickHdl, OMySQLIntroPageSetup*, void);
+ DECL_LINK(ImplModifiedHdl, OGenericAdministrationPage const *, void);
+};
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/defaultobjectnamecheck.hxx b/dbaccess/source/ui/inc/defaultobjectnamecheck.hxx
new file mode 100644
index 000000000..59705fe61
--- /dev/null
+++ b/dbaccess/source/ui/inc/defaultobjectnamecheck.hxx
@@ -0,0 +1,120 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include "objectnamecheck.hxx"
+
+#include <com/sun/star/container/XHierarchicalNameAccess.hpp>
+#include <com/sun/star/sdbc/XConnection.hpp>
+
+#include <memory>
+
+namespace dbaui
+{
+
+ // HierarchicalNameCheck
+ struct HierarchicalNameCheck_Impl;
+ /** class implementing the IObjectNameCheck interface, and checking given object names
+ against a hierarchical name container
+ */
+ class HierarchicalNameCheck :public IObjectNameCheck
+ {
+ private:
+ std::unique_ptr< HierarchicalNameCheck_Impl > m_pImpl;
+
+ public:
+ /** constructs a HierarchicalNameCheck instance
+ @param _rxNames
+ the hierarchical container of named objects, against which given names should be
+ checked
+ @param _rRelativeRoot
+ the root in the hierarchy against which given names should be checked
+ @throws css::lang::IllegalArgumentException
+ if the given container is <NULL/>
+ */
+ HierarchicalNameCheck(
+ const css::uno::Reference< css::container::XHierarchicalNameAccess >& _rxNames,
+ const OUString& _rRelativeRoot
+ );
+
+ virtual ~HierarchicalNameCheck() override;
+
+ HierarchicalNameCheck(const HierarchicalNameCheck&) = delete;
+ const HierarchicalNameCheck& operator=(const HierarchicalNameCheck&) = delete;
+
+ // IObjectNameCheck overridables
+ virtual bool isNameValid(
+ const OUString& _rObjectName,
+ ::dbtools::SQLExceptionInfo& _out_rErrorToDisplay
+ ) const override;
+ };
+
+ // DynamicTableOrQueryNameCheck
+ struct DynamicTableOrQueryNameCheck_Impl;
+ /** class implementing the IObjectNameCheck interface, and checking a given name
+ for being valid as either a query or a table name.
+
+ The class can be parametrized to act as either table name or query name validator.
+
+ For databases which support queries in queries, the name check is implicitly extended
+ to both queries and tables, no matter which category is checked. This prevents, for
+ such databases, that users can create a query with the name of an existing table,
+ or vice versa.
+
+ @seealso dbtools::DatabaseMetaData::supportsSubqueriesInFrom
+ @seealso css::sdb::tools::XObjectNames::checkNameForCreate
+ */
+ class DynamicTableOrQueryNameCheck :public IObjectNameCheck
+ {
+ private:
+ std::unique_ptr< DynamicTableOrQueryNameCheck_Impl > m_pImpl;
+
+ public:
+ /** constructs a DynamicTableOrQueryNameCheck instance
+ @param _rxSdbLevelConnection
+ a connection supporting the css.sdb.Connection service, in other word, it
+ does expose the XTablesSupplier and XQueriesSupplier interfaces.
+ @param _nCommandType
+ specifies whether table names or query names should be checked. Only valid values
+ are CommandType::TABLE and CommandType::QUERY.
+ @throws css::lang::IllegalArgumentException
+ if the given connection is <NULL/>, or the given command type is neither
+ CommandType::TABLE nor CommandType::QUERY.
+ */
+ DynamicTableOrQueryNameCheck(
+ const css::uno::Reference< css::sdbc::XConnection >& _rxSdbLevelConnection,
+ sal_Int32 _nCommandType
+ );
+
+ virtual ~DynamicTableOrQueryNameCheck() override;
+
+ DynamicTableOrQueryNameCheck(const DynamicTableOrQueryNameCheck&) = delete;
+ const DynamicTableOrQueryNameCheck& operator=(const DynamicTableOrQueryNameCheck&) = delete;
+
+ // IObjectNameCheck overridables
+ virtual bool isNameValid(
+ const OUString& _rObjectName,
+ ::dbtools::SQLExceptionInfo& _out_rErrorToDisplay
+ ) const override;
+ };
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/directsql.hxx b/dbaccess/source/ui/inc/directsql.hxx
new file mode 100644
index 000000000..bfe8195fc
--- /dev/null
+++ b/dbaccess/source/ui/inc/directsql.hxx
@@ -0,0 +1,113 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <sal/config.h>
+
+#include <vcl/weld.hxx>
+#include <deque>
+#include <string_view>
+
+#include <com/sun/star/sdbc/XConnection.hpp>
+#include <unotools/eventlisteneradapter.hxx>
+#include <osl/mutex.hxx>
+
+#include "sqledit.hxx"
+
+struct ImplSVEvent;
+
+namespace dbaui
+{
+ // DirectSQLDialog
+ class DirectSQLDialog final
+ : public weld::GenericDialogController
+ , public ::utl::OEventListenerAdapter
+ {
+ ::osl::Mutex m_aMutex;
+
+ std::unique_ptr<weld::Button> m_xExecute;
+ std::unique_ptr<weld::ComboBox> m_xSQLHistory;
+ std::unique_ptr<weld::TextView> m_xStatus;
+ std::unique_ptr<weld::CheckButton> m_xDirectSQL;
+ std::unique_ptr<weld::CheckButton> m_xShowOutput;
+ std::unique_ptr<weld::TextView> m_xOutput;
+ std::unique_ptr<weld::Button> m_xClose;
+ std::unique_ptr<SQLEditView> m_xSQL;
+ std::unique_ptr<weld::CustomWeld> m_xSQLEd;
+
+ typedef std::deque< OUString > StringQueue;
+ StringQueue m_aStatementHistory; // previous statements
+ StringQueue m_aNormalizedHistory; // previous statements, normalized to be used in the list box
+
+ sal_Int32 m_nStatusCount;
+
+ css::uno::Reference< css::sdbc::XConnection >
+ m_xConnection;
+
+ ImplSVEvent* m_pClosingEvent;
+
+ public:
+ DirectSQLDialog(
+ weld::Window* _pParent,
+ const css::uno::Reference< css::sdbc::XConnection >& _rxConn);
+ virtual ~DirectSQLDialog() override;
+
+ /// number of history entries
+ sal_Int32 getHistorySize() const;
+
+ private:
+ void executeCurrent();
+ void switchToHistory(sal_Int32 _nHistoryPos);
+
+ // OEventListenerAdapter
+ virtual void _disposing( const css::lang::EventObject& _rSource ) override;
+
+ DECL_LINK( OnExecute, weld::Button&, void );
+ DECL_LINK( OnClose, void*, void );
+ DECL_LINK( OnCloseClick, weld::Button&, void );
+ DECL_LINK( OnListEntrySelected, weld::ComboBox&, void );
+ DECL_LINK( OnStatementModified, LinkParamNone*, void );
+
+ /// adds a statement to the statement history
+ void implAddToStatementHistory(const OUString& _rStatement);
+
+ /// ensures that our history has at most m_nHistoryLimit entries
+ void implEnsureHistoryLimit();
+
+ /// executes the statement given, adds the status to the status list
+ void implExecuteStatement(const OUString& _rStatement);
+
+ /// adds a status text to the status list
+ void addStatusText(std::u16string_view _rMessage);
+
+ /// adds a status text to the output list
+ void addOutputText(std::u16string_view _rMessage);
+
+ /// displays resultset
+ void display(const css::uno::Reference< css::sdbc::XResultSet >& xRS);
+
+#ifdef DBG_UTIL
+ const char* impl_CheckInvariants() const;
+#endif
+ };
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/dlgattr.hxx b/dbaccess/source/ui/inc/dlgattr.hxx
new file mode 100644
index 000000000..6c3a00f95
--- /dev/null
+++ b/dbaccess/source/ui/inc/dlgattr.hxx
@@ -0,0 +1,41 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <sfx2/tabdlg.hxx>
+
+class SvxNumberInfoItem;
+class SfxItemSet;
+class SvNumberFormatter;
+namespace dbaui
+{
+
+ class SbaSbAttrDlg : public SfxTabDialogController
+ {
+ std::unique_ptr<SvxNumberInfoItem> pNumberInfoItem;
+
+ public:
+ SbaSbAttrDlg(weld::Widget* pParent, const SfxItemSet*, SvNumberFormatter*, bool bHasFormat);
+ virtual ~SbaSbAttrDlg() override;
+
+ virtual void PageCreated(const OString& rPageId, SfxTabPage& rTabPage) override;
+ };
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/dlgsave.hxx b/dbaccess/source/ui/inc/dlgsave.hxx
new file mode 100644
index 000000000..d56fc6ade
--- /dev/null
+++ b/dbaccess/source/ui/inc/dlgsave.hxx
@@ -0,0 +1,81 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <o3tl/typed_flags_set.hxx>
+#include <vcl/weld.hxx>
+#include <memory>
+
+namespace com::sun::star {
+ namespace sdbc {
+ class XConnection;
+ }
+}
+
+enum class SADFlags {
+ NONE = 0x0000,
+ AdditionalDescription = 0x0001,
+ TitlePasteAs = 0x0100,
+ TitleRename = 0x0200,
+};
+namespace o3tl {
+ template<> struct typed_flags<SADFlags> : is_typed_flags<SADFlags, 0x0301> {};
+}
+
+namespace dbaui
+{
+ class OSaveAsDlgImpl;
+ class IObjectNameCheck;
+ class OSaveAsDlg : public weld::GenericDialogController
+ {
+ private:
+ std::unique_ptr<OSaveAsDlgImpl> m_pImpl;
+ css::uno::Reference< css::uno::XComponentContext > m_xContext;
+ public:
+ OSaveAsDlg( weld::Window * pParent, sal_Int32 _rType,
+ const css::uno::Reference< css::uno::XComponentContext >& _rxContext,
+ const css::uno::Reference< css::sdbc::XConnection>& _xConnection,
+ const OUString& rDefault,
+ const IObjectNameCheck& _rObjectNameCheck,
+ SADFlags _nFlags);
+
+ OSaveAsDlg( weld::Window* _pParent,
+ const css::uno::Reference< css::uno::XComponentContext >& _rxContext,
+ const OUString& _rDefault,
+ const OUString& _sLabel,
+ const IObjectNameCheck& _rObjectNameCheck,
+ SADFlags _nFlags);
+ virtual ~OSaveAsDlg() override;
+
+ const OUString& getName() const;
+ OUString getCatalog() const;
+ OUString getSchema() const;
+ private:
+ DECL_LINK(ButtonClickHdl, weld::Button&, void);
+ DECL_LINK(EditModifyHdl, weld::Entry&, void);
+
+ void implInitOnlyTitle(const OUString& _rLabel);
+ void implInit();
+ };
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/dlgsize.hxx b/dbaccess/source/ui/inc/dlgsize.hxx
new file mode 100644
index 000000000..5a673d712
--- /dev/null
+++ b/dbaccess/source/ui/inc/dlgsize.hxx
@@ -0,0 +1,44 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <vcl/weld.hxx>
+
+namespace dbaui
+{
+
+ class DlgSize final : public weld::GenericDialogController
+ {
+ private:
+ sal_Int32 m_nPrevValue;
+ void SetValue( sal_Int32 nVal );
+
+ DECL_LINK(CbClickHdl, weld::Toggleable&, void);
+
+ std::unique_ptr<weld::MetricSpinButton> m_xMF_VALUE;
+ std::unique_ptr<weld::CheckButton> m_xCB_STANDARD;
+
+ public:
+ DlgSize(weld::Window * pParent, sal_Int32 nVal, bool bRow, sal_Int32 _nAlternativeStandard = -1);
+ virtual ~DlgSize() override;
+ sal_Int32 GetValue() const;
+ };
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/dsitems.hxx b/dbaccess/source/ui/inc/dsitems.hxx
new file mode 100644
index 000000000..09410d31b
--- /dev/null
+++ b/dbaccess/source/ui/inc/dsitems.hxx
@@ -0,0 +1,95 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <sal/types.h>
+
+typedef sal_Int32 ItemID;
+
+// item ids for the data source administration dialog
+
+#define DSID_NAME 1 // name of a data source, SfxStringItem
+#define DSID_ORIGINALNAME 2 // original name, internal, SfxStringItem
+#define DSID_CONNECTURL 3 // connection URL, SfxStringItem
+#define DSID_TABLEFILTER 4 // table filter, OStringListItem
+#define DSID_TYPECOLLECTION 5 // collection of data source types, ODsnTypeCollection
+#define DSID_INVALID_SELECTION 6 // is the selection (thus the set data) invalid?, SfxBoolItem
+#define DSID_READONLY 7 // is the selection (thus the set data) readonly?, SfxBoolItem
+#define DSID_USER 8 // the user name used for logon, SfxStringItem
+#define DSID_PASSWORD 9 // the password used for logon, SfxStringItem
+#define DSID_ADDITIONALOPTIONS 10 // additional options used for connecting, SfxStringItem
+#define DSID_CHARSET 11 // character set to use, SfxStringItem by now
+#define DSID_PASSWORDREQUIRED 12 // is the password required to connect?, SfxBoolItem
+#define DSID_SHOWDELETEDROWS 13 // show deleted rows?, SfxBoolItem
+#define DSID_ALLOWLONGTABLENAMES 14 // allow tables names longer than 8.3?, SfxBoolItem
+#define DSID_JDBCDRIVERCLASS 15 // JDBC driver class, SfxStringItem
+#define DSID_FIELDDELIMITER 16 // field delimiter, SfxUInt16Item
+#define DSID_TEXTDELIMITER 17 // text delimiter, SfxUInt16Item
+#define DSID_DECIMALDELIMITER 18 // decimal delimiter, SfxUInt16Item
+#define DSID_THOUSANDSDELIMITER 19 // thousands delimiter, SfxUInt16Item
+#define DSID_TEXTFILEEXTENSION 20 // extension for text files, SfxStringItem
+#define DSID_TEXTFILEHEADER 21 // the text file contains a header?, SfxBoolItem
+#define DSID_PARAMETERNAMESUBST 22
+#define DSID_CONN_PORTNUMBER 23
+#define DSID_SUPPRESSVERSIONCL 24 // meta data: sal_True if the data source described by the set is to-be-deleted
+#define DSID_CONN_SHUTSERVICE 25
+#define DSID_CONN_DATAINC 26
+#define DSID_CONN_CACHESIZE 27
+#define DSID_CONN_CTRLUSER 28
+#define DSID_CONN_CTRLPWD 29
+#define DSID_USECATALOG 30 // should the driver use the catalog name when the database is filebased
+#define DSID_CONN_HOSTNAME 31
+#define DSID_CONN_LDAP_BASEDN 32
+#define DSID_CONN_LDAP_PORTNUMBER 33
+#define DSID_CONN_LDAP_ROWCOUNT 34
+#define DSID_SQL92CHECK 35
+#define DSID_AUTOINCREMENTVALUE 36
+#define DSID_AUTORETRIEVEVALUE 37
+#define DSID_AUTORETRIEVEENABLED 38
+#define DSID_APPEND_TABLE_ALIAS 39
+#define DSID_MYSQL_PORTNUMBER 40
+#define DSID_IGNOREDRIVER_PRIV 41
+#define DSID_BOOLEANCOMPARISON 42
+#define DSID_ORACLE_PORTNUMBER 43
+#define DSID_ENABLEOUTERJOIN 44
+#define DSID_CATALOG 45
+#define DSID_SCHEMA 46
+#define DSID_INDEXAPPENDIX 47
+#define DSID_CONN_LDAP_USESSL 48
+#define DSID_DOCUMENT_URL 49
+#define DSID_DOSLINEENDS 50
+#define DSID_DATABASENAME 51
+#define DSID_AS_BEFORE_CORRNAME 52
+#define DSID_CHECK_REQUIRED_FIELDS 53
+#define DSID_IGNORECURRENCY 54
+#define DSID_CONN_SOCKET 55
+#define DSID_ESCAPE_DATETIME 56
+#define DSID_NAMED_PIPE 57
+#define DSID_PRIMARY_KEY_SUPPORT 58
+#define DSID_MAX_ROW_SCAN 59
+#define DSID_RESPECTRESULTSETTYPE 60
+ // don't forget to adjust DSID_LAST_ITEM_ID below!
+
+// item range. Adjust this if you introduce new items above
+
+#define DSID_FIRST_ITEM_ID DSID_NAME
+#define DSID_LAST_ITEM_ID DSID_RESPECTRESULTSETTYPE
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/dsmeta.hxx b/dbaccess/source/ui/inc/dsmeta.hxx
new file mode 100644
index 000000000..69b13ebb7
--- /dev/null
+++ b/dbaccess/source/ui/inc/dsmeta.hxx
@@ -0,0 +1,125 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <sal/config.h>
+
+#include <set>
+
+#include "dsitems.hxx"
+
+#include <rtl/ustring.hxx>
+
+#include <memory>
+
+namespace dbaui
+{
+
+ // AuthenticationMode
+ enum AuthenticationMode
+ {
+ AuthNone,
+ AuthUserPwd,
+ AuthPwd
+ };
+
+ // DataSourceMetaData
+ class FeatureSet;
+ class DataSourceMetaData_Impl;
+ /** encapsulates meta data for a data source
+
+ On the long run, this class should a) encapsulate *all* meta data which
+ currently is hard coded somewhere in the program logic and b) be initialized
+ from the configuration.
+
+ At the moment, the data a) is still hard coded in the, well, code and b)
+ contains meta data about the advanced settings only.
+ */
+ class DataSourceMetaData
+ {
+ public:
+ DataSourceMetaData( const OUString& _sURL );
+ ~DataSourceMetaData();
+
+ /// returns a struct describing this data source type's support for our known advanced settings
+ const FeatureSet& getFeatureSet() const;
+
+ /// determines whether or not the data source requires authentication
+ static AuthenticationMode getAuthentication( const OUString& _sURL );
+
+ private:
+ std::shared_ptr< DataSourceMetaData_Impl > m_pImpl;
+ };
+
+ // FeatureSet
+ /** can be used to ask for (UI) support for certain advanced features
+ */
+ class FeatureSet
+ {
+ public:
+ typedef std::set< ItemID >::const_iterator const_iterator;
+
+ public:
+ FeatureSet() { }
+
+ void put( const ItemID _id ) { m_aContent.insert( _id ); }
+ bool has( const ItemID _id ) const { return m_aContent.find( _id ) != m_aContent.end(); }
+
+ inline bool supportsAnySpecialSetting() const;
+ inline bool supportsGeneratedValues() const;
+
+ const_iterator begin() const { return m_aContent.begin(); }
+ const_iterator end() const { return m_aContent.end(); }
+
+ private:
+ std::set< ItemID > m_aContent;
+ };
+
+ inline bool FeatureSet::supportsGeneratedValues() const
+ {
+ return has( DSID_AUTORETRIEVEENABLED );
+ }
+
+ inline bool FeatureSet::supportsAnySpecialSetting() const
+ {
+ return has( DSID_SQL92CHECK )
+ || has( DSID_APPEND_TABLE_ALIAS )
+ || has( DSID_AS_BEFORE_CORRNAME )
+ || has( DSID_ENABLEOUTERJOIN )
+ || has( DSID_IGNOREDRIVER_PRIV )
+ || has( DSID_PARAMETERNAMESUBST )
+ || has( DSID_SUPPRESSVERSIONCL )
+ || has( DSID_CATALOG )
+ || has( DSID_SCHEMA )
+ || has( DSID_INDEXAPPENDIX )
+ || has( DSID_DOSLINEENDS )
+ || has( DSID_BOOLEANCOMPARISON )
+ || has( DSID_CHECK_REQUIRED_FIELDS )
+ || has( DSID_IGNORECURRENCY )
+ || has( DSID_ESCAPE_DATETIME )
+ || has( DSID_PRIMARY_KEY_SUPPORT )
+ || has( DSID_MAX_ROW_SCAN )
+ || has( DSID_RESPECTRESULTSETTYPE )
+ ;
+ }
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/exsrcbrw.hxx b/dbaccess/source/ui/inc/exsrcbrw.hxx
new file mode 100644
index 000000000..0ecda1ed6
--- /dev/null
+++ b/dbaccess/source/ui/inc/exsrcbrw.hxx
@@ -0,0 +1,96 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include "brwctrlr.hxx"
+
+#include <comphelper/interfacecontainer3.hxx>
+#include <comphelper/uno3.hxx>
+
+// SbaExternalSourceBrowser
+
+namespace dbaui
+{
+ class SbaXFormAdapter;
+ class SbaExternalSourceBrowser final
+ :public SbaXDataBrowserController
+ ,public css::util::XModifyBroadcaster
+ {
+ ::comphelper::OInterfaceContainerHelper3<css::util::XModifyListener> m_aModifyListeners;
+ // for multiplexing the modify events
+ rtl::Reference<SbaXFormAdapter> m_pDataSourceImpl;
+ bool m_bInQueryDispatch;
+ // our queryDispatch will ask our frame, which first will ask our queryDispatch, so we need to protect against
+ // recursion
+
+ public:
+ SbaExternalSourceBrowser(const css::uno::Reference< css::uno::XComponentContext >& _rM);
+
+ // UNO
+ DECLARE_UNO3_DEFAULTS(SbaExternalSourceBrowser, SbaXDataBrowserController)
+ virtual css::uno::Any SAL_CALL queryInterface(const css::uno::Type& _rType) override;
+ // virtual css::uno::Sequence< css::uno::Reference< css::reflection::XIdlClass > > getIdlClasses();
+
+ // static css::uno::Reference< css::reflection::XIdlClass > getStaticIdlClass();
+
+ // css::frame::XDispatch
+ virtual void SAL_CALL dispatch(const css::util::URL& aURL, const css::uno::Sequence< css::beans::PropertyValue>& aArgs) override;
+
+ // css::frame::XDispatchProvider
+ virtual css::uno::Reference< css::frame::XDispatch > SAL_CALL queryDispatch(const css::util::URL& aURL, const OUString& aTargetFrameName, sal_Int32 nSearchFlags) override;
+
+ // css::util::XModifyListener
+ virtual void SAL_CALL modified(const css::lang::EventObject& aEvent) override;
+
+ // css::util::XModifyBroadcaster
+ virtual void SAL_CALL addModifyListener(const css::uno::Reference< css::util::XModifyListener > & aListener) override;
+ virtual void SAL_CALL removeModifyListener(const css::uno::Reference< css::util::XModifyListener > & aListener) override;
+
+ // css::lang::XComponent
+ virtual void SAL_CALL disposing() override;
+
+ // css::form::XLoadListener
+ virtual void SAL_CALL unloading(const css::lang::EventObject& aEvent) override;
+
+ // css::lang::XEventListener
+ virtual void SAL_CALL disposing(const css::lang::EventObject& Source) override;
+
+ // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override;
+
+ private:
+ virtual ~SbaExternalSourceBrowser() override;
+
+ virtual css::uno::Reference< css::sdbc::XRowSet > CreateForm() override;
+ virtual bool InitializeForm( const css::uno::Reference< css::beans::XPropertySet >& i_formProperties ) override;
+
+ virtual bool LoadForm() override;
+
+ void Attach(const css::uno::Reference< css::sdbc::XRowSet > & xMaster);
+
+ void ClearView();
+
+ void startListening();
+ void stopListening();
+ };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/formadapter.hxx b/dbaccess/source/ui/inc/formadapter.hxx
new file mode 100644
index 000000000..c6d565896
--- /dev/null
+++ b/dbaccess/source/ui/inc/formadapter.hxx
@@ -0,0 +1,436 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include "sbamultiplex.hxx"
+
+#include <com/sun/star/sdbc/XRow.hpp>
+#include <com/sun/star/sdbc/XParameters.hpp>
+#include <com/sun/star/sdbc/XColumnLocate.hpp>
+#include <com/sun/star/sdbc/XCloseable.hpp>
+#include <com/sun/star/sdbcx/XRowLocate.hpp>
+#include <com/sun/star/sdbc/XRowUpdate.hpp>
+#include <com/sun/star/sdbc/XResultSetUpdate.hpp>
+#include <com/sun/star/sdbc/XRowSet.hpp>
+#include <com/sun/star/sdbcx/XDeleteRows.hpp>
+#include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp>
+#include <com/sun/star/sdbc/XWarningsSupplier.hpp>
+#include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
+#include <com/sun/star/sdb/XSQLErrorBroadcaster.hpp>
+#include <com/sun/star/sdb/XRowSetApproveBroadcaster.hpp>
+#include <com/sun/star/form/XLoadable.hpp>
+#include <com/sun/star/sdb/XResultSetAccess.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/container/XNameContainer.hpp>
+#include <com/sun/star/form/XForm.hpp>
+#include <com/sun/star/beans/XMultiPropertySet.hpp>
+#include <com/sun/star/beans/XFastPropertySet.hpp>
+#include <com/sun/star/container/XIndexContainer.hpp>
+#include <com/sun/star/container/XContainer.hpp>
+#include <com/sun/star/form/XReset.hpp>
+#include <com/sun/star/form/XSubmit.hpp>
+#include <com/sun/star/form/XDatabaseParameterBroadcaster.hpp>
+#include <com/sun/star/container/XEnumerationAccess.hpp>
+#include <com/sun/star/beans/XPropertyState.hpp>
+#include <com/sun/star/awt/XTabControllerModel.hpp>
+#include <com/sun/star/io/XPersistObject.hpp>
+#include <com/sun/star/container/XNamed.hpp>
+#include <com/sun/star/util/XCancellable.hpp>
+#include <comphelper/interfacecontainer3.hxx>
+#include <comphelper/uno3.hxx>
+#include <cppuhelper/implbase.hxx>
+#include <cppuhelper/implbase12.hxx>
+#include <cppuhelper/implbase10.hxx>
+
+namespace dbaui
+{
+ // SbaXFormAdapter
+
+ typedef ::cppu::WeakImplHelper< css::sdbc::XResultSetMetaDataSupplier
+ , css::sdb::XResultSetAccess
+ , css::sdbc::XResultSetUpdate
+ , css::sdbc::XRowSet
+ , css::sdb::XRowSetApproveBroadcaster
+ , css::sdbcx::XRowLocate
+ , css::sdbc::XRowUpdate
+ , css::sdbc::XRow
+ , css::sdbcx::XColumnsSupplier
+ , css::sdbc::XColumnLocate
+ // --- stardiv::one::form::component::DatabaseForm ---
+ , css::sdbc::XParameters
+ , css::sdbcx::XDeleteRows
+ > SbaXFormAdapter_BASE1;
+ typedef ::cppu::ImplHelper12 < css::sdbc::XWarningsSupplier
+ , css::sdbc::XCloseable
+ , css::form::XLoadable
+ , css::sdb::XSQLErrorBroadcaster
+ , css::form::XDatabaseParameterBroadcaster
+ // --- stardiv::one::form::component::Form ---
+ , css::form::XForm
+ , css::form::XSubmit
+ , css::awt::XTabControllerModel
+ // --- stardiv::one::form::FormComponent ---
+ , css::lang::XComponent
+ , css::beans::XFastPropertySet
+ // already present : css::form::XFormComponent (base of css::form::XForm)
+ , css::beans::XMultiPropertySet
+ , css::container::XNamed
+ > SbaXFormAdapter_BASE2;
+ typedef ::cppu::ImplHelper10 < css::io::XPersistObject
+ , css::beans::XPropertySet
+ // --- stardiv::one::data::DatabaseCursor ---
+ , css::util::XCancellable
+ // already present : css::beans::XPropertySet
+ // --- stardiv::one::data::DatabaseComponent ---
+ // already present : css::lang::XComponent
+ // already present : css::container::XChild (base of css::form::XForm)
+ // interfaces I don't know the service which they belong to ;)
+ // (they are supported by FmXDatabaseForm, se we support it, too)
+ , css::beans::XPropertyState
+ , css::form::XReset
+ , css::container::XNameContainer
+ , css::container::XIndexContainer
+ , css::container::XContainer
+ , css::container::XEnumerationAccess
+ // interfaces we need because of other reasons
+ , css::beans::XPropertyChangeListener
+ > SbaXFormAdapter_BASE3;
+
+ class SbaXFormAdapter final
+ :public SbaXFormAdapter_BASE1
+ ,public SbaXFormAdapter_BASE2
+ ,public SbaXFormAdapter_BASE3
+ {
+ private:
+ css::uno::Reference< css::sdbc::XRowSet > m_xMainForm;
+ ::osl::Mutex m_aMutex;
+
+ SbaXLoadMultiplexer m_aLoadListeners;
+ SbaXRowSetMultiplexer m_aRowSetListeners;
+ SbaXRowSetApproveMultiplexer m_aRowSetApproveListeners;
+ SbaXSQLErrorMultiplexer m_aErrorListeners;
+ SbaXParameterMultiplexer m_aParameterListeners;
+ SbaXSubmitMultiplexer m_aSubmitListeners;
+ SbaXResetMultiplexer m_aResetListeners;
+
+ SbaXPropertyChangeMultiplexer m_aPropertyChangeListeners;
+ SbaXVetoableChangeMultiplexer m_aVetoablePropertyChangeListeners;
+ SbaXPropertiesChangeMultiplexer m_aPropertiesChangeListeners;
+
+ ::comphelper::OInterfaceContainerHelper3<css::lang::XEventListener> m_aDisposeListeners;
+ ::comphelper::OInterfaceContainerHelper3<css::container::XContainerListener> m_aContainerListeners;
+
+ // hierarchy administration
+ css::uno::Reference< css::uno::XInterface > m_xParent;
+ std::vector< css::uno::Reference< css::form::XFormComponent > > m_aChildren;
+ std::vector< OUString > m_aChildNames;
+
+ // properties
+ OUString m_sName;
+ sal_Int32 m_nNamePropHandle;
+
+ public:
+ const css::uno::Reference< css::sdbc::XRowSet >& getAttachedForm() const { return m_xMainForm; }
+
+ public:
+ SbaXFormAdapter();
+ virtual ~SbaXFormAdapter() override;
+
+ // css::uno::Reference< css::reflection::XIdlClass > getIdlClass();
+ // css::uno::Sequence<css::uno::Reference< css::reflection::XIdlClass > > getIdlClasses();
+
+ void AttachForm(const css::uno::Reference< css::sdbc::XRowSet >& xNewMaster);
+
+ // UNO
+ DECLARE_UNO3_DEFAULTS(SbaXFormAdapter, SbaXFormAdapter_BASE1)
+ virtual css::uno::Any SAL_CALL queryInterface(const css::uno::Type& _rType) override;
+
+ // XTypeProvider
+ virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes( ) override;
+ virtual css::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId( ) override;
+
+ // css::sdbc::XCloseable
+ virtual void SAL_CALL close() override;
+
+ // css::sdbc::XResultSetMetaDataSupplier
+ virtual css::uno::Reference< css::sdbc::XResultSetMetaData > SAL_CALL getMetaData() override;
+
+ // css::sdbc::XColumnLocate
+ virtual sal_Int32 SAL_CALL findColumn(const OUString& columnName) override;
+
+ // css::sdbcx::XColumnsSupplier
+ virtual css::uno::Reference< css::container::XNameAccess > SAL_CALL getColumns() override;
+
+ // css::sdbc::XRow
+ virtual sal_Bool SAL_CALL wasNull() override;
+ virtual OUString SAL_CALL getString(sal_Int32 columnIndex) override;
+ virtual sal_Bool SAL_CALL getBoolean(sal_Int32 columnIndex) override;
+ virtual sal_Int8 SAL_CALL getByte(sal_Int32 columnIndex) override;
+ virtual sal_Int16 SAL_CALL getShort(sal_Int32 columnIndex) override;
+ virtual sal_Int32 SAL_CALL getInt(sal_Int32 columnIndex) override;
+ virtual sal_Int64 SAL_CALL getLong(sal_Int32 columnIndex) override;
+ virtual float SAL_CALL getFloat(sal_Int32 columnIndex) override;
+ virtual double SAL_CALL getDouble(sal_Int32 columnIndex) override;
+ virtual css::uno::Sequence< sal_Int8 > SAL_CALL getBytes(sal_Int32 columnIndex) override;
+ virtual css::util::Date SAL_CALL getDate(sal_Int32 columnIndex) override;
+ virtual css::util::Time SAL_CALL getTime(sal_Int32 columnIndex) override;
+ virtual css::util::DateTime SAL_CALL getTimestamp(sal_Int32 columnIndex) override;
+ virtual css::uno::Reference< css::io::XInputStream > SAL_CALL getBinaryStream(sal_Int32 columnIndex) override;
+ virtual css::uno::Reference< css::io::XInputStream > SAL_CALL getCharacterStream(sal_Int32 columnIndex) override;
+ virtual css::uno::Any SAL_CALL getObject(sal_Int32 columnIndex, const css::uno::Reference< css::container::XNameAccess >& typeMap) override;
+ virtual css::uno::Reference< css::sdbc::XRef > SAL_CALL getRef(sal_Int32 columnIndex) override;
+ virtual css::uno::Reference< css::sdbc::XBlob > SAL_CALL getBlob(sal_Int32 columnIndex) override;
+ virtual css::uno::Reference< css::sdbc::XClob > SAL_CALL getClob(sal_Int32 columnIndex) override;
+ virtual css::uno::Reference< css::sdbc::XArray > SAL_CALL getArray(sal_Int32 columnIndex) override;
+
+ // css::sdbcx::XRowLocate
+ virtual css::uno::Any SAL_CALL getBookmark() override;
+ virtual sal_Bool SAL_CALL moveToBookmark(const css::uno::Any& bookmark) override;
+ virtual sal_Bool SAL_CALL moveRelativeToBookmark(const css::uno::Any& bookmark, sal_Int32 rows) override;
+ virtual sal_Int32 SAL_CALL compareBookmarks(const css::uno::Any& first, const css::uno::Any& second) override;
+ virtual sal_Bool SAL_CALL hasOrderedBookmarks() override;
+ virtual sal_Int32 SAL_CALL hashBookmark(const css::uno::Any& bookmark) override;
+
+ // css::sdbc::XRowUpdate
+ virtual void SAL_CALL updateNull(sal_Int32 columnIndex) override;
+ virtual void SAL_CALL updateBoolean(sal_Int32 columnIndex, sal_Bool x) override;
+ virtual void SAL_CALL updateByte(sal_Int32 columnIndex, sal_Int8 x) override;
+ virtual void SAL_CALL updateShort(sal_Int32 columnIndex, sal_Int16 x) override;
+ virtual void SAL_CALL updateInt(sal_Int32 columnIndex, sal_Int32 x) override;
+ virtual void SAL_CALL updateLong(sal_Int32 columnIndex, sal_Int64 x) override;
+ virtual void SAL_CALL updateFloat(sal_Int32 columnIndex, float x) override;
+ virtual void SAL_CALL updateDouble(sal_Int32 columnIndex, double x) override;
+ virtual void SAL_CALL updateString(sal_Int32 columnIndex, const OUString& x) override;
+ virtual void SAL_CALL updateBytes(sal_Int32 columnIndex, const css::uno::Sequence< sal_Int8 >& x) override;
+ virtual void SAL_CALL updateDate(sal_Int32 columnIndex, const css::util::Date& x) override;
+ virtual void SAL_CALL updateTime(sal_Int32 columnIndex, const css::util::Time& x) override;
+ virtual void SAL_CALL updateTimestamp(sal_Int32 columnIndex, const css::util::DateTime& x) override;
+ virtual void SAL_CALL updateBinaryStream(sal_Int32 columnIndex, const css::uno::Reference< css::io::XInputStream >& x, sal_Int32 length) override;
+ virtual void SAL_CALL updateCharacterStream(sal_Int32 columnIndex, const css::uno::Reference< css::io::XInputStream >& x, sal_Int32 length) override;
+ virtual void SAL_CALL updateObject(sal_Int32 columnIndex, const css::uno::Any& x) override;
+ virtual void SAL_CALL updateNumericObject(sal_Int32 columnIndex, const css::uno::Any& x, sal_Int32 scale) override;
+
+ // css::sdbc::XResultSet
+ virtual sal_Bool SAL_CALL next() override;
+ virtual sal_Bool SAL_CALL isBeforeFirst() override;
+ virtual sal_Bool SAL_CALL isAfterLast() override;
+ virtual sal_Bool SAL_CALL isFirst() override;
+ virtual sal_Bool SAL_CALL isLast() override;
+ virtual void SAL_CALL beforeFirst() override;
+ virtual void SAL_CALL afterLast() override;
+ virtual sal_Bool SAL_CALL first() override;
+ virtual sal_Bool SAL_CALL last() override;
+ virtual sal_Int32 SAL_CALL getRow() override;
+ virtual sal_Bool SAL_CALL absolute(sal_Int32 row) override;
+ virtual sal_Bool SAL_CALL relative(sal_Int32 rows) override;
+ virtual sal_Bool SAL_CALL previous() override;
+ virtual void SAL_CALL refreshRow() override;
+ virtual sal_Bool SAL_CALL rowUpdated() override;
+ virtual sal_Bool SAL_CALL rowInserted() override;
+ virtual sal_Bool SAL_CALL rowDeleted() override;
+ virtual css::uno::Reference< css::uno::XInterface > SAL_CALL getStatement() override;
+
+ // css::sdbc::XResultSetUpdate
+ virtual void SAL_CALL insertRow() override;
+ virtual void SAL_CALL updateRow() override;
+ virtual void SAL_CALL deleteRow() override;
+ virtual void SAL_CALL cancelRowUpdates() override;
+ virtual void SAL_CALL moveToInsertRow() override;
+ virtual void SAL_CALL moveToCurrentRow() override;
+
+ // css::sdbc::XRowSet
+ virtual void SAL_CALL execute() override;
+ virtual void SAL_CALL addRowSetListener(const css::uno::Reference< css::sdbc::XRowSetListener >& listener) override;
+ virtual void SAL_CALL removeRowSetListener(const css::uno::Reference< css::sdbc::XRowSetListener >& listener) override;
+
+ // css::sdbcx::XDeleteRows
+ virtual css::uno::Sequence<sal_Int32> SAL_CALL deleteRows(const css::uno::Sequence< css::uno::Any >& rows) override;
+
+ // css::sdbc::XWarningsSupplier
+ virtual css::uno::Any SAL_CALL getWarnings() override;
+ virtual void SAL_CALL clearWarnings() override;
+
+ // css::sdb::XRowSetApproveBroadcaster
+ virtual void SAL_CALL addRowSetApproveListener(const css::uno::Reference< css::sdb::XRowSetApproveListener >& listener) override;
+ virtual void SAL_CALL removeRowSetApproveListener(const css::uno::Reference< css::sdb::XRowSetApproveListener >& listener) override;
+
+ // css::sdbc::XSQLErrorBroadcaster
+ virtual void SAL_CALL addSQLErrorListener(const css::uno::Reference< css::sdb::XSQLErrorListener >& _rListener) override;
+ virtual void SAL_CALL removeSQLErrorListener(const css::uno::Reference< css::sdb::XSQLErrorListener >& _rListener) override;
+
+ // css::sdb::XResultSetAccess
+ virtual css::uno::Reference< css::sdbc::XResultSet > SAL_CALL createResultSet() override;
+
+ // css::form::XLoadable
+ virtual void SAL_CALL load() override;
+ virtual void SAL_CALL unload() override;
+ virtual void SAL_CALL reload() override;
+ virtual sal_Bool SAL_CALL isLoaded() override;
+ virtual void SAL_CALL addLoadListener(const css::uno::Reference< css::form::XLoadListener >& aListener) override;
+ virtual void SAL_CALL removeLoadListener(const css::uno::Reference< css::form::XLoadListener >& aListener) override;
+
+ // css::sdbc::XParameters
+ virtual void SAL_CALL setNull(sal_Int32 parameterIndex, sal_Int32 sqlType) override;
+ virtual void SAL_CALL setObjectNull(sal_Int32 parameterIndex, sal_Int32 sqlType, const OUString& typeName) override;
+ virtual void SAL_CALL setBoolean(sal_Int32 parameterIndex, sal_Bool x) override;
+ virtual void SAL_CALL setByte(sal_Int32 parameterIndex, sal_Int8 x) override;
+ virtual void SAL_CALL setShort(sal_Int32 parameterIndex, sal_Int16 x) override;
+ virtual void SAL_CALL setInt(sal_Int32 parameterIndex, sal_Int32 x) override;
+ virtual void SAL_CALL setLong(sal_Int32 parameterIndex, sal_Int64 x) override;
+ virtual void SAL_CALL setFloat(sal_Int32 parameterIndex, float x) override;
+ virtual void SAL_CALL setDouble(sal_Int32 parameterIndex, double x) override;
+ virtual void SAL_CALL setString(sal_Int32 parameterIndex, const OUString& x) override;
+ virtual void SAL_CALL setBytes(sal_Int32 parameterIndex, const css::uno::Sequence< sal_Int8 >& x) override;
+ virtual void SAL_CALL setDate(sal_Int32 parameterIndex, const css::util::Date& x) override;
+ virtual void SAL_CALL setTime(sal_Int32 parameterIndex, const css::util::Time& x) override;
+ virtual void SAL_CALL setTimestamp(sal_Int32 parameterIndex, const css::util::DateTime& x) override;
+ virtual void SAL_CALL setBinaryStream(sal_Int32 parameterIndex, const css::uno::Reference< css::io::XInputStream >& x, sal_Int32 length) override;
+ virtual void SAL_CALL setCharacterStream(sal_Int32 parameterIndex, const css::uno::Reference< css::io::XInputStream >& x, sal_Int32 length) override;
+ virtual void SAL_CALL setObject(sal_Int32 parameterIndex, const css::uno::Any& x) override;
+ virtual void SAL_CALL setObjectWithInfo(sal_Int32 parameterIndex, const css::uno::Any& x, sal_Int32 targetSqlType, sal_Int32 scale) override;
+ virtual void SAL_CALL setRef(sal_Int32 parameterIndex, const css::uno::Reference< css::sdbc::XRef >& x) override;
+ virtual void SAL_CALL setBlob(sal_Int32 parameterIndex, const css::uno::Reference< css::sdbc::XBlob >& x) override;
+ virtual void SAL_CALL setClob(sal_Int32 parameterIndex, const css::uno::Reference< css::sdbc::XClob >& x) override;
+ virtual void SAL_CALL setArray(sal_Int32 parameterIndex, const css::uno::Reference< css::sdbc::XArray >& x) override;
+ virtual void SAL_CALL clearParameters() override;
+
+ // css::form::XDatabaseParameterBroadcaster
+ virtual void SAL_CALL addParameterListener(const css::uno::Reference< css::form::XDatabaseParameterListener >& aListener) override;
+ virtual void SAL_CALL removeParameterListener(const css::uno::Reference< css::form::XDatabaseParameterListener >& aListener) override;
+
+ // css::container::XChild
+ virtual css::uno::Reference< css::uno::XInterface > SAL_CALL getParent() override;
+ virtual void SAL_CALL setParent(const css::uno::Reference< css::uno::XInterface >& Parent) override;
+
+ // css::form::XSubmit
+ virtual void SAL_CALL submit(const css::uno::Reference< css::awt::XControl >& aControl, const css::awt::MouseEvent& aMouseEvt) override;
+ virtual void SAL_CALL addSubmitListener(const css::uno::Reference< css::form::XSubmitListener >& aListener) override;
+ virtual void SAL_CALL removeSubmitListener(const css::uno::Reference< css::form::XSubmitListener >& aListener) override;
+
+ // css::awt::XTabControllerModel
+ virtual sal_Bool SAL_CALL getGroupControl() override;
+ virtual void SAL_CALL setGroupControl(sal_Bool GroupControl) override;
+ virtual void SAL_CALL setControlModels(const css::uno::Sequence< css::uno::Reference< css::awt::XControlModel > >& Controls) override;
+ virtual css::uno::Sequence< css::uno::Reference< css::awt::XControlModel > > SAL_CALL getControlModels() override;
+ virtual void SAL_CALL setGroup(const css::uno::Sequence< css::uno::Reference< css::awt::XControlModel > >& _rGroup, const OUString& GroupName) override;
+ virtual sal_Int32 SAL_CALL getGroupCount() override;
+ virtual void SAL_CALL getGroup(sal_Int32 nGroup, css::uno::Sequence< css::uno::Reference< css::awt::XControlModel > >& _rGroup, OUString& Name) override;
+ virtual void SAL_CALL getGroupByName(const OUString& Name, css::uno::Sequence< css::uno::Reference< css::awt::XControlModel > >& _rGroup) override;
+
+ // css::lang::XComponent
+ virtual void SAL_CALL dispose() override;
+ virtual void SAL_CALL addEventListener(const css::uno::Reference< css::lang::XEventListener >& xListener) override;
+ virtual void SAL_CALL removeEventListener(const css::uno::Reference< css::lang::XEventListener >& aListener) override;
+
+ // css::beans::XFastPropertySet
+ virtual void SAL_CALL setFastPropertyValue(sal_Int32 nHandle, const css::uno::Any& aValue) override;
+ virtual css::uno::Any SAL_CALL getFastPropertyValue(sal_Int32 nHandle) override;
+
+ // css::container::XNamed
+ virtual OUString SAL_CALL getName() override;
+ virtual void SAL_CALL setName(const OUString& aName) override;
+
+ // css::io::XPersistObject
+ virtual OUString SAL_CALL getServiceName() override;
+ virtual void SAL_CALL write(const css::uno::Reference< css::io::XObjectOutputStream >& _rxOutStream) override;
+ virtual void SAL_CALL read(const css::uno::Reference< css::io::XObjectInputStream >& _rxInStream) override;
+
+ // css::beans::XMultiPropertySet
+ virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo() override;
+ virtual void SAL_CALL setPropertyValues(const css::uno::Sequence< OUString >& PropertyNames, const css::uno::Sequence< css::uno::Any >& Values) override;
+ virtual css::uno::Sequence< css::uno::Any > SAL_CALL getPropertyValues(const css::uno::Sequence< OUString >& aPropertyNames) override;
+ virtual void SAL_CALL addPropertiesChangeListener(const css::uno::Sequence< OUString >& aPropertyNames, const css::uno::Reference< css::beans::XPropertiesChangeListener >& xListener) override;
+ virtual void SAL_CALL removePropertiesChangeListener(const css::uno::Reference< css::beans::XPropertiesChangeListener >& Listener) override;
+ virtual void SAL_CALL firePropertiesChangeEvent(const css::uno::Sequence< OUString >& aPropertyNames, const css::uno::Reference< css::beans::XPropertiesChangeListener >& xListener) override;
+
+ // css::beans::XPropertySet
+ virtual void SAL_CALL setPropertyValue(const OUString& aPropertyName, const css::uno::Any& aValue) override;
+ virtual css::uno::Any SAL_CALL getPropertyValue(const OUString& PropertyName) override;
+ virtual void SAL_CALL addPropertyChangeListener(const OUString& aPropertyName, const css::uno::Reference< css::beans::XPropertyChangeListener >& xListener) override;
+ virtual void SAL_CALL removePropertyChangeListener(const OUString& aPropertyName, const css::uno::Reference< css::beans::XPropertyChangeListener >& aListener) override;
+ virtual void SAL_CALL addVetoableChangeListener(const OUString& PropertyName, const css::uno::Reference< css::beans::XVetoableChangeListener >& aListener) override;
+ virtual void SAL_CALL removeVetoableChangeListener(const OUString& PropertyName, const css::uno::Reference< css::beans::XVetoableChangeListener >& aListener) override;
+
+ // css::util::XCancellable
+ virtual void SAL_CALL cancel() override;
+
+ // css::beans::XPropertyState
+ virtual css::beans::PropertyState SAL_CALL getPropertyState(const OUString& PropertyName) override;
+ virtual css::uno::Sequence< css::beans::PropertyState > SAL_CALL getPropertyStates(const css::uno::Sequence< OUString >& aPropertyName) override;
+ virtual void SAL_CALL setPropertyToDefault(const OUString& PropertyName) override;
+ virtual css::uno::Any SAL_CALL getPropertyDefault(const OUString& aPropertyName) override;
+
+ // css::form::XReset
+ virtual void SAL_CALL reset() override;
+ virtual void SAL_CALL addResetListener(const css::uno::Reference< css::form::XResetListener >& aListener) override;
+ virtual void SAL_CALL removeResetListener(const css::uno::Reference< css::form::XResetListener >& aListener) override;
+
+ // css::container::XNameContainer
+ virtual void SAL_CALL insertByName(const OUString& aName, const css::uno::Any& aElement) override;
+ virtual void SAL_CALL removeByName(const OUString& Name) override;
+
+ // css::container::XNameReplace
+ virtual void SAL_CALL replaceByName(const OUString& aName, const css::uno::Any& aElement) override;
+
+ // css::container::XNameAccess
+ virtual css::uno::Any SAL_CALL getByName(const OUString& aName) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getElementNames() override;
+ virtual sal_Bool SAL_CALL hasByName(const OUString& aName) override;
+
+ // css::container::XElementAccess
+ virtual css::uno::Type SAL_CALL getElementType() override ;
+ virtual sal_Bool SAL_CALL hasElements() override;
+
+ // css::container::XIndexContainer
+ virtual void SAL_CALL insertByIndex(sal_Int32 _rIndex, const css::uno::Any& Element) override;
+ virtual void SAL_CALL removeByIndex(sal_Int32 _rIndex) override;
+
+ // css::container::XIndexReplace
+ virtual void SAL_CALL replaceByIndex(sal_Int32 _rIndex, const css::uno::Any& Element) override;
+
+ // css::container::XIndexAccess
+ virtual sal_Int32 SAL_CALL getCount() override;
+ virtual css::uno::Any SAL_CALL getByIndex(sal_Int32 _rIndex) override;
+
+ // css::container::XContainer
+ virtual void SAL_CALL addContainerListener(const css::uno::Reference< css::container::XContainerListener >& xListener) override;
+ virtual void SAL_CALL removeContainerListener(const css::uno::Reference< css::container::XContainerListener >& xListener) override;
+
+ // css::container::XEnumerationAccess
+ virtual css::uno::Reference< css::container::XEnumeration > SAL_CALL createEnumeration() override;
+
+ // css::lang::XEventListener
+ virtual void SAL_CALL disposing(const css::lang::EventObject& Source) override;
+
+ // css::beans::XPropertyChangeListener
+ virtual void SAL_CALL propertyChange(const css::beans::PropertyChangeEvent& evt) override;
+
+ private:
+ // container handling
+ /// @throws css::lang::IllegalArgumentException
+ void implInsert(const css::uno::Any& aElement, sal_Int32 nIndex, const OUString* pNewElName = nullptr);
+ sal_Int32 implGetPos(const OUString& rName);
+
+ void StopListening();
+ void StartListening();
+ };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/imageprovider.hxx b/dbaccess/source/ui/inc/imageprovider.hxx
new file mode 100644
index 000000000..a8d24f428
--- /dev/null
+++ b/dbaccess/source/ui/inc/imageprovider.hxx
@@ -0,0 +1,105 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <com/sun/star/graphic/XGraphic.hpp>
+#include <com/sun/star/sdbc/XConnection.hpp>
+
+#include <memory>
+
+namespace dbaui
+{
+ // ImageProvider
+ struct ImageProvider_Data;
+ /** provides images for database objects such as tables, queries, forms, reports ...
+
+ At the moment, this class cares for small icons only, that is, icons which can be used
+ in a tree control. On the medium term, we should extend it with support for different-sized
+ icons.
+ */
+ class ImageProvider
+ {
+ private:
+ std::shared_ptr< ImageProvider_Data > m_pData;
+
+ public:
+ /** creates a semi-functional ImageProvider instance
+
+ The resulting instance is not able to provide any concrete object images,
+ but only default images.
+ */
+ ImageProvider();
+
+ /** creates an ImageProvider instance
+
+ @param _rxConnection
+ denotes the connection to work for. Must not be <NULL/>.
+ */
+ ImageProvider(
+ const css::uno::Reference< css::sdbc::XConnection >& _rxConnection
+ );
+
+ /** returns the image to be used for a database object with the given name
+
+ @param _nDatabaseObjectType
+ the type of the object. Must be one of the css.sdb.application.DatabaseObject
+ constants.
+ @param _rName
+ the name of the object
+ @return
+ the name of the image to be used for the object.
+ */
+ OUString getImageId(
+ const OUString& _rName,
+ const sal_Int32 _nDatabaseObjectType
+ );
+
+ // check whether the connection can give us an icon
+ css::uno::Reference<css::graphic::XGraphic> getXGraphic(const OUString& _rName,
+ const sal_Int32 _nDatabaseObjectType);
+
+ /** returns the resource ID for the default image to be used for a database object
+
+ In opposite to getImageId, this method does not check the concrete object
+ for its image, but returns a default image to be used for all objects of the given
+ type.
+
+ @param _nDatabaseObjectType
+ the type of the object. Must be one of the css.sdb.application.DatabaseObject
+ constants.
+ @return
+ the resource image name to be used for the object type.
+ */
+ static OUString getDefaultImageResourceID(sal_Int32 _nDatabaseObjectType);
+
+ static OUString getFolderImageId(
+ sal_Int32 _nDatabaseObjectType
+ );
+
+ /** retrieves the image to be used for a database as a whole.
+ @return
+ the image to be used for folders of this type
+ */
+ static OUString getDatabaseImage();
+ };
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/indexcollection.hxx b/dbaccess/source/ui/inc/indexcollection.hxx
new file mode 100644
index 000000000..d677eed06
--- /dev/null
+++ b/dbaccess/source/ui/inc/indexcollection.hxx
@@ -0,0 +1,94 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <com/sun/star/container/XNameAccess.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include "indexes.hxx"
+
+namespace dbaui
+{
+
+ // OIndexCollection
+ class OIndexCollection
+ {
+ protected:
+ css::uno::Reference< css::container::XNameAccess >
+ m_xIndexes;
+
+ // cached information
+ Indexes m_aIndexes;
+
+ public:
+ // construction
+ OIndexCollection();
+ OIndexCollection(const OIndexCollection& _rSource);
+ // OIndexCollection(const css::uno::Reference< css::container::XNameAccess >& _rxIndexes);
+
+ OIndexCollection& operator=(const OIndexCollection& _rSource);
+
+ // iterating through the collection
+ typedef OIndex* iterator;
+ typedef OIndex const* const_iterator;
+
+ /// get access to the first element of the index collection
+ Indexes::const_iterator begin() const { return m_aIndexes.begin(); }
+ /// get access to the first element of the index collection
+ Indexes::iterator begin() { return m_aIndexes.begin(); }
+ /// get access to the (last + 1st) element of the index collection
+ Indexes::const_iterator end() const { return m_aIndexes.end(); }
+ /// get access to the (last + 1st) element of the index collection
+ Indexes::iterator end() { return m_aIndexes.end(); }
+
+ // searching
+ Indexes::const_iterator find(const OUString& _rName) const;
+ Indexes::iterator find(const OUString& _rName);
+ Indexes::const_iterator findOriginal(const OUString& _rName) const;
+ Indexes::iterator findOriginal(const OUString& _rName);
+
+ // inserting without committing
+ // the OriginalName of the newly inserted index will be empty, thus indicating that it's new
+ Indexes::iterator insert(const OUString& _rName);
+ // commit a new index, which is already part if the collection, but does not have an equivalent in the
+ // data source, yet
+ void commitNewIndex(const Indexes::iterator& _rPos);
+
+ // reset the data for the given index
+ void resetIndex(const Indexes::iterator& _rPos);
+
+ // attach to a new key container
+ void attach(const css::uno::Reference< css::container::XNameAccess >& _rxIndexes);
+ // detach from the container
+ void detach();
+
+ /// drop an index, and remove it from the collection
+ bool drop(const Indexes::iterator& _rPos);
+ /// simply drop the index described by the name, but don't remove the descriptor from the collection
+ bool dropNoRemove(const Indexes::iterator& _rPos);
+
+ protected:
+ void implConstructFrom(const css::uno::Reference< css::container::XNameAccess >& _rxIndexes);
+ static void implFillIndexInfo(OIndex& _rIndex, const css::uno::Reference< css::beans::XPropertySet >& _rxDescriptor);
+ void implFillIndexInfo(OIndex& _rIndex);
+ };
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/indexdialog.hxx b/dbaccess/source/ui/inc/indexdialog.hxx
new file mode 100644
index 000000000..f03b04f6f
--- /dev/null
+++ b/dbaccess/source/ui/inc/indexdialog.hxx
@@ -0,0 +1,103 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <com/sun/star/container/XNameAccess.hpp>
+#include <com/sun/star/sdbc/XConnection.hpp>
+#include <com/sun/star/uno/Sequence.hxx>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <vcl/weld.hxx>
+#include "indexes.hxx"
+
+namespace dbaui
+{
+ // DbaIndexDialog
+ class IndexFieldsControl;
+ class OIndexCollection;
+ class DbaIndexDialog final : public weld::GenericDialogController
+ {
+ css::uno::Reference< css::sdbc::XConnection > m_xConnection;
+
+ std::unique_ptr<OIndexCollection> m_xIndexes;
+ std::unique_ptr<weld::TreeIter> m_xPreviousSelection;
+ bool m_bEditingActive;
+ bool m_bEditAgain;
+ bool m_bNoHandlerCall;
+
+ css::uno::Reference< css::uno::XComponentContext >
+ m_xContext;
+
+ std::unique_ptr<weld::Toolbar> m_xActions;
+ std::unique_ptr<weld::TreeView> m_xIndexList;
+ std::unique_ptr<weld::Label> m_xIndexDetails;
+ std::unique_ptr<weld::Label> m_xDescriptionLabel;
+ std::unique_ptr<weld::Label> m_xDescription;
+ std::unique_ptr<weld::CheckButton> m_xUnique;
+ std::unique_ptr<weld::Label> m_xFieldsLabel;
+ std::unique_ptr<weld::Button> m_xClose;
+ std::unique_ptr<weld::Container> m_xTable;
+ css::uno::Reference<css::awt::XWindow> m_xTableCtrlParent;
+ VclPtr<IndexFieldsControl> m_xFields;
+
+ public:
+ DbaIndexDialog(
+ weld::Window* _pParent,
+ const css::uno::Sequence< OUString >& _rFieldNames,
+ const css::uno::Reference< css::container::XNameAccess >& _rxIndexes,
+ const css::uno::Reference< css::sdbc::XConnection >& _rxConnection,
+ const css::uno::Reference< css::uno::XComponentContext >& _rxContext);
+ virtual ~DbaIndexDialog() override;
+
+ typedef std::pair<const weld::TreeIter&, OUString> IterString;
+ private:
+ void fillIndexList();
+ void updateToolbox();
+ void updateControls(const weld::TreeIter* pEntry);
+
+ void IndexSelected();
+
+ DECL_LINK( OnIndexSelected, weld::TreeView&, void );
+ DECL_LINK( OnIndexAction, const OString&, void );
+ DECL_LINK( OnEntryEditing, const weld::TreeIter&, bool );
+ DECL_LINK( OnEntryEdited, const IterString&, bool );
+ DECL_LINK( OnModifiedClick, weld::Toggleable&, void );
+ DECL_LINK( OnModified, IndexFieldsControl&, void );
+ DECL_LINK( OnCloseDialog, weld::Button&, void );
+
+ DECL_LINK( OnEditIndexAgain, void*, void );
+
+ void OnNewIndex();
+ void OnDropIndex(bool _bConfirm = true);
+ void OnRenameIndex();
+ void OnSaveIndex();
+ void OnResetIndex();
+
+ bool implCommit(const weld::TreeIter* pEntry);
+ bool implSaveModified(bool _bPlausibility = true);
+ bool implCommitPreviouslySelected();
+
+ bool implDropIndex(const weld::TreeIter* pEntry, bool _bRemoveFromCollection);
+
+ bool implCheckPlausibility(const Indexes::const_iterator& _rPos);
+ };
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/indexes.hxx b/dbaccess/source/ui/inc/indexes.hxx
new file mode 100644
index 000000000..75bd5b44b
--- /dev/null
+++ b/dbaccess/source/ui/inc/indexes.hxx
@@ -0,0 +1,81 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <sal/config.h>
+
+#include <rtl/ustring.hxx>
+
+#include <vector>
+
+namespace dbaui
+{
+ // OIndexField
+ struct OIndexField
+ {
+ OUString sFieldName;
+ bool bSortAscending;
+
+ OIndexField() : bSortAscending(true) { }
+ };
+
+ typedef std::vector<OIndexField> IndexFields;
+
+ // OIndex
+ struct GrantIndexAccess
+ {
+ friend class OIndexCollection;
+ private:
+ GrantIndexAccess() { }
+ };
+
+ struct OIndex final
+ {
+ OUString sOriginalName;
+ bool bModified;
+
+ public:
+ OUString sName;
+ OUString sDescription;
+ bool bPrimaryKey;
+ bool bUnique;
+ IndexFields aFields;
+
+ OIndex(const OUString& _rOriginalName)
+ : sOriginalName(_rOriginalName), bModified(false), sName(_rOriginalName), bPrimaryKey(false), bUnique(false)
+ {
+ }
+
+ const OUString& getOriginalName() const { return sOriginalName; }
+
+ bool isModified() const { return bModified; }
+ void setModified(bool _bModified) { bModified = _bModified; }
+ void clearModified() { setModified(false); }
+
+ bool isNew() const { return getOriginalName().isEmpty(); }
+ void flagAsNew(const GrantIndexAccess&) { sOriginalName.clear(); }
+ void flagAsCommitted(const GrantIndexAccess&) { sOriginalName = sName; }
+ };
+
+ typedef std::vector<OIndex> Indexes;
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/indexfieldscontrol.hxx b/dbaccess/source/ui/inc/indexfieldscontrol.hxx
new file mode 100644
index 000000000..90ae7172e
--- /dev/null
+++ b/dbaccess/source/ui/inc/indexfieldscontrol.hxx
@@ -0,0 +1,91 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <svtools/editbrowsebox.hxx>
+#include <com/sun/star/awt/XWindow.hpp>
+#include <com/sun/star/uno/Sequence.hxx>
+#include "indexes.hxx"
+
+namespace dbaui
+{
+
+ class DbaMouseDownListBoxController;
+
+ // IndexFieldsControl
+ class IndexFieldsControl final : public ::svt::EditBrowseBox
+ {
+ IndexFields m_aSavedValue;
+
+ IndexFields m_aFields; // !! order matters !!
+ IndexFields::const_iterator m_aSeekRow; // !!
+
+ Link<IndexFieldsControl&,void> m_aModifyHdl;
+
+ VclPtr< ::svt::ListBoxControl> m_pSortingCell;
+ VclPtr< ::svt::ListBoxControl> m_pFieldNameCell;
+
+ OUString m_sAscendingText;
+ OUString m_sDescendingText;
+
+ bool m_bAddIndexAppendix;
+
+ public:
+ IndexFieldsControl(const css::uno::Reference<css::awt::XWindow> &rParent);
+ virtual ~IndexFieldsControl() override;
+ virtual void dispose() override;
+
+ void Init(const css::uno::Sequence< OUString >& _rAvailableFields, bool _bAddIndexAppendix);
+
+ void initializeFrom(IndexFields&& _rFields);
+ void commitTo(IndexFields& _rFields);
+
+ bool SaveModified() override;
+ using EditBrowseBox::IsModified;
+
+ const IndexFields& GetSavedValue() const { return m_aSavedValue; }
+ void SaveValue() { m_aSavedValue = m_aFields; }
+
+ void SetModifyHdl(const Link<IndexFieldsControl&,void>& _rHdl) { m_aModifyHdl = _rHdl; }
+ virtual OUString GetCellText(sal_Int32 _nRow,sal_uInt16 nColId) const override;
+
+ private:
+ // EditBrowseBox overridables
+ virtual void PaintCell( OutputDevice& _rDev, const tools::Rectangle& _rRect, sal_uInt16 _nColumnId ) const override;
+ virtual bool SeekRow(sal_Int32 nRow) override;
+ virtual sal_uInt32 GetTotalCellWidth(sal_Int32 nRow, sal_uInt16 nColId) override;
+ virtual bool IsTabAllowed(bool bForward) const override;
+
+ ::svt::CellController* GetController(sal_Int32 _nRow, sal_uInt16 _nColumnId) override;
+ void InitController(::svt::CellControllerRef&, sal_Int32 _nRow, sal_uInt16 _nColumnId) override;
+
+ OUString GetRowCellText(const IndexFields::const_iterator& _rRow,sal_uInt16 nColId) const;
+ bool implGetFieldDesc(sal_Int32 _nRow, IndexFields::const_iterator& _rPos);
+
+ bool isNewField() const { return GetCurRow() >= static_cast<sal_Int32>(m_aFields.size()); }
+
+ DECL_LINK( OnListEntrySelected, DbaMouseDownListBoxController&, void );
+
+ using ::svt::EditBrowseBox::Init;
+ };
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/linkeddocuments.hxx b/dbaccess/source/ui/inc/linkeddocuments.hxx
new file mode 100644
index 000000000..961b2ea4c
--- /dev/null
+++ b/dbaccess/source/ui/inc/linkeddocuments.hxx
@@ -0,0 +1,108 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include "AppElementType.hxx"
+
+#include <com/sun/star/container/XNameAccess.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <com/sun/star/lang/XComponent.hpp>
+#include <com/sun/star/sdbc/XConnection.hpp>
+#include <com/sun/star/sdb/application/XDatabaseDocumentUI.hpp>
+#include <comphelper/namedvaluecollection.hxx>
+
+namespace weld { class Window; }
+namespace dbaui
+{
+
+ // OLinkedDocumentsAccess
+ class OLinkedDocumentsAccess final
+ {
+ css::uno::Reference< css::uno::XComponentContext >
+ m_xContext;
+ css::uno::Reference< css::container::XNameAccess >
+ m_xDocumentContainer;
+ css::uno::Reference< css::sdbc::XConnection>
+ m_xConnection;
+ css::uno::Reference< css::sdb::application::XDatabaseDocumentUI >
+ m_xDocumentUI;
+ weld::Window* m_pDialogParent;
+ OUString m_sDataSourceName;
+
+ public:
+ OLinkedDocumentsAccess(
+ weld::Window* pDialogParent,
+ const css::uno::Reference< css::sdb::application::XDatabaseDocumentUI >& i_rDocumentUI,
+ const css::uno::Reference< css::uno::XComponentContext >& _rxContext,
+ const css::uno::Reference< css::container::XNameAccess >& _rxContainer,
+ const css::uno::Reference< css::sdbc::XConnection>& _xConnection,
+ const OUString& _sDataSourceName
+ );
+ ~OLinkedDocumentsAccess();
+
+ bool isConnected() const { return m_xConnection.is(); }
+
+ css::uno::Reference< css::lang::XComponent>
+ open(
+ const OUString& _rLinkName,
+ css::uno::Reference< css::lang::XComponent>& _xDefinition,
+ ElementOpenMode _eOpenMode,
+ const ::comphelper::NamedValueCollection& _rAdditionalArgs
+ );
+
+ css::uno::Reference< css::lang::XComponent >
+ newDocument(
+ sal_Int32 i_nActionID,
+ const ::comphelper::NamedValueCollection& i_rCreationArgs,
+ css::uno::Reference< css::lang::XComponent >& o_rDefinition
+ );
+
+ void newFormWithPilot(
+ const sal_Int32 _nCommandType,
+ const OUString& _rObjectName
+ );
+ void newReportWithPilot(
+ const sal_Int32 _nCommandType,
+ const OUString& _rObjectName
+ );
+ void newQueryWithPilot();
+ void newTableWithPilot();
+
+ private:
+ css::uno::Reference< css::lang::XComponent >
+ impl_open(
+ const OUString& _rLinkName,
+ css::uno::Reference< css::lang::XComponent >& _xDefinition,
+ ElementOpenMode _eOpenMode,
+ const ::comphelper::NamedValueCollection& _rAdditionalArgs
+ );
+
+ void
+ impl_newWithPilot(
+ const char* _pWizardService,
+ const sal_Int32 _nCommandType,
+ const OUString& _rObjectName
+ );
+
+ };
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/objectnamecheck.hxx b/dbaccess/source/ui/inc/objectnamecheck.hxx
new file mode 100644
index 000000000..52f639e53
--- /dev/null
+++ b/dbaccess/source/ui/inc/objectnamecheck.hxx
@@ -0,0 +1,57 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <rtl/ustring.hxx>
+
+namespace dbtools { class SQLExceptionInfo; }
+
+namespace dbaui
+{
+
+ // IObjectNameCheck
+ /** interface encapsulating the check for the validity of an object name
+ */
+ class IObjectNameCheck
+ {
+ public:
+ /** determines whether a given object name is valid
+
+ @param _rObjectName
+ the name to check
+ @param _out_rErrorToDisplay
+ output parameter taking an error message describing why the name is not
+ valid, if applicable.
+
+ @return
+ <TRUE/> if and only if the given name is valid.
+ */
+ virtual bool isNameValid(
+ const OUString& _rObjectName,
+ ::dbtools::SQLExceptionInfo& _out_rErrorToDisplay
+ ) const = 0;
+
+ public:
+ virtual ~IObjectNameCheck() { }
+ };
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/opendoccontrols.hxx b/dbaccess/source/ui/inc/opendoccontrols.hxx
new file mode 100644
index 000000000..8448a047d
--- /dev/null
+++ b/dbaccess/source/ui/inc/opendoccontrols.hxx
@@ -0,0 +1,78 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <vcl/weld.hxx>
+#include <rtl/ustring.hxx>
+
+namespace dbaui
+{
+
+ // OpenDocumentButton
+ /** a button which can be used to open a document
+
+ The text of the button is the same as for the "Open" command in the application
+ UI. Additionally, the icon for this command is also displayed on the button.
+ */
+ class OpenDocumentButton
+ {
+ private:
+ OUString m_sModule;
+
+ std::unique_ptr<weld::Button> m_xControl;
+ public:
+ OpenDocumentButton(std::unique_ptr<weld::Button> xControl, const char* _pAsciiModuleName);
+
+ void set_sensitive(bool bSensitive) { m_xControl->set_sensitive(bSensitive); }
+ void connect_clicked(const Link<weld::Button&, void>& rLink) { m_xControl->connect_clicked(rLink); }
+
+ private:
+ void impl_init( const char* _pAsciiModuleName );
+ };
+
+ // OpenDocumentListBox
+ class OpenDocumentListBox
+ {
+ private:
+ typedef std::pair< OUString, OUString > StringPair;
+
+ std::vector<StringPair> m_aURLs;
+
+ std::unique_ptr<weld::ComboBox> m_xControl;
+
+ public:
+ OpenDocumentListBox(std::unique_ptr<weld::ComboBox> xControl, const char* _pAsciiModuleName);
+
+ OUString GetSelectedDocumentURL() const;
+
+ void set_sensitive(bool bSensitive) { m_xControl->set_sensitive(bSensitive); }
+ int get_count() const { return m_xControl->get_count(); }
+ void set_active(int nPos) { m_xControl->set_active(nPos); }
+ void connect_changed(const Link<weld::ComboBox&, void>& rLink) { m_xControl->connect_changed(rLink); }
+
+ private:
+ const StringPair & impl_getDocumentAtIndex( sal_uInt16 _nListIndex ) const;
+
+ void impl_init( const char* _pAsciiModuleName );
+ };
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/paramdialog.hxx b/dbaccess/source/ui/inc/paramdialog.hxx
new file mode 100644
index 000000000..489a621e6
--- /dev/null
+++ b/dbaccess/source/ui/inc/paramdialog.hxx
@@ -0,0 +1,103 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <vcl/weld.hxx>
+#include <vcl/timer.hxx>
+
+#include <com/sun/star/util/XNumberFormatter.hpp>
+#include <com/sun/star/container/XIndexAccess.hpp>
+#include <com/sun/star/sdbc/XConnection.hpp>
+#include <com/sun/star/beans/PropertyValue.hpp>
+#include <connectivity/predicateinput.hxx>
+#include <svx/ParseContext.hxx>
+#include <o3tl/typed_flags_set.hxx>
+
+namespace connectivity
+{
+ class OSQLParseNode;
+}
+
+enum class VisitFlags {
+ NONE = 0x00,
+ Visited = 0x01,
+ Dirty = 0x02,
+};
+namespace o3tl {
+ template<> struct typed_flags<VisitFlags> : is_typed_flags<VisitFlags, 0x03> {};
+}
+
+namespace dbaui
+{
+ // OParameterDialog
+ class OParameterDialog final
+ : public weld::GenericDialogController
+ , public ::svxform::OParseContextClient
+ {
+ sal_Int32 m_nCurrentlySelected;
+
+ css::uno::Reference< css::container::XIndexAccess >
+ m_xParams;
+ css::uno::Reference< css::sdbc::XConnection >
+ m_xConnection;
+ css::uno::Reference< css::util::XNumberFormatter >
+ m_xFormatter;
+ ::dbtools::OPredicateInputController
+ m_aPredicateInput;
+
+ std::vector<VisitFlags> m_aVisitedParams;
+ Timer m_aResetVisitFlag;
+ // we reset the "visited flag" 1 second after and entry has been selected
+
+ css::uno::Sequence< css::beans::PropertyValue >
+ m_aFinalValues; /// the final values as entered by the user
+
+ // the controls
+ std::unique_ptr<weld::TreeView> m_xAllParams;
+ std::unique_ptr<weld::Entry> m_xParam;
+ std::unique_ptr<weld::Button> m_xTravelNext;
+ std::unique_ptr<weld::Button> m_xOKBtn;
+ std::unique_ptr<weld::Button> m_xCancelBtn;
+
+ public:
+ OParameterDialog(weld::Window* _pParent,
+ const css::uno::Reference< css::container::XIndexAccess > & _rParamContainer,
+ const css::uno::Reference< css::sdbc::XConnection > & _rxConnection,
+ const css::uno::Reference< css::uno::XComponentContext >& rxContext);
+ virtual ~OParameterDialog() override;
+
+ const css::uno::Sequence< css::beans::PropertyValue >&
+ getValues() const { return m_aFinalValues; }
+
+ private:
+ void Construct();
+
+ DECL_LINK(OnVisitedTimeout, Timer*, void);
+ DECL_LINK(OnValueModified, weld::Entry&, void);
+ DECL_LINK(OnEntryListBoxSelected, weld::TreeView&, void);
+ DECL_LINK(OnButtonClicked, weld::Button&, void);
+ DECL_LINK(OnValueLoseFocusHdl, weld::Widget&, void);
+ bool CheckValueForError();
+ bool OnEntrySelected();
+ };
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/propertystorage.hxx b/dbaccess/source/ui/inc/propertystorage.hxx
new file mode 100644
index 000000000..35d9f24d6
--- /dev/null
+++ b/dbaccess/source/ui/inc/propertystorage.hxx
@@ -0,0 +1,54 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <com/sun/star/uno/Any.hxx>
+#include <map>
+#include <memory>
+
+class SfxItemSet;
+
+namespace dbaui
+{
+
+ /** a PropertyStorage implementation which stores the value in an item set
+ */
+ class SetItemPropertyStorage
+ {
+ public:
+ SetItemPropertyStorage( SfxItemSet& _rItemSet, const sal_uInt16 _nItemID )
+ :m_rItemSet( _rItemSet )
+ ,m_nItemID( _nItemID )
+ {
+ }
+
+ void getPropertyValue( css::uno::Any& _out_rValue ) const;
+ void setPropertyValue( const css::uno::Any& _rValue );
+
+ private:
+ SfxItemSet& m_rItemSet;
+ const sal_uInt16 m_nItemID;
+ };
+
+ typedef std::map< sal_Int32, std::shared_ptr< SetItemPropertyStorage > > PropertyValues;
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/querycontainerwindow.hxx b/dbaccess/source/ui/inc/querycontainerwindow.hxx
new file mode 100644
index 000000000..12583ec0c
--- /dev/null
+++ b/dbaccess/source/ui/inc/querycontainerwindow.hxx
@@ -0,0 +1,104 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <vcl/window.hxx>
+#include <vcl/split.hxx>
+#include <dbaccess/dataview.hxx>
+#include <com/sun/star/frame/XFrame2.hpp>
+#include "QueryViewSwitch.hxx"
+#include <vcl/dockwin.hxx>
+
+namespace dbaui
+{
+
+ // OBeamer
+ // temporary class until the beamer is implemented
+ class OBeamer : public DockingWindow
+ {
+ public:
+ OBeamer(vcl::Window* _pParent) : DockingWindow(_pParent,0){}
+ };
+
+ // OQueryContainerWindow
+ class OQueryContainerWindow : public ODataView
+ {
+ OQueryViewSwitch* m_pViewSwitch;
+ VclPtr<OBeamer> m_pBeamer;
+ VclPtr<Splitter> m_pSplitter;
+ css::uno::Reference< css::frame::XFrame2 > m_xBeamer;
+
+ DECL_LINK( SplitHdl, Splitter*, void );
+ public:
+ OQueryContainerWindow(vcl::Window* pParent, OQueryController& _rController,const css::uno::Reference< css::uno::XComponentContext >&);
+ virtual ~OQueryContainerWindow() override;
+ virtual void dispose() override;
+
+ virtual void Construct() override;
+
+ virtual bool PreNotify( NotifyEvent& rNEvt ) override;
+
+ // show the beamer
+ void showPreview(const css::uno::Reference< css::frame::XFrame >& _xFrame);
+ // called when the beamer has been disposed
+ void disposingPreview();
+
+ const css::uno::Reference< css::frame::XFrame2 >&
+ getPreviewFrame() const { return m_xBeamer; }
+
+ OQueryDesignView* getDesignView() { return m_pViewSwitch->getDesignView(); }
+
+ bool isCutAllowed() const { return m_pViewSwitch->isCutAllowed(); }
+ bool isPasteAllowed() const { return m_pViewSwitch->isPasteAllowed(); }
+ bool isCopyAllowed() const { return m_pViewSwitch->isCopyAllowed(); }
+ void copy() { m_pViewSwitch->copy(); }
+ void cut() { m_pViewSwitch->cut(); }
+ void paste() { m_pViewSwitch->paste(); }
+
+ void clear() { m_pViewSwitch->clear(); }
+ bool isSlotEnabled( sal_Int32 _nSlotId ) { return m_pViewSwitch->isSlotEnabled( _nSlotId ); }
+ void setSlotEnabled( sal_Int32 _nSlotId, bool _bEnable ) { m_pViewSwitch->setSlotEnabled( _nSlotId, _bEnable ); }
+ void setNoneVisibleRow(sal_Int32 _nRows) { m_pViewSwitch->setNoneVisibleRow( _nRows); }
+
+ bool checkStatement() { return m_pViewSwitch->checkStatement( ); }
+ OUString getStatement() { return m_pViewSwitch->getStatement( ); }
+ void setStatement( const OUString& _rsStatement ) { m_pViewSwitch->setStatement( _rsStatement ); }
+
+ void initialize() override { m_pViewSwitch->initialize(); }
+ void SaveUIConfig() { m_pViewSwitch->SaveUIConfig(); }
+ void reset() { m_pViewSwitch->reset(); }
+
+ bool switchView( ::dbtools::SQLExceptionInfo* _pErrorInfo );
+ void forceInitialView();
+
+ virtual void GetFocus() override;
+
+ protected:
+ // re-arrange the controls belonging to the document itself
+ virtual void resizeAll( const tools::Rectangle& _rPlayground ) override;
+
+ // arrange derived classes controls in the rectangle given
+ virtual void resizeDocumentView(tools::Rectangle& _rPlayground) override;
+ };
+ // end of temp classes
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/querycontroller.hxx b/dbaccess/source/ui/inc/querycontroller.hxx
new file mode 100644
index 000000000..94bb5d8f4
--- /dev/null
+++ b/dbaccess/source/ui/inc/querycontroller.hxx
@@ -0,0 +1,217 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include "JoinController.hxx"
+#include "querycontainerwindow.hxx"
+#include <svx/ParseContext.hxx>
+#include "TableFieldDescription.hxx"
+
+#include <com/sun/star/sdb/CommandType.hpp>
+#include <com/sun/star/sdb/XSQLQueryComposer.hpp>
+#include <com/sun/star/sdbcx/XAlterView.hpp>
+
+#include <comphelper/proparrhlp.hxx>
+#include <comphelper/propertycontainer.hxx>
+#include <comphelper/uno3.hxx>
+#include <connectivity/sqliterator.hxx>
+#include <connectivity/sqlparse.hxx>
+
+namespace comphelper
+{
+ class NamedValueCollection;
+}
+
+namespace dbaui
+{
+ class OQueryContainerWindow;
+
+ typedef ::comphelper::OPropertyContainer OQueryController_PBase;
+ typedef ::comphelper::OPropertyArrayUsageHelper< OQueryController > OQueryController_PABase;
+ class OQueryController :public OJoinController
+ ,public OQueryController_PBase
+ ,public OQueryController_PABase
+ {
+ OTableFields m_vTableFieldDesc;
+ OTableFields m_vUnUsedFieldsDesc; // contains fields which aren't visible and don't have any criteria
+
+ css::uno::Sequence< css::beans::PropertyValue > m_aFieldInformation;
+
+ std::unique_ptr<::svxform::OSystemParseContext> m_pParseContext;
+ ::connectivity::OSQLParser m_aSqlParser;
+ std::unique_ptr<::connectivity::OSQLParseTreeIterator> m_pSqlIterator;
+
+ css::uno::Reference< css::sdb::XSQLQueryComposer > m_xComposer;
+ /// if we're editing an existing view, this is non-NULL
+ css::uno::Reference< css::sdbcx::XAlterView > m_xAlterView;
+
+ OUString m_sStatement; // contains the current sql statement
+ OUString m_sUpdateCatalogName; // catalog for update data
+ OUString m_sUpdateSchemaName; // schema for update data
+ mutable OUString
+ m_sName; // name of the query
+
+ sal_Int64 m_nLimit; // the limit of the query result (All==-1)
+
+ sal_Int32 m_nVisibleRows; // which rows the selection browse should show
+ sal_Int32 m_nSplitPos; // the position of the splitter
+ sal_Int32 m_nCommandType; // the type of the object we're designing
+ bool m_bGraphicalDesign; // are we in the graphical design mode (sal_True) or in the text design (sal_False)?
+ bool m_bDistinct; // true when you want "select distinct" otherwise false
+ bool m_bEscapeProcessing;// is true when we shouldn't parse the statement
+
+
+ /** returns the container of queries, views, or command definitions, depending on what object type
+ we design currently.
+
+ Not allowed to be called if we design an independent SQL command.
+ */
+ css::uno::Reference< css::container::XNameAccess >
+ getObjectContainer() const;
+
+ bool editingView() const { return m_nCommandType == css::sdb::CommandType::TABLE; }
+ bool editingQuery() const { return m_nCommandType == css::sdb::CommandType::QUERY; }
+ bool editingCommand() const { return m_nCommandType == css::sdb::CommandType::COMMAND; }
+
+ bool askForNewName( const css::uno::Reference< css::container::XNameAccess>& _xElements,
+ bool _bSaveAs);
+ // creates the querycomposer
+ void setQueryComposer();
+ void deleteIterator();
+ void executeQuery();
+ bool doSaveAsDoc(bool _bSaveAs);
+
+ void saveViewSettings( ::comphelper::NamedValueCollection& o_rViewSettings, const bool i_includingCriteria ) const;
+ void loadViewSettings( const ::comphelper::NamedValueCollection& o_rViewSettings );
+ OUString translateStatement( bool _bFireStatementChange = true );
+
+ void execute_QueryPropDlg();
+
+ protected:
+ // all the features which should be handled by this class
+ virtual void describeSupportedFeatures() override;
+ // state of a feature. 'feature' may be the handle of a css::util::URL somebody requested a dispatch interface for OR a toolbar slot.
+ virtual FeatureState GetState(sal_uInt16 nId) const override;
+ // execute a feature
+ virtual void Execute(sal_uInt16 nId, const css::uno::Sequence< css::beans::PropertyValue>& aArgs) override;
+
+ virtual void reconnect( bool _bUI ) override;
+ virtual OUString getPrivateTitle( ) const override;
+
+ OQueryContainerWindow* getContainer() const { return static_cast< OQueryContainerWindow* >( getView() ); }
+
+ public:
+ OQueryController(const css::uno::Reference< css::uno::XComponentContext >& _rM);
+
+ virtual ~OQueryController() override;
+ OTableFields& getTableFieldDesc() { return m_vTableFieldDesc; }
+ OTableFields& getUnUsedFields() { return m_vUnUsedFieldsDesc; }
+
+ void clearFields();
+
+ virtual void impl_onModifyChanged() override;
+
+ // should the statement be parsed by our own sql parser
+ bool isEscapeProcessing() const { return m_bEscapeProcessing; }
+ bool isGraphicalDesign() const { return m_bGraphicalDesign; }
+ bool isDistinct() const { return m_bDistinct; }
+ sal_Int64 getLimit() const { return m_nLimit; }
+
+ const OUString& getStatement() const { return m_sStatement; }
+ sal_Int32 getSplitPos() const { return m_nSplitPos;}
+ sal_Int32 getVisibleRows() const { return m_nVisibleRows; }
+
+ void setDistinct(bool _bDistinct) { m_bDistinct = _bDistinct;}
+ void setLimit(const sal_Int64 _nLimit) { m_nLimit = _nLimit;}
+ void setSplitPos(sal_Int32 _nSplitPos) { m_nSplitPos = _nSplitPos;}
+ void setVisibleRows(sal_Int32 _nVisibleRows) { m_nVisibleRows = _nVisibleRows;}
+
+ sal_Int32 getColWidth(sal_uInt16 _nColPos) const;
+
+ const css::uno::Sequence< css::beans::PropertyValue >&
+ getFieldInformation() const { return m_aFieldInformation; }
+
+ ::connectivity::OSQLParser& getParser() { return m_aSqlParser; }
+ ::connectivity::OSQLParseTreeIterator& getParseIterator() { return *m_pSqlIterator; }
+
+ virtual bool Construct(vcl::Window* pParent) override;
+
+ DECLARE_XINTERFACE( )
+ DECLARE_XTYPEPROVIDER( )
+ // XPropertySet
+ virtual css::uno::Reference<css::beans::XPropertySetInfo> SAL_CALL getPropertySetInfo() override;
+ virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper() override;
+
+ // XEventListener
+ virtual void SAL_CALL disposing( const css::lang::EventObject& Source ) override;
+
+ // css::lang::XComponent
+ virtual void SAL_CALL disposing() override;
+
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual css::uno::Sequence< OUString> SAL_CALL getSupportedServiceNames() override;
+
+ // XController
+ virtual css::uno::Any SAL_CALL getViewData() override;
+ virtual void SAL_CALL restoreViewData(const css::uno::Any& Data) override;
+
+ private:
+ virtual void onLoadedMenu(const css::uno::Reference< css::frame::XLayoutManager >& _xLayoutManager) override;
+ // OPropertyArrayUsageHelper
+ virtual ::cppu::IPropertyArrayHelper* createArrayHelper( ) const override;
+
+ // OPropertySetHelper
+ virtual void SAL_CALL getFastPropertyValue(
+ css::uno::Any& rValue,
+ sal_Int32 nHandle
+ ) const override;
+
+ virtual OJoinDesignView* getJoinView() override;
+ // ask the user if the design should be saved when it is modified
+ virtual short saveModified() override;
+ virtual void reset() override;
+ virtual void impl_initialize() override;
+
+ void impl_reset( const bool i_bIgnoreQuerySettings = false );
+ /// tells the user that we needed to switch to SQL view automatically
+ void impl_showAutoSQLViewError( const css::uno::Any& _rErrorDetails );
+
+ /** switches to the graphical or SQL view mode, as determined by m_bGraphicalDesign
+ */
+ void impl_setViewMode( ::dbtools::SQLExceptionInfo* _pErrorInfo );
+
+ /// sets m_sStatement, and notifies our respective property change listeners
+ void setStatement_fireEvent( const OUString& _rNewStatement, bool _bFireStatementChange = true );
+ /// sets the m_bEscapeProcessing member, and notifies our respective property change listeners
+ void setEscapeProcessing_fireEvent( const bool _bEscapeProcessing );
+
+ // OJoinController overridables
+ virtual bool allowViews() const override;
+ virtual bool allowQueries() const override;
+
+ private:
+ DECL_LINK( OnExecuteAddTable, void*, void );
+
+ private:
+ using OQueryController_PBase::getFastPropertyValue;
+ };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/queryfilter.hxx b/dbaccess/source/ui/inc/queryfilter.hxx
new file mode 100644
index 000000000..396778f22
--- /dev/null
+++ b/dbaccess/source/ui/inc/queryfilter.hxx
@@ -0,0 +1,109 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <vcl/weld.hxx>
+#include <connectivity/sqliterator.hxx>
+
+#include <connectivity/predicateinput.hxx>
+#include <svx/ParseContext.hxx>
+
+namespace com::sun::star {
+ namespace sdb
+ {
+ class XSingleSelectQueryComposer;
+ }
+ namespace sdbc
+ {
+ class XConnection;
+ class XDatabaseMetaData;
+ }
+ namespace container
+ {
+ class XNameAccess;
+ }
+ namespace beans
+ {
+ struct PropertyValue;
+ }
+}
+
+// DlgFilterCrit
+namespace dbaui
+{
+ class DlgFilterCrit final : public weld::GenericDialogController
+ , public ::svxform::OParseContextClient
+ {
+ private:
+ std::vector<OUString> m_aSTR_COMPARE_OPERATORS;
+
+ css::uno::Reference< css::sdb::XSingleSelectQueryComposer> m_xQueryComposer;
+ css::uno::Reference< css::container::XNameAccess> m_xColumns;
+ css::uno::Reference< css::sdbc::XConnection> m_xConnection;
+ css::uno::Reference< css::sdbc::XDatabaseMetaData> m_xMetaData;
+
+ ::dbtools::OPredicateInputController m_aPredicateInput;
+
+ std::unique_ptr<weld::ComboBox> m_xLB_WHEREFIELD1;
+ std::unique_ptr<weld::ComboBox> m_xLB_WHERECOMP1;
+ std::unique_ptr<weld::Entry> m_xET_WHEREVALUE1;
+
+ std::unique_ptr<weld::ComboBox> m_xLB_WHERECOND2;
+ std::unique_ptr<weld::ComboBox> m_xLB_WHEREFIELD2;
+ std::unique_ptr<weld::ComboBox> m_xLB_WHERECOMP2;
+ std::unique_ptr<weld::Entry> m_xET_WHEREVALUE2;
+
+ std::unique_ptr<weld::ComboBox> m_xLB_WHERECOND3;
+ std::unique_ptr<weld::ComboBox> m_xLB_WHEREFIELD3;
+ std::unique_ptr<weld::ComboBox> m_xLB_WHERECOMP3;
+ std::unique_ptr<weld::Entry> m_xET_WHEREVALUE3;
+
+ static void SelectField(weld::ComboBox& rBox, std::u16string_view rField);
+ DECL_LINK(ListSelectHdl, weld::ComboBox&, void);
+ DECL_LINK(ListSelectCompHdl, weld::ComboBox&, void);
+
+ void SetLine( int nIdx, const css::beans::PropertyValue& _rItem, bool _bOr );
+ void EnableLines();
+ sal_Int32 GetOSQLPredicateType( std::u16string_view _rSelectedPredicate ) const;
+ static sal_Int32 GetSelectionPos(sal_Int32 eType, const weld::ComboBox& rListBox);
+ bool getCondition(const weld::ComboBox& _rField, const weld::ComboBox& _rComp, const weld::Entry& _rValue, css::beans::PropertyValue& _rFilter) const;
+ void fillLines(int &i, const css::uno::Sequence< css::uno::Sequence< css::beans::PropertyValue > >& _aValues);
+
+ css::uno::Reference< css::beans::XPropertySet > getMatchingColumn( const weld::Entry& _rValueInput ) const;
+ css::uno::Reference< css::beans::XPropertySet > getColumn( const OUString& _rFieldName ) const;
+ css::uno::Reference< css::beans::XPropertySet > getQueryColumn( const OUString& _rFieldName ) const;
+
+ public:
+ DlgFilterCrit(weld::Window * pParent,
+ const css::uno::Reference< css::uno::XComponentContext >& rxContext,
+ const css::uno::Reference< css::sdbc::XConnection>& _rxConnection,
+ const css::uno::Reference< css::sdb::XSingleSelectQueryComposer>& _rxComposer,
+ const css::uno::Reference< css::container::XNameAccess>& _rxCols);
+ virtual ~DlgFilterCrit() override;
+
+ void BuildWherePart();
+
+ private:
+ DECL_LINK(PredicateLoseFocus, weld::Widget&, void);
+ };
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/queryorder.hxx b/dbaccess/source/ui/inc/queryorder.hxx
new file mode 100644
index 000000000..523d84f31
--- /dev/null
+++ b/dbaccess/source/ui/inc/queryorder.hxx
@@ -0,0 +1,81 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <vcl/weld.hxx>
+
+#define DOG_ROWS 3
+
+namespace com::sun::star{
+ namespace sdb
+ {
+ class XSingleSelectQueryComposer;
+ }
+ namespace sdbc
+ {
+ class XConnection;
+ }
+ namespace container
+ {
+ class XNameAccess;
+ }
+}
+
+// DlgOrderCrit
+namespace dbaui
+{
+ class DlgOrderCrit final : public weld::GenericDialogController
+ {
+ OUString m_sOrgOrder;
+
+ css::uno::Reference< css::sdb::XSingleSelectQueryComposer> m_xQueryComposer;
+ css::uno::Reference< css::container::XNameAccess> m_xColumns;
+ css::uno::Reference< css::sdbc::XConnection> m_xConnection;
+
+ weld::ComboBox* m_aColumnList[DOG_ROWS];
+ weld::ComboBox* m_aValueList[DOG_ROWS];
+
+ std::unique_ptr<weld::ComboBox> m_xLB_ORDERFIELD1;
+ std::unique_ptr<weld::ComboBox> m_xLB_ORDERVALUE1;
+ std::unique_ptr<weld::ComboBox> m_xLB_ORDERFIELD2;
+ std::unique_ptr<weld::ComboBox> m_xLB_ORDERVALUE2;
+ std::unique_ptr<weld::ComboBox> m_xLB_ORDERFIELD3;
+ std::unique_ptr<weld::ComboBox> m_xLB_ORDERVALUE3;
+
+ DECL_LINK(FieldListSelectHdl, weld::ComboBox&, void);
+ void EnableLines();
+
+ public:
+ DlgOrderCrit(weld::Window * pParent,
+ const css::uno::Reference< css::sdbc::XConnection>& _rxConnection,
+ const css::uno::Reference< css::sdb::XSingleSelectQueryComposer>& _rxComposer,
+ const css::uno::Reference< css::container::XNameAccess>& _rxCols);
+ virtual ~DlgOrderCrit() override;
+
+ void BuildOrderPart();
+
+ OUString GetOrderList( ) const;
+ const OUString& GetOriginalOrder() const { return m_sOrgOrder; }
+
+ private:
+ void impl_initializeOrderList_nothrow();
+ };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/sbagrid.hrc b/dbaccess/source/ui/inc/sbagrid.hrc
new file mode 100644
index 000000000..c84dbccea
--- /dev/null
+++ b/dbaccess/source/ui/inc/sbagrid.hrc
@@ -0,0 +1,37 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef DBACCESS_SBA_GRID_HRC
+#define DBACCESS_SBA_GRID_HRC
+
+//----------------Menueitems-------------------------------------------------
+// Table
+#define SBA_WHICHID_START 100
+
+// Columns
+// Formatting
+#define SBA_DEF_RANGEFORMAT (SBA_WHICHID_START+143) // RangeItem
+#define SBA_DEF_FMTVALUE (SBA_WHICHID_START+144) // SfxULONG, Format
+
+// Justification
+#define SBA_ATTR_ALIGN_HOR_JUSTIFY (SBA_WHICHID_START + 145) // SvxHorJustifyItem
+
+#endif // DBACCESS_SBA_GRID_HRC
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/sbagrid.hxx b/dbaccess/source/ui/inc/sbagrid.hxx
new file mode 100644
index 000000000..0d22f6dce
--- /dev/null
+++ b/dbaccess/source/ui/inc/sbagrid.hxx
@@ -0,0 +1,293 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <svx/fmgridcl.hxx>
+
+#include <svx/fmgridif.hxx>
+
+#include <com/sun/star/frame/XDispatch.hpp>
+#include <com/sun/star/util/URL.hpp>
+#include <comphelper/multiinterfacecontainer3.hxx>
+#include <comphelper/servicehelper.hxx>
+#include <comphelper/uno3.hxx>
+#include "sbamultiplex.hxx"
+#include <svx/dataaccessdescriptor.hxx>
+#include <rtl/ref.hxx>
+#include <map>
+#include <queue>
+
+class SvNumberFormatter;
+
+namespace com::sun::star {
+ namespace lang {
+ class XMultiServiceFactory;
+ }
+}
+
+namespace dbaui
+{
+ struct SbaURLCompare
+ {
+ bool operator() (const css::util::URL& x, const css::util::URL& y) const { return x.Complete == y.Complete; }
+ };
+
+ class SbaXStatusMultiplexer;
+ class SbaXGridControl
+ :public FmXGridControl
+ ,public css::frame::XDispatch
+ {
+ typedef std::map<css::util::URL, rtl::Reference<SbaXStatusMultiplexer>, SbaURLCompare> StatusMultiplexerArray;
+ StatusMultiplexerArray m_aStatusMultiplexer;
+
+ public:
+ SbaXGridControl(const css::uno::Reference< css::uno::XComponentContext >&);
+ virtual ~SbaXGridControl() override;
+
+ // UNO
+ DECLARE_UNO3_DEFAULTS(SbaXGridControl, FmXGridControl)
+ virtual css::uno::Any SAL_CALL queryInterface(const css::uno::Type& _rType) override;
+
+ // XTypeProvider
+ virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes( ) override;
+ virtual css::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId( ) override;
+
+ // css::lang::XServiceInfo
+ OUString SAL_CALL getImplementationName() override;
+ virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override;
+
+ // css::frame::XDispatch
+ virtual void SAL_CALL dispatch(const css::util::URL& aURL, const css::uno::Sequence< css::beans::PropertyValue >& aArgs) override;
+ virtual void SAL_CALL addStatusListener(const css::uno::Reference< css::frame::XStatusListener > & xControl, const css::util::URL& aURL) override;
+ virtual void SAL_CALL removeStatusListener(const css::uno::Reference< css::frame::XStatusListener > & xControl, const css::util::URL& aURL) override;
+
+ // css::lang::XComponent
+ virtual void SAL_CALL dispose() override;
+
+ virtual void SAL_CALL createPeer(const css::uno::Reference< css::awt::XToolkit > & rToolkit, const css::uno::Reference< css::awt::XWindowPeer > & rParentPeer) override;
+
+ protected:
+ virtual rtl::Reference<FmXGridPeer> imp_CreatePeer(vcl::Window* pParent) override;
+ };
+
+ // SbaXGridPeer
+
+ class SbaXGridPeer final
+ :public FmXGridPeer
+ ,public css::frame::XDispatch
+ {
+ comphelper::OMultiTypeInterfaceContainerHelperVar3< css::frame::XStatusListener,
+ css::util::URL, SbaURLCompare> m_aStatusListeners;
+
+ public:
+ SbaXGridPeer(const css::uno::Reference< css::uno::XComponentContext >&);
+ virtual ~SbaXGridPeer() override;
+
+ // UNO
+ virtual void SAL_CALL acquire() noexcept override { FmXGridPeer::acquire(); }
+ virtual void SAL_CALL release() noexcept override { FmXGridPeer::release(); }
+ virtual css::uno::Any SAL_CALL queryInterface(const css::uno::Type& _rType) override;
+
+ virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes() override;
+
+ UNO3_GETIMPLEMENTATION_DECL(SbaXGridPeer)
+
+ // css::frame::XDispatch
+ virtual void SAL_CALL dispatch(const css::util::URL& aURL, const css::uno::Sequence< css::beans::PropertyValue >& aArgs) override;
+ virtual void SAL_CALL addStatusListener(const css::uno::Reference< css::frame::XStatusListener > & xControl, const css::util::URL& aURL) override;
+ virtual void SAL_CALL removeStatusListener(const css::uno::Reference< css::frame::XStatusListener > & xControl, const css::util::URL& aURL) override;
+
+ // css::frame::XDispatchProvider
+ virtual css::uno::Reference< css::frame::XDispatch > SAL_CALL queryDispatch(const css::util::URL& aURL, const OUString& aTargetFrameName, sal_Int32 nSearchFlags) override;
+
+ // css::lang::XComponent
+ virtual void SAL_CALL dispose() override;
+
+ private:
+ virtual VclPtr<FmGridControl> imp_CreateControl(vcl::Window* pParent, WinBits nStyle) override;
+ void NotifyStatusChanged(const css::util::URL& aUrl, const css::uno::Reference< css::frame::XStatusListener > & xControl);
+
+ // for any execution of XDispatch::dispatch
+ struct DispatchArgs
+ {
+ css::util::URL aURL;
+ css::uno::Sequence< css::beans::PropertyValue > aArgs;
+ };
+ std::queue< DispatchArgs > m_aDispatchArgs;
+ DECL_LINK( OnDispatchEvent, void*, void );
+
+ // for dynamic states of our 4 dispatchable URLs
+ enum DispatchType
+ {
+ dtBrowserAttribs,
+ dtRowHeight,
+ dtColumnAttribs,
+ dtColumnWidth,
+
+ dtUnknown
+ };
+ static DispatchType classifyDispatchURL( const css::util::URL& _rURL );
+
+ typedef std::map<DispatchType, bool> MapDispatchToBool;
+ MapDispatchToBool m_aDispatchStates;
+ };
+
+ // SbaGridHeader
+
+ class SbaGridHeader
+ :public FmGridHeader
+ ,public DragSourceHelper
+ {
+ public:
+ SbaGridHeader(BrowseBox* pParent);
+ virtual void dispose() override;
+ virtual ~SbaGridHeader() override;
+ protected:
+
+ // FmGridHeader overridables
+ virtual void PreExecuteColumnContextMenu(sal_uInt16 nColId, weld::Menu& rMenu,
+ weld::Menu& rInsertMenu, weld::Menu& rChangeMenu,
+ weld::Menu& rShowMenu) override;
+ virtual void PostExecuteColumnContextMenu(sal_uInt16 nColId, const weld::Menu& rMenu, const OString& rExecutionResult) override;
+
+ private:
+ // DragSourceHelper overridables
+ virtual void StartDrag( sal_Int8 _nAction, const Point& _rPosPixel ) override;
+
+ // Window overridables
+ virtual void MouseButtonDown( const MouseEvent& rMEvt ) override;
+
+ void ImplStartColumnDrag(sal_Int8 _nAction, const Point& _rMousePos);
+ };
+
+ // interfaces for communication between the vcl grid control and a controller
+ class SbaGridListener
+ {
+ public:
+ virtual void RowChanged() = 0;
+ virtual void ColumnChanged() = 0;
+ virtual void SelectionChanged() = 0;
+ virtual void CellActivated() = 0;
+ virtual void CellDeactivated() = 0;
+ virtual void BeforeDrop() = 0;
+ virtual void AfterDrop() = 0;
+
+ protected:
+ ~SbaGridListener() {}
+ };
+
+ // SbaGridControl
+ class SbaGridControl final : public FmGridControl
+ {
+ friend class SbaGridHeader;
+ friend class SbaXGridPeer;
+
+ // Attributes
+ svx::ODataAccessDescriptor m_aDataDescriptor;
+ SbaGridListener* m_pMasterListener;
+
+ ImplSVEvent * m_nAsyncDropEvent;
+
+ bool m_bActivatingForDrop;
+
+ public:
+ SbaGridControl(css::uno::Reference< css::uno::XComponentContext > const & _rM, Window* pParent, FmXGridPeer* _pPeer, WinBits nBits);
+ virtual ~SbaGridControl() override;
+ virtual void dispose() override;
+
+ virtual void Select() override;
+
+ void SetMasterListener(SbaGridListener* pListener) { m_pMasterListener = pListener; }
+
+ virtual void ActivateCell(sal_Int32 nRow, sal_uInt16 nCol, bool bSetCellFocus = true) override;
+ virtual void DeactivateCell(bool bUpdate = true) override;
+ using FmGridControl::ActivateCell;
+
+ bool IsAllSelected() const { return (GetSelectRowCount() == GetRowCount()) && (GetRowCount() > 0); }
+
+ HeaderBar* GetHeaderBar() const { return FmGridControl::GetHeaderBar(); }
+
+ /** return the description of the specified object.
+ @param eObjType
+ The type to ask for
+ @param _nPosition
+ The position of a tablecell (index position), header bar column/row cell
+ @return
+ The description of the specified object.
+ */
+ virtual OUString GetAccessibleObjectDescription( AccessibleBrowseBoxObjType eObjType,sal_Int32 _nPosition = -1) const override;
+
+ using FmGridControl::DeleteSelectedRows;
+ /** copies the currently selected rows to the clipboard
+ @precond
+ at least one row is selected
+ */
+ void CopySelectedRowsToClipboard();
+
+ private:
+ // DragSourceHelper overridables
+ virtual void StartDrag( sal_Int8 _nAction, const Point& _rPosPixel ) override;
+
+ // BrowseBox overridables
+ virtual sal_Int8 AcceptDrop( const BrowserAcceptDropEvent& rEvt ) override;
+ virtual sal_Int8 ExecuteDrop( const BrowserExecuteDropEvent& rEvt ) override;
+ virtual void MouseButtonDown( const BrowserMouseEvent& rMEvt) override;
+
+ // EditBrowseBox overridables
+ virtual VclPtr<BrowserHeader> imp_CreateHeaderBar(BrowseBox* pParent) override;
+ virtual ::svt::CellController* GetController(sal_Int32 nRow, sal_uInt16 nCol) override;
+
+ // DbGridControl overridables
+ virtual void PreExecuteRowContextMenu(weld::Menu& rMenu) override;
+ virtual void PostExecuteRowContextMenu(const OString& rExecutionResult) override;
+
+ // DbGridControl overridables
+ virtual void onRowChange() override;
+ virtual void onColumnChange() override;
+
+ // get a fields property set from a model pos
+ css::uno::Reference< css::beans::XPropertySet > getField(sal_uInt16 nModelPos);
+
+ // get my data source
+ css::uno::Reference< css::beans::XPropertySet > getDataSource() const;
+
+ // drag events
+ void DoColumnDrag(sal_uInt16 nColumnPos);
+ void DoFieldDrag(sal_uInt16 nColumnPos, sal_Int16 nRowPos);
+
+ void SetBrowserAttrs();
+ void SetColWidth(sal_uInt16 nColId);
+ void SetRowHeight();
+ void SetColAttrs(sal_uInt16 nColId);
+
+ SvNumberFormatter* GetDatasourceFormatter();
+
+ DECL_LINK(AsynchDropEvent, void*, void);
+
+ bool IsReadOnlyDB() const;
+ void implTransferSelectedRows( sal_Int16 nRowPos, bool _bTrueIfClipboardFalseIfDrag );
+
+ using FmGridControl::AcceptDrop;
+ using FmGridControl::ExecuteDrop;
+ using FmGridControl::MouseButtonDown;
+ };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/sbamultiplex.hxx b/dbaccess/source/ui/inc/sbamultiplex.hxx
new file mode 100644
index 000000000..d48e3299e
--- /dev/null
+++ b/dbaccess/source/ui/inc/sbamultiplex.hxx
@@ -0,0 +1,308 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <com/sun/star/beans/XVetoableChangeListener.hpp>
+#include <com/sun/star/form/XDatabaseParameterListener.hpp>
+#include <com/sun/star/form/XLoadListener.hpp>
+#include <com/sun/star/beans/XPropertiesChangeListener.hpp>
+#include <com/sun/star/beans/XPropertyChangeListener.hpp>
+#include <com/sun/star/form/XSubmitListener.hpp>
+#include <com/sun/star/form/XResetListener.hpp>
+#include <com/sun/star/sdb/XSQLErrorListener.hpp>
+#include <com/sun/star/sdb/XRowSetApproveListener.hpp>
+#include <com/sun/star/sdbc/XRowSetListener.hpp>
+#include <com/sun/star/frame/XStatusListener.hpp>
+#include <comphelper/uno3.hxx>
+#include <comphelper/interfacecontainer3.hxx>
+#include <comphelper/multiinterfacecontainer3.hxx>
+#include <cppuhelper/weak.hxx>
+
+namespace dbaui
+{
+ // TODO : replace this class if MM provides a WeakSubObject in cppu
+ class OSbaWeakSubObject : public ::cppu::OWeakObject
+ {
+ protected:
+ ::cppu::OWeakObject& m_rParent;
+
+ public:
+ OSbaWeakSubObject(::cppu::OWeakObject& rParent) : m_rParent(rParent) { }
+
+ virtual void SAL_CALL acquire() noexcept override { m_rParent.acquire(); }
+ virtual void SAL_CALL release() noexcept override { m_rParent.release(); }
+ };
+
+ // some listener multiplexers
+ // css::frame::XStatusListener
+ class SbaXStatusMultiplexer
+ :public OSbaWeakSubObject
+ ,public css::frame::XStatusListener
+ ,public ::comphelper::OInterfaceContainerHelper3<css::frame::XStatusListener>
+ {
+ public:
+ SbaXStatusMultiplexer(::cppu::OWeakObject& rSource, ::osl::Mutex& rMutex);
+ DECLARE_UNO3_DEFAULTS(SbaXStatusMultiplexer, OSbaWeakSubObject)
+ virtual css::uno::Any SAL_CALL queryInterface(const css::uno::Type& _rType) override;
+
+ /* css::lang::XEventListener */
+ virtual void SAL_CALL disposing(const css::lang::EventObject& Source) override;
+
+ virtual void SAL_CALL statusChanged(const css::frame::FeatureStateEvent& e) override;
+
+ private:
+ css::frame::FeatureStateEvent m_aLastKnownStatus;
+ public:
+ const css::frame::FeatureStateEvent& getLastEvent( ) const { return m_aLastKnownStatus; }
+ /* resolve ambiguity : both OWeakObject and OInterfaceContainerHelper2 have these memory operators */
+ using OSbaWeakSubObject::operator new;
+ using OSbaWeakSubObject::operator delete;
+ };
+
+ // css::form::XLoadListener
+ class SbaXLoadMultiplexer
+ :public OSbaWeakSubObject
+ ,public css::form::XLoadListener
+ ,public ::comphelper::OInterfaceContainerHelper3<css::form::XLoadListener>
+ {
+ public:
+ SbaXLoadMultiplexer(::cppu::OWeakObject& rSource, ::osl::Mutex& rMutex);
+ DECLARE_UNO3_DEFAULTS(SbaXLoadMultiplexer, OSbaWeakSubObject)
+ virtual css::uno::Any SAL_CALL queryInterface(const css::uno::Type& _rType) override;
+
+ /* css::lang::XEventListener */
+ virtual void SAL_CALL disposing(const css::lang::EventObject& Source) override;
+
+ virtual void SAL_CALL loaded(const css::lang::EventObject& e) override;
+ virtual void SAL_CALL unloaded(const css::lang::EventObject& e) override;
+ virtual void SAL_CALL unloading(const css::lang::EventObject& e) override;
+ virtual void SAL_CALL reloading(const css::lang::EventObject& e) override;
+ virtual void SAL_CALL reloaded(const css::lang::EventObject& e) override;
+ /* resolve ambiguity : both OWeakObject and OInterfaceContainerHelper2 have these memory operators */
+ using OSbaWeakSubObject::operator new;
+ using OSbaWeakSubObject::operator delete;
+ };
+
+ // css::form::XDatabaseParameterListener
+ class SbaXParameterMultiplexer
+ :public OSbaWeakSubObject
+ ,public css::form::XDatabaseParameterListener
+ ,public ::comphelper::OInterfaceContainerHelper3<css::form::XDatabaseParameterListener>
+ {
+ public:
+ SbaXParameterMultiplexer(::cppu::OWeakObject& rSource, ::osl::Mutex& rMutex);
+ DECLARE_UNO3_DEFAULTS(SbaXParameterMultiplexer, OSbaWeakSubObject)
+ virtual css::uno::Any SAL_CALL queryInterface(const css::uno::Type& _rType) override;
+
+ /* css::lang::XEventListener */
+ virtual void SAL_CALL disposing(const css::lang::EventObject& Source) override;
+ virtual sal_Bool SAL_CALL approveParameter(const css::form::DatabaseParameterEvent& e) override;
+ /* resolve ambiguity : both OWeakObject and OInterfaceContainerHelper2 have these memory operators */
+ using OSbaWeakSubObject::operator new;
+ using OSbaWeakSubObject::operator delete;
+ };
+
+ // css::form::XSubmitListener
+ class SbaXSubmitMultiplexer
+ :public OSbaWeakSubObject
+ ,public css::form::XSubmitListener
+ ,public ::comphelper::OInterfaceContainerHelper3<css::form::XSubmitListener>
+ {
+ public:
+ SbaXSubmitMultiplexer(::cppu::OWeakObject& rSource, ::osl::Mutex& rMutex);
+ DECLARE_UNO3_DEFAULTS(SbaXSubmitMultiplexer, OSbaWeakSubObject)
+ virtual css::uno::Any SAL_CALL queryInterface(const css::uno::Type& _rType) override;
+
+ /* css::lang::XEventListener */
+ virtual void SAL_CALL disposing(const css::lang::EventObject& Source) override;
+ virtual sal_Bool SAL_CALL approveSubmit(const css::lang::EventObject& e) override;
+ /* resolve ambiguity : both OWeakObject and OInterfaceContainerHelper2 have these memory operators */
+ using OSbaWeakSubObject::operator new;
+ using OSbaWeakSubObject::operator delete;
+ };
+
+ // css::form::XResetListener
+ class SbaXResetMultiplexer
+ :public OSbaWeakSubObject
+ ,public css::form::XResetListener
+ ,public ::comphelper::OInterfaceContainerHelper3<css::form::XResetListener>
+ {
+ public:
+ SbaXResetMultiplexer(::cppu::OWeakObject& rSource, ::osl::Mutex& rMutex);
+ DECLARE_UNO3_DEFAULTS(SbaXResetMultiplexer, OSbaWeakSubObject)
+ virtual css::uno::Any SAL_CALL queryInterface(const css::uno::Type& _rType) override;
+
+ /* css::lang::XEventListener */
+ virtual void SAL_CALL disposing(const css::lang::EventObject& Source) override;
+ virtual sal_Bool SAL_CALL approveReset(const css::lang::EventObject& e) override;
+ virtual void SAL_CALL resetted(const css::lang::EventObject& e) override;
+ /* resolve ambiguity : both OWeakObject and OInterfaceContainerHelper2 have these memory operators */
+ using OSbaWeakSubObject::operator new;
+ using OSbaWeakSubObject::operator delete;
+ };
+
+ // css::sdbc::XRowSetListener
+ class SbaXRowSetMultiplexer
+ :public OSbaWeakSubObject
+ ,public css::sdbc::XRowSetListener
+ ,public ::comphelper::OInterfaceContainerHelper3<css::sdbc::XRowSetListener>
+ {
+ public:
+ SbaXRowSetMultiplexer(::cppu::OWeakObject& rSource, ::osl::Mutex& rMutex);
+ DECLARE_UNO3_DEFAULTS(SbaXRowSetMultiplexer, OSbaWeakSubObject)
+ virtual css::uno::Any SAL_CALL queryInterface(const css::uno::Type& _rType) override;
+
+ /* css::lang::XEventListener */
+ virtual void SAL_CALL disposing(const css::lang::EventObject& Source) override;
+ virtual void SAL_CALL cursorMoved(const css::lang::EventObject& e) override;
+ virtual void SAL_CALL rowChanged(const css::lang::EventObject& e) override;
+ virtual void SAL_CALL rowSetChanged(const css::lang::EventObject& e) override;
+ /* resolve ambiguity : both OWeakObject and OInterfaceContainerHelper2 have these memory operators */
+ using OSbaWeakSubObject::operator new;
+ using OSbaWeakSubObject::operator delete;
+ };
+
+ // css::sdb::XRowSetApproveListener
+ class SbaXRowSetApproveMultiplexer
+ :public OSbaWeakSubObject
+ ,public css::sdb::XRowSetApproveListener
+ ,public ::comphelper::OInterfaceContainerHelper3<css::sdb::XRowSetApproveListener>
+ {
+ public:
+ SbaXRowSetApproveMultiplexer(::cppu::OWeakObject& rSource, ::osl::Mutex& rMutex);
+ DECLARE_UNO3_DEFAULTS(SbaXRowSetApproveMultiplexer, OSbaWeakSubObject)
+ virtual css::uno::Any SAL_CALL queryInterface(const css::uno::Type& _rType) override;
+
+ /* css::lang::XEventListener */
+ virtual void SAL_CALL disposing(const css::lang::EventObject& Source) override;
+ virtual sal_Bool SAL_CALL approveCursorMove(const css::lang::EventObject& e) override;
+ virtual sal_Bool SAL_CALL approveRowChange(const css::sdb::RowChangeEvent& e) override;
+ virtual sal_Bool SAL_CALL approveRowSetChange(const css::lang::EventObject& e) override;
+ /* resolve ambiguity : both OWeakObject and OInterfaceContainerHelper2 have these memory operators */
+ using OSbaWeakSubObject::operator new;
+ using OSbaWeakSubObject::operator delete;
+ };
+
+ // css::sdb::XSQLErrorListener
+ class SbaXSQLErrorMultiplexer
+ :public OSbaWeakSubObject
+ ,public css::sdb::XSQLErrorListener
+ ,public ::comphelper::OInterfaceContainerHelper3<css::sdb::XSQLErrorListener>
+ {
+ public:
+ SbaXSQLErrorMultiplexer(::cppu::OWeakObject& rSource, ::osl::Mutex& rMutex);
+ DECLARE_UNO3_DEFAULTS(SbaXSQLErrorMultiplexer, OSbaWeakSubObject)
+ virtual css::uno::Any SAL_CALL queryInterface(const css::uno::Type& _rType) override;
+
+ /* css::lang::XEventListener */
+ virtual void SAL_CALL disposing(const css::lang::EventObject& Source) override;
+ virtual void SAL_CALL errorOccured(const css::sdb::SQLErrorEvent& e) override;
+ /* resolve ambiguity : both OWeakObject and OInterfaceContainerHelper2 have these memory operators */
+ using OSbaWeakSubObject::operator new;
+ using OSbaWeakSubObject::operator delete;
+ };
+
+ // css::beans::XPropertyChangeListener
+ class SbaXPropertyChangeMultiplexer final
+ :public OSbaWeakSubObject
+ ,public css::beans::XPropertyChangeListener
+ {
+ typedef ::comphelper::OMultiTypeInterfaceContainerHelperVar3<css::beans::XPropertyChangeListener, OUString> ListenerContainerMap;
+ ListenerContainerMap m_aListeners;
+
+ public:
+ SbaXPropertyChangeMultiplexer( ::cppu::OWeakObject& rSource, ::osl::Mutex& rMutex );
+ DECLARE_UNO3_DEFAULTS(SbaXPropertyChangeMultiplexer, OSbaWeakSubObject)
+ virtual css::uno::Any SAL_CALL queryInterface(const css::uno::Type& _rType) override;
+
+ /* css::lang::XEventListener */
+ virtual void SAL_CALL disposing(const css::lang::EventObject& Source) override;
+
+ virtual void SAL_CALL propertyChange(const css::beans::PropertyChangeEvent& e) override;
+
+ void addInterface(const OUString& rName, const css::uno::Reference< css::beans::XPropertyChangeListener >& rListener);
+ void removeInterface(const OUString& rName, const css::uno::Reference< css::beans::XPropertyChangeListener >& rListener);
+
+ void disposeAndClear();
+
+ sal_Int32 getOverallLen() const;
+
+ ::comphelper::OInterfaceContainerHelper3<css::beans::XPropertyChangeListener>* getContainer(const OUString& rName)
+ { return m_aListeners.getContainer(rName); }
+
+ private:
+ void Notify(::comphelper::OInterfaceContainerHelper3<css::beans::XPropertyChangeListener>& rListeners, const css::beans::PropertyChangeEvent& e);
+ };
+
+ // css::beans::XVetoableChangeListener
+ class SbaXVetoableChangeMultiplexer final
+ :public OSbaWeakSubObject
+ ,public css::beans::XVetoableChangeListener
+ {
+ typedef ::comphelper::OMultiTypeInterfaceContainerHelperVar3<css::beans::XVetoableChangeListener, OUString > ListenerContainerMap;
+ ListenerContainerMap m_aListeners;
+
+ public:
+ SbaXVetoableChangeMultiplexer( ::cppu::OWeakObject& rSource, ::osl::Mutex& rMutex );
+ DECLARE_UNO3_DEFAULTS(SbaXVetoableChangeMultiplexer, OSbaWeakSubObject)
+ virtual css::uno::Any SAL_CALL queryInterface(const css::uno::Type& _rType) override;
+
+ /* css::lang::XEventListener */
+ virtual void SAL_CALL disposing(const css::lang::EventObject& Source) override;
+
+ virtual void SAL_CALL vetoableChange(const css::beans::PropertyChangeEvent& e) override;
+
+ void addInterface(const OUString& rName, const css::uno::Reference< css::beans::XVetoableChangeListener >& rListener);
+ void removeInterface(const OUString& rName, const css::uno::Reference< css::beans::XVetoableChangeListener >& rListener);
+
+ void disposeAndClear();
+
+ sal_Int32 getOverallLen() const;
+
+ ::comphelper::OInterfaceContainerHelper3<css::beans::XVetoableChangeListener>* getContainer(const OUString& rName)
+ { return m_aListeners.getContainer(rName); }
+
+ private:
+ void Notify(::comphelper::OInterfaceContainerHelper3<css::beans::XVetoableChangeListener>& rListeners, const css::beans::PropertyChangeEvent& e);
+ };
+
+ // css::beans::XPropertiesChangeListener
+ class SbaXPropertiesChangeMultiplexer
+ :public OSbaWeakSubObject
+ ,public css::beans::XPropertiesChangeListener
+ ,public ::comphelper::OInterfaceContainerHelper3<css::beans::XPropertiesChangeListener>
+ {
+ public:
+ SbaXPropertiesChangeMultiplexer(::cppu::OWeakObject& rSource, ::osl::Mutex& rMutex);
+ DECLARE_UNO3_DEFAULTS(SbaXPropertiesChangeMultiplexer, OSbaWeakSubObject)
+ virtual css::uno::Any SAL_CALL queryInterface(const css::uno::Type& _rType) override;
+
+ /* css::lang::XEventListener */
+ virtual void SAL_CALL disposing(const css::lang::EventObject& Source) override;
+ virtual void SAL_CALL propertiesChange(const css::uno::Sequence< css::beans::PropertyChangeEvent >& e) override;
+ /* resolve ambiguity : both OWeakObject and OInterfaceContainerHelper2 have these memory operators */
+ using OSbaWeakSubObject::operator new;
+ using OSbaWeakSubObject::operator delete;
+ };
+ // the SbaXPropertiesChangeMultiplexer doesn't care about the property names a listener logs on for, it simply
+ // forwards _all_ changes to _all_ listeners
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/singledoccontroller.hxx b/dbaccess/source/ui/inc/singledoccontroller.hxx
new file mode 100644
index 000000000..e5e11ba7a
--- /dev/null
+++ b/dbaccess/source/ui/inc/singledoccontroller.hxx
@@ -0,0 +1,78 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <memory>
+#include <dbaccess/dbsubcomponentcontroller.hxx>
+
+#include <com/sun/star/document/XUndoManagerSupplier.hpp>
+
+#include <cppuhelper/implbase.hxx>
+
+class SfxUndoAction;
+class SfxUndoManager;
+
+namespace dbaui
+{
+
+ // OSingleDocumentController
+ struct OSingleDocumentController_Data;
+ typedef ::cppu::ImplInheritanceHelper< DBSubComponentController
+ , css::document::XUndoManagerSupplier
+ > OSingleDocumentController_Base;
+ class OSingleDocumentController : public OSingleDocumentController_Base
+ {
+ protected:
+ OSingleDocumentController( const css::uno::Reference< css::uno::XComponentContext>& _rxORB );
+ virtual ~OSingleDocumentController() override;
+
+ // OComponentHelper
+ virtual void SAL_CALL disposing() override;
+
+ public:
+ /// need for undo's and redo's
+ SfxUndoManager& GetUndoManager() const;
+
+ /// complete clears the Undo/Redo stacks
+ void ClearUndoManager();
+
+ /** addUndoActionAndInvalidate adds an undo action to the undoManager,
+ additionally invalidates the UNDO and REDO slot
+ @param pAction the undo action to add
+ */
+ void addUndoActionAndInvalidate( std::unique_ptr<SfxUndoAction> pAction );
+
+ // OGenericUnoController
+ virtual FeatureState GetState( sal_uInt16 nId ) const override;
+ virtual void Execute( sal_uInt16 nId, const css::uno::Sequence< css::beans::PropertyValue>& aArgs ) override;
+
+ // XUndoManagerSupplier
+ virtual css::uno::Reference< css::document::XUndoManager > SAL_CALL getUndoManager( ) override;
+
+ // XEventListener
+ using OSingleDocumentController_Base::disposing;
+
+ private:
+ std::unique_ptr< OSingleDocumentController_Data > m_pData;
+ };
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/sqledit.hxx b/dbaccess/source/ui/inc/sqledit.hxx
new file mode 100644
index 000000000..0f2ecc8b6
--- /dev/null
+++ b/dbaccess/source/ui/inc/sqledit.hxx
@@ -0,0 +1,99 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <sal/config.h>
+
+#include <comphelper/syntaxhighlight.hxx>
+#include <rtl/ref.hxx>
+#include <svtools/colorcfg.hxx>
+#include <svx/weldeditview.hxx>
+#include <vcl/timer.hxx>
+
+namespace com::sun::star::beans { class XMultiPropertySet; }
+
+namespace dbaui
+{
+ class SQLEditView final : public WeldEditView, public utl::ConfigurationListener
+ {
+ private:
+ class ChangesListener;
+ friend class ChangesListener;
+
+ std::unique_ptr<weld::ScrolledWindow> m_xScrolledWindow;
+ Link<LinkParamNone*,void> m_aModifyLink;
+ const svtools::ColorConfig m_aColorConfig;
+ Timer m_aUpdateDataTimer;
+ const SyntaxHighlighter m_aHighlighter;
+ svtools::ColorConfig m_ColorConfig;
+ rtl::Reference<SfxItemPool> m_pItemPool;
+
+ rtl::Reference<ChangesListener> m_listener;
+ osl::Mutex m_mutex;
+ css::uno::Reference<css::beans::XMultiPropertySet> m_notifier;
+
+ bool m_bInUpdate;
+ bool m_bDisableInternalUndo;
+
+ DECL_LINK(ModifyHdl, LinkParamNone*, void);
+ DECL_LINK(ImplUpdateDataHdl, Timer*, void);
+ DECL_LINK(ScrollHdl, weld::ScrolledWindow&, void);
+ DECL_LINK(EditStatusHdl, EditStatus&, void);
+
+ Color GetColorValue(TokenType aToken);
+
+ void ImplSetFont();
+
+ void DoBracketHilight(sal_uInt16 nKey);
+
+ static void SetItemPoolFont(SfxItemPool* pItemPool);
+
+ void UpdateData();
+
+ void SetScrollBarRange();
+ void DoScroll();
+
+ virtual void EditViewScrollStateChange() override;
+
+ public:
+ SQLEditView(std::unique_ptr<weld::ScrolledWindow> xScrolledWindow);
+ virtual void makeEditEngine() override;
+ virtual void SetDrawingArea(weld::DrawingArea* pDrawingArea) override;
+ virtual ~SQLEditView() override;
+
+ virtual bool KeyInput(const KeyEvent& rKEvt) override;
+ virtual bool Command(const CommandEvent& rCEvt) override;
+
+ void SetTextAndUpdate(const OUString& rNewText);
+
+ void SetModifyHdl(const Link<LinkParamNone*,void>& rLink)
+ {
+ m_aModifyLink = rLink;
+ }
+
+ void DisableInternalUndo();
+
+ static Color GetSyntaxHighlightColor(const svtools::ColorConfig& rColorConfig, HighlighterLanguage eLanguage, TokenType aToken);
+
+ virtual void ConfigurationChanged(utl::ConfigurationBroadcaster*, ConfigurationHints) override;
+ };
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/sqlmessage.hxx b/dbaccess/source/ui/inc/sqlmessage.hxx
new file mode 100644
index 000000000..a2541dc0f
--- /dev/null
+++ b/dbaccess/source/ui/inc/sqlmessage.hxx
@@ -0,0 +1,145 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <connectivity/dbexception.hxx>
+#include <vcl/weld.hxx>
+#include <memory>
+
+// some forwards
+namespace com::sun::star {
+ namespace sdb {
+ class SQLContext;
+ }
+ namespace sdbc {
+ class SQLException;
+ }
+}
+
+namespace dbaui
+{
+
+enum MessageType
+{
+ Info,
+ Error,
+ Warning,
+ Query,
+ AUTO
+};
+
+enum class MessBoxStyle {
+ NONE = 0x0000,
+ Ok = 0x0001,
+ OkCancel = 0x0002,
+ YesNo = 0x0004,
+ YesNoCancel = 0x0008,
+ RetryCancel = 0x0010,
+ DefaultOk = 0x0020,
+ DefaultCancel = 0x0040,
+ DefaultRetry = 0x0080,
+ DefaultYes = 0x0100,
+ DefaultNo = 0x0200,
+};
+
+}
+
+namespace o3tl {
+ template<> struct typed_flags<dbaui::MessBoxStyle> : is_typed_flags<dbaui::MessBoxStyle, 0x03ff> {};
+}
+
+
+namespace dbaui
+{
+
+// OSQLMessageBox
+struct SQLMessageBox_Impl;
+class OSQLMessageBox : public weld::DialogController
+{
+ std::unique_ptr<weld::MessageDialog> m_xDialog;
+ std::unique_ptr<weld::Button> m_xMoreButton;
+ std::unique_ptr<SQLMessageBox_Impl> m_pImpl;
+ OUString m_sHelpURL;
+
+ virtual weld::Dialog* getDialog() override { return m_xDialog.get(); }
+public:
+ /** display an SQLException with auto-recognizing a main and a detailed message
+
+ The first two messages from the exception chain are used as main and detailed message (recognizing the
+ detailed field of an <type scope="css::sdb">SQLContext</type>).
+ */
+ OSQLMessageBox(
+ weld::Window* pParent,
+ const dbtools::SQLExceptionInfo& _rException,
+ MessBoxStyle _nStyle = MessBoxStyle::Ok | MessBoxStyle::DefaultOk,
+ const OUString& _rHelpURL = OUString()
+ );
+
+ /** display a database related error message
+
+ @param rTitle the title to display
+ @param rMessage the detailed message to display
+ @param _eType determines the image to use. AUTO is disallowed in this constructor version
+ */
+ OSQLMessageBox(weld::Window* pParent,
+ const OUString& rTitle,
+ const OUString& rMessage,
+ MessBoxStyle nStyle = MessBoxStyle::Ok | MessBoxStyle::DefaultOk,
+ MessageType _eType = Info,
+ const ::dbtools::SQLExceptionInfo* _pAdditionalErrorInfo = nullptr );
+
+ void set_title(const OUString& rTitle) { m_xDialog->set_title(rTitle); }
+ void add_button(const OUString& rText, int nResponse, const OString& rHelpId = OString()) { m_xDialog->add_button(rText, nResponse, rHelpId); }
+ void set_default_response(int nResponse) { m_xDialog->set_default_response(nResponse); }
+
+ virtual ~OSQLMessageBox() override;
+
+private:
+ void Construct(weld::Window* pParent, MessBoxStyle nStyle, MessageType eImage);
+
+ DECL_LINK(ButtonClickHdl, weld::Button&, void);
+
+private:
+ void impl_fillMessages();
+ void impl_createStandardButtons( MessBoxStyle _nStyle );
+ void impl_addDetailsButton();
+};
+
+// OSQLWarningBox
+class OSQLWarningBox : public OSQLMessageBox
+{
+public:
+ OSQLWarningBox( weld::Window* pParent,
+ const OUString& _rMessage,
+ MessBoxStyle _nStyle = MessBoxStyle::Ok | MessBoxStyle::DefaultOk,
+ const ::dbtools::SQLExceptionInfo* _pAdditionalErrorInfo = nullptr );
+};
+
+// OSQLErrorBox
+class OSQLErrorBox : public OSQLMessageBox
+{
+public:
+ OSQLErrorBox( weld::Window* pParent,
+ const OUString& _rMessage );
+};
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/stringlistitem.hxx b/dbaccess/source/ui/inc/stringlistitem.hxx
new file mode 100644
index 000000000..3d16f6770
--- /dev/null
+++ b/dbaccess/source/ui/inc/stringlistitem.hxx
@@ -0,0 +1,48 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <svl/poolitem.hxx>
+
+#include <com/sun/star/uno/Sequence.hxx>
+#include <rtl/ustring.hxx>
+
+namespace dbaui
+{
+// OStringListItem
+/** <type>SfxPoolItem</type> which transports a sequence of <type scope="rtl">OUString</type>'s
+*/
+class OStringListItem : public SfxPoolItem
+{
+ css::uno::Sequence<OUString> m_aList;
+
+public:
+ OStringListItem(sal_Int16 nWhich, const css::uno::Sequence<OUString>& _rList);
+ OStringListItem(const OStringListItem& _rSource);
+
+ virtual bool operator==(const SfxPoolItem& _rItem) const override;
+ virtual OStringListItem* Clone(SfxItemPool* _pPool = nullptr) const override;
+
+ const css::uno::Sequence<OUString>& getList() const { return m_aList; }
+};
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/tabletree.hxx b/dbaccess/source/ui/inc/tabletree.hxx
new file mode 100644
index 000000000..ebfbf7d29
--- /dev/null
+++ b/dbaccess/source/ui/inc/tabletree.hxx
@@ -0,0 +1,155 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include "imageprovider.hxx"
+#include "dbtreelistbox.hxx"
+
+#include <com/sun/star/sdbc/XDatabaseMetaData.hpp>
+#include <com/sun/star/sdbc/XConnection.hpp>
+#include <com/sun/star/sdb/application/NamedDatabaseObject.hpp>
+#include <memory>
+
+namespace dbaui
+{
+
+// OTableTreeListBox
+class OTableTreeListBox : public TreeListBox
+{
+ css::uno::Reference< css::sdbc::XConnection >
+ m_xConnection; // the connection we're working for, set in implOnNewConnection, called by UpdateTableList
+ std::unique_ptr< ImageProvider >
+ m_xImageProvider; // provider for our images
+ bool m_bVirtualRoot; // should the first entry be visible
+ bool m_bNoEmptyFolders; // should empty catalogs/schematas be prevented from being displayed?
+ bool m_bShowToggles; // show toggle buttons
+
+public:
+ OTableTreeListBox(std::unique_ptr<weld::TreeView> xTreeView, bool bShowToggles);
+
+ void init() { m_bVirtualRoot = true; }
+
+ typedef std::pair< OUString, bool > TTableViewName;
+ typedef std::vector< TTableViewName > TNames;
+
+ void SuppressEmptyFolders() { m_bNoEmptyFolders = true; }
+
+ /** determines whether the given entry denotes a tables folder
+ */
+ bool isFolderEntry(const weld::TreeIter& rEntry) const;
+
+ /** fill the table list with the tables belonging to the connection described by the parameters
+ @param _rxConnection
+ the connection, which must support the service com.sun.star.sdb.Connection
+ @throws
+ <type scope="css::sdbc">SQLException</type> if no connection could be created
+ */
+ void UpdateTableList(
+ const css::uno::Reference< css::sdbc::XConnection >& _rxConnection
+ );
+
+ /** fill the table list with the tables and views determined by the two given containers.
+ The views sequence is used to determine which table is of type view.
+ @param _rxConnection the connection where you got the object names from. Must not be NULL.
+ Used to split the full qualified names into its parts.
+ @param _rTables table/view sequence
+ @param _rViews view sequence
+ */
+ void UpdateTableList(
+ const css::uno::Reference< css::sdbc::XConnection >& _rxConnection,
+ const css::uno::Sequence< OUString>& _rTables,
+ const css::uno::Sequence< OUString>& _rViews
+ );
+
+ /** to be used if a foreign instance added a table
+ */
+ std::unique_ptr<weld::TreeIter> addedTable( const OUString& _rName );
+
+ /** to be used if a foreign instance removed a table
+ */
+ void removedTable( const OUString& _rName );
+
+ std::unique_ptr<weld::TreeIter> getAllObjectsEntry() const;
+
+ /** does a wildcard check of the given entry
+ <p>There are two different 'checked' states: If the user checks all children of an entry, this is different
+ from checking the entry itself. The second is called 'wildcard' checking, 'cause in the resulting
+ table filter it's represented by a wildcard.</p>
+ */
+ void checkWildcard(const weld::TreeIter& rEntry);
+
+ /** determine if the given entry is 'wildcard checked'
+ @see checkWildcard
+ */
+ bool isWildcardChecked(const weld::TreeIter& rEntry);
+
+ void CheckButtons(); // make the button states consistent (bottom-up)
+
+ void checkedButton_noBroadcast(const weld::TreeIter& rEntry);
+private:
+ TriState implDetermineState(const weld::TreeIter& rEntry);
+
+ void implEmphasize(const weld::TreeIter& rEntry, bool _bChecked, bool _bUpdateDescendants = true, bool _bUpdateAncestors = true);
+
+ /** adds the given entry to our list
+ @precond
+ our image provider must already have been reset to the connection to which the meta data
+ belong.
+ */
+ std::unique_ptr<weld::TreeIter> implAddEntry(
+ const css::uno::Reference< css::sdbc::XDatabaseMetaData >& _rxMeta,
+ const OUString& _rTableName,
+ bool _bCheckName = true
+ );
+
+ void implOnNewConnection( const css::uno::Reference< css::sdbc::XConnection >& _rxConnection );
+
+ bool impl_getAndAssertMetaData( css::uno::Reference< css::sdbc::XDatabaseMetaData >& _out_rMetaData ) const;
+
+ bool haveVirtualRoot() const { return m_bVirtualRoot; }
+
+public:
+ /** fill the table list with the tables and views determined by the two given containers
+ @param _rxConnection the connection where you got the object names from. Must not be NULL.
+ Used to split the full qualified names into its parts.
+ @param _rTables table/view sequence, the second argument is <TRUE/> if it is a table, otherwise it is a view.
+ */
+ void UpdateTableList(
+ const css::uno::Reference< css::sdbc::XConnection >& _rxConnection,
+ const TNames& _rTables
+ );
+
+ /** returns a NamedDatabaseObject record which describes the given entry
+ */
+ css::sdb::application::NamedDatabaseObject
+ describeObject(const weld::TreeIter& rEntry);
+
+ /** returns the fully qualified name of a table entry
+ @param _pEntry
+ the entry whose name is to be obtained. Must not denote a folder entry.
+ */
+ OUString getQualifiedTableName(const weld::TreeIter& rEntry) const;
+
+ std::unique_ptr<weld::TreeIter> getEntryByQualifiedName(const OUString& rName);
+};
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/textconnectionsettings.hxx b/dbaccess/source/ui/inc/textconnectionsettings.hxx
new file mode 100644
index 000000000..9d21c8795
--- /dev/null
+++ b/dbaccess/source/ui/inc/textconnectionsettings.hxx
@@ -0,0 +1,59 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include "propertystorage.hxx"
+#include <vcl/weld.hxx>
+#include <memory>
+
+class SfxItemSet;
+namespace dbaui
+{
+
+ class OTextConnectionHelper;
+
+ // TextConnectionSettingsDialog
+ class TextConnectionSettingsDialog : public weld::GenericDialogController
+ {
+ public:
+ TextConnectionSettingsDialog(weld::Window* _pParent, SfxItemSet& rItems);
+ virtual ~TextConnectionSettingsDialog() override;
+
+ /** initializes a set of PropertyStorage instances, which are bound to
+ the text-connection relevant items in our item sets
+ */
+ static void bindItemStorages( SfxItemSet& _rSet, PropertyValues& _rValues );
+
+ virtual short run() override;
+
+ private:
+ SfxItemSet& m_rItems;
+
+ std::unique_ptr<weld::Widget> m_xContainer;
+ std::unique_ptr<weld::Button> m_xOK;
+ std::unique_ptr<OTextConnectionHelper> m_xTextConnectionHelper;
+
+ private:
+ DECL_LINK(OnOK, weld::Button&, void);
+ };
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/undosqledit.hxx b/dbaccess/source/ui/inc/undosqledit.hxx
new file mode 100644
index 000000000..2b760bbad
--- /dev/null
+++ b/dbaccess/source/ui/inc/undosqledit.hxx
@@ -0,0 +1,45 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "GeneralUndo.hxx"
+#include <strings.hrc>
+
+namespace dbaui
+{
+ class OQueryTextView;
+
+ // OSqlEditUndoAct - Undo-class for changing sql text
+ class OSqlEditUndoAct final : public OCommentUndoAction
+ {
+ OQueryTextView& m_rOwner;
+ OUString m_strNextText;
+
+ virtual void Undo() override { ToggleText(); }
+ virtual void Redo() override { ToggleText(); }
+
+ void ToggleText();
+ public:
+ OSqlEditUndoAct(OQueryTextView& rEdit) : OCommentUndoAction(STR_QUERY_UNDO_MODIFYSQLEDIT), m_rOwner(rEdit) { }
+
+ void SetOriginalText(const OUString& strText) { m_strNextText = strText; }
+ };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/unoadmin.hxx b/dbaccess/source/ui/inc/unoadmin.hxx
new file mode 100644
index 000000000..944dccf87
--- /dev/null
+++ b/dbaccess/source/ui/inc/unoadmin.hxx
@@ -0,0 +1,59 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <svtools/genericunodialog.hxx>
+#include <com/sun/star/sdbc/XConnection.hpp>
+#include <dsntypes.hxx>
+
+class SfxItemSet;
+class SfxItemPool;
+class SfxPoolItem;
+
+namespace dbaui
+{
+
+// ODatabaseAdministrationDialog
+typedef ::svt::OGenericUnoDialog ODatabaseAdministrationDialogBase;
+class ODatabaseAdministrationDialog
+ :public ODatabaseAdministrationDialogBase
+{
+protected:
+ std::unique_ptr<SfxItemSet> m_pDatasourceItems; // item set for the dialog
+ rtl::Reference<SfxItemPool> m_pItemPool; // item pool for the item set for the dialog
+ std::vector<SfxPoolItem*>*
+ m_pItemPoolDefaults; // pool defaults
+ std::unique_ptr<::dbaccess::ODsnTypeCollection>
+ m_pCollection; // datasource type collection
+
+ css::uno::Any m_aInitialSelection;
+ css::uno::Reference< css::sdbc::XConnection > m_xActiveConnection;
+
+protected:
+ ODatabaseAdministrationDialog(const css::uno::Reference< css::uno::XComponentContext >& _rxORB);
+ virtual ~ODatabaseAdministrationDialog() override;
+protected:
+// OGenericUnoDialog overridables
+ virtual void implInitialize(const css::uno::Any& _rValue) override;
+};
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/unodatbr.hxx b/dbaccess/source/ui/inc/unodatbr.hxx
new file mode 100644
index 000000000..4bb5c26c7
--- /dev/null
+++ b/dbaccess/source/ui/inc/unodatbr.hxx
@@ -0,0 +1,447 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <memory>
+#include "brwctrlr.hxx"
+#include <com/sun/star/frame/XStatusListener.hpp>
+#include <com/sun/star/frame/XDispatch.hpp>
+#include <com/sun/star/i18n/XCollator.hpp>
+#include <com/sun/star/view/XSelectionSupplier.hpp>
+#include <com/sun/star/awt/XWindow.hpp>
+#include <com/sun/star/document/XScriptInvocationContext.hpp>
+#include <com/sun/star/ui/XContextMenuInterception.hpp>
+#include <com/sun/star/sdb/application/DatabaseObject.hpp>
+#include <com/sun/star/sdb/application/DatabaseObjectContainer.hpp>
+#include <com/sun/star/sdb/XDatabaseRegistrationsListener.hpp>
+#include <comphelper/interfacecontainer2.hxx>
+#include <cppuhelper/implbase5.hxx>
+#include "callbacks.hxx"
+#include <vcl/transfer.hxx>
+#include <svx/dataaccessdescriptor.hxx>
+#include "TableCopyHelper.hxx"
+#include "commontypes.hxx"
+
+class Splitter;
+class ODataClipboard;
+
+namespace com::sun::star::container { class XNameContainer; }
+
+namespace dbaui
+{
+ struct DBTreeEditedEntry;
+ struct DBTreeListUserData;
+ class ImageProvider;
+
+ typedef ::cppu::ImplHelper5 < css::frame::XStatusListener
+ , css::view::XSelectionSupplier
+ , css::document::XScriptInvocationContext
+ , css::ui::XContextMenuInterception
+ , css::sdb::XDatabaseRegistrationsListener
+ > SbaTableQueryBrowser_Base;
+ class SbaTableQueryBrowser final
+ :public SbaXDataBrowserController
+ ,public SbaTableQueryBrowser_Base
+ ,public IControlActionListener
+ ,public IContextMenuProvider
+ {
+ css::uno::Reference< css::i18n::XCollator > m_xCollator;
+ css::uno::Reference< css::frame::XFrame > m_xCurrentFrameParent;
+ css::uno::Reference< css::awt::XWindow > m_xMainToolbar;
+
+ struct ExternalFeature
+ {
+ css::util::URL aURL;
+ css::uno::Reference< css::frame::XDispatch >
+ xDispatcher;
+ bool bEnabled;
+
+ ExternalFeature() : bEnabled( false ) { }
+ ExternalFeature( const css::util::URL& _rURL ) : aURL( _rURL ), bEnabled( false ) { }
+ };
+
+ typedef std::map< sal_uInt16, ExternalFeature > ExternalFeaturesMap;
+ ExternalFeaturesMap m_aExternalFeatures;
+
+ svx::ODataAccessDescriptor m_aDocumentDataSource;
+ // if we're part of a document, this is the state of the DocumentDataSource slot
+
+ ::comphelper::OInterfaceContainerHelper2 m_aSelectionListeners;
+ ::comphelper::OInterfaceContainerHelper2 m_aContextMenuInterceptors;
+
+ OTableCopyHelper::DropDescriptor m_aAsyncDrop;
+ OTableCopyHelper m_aTableCopyHelper;
+
+ OUString m_sQueryCommand; // the command of the query currently loaded (if any)
+ //OUString m_sToBeLoaded; // contains the element name which should be loaded if any
+
+ VclPtr<InterimDBTreeListBox> m_pTreeView; // contains the datasources of the registry
+ VclPtr<Splitter> m_pSplitter;
+ std::unique_ptr<weld::TreeIter> m_xCurrentlyDisplayed;
+ ImplSVEvent * m_nAsyncDrop;
+
+ bool m_bQueryEscapeProcessing : 1; // the escape processing flag of the query currently loaded (if any)
+ bool m_bShowMenu; // if sal_True the menu should be visible otherwise not
+ bool m_bInSuspend;
+ bool m_bEnableBrowser;
+ ::std::optional< bool >
+ m_aDocScriptSupport; // relevant if and only if we are associated with exactly one DBDoc
+
+ virtual OUString getPrivateTitle( ) const override;
+ // attribute access
+ public:
+ SbaTableQueryBrowser(const css::uno::Reference< css::uno::XComponentContext >& _rM);
+ virtual ~SbaTableQueryBrowser() override;
+
+ enum EntryType
+ {
+ // don't change the above definitions! There are places (in particular SbaTableQueryBrowser::getCurrentSelection)
+ // which rely on the fact that the EntryType values really equal the DatabaseObject(Container) values!
+ etDatasource = css::sdb::application::DatabaseObjectContainer::DATA_SOURCE,
+ etQueryContainer = css::sdb::application::DatabaseObjectContainer::QUERIES,
+ etTableContainer = css::sdb::application::DatabaseObjectContainer::TABLES,
+ etQuery = css::sdb::application::DatabaseObject::QUERY,
+ etTableOrView = css::sdb::application::DatabaseObject::TABLE,
+ etUnknown = -1
+ };
+
+ /** returns a DatabaseObject value corresponding to the given EntryType
+ @param _eType
+ the entry type. Must not be etUnknown.
+ */
+ static sal_Int32 getDatabaseObjectType( EntryType _eType );
+
+ DECLARE_UNO3_DEFAULTS(SbaTableQueryBrowser,SbaXDataBrowserController)
+ // late construction
+ virtual bool Construct(vcl::Window* pParent) override;
+ // XInterface
+ virtual css::uno::Any SAL_CALL queryInterface(const css::uno::Type& _rType) override;
+
+ // XTypeProvider
+ virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes( ) override;
+ virtual css::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId( ) override;
+
+ // css::beans::XPropertyChangeListener
+ virtual void SAL_CALL propertyChange(const css::beans::PropertyChangeEvent& evt) override;
+
+ // css::frame::XController
+ virtual sal_Bool SAL_CALL suspend(sal_Bool bSuspend) override;
+ virtual void SAL_CALL attachFrame(const css::uno::Reference< css::frame::XFrame > & xFrame) override;
+
+ // css::lang::XComponent
+ virtual void SAL_CALL disposing() override;
+
+ // XStatusListener
+ virtual void SAL_CALL statusChanged( const css::frame::FeatureStateEvent& Event ) override;
+
+ // XEventListener
+ virtual void SAL_CALL disposing( const css::lang::EventObject& Source ) override;
+
+ // XSelectionSupplier
+ virtual sal_Bool SAL_CALL select( const css::uno::Any& aSelection ) override;
+ virtual css::uno::Any SAL_CALL getSelection( ) override;
+ virtual void SAL_CALL addSelectionChangeListener( const css::uno::Reference< css::view::XSelectionChangeListener >& xListener ) override;
+ virtual void SAL_CALL removeSelectionChangeListener( const css::uno::Reference< css::view::XSelectionChangeListener >& xListener ) override;
+
+ // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override;
+
+ // XContainerListener
+ virtual void SAL_CALL elementInserted( const css::container::ContainerEvent& Event ) override;
+ virtual void SAL_CALL elementRemoved( const css::container::ContainerEvent& Event ) override;
+ virtual void SAL_CALL elementReplaced( const css::container::ContainerEvent& Event ) override;
+ // css::frame::XFrameActionListener
+ virtual void SAL_CALL frameAction(const css::frame::FrameActionEvent& aEvent) override;
+
+ // XScriptInvocationContext
+ virtual css::uno::Reference< css::document::XEmbeddedScripts > SAL_CALL getScriptContainer() override;
+
+ // XContextMenuInterception
+ virtual void SAL_CALL registerContextMenuInterceptor( const css::uno::Reference< css::ui::XContextMenuInterceptor >& Interceptor ) override;
+ virtual void SAL_CALL releaseContextMenuInterceptor( const css::uno::Reference< css::ui::XContextMenuInterceptor >& Interceptor ) override;
+
+ // XDatabaseRegistrationsListener
+ virtual void SAL_CALL registeredDatabaseLocation( const css::sdb::DatabaseRegistrationEvent& Event ) override;
+ virtual void SAL_CALL revokedDatabaseLocation( const css::sdb::DatabaseRegistrationEvent& Event ) override;
+ virtual void SAL_CALL changedDatabaseLocation( const css::sdb::DatabaseRegistrationEvent& Event ) override;
+
+ private:
+ // SbaXDataBrowserController overridable
+ virtual bool InitializeForm( const css::uno::Reference< css::beans::XPropertySet >& i_formProperties ) override;
+
+ void InitializeGridModel(const css::uno::Reference< css::form::XFormComponent > & xGrid);
+
+ virtual bool preReloadForm() override;
+ virtual void postReloadForm() override;
+
+ virtual void addModelListeners(const css::uno::Reference< css::awt::XControlModel > & _xGridControlModel) override;
+ virtual void removeModelListeners(const css::uno::Reference< css::awt::XControlModel > & _xGridControlModel) override;
+
+ virtual void AddColumnListener(const css::uno::Reference< css::beans::XPropertySet > & xCol) override;
+ virtual void RemoveColumnListener(const css::uno::Reference< css::beans::XPropertySet > & xCol) override;
+
+ virtual void LoadFinished(bool _bWasSynch) override;
+
+ virtual void criticalFail() override;
+
+ virtual void describeSupportedFeatures() override;
+ virtual FeatureState GetState(sal_uInt16 nId) const override;
+ virtual void Execute(sal_uInt16 nId, const css::uno::Sequence< css::beans::PropertyValue>& aArgs) override;
+
+ // IControlActionListener overridables
+ virtual bool requestQuickHelp(const void* pUserData, OUString& rText) const override;
+ virtual bool requestDrag(const weld::TreeIter& rEntry) override;
+ virtual sal_Int8 queryDrop( const AcceptDropEvent& _rEvt, const DataFlavorExVector& _rFlavors ) override;
+ virtual sal_Int8 executeDrop( const ExecuteDropEvent& _rEvt ) override;
+
+ // IContextMenuProvider
+ virtual OUString getContextMenuResourceName() const override;
+ virtual IController& getCommandController() override;
+ virtual ::comphelper::OInterfaceContainerHelper2*
+ getContextMenuInterceptors() override;
+ virtual css::uno::Any getCurrentSelection(weld::TreeView& rControl) const override;
+ virtual vcl::Window* getMenuParent() const override;
+ virtual void adjustMenuPosition(const weld::TreeView& rControl, ::Point& rPos) const override;
+
+ virtual void impl_initialize() override;
+
+ // SbaGridListener overridables
+ virtual void RowChanged() override;
+ virtual void ColumnChanged() override;
+ virtual void SelectionChanged() override;
+
+ // methods for showing/hiding the explorer part
+ bool haveExplorer() const;
+ void hideExplorer();
+ void showExplorer();
+ void toggleExplorer() { if (haveExplorer()) hideExplorer(); else showExplorer(); }
+
+ // methods for handling the 'selection' (painting them bold) of SvLBoxEntries
+ // returns <TRUE/> if the entry is selected (which means it's part of the selected path)
+ bool isSelected(const weld::TreeIter& rEntry) const;
+ // select the entry (and only the entry, not the whole path)
+ void select(const weld::TreeIter* pEntry, bool bSelect);
+ // select the path of the entry (which must be an entry without children)
+ void selectPath(const weld::TreeIter* pEntry, bool bSelect = true);
+
+ virtual void loadMenu(const css::uno::Reference< css::frame::XFrame >& _xFrame) override;
+
+ // check the state of the external slot given, update any UI elements if necessary
+ void implCheckExternalSlot( sal_uInt16 _nId );
+
+ // connect to the external dispatchers (if any)
+ void connectExternalDispatches();
+
+ /** get the state of an external slot
+ <p>The slot is available if an external dispatcher is responsible for it, _and_ if this dispatcher
+ told us the slot is available.</p>
+ */
+ bool getExternalSlotState( sal_uInt16 _nId ) const;
+
+ /** add an entry (including the subentries for queries/tables) to the list model
+
+ <p>The given names and images may be empty, in this case they're filled with the correct
+ values. This way they may be reused for the next call, which saves some resource manager calls.</p>
+ */
+ void implAddDatasource(const OUString& _rDbName, OUString& _rDbImage,
+ OUString& _rQueryName, OUString& _rQueryImage,
+ OUString& _rTableName, OUString& _rTableImage,
+ const SharedConnection& _rxConnection
+ );
+
+ void implAddDatasource( const OUString& _rDataSourceName, const SharedConnection& _rxConnection );
+
+ /// removes (and cleans up) the entry for the given data source
+ void impl_cleanupDataSourceEntry( std::u16string_view _rDataSourceName );
+
+ /// clears the tree list box
+ void clearTreeModel();
+
+ /** unloads the form, empties the grid model, cleans up anything related to the currently displayed object
+ @param _bDisposeConnection
+ <TRUE/> if the connection should be disposed
+ @param _bFlushData
+ <TRUE/> if the currently displayed object (if any) should be flushed
+ */
+ void unloadAndCleanup( bool _bDisposeConnection = true );
+
+ // disposes the connection associated with the given entry (which must represent a data source)
+ void disposeConnection(const weld::TreeIter* xpDSEntry);
+
+ /// flushes and disposes the given connection, and de-registers as listener
+ void impl_releaseConnection( SharedConnection& _rxConnection );
+
+ /** close the connection (and collapse the list entries) of the given list entries
+ */
+ void closeConnection(const weld::TreeIter& rEntry, bool bDisposeConnection = true);
+
+ void populateTree(const css::uno::Reference< css::container::XNameAccess>& xNameAccess, const weld::TreeIter& rParent, EntryType eEntryType);
+ void initializeTreeModel();
+
+ /** search in the tree for query- or tablecontainer equal to this interface and return
+ this container entry
+ */
+ std::unique_ptr<weld::TreeIter> getEntryFromContainer(const css::uno::Reference<css::container::XNameAccess>& rxNameAccess);
+
+ // return true when there is connection available
+ bool ensureConnection(const weld::TreeIter* pDSEntry, void * pDSData, SharedConnection& rConnection);
+ bool ensureConnection(const weld::TreeIter* pAnyEntry, SharedConnection& rConnection);
+
+ bool getExistentConnectionFor(const weld::TreeIter* pDSEntry, SharedConnection& rConnection);
+ /** returns an image provider which works with the connection belonging to the given entry
+ */
+ std::unique_ptr<ImageProvider> getImageProviderFor(const weld::TreeIter* pAnyEntry);
+
+ void implAdministrate(const weld::TreeIter& rApplyTo);
+
+ bool implCopyObject(ODataClipboard& rExchange, const weld::TreeIter& rApplyTo, sal_Int32 nCommandType);
+
+ EntryType getEntryType(const weld::TreeIter& rEntry) const;
+ EntryType getChildType(const weld::TreeIter& rEntry) const;
+ static bool isObject( EntryType _eType ) { return ( etTableOrView== _eType ) || ( etQuery == _eType ); }
+ static bool isContainer( EntryType _eType ) { return (etTableContainer == _eType) || (etQueryContainer == _eType); }
+ bool isContainer(const weld::TreeIter& rEntry) const { return isContainer(getEntryType(rEntry)); }
+
+ // ensure that the xObject for the given entry is set on the user data
+ bool ensureEntryObject(const weld::TreeIter& rEntry);
+
+ // get the display text of the entry given
+ OUString GetEntryText(const weld::TreeIter& rEntry) const;
+
+ // is called when a table or a query was selected
+ DECL_LINK( OnSelectionChange, LinkParamNone*, void );
+ DECL_LINK( OnExpandEntry, const weld::TreeIter&, bool );
+
+ DECL_LINK( OnCopyEntry, LinkParamNone*, void );
+
+ int OnTreeEntryCompare(const weld::TreeIter& rLHS, const weld::TreeIter& rRHS);
+
+ DECL_LINK( OnAsyncDrop, void*, void );
+
+ void implRemoveStatusListeners();
+
+ bool implSelect(const svx::ODataAccessDescriptor& _rDescriptor, bool _bSelectDirect = false);
+ bool implSelect(const weld::TreeIter* pEntry);
+
+ /// selects the entry given and loads the grid control with the object's data
+ bool implSelect(
+ const OUString& _rDataSourceName,
+ const OUString& _rCommand,
+ const sal_Int32 _nCommandType,
+ const bool _bEscapeProcessing,
+ const SharedConnection& _rxConnection,
+ bool _bSelectDirect
+ );
+
+ std::unique_ptr<weld::TreeIter> implGetConnectionEntry(const weld::TreeIter& rEntry) const;
+ /// inserts an entry into the tree
+ std::unique_ptr<weld::TreeIter> implAppendEntry(
+ const weld::TreeIter* pParent,
+ const OUString& rName,
+ const DBTreeListUserData* pUserData);
+
+ /// loads the grid control with the data object specified (which may be a table, a query or a command)
+ bool implLoadAnything(const OUString& _rDataSourceName, const OUString& _rCommand,
+ const sal_Int32 _nCommandType, const bool _bEscapeProcessing, const SharedConnection& _rxConnection );
+
+ /** retrieves the tree entry for the object described by <arg>_rDescriptor</arg>
+ @param rDescriptor
+ the object descriptor
+ @param ppDataSourceEntry
+ If not <NULL/>, the data source tree entry will be returned here
+ @param ppContainerEntry
+ If not <NULL/>, the object container tree entry will be returned here
+ */
+ std::unique_ptr<weld::TreeIter> getObjectEntry(const svx::ODataAccessDescriptor& rDescriptor,
+ std::unique_ptr<weld::TreeIter>* ppDataSourceEntry, std::unique_ptr<weld::TreeIter>* ppContainerEntry
+ );
+ /** retrieves the tree entry for the object described by data source name, command and command type
+ @param rDataSource
+ the data source name
+ @param rCommand
+ the command
+ @param nCommandType
+ the command type
+ @param rDescriptor
+ the object descriptor
+ @param ppDataSourceEntry
+ If not <NULL/>, the data source tree entry will be returned here
+ @param ppContainerEntry
+ If not <NULL/>, the object container tree entry will be returned here
+ @param bExpandAncestors
+ If <TRUE/>, all ancestor on the way to the entry will be expanded
+ */
+ std::unique_ptr<weld::TreeIter> getObjectEntry(
+ const OUString& rDataSource, const OUString& rCommand, sal_Int32 nCommandType,
+ std::unique_ptr<weld::TreeIter>* ppDataSourceEntry, std::unique_ptr<weld::TreeIter>* ppContainerEntry,
+ bool _bExpandAncestors = true,
+ const SharedConnection& rxConnection = SharedConnection()
+ );
+
+ /// checks if m_aDocumentDataSource describes a known object
+ void checkDocumentDataSource();
+
+ static void extractDescriptorProps(const svx::ODataAccessDescriptor& _rDescriptor,
+ OUString& _rDataSource, OUString& _rCommand, sal_Int32& _rCommandType, bool& _rEscapeProcessing);
+
+ void transferChangedControlProperty(const OUString& _rProperty, const css::uno::Any& _rNewValue);
+
+ // checks whether the given tree entry denotes a data source
+ bool impl_isDataSourceEntry(const weld::TreeIter* pEntry) const;
+
+ /// retrieves the data source URL/name for the given entry representing a data source
+ OUString getDataSourceAccessor(const weld::TreeIter& rDataSourceEntry) const;
+
+ /** get the signature (command/escape processing) of the query the form is based on
+ <p>If the for is not based on a query or not even loaded, nothing happens and <FALSE/> is returned.</p>
+ */
+ bool implGetQuerySignature( OUString& _rCommand, bool& _bEscapeProcessing );
+
+ bool isEntryCopyAllowed(const weld::TreeIter& rEntry) const;
+
+ void copyEntry(const weld::TreeIter& rEntry);
+
+ // remove all grid columns and dispose them
+ static void clearGridColumns(const css::uno::Reference< css::container::XNameContainer >& _xColContainer);
+
+ /** checks if the currently displayed entry changed
+ @param rName
+ Name of the changed entry
+ @param rContainer
+ The container of the displayed entry
+ @return
+ <TRUE/> if it is the currently displayed otherwise <FALSE/>
+ */
+ bool isCurrentlyDisplayedChanged(std::u16string_view rName, const weld::TreeIter& rContainer);
+
+ /** called whenever the content of the browser is used for preview, as the very last action
+ of the load process
+ */
+ void initializePreviewMode();
+
+ /** checks whether the Order/Filter clauses set at our row set are valid, removes them if not so
+ */
+ void impl_sanitizeRowSetClauses_nothrow();
+ };
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/unosqlmessage.hxx b/dbaccess/source/ui/inc/unosqlmessage.hxx
new file mode 100644
index 000000000..c084ef240
--- /dev/null
+++ b/dbaccess/source/ui/inc/unosqlmessage.hxx
@@ -0,0 +1,68 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <svtools/genericunodialog.hxx>
+#include <comphelper/proparrhlp.hxx>
+
+namespace dbaui
+{
+
+typedef ::svt::OGenericUnoDialog OSQLMessageDialogBase;
+class OSQLMessageDialog final
+ :public OSQLMessageDialogBase
+ ,public ::comphelper::OPropertyArrayUsageHelper< OSQLMessageDialog >
+{
+ // <properties>
+ css::uno::Any m_aException;
+ OUString m_sHelpURL;
+ // </properties>
+
+public:
+ OSQLMessageDialog(const css::uno::Reference< css::uno::XComponentContext >& _rxORB);
+
+ // XTypeProvider
+ virtual css::uno::Sequence<sal_Int8> SAL_CALL getImplementationId( ) override;
+
+ // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override;
+
+ // XPropertySet
+ virtual css::uno::Reference<css::beans::XPropertySetInfo> SAL_CALL getPropertySetInfo() override;
+ virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper() override;
+
+ // OPropertyArrayUsageHelper
+ virtual ::cppu::IPropertyArrayHelper* createArrayHelper( ) const override;
+
+private:
+ virtual void SAL_CALL initialize(css::uno::Sequence< css::uno::Any > const & args) override;
+
+// OPropertySetHelper overridables
+ // (overwriting these three, because we have some special handling for our property)
+ virtual sal_Bool SAL_CALL convertFastPropertyValue( css::uno::Any& _rConvertedValue, css::uno::Any& _rOldValue, sal_Int32 _nHandle, const css::uno::Any& _rValue) override;
+
+ // OGenericUnoDialog overridables
+ virtual std::unique_ptr<weld::DialogController> createDialog(const css::uno::Reference<css::awt::XWindow>& rParent) override;
+};
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/misc/DExport.cxx b/dbaccess/source/ui/misc/DExport.cxx
new file mode 100644
index 000000000..4f25bb467
--- /dev/null
+++ b/dbaccess/source/ui/misc/DExport.cxx
@@ -0,0 +1,840 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <DExport.hxx>
+#include <core_resource.hxx>
+
+#include <com/sun/star/sdbcx/XTablesSupplier.hpp>
+#include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
+#include <com/sun/star/sdbc/DataType.hpp>
+#include <com/sun/star/sdbc/ColumnValue.hpp>
+#include <com/sun/star/sdb/CommandType.hpp>
+#include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp>
+#include <com/sun/star/sdbc/XRow.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <com/sun/star/util/NumberFormat.hpp>
+#include <com/sun/star/util/XNumberFormatTypes.hpp>
+#include <strings.hrc>
+#include <strings.hxx>
+#include <connectivity/dbconversion.hxx>
+#include <sal/log.hxx>
+#include <sfx2/sfxhtml.hxx>
+#include <svl/numuno.hxx>
+#include <connectivity/dbtools.hxx>
+#include <TypeInfo.hxx>
+#include <FieldDescriptions.hxx>
+#include <UITools.hxx>
+#include <tools/diagnose_ex.h>
+#include <com/sun/star/awt/FontDescriptor.hpp>
+#include <WCopyTable.hxx>
+#include <unotools/syslocale.hxx>
+#include <svl/numformat.hxx>
+#include <connectivity/dbexception.hxx>
+#include <connectivity/FValue.hxx>
+#include <com/sun/star/sdb/application/CopyTableOperation.hpp>
+#include <sqlmessage.hxx>
+#include "UpdateHelperImpl.hxx"
+#include <cppuhelper/exc_hlp.hxx>
+
+using namespace dbaui;
+using namespace utl;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::util;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::sdbcx;
+using namespace ::com::sun::star::sdb;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::awt;
+
+namespace CopyTableOperation = ::com::sun::star::sdb::application::CopyTableOperation;
+
+// ODatabaseExport
+ODatabaseExport::ODatabaseExport(sal_Int32 nRows,
+ TPositions&&_rColumnPositions,
+ const Reference< XNumberFormatter >& _rxNumberF,
+ const Reference< css::uno::XComponentContext >& _rxContext,
+ const TColumnVector* pList,
+ const OTypeInfoMap* _pInfoMap,
+ bool _bAutoIncrementEnabled,
+ SvStream& _rInputStream)
+ :m_vColumnPositions(std::move(_rColumnPositions))
+ ,m_aDestColumns(true)
+ ,m_xFormatter(_rxNumberF)
+ ,m_xContext(_rxContext)
+ ,m_pFormatter(nullptr)
+ ,m_rInputStream( _rInputStream )
+ ,m_pColumnList(pList)
+ ,m_pInfoMap(_pInfoMap)
+ ,m_nColumnPos(0)
+ ,m_nRows(1)
+ ,m_nRowCount(0)
+ ,m_bError(false)
+ ,m_bInTbl(false)
+ ,m_bHead(true)
+ ,m_bDontAskAgain(false)
+ ,m_bIsAutoIncrement(_bAutoIncrementEnabled)
+ ,m_bFoundTable(false)
+ ,m_bCheckOnly(false)
+ ,m_bAppendFirstLine(false)
+{
+ m_nRows += nRows;
+ sal_Int32 nCount = 0;
+ for(const std::pair<sal_Int32,sal_Int32> & rPair : m_vColumnPositions)
+ if ( rPair.first != COLUMN_POSITION_NOT_FOUND )
+ ++nCount;
+
+ m_vColumnSize.resize(nCount);
+ m_vNumberFormat.resize(nCount);
+ for(sal_Int32 i=0;i<nCount;++i)
+ {
+ m_vColumnSize[i] = 0;
+ m_vNumberFormat[i] = 0;
+ }
+
+ try
+ {
+ SvtSysLocale aSysLocale;
+ m_aLocale = aSysLocale.GetLanguageTag().getLocale();
+ }
+ catch(Exception&)
+ {
+ }
+
+ SetColumnTypes(pList,_pInfoMap);
+}
+
+ODatabaseExport::ODatabaseExport(const SharedConnection& _rxConnection,
+ const Reference< XNumberFormatter >& _rxNumberF,
+ const Reference< css::uno::XComponentContext >& _rxContext,
+ SvStream& _rInputStream)
+ :m_aDestColumns(_rxConnection->getMetaData().is() && _rxConnection->getMetaData()->supportsMixedCaseQuotedIdentifiers())
+ ,m_xConnection(_rxConnection)
+ ,m_xFormatter(_rxNumberF)
+ ,m_xContext(_rxContext)
+ ,m_pFormatter(nullptr)
+ ,m_rInputStream( _rInputStream )
+ ,m_pColumnList(nullptr)
+ ,m_pInfoMap(nullptr)
+ ,m_nColumnPos(0)
+ ,m_nRows(1)
+ ,m_nRowCount(0)
+ ,m_bError(false)
+ ,m_bInTbl(false)
+ ,m_bHead(true)
+ ,m_bDontAskAgain(false)
+ ,m_bIsAutoIncrement(false)
+ ,m_bFoundTable(false)
+ ,m_bCheckOnly(false)
+ ,m_bAppendFirstLine(false)
+{
+ try
+ {
+ SvtSysLocale aSysLocale;
+ m_aLocale = aSysLocale.GetLanguageTag().getLocale();
+ }
+ catch(Exception&)
+ {
+ }
+
+ Reference<XTablesSupplier> xTablesSup(m_xConnection,UNO_QUERY);
+ if(xTablesSup.is())
+ m_xTables = xTablesSup->getTables();
+
+ Reference<XDatabaseMetaData> xMeta = m_xConnection->getMetaData();
+ Reference<XResultSet> xSet = xMeta.is() ? xMeta->getTypeInfo() : Reference<XResultSet>();
+ if(xSet.is())
+ {
+ ::connectivity::ORowSetValue aValue;
+ std::vector<sal_Int32> aTypes;
+ std::vector<bool> aNullable;
+ Reference<XResultSetMetaData> xResultSetMetaData = Reference<XResultSetMetaDataSupplier>(xSet,UNO_QUERY_THROW)->getMetaData();
+ Reference<XRow> xRow(xSet,UNO_QUERY_THROW);
+ while(xSet->next())
+ {
+ if ( aTypes.empty() )
+ {
+ sal_Int32 nCount = xResultSetMetaData->getColumnCount();
+ if ( nCount < 1 )
+ nCount = 18;
+ aTypes.reserve(nCount+1);
+ aNullable.reserve(nCount+1);
+ aTypes.push_back(-1);
+ aNullable.push_back(false);
+ for (sal_Int32 j = 1; j <= nCount ; ++j)
+ {
+ aNullable.push_back(xResultSetMetaData->isNullable(j) != ColumnValue::NO_NULLS );
+ aTypes.push_back(xResultSetMetaData->getColumnType(j));
+ }
+ }
+
+ sal_Int32 nPos = 1;
+ OSL_ENSURE((nPos) < static_cast<sal_Int32>(aTypes.size()),"aTypes: Illegal index for vector");
+ aValue.fill(nPos,aTypes[nPos],aNullable[nPos],xRow);
+ OUString sTypeName = aValue.getString();
+ ++nPos;
+ OSL_ENSURE((nPos) < static_cast<sal_Int32>(aTypes.size()),"aTypes: Illegal index for vector");
+ aValue.fill(nPos,aTypes[nPos],aNullable[nPos],xRow);
+ sal_Int32 nType = aValue.getInt32();
+ ++nPos;
+
+ if( nType == DataType::VARCHAR )
+ {
+ m_pTypeInfo = std::make_shared<OTypeInfo>();
+
+ m_pTypeInfo->aTypeName = sTypeName;
+ m_pTypeInfo->nType = nType;
+
+ OSL_ENSURE((nPos) < static_cast<sal_Int32>(aTypes.size()),"aTypes: Illegal index for vector");
+ aValue.fill(nPos,aTypes[nPos],aNullable[nPos],xRow);
+ m_pTypeInfo->nPrecision = aValue.getInt32();
+ ++nPos;
+ aValue.fill(nPos,aTypes[nPos],aNullable[nPos],xRow); //LiteralPrefix
+ ++nPos;
+ aValue.fill(nPos,aTypes[nPos],aNullable[nPos],xRow); //LiteralSuffix
+ ++nPos;
+ aValue.fill(nPos,aTypes[nPos],aNullable[nPos],xRow);
+ m_pTypeInfo->aCreateParams = aValue.getString();
+ ++nPos;
+ aValue.fill(nPos,aTypes[nPos],aNullable[nPos],xRow);
+ m_pTypeInfo->bNullable = aValue.getInt32() == ColumnValue::NULLABLE;
+ ++nPos;
+ aValue.fill(nPos,aTypes[nPos],aNullable[nPos],xRow);
+ // bCaseSensitive
+ ++nPos;
+ aValue.fill(nPos,aTypes[nPos],aNullable[nPos],xRow);
+ m_pTypeInfo->nSearchType = aValue.getInt16();
+ ++nPos;
+ aValue.fill(nPos,aTypes[nPos],aNullable[nPos],xRow);
+ // bUnsigned
+ ++nPos;
+ aValue.fill(nPos,aTypes[nPos],aNullable[nPos],xRow);
+ m_pTypeInfo->bCurrency = aValue.getBool();
+ ++nPos;
+ aValue.fill(nPos,aTypes[nPos],aNullable[nPos],xRow);
+ m_pTypeInfo->bAutoIncrement = aValue.getBool();
+ ++nPos;
+ aValue.fill(nPos,aTypes[nPos],aNullable[nPos],xRow);
+ m_pTypeInfo->aLocalTypeName = aValue.getString();
+ ++nPos;
+ aValue.fill(nPos,aTypes[nPos],aNullable[nPos],xRow);
+ m_pTypeInfo->nMinimumScale = aValue.getInt16();
+ ++nPos;
+ aValue.fill(nPos,aTypes[nPos],aNullable[nPos],xRow);
+ m_pTypeInfo->nMaximumScale = aValue.getInt16();
+ nPos = 18;
+ aValue.fill(nPos,aTypes[nPos],xRow);
+ m_pTypeInfo->nNumPrecRadix = aValue.getInt32();
+
+ // check if values are less than zero like it happens in a oracle jdbc driver
+ if( m_pTypeInfo->nPrecision < 0)
+ m_pTypeInfo->nPrecision = 0;
+ if( m_pTypeInfo->nMinimumScale < 0)
+ m_pTypeInfo->nMinimumScale = 0;
+ if( m_pTypeInfo->nMaximumScale < 0)
+ m_pTypeInfo->nMaximumScale = 0;
+ if( m_pTypeInfo->nNumPrecRadix <= 1)
+ m_pTypeInfo->nNumPrecRadix = 10;
+ break;
+ }
+ }
+ }
+ if ( !m_pTypeInfo )
+ m_pTypeInfo = std::make_shared<OTypeInfo>();
+}
+
+ODatabaseExport::~ODatabaseExport()
+{
+ m_pFormatter = nullptr;
+ for (auto const& destColumn : m_aDestColumns)
+ delete destColumn.second;
+ m_vDestVector.clear();
+ m_aDestColumns.clear();
+}
+
+void ODatabaseExport::insertValueIntoColumn()
+{
+ if(m_nColumnPos >= sal_Int32(m_vDestVector.size()))
+ return;
+
+ OFieldDescription* pField = m_vDestVector[m_nColumnPos]->second;
+ if(!pField)
+ return;
+
+ sal_Int32 nNewPos = m_bIsAutoIncrement ? m_nColumnPos+1 : m_nColumnPos;
+ OSL_ENSURE(nNewPos < static_cast<sal_Int32>(m_vColumnPositions.size()),"m_vColumnPositions: Illegal index for vector");
+
+ if ( nNewPos < static_cast<sal_Int32>(m_vColumnPositions.size() ) )
+ {
+ sal_Int32 nPos = m_vColumnPositions[nNewPos].first;
+ if ( nPos != COLUMN_POSITION_NOT_FOUND )
+ {
+ if ( m_sTextToken.isEmpty() && pField->IsNullable() )
+ m_pUpdateHelper->updateNull(nPos,pField->GetType());
+ else
+ {
+ OSL_ENSURE((nNewPos) < static_cast<sal_Int32>(m_vColumnTypes.size()),"Illegal index for vector");
+ if (m_vColumnTypes[nNewPos] != DataType::VARCHAR && m_vColumnTypes[nNewPos] != DataType::CHAR && m_vColumnTypes[nNewPos] != DataType::LONGVARCHAR )
+ {
+ SAL_INFO("dbaccess.ui", "ODatabaseExport::insertValueIntoColumn != DataType::VARCHAR" );
+ ensureFormatter();
+ sal_Int32 nNumberFormat = 0;
+ double fOutNumber = 0.0;
+ bool bNumberFormatError = false;
+ if ( m_pFormatter && !m_sNumToken.isEmpty() )
+ {
+ LanguageType eNumLang = LANGUAGE_NONE;
+ sal_uInt32 nNumberFormat2( nNumberFormat );
+ fOutNumber = SfxHTMLParser::GetTableDataOptionsValNum(nNumberFormat2,eNumLang,m_sTextToken,m_sNumToken,*m_pFormatter);
+ if ( eNumLang != LANGUAGE_NONE )
+ {
+ nNumberFormat2 = m_pFormatter->GetFormatForLanguageIfBuiltIn( nNumberFormat2, eNumLang );
+ (void)m_pFormatter->IsNumberFormat( m_sTextToken, nNumberFormat2, fOutNumber );
+ }
+ nNumberFormat = static_cast<sal_Int32>(nNumberFormat2);
+ }
+ else
+ {
+ Reference< XNumberFormatsSupplier > xSupplier = m_xFormatter->getNumberFormatsSupplier();
+ Reference<XNumberFormatTypes> xNumType(xSupplier->getNumberFormats(),UNO_QUERY);
+ const sal_Int16 nFormats[] = {
+ NumberFormat::DATETIME
+ ,NumberFormat::DATE
+ ,NumberFormat::TIME
+ ,NumberFormat::CURRENCY
+ ,NumberFormat::NUMBER
+ ,NumberFormat::LOGICAL
+ };
+ for (short nFormat : nFormats)
+ {
+ try
+ {
+ nNumberFormat = m_xFormatter->detectNumberFormat(xNumType->getStandardFormat(nFormat,m_aLocale),m_sTextToken);
+ break;
+ }
+ catch(Exception&)
+ {
+ }
+ }
+ try
+ {
+ fOutNumber = m_xFormatter->convertStringToNumber(nNumberFormat,m_sTextToken);
+ }
+ catch(Exception&)
+ {
+ bNumberFormatError = true;
+ m_pUpdateHelper->updateString(nPos,m_sTextToken);
+ }
+ }
+ if ( !bNumberFormatError )
+ {
+ try
+ {
+ Reference< XNumberFormatsSupplier > xSupplier = m_xFormatter->getNumberFormatsSupplier();
+ Reference< XNumberFormats > xFormats = xSupplier->getNumberFormats();
+ Reference<XPropertySet> xProp = xFormats->getByKey(nNumberFormat);
+ sal_Int16 nType = 0;
+ xProp->getPropertyValue(PROPERTY_TYPE) >>= nType;
+ switch(nType)
+ {
+ case NumberFormat::DATE:
+ m_pUpdateHelper->updateDate(nPos,::dbtools::DBTypeConversion::toDate(fOutNumber,m_aNullDate));
+ break;
+ case NumberFormat::DATETIME:
+ m_pUpdateHelper->updateTimestamp(nPos,::dbtools::DBTypeConversion::toDateTime(fOutNumber,m_aNullDate));
+ break;
+ case NumberFormat::TIME:
+ m_pUpdateHelper->updateTime(nPos,::dbtools::DBTypeConversion::toTime(fOutNumber));
+ break;
+ default:
+ m_pUpdateHelper->updateDouble(nPos,fOutNumber);
+ }
+ }
+ catch(Exception&)
+ {
+ m_pUpdateHelper->updateString(nPos,m_sTextToken);
+ }
+ }
+
+ }
+ else
+ m_pUpdateHelper->updateString(nPos,m_sTextToken);
+ }
+ }
+ }
+ eraseTokens();
+}
+
+sal_Int16 ODatabaseExport::CheckString(const OUString& aCheckToken, sal_Int16 _nOldNumberFormat)
+{
+ sal_Int16 nNumberFormat = 0;
+
+ try
+ {
+ Reference< XNumberFormatsSupplier > xSupplier = m_xFormatter->getNumberFormatsSupplier();
+ Reference< XNumberFormats > xFormats = xSupplier->getNumberFormats();
+
+ ensureFormatter();
+ if ( m_pFormatter && !m_sNumToken.isEmpty() )
+ {
+ LanguageType eNumLang;
+ sal_uInt32 nFormatKey(0);
+ double fOutNumber = SfxHTMLParser::GetTableDataOptionsValNum(nFormatKey,eNumLang,m_sTextToken,m_sNumToken,*m_pFormatter);
+ if ( eNumLang != LANGUAGE_NONE )
+ {
+ nFormatKey = m_pFormatter->GetFormatForLanguageIfBuiltIn( nFormatKey, eNumLang );
+ if ( !m_pFormatter->IsNumberFormat( m_sTextToken, nFormatKey, fOutNumber ) )
+ return NumberFormat::TEXT;
+ }
+ Reference<XPropertySet> xProp = xFormats->getByKey(nFormatKey);
+ xProp->getPropertyValue(PROPERTY_TYPE) >>= nNumberFormat;
+ }
+ else
+ {
+ Reference<XNumberFormatTypes> xNumType(xFormats,UNO_QUERY);
+ sal_Int32 nFormatKey = m_xFormatter->detectNumberFormat(xNumType->getStandardFormat(NumberFormat::ALL,m_aLocale),aCheckToken);
+ m_xFormatter->convertStringToNumber(nFormatKey,aCheckToken);
+
+ Reference<XPropertySet> xProp = xFormats->getByKey(nFormatKey);
+ sal_Int16 nType = 0;
+ xProp->getPropertyValue(PROPERTY_TYPE) >>= nType;
+
+ switch(nType)
+ {
+ case NumberFormat::ALL:
+ nNumberFormat = NumberFormat::ALL;
+ break;
+ case NumberFormat::DEFINED:
+ nNumberFormat = NumberFormat::TEXT;
+ break;
+ case NumberFormat::DATE:
+ switch(_nOldNumberFormat)
+ {
+ case NumberFormat::DATETIME:
+ case NumberFormat::TEXT:
+ case NumberFormat::DATE:
+ nNumberFormat = _nOldNumberFormat;
+ break;
+ case NumberFormat::ALL:
+ nNumberFormat = NumberFormat::DATE;
+ break;
+ default:
+ nNumberFormat = NumberFormat::TEXT;
+
+ }
+ break;
+ case NumberFormat::TIME:
+ switch(_nOldNumberFormat)
+ {
+ case NumberFormat::DATETIME:
+ case NumberFormat::TEXT:
+ case NumberFormat::TIME:
+ nNumberFormat = _nOldNumberFormat;
+ break;
+ case NumberFormat::ALL:
+ nNumberFormat = NumberFormat::TIME;
+ break;
+ default:
+ nNumberFormat = NumberFormat::TEXT;
+ break;
+ }
+ break;
+ case NumberFormat::CURRENCY:
+ switch(_nOldNumberFormat)
+ {
+ case NumberFormat::NUMBER:
+ nNumberFormat = NumberFormat::CURRENCY;
+ break;
+ case NumberFormat::CURRENCY:
+ nNumberFormat = _nOldNumberFormat;
+ break;
+ case NumberFormat::ALL:
+ nNumberFormat = NumberFormat::CURRENCY;
+ break;
+ default:
+ nNumberFormat = NumberFormat::TEXT;
+ break;
+ }
+ break;
+ case NumberFormat::NUMBER:
+ case NumberFormat::SCIENTIFIC:
+ case NumberFormat::FRACTION:
+ case NumberFormat::PERCENT:
+ switch(_nOldNumberFormat)
+ {
+ case NumberFormat::NUMBER:
+ nNumberFormat = _nOldNumberFormat;
+ break;
+ case NumberFormat::CURRENCY:
+ nNumberFormat = NumberFormat::CURRENCY;
+ break;
+ case NumberFormat::ALL:
+ nNumberFormat = nType;
+ break;
+ default:
+ nNumberFormat = NumberFormat::TEXT;
+ break;
+ }
+ break;
+ case NumberFormat::TEXT:
+ case NumberFormat::UNDEFINED:
+ case NumberFormat::LOGICAL:
+ nNumberFormat = NumberFormat::TEXT; // Text overwrites everything
+ break;
+ case NumberFormat::DATETIME:
+ switch(_nOldNumberFormat)
+ {
+ case NumberFormat::DATETIME:
+ case NumberFormat::TEXT:
+ case NumberFormat::TIME:
+ nNumberFormat = _nOldNumberFormat;
+ break;
+ case NumberFormat::ALL:
+ nNumberFormat = NumberFormat::DATETIME;
+ break;
+ default:
+ nNumberFormat = NumberFormat::TEXT;
+ break;
+ }
+ break;
+ default:
+ SAL_WARN("dbaccess.ui", "ODatabaseExport: Unknown NumberFormat");
+ }
+ }
+ }
+ catch(Exception&)
+ {
+ nNumberFormat = NumberFormat::TEXT; // Text overwrites everything
+ }
+
+ return nNumberFormat;
+}
+
+void ODatabaseExport::SetColumnTypes(const TColumnVector* _pList,const OTypeInfoMap* _pInfoMap)
+{
+ if(!(_pList && _pInfoMap))
+ return;
+
+ OSL_ENSURE(m_vNumberFormat.size() == m_vColumnSize.size() && m_vColumnSize.size() == _pList->size(),"Illegal columns in list");
+ Reference< XNumberFormatsSupplier > xSupplier = m_xFormatter->getNumberFormatsSupplier();
+ Reference< XNumberFormats > xFormats = xSupplier->getNumberFormats();
+ sal_Int32 minBothSize = std::min<sal_Int32>(m_vNumberFormat.size(), m_vColumnSize.size());
+ sal_Int32 i = 0;
+ for (auto const& elem : *_pList)
+ {
+ if (i >= minBothSize)
+ break;
+
+ sal_Int32 nDataType;
+ sal_Int32 nLength(0),nScale(0);
+ sal_Int16 nType = m_vNumberFormat[i] & ~NumberFormat::DEFINED;
+
+ switch ( nType )
+ {
+ case NumberFormat::ALL:
+ nDataType = DataType::DOUBLE;
+ break;
+ case NumberFormat::DEFINED:
+ nDataType = DataType::VARCHAR;
+ nLength = ((m_vColumnSize[i] % 10 ) ? m_vColumnSize[i]/ 10 + 1: m_vColumnSize[i]/ 10) * 10;
+ break;
+ case NumberFormat::DATE:
+ nDataType = DataType::DATE;
+ break;
+ case NumberFormat::TIME:
+ nDataType = DataType::TIME;
+ break;
+ case NumberFormat::DATETIME:
+ nDataType = DataType::TIMESTAMP;
+ break;
+ case NumberFormat::CURRENCY:
+ nDataType = DataType::NUMERIC;
+ nScale = 4;
+ nLength = 19;
+ break;
+ case NumberFormat::NUMBER:
+ case NumberFormat::SCIENTIFIC:
+ case NumberFormat::FRACTION:
+ case NumberFormat::PERCENT:
+ nDataType = DataType::DOUBLE;
+ break;
+ case NumberFormat::TEXT:
+ case NumberFormat::UNDEFINED:
+ case NumberFormat::LOGICAL:
+ default:
+ nDataType = DataType::VARCHAR;
+ nLength = ((m_vColumnSize[i] % 10 ) ? m_vColumnSize[i]/ 10 + 1: m_vColumnSize[i]/ 10) * 10;
+ break;
+ }
+ OTypeInfoMap::const_iterator aFind = _pInfoMap->find(nDataType);
+ if(aFind != _pInfoMap->end())
+ {
+ elem->second->SetType(aFind->second);
+ elem->second->SetPrecision(std::min<sal_Int32>(aFind->second->nPrecision,nLength));
+ elem->second->SetScale(std::min<sal_Int32>(aFind->second->nMaximumScale,nScale));
+
+ sal_Int32 nFormatKey = ::dbtools::getDefaultNumberFormat( nDataType,
+ elem->second->GetScale(),
+ elem->second->IsCurrency(),
+ Reference< XNumberFormatTypes>(xFormats,UNO_QUERY),
+ m_aLocale);
+
+ elem->second->SetFormatKey(nFormatKey);
+ }
+ ++i;
+ }
+}
+
+void ODatabaseExport::CreateDefaultColumn(const OUString& _rColumnName)
+{
+ Reference< XDatabaseMetaData> xDestMetaData(m_xConnection->getMetaData());
+ sal_Int32 nMaxNameLen(xDestMetaData->getMaxColumnNameLength());
+ OUString aAlias = _rColumnName;
+ if ( isSQL92CheckEnabled(m_xConnection) )
+ aAlias = ::dbtools::convertName2SQLName(_rColumnName,xDestMetaData->getExtraNameCharacters());
+
+ if(nMaxNameLen && aAlias.getLength() > nMaxNameLen)
+ aAlias = aAlias.copy(0, std::min<sal_Int32>( nMaxNameLen-1, aAlias.getLength() ) );
+
+ OUString sName(aAlias);
+ if(m_aDestColumns.find(sName) != m_aDestColumns.end())
+ {
+ sal_Int32 nPos = 0;
+ sal_Int32 nCount = 2;
+ while(m_aDestColumns.find(sName) != m_aDestColumns.end())
+ {
+ sName = aAlias
+ + OUString::number(++nPos);
+ if(nMaxNameLen && sName.getLength() > nMaxNameLen)
+ {
+ aAlias = aAlias.copy(0,std::min<sal_Int32>( nMaxNameLen-nCount, aAlias.getLength() ));
+ sName = aAlias
+ + OUString::number(nPos);
+ ++nCount;
+ }
+ }
+ }
+ aAlias = sName;
+ // now create a column
+ OFieldDescription* pField = new OFieldDescription();
+ pField->SetType(m_pTypeInfo);
+ pField->SetName(aAlias);
+ pField->SetPrecision(std::min<sal_Int32>(sal_Int32(255),m_pTypeInfo->nPrecision));
+ pField->SetScale(0);
+ pField->SetIsNullable(ColumnValue::NULLABLE);
+ pField->SetAutoIncrement(false);
+ pField->SetPrimaryKey(false);
+ pField->SetCurrency(false);
+
+ TColumns::const_iterator aFind = m_aDestColumns.find( aAlias );
+ if ( aFind != m_aDestColumns.end() )
+ {
+ delete aFind->second;
+ m_aDestColumns.erase(aFind);
+ }
+
+ m_vDestVector.emplace_back(m_aDestColumns.emplace(aAlias,pField).first);
+}
+
+void ODatabaseExport::createRowSet()
+{
+ m_pUpdateHelper = std::make_shared<OParameterUpdateHelper>(createPreparedStatment(m_xConnection->getMetaData(),m_xTable,m_vColumnPositions));
+}
+
+bool ODatabaseExport::executeWizard(const OUString& _rTableName, const Any& _aTextColor, const FontDescriptor& _rFont)
+{
+ bool bHaveDefaultTable = !m_sDefaultTableName.isEmpty();
+ OUString sTableName( bHaveDefaultTable ? m_sDefaultTableName : _rTableName );
+ OCopyTableWizard aWizard(
+ nullptr,
+ sTableName,
+ bHaveDefaultTable ? CopyTableOperation::AppendData : CopyTableOperation::CopyDefinitionAndData,
+ ODatabaseExport::TColumns(m_aDestColumns),
+ m_vDestVector,
+ m_xConnection,
+ m_xFormatter,
+ getTypeSelectionPageFactory(),
+ m_rInputStream,
+ m_xContext
+ );
+
+ bool bError = false;
+ try
+ {
+ if (aWizard.run())
+ {
+ switch(aWizard.getOperation())
+ {
+ case CopyTableOperation::CopyDefinitionAndData:
+ case CopyTableOperation::AppendData:
+ {
+ m_xTable = aWizard.returnTable();
+ bError = !m_xTable.is();
+ if(m_xTable.is())
+ {
+ m_xTable->setPropertyValue(PROPERTY_FONT,Any(_rFont));
+ if(_aTextColor.hasValue())
+ m_xTable->setPropertyValue(PROPERTY_TEXTCOLOR,_aTextColor);
+ }
+ m_bIsAutoIncrement = aWizard.shouldCreatePrimaryKey();
+ m_vColumnPositions = aWizard.GetColumnPositions();
+ m_vColumnTypes = aWizard.GetColumnTypes();
+ m_bAppendFirstLine = !aWizard.UseHeaderLine();
+ }
+ break;
+ default:
+ bError = true; // there is no error but I have nothing more to do
+ }
+ }
+ else
+ bError = true;
+
+ if(!bError)
+ createRowSet();
+ }
+ catch( const SQLException&)
+ {
+ ::dbtools::showError( ::dbtools::SQLExceptionInfo( ::cppu::getCaughtException() ), aWizard.getDialog()->GetXWindow(), m_xContext );
+ bError = true;
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+
+ return bError;
+}
+
+void ODatabaseExport::showErrorDialog(const css::sdbc::SQLException& e)
+{
+ if(!m_bDontAskAgain)
+ {
+ OUString aMsg = e.Message
+ + "\n"
+ + DBA_RES( STR_QRY_CONTINUE );
+ OSQLWarningBox aBox(nullptr, aMsg, MessBoxStyle::YesNo | MessBoxStyle::DefaultNo);
+
+ if (aBox.run() == RET_YES)
+ m_bDontAskAgain = true;
+ else
+ m_bError = true;
+ }
+}
+
+void ODatabaseExport::adjustFormat()
+{
+ if ( m_sTextToken.isEmpty() )
+ return;
+
+ sal_Int32 nNewPos = m_bIsAutoIncrement ? m_nColumnPos+1 : m_nColumnPos;
+ OSL_ENSURE(nNewPos < static_cast<sal_Int32>(m_vColumnPositions.size()),"Illegal index for vector");
+ if ( nNewPos < static_cast<sal_Int32>(m_vColumnPositions.size()) )
+ {
+ sal_Int32 nColPos = m_vColumnPositions[nNewPos].first;
+ if( nColPos != COLUMN_POSITION_NOT_FOUND)
+ {
+ --nColPos;
+ OSL_ENSURE((nColPos) < static_cast<sal_Int32>(m_vNumberFormat.size()),"m_vFormatKey: Illegal index for vector");
+ OSL_ENSURE((nColPos) < static_cast<sal_Int32>(m_vColumnSize.size()),"m_vColumnSize: Illegal index for vector");
+ m_vNumberFormat[nColPos] = CheckString(m_sTextToken,m_vNumberFormat[nColPos]);
+ m_vColumnSize[nColPos] = std::max<sal_Int32>(static_cast<sal_Int32>(m_vColumnSize[nColPos]), m_sTextToken.getLength());
+ }
+ }
+ eraseTokens();
+}
+
+void ODatabaseExport::eraseTokens()
+{
+ m_sTextToken.clear();
+ m_sNumToken.clear();
+}
+
+void ODatabaseExport::ensureFormatter()
+{
+ if ( !m_pFormatter )
+ {
+ Reference< XNumberFormatsSupplier > xSupplier = m_xFormatter->getNumberFormatsSupplier();
+ auto pSupplierImpl = comphelper::getFromUnoTunnel<SvNumberFormatsSupplierObj>(xSupplier);
+ m_pFormatter = pSupplierImpl ? pSupplierImpl->GetNumberFormatter() : nullptr;
+ Reference<XPropertySet> xNumberFormatSettings = xSupplier->getNumberFormatSettings();
+ xNumberFormatSettings->getPropertyValue("NullDate") >>= m_aNullDate;
+ }
+}
+
+Reference< XPreparedStatement > ODatabaseExport::createPreparedStatment( const Reference<XDatabaseMetaData>& _xMetaData
+ ,const Reference<XPropertySet>& _xDestTable
+ ,const TPositions& _rvColumns)
+{
+ OUString sComposedTableName = ::dbtools::composeTableName( _xMetaData, _xDestTable, ::dbtools::EComposeRule::InDataManipulation, true );
+
+ OUStringBuffer aSql = "INSERT INTO "
+ + sComposedTableName
+ + " ( ";
+
+ // set values and column names
+ OUStringBuffer aValues(" VALUES ( ");
+
+ OUString aQuote;
+ if ( _xMetaData.is() )
+ aQuote = _xMetaData->getIdentifierQuoteString();
+
+ Reference<XColumnsSupplier> xDestColsSup(_xDestTable,UNO_QUERY_THROW);
+
+ // create sql string and set column types
+ Sequence< OUString> aDestColumnNames = xDestColsSup->getColumns()->getElementNames();
+ if ( !aDestColumnNames.hasElements() )
+ {
+ return Reference< XPreparedStatement > ();
+ }
+ const OUString* pIter = aDestColumnNames.getConstArray();
+ std::vector< OUString> aInsertList;
+ aInsertList.resize(aDestColumnNames.getLength()+1);
+ for(size_t j=0; j < aInsertList.size(); ++j)
+ {
+ ODatabaseExport::TPositions::const_iterator aFind = std::find_if(_rvColumns.begin(),_rvColumns.end(),
+ [j] (const ODatabaseExport::TPositions::value_type& tPos)
+ { return tPos.second == static_cast<sal_Int32>(j+1); });
+ if ( _rvColumns.end() != aFind && aFind->second != COLUMN_POSITION_NOT_FOUND && aFind->first != COLUMN_POSITION_NOT_FOUND )
+ {
+ OSL_ENSURE((aFind->first) < static_cast<sal_Int32>(aInsertList.size()),"aInsertList: Illegal index for vector");
+ aInsertList[aFind->first] = ::dbtools::quoteName( aQuote,*(pIter+j));
+ }
+ }
+
+ // create the sql string
+ for (auto const& elem : aInsertList)
+ {
+ if ( !elem.isEmpty() )
+ {
+ aSql.append(elem);
+ aSql.append(",");
+ aValues.append("?,");
+ }
+ }
+
+ aSql[aSql.getLength()-1] = ')';
+ aValues[aValues.getLength()-1] = ')';
+
+ aSql.append(aValues);
+ // now create,fill and execute the prepared statement
+ return _xMetaData->getConnection()->prepareStatement(aSql.makeStringAndClear());
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/misc/HtmlReader.cxx b/dbaccess/source/ui/misc/HtmlReader.cxx
new file mode 100644
index 000000000..c2917a630
--- /dev/null
+++ b/dbaccess/source/ui/misc/HtmlReader.cxx
@@ -0,0 +1,481 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <HtmlReader.hxx>
+#include <connectivity/dbtools.hxx>
+#include <toolkit/helper/vclunohelper.hxx>
+#include <tools/stream.hxx>
+#include <tools/tenccvt.hxx>
+#include <comphelper/string.hxx>
+#include <strings.hrc>
+#include <osl/diagnose.h>
+#include <core_resource.hxx>
+#include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
+#include <com/sun/star/awt/FontWeight.hpp>
+#include <com/sun/star/awt/FontStrikeout.hpp>
+#include <com/sun/star/awt/FontSlant.hpp>
+#include <com/sun/star/awt/FontUnderline.hpp>
+#include <svtools/htmltokn.h>
+#include <svtools/htmlkywd.hxx>
+#include <tools/color.hxx>
+#include <WExtendPages.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/settings.hxx>
+
+using namespace dbaui;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::sdbcx;
+using namespace ::com::sun::star::awt;
+
+#define DBAUI_HTML_FONTSIZES 8 // like export, HTML-Options
+
+// OHTMLReader
+OHTMLReader::OHTMLReader(SvStream& rIn,const SharedConnection& _rxConnection,
+ const Reference< css::util::XNumberFormatter >& _rxNumberF,
+ const css::uno::Reference< css::uno::XComponentContext >& _rxContext)
+ : HTMLParser(rIn)
+ , ODatabaseExport( _rxConnection, _rxNumberF, _rxContext, rIn )
+ , m_nTableCount(0)
+ , m_nColumnWidth(87)
+{
+ SetSrcEncoding( GetExtendedCompatibilityTextEncoding( RTL_TEXTENCODING_ISO_8859_1 ) );
+ // If the file starts with a BOM, switch to UCS2.
+ SetSwitchToUCS2( true );
+}
+
+OHTMLReader::OHTMLReader(SvStream& rIn,
+ sal_Int32 nRows,
+ TPositions&& _rColumnPositions,
+ const Reference< css::util::XNumberFormatter >& _rxNumberF,
+ const css::uno::Reference< css::uno::XComponentContext >& _rxContext,
+ const TColumnVector* pList,
+ const OTypeInfoMap* _pInfoMap,
+ bool _bAutoIncrementEnabled)
+ : HTMLParser(rIn)
+ , ODatabaseExport( nRows, std::move(_rColumnPositions), _rxNumberF, _rxContext, pList, _pInfoMap, _bAutoIncrementEnabled, rIn )
+ , m_nTableCount(0)
+ , m_nColumnWidth(87)
+{
+ SetSrcEncoding( GetExtendedCompatibilityTextEncoding( RTL_TEXTENCODING_ISO_8859_1 ) );
+ // If the file starts with a BOM, switch to UCS2.
+ SetSwitchToUCS2( true );
+}
+
+OHTMLReader::~OHTMLReader()
+{
+}
+
+SvParserState OHTMLReader::CallParser()
+{
+ rInput.Seek(STREAM_SEEK_TO_BEGIN);
+ rInput.ResetError();
+ SvParserState eParseState = HTMLParser::CallParser();
+ SetColumnTypes(m_pColumnList,m_pInfoMap);
+ return m_bFoundTable ? eParseState : SvParserState::Error;
+}
+
+#if defined _MSC_VER
+#pragma warning(disable: 4702) // unreachable code, bug in MSVC2015
+#endif
+void OHTMLReader::NextToken( HtmlTokenId nToken )
+{
+ if(m_bError || !m_nRows) // if there is an error or no more rows to check, return immediately
+ return;
+ if ( nToken == HtmlTokenId::META )
+ setTextEncoding();
+
+ if(m_xConnection.is()) // names, which CTOR was called and hence, if a table should be created
+ {
+ switch(nToken)
+ {
+ case HtmlTokenId::TABLE_ON:
+ ++m_nTableCount;
+ { // can also be TD or TH, if there was no TABLE before
+ const HTMLOptions& rHtmlOptions = GetOptions();
+ for (const auto & rOption : rHtmlOptions)
+ {
+ if( rOption.GetToken() == HtmlOptionId::WIDTH )
+ { // percentage: of document width respectively outer cell
+ m_nColumnWidth = GetWidthPixel( rOption );
+ }
+ }
+ }
+ [[fallthrough]];
+ case HtmlTokenId::THEAD_ON:
+ case HtmlTokenId::TBODY_ON:
+ {
+ sal_uInt64 const nTell = rInput.Tell(); // perhaps alters position of the stream
+ if ( !m_xTable.is() )
+ {// use first line as header
+ m_bError = !CreateTable(nToken);
+ if ( m_bAppendFirstLine )
+ rInput.Seek(nTell);
+ }
+ }
+ break;
+ case HtmlTokenId::TABLE_OFF:
+ if(!--m_nTableCount)
+ {
+ m_xTable = nullptr;
+ }
+ break;
+ case HtmlTokenId::TABLEROW_ON:
+ if ( !m_pUpdateHelper )
+ m_bError = true;
+ break;
+ case HtmlTokenId::TEXTTOKEN:
+ case HtmlTokenId::SINGLECHAR:
+ if ( m_bInTbl ) //&& !m_bSDNum ) // important, as otherwise we also get the names of the fonts
+ m_sTextToken += aToken;
+ break;
+ case HtmlTokenId::PARABREAK_OFF:
+ m_sCurrent += m_sTextToken;
+ break;
+ case HtmlTokenId::PARABREAK_ON:
+ m_sTextToken.clear();
+ break;
+ case HtmlTokenId::TABLEDATA_ON:
+ fetchOptions();
+ break;
+ case HtmlTokenId::TABLEDATA_OFF:
+ {
+ if ( !m_sCurrent.isEmpty() )
+ m_sTextToken = m_sCurrent;
+ try
+ {
+ insertValueIntoColumn();
+ }
+ catch(SQLException& e)
+ // handling update failure
+ {
+ showErrorDialog(e);
+ }
+ m_sCurrent.clear();
+ m_nColumnPos++;
+ eraseTokens();
+ m_bInTbl = false;
+ }
+ break;
+ case HtmlTokenId::TABLEROW_OFF:
+ if ( !m_pUpdateHelper )
+ {
+ m_bError = true;
+ break;
+ }
+ try
+ {
+ m_nRowCount++;
+ if (m_bIsAutoIncrement) // if bSetAutoIncrement then I have to set the autoincrement
+ m_pUpdateHelper->updateInt(1,m_nRowCount);
+ m_pUpdateHelper->insertRow();
+ }
+ catch(SQLException& e)
+ // handling update failure
+ {
+ showErrorDialog(e);
+ }
+ m_nColumnPos = 0;
+ break;
+ default: break;
+ }
+ }
+ else // branch only valid for type checking
+ {
+ switch(nToken)
+ {
+ case HtmlTokenId::THEAD_ON:
+ case HtmlTokenId::TBODY_ON:
+ // The head of the column is not included
+ if(m_bHead)
+ {
+ do
+ {}
+ while(GetNextToken() != HtmlTokenId::TABLEROW_OFF);
+ m_bHead = false;
+ }
+ break;
+ case HtmlTokenId::TABLEDATA_ON:
+ case HtmlTokenId::TABLEHEADER_ON:
+ fetchOptions();
+ break;
+ case HtmlTokenId::TEXTTOKEN:
+ case HtmlTokenId::SINGLECHAR:
+ if ( m_bInTbl ) // && !m_bSDNum ) // important, as otherwise we also get the names of the fonts
+ m_sTextToken += aToken;
+ break;
+ case HtmlTokenId::PARABREAK_OFF:
+ m_sCurrent += m_sTextToken;
+ break;
+ case HtmlTokenId::PARABREAK_ON:
+ m_sTextToken.clear();
+ break;
+ case HtmlTokenId::TABLEDATA_OFF:
+ if ( !m_sCurrent.isEmpty() )
+ m_sTextToken = m_sCurrent;
+ adjustFormat();
+ m_nColumnPos++;
+ m_bInTbl = false;
+ m_sCurrent.clear();
+ break;
+ case HtmlTokenId::TABLEROW_OFF:
+ if ( !m_sCurrent.isEmpty() )
+ m_sTextToken = m_sCurrent;
+ adjustFormat();
+ m_nColumnPos = 0;
+ m_nRows--;
+ m_sCurrent.clear();
+ break;
+ default: break;
+ }
+ }
+}
+
+void OHTMLReader::fetchOptions()
+{
+ m_bInTbl = true;
+ const HTMLOptions& options = GetOptions();
+ for (const auto & rOption : options)
+ {
+ switch( rOption.GetToken() )
+ {
+ case HtmlOptionId::SDNUM:
+ m_sNumToken = rOption.GetString();
+ break;
+ default: break;
+ }
+ }
+}
+
+void OHTMLReader::TableDataOn(SvxCellHorJustify& eVal)
+{
+ const HTMLOptions& rHtmlOptions = GetOptions();
+ for (const auto & rOption : rHtmlOptions)
+ {
+ switch( rOption.GetToken() )
+ {
+ case HtmlOptionId::ALIGN:
+ {
+ const OUString& rOptVal = rOption.GetString();
+ if (rOptVal.equalsIgnoreAsciiCase( OOO_STRING_SVTOOLS_HTML_AL_right ))
+ eVal = SvxCellHorJustify::Right;
+ else if (rOptVal.equalsIgnoreAsciiCase( OOO_STRING_SVTOOLS_HTML_AL_center ))
+ eVal = SvxCellHorJustify::Center;
+ else if (rOptVal.equalsIgnoreAsciiCase( OOO_STRING_SVTOOLS_HTML_AL_left ))
+ eVal = SvxCellHorJustify::Left;
+ else
+ eVal = SvxCellHorJustify::Standard;
+ }
+ break;
+ default: break;
+ }
+ }
+}
+
+void OHTMLReader::TableFontOn(FontDescriptor& _rFont, Color &_rTextColor)
+{
+ const HTMLOptions& rHtmlOptions = GetOptions();
+ for (const auto & rOption : rHtmlOptions)
+ {
+ switch( rOption.GetToken() )
+ {
+ case HtmlOptionId::COLOR:
+ {
+ Color aColor;
+ rOption.GetColor( aColor );
+ _rTextColor = aColor.GetRGBColor();
+ }
+ break;
+ case HtmlOptionId::FACE :
+ {
+ const OUString& rFace = rOption.GetString();
+ OUStringBuffer aFontName;
+ sal_Int32 nPos = 0;
+ while( nPos != -1 )
+ {
+ // list of fonts, VCL: semicolon as separator, HTML: comma
+ std::u16string_view aFName = o3tl::getToken(rFace, 0, ',', nPos );
+ aFName = comphelper::string::strip(aFName, ' ');
+ if( !aFontName.isEmpty() )
+ aFontName.append(";");
+ aFontName.append(aFName);
+ }
+ if ( !aFontName.isEmpty() )
+ _rFont.Name = aFontName.makeStringAndClear();
+ }
+ break;
+ case HtmlOptionId::SIZE :
+ {
+ sal_Int16 nSize = static_cast<sal_Int16>(rOption.GetNumber());
+ if ( nSize == 0 )
+ nSize = 1;
+ else if ( nSize < DBAUI_HTML_FONTSIZES )
+ nSize = DBAUI_HTML_FONTSIZES;
+
+ _rFont.Height = nSize;
+ }
+ break;
+ default: break;
+ }
+ }
+}
+
+sal_Int16 OHTMLReader::GetWidthPixel( const HTMLOption& rOption )
+{
+ const OUString& rOptVal = rOption.GetString();
+ if ( rOptVal.indexOf('%') != -1 )
+ { // percentage
+ OSL_ENSURE( m_nColumnWidth, "WIDTH Option: m_nColumnWidth==0 and Width%" );
+ return static_cast<sal_Int16>((rOption.GetNumber() * m_nColumnWidth) / 100);
+ }
+ else
+ {
+ if ( rOptVal.indexOf('*') != -1 )
+ { // relative to what?!?
+//TODO: collect ColArray of all relevant values and then MakeCol
+ return 0;
+ }
+ else
+ return static_cast<sal_Int16>(rOption.GetNumber()); // pixel
+ }
+}
+
+bool OHTMLReader::CreateTable(HtmlTokenId nToken)
+{
+ OUString aTempName(DBA_RES(STR_TBL_TITLE));
+ aTempName = aTempName.getToken(0,' ');
+ aTempName = ::dbtools::createUniqueName(m_xTables, aTempName);
+
+ bool bCaption = false;
+ bool bTableHeader = false;
+ OUString aColumnName;
+ SvxCellHorJustify eVal;
+
+ OUString aTableName;
+ FontDescriptor aFont = VCLUnoHelper::CreateFontDescriptor(Application::GetSettings().GetStyleSettings().GetAppFont());
+ Color nTextColor;
+ do
+ {
+ switch (nToken)
+ {
+ case HtmlTokenId::TEXTTOKEN:
+ case HtmlTokenId::SINGLECHAR:
+ if(bTableHeader)
+ aColumnName += aToken;
+ if(bCaption)
+ aTableName += aToken;
+ break;
+ case HtmlTokenId::PARABREAK_OFF:
+ m_sCurrent += aColumnName;
+ break;
+ case HtmlTokenId::PARABREAK_ON:
+ m_sTextToken.clear();
+ break;
+ case HtmlTokenId::TABLEDATA_ON:
+ case HtmlTokenId::TABLEHEADER_ON:
+ TableDataOn(eVal);
+ bTableHeader = true;
+ break;
+ case HtmlTokenId::TABLEDATA_OFF:
+ case HtmlTokenId::TABLEHEADER_OFF:
+ {
+ aColumnName = comphelper::string::strip(aColumnName, ' ' );
+ if (aColumnName.isEmpty() || m_bAppendFirstLine )
+ aColumnName = DBA_RES(STR_COLUMN_NAME);
+ else if ( !m_sCurrent.isEmpty() )
+ aColumnName = m_sCurrent;
+
+ aColumnName = comphelper::string::strip(aColumnName, ' ');
+ CreateDefaultColumn(aColumnName);
+ aColumnName.clear();
+ m_sCurrent.clear();
+
+ eVal = SvxCellHorJustify::Standard;
+ bTableHeader = false;
+ }
+ break;
+
+ case HtmlTokenId::TITLE_ON:
+ case HtmlTokenId::CAPTION_ON:
+ bCaption = true;
+ break;
+ case HtmlTokenId::TITLE_OFF:
+ case HtmlTokenId::CAPTION_OFF:
+ aTableName = comphelper::string::strip(aTableName, ' ');
+ if(aTableName.isEmpty())
+ aTableName = ::dbtools::createUniqueName(m_xTables, aTableName);
+ else
+ aTableName = aTempName;
+ bCaption = false;
+ break;
+ case HtmlTokenId::FONT_ON:
+ TableFontOn(aFont,nTextColor);
+ break;
+ case HtmlTokenId::BOLD_ON:
+ aFont.Weight = css::awt::FontWeight::BOLD;
+ break;
+ case HtmlTokenId::ITALIC_ON:
+ aFont.Slant = css::awt::FontSlant_ITALIC;
+ break;
+ case HtmlTokenId::UNDERLINE_ON:
+ aFont.Underline = css::awt::FontUnderline::SINGLE;
+ break;
+ case HtmlTokenId::STRIKE_ON:
+ aFont.Strikeout = css::awt::FontStrikeout::SINGLE;
+ break;
+ default: break;
+ }
+ nToken = GetNextToken();
+ }
+ while (nToken != HtmlTokenId::TABLEROW_OFF);
+
+ if ( !m_sCurrent.isEmpty() )
+ aColumnName = m_sCurrent;
+ aColumnName = comphelper::string::strip(aColumnName, ' ');
+ if(!aColumnName.isEmpty())
+ CreateDefaultColumn(aColumnName);
+
+ if ( m_vDestVector.empty() )
+ return false;
+
+ if(aTableName.isEmpty())
+ aTableName = aTempName;
+
+ m_bInTbl = false;
+ m_bFoundTable = true;
+
+ if ( isCheckEnabled() )
+ return true;
+
+ return !executeWizard(aTableName,Any(nTextColor),aFont) && m_xTable.is();
+}
+
+void OHTMLReader::setTextEncoding()
+{
+ ParseMetaOptions(nullptr, nullptr);
+}
+
+TypeSelectionPageFactory OHTMLReader::getTypeSelectionPageFactory()
+{
+ return &OWizHTMLExtend::Create;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/misc/RowSetDrop.cxx b/dbaccess/source/ui/misc/RowSetDrop.cxx
new file mode 100644
index 000000000..065fee9ce
--- /dev/null
+++ b/dbaccess/source/ui/misc/RowSetDrop.cxx
@@ -0,0 +1,247 @@
+
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <DExport.hxx>
+#include <TokenWriter.hxx>
+#include <com/sun/star/sdbc/XColumnLocate.hpp>
+#include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp>
+#include <sal/log.hxx>
+#include <osl/diagnose.h>
+#include <core_resource.hxx>
+#include <strings.hrc>
+#include <strings.hxx>
+#include <sqlmessage.hxx>
+#include <com/sun/star/sdbc/XRowUpdate.hpp>
+
+using namespace dbaui;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::util;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::sdb;
+using namespace ::com::sun::star::lang;
+
+// export data
+ORowSetImportExport::ORowSetImportExport(weld::Window* pParent,
+ const Reference< XResultSetUpdate >& xResultSetUpdate,
+ const svx::ODataAccessDescriptor& aDataDescriptor,
+ const Reference< XComponentContext >& rM)
+ : ODatabaseImportExport(aDataDescriptor,rM,nullptr)
+ ,m_xTargetResultSetUpdate(xResultSetUpdate)
+ ,m_xTargetRowUpdate(xResultSetUpdate,UNO_QUERY)
+ ,m_pParent(pParent)
+ ,m_bAlreadyAsked(false)
+{
+ OSL_ENSURE(pParent,"Window can't be null!");
+}
+
+void ORowSetImportExport::initialize()
+{
+ ODatabaseImportExport::initialize();
+ // do namemapping
+ Reference<XColumnLocate> xColumnLocate(m_xResultSet,UNO_QUERY);
+ OSL_ENSURE(xColumnLocate.is(),"The rowset normally should support this");
+
+ m_xTargetResultSetMetaData = Reference<XResultSetMetaDataSupplier>(m_xTargetResultSetUpdate,UNO_QUERY_THROW)->getMetaData();
+ if(!m_xTargetResultSetMetaData.is() || !xColumnLocate.is() || !m_xResultSetMetaData.is() )
+ throw SQLException(DBA_RES(STR_UNEXPECTED_ERROR),*this,"S1000",0,Any());
+
+ sal_Int32 nCount = m_xTargetResultSetMetaData->getColumnCount();
+ m_aColumnMapping.reserve(nCount);
+ m_aColumnTypes.reserve(nCount);
+ for (sal_Int32 i = 1;i <= nCount; ++i)
+ {
+ sal_Int32 nPos = COLUMN_POSITION_NOT_FOUND; // means column is autoincrement or doesn't exist
+ if(!m_xTargetResultSetMetaData->isAutoIncrement(i))
+ {
+ try
+ {
+ OUString sColumnName = m_xTargetResultSetMetaData->getColumnName(i);
+ nPos = xColumnLocate->findColumn(sColumnName);
+ }
+ catch(const SQLException&)
+ {
+ if(m_xTargetResultSetMetaData->isNullable(i))
+ nPos = 0; // column doesn't exist but we could set it to null
+ }
+ }
+
+ m_aColumnMapping.push_back(nPos);
+ if(nPos > 0)
+ m_aColumnTypes.push_back(m_xResultSetMetaData->getColumnType(nPos));
+ else
+ m_aColumnTypes.push_back(DataType::OTHER);
+ }
+}
+
+bool ORowSetImportExport::Write()
+{
+ return true;
+}
+
+bool ORowSetImportExport::Read()
+{
+ // check if there is any column to copy
+ if(std::none_of(m_aColumnMapping.begin(),m_aColumnMapping.end(),
+ [](sal_Int32 n) { return n > 0; }))
+ return false;
+ bool bContinue = true;
+ if(m_aSelection.hasElements())
+ {
+ const Any* pBegin = m_aSelection.getConstArray();
+ const Any* pEnd = pBegin + m_aSelection.getLength();
+ for(;pBegin != pEnd && bContinue;++pBegin)
+ {
+ sal_Int32 nPos = -1;
+ *pBegin >>= nPos;
+ OSL_ENSURE(nPos != -1,"Invalid position!");
+ bContinue = (m_xResultSet.is() && m_xResultSet->absolute(nPos) && insertNewRow());
+ }
+ }
+ else
+ {
+ Reference<XPropertySet> xProp(m_xResultSet,UNO_QUERY);
+ sal_Int32 nRowCount = 0;
+ if ( xProp.is() && xProp->getPropertySetInfo()->hasPropertyByName(PROPERTY_ISROWCOUNTFINAL) )
+ {
+ bool bFinal = false;
+ xProp->getPropertyValue(PROPERTY_ISROWCOUNTFINAL) >>= bFinal;
+ if ( !bFinal )
+ m_xResultSet->afterLast();
+ xProp->getPropertyValue(PROPERTY_ROWCOUNT) >>= nRowCount;
+ }
+ if ( !nRowCount )
+ {
+ m_xResultSet->afterLast();
+ nRowCount = m_xResultSet->getRow();
+ }
+ OSL_ENSURE(nRowCount,"RowCount is 0!");
+ m_xResultSet->beforeFirst();
+ while(m_xResultSet.is() && m_xResultSet->next() && bContinue && nRowCount )
+ {
+ --nRowCount;
+ bContinue = insertNewRow();
+ }
+ }
+ return true;
+}
+
+bool ORowSetImportExport::insertNewRow()
+{
+ try
+ {
+ m_xTargetResultSetUpdate->moveToInsertRow();
+ sal_Int32 i = 1;
+ for (auto const& column : m_aColumnMapping)
+ {
+ if(column > 0)
+ {
+ Any aValue;
+ switch(m_aColumnTypes[i-1])
+ {
+ case DataType::CHAR:
+ case DataType::VARCHAR:
+ aValue <<= m_xRow->getString(column);
+ break;
+ case DataType::DECIMAL:
+ case DataType::NUMERIC:
+ aValue <<= m_xRow->getDouble(column);
+ break;
+ case DataType::BIGINT:
+ aValue <<= m_xRow->getLong(column);
+ break;
+ case DataType::FLOAT:
+ aValue <<= m_xRow->getFloat(column);
+ break;
+ case DataType::DOUBLE:
+ aValue <<= m_xRow->getDouble(column);
+ break;
+ case DataType::LONGVARCHAR:
+ aValue <<= m_xRow->getString(column);
+ break;
+ case DataType::LONGVARBINARY:
+ aValue <<= m_xRow->getBytes(column);
+ break;
+ case DataType::DATE:
+ aValue <<= m_xRow->getDate(column);
+ break;
+ case DataType::TIME:
+ aValue <<= m_xRow->getTime(column);
+ break;
+ case DataType::TIMESTAMP:
+ aValue <<= m_xRow->getTimestamp(column);
+ break;
+ case DataType::BIT:
+ case DataType::BOOLEAN:
+ aValue <<= m_xRow->getBoolean(column);
+ break;
+ case DataType::TINYINT:
+ aValue <<= m_xRow->getByte(column);
+ break;
+ case DataType::SMALLINT:
+ aValue <<= m_xRow->getShort(column);
+ break;
+ case DataType::INTEGER:
+ aValue <<= m_xRow->getInt(column);
+ break;
+ case DataType::REAL:
+ aValue <<= m_xRow->getDouble(column);
+ break;
+ case DataType::BINARY:
+ case DataType::VARBINARY:
+ aValue <<= m_xRow->getBytes(column);
+ break;
+ case DataType::BLOB:
+ aValue <<= m_xRow->getBlob(column);
+ break;
+ case DataType::CLOB:
+ aValue <<= m_xRow->getClob(column);
+ break;
+ default:
+ SAL_WARN("dbaccess.ui", "Unknown type");
+ }
+ if(m_xRow->wasNull())
+ m_xTargetRowUpdate->updateNull(i);
+ else
+ m_xTargetRowUpdate->updateObject(i,aValue);
+ }
+ else if(column == 0)//now we have know that we to set this column to null
+ m_xTargetRowUpdate->updateNull(i);
+ ++i;
+ }
+ m_xTargetResultSetUpdate->insertRow();
+ }
+ catch(const SQLException&)
+ {
+ if(!m_bAlreadyAsked)
+ {
+ OUString sAskIfContinue = DBA_RES(STR_ERROR_OCCURRED_WHILE_COPYING);
+ OSQLWarningBox aDlg(m_pParent, sAskIfContinue, MessBoxStyle::YesNo | MessBoxStyle::DefaultYes);
+ if (aDlg.run() == RET_YES)
+ m_bAlreadyAsked = true;
+ else
+ return false;
+ }
+ }
+ return true;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/misc/RtfReader.cxx b/dbaccess/source/ui/misc/RtfReader.cxx
new file mode 100644
index 000000000..8895d494f
--- /dev/null
+++ b/dbaccess/source/ui/misc/RtfReader.cxx
@@ -0,0 +1,309 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <RtfReader.hxx>
+#include <tools/stream.hxx>
+#include <com/sun/star/sdbcx/XDataDescriptorFactory.hpp>
+#include <com/sun/star/awt/FontDescriptor.hpp>
+#include <com/sun/star/awt/FontWeight.hpp>
+#include <com/sun/star/awt/FontStrikeout.hpp>
+#include <com/sun/star/awt/FontSlant.hpp>
+#include <com/sun/star/awt/FontUnderline.hpp>
+#include <core_resource.hxx>
+#include <svtools/rtftoken.h>
+#include <toolkit/helper/vclunohelper.hxx>
+#include <strings.hrc>
+#include <connectivity/dbtools.hxx>
+#include <comphelper/string.hxx>
+#include <tools/color.hxx>
+#include <WExtendPages.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/settings.hxx>
+
+using namespace dbaui;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::sdbcx;
+using namespace ::com::sun::star::awt;
+
+// ORTFReader
+ORTFReader::ORTFReader( SvStream& rIn,
+ const SharedConnection& _rxConnection,
+ const Reference< css::util::XNumberFormatter >& _rxNumberF,
+ const css::uno::Reference< css::uno::XComponentContext >& _rxContext)
+ :SvRTFParser(rIn)
+ ,ODatabaseExport( _rxConnection, _rxNumberF, _rxContext, rIn )
+{
+ m_bAppendFirstLine = false;
+}
+
+ORTFReader::ORTFReader(SvStream& rIn,
+ sal_Int32 nRows,
+ TPositions&& _rColumnPositions,
+ const Reference< css::util::XNumberFormatter >& _rxNumberF,
+ const css::uno::Reference< css::uno::XComponentContext >& _rxContext,
+ const TColumnVector* pList,
+ const OTypeInfoMap* _pInfoMap,
+ bool _bAutoIncrementEnabled)
+ :SvRTFParser(rIn)
+ ,ODatabaseExport( nRows, std::move(_rColumnPositions), _rxNumberF, _rxContext, pList, _pInfoMap, _bAutoIncrementEnabled, rIn )
+{
+ m_bAppendFirstLine = false;
+}
+
+ORTFReader::~ORTFReader()
+{
+}
+
+SvParserState ORTFReader::CallParser()
+{
+ rInput.Seek(STREAM_SEEK_TO_BEGIN);
+ rInput.ResetError();
+ SvParserState eParseState = SvRTFParser::CallParser();
+ SetColumnTypes(m_pColumnList,m_pInfoMap);
+ return m_bFoundTable ? eParseState : SvParserState::Error;
+}
+
+#if defined _MSC_VER
+#pragma warning(disable: 4702) // unreachable code, bug in MSVC2015
+#endif
+
+void ORTFReader::NextToken( int nToken )
+{
+ if(m_bError || !m_nRows) // if there is an error or no more rows to check, return immediately
+ return;
+
+ if(m_xConnection.is()) // names, which CTOR was called and hence, if a table should be created
+ {
+ switch(nToken)
+ {
+ case RTF_COLORTBL:
+ {
+
+ int nTmpToken2 = GetNextToken();
+ do
+ {
+ Color aColor;
+ do
+ {
+ switch(nTmpToken2)
+ {
+ case RTF_RED: aColor.SetRed(static_cast<sal_uInt8>(nTokenValue)); break;
+ case RTF_BLUE: aColor.SetBlue(static_cast<sal_uInt8>(nTokenValue)); break;
+ case RTF_GREEN: aColor.SetGreen(static_cast<sal_uInt8>(nTokenValue)); break;
+ default: break;
+ }
+ nTmpToken2 = GetNextToken();
+ }
+ while(aToken[0] != ';' && eState != SvParserState::Error && eState != SvParserState::Accepted);
+ m_vecColor.push_back(aColor.GetRGBColor());
+ nTmpToken2 = GetNextToken();
+ }
+ while(nTmpToken2 == RTF_RED && eState != SvParserState::Error && eState != SvParserState::Accepted);
+ SkipToken();
+ }
+ break;
+
+ case RTF_TROWD:
+ {
+ if ( !m_xTable.is() ) // use first line as header
+ {
+ sal_uInt64 const nTell = rInput.Tell(); // perhaps alters position of the stream
+
+ m_bError = !CreateTable(nToken);
+ if ( m_bAppendFirstLine )
+ {
+ rInput.Seek(nTell);
+ rInput.ResetError();
+ }
+ }
+ }
+ break;
+ case RTF_INTBL:
+ if(m_bInTbl)
+ {
+ eraseTokens();
+ }
+
+ m_bInTbl = true; // Now we are in a table description
+ break;
+ case RTF_TEXTTOKEN:
+ case RTF_SINGLECHAR:
+ if(m_bInTbl) // important, as otherwise we also get the names of the fonts
+ m_sTextToken += aToken;
+ break;
+ case RTF_CELL:
+ {
+ try
+ {
+ insertValueIntoColumn();
+ }
+ catch(SQLException& e)
+ // handling update failure
+ {
+ showErrorDialog(e);
+ }
+ m_nColumnPos++;
+ eraseTokens();
+ }
+ break;
+ case RTF_ROW:
+ // it can happen that the last cell is not concluded with \cell
+ try
+ {
+ insertValueIntoColumn();
+ m_nRowCount++;
+ if(m_bIsAutoIncrement) // if bSetAutoIncrement then I have to set the autoincrement
+ m_pUpdateHelper->updateInt(1,m_nRowCount);
+ m_pUpdateHelper->insertRow();
+ }
+ catch(SQLException& e)
+ // handling update failure
+ {
+ showErrorDialog(e);
+ }
+ m_nColumnPos = 0;
+ break;
+ }
+ }
+ else // branch only valid for type checking
+ {
+ switch(nToken)
+ {
+ case RTF_TROWD:
+ // The head of the column is not included
+ if(m_bHead)
+ {
+ do
+ {}
+ while(GetNextToken() != RTF_ROW && eState != SvParserState::Error && eState != SvParserState::Accepted);
+ m_bHead = false;
+ }
+ break;
+ case RTF_INTBL:
+ m_bInTbl = true;
+ break;
+ case RTF_TEXTTOKEN:
+ case RTF_SINGLECHAR:
+ if(m_bInTbl)
+ m_sTextToken += aToken;
+ break;
+ case RTF_CELL:
+ adjustFormat();
+ m_nColumnPos++;
+ break;
+ case RTF_ROW:
+ adjustFormat();
+ m_nColumnPos = 0;
+ m_nRows--;
+ break;
+ }
+ }
+}
+
+bool ORTFReader::CreateTable(int nToken)
+{
+ OUString aTableName(DBA_RES(STR_TBL_TITLE));
+ aTableName = aTableName.getToken(0,' ');
+ aTableName = ::dbtools::createUniqueName(m_xTables, aTableName);
+
+ OUString aColumnName;
+
+ FontDescriptor aFont = VCLUnoHelper::CreateFontDescriptor(Application::GetSettings().GetStyleSettings().GetAppFont());
+ do
+ {
+ switch (nToken)
+ {
+ case RTF_UNKNOWNCONTROL:
+ case RTF_UNKNOWNDATA:
+ m_bInTbl = false;
+ aColumnName.clear();
+ break;
+ case RTF_INTBL:
+ if(m_bInTbl)
+ aColumnName.clear();
+
+ m_bInTbl = true;
+ break;
+ case RTF_TEXTTOKEN:
+ case RTF_SINGLECHAR:
+ if(m_bInTbl)
+ aColumnName += aToken;
+ break;
+ case RTF_CELL:
+ {
+ aColumnName = comphelper::string::strip(aColumnName, ' ');
+ if (aColumnName.isEmpty() || m_bAppendFirstLine )
+ aColumnName = DBA_RES(STR_COLUMN_NAME);
+
+ CreateDefaultColumn(aColumnName);
+ aColumnName.clear();
+ }
+ break;
+ case RTF_CF:
+ break;
+ case RTF_B:
+ aFont.Weight = css::awt::FontWeight::BOLD;
+ break;
+ case RTF_I:
+ aFont.Slant = css::awt::FontSlant_ITALIC;
+ break;
+ case RTF_UL:
+ aFont.Underline = css::awt::FontUnderline::SINGLE;
+ break;
+ case RTF_STRIKE:
+ aFont.Strikeout = css::awt::FontStrikeout::SINGLE;
+ break;
+ }
+ nToken = GetNextToken();
+ }
+ while(nToken != RTF_TROWD && eState != SvParserState::Error && eState != SvParserState::Accepted);
+
+ bool bOk = !m_vDestVector.empty();
+ if(bOk)
+ {
+ if ( !aColumnName.isEmpty() )
+ {
+ if ( m_bAppendFirstLine )
+ aColumnName = DBA_RES(STR_COLUMN_NAME);
+ CreateDefaultColumn(aColumnName);
+ }
+
+ m_bInTbl = false;
+ m_bFoundTable = true;
+
+ if ( isCheckEnabled() )
+ return true;
+ Any aTextColor;
+ if(!m_vecColor.empty())
+ aTextColor <<= m_vecColor[0];
+
+ bOk = !executeWizard(aTableName,aTextColor,aFont) && m_xTable.is();
+ }
+ return bOk;
+}
+
+TypeSelectionPageFactory ORTFReader::getTypeSelectionPageFactory()
+{
+ return &OWizRTFExtend::Create;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/misc/TableCopyHelper.cxx b/dbaccess/source/ui/misc/TableCopyHelper.cxx
new file mode 100644
index 000000000..c855b3b48
--- /dev/null
+++ b/dbaccess/source/ui/misc/TableCopyHelper.cxx
@@ -0,0 +1,306 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <TableCopyHelper.hxx>
+#include <core_resource.hxx>
+#include <strings.hrc>
+#include <strings.hxx>
+#include <dbaccess/genericcontroller.hxx>
+#include <com/sun/star/task/InteractionHandler.hpp>
+#include <com/sun/star/task/XInteractionHandler.hpp>
+#include <com/sun/star/sdb/application/CopyTableOperation.hpp>
+#include <com/sun/star/sdb/application/CopyTableWizard.hpp>
+#include <com/sun/star/sdb/DataAccessDescriptorFactory.hpp>
+#include <com/sun/star/sdb/CommandType.hpp>
+
+#include <TokenWriter.hxx>
+#include <UITools.hxx>
+#include <dbaccess/dataview.hxx>
+#include <svx/dbaexchange.hxx>
+#include <unotools/ucbhelper.hxx>
+#include <tools/urlobj.hxx>
+#include <tools/diagnose_ex.h>
+#include <sal/log.hxx>
+#include <toolkit/helper/vclunohelper.hxx>
+#include <unotools/tempfile.hxx>
+#include <cppuhelper/exc_hlp.hxx>
+
+namespace dbaui
+{
+using namespace ::dbtools;
+using namespace ::svx;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::task;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::sdb;
+using namespace ::com::sun::star::sdb::application;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::sdbcx;
+using namespace ::com::sun::star::ucb;
+
+OTableCopyHelper::OTableCopyHelper(OGenericUnoController* _pController)
+ :m_pController(_pController)
+{
+}
+
+void OTableCopyHelper::insertTable( std::u16string_view i_rSourceDataSource, const Reference<XConnection>& i_rSourceConnection,
+ const OUString& i_rCommand, const sal_Int32 i_nCommandType,
+ const Reference< XResultSet >& i_rSourceRows, const Sequence< Any >& i_rSelection, const bool i_bBookmarkSelection,
+ std::u16string_view i_rDestDataSource, const Reference<XConnection>& i_rDestConnection)
+{
+ if ( CommandType::QUERY != i_nCommandType && CommandType::TABLE != i_nCommandType )
+ {
+ SAL_WARN("dbaccess.ui", "OTableCopyHelper::insertTable: invalid call (no supported format found)!" );
+ return;
+ }
+
+ try
+ {
+ Reference<XConnection> xSrcConnection( i_rSourceConnection );
+ if ( i_rSourceDataSource == i_rDestDataSource )
+ xSrcConnection = i_rDestConnection;
+
+ if ( !xSrcConnection.is() || !i_rDestConnection.is() )
+ {
+ SAL_WARN("dbaccess.ui", "OTableCopyHelper::insertTable: no connection/s!" );
+ return;
+ }
+
+ Reference<XComponentContext> aContext( m_pController->getORB() );
+
+ Reference< XDataAccessDescriptorFactory > xFactory( DataAccessDescriptorFactory::get( aContext ) );
+
+ Reference< XPropertySet > xSource( xFactory->createDataAccessDescriptor(), UNO_SET_THROW );
+ xSource->setPropertyValue( PROPERTY_COMMAND_TYPE, Any( i_nCommandType ) );
+ xSource->setPropertyValue( PROPERTY_COMMAND, Any( i_rCommand ) );
+ xSource->setPropertyValue( PROPERTY_ACTIVE_CONNECTION, Any( xSrcConnection ) );
+ xSource->setPropertyValue( PROPERTY_RESULT_SET, Any( i_rSourceRows ) );
+ xSource->setPropertyValue( PROPERTY_SELECTION, Any( i_rSelection ) );
+ xSource->setPropertyValue( PROPERTY_BOOKMARK_SELECTION, Any( i_bBookmarkSelection ) );
+
+ Reference< XPropertySet > xDest( xFactory->createDataAccessDescriptor(), UNO_SET_THROW );
+ xDest->setPropertyValue( PROPERTY_ACTIVE_CONNECTION, Any( i_rDestConnection ) );
+
+ auto xInteractionHandler = InteractionHandler::createWithParent(aContext, VCLUnoHelper::GetInterface(m_pController->getView()));
+
+ Reference<XCopyTableWizard> xWizard(CopyTableWizard::createWithInteractionHandler(aContext, xSource, xDest, xInteractionHandler), UNO_SET_THROW);
+
+ OUString sTableNameForAppend( GetTableNameForAppend() );
+ xWizard->setDestinationTableName( GetTableNameForAppend() );
+
+ bool bAppendToExisting = !sTableNameForAppend.isEmpty();
+ xWizard->setOperation( bAppendToExisting ? CopyTableOperation::AppendData : CopyTableOperation::CopyDefinitionAndData );
+
+ xWizard->execute();
+ }
+ catch( const SQLException& )
+ {
+ m_pController->showError( SQLExceptionInfo( ::cppu::getCaughtException() ) );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+}
+
+void OTableCopyHelper::pasteTable( const svx::ODataAccessDescriptor& _rPasteData, std::u16string_view i_rDestDataSourceName,
+ const SharedConnection& i_rDestConnection )
+{
+ OUString sSrcDataSourceName = _rPasteData.getDataSource();
+
+ OUString sCommand;
+ _rPasteData[ DataAccessDescriptorProperty::Command ] >>= sCommand;
+
+ Reference<XConnection> xSrcConnection;
+ if ( _rPasteData.has(DataAccessDescriptorProperty::Connection) )
+ {
+ OSL_VERIFY( _rPasteData[DataAccessDescriptorProperty::Connection] >>= xSrcConnection );
+ }
+
+ Reference< XResultSet > xResultSet;
+ if ( _rPasteData.has(DataAccessDescriptorProperty::Cursor) )
+ {
+ OSL_VERIFY( _rPasteData[ DataAccessDescriptorProperty::Cursor ] >>= xResultSet );
+ }
+
+ Sequence< Any > aSelection;
+ if ( _rPasteData.has( DataAccessDescriptorProperty::Selection ) )
+ {
+ OSL_VERIFY( _rPasteData[ DataAccessDescriptorProperty::Selection ] >>= aSelection );
+ OSL_ENSURE( _rPasteData.has( DataAccessDescriptorProperty::BookmarkSelection ), "OTableCopyHelper::pasteTable: you should specify BookmarkSelection, too, to be on the safe side!" );
+ }
+
+ bool bBookmarkSelection( true );
+ if ( _rPasteData.has( DataAccessDescriptorProperty::BookmarkSelection ) )
+ {
+ OSL_VERIFY( _rPasteData[ DataAccessDescriptorProperty::BookmarkSelection ] >>= bBookmarkSelection );
+ }
+ OSL_ENSURE( bBookmarkSelection, "OTableCopyHelper::pasteTable: working with selection-indices (instead of bookmarks) is error-prone, and thus deprecated!" );
+
+ sal_Int32 nCommandType = CommandType::COMMAND;
+ if ( _rPasteData.has(DataAccessDescriptorProperty::CommandType) )
+ _rPasteData[DataAccessDescriptorProperty::CommandType] >>= nCommandType;
+
+ insertTable( sSrcDataSourceName, xSrcConnection, sCommand, nCommandType,
+ xResultSet, aSelection, bBookmarkSelection,
+ i_rDestDataSourceName, i_rDestConnection );
+}
+
+void OTableCopyHelper::pasteTable( SotClipboardFormatId _nFormatId
+ ,const TransferableDataHelper& _rTransData
+ ,std::u16string_view i_rDestDataSource
+ ,const SharedConnection& _xConnection)
+{
+ if ( _nFormatId == SotClipboardFormatId::DBACCESS_TABLE || _nFormatId == SotClipboardFormatId::DBACCESS_QUERY )
+ {
+ if ( ODataAccessObjectTransferable::canExtractObjectDescriptor(_rTransData.GetDataFlavorExVector()) )
+ {
+ svx::ODataAccessDescriptor aPasteData = ODataAccessObjectTransferable::extractObjectDescriptor(_rTransData);
+ pasteTable( aPasteData,i_rDestDataSource,_xConnection);
+ }
+ }
+ else if ( _rTransData.HasFormat(_nFormatId) )
+ {
+ try
+ {
+ DropDescriptor aTrans;
+ bool bOk;
+ if ( _nFormatId != SotClipboardFormatId::RTF )
+ bOk = _rTransData.GetSotStorageStream(SotClipboardFormatId::HTML ,aTrans.aHtmlRtfStorage);
+ else
+ bOk = _rTransData.GetSotStorageStream(SotClipboardFormatId::RTF,aTrans.aHtmlRtfStorage);
+
+ aTrans.nType = E_TABLE;
+ aTrans.bHtml = SotClipboardFormatId::HTML == _nFormatId;
+ aTrans.sDefaultTableName = GetTableNameForAppend();
+ if ( !bOk || !copyTagTable(aTrans,false,_xConnection) )
+ m_pController->showError(SQLException(DBA_RES(STR_NO_TABLE_FORMAT_INSIDE), *m_pController, "S1000", 0, Any()));
+ }
+ catch(const SQLException&)
+ {
+ m_pController->showError( SQLExceptionInfo( ::cppu::getCaughtException() ) );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+ else
+ m_pController->showError(SQLException(DBA_RES(STR_NO_TABLE_FORMAT_INSIDE), *m_pController, "S1000", 0, Any()));
+}
+
+void OTableCopyHelper::pasteTable( const TransferableDataHelper& _rTransData
+ ,std::u16string_view i_rDestDataSource
+ ,const SharedConnection& _xConnection)
+{
+ if ( _rTransData.HasFormat(SotClipboardFormatId::DBACCESS_TABLE) || _rTransData.HasFormat(SotClipboardFormatId::DBACCESS_QUERY) )
+ pasteTable( SotClipboardFormatId::DBACCESS_TABLE,_rTransData,i_rDestDataSource,_xConnection);
+ else if ( _rTransData.HasFormat(SotClipboardFormatId::HTML) )
+ pasteTable( SotClipboardFormatId::HTML,_rTransData,i_rDestDataSource,_xConnection);
+ else if ( _rTransData.HasFormat(SotClipboardFormatId::RTF) )
+ pasteTable( SotClipboardFormatId::RTF,_rTransData,i_rDestDataSource,_xConnection);
+}
+
+bool OTableCopyHelper::copyTagTable(OTableCopyHelper::DropDescriptor const & _rDesc, bool _bCheck, const SharedConnection& _xConnection)
+{
+ rtl::Reference<ODatabaseImportExport> pImport;
+ if ( _rDesc.bHtml )
+ pImport = new OHTMLImportExport(_xConnection,getNumberFormatter(_xConnection, m_pController->getORB()),m_pController->getORB());
+ else
+ pImport = new ORTFImportExport(_xConnection,getNumberFormatter(_xConnection, m_pController->getORB()),m_pController->getORB());
+
+ SvStream* pStream = _rDesc.aHtmlRtfStorage.get();
+ if ( _bCheck )
+ pImport->enableCheckOnly();
+
+ //set the selected tablename
+ pImport->setSTableName(_rDesc.sDefaultTableName);
+
+ pImport->setStream(pStream);
+ return pImport->Read();
+}
+
+bool OTableCopyHelper::isTableFormat(const TransferableDataHelper& _rClipboard)
+{
+ bool bTableFormat = _rClipboard.HasFormat(SotClipboardFormatId::DBACCESS_TABLE)
+ || _rClipboard.HasFormat(SotClipboardFormatId::DBACCESS_QUERY)
+ || _rClipboard.HasFormat(SotClipboardFormatId::RTF)
+ || _rClipboard.HasFormat(SotClipboardFormatId::HTML);
+
+ return bTableFormat;
+}
+
+bool OTableCopyHelper::copyTagTable(const TransferableDataHelper& _aDroppedData
+ ,DropDescriptor& _rAsyncDrop
+ ,const SharedConnection& _xConnection)
+{
+ bool bRet = false;
+ bool bHtml = _aDroppedData.HasFormat(SotClipboardFormatId::HTML);
+ if ( bHtml || _aDroppedData.HasFormat(SotClipboardFormatId::RTF) )
+ {
+ bool bOk;
+ if ( bHtml )
+ bOk = _aDroppedData.GetSotStorageStream(SotClipboardFormatId::HTML ,_rAsyncDrop.aHtmlRtfStorage);
+ else
+ bOk = _aDroppedData.GetSotStorageStream(SotClipboardFormatId::RTF,_rAsyncDrop.aHtmlRtfStorage);
+
+ _rAsyncDrop.bHtml = bHtml;
+ _rAsyncDrop.bError = !copyTagTable(_rAsyncDrop,true,_xConnection);
+
+ bRet = ( !_rAsyncDrop.bError && bOk && _rAsyncDrop.aHtmlRtfStorage.is() );
+ if ( bRet )
+ {
+ // now we need to copy the stream
+ ::utl::TempFile aTmp;
+ _rAsyncDrop.aUrl = aTmp.GetURL();
+ ::tools::SvRef<SotTempStream> aNew = new SotTempStream( aTmp.GetFileName() );
+ _rAsyncDrop.aHtmlRtfStorage->Seek(STREAM_SEEK_TO_BEGIN);
+ _rAsyncDrop.aHtmlRtfStorage->CopyTo( aNew.get() );
+ _rAsyncDrop.aHtmlRtfStorage = aNew;
+ }
+ else
+ _rAsyncDrop.aHtmlRtfStorage = nullptr;
+ }
+ return bRet;
+}
+
+void OTableCopyHelper::asyncCopyTagTable( DropDescriptor& _rDesc
+ ,std::u16string_view i_rDestDataSource
+ ,const SharedConnection& _xConnection)
+{
+ if ( _rDesc.aHtmlRtfStorage.is() )
+ {
+ copyTagTable(_rDesc,false,_xConnection);
+ _rDesc.aHtmlRtfStorage = nullptr;
+ // we now have to delete the temp file created in executeDrop
+ INetURLObject aURL;
+ aURL.SetURL(_rDesc.aUrl);
+ ::utl::UCBContentHelper::Kill(aURL.GetMainURL(INetURLObject::DecodeMechanism::NONE));
+ }
+ else if ( !_rDesc.bError )
+ pasteTable(_rDesc.aDroppedData,i_rDestDataSource,_xConnection);
+ else
+ m_pController->showError(SQLException(DBA_RES(STR_NO_TABLE_FORMAT_INSIDE), *m_pController, "S1000", 0, Any()));
+}
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/misc/TokenWriter.cxx b/dbaccess/source/ui/misc/TokenWriter.cxx
new file mode 100644
index 000000000..974337e8a
--- /dev/null
+++ b/dbaccess/source/ui/misc/TokenWriter.cxx
@@ -0,0 +1,965 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <TokenWriter.hxx>
+#include <tools/diagnose_ex.h>
+#include <tools/stream.hxx>
+#include <osl/diagnose.h>
+#include <rtl/tencinfo.h>
+#include <sal/log.hxx>
+#include <i18nlangtag/languagetag.hxx>
+#include <RtfReader.hxx>
+#include <HtmlReader.hxx>
+#include <strings.hxx>
+#include <comphelper/types.hxx>
+#include <connectivity/dbtools.hxx>
+#include <com/sun/star/sdb/CommandType.hpp>
+#include <com/sun/star/sdb/DatabaseContext.hpp>
+#include <com/sun/star/sdbc/XConnection.hpp>
+#include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
+#include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp>
+#include <com/sun/star/sdbc/XRowSet.hpp>
+#include <com/sun/star/sdbcx/XTablesSupplier.hpp>
+#include <com/sun/star/sdb/XQueriesSupplier.hpp>
+#include <com/sun/star/awt/FontWeight.hpp>
+#include <com/sun/star/awt/FontStrikeout.hpp>
+#include <com/sun/star/awt/FontSlant.hpp>
+#include <com/sun/star/awt/FontUnderline.hpp>
+#include <com/sun/star/document/DocumentProperties.hpp>
+#include <svtools/htmlkywd.hxx>
+#include <svtools/rtfkeywd.hxx>
+#include <tools/color.hxx>
+#include <svtools/htmlout.hxx>
+#include <sfx2/frmhtmlw.hxx>
+#include <svl/numuno.hxx>
+#include <vcl/svapp.hxx>
+#include <UITools.hxx>
+#include <toolkit/helper/vclunohelper.hxx>
+#include <vcl/outdev.hxx>
+#include <vcl/settings.hxx>
+#include <svtools/rtfout.hxx>
+#include <svtools/htmlcfg.hxx>
+#include <o3tl/string_view.hxx>
+#include <connectivity/formattedcolumnvalue.hxx>
+#include <memory>
+
+using namespace dbaui;
+using namespace dbtools;
+using namespace svx;
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::sdb;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::sdbcx;
+using namespace ::com::sun::star::awt;
+using namespace ::com::sun::star::util;
+
+#define CELL_X 1437
+
+ODatabaseImportExport::ODatabaseImportExport(const svx::ODataAccessDescriptor& _aDataDescriptor,
+ const Reference< XComponentContext >& _rM,
+ const Reference< css::util::XNumberFormatter >& _rxNumberF)
+ :m_bBookmarkSelection( false )
+ ,m_pStream(nullptr)
+ ,m_xFormatter(_rxNumberF)
+ ,m_xContext(_rM)
+ ,m_nCommandType(CommandType::TABLE)
+ ,m_bNeedToReInitialize(false)
+ ,m_bInInitialize(false)
+ ,m_bCheckOnly(false)
+{
+ m_eDestEnc = osl_getThreadTextEncoding();
+
+ osl_atomic_increment( &m_refCount );
+ impl_initFromDescriptor( _aDataDescriptor, false );
+ osl_atomic_decrement( &m_refCount );
+}
+
+// import data
+ODatabaseImportExport::ODatabaseImportExport( const ::dbtools::SharedConnection& _rxConnection,
+ const Reference< XNumberFormatter >& _rxNumberF, const Reference< XComponentContext >& _rM )
+ :m_bBookmarkSelection( false )
+ ,m_pStream(nullptr)
+ ,m_xConnection(_rxConnection)
+ ,m_xFormatter(_rxNumberF)
+ ,m_xContext(_rM)
+ ,m_nCommandType(css::sdb::CommandType::TABLE)
+ ,m_bNeedToReInitialize(false)
+ ,m_bInInitialize(false)
+ ,m_bCheckOnly(false)
+{
+ m_eDestEnc = osl_getThreadTextEncoding();
+}
+
+ODatabaseImportExport::~ODatabaseImportExport()
+{
+ acquire();
+ dispose();
+}
+
+void ODatabaseImportExport::dispose()
+{
+ // remove me as listener
+ Reference< XComponent > xComponent(m_xConnection, UNO_QUERY);
+ if (xComponent.is())
+ {
+ Reference< XEventListener> xEvt(this);
+ xComponent->removeEventListener(xEvt);
+ }
+ m_xConnection.clear();
+
+ ::comphelper::disposeComponent(m_xRow);
+
+ m_xObject.clear();
+ m_xResultSetMetaData.clear();
+ m_xResultSet.clear();
+ m_xRow.clear();
+ m_xRowLocate.clear();
+ m_xFormatter.clear();
+}
+
+void SAL_CALL ODatabaseImportExport::disposing( const EventObject& Source )
+{
+ Reference<XConnection> xCon(Source.Source,UNO_QUERY);
+ if(m_xConnection.is() && m_xConnection == xCon)
+ {
+ m_xConnection.clear();
+ dispose();
+ m_bNeedToReInitialize = true;
+ }
+}
+
+void ODatabaseImportExport::initialize( const ODataAccessDescriptor& _aDataDescriptor )
+{
+ impl_initFromDescriptor( _aDataDescriptor, true );
+}
+
+void ODatabaseImportExport::impl_initFromDescriptor( const ODataAccessDescriptor& _aDataDescriptor, bool _bPlusDefaultInit)
+{
+ if ( !_bPlusDefaultInit )
+ {
+ m_sDataSourceName = _aDataDescriptor.getDataSource();
+ _aDataDescriptor[DataAccessDescriptorProperty::CommandType] >>= m_nCommandType;
+ _aDataDescriptor[DataAccessDescriptorProperty::Command] >>= m_sName;
+ // some additional information
+ if(_aDataDescriptor.has(DataAccessDescriptorProperty::Connection))
+ {
+ Reference< XConnection > xPureConn( _aDataDescriptor[DataAccessDescriptorProperty::Connection], UNO_QUERY );
+ m_xConnection.reset( xPureConn, SharedConnection::NoTakeOwnership );
+ Reference< XEventListener> xEvt(this);
+ Reference< XComponent > xComponent(m_xConnection, UNO_QUERY);
+ if (xComponent.is() && xEvt.is())
+ xComponent->addEventListener(xEvt);
+ }
+
+ if ( _aDataDescriptor.has( DataAccessDescriptorProperty::Selection ) )
+ _aDataDescriptor[ DataAccessDescriptorProperty::Selection ] >>= m_aSelection;
+
+ if ( _aDataDescriptor.has( DataAccessDescriptorProperty::BookmarkSelection ) )
+ _aDataDescriptor[ DataAccessDescriptorProperty::BookmarkSelection ] >>= m_bBookmarkSelection;
+
+ if ( _aDataDescriptor.has( DataAccessDescriptorProperty::Cursor ) )
+ {
+ _aDataDescriptor[ DataAccessDescriptorProperty::Cursor ] >>= m_xResultSet;
+ m_xRowLocate.set( m_xResultSet, UNO_QUERY );
+ }
+
+ if ( m_aSelection.hasElements() )
+ {
+ if ( !m_xResultSet.is() )
+ {
+ SAL_WARN("dbaccess.ui", "ODatabaseImportExport::impl_initFromDescriptor: selection without result set is nonsense!" );
+ m_aSelection.realloc( 0 );
+ }
+ }
+
+ if ( m_aSelection.hasElements() )
+ {
+ if ( m_bBookmarkSelection && !m_xRowLocate.is() )
+ {
+ SAL_WARN("dbaccess.ui", "ODatabaseImportExport::impl_initFromDescriptor: no XRowLocate -> no bookmarks!" );
+ m_aSelection.realloc( 0 );
+ }
+ }
+ }
+ else
+ initialize();
+}
+
+void ODatabaseImportExport::initialize()
+{
+ m_bInInitialize = true;
+ m_bNeedToReInitialize = false;
+
+ if ( !m_xConnection.is() )
+ { // we need a connection
+ OSL_ENSURE(!m_sDataSourceName.isEmpty(),"There must be a datsource name!");
+ Reference<XNameAccess> xDatabaseContext( DatabaseContext::create(m_xContext), UNO_QUERY_THROW);
+ Reference< XEventListener> xEvt(this);
+
+ Reference< XConnection > xConnection;
+ SQLExceptionInfo aInfo = ::dbaui::createConnection( m_sDataSourceName, xDatabaseContext, m_xContext, xEvt, xConnection );
+ m_xConnection.reset( xConnection );
+
+ if(aInfo.isValid() && aInfo.getType() == SQLExceptionInfo::TYPE::SQLException)
+ throw *static_cast<const SQLException*>(aInfo);
+ }
+
+ Reference<XNameAccess> xNameAccess;
+ switch(m_nCommandType)
+ {
+ case CommandType::TABLE:
+ {
+ // only for tables
+ Reference<XTablesSupplier> xSup(m_xConnection,UNO_QUERY);
+ if(xSup.is())
+ xNameAccess = xSup->getTables();
+ }
+ break;
+ case CommandType::QUERY:
+ {
+ Reference<XQueriesSupplier> xSup(m_xConnection,UNO_QUERY);
+ if(xSup.is())
+ xNameAccess = xSup->getQueries();
+ }
+ break;
+ }
+ if(xNameAccess.is() && xNameAccess->hasByName(m_sName))
+ {
+ xNameAccess->getByName(m_sName) >>= m_xObject;
+ }
+
+ if(m_xObject.is())
+ {
+ try
+ {
+ if(m_xObject->getPropertySetInfo()->hasPropertyByName(PROPERTY_FONT))
+ m_xObject->getPropertyValue(PROPERTY_FONT) >>= m_aFont;
+
+ // the result set may be already set with the datadescriptor
+ if ( !m_xResultSet.is() )
+ {
+ m_xResultSet.set( m_xContext->getServiceManager()->createInstanceWithContext("com.sun.star.sdb.RowSet", m_xContext), UNO_QUERY );
+ Reference< XPropertySet > xProp( m_xResultSet, UNO_QUERY_THROW );
+ xProp->setPropertyValue( PROPERTY_ACTIVE_CONNECTION, Any( m_xConnection.getTyped() ) );
+ xProp->setPropertyValue( PROPERTY_COMMAND_TYPE, Any( m_nCommandType ) );
+ xProp->setPropertyValue( PROPERTY_COMMAND, Any( m_sName ) );
+ Reference< XRowSet > xRowSet( xProp, UNO_QUERY );
+ xRowSet->execute();
+ }
+ if ( !m_xRow.is() && m_xResultSet.is() )
+ {
+ m_xRow.set( m_xResultSet, UNO_QUERY );
+ m_xRowLocate.set( m_xResultSet, UNO_QUERY );
+ m_xResultSetMetaData = Reference<XResultSetMetaDataSupplier>(m_xRow,UNO_QUERY_THROW)->getMetaData();
+ Reference<XColumnsSupplier> xSup(m_xResultSet,UNO_QUERY_THROW);
+ m_xRowSetColumns.set(xSup->getColumns(),UNO_QUERY_THROW);
+ }
+ }
+ catch(Exception& )
+ {
+ m_xRow = nullptr;
+ m_xResultSetMetaData = nullptr;
+ ::comphelper::disposeComponent(m_xResultSet);
+ throw;
+ }
+ }
+ if ( m_aFont.Name.isEmpty() )
+ {
+ vcl::Font aApplicationFont = OutputDevice::GetDefaultFont(
+ DefaultFontType::SANS_UNICODE,
+ Application::GetSettings().GetUILanguageTag().getLanguageType(),
+ GetDefaultFontFlags::OnlyOne
+ );
+ m_aFont = VCLUnoHelper::CreateFontDescriptor( aApplicationFont );
+ }
+
+ m_bInInitialize = false;
+}
+
+bool ODatabaseImportExport::Write()
+{
+ if ( m_bNeedToReInitialize )
+ {
+ if ( !m_bInInitialize )
+ initialize();
+ }
+ return true;
+}
+
+bool ODatabaseImportExport::Read()
+{
+ if ( m_bNeedToReInitialize )
+ {
+ if ( !m_bInInitialize )
+ initialize();
+ }
+ return true;
+}
+
+bool ORTFImportExport::Write()
+{
+ ODatabaseImportExport::Write();
+ m_pStream->WriteChar( '{' ).WriteCharPtr( OOO_STRING_SVTOOLS_RTF_RTF );
+ m_pStream->WriteCharPtr(OOO_STRING_SVTOOLS_RTF_ANSI);
+ if (sal_uInt32 nCpg = rtl_getWindowsCodePageFromTextEncoding(m_eDestEnc); nCpg && nCpg != 65001)
+ {
+ m_pStream->WriteCharPtr(OOO_STRING_SVTOOLS_RTF_ANSICPG).WriteUInt32AsString(nCpg);
+ }
+ m_pStream->WriteCharPtr(SAL_NEWLINE_STRING);
+
+ bool bBold = ( css::awt::FontWeight::BOLD == m_aFont.Weight );
+ bool bItalic = ( css::awt::FontSlant_ITALIC == m_aFont.Slant );
+ bool bUnderline = ( css::awt::FontUnderline::NONE != m_aFont.Underline );
+ bool bStrikeout = ( css::awt::FontStrikeout::NONE != m_aFont.Strikeout );
+
+ ::Color aColor;
+ if(m_xObject.is())
+ m_xObject->getPropertyValue(PROPERTY_TEXTCOLOR) >>= aColor;
+
+ OString aFonts(OUStringToOString(m_aFont.Name, RTL_TEXTENCODING_MS_1252));
+ if (aFonts.isEmpty())
+ {
+ OUString aName = Application::GetSettings().GetStyleSettings().GetAppFont().GetFamilyName();
+ aFonts = OUStringToOString(aName, RTL_TEXTENCODING_MS_1252);
+ }
+
+ m_pStream->WriteCharPtr( "{\\fonttbl" );
+ if (!aFonts.isEmpty())
+ {
+ sal_Int32 nIdx{0};
+ sal_Int32 nTok{-1}; // to compensate pre-increment
+ do {
+ m_pStream->WriteCharPtr( "\\f" );
+ m_pStream->WriteInt32AsString(++nTok);
+ m_pStream->WriteCharPtr( "\\fcharset0\\fnil " );
+ m_pStream->WriteOString( o3tl::getToken(aFonts, 0, ';', nIdx) );
+ m_pStream->WriteChar( ';' );
+ } while (nIdx>=0);
+ }
+ m_pStream->WriteChar( '}' ) ;
+ m_pStream->WriteCharPtr( SAL_NEWLINE_STRING );
+ // write the rtf color table
+ m_pStream->WriteChar( '{' ).WriteCharPtr( OOO_STRING_SVTOOLS_RTF_COLORTBL ).WriteCharPtr( OOO_STRING_SVTOOLS_RTF_RED );
+ m_pStream->WriteUInt32AsString(aColor.GetRed());
+ m_pStream->WriteCharPtr( OOO_STRING_SVTOOLS_RTF_GREEN );
+ m_pStream->WriteUInt32AsString(aColor.GetGreen());
+ m_pStream->WriteCharPtr( OOO_STRING_SVTOOLS_RTF_BLUE );
+ m_pStream->WriteUInt32AsString(aColor.GetBlue());
+
+ m_pStream->WriteCharPtr( ";\\red255\\green255\\blue255;\\red192\\green192\\blue192;}" )
+ .WriteCharPtr( SAL_NEWLINE_STRING );
+
+ static char const aCell1[] = "\\clbrdrl\\brdrs\\brdrcf0\\clbrdrt\\brdrs\\brdrcf0\\clbrdrb\\brdrs\\brdrcf0\\clbrdrr\\brdrs\\brdrcf0\\clshdng10000\\clcfpat2\\cellx";
+
+ m_pStream->WriteCharPtr( OOO_STRING_SVTOOLS_RTF_TROWD ).WriteCharPtr( OOO_STRING_SVTOOLS_RTF_TRGAPH );
+ m_pStream->WriteInt32AsString(40);
+ m_pStream->WriteCharPtr( SAL_NEWLINE_STRING );
+
+ if(m_xObject.is())
+ {
+ Reference<XColumnsSupplier> xColSup(m_xObject,UNO_QUERY);
+ Reference<XNameAccess> xColumns = xColSup->getColumns();
+ Sequence< OUString> aNames(xColumns->getElementNames());
+ const OUString* pIter = aNames.getConstArray();
+
+ sal_Int32 nCount = aNames.getLength();
+ bool bUseResultMetaData = false;
+ if ( !nCount )
+ {
+ nCount = m_xResultSetMetaData->getColumnCount();
+ bUseResultMetaData = true;
+ }
+
+ for( sal_Int32 i=1; i<=nCount; ++i )
+ {
+ m_pStream->WriteCharPtr( aCell1 );
+ m_pStream->WriteInt32AsString(i*CELL_X);
+ m_pStream->WriteCharPtr( SAL_NEWLINE_STRING );
+ }
+
+ // column description
+ m_pStream->WriteChar( '{' ).WriteCharPtr( SAL_NEWLINE_STRING );
+ m_pStream->WriteCharPtr( "\\trrh-270\\pard\\intbl" );
+
+ std::unique_ptr<OString[]> pHorzChar(new OString[nCount]);
+
+ for ( sal_Int32 i=1; i <= nCount; ++i )
+ {
+ sal_Int32 nAlign = 0;
+ OUString sColumnName;
+ if ( bUseResultMetaData )
+ sColumnName = m_xResultSetMetaData->getColumnName(i);
+ else
+ {
+ sColumnName = *pIter;
+ Reference<XPropertySet> xColumn;
+ xColumns->getByName(sColumnName) >>= xColumn;
+ xColumn->getPropertyValue(PROPERTY_ALIGN) >>= nAlign;
+ ++pIter;
+ }
+
+ const char* pChar;
+ switch( nAlign )
+ {
+ case 1: pChar = OOO_STRING_SVTOOLS_RTF_QC; break;
+ case 2: pChar = OOO_STRING_SVTOOLS_RTF_QR; break;
+ case 0:
+ default:pChar = OOO_STRING_SVTOOLS_RTF_QL; break;
+ }
+
+ pHorzChar[i-1] = pChar; // to avoid to always rummage in the ITEMSET later on
+
+ m_pStream->WriteCharPtr( SAL_NEWLINE_STRING );
+ m_pStream->WriteChar( '{' );
+ m_pStream->WriteCharPtr( OOO_STRING_SVTOOLS_RTF_QC ); // column header always centered
+
+ if ( bBold ) m_pStream->WriteCharPtr( OOO_STRING_SVTOOLS_RTF_B );
+ if ( bItalic ) m_pStream->WriteCharPtr( OOO_STRING_SVTOOLS_RTF_I );
+ if ( bUnderline ) m_pStream->WriteCharPtr( OOO_STRING_SVTOOLS_RTF_UL );
+ if ( bStrikeout ) m_pStream->WriteCharPtr( OOO_STRING_SVTOOLS_RTF_STRIKE );
+
+ m_pStream->WriteCharPtr( "\\fs20\\f0\\cf0\\cb2" );
+ m_pStream->WriteChar( ' ' );
+ RTFOutFuncs::Out_String(*m_pStream, sColumnName, m_eDestEnc);
+
+ m_pStream->WriteCharPtr( OOO_STRING_SVTOOLS_RTF_CELL );
+ m_pStream->WriteChar( '}' );
+ m_pStream->WriteCharPtr( SAL_NEWLINE_STRING );
+ m_pStream->WriteCharPtr( OOO_STRING_SVTOOLS_RTF_PARD ).WriteCharPtr( OOO_STRING_SVTOOLS_RTF_INTBL );
+ }
+
+ m_pStream->WriteCharPtr( OOO_STRING_SVTOOLS_RTF_ROW );
+ m_pStream->WriteCharPtr( SAL_NEWLINE_STRING ).WriteChar( '}' );
+ m_pStream->WriteCharPtr( SAL_NEWLINE_STRING );
+
+ sal_Int32 k=1;
+ sal_Int32 kk=0;
+ if ( m_aSelection.hasElements() )
+ {
+ const Any* pSelIter = m_aSelection.getConstArray();
+ const Any* pEnd = pSelIter + m_aSelection.getLength();
+
+ bool bContinue = true;
+ for( ; pSelIter != pEnd && bContinue; ++pSelIter )
+ {
+ if ( m_bBookmarkSelection )
+ {
+ bContinue = m_xRowLocate->moveToBookmark( *pSelIter );
+ }
+ else
+ {
+ sal_Int32 nPos = -1;
+ OSL_VERIFY( *pSelIter >>= nPos );
+ bContinue = ( m_xResultSet->absolute( nPos ) );
+ }
+
+ if ( bContinue )
+ appendRow( pHorzChar.get(), nCount, k, kk );
+ }
+ }
+ else
+ {
+ m_xResultSet->beforeFirst(); // set back before the first row
+ while(m_xResultSet->next())
+ {
+ appendRow(pHorzChar.get(),nCount,k,kk);
+ }
+ }
+ }
+
+ m_pStream->WriteChar( '}' ).WriteCharPtr( SAL_NEWLINE_STRING );
+ m_pStream->WriteUChar( 0 );
+ return ((*m_pStream).GetError() == ERRCODE_NONE);
+}
+
+void ORTFImportExport::appendRow(OString const * pHorzChar,sal_Int32 _nColumnCount,sal_Int32& k,sal_Int32& kk)
+{
+ ++kk;
+ m_pStream->WriteCharPtr( OOO_STRING_SVTOOLS_RTF_TROWD ).WriteCharPtr( OOO_STRING_SVTOOLS_RTF_TRGAPH );
+ m_pStream->WriteInt32AsString(40);
+ m_pStream->WriteCharPtr( SAL_NEWLINE_STRING );
+
+ static char const aCell2[] = "\\clbrdrl\\brdrs\\brdrcf2\\clbrdrt\\brdrs\\brdrcf2\\clbrdrb\\brdrs\\brdrcf2\\clbrdrr\\brdrs\\brdrcf2\\clshdng10000\\clcfpat1\\cellx";
+
+ for ( sal_Int32 i=1; i<=_nColumnCount; ++i )
+ {
+ m_pStream->WriteCharPtr( aCell2 );
+ m_pStream->WriteInt32AsString(i*CELL_X);
+ m_pStream->WriteCharPtr( SAL_NEWLINE_STRING );
+ }
+
+ const bool bBold = ( css::awt::FontWeight::BOLD == m_aFont.Weight );
+ const bool bItalic = ( css::awt::FontSlant_ITALIC == m_aFont.Slant );
+ const bool bUnderline = ( css::awt::FontUnderline::NONE != m_aFont.Underline );
+ const bool bStrikeout = ( css::awt::FontStrikeout::NONE != m_aFont.Strikeout );
+ Reference< XRowSet > xRowSet(m_xRow,UNO_QUERY);
+
+ m_pStream->WriteChar( '{' );
+ m_pStream->WriteCharPtr( "\\trrh-270\\pard\\intbl" );
+ for ( sal_Int32 i=1; i <= _nColumnCount; ++i )
+ {
+ m_pStream->WriteCharPtr( SAL_NEWLINE_STRING );
+ m_pStream->WriteChar( '{' );
+ m_pStream->WriteOString( pHorzChar[i-1] );
+
+ if ( bBold ) m_pStream->WriteCharPtr( OOO_STRING_SVTOOLS_RTF_B );
+ if ( bItalic ) m_pStream->WriteCharPtr( OOO_STRING_SVTOOLS_RTF_I );
+ if ( bUnderline ) m_pStream->WriteCharPtr( OOO_STRING_SVTOOLS_RTF_UL );
+ if ( bStrikeout ) m_pStream->WriteCharPtr( OOO_STRING_SVTOOLS_RTF_STRIKE );
+
+ m_pStream->WriteCharPtr( "\\fs20\\f1\\cf0\\cb1 " );
+
+ try
+ {
+ Reference<XPropertySet> xColumn(m_xRowSetColumns->getByIndex(i-1),UNO_QUERY_THROW);
+ dbtools::FormattedColumnValue aFormatedValue(m_xContext,xRowSet,xColumn);
+ OUString sValue = aFormatedValue.getFormattedValue();
+ if ( !sValue.isEmpty() )
+ RTFOutFuncs::Out_String(*m_pStream,sValue,m_eDestEnc);
+ }
+ catch (Exception&)
+ {
+ SAL_WARN("dbaccess.ui","RTF WRITE!");
+ }
+
+ m_pStream->WriteCharPtr( OOO_STRING_SVTOOLS_RTF_CELL );
+ m_pStream->WriteChar( '}' );
+ m_pStream->WriteCharPtr( SAL_NEWLINE_STRING );
+ m_pStream->WriteCharPtr( OOO_STRING_SVTOOLS_RTF_PARD ).WriteCharPtr( OOO_STRING_SVTOOLS_RTF_INTBL );
+ }
+ m_pStream->WriteCharPtr( OOO_STRING_SVTOOLS_RTF_ROW ).WriteCharPtr( SAL_NEWLINE_STRING );
+ m_pStream->WriteChar( '}' );
+ ++k;
+}
+
+bool ORTFImportExport::Read()
+{
+ ODatabaseImportExport::Read();
+ SvParserState eState = SvParserState::Error;
+ if ( m_pStream )
+ {
+ tools::SvRef<ORTFReader> xReader(new ORTFReader((*m_pStream),m_xConnection,m_xFormatter,m_xContext));
+ if ( isCheckEnabled() )
+ xReader->enableCheckOnly();
+ eState = xReader->CallParser();
+ }
+
+ return eState != SvParserState::Error;
+}
+
+const sal_Int16 OHTMLImportExport::nCellSpacing = 0;
+const char OHTMLImportExport::sIndentSource[nIndentMax+1] = "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t";
+
+OHTMLImportExport::OHTMLImportExport(const svx::ODataAccessDescriptor& _aDataDescriptor,
+ const Reference< XComponentContext >& _rM,
+ const Reference< css::util::XNumberFormatter >& _rxNumberF)
+ : ODatabaseImportExport(_aDataDescriptor,_rM,_rxNumberF)
+ ,m_nIndent(0)
+#if OSL_DEBUG_LEVEL > 0
+ ,m_bCheckFont(false)
+#endif
+{
+ // set HTML configuration
+ m_eDestEnc = RTL_TEXTENCODING_UTF8;
+ strncpy( sIndent, sIndentSource ,std::min(sizeof(sIndent),sizeof(sIndentSource)));
+ sIndent[0] = 0;
+}
+
+bool OHTMLImportExport::Write()
+{
+ ODatabaseImportExport::Write();
+ if(m_xObject.is())
+ {
+ m_pStream->WriteChar( '<' ).WriteCharPtr( OOO_STRING_SVTOOLS_HTML_doctype ).WriteChar( ' ' ).WriteCharPtr( OOO_STRING_SVTOOLS_HTML_doctype5 ).WriteChar( '>' ).WriteCharPtr( SAL_NEWLINE_STRING ).WriteCharPtr( SAL_NEWLINE_STRING );
+ HTMLOutFuncs::Out_AsciiTag(*m_pStream, OOO_STRING_SVTOOLS_HTML_html).WriteCharPtr(SAL_NEWLINE_STRING).WriteCharPtr(GetIndentStr());
+ WriteHeader();
+ m_pStream->WriteCharPtr(SAL_NEWLINE_STRING).WriteCharPtr(GetIndentStr());
+ WriteBody();
+ m_pStream->WriteCharPtr(SAL_NEWLINE_STRING).WriteCharPtr(GetIndentStr());
+ HTMLOutFuncs::Out_AsciiTag(*m_pStream, OOO_STRING_SVTOOLS_HTML_html, false).WriteCharPtr(SAL_NEWLINE_STRING).WriteCharPtr(GetIndentStr());
+
+ return ((*m_pStream).GetError() == ERRCODE_NONE);
+ }
+ return false;
+}
+
+bool OHTMLImportExport::Read()
+{
+ ODatabaseImportExport::Read();
+ SvParserState eState = SvParserState::Error;
+ if ( m_pStream )
+ {
+ tools::SvRef<OHTMLReader> xReader(new OHTMLReader((*m_pStream),m_xConnection,m_xFormatter,m_xContext));
+ if ( isCheckEnabled() )
+ xReader->enableCheckOnly();
+ xReader->SetTableName(m_sDefaultTableName);
+ eState = xReader->CallParser();
+ }
+
+ return eState != SvParserState::Error;
+}
+
+void OHTMLImportExport::WriteHeader()
+{
+ uno::Reference<document::XDocumentProperties> xDocProps(
+ document::DocumentProperties::create( m_xContext ) );
+ if (xDocProps.is()) {
+ xDocProps->setTitle(m_sName);
+ }
+
+ IncIndent(1);
+ HTMLOutFuncs::Out_AsciiTag(*m_pStream, OOO_STRING_SVTOOLS_HTML_head).WriteCharPtr(SAL_NEWLINE_STRING).WriteCharPtr(GetIndentStr());
+
+ SfxFrameHTMLWriter::Out_DocInfo( (*m_pStream), OUString(),
+ xDocProps, sIndent );
+ m_pStream->WriteCharPtr(SAL_NEWLINE_STRING).WriteCharPtr(GetIndentStr());
+ IncIndent(-1);
+ m_pStream->WriteCharPtr(SAL_NEWLINE_STRING).WriteCharPtr(GetIndentStr());
+ HTMLOutFuncs::Out_AsciiTag(*m_pStream, OOO_STRING_SVTOOLS_HTML_head, false).WriteCharPtr(SAL_NEWLINE_STRING).WriteCharPtr(GetIndentStr());
+}
+
+void OHTMLImportExport::WriteBody()
+{
+ IncIndent(1);
+ m_pStream->WriteCharPtr( "<" ).WriteCharPtr( OOO_STRING_SVTOOLS_HTML_style ).WriteCharPtr( " " ).WriteCharPtr( OOO_STRING_SVTOOLS_HTML_O_type ).WriteCharPtr( "=\"text/css\">" );
+
+ m_pStream->WriteCharPtr( "<!-- " );
+ m_pStream->WriteCharPtr(SAL_NEWLINE_STRING).WriteCharPtr(GetIndentStr());
+ m_pStream->WriteCharPtr( OOO_STRING_SVTOOLS_HTML_body ).WriteCharPtr( " { " ).WriteCharPtr( "font-family: " ).WriteChar( '"' ).WriteOString( OUStringToOString(m_aFont.Name, osl_getThreadTextEncoding()) ).WriteChar( '\"' );
+ // TODO : think about the encoding of the font name
+ m_pStream->WriteCharPtr( "; " ).WriteCharPtr( "font-size: " );
+ m_pStream->WriteInt32AsString(m_aFont.Height);
+ m_pStream->WriteChar( '}' );
+
+ m_pStream->WriteCharPtr(SAL_NEWLINE_STRING).WriteCharPtr(GetIndentStr());
+ m_pStream->WriteCharPtr( " -->" );
+ IncIndent(-1);
+ m_pStream->WriteCharPtr(SAL_NEWLINE_STRING).WriteCharPtr(GetIndentStr());
+ HTMLOutFuncs::Out_AsciiTag(*m_pStream, OOO_STRING_SVTOOLS_HTML_style, false).WriteCharPtr(SAL_NEWLINE_STRING).WriteCharPtr(GetIndentStr());
+ m_pStream->WriteCharPtr(SAL_NEWLINE_STRING).WriteCharPtr(GetIndentStr());
+
+ // default Textcolour black
+ m_pStream->WriteChar( '<' ).WriteCharPtr( OOO_STRING_SVTOOLS_HTML_body ).WriteChar( ' ' ).WriteCharPtr( OOO_STRING_SVTOOLS_HTML_O_text ).WriteChar( '=' );
+ ::Color aColor;
+ if(m_xObject.is())
+ m_xObject->getPropertyValue(PROPERTY_TEXTCOLOR) >>= aColor;
+ HTMLOutFuncs::Out_Color( (*m_pStream), aColor );
+
+ m_pStream->WriteCharPtr( " " OOO_STRING_SVTOOLS_HTML_O_bgcolor "=" );
+ HTMLOutFuncs::Out_Color( (*m_pStream), aColor );
+
+ m_pStream->WriteChar( '>' );
+ m_pStream->WriteCharPtr(SAL_NEWLINE_STRING).WriteCharPtr(GetIndentStr());
+
+ WriteTables();
+
+ HTMLOutFuncs::Out_AsciiTag(*m_pStream, OOO_STRING_SVTOOLS_HTML_body, false).WriteCharPtr(SAL_NEWLINE_STRING).WriteCharPtr(GetIndentStr());
+}
+
+void OHTMLImportExport::WriteTables()
+{
+ OString aStrOut = OOO_STRING_SVTOOLS_HTML_table
+ " "
+ OOO_STRING_SVTOOLS_HTML_frame
+ "="
+ OOO_STRING_SVTOOLS_HTML_TF_void;
+
+ Sequence< OUString> aNames;
+ Reference<XNameAccess> xColumns;
+ bool bUseResultMetaData = false;
+ if(m_xObject.is())
+ {
+ Reference<XColumnsSupplier> xColSup(m_xObject,UNO_QUERY);
+ xColumns = xColSup->getColumns();
+ aNames = xColumns->getElementNames();
+ if ( !aNames.hasElements() )
+ {
+ sal_Int32 nCount = m_xResultSetMetaData->getColumnCount();
+ aNames.realloc(nCount);
+ auto aNamesRange = asNonConstRange(aNames);
+ for (sal_Int32 i= 0; i < nCount; ++i)
+ aNamesRange[i] = m_xResultSetMetaData->getColumnName(i+1);
+ bUseResultMetaData = true;
+ }
+ }
+
+ aStrOut += " "
+ OOO_STRING_SVTOOLS_HTML_O_align
+ "="
+ OOO_STRING_SVTOOLS_HTML_AL_left
+ " "
+ OOO_STRING_SVTOOLS_HTML_O_cellspacing
+ "=" +
+ OString::number(nCellSpacing) +
+ " "
+ OOO_STRING_SVTOOLS_HTML_O_cols
+ "=" +
+ OString::number(aNames.getLength()) +
+ " "
+ OOO_STRING_SVTOOLS_HTML_O_border
+ "=1";
+
+ IncIndent(1);
+ HTMLOutFuncs::Out_AsciiTag(*m_pStream, aStrOut.getStr());
+
+ FontOn();
+
+ HTMLOutFuncs::Out_AsciiTag(*m_pStream, OOO_STRING_SVTOOLS_HTML_caption);
+ HTMLOutFuncs::Out_AsciiTag(*m_pStream, OOO_STRING_SVTOOLS_HTML_bold);
+
+ m_pStream->WriteOString( OUStringToOString(m_sName, osl_getThreadTextEncoding()) );
+ // TODO : think about the encoding of the name
+ HTMLOutFuncs::Out_AsciiTag(*m_pStream, OOO_STRING_SVTOOLS_HTML_bold, false);
+ HTMLOutFuncs::Out_AsciiTag(*m_pStream, OOO_STRING_SVTOOLS_HTML_caption, false);
+
+ FontOff();
+ m_pStream->WriteCharPtr(SAL_NEWLINE_STRING).WriteCharPtr(GetIndentStr());
+ // </FONT>
+
+ IncIndent(1);
+ HTMLOutFuncs::Out_AsciiTag(*m_pStream, OOO_STRING_SVTOOLS_HTML_thead).WriteCharPtr(SAL_NEWLINE_STRING).WriteCharPtr(GetIndentStr());
+
+ IncIndent(1);
+ HTMLOutFuncs::Out_AsciiTag(*m_pStream, OOO_STRING_SVTOOLS_HTML_tablerow).WriteCharPtr(SAL_NEWLINE_STRING).WriteCharPtr(GetIndentStr());
+
+ if(m_xObject.is())
+ {
+ std::unique_ptr<sal_Int32[]> pFormat(new sal_Int32[aNames.getLength()]);
+
+ std::unique_ptr<const char *[]> pHorJustify(new const char*[aNames.getLength()]);
+ std::unique_ptr<sal_Int32[]> pColWidth(new sal_Int32[aNames.getLength()]);
+
+ sal_Int32 nHeight = 0;
+ m_xObject->getPropertyValue(PROPERTY_ROW_HEIGHT) >>= nHeight;
+
+ // 1. writing the column description
+ const OUString* pIter = aNames.getConstArray();
+ const OUString* pEnd = pIter + aNames.getLength();
+
+ for( sal_Int32 i=0;pIter != pEnd; ++pIter,++i )
+ {
+ sal_Int32 nAlign = 0;
+ pFormat[i] = 0;
+ pColWidth[i] = 100;
+ if ( !bUseResultMetaData )
+ {
+ Reference<XPropertySet> xColumn;
+ xColumns->getByName(*pIter) >>= xColumn;
+ xColumn->getPropertyValue(PROPERTY_ALIGN) >>= nAlign;
+ pFormat[i] = ::comphelper::getINT32(xColumn->getPropertyValue(PROPERTY_FORMATKEY));
+ pColWidth[i] = ::comphelper::getINT32(xColumn->getPropertyValue(PROPERTY_WIDTH));
+ }
+
+ switch( nAlign )
+ {
+ case 1: pHorJustify[i] = OOO_STRING_SVTOOLS_HTML_AL_center; break;
+ case 2: pHorJustify[i] = OOO_STRING_SVTOOLS_HTML_AL_right; break;
+ default: pHorJustify[i] = OOO_STRING_SVTOOLS_HTML_AL_left; break;
+ }
+
+ if(i == aNames.getLength()-1)
+ IncIndent(-1);
+
+ WriteCell(pFormat[i],pColWidth[i],nHeight,pHorJustify[i],*pIter,OOO_STRING_SVTOOLS_HTML_tableheader);
+ }
+
+ IncIndent(-1);
+ HTMLOutFuncs::Out_AsciiTag(*m_pStream, OOO_STRING_SVTOOLS_HTML_tablerow, false).WriteCharPtr(SAL_NEWLINE_STRING).WriteCharPtr(GetIndentStr());
+ HTMLOutFuncs::Out_AsciiTag(*m_pStream, OOO_STRING_SVTOOLS_HTML_thead, false).WriteCharPtr(SAL_NEWLINE_STRING).WriteCharPtr(GetIndentStr());
+
+ IncIndent(1);
+ HTMLOutFuncs::Out_AsciiTag(*m_pStream, OOO_STRING_SVTOOLS_HTML_tbody).WriteCharPtr(SAL_NEWLINE_STRING).WriteCharPtr(GetIndentStr());
+
+ // 2. and now the data
+ Reference< XRowSet > xRowSet(m_xRow,UNO_QUERY);
+ m_xResultSet->beforeFirst(); // set back before the first row
+ while(m_xResultSet->next())
+ {
+ IncIndent(1);
+ HTMLOutFuncs::Out_AsciiTag(*m_pStream, OOO_STRING_SVTOOLS_HTML_tablerow).WriteCharPtr(SAL_NEWLINE_STRING).WriteCharPtr(GetIndentStr());
+
+ for(sal_Int32 i=1;i<=aNames.getLength();++i)
+ {
+ if(i == aNames.getLength())
+ IncIndent(-1);
+
+ OUString aValue;
+ try
+ {
+ Reference<XPropertySet> xColumn(m_xRowSetColumns->getByIndex(i-1),UNO_QUERY_THROW);
+ dbtools::FormattedColumnValue aFormatedValue(m_xContext,xRowSet,xColumn);
+ OUString sValue = aFormatedValue.getFormattedValue();
+ if (!sValue.isEmpty())
+ {
+ aValue = sValue;
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ WriteCell(pFormat[i-1],pColWidth[i-1],nHeight,pHorJustify[i-1],aValue,OOO_STRING_SVTOOLS_HTML_tabledata);
+ }
+ HTMLOutFuncs::Out_AsciiTag(*m_pStream, OOO_STRING_SVTOOLS_HTML_tablerow, false).WriteCharPtr(SAL_NEWLINE_STRING).WriteCharPtr(GetIndentStr());
+ }
+ }
+ else
+ {
+ IncIndent(-1);
+ HTMLOutFuncs::Out_AsciiTag(*m_pStream, OOO_STRING_SVTOOLS_HTML_tablerow, false).WriteCharPtr(SAL_NEWLINE_STRING).WriteCharPtr(GetIndentStr());
+ HTMLOutFuncs::Out_AsciiTag(*m_pStream, OOO_STRING_SVTOOLS_HTML_thead, false).WriteCharPtr(SAL_NEWLINE_STRING).WriteCharPtr(GetIndentStr());
+
+ IncIndent(1);
+ HTMLOutFuncs::Out_AsciiTag(*m_pStream, OOO_STRING_SVTOOLS_HTML_tbody).WriteCharPtr(SAL_NEWLINE_STRING).WriteCharPtr(GetIndentStr());
+ }
+
+ IncIndent(-1);
+ m_pStream->WriteCharPtr(SAL_NEWLINE_STRING).WriteCharPtr(GetIndentStr());
+ HTMLOutFuncs::Out_AsciiTag(*m_pStream, OOO_STRING_SVTOOLS_HTML_tbody, false).WriteCharPtr(SAL_NEWLINE_STRING).WriteCharPtr(GetIndentStr());
+ IncIndent(-1);
+ HTMLOutFuncs::Out_AsciiTag(*m_pStream, OOO_STRING_SVTOOLS_HTML_table, false).WriteCharPtr(SAL_NEWLINE_STRING).WriteCharPtr(GetIndentStr());
+}
+
+void OHTMLImportExport::WriteCell( sal_Int32 nFormat, sal_Int32 nWidthPixel, sal_Int32 nHeightPixel, const char* pChar,
+ const OUString& rValue, const char* pHtmlTag)
+{
+ OString aStrTD = pHtmlTag;
+
+ nWidthPixel = nWidthPixel ? nWidthPixel : 86;
+ nHeightPixel = nHeightPixel ? nHeightPixel : 17;
+
+ // despite the <TABLE COLS=n> and <COL WIDTH=x> designation necessary,
+ // as Netscape is not paying attention to them.
+ // column width
+ aStrTD += " "
+ OOO_STRING_SVTOOLS_HTML_O_width
+ "=" +
+ OString::number(nWidthPixel) +
+ // line height
+ " "
+ OOO_STRING_SVTOOLS_HTML_O_height
+ "=" +
+ OString::number(nHeightPixel) +
+ " "
+ OOO_STRING_SVTOOLS_HTML_O_align
+ "=" +
+ pChar;
+
+ SvNumberFormatsSupplierObj* pSupplierImpl = m_xFormatter.is() ? comphelper::getFromUnoTunnel<SvNumberFormatsSupplierObj>(m_xFormatter->getNumberFormatsSupplier()) : nullptr;
+ SvNumberFormatter* pFormatter = pSupplierImpl ? pSupplierImpl->GetNumberFormatter() : nullptr;
+ if(pFormatter)
+ {
+ double fVal = 0.0;
+
+ try
+ {
+ fVal = m_xFormatter->convertStringToNumber(nFormat,rValue);
+ HTMLOutFuncs::CreateTableDataOptionsValNum(false, fVal,nFormat, *pFormatter);
+ }
+ catch(const Exception&)
+ {
+ HTMLOutFuncs::CreateTableDataOptionsValNum(false, fVal,nFormat, *pFormatter);
+ }
+ }
+
+ HTMLOutFuncs::Out_AsciiTag(*m_pStream, aStrTD.getStr());
+
+ FontOn();
+
+ bool bBold = ( css::awt::FontWeight::BOLD == m_aFont.Weight );
+ bool bItalic = ( css::awt::FontSlant_ITALIC == m_aFont.Slant );
+ bool bUnderline = ( css::awt::FontUnderline::NONE != m_aFont.Underline );
+ bool bStrikeout = ( css::awt::FontStrikeout::NONE != m_aFont.Strikeout );
+
+ if ( bBold ) HTMLOutFuncs::Out_AsciiTag(*m_pStream, OOO_STRING_SVTOOLS_HTML_bold);
+ if ( bItalic ) HTMLOutFuncs::Out_AsciiTag(*m_pStream, OOO_STRING_SVTOOLS_HTML_italic);
+ if ( bUnderline ) HTMLOutFuncs::Out_AsciiTag(*m_pStream, OOO_STRING_SVTOOLS_HTML_underline);
+ if ( bStrikeout ) HTMLOutFuncs::Out_AsciiTag(*m_pStream, OOO_STRING_SVTOOLS_HTML_strike);
+
+ if ( rValue.isEmpty() )
+ HTMLOutFuncs::Out_AsciiTag(*m_pStream, OOO_STRING_SVTOOLS_HTML_linebreak); // no completely empty cell
+ else
+ HTMLOutFuncs::Out_String( (*m_pStream), rValue );
+
+ if ( bStrikeout ) HTMLOutFuncs::Out_AsciiTag(*m_pStream, OOO_STRING_SVTOOLS_HTML_strike, false);
+ if ( bUnderline ) HTMLOutFuncs::Out_AsciiTag(*m_pStream, OOO_STRING_SVTOOLS_HTML_underline, false);
+ if ( bItalic ) HTMLOutFuncs::Out_AsciiTag(*m_pStream, OOO_STRING_SVTOOLS_HTML_italic, false);
+ if ( bBold ) HTMLOutFuncs::Out_AsciiTag(*m_pStream, OOO_STRING_SVTOOLS_HTML_bold, false);
+
+ FontOff();
+
+ HTMLOutFuncs::Out_AsciiTag(*m_pStream, pHtmlTag, false).WriteCharPtr(SAL_NEWLINE_STRING).WriteCharPtr(GetIndentStr());
+}
+
+void OHTMLImportExport::FontOn()
+{
+#if OSL_DEBUG_LEVEL > 0
+ m_bCheckFont = true;
+#endif
+
+ // <FONT FACE="xxx">
+ OString aStrOut = "<"
+ OOO_STRING_SVTOOLS_HTML_font
+ " "
+ OOO_STRING_SVTOOLS_HTML_O_face
+ "="
+ "\"" +
+ OUStringToOString(m_aFont.Name,osl_getThreadTextEncoding()) +
+ // TODO : think about the encoding of the font name
+ "\""
+ " "
+ OOO_STRING_SVTOOLS_HTML_O_color
+ "=";
+ m_pStream->WriteOString( aStrOut );
+
+ ::Color aColor;
+ if(m_xObject.is())
+ m_xObject->getPropertyValue(PROPERTY_TEXTCOLOR) >>= aColor;
+
+ HTMLOutFuncs::Out_Color( (*m_pStream), aColor );
+ m_pStream->WriteCharPtr( ">" );
+}
+
+inline void OHTMLImportExport::FontOff()
+{
+#if OSL_DEBUG_LEVEL > 0
+ OSL_ENSURE(m_bCheckFont,"No FontOn() called");
+#endif
+ HTMLOutFuncs::Out_AsciiTag(*m_pStream, OOO_STRING_SVTOOLS_HTML_font, false);
+#if OSL_DEBUG_LEVEL > 0
+ m_bCheckFont = false;
+#endif
+}
+
+void OHTMLImportExport::IncIndent( sal_Int16 nVal )
+{
+ sIndent[m_nIndent] = '\t';
+ m_nIndent = m_nIndent + nVal;
+ if ( m_nIndent < 0 )
+ m_nIndent = 0;
+ else if ( m_nIndent > nIndentMax )
+ m_nIndent = nIndentMax;
+ sIndent[m_nIndent] = 0;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/misc/UITools.cxx b/dbaccess/source/ui/misc/UITools.cxx
new file mode 100644
index 000000000..7a9553e49
--- /dev/null
+++ b/dbaccess/source/ui/misc/UITools.cxx
@@ -0,0 +1,1370 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <UITools.hxx>
+#include <sfx2/docfilt.hxx>
+#include <core_resource.hxx>
+#include <dlgsave.hxx>
+#include <defaultobjectnamecheck.hxx>
+#include <strings.hxx>
+#include <comphelper/extract.hxx>
+#include <com/sun/star/sdb/DatabaseContext.hpp>
+#include <com/sun/star/sdb/XSingleSelectQueryAnalyzer.hpp>
+#include <com/sun/star/sdb/XCompletedConnection.hpp>
+#include <com/sun/star/sdbc/XDataSource.hpp>
+#include <com/sun/star/sdb/SQLContext.hpp>
+#include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
+#include <com/sun/star/sdbcx/XViewsSupplier.hpp>
+#include <com/sun/star/sdbcx/XTablesSupplier.hpp>
+#include <com/sun/star/sdbcx/XDataDescriptorFactory.hpp>
+#include <com/sun/star/sdbcx/XAppend.hpp>
+#include <com/sun/star/sdbc/XRow.hpp>
+#include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp>
+#include <com/sun/star/sdbc/XResultSetMetaData.hpp>
+#include <com/sun/star/sdbc/ColumnValue.hpp>
+#include <com/sun/star/task/InteractionHandler.hpp>
+#include <com/sun/star/ucb/XContent.hpp>
+#include <com/sun/star/ui/dialogs/XExecutableDialog.hpp>
+#include <com/sun/star/beans/PropertyValue.hpp>
+#include <com/sun/star/container/XNameContainer.hpp>
+#include <com/sun/star/ucb/InteractiveIOException.hpp>
+#include <com/sun/star/sdb/XDocumentDataSource.hpp>
+#include <com/sun/star/ucb/IOErrorCode.hpp>
+#include <vcl/syswin.hxx>
+#include <vcl/settings.hxx>
+#include <vcl/svapp.hxx>
+#include <com/sun/star/beans/XPropertySetInfo.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/container/XNameAccess.hpp>
+#include <com/sun/star/container/XHierarchicalNameContainer.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/awt/TextAlign.hpp>
+#include <TypeInfo.hxx>
+#include <FieldDescriptions.hxx>
+#include <comphelper/stl_types.hxx>
+#include <comphelper/types.hxx>
+#include <comphelper/propertysequence.hxx>
+
+#include <svx/svxids.hrc>
+
+#include <sal/log.hxx>
+#include <svl/numformat.hxx>
+#include <svl/itempool.hxx>
+#include <helpids.h>
+#include <svl/itemset.hxx>
+#include <sbagrid.hrc>
+#include <svl/rngitem.hxx>
+#include <svl/intitem.hxx>
+#include <svx/numinf.hxx>
+#include <svl/zforlist.hxx>
+#include <dlgattr.hxx>
+#include <com/sun/star/container/XChild.hpp>
+#include <com/sun/star/util/NumberFormatter.hpp>
+#include <com/sun/star/util/XNumberFormatsSupplier.hpp>
+#include <com/sun/star/util/XNumberFormatter.hpp>
+#include <strings.hrc>
+#include <sqlmessage.hxx>
+#include <dlgsize.hxx>
+#include <svtools/editbrowsebox.hxx>
+#include <tools/urlobj.hxx>
+#include <tools/diagnose_ex.h>
+#include <svl/numuno.hxx>
+#include <svl/filenotation.hxx>
+#include <connectivity/FValue.hxx>
+
+#include <editeng/justifyitem.hxx>
+#include <memory>
+
+namespace dbaui
+{
+using namespace ::dbtools;
+using namespace ::comphelper;
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::task;
+using namespace ::com::sun::star::sdbcx;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::sdb;
+using namespace ::com::sun::star::util;
+using namespace ::com::sun::star::ucb;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::ui::dialogs;
+using namespace ::svt;
+using ::com::sun::star::ucb::InteractiveIOException;
+using ::com::sun::star::ucb::IOErrorCode_NO_FILE;
+using ::com::sun::star::ucb::IOErrorCode_NOT_EXISTING;
+
+SQLExceptionInfo createConnection( const OUString& _rsDataSourceName,
+ const Reference< css::container::XNameAccess >& _xDatabaseContext,
+ const Reference< css::uno::XComponentContext >& _rxContext,
+ Reference< css::lang::XEventListener> const & _rEvtLst,
+ Reference< css::sdbc::XConnection>& _rOUTConnection )
+{
+ Reference<XPropertySet> xProp;
+ try
+ {
+ xProp.set(_xDatabaseContext->getByName(_rsDataSourceName),UNO_QUERY);
+ }
+ catch(const Exception&)
+ {
+ }
+
+ return createConnection(xProp,_rxContext,_rEvtLst,_rOUTConnection);
+}
+
+SQLExceptionInfo createConnection( const Reference< css::beans::XPropertySet>& _xDataSource,
+ const Reference< css::uno::XComponentContext >& _rxContext,
+ Reference< css::lang::XEventListener> const & _rEvtLst,
+ Reference< css::sdbc::XConnection>& _rOUTConnection )
+{
+ SQLExceptionInfo aInfo;
+ if ( !_xDataSource.is() )
+ {
+ SAL_WARN("dbaccess.ui", "createConnection: could not retrieve the data source!");
+ return aInfo;
+ }
+
+ OUString sPwd, sUser;
+ bool bPwdReq = false;
+ try
+ {
+ _xDataSource->getPropertyValue(PROPERTY_PASSWORD) >>= sPwd;
+ bPwdReq = ::cppu::any2bool(_xDataSource->getPropertyValue(PROPERTY_ISPASSWORDREQUIRED));
+ _xDataSource->getPropertyValue(PROPERTY_USER) >>= sUser;
+ }
+ catch(const Exception&)
+ {
+ SAL_WARN("dbaccess.ui", "createConnection: error while retrieving data source properties!");
+ }
+
+ try
+ {
+ if(bPwdReq && sPwd.isEmpty())
+ { // password required, but empty -> connect using an interaction handler
+ Reference<XCompletedConnection> xConnectionCompletion(_xDataSource, UNO_QUERY);
+ if (!xConnectionCompletion.is())
+ {
+ SAL_WARN("dbaccess.ui", "createConnection: missing an interface ... need an error message here!");
+ }
+ else
+ { // instantiate the default SDB interaction handler
+ Reference< XInteractionHandler > xHandler = InteractionHandler::createWithParent(_rxContext, nullptr);
+ _rOUTConnection = xConnectionCompletion->connectWithCompletion(xHandler);
+ }
+ }
+ else
+ {
+ Reference<XDataSource> xDataSource(_xDataSource,UNO_QUERY);
+ _rOUTConnection = xDataSource->getConnection(sUser, sPwd);
+ }
+ // be notified when connection is in disposing
+ Reference< XComponent > xComponent(_rOUTConnection, UNO_QUERY);
+ if (xComponent.is() && _rEvtLst.is())
+ xComponent->addEventListener(_rEvtLst);
+ }
+ catch(const SQLContext& e) { aInfo = SQLExceptionInfo(e); }
+ catch(const SQLWarning& e) { aInfo = SQLExceptionInfo(e); }
+ catch(const SQLException& e) { aInfo = SQLExceptionInfo(e); }
+ catch(const Exception&) {
+ TOOLS_WARN_EXCEPTION("dbaccess.ui", "SbaTableQueryBrowser::OnExpandEntry: could not connect - unknown exception");
+ }
+
+ return aInfo;
+}
+
+Reference< XDataSource > getDataSourceByName( const OUString& _rDataSourceName,
+ weld::Window* _pErrorMessageParent, const Reference< XComponentContext >& _rxContext, ::dbtools::SQLExceptionInfo* _pErrorInfo )
+{
+ Reference< XDatabaseContext > xDatabaseContext = DatabaseContext::create(_rxContext);
+
+ Reference< XDataSource > xDatasource;
+ SQLExceptionInfo aSQLError;
+ try
+ {
+ xDatabaseContext->getByName( _rDataSourceName ) >>= xDatasource;
+ }
+ catch(const WrappedTargetException& e)
+ {
+ InteractiveIOException aIOException;
+ if ( ( e.TargetException >>= aIOException )
+ && ( ( aIOException.Code == IOErrorCode_NO_FILE )
+ || ( aIOException.Code == IOErrorCode_NOT_EXISTING )
+ )
+ )
+ {
+ OUString sErrorMessage( DBA_RES( STR_FILE_DOES_NOT_EXIST ) );
+ OFileNotation aTransformer( e.Message );
+ sErrorMessage = sErrorMessage.replaceFirst( "$file$", aTransformer.get( OFileNotation::N_SYSTEM ) );
+ aSQLError = SQLExceptionInfo( sErrorMessage ).get();
+ }
+ else
+ {
+ aSQLError = SQLExceptionInfo( e.TargetException );
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+
+ if ( xDatasource.is() )
+ return xDatasource;
+
+ if ( aSQLError.isValid() )
+ {
+ if ( _pErrorInfo )
+ {
+ *_pErrorInfo = aSQLError;
+ }
+ else
+ {
+ showError( aSQLError, _pErrorMessageParent ? _pErrorMessageParent->GetXWindow() : nullptr, _rxContext );
+ }
+ }
+
+ return Reference<XDataSource>();
+}
+
+Reference< XInterface > getDataSourceOrModel(const Reference< XInterface >& _xObject)
+{
+ Reference< XInterface > xRet;
+ Reference<XDocumentDataSource> xDocumentDataSource(_xObject,UNO_QUERY);
+ if ( xDocumentDataSource.is() )
+ xRet = xDocumentDataSource->getDatabaseDocument();
+
+ if ( !xRet.is() )
+ {
+ Reference<XOfficeDatabaseDocument> xOfficeDoc(_xObject,UNO_QUERY);
+ if ( xOfficeDoc.is() )
+ xRet = xOfficeDoc->getDataSource();
+ }
+
+ return xRet;
+}
+
+TOTypeInfoSP getTypeInfoFromType(const OTypeInfoMap& _rTypeInfo,
+ sal_Int32 _nType,
+ const OUString& _sTypeName,
+ const OUString& _sCreateParams,
+ sal_Int32 _nPrecision,
+ sal_Int32 _nScale,
+ bool _bAutoIncrement,
+ bool& _brForceToType)
+{
+ TOTypeInfoSP pTypeInfo;
+ _brForceToType = false;
+ // search for type
+ std::pair<OTypeInfoMap::const_iterator, OTypeInfoMap::const_iterator> aPair = _rTypeInfo.equal_range(_nType);
+ OTypeInfoMap::const_iterator aIter = aPair.first;
+ if(aIter != _rTypeInfo.end()) // compare with end is correct here
+ {
+ for(;aIter != aPair.second;++aIter)
+ {
+ // search the best matching type
+ #ifdef DBG_UTIL
+ OUString sDBTypeName = aIter->second->aTypeName; (void)sDBTypeName;
+ #endif
+ if ( (
+ _sTypeName.isEmpty()
+ || (aIter->second->aTypeName.equalsIgnoreAsciiCase(_sTypeName))
+ )
+ && (
+ (
+ !aIter->second->aCreateParams.getLength()
+ && _sCreateParams.isEmpty()
+ )
+ || (
+ (aIter->second->nPrecision >= _nPrecision)
+ && (aIter->second->nMaximumScale >= _nScale)
+ && ( (_bAutoIncrement && aIter->second->bAutoIncrement) || !_bAutoIncrement )
+ )
+ )
+ )
+ break;
+ }
+
+ if (aIter == aPair.second)
+ {
+ for(aIter = aPair.first; aIter != aPair.second; ++aIter)
+ {
+ sal_Int32 nPrec = aIter->second->nPrecision;
+ sal_Int32 nScale = aIter->second->nMaximumScale;
+ // search the best matching type (now comparing the local names)
+ if ( (aIter->second->aLocalTypeName.equalsIgnoreAsciiCase(_sTypeName))
+ && (nPrec >= _nPrecision)
+ && (nScale >= _nScale)
+ && ( (_bAutoIncrement && aIter->second->bAutoIncrement) || !_bAutoIncrement )
+ )
+ {
+ SAL_WARN("dbaccess.ui", "getTypeInfoFromType: assuming column type " <<
+ aIter->second->aTypeName << "\" (expected type name " <<
+ _sTypeName << " matches the type's local name).");
+ break;
+ }
+ }
+ }
+
+ if (aIter == aPair.second)
+ { // no match for the names, no match for the local names
+ // -> drop the precision and the scale restriction, accept any type with the property
+ // type id (nType)
+
+ for(aIter = aPair.first; aIter != aPair.second; ++aIter)
+ {
+ // search the best matching type (now comparing the local names)
+ sal_Int32 nPrec = aIter->second->nPrecision;
+ sal_Int32 nScale = aIter->second->nMaximumScale;
+ if ( (nPrec >= _nPrecision)
+ && (nScale >= _nScale)
+ && ( (_bAutoIncrement && aIter->second->bAutoIncrement) || !_bAutoIncrement )
+ )
+ break;
+ }
+ }
+ if (aIter == aPair.second)
+ {
+ if ( _bAutoIncrement )
+ {
+ for(aIter = aPair.first; aIter != aPair.second; ++aIter)
+ {
+ // search the best matching type (now comparing the local names)
+ sal_Int32 nScale = aIter->second->nMaximumScale;
+ if ( (nScale >= _nScale)
+ && (aIter->second->bAutoIncrement == _bAutoIncrement)
+ )
+ break;
+ }
+ if ( aIter == aPair.second )
+ {
+ // try it without the auto increment flag
+ pTypeInfo = getTypeInfoFromType(_rTypeInfo,
+ _nType,
+ _sTypeName,
+ _sCreateParams,
+ _nPrecision,
+ _nScale,
+ false,
+ _brForceToType);
+ }
+ else
+ pTypeInfo = aIter->second;
+ }
+ else
+ {
+ pTypeInfo = aPair.first->second;
+ _brForceToType = true;
+ }
+ }
+ else
+ pTypeInfo = aIter->second;
+ }
+ else
+ {
+ ::comphelper::UStringMixEqual aCase(false);
+ // search for typeinfo where the typename is equal _sTypeName
+ for (auto const& elem : _rTypeInfo)
+ {
+ if ( aCase( elem.second->getDBName() , _sTypeName ) )
+ {
+ pTypeInfo = elem.second;
+ break;
+ }
+ }
+ }
+
+ OSL_ENSURE(pTypeInfo, "getTypeInfoFromType: no type info found for this type!");
+ return pTypeInfo;
+}
+
+void fillTypeInfo( const Reference< css::sdbc::XConnection>& _rxConnection,
+ std::u16string_view _rsTypeNames,
+ OTypeInfoMap& _rTypeInfoMap,
+ std::vector<OTypeInfoMap::iterator>& _rTypeInfoIters)
+{
+ if(!_rxConnection.is())
+ return;
+ Reference< XResultSet> xRs = _rxConnection->getMetaData ()->getTypeInfo ();
+ Reference< XRow> xRow(xRs,UNO_QUERY);
+ // Information for a single SQL type
+ if(!xRs.is())
+ return;
+
+ Reference<XResultSetMetaData> xResultSetMetaData = Reference<XResultSetMetaDataSupplier>(xRs,UNO_QUERY_THROW)->getMetaData();
+ ::connectivity::ORowSetValue aValue;
+ std::vector<sal_Int32> aTypes;
+ std::vector<bool> aNullable;
+ // Loop on the result set until we reach end of file
+ while (xRs->next())
+ {
+ TOTypeInfoSP pInfo = std::make_shared<OTypeInfo>();
+ sal_Int32 nPos = 1;
+ if ( aTypes.empty() )
+ {
+ sal_Int32 nCount = xResultSetMetaData->getColumnCount();
+ if ( nCount < 1 )
+ nCount = 18;
+ aTypes.reserve(nCount+1);
+ aTypes.push_back(-1);
+ aNullable.push_back(false);
+ for (sal_Int32 j = 1; j <= nCount ; ++j)
+ {
+ aTypes.push_back(xResultSetMetaData->getColumnType(j));
+ aNullable.push_back(xResultSetMetaData->isNullable(j) != ColumnValue::NO_NULLS);
+ }
+ }
+
+ aValue.fill(nPos,aTypes[nPos],aNullable[nPos],xRow);
+ pInfo->aTypeName = aValue.getString();
+ ++nPos;
+ aValue.fill(nPos,aTypes[nPos],aNullable[nPos],xRow);
+ pInfo->nType = aValue.getInt32();
+ ++nPos;
+ aValue.fill(nPos,aTypes[nPos],aNullable[nPos],xRow);
+ pInfo->nPrecision = aValue.getInt32();
+ ++nPos;
+ aValue.fill(nPos,aTypes[nPos],aNullable[nPos],xRow); // LiteralPrefix
+ ++nPos;
+ aValue.fill(nPos,aTypes[nPos],aNullable[nPos],xRow); //LiteralSuffix
+ ++nPos;
+ aValue.fill(nPos,aTypes[nPos],aNullable[nPos],xRow);
+ pInfo->aCreateParams = aValue.getString();
+ ++nPos;
+ aValue.fill(nPos,aTypes[nPos],aNullable[nPos],xRow);
+ pInfo->bNullable = aValue.getInt32() == ColumnValue::NULLABLE;
+ ++nPos;
+ aValue.fill(nPos,aTypes[nPos],aNullable[nPos],xRow);
+ // bCaseSensitive
+ ++nPos;
+ aValue.fill(nPos,aTypes[nPos],aNullable[nPos],xRow);
+ pInfo->nSearchType = aValue.getInt16();
+ ++nPos;
+ aValue.fill(nPos,aTypes[nPos],aNullable[nPos],xRow);
+ // bUnsigned
+ ++nPos;
+ aValue.fill(nPos,aTypes[nPos],aNullable[nPos],xRow);
+ pInfo->bCurrency = aValue.getBool();
+ ++nPos;
+ aValue.fill(nPos,aTypes[nPos],aNullable[nPos],xRow);
+ pInfo->bAutoIncrement = aValue.getBool();
+ ++nPos;
+ aValue.fill(nPos,aTypes[nPos],aNullable[nPos],xRow);
+ pInfo->aLocalTypeName = aValue.getString();
+ ++nPos;
+ aValue.fill(nPos,aTypes[nPos],aNullable[nPos],xRow);
+ pInfo->nMinimumScale = aValue.getInt16();
+ ++nPos;
+ aValue.fill(nPos,aTypes[nPos],aNullable[nPos],xRow);
+ pInfo->nMaximumScale = aValue.getInt16();
+ assert(nPos == 15);
+ // 16 and 17 are unused
+ nPos = 18;
+ aValue.fill(nPos,aTypes[nPos],aNullable[nPos],xRow);
+ pInfo->nNumPrecRadix = aValue.getInt32();
+
+ // check if values are less than zero like it happens in a oracle jdbc driver
+ if( pInfo->nPrecision < 0)
+ pInfo->nPrecision = 0;
+ if( pInfo->nMinimumScale < 0)
+ pInfo->nMinimumScale = 0;
+ if( pInfo->nMaximumScale < 0)
+ pInfo->nMaximumScale = 0;
+ if( pInfo->nNumPrecRadix <= 1)
+ pInfo->nNumPrecRadix = 10;
+
+ std::u16string_view aName;
+ switch(pInfo->nType)
+ {
+ case DataType::CHAR:
+ aName = o3tl::getToken(_rsTypeNames, TYPE_CHAR, ';');
+ break;
+ case DataType::VARCHAR:
+ aName = o3tl::getToken(_rsTypeNames, TYPE_TEXT, ';');
+ break;
+ case DataType::DECIMAL:
+ aName = o3tl::getToken(_rsTypeNames, TYPE_DECIMAL, ';');
+ break;
+ case DataType::NUMERIC:
+ aName = o3tl::getToken(_rsTypeNames, TYPE_NUMERIC, ';');
+ break;
+ case DataType::BIGINT:
+ aName = o3tl::getToken(_rsTypeNames, TYPE_BIGINT, ';');
+ break;
+ case DataType::FLOAT:
+ aName = o3tl::getToken(_rsTypeNames, TYPE_FLOAT, ';');
+ break;
+ case DataType::DOUBLE:
+ aName = o3tl::getToken(_rsTypeNames, TYPE_DOUBLE, ';');
+ break;
+ case DataType::LONGVARCHAR:
+ aName = o3tl::getToken(_rsTypeNames, TYPE_MEMO, ';');
+ break;
+ case DataType::LONGVARBINARY:
+ aName = o3tl::getToken(_rsTypeNames, TYPE_IMAGE, ';');
+ break;
+ case DataType::DATE:
+ aName = o3tl::getToken(_rsTypeNames, TYPE_DATE, ';');
+ break;
+ case DataType::TIME:
+ aName = o3tl::getToken(_rsTypeNames, TYPE_TIME, ';');
+ break;
+ case DataType::TIMESTAMP:
+ aName = o3tl::getToken(_rsTypeNames, TYPE_DATETIME, ';');
+ break;
+ case DataType::BIT:
+ if ( !pInfo->aCreateParams.isEmpty() )
+ {
+ aName = o3tl::getToken(_rsTypeNames, TYPE_BIT, ';');
+ break;
+ }
+ [[fallthrough]];
+ case DataType::BOOLEAN:
+ aName = o3tl::getToken(_rsTypeNames, TYPE_BOOL, ';');
+ break;
+ case DataType::TINYINT:
+ aName = o3tl::getToken(_rsTypeNames, TYPE_TINYINT, ';');
+ break;
+ case DataType::SMALLINT:
+ aName = o3tl::getToken(_rsTypeNames, TYPE_SMALLINT, ';');
+ break;
+ case DataType::INTEGER:
+ aName = o3tl::getToken(_rsTypeNames, TYPE_INTEGER, ';');
+ break;
+ case DataType::REAL:
+ aName = o3tl::getToken(_rsTypeNames, TYPE_REAL, ';');
+ break;
+ case DataType::BINARY:
+ aName = o3tl::getToken(_rsTypeNames, TYPE_BINARY, ';');
+ break;
+ case DataType::VARBINARY:
+ aName = o3tl::getToken(_rsTypeNames, TYPE_VARBINARY, ';');
+ break;
+ case DataType::SQLNULL:
+ aName = o3tl::getToken(_rsTypeNames, TYPE_SQLNULL, ';');
+ break;
+ case DataType::OBJECT:
+ aName = o3tl::getToken(_rsTypeNames, TYPE_OBJECT, ';');
+ break;
+ case DataType::DISTINCT:
+ aName = o3tl::getToken(_rsTypeNames, TYPE_DISTINCT, ';');
+ break;
+ case DataType::STRUCT:
+ aName = o3tl::getToken(_rsTypeNames, TYPE_STRUCT, ';');
+ break;
+ case DataType::ARRAY:
+ aName = o3tl::getToken(_rsTypeNames, TYPE_ARRAY, ';');
+ break;
+ case DataType::BLOB:
+ aName = o3tl::getToken(_rsTypeNames, TYPE_BLOB, ';');
+ break;
+ case DataType::CLOB:
+ aName = o3tl::getToken(_rsTypeNames, TYPE_CLOB, ';');
+ break;
+ case DataType::REF:
+ aName = o3tl::getToken(_rsTypeNames, TYPE_REF, ';');
+ break;
+ case DataType::OTHER:
+ aName = o3tl::getToken(_rsTypeNames, TYPE_OTHER, ';');
+ break;
+ }
+ if ( !aName.empty() )
+ {
+ pInfo->aUIName = aName;
+ pInfo->aUIName += " [ ";
+ }
+ pInfo->aUIName += pInfo->aTypeName;
+ if ( !aName.empty() )
+ pInfo->aUIName += " ]";
+ // Now that we have the type info, save it in the multimap
+ _rTypeInfoMap.emplace(pInfo->nType,pInfo);
+ }
+ // for a faster index access
+ _rTypeInfoIters.reserve(_rTypeInfoMap.size());
+
+ OTypeInfoMap::iterator aIter = _rTypeInfoMap.begin();
+ OTypeInfoMap::const_iterator aEnd = _rTypeInfoMap.end();
+ for(;aIter != aEnd;++aIter)
+ _rTypeInfoIters.push_back(aIter);
+
+ // Close the result set/statement.
+
+ ::comphelper::disposeComponent(xRs);
+}
+
+void setColumnProperties(const Reference<XPropertySet>& _rxColumn,const OFieldDescription* _pFieldDesc)
+{
+ _rxColumn->setPropertyValue(PROPERTY_NAME,Any(_pFieldDesc->GetName()));
+ _rxColumn->setPropertyValue(PROPERTY_TYPENAME,Any(_pFieldDesc->getTypeInfo()->aTypeName));
+ _rxColumn->setPropertyValue(PROPERTY_TYPE,Any(_pFieldDesc->GetType()));
+ _rxColumn->setPropertyValue(PROPERTY_PRECISION,Any(_pFieldDesc->GetPrecision()));
+ _rxColumn->setPropertyValue(PROPERTY_SCALE,Any(_pFieldDesc->GetScale()));
+ _rxColumn->setPropertyValue(PROPERTY_ISNULLABLE, Any(_pFieldDesc->GetIsNullable()));
+ _rxColumn->setPropertyValue(PROPERTY_ISAUTOINCREMENT, css::uno::Any(_pFieldDesc->IsAutoIncrement()));
+ _rxColumn->setPropertyValue(PROPERTY_DESCRIPTION,Any(_pFieldDesc->GetDescription()));
+ if ( _rxColumn->getPropertySetInfo()->hasPropertyByName(PROPERTY_ISCURRENCY) && _pFieldDesc->IsCurrency() )
+ _rxColumn->setPropertyValue(PROPERTY_ISCURRENCY, css::uno::Any(_pFieldDesc->IsCurrency()));
+ // set autoincrement value when available
+ // and only set when the entry is not empty, that lets the value in the column untouched
+ if ( _pFieldDesc->IsAutoIncrement() && !_pFieldDesc->GetAutoIncrementValue().isEmpty() && _rxColumn->getPropertySetInfo()->hasPropertyByName(PROPERTY_AUTOINCREMENTCREATION) )
+ _rxColumn->setPropertyValue(PROPERTY_AUTOINCREMENTCREATION,Any(_pFieldDesc->GetAutoIncrementValue()));
+}
+
+OUString createDefaultName(const Reference< XDatabaseMetaData>& _xMetaData,const Reference<XNameAccess>& _xTables,const OUString& _sName)
+{
+ OSL_ENSURE(_xMetaData.is(),"No MetaData!");
+ OUString sDefaultName = _sName;
+ try
+ {
+ OUString sCatalog,sSchema,sCompsedName;
+ if(_xMetaData->supportsCatalogsInTableDefinitions())
+ {
+ try
+ {
+ Reference< XConnection> xCon = _xMetaData->getConnection();
+ if ( xCon.is() )
+ sCatalog = xCon->getCatalog();
+ if ( sCatalog.isEmpty() )
+ {
+ Reference<XResultSet> xRes = _xMetaData->getCatalogs();
+ Reference<XRow> xRow(xRes,UNO_QUERY);
+ while(xRes.is() && xRes->next())
+ {
+ sCatalog = xRow->getString(1);
+ if(!xRow->wasNull())
+ break;
+ }
+ }
+ }
+ catch(const SQLException&)
+ {
+ }
+ }
+ if(_xMetaData->supportsSchemasInTableDefinitions())
+ {
+ sSchema = _xMetaData->getUserName();
+ }
+ sCompsedName = ::dbtools::composeTableName( _xMetaData, sCatalog, sSchema, _sName, false, ::dbtools::EComposeRule::InDataManipulation );
+ sDefaultName = ::dbtools::createUniqueName(_xTables,sCompsedName);
+ }
+ catch(const SQLException&)
+ {
+ }
+ return sDefaultName;
+}
+
+bool checkDataSourceAvailable(const OUString& _sDataSourceName,const Reference< css::uno::XComponentContext >& _xContext)
+{
+ Reference< XDatabaseContext > xDataBaseContext = DatabaseContext::create(_xContext);
+ bool bRet = xDataBaseContext->hasByName(_sDataSourceName);
+ if ( !bRet )
+ { // try if this one is a URL
+ try
+ {
+ bRet = xDataBaseContext->getByName(_sDataSourceName).hasValue();
+ }
+ catch(const Exception&)
+ {
+ }
+ }
+ return bRet;
+}
+
+sal_Int32 mapTextAlign(const SvxCellHorJustify& _eAlignment)
+{
+ sal_Int32 nAlignment = css::awt::TextAlign::LEFT;
+ switch (_eAlignment)
+ {
+ case SvxCellHorJustify::Standard:
+ case SvxCellHorJustify::Left: nAlignment = css::awt::TextAlign::LEFT; break;
+ case SvxCellHorJustify::Center: nAlignment = css::awt::TextAlign::CENTER; break;
+ case SvxCellHorJustify::Right: nAlignment = css::awt::TextAlign::RIGHT; break;
+ default:
+ SAL_WARN("dbaccess.ui", "Invalid TextAlign!");
+ }
+ return nAlignment;
+}
+
+SvxCellHorJustify mapTextJustify(sal_Int32 _nAlignment)
+{
+ SvxCellHorJustify eJustify = SvxCellHorJustify::Left;
+ switch (_nAlignment)
+ {
+ case css::awt::TextAlign::LEFT : eJustify = SvxCellHorJustify::Left; break;
+ case css::awt::TextAlign::CENTER : eJustify = SvxCellHorJustify::Center; break;
+ case css::awt::TextAlign::RIGHT : eJustify = SvxCellHorJustify::Right; break;
+ default:
+ SAL_WARN("dbaccess.ui", "Invalid TextAlign!");
+ }
+ return eJustify;
+}
+
+void callColumnFormatDialog(const Reference<XPropertySet>& xAffectedCol,
+ const Reference<XPropertySet>& xField,
+ SvNumberFormatter* _pFormatter,
+ weld::Widget* _pParent)
+{
+ if (!(xAffectedCol.is() && xField.is()))
+ return;
+
+ try
+ {
+ Reference< XPropertySetInfo > xInfo = xAffectedCol->getPropertySetInfo();
+ bool bHasFormat = xInfo->hasPropertyByName(PROPERTY_FORMATKEY);
+ sal_Int32 nDataType = ::comphelper::getINT32(xField->getPropertyValue(PROPERTY_TYPE));
+
+ SvxCellHorJustify eJustify(SvxCellHorJustify::Standard);
+ Any aAlignment = xAffectedCol->getPropertyValue(PROPERTY_ALIGN);
+ if (aAlignment.hasValue())
+ eJustify = dbaui::mapTextJustify(::comphelper::getINT16(aAlignment));
+ sal_Int32 nFormatKey = 0;
+ if ( bHasFormat )
+ nFormatKey = ::comphelper::getINT32(xAffectedCol->getPropertyValue(PROPERTY_FORMATKEY));
+
+ if(callColumnFormatDialog(_pParent,_pFormatter,nDataType,nFormatKey,eJustify,bHasFormat))
+ {
+ xAffectedCol->setPropertyValue(PROPERTY_ALIGN, Any(static_cast<sal_Int16>(dbaui::mapTextAlign(eJustify))));
+ if (bHasFormat)
+ xAffectedCol->setPropertyValue(PROPERTY_FORMATKEY, Any(nFormatKey));
+
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+}
+
+bool callColumnFormatDialog(weld::Widget* _pParent,
+ SvNumberFormatter* _pFormatter,
+ sal_Int32 _nDataType,
+ sal_Int32& _nFormatKey,
+ SvxCellHorJustify& _eJustify,
+ bool _bHasFormat)
+{
+ bool bRet = false;
+
+ // UNO->ItemSet
+ static SfxItemInfo aItemInfos[] =
+ {
+ { 0, false },
+ { SID_ATTR_NUMBERFORMAT_VALUE, true },
+ { SID_ATTR_ALIGN_HOR_JUSTIFY, true },
+ { SID_ATTR_NUMBERFORMAT_INFO, true },
+ { SID_ATTR_NUMBERFORMAT_ONE_AREA, true }
+ };
+ static const auto aAttrMap = svl::Items<
+ SBA_DEF_RANGEFORMAT, SBA_ATTR_ALIGN_HOR_JUSTIFY,
+ SID_ATTR_NUMBERFORMAT_INFO, SID_ATTR_NUMBERFORMAT_INFO,
+ SID_ATTR_NUMBERFORMAT_ONE_AREA, SID_ATTR_NUMBERFORMAT_ONE_AREA
+ >;
+
+ std::vector<SfxPoolItem*> pDefaults
+ {
+ new SfxRangeItem(SBA_DEF_RANGEFORMAT, SBA_DEF_FMTVALUE, SBA_ATTR_ALIGN_HOR_JUSTIFY),
+ new SfxUInt32Item(SBA_DEF_FMTVALUE),
+ new SvxHorJustifyItem(SvxCellHorJustify::Standard, SBA_ATTR_ALIGN_HOR_JUSTIFY),
+ new SvxNumberInfoItem(SID_ATTR_NUMBERFORMAT_INFO),
+ new SfxBoolItem(SID_ATTR_NUMBERFORMAT_ONE_AREA, false)
+ };
+
+ rtl::Reference<SfxItemPool> pPool(new SfxItemPool("GridBrowserProperties", SBA_DEF_RANGEFORMAT, SBA_ATTR_ALIGN_HOR_JUSTIFY, aItemInfos, &pDefaults));
+ pPool->SetDefaultMetric( MapUnit::MapTwip ); // ripped, don't understand why
+ pPool->FreezeIdRanges(); // the same
+
+ std::optional<SfxItemSet> pFormatDescriptor(SfxItemSet(*pPool, aAttrMap));
+ // fill it
+ pFormatDescriptor->Put(SvxHorJustifyItem(_eJustify, SBA_ATTR_ALIGN_HOR_JUSTIFY));
+ bool bText = false;
+ if (_bHasFormat)
+ {
+ // if the col is bound to a text field we have to disallow all non-text formats
+ if ((DataType::CHAR == _nDataType) || (DataType::VARCHAR == _nDataType) || (DataType::LONGVARCHAR == _nDataType) || (DataType::CLOB == _nDataType))
+ {
+ bText = true;
+ pFormatDescriptor->Put(SfxBoolItem(SID_ATTR_NUMBERFORMAT_ONE_AREA, true));
+ if (!_pFormatter->IsTextFormat(_nFormatKey))
+ // text fields can only have text formats
+ _nFormatKey = _pFormatter->GetStandardFormat(SvNumFormatType::TEXT, Application::GetSettings().GetLanguageTag().getLanguageType());
+ }
+
+ pFormatDescriptor->Put(SfxUInt32Item(SBA_DEF_FMTVALUE, _nFormatKey));
+ }
+
+ if (!bText)
+ {
+ SvxNumberInfoItem aFormatter(_pFormatter, 1234.56789, SID_ATTR_NUMBERFORMAT_INFO);
+ pFormatDescriptor->Put(aFormatter);
+ }
+
+ { // want the dialog to be destroyed before our set
+ SbaSbAttrDlg aDlg(_pParent, &*pFormatDescriptor, _pFormatter, _bHasFormat);
+ if (RET_OK == aDlg.run())
+ {
+ // ItemSet->UNO
+ // UNO-properties
+ const SfxItemSet* pSet = aDlg.GetExampleSet();
+ // (of course we could put the modified items directly into the column, but then the UNO-model
+ // won't reflect these changes, and why do we have a model, then ?)
+
+ // horizontal justify
+ const SvxHorJustifyItem* pHorJustify = pSet->GetItem<SvxHorJustifyItem>(SBA_ATTR_ALIGN_HOR_JUSTIFY);
+
+ _eJustify = pHorJustify->GetValue();
+
+ // format key
+ if (_bHasFormat)
+ {
+ const SfxUInt32Item* pFormat = pSet->GetItem<SfxUInt32Item>(SBA_DEF_FMTVALUE);
+ _nFormatKey = static_cast<sal_Int32>(pFormat->GetValue());
+ }
+ bRet = true;
+ }
+ // deleted formats
+ const SfxItemSet* pResult = aDlg.GetOutputItemSet();
+ if (pResult)
+ {
+ const SfxPoolItem* pItem = pResult->GetItem( SID_ATTR_NUMBERFORMAT_INFO );
+ const SvxNumberInfoItem* pInfoItem = static_cast<const SvxNumberInfoItem*>(pItem);
+ if (pInfoItem)
+ {
+ for (sal_uInt32 key : pInfoItem->GetDelFormats())
+ _pFormatter->DeleteEntry(key);
+ }
+ }
+ }
+
+ pFormatDescriptor.reset();
+ pPool.clear();
+ for (SfxPoolItem* pDefault : pDefaults)
+ delete pDefault;
+
+ return bRet;
+}
+
+std::shared_ptr<const SfxFilter> getStandardDatabaseFilter()
+{
+ std::shared_ptr<const SfxFilter> pFilter = SfxFilter::GetFilterByName("StarOffice XML (Base)");
+ OSL_ENSURE(pFilter,"Filter: StarOffice XML (Base) could not be found!");
+ return pFilter;
+}
+
+bool appendToFilter(const Reference<XConnection>& _xConnection,
+ const OUString& _sName,
+ const Reference< XComponentContext >& _rxContext,
+ weld::Window* pParent)
+{
+ bool bRet = false;
+ Reference< XChild> xChild(_xConnection,UNO_QUERY);
+ if(xChild.is())
+ {
+ Reference< XPropertySet> xProp(xChild->getParent(),UNO_QUERY);
+ if(xProp.is())
+ {
+ Sequence< OUString > aFilter;
+ xProp->getPropertyValue(PROPERTY_TABLEFILTER) >>= aFilter;
+ // first check if we have something like SCHEMA.%
+ bool bHasToInsert = true;
+ for (const OUString& rItem : std::as_const(aFilter))
+ {
+ if(rItem.indexOf('%') != -1)
+ {
+ sal_Int32 nLen = rItem.lastIndexOf('.');
+ if(nLen != -1 && !rItem.compareTo(_sName,nLen))
+ bHasToInsert = false;
+ else if(rItem.getLength() == 1)
+ bHasToInsert = false;
+ }
+ }
+
+ bRet = true;
+ if(bHasToInsert)
+ {
+ if(! ::dbaui::checkDataSourceAvailable(::comphelper::getString(xProp->getPropertyValue(PROPERTY_NAME)),_rxContext))
+ {
+ OUString aMessage(DBA_RES(STR_TABLEDESIGN_DATASOURCE_DELETED));
+ OSQLWarningBox aWarning(pParent, aMessage);
+ aWarning.run();
+ bRet = false;
+ }
+ else
+ {
+ aFilter.realloc(aFilter.getLength()+1);
+ aFilter.getArray()[aFilter.getLength()-1] = _sName;
+ xProp->setPropertyValue(PROPERTY_TABLEFILTER,Any(aFilter));
+ }
+ }
+ }
+ }
+ return bRet;
+}
+
+void notifySystemWindow(vcl::Window const * _pWindow, vcl::Window* _pToRegister, const ::comphelper::mem_fun1_t<TaskPaneList,vcl::Window*>& _rMemFunc)
+{
+ OSL_ENSURE(_pWindow,"Window can not be null!");
+ SystemWindow* pSystemWindow = _pWindow ? _pWindow->GetSystemWindow() : nullptr;
+ if ( pSystemWindow )
+ {
+ _rMemFunc( pSystemWindow->GetTaskPaneList(), _pToRegister );
+ }
+}
+
+void adjustBrowseBoxColumnWidth( ::svt::EditBrowseBox* _pBox, sal_uInt16 _nColId )
+{
+ sal_Int32 nColSize = -1;
+ sal_uInt32 nDefaultWidth = _pBox->GetDefaultColumnWidth( _pBox->GetColumnTitle( _nColId ) );
+ if ( nDefaultWidth != _pBox->GetColumnWidth( _nColId ) )
+ {
+ Size aSizeMM = _pBox->PixelToLogic( Size( _pBox->GetColumnWidth( _nColId ), 0 ), MapMode( MapUnit::MapMM ) );
+ nColSize = aSizeMM.Width() * 10;
+ }
+
+ Size aDefaultMM = _pBox->PixelToLogic( Size( nDefaultWidth, 0 ), MapMode( MapUnit::MapMM ) );
+
+ DlgSize aColumnSizeDlg(_pBox->GetFrameWeld(), nColSize, false, aDefaultMM.Width() * 10);
+ if (aColumnSizeDlg.run() != RET_OK)
+ return;
+
+ sal_Int32 nValue = aColumnSizeDlg.GetValue();
+ if ( -1 == nValue )
+ { // default width
+ nValue = _pBox->GetDefaultColumnWidth( _pBox->GetColumnTitle( _nColId ) );
+ }
+ else
+ {
+ Size aSizeMM( nValue / 10, 0 );
+ nValue = _pBox->LogicToPixel( aSizeMM, MapMode( MapUnit::MapMM ) ).Width();
+ }
+ _pBox->SetColumnWidth( _nColId, nValue );
+}
+
+// check if SQL92 name checking is enabled
+bool isSQL92CheckEnabled(const Reference<XConnection>& _xConnection)
+{
+ return ::dbtools::getBooleanDataSourceSetting( _xConnection, PROPERTY_ENABLESQL92CHECK );
+}
+
+bool isAppendTableAliasEnabled(const Reference<XConnection>& _xConnection)
+{
+ return ::dbtools::getBooleanDataSourceSetting( _xConnection, INFO_APPEND_TABLE_ALIAS );
+}
+
+bool generateAsBeforeTableAlias(const Reference<XConnection>& _xConnection)
+{
+ return ::dbtools::getBooleanDataSourceSetting( _xConnection, INFO_AS_BEFORE_CORRELATION_NAME );
+}
+
+void fillAutoIncrementValue(const Reference<XPropertySet>& _xDatasource,
+ bool& _rAutoIncrementValueEnabled,
+ OUString& _rsAutoIncrementValue)
+{
+ if ( !_xDatasource.is() )
+ return;
+
+ OSL_ENSURE(_xDatasource->getPropertySetInfo()->hasPropertyByName(PROPERTY_INFO),"NO datasource supplied!");
+ Sequence<PropertyValue> aInfo;
+ _xDatasource->getPropertyValue(PROPERTY_INFO) >>= aInfo;
+
+ // search the right propertyvalue
+ const PropertyValue* pValue =std::find_if(std::cbegin(aInfo), std::cend(aInfo),
+ [](const PropertyValue& lhs)
+ {return lhs.Name == PROPERTY_AUTOINCREMENTCREATION;} );
+
+ if ( pValue != std::cend(aInfo) )
+ pValue->Value >>= _rsAutoIncrementValue;
+ pValue =std::find_if(std::cbegin(aInfo), std::cend(aInfo),
+ [](const PropertyValue& lhs)
+ {return lhs.Name == "IsAutoRetrievingEnabled";} );
+
+ if ( pValue != std::cend(aInfo) )
+ pValue->Value >>= _rAutoIncrementValueEnabled;
+}
+
+void fillAutoIncrementValue(const Reference<XConnection>& _xConnection,
+ bool& _rAutoIncrementValueEnabled,
+ OUString& _rsAutoIncrementValue)
+{
+ Reference< XChild> xChild(_xConnection,UNO_QUERY);
+ if(xChild.is())
+ {
+ Reference< XPropertySet> xProp(xChild->getParent(),UNO_QUERY);
+ fillAutoIncrementValue(xProp,_rAutoIncrementValueEnabled,_rsAutoIncrementValue);
+ }
+}
+
+OUString getStrippedDatabaseName(const Reference<XPropertySet>& _xDataSource,OUString& _rsDatabaseName)
+{
+ if ( _rsDatabaseName.isEmpty() && _xDataSource.is() )
+ {
+ try
+ {
+ _xDataSource->getPropertyValue(PROPERTY_NAME) >>= _rsDatabaseName;
+ }
+ catch(const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+ OUString sName = _rsDatabaseName;
+ INetURLObject aURL(sName);
+ if ( aURL.GetProtocol() != INetProtocol::NotValid )
+ sName = aURL.getBase(INetURLObject::LAST_SEGMENT,true,INetURLObject::DecodeMechanism::Unambiguous);
+ return sName;
+}
+
+void setEvalDateFormatForFormatter(Reference< css::util::XNumberFormatter > const & _rxFormatter)
+{
+ OSL_ENSURE( _rxFormatter.is(),"setEvalDateFormatForFormatter: Formatter is NULL!");
+ if ( !_rxFormatter.is() )
+ return;
+
+ Reference< css::util::XNumberFormatsSupplier > xSupplier = _rxFormatter->getNumberFormatsSupplier();
+
+ auto pSupplierImpl = comphelper::getFromUnoTunnel<SvNumberFormatsSupplierObj>(xSupplier);
+ OSL_ENSURE(pSupplierImpl,"No Supplier!");
+
+ if ( pSupplierImpl )
+ {
+ SvNumberFormatter* pFormatter = pSupplierImpl->GetNumberFormatter();
+ pFormatter->SetEvalDateFormat(NF_EVALDATEFORMAT_FORMAT);
+ }
+}
+
+TOTypeInfoSP queryPrimaryKeyType(const OTypeInfoMap& _rTypeInfo)
+{
+ TOTypeInfoSP pTypeInfo;
+ // first we search for a type which supports autoIncrement
+ for (auto const& elem : _rTypeInfo)
+ {
+ // OJ: we don't want to set an autoincrement column to be key
+ // because we don't have the possibility to know how to create
+ // such auto increment column later on
+ // so until we know how to do it, we create a column without autoincrement
+ // therefore we have searched
+ if ( elem.second->nType == DataType::INTEGER )
+ {
+ pTypeInfo = elem.second; // alternative
+ break;
+ }
+ else if ( !pTypeInfo && elem.second->nType == DataType::DOUBLE )
+ pTypeInfo = elem.second; // alternative
+ else if ( !pTypeInfo && elem.second->nType == DataType::REAL )
+ pTypeInfo = elem.second; // alternative
+ }
+ if ( !pTypeInfo ) // just a fallback
+ pTypeInfo = queryTypeInfoByType(DataType::VARCHAR,_rTypeInfo);
+
+ OSL_ENSURE(pTypeInfo,"checkColumns: can't find a type which is usable as a key!");
+ return pTypeInfo;
+}
+
+TOTypeInfoSP queryTypeInfoByType(sal_Int32 _nDataType,const OTypeInfoMap& _rTypeInfo)
+{
+ OTypeInfoMap::const_iterator aIter = _rTypeInfo.find(_nDataType);
+ if(aIter != _rTypeInfo.end())
+ return aIter->second;
+ // fall back if the type is unknown
+ TOTypeInfoSP pTypeInfo;
+ switch(_nDataType)
+ {
+ case DataType::TINYINT:
+ if( (pTypeInfo = queryTypeInfoByType(DataType::SMALLINT,_rTypeInfo) ) )
+ break;
+ [[fallthrough]];
+ case DataType::SMALLINT:
+ if( (pTypeInfo = queryTypeInfoByType(DataType::INTEGER,_rTypeInfo) ) )
+ break;
+ [[fallthrough]];
+ case DataType::INTEGER:
+ if( (pTypeInfo = queryTypeInfoByType(DataType::FLOAT,_rTypeInfo) ) )
+ break;
+ [[fallthrough]];
+ case DataType::FLOAT:
+ if( (pTypeInfo = queryTypeInfoByType(DataType::REAL,_rTypeInfo) ) )
+ break;
+ [[fallthrough]];
+ case DataType::DATE:
+ case DataType::TIME:
+ if( DataType::DATE == _nDataType || DataType::TIME == _nDataType )
+ {
+ if( (pTypeInfo = queryTypeInfoByType(DataType::TIMESTAMP,_rTypeInfo) ) )
+ break;
+ }
+ [[fallthrough]];
+ case DataType::TIMESTAMP:
+ case DataType::REAL:
+ case DataType::BIGINT:
+ if ( (pTypeInfo = queryTypeInfoByType(DataType::DOUBLE,_rTypeInfo) ) )
+ break;
+ [[fallthrough]];
+ case DataType::DOUBLE:
+ if ( (pTypeInfo = queryTypeInfoByType(DataType::NUMERIC,_rTypeInfo) ) )
+ break;
+ [[fallthrough]];
+ case DataType::NUMERIC:
+ pTypeInfo = queryTypeInfoByType(DataType::DECIMAL,_rTypeInfo);
+ break;
+ case DataType::DECIMAL:
+ if ( (pTypeInfo = queryTypeInfoByType(DataType::NUMERIC,_rTypeInfo) ) )
+ break;
+ if ( (pTypeInfo = queryTypeInfoByType(DataType::DOUBLE,_rTypeInfo) ) )
+ break;
+ break;
+ case DataType::VARCHAR:
+ if ( (pTypeInfo = queryTypeInfoByType(DataType::LONGVARCHAR,_rTypeInfo) ) )
+ break;
+ break;
+ case DataType::LONGVARCHAR:
+ if ( (pTypeInfo = queryTypeInfoByType(DataType::CLOB,_rTypeInfo) ) )
+ break;
+ break;
+ default:
+ ;
+ }
+ if ( !pTypeInfo )
+ {
+ bool bForce = true;
+ pTypeInfo = ::dbaui::getTypeInfoFromType(_rTypeInfo,DataType::VARCHAR,OUString(),"x",50,0,false,bForce);
+ }
+ OSL_ENSURE(pTypeInfo,"Wrong DataType supplied!");
+ return pTypeInfo;
+}
+
+sal_Int32 askForUserAction(weld::Window* pParent, TranslateId pTitle, TranslateId pText, bool _bAll, std::u16string_view _sName)
+{
+ SolarMutexGuard aGuard;
+ OUString aMsg = DBA_RES(pText);
+ aMsg = aMsg.replaceFirst("%1", _sName);
+ OSQLMessageBox aAsk(pParent, DBA_RES(pTitle), aMsg, MessBoxStyle::YesNo | MessBoxStyle::DefaultYes, MessageType::Query);
+ if ( _bAll )
+ {
+ aAsk.add_button(DBA_RES(STR_BUTTON_TEXT_ALL), RET_ALL, HID_CONFIRM_DROP_BUTTON_ALL);
+ }
+ return aAsk.run();
+}
+
+namespace
+{
+ OUString lcl_createSDBCLevelStatement( const OUString& _rStatement, const Reference< XConnection >& _rxConnection )
+ {
+ OUString sSDBCLevelStatement( _rStatement );
+ try
+ {
+ Reference< XMultiServiceFactory > xAnalyzerFactory( _rxConnection, UNO_QUERY_THROW );
+ Reference< XSingleSelectQueryAnalyzer > xAnalyzer( xAnalyzerFactory->createInstance( SERVICE_NAME_SINGLESELECTQUERYCOMPOSER ), UNO_QUERY_THROW );
+ xAnalyzer->setQuery( _rStatement );
+ sSDBCLevelStatement = xAnalyzer->getQueryWithSubstitution();
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ return sSDBCLevelStatement;
+ }
+}
+
+Reference< XPropertySet > createView( const OUString& _rName, const Reference< XConnection >& _rxConnection,
+ const OUString& _rCommand )
+{
+ Reference<XViewsSupplier> xSup(_rxConnection,UNO_QUERY);
+ Reference< XNameAccess > xViews;
+ if(xSup.is())
+ xViews = xSup->getViews();
+ Reference<XDataDescriptorFactory> xFact(xViews,UNO_QUERY);
+ OSL_ENSURE(xFact.is(),"No XDataDescriptorFactory available!");
+ if(!xFact.is())
+ return nullptr;
+
+ Reference<XPropertySet> xView = xFact->createDataDescriptor();
+ if ( !xView.is() )
+ return nullptr;
+
+ OUString sCatalog,sSchema,sTable;
+ ::dbtools::qualifiedNameComponents(_rxConnection->getMetaData(),
+ _rName,
+ sCatalog,
+ sSchema,
+ sTable,
+ ::dbtools::EComposeRule::InDataManipulation);
+
+ xView->setPropertyValue(PROPERTY_CATALOGNAME,Any(sCatalog));
+ xView->setPropertyValue(PROPERTY_SCHEMANAME,Any(sSchema));
+ xView->setPropertyValue(PROPERTY_NAME,Any(sTable));
+
+ xView->setPropertyValue( PROPERTY_COMMAND, Any( _rCommand ) );
+
+ Reference<XAppend> xAppend(xViews,UNO_QUERY);
+ if(xAppend.is())
+ xAppend->appendByDescriptor(xView);
+
+ xView = nullptr;
+ // we need to reget the view because after appending it, it is no longer valid
+ // but this time it isn't a view object it is a table object with type "VIEW"
+ Reference<XTablesSupplier> xTabSup(_rxConnection,UNO_QUERY);
+ Reference< XNameAccess > xTables;
+ if ( xTabSup.is() )
+ {
+ xTables = xTabSup->getTables();
+ if ( xTables.is() && xTables->hasByName( _rName ) )
+ xTables->getByName( _rName ) >>= xView;
+ }
+
+ return xView;
+}
+
+Reference<XPropertySet> createView( const OUString& _rName, const Reference< XConnection >& _rxConnection
+ ,const Reference<XPropertySet>& _rxSourceObject)
+{
+ OUString sCommand;
+ Reference< XPropertySetInfo > xPSI( _rxSourceObject->getPropertySetInfo(), UNO_SET_THROW );
+ if ( xPSI->hasPropertyByName( PROPERTY_COMMAND ) )
+ {
+ _rxSourceObject->getPropertyValue( PROPERTY_COMMAND ) >>= sCommand;
+
+ bool bEscapeProcessing( false );
+ OSL_VERIFY( _rxSourceObject->getPropertyValue( PROPERTY_ESCAPE_PROCESSING ) >>= bEscapeProcessing );
+ if ( bEscapeProcessing )
+ sCommand = lcl_createSDBCLevelStatement( sCommand, _rxConnection );
+ }
+ else
+ {
+ sCommand = "SELECT * FROM " + composeTableNameForSelect( _rxConnection, _rxSourceObject );
+ }
+ return createView( _rName, _rxConnection, sCommand );
+}
+
+bool insertHierarchyElement(weld::Window* pParent, const Reference< XComponentContext >& _rxContext,
+ const Reference<XHierarchicalNameContainer>& _xNames,
+ const OUString& _sParentFolder,
+ bool _bForm,
+ bool _bCollection,
+ const Reference<XContent>& _xContent,
+ bool _bMove)
+{
+ OSL_ENSURE( _xNames.is(), "insertHierarchyElement: illegal name container!" );
+ if ( !_xNames.is() )
+ return false;
+
+ Reference<XNameAccess> xNameAccess( _xNames, UNO_QUERY );
+ if ( _xNames->hasByHierarchicalName(_sParentFolder) )
+ {
+ Reference<XChild> xChild(_xNames->getByHierarchicalName(_sParentFolder),UNO_QUERY);
+ xNameAccess.set(xChild,UNO_QUERY);
+ if ( !xNameAccess.is() && xChild.is() )
+ xNameAccess.set(xChild->getParent(),UNO_QUERY);
+ }
+
+ OSL_ENSURE( xNameAccess.is(), "insertHierarchyElement: could not find the proper name container!" );
+ if ( !xNameAccess.is() )
+ return false;
+
+ OUString sNewName;
+ Reference<XPropertySet> xProp(_xContent,UNO_QUERY);
+ if ( xProp.is() )
+ xProp->getPropertyValue(PROPERTY_NAME) >>= sNewName;
+
+ if ( !_bMove || sNewName.isEmpty() )
+ {
+ if ( sNewName.isEmpty() || xNameAccess->hasByName(sNewName) )
+ {
+ OUString sLabel, sTargetName;
+ if ( !sNewName.isEmpty() )
+ sTargetName = sNewName;
+ else
+ sTargetName = DBA_RES( _bCollection ? STR_NEW_FOLDER : ((_bForm) ? RID_STR_FORM : RID_STR_REPORT));
+ sLabel = DBA_RES( _bCollection ? STR_FOLDER_LABEL : ((_bForm) ? STR_FRM_LABEL : STR_RPT_LABEL));
+ sTargetName = ::dbtools::createUniqueName(xNameAccess,sTargetName);
+
+ // here we have everything needed to create a new query object ...
+ HierarchicalNameCheck aNameChecker( _xNames, _sParentFolder );
+ // ... ehm, except a new name
+ OSaveAsDlg aAskForName(pParent,
+ _rxContext,
+ sTargetName,
+ sLabel,
+ aNameChecker,
+ SADFlags::AdditionalDescription | SADFlags::TitlePasteAs);
+ if ( RET_OK != aAskForName.run() )
+ // cancelled by the user
+ return false;
+
+ sNewName = aAskForName.getName();
+ }
+ }
+ else if ( xNameAccess->hasByName(sNewName) )
+ {
+ OUString sError(DBA_RES(STR_NAME_ALREADY_EXISTS));
+ sError = sError.replaceFirst("#",sNewName);
+ throw SQLException(sError,nullptr,"S1000",0,Any());
+ }
+
+ try
+ {
+ Reference<XMultiServiceFactory> xORB( xNameAccess, UNO_QUERY_THROW );
+ uno::Sequence<uno::Any> aArguments(comphelper::InitAnyPropertySequence(
+ {
+ {"Name", uno::Any(sNewName)}, // set as folder
+ {"Parent", uno::Any(xNameAccess)},
+ {PROPERTY_EMBEDDEDOBJECT, uno::Any(_xContent)},
+ }));
+ OUString sServiceName(_bCollection ? (_bForm ? OUString(SERVICE_NAME_FORM_COLLECTION) : OUString(SERVICE_NAME_REPORT_COLLECTION)) : OUString(SERVICE_SDB_DOCUMENTDEFINITION));
+
+ Reference<XContent > xNew( xORB->createInstanceWithArguments( sServiceName, aArguments ), UNO_QUERY_THROW );
+ Reference< XNameContainer > xNameContainer( xNameAccess, UNO_QUERY_THROW );
+ xNameContainer->insertByName( sNewName, Any( xNew ) );
+ }
+ catch( const IllegalArgumentException& e )
+ {
+ ::dbtools::throwGenericSQLException( e.Message, e.Context );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ return false;
+ }
+
+ return true;
+}
+
+Reference< XNumberFormatter > getNumberFormatter(const Reference< XConnection >& _rxConnection, const Reference< css::uno::XComponentContext >& _rxContext )
+{
+ // create a formatter working with the connections format supplier
+ Reference< XNumberFormatter > xFormatter;
+
+ try
+ {
+ Reference< css::util::XNumberFormatsSupplier > xSupplier(::dbtools::getNumberFormats(_rxConnection, true, _rxContext));
+
+ if ( xSupplier.is() )
+ {
+ // create a new formatter
+ xFormatter.set(util::NumberFormatter::create( _rxContext ), UNO_QUERY_THROW);
+ xFormatter->attachNumberFormatsSupplier(xSupplier);
+ }
+ }
+ catch(const Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ return xFormatter;
+}
+
+} // dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/misc/UpdateHelperImpl.hxx b/dbaccess/source/ui/misc/UpdateHelperImpl.hxx
new file mode 100644
index 000000000..9f8d0d399
--- /dev/null
+++ b/dbaccess/source/ui/misc/UpdateHelperImpl.hxx
@@ -0,0 +1,74 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <com/sun/star/sdbc/XParameters.hpp>
+#include <com/sun/star/sdbc/XPreparedStatement.hpp>
+#include <IUpdateHelper.hxx>
+
+namespace dbaui
+{
+ class OParameterUpdateHelper : public IUpdateHelper
+ {
+ css::uno::Reference< css::sdbc::XPreparedStatement > m_xPrepared;
+ css::uno::Reference< css::sdbc::XParameters > m_xParameters;
+
+ public:
+ explicit OParameterUpdateHelper(const css::uno::Reference< css::sdbc::XPreparedStatement >& _xPrepared)
+ :m_xPrepared(_xPrepared)
+ ,m_xParameters(_xPrepared,css::uno::UNO_QUERY)
+ {
+ }
+ virtual ~OParameterUpdateHelper() {}
+ virtual void updateString(sal_Int32 _nPos, const OUString& _sValue) override
+ {
+ m_xParameters->setString(_nPos, _sValue);
+ }
+ virtual void updateDouble(sal_Int32 _nPos,const double& _nValue) override
+ {
+ m_xParameters->setDouble(_nPos, _nValue);
+ }
+ virtual void updateDate(sal_Int32 _nPos,const css::util::Date& _nValue) override
+ {
+ m_xParameters->setDate(_nPos, _nValue);
+ }
+ virtual void updateTime(sal_Int32 _nPos,const css::util::Time& _nValue) override
+ {
+ m_xParameters->setTime(_nPos, _nValue);
+ }
+ virtual void updateTimestamp(sal_Int32 _nPos,const css::util::DateTime& _nValue) override
+ {
+ m_xParameters->setTimestamp(_nPos, _nValue);
+ }
+ virtual void updateInt(sal_Int32 _nPos, sal_Int32 _nValue) override
+ {
+ m_xParameters->setInt(_nPos, _nValue);
+ }
+ virtual void updateNull(sal_Int32 _nPos, ::sal_Int32 sqlType) override
+ {
+ m_xParameters->setNull(_nPos,sqlType);
+ }
+ virtual void insertRow() override
+ {
+ m_xPrepared->executeUpdate();
+ }
+ };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/misc/WCPage.cxx b/dbaccess/source/ui/misc/WCPage.cxx
new file mode 100644
index 000000000..602edd2d6
--- /dev/null
+++ b/dbaccess/source/ui/misc/WCPage.cxx
@@ -0,0 +1,325 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <WCPage.hxx>
+#include <WCopyTable.hxx>
+
+#include <defaultobjectnamecheck.hxx>
+#include <strings.hrc>
+#include <core_resource.hxx>
+#include <com/sun/star/sdb/CommandType.hpp>
+#include <com/sun/star/sdbcx/XTablesSupplier.hpp>
+#include <com/sun/star/sdb/application/CopyTableOperation.hpp>
+#include <connectivity/dbexception.hxx>
+#include <connectivity/dbtools.hxx>
+
+using namespace ::dbaui;
+using namespace ::dbtools;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::util;
+using namespace ::com::sun::star::sdb;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::sdbcx;
+
+namespace CopyTableOperation = css::sdb::application::CopyTableOperation;
+
+OCopyTable::OCopyTable(weld::Container* pPage, OCopyTableWizard* pWizard)
+ : OWizardPage(pPage, pWizard, "dbaccess/ui/copytablepage.ui", "CopyTablePage")
+ , m_bPKeyAllowed(false)
+ , m_bUseHeaderAllowed(true)
+ , m_nOldOperation(0)
+ , m_xEdTableName(m_xBuilder->weld_entry("name"))
+ , m_xRB_DefData(m_xBuilder->weld_radio_button("defdata"))
+ , m_xRB_Def(m_xBuilder->weld_radio_button("def"))
+ , m_xRB_View(m_xBuilder->weld_radio_button("view"))
+ , m_xRB_AppendData(m_xBuilder->weld_radio_button("data"))
+ , m_xCB_UseHeaderLine(m_xBuilder->weld_check_button("firstline"))
+ , m_xCB_PrimaryColumn(m_xBuilder->weld_check_button("primarykey"))
+ , m_xFT_KeyName(m_xBuilder->weld_label("keynamelabel"))
+ , m_xEdKeyName(m_xBuilder->weld_entry("keyname"))
+{
+ if ( m_pParent->m_xDestConnection.is() )
+ {
+ if (!m_pParent->supportsViews())
+ m_xRB_View->set_sensitive(false);
+
+ m_xCB_UseHeaderLine->set_active(true);
+ m_bPKeyAllowed = m_pParent->supportsPrimaryKey();
+
+ m_xCB_PrimaryColumn->set_sensitive(m_bPKeyAllowed);
+
+ m_xRB_AppendData->connect_toggled( LINK( this, OCopyTable, RadioChangeHdl ) );
+ m_xRB_DefData->connect_toggled( LINK( this, OCopyTable, RadioChangeHdl ) );
+ m_xRB_Def->connect_toggled( LINK( this, OCopyTable, RadioChangeHdl ) );
+ m_xRB_View->connect_toggled( LINK( this, OCopyTable, RadioChangeHdl ) );
+
+ m_xCB_PrimaryColumn->connect_toggled(LINK( this, OCopyTable, KeyClickHdl ) );
+
+ m_xFT_KeyName->set_sensitive(false);
+ m_xEdKeyName->set_sensitive(false);
+ m_xEdKeyName->set_text(m_pParent->createUniqueName("ID"));
+
+ const sal_Int32 nMaxLen = m_pParent->getMaxColumnNameLength();
+ m_xEdKeyName->set_max_length(nMaxLen);
+ }
+
+ SetPageTitle(DBA_RES(STR_COPYTABLE_TITLE_COPY));
+}
+
+OCopyTable::~OCopyTable()
+{
+}
+
+void OCopyTable::SetAppendDataRadio()
+{
+ m_pParent->EnableNextButton(true);
+ m_xFT_KeyName->set_sensitive(false);
+ m_xCB_PrimaryColumn->set_sensitive(false);
+ m_xEdKeyName->set_sensitive(false);
+ m_pParent->setOperation(CopyTableOperation::AppendData);
+}
+
+IMPL_LINK(OCopyTable, RadioChangeHdl, weld::Toggleable&, rButton, void)
+{
+ if (!rButton.get_active())
+ return;
+ if (m_xRB_AppendData->get_active())
+ {
+ SetAppendDataRadio();
+ return;
+ }
+ m_pParent->EnableNextButton(!m_xRB_View->get_active());
+ bool bKey = m_bPKeyAllowed && !m_xRB_View->get_active();
+ m_xFT_KeyName->set_sensitive(bKey && m_xCB_PrimaryColumn->get_active());
+ m_xEdKeyName->set_sensitive(bKey && m_xCB_PrimaryColumn->get_active());
+ m_xCB_PrimaryColumn->set_sensitive(bKey);
+ m_xCB_UseHeaderLine->set_sensitive(m_bUseHeaderAllowed && IsOptionDefData());
+
+ // set type what to do
+ if( IsOptionDefData() )
+ m_pParent->setOperation( CopyTableOperation::CopyDefinitionAndData );
+ else if( IsOptionDef() )
+ m_pParent->setOperation( CopyTableOperation::CopyDefinitionOnly );
+ else if( IsOptionView() )
+ m_pParent->setOperation( CopyTableOperation::CreateAsView );
+}
+
+IMPL_LINK_NOARG( OCopyTable, KeyClickHdl, weld::Toggleable&, void )
+{
+ m_xEdKeyName->set_sensitive(m_xCB_PrimaryColumn->get_active());
+ m_xFT_KeyName->set_sensitive(m_xCB_PrimaryColumn->get_active());
+}
+
+bool OCopyTable::LeavePage()
+{
+ m_pParent->m_bCreatePrimaryKeyColumn = m_bPKeyAllowed && m_xCB_PrimaryColumn->get_sensitive() && m_xCB_PrimaryColumn->get_active();
+ m_pParent->m_aKeyName = m_pParent->m_bCreatePrimaryKeyColumn ? m_xEdKeyName->get_text() : OUString();
+ m_pParent->setUseHeaderLine( m_xCB_UseHeaderLine->get_active() );
+
+ // first check if the table already exists in the database
+ if( m_pParent->getOperation() != CopyTableOperation::AppendData )
+ {
+ m_pParent->clearDestColumns();
+ DynamicTableOrQueryNameCheck aNameCheck( m_pParent->m_xDestConnection, CommandType::TABLE );
+ SQLExceptionInfo aErrorInfo;
+ if ( !aNameCheck.isNameValid( m_xEdTableName->get_text(), aErrorInfo ) )
+ {
+ aErrorInfo.append( SQLExceptionInfo::TYPE::SQLContext, DBA_RES( STR_SUGGEST_APPEND_TABLE_DATA ) );
+ m_pParent->showError(aErrorInfo.get());
+
+ return false;
+ }
+
+ // have to check the length of the table name
+ Reference< XDatabaseMetaData > xMeta = m_pParent->m_xDestConnection->getMetaData();
+ OUString sCatalog;
+ OUString sSchema;
+ OUString sTable;
+ ::dbtools::qualifiedNameComponents( xMeta,
+ m_xEdTableName->get_text(),
+ sCatalog,
+ sSchema,
+ sTable,
+ ::dbtools::EComposeRule::InDataManipulation);
+ sal_Int32 nMaxLength = xMeta->getMaxTableNameLength();
+ if ( nMaxLength && sTable.getLength() > nMaxLength )
+ {
+ m_pParent->showError(DBA_RES(STR_INVALID_TABLE_NAME_LENGTH));
+ return false;
+ }
+
+ // now we have to check if the name of the primary key already exists
+ if ( m_pParent->m_bCreatePrimaryKeyColumn
+ && m_pParent->m_aKeyName != m_pParent->createUniqueName(m_pParent->m_aKeyName) )
+ {
+ m_pParent->showError(DBA_RES(STR_WIZ_NAME_ALREADY_DEFINED) + " " + m_pParent->m_aKeyName);
+ return false;
+ }
+ }
+
+ if (m_xEdTableName->get_value_changed_from_saved())
+ { // table exists and name has changed
+ if ( m_pParent->getOperation() == CopyTableOperation::AppendData )
+ {
+ if(!checkAppendData())
+ return false;
+ }
+ else if ( m_nOldOperation == CopyTableOperation::AppendData )
+ {
+ m_xEdTableName->save_value();
+ return LeavePage();
+ }
+ }
+ else
+ { // table exist and is not new or doesn't exist and so on
+ if ( CopyTableOperation::AppendData == m_pParent->getOperation() )
+ {
+ if( !checkAppendData() )
+ return false;
+ }
+ }
+ m_pParent->m_sName = m_xEdTableName->get_text();
+ m_xEdTableName->save_value();
+
+ if(m_pParent->m_sName.isEmpty())
+ {
+ m_pParent->showError(DBA_RES(STR_INVALID_TABLE_NAME));
+ return false;
+ }
+
+ return true;
+}
+
+void OCopyTable::Activate()
+{
+ m_pParent->GetOKButton().set_sensitive(true);
+ m_nOldOperation = m_pParent->getOperation();
+ m_xEdTableName->grab_focus();
+ m_xCB_UseHeaderLine->set_active(m_pParent->UseHeaderLine());
+}
+
+OUString OCopyTable::GetTitle() const
+{
+ return DBA_RES(STR_WIZ_TABLE_COPY);
+}
+
+void OCopyTable::Reset()
+{
+ m_bFirstTime = false;
+
+ m_xEdTableName->set_text( m_pParent->m_sName );
+ m_xEdTableName->save_value();
+}
+
+bool OCopyTable::checkAppendData()
+{
+ m_pParent->clearDestColumns();
+ Reference< XPropertySet > xTable;
+ Reference< XTablesSupplier > xSup( m_pParent->m_xDestConnection, UNO_QUERY );
+ Reference<XNameAccess> xTables;
+ if (xSup.is())
+ xTables = xSup->getTables();
+ if (xTables.is() && xTables->hasByName(m_xEdTableName->get_text()))
+ {
+ const ODatabaseExport::TColumnVector& rSrcColumns = m_pParent->getSrcVector();
+ const sal_uInt32 nSrcSize = rSrcColumns.size();
+ m_pParent->m_vColumnPositions.resize( nSrcSize, ODatabaseExport::TPositions::value_type( COLUMN_POSITION_NOT_FOUND, COLUMN_POSITION_NOT_FOUND ) );
+ m_pParent->m_vColumnTypes.resize( nSrcSize , COLUMN_POSITION_NOT_FOUND );
+
+ // set new destination
+ xTables->getByName( m_xEdTableName->get_text() ) >>= xTable;
+ ObjectCopySource aTableCopySource( m_pParent->m_xDestConnection, xTable );
+ m_pParent->loadData( aTableCopySource, m_pParent->m_vDestColumns, m_pParent->m_aDestVec );
+ const ODatabaseExport::TColumnVector& rDestColumns = m_pParent->getDestVector();
+ const sal_uInt32 nMinSrcDestSize = std::min<sal_uInt32>(nSrcSize, rDestColumns.size());
+ sal_uInt32 i = 0;
+ for (auto const& column : rDestColumns)
+ {
+ if (i >= nMinSrcDestSize)
+ break;
+ bool bNotConvert = true;
+ m_pParent->m_vColumnPositions[i] = ODatabaseExport::TPositions::value_type(i+1,i+1);
+ TOTypeInfoSP pTypeInfo = m_pParent->convertType(column->second->getSpecialTypeInfo(),bNotConvert);
+ if ( !bNotConvert )
+ {
+ m_pParent->showColumnTypeNotSupported(column->first);
+ return false;
+ }
+
+ if ( pTypeInfo )
+ m_pParent->m_vColumnTypes[i] = pTypeInfo->nType;
+ else
+ m_pParent->m_vColumnTypes[i] = DataType::VARCHAR;
+ ++i;
+ }
+
+ }
+
+ if ( !xTable.is() )
+ {
+ m_pParent->showError(DBA_RES(STR_INVALID_TABLE_NAME));
+ return false;
+ }
+ return true;
+}
+
+void OCopyTable::setCreatePrimaryKey( bool _bDoCreate, const OUString& _rSuggestedName )
+{
+ bool bCreatePK = m_bPKeyAllowed && _bDoCreate;
+ m_xCB_PrimaryColumn->set_active( bCreatePK );
+ m_xEdKeyName->set_text( _rSuggestedName );
+
+ m_xFT_KeyName->set_sensitive( bCreatePK );
+ m_xEdKeyName->set_sensitive( bCreatePK );
+}
+
+void OCopyTable::setCreateStyleAction()
+{
+ // reselect the last action before
+ switch (m_pParent->getOperation())
+ {
+ case CopyTableOperation::CopyDefinitionAndData:
+ m_xRB_DefData->set_active(true);
+ RadioChangeHdl(*m_xRB_DefData);
+ break;
+ case CopyTableOperation::CopyDefinitionOnly:
+ m_xRB_Def->set_active(true);
+ RadioChangeHdl(*m_xRB_Def);
+ break;
+ case CopyTableOperation::AppendData:
+ m_xRB_AppendData->set_active(true);
+ SetAppendDataRadio();
+ break;
+ case CopyTableOperation::CreateAsView:
+ if (m_xRB_View->get_sensitive())
+ {
+ m_xRB_View->set_active(true);
+ RadioChangeHdl(*m_xRB_View);
+ }
+ else
+ {
+ m_xRB_DefData->set_active(true);
+ RadioChangeHdl(*m_xRB_DefData);
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/misc/WColumnSelect.cxx b/dbaccess/source/ui/misc/WColumnSelect.cxx
new file mode 100644
index 000000000..8937cfb2d
--- /dev/null
+++ b/dbaccess/source/ui/misc/WColumnSelect.cxx
@@ -0,0 +1,403 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <WColumnSelect.hxx>
+#include <strings.hrc>
+#include <osl/diagnose.h>
+#include <WCopyTable.hxx>
+#include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
+#include <core_resource.hxx>
+#include <com/sun/star/sdb/application/CopyTableOperation.hpp>
+
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::sdbcx;
+using namespace dbaui;
+
+namespace CopyTableOperation = ::com::sun::star::sdb::application::CopyTableOperation;
+
+OUString OWizColumnSelect::GetTitle() const { return DBA_RES(STR_WIZ_COLUMN_SELECT_TITLE); }
+
+OWizardPage::OWizardPage(weld::Container* pPage, OCopyTableWizard* pWizard, const OUString& rUIXMLDescription, const OString& rID)
+ : ::vcl::OWizardPage(pPage, pWizard, rUIXMLDescription, rID)
+ , m_pParent(pWizard)
+ , m_bFirstTime(true)
+{
+}
+
+OWizardPage::~OWizardPage()
+{
+}
+
+// OWizColumnSelect
+OWizColumnSelect::OWizColumnSelect(weld::Container* pPage, OCopyTableWizard* pWizard)
+ : OWizardPage(pPage, pWizard, "dbaccess/ui/applycolpage.ui", "ApplyColPage")
+ , m_xOrgColumnNames(m_xBuilder->weld_tree_view("from"))
+ , m_xColumn_RH(m_xBuilder->weld_button("colrh"))
+ , m_xColumns_RH(m_xBuilder->weld_button("colsrh"))
+ , m_xColumn_LH(m_xBuilder->weld_button("collh"))
+ , m_xColumns_LH(m_xBuilder->weld_button("colslh"))
+ , m_xNewColumnNames(m_xBuilder->weld_tree_view("to"))
+{
+ m_xColumn_RH->connect_clicked(LINK(this,OWizColumnSelect,ButtonClickHdl));
+ m_xColumn_LH->connect_clicked(LINK(this,OWizColumnSelect,ButtonClickHdl));
+ m_xColumns_RH->connect_clicked(LINK(this,OWizColumnSelect,ButtonClickHdl));
+ m_xColumns_LH->connect_clicked(LINK(this,OWizColumnSelect,ButtonClickHdl));
+
+ m_xOrgColumnNames->set_selection_mode(SelectionMode::Multiple);
+ m_xNewColumnNames->set_selection_mode(SelectionMode::Multiple);
+
+ m_xOrgColumnNames->connect_row_activated(LINK(this,OWizColumnSelect,ListDoubleClickHdl));
+ m_xNewColumnNames->connect_row_activated(LINK(this,OWizColumnSelect,ListDoubleClickHdl));
+}
+
+OWizColumnSelect::~OWizColumnSelect()
+{
+ while (m_xNewColumnNames->n_children())
+ {
+ delete weld::fromId<OFieldDescription*>(m_xNewColumnNames->get_id(0));
+ m_xNewColumnNames->remove(0);
+ }
+}
+
+void OWizColumnSelect::Reset()
+{
+ // restore original state
+ clearListBox(*m_xOrgColumnNames);
+ clearListBox(*m_xNewColumnNames);
+ m_pParent->m_mNameMapping.clear();
+
+ // insert the source columns in the left listbox
+ const ODatabaseExport::TColumnVector& rSrcColumns = m_pParent->getSrcVector();
+
+ for (auto const& column : rSrcColumns)
+ {
+ OUString sId(weld::toId(column->second));
+ m_xOrgColumnNames->append(sId, column->first);
+ }
+
+ if (m_xOrgColumnNames->n_children())
+ m_xOrgColumnNames->select(0);
+
+ m_bFirstTime = false;
+}
+
+void OWizColumnSelect::Activate( )
+{
+ // if there are no dest columns reset the left side with the original columns
+ if(m_pParent->getDestColumns().empty())
+ Reset();
+
+ clearListBox(*m_xNewColumnNames);
+
+ const ODatabaseExport::TColumnVector& rDestColumns = m_pParent->getDestVector();
+
+ // tdf#113923, the added columns must exist in the table
+ // in the case where:
+ // 1: we enabled the creation of a primary key
+ // 2: we come back here from the "Back" button of the next page,
+ // we want to avoid to list the new column generated in the next page
+ const ODatabaseExport::TColumns& rSrcColumns = m_pParent->getSourceColumns();
+
+ for (auto const& column : rDestColumns)
+ {
+ if (rSrcColumns.find(column->first) != rSrcColumns.end())
+ {
+ OUString sId(weld::toId(new OFieldDescription(*(column->second))));
+ m_xNewColumnNames->append(sId, column->first);
+ int nRemove = m_xOrgColumnNames->find_text(column->first);
+ if (nRemove != -1)
+ m_xOrgColumnNames->remove(nRemove);
+ }
+ }
+ m_pParent->GetOKButton().set_sensitive(m_xNewColumnNames->n_children() != 0);
+ m_pParent->EnableNextButton(m_xNewColumnNames->n_children() && m_pParent->getOperation() != CopyTableOperation::AppendData);
+ m_xColumns_RH->grab_focus();
+}
+
+bool OWizColumnSelect::LeavePage()
+{
+
+ m_pParent->clearDestColumns();
+
+ for(sal_Int32 i=0 ; i< m_xNewColumnNames->n_children();++i)
+ {
+ OFieldDescription* pField = weld::fromId<OFieldDescription*>(m_xNewColumnNames->get_id(i));
+ OSL_ENSURE(pField,"The field information can not be null!");
+ m_pParent->insertColumn(i,pField);
+ }
+
+ clearListBox(*m_xNewColumnNames);
+
+ if ( m_pParent->GetPressedButton() == OCopyTableWizard::WIZARD_NEXT
+ || m_pParent->GetPressedButton() == OCopyTableWizard::WIZARD_FINISH
+ )
+ return !m_pParent->getDestColumns().empty();
+ else
+ return true;
+}
+
+IMPL_LINK(OWizColumnSelect, ButtonClickHdl, weld::Button&, rButton, void)
+{
+ weld::TreeView *pLeft = nullptr;
+ weld::TreeView *pRight = nullptr;
+ bool bAll = false;
+
+ if (&rButton == m_xColumn_RH.get())
+ {
+ pLeft = m_xOrgColumnNames.get();
+ pRight = m_xNewColumnNames.get();
+ }
+ else if (&rButton == m_xColumn_LH.get())
+ {
+ pLeft = m_xNewColumnNames.get();
+ pRight = m_xOrgColumnNames.get();
+ }
+ else if (&rButton == m_xColumns_RH.get())
+ {
+ pLeft = m_xOrgColumnNames.get();
+ pRight = m_xNewColumnNames.get();
+ bAll = true;
+ }
+ else if (&rButton == m_xColumns_LH.get())
+ {
+ pLeft = m_xNewColumnNames.get();
+ pRight = m_xOrgColumnNames.get();
+ bAll = true;
+ }
+
+ if (!pLeft || !pRight)
+ return;
+
+ Reference< XDatabaseMetaData > xMetaData( m_pParent->m_xDestConnection->getMetaData() );
+ OUString sExtraChars = xMetaData->getExtraNameCharacters();
+ sal_Int32 nMaxNameLen = m_pParent->getMaxColumnNameLength();
+
+ ::comphelper::UStringMixEqual aCase(xMetaData->supportsMixedCaseQuotedIdentifiers());
+ std::vector< OUString> aRightColumns;
+ fillColumns(pRight,aRightColumns);
+
+ if(!bAll)
+ {
+ auto aRows = pLeft->get_selected_rows();
+ std::sort(aRows.begin(), aRows.end());
+
+ for (auto it = aRows.begin(); it != aRows.end(); ++it)
+ moveColumn(pRight,pLeft,aRightColumns,pLeft->get_text(*it),sExtraChars,nMaxNameLen,aCase);
+
+ for (auto it = aRows.rbegin(); it != aRows.rend(); ++it)
+ pLeft->remove(*it);
+ }
+ else
+ {
+ const sal_Int32 nEntries = pLeft->n_children();
+ for(sal_Int32 i=0; i < nEntries; ++i)
+ moveColumn(pRight,pLeft,aRightColumns,pLeft->get_text(i),sExtraChars,nMaxNameLen,aCase);
+ for(sal_Int32 j=pLeft->n_children(); j ; )
+ pLeft->remove(--j);
+ }
+
+ enableButtons();
+
+ if (m_xOrgColumnNames->n_children())
+ m_xOrgColumnNames->select(0);
+}
+
+IMPL_LINK( OWizColumnSelect, ListDoubleClickHdl, weld::TreeView&, rListBox, bool )
+{
+ weld::TreeView *pLeft,*pRight;
+ if (&rListBox == m_xOrgColumnNames.get())
+ {
+ pLeft = m_xOrgColumnNames.get();
+ pRight = m_xNewColumnNames.get();
+ }
+ else
+ {
+ pRight = m_xOrgColumnNames.get();
+ pLeft = m_xNewColumnNames.get();
+ }
+
+ // If database is able to process PrimaryKeys, set PrimaryKey
+ Reference< XDatabaseMetaData > xMetaData( m_pParent->m_xDestConnection->getMetaData() );
+ OUString sExtraChars = xMetaData->getExtraNameCharacters();
+ sal_Int32 nMaxNameLen = m_pParent->getMaxColumnNameLength();
+
+ ::comphelper::UStringMixEqual aCase(xMetaData->supportsMixedCaseQuotedIdentifiers());
+ std::vector< OUString> aRightColumns;
+ fillColumns(pRight,aRightColumns);
+
+ auto aRows = pLeft->get_selected_rows();
+ std::sort(aRows.begin(), aRows.end());
+
+ for (auto it = aRows.begin(); it != aRows.end(); ++it)
+ moveColumn(pRight,pLeft,aRightColumns,pLeft->get_text(*it),sExtraChars,nMaxNameLen,aCase);
+
+ for (auto it = aRows.rbegin(); it != aRows.rend(); ++it)
+ pLeft->remove(*it);
+
+ enableButtons();
+
+ return true;
+}
+
+void OWizColumnSelect::clearListBox(weld::TreeView& rListBox)
+{
+ rListBox.clear();
+}
+
+void OWizColumnSelect::fillColumns(weld::TreeView const * pRight,std::vector< OUString> &_rRightColumns)
+{
+ const sal_Int32 nCount = pRight->n_children();
+ _rRightColumns.reserve(nCount);
+ for (sal_Int32 i=0; i < nCount; ++i)
+ _rRightColumns.push_back(pRight->get_text(i));
+}
+
+void OWizColumnSelect::createNewColumn( weld::TreeView* _pListbox,
+ OFieldDescription const * _pSrcField,
+ std::vector< OUString>& _rRightColumns,
+ const OUString& _sColumnName,
+ std::u16string_view _sExtraChars,
+ sal_Int32 _nMaxNameLen,
+ const ::comphelper::UStringMixEqual& _aCase)
+{
+ OUString sConvertedName = m_pParent->convertColumnName(TMultiListBoxEntryFindFunctor(&_rRightColumns,_aCase),
+ _sColumnName,
+ _sExtraChars,
+ _nMaxNameLen);
+ OFieldDescription* pNewField = new OFieldDescription(*_pSrcField);
+ pNewField->SetName(sConvertedName);
+ bool bNotConvert = true;
+ pNewField->SetType(m_pParent->convertType(_pSrcField->getSpecialTypeInfo(),bNotConvert));
+ if ( !m_pParent->supportsPrimaryKey() )
+ pNewField->SetPrimaryKey(false);
+
+ _pListbox->append(weld::toId(pNewField), sConvertedName);
+ _rRightColumns.push_back(sConvertedName);
+
+ if ( !bNotConvert )
+ m_pParent->showColumnTypeNotSupported(sConvertedName);
+}
+
+void OWizColumnSelect::moveColumn( weld::TreeView* _pRight,
+ weld::TreeView const * _pLeft,
+ std::vector< OUString>& _rRightColumns,
+ const OUString& _sColumnName,
+ std::u16string_view _sExtraChars,
+ sal_Int32 _nMaxNameLen,
+ const ::comphelper::UStringMixEqual& _aCase)
+{
+ if(_pRight == m_xNewColumnNames.get())
+ {
+ // we copy the column into the new format for the dest
+ OFieldDescription* pSrcField = weld::fromId<OFieldDescription*>(_pLeft->get_id(_pLeft->find_text(_sColumnName)));
+ createNewColumn(_pRight,pSrcField,_rRightColumns,_sColumnName,_sExtraChars,_nMaxNameLen,_aCase);
+ }
+ else
+ {
+ // find the new column in the dest name mapping to obtain the old column
+ OCopyTableWizard::TNameMapping::const_iterator aIter = std::find_if(m_pParent->m_mNameMapping.begin(),m_pParent->m_mNameMapping.end(),
+ [&_aCase, &_sColumnName] (const OCopyTableWizard::TNameMapping::value_type& nameMap) {
+ return _aCase(nameMap.second, _sColumnName);
+ });
+
+ OSL_ENSURE(aIter != m_pParent->m_mNameMapping.end(),"Column must be defined");
+ if ( aIter == m_pParent->m_mNameMapping.end() )
+ return; // do nothing
+ const ODatabaseExport::TColumns& rSrcColumns = m_pParent->getSourceColumns();
+ ODatabaseExport::TColumns::const_iterator aSrcIter = rSrcColumns.find((*aIter).first);
+ if ( aSrcIter != rSrcColumns.end() )
+ {
+ // we need also the old position of this column to insert it back on that position again
+ const ODatabaseExport::TColumnVector& rSrcVector = m_pParent->getSrcVector();
+ ODatabaseExport::TColumnVector::const_iterator aPos = std::find(rSrcVector.begin(), rSrcVector.end(), aSrcIter);
+ OSL_ENSURE( aPos != rSrcVector.end(),"Invalid position for the iterator here!");
+ ODatabaseExport::TColumnVector::size_type nPos = (aPos - rSrcVector.begin()) - adjustColumnPosition(_pLeft, _sColumnName, (aPos - rSrcVector.begin()), _aCase);
+
+ OUString sId(weld::toId(aSrcIter->second));
+ const OUString& rStr = (*aIter).first;
+ _pRight->insert(nullptr, nPos, &rStr, &sId, nullptr, nullptr, false, nullptr);
+ _rRightColumns.push_back(rStr);
+ m_pParent->removeColumnNameFromNameMap(_sColumnName);
+ }
+ }
+}
+
+// Simply returning fields back to their original position is
+// not enough. We need to take into account what fields have
+// been removed earlier and adjust accordingly. Based on the
+// algorithm employed in moveColumn().
+sal_Int32 OWizColumnSelect::adjustColumnPosition(weld::TreeView const * _pLeft,
+ std::u16string_view _sColumnName,
+ ODatabaseExport::TColumnVector::size_type nCurrentPos,
+ const ::comphelper::UStringMixEqual& _aCase)
+{
+ sal_Int32 nAdjustedPos = 0;
+
+ // if returning all entries to their original position,
+ // then there is no need to adjust the positions.
+ if (m_xColumns_LH->has_focus())
+ return nAdjustedPos;
+
+ const sal_Int32 nCount = _pLeft->n_children();
+ OUString sColumnString;
+ for(sal_Int32 i=0; i < nCount; ++i)
+ {
+ sColumnString = _pLeft->get_text(i);
+ if(_sColumnName != sColumnString)
+ {
+ // find the new column in the dest name mapping to obtain the old column
+ OCopyTableWizard::TNameMapping::const_iterator aIter = std::find_if(m_pParent->m_mNameMapping.begin(),m_pParent->m_mNameMapping.end(),
+ [&_aCase, &sColumnString] (const OCopyTableWizard::TNameMapping::value_type& nameMap) {
+ return _aCase(nameMap.second, sColumnString);
+ });
+
+ OSL_ENSURE(aIter != m_pParent->m_mNameMapping.end(),"Column must be defined");
+ const ODatabaseExport::TColumns& rSrcColumns = m_pParent->getSourceColumns();
+ ODatabaseExport::TColumns::const_iterator aSrcIter = rSrcColumns.find((*aIter).first);
+ if ( aSrcIter != rSrcColumns.end() )
+ {
+ // we need also the old position of this column to insert it back on that position again
+ const ODatabaseExport::TColumnVector& rSrcVector = m_pParent->getSrcVector();
+ ODatabaseExport::TColumnVector::const_iterator aPos = std::find(rSrcVector.begin(), rSrcVector.end(), aSrcIter);
+ ODatabaseExport::TColumnVector::size_type nPos = aPos - rSrcVector.begin();
+ if( nPos < nCurrentPos)
+ {
+ nAdjustedPos++;
+ }
+ }
+ }
+ }
+
+ return nAdjustedPos;
+}
+
+void OWizColumnSelect::enableButtons()
+{
+ bool bEntries = m_xNewColumnNames->n_children() != 0;
+ if (!bEntries)
+ m_pParent->m_mNameMapping.clear();
+
+ m_pParent->GetOKButton().set_sensitive(bEntries);
+ m_pParent->EnableNextButton(bEntries && m_pParent->getOperation() != CopyTableOperation::AppendData);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/misc/WCopyTable.cxx b/dbaccess/source/ui/misc/WCopyTable.cxx
new file mode 100644
index 000000000..64301bccd
--- /dev/null
+++ b/dbaccess/source/ui/misc/WCopyTable.cxx
@@ -0,0 +1,1554 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <strings.hrc>
+#include <strings.hxx>
+#include <core_resource.hxx>
+#include <sqlmessage.hxx>
+#include <UITools.hxx>
+#include <WColumnSelect.hxx>
+#include <WCopyTable.hxx>
+#include <WCPage.hxx>
+#include <WExtendPages.hxx>
+#include <WNameMatch.hxx>
+#include <WTypeSelect.hxx>
+
+#include <com/sun/star/sdb/application/CopyTableOperation.hpp>
+#include <com/sun/star/sdb/SQLContext.hpp>
+#include <com/sun/star/sdbc/ColumnValue.hpp>
+#include <com/sun/star/sdbc/DataType.hpp>
+#include <com/sun/star/sdbc/XResultSet.hpp>
+#include <com/sun/star/sdbc/XStatement.hpp>
+#include <com/sun/star/sdbc/XRow.hpp>
+#include <com/sun/star/sdbcx/KeyType.hpp>
+#include <com/sun/star/sdbcx/XAppend.hpp>
+#include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
+#include <com/sun/star/sdbcx/XDataDescriptorFactory.hpp>
+#include <com/sun/star/sdbcx/XKeysSupplier.hpp>
+#include <com/sun/star/sdbcx/XTablesSupplier.hpp>
+#include <com/sun/star/sdbcx/XViewsSupplier.hpp>
+#include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp>
+#include <com/sun/star/task/InteractionHandler.hpp>
+
+#include <comphelper/interaction.hxx>
+#include <connectivity/dbtools.hxx>
+#include <connectivity/dbmetadata.hxx>
+#include <connectivity/dbexception.hxx>
+#include <o3tl/safeint.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <sal/log.hxx>
+#include <tools/diagnose_ex.h>
+
+#include <algorithm>
+
+using namespace ::dbaui;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::util;
+using namespace ::com::sun::star::sdb;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::sdbcx;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::task;
+using namespace dbtools;
+
+namespace CopyTableOperation = ::com::sun::star::sdb::application::CopyTableOperation;
+
+#define MAX_PAGES 4 // max. number of pages, which are shown
+
+namespace
+{
+ void clearColumns(ODatabaseExport::TColumns& _rColumns, ODatabaseExport::TColumnVector& _rColumnsVec)
+ {
+ for (auto const& column : _rColumns)
+ delete column.second;
+
+ _rColumnsVec.clear();
+ _rColumns.clear();
+ }
+}
+
+// ICopyTableSourceObject
+ICopyTableSourceObject::~ICopyTableSourceObject()
+{
+}
+
+// ObjectCopySource
+ObjectCopySource::ObjectCopySource( const Reference< XConnection >& _rxConnection, const Reference< XPropertySet >& _rxObject )
+ :m_xConnection( _rxConnection, UNO_SET_THROW )
+ ,m_xMetaData( _rxConnection->getMetaData(), UNO_SET_THROW )
+ ,m_xObject( _rxObject, UNO_SET_THROW )
+ ,m_xObjectPSI( _rxObject->getPropertySetInfo(), UNO_SET_THROW )
+ ,m_xObjectColumns( Reference< XColumnsSupplier >( _rxObject, UNO_QUERY_THROW )->getColumns(), UNO_SET_THROW )
+{
+}
+
+OUString ObjectCopySource::getQualifiedObjectName() const
+{
+ OUString sName;
+
+ if ( !m_xObjectPSI->hasPropertyByName( PROPERTY_COMMAND ) )
+ sName = ::dbtools::composeTableName( m_xMetaData, m_xObject, ::dbtools::EComposeRule::InDataManipulation, false );
+ else
+ m_xObject->getPropertyValue( PROPERTY_NAME ) >>= sName;
+ return sName;
+}
+
+bool ObjectCopySource::isView() const
+{
+ bool bIsView = false;
+ try
+ {
+ if ( m_xObjectPSI->hasPropertyByName( PROPERTY_TYPE ) )
+ {
+ OUString sObjectType;
+ OSL_VERIFY( m_xObject->getPropertyValue( PROPERTY_TYPE ) >>= sObjectType );
+ bIsView = sObjectType == "VIEW";
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ return bIsView;
+}
+
+void ObjectCopySource::copyUISettingsTo( const Reference< XPropertySet >& _rxObject ) const
+{
+ const OUString aCopyProperties[] = {
+ OUString(PROPERTY_FONT), OUString(PROPERTY_ROW_HEIGHT), OUString(PROPERTY_TEXTCOLOR),OUString(PROPERTY_TEXTLINECOLOR),OUString(PROPERTY_TEXTEMPHASIS),OUString(PROPERTY_TEXTRELIEF)
+ };
+ for (const auto & aCopyProperty : aCopyProperties)
+ {
+ if ( m_xObjectPSI->hasPropertyByName( aCopyProperty ) )
+ _rxObject->setPropertyValue( aCopyProperty, m_xObject->getPropertyValue( aCopyProperty ) );
+ }
+}
+
+void ObjectCopySource::copyFilterAndSortingTo( const Reference< XConnection >& _xConnection,const Reference< XPropertySet >& _rxObject ) const
+{
+ std::pair< OUString, OUString > aProperties[] = {
+ std::pair< OUString, OUString >(PROPERTY_FILTER,OUString(" AND "))
+ ,std::pair< OUString, OUString >(PROPERTY_ORDER,OUString(" ORDER BY "))
+ };
+
+ try
+ {
+ const OUString sSourceName = ::dbtools::composeTableNameForSelect(m_xConnection,m_xObject) + ".";
+ const OUString sTargetName = ::dbtools::composeTableNameForSelect(_xConnection,_rxObject);
+ const OUString sTargetNameTemp = sTargetName + ".";
+
+ OUStringBuffer sStatement = "SELECT * FROM " + sTargetName + " WHERE 0=1";
+
+ for (const std::pair<OUString,OUString> & aProperty : aProperties)
+ {
+ if ( m_xObjectPSI->hasPropertyByName( aProperty.first ) )
+ {
+ OUString sFilter;
+ m_xObject->getPropertyValue( aProperty.first ) >>= sFilter;
+ if ( !sFilter.isEmpty() )
+ {
+ sStatement.append(aProperty.second);
+ sFilter = sFilter.replaceFirst(sSourceName,sTargetNameTemp);
+ _rxObject->setPropertyValue( aProperty.first, Any(sFilter) );
+ sStatement.append(sFilter);
+ }
+ }
+ }
+
+ _xConnection->createStatement()->executeQuery(sStatement.makeStringAndClear());
+
+ if ( m_xObjectPSI->hasPropertyByName( PROPERTY_APPLYFILTER ) )
+ _rxObject->setPropertyValue( PROPERTY_APPLYFILTER, m_xObject->getPropertyValue( PROPERTY_APPLYFILTER ) );
+ }
+ catch(Exception&)
+ {
+ }
+}
+
+Sequence< OUString > ObjectCopySource::getColumnNames() const
+{
+ return m_xObjectColumns->getElementNames();
+}
+
+Sequence< OUString > ObjectCopySource::getPrimaryKeyColumnNames() const
+{
+ const Reference<XNameAccess> xPrimaryKeyColumns = getPrimaryKeyColumns_throw(m_xObject);
+ Sequence< OUString > aKeyColNames;
+ if ( xPrimaryKeyColumns.is() )
+ aKeyColNames = xPrimaryKeyColumns->getElementNames();
+ return aKeyColNames;
+}
+
+OFieldDescription* ObjectCopySource::createFieldDescription( const OUString& _rColumnName ) const
+{
+ Reference< XPropertySet > xColumn( m_xObjectColumns->getByName( _rColumnName ), UNO_QUERY_THROW );
+ return new OFieldDescription( xColumn );
+}
+
+OUString ObjectCopySource::getSelectStatement() const
+{
+ OUString sSelectStatement;
+ if ( m_xObjectPSI->hasPropertyByName( PROPERTY_COMMAND ) )
+ { // query
+ OSL_VERIFY( m_xObject->getPropertyValue( PROPERTY_COMMAND ) >>= sSelectStatement );
+ }
+ else
+ { // table
+ OUStringBuffer aSQL;
+ aSQL.append( "SELECT " );
+
+ // we need to create the sql stmt with column names
+ // otherwise it is possible that names don't match
+ const OUString sQuote = m_xMetaData->getIdentifierQuoteString();
+
+ Sequence< OUString > aColumnNames = getColumnNames();
+ const OUString* pColumnName = aColumnNames.getConstArray();
+ const OUString* pEnd = pColumnName + aColumnNames.getLength();
+ for ( ; pColumnName != pEnd; )
+ {
+ aSQL.append( ::dbtools::quoteName( sQuote, *pColumnName++ ) );
+
+ if ( pColumnName == pEnd )
+ aSQL.append( " " );
+ else
+ aSQL.append( ", " );
+ }
+
+ aSQL.append( "FROM " + ::dbtools::composeTableNameForSelect( m_xConnection, m_xObject ) );
+
+ sSelectStatement = aSQL.makeStringAndClear();
+ }
+
+ return sSelectStatement;
+}
+
+::utl::SharedUNOComponent< XPreparedStatement > ObjectCopySource::getPreparedSelectStatement() const
+{
+ ::utl::SharedUNOComponent< XPreparedStatement > xStatement(
+ m_xConnection->prepareStatement( getSelectStatement() ),
+ ::utl::SharedUNOComponent< XPreparedStatement >::TakeOwnership
+ );
+ return xStatement;
+}
+
+// NamedTableCopySource
+NamedTableCopySource::NamedTableCopySource( const Reference< XConnection >& _rxConnection, const OUString& _rTableName )
+ :m_xConnection( _rxConnection, UNO_SET_THROW )
+ ,m_xMetaData( _rxConnection->getMetaData(), UNO_SET_THROW )
+ ,m_sTableName( _rTableName )
+{
+ ::dbtools::qualifiedNameComponents( m_xMetaData, m_sTableName, m_sTableCatalog, m_sTableSchema, m_sTableBareName, ::dbtools::EComposeRule::Complete );
+ impl_ensureColumnInfo_throw();
+}
+
+OUString NamedTableCopySource::getQualifiedObjectName() const
+{
+ return m_sTableName;
+}
+
+bool NamedTableCopySource::isView() const
+{
+ OUString sTableType;
+ try
+ {
+ Reference< XResultSet > xTableDesc( m_xMetaData->getTables( Any( m_sTableCatalog ), m_sTableSchema, m_sTableBareName,
+ Sequence< OUString >() ) );
+ Reference< XRow > xTableDescRow( xTableDesc, UNO_QUERY_THROW );
+ OSL_VERIFY( xTableDesc->next() );
+ sTableType = xTableDescRow->getString( 4 );
+ OSL_ENSURE( !xTableDescRow->wasNull(), "NamedTableCopySource::isView: invalid table type!" );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ return sTableType == "VIEW";
+}
+
+void NamedTableCopySource::copyUISettingsTo( const Reference< XPropertySet >& /*_rxObject*/ ) const
+{
+ // not supported: we do not have UI settings to copy
+}
+
+void NamedTableCopySource::copyFilterAndSortingTo( const Reference< XConnection >& ,const Reference< XPropertySet >& /*_rxObject*/ ) const
+{
+}
+
+void NamedTableCopySource::impl_ensureColumnInfo_throw()
+{
+ if ( !m_aColumnInfo.empty() )
+ return;
+
+ Reference< XResultSetMetaDataSupplier > xStatementMetaSupp( impl_ensureStatement_throw().getTyped(), UNO_QUERY_THROW );
+ Reference< XResultSetMetaData > xStatementMeta( xStatementMetaSupp->getMetaData(), UNO_SET_THROW );
+
+ sal_Int32 nColCount( xStatementMeta->getColumnCount() );
+ for ( sal_Int32 i = 1; i <= nColCount; ++i )
+ {
+ OFieldDescription aDesc;
+
+ aDesc.SetName( xStatementMeta->getColumnName( i ) );
+ aDesc.SetHelpText( xStatementMeta->getColumnLabel( i ) );
+ aDesc.SetTypeValue( xStatementMeta->getColumnType( i ) );
+ aDesc.SetTypeName( xStatementMeta->getColumnTypeName( i ) );
+ aDesc.SetPrecision( xStatementMeta->getPrecision( i ) );
+ aDesc.SetScale( xStatementMeta->getScale( i ) );
+ aDesc.SetIsNullable( xStatementMeta->isNullable( i ) );
+ aDesc.SetCurrency( xStatementMeta->isCurrency( i ) );
+ aDesc.SetAutoIncrement( xStatementMeta->isAutoIncrement( i ) );
+
+ m_aColumnInfo.push_back( aDesc );
+ }
+}
+
+::utl::SharedUNOComponent< XPreparedStatement > const & NamedTableCopySource::impl_ensureStatement_throw()
+{
+ if ( !m_xStatement.is() )
+ m_xStatement.set( m_xConnection->prepareStatement( getSelectStatement() ), UNO_SET_THROW );
+ return m_xStatement;
+}
+
+Sequence< OUString > NamedTableCopySource::getColumnNames() const
+{
+ Sequence< OUString > aNames( m_aColumnInfo.size() );
+ std::transform(m_aColumnInfo.begin(), m_aColumnInfo.end(), aNames.getArray(),
+ [](const auto& elem) { return elem.GetName(); });
+
+ return aNames;
+}
+
+Sequence< OUString > NamedTableCopySource::getPrimaryKeyColumnNames() const
+{
+ Sequence< OUString > aPKColNames;
+
+ try
+ {
+ Reference< XResultSet > xPKDesc( m_xMetaData->getPrimaryKeys( Any( m_sTableCatalog ), m_sTableSchema, m_sTableBareName ) );
+ Reference< XRow > xPKDescRow( xPKDesc, UNO_QUERY_THROW );
+ while ( xPKDesc->next() )
+ {
+ sal_Int32 len( aPKColNames.getLength() );
+ aPKColNames.realloc( len + 1 );
+ aPKColNames.getArray()[ len ] = xPKDescRow->getString( 4 ); // COLUMN_NAME
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+
+ return aPKColNames;
+}
+
+OFieldDescription* NamedTableCopySource::createFieldDescription( const OUString& _rColumnName ) const
+{
+ for (auto const& elem : m_aColumnInfo)
+ if ( elem.GetName() == _rColumnName )
+ return new OFieldDescription(elem);
+
+ return nullptr;
+}
+
+OUString NamedTableCopySource::getSelectStatement() const
+{
+ return "SELECT * FROM " +
+ ::dbtools::composeTableNameForSelect( m_xConnection, m_sTableCatalog, m_sTableSchema, m_sTableBareName );
+}
+
+::utl::SharedUNOComponent< XPreparedStatement > NamedTableCopySource::getPreparedSelectStatement() const
+{
+ return const_cast< NamedTableCopySource* >( this )->impl_ensureStatement_throw();
+}
+
+namespace {
+
+// DummyCopySource
+class DummyCopySource : public ICopyTableSourceObject
+{
+public:
+ DummyCopySource() { }
+
+ static const DummyCopySource& Instance();
+
+ // ICopyTableSourceObject overridables
+ virtual OUString getQualifiedObjectName() const override;
+ virtual bool isView() const override;
+ virtual void copyUISettingsTo( const css::uno::Reference< css::beans::XPropertySet >& _rxObject ) const override;
+ virtual void copyFilterAndSortingTo(const css::uno::Reference< css::sdbc::XConnection >& _xConnection, const css::uno::Reference< css::beans::XPropertySet >& _rxObject ) const override;
+ virtual css::uno::Sequence< OUString >
+ getColumnNames() const override;
+ virtual css::uno::Sequence< OUString >
+ getPrimaryKeyColumnNames() const override;
+ virtual OFieldDescription* createFieldDescription( const OUString& _rColumnName ) const override;
+ virtual OUString getSelectStatement() const override;
+ virtual ::utl::SharedUNOComponent< XPreparedStatement >
+ getPreparedSelectStatement() const override;
+};
+
+}
+
+const DummyCopySource& DummyCopySource::Instance()
+{
+ static DummyCopySource s_aTheInstance;
+ return s_aTheInstance;
+}
+
+OUString DummyCopySource::getQualifiedObjectName() const
+{
+ SAL_WARN("dbaccess.ui", "DummyCopySource::getQualifiedObjectName: not to be called!" );
+ return OUString();
+}
+
+bool DummyCopySource::isView() const
+{
+ SAL_WARN("dbaccess.ui", "DummyCopySource::isView: not to be called!" );
+ return false;
+}
+
+void DummyCopySource::copyUISettingsTo( const Reference< XPropertySet >& /*_rxObject*/ ) const
+{
+ // no support
+}
+
+void DummyCopySource::copyFilterAndSortingTo( const Reference< XConnection >& ,const Reference< XPropertySet >& /*_rxObject*/ ) const
+{
+}
+
+Sequence< OUString > DummyCopySource::getColumnNames() const
+{
+ return Sequence< OUString >();
+}
+
+Sequence< OUString > DummyCopySource::getPrimaryKeyColumnNames() const
+{
+ SAL_WARN("dbaccess.ui", "DummyCopySource::getPrimaryKeyColumnNames: not to be called!" );
+ return Sequence< OUString >();
+}
+
+OFieldDescription* DummyCopySource::createFieldDescription( const OUString& /*_rColumnName*/ ) const
+{
+ SAL_WARN("dbaccess.ui", "DummyCopySource::createFieldDescription: not to be called!" );
+ return nullptr;
+}
+
+OUString DummyCopySource::getSelectStatement() const
+{
+ SAL_WARN("dbaccess.ui", "DummyCopySource::getSelectStatement: not to be called!" );
+ return OUString();
+}
+
+::utl::SharedUNOComponent< XPreparedStatement > DummyCopySource::getPreparedSelectStatement() const
+{
+ SAL_WARN("dbaccess.ui", "DummyCopySource::getPreparedSelectStatement: not to be called!" );
+ return ::utl::SharedUNOComponent< XPreparedStatement >();
+}
+
+namespace
+{
+ bool lcl_canCreateViewFor_nothrow( const Reference< XConnection >& _rxConnection )
+ {
+ Reference< XViewsSupplier > xSup( _rxConnection, UNO_QUERY );
+ Reference< XDataDescriptorFactory > xViewFac;
+ if ( xSup.is() )
+ xViewFac.set( xSup->getViews(), UNO_QUERY );
+ return xViewFac.is();
+ }
+
+ bool lcl_sameConnection_throw( const Reference< XConnection >& _rxLHS, const Reference< XConnection >& _rxRHS )
+ {
+ Reference< XDatabaseMetaData > xMetaLHS( _rxLHS->getMetaData(), UNO_SET_THROW );
+ Reference< XDatabaseMetaData > xMetaRHS( _rxRHS->getMetaData(), UNO_SET_THROW );
+ return xMetaLHS->getURL() == xMetaRHS->getURL();
+ }
+}
+
+// OCopyTableWizard
+OCopyTableWizard::OCopyTableWizard(weld::Window* pParent, const OUString& _rDefaultName, sal_Int16 _nOperation,
+ const ICopyTableSourceObject& _rSourceObject, const Reference< XConnection >& _xSourceConnection,
+ const Reference< XConnection >& _xConnection, const Reference< XComponentContext >& _rxContext,
+ const Reference< XInteractionHandler>& _xInteractionHandler)
+ : vcl::RoadmapWizardMachine(pParent)
+ , m_mNameMapping(_xConnection->getMetaData().is() && _xConnection->getMetaData()->supportsMixedCaseQuotedIdentifiers())
+ , m_xDestConnection( _xConnection )
+ , m_rSourceObject( _rSourceObject )
+ , m_xFormatter( getNumberFormatter( _xConnection, _rxContext ) )
+ , m_xContext(_rxContext)
+ , m_xInteractionHandler(_xInteractionHandler)
+ , m_sTypeNames(DBA_RES(STR_TABLEDESIGN_DBFIELDTYPES))
+ , m_nPageCount(0)
+ , m_bDeleteSourceColumns(true)
+ , m_bInterConnectionCopy( _xSourceConnection != _xConnection )
+ , m_sName( _rDefaultName )
+ , m_nOperation( _nOperation )
+ , m_ePressed( WIZARD_NONE )
+ , m_bCreatePrimaryKeyColumn(false)
+ , m_bUseHeaderLine(false)
+{
+ construct();
+
+ // extract table name
+ OUString sInitialTableName( _rDefaultName );
+ try
+ {
+ m_sSourceName = m_rSourceObject.getQualifiedObjectName();
+ OSL_ENSURE( !m_sSourceName.isEmpty(), "OCopyTableWizard::OCopyTableWizard: unable to retrieve the source object's name!" );
+
+ if ( sInitialTableName.isEmpty() )
+ sInitialTableName = m_sSourceName;
+
+ if ( m_sName.isEmpty() )
+ {
+ if ( _xSourceConnection == m_xDestConnection )
+ {
+ Reference< XTablesSupplier > xSup( m_xDestConnection, UNO_QUERY_THROW );
+ m_sName = ::dbtools::createUniqueName( xSup->getTables(), sInitialTableName, false );
+ }
+ else
+ m_sName = sInitialTableName;
+ }
+ }
+ catch ( const Exception& )
+ {
+ m_sName = sInitialTableName;
+ }
+
+ ::dbaui::fillTypeInfo( _xSourceConnection, m_sTypeNames, m_aTypeInfo, m_aTypeInfoIndex );
+ ::dbaui::fillTypeInfo( m_xDestConnection, m_sTypeNames, m_aDestTypeInfo, m_aDestTypeInfoIndex );
+ loadData( m_rSourceObject, m_vSourceColumns, m_vSourceVec );
+
+ bool bAllowViews = true;
+ // if the source is a, don't allow creating views
+ if ( m_rSourceObject.isView() )
+ bAllowViews = false;
+ // no views if the target connection does not support creating them
+ if ( !lcl_canCreateViewFor_nothrow( m_xDestConnection ) )
+ bAllowViews = false;
+ // no views if we're copying to a different database
+ if ( !lcl_sameConnection_throw( _xSourceConnection, m_xDestConnection ) )
+ bAllowViews = false;
+
+ if ( m_bInterConnectionCopy )
+ {
+ Reference< XDatabaseMetaData > xSrcMeta = _xSourceConnection->getMetaData();
+ OUString sCatalog;
+ OUString sSchema;
+ OUString sTable;
+ ::dbtools::qualifiedNameComponents( xSrcMeta,
+ m_sName,
+ sCatalog,
+ sSchema,
+ sTable,
+ ::dbtools::EComposeRule::InDataManipulation);
+
+ m_sName = ::dbtools::composeTableName(m_xDestConnection->getMetaData(),sCatalog,sSchema,sTable,false,::dbtools::EComposeRule::InTableDefinitions);
+ }
+
+ std::unique_ptr<OCopyTable> xPage1(new OCopyTable(CreatePageContainer(), this));
+ xPage1->disallowUseHeaderLine();
+ if ( !bAllowViews )
+ xPage1->disallowViews();
+ xPage1->setCreateStyleAction();
+ AddWizardPage(std::move(xPage1));
+
+ AddWizardPage( std::make_unique<OWizNameMatching>(CreatePageContainer(), this));
+ AddWizardPage( std::make_unique<OWizColumnSelect>(CreatePageContainer(), this));
+ AddWizardPage( std::make_unique<OWizNormalExtend>(CreatePageContainer(), this));
+ ActivatePage();
+
+ m_xAssistant->set_current_page(0);
+}
+
+weld::Container* OCopyTableWizard::CreatePageContainer()
+{
+ OString sIdent(OString::number(m_nPageCount));
+ weld::Container* pPageContainer = m_xAssistant->append_page(sIdent);
+ return pPageContainer;
+}
+
+OCopyTableWizard::OCopyTableWizard( weld::Window* pParent, const OUString& _rDefaultName, sal_Int16 _nOperation,
+ ODatabaseExport::TColumns&& _rSourceColumns, const ODatabaseExport::TColumnVector& _rSourceColVec,
+ const Reference< XConnection >& _xConnection, const Reference< XNumberFormatter >& _xFormatter,
+ TypeSelectionPageFactory _pTypeSelectionPageFactory, SvStream& _rTypeSelectionPageArg, const Reference< XComponentContext >& _rxContext )
+ : vcl::RoadmapWizardMachine(pParent)
+ , m_vSourceColumns(std::move(_rSourceColumns))
+ , m_mNameMapping(_xConnection->getMetaData().is() && _xConnection->getMetaData()->supportsMixedCaseQuotedIdentifiers())
+ , m_xDestConnection( _xConnection )
+ , m_rSourceObject( DummyCopySource::Instance() )
+ , m_xFormatter(_xFormatter)
+ , m_xContext(_rxContext)
+ , m_sTypeNames(DBA_RES(STR_TABLEDESIGN_DBFIELDTYPES))
+ , m_nPageCount(0)
+ , m_bDeleteSourceColumns(false)
+ , m_bInterConnectionCopy( false )
+ , m_sName(_rDefaultName)
+ , m_nOperation( _nOperation )
+ , m_ePressed( WIZARD_NONE )
+ , m_bCreatePrimaryKeyColumn(false)
+ , m_bUseHeaderLine(false)
+{
+ construct();
+ for (auto const& sourceCol : _rSourceColVec)
+ {
+ m_vSourceVec.emplace_back(m_vSourceColumns.find(sourceCol->first));
+ }
+
+ ::dbaui::fillTypeInfo( _xConnection, m_sTypeNames, m_aTypeInfo, m_aTypeInfoIndex );
+ ::dbaui::fillTypeInfo( _xConnection, m_sTypeNames, m_aDestTypeInfo, m_aDestTypeInfoIndex );
+
+ m_xInteractionHandler = InteractionHandler::createWithParent(m_xContext, nullptr);
+
+ std::unique_ptr<OCopyTable> xPage1(new OCopyTable(CreatePageContainer(), this));
+ xPage1->disallowViews();
+ xPage1->setCreateStyleAction();
+ AddWizardPage(std::move(xPage1));
+
+ AddWizardPage(std::make_unique<OWizNameMatching>(CreatePageContainer(), this));
+ AddWizardPage(std::make_unique<OWizColumnSelect>(CreatePageContainer(), this));
+ AddWizardPage((*_pTypeSelectionPageFactory)(CreatePageContainer(), this, _rTypeSelectionPageArg));
+
+ ActivatePage();
+
+ m_xAssistant->set_current_page(0);
+}
+
+void OCopyTableWizard::construct()
+{
+ m_xAssistant->set_size_request(700, 350);
+
+ m_xPrevPage->set_label(DBA_RES(STR_WIZ_PB_PREV));
+ m_xNextPage->set_label(DBA_RES(STR_WIZ_PB_NEXT));
+ m_xFinish->set_label(DBA_RES(STR_WIZ_PB_OK));
+
+ m_xHelp->show();
+ m_xCancel->show();
+ m_xPrevPage->show();
+ m_xNextPage->show();
+ m_xFinish->show();
+
+ m_xPrevPage->connect_clicked( LINK( this, OCopyTableWizard, ImplPrevHdl ) );
+ m_xNextPage->connect_clicked( LINK( this, OCopyTableWizard, ImplNextHdl ) );
+ m_xFinish->connect_clicked( LINK( this, OCopyTableWizard, ImplOKHdl ) );
+
+ m_xNextPage->grab_focus();
+
+ if (!m_vDestColumns.empty())
+ // source is a html or rtf table
+ m_xAssistant->change_default_widget(nullptr, m_xNextPage.get());
+ else
+ m_xAssistant->change_default_widget(nullptr, m_xFinish.get());
+
+ m_pTypeInfo = std::make_shared<OTypeInfo>();
+ m_pTypeInfo->aUIName = m_sTypeNames.getToken(TYPE_OTHER, ';');
+ m_bAddPKFirstTime = true;
+}
+
+OCopyTableWizard::~OCopyTableWizard()
+{
+ if ( m_bDeleteSourceColumns )
+ clearColumns(m_vSourceColumns,m_vSourceVec);
+
+ clearColumns(m_vDestColumns,m_aDestVec);
+
+ // clear the type information
+ m_aTypeInfoIndex.clear();
+ m_aTypeInfo.clear();
+ m_aDestTypeInfoIndex.clear();
+ m_aDestTypeInfo.clear();
+}
+
+IMPL_LINK_NOARG(OCopyTableWizard, ImplPrevHdl, weld::Button&, void)
+{
+ m_ePressed = WIZARD_PREV;
+ if ( GetCurLevel() )
+ {
+ if ( getOperation() != CopyTableOperation::AppendData )
+ {
+ if(GetCurLevel() == 2)
+ ShowPage(GetCurLevel()-2);
+ else
+ ShowPrevPage();
+ }
+ else
+ ShowPrevPage();
+ }
+}
+
+IMPL_LINK_NOARG(OCopyTableWizard, ImplNextHdl, weld::Button&, void)
+{
+ m_ePressed = WIZARD_NEXT;
+ if ( GetCurLevel() < MAX_PAGES )
+ {
+ if ( getOperation() != CopyTableOperation::AppendData )
+ {
+ if(GetCurLevel() == 0)
+ ShowPage(GetCurLevel()+2);
+ else
+ ShowNextPage();
+ }
+ else
+ ShowNextPage();
+ }
+}
+
+bool OCopyTableWizard::CheckColumns(sal_Int32& _rnBreakPos)
+{
+ bool bRet = true;
+ m_vColumnPositions.clear();
+ m_vColumnTypes.clear();
+
+ OSL_ENSURE( m_xDestConnection.is(), "OCopyTableWizard::CheckColumns: No connection!" );
+ // If database is able to process PrimaryKeys, set PrimaryKey
+ if ( m_xDestConnection.is() )
+ {
+ bool bPKeyAllowed = supportsPrimaryKey();
+
+ bool bContainsColumns = !m_vDestColumns.empty();
+
+ if ( bPKeyAllowed && shouldCreatePrimaryKey() )
+ {
+ // add extra column for the primary key
+ TOTypeInfoSP pTypeInfo = queryPrimaryKeyType(m_aDestTypeInfo);
+ if ( pTypeInfo )
+ {
+ if ( m_bAddPKFirstTime )
+ {
+ // tdf#114955: since we chose to create a primary key
+ // be sure all other columns won't be in primary key
+ for (auto const& elem : m_vDestColumns)
+ elem.second->SetPrimaryKey(false);
+ OFieldDescription* pField = new OFieldDescription();
+ pField->SetName(m_aKeyName);
+ pField->FillFromTypeInfo(pTypeInfo,true,true);
+ pField->SetPrimaryKey(true);
+ m_bAddPKFirstTime = false;
+ insertColumn(0,pField);
+ }
+ m_vColumnPositions.emplace_back(1,1);
+ m_vColumnTypes.push_back(pTypeInfo->nType);
+ }
+ }
+
+ if ( bContainsColumns )
+ { // we have dest columns so look for the matching column
+ for (auto const& elemSource : m_vSourceVec)
+ {
+ ODatabaseExport::TColumns::const_iterator aDestIter = m_vDestColumns.find(m_mNameMapping[elemSource->first]);
+
+ if ( aDestIter != m_vDestColumns.end() )
+ {
+ ODatabaseExport::TColumnVector::const_iterator aFind = std::find(m_aDestVec.begin(),m_aDestVec.end(),aDestIter);
+ assert(aFind != m_aDestVec.end());
+ sal_Int32 nPos = (aFind - m_aDestVec.begin())+1;
+ m_vColumnPositions.emplace_back(nPos,nPos);
+ m_vColumnTypes.push_back((*aFind)->second->GetType());
+ }
+ else
+ {
+ m_vColumnPositions.emplace_back( COLUMN_POSITION_NOT_FOUND, COLUMN_POSITION_NOT_FOUND );
+ m_vColumnTypes.push_back(0);
+ }
+ }
+ }
+ else
+ {
+ Reference< XDatabaseMetaData > xMetaData( m_xDestConnection->getMetaData() );
+ OUString sExtraChars = xMetaData->getExtraNameCharacters();
+ sal_Int32 nMaxNameLen = getMaxColumnNameLength();
+
+ _rnBreakPos=0;
+ for (auto const& elemSource : m_vSourceVec)
+ {
+ OFieldDescription* pField = new OFieldDescription(*elemSource->second);
+ pField->SetName(convertColumnName(TExportColumnFindFunctor(&m_vDestColumns),elemSource->first,sExtraChars,nMaxNameLen));
+ TOTypeInfoSP pType = convertType(elemSource->second->getSpecialTypeInfo(),bRet);
+ pField->SetType(pType);
+ if ( !bPKeyAllowed )
+ pField->SetPrimaryKey(false);
+
+ // now create a column
+ insertColumn(m_vDestColumns.size(),pField);
+ m_vColumnPositions.emplace_back(m_vDestColumns.size(),m_vDestColumns.size());
+ m_vColumnTypes.push_back(elemSource->second->GetType());
+ ++_rnBreakPos;
+ if (!bRet)
+ break;
+ }
+ }
+ }
+ return bRet;
+}
+
+IMPL_LINK_NOARG(OCopyTableWizard, ImplOKHdl, weld::Button&, void)
+{
+ m_ePressed = WIZARD_FINISH;
+ bool bFinish = DeactivatePage();
+
+ if(!bFinish)
+ return;
+
+ weld::WaitObject aWait(m_xAssistant.get());
+ switch(getOperation())
+ {
+ case CopyTableOperation::CopyDefinitionAndData:
+ case CopyTableOperation::CopyDefinitionOnly:
+ {
+ bool bOnFirstPage = GetCurLevel() == 0;
+ if ( bOnFirstPage )
+ {
+ // we came from the first page so we have to clear
+ // all column information already collected
+ clearDestColumns();
+ m_mNameMapping.clear();
+ }
+ sal_Int32 nBreakPos = 0;
+ bool bCheckOk = CheckColumns(nBreakPos);
+ if ( bOnFirstPage && !bCheckOk )
+ {
+ showColumnTypeNotSupported(m_vSourceVec[nBreakPos-1]->first);
+ OWizTypeSelect* pPage = static_cast<OWizTypeSelect*>(GetPage(3));
+ if ( pPage )
+ {
+ m_mNameMapping.clear();
+ pPage->setDisplayRow(nBreakPos);
+ ShowPage(3);
+ return;
+ }
+ }
+ if ( m_xDestConnection.is() )
+ {
+ if ( supportsPrimaryKey() )
+ {
+ bool noPrimaryKey = std::none_of(m_vDestColumns.begin(),m_vDestColumns.end(),
+ [] (const ODatabaseExport::TColumns::value_type& tCol) { return tCol.second->IsPrimaryKey(); });
+ if ( noPrimaryKey && m_xInteractionHandler.is() )
+ {
+
+ OUString sMsg(DBA_RES(STR_TABLEDESIGN_NO_PRIM_KEY));
+ SQLContext aError;
+ aError.Message = sMsg;
+ ::rtl::Reference xRequest( new ::comphelper::OInteractionRequest( Any( aError ) ) );
+ ::rtl::Reference xYes = new ::comphelper::OInteractionApprove;
+ xRequest->addContinuation( xYes );
+ xRequest->addContinuation( new ::comphelper::OInteractionDisapprove );
+ ::rtl::Reference< ::comphelper::OInteractionAbort > xAbort = new ::comphelper::OInteractionAbort;
+ xRequest->addContinuation( xAbort );
+
+ m_xInteractionHandler->handle( xRequest );
+
+ if ( xYes->wasSelected() )
+ {
+ OCopyTable* pPage = static_cast<OCopyTable*>(GetPage(0));
+ m_bCreatePrimaryKeyColumn = true;
+ m_aKeyName = pPage->GetKeyName();
+ if ( m_aKeyName.isEmpty() )
+ m_aKeyName = "ID";
+ m_aKeyName = createUniqueName( m_aKeyName );
+ sal_Int32 nBreakPos2 = 0;
+ CheckColumns(nBreakPos2);
+ }
+ else if ( xAbort->wasSelected() )
+ {
+ ShowPage(3);
+ return;
+ }
+ }
+ }
+ }
+ break;
+ }
+ case CopyTableOperation::AppendData:
+ case CopyTableOperation::CreateAsView:
+ break;
+ default:
+ {
+ SAL_WARN("dbaccess.ui", "OCopyTableWizard::ImplOKHdl: invalid creation style!");
+ }
+ }
+
+ m_xAssistant->response(RET_OK);
+}
+
+void OCopyTableWizard::setCreatePrimaryKey( bool _bDoCreate, const OUString& _rSuggestedName )
+{
+ m_bCreatePrimaryKeyColumn = _bDoCreate;
+ if ( !_rSuggestedName.isEmpty() )
+ m_aKeyName = _rSuggestedName;
+
+ OCopyTable* pSettingsPage = dynamic_cast< OCopyTable* >( GetPage( 0 ) );
+ OSL_ENSURE( pSettingsPage, "OCopyTableWizard::setCreatePrimaryKey: page should have been added in the ctor!" );
+ if ( pSettingsPage )
+ pSettingsPage->setCreatePrimaryKey( _bDoCreate, _rSuggestedName );
+}
+
+void OCopyTableWizard::ActivatePage()
+{
+ OWizardPage* pCurrent = static_cast<OWizardPage*>(GetPage(GetCurLevel()));
+ if (pCurrent)
+ {
+ bool bFirstTime = pCurrent->IsFirstTime();
+ if(bFirstTime)
+ pCurrent->Reset();
+
+ CheckButtons();
+
+ m_xAssistant->set_title(pCurrent->GetTitle());
+ }
+}
+
+void OCopyTableWizard::CheckButtons()
+{
+ if(GetCurLevel() == 0) // the first page has no back button
+ {
+ if(m_nPageCount > 1)
+ m_xNextPage->set_sensitive(true);
+ else
+ m_xNextPage->set_sensitive(false);
+
+ m_xPrevPage->set_sensitive(false);
+ }
+ else if(GetCurLevel() == m_nPageCount-1) // the last page has no next button
+ {
+ m_xNextPage->set_sensitive(false);
+ m_xPrevPage->set_sensitive(true);
+ }
+ else
+ {
+ m_xPrevPage->set_sensitive(true);
+ // next already has its state
+ }
+}
+
+void OCopyTableWizard::EnableNextButton(bool bEnable)
+{
+ m_xNextPage->set_sensitive(bEnable);
+}
+
+bool OCopyTableWizard::DeactivatePage()
+{
+ OWizardPage* pPage = static_cast<OWizardPage*>(GetPage(GetCurLevel()));
+ return pPage && pPage->LeavePage();
+}
+
+void OCopyTableWizard::AddWizardPage(std::unique_ptr<OWizardPage> xPage)
+{
+ AddPage(std::move(xPage));
+ ++m_nPageCount;
+}
+
+void OCopyTableWizard::insertColumn(sal_Int32 _nPos,OFieldDescription* _pField)
+{
+ OSL_ENSURE(_pField,"FieldDescrioption is null!");
+ if ( !_pField )
+ return;
+
+ ODatabaseExport::TColumns::const_iterator aFind = m_vDestColumns.find(_pField->GetName());
+ if ( aFind != m_vDestColumns.end() )
+ {
+ delete aFind->second;
+ m_vDestColumns.erase(aFind);
+ }
+
+ m_aDestVec.insert(m_aDestVec.begin() + _nPos,
+ m_vDestColumns.emplace(_pField->GetName(),_pField).first);
+ m_mNameMapping[_pField->GetName()] = _pField->GetName();
+}
+
+void OCopyTableWizard::replaceColumn(sal_Int32 _nPos,OFieldDescription* _pField,const OUString& _sOldName)
+{
+ OSL_ENSURE(_pField,"FieldDescrioption is null!");
+ if ( _pField )
+ {
+ m_vDestColumns.erase(_sOldName);
+ OSL_ENSURE( m_vDestColumns.find(_pField->GetName()) == m_vDestColumns.end(),"Column with that name already exist!");
+
+ m_aDestVec[_nPos] = m_vDestColumns.emplace(_pField->GetName(),_pField).first;
+ }
+}
+
+void OCopyTableWizard::loadData( const ICopyTableSourceObject& _rSourceObject, ODatabaseExport::TColumns& _rColumns, ODatabaseExport::TColumnVector& _rColVector )
+{
+ for (auto const& column : _rColumns)
+ delete column.second;
+
+ _rColVector.clear();
+ _rColumns.clear();
+
+ OFieldDescription* pActFieldDescr = nullptr;
+ OUString const sCreateParam("x");
+ // ReadOnly-Flag
+ // On drop no line must be editable.
+ // On add only empty lines must be editable.
+ // On Add and Drop all lines can be edited.
+ Sequence< OUString > aColumns( _rSourceObject.getColumnNames() );
+ const OUString* pColumn = aColumns.getConstArray();
+ const OUString* pColumnEnd = pColumn + aColumns.getLength();
+
+ for ( ; pColumn != pColumnEnd; ++pColumn )
+ {
+ // get the properties of the column
+ pActFieldDescr = _rSourceObject.createFieldDescription( *pColumn );
+ OSL_ENSURE( pActFieldDescr, "OCopyTableWizard::loadData: illegal field description!" );
+ if ( !pActFieldDescr )
+ continue;
+
+ sal_Int32 nType = pActFieldDescr->GetType();
+ sal_Int32 nScale = pActFieldDescr->GetScale();
+ sal_Int32 nPrecision = pActFieldDescr->GetPrecision();
+ bool bAutoIncrement = pActFieldDescr->IsAutoIncrement();
+ OUString sTypeName = pActFieldDescr->GetTypeName();
+
+ // search for type
+ bool bForce;
+ TOTypeInfoSP pTypeInfo = ::dbaui::getTypeInfoFromType(m_aTypeInfo,nType,sTypeName,sCreateParam,nPrecision,nScale,bAutoIncrement,bForce);
+ if ( !pTypeInfo )
+ pTypeInfo = m_pTypeInfo;
+
+ pActFieldDescr->FillFromTypeInfo(pTypeInfo,true,false);
+ _rColVector.emplace_back(_rColumns.emplace(pActFieldDescr->GetName(),pActFieldDescr).first);
+ }
+
+ // determine which columns belong to the primary key
+ Sequence< OUString > aPrimaryKeyColumns( _rSourceObject.getPrimaryKeyColumnNames() );
+ const OUString* pKeyColName = aPrimaryKeyColumns.getConstArray();
+ const OUString* pKeyColEnd = pKeyColName + aPrimaryKeyColumns.getLength();
+
+ for( ; pKeyColName != pKeyColEnd; ++pKeyColName )
+ {
+ ODatabaseExport::TColumns::const_iterator keyPos = _rColumns.find( *pKeyColName );
+ if ( keyPos != _rColumns.end() )
+ {
+ keyPos->second->SetPrimaryKey( true );
+ keyPos->second->SetIsNullable( ColumnValue::NO_NULLS );
+ }
+ }
+}
+
+void OCopyTableWizard::clearDestColumns()
+{
+ clearColumns(m_vDestColumns,m_aDestVec);
+ m_bAddPKFirstTime = true;
+ m_mNameMapping.clear();
+}
+
+void OCopyTableWizard::appendColumns( Reference<XColumnsSupplier> const & _rxColSup, const ODatabaseExport::TColumnVector* _pVec, bool _bKeyColumns)
+{
+ // now append the columns
+ OSL_ENSURE(_rxColSup.is(),"No columns supplier");
+ if(!_rxColSup.is())
+ return;
+ Reference<XNameAccess> xColumns = _rxColSup->getColumns();
+ OSL_ENSURE(xColumns.is(),"No columns");
+ Reference<XDataDescriptorFactory> xColumnFactory(xColumns,UNO_QUERY);
+
+ Reference<XAppend> xAppend(xColumns,UNO_QUERY);
+ OSL_ENSURE(xAppend.is(),"No XAppend Interface!");
+
+ for (auto const& elem : *_pVec)
+ {
+ OFieldDescription* pField = elem->second;
+ if(!pField)
+ continue;
+
+ Reference<XPropertySet> xColumn;
+ if(pField->IsPrimaryKey() || !_bKeyColumns)
+ xColumn = xColumnFactory->createDataDescriptor();
+ if(xColumn.is())
+ {
+ if(!_bKeyColumns)
+ dbaui::setColumnProperties(xColumn,pField);
+ else
+ xColumn->setPropertyValue(PROPERTY_NAME,Any(pField->GetName()));
+
+ xAppend->appendByDescriptor(xColumn);
+ xColumn = nullptr;
+ // now only the settings are missing
+ if(xColumns->hasByName(pField->GetName()))
+ {
+ xColumn.set(xColumns->getByName(pField->GetName()),UNO_QUERY);
+ OSL_ENSURE(xColumn.is(),"OCopyTableWizard::appendColumns: Column is NULL!");
+ if ( xColumn.is() )
+ pField->copyColumnSettingsTo(xColumn);
+ }
+ else
+ {
+ SAL_WARN("dbaccess.ui", "OCopyTableWizard::appendColumns: invalid field name!");
+ }
+
+ }
+ }
+}
+
+void OCopyTableWizard::appendKey( Reference<XKeysSupplier> const & _rxSup, const ODatabaseExport::TColumnVector* _pVec)
+{
+ if(!_rxSup.is())
+ return; // the database doesn't support keys
+ OSL_ENSURE(_rxSup.is(),"No XKeysSupplier!");
+ Reference<XDataDescriptorFactory> xKeyFactory(_rxSup->getKeys(),UNO_QUERY);
+ OSL_ENSURE(xKeyFactory.is(),"No XDataDescriptorFactory Interface!");
+ if ( !xKeyFactory.is() )
+ return;
+ Reference<XAppend> xAppend(xKeyFactory,UNO_QUERY);
+ OSL_ENSURE(xAppend.is(),"No XAppend Interface!");
+
+ Reference<XPropertySet> xKey = xKeyFactory->createDataDescriptor();
+ OSL_ENSURE(xKey.is(),"Key is null!");
+ xKey->setPropertyValue(PROPERTY_TYPE,Any(KeyType::PRIMARY));
+
+ Reference<XColumnsSupplier> xColSup(xKey,UNO_QUERY);
+ if(xColSup.is())
+ {
+ appendColumns(xColSup,_pVec,true);
+ Reference<XNameAccess> xColumns = xColSup->getColumns();
+ if(xColumns.is() && xColumns->getElementNames().hasElements())
+ xAppend->appendByDescriptor(xKey);
+ }
+
+}
+
+Reference< XPropertySet > OCopyTableWizard::createView() const
+{
+ OUString sCommand( m_rSourceObject.getSelectStatement() );
+ OSL_ENSURE( !sCommand.isEmpty(), "OCopyTableWizard::createView: no statement in the source object!" );
+ // there are legitimate cases in which getSelectStatement does not provide a statement,
+ // but in all those cases, this method here should never be called.
+ return ::dbaui::createView( m_sName, m_xDestConnection, sCommand );
+}
+
+Reference< XPropertySet > OCopyTableWizard::returnTable()
+{
+ if ( getOperation() == CopyTableOperation::AppendData )
+ return getTable();
+ else
+ return createTable();
+}
+
+Reference< XPropertySet > OCopyTableWizard::getTable() const
+{
+ Reference< XPropertySet > xTable;
+
+ Reference<XTablesSupplier> xSup( m_xDestConnection, UNO_QUERY );
+ Reference< XNameAccess > xTables;
+ if(xSup.is())
+ xTables = xSup->getTables();
+ if(xTables.is() && xTables->hasByName(m_sName))
+ xTables->getByName(m_sName) >>= xTable;
+
+ return xTable;
+}
+
+Reference< XPropertySet > OCopyTableWizard::createTable()
+{
+ Reference< XPropertySet > xTable;
+
+ Reference<XTablesSupplier> xSup( m_xDestConnection, UNO_QUERY );
+ Reference< XNameAccess > xTables;
+ if(xSup.is())
+ xTables = xSup->getTables();
+ Reference<XDataDescriptorFactory> xFact(xTables,UNO_QUERY);
+ OSL_ENSURE(xFact.is(),"No XDataDescriptorFactory available!");
+ if(!xFact.is())
+ return nullptr;
+
+ xTable = xFact->createDataDescriptor();
+ OSL_ENSURE(xTable.is(),"Could not create a new object!");
+ if(!xTable.is())
+ return nullptr;
+
+ OUString sCatalog,sSchema,sTable;
+ Reference< XDatabaseMetaData> xMetaData = m_xDestConnection->getMetaData();
+ ::dbtools::qualifiedNameComponents(xMetaData,
+ m_sName,
+ sCatalog,
+ sSchema,
+ sTable,
+ ::dbtools::EComposeRule::InDataManipulation);
+
+ if ( sCatalog.isEmpty() && xMetaData->supportsCatalogsInTableDefinitions() )
+ {
+ sCatalog = m_xDestConnection->getCatalog();
+ }
+
+ if ( sSchema.isEmpty() && xMetaData->supportsSchemasInTableDefinitions() )
+ {
+ // query of current schema is quite inconsistent. In case of some
+ // DBMS's each user has their own schema.
+ sSchema = xMetaData->getUserName();
+ // In case of mysql it is not that simple
+ if(xMetaData->getDatabaseProductName() == "MySQL")
+ {
+ Reference< XStatement > xSelect = m_xDestConnection->createStatement();
+ Reference< XResultSet > xRs = xSelect->executeQuery("select database()");
+ (void)xRs->next(); // first and only result
+ Reference< XRow > xRow( xRs, UNO_QUERY_THROW );
+ sSchema = xRow->getString(1);
+ }
+ }
+
+ xTable->setPropertyValue(PROPERTY_CATALOGNAME,Any(sCatalog));
+ xTable->setPropertyValue(PROPERTY_SCHEMANAME,Any(sSchema));
+ xTable->setPropertyValue(PROPERTY_NAME,Any(sTable));
+
+ Reference< XColumnsSupplier > xSuppDestinationColumns( xTable, UNO_QUERY );
+ // now append the columns
+ const ODatabaseExport::TColumnVector& rVec = getDestVector();
+ appendColumns( xSuppDestinationColumns, &rVec );
+ // now append the primary key
+ Reference<XKeysSupplier> xKeySup(xTable,UNO_QUERY);
+ appendKey(xKeySup, &rVec);
+
+ Reference<XAppend> xAppend(xTables,UNO_QUERY);
+ if(xAppend.is())
+ xAppend->appendByDescriptor(xTable);
+
+ // xTable = NULL;
+ // we need to reget the table because after appending it, it is no longer valid
+ if(xTables->hasByName(m_sName))
+ xTables->getByName(m_sName) >>= xTable;
+ else
+ {
+ OUString sComposedName(
+ ::dbtools::composeTableName( m_xDestConnection->getMetaData(), xTable, ::dbtools::EComposeRule::InDataManipulation, false ) );
+ if(xTables->hasByName(sComposedName))
+ {
+ xTables->getByName(sComposedName) >>= xTable;
+ m_sName = sComposedName;
+ }
+ else
+ xTable = nullptr;
+ }
+
+ if(xTable.is())
+ {
+ xSuppDestinationColumns.set( xTable, UNO_QUERY_THROW );
+ // insert new table name into table filter
+ ::dbaui::appendToFilter(m_xDestConnection, m_sName, GetComponentContext(), m_xAssistant.get());
+
+ // copy ui settings
+ m_rSourceObject.copyUISettingsTo( xTable );
+ //copy filter and sorting
+ m_rSourceObject.copyFilterAndSortingTo(m_xDestConnection,xTable);
+ // set column mappings
+ Reference<XNameAccess> xNameAccess = xSuppDestinationColumns->getColumns();
+ Sequence< OUString> aSeq = xNameAccess->getElementNames();
+ const OUString* pIter = aSeq.getConstArray();
+ const OUString* pEnd = pIter + aSeq.getLength();
+
+ for(sal_Int32 nNewPos=1;pIter != pEnd;++pIter,++nNewPos)
+ {
+ ODatabaseExport::TColumns::const_iterator aDestIter = m_vDestColumns.find(*pIter);
+
+ if ( aDestIter != m_vDestColumns.end() )
+ {
+ ODatabaseExport::TColumnVector::const_iterator aFind = std::find(m_aDestVec.begin(),m_aDestVec.end(),aDestIter);
+ sal_Int32 nPos = (aFind - m_aDestVec.begin())+1;
+
+ ODatabaseExport::TPositions::iterator aPosFind = std::find_if(
+ m_vColumnPositions.begin(),
+ m_vColumnPositions.end(),
+ [nPos] (const ODatabaseExport::TPositions::value_type& tPos) {
+ return tPos.first == nPos;
+ }
+ );
+
+ if ( m_vColumnPositions.end() != aPosFind )
+ {
+ aPosFind->second = nNewPos;
+ OSL_ENSURE( m_vColumnTypes.size() > o3tl::make_unsigned( aPosFind - m_vColumnPositions.begin() ),
+ "Invalid index for vector!" );
+ m_vColumnTypes[ aPosFind - m_vColumnPositions.begin() ] = (*aFind)->second->GetType();
+ }
+ }
+ }
+ }
+
+ return xTable;
+}
+
+bool OCopyTableWizard::supportsPrimaryKey( const Reference< XConnection >& _rxConnection )
+{
+ OSL_PRECOND( _rxConnection.is(), "OCopyTableWizard::supportsPrimaryKey: invalid connection!" );
+ if ( !_rxConnection.is() )
+ return false;
+
+ ::dbtools::DatabaseMetaData aMetaData( _rxConnection );
+ return aMetaData.supportsPrimaryKeys();
+}
+
+bool OCopyTableWizard::supportsViews( const Reference< XConnection >& _rxConnection )
+{
+ OSL_PRECOND( _rxConnection.is(), "OCopyTableWizard::supportsViews: invalid connection!" );
+ if ( !_rxConnection.is() )
+ return false;
+
+ bool bSupportsViews( false );
+ try
+ {
+ Reference< XDatabaseMetaData > xMetaData( _rxConnection->getMetaData(), UNO_SET_THROW );
+ Reference< XViewsSupplier > xViewSups( _rxConnection, UNO_QUERY );
+ bSupportsViews = xViewSups.is();
+ if ( !bSupportsViews )
+ {
+ try
+ {
+ Reference< XResultSet > xRs( xMetaData->getTableTypes(), UNO_SET_THROW );
+ Reference< XRow > xRow( xRs, UNO_QUERY_THROW );
+ while ( xRs->next() )
+ {
+ OUString sValue = xRow->getString( 1 );
+ if ( !xRow->wasNull() && sValue.equalsIgnoreAsciiCase("View") )
+ {
+ bSupportsViews = true;
+ break;
+ }
+ }
+ }
+ catch( const SQLException& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ return bSupportsViews;
+}
+
+sal_Int32 OCopyTableWizard::getMaxColumnNameLength() const
+{
+ sal_Int32 nLen = 0;
+ if ( m_xDestConnection.is() )
+ {
+ try
+ {
+ Reference< XDatabaseMetaData > xMetaData( m_xDestConnection->getMetaData(), UNO_SET_THROW );
+ nLen = xMetaData->getMaxColumnNameLength();
+ }
+ catch(const Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+ return nLen;
+}
+
+void OCopyTableWizard::setOperation( const sal_Int16 _nOperation )
+{
+ m_nOperation = _nOperation;
+}
+
+
+OUString OCopyTableWizard::convertColumnName(const TColumnFindFunctor& _rCmpFunctor,
+ const OUString& _sColumnName,
+ std::u16string_view _sExtraChars,
+ sal_Int32 _nMaxNameLen)
+{
+ OUString sAlias = _sColumnName;
+ if ( isSQL92CheckEnabled( m_xDestConnection ) )
+ sAlias = ::dbtools::convertName2SQLName(_sColumnName,_sExtraChars);
+ if((_nMaxNameLen && sAlias.getLength() > _nMaxNameLen) || _rCmpFunctor(sAlias))
+ {
+ sal_Int32 nDiff = 1;
+ do
+ {
+ ++nDiff;
+ if(_nMaxNameLen && sAlias.getLength() >= _nMaxNameLen)
+ sAlias = sAlias.copy(0,sAlias.getLength() - (sAlias.getLength()-_nMaxNameLen+nDiff));
+
+ OUString sName(sAlias);
+ sal_Int32 nPos = 1;
+ sName += OUString::number(nPos);
+
+ while(_rCmpFunctor(sName))
+ {
+ sName = sAlias + OUString::number(++nPos);
+ }
+ sAlias = sName;
+ // we have to check again, it could happen that the name is already too long
+ }
+ while(_nMaxNameLen && sAlias.getLength() > _nMaxNameLen);
+ }
+ OSL_ENSURE(m_mNameMapping.find(_sColumnName) == m_mNameMapping.end(),"name doubled!");
+ m_mNameMapping[_sColumnName] = sAlias;
+ return sAlias;
+}
+
+void OCopyTableWizard::removeColumnNameFromNameMap(const OUString& _sName)
+{
+ m_mNameMapping.erase(_sName);
+}
+
+bool OCopyTableWizard::supportsType(sal_Int32 _nDataType, sal_Int32& _rNewDataType)
+{
+ bool bRet = m_aDestTypeInfo.find(_nDataType) != m_aDestTypeInfo.end();
+ if ( bRet )
+ _rNewDataType = _nDataType;
+ return bRet;
+}
+
+TOTypeInfoSP OCopyTableWizard::convertType(const TOTypeInfoSP& _pType, bool& _bNotConvert)
+{
+ if ( !m_bInterConnectionCopy )
+ // no need to convert if the source and destination connection are the same
+ return _pType;
+
+ bool bForce;
+ TOTypeInfoSP pType = ::dbaui::getTypeInfoFromType(m_aDestTypeInfo,_pType->nType,_pType->aTypeName,_pType->aCreateParams,_pType->nPrecision,_pType->nMaximumScale,_pType->bAutoIncrement,bForce);
+ if ( !pType || bForce )
+ { // no type found so we have to find the correct one ourself
+ sal_Int32 nDefaultType = DataType::VARCHAR;
+ switch(_pType->nType)
+ {
+ case DataType::TINYINT:
+ if(supportsType(DataType::SMALLINT,nDefaultType))
+ break;
+ [[fallthrough]];
+ case DataType::SMALLINT:
+ if(supportsType(DataType::INTEGER,nDefaultType))
+ break;
+ [[fallthrough]];
+ case DataType::INTEGER:
+ if(supportsType(DataType::FLOAT,nDefaultType))
+ break;
+ [[fallthrough]];
+ case DataType::FLOAT:
+ if(supportsType(DataType::REAL,nDefaultType))
+ break;
+ [[fallthrough]];
+ case DataType::DATE:
+ case DataType::TIME:
+ if( DataType::DATE == _pType->nType || DataType::TIME == _pType->nType )
+ {
+ if(supportsType(DataType::TIMESTAMP,nDefaultType))
+ break;
+ }
+ [[fallthrough]];
+ case DataType::TIMESTAMP:
+ case DataType::REAL:
+ case DataType::BIGINT:
+ if ( supportsType(DataType::DOUBLE,nDefaultType) )
+ break;
+ [[fallthrough]];
+ case DataType::DOUBLE:
+ if ( supportsType(DataType::NUMERIC,nDefaultType) )
+ break;
+ [[fallthrough]];
+ case DataType::NUMERIC:
+ supportsType(DataType::DECIMAL,nDefaultType);
+ break;
+ case DataType::DECIMAL:
+ if ( supportsType(DataType::NUMERIC,nDefaultType) )
+ break;
+ if ( supportsType(DataType::DOUBLE,nDefaultType) )
+ break;
+ break;
+ case DataType::VARCHAR:
+ if ( supportsType(DataType::LONGVARCHAR,nDefaultType) )
+ break;
+ break;
+ case DataType::LONGVARCHAR:
+ if ( supportsType(DataType::CLOB,nDefaultType) )
+ break;
+ break;
+ case DataType::BINARY:
+ if ( supportsType(DataType::VARBINARY,nDefaultType) )
+ break;
+ break;
+ case DataType::VARBINARY:
+ if ( supportsType(DataType::LONGVARBINARY,nDefaultType) )
+ break;
+ break;
+ case DataType::LONGVARBINARY:
+ if ( supportsType(DataType::BLOB,nDefaultType) )
+ break;
+ if ( supportsType(DataType::LONGVARCHAR,nDefaultType) )
+ break;
+ if ( supportsType(DataType::CLOB,nDefaultType) )
+ break;
+ break;
+ default:
+ nDefaultType = DataType::VARCHAR;
+ }
+ pType = ::dbaui::getTypeInfoFromType(m_aDestTypeInfo,nDefaultType,_pType->aTypeName,_pType->aCreateParams,_pType->nPrecision,_pType->nMaximumScale,_pType->bAutoIncrement,bForce);
+ if ( !pType )
+ {
+ _bNotConvert = false;
+ pType = ::dbaui::getTypeInfoFromType(m_aDestTypeInfo,DataType::VARCHAR,_pType->aTypeName,"x",50,0,false,bForce);
+ if ( !pType )
+ pType = m_pTypeInfo;
+ }
+ else if ( bForce )
+ _bNotConvert = false;
+ }
+ return pType;
+}
+
+OUString OCopyTableWizard::createUniqueName(const OUString& _sName)
+{
+ OUString sName = _sName;
+ Sequence< OUString > aColumnNames( m_rSourceObject.getColumnNames() );
+ if ( aColumnNames.hasElements() )
+ sName = ::dbtools::createUniqueName( aColumnNames, sName, false );
+ else
+ {
+ if ( m_vSourceColumns.find(sName) != m_vSourceColumns.end())
+ {
+ sal_Int32 nPos = 0;
+ while(m_vSourceColumns.find(sName) != m_vSourceColumns.end())
+ {
+ sName = _sName + OUString::number(++nPos);
+ }
+ }
+ }
+ return sName;
+}
+
+void OCopyTableWizard::showColumnTypeNotSupported(std::u16string_view _rColumnName)
+{
+ OUString sMessage( DBA_RES( STR_UNKNOWN_TYPE_FOUND ) );
+ sMessage = sMessage.replaceFirst("#1",_rColumnName);
+ showError(sMessage);
+}
+
+void OCopyTableWizard::showError(const OUString& _sErrorMessage)
+{
+ SQLExceptionInfo aInfo(_sErrorMessage);
+ showError(aInfo.get());
+}
+
+void OCopyTableWizard::showError(const Any& _aError)
+{
+ if ( _aError.hasValue() && m_xInteractionHandler.is() )
+ {
+ try
+ {
+ ::rtl::Reference< ::comphelper::OInteractionRequest > xRequest( new ::comphelper::OInteractionRequest( _aError ) );
+ m_xInteractionHandler->handle( xRequest );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/misc/WExtendPages.cxx b/dbaccess/source/ui/misc/WExtendPages.cxx
new file mode 100644
index 000000000..c7eac9181
--- /dev/null
+++ b/dbaccess/source/ui/misc/WExtendPages.cxx
@@ -0,0 +1,62 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <WExtendPages.hxx>
+#include <RtfReader.hxx>
+#include <HtmlReader.hxx>
+#include <WCopyTable.hxx>
+
+using namespace com::sun::star;
+
+namespace dbaui
+{
+
+void OWizHTMLExtend::createReaderAndCallParser(sal_Int32 _nRows)
+{
+ tools::SvRef<OHTMLReader> xParser = new OHTMLReader(*m_pParserStream,
+ _nRows,
+ std::vector(m_pParent->GetColumnPositions()),
+ m_pParent->GetFormatter(),
+ m_pParent->GetComponentContext(),
+ &m_pParent->getDestVector(),
+ &m_pParent->getTypeInfo(),
+ m_pParent->shouldCreatePrimaryKey());
+ xParser->CallParser();
+}
+
+void OWizRTFExtend::createReaderAndCallParser(sal_Int32 _nRows)
+{
+ tools::SvRef<ORTFReader> xParser = new ORTFReader(*m_pParserStream,
+ _nRows,
+ std::vector(m_pParent->GetColumnPositions()),
+ m_pParent->GetFormatter(),
+ m_pParent->GetComponentContext(),
+ &m_pParent->getDestVector(),
+ &m_pParent->getTypeInfo(),
+ m_pParent->shouldCreatePrimaryKey());
+ xParser->CallParser();
+}
+
+void OWizNormalExtend::createReaderAndCallParser(sal_Int32 /*_nRows*/)
+{
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/misc/WNameMatch.cxx b/dbaccess/source/ui/misc/WNameMatch.cxx
new file mode 100644
index 000000000..a6bb59da8
--- /dev/null
+++ b/dbaccess/source/ui/misc/WNameMatch.cxx
@@ -0,0 +1,330 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <WNameMatch.hxx>
+#include <osl/diagnose.h>
+#include <FieldDescriptions.hxx>
+#include <WCopyTable.hxx>
+#include <core_resource.hxx>
+#include <strings.hrc>
+#include <bitmaps.hlst>
+#include <com/sun/star/sdbc/DataType.hpp>
+
+using namespace ::dbaui;
+
+// OWizColumnSelect
+OWizNameMatching::OWizNameMatching(weld::Container* pPage, OCopyTableWizard* pWizard)
+ : OWizardPage(pPage, pWizard, "dbaccess/ui/namematchingpage.ui", "NameMatching")
+ , m_xTABLE_LEFT(m_xBuilder->weld_label("leftlabel"))
+ , m_xTABLE_RIGHT(m_xBuilder->weld_label("rightlabel"))
+ , m_xCTRL_LEFT(m_xBuilder->weld_tree_view("left"))
+ , m_xCTRL_RIGHT(m_xBuilder->weld_tree_view("right"))
+ , m_xColumn_up(m_xBuilder->weld_button("up"))
+ , m_xColumn_down(m_xBuilder->weld_button("down"))
+ , m_xColumn_up_right(m_xBuilder->weld_button("up_right"))
+ , m_xColumn_down_right(m_xBuilder->weld_button("down_right"))
+ , m_xAll(m_xBuilder->weld_button("all"))
+ , m_xNone(m_xBuilder->weld_button("none"))
+{
+ OUString aImgUp(BMP_UP);
+ OUString aImgDown(BMP_DOWN);
+ m_xColumn_up->set_from_icon_name(aImgUp);
+ m_xColumn_down->set_from_icon_name(aImgDown);
+ m_xColumn_up_right->set_from_icon_name(aImgUp);
+ m_xColumn_down_right->set_from_icon_name(aImgDown);
+
+ m_xColumn_up->connect_clicked(LINK(this,OWizNameMatching,ButtonClickHdl));
+ m_xColumn_down->connect_clicked(LINK(this,OWizNameMatching,ButtonClickHdl));
+
+ m_xColumn_up_right->connect_clicked(LINK(this,OWizNameMatching,RightButtonClickHdl));
+ m_xColumn_down_right->connect_clicked(LINK(this,OWizNameMatching,RightButtonClickHdl));
+
+ m_xAll->connect_clicked(LINK(this,OWizNameMatching,AllNoneClickHdl));
+ m_xNone->connect_clicked(LINK(this,OWizNameMatching,AllNoneClickHdl));
+
+ m_xCTRL_LEFT->enable_toggle_buttons(weld::ColumnToggleType::Check);
+
+ m_xCTRL_LEFT->connect_changed(LINK(this,OWizNameMatching,TableListClickHdl));
+ m_xCTRL_RIGHT->connect_changed(LINK(this,OWizNameMatching,TableListRightSelectHdl));
+
+ m_sSourceText = m_xTABLE_LEFT->get_label() + "\n";
+ m_sDestText = m_xTABLE_RIGHT->get_label() + "\n";
+}
+
+OWizNameMatching::~OWizNameMatching()
+{
+}
+
+void OWizNameMatching::Reset()
+{
+ m_bFirstTime = false;
+}
+
+void OWizNameMatching::Activate( )
+{
+ // set source table name
+ OUString aName = m_sSourceText + m_pParent->m_sSourceName;
+
+ m_xTABLE_LEFT->set_label(aName);
+
+ // set dest table name
+ aName = m_sDestText + m_pParent->m_sName;
+ m_xTABLE_RIGHT->set_label(aName);
+
+ FillListBox(*m_xCTRL_LEFT, m_pParent->getSrcVector(), true);
+ FillListBox(*m_xCTRL_RIGHT, m_pParent->getDestVector(), false);
+
+ m_xColumn_up->set_sensitive( m_xCTRL_LEFT->n_children() > 1 );
+ m_xColumn_down->set_sensitive( m_xCTRL_LEFT->n_children() > 1 );
+
+ m_xColumn_up_right->set_sensitive( m_xCTRL_RIGHT->n_children() > 1 );
+ m_xColumn_down_right->set_sensitive( m_xCTRL_RIGHT->n_children() > 1 );
+
+ m_pParent->EnableNextButton(false);
+ m_xCTRL_LEFT->grab_focus();
+ TableListClickHdl(*m_xCTRL_LEFT);
+}
+
+bool OWizNameMatching::LeavePage()
+{
+
+ const ODatabaseExport::TColumnVector& rSrcColumns = m_pParent->getSrcVector();
+
+ m_pParent->m_vColumnPositions.clear();
+ m_pParent->m_vColumnTypes.clear();
+ m_pParent->m_vColumnPositions.resize( rSrcColumns.size(), ODatabaseExport::TPositions::value_type( COLUMN_POSITION_NOT_FOUND, COLUMN_POSITION_NOT_FOUND ) );
+ m_pParent->m_vColumnTypes.resize( rSrcColumns.size(), COLUMN_POSITION_NOT_FOUND );
+
+ std::unique_ptr<weld::TreeIter> xLeftEntry = m_xCTRL_LEFT->make_iterator();
+ std::unique_ptr<weld::TreeIter> xRightEntry = m_xCTRL_RIGHT->make_iterator();
+
+ sal_Int32 nParamPos = 0;
+ bool bLeftEntry = m_xCTRL_LEFT->get_iter_first(*xLeftEntry);
+ bool bRightEntry = m_xCTRL_RIGHT->get_iter_first(*xRightEntry);
+ while (bLeftEntry && bRightEntry)
+ {
+ OFieldDescription* pSrcField = weld::fromId<OFieldDescription*>(m_xCTRL_LEFT->get_id(*xLeftEntry));
+ OSL_ENSURE(pSrcField,"OWizNameMatching: OColumn can not be null!");
+
+ sal_Int32 nPos = 0;
+ for (auto const& column : rSrcColumns)
+ {
+ if (column->second == pSrcField)
+ break;
+ ++nPos;
+ }
+
+ if (m_xCTRL_LEFT->get_toggle(*xLeftEntry) == TRISTATE_TRUE)
+ {
+ OFieldDescription* pDestField = weld::fromId<OFieldDescription*>(m_xCTRL_RIGHT->get_id(*xRightEntry));
+ OSL_ENSURE(pDestField,"OWizNameMatching: OColumn can not be null!");
+ const ODatabaseExport::TColumnVector& rDestColumns = m_pParent->getDestVector();
+ sal_Int32 nPosDest = 1;
+ bool bDestColumnFound = false;
+ TOTypeInfoSP typeInfoSPFound;
+ for (auto const& column : rDestColumns)
+ {
+ if (column->second == pDestField)
+ {
+ bDestColumnFound = true;
+ typeInfoSPFound = column->second->getSpecialTypeInfo();
+ break;
+ }
+ ++nPosDest;
+ }
+
+ OSL_ENSURE((nPos) < static_cast<sal_Int32>(m_pParent->m_vColumnPositions.size()),"m_pParent->m_vColumnPositions: Illegal index for vector");
+ m_pParent->m_vColumnPositions[nPos].first = ++nParamPos;
+ m_pParent->m_vColumnPositions[nPos].second = nPosDest;
+
+ TOTypeInfoSP pTypeInfo;
+
+ assert(bDestColumnFound);
+ if (bDestColumnFound)
+ {
+ bool bNotConvert = true;
+ pTypeInfo = m_pParent->convertType(typeInfoSPFound, bNotConvert);
+ }
+
+ sal_Int32 nType = css::sdbc::DataType::VARCHAR;
+ if ( pTypeInfo )
+ nType = pTypeInfo->nType;
+ m_pParent->m_vColumnTypes[nPos] = nType;
+ }
+ else
+ {
+ m_pParent->m_vColumnPositions[nPos].first = COLUMN_POSITION_NOT_FOUND;
+ m_pParent->m_vColumnPositions[nPos].second = COLUMN_POSITION_NOT_FOUND;
+ }
+
+ bLeftEntry = m_xCTRL_LEFT->iter_next(*xLeftEntry);
+ bRightEntry = m_xCTRL_RIGHT->iter_next(*xRightEntry);
+ }
+
+ return true;
+}
+
+OUString OWizNameMatching::GetTitle() const { return DBA_RES(STR_WIZ_NAME_MATCHING_TITLE); }
+
+IMPL_LINK(OWizNameMatching, ButtonClickHdl, weld::Button&, rButton, void)
+{
+ int nPos = m_xCTRL_LEFT->get_selected_index();
+ if (nPos == -1)
+ return;
+
+ int nOrigPos = nPos;
+ if (&rButton == m_xColumn_up.get() && nPos)
+ --nPos;
+ else if (&rButton == m_xColumn_down.get() && nPos < m_xCTRL_LEFT->n_children() - 1)
+ ++nPos;
+
+ m_xCTRL_LEFT->swap(nOrigPos, nPos);
+
+ m_xCTRL_LEFT->scroll_to_row(nPos);
+
+ TableListClickHdl(*m_xCTRL_LEFT);
+}
+
+IMPL_LINK( OWizNameMatching, RightButtonClickHdl, weld::Button&, rButton, void )
+{
+ int nPos = m_xCTRL_RIGHT->get_selected_index();
+ if (nPos == -1)
+ return;
+
+ int nOrigPos = nPos;
+ if (&rButton == m_xColumn_up_right.get() && nPos)
+ --nPos;
+ else if (&rButton == m_xColumn_down_right.get() && nPos < m_xCTRL_RIGHT->n_children() - 1)
+ ++nPos;
+
+ m_xCTRL_RIGHT->swap(nOrigPos, nPos);
+
+ m_xCTRL_RIGHT->scroll_to_row(nPos);
+
+ TableListRightSelectHdl(*m_xCTRL_RIGHT);
+}
+
+namespace
+{
+ int GetFirstEntryInView(weld::TreeView& rTreeView)
+ {
+ int nFirstEntryInView = -1;
+
+ rTreeView.visible_foreach([&nFirstEntryInView, &rTreeView](weld::TreeIter& rEntry){
+ nFirstEntryInView = rTreeView.get_iter_index_in_parent(rEntry);
+ // stop after first entry
+ return true;
+ });
+
+ return nFirstEntryInView;
+ }
+}
+
+IMPL_LINK_NOARG(OWizNameMatching, TableListClickHdl, weld::TreeView&, void)
+{
+ int nPos = m_xCTRL_LEFT->get_selected_index();
+ if (nPos == -1)
+ return;
+
+ int nOldEntry = m_xCTRL_RIGHT->get_selected_index();
+ if (nOldEntry != -1 && nPos != nOldEntry)
+ {
+ m_xCTRL_RIGHT->unselect(nOldEntry);
+ if (nPos < m_xCTRL_RIGHT->n_children())
+ {
+ int nNewPos = GetFirstEntryInView(*m_xCTRL_LEFT);
+ if ( nNewPos - nPos == 1 )
+ --nNewPos;
+ m_xCTRL_RIGHT->scroll_to_row(nNewPos);
+ m_xCTRL_RIGHT->select(nPos);
+ }
+ }
+ else if (nOldEntry == -1)
+ {
+ if (nPos < m_xCTRL_RIGHT->n_children())
+ m_xCTRL_RIGHT->select(nPos);
+ }
+}
+
+IMPL_LINK_NOARG( OWizNameMatching, TableListRightSelectHdl, weld::TreeView&, void )
+{
+ int nPos = m_xCTRL_RIGHT->get_selected_index();
+ if (nPos == -1)
+ return;
+
+ OFieldDescription* pColumn = weld::fromId<OFieldDescription*>(m_xCTRL_RIGHT->get_id(nPos));
+ if (pColumn->IsAutoIncrement())
+ {
+ m_xCTRL_RIGHT->unselect(nPos);
+ return;
+ }
+
+ int nOldEntry = m_xCTRL_LEFT->get_selected_index();
+ if (nOldEntry != -1 && nPos != nOldEntry)
+ {
+ m_xCTRL_LEFT->unselect(nOldEntry);
+ if (nPos < m_xCTRL_LEFT->n_children())
+ {
+ int nNewPos = GetFirstEntryInView(*m_xCTRL_RIGHT);
+ if ( nNewPos - nPos == 1 )
+ nNewPos--;
+ m_xCTRL_LEFT->scroll_to_row(nNewPos);
+ m_xCTRL_LEFT->select(nPos);
+ }
+ }
+ else if (nOldEntry == -1)
+ {
+ if (nPos < m_xCTRL_LEFT->n_children())
+ m_xCTRL_LEFT->select(nPos);
+ }
+}
+
+IMPL_LINK(OWizNameMatching, AllNoneClickHdl, weld::Button&, rButton, void)
+{
+ bool bAll = &rButton == m_xAll.get();
+ m_xCTRL_LEFT->all_foreach([this, bAll](weld::TreeIter& rEntry){
+ m_xCTRL_LEFT->set_toggle(rEntry, bAll ? TRISTATE_TRUE : TRISTATE_FALSE);
+ return false;
+ });
+}
+
+void OWizNameMatching::FillListBox(weld::TreeView& rTreeView, const ODatabaseExport::TColumnVector& rList, bool bCheckButtons)
+{
+ rTreeView.clear();
+
+ int nRow(0);
+
+ for (auto const& elem : rList)
+ {
+ rTreeView.append();
+ if (bCheckButtons)
+ {
+ bool bChecked = !elem->second->IsAutoIncrement();
+ rTreeView.set_toggle(nRow, bChecked ? TRISTATE_TRUE : TRISTATE_FALSE);
+ }
+ rTreeView.set_text(nRow, elem->first, 0);
+ rTreeView.set_id(nRow, weld::toId(elem->second));
+ ++nRow;
+ }
+
+ if (rTreeView.n_children())
+ rTreeView.select(0);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/misc/WTypeSelect.cxx b/dbaccess/source/ui/misc/WTypeSelect.cxx
new file mode 100644
index 000000000..d5462ed3f
--- /dev/null
+++ b/dbaccess/source/ui/misc/WTypeSelect.cxx
@@ -0,0 +1,417 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <WTypeSelect.hxx>
+#include <bitmaps.hlst>
+#include <tools/diagnose_ex.h>
+#include <osl/diagnose.h>
+#include <FieldDescriptions.hxx>
+#include <WCopyTable.hxx>
+#include <strings.hrc>
+#include <tools/stream.hxx>
+#include <vcl/commandevent.hxx>
+#include <vcl/svapp.hxx>
+#include <UITools.hxx>
+#include <core_resource.hxx>
+#include <FieldControls.hxx>
+
+using namespace ::dbaui;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::util;
+using namespace ::com::sun::star::sdbc;
+
+// OWizTypeSelectControl
+OWizTypeSelectControl::OWizTypeSelectControl(weld::Container* pPage, OWizTypeSelect* pParentTabPage)
+ : OFieldDescControl(pPage, nullptr)
+ , m_pParentTabPage(pParentTabPage)
+{
+}
+
+OWizTypeSelectControl::~OWizTypeSelectControl()
+{
+}
+
+void OWizTypeSelectControl::ActivateAggregate( EControlType eType )
+{
+ switch(eType )
+ {
+ case tpFormat:
+ case tpDefault:
+ case tpAutoIncrement:
+ case tpAutoIncrementValue:
+ break;
+ default:
+ OFieldDescControl::ActivateAggregate( eType );
+ }
+}
+
+void OWizTypeSelectControl::DeactivateAggregate( EControlType eType )
+{
+ switch(eType )
+ {
+ case tpFormat:
+ case tpDefault:
+ case tpAutoIncrement:
+ case tpAutoIncrementValue:
+ break;
+ default:
+ OFieldDescControl::DeactivateAggregate( eType );
+ }
+}
+
+void OWizTypeSelectControl::CellModified(sal_Int32 nRow, sal_uInt16 nColId )
+{
+ OSL_ENSURE(nRow == -1,"nRow must be -1!");
+
+ weld::TreeView* pListBox = m_pParentTabPage->m_xColumnNames->GetWidget();
+
+ OFieldDescription* pCurFieldDescr = getCurrentFieldDescData();
+
+ const sal_Int32 nPos = pListBox->find_text(pCurFieldDescr->GetName());
+ pCurFieldDescr = weld::fromId<OFieldDescription*>(pListBox->get_id(nPos));
+ OSL_ENSURE( pCurFieldDescr, "OWizTypeSelectControl::CellModified: Columnname/type not found in the listbox!" );
+ if ( !pCurFieldDescr )
+ return;
+ setCurrentFieldDescData( pCurFieldDescr );
+
+ OUString sName = pCurFieldDescr->GetName();
+ OUString sNewName;
+ const OPropColumnEditCtrl* pColumnName = getColumnCtrl();
+ if ( pColumnName )
+ sNewName = pColumnName->get_text();
+
+ switch(nColId)
+ {
+ case FIELD_PROPERTY_COLUMNNAME:
+ {
+ OCopyTableWizard* pWiz = m_pParentTabPage->m_pParent;
+ // first we have to check if this name already exists
+ bool bDoubleName = false;
+ bool bCase = true;
+ if ( getMetaData().is() && !getMetaData()->supportsMixedCaseQuotedIdentifiers() )
+ {
+ bCase = false;
+ const sal_Int32 nCount = pListBox->n_children();
+ for (sal_Int32 i=0 ; !bDoubleName && i < nCount ; ++i)
+ {
+ OUString sEntry(pListBox->get_text(i));
+ bDoubleName = sNewName.equalsIgnoreAsciiCase(sEntry);
+ }
+ if ( !bDoubleName && pWiz->shouldCreatePrimaryKey() )
+ bDoubleName = sNewName.equalsIgnoreAsciiCase(pWiz->getPrimaryKeyName());
+
+ }
+ else
+ bDoubleName = ((pListBox->find_text(sNewName) != -1)
+ || ( pWiz->shouldCreatePrimaryKey()
+ && pWiz->getPrimaryKeyName() == sNewName) );
+
+ if ( bDoubleName )
+ {
+ OUString strMessage = DBA_RES(STR_TABLEDESIGN_DUPLICATE_NAME);
+ strMessage = strMessage.replaceFirst("$column$", sNewName);
+ pWiz->showError(strMessage);
+ pCurFieldDescr->SetName(sName);
+ DisplayData(pCurFieldDescr);
+ m_pParentTabPage->setDuplicateName(true);
+ return;
+ }
+
+ OUString sOldName = pCurFieldDescr->GetName();
+ pCurFieldDescr->SetName(sNewName);
+ m_pParentTabPage->setDuplicateName(false);
+
+ // now we change the name
+
+ ::comphelper::UStringMixEqual aCase(bCase);
+ for (auto & elem : pWiz->m_mNameMapping)
+ {
+ if ( aCase(elem.second,sName) )
+ {
+ elem.second = sNewName;
+ break;
+ }
+ }
+
+ pListBox->remove(nPos);
+ pListBox->insert_text(nPos, pCurFieldDescr->GetName());
+ pListBox->set_id(nPos, weld::toId(pCurFieldDescr));
+
+ pWiz->replaceColumn(nPos,pCurFieldDescr,sOldName);
+ }
+ break;
+ }
+ saveCurrentFieldDescData();
+}
+
+css::lang::Locale OWizTypeSelectControl::GetLocale() const
+{
+ return m_pParentTabPage->m_pParent->GetLocale();
+}
+
+Reference< XNumberFormatter > OWizTypeSelectControl::GetFormatter() const
+{
+ return m_pParentTabPage->m_pParent->GetFormatter();
+}
+
+TOTypeInfoSP OWizTypeSelectControl::getTypeInfo(sal_Int32 _nPos)
+{
+ return m_pParentTabPage->m_pParent->getDestTypeInfo(_nPos);
+}
+
+const OTypeInfoMap* OWizTypeSelectControl::getTypeInfo() const
+{
+ return &m_pParentTabPage->m_pParent->getDestTypeInfo();
+}
+
+css::uno::Reference< css::sdbc::XDatabaseMetaData> OWizTypeSelectControl::getMetaData()
+{
+ return m_pParentTabPage->m_pParent->m_xDestConnection->getMetaData();
+}
+
+css::uno::Reference< css::sdbc::XConnection> OWizTypeSelectControl::getConnection()
+{
+ return m_pParentTabPage->m_pParent->m_xDestConnection;
+}
+
+bool OWizTypeSelectControl::isAutoIncrementValueEnabled() const
+{
+ return m_pParentTabPage->m_bAutoIncrementEnabled;
+}
+
+OUString OWizTypeSelectControl::getAutoIncrementValue() const
+{
+ return m_pParentTabPage->m_sAutoIncrementValue;
+}
+
+OWizTypeSelect::OWizTypeSelect(weld::Container* pPage, OCopyTableWizard* pWizard, SvStream* pStream)
+ : OWizardPage(pPage, pWizard, "dbaccess/ui/typeselectpage.ui", "TypeSelect")
+ , m_xColumnNames(new OWizTypeSelectList(m_xBuilder->weld_tree_view("columnnames")))
+ , m_xColumns(m_xBuilder->weld_label("columns"))
+ , m_xControlContainer(m_xBuilder->weld_container("control_container"))
+ , m_xTypeControl(new OWizTypeSelectControl(m_xControlContainer.get(), this))
+ , m_xAutoType(m_xBuilder->weld_label("autotype"))
+ , m_xAutoFt(m_xBuilder->weld_label("autolabel"))
+ , m_xAutoEt(m_xBuilder->weld_spin_button("auto"))
+ , m_xAutoPb(m_xBuilder->weld_button("autobutton"))
+ , m_pParserStream(pStream)
+ , m_nDisplayRow(0)
+ , m_bAutoIncrementEnabled(false)
+ , m_bDuplicateName(false)
+{
+ m_xColumnNames->connect_changed(LINK(this,OWizTypeSelect,ColumnSelectHdl));
+
+ m_xTypeControl->Init();
+
+ m_xAutoEt->set_text("10");
+ m_xAutoEt->set_digits(0);
+ m_xAutoPb->connect_clicked(LINK(this,OWizTypeSelect,ButtonClickHdl));
+ m_xColumnNames->set_selection_mode(SelectionMode::Multiple);
+
+ try
+ {
+ m_xColumnNames->SetPKey( m_pParent->supportsPrimaryKey() );
+ ::dbaui::fillAutoIncrementValue( m_pParent->m_xDestConnection, m_bAutoIncrementEnabled, m_sAutoIncrementValue );
+ }
+ catch(const Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+}
+
+OWizTypeSelect::~OWizTypeSelect()
+{
+}
+
+OUString OWizTypeSelect::GetTitle() const
+{
+ return DBA_RES(STR_WIZ_TYPE_SELECT_TITLE);
+}
+
+IMPL_LINK_NOARG(OWizTypeSelect, ColumnSelectHdl, weld::TreeView&, void)
+{
+ OFieldDescription* pField = weld::fromId<OFieldDescription*>(m_xColumnNames->get_selected_id());
+ if (pField)
+ m_xTypeControl->DisplayData(pField);
+
+ m_xTypeControl->Enable(m_xColumnNames->count_selected_rows() == 1);
+}
+
+void OWizTypeSelect::Reset()
+{
+ // restore original state
+ m_xColumnNames->clear();
+ sal_Int32 nCount(0), nBreakPos;
+ m_pParent->CheckColumns(nBreakPos);
+
+ const ODatabaseExport::TColumnVector& rDestColumns = m_pParent->getDestVector();
+ for (auto const& column : rDestColumns)
+ {
+ OUString sId(weld::toId(column->second));
+ m_xColumnNames->append(sId, column->first);
+ if (column->second->IsPrimaryKey())
+ m_xColumnNames->set_image(nCount, BMP_PRIMARY_KEY);
+ ++nCount;
+ }
+ m_bFirstTime = false;
+}
+
+void OWizTypeSelect::Activate( )
+{
+ bool bOldFirstTime = m_bFirstTime;
+ Reset();
+ m_bFirstTime = bOldFirstTime;
+
+ m_xColumnNames->select(m_nDisplayRow);
+ m_nDisplayRow = 0;
+ ColumnSelectHdl(*m_xColumnNames->GetWidget());
+}
+
+bool OWizTypeSelect::LeavePage()
+{
+ bool bDuplicateName = false;
+ OFieldDescription* pField = weld::fromId<OFieldDescription*>(m_xColumnNames->get_selected_id());
+ if ( pField )
+ {
+ m_xTypeControl->SaveData(pField);
+ bDuplicateName = m_bDuplicateName;
+ }
+ return !bDuplicateName;
+}
+
+void OWizTypeSelect::EnableAuto(bool bEnable)
+{
+ m_xAutoFt->set_visible(bEnable);
+ m_xAutoEt->set_visible(bEnable);
+ m_xAutoPb->set_visible(bEnable);
+ m_xAutoType->set_visible(bEnable);
+}
+
+IMPL_LINK_NOARG(OWizTypeSelect, ButtonClickHdl, weld::Button&, void)
+{
+ sal_Int32 nBreakPos;
+ m_pParent->CheckColumns(nBreakPos);
+
+ // fill column list
+ sal_uInt32 nRows = m_xAutoEt->get_text().toInt32();
+ if(m_pParserStream)
+ {
+ sal_uInt64 const nTell = m_pParserStream->Tell(); // might change seek position of stream
+
+ createReaderAndCallParser(nRows);
+ m_pParserStream->Seek(nTell);
+ }
+
+ Activate();
+}
+
+OWizTypeSelectList::OWizTypeSelectList(std::unique_ptr<weld::TreeView> xControl)
+ : m_xControl(std::move(xControl))
+ , m_bPKey(false)
+{
+ m_xControl->connect_popup_menu(LINK(this, OWizTypeSelectList, CommandHdl));
+}
+
+bool OWizTypeSelectList::IsPrimaryKeyAllowed() const
+{
+ auto aRows = m_xControl->get_selected_rows();
+ std::sort(aRows.begin(), aRows.end());
+
+ const sal_Int32 nCount = aRows.size();
+
+ for( sal_Int32 j = 0; m_bPKey && j < nCount; ++j )
+ {
+ OFieldDescription* pField = weld::fromId<OFieldDescription*>(m_xControl->get_id(aRows[j]));
+ if(!pField || pField->getTypeInfo()->nSearchType == ColumnSearch::NONE)
+ return false;
+ }
+ return true;
+}
+
+void OWizTypeSelectList::setPrimaryKey(OFieldDescription* _pFieldDescr, sal_uInt16 _nPos, bool _bSet)
+{
+ _pFieldDescr->SetPrimaryKey(_bSet);
+ if( _bSet )
+ {
+ m_xControl->set_image(_nPos, BMP_PRIMARY_KEY);
+ }
+ else if( _pFieldDescr->getTypeInfo()->bNullable )
+ {
+ _pFieldDescr->SetControlDefault(Any());
+ m_xControl->set_image(_nPos, OUString());
+ }
+}
+
+IMPL_LINK(OWizTypeSelectList, CommandHdl, const CommandEvent&, rCEvt, bool)
+{
+ if (rCEvt.GetCommand() != CommandEventId::ContextMenu)
+ return false;
+ if (!IsPrimaryKeyAllowed())
+ return false;
+
+ std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(m_xControl.get(), "dbaccess/ui/keymenu.ui"));
+ auto xContextMenu = xBuilder->weld_menu("menu");
+ // Should primary key checkbox be checked?
+ const sal_Int32 nCount = m_xControl->n_children();
+ bool bCheckOk = false;
+ for(sal_Int32 j = 0 ; j < nCount ; ++j)
+ {
+ OFieldDescription* pFieldDescr = weld::fromId<OFieldDescription*>(m_xControl->get_id(j));
+ // if at least one of the fields is selected but not in the primary key,
+ // or is in the primary key but not selected, then don't check the
+ // primary key checkbox.
+ if( pFieldDescr && pFieldDescr->IsPrimaryKey() != m_xControl->is_selected(j) )
+ {
+ bCheckOk = false;
+ break;
+ }
+ if (!bCheckOk && m_xControl->is_selected(j))
+ bCheckOk = true;
+ }
+
+ if (bCheckOk)
+ xContextMenu->set_active("primarykey", true);
+
+ OString sCommand(xContextMenu->popup_at_rect(m_xControl.get(), tools::Rectangle(rCEvt.GetMousePosPixel(), Size(1,1))));
+ if (sCommand != "primarykey")
+ return true;
+
+ for (sal_Int32 j = 0 ; j < nCount; ++j)
+ {
+ OFieldDescription* pFieldDescr = weld::fromId<OFieldDescription*>(m_xControl->get_id(j));
+ if (pFieldDescr)
+ {
+ if(!bCheckOk && m_xControl->is_selected(j))
+ {
+ setPrimaryKey(pFieldDescr,j,true);
+ }
+ else
+ {
+ setPrimaryKey(pFieldDescr,j);
+ }
+ }
+ }
+ m_aChangeHdl.Call(*m_xControl);
+
+ return true;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/misc/asyncmodaldialog.cxx b/dbaccess/source/ui/misc/asyncmodaldialog.cxx
new file mode 100644
index 000000000..3c59a58f8
--- /dev/null
+++ b/dbaccess/source/ui/misc/asyncmodaldialog.cxx
@@ -0,0 +1,91 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <asyncmodaldialog.hxx>
+
+#include <com/sun/star/lang/IllegalArgumentException.hpp>
+
+#include <vcl/svapp.hxx>
+#include <tools/diagnose_ex.h>
+
+namespace dbaui
+{
+
+ using ::com::sun::star::uno::Reference;
+ using ::com::sun::star::ui::dialogs::XExecutableDialog;
+ using ::com::sun::star::lang::IllegalArgumentException;
+ using ::com::sun::star::uno::Exception;
+
+ namespace {
+
+ // AsyncDialogExecutor
+ class DialogExecutor_Impl
+ {
+ Reference< XExecutableDialog > m_xDialog;
+
+ public:
+ explicit DialogExecutor_Impl( const Reference< XExecutableDialog >& _rxDialog )
+ :m_xDialog( _rxDialog )
+ {
+ }
+
+ void execute()
+ {
+ Application::PostUserEvent( LINK( this, DialogExecutor_Impl, onExecute ) );
+ }
+
+ protected:
+ ~DialogExecutor_Impl()
+ {
+ }
+
+ private:
+ DECL_LINK( onExecute, void*, void );
+ };
+
+ }
+
+ IMPL_LINK_NOARG( DialogExecutor_Impl, onExecute, void*, void )
+ {
+ try
+ {
+ m_xDialog->execute();
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+
+ delete this;
+ }
+
+ // AsyncDialogExecutor
+ void AsyncDialogExecutor::executeModalDialogAsync( const Reference< XExecutableDialog >& _rxDialog )
+ {
+ if ( !_rxDialog.is() )
+ throw IllegalArgumentException();
+
+ DialogExecutor_Impl* pExecutor = new DialogExecutor_Impl( _rxDialog );
+ pExecutor->execute();
+ // will delete itself
+ }
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/misc/charsets.cxx b/dbaccess/source/ui/misc/charsets.cxx
new file mode 100644
index 000000000..546d21cb0
--- /dev/null
+++ b/dbaccess/source/ui/misc/charsets.cxx
@@ -0,0 +1,130 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <charsets.hxx>
+#include <core_resource.hxx>
+#include <osl/diagnose.h>
+#include <strings.hrc>
+#include <rtl/tencinfo.h>
+#include <svx/txenctab.hxx>
+
+namespace dbaui
+{
+ using namespace ::dbtools;
+
+ // OCharsetDisplay
+ OCharsetDisplay::OCharsetDisplay()
+ : m_aSystemDisplayName(DBA_RES( STR_RSC_CHARSETS ))
+ {
+ }
+
+ bool OCharsetDisplay::approveEncoding( const rtl_TextEncoding _eEncoding, const rtl_TextEncodingInfo& _rInfo ) const
+ {
+ if ( !OCharsetMap::approveEncoding( _eEncoding, _rInfo ) )
+ return false;
+
+ if ( RTL_TEXTENCODING_DONTKNOW == _eEncoding )
+ return true;
+
+ return !SvxTextEncodingTable::GetTextString(_eEncoding).isEmpty();
+ }
+
+ OCharsetDisplay::const_iterator OCharsetDisplay::begin() const
+ {
+ return const_iterator( this, OCharsetMap::begin() );
+ }
+
+ OCharsetDisplay::const_iterator OCharsetDisplay::end() const
+ {
+ return const_iterator( this, OCharsetMap::end() );
+ }
+
+ OCharsetDisplay::const_iterator OCharsetDisplay::findEncoding(const rtl_TextEncoding _eEncoding) const
+ {
+ OCharsetMap::const_iterator aBaseIter = OCharsetMap::find(_eEncoding);
+ return const_iterator( this, aBaseIter );
+ }
+
+ OCharsetDisplay::const_iterator OCharsetDisplay::findIanaName(const OUString& _rIanaName) const
+ {
+ OCharsetMap::const_iterator aBaseIter = OCharsetMap::findIanaName(_rIanaName);
+ return const_iterator( this, aBaseIter );
+ }
+
+ OCharsetDisplay::const_iterator OCharsetDisplay::findDisplayName(const OUString& _rDisplayName) const
+ {
+ rtl_TextEncoding eEncoding = RTL_TEXTENCODING_DONTKNOW;
+ if ( _rDisplayName != m_aSystemDisplayName )
+ {
+ eEncoding = SvxTextEncodingTable::GetTextEncoding(_rDisplayName);
+ OSL_ENSURE( RTL_TEXTENCODING_DONTKNOW != eEncoding,
+ "OCharsetDisplay::find: non-empty display name, but DONTKNOW!" );
+ }
+ return const_iterator( this, OCharsetMap::find( eEncoding ) );
+ }
+
+ // CharsetDisplayDerefHelper
+ CharsetDisplayDerefHelper::CharsetDisplayDerefHelper(const CharsetDisplayDerefHelper& _rSource)
+ :CharsetDisplayDerefHelper_Base(_rSource)
+ ,m_sDisplayName(_rSource.m_sDisplayName)
+ {
+ }
+
+ CharsetDisplayDerefHelper::CharsetDisplayDerefHelper(const ::dbtools::CharsetIteratorDerefHelper& _rBase, const OUString& _rDisplayName)
+ :CharsetDisplayDerefHelper_Base(_rBase)
+ ,m_sDisplayName(_rDisplayName)
+ {
+ OSL_ENSURE( !m_sDisplayName.isEmpty(), "CharsetDisplayDerefHelper::CharsetDisplayDerefHelper: invalid display name!" );
+ }
+
+ // OCharsetDisplay::ExtendedCharsetIterator
+ OCharsetDisplay::ExtendedCharsetIterator::ExtendedCharsetIterator( const OCharsetDisplay* _pContainer, const base_iterator& _rPosition )
+ :m_pContainer(_pContainer)
+ ,m_aPosition(_rPosition)
+ {
+ OSL_ENSURE(m_pContainer, "OCharsetDisplay::ExtendedCharsetIterator::ExtendedCharsetIterator : invalid container!");
+ }
+
+ CharsetDisplayDerefHelper OCharsetDisplay::ExtendedCharsetIterator::operator*() const
+ {
+ OSL_ENSURE( m_aPosition != m_pContainer->OCharsetDisplay_Base::end(), "OCharsetDisplay::ExtendedCharsetIterator::operator* : invalid position!");
+
+ rtl_TextEncoding eEncoding = (*m_aPosition).getEncoding();
+ return CharsetDisplayDerefHelper(
+ *m_aPosition,
+ RTL_TEXTENCODING_DONTKNOW == eEncoding ? m_pContainer->m_aSystemDisplayName : SvxTextEncodingTable::GetTextString(eEncoding)
+ );
+ }
+
+ const OCharsetDisplay::ExtendedCharsetIterator& OCharsetDisplay::ExtendedCharsetIterator::operator++()
+ {
+ OSL_ENSURE( m_aPosition != m_pContainer->OCharsetDisplay_Base::end(), "OCharsetDisplay::ExtendedCharsetIterator::operator++ : invalid position!");
+ if ( m_aPosition != m_pContainer->OCharsetDisplay_Base::end() )
+ ++m_aPosition;
+ return *this;
+ }
+
+ bool operator==(const OCharsetDisplay::ExtendedCharsetIterator& lhs, const OCharsetDisplay::ExtendedCharsetIterator& rhs)
+ {
+ return (lhs.m_pContainer == rhs.m_pContainer) && (lhs.m_aPosition == rhs.m_aPosition);
+ }
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/misc/controllerframe.cxx b/dbaccess/source/ui/misc/controllerframe.cxx
new file mode 100644
index 000000000..3634a56eb
--- /dev/null
+++ b/dbaccess/source/ui/misc/controllerframe.cxx
@@ -0,0 +1,390 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <dbaccess/controllerframe.hxx>
+#include <dbaccess/IController.hxx>
+
+#include <com/sun/star/awt/XTopWindow.hpp>
+#include <com/sun/star/awt/XWindow2.hpp>
+#include <com/sun/star/lang/DisposedException.hpp>
+#include <com/sun/star/document/XDocumentEventBroadcaster.hpp>
+#include <com/sun/star/frame/XController2.hpp>
+
+#include <cppuhelper/implbase.hxx>
+#include <rtl/ref.hxx>
+#include <sfx2/objsh.hxx>
+#include <tools/diagnose_ex.h>
+#include <toolkit/helper/vclunohelper.hxx>
+#include <vcl/window.hxx>
+
+namespace dbaui
+{
+
+ using ::com::sun::star::uno::Reference;
+ using ::com::sun::star::uno::XInterface;
+ using ::com::sun::star::uno::UNO_QUERY;
+ using ::com::sun::star::uno::UNO_QUERY_THROW;
+ using ::com::sun::star::uno::UNO_SET_THROW;
+ using ::com::sun::star::uno::Exception;
+ using ::com::sun::star::uno::RuntimeException;
+ using ::com::sun::star::uno::Any;
+ using ::com::sun::star::frame::XFrame;
+ using ::com::sun::star::frame::FrameAction;
+ using ::com::sun::star::frame::FrameAction_FRAME_ACTIVATED;
+ using ::com::sun::star::frame::FrameAction_FRAME_UI_ACTIVATED;
+ using ::com::sun::star::frame::FrameAction_FRAME_DEACTIVATING;
+ using ::com::sun::star::frame::FrameAction_FRAME_UI_DEACTIVATING;
+ using ::com::sun::star::frame::XModel;
+ using ::com::sun::star::frame::XController;
+ using ::com::sun::star::frame::XController2;
+ using ::com::sun::star::awt::XTopWindow;
+ using ::com::sun::star::awt::XTopWindowListener;
+ using ::com::sun::star::awt::XWindow2;
+ using ::com::sun::star::lang::DisposedException;
+ using ::com::sun::star::lang::EventObject;
+ using ::com::sun::star::document::XDocumentEventBroadcaster;
+ using ::com::sun::star::awt::XWindow;
+
+ // FrameWindowActivationListener
+ typedef ::cppu::WeakImplHelper< XTopWindowListener
+ > FrameWindowActivationListener_Base;
+
+ namespace {
+
+ class FrameWindowActivationListener : public FrameWindowActivationListener_Base
+ {
+ public:
+ explicit FrameWindowActivationListener( ControllerFrame_Data& _rData );
+
+ void dispose();
+
+ protected:
+ virtual ~FrameWindowActivationListener() override;
+
+ // XTopWindowListener
+ virtual void SAL_CALL windowOpened( const css::lang::EventObject& e ) override;
+ virtual void SAL_CALL windowClosing( const css::lang::EventObject& e ) override;
+ virtual void SAL_CALL windowClosed( const css::lang::EventObject& e ) override;
+ virtual void SAL_CALL windowMinimized( const css::lang::EventObject& e ) override;
+ virtual void SAL_CALL windowNormalized( const css::lang::EventObject& e ) override;
+ virtual void SAL_CALL windowActivated( const css::lang::EventObject& e ) override;
+ virtual void SAL_CALL windowDeactivated( const css::lang::EventObject& e ) override;
+
+ // XEventListener
+ virtual void SAL_CALL disposing( const css::lang::EventObject& Source ) override;
+
+ private:
+ void impl_checkDisposed_throw() const;
+ void impl_registerOnFrameContainerWindow_nothrow( bool _bRegister );
+
+ private:
+ ControllerFrame_Data* m_pData;
+ };
+
+ }
+
+ // ControllerFrame_Data
+ struct ControllerFrame_Data
+ {
+ explicit ControllerFrame_Data( IController& _rController )
+ :m_rController( _rController )
+ ,m_bActive( false )
+ ,m_bIsTopLevelDocumentWindow( false )
+ {
+ }
+
+ IController& m_rController;
+ Reference< XFrame > m_xFrame;
+ Reference< XDocumentEventBroadcaster > m_xDocEventBroadcaster;
+ ::rtl::Reference< FrameWindowActivationListener > m_pListener;
+ bool m_bActive;
+ bool m_bIsTopLevelDocumentWindow;
+ };
+
+ // helper
+ static void lcl_setFrame_nothrow( ControllerFrame_Data& _rData, const Reference< XFrame >& _rxFrame )
+ {
+ // release old listener
+ if (_rData.m_pListener)
+ {
+ _rData.m_pListener->dispose();
+ _rData.m_pListener = nullptr;
+ }
+
+ // remember new frame
+ _rData.m_xFrame = _rxFrame;
+
+ // create new listener
+ if ( _rData.m_xFrame.is() )
+ _rData.m_pListener = new FrameWindowActivationListener( _rData );
+
+ // at this point in time, we can assume the controller also has a model set, if it supports models
+ try
+ {
+ Reference< XController > xController( _rData.m_rController.getXController(), UNO_SET_THROW );
+ Reference< XModel > xModel( xController->getModel() );
+ if ( xModel.is() )
+ _rData.m_xDocEventBroadcaster.set( xModel, UNO_QUERY );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+
+ static bool lcl_isActive_nothrow( const Reference< XFrame >& _rxFrame )
+ {
+ bool bIsActive = false;
+ try
+ {
+ if ( _rxFrame.is() )
+ {
+ Reference< XWindow2 > xWindow( _rxFrame->getContainerWindow(), UNO_QUERY_THROW );
+ bIsActive = xWindow->isActive();
+ }
+
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ return bIsActive;
+ }
+
+ /** updates various global and local states with a new active component
+
+ In particular, the following are updated
+ * the global working document (aka Basic's ThisComponent in the application
+ Basic), with our controller's model, or the controller itself if there is no such
+ model.
+ */
+ static void lcl_updateActiveComponents_nothrow( const ControllerFrame_Data& _rData )
+ {
+ try
+ {
+ Reference< XController > xCompController( _rData.m_rController.getXController() );
+ OSL_ENSURE( xCompController.is(), "lcl_updateActiveComponents_nothrow: can't do anything without a controller!" );
+ if ( !xCompController.is() )
+ return;
+
+ if ( _rData.m_bActive && _rData.m_bIsTopLevelDocumentWindow )
+ {
+ // set the "current component" at the SfxObjectShell
+ Reference< XModel > xModel( xCompController->getModel() );
+ Reference< XInterface > xCurrentComponent;
+ if ( xModel.is() )
+ xCurrentComponent = xModel;
+ else
+ xCurrentComponent = xCompController;
+ SfxObjectShell::SetCurrentComponent( xCurrentComponent );
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+
+ /** broadcasts the OnFocus resp. OnUnfocus event
+ */
+ static void lcl_notifyFocusChange_nothrow( ControllerFrame_Data& _rData, bool _bActive )
+ {
+ try
+ {
+ if ( _rData.m_xDocEventBroadcaster.is() )
+ {
+ OUString sEventName = _bActive ? OUString("OnFocus") : OUString("OnUnfocus");
+ Reference< XController2 > xController( _rData.m_rController.getXController(), UNO_QUERY_THROW );
+ _rData.m_xDocEventBroadcaster->notifyDocumentEvent( sEventName, xController, Any() );
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+
+ static void lcl_updateActive_nothrow( ControllerFrame_Data& _rData, bool _bActive )
+ {
+ if ( _rData.m_bActive == _bActive )
+ return;
+ _rData.m_bActive = _bActive;
+
+ lcl_updateActiveComponents_nothrow( _rData );
+ lcl_notifyFocusChange_nothrow( _rData, _bActive );
+ }
+
+ FrameWindowActivationListener::FrameWindowActivationListener( ControllerFrame_Data& _rData )
+ :m_pData( &_rData )
+ {
+ impl_registerOnFrameContainerWindow_nothrow( true );
+ }
+
+ FrameWindowActivationListener::~FrameWindowActivationListener()
+ {
+ }
+
+ void FrameWindowActivationListener::dispose()
+ {
+ impl_registerOnFrameContainerWindow_nothrow( false );
+ m_pData = nullptr;
+ }
+
+ void FrameWindowActivationListener::impl_registerOnFrameContainerWindow_nothrow( bool _bRegister )
+ {
+ OSL_ENSURE( m_pData && m_pData->m_xFrame.is(), "FrameWindowActivationListener::impl_registerOnFrameContainerWindow_nothrow: no frame!" );
+ if ( !m_pData || !m_pData->m_xFrame.is() )
+ return;
+
+ try
+ {
+ void ( SAL_CALL XTopWindow::*pListenerAction )( const Reference< XTopWindowListener >& ) =
+ _bRegister ? &XTopWindow::addTopWindowListener : &XTopWindow::removeTopWindowListener;
+
+ const Reference< XWindow > xContainerWindow( m_pData->m_xFrame->getContainerWindow(), UNO_SET_THROW );
+ if ( _bRegister )
+ {
+ const vcl::Window* pContainerWindow = VCLUnoHelper::GetWindow( xContainerWindow );
+ ENSURE_OR_THROW( pContainerWindow, "no Window implementation for the frame's container window!" );
+
+ m_pData->m_bIsTopLevelDocumentWindow = bool( pContainerWindow->GetExtendedStyle() & WindowExtendedStyle::Document );
+ }
+
+ const Reference< XTopWindow > xFrameContainer( xContainerWindow, UNO_QUERY );
+ if ( xFrameContainer.is() )
+ (xFrameContainer.get()->*pListenerAction)( this );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+
+ void FrameWindowActivationListener::impl_checkDisposed_throw() const
+ {
+ if ( !m_pData )
+ throw DisposedException( OUString(), *const_cast< FrameWindowActivationListener* >( this ) );
+ }
+
+ void SAL_CALL FrameWindowActivationListener::windowOpened( const EventObject& /*_rEvent*/ )
+ {
+ // not interested in
+ }
+
+ void SAL_CALL FrameWindowActivationListener::windowClosing( const EventObject& /*_rEvent*/ )
+ {
+ // not interested in
+ }
+
+ void SAL_CALL FrameWindowActivationListener::windowClosed( const EventObject& /*_rEvent*/ )
+ {
+ // not interested in
+ }
+
+ void SAL_CALL FrameWindowActivationListener::windowMinimized( const EventObject& /*_rEvent*/ )
+ {
+ // not interested in
+ }
+
+ void SAL_CALL FrameWindowActivationListener::windowNormalized( const EventObject& /*_rEvent*/ )
+ {
+ // not interested in
+ }
+
+ void SAL_CALL FrameWindowActivationListener::windowActivated( const EventObject& /*_rEvent*/ )
+ {
+ impl_checkDisposed_throw();
+ lcl_updateActive_nothrow( *m_pData, true );
+ }
+
+ void SAL_CALL FrameWindowActivationListener::windowDeactivated( const EventObject& /*_rEvent*/ )
+ {
+ impl_checkDisposed_throw();
+ lcl_updateActive_nothrow( *m_pData, false );
+ }
+
+ void SAL_CALL FrameWindowActivationListener::disposing( const EventObject& /*_rEvent*/ )
+ {
+ dispose();
+ }
+
+ // ControllerFrame
+ ControllerFrame::ControllerFrame( IController& _rController )
+ :m_pData( new ControllerFrame_Data( _rController ) )
+ {
+ }
+
+ ControllerFrame::~ControllerFrame()
+ {
+ }
+
+ const Reference< XFrame >& ControllerFrame::attachFrame( const Reference< XFrame >& _rxFrame )
+ {
+ // set new frame, including listener handling
+ lcl_setFrame_nothrow( *m_pData, _rxFrame );
+
+ // determine whether we're active
+ m_pData->m_bActive = lcl_isActive_nothrow( m_pData->m_xFrame );
+
+ // update active component
+ if ( m_pData->m_bActive )
+ {
+ lcl_updateActiveComponents_nothrow( *m_pData );
+ lcl_notifyFocusChange_nothrow( *m_pData, true );
+ }
+
+ return m_pData->m_xFrame;
+ }
+
+ const Reference< XFrame >& ControllerFrame::getFrame() const
+ {
+ return m_pData->m_xFrame;
+ }
+
+ bool ControllerFrame::isActive() const
+ {
+ return m_pData->m_bActive;
+ }
+
+ void ControllerFrame::frameAction( FrameAction _eAction )
+ {
+ bool bActive = m_pData->m_bActive;
+
+ switch ( _eAction )
+ {
+ case FrameAction_FRAME_ACTIVATED:
+ case FrameAction_FRAME_UI_ACTIVATED:
+ bActive = true;
+ break;
+
+ case FrameAction_FRAME_DEACTIVATING:
+ case FrameAction_FRAME_UI_DEACTIVATING:
+ bActive = false;
+ break;
+
+ default:
+ break;
+ }
+
+ lcl_updateActive_nothrow( *m_pData, bActive );
+ }
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/misc/databaseobjectview.cxx b/dbaccess/source/ui/misc/databaseobjectview.cxx
new file mode 100644
index 000000000..cb4478295
--- /dev/null
+++ b/dbaccess/source/ui/misc/databaseobjectview.cxx
@@ -0,0 +1,280 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <databaseobjectview.hxx>
+#include <strings.hxx>
+#include <asyncmodaldialog.hxx>
+
+#include <com/sun/star/lang/XSingleServiceFactory.hpp>
+#include <com/sun/star/frame/TaskCreator.hpp>
+#include <com/sun/star/frame/XFrame.hpp>
+#include <com/sun/star/sdb/CommandType.hpp>
+#include <com/sun/star/sdb/application/XTableUIProvider.hpp>
+#include <com/sun/star/beans/NamedValue.hpp>
+
+#include <connectivity/dbtools.hxx>
+#include <osl/diagnose.h>
+#include <toolkit/helper/vclunohelper.hxx>
+#include <tools/diagnose_ex.h>
+#include <vcl/window.hxx>
+
+namespace dbaui
+{
+
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::sdbc;
+ using namespace ::com::sun::star::sdb;
+ using namespace ::com::sun::star::sdb::application;
+ using namespace ::com::sun::star::ui::dialogs;
+ using namespace ::com::sun::star::frame;
+ using namespace ::com::sun::star::lang;
+ using namespace ::com::sun::star::beans;
+ using namespace ::com::sun::star::awt;
+
+ // DatabaseObjectView
+ DatabaseObjectView::DatabaseObjectView( const Reference< XComponentContext >& _rxORB,
+ const Reference< XDatabaseDocumentUI >& _rxApplication,
+ const Reference< XFrame >& _rxParentFrame,
+ const OUString& _rComponentURL )
+ :m_xORB ( _rxORB )
+ ,m_xParentFrame ( _rxParentFrame )
+ ,m_xApplication ( _rxApplication )
+ ,m_sComponentURL ( _rComponentURL )
+ {
+ OSL_ENSURE( m_xORB.is(), "DatabaseObjectView::DatabaseObjectView: invalid service factory!" );
+ OSL_ENSURE( m_xApplication.is(), "DatabaseObjectView::DatabaseObjectView: invalid connection!" );
+ }
+
+ Reference< XConnection > DatabaseObjectView::getConnection() const
+ {
+ Reference< XConnection > xConnection;
+ if ( m_xApplication.is() )
+ xConnection = m_xApplication->getActiveConnection();
+ return xConnection;
+ }
+
+ Reference< XComponent > DatabaseObjectView::createNew( const Reference< XDataSource >& _xDataSource, const ::comphelper::NamedValueCollection& i_rDispatchArgs )
+ {
+ return doCreateView( Any( _xDataSource ), OUString(), i_rDispatchArgs );
+ }
+
+ Reference< XComponent > DatabaseObjectView::openExisting( const Any& _rDataSource, const OUString& _rName,
+ const ::comphelper::NamedValueCollection& i_rDispatchArgs )
+ {
+ return doCreateView( _rDataSource, _rName, i_rDispatchArgs );
+ }
+
+ Reference< XComponent > DatabaseObjectView::doCreateView( const Any& _rDataSource, const OUString& _rObjectName,
+ const ::comphelper::NamedValueCollection& i_rCreationArgs )
+ {
+ ::comphelper::NamedValueCollection aDispatchArgs;
+
+ aDispatchArgs.merge( i_rCreationArgs, false ); // false => do not overwrite
+ fillDispatchArgs( aDispatchArgs, _rDataSource, _rObjectName );
+ aDispatchArgs.merge( i_rCreationArgs, true ); // true => do overwrite
+
+ return doDispatch( aDispatchArgs );
+ }
+
+ Reference< XComponent > DatabaseObjectView::doDispatch( const ::comphelper::NamedValueCollection& i_rDispatchArgs )
+ {
+ Reference< XComponent > xReturn;
+ if ( m_xORB.is() )
+ {
+ try
+ {
+ // if we have no externally provided frame, create one
+ if ( !m_xFrameLoader.is() )
+ {
+ Reference< XSingleServiceFactory > xFact = TaskCreator::create(m_xORB);
+ Sequence< Any > lArgs{ Any(NamedValue("ParentFrame", Any(m_xParentFrame))),
+ Any(NamedValue("TopWindow", Any(true))),
+ Any(NamedValue("SupportPersistentWindowState",
+ Any(true))) };
+
+ m_xFrameLoader.set(xFact->createInstanceWithArguments(lArgs), UNO_QUERY_THROW);
+
+ // everything we load can be considered a "top level document", so set the respective bit at the window.
+ // This, amongst other things, triggers that the component in this task participates in the
+ // "ThisComponent"-game for the global application Basic.
+ const Reference< XFrame > xFrame( m_xFrameLoader, UNO_QUERY_THROW );
+ const Reference< XWindow > xFrameWindow( xFrame->getContainerWindow(), UNO_SET_THROW );
+ VclPtr<vcl::Window> pContainerWindow = VCLUnoHelper::GetWindow( xFrameWindow );
+ ENSURE_OR_THROW( pContainerWindow, "no implementation access to the frame's container window!" );
+ pContainerWindow->SetExtendedStyle( pContainerWindow->GetExtendedStyle() | WindowExtendedStyle::Document );
+ }
+
+ Reference< XComponentLoader > xFrameLoader( m_xFrameLoader, UNO_SET_THROW );
+ xReturn = xFrameLoader->loadComponentFromURL(
+ m_sComponentURL,
+ "_self",
+ 0,
+ i_rDispatchArgs.getPropertyValues()
+ );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+ return xReturn;
+ }
+
+ void DatabaseObjectView::fillDispatchArgs(
+ ::comphelper::NamedValueCollection& i_rDispatchArgs,
+ const Any& _aDataSource,
+ const OUString& /* _rName */
+ )
+ {
+ OUString sDataSource;
+ Reference<XDataSource> xDataSource;
+ if ( _aDataSource >>= sDataSource )
+ {
+ i_rDispatchArgs.put( PROPERTY_DATASOURCENAME, sDataSource );
+ }
+ else if ( _aDataSource >>= xDataSource )
+ {
+ i_rDispatchArgs.put( PROPERTY_DATASOURCE, xDataSource );
+ }
+
+ i_rDispatchArgs.put( PROPERTY_ACTIVE_CONNECTION, getConnection() );
+ }
+
+ // QueryDesigner
+ QueryDesigner::QueryDesigner( const Reference< XComponentContext >& _rxORB, const Reference< XDatabaseDocumentUI >& _rxApplication,
+ const Reference< XFrame >& _rxParentFrame, bool _bCreateView )
+ :DatabaseObjectView( _rxORB, _rxApplication, _rxParentFrame, _bCreateView ? OUString(URL_COMPONENT_VIEWDESIGN) : OUString(URL_COMPONENT_QUERYDESIGN) )
+ ,m_nCommandType( _bCreateView ? CommandType::TABLE : CommandType::QUERY )
+ {
+ }
+
+ void QueryDesigner::fillDispatchArgs( ::comphelper::NamedValueCollection& i_rDispatchArgs, const Any& _aDataSource,
+ const OUString& _rObjectName )
+ {
+ DatabaseObjectView::fillDispatchArgs( i_rDispatchArgs, _aDataSource, _rObjectName );
+
+ const bool bIncludeQueryName = !_rObjectName.isEmpty();
+ const bool bGraphicalDesign = i_rDispatchArgs.getOrDefault( PROPERTY_GRAPHICAL_DESIGN, true );
+ const bool bEditViewAsSQLCommand = ( m_nCommandType == CommandType::TABLE ) && !bGraphicalDesign;
+
+ i_rDispatchArgs.put( PROPERTY_COMMAND_TYPE, m_nCommandType );
+
+ if ( bIncludeQueryName )
+ {
+ i_rDispatchArgs.put( PROPERTY_COMMAND, _rObjectName );
+ }
+
+ if ( bEditViewAsSQLCommand )
+ {
+ i_rDispatchArgs.put( PROPERTY_ESCAPE_PROCESSING, false );
+ }
+ }
+
+ // TableDesigner
+ TableDesigner::TableDesigner( const Reference< XComponentContext >& _rxORB, const Reference< XDatabaseDocumentUI >& _rxApplication, const Reference< XFrame >& _rxParentFrame )
+ :DatabaseObjectView( _rxORB, _rxApplication, _rxParentFrame, static_cast< OUString >( URL_COMPONENT_TABLEDESIGN ) )
+ {
+ }
+
+ void TableDesigner::fillDispatchArgs( ::comphelper::NamedValueCollection& i_rDispatchArgs, const Any& _aDataSource,
+ const OUString& _rObjectName )
+ {
+ DatabaseObjectView::fillDispatchArgs( i_rDispatchArgs, _aDataSource, _rObjectName );
+
+ if ( !_rObjectName.isEmpty() )
+ {
+ i_rDispatchArgs.put( PROPERTY_CURRENTTABLE, _rObjectName );
+ }
+ }
+
+ Reference< XComponent > TableDesigner::doCreateView( const Any& _rDataSource, const OUString& _rObjectName,
+ const ::comphelper::NamedValueCollection& i_rCreationArgs )
+ {
+ bool bIsNewDesign = _rObjectName.isEmpty();
+
+ // let's see whether the connection can provide a dedicated table designer
+ Reference< XInterface > xDesigner;
+ if ( !bIsNewDesign )
+ xDesigner = impl_getConnectionProvidedDesigner_nothrow( _rObjectName );
+
+ if ( !xDesigner.is() )
+ return DatabaseObjectView::doCreateView( _rDataSource, _rObjectName, i_rCreationArgs );
+
+ // try whether the designer is a dialog
+ Reference< XExecutableDialog > xDialog( xDesigner, UNO_QUERY_THROW );
+ try { AsyncDialogExecutor::executeModalDialogAsync( xDialog ); }
+ catch( const Exception& ) { DBG_UNHANDLED_EXCEPTION("dbaccess"); }
+ return nullptr;
+ }
+
+ Reference< XInterface > TableDesigner::impl_getConnectionProvidedDesigner_nothrow( const OUString& _rTableName )
+ {
+ Reference< XInterface > xDesigner;
+ try
+ {
+ Reference< XTableUIProvider > xTableUIProv( getConnection(), UNO_QUERY );
+ if ( xTableUIProv.is() )
+ xDesigner = xTableUIProv->getTableEditor( getApplicationUI(), _rTableName );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ return xDesigner;
+ }
+
+ // ResultSetBrowser
+ ResultSetBrowser::ResultSetBrowser( const Reference< XComponentContext >& _rxORB, const Reference< XDatabaseDocumentUI >& _rxApplication, const Reference< XFrame >& _rxParentFrame,
+ bool _bTable )
+ :DatabaseObjectView( _rxORB, _rxApplication, _rxParentFrame, static_cast < OUString >( URL_COMPONENT_DATASOURCEBROWSER ) )
+ ,m_bTable(_bTable)
+ {
+ }
+
+ void ResultSetBrowser::fillDispatchArgs( ::comphelper::NamedValueCollection& i_rDispatchArgs, const Any& _aDataSource,
+ const OUString& _rQualifiedName)
+ {
+ DatabaseObjectView::fillDispatchArgs( i_rDispatchArgs, _aDataSource, _rQualifiedName );
+ OSL_ENSURE( !_rQualifiedName.isEmpty(),"A Table name must be set");
+ OUString sCatalog;
+ OUString sSchema;
+ OUString sTable;
+ if ( m_bTable )
+ ::dbtools::qualifiedNameComponents( getConnection()->getMetaData(), _rQualifiedName, sCatalog, sSchema, sTable, ::dbtools::EComposeRule::InDataManipulation );
+
+ i_rDispatchArgs.put( PROPERTY_COMMAND_TYPE, (m_bTable ? CommandType::TABLE : CommandType::QUERY) );
+ i_rDispatchArgs.put( PROPERTY_COMMAND, _rQualifiedName );
+ i_rDispatchArgs.put( PROPERTY_ENABLE_BROWSER, false );
+
+ if ( m_bTable )
+ {
+ i_rDispatchArgs.put( PROPERTY_UPDATE_CATALOGNAME, sCatalog );
+ i_rDispatchArgs.put( PROPERTY_UPDATE_SCHEMANAME, sSchema );
+ i_rDispatchArgs.put( PROPERTY_UPDATE_TABLENAME, sTable );
+ }
+ }
+
+ // RelationDesigner
+ RelationDesigner::RelationDesigner( const Reference< XComponentContext >& _rxORB, const Reference< XDatabaseDocumentUI >& _rxApplication, const Reference< XFrame >& _rxParentFrame )
+ :DatabaseObjectView( _rxORB, _rxApplication, _rxParentFrame, static_cast< OUString >( URL_COMPONENT_RELATIONDESIGN ) )
+ {
+ }
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/misc/datasourceconnector.cxx b/dbaccess/source/ui/misc/datasourceconnector.cxx
new file mode 100644
index 000000000..49053e569
--- /dev/null
+++ b/dbaccess/source/ui/misc/datasourceconnector.cxx
@@ -0,0 +1,202 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <core_resource.hxx>
+#include <datasourceconnector.hxx>
+#include <osl/diagnose.h>
+#include <com/sun/star/sdbc/XWarningsSupplier.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/sdb/XCompletedConnection.hpp>
+#include <com/sun/star/task/InteractionHandler.hpp>
+#include <com/sun/star/frame/XModel.hpp>
+#include <com/sun/star/sdbc/SQLWarning.hpp>
+#include <comphelper/namedvaluecollection.hxx>
+#include <connectivity/dbexception.hxx>
+#include <com/sun/star/sdbc/XDataSource.hpp>
+#include <UITools.hxx>
+#include <vcl/outdev.hxx>
+#include <vcl/stdtext.hxx>
+#include <vcl/weld.hxx>
+#include <tools/diagnose_ex.h>
+#include <cppuhelper/exc_hlp.hxx>
+#include <strings.hrc>
+#include <strings.hxx>
+
+namespace dbaui
+{
+
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::lang;
+ using namespace ::com::sun::star::sdb;
+ using namespace ::com::sun::star::sdbc;
+ using namespace ::com::sun::star::task;
+ using namespace ::com::sun::star::beans;
+ using namespace ::com::sun::star::container;
+ using namespace ::com::sun::star::frame;
+ using namespace ::dbtools;
+
+ // ODatasourceConnector
+ ODatasourceConnector::ODatasourceConnector(const Reference< XComponentContext >& _rxContext, weld::Window* _pMessageParent)
+ :m_pErrorMessageParent(_pMessageParent)
+ ,m_xContext(_rxContext)
+ {
+ }
+
+ ODatasourceConnector::ODatasourceConnector( const Reference< XComponentContext >& _rxContext, weld::Window* _pMessageParent,
+ const OUString& _rContextInformation )
+ :m_pErrorMessageParent(_pMessageParent)
+ ,m_xContext(_rxContext)
+ ,m_sContextInformation( _rContextInformation )
+ {
+ }
+
+ Reference< XConnection > ODatasourceConnector::connect( const OUString& _rDataSourceName,
+ ::dbtools::SQLExceptionInfo* _pErrorInfo ) const
+ {
+ Reference< XConnection > xConnection;
+
+ OSL_ENSURE(isValid(), "ODatasourceConnector::connect: invalid object!");
+ if (!isValid())
+ return xConnection;
+
+ // get the data source
+ Reference< XDataSource > xDatasource =
+ getDataSourceByName( _rDataSourceName, m_pErrorMessageParent, m_xContext, _pErrorInfo );
+
+ if ( xDatasource.is() )
+ xConnection = connect( xDatasource, _pErrorInfo );
+ return xConnection;
+ }
+
+ Reference< XConnection > ODatasourceConnector::connect(const Reference< XDataSource>& _xDataSource,
+ ::dbtools::SQLExceptionInfo* _pErrorInfo ) const
+ {
+ Reference< XConnection > xConnection;
+
+ OSL_ENSURE( isValid() && _xDataSource.is(), "ODatasourceConnector::connect: invalid object or argument!" );
+ if ( !isValid() || !_xDataSource.is() )
+ return xConnection;
+
+ // get user/password
+ OUString sPassword, sUser;
+ bool bPwdRequired = false;
+ Reference<XPropertySet> xProp(_xDataSource,UNO_QUERY);
+ try
+ {
+ xProp->getPropertyValue(PROPERTY_PASSWORD) >>= sPassword;
+ xProp->getPropertyValue(PROPERTY_ISPASSWORDREQUIRED) >>= bPwdRequired;
+ xProp->getPropertyValue(PROPERTY_USER) >>= sUser;
+ }
+ catch(Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+
+ // try to connect
+ SQLExceptionInfo aInfo;
+ try
+ {
+ if (bPwdRequired && sPassword.isEmpty())
+ { // password required, but empty -> connect using an interaction handler
+ Reference< XCompletedConnection > xConnectionCompletion( _xDataSource, UNO_QUERY_THROW );
+
+ Reference< XModel > xModel( getDataSourceOrModel( _xDataSource ), UNO_QUERY_THROW );
+ ::comphelper::NamedValueCollection aArgs( xModel->getArgs() );
+ Reference< XInteractionHandler > xHandler( aArgs.getOrDefault( "InteractionHandler", Reference< XInteractionHandler >() ) );
+
+ if ( !xHandler.is() )
+ {
+ // instantiate the default SDB interaction handler
+ xHandler = InteractionHandler::createWithParent(m_xContext, m_pErrorMessageParent ? m_pErrorMessageParent->GetXWindow() : nullptr);
+ }
+
+ xConnection = xConnectionCompletion->connectWithCompletion(xHandler);
+ }
+ else
+ {
+ xConnection = _xDataSource->getConnection(sUser, sPassword);
+ }
+ }
+ catch( const SQLException& )
+ {
+ aInfo = ::cppu::getCaughtException();
+ }
+ catch(const Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+
+ if ( !aInfo.isValid() )
+ {
+ // there was no error during connecting, but perhaps a warning?
+ Reference< XWarningsSupplier > xConnectionWarnings( xConnection, UNO_QUERY );
+ if ( xConnectionWarnings.is() )
+ {
+ try
+ {
+ Any aWarnings( xConnectionWarnings->getWarnings() );
+ if ( aWarnings.hasValue() )
+ {
+ OUString sMessage( DBA_RES( STR_WARNINGS_DURING_CONNECT ) );
+ sMessage = sMessage.replaceFirst( "$buttontext$", GetStandardText( StandardButtonType::More ) );
+ sMessage = OutputDevice::GetNonMnemonicString( sMessage );
+
+ SQLWarning aContext;
+ aContext.Message = sMessage;
+ aContext.NextException = aWarnings;
+ aInfo = aContext;
+ }
+ xConnectionWarnings->clearWarnings();
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+ }
+ else
+ {
+ if ( !m_sContextInformation.isEmpty() )
+ {
+ SQLException aError;
+ aError.Message = m_sContextInformation;
+ aError.NextException = aInfo.get();
+
+ aInfo = aError;
+ }
+ }
+
+ // was there an error?
+ if ( aInfo.isValid() )
+ {
+ if ( _pErrorInfo )
+ {
+ *_pErrorInfo = aInfo;
+ }
+ else
+ {
+ showError(aInfo, m_pErrorMessageParent ? m_pErrorMessageParent->GetXWindow() : nullptr, m_xContext);
+ }
+ }
+ return xConnection;
+ }
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/misc/dbaundomanager.cxx b/dbaccess/source/ui/misc/dbaundomanager.cxx
new file mode 100644
index 000000000..9ed72bbdf
--- /dev/null
+++ b/dbaccess/source/ui/misc/dbaundomanager.cxx
@@ -0,0 +1,324 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <dbaccess/dbaundomanager.hxx>
+
+#include <com/sun/star/lang/DisposedException.hpp>
+#include <com/sun/star/lang/NoSupportException.hpp>
+
+#include <svl/undo.hxx>
+#include <vcl/svapp.hxx>
+#include <framework/undomanagerhelper.hxx>
+#include <framework/imutex.hxx>
+
+namespace dbaui
+{
+
+ using ::com::sun::star::uno::Reference;
+ using ::com::sun::star::uno::XInterface;
+ using ::com::sun::star::uno::Sequence;
+ using ::com::sun::star::document::XUndoManager;
+ using ::com::sun::star::lang::DisposedException;
+ using ::com::sun::star::document::XUndoAction;
+ using ::com::sun::star::document::XUndoManagerListener;
+ using ::com::sun::star::lang::NoSupportException;
+
+ // UndoManager_Impl
+ struct UndoManager_Impl : public ::framework::IUndoManagerImplementation
+ {
+ UndoManager_Impl( UndoManager& i_antiImpl, ::cppu::OWeakObject& i_parent, ::osl::Mutex& i_mutex )
+ :rAntiImpl( i_antiImpl )
+ ,rParent( i_parent )
+ ,rMutex( i_mutex )
+ ,bDisposed( false )
+ ,aUndoHelper( *this )
+ {
+ }
+
+ virtual ~UndoManager_Impl()
+ {
+ }
+
+ UndoManager& rAntiImpl;
+ ::cppu::OWeakObject& rParent;
+ ::osl::Mutex& rMutex;
+ bool bDisposed;
+ SfxUndoManager aUndoManager;
+ ::framework::UndoManagerHelper aUndoHelper;
+
+ // IUndoManagerImplementation
+ virtual SfxUndoManager& getImplUndoManager() override;
+ virtual Reference< XUndoManager > getThis() override;
+ };
+
+ SfxUndoManager& UndoManager_Impl::getImplUndoManager()
+ {
+ return aUndoManager;
+ }
+
+ Reference< XUndoManager > UndoManager_Impl::getThis()
+ {
+ return static_cast< XUndoManager* >( &rAntiImpl );
+ }
+
+ namespace {
+
+ // OslMutexFacade
+ class OslMutexFacade : public ::framework::IMutex
+ {
+ public:
+ explicit OslMutexFacade( ::osl::Mutex& i_mutex )
+ :m_rMutex( i_mutex )
+ {
+ }
+
+ virtual ~OslMutexFacade() {}
+
+ virtual void acquire() override;
+ virtual void release() override;
+
+ private:
+ ::osl::Mutex& m_rMutex;
+ };
+
+ }
+
+ void OslMutexFacade::acquire()
+ {
+ m_rMutex.acquire();
+ }
+
+ void OslMutexFacade::release()
+ {
+ m_rMutex.release();
+ }
+
+ namespace {
+
+ // UndoManagerMethodGuard
+ /** guard for public UNO methods of the UndoManager
+ */
+ class UndoManagerMethodGuard : public ::framework::IMutexGuard
+ {
+ public:
+ explicit UndoManagerMethodGuard( UndoManager_Impl& i_impl )
+ :m_aGuard( i_impl.rMutex )
+ ,m_aMutexFacade( i_impl.rMutex )
+ {
+ // throw if the instance is already disposed
+ if ( i_impl.bDisposed )
+ throw DisposedException( OUString(), i_impl.getThis() );
+ }
+ virtual ~UndoManagerMethodGuard()
+ {
+ }
+
+ // IMutexGuard
+ virtual void clear() override;
+ virtual ::framework::IMutex& getGuardedMutex() override;
+
+ private:
+ osl::ClearableMutexGuard m_aGuard;
+ OslMutexFacade m_aMutexFacade;
+ };
+
+ }
+
+ ::framework::IMutex& UndoManagerMethodGuard::getGuardedMutex()
+ {
+ return m_aMutexFacade;
+ }
+
+ void UndoManagerMethodGuard::clear()
+ {
+ m_aGuard.clear();
+ }
+
+ // UndoManager
+ UndoManager::UndoManager( ::cppu::OWeakObject& i_parent, ::osl::Mutex& i_mutex )
+ :m_xImpl( new UndoManager_Impl( *this, i_parent, i_mutex ) )
+ {
+ }
+
+ UndoManager::~UndoManager()
+ {
+ }
+
+ SfxUndoManager& UndoManager::GetSfxUndoManager() const
+ {
+ return m_xImpl->aUndoManager;
+ }
+
+ void SAL_CALL UndoManager::acquire( ) noexcept
+ {
+ m_xImpl->rParent.acquire();
+ }
+
+ void SAL_CALL UndoManager::release( ) noexcept
+ {
+ m_xImpl->rParent.release();
+ }
+
+ void UndoManager::disposing()
+ {
+ {
+ ::osl::MutexGuard aGuard( m_xImpl->rMutex );
+ m_xImpl->bDisposed = true;
+ }
+ m_xImpl->aUndoHelper.disposing();
+ }
+
+ void SAL_CALL UndoManager::enterUndoContext( const OUString& i_title )
+ {
+ UndoManagerMethodGuard aGuard( *m_xImpl );
+ m_xImpl->aUndoHelper.enterUndoContext( i_title, aGuard );
+ }
+
+ void SAL_CALL UndoManager::enterHiddenUndoContext( )
+ {
+ UndoManagerMethodGuard aGuard( *m_xImpl );
+ m_xImpl->aUndoHelper.enterHiddenUndoContext( aGuard );
+ }
+
+ void SAL_CALL UndoManager::leaveUndoContext( )
+ {
+ UndoManagerMethodGuard aGuard( *m_xImpl );
+ m_xImpl->aUndoHelper.leaveUndoContext( aGuard );
+ }
+
+ void SAL_CALL UndoManager::addUndoAction( const Reference< XUndoAction >& i_action )
+ {
+ UndoManagerMethodGuard aGuard( *m_xImpl );
+ m_xImpl->aUndoHelper.addUndoAction( i_action, aGuard );
+ }
+
+ void SAL_CALL UndoManager::undo( )
+ {
+ SolarMutexGuard aSolarGuard;
+ // (all our UndoActions work directly on VCL code, usually, so ...)
+ UndoManagerMethodGuard aGuard( *m_xImpl );
+ m_xImpl->aUndoHelper.undo( aGuard );
+ }
+
+ void SAL_CALL UndoManager::redo( )
+ {
+ SolarMutexGuard aSolarGuard;
+ // (all our UndoActions work directly on VCL code, usually, so ...)
+ UndoManagerMethodGuard aGuard( *m_xImpl );
+ m_xImpl->aUndoHelper.redo( aGuard );
+ }
+
+ sal_Bool SAL_CALL UndoManager::isUndoPossible( )
+ {
+ UndoManagerMethodGuard aGuard( *m_xImpl );
+ return m_xImpl->aUndoHelper.isUndoPossible();
+ }
+
+ sal_Bool SAL_CALL UndoManager::isRedoPossible( )
+ {
+ UndoManagerMethodGuard aGuard( *m_xImpl );
+ return m_xImpl->aUndoHelper.isRedoPossible();
+ }
+
+ OUString SAL_CALL UndoManager::getCurrentUndoActionTitle( )
+ {
+ UndoManagerMethodGuard aGuard( *m_xImpl );
+ return m_xImpl->aUndoHelper.getCurrentUndoActionTitle();
+ }
+
+ OUString SAL_CALL UndoManager::getCurrentRedoActionTitle( )
+ {
+ UndoManagerMethodGuard aGuard( *m_xImpl );
+ return m_xImpl->aUndoHelper.getCurrentRedoActionTitle();
+ }
+
+ Sequence< OUString > SAL_CALL UndoManager::getAllUndoActionTitles( )
+ {
+ UndoManagerMethodGuard aGuard( *m_xImpl );
+ return m_xImpl->aUndoHelper.getAllUndoActionTitles();
+ }
+
+ Sequence< OUString > SAL_CALL UndoManager::getAllRedoActionTitles( )
+ {
+ UndoManagerMethodGuard aGuard( *m_xImpl );
+ return m_xImpl->aUndoHelper.getAllRedoActionTitles();
+ }
+
+ void SAL_CALL UndoManager::clear( )
+ {
+ UndoManagerMethodGuard aGuard( *m_xImpl );
+ m_xImpl->aUndoHelper.clear( aGuard );
+ }
+
+ void SAL_CALL UndoManager::clearRedo( )
+ {
+ UndoManagerMethodGuard aGuard( *m_xImpl );
+ m_xImpl->aUndoHelper.clearRedo( aGuard );
+ }
+
+ void SAL_CALL UndoManager::reset( )
+ {
+ UndoManagerMethodGuard aGuard( *m_xImpl );
+ m_xImpl->aUndoHelper.reset( aGuard );
+ }
+
+ void SAL_CALL UndoManager::addUndoManagerListener( const Reference< XUndoManagerListener >& i_listener )
+ {
+ UndoManagerMethodGuard aGuard( *m_xImpl );
+ m_xImpl->aUndoHelper.addUndoManagerListener( i_listener );
+ }
+
+ void SAL_CALL UndoManager::removeUndoManagerListener( const Reference< XUndoManagerListener >& i_listener )
+ {
+ UndoManagerMethodGuard aGuard( *m_xImpl );
+ m_xImpl->aUndoHelper.removeUndoManagerListener( i_listener );
+ }
+
+ void SAL_CALL UndoManager::lock( )
+ {
+ UndoManagerMethodGuard aGuard( *m_xImpl );
+ m_xImpl->aUndoHelper.lock();
+ }
+
+ void SAL_CALL UndoManager::unlock( )
+ {
+ UndoManagerMethodGuard aGuard( *m_xImpl );
+ m_xImpl->aUndoHelper.unlock();
+ }
+
+ sal_Bool SAL_CALL UndoManager::isLocked( )
+ {
+ UndoManagerMethodGuard aGuard( *m_xImpl );
+ return m_xImpl->aUndoHelper.isLocked();
+ }
+
+ Reference< XInterface > SAL_CALL UndoManager::getParent( )
+ {
+ UndoManagerMethodGuard aGuard( *m_xImpl );
+ return m_xImpl->rParent;
+ }
+
+ void SAL_CALL UndoManager::setParent( const Reference< XInterface >& )
+ {
+ throw NoSupportException( OUString(), m_xImpl->getThis() );
+ }
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/misc/dbsubcomponentcontroller.cxx b/dbaccess/source/ui/misc/dbsubcomponentcontroller.cxx
new file mode 100644
index 000000000..467a6e925
--- /dev/null
+++ b/dbaccess/source/ui/misc/dbsubcomponentcontroller.cxx
@@ -0,0 +1,606 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <browserids.hxx>
+#include <commontypes.hxx>
+#include <core_resource.hxx>
+#include <dbaccess/dataview.hxx>
+#include <strings.hrc>
+#include <strings.hxx>
+#include <dbaccess/dbsubcomponentcontroller.hxx>
+
+#include <com/sun/star/frame/XUntitledNumbers.hpp>
+#include <com/sun/star/container/XChild.hpp>
+#include <com/sun/star/sdb/XDocumentDataSource.hpp>
+#include <com/sun/star/sdb/XOfficeDatabaseDocument.hpp>
+#include <com/sun/star/sdbc/XDataSource.hpp>
+#include <com/sun/star/util/NumberFormatter.hpp>
+#include <com/sun/star/lang/IllegalArgumentException.hpp>
+
+#include <comphelper/types.hxx>
+#include <connectivity/dbexception.hxx>
+#include <connectivity/dbmetadata.hxx>
+#include <connectivity/dbtools.hxx>
+#include <comphelper/interfacecontainer3.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <sal/log.hxx>
+#include <toolkit/helper/vclunohelper.hxx>
+#include <tools/debug.hxx>
+#include <tools/diagnose_ex.h>
+#include <vcl/svapp.hxx>
+#include <vcl/weld.hxx>
+
+namespace dbaui
+{
+
+ using ::com::sun::star::uno::Any;
+ using ::com::sun::star::uno::Reference;
+ using ::com::sun::star::beans::XPropertySet;
+ using ::com::sun::star::uno::Sequence;
+ using ::com::sun::star::uno::Type;
+ using ::com::sun::star::uno::XComponentContext;
+ using ::com::sun::star::sdbc::XConnection;
+ using ::com::sun::star::uno::UNO_QUERY;
+ using ::com::sun::star::container::XChild;
+ using ::com::sun::star::sdbc::XDataSource;
+ using ::com::sun::star::util::NumberFormatter;
+ using ::com::sun::star::util::XNumberFormatter;
+ using ::com::sun::star::util::XNumberFormatsSupplier;
+ using ::com::sun::star::frame::XFrame;
+ using ::com::sun::star::uno::Exception;
+ using ::com::sun::star::lang::EventObject;
+ using ::com::sun::star::beans::PropertyValue;
+ using ::com::sun::star::frame::XModel;
+ using ::com::sun::star::sdb::XOfficeDatabaseDocument;
+ using ::com::sun::star::awt::XWindow;
+ using ::com::sun::star::sdbc::XDatabaseMetaData;
+ using ::com::sun::star::sdb::XDocumentDataSource;
+ using ::com::sun::star::document::XEmbeddedScripts;
+ using ::com::sun::star::lang::IllegalArgumentException;
+ using ::com::sun::star::uno::UNO_SET_THROW;
+ using ::com::sun::star::uno::UNO_QUERY_THROW;
+ using ::com::sun::star::frame::XUntitledNumbers;
+
+ namespace {
+
+ class DataSourceHolder
+ {
+ public:
+ DataSourceHolder()
+ {
+ }
+
+ explicit DataSourceHolder(const Reference< XDataSource >& _rxDataSource)
+ : m_xDataSource(_rxDataSource)
+ {
+ Reference< XDocumentDataSource > xDocDS( m_xDataSource, UNO_QUERY );
+ if ( xDocDS.is() )
+ m_xDocument = xDocDS->getDatabaseDocument();
+
+ m_xDataSourceProps.set( m_xDataSource, UNO_QUERY );
+ }
+
+ const Reference< XDataSource >& getDataSource() const { return m_xDataSource; }
+ const Reference< XPropertySet >& getDataSourceProps() const { return m_xDataSourceProps; }
+ const Reference< XOfficeDatabaseDocument >& getDatabaseDocument() const { return m_xDocument; }
+
+ bool is() const { return m_xDataSource.is(); }
+
+ void clear()
+ {
+ m_xDataSource.clear();
+ m_xDocument.clear();
+ }
+
+ private:
+ Reference< XDataSource > m_xDataSource;
+ Reference< XPropertySet > m_xDataSourceProps;
+ Reference< XOfficeDatabaseDocument > m_xDocument;
+ };
+
+ }
+
+ struct DBSubComponentController_Impl
+ {
+ private:
+ ::std::optional< bool > m_aDocScriptSupport;
+
+ public:
+ ::dbtools::SQLExceptionInfo m_aCurrentError;
+
+ ::comphelper::OInterfaceContainerHelper3<css::util::XModifyListener>
+ m_aModifyListeners;
+
+ // <properties>
+ SharedConnection m_xConnection;
+ ::dbtools::DatabaseMetaData m_aSdbMetaData;
+ // </properties>
+ OUString m_sDataSourceName; // the data source we're working for
+ DataSourceHolder m_aDataSource;
+ Reference< XNumberFormatter > m_xFormatter; // a number formatter working with the connection's NumberFormatsSupplier
+ sal_Int32 m_nDocStartNumber;
+ bool m_bSuspended; // is true when the controller was already suspended
+ bool m_bEditable; // is the control readonly or not
+ bool m_bModified; // is the data modified
+ bool m_bNotAttached;
+
+ explicit DBSubComponentController_Impl(osl::Mutex& i_rMutex)
+ :m_aModifyListeners( i_rMutex )
+ ,m_nDocStartNumber(0)
+ ,m_bSuspended( false )
+ ,m_bEditable(true)
+ ,m_bModified(false)
+ ,m_bNotAttached(true)
+ {
+ }
+
+ bool documentHasScriptSupport() const
+ {
+ OSL_PRECOND( !!m_aDocScriptSupport,
+ "DBSubComponentController_Impl::documentHasScriptSupport: not completely initialized, yet - don't know!?" );
+ return !!m_aDocScriptSupport && *m_aDocScriptSupport;
+ }
+
+ void setDocumentScriptSupport( const bool _bSupport )
+ {
+ OSL_PRECOND( !m_aDocScriptSupport,
+ "DBSubComponentController_Impl::setDocumentScriptSupport: already initialized!" );
+ m_aDocScriptSupport = ::std::optional< bool >( _bSupport );
+ }
+ };
+
+ // DBSubComponentController
+ DBSubComponentController::DBSubComponentController(const Reference< XComponentContext >& _rxORB)
+ :DBSubComponentController_Base( _rxORB )
+ ,m_pImpl( new DBSubComponentController_Impl( getMutex() ) )
+ {
+ }
+
+ DBSubComponentController::~DBSubComponentController()
+ {
+ }
+
+ void DBSubComponentController::impl_initialize()
+ {
+ OGenericUnoController::impl_initialize();
+
+ const ::comphelper::NamedValueCollection& rArguments( getInitParams() );
+
+ Reference< XConnection > xConnection;
+ xConnection = rArguments.getOrDefault( PROPERTY_ACTIVE_CONNECTION, xConnection );
+
+ if ( !xConnection.is() )
+ ::dbtools::isEmbeddedInDatabase( getModel(), xConnection );
+
+ if ( xConnection.is() )
+ initializeConnection( xConnection );
+
+ bool bShowError = true;
+ if ( !isConnected() )
+ {
+ reconnect( false );
+ bShowError = false;
+ }
+ if ( !isConnected() )
+ {
+ if ( bShowError )
+ connectionLostMessage();
+ throw IllegalArgumentException();
+ }
+ }
+
+ Any SAL_CALL DBSubComponentController::queryInterface(const Type& _rType)
+ {
+ if ( _rType.equals( cppu::UnoType<XScriptInvocationContext>::get() ) )
+ {
+ if ( m_pImpl->documentHasScriptSupport() )
+ return Any( Reference< XScriptInvocationContext >( this ) );
+ return Any();
+ }
+
+ return DBSubComponentController_Base::queryInterface( _rType );
+ }
+
+ Sequence< Type > SAL_CALL DBSubComponentController::getTypes( )
+ {
+ Sequence< Type > aTypes( DBSubComponentController_Base::getTypes() );
+ if ( !m_pImpl->documentHasScriptSupport() )
+ {
+ auto [begin, end] = asNonConstRange(aTypes);
+ auto newEnd = std::remove_if( begin, end,
+ [](const Type& type)
+ { return type == cppu::UnoType<XScriptInvocationContext>::get(); } );
+ aTypes.realloc( std::distance(begin, newEnd) );
+ }
+ return aTypes;
+ }
+
+ void DBSubComponentController::initializeConnection( const Reference< XConnection >& _rxForeignConn )
+ {
+ DBG_ASSERT( !isConnected(), "DBSubComponentController::initializeConnection: not to be called when already connected!" );
+ // usually this gets called from within initialize of derived classes ...
+ if ( isConnected() )
+ disconnect();
+
+ m_pImpl->m_xConnection.reset( _rxForeignConn, SharedConnection::NoTakeOwnership );
+ m_pImpl->m_aSdbMetaData.reset( m_pImpl->m_xConnection );
+ startConnectionListening( m_pImpl->m_xConnection );
+
+ // get the data source the connection belongs to
+ try
+ {
+ // determine our data source
+ OSL_PRECOND( !m_pImpl->m_aDataSource.is(), "DBSubComponentController::initializeConnection: already a data source in this phase?" );
+ {
+ Reference< XChild > xConnAsChild( m_pImpl->m_xConnection, UNO_QUERY );
+ Reference< XDataSource > xDS;
+ if ( xConnAsChild.is() )
+ xDS.set( xConnAsChild->getParent(), UNO_QUERY );
+
+ // (take the indirection through XDataSource to ensure we have a correct object...)
+ m_pImpl->m_aDataSource = DataSourceHolder(xDS);
+ }
+ SAL_WARN_IF( !m_pImpl->m_aDataSource.is(), "dbaccess.ui", "DBSubComponentController::initializeConnection: unable to obtain the data source object!" );
+
+ if ( m_pImpl->m_bNotAttached )
+ {
+ Reference< XUntitledNumbers > xUntitledProvider( getDatabaseDocument(), UNO_QUERY );
+ m_pImpl->m_nDocStartNumber = 1;
+ if ( xUntitledProvider.is() )
+ m_pImpl->m_nDocStartNumber = xUntitledProvider->leaseNumber( static_cast< XWeak* >( this ) );
+ }
+
+ // determine the availability of script support in our document. Our own XScriptInvocationContext
+ // interface depends on this
+ m_pImpl->setDocumentScriptSupport( Reference< XEmbeddedScripts >( getDatabaseDocument(), UNO_QUERY ).is() );
+
+ // get a number formatter
+ Reference< XPropertySet > xDataSourceProps( m_pImpl->m_aDataSource.getDataSourceProps(), UNO_SET_THROW );
+ xDataSourceProps->getPropertyValue( PROPERTY_NAME ) >>= m_pImpl->m_sDataSourceName;
+ DBG_ASSERT( !m_pImpl->m_sDataSourceName.isEmpty(), "DBSubComponentController::initializeConnection: invalid data source name!" );
+ Reference< XNumberFormatsSupplier> xSupplier = ::dbtools::getNumberFormats(m_pImpl->m_xConnection);
+ if(xSupplier.is())
+ {
+ m_pImpl->m_xFormatter.set(NumberFormatter::create(getORB()), UNO_QUERY_THROW);
+ m_pImpl->m_xFormatter->attachNumberFormatsSupplier(xSupplier);
+ }
+ OSL_ENSURE(m_pImpl->m_xFormatter.is(),"No NumberFormatter!");
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+
+ void DBSubComponentController::reconnect( bool _bUI )
+ {
+ OSL_ENSURE(!m_pImpl->m_bSuspended, "Cannot reconnect while suspended!");
+
+ stopConnectionListening( m_pImpl->m_xConnection );
+ m_pImpl->m_aSdbMetaData.reset( nullptr );
+ m_pImpl->m_xConnection.clear();
+
+ // reconnect
+ bool bReConnect = true;
+ if ( _bUI )
+ {
+ std::unique_ptr<weld::MessageDialog> xQuery(Application::CreateMessageDialog(getFrameWeld(),
+ VclMessageType::Question, VclButtonsType::YesNo,
+ DBA_RES(STR_QUERY_CONNECTION_LOST)));
+ bReConnect = (RET_YES == xQuery->run());
+ }
+
+ // now really reconnect ...
+ if ( bReConnect )
+ {
+ m_pImpl->m_xConnection.reset( connect( m_pImpl->m_aDataSource.getDataSource() ), SharedConnection::TakeOwnership );
+ m_pImpl->m_aSdbMetaData.reset( m_pImpl->m_xConnection );
+ }
+
+ // invalidate all slots
+ InvalidateAll();
+ }
+
+ void DBSubComponentController::disconnect()
+ {
+ stopConnectionListening(m_pImpl->m_xConnection);
+ m_pImpl->m_aSdbMetaData.reset( nullptr );
+ m_pImpl->m_xConnection.clear();
+
+ InvalidateAll();
+ }
+
+ void DBSubComponentController::losingConnection()
+ {
+ // our connection was disposed so we need a new one
+ reconnect( true );
+ InvalidateAll();
+ }
+
+ void SAL_CALL DBSubComponentController::disposing()
+ {
+ DBSubComponentController_Base::disposing();
+
+ disconnect();
+
+ attachFrame( Reference < XFrame >() );
+
+ m_pImpl->m_aDataSource.clear();
+ }
+
+ void SAL_CALL DBSubComponentController::disposing(const EventObject& _rSource)
+ {
+ if ( _rSource.Source == getConnection() )
+ {
+ if ( !m_pImpl->m_bSuspended // when already suspended then we don't have to reconnect
+ && !getBroadcastHelper().bInDispose
+ && !getBroadcastHelper().bDisposed
+ && isConnected()
+ )
+ {
+ losingConnection();
+ }
+ else
+ {
+ m_pImpl->m_xConnection.reset( m_pImpl->m_xConnection, SharedConnection::NoTakeOwnership );
+ // this prevents the "disposeComponent" call in disconnect
+ disconnect();
+ }
+ }
+ else
+ DBSubComponentController_Base::disposing( _rSource );
+ }
+
+ void DBSubComponentController::appendError( const OUString& _rErrorMessage )
+ {
+ m_pImpl->m_aCurrentError.append( ::dbtools::SQLExceptionInfo::TYPE::SQLException, _rErrorMessage,
+ getStandardSQLState( ::dbtools::StandardSQLState::GENERAL_ERROR ),
+ 1000 );
+ }
+ void DBSubComponentController::clearError()
+ {
+ m_pImpl->m_aCurrentError = ::dbtools::SQLExceptionInfo();
+ }
+
+ bool DBSubComponentController::hasError() const
+ {
+ return m_pImpl->m_aCurrentError.isValid();
+ }
+
+ const ::dbtools::SQLExceptionInfo& DBSubComponentController::getError() const
+ {
+ return m_pImpl->m_aCurrentError;
+ }
+
+ void DBSubComponentController::displayError()
+ {
+ showError( m_pImpl->m_aCurrentError );
+ }
+
+ sal_Bool SAL_CALL DBSubComponentController::suspend(sal_Bool bSuspend)
+ {
+ m_pImpl->m_bSuspended = bSuspend;
+ if ( !bSuspend && !isConnected() )
+ reconnect(true);
+
+ return true;
+ }
+
+ sal_Bool SAL_CALL DBSubComponentController::attachModel( const Reference< XModel > & _rxModel)
+ {
+ if ( !_rxModel.is() )
+ return false;
+ if ( !DBSubComponentController_Base::attachModel( _rxModel ) )
+ return false;
+
+ m_pImpl->m_bNotAttached = false;
+ if ( m_pImpl->m_nDocStartNumber == 1 )
+ releaseNumberForComponent();
+
+ Reference< XUntitledNumbers > xUntitledProvider( _rxModel, UNO_QUERY );
+ m_pImpl->m_nDocStartNumber = 1;
+ if ( xUntitledProvider.is() )
+ m_pImpl->m_nDocStartNumber = xUntitledProvider->leaseNumber( static_cast< XWeak* >( this ) );
+
+ return true;
+ }
+
+ void DBSubComponentController::Execute(sal_uInt16 _nId, const Sequence< PropertyValue >& _rArgs)
+ {
+ if ( _nId == ID_BROWSER_CLOSE )
+ {
+ closeTask();
+ return;
+ }
+
+ DBSubComponentController_Base::Execute( _nId, _rArgs );
+ InvalidateFeature( _nId );
+ }
+
+ OUString DBSubComponentController::getDataSourceName() const
+ {
+ OUString sName;
+ Reference< XPropertySet > xDataSourceProps( m_pImpl->m_aDataSource.getDataSourceProps() );
+ if ( xDataSourceProps.is() )
+ xDataSourceProps->getPropertyValue(PROPERTY_NAME) >>= sName;
+ return sName;
+ }
+ void DBSubComponentController::connectionLostMessage() const
+ {
+ OUString aMessage(DBA_RES(RID_STR_CONNECTION_LOST));
+ Reference< XWindow > xWindow = getTopMostContainerWindow();
+ vcl::Window* pWin = nullptr;
+ if ( xWindow.is() )
+ pWin = VCLUnoHelper::GetWindow(xWindow);
+ if ( !pWin )
+ pWin = getView()->Window::GetParent();
+
+ std::unique_ptr<weld::MessageDialog> xInfo(Application::CreateMessageDialog(pWin ? pWin->GetFrameWeld() : nullptr,
+ VclMessageType::Info, VclButtonsType::Ok, aMessage));
+ xInfo->run();
+ }
+ const Reference< XConnection >& DBSubComponentController::getConnection() const
+ {
+ return m_pImpl->m_xConnection;
+ }
+
+ bool DBSubComponentController::isReadOnly() const
+ {
+ return !m_pImpl->m_bEditable;
+ }
+
+ bool DBSubComponentController::isEditable() const
+ {
+ return m_pImpl->m_bEditable;
+ }
+
+ void DBSubComponentController::setEditable(bool _bEditable)
+ {
+ m_pImpl->m_bEditable = _bEditable;
+ }
+
+ const ::dbtools::DatabaseMetaData& DBSubComponentController::getSdbMetaData() const
+ {
+ return m_pImpl->m_aSdbMetaData;
+ }
+
+ bool DBSubComponentController::isConnected() const
+ {
+ return m_pImpl->m_xConnection.is();
+ }
+
+ Reference< XDatabaseMetaData > DBSubComponentController::getMetaData( ) const
+ {
+ Reference< XDatabaseMetaData > xMeta;
+ try
+ {
+ if ( isConnected() )
+ xMeta.set( m_pImpl->m_xConnection->getMetaData(), UNO_SET_THROW );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ return xMeta;
+ }
+
+ const Reference< XPropertySet >& DBSubComponentController::getDataSource() const
+ {
+ return m_pImpl->m_aDataSource.getDataSourceProps();
+ }
+
+ bool DBSubComponentController::haveDataSource() const
+ {
+ return m_pImpl->m_aDataSource.is();
+ }
+
+ Reference< XModel > DBSubComponentController::getDatabaseDocument() const
+ {
+ return Reference< XModel >( m_pImpl->m_aDataSource.getDatabaseDocument(), UNO_QUERY );
+ }
+
+ Reference< XNumberFormatter > const & DBSubComponentController::getNumberFormatter() const
+ {
+ return m_pImpl->m_xFormatter;
+ }
+
+ Reference< XModel > DBSubComponentController::getPrivateModel() const
+ {
+ return getDatabaseDocument();
+ }
+ // XTitle
+ OUString SAL_CALL DBSubComponentController::getTitle()
+ {
+ ::osl::MutexGuard aGuard( getMutex() );
+ if ( m_bExternalTitle )
+ return impl_getTitleHelper_throw()->getTitle ();
+
+ OUStringBuffer sTitle;
+ Reference< XTitle > xTitle(getPrivateModel(),UNO_QUERY);
+ if ( xTitle.is() )
+ {
+ sTitle.append( xTitle->getTitle() );
+ sTitle.append(" : ");
+ }
+ sTitle.append( getPrivateTitle() );
+ return sTitle.makeStringAndClear();
+ }
+
+ sal_Int32 DBSubComponentController::getCurrentStartNumber() const
+ {
+ return m_pImpl->m_nDocStartNumber;
+ }
+
+ Reference< XEmbeddedScripts > SAL_CALL DBSubComponentController::getScriptContainer()
+ {
+ ::osl::MutexGuard aGuard( getMutex() );
+ if ( !m_pImpl->documentHasScriptSupport() )
+ return nullptr;
+
+ return Reference< XEmbeddedScripts >( getDatabaseDocument(), UNO_QUERY_THROW );
+ }
+
+ void SAL_CALL DBSubComponentController::addModifyListener( const Reference< XModifyListener >& i_Listener )
+ {
+ ::osl::MutexGuard aGuard( getMutex() );
+ m_pImpl->m_aModifyListeners.addInterface( i_Listener );
+ }
+
+ void SAL_CALL DBSubComponentController::removeModifyListener( const Reference< XModifyListener >& i_Listener )
+ {
+ ::osl::MutexGuard aGuard( getMutex() );
+ m_pImpl->m_aModifyListeners.removeInterface( i_Listener );
+ }
+
+ sal_Bool SAL_CALL DBSubComponentController::isModified( )
+ {
+ ::osl::MutexGuard aGuard( getMutex() );
+ return impl_isModified();
+ }
+
+ void SAL_CALL DBSubComponentController::setModified( sal_Bool i_bModified )
+ {
+ ::osl::ClearableMutexGuard aGuard( getMutex() );
+
+ if ( m_pImpl->m_bModified == bool(i_bModified) )
+ return;
+
+ m_pImpl->m_bModified = i_bModified;
+ impl_onModifyChanged();
+
+ EventObject aEvent( *this );
+ aGuard.clear();
+ m_pImpl->m_aModifyListeners.notifyEach( &XModifyListener::modified, aEvent );
+ }
+
+ bool DBSubComponentController::impl_isModified() const
+ {
+ return m_pImpl->m_bModified;
+ }
+
+ void DBSubComponentController::impl_onModifyChanged()
+ {
+ InvalidateFeature( ID_BROWSER_SAVEDOC );
+ if ( isFeatureSupported( ID_BROWSER_SAVEASDOC ) )
+ InvalidateFeature( ID_BROWSER_SAVEASDOC );
+ }
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/misc/defaultobjectnamecheck.cxx b/dbaccess/source/ui/misc/defaultobjectnamecheck.cxx
new file mode 100644
index 000000000..53ef26fa3
--- /dev/null
+++ b/dbaccess/source/ui/misc/defaultobjectnamecheck.cxx
@@ -0,0 +1,160 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <core_resource.hxx>
+#include <defaultobjectnamecheck.hxx>
+
+#include <strings.hrc>
+
+#include <com/sun/star/lang/IllegalArgumentException.hpp>
+#include <com/sun/star/sdb/CommandType.hpp>
+#include <com/sun/star/sdb/tools/XConnectionTools.hpp>
+#include <com/sun/star/sdbc/SQLException.hpp>
+
+#include <connectivity/dbexception.hxx>
+#include <connectivity/dbmetadata.hxx>
+
+#include <rtl/ustrbuf.hxx>
+
+#include <tools/diagnose_ex.h>
+#include <cppuhelper/exc_hlp.hxx>
+
+#include <memory>
+#include <string_view>
+
+namespace dbaui
+{
+
+ using ::com::sun::star::uno::Reference;
+ using ::com::sun::star::lang::IllegalArgumentException;
+ using ::com::sun::star::container::XHierarchicalNameAccess;
+ using ::com::sun::star::sdbc::SQLException;
+ using ::com::sun::star::uno::Exception;
+ using ::com::sun::star::sdbc::XConnection;
+ using ::com::sun::star::sdb::tools::XObjectNames;
+ using ::com::sun::star::sdb::tools::XConnectionTools;
+ using ::com::sun::star::uno::UNO_QUERY;
+
+ using namespace dbtools;
+
+ namespace CommandType = ::com::sun::star::sdb::CommandType;
+
+ // helper
+ namespace
+ {
+ void lcl_fillNameExistsError( std::u16string_view _rObjectName, SQLExceptionInfo& _out_rErrorToDisplay )
+ {
+ SQLException aError;
+ OUString sErrorMessage = DBA_RES(STR_NAMED_OBJECT_ALREADY_EXISTS);
+ aError.Message = sErrorMessage.replaceAll("$#$", _rObjectName);
+ _out_rErrorToDisplay = aError;
+ }
+
+ }
+
+ // HierarchicalNameCheck_Impl
+ struct HierarchicalNameCheck_Impl
+ {
+ Reference< XHierarchicalNameAccess > xHierarchicalNames;
+ OUString sRelativeRoot;
+ };
+
+ // HierarchicalNameCheck
+ HierarchicalNameCheck::HierarchicalNameCheck( const Reference< XHierarchicalNameAccess >& _rxNames, const OUString& _rRelativeRoot )
+ :m_pImpl( new HierarchicalNameCheck_Impl )
+ {
+ m_pImpl->xHierarchicalNames = _rxNames;
+ m_pImpl->sRelativeRoot = _rRelativeRoot;
+
+ if ( !m_pImpl->xHierarchicalNames.is() )
+ throw IllegalArgumentException();
+ }
+
+ HierarchicalNameCheck::~HierarchicalNameCheck()
+ {
+ }
+
+ bool HierarchicalNameCheck::isNameValid( const OUString& _rObjectName, SQLExceptionInfo& _out_rErrorToDisplay ) const
+ {
+ try
+ {
+ OUStringBuffer aCompleteName;
+ if ( !m_pImpl->sRelativeRoot.isEmpty() )
+ {
+ aCompleteName.append( m_pImpl->sRelativeRoot );
+ aCompleteName.append( "/" );
+ }
+ aCompleteName.append( _rObjectName );
+
+ OUString sCompleteName( aCompleteName.makeStringAndClear() );
+ if ( !m_pImpl->xHierarchicalNames->hasByHierarchicalName( sCompleteName ) )
+ return true;
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+
+ lcl_fillNameExistsError( _rObjectName, _out_rErrorToDisplay );
+ return false;
+ }
+
+ // DynamicTableOrQueryNameCheck_Impl
+ struct DynamicTableOrQueryNameCheck_Impl
+ {
+ sal_Int32 nCommandType;
+ Reference< XObjectNames > xObjectNames;
+ };
+
+ // DynamicTableOrQueryNameCheck
+ DynamicTableOrQueryNameCheck::DynamicTableOrQueryNameCheck( const Reference< XConnection >& _rxSdbLevelConnection, sal_Int32 _nCommandType )
+ :m_pImpl( new DynamicTableOrQueryNameCheck_Impl )
+ {
+ Reference< XConnectionTools > xConnTools( _rxSdbLevelConnection, UNO_QUERY );
+ if ( xConnTools.is() )
+ m_pImpl->xObjectNames.set( xConnTools->getObjectNames() );
+ if ( !m_pImpl->xObjectNames.is() )
+ throw IllegalArgumentException();
+
+ if ( ( _nCommandType != CommandType::QUERY ) && ( _nCommandType != CommandType::TABLE ) )
+ throw IllegalArgumentException();
+ m_pImpl->nCommandType = _nCommandType;
+ }
+
+ DynamicTableOrQueryNameCheck::~DynamicTableOrQueryNameCheck()
+ {
+ }
+
+ bool DynamicTableOrQueryNameCheck::isNameValid( const OUString& _rObjectName, ::dbtools::SQLExceptionInfo& _out_rErrorToDisplay ) const
+ {
+ try
+ {
+ m_pImpl->xObjectNames->checkNameForCreate( m_pImpl->nCommandType, _rObjectName );
+ return true;
+ }
+ catch( const SQLException& )
+ {
+ _out_rErrorToDisplay = ::dbtools::SQLExceptionInfo( ::cppu::getCaughtException() );
+ }
+ return false;
+ }
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/misc/dsmeta.cxx b/dbaccess/source/ui/misc/dsmeta.cxx
new file mode 100644
index 000000000..286ce63aa
--- /dev/null
+++ b/dbaccess/source/ui/misc/dsmeta.cxx
@@ -0,0 +1,182 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <dsmeta.hxx>
+#include <connectivity/DriversConfig.hxx>
+#include <dsntypes.hxx>
+#include <comphelper/processfactory.hxx>
+
+#include <map>
+#include <utility>
+
+namespace dbaui
+{
+
+ using namespace dbaccess;
+ using namespace ::com::sun::star;
+
+ namespace {
+
+ struct FeatureSupport
+ {
+ // authentication mode of the data source
+ AuthenticationMode eAuthentication;
+
+ FeatureSupport()
+ :eAuthentication( AuthUserPwd )
+ {
+ }
+
+ explicit FeatureSupport(AuthenticationMode Auth)
+ :eAuthentication( Auth )
+ {
+ }
+ };
+
+ struct FeatureMapping
+ {
+ /// one of the items from dsitems.hxx
+ ItemID nItemID;
+ OUString pAsciiFeatureName;
+ };
+
+ // global tables
+ const FeatureMapping s_aMappings[] = {
+ { DSID_AUTORETRIEVEENABLED, "GeneratedValues" },
+ { DSID_AUTOINCREMENTVALUE, "GeneratedValues" },
+ { DSID_AUTORETRIEVEVALUE, "GeneratedValues" },
+ { DSID_SQL92CHECK, "UseSQL92NamingConstraints" },
+ { DSID_APPEND_TABLE_ALIAS, "AppendTableAliasInSelect" },
+ { DSID_AS_BEFORE_CORRNAME, "UseKeywordAsBeforeAlias" },
+ { DSID_ENABLEOUTERJOIN, "UseBracketedOuterJoinSyntax" },
+ { DSID_IGNOREDRIVER_PRIV, "IgnoreDriverPrivileges" },
+ { DSID_PARAMETERNAMESUBST, "ParameterNameSubstitution" },
+ { DSID_SUPPRESSVERSIONCL, "DisplayVersionColumns" },
+ { DSID_CATALOG, "UseCatalogInSelect" },
+ { DSID_SCHEMA, "UseSchemaInSelect" },
+ { DSID_INDEXAPPENDIX, "UseIndexDirectionKeyword" },
+ { DSID_DOSLINEENDS, "UseDOSLineEnds" },
+ { DSID_BOOLEANCOMPARISON, "BooleanComparisonMode" },
+ { DSID_CHECK_REQUIRED_FIELDS, "FormsCheckRequiredFields" },
+ { DSID_IGNORECURRENCY, "IgnoreCurrency" },
+ { DSID_ESCAPE_DATETIME, "EscapeDateTime" },
+ { DSID_PRIMARY_KEY_SUPPORT, "PrimaryKeySupport" },
+ { DSID_RESPECTRESULTSETTYPE, "RespectDriverResultSetType" },
+ { DSID_MAX_ROW_SCAN, "MaxRowScan" },
+ };
+ }
+
+ static const FeatureSet& lcl_getFeatureSet( const OUString& _rURL )
+ {
+ typedef std::map< OUString, FeatureSet > FeatureSets;
+ static FeatureSets s_aFeatureSets = []()
+ {
+ FeatureSets tmp;
+ ::connectivity::DriversConfig aDriverConfig( ::comphelper::getProcessComponentContext() );
+ const uno::Sequence< OUString > aPatterns = aDriverConfig.getURLs();
+ for ( auto const & pattern : aPatterns )
+ {
+ FeatureSet aCurrentSet;
+ const ::comphelper::NamedValueCollection aCurrentFeatures( aDriverConfig.getFeatures( pattern ).getNamedValues() );
+
+ for ( const FeatureMapping& rFeatureMapping : s_aMappings )
+ {
+ if ( aCurrentFeatures.has( rFeatureMapping.pAsciiFeatureName ) )
+ aCurrentSet.put( rFeatureMapping.nItemID );
+ }
+
+ tmp[ pattern ] = aCurrentSet;
+ }
+ return tmp;
+ }();
+
+ OSL_ENSURE( s_aFeatureSets.find( _rURL ) != s_aFeatureSets.end(), "invalid URL/pattern!" );
+ return s_aFeatureSets[ _rURL ];
+ }
+
+ static AuthenticationMode getAuthenticationMode( const OUString& _sURL )
+ {
+ static std::map< OUString, FeatureSupport > s_aSupport = []()
+ {
+ std::map< OUString, FeatureSupport > tmp;
+ ::connectivity::DriversConfig aDriverConfig(::comphelper::getProcessComponentContext());
+ const uno::Sequence< OUString > aURLs = aDriverConfig.getURLs();
+ const OUString* pIter = aURLs.getConstArray();
+ const OUString* pEnd = pIter + aURLs.getLength();
+ for(;pIter != pEnd;++pIter)
+ {
+ FeatureSupport aInit( AuthNone );
+ const ::comphelper::NamedValueCollection& aMetaData = aDriverConfig.getMetaData(*pIter);
+ if ( aMetaData.has("Authentication") )
+ {
+ OUString sAuth;
+ aMetaData.get("Authentication") >>= sAuth;
+ if ( sAuth == "UserPassword" )
+ aInit = FeatureSupport(AuthUserPwd);
+ else if ( sAuth == "Password" )
+ aInit = FeatureSupport(AuthPwd);
+ }
+ tmp.insert(std::make_pair(*pIter,aInit));
+ }
+ return tmp;
+ }();
+ OSL_ENSURE(s_aSupport.find(_sURL) != s_aSupport.end(),"Illegal URL!");
+ return s_aSupport[ _sURL ].eAuthentication;
+ }
+
+ // DataSourceMetaData_Impl
+ class DataSourceMetaData_Impl
+ {
+ public:
+ explicit DataSourceMetaData_Impl(const OUString& rURL);
+
+ const OUString& getType() const { return m_sURL; }
+
+ private:
+ const OUString m_sURL;
+ };
+
+ DataSourceMetaData_Impl::DataSourceMetaData_Impl( const OUString& _sURL )
+ :m_sURL( _sURL )
+ {
+ }
+
+ // DataSourceMetaData
+ DataSourceMetaData::DataSourceMetaData( const OUString& _sURL )
+ :m_pImpl( std::make_shared<DataSourceMetaData_Impl>( _sURL ) )
+ {
+ }
+
+ DataSourceMetaData::~DataSourceMetaData()
+ {
+ }
+
+ const FeatureSet& DataSourceMetaData::getFeatureSet() const
+ {
+ return lcl_getFeatureSet( m_pImpl->getType() );
+ }
+
+ AuthenticationMode DataSourceMetaData::getAuthentication( const OUString& _sURL )
+ {
+ return getAuthenticationMode( _sURL );
+ }
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/misc/imageprovider.cxx b/dbaccess/source/ui/misc/imageprovider.cxx
new file mode 100644
index 000000000..b69ec70e6
--- /dev/null
+++ b/dbaccess/source/ui/misc/imageprovider.cxx
@@ -0,0 +1,202 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <imageprovider.hxx>
+#include <bitmaps.hlst>
+
+#include <com/sun/star/graphic/GraphicColorMode.hpp>
+#include <com/sun/star/sdb/application/XTableUIProvider.hpp>
+#include <com/sun/star/sdb/application/DatabaseObject.hpp>
+#include <com/sun/star/sdbcx/XViewsSupplier.hpp>
+
+#include <tools/diagnose_ex.h>
+
+namespace dbaui
+{
+
+ using ::com::sun::star::uno::Reference;
+ using ::com::sun::star::sdbc::XConnection;
+ using ::com::sun::star::uno::Exception;
+ using ::com::sun::star::container::XNameAccess;
+ using ::com::sun::star::graphic::XGraphic;
+ using ::com::sun::star::sdb::application::XTableUIProvider;
+ using ::com::sun::star::uno::UNO_QUERY;
+ using ::com::sun::star::sdbcx::XViewsSupplier;
+ using ::com::sun::star::uno::UNO_SET_THROW;
+
+ namespace GraphicColorMode = css::graphic::GraphicColorMode;
+ namespace DatabaseObject = css::sdb::application::DatabaseObject;
+
+ // ImageProvider_Data
+ struct ImageProvider_Data
+ {
+ /// the connection we work with
+ Reference< XConnection > xConnection;
+ /// the views of the connection, if the DB supports views
+ Reference< XNameAccess > xViews;
+ /// interface for providing table's UI
+ Reference< XTableUIProvider > xTableUI;
+ };
+
+ namespace
+ {
+ void lcl_getConnectionProvidedTableIcon_nothrow( const ImageProvider_Data& _rData,
+ const OUString& _rName, Reference< XGraphic >& _out_rxGraphic )
+ {
+ try
+ {
+ if ( _rData.xTableUI.is() )
+ _out_rxGraphic = _rData.xTableUI->getTableIcon( _rName, GraphicColorMode::NORMAL );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+
+ void lcl_getTableImageResourceID_nothrow( const ImageProvider_Data& _rData, const OUString& _rName,
+ OUString& _out_rResourceID)
+ {
+ _out_rResourceID = OUString();
+ try
+ {
+ bool bIsView = _rData.xViews.is() && _rData.xViews->hasByName( _rName );
+ if ( bIsView )
+ {
+ _out_rResourceID = VIEW_TREE_ICON;
+ }
+ else
+ {
+ _out_rResourceID = TABLE_TREE_ICON;
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+ }
+ // ImageProvider
+ ImageProvider::ImageProvider()
+ :m_pData( std::make_shared<ImageProvider_Data>() )
+ {
+ }
+
+ ImageProvider::ImageProvider( const Reference< XConnection >& _rxConnection )
+ :m_pData( std::make_shared<ImageProvider_Data>() )
+ {
+ m_pData->xConnection = _rxConnection;
+ try
+ {
+ Reference< XViewsSupplier > xSuppViews( m_pData->xConnection, UNO_QUERY );
+ if ( xSuppViews.is() )
+ m_pData->xViews.set( xSuppViews->getViews(), UNO_SET_THROW );
+
+ m_pData->xTableUI.set( _rxConnection, UNO_QUERY );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+
+ OUString ImageProvider::getImageId(const OUString& _rName, const sal_Int32 _nDatabaseObjectType)
+ {
+ if (_nDatabaseObjectType != DatabaseObject::TABLE)
+ {
+ // for types other than tables, the icon does not depend on the concrete object
+ return getDefaultImageResourceID( _nDatabaseObjectType );
+ }
+ else
+ {
+ // no -> determine by type
+ OUString sImageResourceID;
+ lcl_getTableImageResourceID_nothrow( *m_pData, _rName, sImageResourceID );
+ return sImageResourceID;
+ }
+ }
+
+ Reference<XGraphic> ImageProvider::getXGraphic(const OUString& _rName, const sal_Int32 _nDatabaseObjectType)
+ {
+ Reference<XGraphic> xGraphic;
+ if (_nDatabaseObjectType == DatabaseObject::TABLE)
+ {
+ // check whether the connection can give us an icon
+ lcl_getConnectionProvidedTableIcon_nothrow( *m_pData, _rName, xGraphic );
+ }
+ return xGraphic;
+ }
+
+ OUString ImageProvider::getDefaultImageResourceID( sal_Int32 _nDatabaseObjectType)
+ {
+ OUString sImageResourceID;
+ switch ( _nDatabaseObjectType )
+ {
+ case DatabaseObject::QUERY:
+ sImageResourceID = QUERY_TREE_ICON;
+ break;
+ case DatabaseObject::FORM:
+ sImageResourceID = FORM_TREE_ICON;
+ break;
+ case DatabaseObject::REPORT:
+ sImageResourceID = REPORT_TREE_ICON;
+ break;
+ case DatabaseObject::TABLE:
+ sImageResourceID = TABLE_TREE_ICON;
+ break;
+ default:
+ OSL_FAIL( "ImageProvider::getDefaultImage: invalid database object type!" );
+ break;
+ }
+ return sImageResourceID;
+ }
+
+ OUString ImageProvider::getFolderImageId( sal_Int32 _nDatabaseObjectType )
+ {
+ OUString sImageResourceID;
+ switch ( _nDatabaseObjectType )
+ {
+ case DatabaseObject::QUERY:
+ sImageResourceID = QUERYFOLDER_TREE_ICON;
+ break;
+ case DatabaseObject::FORM:
+ sImageResourceID = FORMFOLDER_TREE_ICON;
+ break;
+ case DatabaseObject::REPORT:
+ sImageResourceID = REPORTFOLDER_TREE_ICON;
+ break;
+ case DatabaseObject::TABLE:
+ sImageResourceID = TABLEFOLDER_TREE_ICON;
+ break;
+ default:
+ OSL_FAIL( "ImageProvider::getDefaultImage: invalid database object type!" );
+ break;
+ }
+
+ return sImageResourceID;
+ }
+
+ OUString ImageProvider::getDatabaseImage()
+ {
+ return DATABASE_TREE_ICON;
+ }
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/misc/indexcollection.cxx b/dbaccess/source/ui/misc/indexcollection.cxx
new file mode 100644
index 000000000..1b9377362
--- /dev/null
+++ b/dbaccess/source/ui/misc/indexcollection.cxx
@@ -0,0 +1,328 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <indexcollection.hxx>
+#include <tools/diagnose_ex.h>
+#include <com/sun/star/sdbc/SQLException.hpp>
+#include <com/sun/star/sdbcx/XAppend.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
+#include <com/sun/star/sdbcx/XDataDescriptorFactory.hpp>
+#include <comphelper/extract.hxx>
+#include <com/sun/star/sdbcx/XDrop.hpp>
+
+namespace dbaui
+{
+
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::container;
+ using namespace ::com::sun::star::beans;
+ using namespace ::com::sun::star::sdbcx;
+ using namespace ::com::sun::star::sdbc;
+
+ // OIndexCollection
+ OIndexCollection::OIndexCollection()
+ {
+ }
+
+ OIndexCollection::OIndexCollection(const OIndexCollection& _rSource)
+ {
+ *this = _rSource;
+ }
+
+ OIndexCollection& OIndexCollection::operator=(const OIndexCollection& _rSource)
+ {
+ detach();
+ m_xIndexes = _rSource.m_xIndexes;
+ m_aIndexes = _rSource.m_aIndexes;
+ return *this;
+ }
+
+ void OIndexCollection::attach(const Reference< XNameAccess >& _rxIndexes)
+ {
+ implConstructFrom(_rxIndexes);
+ }
+
+ void OIndexCollection::detach()
+ {
+ m_xIndexes.clear();
+ m_aIndexes.clear();
+ }
+
+ Indexes::const_iterator OIndexCollection::find(const OUString& _rName) const
+ {
+ // loop'n'compare
+ return std::find_if(m_aIndexes.cbegin(), m_aIndexes.cend(),
+ [&_rName](const OIndex& rIndex) { return rIndex.sName == _rName; });
+ }
+
+ Indexes::iterator OIndexCollection::find(const OUString& _rName)
+ {
+ // loop'n'compare
+ return std::find_if(m_aIndexes.begin(), m_aIndexes.end(),
+ [&_rName](const OIndex& rIndex) { return rIndex.sName == _rName; });
+ }
+
+ Indexes::const_iterator OIndexCollection::findOriginal(const OUString& _rName) const
+ {
+ // loop'n'compare
+ return std::find_if(m_aIndexes.cbegin(), m_aIndexes.cend(),
+ [&_rName](const OIndex& rIndex) { return rIndex.getOriginalName() == _rName; });
+ }
+
+ Indexes::iterator OIndexCollection::findOriginal(const OUString& _rName)
+ {
+ // loop'n'compare
+ return std::find_if(m_aIndexes.begin(), m_aIndexes.end(),
+ [&_rName](const OIndex& rIndex) { return rIndex.getOriginalName() == _rName; });
+ }
+
+ void OIndexCollection::commitNewIndex(const Indexes::iterator& _rPos)
+ {
+ OSL_ENSURE(_rPos->isNew(), "OIndexCollection::commitNewIndex: index must be new!");
+
+ try
+ {
+ Reference< XDataDescriptorFactory > xIndexFactory(m_xIndexes, UNO_QUERY);
+ Reference< XAppend > xAppendIndex(xIndexFactory, UNO_QUERY);
+ if (!xAppendIndex.is())
+ {
+ OSL_FAIL("OIndexCollection::commitNewIndex: missing an interface of the index container!");
+ return;
+ }
+
+ Reference< XPropertySet > xIndexDescriptor = xIndexFactory->createDataDescriptor();
+ Reference< XColumnsSupplier > xColsSupp(xIndexDescriptor, UNO_QUERY);
+ Reference< XNameAccess > xCols;
+ if (xColsSupp.is())
+ xCols = xColsSupp->getColumns();
+
+ Reference< XDataDescriptorFactory > xColumnFactory(xCols, UNO_QUERY);
+ Reference< XAppend > xAppendCols(xColumnFactory, UNO_QUERY);
+ if (!xAppendCols.is())
+ {
+ OSL_FAIL("OIndexCollection::commitNewIndex: invalid index descriptor returned!");
+ return;
+ }
+
+ // set the properties
+ static constexpr OUStringLiteral s_sNamePropertyName = u"Name";
+ // the index' own props
+ xIndexDescriptor->setPropertyValue("IsUnique", css::uno::Any(_rPos->bUnique));
+ xIndexDescriptor->setPropertyValue(s_sNamePropertyName, Any(_rPos->sName));
+
+ // the fields
+ for (auto const& field : _rPos->aFields)
+ {
+ OSL_ENSURE(!xCols->hasByName(field.sFieldName), "OIndexCollection::commitNewIndex: double column name (need to prevent this outside)!");
+
+ Reference< XPropertySet > xColDescriptor = xColumnFactory->createDataDescriptor();
+ OSL_ENSURE(xColDescriptor.is(), "OIndexCollection::commitNewIndex: invalid column descriptor!");
+ if (xColDescriptor.is())
+ {
+ xColDescriptor->setPropertyValue("IsAscending", css::uno::Any(field.bSortAscending));
+ xColDescriptor->setPropertyValue(s_sNamePropertyName, Any(field.sFieldName));
+ xAppendCols->appendByDescriptor(xColDescriptor);
+ }
+ }
+
+ xAppendIndex->appendByDescriptor(xIndexDescriptor);
+
+ _rPos->flagAsCommitted(GrantIndexAccess());
+ _rPos->clearModified();
+ }
+ catch(SQLException&)
+ { // allowed to pass
+ throw;
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+
+ bool OIndexCollection::dropNoRemove(const Indexes::iterator& _rPos)
+ {
+ try
+ {
+ OSL_ENSURE(m_xIndexes->hasByName(_rPos->getOriginalName()), "OIndexCollection::drop: invalid name!");
+
+ Reference< XDrop > xDropIndex(m_xIndexes, UNO_QUERY);
+ if (!xDropIndex.is())
+ {
+ OSL_FAIL("OIndexCollection::drop: no XDrop interface!");
+ return false;
+ }
+
+ xDropIndex->dropByName(_rPos->getOriginalName());
+ }
+ catch(SQLException&)
+ { // allowed to pass
+ throw;
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ return false;
+ }
+
+ // adjust the OIndex structure
+ Indexes::iterator aDropped = findOriginal(_rPos->getOriginalName());
+ OSL_ENSURE(aDropped != m_aIndexes.end(), "OIndexCollection::drop: invalid original name, but successful commit?!");
+ aDropped->flagAsNew(GrantIndexAccess());
+
+ return true;
+ }
+
+ bool OIndexCollection::drop(const Indexes::iterator& _rPos)
+ {
+ OSL_ENSURE((_rPos >= m_aIndexes.begin()) && (_rPos < m_aIndexes.end()),
+ "OIndexCollection::drop: invalid position (fasten your seatbelt... this will crash)!");
+
+ if (!_rPos->isNew())
+ if (!dropNoRemove(_rPos))
+ return false;
+
+ // adjust the index array
+ m_aIndexes.erase(_rPos);
+ return true;
+ }
+
+ void OIndexCollection::implFillIndexInfo(OIndex& _rIndex)
+ {
+ // get the UNO descriptor for the index
+ Reference< XPropertySet > xIndex;
+ m_xIndexes->getByName(_rIndex.getOriginalName()) >>= xIndex;
+ if (!xIndex.is())
+ {
+ OSL_FAIL("OIndexCollection::implFillIndexInfo: got an invalid index object!");
+ }
+ else
+ implFillIndexInfo(_rIndex, xIndex);
+ }
+
+ void OIndexCollection::implFillIndexInfo(OIndex& _rIndex, const Reference< XPropertySet >& _rxDescriptor)
+ {
+ _rIndex.bPrimaryKey = ::cppu::any2bool(_rxDescriptor->getPropertyValue("IsPrimaryKeyIndex"));
+ _rIndex.bUnique = ::cppu::any2bool(_rxDescriptor->getPropertyValue("IsUnique"));
+ _rxDescriptor->getPropertyValue("Catalog") >>= _rIndex.sDescription;
+
+ // the columns
+ Reference< XColumnsSupplier > xSuppCols(_rxDescriptor, UNO_QUERY);
+ Reference< XNameAccess > xCols;
+ if (xSuppCols.is())
+ xCols = xSuppCols->getColumns();
+ OSL_ENSURE(xCols.is(), "OIndexCollection::implFillIndexInfo: the index does not have columns!");
+ if (!xCols.is())
+ return;
+
+ Sequence< OUString > aFieldNames = xCols->getElementNames();
+ _rIndex.aFields.resize(aFieldNames.getLength());
+
+ const OUString* pFieldNames = aFieldNames.getConstArray();
+ const OUString* pFieldNamesEnd = pFieldNames + aFieldNames.getLength();
+ IndexFields::iterator aCopyTo = _rIndex.aFields.begin();
+
+ Reference< XPropertySet > xIndexColumn;
+ for (;pFieldNames < pFieldNamesEnd; ++pFieldNames, ++aCopyTo)
+ {
+ // extract the column
+ xIndexColumn.clear();
+ xCols->getByName(*pFieldNames) >>= xIndexColumn;
+ if (!xIndexColumn.is())
+ {
+ OSL_FAIL("OIndexCollection::implFillIndexInfo: invalid index column!");
+ --aCopyTo;
+ continue;
+ }
+
+ // get the relevant properties
+ aCopyTo->sFieldName = *pFieldNames;
+ aCopyTo->bSortAscending = ::cppu::any2bool(xIndexColumn->getPropertyValue("IsAscending"));
+ }
+
+ _rIndex.aFields.resize(aCopyTo - _rIndex.aFields.begin());
+ // (just in case some fields were invalid ...)
+ }
+
+ void OIndexCollection::resetIndex(const Indexes::iterator& _rPos)
+ {
+ OSL_ENSURE(_rPos >= m_aIndexes.begin() && _rPos < m_aIndexes.end(),
+ "OIndexCollection::resetIndex: invalid position!");
+
+ try
+ {
+ _rPos->sName = _rPos->getOriginalName();
+ implFillIndexInfo(*_rPos);
+
+ _rPos->clearModified();
+ _rPos->flagAsCommitted(GrantIndexAccess());
+ }
+ catch(SQLException&)
+ { // allowed to pass
+ throw;
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+
+ Indexes::iterator OIndexCollection::insert(const OUString& _rName)
+ {
+ OSL_ENSURE(end() == find(_rName), "OIndexCollection::insert: invalid new name!");
+ OIndex aNewIndex((OUString())); // the empty string indicates the index is a new one
+ aNewIndex.sName = _rName;
+ m_aIndexes.push_back(aNewIndex);
+ return m_aIndexes.end() - 1; // the last element is the new one ...
+ }
+
+ void OIndexCollection::implConstructFrom(const Reference< XNameAccess >& _rxIndexes)
+ {
+ detach();
+
+ m_xIndexes = _rxIndexes;
+ if (!m_xIndexes.is())
+ return;
+
+ // loop through all the indexes
+ Sequence< OUString > aNames = m_xIndexes->getElementNames();
+ const OUString* pNames = aNames.getConstArray();
+ const OUString* pEnd = pNames + aNames.getLength();
+ for (; pNames < pEnd; ++pNames)
+ {
+ // extract the index object
+ Reference< XPropertySet > xIndex;
+ m_xIndexes->getByName(*pNames) >>= xIndex;
+ if (!xIndex.is())
+ {
+ OSL_FAIL("OIndexCollection::implConstructFrom: got an invalid index object ... ignoring!");
+ continue;
+ }
+
+ // fill the OIndex structure
+ OIndex aCurrentIndex(*pNames);
+ implFillIndexInfo(aCurrentIndex);
+ m_aIndexes.push_back(aCurrentIndex);
+ }
+ }
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/misc/linkeddocuments.cxx b/dbaccess/source/ui/misc/linkeddocuments.cxx
new file mode 100644
index 000000000..192331ced
--- /dev/null
+++ b/dbaccess/source/ui/misc/linkeddocuments.cxx
@@ -0,0 +1,354 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <core_resource.hxx>
+#include <linkeddocuments.hxx>
+#include <osl/diagnose.h>
+#include <tools/diagnose_ex.h>
+#include <unotools/confignode.hxx>
+#include <comphelper/classids.hxx>
+#include <comphelper/namedvaluecollection.hxx>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/frame/XComponentLoader.hpp>
+#include <com/sun/star/sdbc/SQLException.hpp>
+#include <com/sun/star/ucb/XCommandProcessor.hpp>
+#include <com/sun/star/ucb/OpenCommandArgument.hpp>
+#include <com/sun/star/ucb/OpenMode.hpp>
+#include <com/sun/star/task/XJobExecutor.hpp>
+#include <comphelper/types.hxx>
+#include <strings.hrc>
+#include <strings.hxx>
+#include <svl/filenotation.hxx>
+#include <browserids.hxx>
+#include <com/sun/star/container/XHierarchicalNameContainer.hpp>
+#include <comphelper/mimeconfighelper.hxx>
+#include <vcl/weld.hxx>
+
+#include <cppuhelper/exc_hlp.hxx>
+#include <connectivity/dbtools.hxx>
+#include <com/sun/star/io/WrongFormatException.hpp>
+
+namespace dbaui
+{
+
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::container;
+ using namespace ::com::sun::star::lang;
+ using namespace ::com::sun::star::frame;
+ using namespace ::com::sun::star::beans;
+ using namespace ::com::sun::star::util;
+ using namespace ::com::sun::star::ucb;
+ using namespace ::com::sun::star::sdbc;
+ using namespace ::com::sun::star::sdb::application;
+ using namespace ::com::sun::star::task;
+ using namespace ::svt;
+
+ namespace
+ {
+ Sequence< sal_Int8 > lcl_GetSequenceClassID( sal_uInt32 n1, sal_uInt16 n2, sal_uInt16 n3,
+ sal_uInt8 b8, sal_uInt8 b9, sal_uInt8 b10, sal_uInt8 b11,
+ sal_uInt8 b12, sal_uInt8 b13, sal_uInt8 b14, sal_uInt8 b15 )
+ {
+ Sequence< sal_Int8 > aResult{ /* [ 0] */ static_cast<sal_Int8>(n1 >> 24),
+ /* [ 1] */ static_cast<sal_Int8>(( n1 << 8 ) >> 24),
+ /* [ 2] */ static_cast<sal_Int8>(( n1 << 16 ) >> 24),
+ /* [ 3] */ static_cast<sal_Int8>(( n1 << 24 ) >> 24),
+ /* [ 4] */ static_cast<sal_Int8>(n2 >> 8),
+ /* [ 5] */ static_cast<sal_Int8>(( n2 << 8 ) >> 8),
+ /* [ 6] */ static_cast<sal_Int8>(n3 >> 8),
+ /* [ 7] */ static_cast<sal_Int8>(( n3 << 8 ) >> 8),
+ /* [ 8] */ static_cast<sal_Int8>(b8),
+ /* [ 9] */ static_cast<sal_Int8>(b9),
+ /* [10] */ static_cast<sal_Int8>(b10),
+ /* [11] */ static_cast<sal_Int8>(b11),
+ /* [12] */ static_cast<sal_Int8>(b12),
+ /* [13] */ static_cast<sal_Int8>(b13),
+ /* [14] */ static_cast<sal_Int8>(b14),
+ /* [15] */ static_cast<sal_Int8>(b15) };
+ return aResult;
+ }
+ }
+
+ // OLinkedDocumentsAccess
+ OLinkedDocumentsAccess::OLinkedDocumentsAccess( weld::Window* pDialogParent, const Reference< XDatabaseDocumentUI >& i_rDocumentUI,
+ const Reference< XComponentContext >& _rxContext, const Reference< XNameAccess >& _rxContainer,
+ const Reference< XConnection>& _xConnection, const OUString& _sDataSourceName )
+ :m_xContext(_rxContext)
+ ,m_xDocumentContainer(_rxContainer)
+ ,m_xConnection(_xConnection)
+ ,m_xDocumentUI( i_rDocumentUI )
+ ,m_pDialogParent(pDialogParent)
+ ,m_sDataSourceName(_sDataSourceName)
+ {
+ OSL_ENSURE(m_xContext.is(), "OLinkedDocumentsAccess::OLinkedDocumentsAccess: invalid service factory!");
+ assert(m_pDialogParent && "OLinkedDocumentsAccess::OLinkedDocumentsAccess: really need a dialog parent!");
+ }
+ OLinkedDocumentsAccess::~OLinkedDocumentsAccess()
+ {
+ }
+ Reference< XComponent> OLinkedDocumentsAccess::impl_open( const OUString& _rLinkName, Reference< XComponent >& _xDefinition,
+ ElementOpenMode _eOpenMode, const ::comphelper::NamedValueCollection& _rAdditionalArgs )
+ {
+ Reference< XComponent> xRet;
+ OSL_ENSURE(m_xDocumentContainer.is(), "OLinkedDocumentsAccess::OLinkedDocumentsAccess: invalid document container!");
+ Reference< XComponentLoader > xComponentLoader(m_xDocumentContainer,UNO_QUERY);
+ if ( !xComponentLoader.is() )
+ return xRet;
+
+ weld::WaitObject aWaitCursor(m_pDialogParent);
+
+ ::comphelper::NamedValueCollection aArguments;
+ OUString sOpenMode;
+ switch ( _eOpenMode )
+ {
+ case E_OPEN_NORMAL:
+ sOpenMode = "open";
+ break;
+
+ case E_OPEN_FOR_MAIL:
+ aArguments.put( "Hidden", true );
+ [[fallthrough]];
+
+ case E_OPEN_DESIGN:
+ sOpenMode = "openDesign";
+ break;
+
+ default:
+ OSL_FAIL( "OLinkedDocumentsAccess::implOpen: invalid open mode!" );
+ break;
+ }
+ aArguments.put( "OpenMode", sOpenMode );
+
+ aArguments.put( PROPERTY_ACTIVE_CONNECTION, m_xConnection );
+
+ Reference<XHierarchicalNameContainer> xHier(m_xDocumentContainer,UNO_QUERY);
+ if ( xHier.is() && xHier->hasByHierarchicalName(_rLinkName) )
+ {
+ _xDefinition.set(xHier->getByHierarchicalName(_rLinkName),UNO_QUERY);
+ }
+
+ aArguments.merge( _rAdditionalArgs, true );
+
+ xRet = xComponentLoader->loadComponentFromURL( _rLinkName, OUString(), 0, aArguments.getPropertyValues() );
+
+ return xRet;
+ }
+ void OLinkedDocumentsAccess::impl_newWithPilot( const char* _pWizardService,
+ const sal_Int32 _nCommandType, const OUString& _rObjectName )
+ {
+ try
+ {
+ ::comphelper::NamedValueCollection aArgs;
+ aArgs.put( "DataSourceName", m_sDataSourceName );
+
+ if ( m_xConnection.is() )
+ aArgs.put( "ActiveConnection", m_xConnection );
+
+ if ( !_rObjectName.isEmpty() && ( _nCommandType != -1 ) )
+ {
+ aArgs.put( "CommandType", _nCommandType );
+ aArgs.put( "Command", _rObjectName );
+ }
+
+ aArgs.put( "DocumentUI", m_xDocumentUI );
+
+ Reference< XJobExecutor > xWizard;
+ {
+ weld::WaitObject aWaitCursor(m_pDialogParent);
+ xWizard.set( m_xContext->getServiceManager()->createInstanceWithArgumentsAndContext(
+ OUString::createFromAscii( _pWizardService ),
+ aArgs.getWrappedPropertyValues(),
+ m_xContext
+ ), UNO_QUERY_THROW );
+ }
+
+ xWizard->trigger( "start" );
+ ::comphelper::disposeComponent( xWizard );
+ }
+ catch(const Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+ void OLinkedDocumentsAccess::newFormWithPilot( const sal_Int32 _nCommandType,const OUString& _rObjectName )
+ {
+ impl_newWithPilot( "com.sun.star.wizards.form.CallFormWizard", _nCommandType, _rObjectName );
+ }
+
+ void OLinkedDocumentsAccess::newReportWithPilot( const sal_Int32 _nCommandType, const OUString& _rObjectName )
+ {
+ impl_newWithPilot( "com.sun.star.wizards.report.CallReportWizard", _nCommandType, _rObjectName );
+ }
+ void OLinkedDocumentsAccess::newTableWithPilot()
+ {
+ impl_newWithPilot( "com.sun.star.wizards.table.CallTableWizard", -1, OUString() );
+ }
+ void OLinkedDocumentsAccess::newQueryWithPilot()
+ {
+ impl_newWithPilot( "com.sun.star.wizards.query.CallQueryWizard", -1, OUString() );
+ }
+ Reference< XComponent > OLinkedDocumentsAccess::newDocument( sal_Int32 i_nActionID,
+ const ::comphelper::NamedValueCollection& i_rCreationArgs, Reference< XComponent >& o_rDefinition )
+ {
+ OSL_ENSURE(m_xDocumentContainer.is(), "OLinkedDocumentsAccess::newDocument: invalid document container!");
+ // determine the class ID to use for the new document
+ Sequence<sal_Int8> aClassId;
+ if ( !i_rCreationArgs.has( "ClassID" )
+ && !i_rCreationArgs.has( "MediaType" )
+ && !i_rCreationArgs.has( "DocumentServiceName" )
+ )
+ {
+ switch ( i_nActionID )
+ {
+ case ID_FORM_NEW_TEXT:
+ aClassId = lcl_GetSequenceClassID(SO3_SW_CLASSID);
+ OSL_ENSURE(aClassId == comphelper::MimeConfigurationHelper::GetSequenceClassID(SO3_SW_CLASSID),"Not equal");
+ break;
+
+ case ID_FORM_NEW_CALC:
+ aClassId = lcl_GetSequenceClassID(SO3_SC_CLASSID);
+ break;
+
+ case ID_FORM_NEW_IMPRESS:
+ aClassId = lcl_GetSequenceClassID(SO3_SIMPRESS_CLASSID);
+ break;
+
+ case ID_REPORT_NEW_TEXT:
+ aClassId = comphelper::MimeConfigurationHelper::GetSequenceClassID(SO3_RPT_CLASSID_90);
+ break;
+
+ default:
+ OSL_FAIL( "OLinkedDocumentsAccess::newDocument: please use newFormWithPilot!" );
+ return Reference< XComponent >();
+
+ }
+ }
+
+ // load the document as template
+ Reference< XComponent > xNewDocument;
+ try
+ { // get the desktop object
+
+ Reference<XMultiServiceFactory> xORB(m_xDocumentContainer,UNO_QUERY);
+ if ( xORB.is() )
+ {
+ ::comphelper::NamedValueCollection aCreationArgs( i_rCreationArgs );
+ if ( aClassId.hasElements() )
+ aCreationArgs.put( "ClassID", aClassId );
+ aCreationArgs.put( PROPERTY_ACTIVE_CONNECTION, m_xConnection );
+
+ // separate values which are real creation args from args relevant for opening the doc
+ ::comphelper::NamedValueCollection aCommandArgs;
+ if ( aCreationArgs.has( "Hidden" ) )
+ {
+ aCommandArgs.put( "Hidden", aCreationArgs.get( "Hidden" ) );
+ aCreationArgs.remove( "Hidden" );
+ }
+
+ Reference< XCommandProcessor > xContent( xORB->createInstanceWithArguments(
+ SERVICE_SDB_DOCUMENTDEFINITION,
+ aCreationArgs.getWrappedPropertyValues()
+ ),
+ UNO_QUERY_THROW
+ );
+ o_rDefinition.set( xContent, UNO_QUERY );
+
+ // put the OpenMode into the OpenArgs
+ OpenCommandArgument aOpenModeArg;
+ aOpenModeArg.Mode = OpenMode::DOCUMENT;
+ aCommandArgs.put( "OpenMode", aOpenModeArg );
+
+ Command aCommand;
+ aCommand.Name = "openDesign";
+ aCommand.Argument <<= aCommandArgs.getPropertyValues();
+ weld::WaitObject aWaitCursor(m_pDialogParent);
+ xNewDocument.set( xContent->execute( aCommand, xContent->createCommandIdentifier(), nullptr ), UNO_QUERY );
+ }
+ }
+ catch(const Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+
+ return xNewDocument;
+ }
+
+ Reference< XComponent > OLinkedDocumentsAccess::open( const OUString& _rLinkName, Reference< XComponent >& _xDefinition,
+ ElementOpenMode _eOpenMode, const ::comphelper::NamedValueCollection& _rAdditionalArgs )
+ {
+ dbtools::SQLExceptionInfo aInfo;
+ Reference< XComponent > xRet;
+ try
+ {
+ xRet = impl_open( _rLinkName, _xDefinition, _eOpenMode, _rAdditionalArgs );
+ if ( !xRet.is() )
+ {
+ OUString sMessage = DBA_RES(STR_COULDNOTOPEN_LINKEDDOC);
+ sMessage = sMessage.replaceFirst("$file$",_rLinkName);
+
+ css::sdbc::SQLException aSQLException;
+ aSQLException.Message = sMessage;
+ aInfo = dbtools::SQLExceptionInfo(aSQLException);
+ }
+ }
+ catch(const css::io::WrongFormatException &e)
+ {
+ css::sdbc::SQLException aSQLException;
+ aSQLException.Message = e.Message;
+ aSQLException.Context = e.Context;
+ aInfo = dbtools::SQLExceptionInfo(aSQLException);
+
+ // more like a hack, insert an empty message
+ OUString sText( DBA_RES( RID_STR_EXTENSION_NOT_PRESENT ) );
+ sText = sText.replaceFirst("$file$",_rLinkName);
+ aInfo.prepend(sText);
+
+ OUString sMessage = DBA_RES(STR_COULDNOTOPEN_LINKEDDOC);
+ sMessage = sMessage.replaceFirst("$file$",_rLinkName);
+ aInfo.prepend(sMessage);
+ }
+ catch(const Exception& e)
+ {
+ Any aAny = ::cppu::getCaughtException();
+ css::sdbc::SQLException a;
+ if ( !(aAny >>= a) || (a.ErrorCode != dbtools::ParameterInteractionCancelled) )
+ {
+ css::sdbc::SQLException aSQLException;
+ aSQLException.Message = e.Message;
+ aSQLException.Context = e.Context;
+ aInfo = dbtools::SQLExceptionInfo(aSQLException);
+
+ // more like a hack, insert an empty message
+ aInfo.prepend(" \n");
+
+ OUString sMessage = DBA_RES(STR_COULDNOTOPEN_LINKEDDOC);
+ sMessage = sMessage.replaceFirst("$file$",_rLinkName);
+ aInfo.prepend(sMessage);
+ }
+ }
+ if (aInfo.isValid())
+ {
+ showError(aInfo, m_pDialogParent->GetXWindow(), m_xContext);
+ }
+ return xRet;
+ }
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/misc/propertystorage.cxx b/dbaccess/source/ui/misc/propertystorage.cxx
new file mode 100644
index 000000000..c3c504994
--- /dev/null
+++ b/dbaccess/source/ui/misc/propertystorage.cxx
@@ -0,0 +1,106 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <propertystorage.hxx>
+
+#include <svl/itemset.hxx>
+#include <svl/stritem.hxx>
+#include <svl/eitem.hxx>
+
+#include <osl/diagnose.h>
+
+#include <cassert>
+#include <memory>
+
+namespace dbaui
+{
+
+ using ::com::sun::star::uno::Any;
+
+ // helper
+ namespace
+ {
+ template < class ITEMTYPE, class UNOTYPE >
+ class ItemAdapter
+ {
+ public:
+ static bool trySet( SfxItemSet& _rSet, sal_uInt16 _nItemId, const Any& _rValue )
+ {
+ const SfxPoolItem& rItem( _rSet.Get( _nItemId ) );
+ const ITEMTYPE* pTypedItem = dynamic_cast< const ITEMTYPE* >( &rItem );
+ if ( !pTypedItem )
+ return false;
+
+ UNOTYPE aValue( pTypedItem->GetValue() );
+ OSL_VERIFY( _rValue >>= aValue );
+ // TODO: one could throw an IllegalArgumentException here - finally, this method
+ // is (to be) used from within an XPropertySet::setPropertyValue implementation,
+ // where this would be the appropriate reaction on wrong value types
+ ITEMTYPE* pCloneItem = dynamic_cast< ITEMTYPE* >( pTypedItem->Clone() );
+ if(!pCloneItem)
+ {
+ return false;
+ }
+ std::unique_ptr< ITEMTYPE > pClone( pCloneItem);
+ assert(pClone.get());
+ pClone->SetValue( aValue );
+ _rSet.Put( std::move(pClone) );
+ return true;
+ }
+
+ static bool tryGet( const SfxPoolItem& _rItem, Any& _out_rValue )
+ {
+ const ITEMTYPE* pTypedItem = dynamic_cast< const ITEMTYPE* >( &_rItem );
+ if ( !pTypedItem )
+ return false;
+
+ _out_rValue <<= UNOTYPE( pTypedItem->GetValue() );
+ return true;
+ }
+ };
+ }
+
+ // SetItemPropertyStorage
+ void SetItemPropertyStorage::getPropertyValue( Any& _out_rValue ) const
+ {
+ const SfxPoolItem& rItem( m_rItemSet.Get( m_nItemID ) );
+
+ // try some known item types
+ if ( ItemAdapter< SfxBoolItem, bool >::tryGet( rItem, _out_rValue )
+ || ItemAdapter< SfxStringItem, OUString >::tryGet( rItem, _out_rValue )
+ )
+ return;
+
+ OSL_FAIL( "SetItemPropertyStorage::getPropertyValue: unsupported item type!" );
+ }
+
+ void SetItemPropertyStorage::setPropertyValue( const Any& _rValue )
+ {
+ // try some known item types
+ if ( ItemAdapter< SfxBoolItem, bool >::trySet( m_rItemSet, m_nItemID, _rValue )
+ || ItemAdapter< SfxStringItem, OUString >::trySet( m_rItemSet, m_nItemID, _rValue )
+ )
+ return;
+
+ OSL_FAIL( "SetItemPropertyStorage::setPropertyValue: unsupported item type!" );
+ }
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/misc/singledoccontroller.cxx b/dbaccess/source/ui/misc/singledoccontroller.cxx
new file mode 100644
index 000000000..28b0c9e77
--- /dev/null
+++ b/dbaccess/source/ui/misc/singledoccontroller.cxx
@@ -0,0 +1,184 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <dbaccess/dbaundomanager.hxx>
+#include <dbaccess/dataview.hxx>
+#include <core_resource.hxx>
+#include <singledoccontroller.hxx>
+#include <browserids.hxx>
+#include <strings.hrc>
+
+#include <svl/undo.hxx>
+
+namespace dbaui
+{
+
+ using ::com::sun::star::uno::Reference;
+ using ::com::sun::star::uno::Sequence;
+ using ::com::sun::star::uno::XComponentContext;
+ using ::com::sun::star::document::XUndoManager;
+ using ::com::sun::star::beans::PropertyValue;
+
+ // OSingleDocumentController_Data
+ struct OSingleDocumentController_Data
+ {
+ // no Reference! see UndoManager::acquire
+ std::unique_ptr<UndoManager> m_pUndoManager;
+
+ OSingleDocumentController_Data( ::cppu::OWeakObject& i_parent, ::osl::Mutex& i_mutex )
+ : m_pUndoManager(new UndoManager(i_parent, i_mutex))
+ {
+ }
+ };
+
+ // OSingleDocumentController
+ OSingleDocumentController::OSingleDocumentController( const Reference< XComponentContext >& _rxORB )
+ :OSingleDocumentController_Base( _rxORB )
+ ,m_pData( new OSingleDocumentController_Data( *this, getMutex() ) )
+ {
+ }
+
+ OSingleDocumentController::~OSingleDocumentController()
+ {
+ }
+
+ void SAL_CALL OSingleDocumentController::disposing()
+ {
+ OSingleDocumentController_Base::disposing();
+ ClearUndoManager();
+ m_pData->m_pUndoManager->disposing();
+ }
+
+ void OSingleDocumentController::ClearUndoManager()
+ {
+ GetUndoManager().Clear();
+ }
+
+ SfxUndoManager& OSingleDocumentController::GetUndoManager() const
+ {
+ return m_pData->m_pUndoManager->GetSfxUndoManager();
+ }
+
+ void OSingleDocumentController::addUndoActionAndInvalidate(std::unique_ptr<SfxUndoAction> _pAction)
+ {
+ // add undo action
+ GetUndoManager().AddUndoAction( std::move(_pAction) );
+
+ // when we add an undo action the controller was modified
+ setModified( true );
+
+ // now inform me that or states changed
+ InvalidateFeature( ID_BROWSER_UNDO );
+ InvalidateFeature( ID_BROWSER_REDO );
+ }
+
+ Reference< XUndoManager > SAL_CALL OSingleDocumentController::getUndoManager( )
+ {
+ // see UndoManager::acquire
+ return m_pData->m_pUndoManager.get();
+ }
+
+ FeatureState OSingleDocumentController::GetState(sal_uInt16 _nId) const
+ {
+ FeatureState aReturn;
+ switch ( _nId )
+ {
+ case ID_BROWSER_UNDO:
+ aReturn.bEnabled = isEditable() && GetUndoManager().GetUndoActionCount() != 0;
+ if ( aReturn.bEnabled )
+ {
+ OUString sUndo = DBA_RES(STR_UNDO_COLON) + " " +
+ GetUndoManager().GetUndoActionComment();
+ aReturn.sTitle = sUndo;
+ }
+ break;
+
+ case ID_BROWSER_REDO:
+ aReturn.bEnabled = isEditable() && GetUndoManager().GetRedoActionCount() != 0;
+ if ( aReturn.bEnabled )
+ {
+ OUString sRedo = DBA_RES(STR_REDO_COLON) + " " +
+ GetUndoManager().GetRedoActionComment();
+ aReturn.sTitle = sRedo;
+ }
+ break;
+
+ case SID_GETUNDOSTRINGS:
+ {
+ size_t nCount(GetUndoManager().GetUndoActionCount());
+ Sequence<OUString> aSeq(nCount);
+ auto aSeqRange = asNonConstRange(aSeq);
+ for (size_t n = 0; n < nCount; ++n)
+ aSeqRange[n] = GetUndoManager().GetUndoActionComment(n);
+ aReturn.aValue <<= aSeq;
+ aReturn.bEnabled = true;
+ break;
+ }
+
+ case SID_GETREDOSTRINGS:
+ {
+ size_t nCount(GetUndoManager().GetRedoActionCount());
+ Sequence<OUString> aSeq(nCount);
+ auto aSeqRange = asNonConstRange(aSeq);
+ for (size_t n = 0; n < nCount; ++n)
+ aSeqRange[n] = GetUndoManager().GetRedoActionComment(n);
+ aReturn.aValue <<= aSeq;
+ aReturn.bEnabled = true;
+ break;
+ }
+
+ default:
+ aReturn = OSingleDocumentController_Base::GetState(_nId);
+ }
+ return aReturn;
+ }
+ void OSingleDocumentController::Execute( sal_uInt16 _nId, const Sequence< PropertyValue >& _rArgs )
+ {
+ switch ( _nId )
+ {
+ case ID_BROWSER_UNDO:
+ case ID_BROWSER_REDO:
+ {
+ sal_Int16 nCount(1);
+ if (_rArgs.hasElements() && _rArgs[0].Name != "KeyModifier")
+ _rArgs[0].Value >>= nCount;
+
+ while (nCount--)
+ {
+ if (_nId == ID_BROWSER_UNDO)
+ GetUndoManager().Undo();
+ else
+ GetUndoManager().Redo();
+ }
+
+ InvalidateFeature( ID_BROWSER_UNDO );
+ InvalidateFeature( ID_BROWSER_REDO );
+ break;
+ }
+
+ default:
+ OSingleDocumentController_Base::Execute( _nId, _rArgs );
+ break;
+ }
+ InvalidateFeature(_nId);
+ }
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/misc/stringlistitem.cxx b/dbaccess/source/ui/misc/stringlistitem.cxx
new file mode 100644
index 000000000..97e75fe6d
--- /dev/null
+++ b/dbaccess/source/ui/misc/stringlistitem.cxx
@@ -0,0 +1,62 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <stringlistitem.hxx>
+
+namespace dbaui
+{
+using namespace ::com::sun::star::uno;
+
+// OStringListItem
+OStringListItem::OStringListItem(sal_Int16 _nWhich, const Sequence<OUString>& _rList)
+ : SfxPoolItem(_nWhich)
+ , m_aList(_rList)
+{
+}
+
+OStringListItem::OStringListItem(const OStringListItem& _rSource)
+ : SfxPoolItem(_rSource)
+ , m_aList(_rSource.m_aList)
+{
+}
+
+bool OStringListItem::operator==(const SfxPoolItem& _rItem) const
+{
+ if (!SfxPoolItem::operator==(_rItem))
+ return false;
+ const OStringListItem* pCompare = static_cast<const OStringListItem*>(&_rItem);
+ if (pCompare->m_aList.getLength() != m_aList.getLength())
+ return false;
+
+ // compare all strings individually
+ for (sal_Int32 i = 0; i < m_aList.getLength(); ++i)
+ if (m_aList[i] != pCompare->m_aList[i])
+ return false;
+
+ return true;
+}
+
+OStringListItem* OStringListItem::Clone(SfxItemPool* /* _pPool */) const
+{
+ return new OStringListItem(*this);
+}
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/querydesign/ConnectionLine.cxx b/dbaccess/source/ui/querydesign/ConnectionLine.cxx
new file mode 100644
index 000000000..77a67004e
--- /dev/null
+++ b/dbaccess/source/ui/querydesign/ConnectionLine.cxx
@@ -0,0 +1,356 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <ConnectionLine.hxx>
+#include <ConnectionLineData.hxx>
+#include <TableWindow.hxx>
+#include <TableWindowListBox.hxx>
+#include <TableConnection.hxx>
+#include <vcl/svapp.hxx>
+#include <math.h>
+#include <osl/diagnose.h>
+#include <vcl/lineinfo.hxx>
+#include <vcl/settings.hxx>
+
+using namespace dbaui;
+const tools::Long DESCRIPT_LINE_WIDTH = 15;
+const tools::Long HIT_SENSITIVE_RADIUS = 5;
+
+namespace
+{
+ /** calcRect creates a new rectangle with the given points
+ @param _rBase the base point
+ @param _aVector the vector which will be added
+ */
+ tools::Rectangle calcRect(const Point& _rBase,const Point& _aVector)
+ {
+ return tools::Rectangle( _rBase - _aVector, _rBase + _aVector );
+ }
+ /** GetTextPos calculate the rectangle for the connection to be drawn
+ @param _pWin the table window where to draw it
+ @param _aConnPos the connection point
+ @param _aDescrLinePos the description line pos
+ */
+ tools::Rectangle GetTextPos(const OTableWindow* _pWin, const Point& _aConnPos,const Point& _aDescrLinePos)
+ {
+ VclPtr<OTableWindowListBox> pListBox = _pWin ? _pWin->GetListBox() : nullptr;
+ OSL_ENSURE(_pWin && pListBox, "OConnectionLine::GetSourceTextPos : invalid call !");
+
+ tools::Rectangle aReturn;
+ if ( pListBox )
+ {
+ const tools::Long nRowHeight = pListBox->get_widget().get_height_rows(1);
+ aReturn.SetTop( _aConnPos.Y() - nRowHeight );
+ aReturn.SetBottom( aReturn.Top() + nRowHeight );
+ if (_aDescrLinePos.X() < _aConnPos.X())
+ {
+ aReturn.SetLeft( _aDescrLinePos.X() );
+ aReturn.SetRight( aReturn.Left() + _aConnPos.X() - _aDescrLinePos.X() );
+ }
+ else
+ {
+ aReturn.SetLeft( _aConnPos.X() );
+ aReturn.SetRight( aReturn.Left() + _aDescrLinePos.X() - _aConnPos.X() );
+ }
+ }
+
+ return aReturn;
+ }
+ /** calcPointsYValue calculate the points Y value in relation to the listbox entry
+ @param _pWin the corresponding window
+ @param _nEntry the source or dest entry
+ @param _rNewConPos (in/out) the connection pos
+ @param _rNewDescrPos (in/out) the description pos
+ */
+ void calcPointsYValue(const OTableWindow* _pWin, int _nEntry, Point& _rNewConPos, Point& _rNewDescrPos)
+ {
+ const OTableWindowListBox* pListBox = _pWin->GetListBox();
+ _rNewConPos.setY( _pWin->GetPosPixel().Y() );
+
+ std::unique_ptr<weld::TreeIter> xEntry;
+ const weld::TreeView& rTreeView = pListBox->get_widget();
+
+ if (_nEntry != -1)
+ {
+ _rNewConPos.AdjustY(pListBox->GetPosPixel().Y() );
+ xEntry = rTreeView.make_iterator();
+ if (!rTreeView.get_iter_first(*xEntry) || !rTreeView.iter_nth_sibling(*xEntry, _nEntry))
+ xEntry.reset();
+ }
+
+ if (xEntry)
+ {
+ auto nEntryPos = rTreeView.get_row_area(*xEntry).Center().Y();
+
+ if( nEntryPos >= 0 )
+ {
+ _rNewConPos.AdjustY(nEntryPos);
+ }
+ else
+ {
+ const auto nRowHeight = rTreeView.get_height_rows(1);
+ _rNewConPos.AdjustY( -static_cast<tools::Long>( 0.5 * nRowHeight ) );
+ }
+
+ tools::Long nListBoxBottom = _pWin->GetPosPixel().Y()
+ + pListBox->GetPosPixel().Y()
+ + pListBox->GetSizePixel().Height();
+ if( _rNewConPos.Y() > nListBoxBottom )
+ _rNewConPos.setY( nListBoxBottom + 2 );
+ }
+ else
+ _rNewConPos.AdjustY(static_cast<sal_Int32>(pListBox->GetPosPixel().Y()*0.5) );
+
+ _rNewDescrPos.setY( _rNewConPos.Y() );
+ }
+}
+
+OConnectionLine::OConnectionLine( OTableConnection* _pConn, OConnectionLineDataRef const & _pLineData )
+ : m_pTabConn( _pConn )
+ , m_pData( _pLineData )
+{
+}
+
+OConnectionLine::OConnectionLine( const OConnectionLine& _rLine )
+ : m_pTabConn(nullptr)
+{
+ m_pData = new OConnectionLineData( *_rLine.GetData() );
+ *this = _rLine;
+}
+
+OConnectionLine::~OConnectionLine()
+{
+}
+
+OConnectionLine& OConnectionLine::operator=( const OConnectionLine& rLine )
+{
+ if( &rLine != this )
+ {
+ // as the data does not belong to me, I don't delete the old one
+ m_pData->CopyFrom(*rLine.GetData());
+ // CopyFrom is virtual, therefore it is not a problem, if m_pData is of a type derived from OTableConnectionData
+
+ m_pTabConn = rLine.m_pTabConn;
+ m_aSourceConnPos = rLine.m_aSourceConnPos;
+ m_aDestConnPos = rLine.m_aDestConnPos;
+ m_aSourceDescrLinePos = rLine.m_aSourceDescrLinePos;
+ m_aDestDescrLinePos = rLine.m_aDestDescrLinePos;
+ }
+
+ return *this;
+}
+
+tools::Rectangle OConnectionLine::GetBoundingRect() const
+{
+ // determine surrounding rectangle
+ tools::Rectangle aBoundingRect( Point(0,0), Point(0,0) );
+ if( !IsValid() )
+ return aBoundingRect;
+
+ Point aTopLeft;
+ Point aBottomRight;
+
+ if( m_aSourceDescrLinePos.Y() <= m_aDestDescrLinePos.Y() )
+ {
+ aTopLeft.setY( m_aSourceDescrLinePos.Y() );
+ aBottomRight.setY( m_aDestDescrLinePos.Y() );
+ }
+ else
+ {
+ aTopLeft.setY( m_aDestDescrLinePos.Y() );
+ aBottomRight.setY( m_aSourceDescrLinePos.Y() );
+ }
+
+ if( m_aSourceDescrLinePos.X() <= m_aDestDescrLinePos.X() )
+ {
+ aTopLeft.setX( m_aSourceDescrLinePos.X() );
+ aBottomRight.setX( m_aDestDescrLinePos.X() );
+ }
+ else
+ {
+ aTopLeft.setX( m_aDestDescrLinePos.X() );
+ aBottomRight.setX( m_aSourceDescrLinePos.X() );
+ }
+
+ const OTableWindow* pSourceWin = m_pTabConn->GetSourceWin();
+ const OTableWindow* pDestWin = m_pTabConn->GetDestWin();
+ // line proceeds in z-Form
+ if( pSourceWin == pDestWin || std::abs(m_aSourceConnPos.X() - m_aDestConnPos.X()) > std::abs(m_aSourceDescrLinePos.X() - m_aDestDescrLinePos.X()) )
+ {
+ aTopLeft.AdjustX( -DESCRIPT_LINE_WIDTH );
+ aBottomRight.AdjustX(DESCRIPT_LINE_WIDTH );
+ }
+
+ aBoundingRect = tools::Rectangle( aTopLeft-Point(2,17), aBottomRight+Point(2,2) );
+
+ return aBoundingRect;
+}
+
+static void calcPointX1(const OTableWindow* _pWin,Point& _rNewConPos,Point& _rNewDescrPos)
+{
+ _rNewConPos.setX( _pWin->GetPosPixel().X() + _pWin->GetSizePixel().Width() );
+ _rNewDescrPos.setX( _rNewConPos.X() );
+ _rNewConPos.AdjustX(DESCRIPT_LINE_WIDTH );
+}
+
+static void calcPointX2(const OTableWindow* _pWin,Point& _rNewConPos,Point& _rNewDescrPos)
+{
+ _rNewConPos.setX( _pWin->GetPosPixel().X() );
+ _rNewDescrPos.setX( _rNewConPos.X() );
+ _rNewConPos.AdjustX( -DESCRIPT_LINE_WIDTH );
+}
+
+bool OConnectionLine::RecalcLine()
+{
+ // Windows and entries must be set
+ const OTableWindow* pSourceWin = m_pTabConn->GetSourceWin();
+ const OTableWindow* pDestWin = m_pTabConn->GetDestWin();
+
+ if( !pSourceWin || !pDestWin )
+ return false;
+
+ int nSourceEntry = pSourceWin->GetListBox()->GetEntryFromText( GetData()->GetSourceFieldName() );
+ int nDestEntry = pDestWin->GetListBox()->GetEntryFromText( GetData()->GetDestFieldName() );
+
+ // determine X-coordinates
+ Point aSourceCenter( 0, 0 );
+ Point aDestCenter( 0, 0 );
+
+ aSourceCenter.setX( pSourceWin->GetPosPixel().X() + static_cast<tools::Long>( 0.5*pSourceWin->GetSizePixel().Width() ) );
+ aDestCenter.setX( pDestWin->GetPosPixel().X() + static_cast<tools::Long>( 0.5*pDestWin->GetSizePixel().Width() ) );
+
+ const OTableWindow* pFirstWin = pDestWin;
+ const OTableWindow* pSecondWin = pSourceWin;
+ Point* pFirstConPos = &m_aDestConnPos;
+ Point* pFirstDescrPos = &m_aDestDescrLinePos;
+ Point* pSecondConPos = &m_aSourceConnPos;
+ Point* pSecondDescrPos = &m_aSourceDescrLinePos;
+ if( aDestCenter.X() > aSourceCenter.X() )
+ {
+ pFirstWin = pSourceWin;
+ pSecondWin = pDestWin;
+ pFirstConPos = &m_aSourceConnPos;
+ pFirstDescrPos = &m_aSourceDescrLinePos;
+ pSecondConPos = &m_aDestConnPos;
+ pSecondDescrPos = &m_aDestDescrLinePos;
+ }
+
+ if (pFirstWin == pSecondWin && nSourceEntry != nDestEntry)
+ calcPointX2(pFirstWin,*pFirstConPos,*pFirstDescrPos);
+ else
+ calcPointX1(pFirstWin,*pFirstConPos,*pFirstDescrPos);
+ calcPointX2(pSecondWin,*pSecondConPos,*pSecondDescrPos);
+
+ // determine aSourceConnPosY
+ calcPointsYValue(pSourceWin, nSourceEntry, m_aSourceConnPos,m_aSourceDescrLinePos);
+
+ // determine aDestConnPosY
+ calcPointsYValue(pDestWin, nDestEntry, m_aDestConnPos,m_aDestDescrLinePos);
+
+ return true;
+}
+
+void OConnectionLine::Draw( OutputDevice* pOutDev )
+{
+ const sal_uInt16 nRectSize = 3;
+
+ // calculate new dimension
+ if( !RecalcLine() )
+ return;
+
+ // draw lines
+ if (m_pTabConn->IsSelected())
+ pOutDev->SetLineColor(Application::GetSettings().GetStyleSettings().GetHighlightColor());
+ else
+ pOutDev->SetLineColor(Application::GetSettings().GetStyleSettings().GetWindowTextColor());
+
+ LineInfo aLineInfo;
+ if ( m_pTabConn->IsSelected() )
+ aLineInfo.SetWidth(3);
+ tools::Polygon aPoly;
+ aPoly.Insert(0,m_aSourceDescrLinePos);
+ aPoly.Insert(1,m_aSourceConnPos);
+ aPoly.Insert(2,m_aDestConnPos);
+ aPoly.Insert(3,m_aDestDescrLinePos);
+ pOutDev->DrawPolyLine(aPoly,aLineInfo);
+
+ // draw the connection rectangles
+ pOutDev->SetFillColor(Application::GetSettings().GetStyleSettings().GetWindowColor());
+
+ Point aVector(nRectSize,nRectSize);
+ pOutDev->DrawRect( calcRect(m_aSourceDescrLinePos,aVector) );
+ pOutDev->DrawRect( calcRect( m_aDestDescrLinePos,aVector) );
+}
+
+bool OConnectionLine::IsValid() const
+{
+ return m_pData.is();
+}
+
+static double dist_Euklid(const Point &p1, const Point& p2,const Point& pM, Point& q)
+{
+ Point v(p2 - p1);
+ Point w(pM - p1);
+ double a = std::hypot(v.X(), v.Y());
+ double l = (v.X() * w.Y() - v.Y() * w.X()) / a;
+ double a2 = w.X()*v.X()+w.Y()*v.Y();
+ a = a2 / (a * a);
+ q.setX( tools::Long(p1.X() + a * v.X()) );
+ q.setY( tools::Long(p1.Y() + a * v.Y()) );
+ return l;
+}
+
+bool OConnectionLine::CheckHit( const Point& rMousePos ) const
+{
+ /*
+ course of action with HitTest:
+ the distance is calculated according to Euklid.
+ */
+ Point q;
+ double l = fabs(dist_Euklid(m_aSourceConnPos,m_aDestConnPos,rMousePos,q));
+ if( l < HIT_SENSITIVE_RADIUS)
+ {
+ if(std::min(m_aSourceConnPos.X(),m_aDestConnPos.X()) <= q.X() && std::min(m_aSourceConnPos.Y(),m_aDestConnPos.Y()) <= q.Y()
+ && q.X() <= std::max(m_aDestConnPos.X(),m_aSourceConnPos.X()) && q.Y() <= std::max(m_aDestConnPos.Y(),m_aSourceConnPos.Y()))
+ return true;
+ }
+
+ return false;
+}
+
+tools::Rectangle OConnectionLine::GetSourceTextPos() const
+{
+ return GetTextPos(m_pTabConn->GetSourceWin(),m_aSourceConnPos,m_aSourceDescrLinePos);
+}
+
+tools::Rectangle OConnectionLine::GetDestTextPos() const
+{
+ return GetTextPos(m_pTabConn->GetDestWin(),m_aDestConnPos,m_aDestDescrLinePos);
+}
+
+Point OConnectionLine::getMidPoint() const
+{
+ Point aDest = m_aDestConnPos - m_aSourceConnPos;
+ aDest.setX( aDest.X() / 2 );
+ aDest.setY( aDest.Y() / 2 );
+
+ return m_aSourceConnPos + aDest;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/querydesign/ConnectionLineAccess.cxx b/dbaccess/source/ui/querydesign/ConnectionLineAccess.cxx
new file mode 100644
index 000000000..f11ca853c
--- /dev/null
+++ b/dbaccess/source/ui/querydesign/ConnectionLineAccess.cxx
@@ -0,0 +1,187 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <ConnectionLineAccess.hxx>
+#include <ConnectionLine.hxx>
+#include <JoinTableView.hxx>
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <com/sun/star/accessibility/AccessibleRelationType.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <TableConnection.hxx>
+#include <TableWindow.hxx>
+#include <comphelper/sequence.hxx>
+
+namespace dbaui
+{
+ using namespace ::com::sun::star::accessibility;
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::beans;
+ using namespace ::com::sun::star::lang;
+ using namespace ::com::sun::star;
+
+ OConnectionLineAccess::OConnectionLineAccess(OTableConnection* _pLine)
+ : VCLXAccessibleComponent(_pLine->GetComponentInterface().is() ? _pLine->GetWindowPeer() : nullptr)
+ ,m_pLine(_pLine)
+ {
+ }
+ void SAL_CALL OConnectionLineAccess::disposing()
+ {
+ m_pLine = nullptr;
+ VCLXAccessibleComponent::disposing();
+ }
+ Any SAL_CALL OConnectionLineAccess::queryInterface( const Type& aType )
+ {
+ Any aRet(VCLXAccessibleComponent::queryInterface( aType ));
+ return aRet.hasValue() ? aRet : OConnectionLineAccess_BASE::queryInterface( aType );
+ }
+ Sequence< Type > SAL_CALL OConnectionLineAccess::getTypes( )
+ {
+ return ::comphelper::concatSequences(VCLXAccessibleComponent::getTypes(),OConnectionLineAccess_BASE::getTypes());
+ }
+ OUString SAL_CALL OConnectionLineAccess::getImplementationName()
+ {
+ return "org.openoffice.comp.dbu.ConnectionLineAccessibility";
+ }
+ // XAccessibleContext
+ sal_Int32 SAL_CALL OConnectionLineAccess::getAccessibleChildCount( )
+ {
+ return 0;
+ }
+ Reference< XAccessible > SAL_CALL OConnectionLineAccess::getAccessibleChild( sal_Int32 /*i*/ )
+ {
+ return Reference< XAccessible >();
+ }
+ sal_Int32 SAL_CALL OConnectionLineAccess::getAccessibleIndexInParent( )
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+ sal_Int32 nIndex = -1;
+ if( m_pLine )
+ {
+ // search the position of our table window in the table window map
+ // TODO JNA Shouldn't nIndex begin at 0?
+ nIndex = m_pLine->GetParent()->GetTabWinMap().size();
+ const auto& rVec = m_pLine->GetParent()->getTableConnections();
+ bool bFound = false;
+ for (auto const& elem : rVec)
+ {
+ if (elem.get() == m_pLine)
+ {
+ bFound = true;
+ break;
+ }
+ ++nIndex;
+ }
+ nIndex = bFound ? nIndex : -1;
+ }
+ return nIndex;
+ }
+ sal_Int16 SAL_CALL OConnectionLineAccess::getAccessibleRole( )
+ {
+ return AccessibleRole::UNKNOWN; // ? or may be an AccessibleRole::WINDOW
+ }
+ OUString SAL_CALL OConnectionLineAccess::getAccessibleDescription( )
+ {
+ return "Relation";
+ }
+ Reference< XAccessibleRelationSet > SAL_CALL OConnectionLineAccess::getAccessibleRelationSet( )
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+ return this;
+ }
+ // XAccessibleComponent
+ Reference< XAccessible > SAL_CALL OConnectionLineAccess::getAccessibleAtPoint( const awt::Point& /*_aPoint*/ )
+ {
+ return Reference< XAccessible >();
+ }
+ awt::Rectangle SAL_CALL OConnectionLineAccess::getBounds( )
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+ tools::Rectangle aRect(m_pLine ? m_pLine->GetBoundingRect() : tools::Rectangle());
+ return awt::Rectangle(aRect.Left(),aRect.Top(),aRect.getWidth(),aRect.getHeight());
+ }
+ awt::Point SAL_CALL OConnectionLineAccess::getLocation( )
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+ Point aPoint(m_pLine ? m_pLine->GetBoundingRect().TopLeft() : Point());
+ return awt::Point(aPoint.X(),aPoint.Y());
+ }
+ awt::Point SAL_CALL OConnectionLineAccess::getLocationOnScreen( )
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+ Point aPoint(m_pLine ? m_pLine->GetParent()->ScreenToOutputPixel(m_pLine->GetBoundingRect().TopLeft()) : Point());
+ return awt::Point(aPoint.X(),aPoint.Y());
+ }
+ awt::Size SAL_CALL OConnectionLineAccess::getSize( )
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+ Size aSize(m_pLine ? m_pLine->GetBoundingRect().GetSize() : Size());
+ return awt::Size(aSize.Width(),aSize.Height());
+ }
+ // XAccessibleRelationSet
+ sal_Int32 SAL_CALL OConnectionLineAccess::getRelationCount( )
+ {
+ return 1;
+ }
+ AccessibleRelation SAL_CALL OConnectionLineAccess::getRelation( sal_Int32 nIndex )
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+ if( nIndex < 0 || nIndex >= getRelationCount() )
+ throw IndexOutOfBoundsException();
+
+ Sequence< Reference<XInterface> > aSeq;
+ if( m_pLine )
+ {
+ aSeq = { m_pLine->GetSourceWin()->GetAccessible(),
+ m_pLine->GetDestWin()->GetAccessible() };
+ }
+
+ return AccessibleRelation(AccessibleRelationType::CONTROLLED_BY,aSeq);
+ }
+ sal_Bool SAL_CALL OConnectionLineAccess::containsRelation( sal_Int16 aRelationType )
+ {
+ return AccessibleRelationType::CONTROLLED_BY == aRelationType;
+ }
+ AccessibleRelation SAL_CALL OConnectionLineAccess::getRelationByType( sal_Int16 aRelationType )
+ {
+ if( AccessibleRelationType::CONTROLLED_BY == aRelationType )
+ return getRelation(0);
+ return AccessibleRelation();
+ }
+ Reference< XAccessible > OTableConnection::CreateAccessible()
+ {
+ return new OConnectionLineAccess(this);
+ }
+ OTableConnection::~OTableConnection()
+ {
+ disposeOnce();
+ }
+ void OTableConnection::dispose()
+ {
+ // clear vector
+ clearLineData();
+ m_pParent.clear();
+ vcl::Window::dispose();
+ }
+ Reference< XAccessibleContext > SAL_CALL OConnectionLineAccess::getAccessibleContext( )
+ {
+ return this;
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/querydesign/ConnectionLineData.cxx b/dbaccess/source/ui/querydesign/ConnectionLineData.cxx
new file mode 100644
index 000000000..db7177294
--- /dev/null
+++ b/dbaccess/source/ui/querydesign/ConnectionLineData.cxx
@@ -0,0 +1,76 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <ConnectionLineData.hxx>
+
+using namespace dbaui;
+OConnectionLineData::OConnectionLineData()
+{
+}
+
+OConnectionLineData::OConnectionLineData( const OUString& rSourceFieldName, const OUString& rDestFieldName )
+ :m_aSourceFieldName( rSourceFieldName )
+ ,m_aDestFieldName( rDestFieldName )
+{
+}
+
+OConnectionLineData::OConnectionLineData( const OConnectionLineData& rConnLineData )
+ : ::salhelper::SimpleReferenceObject()
+{
+ *this = rConnLineData;
+}
+
+OConnectionLineData::~OConnectionLineData()
+{
+}
+
+void OConnectionLineData::CopyFrom(const OConnectionLineData& rSource)
+{
+ *this = rSource;
+ // Here I rely on the (non-virtual) operator=, which only copies my members
+}
+
+OConnectionLineData& OConnectionLineData::operator=( const OConnectionLineData& rConnLineData )
+{
+ if (&rConnLineData == this)
+ return *this;
+
+ m_aSourceFieldName = rConnLineData.GetSourceFieldName();
+ m_aDestFieldName = rConnLineData.GetDestFieldName();
+
+ return *this;
+}
+
+void OConnectionLineData::Reset()
+{
+ m_aDestFieldName.clear();
+ m_aSourceFieldName.clear();
+}
+
+namespace dbaui
+{
+bool operator==(const OConnectionLineData& lhs, const OConnectionLineData& rhs)
+{
+ return (lhs.m_aSourceFieldName == rhs.m_aSourceFieldName)
+ && (lhs.m_aDestFieldName == rhs.m_aDestFieldName);
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/querydesign/JAccess.cxx b/dbaccess/source/ui/querydesign/JAccess.cxx
new file mode 100644
index 000000000..8068f0fa7
--- /dev/null
+++ b/dbaccess/source/ui/querydesign/JAccess.cxx
@@ -0,0 +1,91 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <JAccess.hxx>
+#include <JoinTableView.hxx>
+#include <TableWindow.hxx>
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <TableConnection.hxx>
+#include <o3tl/safeint.hxx>
+
+namespace dbaui
+{
+ using namespace ::com::sun::star::accessibility;
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::beans;
+ using namespace ::com::sun::star::lang;
+
+ OJoinDesignViewAccess::OJoinDesignViewAccess(OJoinTableView* _pTableView)
+ :VCLXAccessibleComponent(_pTableView->GetComponentInterface().is() ? _pTableView->GetWindowPeer() : nullptr)
+ ,m_pTableView(_pTableView)
+ {
+ }
+ OUString SAL_CALL OJoinDesignViewAccess::getImplementationName()
+ {
+ return "org.openoffice.comp.dbu.JoinViewAccessibility";
+ }
+ void OJoinDesignViewAccess::clearTableView()
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+ m_pTableView = nullptr;
+ }
+ // XAccessibleContext
+ sal_Int32 SAL_CALL OJoinDesignViewAccess::getAccessibleChildCount( )
+ {
+ // TODO may be this will change to only visible windows
+ // this is the same assumption mt implements
+ ::osl::MutexGuard aGuard( m_aMutex );
+ sal_Int32 nChildCount = 0;
+ if ( m_pTableView )
+ nChildCount = m_pTableView->GetTabWinCount() + m_pTableView->getTableConnections().size();
+ return nChildCount;
+ }
+ Reference< XAccessible > SAL_CALL OJoinDesignViewAccess::getAccessibleChild( sal_Int32 i )
+ {
+ Reference< XAccessible > aRet;
+ ::osl::MutexGuard aGuard( m_aMutex );
+ if(i < 0 || i >= getAccessibleChildCount() || !m_pTableView)
+ throw IndexOutOfBoundsException();
+ // check if we should return a table window or a connection
+ sal_Int32 nTableWindowCount = m_pTableView->GetTabWinCount();
+ if( i < nTableWindowCount )
+ {
+ OJoinTableView::OTableWindowMap::const_iterator aIter = std::next(m_pTableView->GetTabWinMap().begin(), i);
+ aRet = aIter->second->GetAccessible();
+ }
+ else if( o3tl::make_unsigned(i - nTableWindowCount) < m_pTableView->getTableConnections().size() )
+ aRet = m_pTableView->getTableConnections()[i - nTableWindowCount]->GetAccessible();
+ return aRet;
+ }
+ sal_Int16 SAL_CALL OJoinDesignViewAccess::getAccessibleRole( )
+ {
+ return AccessibleRole::VIEW_PORT;
+ }
+ Reference< XAccessibleContext > SAL_CALL OJoinDesignViewAccess::getAccessibleContext( )
+ {
+ return this;
+ }
+ // XInterface
+ IMPLEMENT_FORWARD_XINTERFACE2( OJoinDesignViewAccess, VCLXAccessibleComponent, OJoinDesignViewAccess_BASE )
+ // XTypeProvider
+ IMPLEMENT_FORWARD_XTYPEPROVIDER2( OJoinDesignViewAccess, VCLXAccessibleComponent, OJoinDesignViewAccess_BASE )
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/querydesign/JoinController.cxx b/dbaccess/source/ui/querydesign/JoinController.cxx
new file mode 100644
index 000000000..0857e0448
--- /dev/null
+++ b/dbaccess/source/ui/querydesign/JoinController.cxx
@@ -0,0 +1,406 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <browserids.hxx>
+#include <com/sun/star/sdbc/XRow.hpp>
+#include <connectivity/dbexception.hxx>
+#include <com/sun/star/ui/dialogs/XExecutableDialog.hpp>
+#include <JoinController.hxx>
+#include <TableWindowData.hxx>
+#include <TableWindow.hxx>
+#include <TableConnectionData.hxx>
+#include <adtabdlg.hxx>
+#include <vcl/svapp.hxx>
+#include <osl/mutex.hxx>
+#include <osl/diagnose.h>
+
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::io;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::frame;
+using namespace ::com::sun::star::util;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::sdb;
+using namespace ::com::sun::star::ui::dialogs;
+using namespace ::dbtools;
+using namespace ::comphelper;
+
+namespace dbaui
+{
+
+// AddTableDialogContext
+class AddTableDialogContext : public IAddTableDialogContext
+{
+ OJoinController& m_rController;
+
+public:
+ explicit AddTableDialogContext( OJoinController& _rController )
+ :m_rController( _rController )
+ {
+ }
+
+ virtual ~AddTableDialogContext() {}
+
+ // IAddTableDialogContext
+ virtual css::uno::Reference< css::sdbc::XConnection >
+ getConnection() const override;
+ virtual bool allowViews() const override;
+ virtual bool allowQueries() const override;
+ virtual bool allowAddition() const override;
+ virtual void addTableWindow( const OUString& _rQualifiedTableName, const OUString& _rAliasName ) override;
+ virtual void onWindowClosing() override;
+
+private:
+ OJoinTableView* getTableView() const;
+};
+
+Reference< XConnection > AddTableDialogContext::getConnection() const
+{
+ return m_rController.getConnection();
+}
+
+bool AddTableDialogContext::allowViews() const
+{
+ return m_rController.allowViews();
+}
+
+bool AddTableDialogContext::allowQueries() const
+{
+ return m_rController.allowQueries();
+}
+
+bool AddTableDialogContext::allowAddition() const
+{
+ return m_rController.getJoinView()->getTableView()->IsAddAllowed();
+}
+
+void AddTableDialogContext::addTableWindow( const OUString& _rQualifiedTableName, const OUString& _rAliasName )
+{
+ getTableView()->AddTabWin( _rQualifiedTableName, _rAliasName, true );
+}
+
+void AddTableDialogContext::onWindowClosing()
+{
+ if (!m_rController.getView())
+ return;
+ m_rController.InvalidateFeature( ID_BROWSER_ADDTABLE );
+ m_rController.getView()->GrabFocus();
+}
+
+OJoinTableView* AddTableDialogContext::getTableView() const
+{
+ if ( m_rController.getJoinView() )
+ return m_rController.getJoinView()->getTableView();
+ return nullptr;
+}
+
+// OJoinController
+
+OJoinController::OJoinController(const Reference< XComponentContext >& _rM)
+ : OJoinController_BASE(_rM)
+{
+}
+
+OJoinController::~OJoinController()
+{
+}
+
+OJoinDesignView* OJoinController::getJoinView()
+{
+ return static_cast< OJoinDesignView* >( getView() );
+}
+
+void OJoinController::disposing()
+{
+ if (m_xAddTableDialog)
+ {
+ m_xAddTableDialog->response(RET_CLOSE);
+ m_xAddTableDialog.reset();
+ }
+
+ OJoinController_BASE::disposing();
+
+ clearView();
+
+ m_vTableConnectionData.clear();
+ m_vTableData.clear();
+}
+
+void OJoinController::reconnect( bool _bUI )
+{
+ OJoinController_BASE::reconnect( _bUI );
+ if ( isConnected() && m_xAddTableDialog )
+ m_xAddTableDialog->Update();
+}
+
+void OJoinController::impl_onModifyChanged()
+{
+ OJoinController_BASE::impl_onModifyChanged();
+ InvalidateFeature( SID_RELATION_ADD_RELATION );
+}
+
+void OJoinController::SaveTabWinPosSize(OTableWindow const * pTabWin, tools::Long nOffsetX, tools::Long nOffsetY)
+{
+ // the data for the window
+ const TTableWindowData::value_type& pData = pTabWin->GetData();
+ OSL_ENSURE(pData != nullptr, "SaveTabWinPosSize : TabWin has no data !");
+
+ // set Position & Size of data anew (with current window parameters)
+ Point aPos = pTabWin->GetPosPixel();
+ aPos.AdjustX(nOffsetX );
+ aPos.AdjustY(nOffsetY );
+ pData->SetPosition(aPos);
+ pData->SetSize(pTabWin->GetSizePixel());
+
+}
+
+FeatureState OJoinController::GetState(sal_uInt16 _nId) const
+{
+ FeatureState aReturn;
+ // (disabled automatically)
+ aReturn.bEnabled = true;
+
+ switch (_nId)
+ {
+ case ID_BROWSER_EDITDOC:
+ aReturn.bChecked = isEditable();
+ break;
+ case ID_BROWSER_ADDTABLE:
+ aReturn.bEnabled = ( getView() != nullptr )
+ && const_cast< OJoinController* >( this )->getJoinView()->getTableView()->IsAddAllowed();
+ aReturn.bChecked = aReturn.bEnabled && m_xAddTableDialog;
+ if ( aReturn.bEnabled )
+ aReturn.sTitle = OAddTableDlg::getDialogTitleForContext( impl_getDialogContext() );
+ break;
+
+ default:
+ aReturn = OJoinController_BASE::GetState(_nId);
+ }
+ return aReturn;
+}
+
+AddTableDialogContext& OJoinController::impl_getDialogContext() const
+{
+ if (!m_pDialogContext)
+ {
+ OJoinController* pNonConstThis = const_cast< OJoinController* >( this );
+ pNonConstThis->m_pDialogContext.reset( new AddTableDialogContext( *pNonConstThis ) );
+ }
+ assert(m_pDialogContext && "always exists at this point");
+ return *m_pDialogContext;
+}
+
+void OJoinController::Execute(sal_uInt16 _nId, const Sequence< PropertyValue >& aArgs)
+{
+ switch(_nId)
+ {
+ case ID_BROWSER_EDITDOC:
+ if(isEditable())
+ { // the state should be changed to not editable
+ switch (saveModified())
+ {
+ case RET_CANCEL:
+ // don't change anything here so return
+ return;
+ case RET_NO:
+ reset();
+ setModified(false); // and we are not modified yet
+ break;
+ default:
+ break;
+ }
+ }
+ setEditable(!isEditable());
+ getJoinView()->setReadOnly(!isEditable());
+ InvalidateAll();
+ return;
+ case ID_BROWSER_ADDTABLE:
+ if (m_xAddTableDialog)
+ {
+ m_xAddTableDialog->response(RET_CLOSE);
+ getView()->GrabFocus();
+ }
+ else
+ {
+ runDialogAsync();
+ }
+ break;
+ default:
+ OJoinController_BASE::Execute(_nId,aArgs);
+ }
+ InvalidateFeature(_nId);
+}
+
+void OJoinController::runDialogAsync()
+{
+ assert(!m_xAddTableDialog);
+ m_xAddTableDialog = std::make_shared<OAddTableDlg>(getFrameWeld(), impl_getDialogContext());
+ {
+ weld::WaitObject aWaitCursor(getFrameWeld());
+ m_xAddTableDialog->Update();
+ }
+ weld::DialogController::runAsync(m_xAddTableDialog, [this](sal_Int32 /*nResult*/){
+ m_xAddTableDialog->OnClose();
+ m_xAddTableDialog.reset();
+ });
+}
+
+void OJoinController::SaveTabWinsPosSize( OJoinTableView::OTableWindowMap* pTabWinList, tools::Long nOffsetX, tools::Long nOffsetY )
+{
+ // Deletion and recreation of the old implementation with the current model is not correct anymore:
+ // The TabWins have a pointer to their data, but they are managed by me. When I delete the old ones, the TabWins suddenly have a pointer to objects, which no longer exist.
+ // If the TabWins had a SetData, I could save that effort... but they don't, further I also would still have to set information anew, which actually didn't change.
+ // So I don't delete the TabWinDatas, but only update them.
+ OSL_ENSURE(m_vTableData.size() == pTabWinList->size(),
+ "OJoinController::SaveTabWinsPosSize : inconsistent state : should have as many TabWinDatas as TabWins !");
+
+ for (auto const& tabWin : *pTabWinList)
+ SaveTabWinPosSize(tabWin.second, nOffsetX, nOffsetY);
+}
+
+void OJoinController::removeConnectionData(const TTableConnectionData::value_type& _pData)
+{
+ m_vTableConnectionData.erase( std::remove(m_vTableConnectionData.begin(),m_vTableConnectionData.end(),_pData),m_vTableConnectionData.end());
+}
+
+void OJoinController::describeSupportedFeatures()
+{
+ OJoinController_BASE::describeSupportedFeatures();
+ implDescribeSupportedFeature( ".uno:Redo", ID_BROWSER_REDO, CommandGroup::EDIT );
+ implDescribeSupportedFeature( ".uno:Save", ID_BROWSER_SAVEDOC, CommandGroup::DOCUMENT );
+ implDescribeSupportedFeature( ".uno:Undo", ID_BROWSER_UNDO, CommandGroup::EDIT );
+ implDescribeSupportedFeature( ".uno:AddTable", ID_BROWSER_ADDTABLE,CommandGroup::EDIT );
+ implDescribeSupportedFeature( ".uno:EditDoc", ID_BROWSER_EDITDOC, CommandGroup::EDIT );
+ implDescribeSupportedFeature( ".uno:GetUndoStrings", SID_GETUNDOSTRINGS );
+ implDescribeSupportedFeature( ".uno:GetRedoStrings", SID_GETREDOSTRINGS );
+}
+
+sal_Bool SAL_CALL OJoinController::suspend(sal_Bool _bSuspend)
+{
+ if ( getBroadcastHelper().bInDispose || getBroadcastHelper().bDisposed )
+ return true;
+
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( getMutex() );
+ if ( getView() && getView()->IsInModalMode() )
+ return false;
+ bool bCheck = true;
+ if ( _bSuspend )
+ {
+ bCheck = saveModified() != RET_CANCEL;
+ if ( bCheck )
+ OSingleDocumentController::suspend(_bSuspend);
+ }
+ return bCheck;
+}
+
+void OJoinController::loadTableWindows( const ::comphelper::NamedValueCollection& i_rViewSettings )
+{
+ m_vTableData.clear();
+
+ m_aMinimumTableViewSize = Point();
+
+ Sequence< PropertyValue > aWindowData;
+ aWindowData = i_rViewSettings.getOrDefault( "Tables", aWindowData );
+
+ const PropertyValue* pTablesIter = aWindowData.getConstArray();
+ const PropertyValue* pTablesEnd = pTablesIter + aWindowData.getLength();
+ for ( ; pTablesIter != pTablesEnd; ++pTablesIter )
+ {
+ ::comphelper::NamedValueCollection aSingleTableData( pTablesIter->Value );
+ loadTableWindow( aSingleTableData );
+ }
+ if ( m_aMinimumTableViewSize != Point() )
+ {
+ getJoinView()->getScrollHelper()->resetRange( m_aMinimumTableViewSize );
+ }
+}
+
+void OJoinController::loadTableWindow( const ::comphelper::NamedValueCollection& i_rTableWindowSettings )
+{
+ sal_Int32 nX = -1, nY = -1, nHeight = -1, nWidth = -1;
+
+ OUString sComposedName,sTableName,sWindowName;
+ bool bShowAll = false;
+
+ sComposedName = i_rTableWindowSettings.getOrDefault( "ComposedName", sComposedName );
+ sTableName = i_rTableWindowSettings.getOrDefault( "TableName", sTableName );
+ sWindowName = i_rTableWindowSettings.getOrDefault( "WindowName", sWindowName );
+ nY = i_rTableWindowSettings.getOrDefault( "WindowTop", nY );
+ nX = i_rTableWindowSettings.getOrDefault( "WindowLeft", nX );
+ nWidth = i_rTableWindowSettings.getOrDefault( "WindowWidth", nWidth );
+ nHeight = i_rTableWindowSettings.getOrDefault( "WindowHeight", nHeight );
+ bShowAll = i_rTableWindowSettings.getOrDefault( "ShowAll", bShowAll );
+
+ TTableWindowData::value_type pData = createTableWindowData(sComposedName,sTableName,sWindowName);
+ if ( pData )
+ {
+ pData->SetPosition(Point(nX,nY));
+ pData->SetSize( Size( nWidth, nHeight ) );
+ pData->ShowAll(bShowAll);
+ m_vTableData.push_back(pData);
+ if ( m_aMinimumTableViewSize.X() < (nX+nWidth) )
+ m_aMinimumTableViewSize.setX( nX+nWidth );
+ if ( m_aMinimumTableViewSize.Y() < (nY+nHeight) )
+ m_aMinimumTableViewSize.setY( nY+nHeight );
+ }
+}
+
+void OJoinController::saveTableWindows( ::comphelper::NamedValueCollection& o_rViewSettings ) const
+{
+ if ( m_vTableData.empty() )
+ return;
+
+ ::comphelper::NamedValueCollection aAllTablesData;
+
+ sal_Int32 i = 1;
+ for (auto const& elem : m_vTableData)
+ {
+ ::comphelper::NamedValueCollection aWindowData;
+ aWindowData.put( "ComposedName", elem->GetComposedName() );
+ aWindowData.put( "TableName", elem->GetTableName() );
+ aWindowData.put( "WindowName", elem->GetWinName() );
+ aWindowData.put( "WindowTop", static_cast<sal_Int32>(elem->GetPosition().Y()) );
+ aWindowData.put( "WindowLeft", static_cast<sal_Int32>(elem->GetPosition().X()) );
+ aWindowData.put( "WindowWidth", static_cast<sal_Int32>(elem->GetSize().Width()) );
+ aWindowData.put( "WindowHeight", static_cast<sal_Int32>(elem->GetSize().Height()) );
+ aWindowData.put( "ShowAll", elem->IsShowAll() );
+
+ const OUString sTableName( "Table" + OUString::number( i++ ) );
+ aAllTablesData.put( sTableName, aWindowData.getPropertyValues() );
+ }
+
+ o_rViewSettings.put( "Tables", aAllTablesData.getPropertyValues() );
+}
+
+TTableWindowData::value_type OJoinController::createTableWindowData(const OUString& _sComposedName,const OUString& _sTableName,const OUString& _sWindowName)
+{
+ OJoinDesignView* pView = getJoinView();
+ if( pView )
+ return pView->getTableView()->createTableWindowData(_sComposedName,_sTableName,_sWindowName);
+ OSL_FAIL("We should never ever reach this point!");
+
+ return TTableWindowData::value_type();
+}
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/querydesign/JoinDesignView.cxx b/dbaccess/source/ui/querydesign/JoinDesignView.cxx
new file mode 100644
index 000000000..c0d3ea81c
--- /dev/null
+++ b/dbaccess/source/ui/querydesign/JoinDesignView.cxx
@@ -0,0 +1,100 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <JoinDesignView.hxx>
+#include <JoinTableView.hxx>
+#include <JoinController.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/settings.hxx>
+
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::util;
+
+namespace dbaui
+{
+
+// OJoinDesignView
+OJoinDesignView::OJoinDesignView(vcl::Window* _pParent, OJoinController& _rController,const Reference< XComponentContext >& _rxContext)
+ :ODataView( _pParent, _rController, _rxContext )
+ ,m_pTableView(nullptr)
+ ,m_rController( _rController )
+{
+ m_pScrollWindow = VclPtr<OScrollWindowHelper>::Create(this);
+}
+
+OJoinDesignView::~OJoinDesignView()
+{
+ disposeOnce();
+}
+
+void OJoinDesignView::dispose()
+{
+ m_pTableView.disposeAndClear();
+ m_pScrollWindow.disposeAndClear();
+ ODataView::dispose();
+}
+
+void OJoinDesignView::Construct()
+{
+ m_pScrollWindow->setTableView(m_pTableView);
+ m_pScrollWindow->Show();
+ m_pTableView->Show();
+
+ SetBackground( Wallpaper( Application::GetSettings().GetStyleSettings().GetFaceColor()) );
+
+ ODataView::Construct();
+}
+
+void OJoinDesignView::initialize()
+{
+}
+
+void OJoinDesignView::resizeDocumentView(tools::Rectangle& _rPlayground)
+{
+ m_pScrollWindow->SetPosSizePixel( _rPlayground.TopLeft(), _rPlayground.GetSize() );
+
+ // just for completeness: there is no space left, we occupied it all ...
+ _rPlayground.SetPos( _rPlayground.BottomRight() );
+ _rPlayground.SetSize( Size( 0, 0 ) );
+}
+
+void OJoinDesignView::setReadOnly(bool /*_bReadOnly*/)
+{
+}
+
+void OJoinDesignView::SaveTabWinUIConfig(OTableWindow const * pWin)
+{
+ OJoinController::SaveTabWinPosSize(pWin, m_pScrollWindow->GetHScrollBar().GetThumbPos(), m_pScrollWindow->GetVScrollBar().GetThumbPos());
+}
+
+void OJoinDesignView::KeyInput( const KeyEvent& rEvt )
+{
+ if ( m_pTableView && m_pTableView->IsVisible() )
+ m_pTableView->KeyInput( rEvt );
+ else
+ ODataView::KeyInput(rEvt);
+}
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/querydesign/JoinExchange.cxx b/dbaccess/source/ui/querydesign/JoinExchange.cxx
new file mode 100644
index 000000000..0dc88e2cc
--- /dev/null
+++ b/dbaccess/source/ui/querydesign/JoinExchange.cxx
@@ -0,0 +1,114 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <JoinExchange.hxx>
+#include <sot/formats.hxx>
+#include <comphelper/servicehelper.hxx>
+
+namespace dbaui
+{
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::lang;
+ using namespace ::com::sun::star::datatransfer;
+
+ void OJoinExchObj::setDescriptors(const OJoinExchangeData& jxdSource,bool _bFirstEntry)
+ {
+ m_bFirstEntry = _bFirstEntry;
+ m_jxdSourceDescription = jxdSource;
+ }
+
+ OJoinExchObj::OJoinExchObj()
+ : m_bFirstEntry(false)
+ {
+ }
+
+ OJoinExchObj::~OJoinExchObj()
+ {
+ }
+
+ bool OJoinExchObj::isFormatAvailable( const DataFlavorExVector& _rFormats ,SotClipboardFormatId _nSlotID)
+ {
+ for (auto const& format : _rFormats)
+ {
+ if ( _nSlotID == format.mnSotId )
+ return true;
+ }
+ return false;
+ }
+
+ OJoinExchangeData OJoinExchObj::GetSourceDescription(const Reference< XTransferable >& _rxObject)
+ {
+ OJoinExchangeData aReturn;
+ auto pImplementation = comphelper::getFromUnoTunnel<OJoinExchObj>(_rxObject);
+ if (pImplementation)
+ aReturn = pImplementation->m_jxdSourceDescription;
+ return aReturn;
+ }
+
+ const Sequence< sal_Int8 > & OJoinExchObj::getUnoTunnelId()
+ {
+ static const comphelper::UnoIdInit implId;
+ return implId.getSeq();
+ }
+
+ sal_Int64 SAL_CALL OJoinExchObj::getSomething( const Sequence< sal_Int8 >& _rIdentifier )
+ {
+ return comphelper::getSomethingImpl(_rIdentifier, this);
+ }
+
+ void OJoinExchObj::AddSupportedFormats()
+ {
+ AddFormat( SotClipboardFormatId::SBA_JOIN );
+ if ( m_bFirstEntry )
+ AddFormat( SotClipboardFormatId::SBA_TABID );
+ }
+
+ bool OJoinExchObj::GetData( const css::datatransfer::DataFlavor& rFlavor, const OUString& /*rDestDoc*/ )
+ {
+ SotClipboardFormatId nFormat = SotExchange::GetFormat(rFlavor);
+ if ( SotClipboardFormatId::SBA_JOIN == nFormat )
+ // this is a HACK
+ // we don't really copy our data, the instances using us have to call GetSourceDescription...
+ // if, one day, we have a _lot_ of time, this hack should be removed...
+ return true;
+
+ return false;
+ }
+
+ Any SAL_CALL OJoinExchObj::queryInterface( const Type& _rType )
+ {
+ Any aReturn = TransferDataContainer::queryInterface(_rType);
+ if (!aReturn.hasValue())
+ aReturn = OJoinExchObj_Base::queryInterface(_rType);
+ return aReturn;
+ }
+
+ void SAL_CALL OJoinExchObj::acquire( ) noexcept
+ {
+ TransferDataContainer::acquire( );
+ }
+
+ void SAL_CALL OJoinExchObj::release( ) noexcept
+ {
+ TransferDataContainer::release( );
+ }
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/querydesign/JoinTableView.cxx b/dbaccess/source/ui/querydesign/JoinTableView.cxx
new file mode 100644
index 000000000..055628133
--- /dev/null
+++ b/dbaccess/source/ui/querydesign/JoinTableView.cxx
@@ -0,0 +1,1568 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <JoinTableView.hxx>
+#include <osl/diagnose.h>
+#include <JoinController.hxx>
+#include <JoinDesignView.hxx>
+#include <TableWindow.hxx>
+#include <TableWindowListBox.hxx>
+#include <TableConnection.hxx>
+#include <TableConnectionData.hxx>
+#include <ConnectionLine.hxx>
+#include <ConnectionLineData.hxx>
+#include <browserids.hxx>
+#include <com/sun/star/sdbc/XDatabaseMetaData.hpp>
+#include <com/sun/star/sdbc/SQLException.hpp>
+#include "QueryMoveTabWinUndoAct.hxx"
+#include "QuerySizeTabWinUndoAct.hxx"
+#include <toolkit/helper/vclunohelper.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/settings.hxx>
+#include <vcl/commandevent.hxx>
+#include <vcl/event.hxx>
+#include <vcl/ptrstyle.hxx>
+#include <vcl/weldutils.hxx>
+#include <TableWindowData.hxx>
+#include <JAccess.hxx>
+#include <com/sun/star/accessibility/XAccessible.hpp>
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <com/sun/star/accessibility/AccessibleEventId.hpp>
+#include <cppuhelper/exc_hlp.hxx>
+#include <connectivity/dbtools.hxx>
+#include <tools/diagnose_ex.h>
+#include <algorithm>
+#include <functional>
+
+using namespace dbaui;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::accessibility;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::lang;
+
+#define LINE_SIZE 50
+// Constants for the window layout
+#define TABWIN_SPACING_X 17
+#define TABWIN_SPACING_Y 17
+
+#define TABWIN_WIDTH_STD 120
+#define TABWIN_HEIGHT_STD 120
+
+OScrollWindowHelper::OScrollWindowHelper( vcl::Window* pParent) : Window( pParent)
+ ,m_aHScrollBar( VclPtr<ScrollBar>::Create(this, WB_HSCROLL|WB_REPEAT|WB_DRAG) )
+ ,m_aVScrollBar( VclPtr<ScrollBar>::Create(this, WB_VSCROLL|WB_REPEAT|WB_DRAG) )
+ ,m_pCornerWindow(VclPtr<ScrollBarBox>::Create(this, WB_3DLOOK))
+ ,m_pTableView(nullptr)
+{
+
+ // ScrollBars
+
+ GetHScrollBar().SetRange( Range(0, 1000) );
+ GetVScrollBar().SetRange( Range(0, 1000) );
+
+ GetHScrollBar().SetLineSize( LINE_SIZE );
+ GetVScrollBar().SetLineSize( LINE_SIZE );
+
+ GetHScrollBar().Show();
+ GetVScrollBar().Show();
+ m_pCornerWindow->Show();
+
+ // normally we should be SCROLL_PANE
+ SetAccessibleRole(AccessibleRole::SCROLL_PANE);
+}
+
+OScrollWindowHelper::~OScrollWindowHelper()
+{
+ disposeOnce();
+}
+
+void OScrollWindowHelper::dispose()
+{
+ m_aHScrollBar.disposeAndClear();
+ m_aVScrollBar.disposeAndClear();
+ m_pCornerWindow.disposeAndClear();
+ m_pTableView.clear();
+ vcl::Window::dispose();
+}
+
+void OScrollWindowHelper::setTableView(OJoinTableView* _pTableView)
+{
+ m_pTableView = _pTableView;
+ // ScrollBars
+ GetHScrollBar().SetScrollHdl( LINK(m_pTableView, OJoinTableView, ScrollHdl) );
+ GetVScrollBar().SetScrollHdl( LINK(m_pTableView, OJoinTableView, ScrollHdl) );
+}
+
+void OScrollWindowHelper::resetRange(const Point& _aSize)
+{
+ Point aPos = PixelToLogic(_aSize);
+ GetHScrollBar().SetRange( Range(0, aPos.X() + TABWIN_SPACING_X) );
+ GetVScrollBar().SetRange( Range(0, aPos.Y() + TABWIN_SPACING_Y) );
+}
+
+void OScrollWindowHelper::Resize()
+{
+ Window::Resize();
+
+ Size aTotalOutputSize = GetOutputSizePixel();
+ tools::Long nHScrollHeight = GetHScrollBar().GetSizePixel().Height();
+ tools::Long nVScrollWidth = GetVScrollBar().GetSizePixel().Width();
+
+ GetHScrollBar().SetPosSizePixel(
+ Point( 0, aTotalOutputSize.Height()-nHScrollHeight ),
+ Size( aTotalOutputSize.Width()-nVScrollWidth, nHScrollHeight )
+ );
+
+ GetVScrollBar().SetPosSizePixel(
+ Point( aTotalOutputSize.Width()-nVScrollWidth, 0 ),
+ Size( nVScrollWidth, aTotalOutputSize.Height()-nHScrollHeight )
+ );
+
+ m_pCornerWindow->SetPosSizePixel(
+ Point( aTotalOutputSize.Width() - nVScrollWidth, aTotalOutputSize.Height() - nHScrollHeight),
+ Size( nVScrollWidth, nHScrollHeight )
+ );
+
+ GetHScrollBar().SetPageSize( aTotalOutputSize.Width() );
+ GetHScrollBar().SetVisibleSize( aTotalOutputSize.Width() );
+
+ GetVScrollBar().SetPageSize( aTotalOutputSize.Height() );
+ GetVScrollBar().SetVisibleSize( aTotalOutputSize.Height() );
+
+ // adjust the ranges of the scrollbars if necessary
+ tools::Long lRange = GetHScrollBar().GetRange().Max() - GetHScrollBar().GetRange().Min();
+ if (m_pTableView->GetScrollOffset().X() + aTotalOutputSize.Width() > lRange)
+ GetHScrollBar().SetRangeMax(m_pTableView->GetScrollOffset().X() + aTotalOutputSize.Width() + GetHScrollBar().GetRange().Min());
+
+ lRange = GetVScrollBar().GetRange().Max() - GetVScrollBar().GetRange().Min();
+ if (m_pTableView->GetScrollOffset().Y() + aTotalOutputSize.Height() > lRange)
+ GetVScrollBar().SetRangeMax(m_pTableView->GetScrollOffset().Y() + aTotalOutputSize.Height() + GetVScrollBar().GetRange().Min());
+
+ m_pTableView->SetPosSizePixel(Point( 0, 0 ),Size( aTotalOutputSize.Width()-nVScrollWidth, aTotalOutputSize.Height()-nHScrollHeight ));
+}
+
+
+OJoinTableView::OJoinTableView( vcl::Window* pParent, OJoinDesignView* pView )
+ :Window( pParent,WB_BORDER )
+ ,DropTargetHelper(this)
+ ,m_aDragScrollIdle("dbaccess OJoinTableView m_aDragScrollIdle")
+ ,m_aDragOffset( Point(0,0) )
+ ,m_aScrollOffset( Point(0,0) )
+ ,m_pDragWin( nullptr )
+ ,m_pSizingWin( nullptr )
+ ,m_pSelectedConn( nullptr )
+ ,m_pLastFocusTabWin(nullptr)
+ ,m_pView( pView )
+{
+ SetSizePixel( Size(1000, 1000) );
+
+ InitColors();
+
+ m_aDragScrollIdle.SetInvokeHandler(LINK(this, OJoinTableView, OnDragScrollTimer));
+}
+
+OJoinTableView::~OJoinTableView()
+{
+ disposeOnce();
+}
+
+void OJoinTableView::dispose()
+{
+ if( m_pAccessible )
+ {
+ m_pAccessible->clearTableView();
+ m_pAccessible = nullptr;
+ }
+ // delete lists
+ clearLayoutInformation();
+ m_pDragWin.clear();
+ m_pSizingWin.clear();
+ m_pSelectedConn.clear();
+ m_pLastFocusTabWin.clear();
+ m_pView.clear();
+ m_vTableConnection.clear();
+ vcl::Window::dispose();
+}
+
+IMPL_LINK( OJoinTableView, ScrollHdl, ScrollBar*, pScrollBar, void )
+{
+ // move all windows
+ ScrollPane( pScrollBar->GetDelta(), (pScrollBar == &GetHScrollBar()), false );
+}
+
+void OJoinTableView::Resize()
+{
+ Window::Resize();
+ m_aOutputSize = GetSizePixel();
+
+ // tab win positions may not be up-to-date
+ if (m_aTableMap.empty())
+ // no tab wins ...
+ return;
+
+ // we have at least one table so resize it
+ m_aScrollOffset.setX( GetHScrollBar().GetThumbPos() );
+ m_aScrollOffset.setY( GetVScrollBar().GetThumbPos() );
+
+ VclPtr<OTableWindow> pCheck = m_aTableMap.begin()->second;
+ Point aRealPos = pCheck->GetPosPixel();
+ Point aAssumedPos = pCheck->GetData()->GetPosition() - GetScrollOffset();
+
+ if (aRealPos == aAssumedPos)
+ // all ok
+ return;
+
+ for (auto const& elem : m_aTableMap)
+ {
+ OTableWindow* pCurrent = elem.second;
+ Point aPos(pCurrent->GetData()->GetPosition() - GetScrollOffset());
+ pCurrent->SetPosPixel(aPos);
+ }
+}
+
+sal_uLong OJoinTableView::GetTabWinCount() const
+{
+ return m_aTableMap.size();
+}
+
+bool OJoinTableView::RemoveConnection(VclPtr<OTableConnection>& rConn, bool _bDelete)
+{
+ VclPtr<OTableConnection> xConn(rConn);
+
+ DeselectConn(xConn);
+
+ // to force a redraw
+ xConn->InvalidateConnection();
+
+ m_pView->getController().removeConnectionData(xConn->GetData());
+
+ m_vTableConnection.erase(std::find(m_vTableConnection.begin(), m_vTableConnection.end(), xConn));
+
+ modified();
+ if ( m_pAccessible )
+ m_pAccessible->notifyAccessibleEvent( AccessibleEventId::CHILD,
+ Any(xConn->GetAccessible()),
+ Any());
+ if (_bDelete)
+ xConn->disposeOnce();
+
+ return true;
+}
+
+OTableWindow* OJoinTableView::GetTabWindow( const OUString& rName )
+{
+ OTableWindowMap::const_iterator aIter = m_aTableMap.find(rName);
+
+ return aIter == m_aTableMap.end() ? nullptr : aIter->second;
+}
+
+TTableWindowData::value_type OJoinTableView::createTableWindowData(const OUString& _rComposedName
+ ,const OUString& _sTableName
+ ,const OUString& _rWinName)
+{
+ TTableWindowData::value_type pData( CreateImpl(_rComposedName, _sTableName,_rWinName) );
+ OJoinDesignView* pParent = getDesignView();
+ try
+ {
+ if ( !pData->init(pParent->getController().getConnection(),allowQueries()) )
+ {
+ if ( pData->isValid() )
+ onNoColumns_throw();
+ else
+ pData.reset();
+ }
+ }
+ catch ( const SQLException& )
+ {
+ ::dbtools::showError( ::dbtools::SQLExceptionInfo( ::cppu::getCaughtException() ),
+ VCLUnoHelper::GetInterface(pParent), pParent->getController().getORB() );
+ }
+ catch( const WrappedTargetException& e )
+ {
+ SQLException aSql;
+ if ( e.TargetException >>= aSql )
+ ::dbtools::showError( ::dbtools::SQLExceptionInfo( aSql ), VCLUnoHelper::GetInterface(pParent), pParent->getController().getORB() );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ return pData;
+}
+
+std::shared_ptr<OTableWindowData> OJoinTableView::CreateImpl(const OUString& _rComposedName
+ ,const OUString& _sTableName
+ ,const OUString& _rWinName)
+{
+ return std::make_shared<OTableWindowData>( nullptr,_rComposedName,_sTableName, _rWinName );
+}
+
+void OJoinTableView::AddTabWin(const OUString& _rComposedName, const OUString& rWinName, bool /*bNewTable*/)
+{
+ OSL_ENSURE(!_rComposedName.isEmpty(),"There must be a table name supplied!");
+
+ TTableWindowData::value_type pNewTabWinData(createTableWindowData( _rComposedName, rWinName,rWinName ));
+
+ // insert new window in window list
+ VclPtr<OTableWindow> pNewTabWin = createWindow( pNewTabWinData );
+ if ( pNewTabWin->Init() )
+ {
+ m_pView->getController().getTableWindowData().push_back( pNewTabWinData);
+ // when we already have a table with this name insert the full qualified one instead
+ if(m_aTableMap.find(rWinName) != m_aTableMap.end())
+ m_aTableMap[_rComposedName] = pNewTabWin;
+ else
+ m_aTableMap[rWinName] = pNewTabWin;
+
+ SetDefaultTabWinPosSize( pNewTabWin );
+ pNewTabWin->Show();
+
+ modified();
+ if ( m_pAccessible )
+ m_pAccessible->notifyAccessibleEvent( AccessibleEventId::CHILD,
+ Any(),
+ Any(pNewTabWin->GetAccessible()));
+ }
+ else
+ {
+ pNewTabWin->clearListBox();
+ pNewTabWin.disposeAndClear();
+ }
+}
+
+void OJoinTableView::RemoveTabWin( OTableWindow* pTabWin )
+{
+ // first delete all connections of this window to others
+ bool bRemove = true;
+ TTableWindowData::value_type pData = pTabWin->GetData();
+ sal_Int32 nCount = m_vTableConnection.size();
+ auto aIter = m_vTableConnection.rbegin();
+ while(aIter != m_vTableConnection.rend() && bRemove)
+ {
+ VclPtr<OTableConnection>& rTabConn = *aIter;
+ if (
+ (pData == rTabConn->GetData()->getReferencingTable()) ||
+ (pData == rTabConn->GetData()->getReferencedTable())
+ )
+ {
+ bRemove = RemoveConnection(rTabConn, true);
+ aIter = m_vTableConnection.rbegin();
+ }
+ else
+ ++aIter;
+ }
+
+ // then delete the window itself
+ if ( bRemove )
+ {
+ if ( m_pAccessible )
+ m_pAccessible->notifyAccessibleEvent( AccessibleEventId::CHILD,
+ Any(pTabWin->GetAccessible()),Any()
+ );
+
+ pTabWin->Hide();
+ OJoinController& rController = m_pView->getController();
+ TTableWindowData::iterator aFind = std::find(rController.getTableWindowData().begin(), rController.getTableWindowData().end(), pData);
+ if(aFind != rController.getTableWindowData().end())
+ {
+ rController.getTableWindowData().erase(aFind);
+ rController.setModified(true);
+ }
+
+ if ( !m_aTableMap.erase( pTabWin->GetWinName() ) )
+ m_aTableMap.erase( pTabWin->GetComposedName() );
+
+ if (pTabWin == m_pLastFocusTabWin)
+ m_pLastFocusTabWin = nullptr;
+
+ pTabWin->clearListBox();
+ pTabWin->disposeOnce();
+ }
+
+ if ( static_cast<sal_Int32>(m_vTableConnection.size()) < (nCount-1) ) // if some connections could be removed
+ modified();
+}
+
+namespace
+{
+ bool isScrollAllowed( OJoinTableView* _pView,tools::Long nDelta, bool bHoriz)
+ {
+ // adjust ScrollBar-Positions
+ ScrollBar& rBar = bHoriz ? _pView->GetHScrollBar() : _pView->GetVScrollBar() ;
+
+ tools::Long nOldThumbPos = rBar.GetThumbPos();
+ tools::Long nNewThumbPos = nOldThumbPos + nDelta;
+ if( nNewThumbPos < 0 )
+ nNewThumbPos = 0;
+ else if( nNewThumbPos > rBar.GetRangeMax() )
+ nNewThumbPos = rBar.GetRangeMax();
+
+ if ( bHoriz )
+ {
+ if( nNewThumbPos == _pView->GetScrollOffset().X() )
+ return false;
+ }
+ else if ( nNewThumbPos == _pView->GetScrollOffset().Y() )
+ return false;
+
+ return true;
+ }
+ bool getMovementImpl(OJoinTableView* _pView,const Point& _rPoint,const Size& _rSize,tools::Long& _nScrollX,tools::Long& _nScrollY)
+ {
+ _nScrollY = _nScrollX = 0;
+ // data about the tab win
+ Point aUpperLeft = _rPoint;
+ // normalize with respect to visibility
+ aUpperLeft -= _pView->GetScrollOffset();
+ Point aLowerRight(aUpperLeft.X() + _rSize.Width(), aUpperLeft.Y() + _rSize.Height());
+
+ // data about ourself
+ Size aSize = _pView->getRealOutputSize(); //GetOutputSizePixel();
+
+ bool bVisible = true;
+ bool bFitsHor = (aUpperLeft.X() >= 0) && (aLowerRight.X() <= aSize.Width());
+ bool bFitsVert= (aUpperLeft.Y() >= 0) && (aLowerRight.Y() <= aSize.Height());
+ if (!bFitsHor || !bFitsVert)
+ {
+ if (!bFitsHor)
+ {
+ // ensure the visibility of the right border
+ if ( aLowerRight.X() > aSize.Width() )
+ _nScrollX = aLowerRight.X() - aSize.Width() + TABWIN_SPACING_X;
+
+ // ensure the visibility of the left border (higher priority)
+ if ( aUpperLeft.X() < 0 )
+ _nScrollX = aUpperLeft.X() - TABWIN_SPACING_X;
+ }
+
+ if (!bFitsVert)
+ {
+ // lower border
+ if ( aLowerRight.Y() > aSize.Height() )
+ _nScrollY = aLowerRight.Y() - aSize.Height() + TABWIN_SPACING_Y;
+ // upper border
+ if ( aUpperLeft.Y() < 0 )
+ _nScrollY = aUpperLeft.Y() - TABWIN_SPACING_Y;
+ }
+
+ if ( _nScrollX ) // aSize.Width() > _rSize.Width() &&
+ bVisible = isScrollAllowed(_pView,_nScrollX, true);
+
+ if ( _nScrollY ) // aSize.Height() > _rSize.Height() &&
+ bVisible = bVisible && isScrollAllowed(_pView,_nScrollY, false);
+
+ if ( bVisible )
+ {
+ sal_Int32 nHRangeMax = _pView->GetHScrollBar().GetRangeMax();
+ sal_Int32 nVRangeMax = _pView->GetVScrollBar().GetRangeMax();
+
+ if ( aSize.Width() + _pView->GetHScrollBar().GetThumbPos() + _nScrollX > nHRangeMax )
+ bVisible = false;
+ if ( bVisible && aSize.Height() + _pView->GetVScrollBar().GetThumbPos() + _nScrollY > nVRangeMax )
+ bVisible = false;
+ }
+ }
+
+ return bVisible;
+ }
+} // end of ano namespace
+
+bool OJoinTableView::isMovementAllowed(const Point& _rPoint,const Size& _rSize)
+{
+ tools::Long nX,nY;
+ return getMovementImpl(this,_rPoint,_rSize,nX,nY);
+}
+
+void OJoinTableView::EnsureVisible(const OTableWindow* _pWin)
+{
+ // data about the tab win
+ TTableWindowData::value_type pData = _pWin->GetData();
+ EnsureVisible( pData->GetPosition() , pData->GetSize());
+ Invalidate(InvalidateFlags::NoChildren);
+}
+
+void OJoinTableView::EnsureVisible(const Point& _rPoint,const Size& _rSize)
+{
+ tools::Long nScrollX,nScrollY;
+
+ if ( getMovementImpl(this,_rPoint,_rSize,nScrollX,nScrollY) )
+ {
+ bool bVisible = true;
+ if (nScrollX)
+ bVisible = ScrollPane(nScrollX, true, true);
+
+ if (nScrollY && bVisible)
+ ScrollPane(nScrollY, false, true);
+ }
+}
+
+void OJoinTableView::SetDefaultTabWinPosSize( OTableWindow* pTabWin )
+{
+ // determine position:
+ // the window is divided into lines with height TABWIN_SPACING_Y+TABWIN_HEIGHT_STD.
+ // Then for each line is checked, if there is space for another window.
+ // If there is no space, the next line is checked.
+ Size aOutSize = GetSizePixel();
+ Point aNewPos( 0,0 );
+ sal_uInt16 nRow = 0;
+ bool bEnd = false;
+ while( !bEnd )
+ {
+ // Set new position to start of line
+ aNewPos.setX( TABWIN_SPACING_X );
+ aNewPos.setY( (nRow+1) * TABWIN_SPACING_Y );
+
+ // determine rectangle for the corresponding line
+ tools::Rectangle aRowRect( Point(0,0), aOutSize );
+ aRowRect.SetTop( nRow * ( TABWIN_SPACING_Y + TABWIN_HEIGHT_STD ) );
+ aRowRect.SetBottom( (nRow+1) * ( TABWIN_SPACING_Y + TABWIN_HEIGHT_STD ) );
+
+ // check occupied areas of this line
+ for (auto const& elem : m_aTableMap)
+ {
+ OTableWindow* pOtherTabWin = elem.second;
+ tools::Rectangle aOtherTabWinRect( pOtherTabWin->GetPosPixel(), pOtherTabWin->GetSizePixel() );
+
+ if(
+ ( (aOtherTabWinRect.Top()>aRowRect.Top()) && (aOtherTabWinRect.Top()<aRowRect.Bottom()) ) ||
+ ( (aOtherTabWinRect.Bottom()>aRowRect.Top()) && (aOtherTabWinRect.Bottom()<aRowRect.Bottom()) )
+ )
+ {
+ // TabWin is in the line
+ if( aOtherTabWinRect.Right()>aNewPos.X() )
+ aNewPos.setX( aOtherTabWinRect.Right() + TABWIN_SPACING_X );
+ }
+ }
+
+ // Is there space left in this line?
+ if( (aNewPos.X()+TABWIN_WIDTH_STD)<aRowRect.Right() )
+ {
+ aNewPos.setY( aRowRect.Top() + TABWIN_SPACING_Y );
+ bEnd = true;
+ }
+ else
+ {
+ if( (aRowRect.Bottom()+aRowRect.GetHeight()) > aOutSize.Height() )
+ {
+ // insert it in the first row
+ sal_Int32 nCount = m_aTableMap.size() % (nRow+1);
+ ++nCount;
+ aNewPos.setY( nCount * TABWIN_SPACING_Y + (nCount-1)*CalcZoom(TABWIN_HEIGHT_STD) );
+ bEnd = true;
+ }
+ else
+ nRow++;
+
+ }
+ }
+
+ // determine size
+ Size aNewSize( CalcZoom(TABWIN_WIDTH_STD), CalcZoom(TABWIN_HEIGHT_STD) );
+
+ // check if the new position in inside the scrollbars ranges
+ Point aBottom(aNewPos);
+ aBottom.AdjustX(aNewSize.Width() );
+ aBottom.AdjustY(aNewSize.Height() );
+
+ if(!GetHScrollBar().GetRange().Contains(aBottom.X()))
+ GetHScrollBar().SetRange( Range(0, aBottom.X()) );
+ if(!GetVScrollBar().GetRange().Contains(aBottom.Y()))
+ GetVScrollBar().SetRange( Range(0, aBottom.Y()) );
+
+ pTabWin->SetPosSizePixel( aNewPos, aNewSize );
+}
+
+void OJoinTableView::DataChanged(const DataChangedEvent& rDCEvt)
+{
+ if (rDCEvt.GetType() == DataChangedEventType::SETTINGS)
+ {
+ // consider the worst case: the colors changed, so adjust me
+ InitColors();
+ Invalidate(InvalidateFlags::NoChildren);
+ // due to the Invalidate, the connections are redrawn, so that they are also pictured in the new colors
+ }
+}
+
+void OJoinTableView::InitColors()
+{
+ // the colors for the illustration should be the system colors
+ StyleSettings aSystemStyle = Application::GetSettings().GetStyleSettings();
+ SetBackground(Wallpaper(aSystemStyle.GetDialogColor()));
+}
+
+void OJoinTableView::BeginChildMove( OTableWindow* pTabWin, const Point& rMousePos )
+{
+
+ if (m_pView->getController().isReadOnly())
+ return;
+
+ m_pDragWin = pTabWin;
+ SetPointer(PointerStyle::Move);
+ Point aMousePos = ScreenToOutputPixel( rMousePos );
+ m_aDragOffset = aMousePos - pTabWin->GetPosPixel();
+ m_pDragWin->SetZOrder(nullptr, ZOrderFlags::First);
+ StartTracking();
+}
+
+void OJoinTableView::NotifyTitleClicked( OTableWindow* pTabWin, const Point& rMousePos )
+{
+ DeselectConn(GetSelectedConn());
+ BeginChildMove(pTabWin, rMousePos);
+}
+
+void OJoinTableView::BeginChildSizing( OTableWindow* pTabWin, PointerStyle nPointer )
+{
+
+ if (m_pView->getController().isReadOnly())
+ return;
+
+ SetPointer( nPointer );
+ m_pSizingWin = pTabWin;
+ StartTracking();
+}
+
+bool OJoinTableView::ScrollPane( tools::Long nDelta, bool bHoriz, bool bPaintScrollBars )
+{
+ bool bRet = true;
+
+ // adjust ScrollBar-Positions
+ if( bPaintScrollBars )
+ {
+ if( bHoriz )
+ {
+ tools::Long nOldThumbPos = GetHScrollBar().GetThumbPos();
+ tools::Long nNewThumbPos = nOldThumbPos + nDelta;
+ if( nNewThumbPos < 0 )
+ {
+ nNewThumbPos = 0;
+ bRet = false;
+ }
+ if( nNewThumbPos > GetHScrollBar().GetRange().Max() )
+ {
+ nNewThumbPos = GetHScrollBar().GetRange().Max();
+ bRet = false;
+ }
+ GetHScrollBar().SetThumbPos( nNewThumbPos );
+ nDelta = GetHScrollBar().GetThumbPos() - nOldThumbPos;
+ }
+ else
+ {
+ tools::Long nOldThumbPos = GetVScrollBar().GetThumbPos();
+ tools::Long nNewThumbPos = nOldThumbPos+nDelta;
+ if( nNewThumbPos < 0 )
+ {
+ nNewThumbPos = 0;
+ bRet = false;
+ }
+ if( nNewThumbPos > GetVScrollBar().GetRange().Max() )
+ {
+ nNewThumbPos = GetVScrollBar().GetRange().Max();
+ bRet = false;
+ }
+ GetVScrollBar().SetThumbPos( nNewThumbPos );
+ nDelta = GetVScrollBar().GetThumbPos() - nOldThumbPos;
+ }
+ }
+
+ // If ScrollOffset hitting borders, no redrawing.
+ if( (GetHScrollBar().GetThumbPos()==m_aScrollOffset.X()) &&
+ (GetVScrollBar().GetThumbPos()==m_aScrollOffset.Y()) )
+ return false;
+
+ // set ScrollOffset anew
+ if (bHoriz)
+ m_aScrollOffset.setX( GetHScrollBar().GetThumbPos() );
+ else
+ m_aScrollOffset.setY( GetVScrollBar().GetThumbPos() );
+
+ // move all windows
+ OTableWindow* pTabWin;
+ Point aPos;
+
+ for (auto const& elem : m_aTableMap)
+ {
+ pTabWin = elem.second;
+ aPos = pTabWin->GetPosPixel();
+
+ if( bHoriz )
+ aPos.AdjustX( -nDelta );
+ else aPos.AdjustY( -nDelta );
+
+ pTabWin->SetPosPixel( aPos );
+ }
+
+ Invalidate(); // InvalidateFlags::NoChildren
+
+ return bRet;
+}
+
+void OJoinTableView::Tracking( const TrackingEvent& rTEvt )
+{
+ HideTracking();
+
+ if (rTEvt.IsTrackingEnded())
+ {
+ if( m_pDragWin )
+ {
+ if (m_aDragScrollIdle.IsActive())
+ m_aDragScrollIdle.Stop();
+
+ // adjust position of child after moving
+ // windows are not allowed to leave display range
+ Point aDragWinPos = rTEvt.GetMouseEvent().GetPosPixel() - m_aDragOffset;
+ Size aDragWinSize = m_pDragWin->GetSizePixel();
+ if( aDragWinPos.X() < 0 )
+ aDragWinPos.setX( 0 );
+ if( aDragWinPos.Y() < 0 )
+ aDragWinPos.setY( 0 );
+ if( (aDragWinPos.X() + aDragWinSize.Width()) > m_aOutputSize.Width() )
+ aDragWinPos.setX( m_aOutputSize.Width() - aDragWinSize.Width() - 1 );
+ if( (aDragWinPos.Y() + aDragWinSize.Height()) > m_aOutputSize.Height() )
+ aDragWinPos.setY( m_aOutputSize.Height() - aDragWinSize.Height() - 1 );
+ if( aDragWinPos.X() < 0 )
+ aDragWinPos.setX( 0 );
+ if( aDragWinPos.Y() < 0 )
+ aDragWinPos.setY( 0 );
+ // TODO : don't position window anew, if it is leaving range, but just expand the range
+
+ // position window
+ EndTracking();
+ m_pDragWin->SetZOrder(nullptr, ZOrderFlags::First);
+ // check, if I really moved
+ // (this prevents setting the modified-Flag, when there actually was no change0
+ TTableWindowData::value_type pData = m_pDragWin->GetData();
+ if ( ! (pData && pData->HasPosition() && (pData->GetPosition() == aDragWinPos)))
+ {
+ // old logic coordinates
+ Point ptOldPos = m_pDragWin->GetPosPixel() + Point(GetHScrollBar().GetThumbPos(), GetVScrollBar().GetThumbPos());
+ // new positioning
+ m_pDragWin->SetPosPixel(aDragWinPos);
+ TabWinMoved(m_pDragWin, ptOldPos);
+
+ m_pDragWin->GrabFocus();
+ }
+ m_pDragWin = nullptr;
+ SetPointer(PointerStyle::Arrow);
+ }
+ // else we handle the resizing
+ else if( m_pSizingWin )
+ {
+ SetPointer( PointerStyle::Arrow );
+ EndTracking();
+
+ // old physical coordinates
+
+ Size szOld = m_pSizingWin->GetSizePixel();
+ Point ptOld = m_pSizingWin->GetPosPixel();
+ Size aNewSize(CalcZoom(m_aSizingRect.GetSize().Width()),CalcZoom(m_aSizingRect.GetSize().Height()));
+ m_pSizingWin->SetPosSizePixel( m_aSizingRect.TopLeft(), aNewSize );
+ TabWinSized(m_pSizingWin, ptOld, szOld);
+
+ m_pSizingWin->Invalidate( m_aSizingRect );
+ m_pSizingWin = nullptr;
+ }
+ }
+ else if (rTEvt.IsTrackingCanceled())
+ {
+ if (m_aDragScrollIdle.IsActive())
+ m_aDragScrollIdle.Stop();
+ EndTracking();
+ }
+ else
+ {
+ if( m_pDragWin )
+ {
+ m_ptPrevDraggingPos = rTEvt.GetMouseEvent().GetPosPixel();
+ // scroll at window borders
+ ScrollWhileDragging();
+ }
+
+ if( m_pSizingWin )
+ {
+ Point aMousePos = rTEvt.GetMouseEvent().GetPosPixel();
+ m_aSizingRect = m_pSizingWin->getSizingRect(aMousePos,m_aOutputSize);
+ PaintImmediately();
+ ShowTracking( m_aSizingRect, ShowTrackFlags::Small | ShowTrackFlags::TrackWindow );
+ }
+ }
+}
+
+void OJoinTableView::ConnDoubleClicked(VclPtr<OTableConnection>& /*rConnection*/)
+{
+}
+
+void OJoinTableView::MouseButtonDown( const MouseEvent& rEvt )
+{
+ GrabFocus();
+ Window::MouseButtonDown(rEvt);
+}
+
+void OJoinTableView::MouseButtonUp( const MouseEvent& rEvt )
+{
+ Window::MouseButtonUp(rEvt);
+ // Has a connection been selected?
+ if( m_vTableConnection.empty() )
+ return;
+
+ DeselectConn(GetSelectedConn());
+
+ for (auto & elem : m_vTableConnection)
+ {
+ if( elem->CheckHit(rEvt.GetPosPixel()) )
+ {
+ SelectConn(elem);
+
+ // Double-click
+ if( rEvt.GetClicks() == 2 )
+ ConnDoubleClicked(elem);
+
+ break;
+ }
+ }
+}
+
+void OJoinTableView::KeyInput( const KeyEvent& rEvt )
+{
+ sal_uInt16 nCode = rEvt.GetKeyCode().GetCode();
+ bool bShift = rEvt.GetKeyCode().IsShift();
+ bool bCtrl = rEvt.GetKeyCode().IsMod1();
+
+ if( !bCtrl && !bShift && (nCode==KEY_DELETE) )
+ {
+ if (GetSelectedConn())
+ RemoveConnection(GetSelectedConn(), true);
+ }
+ else
+ Window::KeyInput( rEvt );
+}
+
+void OJoinTableView::DeselectConn(OTableConnection* pConn)
+{
+ if (!pConn || !pConn->IsSelected())
+ return;
+
+ // deselect the corresponding entries in the ListBox of the table window
+ OTableWindow* pWin = pConn->GetSourceWin();
+ if (pWin && pWin->GetListBox())
+ pWin->GetListBox()->get_widget().unselect_all();
+
+ pWin = pConn->GetDestWin();
+ if (pWin && pWin->GetListBox())
+ pWin->GetListBox()->get_widget().unselect_all();
+
+ pConn->Deselect();
+ m_pSelectedConn = nullptr;
+}
+
+void OJoinTableView::SelectConn(OTableConnection* pConn)
+{
+ DeselectConn(GetSelectedConn());
+
+ pConn->Select();
+ m_pSelectedConn = pConn;
+ GrabFocus(); // has to be called here because a table window may still be focused
+
+ // select the concerned entries in the windows
+ OTableWindow* pConnSource = pConn->GetSourceWin();
+ OTableWindow* pConnDest = pConn->GetDestWin();
+ if (!(pConnSource && pConnDest))
+ return;
+
+ OTableWindowListBox* pSourceBox = pConnSource->GetListBox().get();
+ OTableWindowListBox* pDestBox = pConnDest->GetListBox().get();
+ if (!(pSourceBox && pDestBox))
+ return;
+
+ pSourceBox->get_widget().unselect_all();
+ pDestBox->get_widget().unselect_all();
+
+ bool bScrolled = false;
+
+ const std::vector<std::unique_ptr<OConnectionLine>>& rLines = pConn->GetConnLineList();
+ auto aIter = rLines.rbegin();
+ for(;aIter != rLines.rend();++aIter)
+ {
+ if ((*aIter)->IsValid())
+ {
+ int nSourceEntry = pSourceBox->GetEntryFromText((*aIter)->GetData()->GetSourceFieldName());
+ if (nSourceEntry != -1)
+ {
+ pSourceBox->get_widget().select(nSourceEntry);
+ pSourceBox->get_widget().scroll_to_row(nSourceEntry);
+ bScrolled = true;
+ }
+
+ int nDestEntry = pDestBox->GetEntryFromText((*aIter)->GetData()->GetDestFieldName());
+ if (nDestEntry != -1)
+ {
+ pDestBox->get_widget().select(nDestEntry);
+ pDestBox->get_widget().scroll_to_row(nDestEntry);
+ bScrolled = true;
+ }
+ }
+ }
+
+ if (bScrolled)
+ {
+ // scrolling was done -> redraw
+ Invalidate(InvalidateFlags::NoChildren);
+ }
+}
+
+void OJoinTableView::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect)
+{
+ DrawConnections(rRenderContext, rRect);
+}
+
+void OJoinTableView::InvalidateConnections()
+{
+ // draw Joins
+ for (auto & conn : m_vTableConnection)
+ conn->InvalidateConnection();
+}
+
+void OJoinTableView::DrawConnections(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect)
+{
+ // draw Joins
+ for(const auto& connection : m_vTableConnection)
+ connection->Draw(rRenderContext, rRect);
+ // finally redraw the selected one above all others
+ if (GetSelectedConn())
+ GetSelectedConn()->Draw(rRenderContext, rRect);
+}
+
+std::vector<VclPtr<OTableConnection> >::const_iterator OJoinTableView::getTableConnections(const OTableWindow* _pFromWin) const
+{
+ return std::find_if( m_vTableConnection.begin(),
+ m_vTableConnection.end(),
+ [_pFromWin](OTableConnection * p) { return p->isTableConnection(_pFromWin); });
+}
+
+sal_Int32 OJoinTableView::getConnectionCount(const OTableWindow* _pFromWin) const
+{
+ return std::count_if( m_vTableConnection.begin(),
+ m_vTableConnection.end(),
+ [_pFromWin](OTableConnection * p) { return p->isTableConnection(_pFromWin); });
+}
+
+bool OJoinTableView::ExistsAConn(const OTableWindow* pFrom) const
+{
+ return getTableConnections(pFrom) != m_vTableConnection.end();
+}
+
+void OJoinTableView::ClearAll()
+{
+ SetUpdateMode(false);
+
+ HideTabWins();
+
+ // and the same with the Connections
+ for (auto & elem : m_vTableConnection)
+ {
+ RemoveConnection(elem, true);
+ }
+ m_vTableConnection.clear();
+
+ m_pLastFocusTabWin = nullptr;
+ m_pSelectedConn = nullptr;
+
+ // scroll to the upper left
+ ScrollPane(-GetScrollOffset().X(), true, true);
+ ScrollPane(-GetScrollOffset().Y(), false, true);
+ Invalidate();
+}
+
+void OJoinTableView::ScrollWhileDragging()
+{
+ OSL_ENSURE(m_pDragWin != nullptr, "OJoinTableView::ScrollWhileDragging must not be called when a window is being dragged !");
+
+ // kill the timer
+ if (m_aDragScrollIdle.IsActive())
+ m_aDragScrollIdle.Stop();
+
+ Point aDragWinPos = m_ptPrevDraggingPos - m_aDragOffset;
+ Size aDragWinSize = m_pDragWin->GetSizePixel();
+ Point aLowerRight(aDragWinPos.X() + aDragWinSize.Width(), aDragWinPos.Y() + aDragWinSize.Height());
+
+ if (aDragWinPos == m_pDragWin->GetPosPixel())
+ return;
+
+ // avoid illustration errors (when scrolling with active TrackingRect)
+ HideTracking();
+
+ bool bScrolling = false;
+ bool bNeedScrollTimer = false;
+
+ // scroll at window borders
+ // TODO : only catch, if window would disappear completely (don't, if there is still a pixel visible)
+ if( aDragWinPos.X() < 5 )
+ {
+ bScrolling = ScrollPane( -LINE_SIZE, true, true );
+ if( !bScrolling && (aDragWinPos.X()<0) )
+ aDragWinPos.setX( 0 );
+
+ // do I need further (timer controlled) scrolling ?
+ bNeedScrollTimer = bScrolling && (aDragWinPos.X() < 5);
+ }
+
+ if( aLowerRight.X() > m_aOutputSize.Width() - 5 )
+ {
+ bScrolling = ScrollPane( LINE_SIZE, true, true ) ;
+ if( !bScrolling && ( aLowerRight.X() > m_aOutputSize.Width() ) )
+ aDragWinPos.setX( m_aOutputSize.Width() - aDragWinSize.Width() );
+
+ // do I need further (timer controlled) scrolling ?
+ bNeedScrollTimer = bScrolling && (aLowerRight.X() > m_aOutputSize.Width() - 5);
+ }
+
+ if( aDragWinPos.Y() < 5 )
+ {
+ bScrolling = ScrollPane( -LINE_SIZE, false, true );
+ if( !bScrolling && (aDragWinPos.Y()<0) )
+ aDragWinPos.setY( 0 );
+
+ bNeedScrollTimer = bScrolling && (aDragWinPos.Y() < 5);
+ }
+
+ if( aLowerRight.Y() > m_aOutputSize.Height() - 5 )
+ {
+ bScrolling = ScrollPane( LINE_SIZE, false, true );
+ if( !bScrolling && ( (aDragWinPos.Y() + aDragWinSize.Height()) > m_aOutputSize.Height() ) )
+ aDragWinPos.setY( m_aOutputSize.Height() - aDragWinSize.Height() );
+
+ bNeedScrollTimer = bScrolling && (aLowerRight.Y() > m_aOutputSize.Height() - 5);
+ }
+
+ // resetting timer, if still necessary
+ if (bNeedScrollTimer)
+ {
+ m_aDragScrollIdle.SetPriority( TaskPriority::HIGH_IDLE );
+ m_aDragScrollIdle.Start();
+ }
+
+ // redraw DraggingRect
+ m_aDragRect = tools::Rectangle(m_ptPrevDraggingPos - m_aDragOffset, m_pDragWin->GetSizePixel());
+ PaintImmediately();
+ ShowTracking( m_aDragRect, ShowTrackFlags::Small | ShowTrackFlags::TrackWindow );
+}
+
+IMPL_LINK_NOARG(OJoinTableView, OnDragScrollTimer, Timer *, void)
+{
+ ScrollWhileDragging();
+}
+
+void OJoinTableView::invalidateAndModify(std::unique_ptr<SfxUndoAction> _pAction)
+{
+ Invalidate(InvalidateFlags::NoChildren);
+ m_pView->getController().addUndoActionAndInvalidate(std::move(_pAction));
+}
+
+void OJoinTableView::TabWinMoved(OTableWindow* ptWhich, const Point& ptOldPosition)
+{
+ Point ptThumbPos(GetHScrollBar().GetThumbPos(), GetVScrollBar().GetThumbPos());
+ ptWhich->GetData()->SetPosition(ptWhich->GetPosPixel() + ptThumbPos);
+
+ invalidateAndModify(std::make_unique<OJoinMoveTabWinUndoAct>(this, ptOldPosition, ptWhich));
+}
+
+void OJoinTableView::TabWinSized(OTableWindow* ptWhich, const Point& ptOldPosition, const Size& szOldSize)
+{
+ ptWhich->GetData()->SetSize(ptWhich->GetSizePixel());
+ ptWhich->GetData()->SetPosition(ptWhich->GetPosPixel());
+
+ invalidateAndModify(std::make_unique<OJoinSizeTabWinUndoAct>(this, ptOldPosition, szOldSize, ptWhich));
+}
+
+bool OJoinTableView::IsAddAllowed()
+{
+
+ // not, if Db readonly
+ if (m_pView->getController().isReadOnly())
+ return false;
+
+ try
+ {
+ Reference< XConnection> xConnection = m_pView->getController().getConnection();
+ if(!xConnection.is())
+ return false;
+ // not, if too many tables already
+ Reference < XDatabaseMetaData > xMetaData( xConnection->getMetaData() );
+
+ sal_Int32 nMax = xMetaData.is() ? xMetaData->getMaxTablesInSelect() : 0;
+ if (nMax && nMax <= static_cast<sal_Int32>(m_aTableMap.size()))
+ return false;
+ }
+ catch(SQLException&)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+void OJoinTableView::executePopup(const Point& rPos, VclPtr<OTableConnection>& rSelConnection)
+{
+ ::tools::Rectangle aRect(rPos, Size(1, 1));
+ weld::Window* pPopupParent = weld::GetPopupParent(*this, aRect);
+ std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(pPopupParent, "dbaccess/ui/joinviewmenu.ui"));
+ std::unique_ptr<weld::Menu> xContextMenu(xBuilder->weld_menu("menu"));
+ OString sIdent = xContextMenu->popup_at_rect(pPopupParent, aRect);
+ if (sIdent == "delete")
+ RemoveConnection(rSelConnection, true);
+ else if (sIdent == "edit")
+ ConnDoubleClicked(rSelConnection); // is the same as double clicked
+}
+
+void OJoinTableView::Command(const CommandEvent& rEvt)
+{
+
+ bool bHandled = false;
+
+ switch (rEvt.GetCommand())
+ {
+ case CommandEventId::ContextMenu:
+ {
+ if( m_vTableConnection.empty() )
+ return;
+
+ VclPtr<OTableConnection>& rSelConnection = GetSelectedConn();
+ // when it wasn't a mouse event use the selected connection
+ if (!rEvt.IsMouseEvent())
+ {
+ if (rSelConnection)
+ {
+ const std::vector<std::unique_ptr<OConnectionLine>>& rLines = rSelConnection->GetConnLineList();
+ auto aIter = std::find_if(rLines.begin(), rLines.end(),std::mem_fn(&OConnectionLine::IsValid));
+ if( aIter != rLines.end() )
+ executePopup((*aIter)->getMidPoint(), rSelConnection);
+ }
+ }
+ else
+ {
+ DeselectConn(rSelConnection);
+
+ const Point& aMousePos = rEvt.GetMousePosPixel();
+ for (auto & elem : m_vTableConnection)
+ {
+ if( elem->CheckHit(aMousePos) )
+ {
+ SelectConn(elem);
+ if(!getDesignView()->getController().isReadOnly() && getDesignView()->getController().isConnected())
+ executePopup(rEvt.GetMousePosPixel(),elem);
+ break;
+ }
+ }
+ }
+ bHandled = true;
+ }
+ break;
+ default: break;
+ }
+ if (!bHandled)
+ Window::Command(rEvt);
+}
+
+OTableConnection* OJoinTableView::GetTabConn(const OTableWindow* pLhs,const OTableWindow* pRhs,bool _bSuppressCrossOrNaturalJoin) const
+{
+ OTableConnection* pConn = nullptr;
+ OSL_ENSURE(pRhs || pLhs, "OJoinTableView::GetTabConn : invalid args !");
+ // only one NULL-arg allowed
+
+ if ((!pLhs || pLhs->ExistsAConn()) && (!pRhs || pRhs->ExistsAConn()))
+ {
+ for(VclPtr<OTableConnection> const & pData : m_vTableConnection)
+ {
+ if ( ( (pData->GetSourceWin() == pLhs)
+ && ( (pData->GetDestWin() == pRhs)
+ || (nullptr == pRhs)
+ )
+ )
+ || ( (pData->GetSourceWin() == pRhs)
+ && ( (pData->GetDestWin() == pLhs)
+ || (nullptr == pLhs)
+ )
+ )
+ )
+ {
+ if ( _bSuppressCrossOrNaturalJoin )
+ {
+ if ( suppressCrossNaturalJoin(pData->GetData()) )
+ continue;
+ }
+ pConn = pData;
+ break;
+ }
+ }
+ }
+ return pConn;
+}
+
+bool OJoinTableView::PreNotify(NotifyEvent& rNEvt)
+{
+ bool bHandled = false;
+ switch (rNEvt.GetType())
+ {
+ case MouseNotifyEvent::COMMAND:
+ {
+ const CommandEvent* pCommand = rNEvt.GetCommandEvent();
+ if (pCommand->GetCommand() == CommandEventId::Wheel)
+ {
+ const CommandWheelData* pData = rNEvt.GetCommandEvent()->GetWheelData();
+ if (pData->GetMode() == CommandWheelMode::SCROLL)
+ {
+ if (pData->GetDelta() > 0)
+ ScrollPane(-10 * pData->GetScrollLines(), pData->IsHorz(), true);
+ else
+ ScrollPane(10 * pData->GetScrollLines(), pData->IsHorz(), true);
+ bHandled = true;
+ }
+ }
+ }
+ break;
+ case MouseNotifyEvent::KEYINPUT:
+ {
+ if (m_aTableMap.empty())
+ // no tab wins -> no conns -> no traveling
+ break;
+
+ const KeyEvent* pKeyEvent = rNEvt.GetKeyEvent();
+ if (!pKeyEvent->GetKeyCode().IsMod1())
+ {
+ switch (pKeyEvent->GetKeyCode().GetCode())
+ {
+ case KEY_TAB:
+ {
+ if (!HasChildPathFocus())
+ break;
+
+ bool bForward = !pKeyEvent->GetKeyCode().IsShift();
+ // is there an active tab win ?
+ OTableWindowMap::const_iterator aIter = std::find_if(m_aTableMap.begin(), m_aTableMap.end(),
+ [](const OTableWindowMap::value_type& rEntry) { return rEntry.second && rEntry.second->HasChildPathFocus(); });
+
+ OTableWindow* pNextWin = nullptr;
+ OTableConnection* pNextConn = nullptr;
+
+ if (aIter != m_aTableMap.end())
+ { // there is a currently active tab win
+ // check if there is an "overflow" and we should select a conn instead of a win
+ if (!m_vTableConnection.empty())
+ {
+ if ((aIter->second == m_aTableMap.rbegin()->second) && bForward)
+ // the last win is active and we're travelling forward -> select the first conn
+ pNextConn = m_vTableConnection.begin()->get();
+ if ((aIter == m_aTableMap.begin()) && !bForward)
+ // the first win is active and we're traveling backward -> select the last conn
+ pNextConn = m_vTableConnection.rbegin()->get();
+ }
+
+ if (!pNextConn)
+ {
+ // no conn for any reason -> select the next or previous tab win
+ if(bForward)
+ {
+ if ( aIter->second == m_aTableMap.rbegin()->second )
+ pNextWin = m_aTableMap.begin()->second;
+ else
+ {
+ ++aIter;
+ pNextWin = aIter->second;
+ }
+ }
+ else
+ {
+ if (aIter == m_aTableMap.begin())
+ pNextWin = m_aTableMap.rbegin()->second;
+ else
+ {
+ --aIter;
+ pNextWin = aIter->second;
+ }
+ }
+ }
+ }
+ else
+ { // no active tab win -> travel the connections
+ // find the currently selected conn within the conn list
+ sal_Int32 i(0);
+ for (auto const& elem : m_vTableConnection)
+ {
+ if ( elem.get() == GetSelectedConn() )
+ break;
+ ++i;
+ }
+ if (i == sal_Int32(m_vTableConnection.size() - 1) && bForward)
+ // the last conn is active and we're travelling forward -> select the first win
+ pNextWin = m_aTableMap.begin()->second;
+ if ((i == 0) && !bForward && !m_aTableMap.empty())
+ // the first conn is active and we're travelling backward -> select the last win
+ pNextWin = m_aTableMap.rbegin()->second;
+
+ if (pNextWin)
+ DeselectConn(GetSelectedConn());
+ else
+ // no win for any reason -> select the next or previous conn
+ if (i < static_cast<sal_Int32>(m_vTableConnection.size()))
+ // there is a currently active conn
+ pNextConn = m_vTableConnection[(i + (bForward ? 1 : m_vTableConnection.size() - 1)) % m_vTableConnection.size()].get();
+ else
+ { // no tab win selected, no conn selected
+ if (!m_vTableConnection.empty())
+ pNextConn = m_vTableConnection[bForward ? 0 : m_vTableConnection.size() - 1].get();
+ else if (!m_aTableMap.empty())
+ {
+ if(bForward)
+ pNextWin = m_aTableMap.begin()->second;
+ else
+ pNextWin = m_aTableMap.rbegin()->second;
+ }
+ }
+ }
+
+ // now select the object
+ if (pNextWin)
+ {
+ if (pNextWin->GetListBox())
+ pNextWin->GetListBox()->GrabFocus();
+ else
+ pNextWin->GrabFocus();
+ EnsureVisible(pNextWin);
+ }
+ else if (pNextConn)
+ {
+ GrabFocus();
+ // necessary : a conn may be selected even if a tab win has the focus, in this case
+ // the next travel would select the same conn again if we would not reset the focus ...
+ SelectConn(pNextConn);
+ }
+ }
+ break;
+ case KEY_RETURN:
+ {
+ if (!pKeyEvent->GetKeyCode().IsShift() && GetSelectedConn() && HasFocus())
+ ConnDoubleClicked(GetSelectedConn());
+ break;
+ }
+ }
+ }
+ }
+ break;
+ case MouseNotifyEvent::GETFOCUS:
+ {
+ if (m_aTableMap.empty())
+ // no tab wins -> no conns -> no focus change
+ break;
+ vcl::Window* pSource = rNEvt.GetWindow();
+ if (pSource)
+ {
+ vcl::Window* pSearchFor = nullptr;
+ if (pSource->GetParent() == this)
+ // it may be one of the tab wins
+ pSearchFor = pSource;
+ else if (pSource->GetParent() && (pSource->GetParent()->GetParent() == this))
+ // it may be one of th list boxes of one of the tab wins
+ pSearchFor = pSource->GetParent();
+
+ if (pSearchFor)
+ {
+ for (auto const& elem : m_aTableMap)
+ {
+ if (elem.second == pSearchFor)
+ {
+ m_pLastFocusTabWin = elem.second;
+ break;
+ }
+ }
+ }
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (!bHandled)
+ return Window::PreNotify(rNEvt);
+ return true;
+}
+
+void OJoinTableView::GrabTabWinFocus()
+{
+ if (m_pLastFocusTabWin && m_pLastFocusTabWin->IsVisible())
+ {
+ if (m_pLastFocusTabWin->GetListBox())
+ m_pLastFocusTabWin->GetListBox()->GrabFocus();
+ else
+ m_pLastFocusTabWin->GrabFocus();
+ }
+ else if (!m_aTableMap.empty() && m_aTableMap.begin()->second && m_aTableMap.begin()->second->IsVisible())
+ {
+ VclPtr<OTableWindow> pFirstWin = m_aTableMap.begin()->second;
+ if (pFirstWin->GetListBox())
+ pFirstWin->GetListBox()->GrabFocus();
+ else
+ pFirstWin->GrabFocus();
+ }
+}
+
+void OJoinTableView::StateChanged( StateChangedType nType )
+{
+ Window::StateChanged( nType );
+
+ // FIXME RenderContext
+ if ( nType != StateChangedType::Zoom )
+ return;
+
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+
+ vcl::Font aFont = rStyleSettings.GetGroupFont();
+ if ( IsControlFont() )
+ aFont.Merge( GetControlFont() );
+ SetZoomedPointFont(*GetOutDev(), aFont);
+
+ for (auto const& elem : m_aTableMap)
+ {
+ elem.second->SetZoom(GetZoom());
+ Size aSize(CalcZoom(elem.second->GetSizePixel().Width()),CalcZoom(elem.second->GetSizePixel().Height()));
+ elem.second->SetSizePixel(aSize);
+ }
+ Resize();
+}
+
+void OJoinTableView::HideTabWins()
+{
+ SetUpdateMode(false);
+
+ OTableWindowMap& rTabWins = GetTabWinMap();
+
+ // working on a copy because the real list will be cleared in inner calls
+ OTableWindowMap aCopy(rTabWins);
+ for (auto const& elem : aCopy)
+ RemoveTabWin(elem.second);
+
+ m_pView->getController().setModified(true);
+
+ SetUpdateMode(true);
+
+}
+
+sal_Int8 OJoinTableView::AcceptDrop( const AcceptDropEvent& /*_rEvt*/ )
+{
+ return DND_ACTION_NONE;
+}
+
+sal_Int8 OJoinTableView::ExecuteDrop( const ExecuteDropEvent& /*_rEvt*/ )
+{
+ return DND_ACTION_NONE;
+}
+
+void OJoinTableView::dragFinished( )
+{
+}
+
+void OJoinTableView::clearLayoutInformation()
+{
+ m_pLastFocusTabWin = nullptr;
+ m_pSelectedConn = nullptr;
+ // delete lists
+ for (auto & elem : m_aTableMap)
+ {
+ if ( elem.second )
+ elem.second->clearListBox();
+ elem.second.disposeAndClear();
+ }
+
+ m_aTableMap.clear();
+
+ for (auto & elem : m_vTableConnection)
+ elem.disposeAndClear();
+
+ m_vTableConnection.clear();
+}
+
+void OJoinTableView::lookForUiActivities()
+{
+}
+
+void OJoinTableView::LoseFocus()
+{
+ DeselectConn(GetSelectedConn());
+ Window::LoseFocus();
+}
+
+void OJoinTableView::GetFocus()
+{
+ Window::GetFocus();
+ if ( !m_aTableMap.empty() && !GetSelectedConn() )
+ GrabTabWinFocus();
+}
+
+Reference< XAccessible > OJoinTableView::CreateAccessible()
+{
+ m_pAccessible = new OJoinDesignViewAccess(this);
+ return m_pAccessible;
+}
+
+void OJoinTableView::modified()
+{
+ OJoinController& rController = m_pView->getController();
+ rController.setModified( true );
+ rController.InvalidateFeature(ID_BROWSER_ADDTABLE);
+ rController.InvalidateFeature(SID_RELATION_ADD_RELATION);
+}
+
+void OJoinTableView::addConnection(OTableConnection* _pConnection,bool _bAddData)
+{
+ if ( _bAddData )
+ {
+#if OSL_DEBUG_LEVEL > 0
+ TTableConnectionData& rTabConnDataList = m_pView->getController().getTableConnectionData();
+ OSL_ENSURE( std::find(rTabConnDataList.begin(), rTabConnDataList.end(),_pConnection->GetData()) == rTabConnDataList.end(),"Data already in vector!");
+#endif
+ m_pView->getController().getTableConnectionData().push_back(_pConnection->GetData());
+ }
+ m_vTableConnection.emplace_back(_pConnection);
+ _pConnection->RecalcLines();
+ _pConnection->InvalidateConnection();
+
+ modified();
+ if ( m_pAccessible )
+ m_pAccessible->notifyAccessibleEvent( AccessibleEventId::CHILD,
+ Any(),
+ Any(_pConnection->GetAccessible()));
+}
+
+bool OJoinTableView::allowQueries() const
+{
+ return true;
+}
+
+void OJoinTableView::onNoColumns_throw()
+{
+ OSL_FAIL( "OTableWindow::onNoColumns_throw: cannot really handle this!" );
+ throw SQLException();
+}
+
+bool OJoinTableView::suppressCrossNaturalJoin(const TTableConnectionData::value_type& ) const
+{
+ return false;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/querydesign/QTableConnection.cxx b/dbaccess/source/ui/querydesign/QTableConnection.cxx
new file mode 100644
index 000000000..c5db155f2
--- /dev/null
+++ b/dbaccess/source/ui/querydesign/QTableConnection.cxx
@@ -0,0 +1,73 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "QTableConnection.hxx"
+#include <osl/diagnose.h>
+#include <QueryTableView.hxx>
+
+using namespace dbaui;
+
+OQueryTableConnection::OQueryTableConnection(OQueryTableView* pContainer, const TTableConnectionData::value_type& pTabConnData)
+ : OTableConnection(pContainer, pTabConnData)
+ , m_bVisited(false)
+{
+}
+
+OQueryTableConnection::OQueryTableConnection(const OQueryTableConnection& rConn)
+ : VclReferenceBase(),
+ OTableConnection( rConn )
+ , m_bVisited(false)
+{
+ // no own members, so base class functionality is sufficient
+}
+
+OQueryTableConnection& OQueryTableConnection::operator=(const OQueryTableConnection& rConn)
+{
+ if (&rConn == this)
+ return *this;
+
+ OTableConnection::operator=(rConn);
+ // no own members ...
+ return *this;
+}
+
+bool OQueryTableConnection::operator==(const OQueryTableConnection& rCompare) const
+{
+ OSL_ENSURE(GetData() && rCompare.GetData(), "OQueryTableConnection::operator== : one of the two participants has no data!");
+
+ // I don't have to compare all too much (especially not all the members) : merely the windows, which we are connected to, and the indices in the corresponding table have to match.
+ OQueryTableConnectionData* pMyData = static_cast<OQueryTableConnectionData*>(GetData().get());
+ OQueryTableConnectionData* pCompData = static_cast<OQueryTableConnectionData*>(rCompare.GetData().get());
+
+ // Connections are seen as equal, if source and destination window names and source and destination field Indices match...
+ return ( ( (pMyData->getReferencedTable() == pCompData->getReferencedTable()) &&
+ (pMyData->getReferencingTable() == pCompData->getReferencingTable()) &&
+ (pMyData->GetFieldIndex(JTCS_TO) == pCompData->GetFieldIndex(JTCS_TO)) &&
+ (pMyData->GetFieldIndex(JTCS_FROM) == pCompData->GetFieldIndex(JTCS_FROM))
+ )
+ || // ... or this cross matching is given
+ ( (pMyData->getReferencingTable() == pCompData->getReferencedTable()) &&
+ (pMyData->getReferencedTable() == pCompData->getReferencingTable()) &&
+ (pMyData->GetFieldIndex(JTCS_TO) == pCompData->GetFieldIndex(JTCS_FROM)) &&
+ (pMyData->GetFieldIndex(JTCS_FROM) == pCompData->GetFieldIndex(JTCS_TO))
+ )
+ );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/querydesign/QTableConnection.hxx b/dbaccess/source/ui/querydesign/QTableConnection.hxx
new file mode 100644
index 000000000..c6bd2e10d
--- /dev/null
+++ b/dbaccess/source/ui/querydesign/QTableConnection.hxx
@@ -0,0 +1,46 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <TableConnection.hxx>
+#include "QTableConnectionData.hxx"
+#include <QEnumTypes.hxx>
+
+namespace dbaui
+{
+ class OQueryTableView;
+ class OQueryTableConnection : public OTableConnection
+ {
+ bool m_bVisited; // is true if the conn was already visited through the join algorithm
+ public:
+ OQueryTableConnection(OQueryTableView* pContainer, const TTableConnectionData::value_type& pTabConnData);
+ OQueryTableConnection(const OQueryTableConnection& rConn);
+
+ OQueryTableConnection& operator=(const OQueryTableConnection& rConn);
+ bool operator==(const OQueryTableConnection& rCompare) const;
+
+ OUString const & GetAliasName(EConnectionSide nWhich) const { return static_cast<OQueryTableConnectionData*>(GetData().get())->GetAliasName(nWhich); }
+
+ bool IsVisited() const { return m_bVisited; }
+ void SetVisited(bool bVisited) { m_bVisited = bVisited; }
+
+ };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/querydesign/QTableConnectionData.cxx b/dbaccess/source/ui/querydesign/QTableConnectionData.cxx
new file mode 100644
index 000000000..ce66828fa
--- /dev/null
+++ b/dbaccess/source/ui/querydesign/QTableConnectionData.cxx
@@ -0,0 +1,112 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "QTableConnectionData.hxx"
+#include "QTableWindow.hxx"
+
+#include <osl/diagnose.h>
+
+using namespace dbaui;
+
+OQueryTableConnectionData::OQueryTableConnectionData()
+ : m_nFromEntryIndex(0)
+ , m_nDestEntryIndex(0)
+ , m_eJoinType (INNER_JOIN)
+ , m_bNatural(false)
+{
+}
+
+OQueryTableConnectionData::OQueryTableConnectionData( const OQueryTableConnectionData& rConnData )
+ : OTableConnectionData( rConnData )
+ , m_nFromEntryIndex(rConnData.m_nFromEntryIndex)
+ , m_nDestEntryIndex(rConnData.m_nDestEntryIndex)
+ , m_eJoinType(rConnData.m_eJoinType)
+ , m_bNatural(rConnData.m_bNatural)
+{
+}
+
+OQueryTableConnectionData::OQueryTableConnectionData(const TTableWindowData::value_type& _pReferencingTable,
+ const TTableWindowData::value_type& _pReferencedTable)
+ : OTableConnectionData( _pReferencingTable,_pReferencedTable )
+ , m_nFromEntryIndex(0)
+ , m_nDestEntryIndex(0)
+ , m_eJoinType (INNER_JOIN)
+ , m_bNatural(false)
+{
+}
+
+OQueryTableConnectionData::~OQueryTableConnectionData()
+{
+}
+
+void OQueryTableConnectionData::CopyFrom(const OTableConnectionData& rSource)
+{
+ // same as in base class, use of (non-virtual) operator=
+ *this = static_cast<const OQueryTableConnectionData&>(rSource);
+}
+
+OQueryTableConnectionData& OQueryTableConnectionData::operator=(const OQueryTableConnectionData& rConnData)
+{
+ if (&rConnData == this)
+ return *this;
+
+ OTableConnectionData::operator=(rConnData);
+
+ m_nFromEntryIndex = rConnData.m_nFromEntryIndex;
+ m_nDestEntryIndex = rConnData.m_nDestEntryIndex;
+
+ m_eJoinType = rConnData.m_eJoinType;
+ m_bNatural = rConnData.m_bNatural;
+
+ return *this;
+}
+
+OUString const & OQueryTableConnectionData::GetAliasName(EConnectionSide nWhich) const
+{
+ return nWhich == JTCS_FROM ? m_pReferencingTable->GetWinName() : m_pReferencedTable->GetWinName();
+}
+
+void OQueryTableConnectionData::InitFromDrag(const OTableFieldDescRef& rDragLeft, const OTableFieldDescRef& rDragRight)
+{
+ // convert Information in rDrag into parameters for the base class init
+ OQueryTableWindow* pSourceWin = static_cast<OQueryTableWindow*>(rDragLeft->GetTabWindow());
+ OQueryTableWindow* pDestWin = static_cast<OQueryTableWindow*>(rDragRight->GetTabWindow());
+ OSL_ENSURE(pSourceWin,"NO Source window found!");
+ OSL_ENSURE(pDestWin,"NO Dest window found!");
+ m_pReferencingTable = pSourceWin->GetData();
+ m_pReferencedTable = pDestWin->GetData();
+
+ // set members
+ SetFieldIndex(JTCS_FROM, rDragLeft->GetFieldIndex());
+ SetFieldIndex(JTCS_TO, rDragRight->GetFieldIndex());
+
+ AppendConnLine(rDragLeft->GetField(), rDragRight->GetField());
+}
+
+std::shared_ptr<OTableConnectionData> OQueryTableConnectionData::NewInstance() const
+{
+ return std::make_shared<OQueryTableConnectionData>();
+}
+
+bool OQueryTableConnectionData::Update()
+{
+ return true;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/querydesign/QTableConnectionData.hxx b/dbaccess/source/ui/querydesign/QTableConnectionData.hxx
new file mode 100644
index 000000000..7ccbb03ac
--- /dev/null
+++ b/dbaccess/source/ui/querydesign/QTableConnectionData.hxx
@@ -0,0 +1,67 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <TableConnectionData.hxx>
+#include <TableFieldDescription.hxx>
+#include <QEnumTypes.hxx>
+
+namespace dbaui
+{
+ class OQueryTableConnectionData final : public OTableConnectionData
+ {
+ sal_Int32 m_nFromEntryIndex;
+ sal_Int32 m_nDestEntryIndex;
+ EJoinType m_eJoinType;
+ bool m_bNatural;
+
+ OQueryTableConnectionData& operator=( const OQueryTableConnectionData& rConnData );
+ public:
+ OQueryTableConnectionData();
+ OQueryTableConnectionData( const OQueryTableConnectionData& rConnData );
+ OQueryTableConnectionData( const TTableWindowData::value_type& _pReferencingTable,const TTableWindowData::value_type& _pReferencedTable );
+ virtual ~OQueryTableConnectionData() override;
+
+ virtual void CopyFrom(const OTableConnectionData& rSource) override;
+ virtual std::shared_ptr<OTableConnectionData> NewInstance() const override;
+
+
+ /** Update create a new connection
+
+ @return true if successful
+ */
+ virtual bool Update() override;
+
+ OUString const & GetAliasName(EConnectionSide nWhich) const;
+
+ sal_Int32 GetFieldIndex(EConnectionSide nWhich) const { return nWhich==JTCS_TO ? m_nDestEntryIndex : m_nFromEntryIndex; }
+ void SetFieldIndex(EConnectionSide nWhich, sal_Int32 nVal) { if (nWhich==JTCS_TO) m_nDestEntryIndex=nVal; else m_nFromEntryIndex=nVal; }
+
+ void InitFromDrag(const OTableFieldDescRef& rDragLeft, const OTableFieldDescRef& rDragRight);
+
+ EJoinType GetJoinType() const { return m_eJoinType; };
+ void SetJoinType(const EJoinType& eJT) { m_eJoinType = eJT; };
+
+ void setNatural(bool _bNatural) { m_bNatural = _bNatural; }
+ bool isNatural() const { return m_bNatural; }
+ };
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/querydesign/QTableWindow.cxx b/dbaccess/source/ui/querydesign/QTableWindow.cxx
new file mode 100644
index 000000000..6b129c32d
--- /dev/null
+++ b/dbaccess/source/ui/querydesign/QTableWindow.cxx
@@ -0,0 +1,175 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "QTableWindow.hxx"
+#include <QueryTableView.hxx>
+#include <JoinController.hxx>
+#include <JoinDesignView.hxx>
+#include <osl/diagnose.h>
+#include <helpids.h>
+#include <browserids.hxx>
+#include <TableWindowListBox.hxx>
+#include <strings.hxx>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/sdbc/SQLException.hpp>
+#include "TableFieldInfo.hxx"
+#include <comphelper/stl_types.hxx>
+#include <comphelper/types.hxx>
+
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::beans;
+using namespace dbaui;
+OQueryTableWindow::OQueryTableWindow( vcl::Window* pParent, const TTableWindowData::value_type& pTabWinData)
+ :OTableWindow( pParent, pTabWinData )
+ ,m_nAliasNum(0)
+{
+ m_strInitialAlias = GetAliasName();
+
+ // if table name matches alias, do not pass to InitialAlias,
+ // as the appending of a possible token could not succeed...
+ if (m_strInitialAlias == pTabWinData->GetTableName())
+ m_strInitialAlias.clear();
+
+ SetHelpId(HID_CTL_QRYDGNTAB);
+}
+
+bool OQueryTableWindow::Init()
+{
+ bool bSuccess = OTableWindow::Init();
+ if (!bSuccess)
+ return bSuccess;
+
+ OQueryTableView* pContainer = static_cast<OQueryTableView*>(getTableView());
+
+ // first determine Alias
+ OUString sAliasName;
+
+ TTableWindowData::value_type pWinData = GetData();
+
+ if (!m_strInitialAlias.isEmpty() )
+ // Alias was explicitly given
+ sAliasName = m_strInitialAlias;
+ else if ( GetTable().is() )
+ GetTable()->getPropertyValue( PROPERTY_NAME ) >>= sAliasName;
+ else
+ return false;
+
+ // Alias with successive number
+ if (pContainer->CountTableAlias(sAliasName, m_nAliasNum))
+ {
+ sAliasName += "_" + OUString::number(m_nAliasNum);
+ }
+
+ sAliasName = sAliasName.replaceAll("\"", "");
+ SetAliasName(sAliasName);
+ // SetAliasName passes it as WinName, hence it uses the base class
+ // reset the title
+ m_xTitle->SetText( pWinData->GetWinName() );
+ m_xTitle->Show();
+
+ getTableView()->getDesignView()->getController().InvalidateFeature(ID_BROWSER_QUERY_EXECUTE);
+ return bSuccess;
+}
+
+void* OQueryTableWindow::createUserData(const Reference< XPropertySet>& _xColumn,bool _bPrimaryKey)
+{
+ OTableFieldInfo* pInfo = new OTableFieldInfo();
+ pInfo->SetKey(_bPrimaryKey ? TAB_PRIMARY_FIELD : TAB_NORMAL_FIELD);
+ if ( _xColumn.is() )
+ pInfo->SetDataType(::comphelper::getINT32(_xColumn->getPropertyValue(PROPERTY_TYPE)));
+ return pInfo;
+}
+
+void OQueryTableWindow::deleteUserData(void*& _pUserData)
+{
+ delete static_cast<OTableFieldInfo*>(_pUserData);
+ _pUserData = nullptr;
+}
+
+void OQueryTableWindow::OnEntryDoubleClicked(weld::TreeIter& rEntry)
+{
+ if (getTableView()->getDesignView()->getController().isReadOnly())
+ return;
+
+ weld::TreeView& rTreeView = m_xListBox->get_widget();
+ OTableFieldInfo* pInf = weld::fromId<OTableFieldInfo*>(rTreeView.get_id(rEntry));
+ OSL_ENSURE(pInf != nullptr, "OQueryTableWindow::OnEntryDoubleClicked : field doesn't have FieldInfo !");
+
+ // build up DragInfo
+ OTableFieldDescRef aInfo = new OTableFieldDesc(GetTableName(), rTreeView.get_text(rEntry));
+ aInfo->SetTabWindow(this);
+ aInfo->SetAlias(GetAliasName());
+ aInfo->SetFieldIndex(rTreeView.get_iter_index_in_parent(rEntry));
+ aInfo->SetDataType(pInf->GetDataType());
+
+ // and insert corresponding field
+ static_cast<OQueryTableView*>(getTableView())->InsertField(aInfo);
+}
+
+bool OQueryTableWindow::ExistsField(const OUString& strFieldName, OTableFieldDescRef const & rInfo)
+{
+ OSL_ENSURE(m_xListBox != nullptr, "OQueryTableWindow::ExistsField : doesn't have css::form::ListBox !");
+ OSL_ENSURE(rInfo.is(),"OQueryTableWindow::ExistsField: invalid argument for OTableFieldDescRef!");
+ Reference< XConnection> xConnection = getTableView()->getDesignView()->getController().getConnection();
+ bool bExists = false;
+ if(xConnection.is())
+ {
+ weld::TreeView& rTreeView = m_xListBox->get_widget();
+ std::unique_ptr<weld::TreeIter> xEntry(rTreeView.make_iterator());
+ bool bEntry = rTreeView.get_iter_first(*xEntry);
+ try
+ {
+ Reference<XDatabaseMetaData> xMeta = xConnection->getMetaData();
+ ::comphelper::UStringMixEqual bCase(xMeta.is() && xMeta->supportsMixedCaseQuotedIdentifiers());
+
+ while (bEntry)
+ {
+ if (bCase(strFieldName, rTreeView.get_text(*xEntry)))
+ {
+ OTableFieldInfo* pInf = weld::fromId<OTableFieldInfo*>(rTreeView.get_id(*xEntry));
+ assert(pInf && "OQueryTableWindow::ExistsField : field doesn't have FieldInfo !");
+
+ rInfo->SetTabWindow(this);
+ rInfo->SetField(strFieldName);
+ rInfo->SetTable(GetTableName());
+ rInfo->SetAlias(GetAliasName());
+ rInfo->SetFieldIndex(rTreeView.get_iter_index_in_parent(*xEntry));
+ rInfo->SetDataType(pInf->GetDataType());
+ bExists = true;
+ break;
+ }
+ bEntry = rTreeView.iter_next(*xEntry);
+ }
+ }
+ catch(SQLException&)
+ {
+ }
+ }
+
+ return bExists;
+}
+
+bool OQueryTableWindow::ExistsAVisitedConn() const
+{
+ return static_cast<const OQueryTableView*>(getTableView())->ExistsAVisitedConn(this);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/querydesign/QTableWindow.hxx b/dbaccess/source/ui/querydesign/QTableWindow.hxx
new file mode 100644
index 000000000..72c698c83
--- /dev/null
+++ b/dbaccess/source/ui/querydesign/QTableWindow.hxx
@@ -0,0 +1,76 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <TableWindow.hxx>
+#include "QTableWindowData.hxx"
+#include <TableFieldDescription.hxx>
+
+namespace dbaui
+{
+ class OQueryTableWindow : public OTableWindow
+ {
+ sal_Int32 m_nAliasNum;
+ OUString m_strInitialAlias;
+ public:
+ OQueryTableWindow( vcl::Window* pParent, const TTableWindowData::value_type& pTabWinData );
+
+ OUString const & GetAliasName() const
+ {
+ return static_cast<OQueryTableWindowData*>(GetData().get())->GetAliasName();
+ }
+ void SetAliasName(const OUString& strNewAlias)
+ {
+ static_cast<OQueryTableWindowData*>(GetData().get())->SetAliasName(strNewAlias);
+ }
+
+ // late Constructor, the base class CREATES Listbox on first call
+ virtual bool Init() override;
+
+ bool ExistsField(const OUString& strFieldName, OTableFieldDescRef const & rInfo);
+ bool ExistsAVisitedConn() const;
+
+ virtual OUString GetName() const override { return GetWinName(); }
+
+ protected:
+
+ virtual void OnEntryDoubleClicked(weld::TreeIter& rEntry) override;
+ // is called from DoubleClickHdl of the ListBox
+ /** delete the user data with the equal type as created within createUserData
+ @param _pUserData
+ The user data store in the listbox entries. Created with a call to createUserData.
+ _pUserData may be <NULL/>.
+ */
+ virtual void deleteUserData(void*& _pUserData) override;
+
+ /** creates user information that will be append at the ListBoxentry
+ @param _xColumn
+ The corresponding column, can be <NULL/>.
+ @param _bPrimaryKey
+ <TRUE/> when the column belongs to the primary key
+ @return
+ the user data which will be append at the listbox entry, may be <NULL/>
+ */
+ virtual void* createUserData(const css::uno::Reference<
+ css::beans::XPropertySet>& _xColumn,
+ bool _bPrimaryKey) override;
+ };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/querydesign/QTableWindowData.cxx b/dbaccess/source/ui/querydesign/QTableWindowData.cxx
new file mode 100644
index 000000000..d8f2f2efd
--- /dev/null
+++ b/dbaccess/source/ui/querydesign/QTableWindowData.cxx
@@ -0,0 +1,34 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "QTableWindowData.hxx"
+
+using namespace dbaui;
+using namespace ::com::sun::star::uno;
+
+OQueryTableWindowData::OQueryTableWindowData(const OUString& _rComposedName, const OUString& rTableName, const OUString& rTableAlias )
+ :OTableWindowData(nullptr,_rComposedName, rTableName, rTableAlias)
+{
+}
+
+OQueryTableWindowData::~OQueryTableWindowData()
+{
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/querydesign/QTableWindowData.hxx b/dbaccess/source/ui/querydesign/QTableWindowData.hxx
new file mode 100644
index 000000000..327dc27f1
--- /dev/null
+++ b/dbaccess/source/ui/querydesign/QTableWindowData.hxx
@@ -0,0 +1,38 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <TableWindowData.hxx>
+
+
+namespace dbaui
+{
+ class OQueryTableWindowData : public OTableWindowData
+ {
+ public:
+ explicit OQueryTableWindowData(const OUString& _rComposedName, const OUString& rTableName, const OUString& rTableAlias);
+ virtual ~OQueryTableWindowData() override;
+
+ OUString const & GetAliasName() const { return GetWinName(); }
+ void SetAliasName(const OUString& rNewAlias) { SetWinName(rNewAlias); }
+ };
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/querydesign/QueryAddTabConnUndoAction.hxx b/dbaccess/source/ui/querydesign/QueryAddTabConnUndoAction.hxx
new file mode 100644
index 000000000..dd641be1d
--- /dev/null
+++ b/dbaccess/source/ui/querydesign/QueryAddTabConnUndoAction.hxx
@@ -0,0 +1,49 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "QueryTabConnUndoAction.hxx"
+
+namespace dbaui
+{
+ // OQueryAddTabConnUndoAction - Undo class for inserting a connection
+
+ class OQueryTableView;
+ class OQueryAddTabConnUndoAction : public OQueryTabConnUndoAction
+ {
+ public:
+ explicit OQueryAddTabConnUndoAction(OQueryTableView* pOwner);
+
+ virtual void Undo() override;
+ virtual void Redo() override;
+ };
+
+ // OQueryDelTabConnUndoAction - Undo class for inserting a connection
+
+ class OQueryDelTabConnUndoAction : public OQueryTabConnUndoAction
+ {
+ public:
+ explicit OQueryDelTabConnUndoAction(OQueryTableView* pOwner);
+
+ virtual void Undo() override;
+ virtual void Redo() override;
+ };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/querydesign/QueryDesignFieldUndoAct.hxx b/dbaccess/source/ui/querydesign/QueryDesignFieldUndoAct.hxx
new file mode 100644
index 000000000..13262f570
--- /dev/null
+++ b/dbaccess/source/ui/querydesign/QueryDesignFieldUndoAct.hxx
@@ -0,0 +1,138 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <GeneralUndo.hxx>
+#include <strings.hrc>
+#include "SelectionBrowseBox.hxx"
+#include <osl/diagnose.h>
+
+namespace dbaui
+{
+ // OQueryDesignFieldUndoAct - Basisclass for undo's in the fieldlist of a query design
+
+ class OQueryDesignFieldUndoAct : public OCommentUndoAction
+ {
+ protected:
+ VclPtr<OSelectionBrowseBox> pOwner;
+ sal_uInt16 m_nColumnPosition;
+
+ virtual void Undo() override = 0;
+ virtual void Redo() override = 0;
+
+ public:
+ OQueryDesignFieldUndoAct(OSelectionBrowseBox* pSelBrwBox, TranslateId pCommentID);
+ virtual ~OQueryDesignFieldUndoAct() override;
+
+ void SetColumnPosition(sal_uInt16 _nColumnPosition)
+ {
+ m_nColumnPosition = _nColumnPosition;
+ OSL_ENSURE(m_nColumnPosition != BROWSER_INVALIDID,"Column position was not set add the undo action!");
+ OSL_ENSURE(m_nColumnPosition < pOwner->GetColumnCount(),"Position outside the column count!");
+ }
+ };
+
+ // OTabFieldCellModifiedUndoAct - undo class to change a line of the column description
+
+ class OTabFieldCellModifiedUndoAct final : public OQueryDesignFieldUndoAct
+ {
+ OUString m_strNextCellContents;
+ sal_Int32 m_nCellIndex;
+
+ public:
+ explicit OTabFieldCellModifiedUndoAct(OSelectionBrowseBox* pSelBrwBox)
+ : OQueryDesignFieldUndoAct(pSelBrwBox, STR_QUERY_UNDO_MODIFY_CELL)
+ ,m_nCellIndex(BROWSER_INVALIDID){ }
+
+ void SetCellContents(const OUString& str) { m_strNextCellContents = str; }
+ void SetCellIndex(sal_Int32 nIndex) { m_nCellIndex = nIndex; }
+
+ virtual void Undo() override;
+ virtual void Redo() override { Undo(); }
+ };
+
+ // OTabFieldSizedUndoAct - undo class to change the column width
+
+ class OTabFieldSizedUndoAct final : public OQueryDesignFieldUndoAct
+ {
+ tools::Long m_nNextWidth;
+
+ public:
+ explicit OTabFieldSizedUndoAct(OSelectionBrowseBox* pSelBrwBox) : OQueryDesignFieldUndoAct(pSelBrwBox, STR_QUERY_UNDO_SIZE_COLUMN), m_nNextWidth(0) { }
+
+ void SetOriginalWidth(tools::Long nWidth) { m_nNextWidth = nWidth; }
+
+ virtual void Undo() override;
+ virtual void Redo() override { Undo(); }
+ };
+
+ // OTabFieldUndoAct - base class for undos in the fieldlist of a query design, which are used to change complete field descriptions
+
+ class OTabFieldUndoAct : public OQueryDesignFieldUndoAct
+ {
+ protected:
+ OTableFieldDescRef pDescr; // the deleted column description
+
+ public:
+ OTabFieldUndoAct(OSelectionBrowseBox* pSelBrwBox, TranslateId pCommentID) : OQueryDesignFieldUndoAct(pSelBrwBox, pCommentID) { }
+
+ void SetTabFieldDescr(OTableFieldDescRef const & pDescription) { pDescr = pDescription; }
+ };
+
+ // OTabFieldDelUndoAct - undo class to delete a field
+
+ class OTabFieldDelUndoAct : public OTabFieldUndoAct
+ {
+ protected:
+ virtual void Undo() override { pOwner->EnterUndoMode();pOwner->InsertColumn(pDescr, m_nColumnPosition);pOwner->LeaveUndoMode(); }
+ virtual void Redo() override { pOwner->EnterUndoMode();pOwner->RemoveColumn(pDescr->GetColumnId());pOwner->LeaveUndoMode(); }
+
+ public:
+ explicit OTabFieldDelUndoAct(OSelectionBrowseBox* pSelBrwBox) : OTabFieldUndoAct(pSelBrwBox, STR_QUERY_UNDO_TABFIELDDELETE) { }
+ };
+
+ // OTabFieldCreateUndoAct - undo class for creating a field
+
+ class OTabFieldCreateUndoAct : public OTabFieldUndoAct
+ {
+ protected:
+ virtual void Undo() override { pOwner->EnterUndoMode();pOwner->RemoveColumn(pDescr->GetColumnId());pOwner->LeaveUndoMode();}
+ virtual void Redo() override { pOwner->EnterUndoMode();pOwner->InsertColumn(pDescr, m_nColumnPosition);pOwner->LeaveUndoMode();}
+
+ public:
+ explicit OTabFieldCreateUndoAct(OSelectionBrowseBox* pSelBrwBox) : OTabFieldUndoAct(pSelBrwBox, STR_QUERY_UNDO_TABFIELDCREATE) { }
+ };
+
+ // OTabFieldMovedUndoAct - Undo class when a field was moved inside the selection
+
+ class OTabFieldMovedUndoAct : public OTabFieldUndoAct
+ {
+ protected:
+ virtual void Undo() override;
+ virtual void Redo() override
+ {
+ Undo();
+ }
+
+ public:
+ explicit OTabFieldMovedUndoAct(OSelectionBrowseBox* pSelBrwBox) : OTabFieldUndoAct(pSelBrwBox, STR_QUERY_UNDO_TABFIELDMOVED) { }
+ };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/querydesign/QueryDesignUndoAction.hxx b/dbaccess/source/ui/querydesign/QueryDesignUndoAction.hxx
new file mode 100644
index 000000000..8a8742393
--- /dev/null
+++ b/dbaccess/source/ui/querydesign/QueryDesignUndoAction.hxx
@@ -0,0 +1,39 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <GeneralUndo.hxx>
+#include <JoinTableView.hxx>
+#include <vcl/vclptr.hxx>
+
+namespace dbaui
+{
+ // OQueryDesignUndoAction - undo base class for actions in graphical query design (without field list)
+ class OJoinTableView;
+ class OQueryDesignUndoAction : public OCommentUndoAction
+ {
+ protected:
+ VclPtr<OJoinTableView> m_pOwner; // in this container it all happens
+
+ public:
+ OQueryDesignUndoAction(OJoinTableView* pOwner, TranslateId pCommentID) : OCommentUndoAction(pCommentID), m_pOwner(pOwner) { }
+ };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/querydesign/QueryDesignView.cxx b/dbaccess/source/ui/querydesign/QueryDesignView.cxx
new file mode 100644
index 000000000..f5e4288e9
--- /dev/null
+++ b/dbaccess/source/ui/querydesign/QueryDesignView.cxx
@@ -0,0 +1,3441 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <QueryDesignView.hxx>
+#include <QueryTableView.hxx>
+#include "QTableWindow.hxx"
+#include <querycontroller.hxx>
+#include <sqlbison.hxx>
+#include <vcl/split.hxx>
+#include <tools/diagnose_ex.h>
+#include <o3tl/safeint.hxx>
+#include <o3tl/string_view.hxx>
+#include <osl/diagnose.h>
+#include <vcl/svapp.hxx>
+#include <vcl/weld.hxx>
+#include <browserids.hxx>
+#include "SelectionBrowseBox.hxx"
+#include <strings.hrc>
+#include <strings.hxx>
+#include <comphelper/string.hxx>
+#include <connectivity/dbtools.hxx>
+#include <connectivity/dbexception.hxx>
+#include <com/sun/star/sdbc/DataType.hpp>
+#include <com/sun/star/container/XNameAccess.hpp>
+#include <com/sun/star/sdbc/ColumnValue.hpp>
+#include <connectivity/PColumn.hxx>
+#include "QTableConnection.hxx"
+#include <ConnectionLineData.hxx>
+#include "QTableConnectionData.hxx"
+#include <core_resource.hxx>
+#include <UITools.hxx>
+#include <querycontainerwindow.hxx>
+#include <unotools/localedatawrapper.hxx>
+#include <unotools/syslocale.hxx>
+#include <memory>
+#include <set>
+#include <string_view>
+
+using namespace ::dbaui;
+using namespace ::utl;
+using namespace ::connectivity;
+using namespace ::dbtools;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::i18n;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::container;
+
+// here we define our functions used in the anonymous namespace to get our header file smaller
+// please look at the book LargeScale C++ to know why
+namespace
+{
+ const char C_AND[] = " AND ";
+ const char C_OR[] = " OR ";
+
+ bool InsertJoin( const OQueryDesignView* _pView,
+ const ::connectivity::OSQLParseNode *pNode);
+
+ SqlParseError InstallFields(OQueryDesignView* _pView,
+ const ::connectivity::OSQLParseNode* pNode,
+ OJoinTableView::OTableWindowMap* pTabList );
+
+ SqlParseError GetGroupCriteria( OQueryDesignView* _pView,
+ OSelectionBrowseBox* _pSelectionBrw,
+ const ::connectivity::OSQLParseNode* pSelectRoot );
+
+ SqlParseError GetHavingCriteria(OQueryDesignView* _pView,
+ OSelectionBrowseBox* _pSelectionBrw,
+ const ::connectivity::OSQLParseNode* pSelectRoot,
+ sal_uInt16& rLevel );
+
+ SqlParseError GetOrderCriteria( OQueryDesignView* _pView,
+ OSelectionBrowseBox* _pSelectionBrw,
+ const ::connectivity::OSQLParseNode* pParseRoot );
+
+ SqlParseError AddFunctionCondition(OQueryDesignView const * _pView,
+ OSelectionBrowseBox* _pSelectionBrw,
+ const ::connectivity::OSQLParseNode * pCondition,
+ const sal_uInt16 nLevel,
+ bool bHaving,
+ bool _bAddOrOnOneLine);
+
+ OUString quoteTableAlias(bool _bQuote, const OUString& _sAliasName, const OUString& _sQuote)
+ {
+ OUString sRet;
+ if ( _bQuote && !_sAliasName.isEmpty() )
+ {
+ sRet = ::dbtools::quoteName(_sQuote,_sAliasName) + ".";
+ }
+ return sRet;
+ }
+ OUString getTableRange(const OQueryDesignView* _pView,const ::connectivity::OSQLParseNode* _pTableRef)
+ {
+ Reference< XConnection> xConnection = static_cast<OQueryController&>(_pView->getController()).getConnection();
+ OUString sTableRange;
+ if ( _pTableRef )
+ {
+ sTableRange = ::connectivity::OSQLParseNode::getTableRange(_pTableRef);
+ if ( sTableRange.isEmpty() )
+ _pTableRef->parseNodeToStr(sTableRange,xConnection,nullptr,false,false);
+ }
+ return sTableRange;
+ }
+ void insertConnection(const OQueryDesignView* _pView,const EJoinType& _eJoinType, const OTableFieldDescRef& _aDragLeft, const OTableFieldDescRef& _aDragRight, bool _bNatural = false)
+ {
+ OQueryTableView* pTableView = static_cast<OQueryTableView*>(_pView->getTableView());
+ OQueryTableConnection* pConn = static_cast<OQueryTableConnection*>( pTableView->GetTabConn(static_cast<OTableWindow*>(_aDragLeft->GetTabWindow()),static_cast<OTableWindow*>(_aDragRight->GetTabWindow()),true));
+
+ if ( !pConn )
+ {
+ auto xInfoData = std::make_shared<OQueryTableConnectionData>();
+ xInfoData->InitFromDrag(_aDragLeft, _aDragRight);
+ xInfoData->SetJoinType(_eJoinType);
+
+ if ( _bNatural )
+ {
+ xInfoData->ResetConnLines();
+ xInfoData->setNatural(_bNatural);
+ try
+ {
+ Reference<XNameAccess> xReferencedTableColumns(xInfoData->getReferencedTable()->getColumns());
+ Sequence< OUString> aSeq = xInfoData->getReferencingTable()->getColumns()->getElementNames();
+ const OUString* pIter = aSeq.getConstArray();
+ const OUString* pEnd = pIter + aSeq.getLength();
+ for(;pIter != pEnd;++pIter)
+ {
+ if ( xReferencedTableColumns->hasByName(*pIter) )
+ xInfoData->AppendConnLine(*pIter,*pIter);
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+
+ ScopedVclPtrInstance< OQueryTableConnection > aInfo(pTableView, xInfoData);
+ // Because OQueryTableConnection never takes ownership of the data passed to it, but only remembers the pointer,
+ // this pointer to a local variable is not critical, as xInfoData and aInfo have the same lifetime
+ pTableView->NotifyTabConnection( *aInfo );
+ }
+ else
+ {
+ OUString aSourceFieldName(_aDragLeft->GetField());
+ OUString aDestFieldName(_aDragRight->GetField());
+ // the connection could point on the other side
+ if(pConn->GetSourceWin() == _aDragRight->GetTabWindow())
+ {
+ OUString aTmp(aSourceFieldName);
+ aSourceFieldName = aDestFieldName;
+ aDestFieldName = aTmp;
+ }
+ pConn->GetData()->AppendConnLine( aSourceFieldName,aDestFieldName);
+ pConn->UpdateLineList();
+ // Modified-Flag
+ // SetModified();
+ // and redraw
+ pConn->RecalcLines();
+ // for the following Invalidate, the new Connection must first be able
+ // to determine its BoundingRect
+ pConn->InvalidateConnection();
+ }
+ }
+ OUString ParseCondition( OQueryController& rController
+ ,const ::connectivity::OSQLParseNode* pCondition
+ ,const OUString& _sDecimal
+ ,const css::lang::Locale& _rLocale
+ ,sal_uInt32 _nStartIndex)
+ {
+ OUString aCondition;
+ Reference< XConnection> xConnection = rController.getConnection();
+ if ( xConnection.is() )
+ {
+ sal_uInt32 nCount = pCondition->count();
+ for(sal_uInt32 i = _nStartIndex ; i < nCount ; ++i)
+ pCondition->getChild(i)->parseNodeToPredicateStr(aCondition,
+ xConnection,
+ rController.getNumberFormatter(),
+ _rLocale,
+ _sDecimal,
+ &rController.getParser().getContext());
+ }
+ return aCondition;
+ }
+ SqlParseError FillOuterJoins(OQueryDesignView const * _pView,
+ const ::connectivity::OSQLParseNode* pTableRefList)
+ {
+ SqlParseError eErrorCode = eOk;
+ sal_uInt32 nCount = pTableRefList->count();
+ bool bError = false;
+ for (sal_uInt32 i=0; !bError && i < nCount; ++i)
+ {
+ const ::connectivity::OSQLParseNode* pParseNode = pTableRefList->getChild(i);
+ const ::connectivity::OSQLParseNode* pJoinNode = nullptr;
+
+ if ( SQL_ISRULE( pParseNode, qualified_join ) || SQL_ISRULE( pParseNode, joined_table ) || SQL_ISRULE( pParseNode, cross_union ) )
+ pJoinNode = pParseNode;
+ else if( SQL_ISRULE(pParseNode,table_ref)
+ && pParseNode->count() == 4 ) // '{' SQL_TOKEN_OJ joined_table '}'
+ pJoinNode = pParseNode->getChild(2);
+
+ if ( pJoinNode )
+ {
+ if ( !InsertJoin(_pView,pJoinNode) )
+ bError = true;
+ }
+ }
+ // check if error occurred
+ if ( bError )
+ eErrorCode = eIllegalJoin;
+
+ return eErrorCode;
+ }
+
+ /** FillDragInfo fills the field description out of the table
+ */
+ SqlParseError FillDragInfo( const OQueryDesignView* _pView,
+ const ::connectivity::OSQLParseNode* pColumnRef,
+ OTableFieldDescRef const & _rDragInfo)
+ {
+ SqlParseError eErrorCode = eOk;
+
+ bool bErg = false;
+
+ OUString aTableRange,aColumnName;
+ ::connectivity::OSQLParseTreeIterator& rParseIter = static_cast<OQueryController&>(_pView->getController()).getParseIterator();
+ rParseIter.getColumnRange( pColumnRef, aColumnName, aTableRange );
+
+ if ( !aTableRange.isEmpty() )
+ {
+ OQueryTableWindow* pSTW = static_cast<OQueryTableView*>(_pView->getTableView())->FindTable( aTableRange );
+ bErg = (pSTW && pSTW->ExistsField( aColumnName, _rDragInfo ) );
+ }
+ if ( !bErg )
+ {
+ sal_uInt16 nCntAccount;
+ bErg = static_cast<OQueryTableView*>(_pView->getTableView())->FindTableFromField(aColumnName, _rDragInfo, nCntAccount);
+ if ( !bErg )
+ bErg = _pView->HasFieldByAliasName(aColumnName, _rDragInfo);
+ }
+ if ( !bErg )
+ {
+ eErrorCode = eColumnNotFound;
+ OUString sError(DBA_RES(STR_QRY_COLUMN_NOT_FOUND));
+ sError = sError.replaceFirst("$name$",aColumnName);
+ _pView->getController().appendError( sError );
+
+ try
+ {
+ Reference<XDatabaseMetaData> xMeta = _pView->getController().getConnection()->getMetaData();
+ if ( xMeta.is() && xMeta->supportsMixedCaseQuotedIdentifiers() )
+ _pView->getController().appendError(DBA_RES(STR_QRY_CHECK_CASESENSITIVE));
+ }
+ catch(Exception&)
+ {
+ }
+ }
+
+ return eErrorCode;
+ }
+ OUString BuildJoinCriteria( const Reference< XConnection>& _xConnection,
+ const OConnectionLineDataVec* pLineDataList,
+ const OQueryTableConnectionData* pData)
+ {
+ OUStringBuffer aCondition;
+ if ( _xConnection.is() )
+ {
+ try
+ {
+ const Reference< XDatabaseMetaData > xMetaData = _xConnection->getMetaData();
+ const OUString aQuote = xMetaData->getIdentifierQuoteString();
+
+ for (auto const& lineData : *pLineDataList)
+ {
+ if(!aCondition.isEmpty())
+ aCondition.append(C_AND);
+ aCondition.append(quoteTableAlias(true,pData->GetAliasName(JTCS_FROM),aQuote));
+ aCondition.append(::dbtools::quoteName(aQuote, lineData->GetFieldName(JTCS_FROM) ));
+ aCondition.append(" = ");
+ aCondition.append(quoteTableAlias(true,pData->GetAliasName(JTCS_TO),aQuote));
+ aCondition.append(::dbtools::quoteName(aQuote, lineData->GetFieldName(JTCS_TO) ));
+ }
+ }
+ catch(SQLException&)
+ {
+ OSL_FAIL("Failure while building Join criteria!");
+ }
+ }
+
+ return aCondition.makeStringAndClear();
+ }
+ /** JoinCycle looks for a join cycle and append it to the string
+ @param _xConnection the connection
+ @param _pEntryConn the table connection which holds the data
+ @param _pEntryTabTo the corresponding table window
+ @param _rJoin the String which will contain the resulting string
+ */
+ void JoinCycle( const Reference< XConnection>& _xConnection,
+ OQueryTableConnection* _pEntryConn,
+ const OQueryTableWindow* _pEntryTabTo,
+ OUString& _rJoin )
+ {
+ OSL_ENSURE(_pEntryConn,"TableConnection can not be null!");
+
+ OQueryTableConnectionData* pData = static_cast< OQueryTableConnectionData*>(_pEntryConn->GetData().get());
+ if ( !(pData->GetJoinType() != INNER_JOIN && _pEntryTabTo->ExistsAVisitedConn()) )
+ return;
+
+ bool bBrace = false;
+ if(_rJoin.endsWith(")"))
+ {
+ bBrace = true;
+ _rJoin = _rJoin.replaceAt(_rJoin.getLength()-1,1, u" ");
+ }
+ _rJoin += C_AND + BuildJoinCriteria(_xConnection,&pData->GetConnLineDataList(),pData);
+ if(bBrace)
+ _rJoin += ")";
+ _pEntryConn->SetVisited(true);
+ }
+ OUString BuildTable( const Reference< XConnection>& _xConnection,
+ const OQueryTableWindow* pEntryTab,
+ bool _bForce = false
+ )
+ {
+ OUString aDBName(pEntryTab->GetComposedName());
+
+ if( _xConnection.is() )
+ {
+ try
+ {
+ Reference< XDatabaseMetaData > xMetaData = _xConnection->getMetaData();
+
+ OUString sCatalog, sSchema, sTable;
+ ::dbtools::qualifiedNameComponents( xMetaData, aDBName, sCatalog, sSchema, sTable, ::dbtools::EComposeRule::InDataManipulation );
+ OUString aTableListStr = ::dbtools::composeTableNameForSelect( _xConnection, sCatalog, sSchema, sTable );
+
+ OUString aQuote = xMetaData->getIdentifierQuoteString();
+ if ( _bForce || isAppendTableAliasEnabled( _xConnection ) || pEntryTab->GetAliasName() != aDBName )
+ {
+ aTableListStr += " ";
+ if ( generateAsBeforeTableAlias( _xConnection ) )
+ aTableListStr += "AS ";
+ aTableListStr += ::dbtools::quoteName( aQuote, pEntryTab->GetAliasName() );
+ }
+ aDBName = aTableListStr;
+ }
+ catch(const SQLException&)
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+ return aDBName;
+ }
+ OUString BuildJoin( const Reference< XConnection>& _xConnection,
+ const OUString& rLh,
+ std::u16string_view rRh,
+ const OQueryTableConnectionData* pData)
+ {
+
+ OUString aErg(rLh);
+ if ( pData->isNatural() && pData->GetJoinType() != CROSS_JOIN )
+ aErg += " NATURAL ";
+ switch(pData->GetJoinType())
+ {
+ case LEFT_JOIN:
+ aErg += " LEFT OUTER ";
+ break;
+ case RIGHT_JOIN:
+ aErg += " RIGHT OUTER ";
+ break;
+ case CROSS_JOIN:
+ OSL_ENSURE(!pData->isNatural(),"OQueryDesignView::BuildJoin: This should not happen!");
+ aErg += " CROSS ";
+ break;
+ case INNER_JOIN:
+ OSL_ENSURE(pData->isNatural(),"OQueryDesignView::BuildJoin: This should not happen!");
+ aErg += " INNER ";
+ break;
+ default:
+ aErg += " FULL OUTER ";
+ break;
+ }
+ aErg += OUString::Concat("JOIN ") + rRh;
+ if ( CROSS_JOIN != pData->GetJoinType() && !pData->isNatural() )
+ {
+ aErg += " ON " + BuildJoinCriteria(_xConnection,&pData->GetConnLineDataList(),pData);
+ }
+
+ return aErg;
+ }
+ OUString BuildJoin( const Reference< XConnection>& _xConnection,
+ const OQueryTableWindow* pLh,
+ const OQueryTableWindow* pRh,
+ const OQueryTableConnectionData* pData
+ )
+ {
+ bool bForce = pData->GetJoinType() == CROSS_JOIN || pData->isNatural();
+ return BuildJoin(_xConnection,BuildTable(_xConnection,pLh,bForce),BuildTable(_xConnection,pRh,bForce),pData);
+ }
+ OUString BuildJoin( const Reference< XConnection>& _xConnection,
+ const OUString &rLh,
+ const OQueryTableWindow* pRh,
+ const OQueryTableConnectionData* pData
+ )
+ {
+ return BuildJoin(_xConnection,rLh,BuildTable(_xConnection,pRh),pData);
+ }
+ OUString BuildJoin( const Reference< XConnection>& _xConnection,
+ const OQueryTableWindow* pLh,
+ const OUString &rRh,
+ const OQueryTableConnectionData* pData
+ )
+ {
+ // strict ANSI SQL:
+ // - does not support any bracketing of JOINS
+ // - supports nested joins only in the LEFT HAND SIDE
+ // In this case, we are trying to build a join with a nested join
+ // in the right hand side.
+ // So switch the direction of the join and both hand sides.
+ OQueryTableConnectionData data(*pData);
+ switch (data.GetJoinType())
+ {
+ case LEFT_JOIN:
+ data.SetJoinType(RIGHT_JOIN);
+ break;
+ case RIGHT_JOIN:
+ data.SetJoinType(LEFT_JOIN);
+ break;
+ default:
+ // the other join types are symmetric, so nothing to change
+ break;
+ }
+ return BuildJoin(_xConnection, rRh, BuildTable(_xConnection,pLh), &data);
+ }
+ void addConnectionTableNames( const Reference< XConnection>& _xConnection,
+ const OQueryTableConnection* const pEntryConn,
+ std::set<OUString> &_rTableNames )
+ {
+ // insert tables into table list to avoid double entries
+ const OQueryTableWindow* const pEntryTabFrom = static_cast<OQueryTableWindow*>(pEntryConn->GetSourceWin());
+ const OQueryTableWindow* const pEntryTabTo = static_cast<OQueryTableWindow*>(pEntryConn->GetDestWin());
+ _rTableNames.insert(BuildTable(_xConnection,pEntryTabFrom));
+ _rTableNames.insert(BuildTable(_xConnection,pEntryTabTo));
+ }
+ void GetNextJoin( const Reference< XConnection>& _xConnection,
+ OQueryTableConnection* pEntryConn,
+ OQueryTableWindow const * pEntryTabTo,
+ OUString &aJoin,
+ std::set<OUString> &_rTableNames)
+ {
+ OQueryTableConnectionData* pEntryConnData = static_cast<OQueryTableConnectionData*>(pEntryConn->GetData().get());
+ if ( pEntryConnData->GetJoinType() == INNER_JOIN && !pEntryConnData->isNatural() )
+ return;
+
+ if(aJoin.isEmpty())
+ {
+ addConnectionTableNames(_xConnection, pEntryConn, _rTableNames);
+ OQueryTableWindow* pEntryTabFrom = static_cast<OQueryTableWindow*>(pEntryConn->GetSourceWin());
+ aJoin = BuildJoin(_xConnection,pEntryTabFrom,pEntryTabTo,pEntryConnData);
+ }
+ else if(pEntryTabTo == pEntryConn->GetDestWin())
+ {
+ addConnectionTableNames(_xConnection, pEntryConn, _rTableNames);
+ aJoin = BuildJoin(_xConnection,aJoin,pEntryTabTo,pEntryConnData);
+ }
+ else if(pEntryTabTo == pEntryConn->GetSourceWin())
+ {
+ addConnectionTableNames(_xConnection, pEntryConn, _rTableNames);
+ aJoin = BuildJoin(_xConnection,pEntryTabTo,aJoin,pEntryConnData);
+ }
+
+ pEntryConn->SetVisited(true);
+
+ // first search for the "to" window
+ const auto& rConnections = pEntryConn->GetParent()->getTableConnections();
+ bool bFound = false;
+ for (auto const& connection : rConnections)
+ {
+ OQueryTableConnection* pNext = static_cast<OQueryTableConnection*>(connection.get());
+ if(!pNext->IsVisited() && (pNext->GetSourceWin() == pEntryTabTo || pNext->GetDestWin() == pEntryTabTo))
+ {
+ OQueryTableWindow* pEntryTab = pNext->GetSourceWin() == pEntryTabTo ? static_cast<OQueryTableWindow*>(pNext->GetDestWin()) : static_cast<OQueryTableWindow*>(pNext->GetSourceWin());
+ // exists there a connection to a OQueryTableWindow that holds a connection that has been already visited
+ JoinCycle(_xConnection,pNext,pEntryTab,aJoin);
+ if(!pNext->IsVisited())
+ GetNextJoin(_xConnection, pNext, pEntryTab, aJoin, _rTableNames);
+ bFound = true;
+ }
+ }
+
+ // when nothing found look for the "from" window
+ if(bFound)
+ return;
+
+ OQueryTableWindow* pEntryTabFrom = static_cast<OQueryTableWindow*>(pEntryConn->GetSourceWin());
+ for (auto const& connection : rConnections)
+ {
+ OQueryTableConnection* pNext = static_cast<OQueryTableConnection*>(connection.get());
+ if(!pNext->IsVisited() && (pNext->GetSourceWin() == pEntryTabFrom || pNext->GetDestWin() == pEntryTabFrom))
+ {
+ OQueryTableWindow* pEntryTab = pNext->GetSourceWin() == pEntryTabFrom ? static_cast<OQueryTableWindow*>(pNext->GetDestWin()) : static_cast<OQueryTableWindow*>(pNext->GetSourceWin());
+ // exists there a connection to a OQueryTableWindow that holds a connection that has been already visited
+ JoinCycle(_xConnection,pNext,pEntryTab,aJoin);
+ if(!pNext->IsVisited())
+ GetNextJoin(_xConnection, pNext, pEntryTab, aJoin, _rTableNames);
+ }
+ }
+ }
+ SqlParseError InsertJoinConnection( const OQueryDesignView* _pView,
+ const ::connectivity::OSQLParseNode *pNode,
+ const EJoinType& _eJoinType,
+ const ::connectivity::OSQLParseNode *pLeftTable,
+ const ::connectivity::OSQLParseNode *pRightTable)
+ {
+ SqlParseError eErrorCode = eOk;
+ if (pNode->count() == 3 && // statement between brackets
+ SQL_ISPUNCTUATION(pNode->getChild(0),"(") &&
+ SQL_ISPUNCTUATION(pNode->getChild(2),")"))
+ {
+ eErrorCode = InsertJoinConnection(_pView,pNode->getChild(1), _eJoinType,pLeftTable,pRightTable);
+ }
+ else if (SQL_ISRULEOR2(pNode,search_condition,boolean_term) && // AND/OR-joints:
+ pNode->count() == 3)
+ {
+ // only allow AND joints
+ if (!SQL_ISTOKEN(pNode->getChild(1),AND))
+ eErrorCode = eIllegalJoinCondition;
+ else if ( eOk == (eErrorCode = InsertJoinConnection(_pView,pNode->getChild(0), _eJoinType,pLeftTable,pRightTable)) )
+ eErrorCode = InsertJoinConnection(_pView,pNode->getChild(2), _eJoinType,pLeftTable,pRightTable);
+ }
+ else if (SQL_ISRULE(pNode,comparison_predicate))
+ {
+ // only the comparison of columns is allowed
+ OSL_ENSURE(pNode->count() == 3,"OQueryDesignView::InsertJoinConnection: Error in Parse Tree");
+ if (!(SQL_ISRULE(pNode->getChild(0),column_ref) &&
+ SQL_ISRULE(pNode->getChild(2),column_ref) &&
+ pNode->getChild(1)->getNodeType() == SQLNodeType::Equal))
+ {
+ OUString sError(DBA_RES(STR_QRY_JOIN_COLUMN_COMPARE));
+ _pView->getController().appendError( sError );
+ return eIllegalJoin;
+ }
+
+ OTableFieldDescRef aDragLeft = new OTableFieldDesc();
+ OTableFieldDescRef aDragRight = new OTableFieldDesc();
+ eErrorCode = FillDragInfo(_pView,pNode->getChild(0),aDragLeft);
+ if ( eOk != eErrorCode )
+ return eErrorCode;
+ eErrorCode = FillDragInfo(_pView,pNode->getChild(2),aDragRight);
+ if ( eOk != eErrorCode )
+ return eErrorCode;
+
+ if ( pLeftTable )
+ {
+ OQueryTableWindow* pLeftWindow = static_cast<OQueryTableView*>(_pView->getTableView())->FindTable( getTableRange(_pView,pLeftTable->getByRule(OSQLParseNode::table_ref) ));
+ if ( pLeftWindow == aDragLeft->GetTabWindow() )
+ insertConnection(_pView,_eJoinType,aDragLeft,aDragRight);
+ else
+ insertConnection(_pView,_eJoinType,aDragRight,aDragLeft);
+ }
+ else
+ insertConnection(_pView,_eJoinType,aDragLeft,aDragRight);
+ }
+ else
+ eErrorCode = eIllegalJoin;
+ return eErrorCode;
+ }
+ bool GetInnerJoinCriteria( const OQueryDesignView* _pView,
+ const ::connectivity::OSQLParseNode *pCondition)
+ {
+ return InsertJoinConnection(_pView,pCondition, INNER_JOIN,nullptr,nullptr) != eOk;
+ }
+ OUString GenerateSelectList( const OQueryDesignView* _pView,
+ OTableFields& _rFieldList,
+ bool bAlias)
+ {
+ Reference< XConnection> xConnection = static_cast<OQueryController&>(_pView->getController()).getConnection();
+ if ( !xConnection.is() )
+ return OUString();
+
+ OUStringBuffer aTmpStr,aFieldListStr;
+
+ bool bAsterisk = false;
+ int nVis = 0;
+ for (auto const& field : _rFieldList)
+ {
+ if ( field->IsVisible() )
+ {
+ if ( field->GetField().toChar() == '*' )
+ bAsterisk = true;
+ ++nVis;
+ }
+ }
+ if(nVis == 1)
+ bAsterisk = false;
+
+ try
+ {
+ const Reference< XDatabaseMetaData > xMetaData = xConnection->getMetaData();
+ const OUString aQuote = xMetaData->getIdentifierQuoteString();
+
+ OJoinTableView::OTableWindowMap& rTabList = _pView->getTableView()->GetTabWinMap();
+
+ for (auto const& field : _rFieldList)
+ {
+ OUString rFieldName = field->GetField();
+ if ( !rFieldName.isEmpty() && field->IsVisible() )
+ {
+ aTmpStr = "";
+ const OUString rAlias = field->GetAlias();
+ const OUString rFieldAlias = field->GetFieldAlias();
+
+ aTmpStr.append(quoteTableAlias((bAlias || bAsterisk),rAlias,aQuote));
+
+ // if we have a none numeric field, the table alias could be in the name
+ // otherwise we are not allowed to do this (e.g. 0.1 * PRICE )
+ if ( !field->isOtherFunction() )
+ {
+ // we have to look if we have alias.* here but before we have to check if the column doesn't already exist
+ OTableFieldDescRef aInfo = new OTableFieldDesc();
+ for (auto const& table : rTabList)
+ {
+ OQueryTableWindow* pTabWin = static_cast<OQueryTableWindow*>(table.second.get());
+
+ if ( pTabWin->ExistsField( rFieldName, aInfo ) )
+ {
+ rFieldName = aInfo->GetField();
+ break;
+ }
+ }
+ if ( ( rFieldName.toChar() != '*' ) && ( rFieldName.indexOf( aQuote ) == -1 ) )
+ {
+ OSL_ENSURE(!field->GetTable().isEmpty(),"No table field name!");
+ aTmpStr.append(::dbtools::quoteName(aQuote, rFieldName));
+ }
+ else
+ aTmpStr.append(rFieldName);
+ }
+ else
+ aTmpStr.append(rFieldName);
+
+ if ( field->isAggregateFunction() )
+ {
+ OSL_ENSURE(!field->GetFunction().isEmpty(),"Function name must not be empty! ;-(");
+ OUStringBuffer aTmpStr2( field->GetFunction() + "(" + aTmpStr + ")");
+ aTmpStr = aTmpStr2;
+ }
+
+ if (!rFieldAlias.isEmpty() &&
+ (rFieldName.toChar() != '*' ||
+ field->isNumericOrAggregateFunction() ||
+ field->isOtherFunction()))
+ {
+ aTmpStr.append(" AS ");
+ aTmpStr.append(::dbtools::quoteName(aQuote, rFieldAlias));
+ }
+ aFieldListStr.append(aTmpStr);
+ aTmpStr.setLength(0);
+ aFieldListStr.append(", ");
+ }
+ }
+ if(!aFieldListStr.isEmpty())
+ aFieldListStr.setLength(aFieldListStr.getLength()-2);
+ }
+ catch(SQLException&)
+ {
+ OSL_FAIL("Failure while building select list!");
+ }
+ return aFieldListStr.makeStringAndClear();
+ }
+ bool GenerateCriterias( OQueryDesignView const * _pView,
+ OUStringBuffer& rRetStr,
+ OUStringBuffer& rHavingStr,
+ OTableFields& _rFieldList,
+ bool bMulti )
+ {
+ Reference< XConnection> xConnection = static_cast<OQueryController&>(_pView->getController()).getConnection();
+ if(!xConnection.is())
+ return false;
+
+ OUString aFieldName,aCriteria,aWhereStr,aHavingStr,aWork/*,aOrderStr*/;
+ // print line by line joined with AND
+ sal_uInt16 nMaxCriteria = 0;
+ for (auto const& field : _rFieldList)
+ {
+ nMaxCriteria = std::max<sal_uInt16>(nMaxCriteria,static_cast<sal_uInt16>(field->GetCriteria().size()));
+ }
+ try
+ {
+ const Reference< XDatabaseMetaData > xMetaData = xConnection->getMetaData();
+ const OUString aQuote = xMetaData->getIdentifierQuoteString();
+ const IParseContext& rContext = static_cast<OQueryController&>(_pView->getController()).getParser().getContext();
+ // * must not contain a filter : have I already shown the correct warning ?
+ bool bCritsOnAsteriskWarning = false; // ** TMFS **
+
+ for (sal_uInt16 i=0 ; i < nMaxCriteria ; i++)
+ {
+ aHavingStr.clear();
+ aWhereStr.clear();
+
+ for (auto const& field : _rFieldList)
+ {
+ aFieldName = field->GetField();
+
+ if (aFieldName.isEmpty())
+ continue;
+ aCriteria = field->GetCriteria( i );
+ if ( !aCriteria.isEmpty() )
+ {
+ // * is not allowed to contain any filter, only when used in combination an aggregate function
+ if ( aFieldName.toChar() == '*' && field->isNoneFunction() )
+ {
+ // only show the messagebox the first time
+ if (!bCritsOnAsteriskWarning)
+ {
+ std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(_pView->GetFrameWeld(),
+ VclMessageType::Warning, VclButtonsType::Ok,
+ DBA_RES(STR_QRY_CRITERIA_ON_ASTERISK)));
+ xBox->run();
+ }
+ bCritsOnAsteriskWarning = true;
+ continue;
+ }
+ aWork = quoteTableAlias(bMulti,field->GetAlias(),aQuote);
+
+ if ( (field->GetFunctionType() & (FKT_OTHER|FKT_NUMERIC)) || (aFieldName.toChar() == '*') )
+ aWork += aFieldName;
+ else
+ aWork += ::dbtools::quoteName(aQuote, aFieldName);
+
+ if ( field->isAggregateFunction() || field->IsGroupBy() )
+ {
+ if (aHavingStr.isEmpty()) // no more criteria
+ aHavingStr += "("; // bracket
+ else
+ aHavingStr += C_AND;
+
+ if ( field->isAggregateFunction() )
+ {
+ OSL_ENSURE(!field->GetFunction().isEmpty(),"No function name for aggregate given!");
+ aHavingStr += field->GetFunction() + "(" + aWork + ")"; // bracket
+ }
+ else
+ aHavingStr += aWork;
+
+ OUString aErrorMsg;
+ Reference<XPropertySet> xColumn;
+ std::unique_ptr< ::connectivity::OSQLParseNode> pParseNode(_pView->getPredicateTreeFromEntry(field,aCriteria,aErrorMsg,xColumn));
+ if (pParseNode)
+ {
+ if (bMulti && !(field->isOtherFunction() || (aFieldName.toChar() == '*')))
+ pParseNode->replaceNodeValue(field->GetAlias(),aFieldName);
+ OUString sHavingStr = aHavingStr;
+
+ sal_uInt32 nCount = pParseNode->count();
+ for( sal_uInt32 node = 1 ; node < nCount ; ++node)
+ pParseNode->getChild(node)->parseNodeToStr( sHavingStr,
+ xConnection,
+ &rContext,
+ false,
+ !field->isOtherFunction());
+ aHavingStr = sHavingStr;
+ }
+ else
+ aHavingStr += aCriteria;
+ }
+ else
+ {
+ if ( aWhereStr.isEmpty() ) // no more criteria
+ aWhereStr += "("; // bracket
+ else
+ aWhereStr += C_AND;
+
+ aWhereStr += " ";
+ // aCriteria could have some German numbers so I have to be sure here
+ OUString aErrorMsg;
+ Reference<XPropertySet> xColumn;
+ std::unique_ptr< ::connectivity::OSQLParseNode> pParseNode( _pView->getPredicateTreeFromEntry(field,aCriteria,aErrorMsg,xColumn));
+ if (pParseNode)
+ {
+ if (bMulti && !(field->isOtherFunction() || (aFieldName.toChar() == '*')))
+ pParseNode->replaceNodeValue(field->GetAlias(),aFieldName);
+ OUString aWhere = aWhereStr;
+ pParseNode->parseNodeToStr( aWhere,
+ xConnection,
+ &rContext,
+ false,
+ !field->isOtherFunction() );
+ aWhereStr = aWhere;
+ }
+ else
+ {
+ aWhereStr += aWork + "=" + aCriteria;
+ }
+ }
+ }
+ // only once for each field
+ else if ( !i && field->isCondition() )
+ {
+ if (aWhereStr.isEmpty()) // no more criteria
+ aWhereStr += "("; // bracket
+ else
+ aWhereStr += C_AND;
+ aWhereStr += field->GetField();
+ }
+ }
+ if (!aWhereStr.isEmpty())
+ {
+ aWhereStr += ")"; // close bracket for the AND branch
+ if (!rRetStr.isEmpty()) // are there conditions on the field?
+ rRetStr.append(C_OR);
+ else // open bracket for the OR branch
+ rRetStr.append('(');
+ rRetStr.append(aWhereStr);
+ }
+ if (!aHavingStr.isEmpty())
+ {
+ aHavingStr += ")"; // close bracket for the AND branch
+ if (!rHavingStr.isEmpty()) // are there conditions on the field?
+ rHavingStr.append(C_OR);
+ else // Open bracket for the OR branch
+ rHavingStr.append('(');
+ rHavingStr.append(aHavingStr);
+ }
+ }
+
+ if (!rRetStr.isEmpty())
+ rRetStr.append(')'); // close bracket for the OR branch
+ if (!rHavingStr.isEmpty())
+ rHavingStr.append(')'); // close bracket for the OR branch
+ }
+ catch(SQLException&)
+ {
+ OSL_FAIL("Failure while building where clause!");
+ }
+ return true;
+ }
+ SqlParseError GenerateOrder( OQueryDesignView const * _pView,
+ OTableFields& _rFieldList,
+ bool bMulti,
+ OUString& _rsRet)
+ {
+ const OQueryController& rController = static_cast<OQueryController&>(_pView->getController());
+ const Reference< XConnection>& xConnection = rController.getConnection();
+ if ( !xConnection.is() )
+ return eNoConnection;
+
+ SqlParseError eErrorCode = eOk;
+
+ OUString aColumnName;
+ OUString aWorkStr;
+ try
+ {
+ const bool bColumnAliasInOrderBy = rController.getSdbMetaData().supportsColumnAliasInOrderBy();
+ Reference< XDatabaseMetaData > xMetaData = xConnection->getMetaData();
+ OUString aQuote = xMetaData->getIdentifierQuoteString();
+ // * must not contain filter - have I already shown the warning?
+ bool bCritsOnAsteriskWarning = false; // ** TMFS **
+ for (auto const& field : _rFieldList)
+ {
+ EOrderDir eOrder = field->GetOrderDir();
+ // only create a sort expression when the table name and the sort criteria are defined
+ // otherwise they will be built in GenerateCriteria
+ if ( eOrder != ORDER_NONE )
+ {
+ aColumnName = field->GetField();
+ if(aColumnName.toChar() == '*')
+ {
+ // only show the MessageBox the first time
+ if (!bCritsOnAsteriskWarning)
+ {
+ std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(_pView->GetFrameWeld(),
+ VclMessageType::Warning, VclButtonsType::Ok,
+ DBA_RES(STR_QRY_ORDERBY_ON_ASTERISK)));
+ xBox->run();
+ }
+ bCritsOnAsteriskWarning = true;
+ continue;
+ }
+
+ if ( bColumnAliasInOrderBy && !field->GetFieldAlias().isEmpty() )
+ {
+ aWorkStr += ::dbtools::quoteName(aQuote, field->GetFieldAlias());
+ }
+ else if ( field->isNumericOrAggregateFunction() )
+ {
+ OSL_ENSURE(!field->GetFunction().isEmpty(),"Function name cannot be empty! ;-(");
+ aWorkStr += field->GetFunction() + "("
+ + quoteTableAlias(
+ bMulti, field->GetAlias(), aQuote);
+ // only quote column name when we don't have a numeric
+ if ( field->isNumeric() )
+ aWorkStr += aColumnName;
+ else
+ aWorkStr += ::dbtools::quoteName(aQuote, aColumnName);
+
+ aWorkStr += ")";
+ }
+ else if ( field->isOtherFunction() )
+ {
+ aWorkStr += aColumnName;
+ }
+ else
+ {
+ aWorkStr += quoteTableAlias(bMulti,field->GetAlias(),aQuote) + ::dbtools::quoteName(aQuote, aColumnName);
+ }
+ aWorkStr += OUString::Concat(" ") + o3tl::getToken( u";ASC;DESC", static_cast<sal_uInt16>(eOrder), ';' ) + ",";
+ }
+ }
+
+ {
+ OUString sTemp(comphelper::string::stripEnd(aWorkStr, ','));
+ aWorkStr = sTemp;
+ }
+
+ if ( !aWorkStr.isEmpty() )
+ {
+ const sal_Int32 nMaxOrder = xMetaData->getMaxColumnsInOrderBy();
+ if ( nMaxOrder && nMaxOrder < comphelper::string::getTokenCount(aWorkStr, ',') )
+ eErrorCode = eStatementTooLong;
+ else
+ {
+ _rsRet = " ORDER BY " + aWorkStr;
+ }
+ }
+ }
+ catch(SQLException&)
+ {
+ OSL_FAIL("Failure while building group by!");
+ }
+
+ return eErrorCode;
+ }
+
+ void GenerateInnerJoinCriterias(const Reference< XConnection>& _xConnection,
+ OUString& _rJoinCrit,
+ const std::vector<VclPtr<OTableConnection> >& _rConnList)
+ {
+ for (auto const& connection : _rConnList)
+ {
+ const OQueryTableConnection* pEntryConn = static_cast<const OQueryTableConnection*>(connection.get());
+ OQueryTableConnectionData* pEntryConnData = static_cast<OQueryTableConnectionData*>(pEntryConn->GetData().get());
+ if ( pEntryConnData->GetJoinType() == INNER_JOIN && !pEntryConnData->isNatural() )
+ {
+ if(!_rJoinCrit.isEmpty())
+ _rJoinCrit += C_AND;
+ _rJoinCrit += BuildJoinCriteria(_xConnection,&pEntryConnData->GetConnLineDataList(),pEntryConnData);
+ }
+ }
+ }
+ void searchAndAppendName(const Reference< XConnection>& _xConnection,
+ const OQueryTableWindow* _pTableWindow,
+ std::set<OUString>& _rTableNames,
+ OUString& _rsTableListStr
+ )
+ {
+ OUString sTabName(BuildTable(_xConnection,_pTableWindow));
+
+ if(_rTableNames.insert(sTabName).second)
+ {
+ _rsTableListStr += sTabName + ",";
+ }
+ }
+ OUString GenerateFromClause( const Reference< XConnection>& _xConnection,
+ const OQueryTableView::OTableWindowMap* pTabList,
+ const std::vector<VclPtr<OTableConnection> >& rConnList
+ )
+ {
+
+ OUString aTableListStr;
+ // used to avoid putting a table twice in FROM clause
+ std::set<OUString> aTableNames;
+
+ // generate outer join clause in from
+ if(!rConnList.empty())
+ {
+ std::map<OTableWindow*,sal_Int32> aConnectionCount;
+ auto aEnd = rConnList.end();
+ for (auto const& connection : rConnList)
+ {
+ static_cast<OQueryTableConnection*>(connection.get())->SetVisited(false);
+ ++aConnectionCount[connection->GetSourceWin()];
+ ++aConnectionCount[connection->GetDestWin()];
+ }
+ std::multimap<sal_Int32 , OTableWindow*> aMulti;
+ for (auto const& elem : aConnectionCount)
+ {
+ aMulti.emplace(elem.second,elem.first);
+ }
+
+ const bool bUseEscape = ::dbtools::getBooleanDataSourceSetting( _xConnection, PROPERTY_OUTERJOINESCAPE );
+ std::multimap<sal_Int32 , OTableWindow*>::const_reverse_iterator aRIter = aMulti.rbegin();
+ std::multimap<sal_Int32 , OTableWindow*>::const_reverse_iterator aREnd = aMulti.rend();
+ for(;aRIter != aREnd;++aRIter)
+ {
+ auto aConIter = aRIter->second->getTableView()->getTableConnections(aRIter->second);
+ for(;aConIter != aEnd;++aConIter)
+ {
+ OQueryTableConnection* pEntryConn = static_cast<OQueryTableConnection*>((*aConIter).get());
+ if(!pEntryConn->IsVisited() && pEntryConn->GetSourceWin() == aRIter->second )
+ {
+ OUString aJoin;
+ GetNextJoin(_xConnection,
+ pEntryConn,
+ static_cast<OQueryTableWindow*>(pEntryConn->GetDestWin()),
+ aJoin,
+ aTableNames);
+
+ if(!aJoin.isEmpty())
+ {
+ OUString aStr;
+ switch(static_cast<OQueryTableConnectionData*>(pEntryConn->GetData().get())->GetJoinType())
+ {
+ case LEFT_JOIN:
+ case RIGHT_JOIN:
+ case FULL_JOIN:
+ {
+ // create outer join
+ if ( bUseEscape )
+ aStr += "{ oj ";
+ aStr += aJoin;
+ if ( bUseEscape )
+ aStr += " }";
+ }
+ break;
+ default:
+ aStr += aJoin;
+ break;
+ }
+ aStr += ",";
+ aTableListStr += aStr;
+ }
+ }
+ }
+ }
+
+ // and now all inner joins
+ // these are implemented as
+ // "FROM tbl1, tbl2 WHERE tbl1.col1=tlb2.col2"
+ // rather than
+ // "FROM tbl1 INNER JOIN tbl2 ON tbl1.col1=tlb2.col2"
+ for (auto const& connection : rConnList)
+ {
+ OQueryTableConnection* pEntryConn = static_cast<OQueryTableConnection*>(connection.get());
+ if(!pEntryConn->IsVisited())
+ {
+ searchAndAppendName(_xConnection,
+ static_cast<OQueryTableWindow*>(pEntryConn->GetSourceWin()),
+ aTableNames,
+ aTableListStr);
+
+ searchAndAppendName(_xConnection,
+ static_cast<OQueryTableWindow*>(pEntryConn->GetDestWin()),
+ aTableNames,
+ aTableListStr);
+ }
+ }
+ }
+ // all tables that haven't a connection to anyone
+ for (auto const& table : *pTabList)
+ {
+ const OQueryTableWindow* pEntryTab = static_cast<const OQueryTableWindow*>(table.second.get());
+ if(!pEntryTab->ExistsAConn())
+ {
+ aTableListStr += BuildTable(_xConnection,pEntryTab) + ",";
+ }
+ }
+
+ if(!aTableListStr.isEmpty())
+ aTableListStr = aTableListStr.replaceAt(aTableListStr.getLength()-1,1, u"" );
+ return aTableListStr;
+ }
+ OUString GenerateGroupBy(const OQueryDesignView* _pView,OTableFields& _rFieldList, bool bMulti )
+ {
+ OQueryController& rController = static_cast<OQueryController&>(_pView->getController());
+ const Reference< XConnection> xConnection = rController.getConnection();
+ if(!xConnection.is())
+ return OUString();
+
+ std::map< OUString,bool> aGroupByNames;
+
+ OUString aGroupByStr;
+ try
+ {
+ const Reference< XDatabaseMetaData > xMetaData = xConnection->getMetaData();
+ const OUString aQuote = xMetaData->getIdentifierQuoteString();
+
+ for (auto const& field : _rFieldList)
+ {
+ if ( field->IsGroupBy() )
+ {
+ OSL_ENSURE(!field->GetField().isEmpty(),"No Field Name available!;-(");
+ OUString sGroupByPart = quoteTableAlias(bMulti,field->GetAlias(),aQuote);
+
+ // only quote the field name when it isn't calculated
+ if ( field->isNoneFunction() )
+ {
+ sGroupByPart += ::dbtools::quoteName(aQuote, field->GetField());
+ }
+ else
+ {
+ OUString aTmp = field->GetField();
+ OUString aErrorMsg;
+ Reference<XPropertySet> xColumn;
+ std::unique_ptr< ::connectivity::OSQLParseNode> pParseNode(_pView->getPredicateTreeFromEntry(field,aTmp,aErrorMsg,xColumn));
+ if (pParseNode)
+ {
+ OUString sGroupBy;
+ pParseNode->getChild(0)->parseNodeToStr( sGroupBy,
+ xConnection,
+ &rController.getParser().getContext(),
+ false,
+ !field->isOtherFunction());
+ sGroupByPart += sGroupBy;
+ }
+ else
+ sGroupByPart += field->GetField();
+ }
+ if ( aGroupByNames.find(sGroupByPart) == aGroupByNames.end() )
+ {
+ aGroupByNames.emplace(sGroupByPart,true);
+ aGroupByStr += sGroupByPart + ",";
+ }
+ }
+ }
+ if ( !aGroupByStr.isEmpty() )
+ {
+ aGroupByStr = aGroupByStr.replaceAt(aGroupByStr.getLength()-1,1, u" " );
+ OUString aGroupByStr2 = " GROUP BY " + aGroupByStr;
+ aGroupByStr = aGroupByStr2;
+ }
+ }
+ catch(SQLException&)
+ {
+ OSL_FAIL("Failure while building group by!");
+ }
+ return aGroupByStr;
+ }
+ SqlParseError GetORCriteria(OQueryDesignView* _pView,
+ OSelectionBrowseBox* _pSelectionBrw,
+ const ::connectivity::OSQLParseNode * pCondition,
+ sal_uInt16& nLevel ,
+ bool bHaving = false,
+ bool bAddOrOnOneLine = false);
+ SqlParseError GetSelectionCriteria( OQueryDesignView* _pView,
+ OSelectionBrowseBox* _pSelectionBrw,
+ const ::connectivity::OSQLParseNode* pNode,
+ sal_uInt16& rLevel )
+ {
+ if (!pNode || !SQL_ISRULE(pNode, select_statement))
+ return eNoSelectStatement;
+
+ // nyi: more checking for the correct structure!
+ pNode = pNode->getChild(3)->getChild(1);
+ // no where clause found
+ if (!pNode || pNode->isLeaf())
+ return eOk;
+
+ // Next free sentence...
+ SqlParseError eErrorCode = eOk;
+ ::connectivity::OSQLParseNode * pCondition = pNode->getChild(1);
+ if ( pCondition ) // no where clause
+ {
+ // now we have to check the other conditions
+ // first make the logical easier
+ ::connectivity::OSQLParseNode::negateSearchCondition(pCondition);
+ ::connectivity::OSQLParseNode *pNodeTmp = pNode->getChild(1);
+
+ ::connectivity::OSQLParseNode::disjunctiveNormalForm(pNodeTmp);
+ pNodeTmp = pNode->getChild(1);
+ ::connectivity::OSQLParseNode::absorptions(pNodeTmp);
+ pNodeTmp = pNode->getChild(1);
+ // compress sort the criteria @see https://bz.apache.org/ooo/show_bug.cgi?id=24079
+ OSQLParseNode::compress(pNodeTmp);
+ pNodeTmp = pNode->getChild(1);
+
+ // first extract the inner joins conditions
+ GetInnerJoinCriteria(_pView,pNodeTmp);
+ // now simplify again, join are checked in ComparisonPredicate
+ ::connectivity::OSQLParseNode::absorptions(pNodeTmp);
+ pNodeTmp = pNode->getChild(1);
+
+ // it could happen that pCondition is not more valid
+ eErrorCode = GetORCriteria(_pView,_pSelectionBrw,pNodeTmp, rLevel);
+ }
+ return eErrorCode;
+ }
+ SqlParseError GetANDCriteria( OQueryDesignView* _pView,
+ OSelectionBrowseBox* _pSelectionBrw,
+ const ::connectivity::OSQLParseNode * pCondition,
+ sal_uInt16& nLevel,
+ bool bHaving,
+ bool bAddOrOnOneLine);
+ SqlParseError ComparisonPredicate(OQueryDesignView const * _pView,
+ OSelectionBrowseBox* _pSelectionBrw,
+ const ::connectivity::OSQLParseNode * pCondition,
+ const sal_uInt16 nLevel,
+ bool bHaving,
+ bool bAddOrOnOneLine);
+ SqlParseError GetORCriteria(OQueryDesignView* _pView,
+ OSelectionBrowseBox* _pSelectionBrw,
+ const ::connectivity::OSQLParseNode * pCondition,
+ sal_uInt16& nLevel ,
+ bool bHaving,
+ bool bAddOrOnOneLine)
+ {
+ SqlParseError eErrorCode = eOk;
+
+ // round brackets around the printout
+ if (pCondition->count() == 3 &&
+ SQL_ISPUNCTUATION(pCondition->getChild(0),"(") &&
+ SQL_ISPUNCTUATION(pCondition->getChild(2),")"))
+ {
+ eErrorCode = GetORCriteria(_pView,_pSelectionBrw,pCondition->getChild(1),nLevel,bHaving,bAddOrOnOneLine);
+ }
+ // OR condition
+ // a searchcondition can only look like this: search_condition SQL_TOKEN_OR boolean_term
+ else if (SQL_ISRULE(pCondition,search_condition))
+ {
+ for (int i = 0; i < 3 && eErrorCode == eOk ; i+=2)
+ {
+ const ::connectivity::OSQLParseNode* pChild = pCondition->getChild(i);
+ if ( SQL_ISRULE(pChild,search_condition) )
+ eErrorCode = GetORCriteria(_pView,_pSelectionBrw,pChild,nLevel,bHaving,bAddOrOnOneLine);
+ else
+ {
+ eErrorCode = GetANDCriteria(_pView,_pSelectionBrw,pChild, nLevel,bHaving, i != 0 && bAddOrOnOneLine);
+ if ( !bAddOrOnOneLine)
+ nLevel++;
+ }
+ }
+ }
+ else
+ eErrorCode = GetANDCriteria( _pView,_pSelectionBrw,pCondition, nLevel, bHaving,bAddOrOnOneLine );
+
+ return eErrorCode;
+ }
+ bool CheckOrCriteria(const ::connectivity::OSQLParseNode* _pCondition,::connectivity::OSQLParseNode* _pFirstColumnRef)
+ {
+ bool bRet = true;
+ ::connectivity::OSQLParseNode* pFirstColumnRef = _pFirstColumnRef;
+ for (size_t i = 0; bRet && i < _pCondition->count(); ++i)
+ {
+ const ::connectivity::OSQLParseNode* pChild = _pCondition->getChild(i);
+ if ( pChild->isToken() )
+ continue;
+ else if ( SQL_ISRULE(pChild,search_condition) )
+ bRet = CheckOrCriteria(pChild,pFirstColumnRef);
+ else
+ {
+ // this is a simple way to test columns are the same, may be we have to adjust this algo a little bit in future. :-)
+ ::connectivity::OSQLParseNode* pSecondColumnRef = pChild->getByRule(::connectivity::OSQLParseNode::column_ref);
+ if ( pFirstColumnRef && pSecondColumnRef )
+ bRet = *pFirstColumnRef == *pSecondColumnRef;
+ else if ( !pFirstColumnRef )
+ pFirstColumnRef = pSecondColumnRef;
+ }
+ }
+ return bRet;
+ }
+ SqlParseError GetANDCriteria( OQueryDesignView* _pView,
+ OSelectionBrowseBox* _pSelectionBrw,
+ const ::connectivity::OSQLParseNode * pCondition,
+ sal_uInt16& nLevel,
+ bool bHaving,
+ bool bAddOrOnOneLine)
+ {
+ const css::lang::Locale aLocale = _pView->getLocale();
+ const OUString sDecimal = _pView->getDecimalSeparator();
+
+ // I will need a cast pointer to my css::sdbcx::Container
+ OQueryController& rController = static_cast<OQueryController&>(_pView->getController());
+ SqlParseError eErrorCode = eOk;
+
+ // round brackets
+ if (SQL_ISRULE(pCondition,boolean_primary))
+ {
+ // check if we have to put the or criteria on one line.
+ const ::connectivity::OSQLParseNode* pSearchCondition = pCondition->getChild(1);
+ bool bMustAddOrOnOneLine = CheckOrCriteria(pSearchCondition,nullptr);
+ if ( SQL_ISRULE( pSearchCondition, search_condition) ) // we have a or
+ {
+ _pSelectionBrw->DuplicateConditionLevel( nLevel);
+ eErrorCode = GetORCriteria(_pView,_pSelectionBrw,pSearchCondition->getChild(0), nLevel,bHaving,bMustAddOrOnOneLine );
+ if ( eErrorCode == eOk )
+ {
+ ++nLevel;
+ eErrorCode = GetORCriteria(_pView,_pSelectionBrw,pSearchCondition->getChild(2), nLevel,bHaving,bMustAddOrOnOneLine );
+ }
+ }
+ else
+ eErrorCode = GetORCriteria(_pView,_pSelectionBrw,pSearchCondition, nLevel,bHaving,bMustAddOrOnOneLine );
+ }
+ // The first element is (again) an AND condition
+ else if ( SQL_ISRULE(pCondition,boolean_term) )
+ {
+ OSL_ENSURE(pCondition->count() == 3,"Illegal definition of boolean_term");
+ eErrorCode = GetANDCriteria(_pView,_pSelectionBrw,pCondition->getChild(0), nLevel,bHaving,bAddOrOnOneLine );
+ if ( eErrorCode == eOk )
+ eErrorCode = GetANDCriteria(_pView,_pSelectionBrw,pCondition->getChild(2), nLevel,bHaving,bAddOrOnOneLine );
+ }
+ else if (SQL_ISRULE( pCondition, comparison_predicate))
+ {
+ eErrorCode = ComparisonPredicate(_pView,_pSelectionBrw,pCondition,nLevel,bHaving,bAddOrOnOneLine);
+ }
+ else if( SQL_ISRULE(pCondition,like_predicate) )
+ {
+ const ::connectivity::OSQLParseNode* pValueExp = pCondition->getChild(0);
+ if (SQL_ISRULE(pValueExp, column_ref ) )
+ {
+ OUString aCondition;
+ Reference< XConnection> xConnection = rController.getConnection();
+ if ( xConnection.is() )
+ {
+ OUString aColumnName;
+ // the international doesn't matter I have a string
+ pCondition->parseNodeToPredicateStr(aCondition,
+ xConnection,
+ rController.getNumberFormatter(),
+ aLocale,
+ sDecimal,
+ &rController.getParser().getContext());
+
+ pValueExp->parseNodeToPredicateStr( aColumnName,
+ xConnection,
+ rController.getNumberFormatter(),
+ aLocale,
+ sDecimal,
+ &rController.getParser().getContext());
+
+ // don't display the column name
+ aCondition = aCondition.copy(aColumnName.getLength());
+ aCondition = aCondition.trim();
+ }
+
+ OTableFieldDescRef aDragLeft = new OTableFieldDesc();
+ if ( eOk == ( eErrorCode = FillDragInfo(_pView,pValueExp,aDragLeft) ))
+ {
+ if ( bHaving )
+ aDragLeft->SetGroupBy(true);
+ _pSelectionBrw->AddCondition(aDragLeft, aCondition, nLevel,bAddOrOnOneLine);
+ }
+ }
+ else if(SQL_ISRULEOR3(pValueExp, general_set_fct, set_fct_spec, position_exp) ||
+ SQL_ISRULEOR3(pValueExp, extract_exp, fold, char_substring_fct) ||
+ SQL_ISRULEOR2(pValueExp, length_exp, char_value_fct))
+ {
+ AddFunctionCondition( _pView,
+ _pSelectionBrw,
+ pCondition,
+ nLevel,
+ bHaving,
+ bAddOrOnOneLine);
+ }
+ else
+ {
+ eErrorCode = eNoColumnInLike;
+ OUString sError(DBA_RES(STR_QRY_LIKE_LEFT_NO_COLUMN));
+ _pView->getController().appendError( sError );
+ }
+ }
+ else if( SQL_ISRULEOR2(pCondition,test_for_null,in_predicate)
+ || SQL_ISRULEOR2(pCondition,all_or_any_predicate,between_predicate))
+ {
+ if ( SQL_ISRULEOR2(pCondition->getChild(0), set_fct_spec , general_set_fct ) )
+ {
+ AddFunctionCondition( _pView,
+ _pSelectionBrw,
+ pCondition,
+ nLevel,
+ bHaving,
+ bAddOrOnOneLine);
+ }
+ else if ( SQL_ISRULE(pCondition->getChild(0), column_ref ) )
+ {
+ // parse condition
+ OUString sCondition = ParseCondition(rController,pCondition,sDecimal,aLocale,1);
+ OTableFieldDescRef aDragLeft = new OTableFieldDesc();
+ if ( eOk == ( eErrorCode = FillDragInfo(_pView,pCondition->getChild(0),aDragLeft)) )
+ {
+ if ( bHaving )
+ aDragLeft->SetGroupBy(true);
+ _pSelectionBrw->AddCondition(aDragLeft, sCondition, nLevel,bAddOrOnOneLine);
+ }
+ }
+ else
+ {
+ // Parse the function condition
+ OUString sCondition = ParseCondition(rController,pCondition,sDecimal,aLocale,1);
+ Reference< XConnection> xConnection = rController.getConnection();
+ // the international doesn't matter I have a string
+ OUString sName;
+ pCondition->getChild(0)->parseNodeToPredicateStr(sName,
+ xConnection,
+ rController.getNumberFormatter(),
+ aLocale,
+ sDecimal,
+ &rController.getParser().getContext());
+
+ OTableFieldDescRef aDragLeft = new OTableFieldDesc();
+ aDragLeft->SetField(sName);
+ aDragLeft->SetFunctionType(FKT_OTHER);
+
+ if ( bHaving )
+ aDragLeft->SetGroupBy(true);
+ _pSelectionBrw->AddCondition(aDragLeft, sCondition, nLevel,bAddOrOnOneLine);
+ }
+ }
+ else if( SQL_ISRULEOR2(pCondition,existence_test,unique_test) )
+ {
+ // Parse the function condition
+ OUString aCondition = ParseCondition(rController,pCondition,sDecimal,aLocale,0);
+
+ OTableFieldDescRef aDragLeft = new OTableFieldDesc();
+ aDragLeft->SetField(aCondition);
+ aDragLeft->SetFunctionType(FKT_CONDITION);
+
+ eErrorCode = _pSelectionBrw->InsertField(aDragLeft,BROWSER_INVALIDID,false).is() ? eOk : eTooManyColumns;
+ }
+ else //! TODO not supported yet
+ eErrorCode = eStatementTooComplex;
+ // Pass on the error code
+ return eErrorCode;
+ }
+ SqlParseError AddFunctionCondition(OQueryDesignView const * _pView,
+ OSelectionBrowseBox* _pSelectionBrw,
+ const ::connectivity::OSQLParseNode * pCondition,
+ const sal_uInt16 nLevel,
+ bool bHaving,
+ bool bAddOrOnOneLine)
+ {
+ SqlParseError eErrorCode = eOk;
+ OQueryController& rController = static_cast<OQueryController&>(_pView->getController());
+
+ OSQLParseNode* pFunction = pCondition->getChild(0);
+
+ OSL_ENSURE(SQL_ISRULEOR3(pFunction, general_set_fct, set_fct_spec, position_exp) ||
+ SQL_ISRULEOR3(pFunction, extract_exp, fold, char_substring_fct) ||
+ SQL_ISRULEOR2(pFunction,length_exp,char_value_fct),
+ "Illegal call!");
+
+ Reference< XConnection> xConnection = rController.getConnection();
+ if(xConnection.is())
+ {
+ OUString aCondition;
+ OUString aColumnName;
+ OTableFieldDescRef aDragLeft = new OTableFieldDesc();
+ pCondition->parseNodeToPredicateStr(aCondition,
+ xConnection,
+ rController.getNumberFormatter(),
+ _pView->getLocale(),
+ _pView->getDecimalSeparator(),
+ &rController.getParser().getContext());
+
+ pFunction->parseNodeToStr( aColumnName,
+ xConnection,
+ &rController.getParser().getContext(),
+ true); // quote is to true because we need quoted elements inside the function
+ // don't display the column name
+ aCondition = aCondition.copy(aColumnName.getLength());
+ aCondition = aCondition.trim();
+ if ( aCondition.startsWith("=") ) // ignore the equal sign
+ aCondition = aCondition.copy(1);
+
+ if ( SQL_ISRULE(pFunction, general_set_fct ) )
+ {
+ sal_Int32 nFunctionType = FKT_AGGREGATE;
+ OSQLParseNode* pParamNode = pFunction->getChild(pFunction->count()-2);
+ if ( pParamNode && pParamNode->getTokenValue().toChar() == '*' )
+ {
+ OJoinTableView::OTableWindowMap& rTabList = _pView->getTableView()->GetTabWinMap();
+ for (auto const& table : rTabList)
+ {
+ OQueryTableWindow* pTabWin = static_cast<OQueryTableWindow*>(table.second.get());
+ if (pTabWin->ExistsField( "*", aDragLeft ))
+ {
+ aDragLeft->SetAlias(OUString());
+ aDragLeft->SetTable(OUString());
+ break;
+ }
+ }
+ }
+ else if (pParamNode)
+ {
+ eErrorCode = FillDragInfo(_pView,pParamNode,aDragLeft);
+ if ( eOk != eErrorCode && SQL_ISRULE(pParamNode,num_value_exp))
+ {
+ OUString sParameterValue;
+ pParamNode->parseNodeToStr( sParameterValue,
+ xConnection,
+ &rController.getParser().getContext());
+ nFunctionType |= FKT_NUMERIC;
+ aDragLeft->SetField(sParameterValue);
+ eErrorCode = eOk;
+ }
+ }
+ aDragLeft->SetFunctionType(nFunctionType);
+ if ( bHaving )
+ aDragLeft->SetGroupBy(true);
+ aDragLeft->SetFunction(aColumnName.getToken(0, '('));
+ }
+ else
+ {
+ // for an unknown function we write the whole text in the field
+ aDragLeft->SetField(aColumnName);
+ if(bHaving)
+ aDragLeft->SetGroupBy(true);
+ aDragLeft->SetFunctionType(FKT_OTHER|FKT_NUMERIC);
+ }
+ _pSelectionBrw->AddCondition(aDragLeft, aCondition, nLevel,bAddOrOnOneLine);
+ }
+
+ return eErrorCode;
+ }
+ SqlParseError ComparisonPredicate(OQueryDesignView const * _pView,
+ OSelectionBrowseBox* _pSelectionBrw,
+ const ::connectivity::OSQLParseNode * pCondition,
+ const sal_uInt16 nLevel,
+ bool bHaving
+ ,bool bAddOrOnOneLine)
+ {
+ SqlParseError eErrorCode = eOk;
+ OQueryController& rController = static_cast<OQueryController&>(_pView->getController());
+
+ OSL_ENSURE(SQL_ISRULE( pCondition, comparison_predicate),"ComparisonPredicate: pCondition is not a Comparison Predicate");
+ if ( SQL_ISRULE(pCondition->getChild(0), column_ref )
+ || SQL_ISRULE(pCondition->getChild(pCondition->count()-1), column_ref) )
+ {
+ OUString aCondition;
+ OTableFieldDescRef aDragLeft = new OTableFieldDesc();
+
+ if ( SQL_ISRULE(pCondition->getChild(0), column_ref ) && SQL_ISRULE(pCondition->getChild(pCondition->count()-1), column_ref ) )
+ {
+ OTableFieldDescRef aDragRight = new OTableFieldDesc();
+ eErrorCode = FillDragInfo(_pView,pCondition->getChild(0),aDragLeft);
+ if (eOk != eErrorCode)
+ return eErrorCode;
+ eErrorCode = FillDragInfo(_pView,pCondition->getChild(2),aDragRight);
+ if (eOk != eErrorCode)
+ return eErrorCode;
+
+ OQueryTableConnection* pConn = static_cast<OQueryTableConnection*>(
+ _pView->getTableView()->GetTabConn(static_cast<OQueryTableWindow*>(aDragLeft->GetTabWindow()),
+ static_cast<OQueryTableWindow*>(aDragRight->GetTabWindow()),
+ true));
+ if ( pConn )
+ {
+ OConnectionLineDataVec& rLineDataList = pConn->GetData()->GetConnLineDataList();
+ for (auto const& lineData : rLineDataList)
+ {
+ if(lineData->GetSourceFieldName() == aDragLeft->GetField() ||
+ lineData->GetDestFieldName() == aDragLeft->GetField() )
+ return eOk;
+ }
+ }
+ }
+
+ sal_uInt32 nPos = 0;
+ if(SQL_ISRULE(pCondition->getChild(0), column_ref ))
+ {
+ nPos = 0;
+ sal_uInt32 i=1;
+
+ // don't display the equal
+ if (pCondition->getChild(i)->getNodeType() == SQLNodeType::Equal)
+ i++;
+
+ // parse the condition
+ aCondition = ParseCondition(rController
+ ,pCondition
+ ,_pView->getDecimalSeparator()
+ ,_pView->getLocale()
+ ,i);
+ }
+ else if( SQL_ISRULE(pCondition->getChild(pCondition->count()-1), column_ref ) )
+ {
+ nPos = pCondition->count()-1;
+
+ sal_Int32 i = static_cast<sal_Int32>(pCondition->count() - 2);
+ switch (pCondition->getChild(i)->getNodeType())
+ {
+ case SQLNodeType::Equal:
+ // don't display the equal
+ i--;
+ break;
+ case SQLNodeType::Less:
+ // take the opposite as we change the order
+ i--;
+ aCondition += ">";
+ break;
+ case SQLNodeType::LessEq:
+ // take the opposite as we change the order
+ i--;
+ aCondition += ">=";
+ break;
+ case SQLNodeType::Great:
+ // take the opposite as we change the order
+ i--;
+ aCondition += "<";
+ break;
+ case SQLNodeType::GreatEq:
+ // take the opposite as we change the order
+ i--;
+ aCondition += "<=";
+ break;
+ default:
+ break;
+ }
+
+ // go backward
+ Reference< XConnection> xConnection = rController.getConnection();
+ if(xConnection.is())
+ {
+ for (; i >= 0; i--)
+ pCondition->getChild(i)->parseNodeToPredicateStr(aCondition,
+ xConnection,
+ rController.getNumberFormatter(),
+ _pView->getLocale(),
+ _pView->getDecimalSeparator(),
+ &rController.getParser().getContext());
+ }
+ }
+ // else ???
+
+ if( eOk == ( eErrorCode = FillDragInfo(_pView,pCondition->getChild(nPos),aDragLeft)))
+ {
+ if(bHaving)
+ aDragLeft->SetGroupBy(true);
+ _pSelectionBrw->AddCondition(aDragLeft, aCondition, nLevel,bAddOrOnOneLine);
+ }
+ }
+ else if( SQL_ISRULEOR2(pCondition->getChild(0), set_fct_spec , general_set_fct ) )
+ {
+ AddFunctionCondition( _pView,
+ _pSelectionBrw,
+ pCondition,
+ nLevel,
+ bHaving,
+ bAddOrOnOneLine);
+ }
+ else // it can only be an Expr
+ {
+ OUString aName,aCondition;
+
+ // Field name
+ Reference< XConnection> xConnection = rController.getConnection();
+ if(xConnection.is())
+ {
+ ::connectivity::OSQLParseNode *pLhs = pCondition->getChild(0);
+ ::connectivity::OSQLParseNode *pRhs = pCondition->getChild(2);
+ pLhs->parseNodeToStr(aName,
+ xConnection,
+ &rController.getParser().getContext(),
+ true);
+ // Criteria
+ aCondition = pCondition->getChild(1)->getTokenValue();
+ pRhs->parseNodeToPredicateStr(aCondition,
+ xConnection,
+ rController.getNumberFormatter(),
+ _pView->getLocale(),
+ _pView->getDecimalSeparator(),
+ &rController.getParser().getContext());
+ }
+
+ OTableFieldDescRef aDragLeft = new OTableFieldDesc();
+ aDragLeft->SetField(aName);
+ aDragLeft->SetFunctionType(FKT_OTHER|FKT_NUMERIC);
+ // and add it on
+ _pSelectionBrw->AddCondition(aDragLeft, aCondition, nLevel,bAddOrOnOneLine);
+ }
+ return eErrorCode;
+ }
+
+ OQueryTableWindow* lcl_findColumnInTables( const OUString& _rColumName, const OJoinTableView::OTableWindowMap& _rTabList, OTableFieldDescRef const & _rInfo )
+ {
+ for (auto const& table : _rTabList)
+ {
+ OQueryTableWindow* pTabWin = static_cast< OQueryTableWindow* >( table.second.get() );
+ if ( pTabWin && pTabWin->ExistsField( _rColumName, _rInfo ) )
+ return pTabWin;
+ }
+ return nullptr;
+ }
+
+ void InsertColumnRef(const OQueryDesignView* _pView,
+ const ::connectivity::OSQLParseNode * pColumnRef,
+ OUString& aColumnName,
+ const OUString& aColumnAlias,
+ OUString& aTableRange,
+ OTableFieldDescRef const & _raInfo,
+ OJoinTableView::OTableWindowMap const * pTabList)
+ {
+
+ // Put the table names together
+ ::connectivity::OSQLParseTreeIterator& rParseIter = static_cast<OQueryController&>(_pView->getController()).getParseIterator();
+ rParseIter.getColumnRange( pColumnRef, aColumnName, aTableRange );
+
+ bool bFound(false);
+ OSL_ENSURE(!aColumnName.isEmpty(),"Column name must not be empty");
+ if (aTableRange.isEmpty())
+ {
+ // SELECT column, ...
+ bFound = nullptr != lcl_findColumnInTables( aColumnName, *pTabList, _raInfo );
+ if ( bFound && ( aColumnName.toChar() != '*' ) )
+ _raInfo->SetFieldAlias(aColumnAlias);
+ }
+ else
+ {
+ // SELECT range.column, ...
+ OQueryTableWindow* pTabWin = static_cast<OQueryTableView*>(_pView->getTableView())->FindTable(aTableRange);
+
+ if (pTabWin && pTabWin->ExistsField(aColumnName, _raInfo))
+ {
+ if(aColumnName.toChar() != '*')
+ _raInfo->SetFieldAlias(aColumnAlias);
+ bFound = true;
+ }
+ }
+ if (!bFound)
+ {
+ _raInfo->SetTable(OUString());
+ _raInfo->SetAlias(OUString());
+ _raInfo->SetField(aColumnName);
+ _raInfo->SetFieldAlias(aColumnAlias); // nyi : here it continues Expr_1, Expr_2 ...
+ _raInfo->SetFunctionType(FKT_OTHER);
+ }
+ }
+ bool checkJoinConditions( const OQueryDesignView* _pView,
+ const ::connectivity::OSQLParseNode* _pNode )
+ {
+ const ::connectivity::OSQLParseNode* pJoinNode = nullptr;
+ bool bRet = true;
+ if (SQL_ISRULE(_pNode,qualified_join))
+ pJoinNode = _pNode;
+ else if (SQL_ISRULE(_pNode,table_ref)
+ && _pNode->count() == 3
+ && SQL_ISPUNCTUATION(_pNode->getChild(0),"(")
+ && SQL_ISPUNCTUATION(_pNode->getChild(2),")") ) // '(' joined_table ')'
+ pJoinNode = _pNode->getChild(1);
+ else if (! ( SQL_ISRULE(_pNode, table_ref) && _pNode->count() == 2) ) // table_node table_primary_as_range_column
+ bRet = false;
+
+ if (pJoinNode && !InsertJoin(_pView,pJoinNode))
+ bRet = false;
+ return bRet;
+ }
+ bool InsertJoin(const OQueryDesignView* _pView,
+ const ::connectivity::OSQLParseNode *pNode)
+ {
+ OSL_ENSURE( SQL_ISRULE( pNode, qualified_join ) || SQL_ISRULE( pNode, joined_table ) || SQL_ISRULE( pNode, cross_union ),
+ "OQueryDesignView::InsertJoin: Error in the Parse Tree");
+
+ if (SQL_ISRULE(pNode,joined_table))
+ return InsertJoin(_pView,pNode->getChild(1));
+
+ // first check the left and right side
+ const ::connectivity::OSQLParseNode* pRightTableRef = pNode->getChild(3); // table_ref
+ if ( SQL_ISRULE(pNode, qualified_join) && SQL_ISTOKEN(pNode->getChild(1),NATURAL) )
+ pRightTableRef = pNode->getChild(4); // table_ref
+
+ if ( !checkJoinConditions(_pView,pNode->getChild(0)) || !checkJoinConditions(_pView,pRightTableRef))
+ return false;
+
+ // named column join may be implemented later
+ // SQL_ISRULE(pNode->getChild(4),named_columns_join)
+ EJoinType eJoinType = INNER_JOIN;
+ bool bNatural = false;
+ if ( SQL_ISRULE(pNode, qualified_join) )
+ {
+ ::connectivity::OSQLParseNode* pJoinType = pNode->getChild(1); // join_type
+ if ( SQL_ISTOKEN(pJoinType,NATURAL) )
+ {
+ bNatural = true;
+ pJoinType = pNode->getChild(2);
+ }
+
+ if (SQL_ISRULE(pJoinType,join_type) && (!pJoinType->count() || SQL_ISTOKEN(pJoinType->getChild(0),INNER)))
+ {
+ eJoinType = INNER_JOIN;
+ }
+ else
+ {
+ if (SQL_ISRULE(pJoinType,join_type)) // one level deeper
+ pJoinType = pJoinType->getChild(0);
+
+ if (SQL_ISTOKEN(pJoinType->getChild(0),LEFT))
+ eJoinType = LEFT_JOIN;
+ else if(SQL_ISTOKEN(pJoinType->getChild(0),RIGHT))
+ eJoinType = RIGHT_JOIN;
+ else
+ eJoinType = FULL_JOIN;
+ }
+ if ( SQL_ISRULE(pNode->getChild(4),join_condition) )
+ {
+ if ( InsertJoinConnection(_pView,pNode->getChild(4)->getChild(1), eJoinType,pNode->getChild(0),pRightTableRef) != eOk )
+ return false;
+ }
+ }
+ else if ( SQL_ISRULE(pNode, cross_union) )
+ {
+ eJoinType = CROSS_JOIN;
+ pRightTableRef = pNode->getChild(pNode->count() - 1);
+ }
+ else
+ return false;
+
+ if ( eJoinType != CROSS_JOIN && !bNatural )
+ return true;
+
+ OQueryTableWindow* pLeftWindow = static_cast<OQueryTableView*>(_pView->getTableView())->FindTable( getTableRange(_pView,pNode->getChild(0)) );
+ OQueryTableWindow* pRightWindow = static_cast<OQueryTableView*>(_pView->getTableView())->FindTable( getTableRange(_pView,pRightTableRef) );
+ OSL_ENSURE(pLeftWindow && pRightWindow,"Table Windows could not be found!");
+ if ( !pLeftWindow || !pRightWindow )
+ return false;
+
+ OTableFieldDescRef aDragLeft = new OTableFieldDesc();
+ aDragLeft->SetTabWindow(pLeftWindow);
+ aDragLeft->SetTable(pLeftWindow->GetTableName());
+ aDragLeft->SetAlias(pLeftWindow->GetAliasName());
+
+ OTableFieldDescRef aDragRight = new OTableFieldDesc();
+ aDragRight->SetTabWindow(pRightWindow);
+ aDragRight->SetTable(pRightWindow->GetTableName());
+ aDragRight->SetAlias(pRightWindow->GetAliasName());
+
+ insertConnection(_pView,eJoinType,aDragLeft,aDragRight,bNatural);
+
+ return true;
+ }
+ void insertUnUsedFields(OQueryDesignView const * _pView,OSelectionBrowseBox* _pSelectionBrw)
+ {
+ // now we have to insert the fields which aren't in the statement
+ OQueryController& rController = static_cast<OQueryController&>(_pView->getController());
+ OTableFields& rUnUsedFields = rController.getUnUsedFields();
+ for (auto & unusedField : rUnUsedFields)
+ if(_pSelectionBrw->InsertField(unusedField,BROWSER_INVALIDID,false,false).is())
+ unusedField = nullptr;
+ OTableFields().swap( rUnUsedFields );
+ }
+
+ SqlParseError InitFromParseNodeImpl(OQueryDesignView* _pView,OSelectionBrowseBox* _pSelectionBrw)
+ {
+ SqlParseError eErrorCode = eOk;
+
+ OQueryController& rController = static_cast<OQueryController&>(_pView->getController());
+
+ _pSelectionBrw->PreFill();
+ _pSelectionBrw->SetReadOnly(rController.isReadOnly());
+ _pSelectionBrw->Fill();
+
+ ::connectivity::OSQLParseTreeIterator& aIterator = rController.getParseIterator();
+ const ::connectivity::OSQLParseNode* pParseTree = aIterator.getParseTree();
+
+ do
+ {
+ if ( !pParseTree )
+ {
+ // now we have to insert the fields which aren't in the statement
+ insertUnUsedFields(_pView,_pSelectionBrw);
+ break;
+ }
+
+ if ( !rController.isEscapeProcessing() ) // not allowed in this mode
+ {
+ eErrorCode = eNativeMode;
+ break;
+ }
+
+ if ( !( SQL_ISRULE( pParseTree, select_statement ) ) )
+ {
+ eErrorCode = eNoSelectStatement;
+ break;
+ }
+
+ const OSQLParseNode* pTableExp = pParseTree->getChild(3);
+ if ( pTableExp->getChild(7)->count() > 0 || pTableExp->getChild(8)->count() > 0)
+ {
+ eErrorCode = eStatementTooComplex;
+ break;
+ }
+
+ Reference< XConnection> xConnection = rController.getConnection();
+ if ( !xConnection.is() )
+ {
+ OSL_FAIL( "InitFromParseNodeImpl: no connection? no connection!" );
+ break;
+ }
+
+ const OSQLTables& aMap = aIterator.getTables();
+ ::comphelper::UStringMixLess aTmp(aMap.key_comp());
+ ::comphelper::UStringMixEqual aKeyComp( aTmp.isCaseSensitive() );
+
+ Reference< XDatabaseMetaData > xMetaData = xConnection->getMetaData();
+ try
+ {
+ sal_Int32 nMax = xMetaData->getMaxTablesInSelect();
+ if ( nMax && nMax < static_cast<sal_Int32>(aMap.size()) )
+ {
+ eErrorCode = eTooManyTables;
+ break;
+ }
+
+ OUString sComposedName;
+ OUString sAlias;
+
+ OQueryTableView* pTableView = static_cast<OQueryTableView*>(_pView->getTableView());
+ pTableView->clearLayoutInformation();
+ for (auto const& elem : aMap)
+ {
+ OSQLTable xTable = elem.second;
+ Reference< XPropertySet > xTableProps( xTable, UNO_QUERY_THROW );
+
+ sAlias = elem.first;
+
+ // check whether this is a query
+ Reference< XPropertySetInfo > xPSI = xTableProps->getPropertySetInfo();
+ bool bIsQuery = xPSI.is() && xPSI->hasPropertyByName( PROPERTY_COMMAND );
+
+ if ( bIsQuery )
+ OSL_VERIFY( xTableProps->getPropertyValue( PROPERTY_NAME ) >>= sComposedName );
+ else
+ {
+ sComposedName = ::dbtools::composeTableName( xMetaData, xTableProps, ::dbtools::EComposeRule::InDataManipulation, false );
+
+ // if the alias is the complete (composed) table, then shorten it
+ if ( aKeyComp( sComposedName, elem.first ) )
+ {
+ OUString sCatalog, sSchema, sTable;
+ ::dbtools::qualifiedNameComponents( xMetaData, sComposedName, sCatalog, sSchema, sTable, ::dbtools::EComposeRule::InDataManipulation );
+ sAlias = sTable;
+ }
+ }
+
+ // find the existent window for this alias
+ OQueryTableWindow* pExistentWin = pTableView->FindTable( sAlias );
+ if ( !pExistentWin )
+ {
+ pTableView->AddTabWin( sComposedName, sAlias ); // don't create data here
+ }
+ else
+ {
+ // there already exists a window for this alias...
+ if ( !aKeyComp( pExistentWin->GetData()->GetComposedName(), sComposedName ) )
+ // ... but for another complete table name -> new window
+ pTableView->AddTabWin(sComposedName, sAlias);
+ }
+ }
+
+ // now delete the data for which we haven't any tablewindow
+ OJoinTableView::OTableWindowMap aTableMap(pTableView->GetTabWinMap());
+ for (auto const& table : aTableMap)
+ {
+ if(aMap.find(table.second->GetComposedName()) == aMap.end() &&
+ aMap.find(table.first) == aMap.end())
+ pTableView->RemoveTabWin(table.second);
+ }
+
+ if ( eOk == (eErrorCode = FillOuterJoins(_pView,pTableExp->getChild(0)->getChild(1))) )
+ {
+ // check if we have a distinct statement
+ if(SQL_ISTOKEN(pParseTree->getChild(1),DISTINCT))
+ {
+ rController.setDistinct(true);
+ rController.InvalidateFeature(SID_QUERY_DISTINCT_VALUES);
+ }
+ else
+ {
+ rController.setDistinct(false);
+ }
+
+ ///check if query has a limit
+ if( pTableExp->getChild(6)->count() >= 2 && pTableExp->getChild(6)->getChild(1) )
+ {
+ rController.setLimit(
+ pTableExp->getChild(6)->getChild(1)->getTokenValue().toInt64() );
+ }
+ else
+ {
+ rController.setLimit(-1);
+ }
+
+ if ( (eErrorCode = InstallFields(_pView, pParseTree, &pTableView->GetTabWinMap())) == eOk )
+ {
+ // GetSelectionCriteria must be called before GetHavingCriteria
+ sal_uInt16 nLevel=0;
+
+ if ( eOk == (eErrorCode = GetSelectionCriteria(_pView,_pSelectionBrw,pParseTree,nLevel)) )
+ {
+ if ( eOk == (eErrorCode = GetGroupCriteria(_pView,_pSelectionBrw,pParseTree)) )
+ {
+ if ( eOk == (eErrorCode = GetHavingCriteria(_pView,_pSelectionBrw,pParseTree,nLevel)) )
+ {
+ if ( eOk == (eErrorCode = GetOrderCriteria(_pView,_pSelectionBrw,pParseTree)) )
+ insertUnUsedFields(_pView,_pSelectionBrw);
+ }
+ }
+ }
+ }
+ }
+ }
+ catch(SQLException&)
+ {
+ OSL_FAIL("getMaxTablesInSelect!");
+ }
+ }
+ while ( false );
+
+ // New Undo-Actions were created in the Manager by the regeneration
+ rController.ClearUndoManager();
+ _pSelectionBrw->Invalidate();
+ return eErrorCode;
+ }
+ /** fillSelectSubList
+ @return
+ <TRUE/> when columns could be inserted otherwise <FALSE/>
+ */
+ SqlParseError fillSelectSubList( OQueryDesignView* _pView,
+ OJoinTableView::OTableWindowMap* _pTabList)
+ {
+ SqlParseError eErrorCode = eOk;
+ bool bFirstField = true;
+ for (auto const& table : *_pTabList)
+ {
+ OQueryTableWindow* pTabWin = static_cast<OQueryTableWindow*>(table.second.get());
+ OTableFieldDescRef aInfo = new OTableFieldDesc();
+ if (pTabWin->ExistsField( "*", aInfo ))
+ {
+ eErrorCode = _pView->InsertField(aInfo, bFirstField);
+ bFirstField = false;
+ if (eErrorCode != eOk)
+ break;
+ }
+ }
+ return eErrorCode;
+ }
+ SqlParseError InstallFields(OQueryDesignView* _pView,
+ const ::connectivity::OSQLParseNode* pNode,
+ OJoinTableView::OTableWindowMap* pTabList )
+ {
+ if( pNode==nullptr || !SQL_ISRULE(pNode,select_statement))
+ return eNoSelectStatement;
+
+ ::connectivity::OSQLParseNode* pParseTree = pNode->getChild(2); // selection
+ bool bFirstField = true; // When initializing, the first field must be reactivated
+
+ SqlParseError eErrorCode = eOk;
+
+ if ( pParseTree->isRule() && SQL_ISPUNCTUATION(pParseTree->getChild(0),"*") )
+ {
+ // SELECT * ...
+ eErrorCode = fillSelectSubList(_pView,pTabList);
+ }
+ else if (SQL_ISRULE(pParseTree,scalar_exp_commalist) )
+ {
+ // SELECT column, ...
+ OQueryController& rController = static_cast<OQueryController&>(_pView->getController());
+ Reference< XConnection> xConnection = rController.getConnection();
+
+ OUString aColumnName,aTableRange;
+ for (size_t i = 0; i < pParseTree->count() && eOk == eErrorCode ; ++i)
+ {
+ ::connectivity::OSQLParseNode * pColumnRef = pParseTree->getChild(i);
+
+ do {
+
+ if ( SQL_ISRULE(pColumnRef,select_sublist) )
+ {
+ eErrorCode = fillSelectSubList(_pView,pTabList);
+ break;
+ }
+
+ if ( SQL_ISRULE(pColumnRef,derived_column) )
+ {
+ OUString aColumnAlias(connectivity::OSQLParseTreeIterator::getColumnAlias(pColumnRef)); // might be empty
+ pColumnRef = pColumnRef->getChild(0);
+ OTableFieldDescRef aInfo = new OTableFieldDesc();
+
+ if ( pColumnRef->getKnownRuleID() != OSQLParseNode::subquery &&
+ pColumnRef->count() == 3 &&
+ SQL_ISPUNCTUATION(pColumnRef->getChild(0),"(") &&
+ SQL_ISPUNCTUATION(pColumnRef->getChild(2),")")
+ )
+ pColumnRef = pColumnRef->getChild(1);
+
+ if (SQL_ISRULE(pColumnRef,column_ref))
+ {
+ InsertColumnRef(_pView,pColumnRef,aColumnName,aColumnAlias,aTableRange,aInfo,pTabList);
+ eErrorCode = _pView->InsertField(aInfo, bFirstField);
+ bFirstField = false;
+ }
+ else if(SQL_ISRULEOR3(pColumnRef, general_set_fct, set_fct_spec, position_exp) ||
+ SQL_ISRULEOR3(pColumnRef, extract_exp, fold, char_substring_fct) ||
+ SQL_ISRULEOR2(pColumnRef,length_exp,char_value_fct))
+ {
+ OUString aColumns;
+ pColumnRef->parseNodeToPredicateStr(aColumns,
+ xConnection,
+ rController.getNumberFormatter(),
+ _pView->getLocale(),
+ _pView->getDecimalSeparator(),
+ &rController.getParser().getContext());
+
+ sal_Int32 nFunctionType = FKT_NONE;
+ ::connectivity::OSQLParseNode* pParamRef = nullptr;
+ sal_Int32 nColumnRefPos = pColumnRef->count() - 2;
+ if ( nColumnRefPos >= 0 && o3tl::make_unsigned(nColumnRefPos) < pColumnRef->count() )
+ pParamRef = pColumnRef->getChild(nColumnRefPos);
+
+ if ( SQL_ISRULE(pColumnRef,general_set_fct)
+ && pParamRef && SQL_ISRULE(pParamRef,column_ref) )
+ {
+ // Check the parameters for Column references
+ InsertColumnRef(_pView,pParamRef,aColumnName,aColumnAlias,aTableRange,aInfo,pTabList);
+ }
+ else if ( SQL_ISRULE(pColumnRef,general_set_fct) )
+ {
+ if ( pParamRef && pParamRef->getTokenValue().toChar() == '*' )
+ {
+ for (auto const& table : *pTabList)
+ {
+ OQueryTableWindow* pTabWin = static_cast<OQueryTableWindow*>(table.second.get());
+ if (pTabWin->ExistsField( "*", aInfo ))
+ {
+ aInfo->SetAlias(OUString());
+ aInfo->SetTable(OUString());
+ break;
+ }
+ }
+ }
+ else
+ {
+ OUString sFieldName = aColumns;
+ if ( pParamRef )
+ { // we got an aggregate function but without column name inside
+ // so we set the whole argument of the function as field name
+ nFunctionType |= FKT_NUMERIC;
+ sFieldName.clear();
+ pParamRef->parseNodeToStr( sFieldName,
+ xConnection,
+ &rController.getParser().getContext(),
+ true); // quote is to true because we need quoted elements inside the function
+ }
+ aInfo->SetDataType(DataType::DOUBLE);
+ aInfo->SetFieldType(TAB_NORMAL_FIELD);
+ aInfo->SetField(sFieldName);
+ }
+ aInfo->SetTabWindow(nullptr);
+ aInfo->SetFieldAlias(aColumnAlias);
+ }
+ else
+ {
+ _pView->fillFunctionInfo(pColumnRef,aColumns,aInfo);
+ aInfo->SetFieldAlias(aColumnAlias);
+ }
+
+ if ( SQL_ISRULE(pColumnRef,general_set_fct) )
+ {
+ aInfo->SetFunctionType(nFunctionType|FKT_AGGREGATE);
+ aInfo->SetFunction(OUString(comphelper::string::stripEnd(o3tl::getToken(aColumns,0,'('), ' ')));
+ }
+ else
+ aInfo->SetFunctionType(nFunctionType|FKT_OTHER);
+
+ eErrorCode = _pView->InsertField(aInfo, bFirstField);
+ bFirstField = false;
+ }
+ else
+ {
+ OUString aColumns;
+ pColumnRef->parseNodeToStr( aColumns,
+ xConnection,
+ &rController.getParser().getContext(),
+ true); // quote is to true because we need quoted elements inside the function
+
+ aInfo->SetTabWindow( nullptr );
+
+ // since we support queries in queries, the thingie might belong to an existing "table"
+ OQueryTableWindow* pExistingTable = lcl_findColumnInTables( aColumns, *pTabList, aInfo );
+ if ( pExistingTable )
+ {
+ aInfo->SetTabWindow( pExistingTable );
+ aInfo->SetTable( pExistingTable->GetTableName() );
+ aInfo->SetAlias( pExistingTable->GetAliasName() );
+ }
+
+ aInfo->SetDataType(DataType::DOUBLE);
+ aInfo->SetFieldType(TAB_NORMAL_FIELD);
+ aInfo->SetField(aColumns);
+ aInfo->SetFieldAlias(aColumnAlias);
+ aInfo->SetFunctionType(FKT_NUMERIC | FKT_OTHER);
+
+ eErrorCode = _pView->InsertField(aInfo, bFirstField);
+ bFirstField = false;
+ }
+
+ break;
+ }
+
+ OSL_FAIL( "InstallFields: don't know how to interpret this parse node!" );
+
+ } while ( false );
+ }
+ }
+ else
+ eErrorCode = eStatementTooComplex;
+
+ return eErrorCode;
+ }
+ SqlParseError GetOrderCriteria( OQueryDesignView* _pView,
+ OSelectionBrowseBox* _pSelectionBrw,
+ const ::connectivity::OSQLParseNode* pParseRoot )
+ {
+ SqlParseError eErrorCode = eOk;
+ if (!pParseRoot->getChild(3)->getChild(ORDER_BY_CHILD_POS)->isLeaf())
+ {
+ ::connectivity::OSQLParseNode* pNode = pParseRoot->getChild(3)->getChild(ORDER_BY_CHILD_POS)->getChild(2);
+ ::connectivity::OSQLParseNode* pParamRef = nullptr;
+
+ OQueryController& rController = static_cast<OQueryController&>(_pView->getController());
+ EOrderDir eOrderDir;
+ for( size_t i=0 ; i<pNode->count() ; i++ )
+ {
+ OTableFieldDescRef aDragLeft = new OTableFieldDesc();
+ eOrderDir = ORDER_ASC;
+ ::connectivity::OSQLParseNode* pChild = pNode->getChild( i );
+
+ if (SQL_ISTOKEN( pChild->getChild(1), DESC ) )
+ eOrderDir = ORDER_DESC;
+
+ ::connectivity::OSQLParseNode* pArgument = pChild->getChild(0);
+
+ if(SQL_ISRULE(pArgument,column_ref))
+ {
+ if( eOk == FillDragInfo(_pView,pArgument,aDragLeft))
+ _pSelectionBrw->AddOrder( aDragLeft, eOrderDir, i);
+ else // it could be an alias name for a field
+ {
+ OUString aTableRange,aColumnName;
+ ::connectivity::OSQLParseTreeIterator& rParseIter = rController.getParseIterator();
+ rParseIter.getColumnRange( pArgument, aColumnName, aTableRange );
+
+ OTableFields& aList = rController.getTableFieldDesc();
+ for (auto const& elem : aList)
+ {
+ if(elem.is() && elem->GetFieldAlias() == aColumnName)
+ elem->SetOrderDir( eOrderDir );
+ }
+ }
+ }
+ else if(SQL_ISRULE(pArgument, general_set_fct ) &&
+ SQL_ISRULE(pParamRef = pArgument->getChild(pArgument->count()-2),column_ref) &&
+ eOk == FillDragInfo(_pView,pParamRef,aDragLeft))
+ _pSelectionBrw->AddOrder( aDragLeft, eOrderDir, i );
+ else if( SQL_ISRULE(pArgument, set_fct_spec ) )
+ {
+
+ Reference< XConnection> xConnection = rController.getConnection();
+ if(xConnection.is())
+ {
+ OUString sCondition;
+ pArgument->parseNodeToPredicateStr(sCondition,
+ xConnection,
+ rController.getNumberFormatter(),
+ _pView->getLocale(),
+ _pView->getDecimalSeparator(),
+ &rController.getParser().getContext());
+ _pView->fillFunctionInfo(pArgument,sCondition,aDragLeft);
+ aDragLeft->SetFunctionType(FKT_OTHER);
+ aDragLeft->SetOrderDir(eOrderDir);
+ aDragLeft->SetVisible(false);
+ _pSelectionBrw->AddOrder( aDragLeft, eOrderDir, i );
+ }
+ else
+ eErrorCode = eColumnNotFound;
+ }
+ else
+ eErrorCode = eColumnNotFound;
+ }
+ }
+ return eErrorCode;
+ }
+ SqlParseError GetHavingCriteria( OQueryDesignView* _pView,
+ OSelectionBrowseBox* _pSelectionBrw,
+ const ::connectivity::OSQLParseNode* pSelectRoot,
+ sal_uInt16& rLevel )
+ {
+ SqlParseError eErrorCode = eOk;
+ if (!pSelectRoot->getChild(3)->getChild(3)->isLeaf())
+ eErrorCode = GetORCriteria(_pView,_pSelectionBrw,pSelectRoot->getChild(3)->getChild(3)->getChild(1),rLevel, true);
+ return eErrorCode;
+ }
+ SqlParseError GetGroupCriteria( OQueryDesignView* _pView,
+ OSelectionBrowseBox* _pSelectionBrw,
+ const ::connectivity::OSQLParseNode* pSelectRoot )
+ {
+ SqlParseError eErrorCode = eOk;
+ if (!pSelectRoot->getChild(3)->getChild(2)->isLeaf()) // opt_group_by_clause
+ {
+ OQueryController& rController = static_cast<OQueryController&>(_pView->getController());
+ ::connectivity::OSQLParseNode* pGroupBy = pSelectRoot->getChild(3)->getChild(2)->getChild(2);
+
+ for( size_t i=0 ; i < pGroupBy->count() && eOk == eErrorCode; ++i )
+ {
+ OTableFieldDescRef aDragInfo = new OTableFieldDesc();
+ ::connectivity::OSQLParseNode* pParamRef = nullptr;
+ ::connectivity::OSQLParseNode* pArgument = pGroupBy->getChild( i );
+ if(SQL_ISRULE(pArgument,column_ref))
+ {
+ if ( eOk == (eErrorCode = FillDragInfo(_pView,pArgument,aDragInfo)) )
+ {
+ aDragInfo->SetGroupBy(true);
+ _pSelectionBrw->AddGroupBy(aDragInfo);
+ }
+ }
+ else if(SQL_ISRULE(pArgument, general_set_fct ) &&
+ SQL_ISRULE(pParamRef = pArgument->getChild(pArgument->count()-2),column_ref) &&
+ eOk == FillDragInfo(_pView,pParamRef,aDragInfo))
+ {
+ aDragInfo->SetGroupBy(true);
+ _pSelectionBrw->AddGroupBy( aDragInfo );
+ }
+ else if( SQL_ISRULE(pArgument, set_fct_spec ) )
+ {
+ Reference< XConnection> xConnection = rController.getConnection();
+ if(xConnection.is())
+ {
+ OUString sGroupByExpression;
+ pArgument->parseNodeToStr( sGroupByExpression,
+ xConnection,
+ &rController.getParser().getContext(),
+ true); // quote is to true because we need quoted elements inside the function
+ _pView->fillFunctionInfo(pArgument,sGroupByExpression,aDragInfo);
+ aDragInfo->SetFunctionType(FKT_OTHER);
+ aDragInfo->SetGroupBy(true);
+ aDragInfo->SetVisible(false);
+ _pSelectionBrw->AddGroupBy( aDragInfo );
+ }
+ else
+ eErrorCode = eColumnNotFound;
+ }
+ }
+ }
+ return eErrorCode;
+ }
+
+ OUString getParseErrorMessage( SqlParseError _eErrorCode )
+ {
+ TranslateId pResId;
+ switch (_eErrorCode)
+ {
+ case eIllegalJoin:
+ pResId = STR_QRY_ILLEGAL_JOIN;
+ break;
+ case eStatementTooLong:
+ pResId = STR_QRY_TOO_LONG_STATEMENT;
+ break;
+ case eNoConnection:
+ pResId = STR_QRY_SYNTAX;
+ break;
+ case eNoSelectStatement:
+ pResId = STR_QRY_NOSELECT;
+ break;
+ case eNoColumnInLike:
+ pResId = STR_QRY_SYNTAX;
+ break;
+ case eColumnNotFound:
+ pResId = STR_QRY_SYNTAX;
+ break;
+ case eNativeMode:
+ pResId = STR_QRY_NATIVE;
+ break;
+ case eTooManyTables:
+ pResId = STR_QRY_TOO_MANY_TABLES;
+ break;
+ case eTooManyColumns:
+ pResId = STR_QRY_TOO_MANY_COLUMNS;
+ break;
+ case eStatementTooComplex:
+ pResId = STR_QRY_TOOCOMPLEX;
+ break;
+ default:
+ pResId = STR_QRY_SYNTAX;
+ break;
+ }
+ return DBA_RES(pResId);
+ }
+}
+
+// end of anonymous namespace
+
+OQueryDesignView::OQueryDesignView( OQueryContainerWindow* _pParent,
+ OQueryController& _rController,
+ const Reference< XComponentContext >& _rxContext)
+ :OJoinDesignView( _pParent, _rController, _rxContext )
+ ,m_aSplitter( VclPtr<Splitter>::Create(this) )
+ ,m_eChildFocus(NONE)
+ ,m_bInSplitHandler( false )
+{
+
+ try
+ {
+ SvtSysLocale aSysLocale;
+ m_aLocale = aSysLocale.GetLanguageTag().getLocale();
+ m_sDecimalSep = aSysLocale.GetLocaleData().getNumDecimalSep();
+ }
+ catch(Exception&)
+ {
+ }
+
+ m_pSelectionBox = VclPtr<OSelectionBrowseBox>::Create(this);
+
+ setNoneVisibleRow(static_cast<OQueryController&>(getController()).getVisibleRows());
+ m_pSelectionBox->Show();
+ // setup Splitter
+ m_aSplitter->SetSplitHdl(LINK(this, OQueryDesignView,SplitHdl));
+ m_aSplitter->Show();
+
+}
+
+OQueryDesignView::~OQueryDesignView()
+{
+ disposeOnce();
+}
+
+void OQueryDesignView::dispose()
+{
+ if ( m_pTableView )
+ ::dbaui::notifySystemWindow(this,m_pTableView,::comphelper::mem_fun(&TaskPaneList::RemoveWindow));
+ m_pSelectionBox.disposeAndClear();
+ m_aSplitter.disposeAndClear();
+ OJoinDesignView::dispose();
+}
+
+IMPL_LINK_NOARG( OQueryDesignView, SplitHdl, Splitter*, void )
+{
+ if (!getController().isReadOnly())
+ {
+ m_bInSplitHandler = true;
+ m_aSplitter->SetPosPixel( Point( m_aSplitter->GetPosPixel().X(),m_aSplitter->GetSplitPosPixel() ) );
+ static_cast<OQueryController&>(getController()).setSplitPos(m_aSplitter->GetSplitPosPixel());
+ static_cast<OQueryController&>(getController()).setModified( true );
+ Resize();
+ m_bInSplitHandler = true;
+ }
+}
+
+void OQueryDesignView::Construct()
+{
+ m_pTableView = VclPtr<OQueryTableView>::Create(m_pScrollWindow,this);
+ ::dbaui::notifySystemWindow(this,m_pTableView,::comphelper::mem_fun(&TaskPaneList::AddWindow));
+ OJoinDesignView::Construct();
+}
+
+void OQueryDesignView::initialize()
+{
+ if(static_cast<OQueryController&>(getController()).getSplitPos() != -1)
+ {
+ m_aSplitter->SetPosPixel( Point( m_aSplitter->GetPosPixel().X(),static_cast<OQueryController&>(getController()).getSplitPos() ) );
+ m_aSplitter->SetSplitPosPixel(static_cast<OQueryController&>(getController()).getSplitPos());
+ }
+ m_pSelectionBox->initialize();
+ reset();
+}
+
+void OQueryDesignView::resizeDocumentView(tools::Rectangle& _rPlayground)
+{
+ Point aPlaygroundPos( _rPlayground.TopLeft() );
+ Size aPlaygroundSize( _rPlayground.GetSize() );
+
+ // calc the split pos, and forward it to the controller
+ sal_Int32 nSplitPos = static_cast<OQueryController&>(getController()).getSplitPos();
+ if ( 0 != aPlaygroundSize.Height() )
+ {
+ if ( ( -1 == nSplitPos )
+ || ( nSplitPos >= aPlaygroundSize.Height() )
+ )
+ {
+ // let the selection browse box determine an optimal size
+ Size aSelectionBoxSize = m_pSelectionBox->CalcOptimalSize( aPlaygroundSize );
+ nSplitPos = aPlaygroundSize.Height() - aSelectionBoxSize.Height() - m_aSplitter->GetSizePixel().Height();
+ // still an invalid size?
+ if ( nSplitPos == -1 || nSplitPos >= aPlaygroundSize.Height() )
+ nSplitPos = sal_Int32(aPlaygroundSize.Height()*0.6);
+
+ static_cast<OQueryController&>(getController()).setSplitPos(nSplitPos);
+ }
+
+ if ( !m_bInSplitHandler )
+ { // the resize is triggered by something else than the split handler
+ // our main focus is to try to preserve the size of the selectionbrowse box
+ Size aSelBoxSize = m_pSelectionBox->GetSizePixel();
+ if ( aSelBoxSize.Height() )
+ {
+ // keep the size of the sel box constant
+ nSplitPos = aPlaygroundSize.Height() - m_aSplitter->GetSizePixel().Height() - aSelBoxSize.Height();
+
+ // and if the box is smaller than the optimal size, try to do something about it
+ Size aSelBoxOptSize = m_pSelectionBox->CalcOptimalSize( aPlaygroundSize );
+ if ( aSelBoxOptSize.Height() > aSelBoxSize.Height() )
+ {
+ nSplitPos = aPlaygroundSize.Height() - m_aSplitter->GetSizePixel().Height() - aSelBoxOptSize.Height();
+ }
+
+ static_cast< OQueryController& >(getController()).setSplitPos( nSplitPos );
+ }
+ }
+ }
+
+ // normalize the split pos
+ Point aSplitPos( _rPlayground.Left(), nSplitPos );
+ Size aSplitSize( _rPlayground.GetSize().Width(), m_aSplitter->GetSizePixel().Height() );
+
+ if( ( aSplitPos.Y() + aSplitSize.Height() ) > ( aPlaygroundSize.Height() ))
+ aSplitPos.setY( aPlaygroundSize.Height() - aSplitSize.Height() );
+
+ if( aSplitPos.Y() <= aPlaygroundPos.Y() )
+ aSplitPos.setY( aPlaygroundPos.Y() + sal_Int32(aPlaygroundSize.Height() * 0.2) );
+
+ // position the table
+ Size aTableViewSize(aPlaygroundSize.Width(), aSplitPos.Y() - aPlaygroundPos.Y());
+ m_pScrollWindow->SetPosSizePixel(aPlaygroundPos, aTableViewSize);
+
+ // position the selection browse box
+ Point aPos( aPlaygroundPos.X(), aSplitPos.Y() + aSplitSize.Height() );
+ m_pSelectionBox->SetPosSizePixel( aPos, Size( aPlaygroundSize.Width(), aPlaygroundSize.Height() - aSplitSize.Height() - aTableViewSize.Height() ));
+
+ // set the size of the splitter
+ m_aSplitter->SetPosSizePixel( aSplitPos, aSplitSize );
+ m_aSplitter->SetDragRectPixel( _rPlayground );
+
+ // just for completeness: there is no space left, we occupied it all ...
+ _rPlayground.SetPos( _rPlayground.BottomRight() );
+ _rPlayground.SetSize( Size( 0, 0 ) );
+}
+
+void OQueryDesignView::setReadOnly(bool _bReadOnly)
+{
+ m_pSelectionBox->SetReadOnly(_bReadOnly);
+}
+
+void OQueryDesignView::clear()
+{
+ m_pSelectionBox->ClearAll(); // clear the whole selection
+ m_pTableView->ClearAll();
+}
+
+void OQueryDesignView::copy()
+{
+ if( m_eChildFocus == SELECTION)
+ m_pSelectionBox->copy();
+}
+
+bool OQueryDesignView::isCutAllowed() const
+{
+ bool bAllowed = false;
+ if ( SELECTION == m_eChildFocus )
+ bAllowed = m_pSelectionBox->isCutAllowed();
+ return bAllowed;
+}
+
+bool OQueryDesignView::isPasteAllowed() const
+{
+ bool bAllowed = false;
+ if ( SELECTION == m_eChildFocus )
+ bAllowed = m_pSelectionBox->isPasteAllowed();
+ return bAllowed;
+}
+
+bool OQueryDesignView::isCopyAllowed() const
+{
+ bool bAllowed = false;
+ if ( SELECTION == m_eChildFocus )
+ bAllowed = m_pSelectionBox->isCopyAllowed();
+ return bAllowed;
+}
+
+void OQueryDesignView::stopTimer()
+{
+ m_pSelectionBox->stopTimer();
+}
+
+void OQueryDesignView::startTimer()
+{
+ m_pSelectionBox->startTimer();
+}
+
+void OQueryDesignView::cut()
+{
+ if( m_eChildFocus == SELECTION)
+ {
+ m_pSelectionBox->cut();
+ static_cast<OQueryController&>(getController()).setModified(true);
+ }
+}
+
+void OQueryDesignView::paste()
+{
+ if( m_eChildFocus == SELECTION)
+ {
+ m_pSelectionBox->paste();
+ static_cast<OQueryController&>(getController()).setModified(true);
+ }
+}
+
+void OQueryDesignView::TableDeleted(const OUString& rAliasName)
+{
+ // message that the table was removed from the window
+ m_pSelectionBox->DeleteFields( rAliasName );
+ static_cast<OQueryController&>(getController()).InvalidateFeature(ID_BROWSER_ADDTABLE); // inform the view again
+}
+
+bool OQueryDesignView::HasFieldByAliasName(std::u16string_view rFieldName, OTableFieldDescRef const & rInfo) const
+{
+ return m_pSelectionBox->HasFieldByAliasName( rFieldName, rInfo);
+}
+
+SqlParseError OQueryDesignView::InsertField( const OTableFieldDescRef& rInfo, bool bActivate)
+{
+ return m_pSelectionBox->InsertField( rInfo, BROWSER_INVALIDID, true/*bVis*/, bActivate ).is() ? eOk : eTooManyColumns;
+}
+
+sal_Int32 OQueryDesignView::getColWidth(sal_uInt16 _nColPos) const
+{
+ static sal_Int32 s_nDefaultWidth = GetTextWidth("0") * 15;
+ sal_Int32 nWidth = static_cast<OQueryController&>(getController()).getColWidth(_nColPos);
+ if ( !nWidth )
+ nWidth = s_nDefaultWidth;
+ return nWidth;
+}
+
+void OQueryDesignView::fillValidFields(std::u16string_view sAliasName, weld::ComboBox& rFieldList)
+{
+ rFieldList.clear();
+
+ bool bAllTables = sAliasName.empty();
+
+ OJoinTableView::OTableWindowMap& rTabWins = m_pTableView->GetTabWinMap();
+ OUString strCurrentPrefix;
+ std::vector< OUString> aFields;
+ for (auto const& tabWin : rTabWins)
+ {
+ OQueryTableWindow* pCurrentWin = static_cast<OQueryTableWindow*>(tabWin.second.get());
+ if (bAllTables || (pCurrentWin->GetAliasName() == sAliasName))
+ {
+ strCurrentPrefix = pCurrentWin->GetAliasName() + ".";
+
+ pCurrentWin->EnumValidFields(aFields);
+
+ for (auto const& field : aFields)
+ {
+ if (bAllTables || field.toChar() == '*')
+ rFieldList.append_text(strCurrentPrefix + field);
+ else
+ rFieldList.append_text(field);
+ }
+
+ if (!bAllTables)
+ // this means that I came into this block because the table name was exactly what I was looking for so I can end here
+ // (and I prevent that fields get added more than once, if a table is repeated in TabWin)
+ break;
+ }
+ }
+}
+
+bool OQueryDesignView::PreNotify(NotifyEvent& rNEvt)
+{
+ if (rNEvt.GetType() == MouseNotifyEvent::GETFOCUS)
+ {
+ if ( m_pSelectionBox && m_pSelectionBox->HasChildPathFocus() )
+ m_eChildFocus = SELECTION;
+ else
+ m_eChildFocus = TABLEVIEW;
+ }
+
+ return OJoinDesignView::PreNotify(rNEvt);
+}
+
+// check if the statement is correct when not returning false
+bool OQueryDesignView::checkStatement()
+{
+ bool bRet = true;
+ if ( m_pSelectionBox )
+ bRet = m_pSelectionBox->Save(); // an error occurred so we return no
+ return bRet;
+}
+
+OUString OQueryDesignView::getStatement()
+{
+ OQueryController& rController = static_cast<OQueryController&>(getController());
+ m_rController.clearError();
+ // used for fields which aren't any longer in the statement
+ OTableFields& rUnUsedFields = rController.getUnUsedFields();
+ OTableFields().swap( rUnUsedFields );
+
+ // create the select columns
+ sal_uInt32 nFieldcount = 0;
+ OTableFields& rFieldList = rController.getTableFieldDesc();
+ for (auto const& field : rFieldList)
+ {
+ if (!field->GetField().isEmpty() && field->IsVisible() )
+ ++nFieldcount;
+ else if (!field->GetField().isEmpty() &&
+ !field->HasCriteria() &&
+ field->isNoneFunction() &&
+ field->GetOrderDir() == ORDER_NONE &&
+ !field->IsGroupBy() &&
+ field->GetFunction().isEmpty() )
+ rUnUsedFields.push_back(field);
+ }
+ if ( !nFieldcount ) // no visible fields so return
+ {
+ rUnUsedFields = rFieldList;
+ return OUString();
+ }
+
+ OQueryTableView::OTableWindowMap& rTabList = m_pTableView->GetTabWinMap();
+ sal_uInt32 nTabcount = rTabList.size();
+
+ OUString aFieldListStr(GenerateSelectList(this,rFieldList,nTabcount>1));
+ if( aFieldListStr.isEmpty() )
+ return OUString();
+
+ // Exception handling, if no fields have been passed we should not
+ // change the tab page
+ // TabBarSelectHdl will query the SQL-OUString for STATEMENT_NOFIELDS
+ // and trigger an error message
+ // ----------------- Build table list ----------------------
+
+ const auto& rConnList = m_pTableView->getTableConnections();
+ Reference< XConnection> xConnection = rController.getConnection();
+ OUString aTableListStr(GenerateFromClause(xConnection,&rTabList,rConnList));
+ OSL_ENSURE(!aTableListStr.isEmpty(), "OQueryDesignView::getStatement() : unexpected : have Fields, but no Tables !");
+ // if fields exist now, these only can be created by inserting from an already existing table; if on the other hand
+ // a table is deleted, also the belonging fields will be deleted -> therefore it CANNOT occur that fields
+ // exist but no tables exist (and aFieldListStr has its length, I secure this above)
+ OUStringBuffer aHavingStr,aCriteriaListStr;
+
+ // ----------------- build the criteria ----------------------
+ if (!GenerateCriterias(this,aCriteriaListStr,aHavingStr,rFieldList, nTabcount > 1))
+ return OUString();
+
+ OUString aJoinCrit;
+ GenerateInnerJoinCriterias(xConnection,aJoinCrit,rConnList);
+ if(!aJoinCrit.isEmpty())
+ {
+ OUString aTmp = "( " + aJoinCrit + " )";
+ if(!aCriteriaListStr.isEmpty())
+ {
+ aTmp += C_AND;
+ }
+ aCriteriaListStr.insert(0, aTmp);
+ }
+ // ----------------- construct statement ----------------------
+ OUStringBuffer aSqlCmd("SELECT ");
+ if(rController.isDistinct())
+ aSqlCmd.append(" DISTINCT ");
+ aSqlCmd.append(aFieldListStr);
+ aSqlCmd.append(" FROM ");
+ aSqlCmd.append(aTableListStr);
+
+ if (!aCriteriaListStr.isEmpty())
+ {
+ aSqlCmd.append(" WHERE ");
+ aSqlCmd.append(aCriteriaListStr);
+ }
+ Reference<XDatabaseMetaData> xMeta;
+ if ( xConnection.is() )
+ xMeta = xConnection->getMetaData();
+ bool bUseAlias = nTabcount > 1;
+ if ( xMeta.is() )
+ bUseAlias = bUseAlias || !xMeta->supportsGroupByUnrelated();
+
+ aSqlCmd.append(GenerateGroupBy(this,rFieldList,bUseAlias));
+ // ----------------- construct GroupBy and attach ------------
+ if(!aHavingStr.isEmpty())
+ {
+ aSqlCmd.append(" HAVING ");
+ aSqlCmd.append(aHavingStr);
+ }
+ // ----------------- construct sorting and attach ------------
+ OUString sOrder;
+ SqlParseError eErrorCode = eOk;
+ if ( (eErrorCode = GenerateOrder(this,rFieldList,nTabcount > 1,sOrder)) == eOk)
+ aSqlCmd.append(sOrder);
+ else
+ {
+ if ( !m_rController.hasError() )
+ m_rController.appendError( getParseErrorMessage( eErrorCode ) );
+
+ m_rController.displayError();
+ }
+ // --------------------- Limit Clause -------------------
+ {
+ const sal_Int64 nLimit = rController.getLimit();
+ if( nLimit != -1 )
+ {
+ aSqlCmd.append( " LIMIT " + OUString::number(nLimit) );
+ }
+ }
+
+ OUString sSQL = aSqlCmd.makeStringAndClear();
+ if ( xConnection.is() )
+ {
+ ::connectivity::OSQLParser& rParser( rController.getParser() );
+ OUString sErrorMessage;
+ std::unique_ptr<OSQLParseNode> pParseNode( rParser.parseTree( sErrorMessage, sSQL, true ) );
+ if (pParseNode)
+ {
+ OSQLParseNode* pNode = pParseNode->getChild(3)->getChild(1);
+ if ( pNode->count() > 1 )
+ {
+ ::connectivity::OSQLParseNode * pCondition = pNode->getChild(1);
+ if ( pCondition ) // no where clause
+ {
+ OSQLParseNode::compress(pCondition);
+ OUString sTemp;
+ pParseNode->parseNodeToStr(sTemp,xConnection);
+ sSQL = sTemp;
+ }
+ }
+ }
+ }
+ return sSQL;
+}
+
+void OQueryDesignView::setSlotEnabled(sal_Int32 _nSlotId, bool _bEnable)
+{
+ sal_uInt16 nRow;
+ switch (_nSlotId)
+ {
+ case SID_QUERY_VIEW_FUNCTIONS:
+ nRow = BROW_FUNCTION_ROW;
+ break;
+ case SID_QUERY_VIEW_TABLES:
+ nRow = BROW_TABLE_ROW;
+ break;
+ case SID_QUERY_VIEW_ALIASES:
+ nRow = BROW_COLUMNALIAS_ROW;
+ break;
+ default:
+ // ????????????
+ nRow = 0;
+ break;
+ }
+ m_pSelectionBox->SetRowVisible(nRow,_bEnable);
+ m_pSelectionBox->Invalidate();
+}
+
+bool OQueryDesignView::isSlotEnabled(sal_Int32 _nSlotId)
+{
+ sal_uInt16 nRow;
+ switch (_nSlotId)
+ {
+ case SID_QUERY_VIEW_FUNCTIONS:
+ nRow = BROW_FUNCTION_ROW;
+ break;
+ case SID_QUERY_VIEW_TABLES:
+ nRow = BROW_TABLE_ROW;
+ break;
+ case SID_QUERY_VIEW_ALIASES:
+ nRow = BROW_COLUMNALIAS_ROW;
+ break;
+ default:
+ // ?????????
+ nRow = 0;
+ break;
+ }
+ return m_pSelectionBox->IsRowVisible(nRow);
+}
+
+void OQueryDesignView::SaveUIConfig()
+{
+ OQueryController& rCtrl = static_cast<OQueryController&>(getController());
+ rCtrl.SaveTabWinsPosSize( &m_pTableView->GetTabWinMap(), m_pScrollWindow->GetHScrollBar().GetThumbPos(), m_pScrollWindow->GetVScrollBar().GetThumbPos() );
+ rCtrl.setVisibleRows( m_pSelectionBox->GetNoneVisibleRows() );
+ if ( m_aSplitter->GetSplitPosPixel() != 0 )
+ rCtrl.setSplitPos( m_aSplitter->GetSplitPosPixel() );
+}
+
+std::unique_ptr<OSQLParseNode> OQueryDesignView::getPredicateTreeFromEntry(const OTableFieldDescRef& pEntry,
+ const OUString& _sCriteria,
+ OUString& _rsErrorMessage,
+ Reference<XPropertySet>& _rxColumn) const
+{
+ OSL_ENSURE(pEntry.is(),"Entry is null!");
+ if(!pEntry.is())
+ return nullptr;
+ Reference< XConnection> xConnection = static_cast<OQueryController&>(getController()).getConnection();
+ if(!xConnection.is())
+ return nullptr;
+
+ ::connectivity::OSQLParser& rParser( static_cast<OQueryController&>(getController()).getParser() );
+ OQueryTableWindow* pWin = static_cast<OQueryTableWindow*>(pEntry->GetTabWindow());
+
+ // special handling for functions
+ if ( pEntry->GetFunctionType() & (FKT_OTHER | FKT_AGGREGATE | FKT_NUMERIC) )
+ {
+ // we have a function here so we have to distinguish the type of return value
+ OUString sFunction;
+ if ( pEntry->isNumericOrAggregateFunction() )
+ sFunction = pEntry->GetFunction().getToken(0, '(');
+
+ if ( sFunction.isEmpty() )
+ sFunction = pEntry->GetField().getToken(0, '(');
+
+ sal_Int32 nType = ::connectivity::OSQLParser::getFunctionReturnType(sFunction,&rParser.getContext());
+ if ( nType == DataType::OTHER || (sFunction.isEmpty() && pEntry->isNumericOrAggregateFunction()) )
+ {
+ // first try the international version
+ OUString sSql = "SELECT * FROM x WHERE " + pEntry->GetField() + _sCriteria;
+ std::unique_ptr<OSQLParseNode> pParseNode( rParser.parseTree( _rsErrorMessage, sSql, true ) );
+ nType = DataType::DOUBLE;
+ if (pParseNode)
+ {
+ OSQLParseNode* pColumnRef = pParseNode->getByRule(OSQLParseNode::column_ref);
+ if ( pColumnRef )
+ {
+ OTableFieldDescRef aField = new OTableFieldDesc();
+ if ( eOk == FillDragInfo(this,pColumnRef,aField) )
+ {
+ nType = aField->GetDataType();
+ }
+ }
+ }
+ }
+
+ Reference<XDatabaseMetaData> xMeta = xConnection->getMetaData();
+ rtl::Reference<parse::OParseColumn> pColumn = new parse::OParseColumn( pEntry->GetField(),
+ OUString(),
+ OUString(),
+ OUString(),
+ ColumnValue::NULLABLE_UNKNOWN,
+ 0,
+ 0,
+ nType,
+ false,
+ false,
+ xMeta.is() && xMeta->supportsMixedCaseQuotedIdentifiers(),
+ OUString(),
+ OUString(),
+ OUString());
+ _rxColumn = pColumn;
+ pColumn->setFunction(true);
+ pColumn->setRealName(pEntry->GetField());
+ }
+ else
+ {
+ if (pWin)
+ {
+ Reference<XNameAccess> xColumns = pWin->GetOriginalColumns();
+ if (xColumns.is() && xColumns->hasByName(pEntry->GetField()))
+ xColumns->getByName(pEntry->GetField()) >>= _rxColumn;
+ }
+ }
+
+ // _rxColumn, if it is a "lookup" column, not a computed column,
+ // is guaranteed to be the column taken from the *source* of the column,
+ // that is either a table or another query.
+ // _rxColumn is *not* taken from the columns of the query we are constructing
+ // (and rightfully so, since it may not be part of these columns; SELECT A FROM t WHERE B = foo)
+ // If it is a computed column, we just constructed it above, with same Name and RealName.
+ // In all cases, we should use the "external" name of the column, not the "RealName";
+ // the latter is the name that the column had in the source of the source query.
+ // An example: we are designing "SELECT A, B FROM q WHERE C='foo'"
+ // q itself is query "SELECT aye AS A, bee as B, cee as C FROM t"
+ // We are currently treating the entry "C='foo'"
+ // Then _rxColumn has Name "C" and RealName "cee". We should *obviously* use "C", not "cee".
+ std::unique_ptr<OSQLParseNode> pParseNode = rParser.predicateTree( _rsErrorMessage,
+ _sCriteria,
+ static_cast<OQueryController&>(getController()).getNumberFormatter(),
+ _rxColumn,
+ false);
+ return pParseNode;
+}
+
+void OQueryDesignView::GetFocus()
+{
+ OJoinDesignView::GetFocus();
+ if ( m_pSelectionBox && !m_pSelectionBox->HasChildPathFocus() )
+ {
+ // first we have to deactivate the current cell to refill when necessary
+ m_pSelectionBox->DeactivateCell();
+ m_pSelectionBox->ActivateCell(m_pSelectionBox->GetCurRow(), m_pSelectionBox->GetCurColumnId());
+ m_pSelectionBox->GrabFocus();
+ }
+}
+
+void OQueryDesignView::reset()
+{
+ m_pTableView->ClearAll();
+ m_pTableView->ReSync();
+}
+
+void OQueryDesignView::setNoneVisibleRow(sal_Int32 _nRows)
+{
+ m_pSelectionBox->SetNoneVisibleRow(_nRows);
+}
+
+void OQueryDesignView::initByFieldDescriptions( const Sequence< PropertyValue >& i_rFieldDescriptions )
+{
+ OQueryController& rController = static_cast< OQueryController& >( getController() );
+
+ m_pSelectionBox->PreFill();
+ m_pSelectionBox->SetReadOnly( rController.isReadOnly() );
+ m_pSelectionBox->Fill();
+
+ for ( auto const & field : i_rFieldDescriptions )
+ {
+ ::rtl::Reference< OTableFieldDesc > pField( new OTableFieldDesc() );
+ pField->Load( field, true );
+ InsertField( pField, false );
+ }
+
+ rController.ClearUndoManager();
+ m_pSelectionBox->Invalidate();
+}
+
+bool OQueryDesignView::initByParseIterator( ::dbtools::SQLExceptionInfo* _pErrorInfo )
+{
+ SqlParseError eErrorCode = eNativeMode;
+ m_rController.clearError();
+
+ try
+ {
+ eErrorCode = InitFromParseNodeImpl( this, m_pSelectionBox );
+
+ if ( eErrorCode != eOk )
+ {
+ if ( !m_rController.hasError() )
+ m_rController.appendError( getParseErrorMessage( eErrorCode ) );
+
+ if ( _pErrorInfo )
+ {
+ *_pErrorInfo = m_rController.getError();
+ }
+ else
+ {
+ m_rController.displayError();
+ }
+ }
+ }
+ catch ( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ return eErrorCode == eOk;
+}
+
+// Utility function for fillFunctionInfo
+namespace {
+ sal_Int32 char_datatype(const::connectivity::OSQLParseNode* pDataType, const unsigned int offset) {
+ int cnt = pDataType->count() - offset;
+ if ( cnt < 0 )
+ {
+ OSL_FAIL("internal error in decoding character datatype specification");
+ return DataType::VARCHAR;
+ }
+ else if ( cnt == 0 )
+ {
+ if ( offset == 0 )
+ {
+ // The datatype is the node itself
+ if ( SQL_ISTOKENOR2 (pDataType, CHARACTER, CHAR) )
+ return DataType::CHAR;
+ else if ( SQL_ISTOKEN (pDataType, VARCHAR) )
+ return DataType::VARCHAR;
+ else if ( SQL_ISTOKEN (pDataType, CLOB) )
+ return DataType::CLOB;
+ else
+ {
+ OSL_FAIL("unknown/unexpected token in decoding character datatype specification");
+ return DataType::VARCHAR;
+ }
+ }
+ else
+ {
+ // No child left to read!
+ OSL_FAIL("incomplete datatype in decoding character datatype specification");
+ return DataType::VARCHAR;
+ }
+ }
+
+ if ( SQL_ISTOKEN(pDataType->getChild(offset), NATIONAL) )
+ return char_datatype(pDataType, offset+1);
+ else if ( SQL_ISTOKENOR3(pDataType->getChild(offset), CHARACTER, CHAR, NCHAR) )
+ {
+ if ( cnt > 2 && SQL_ISTOKEN(pDataType->getChild(offset+1), LARGE) && SQL_ISTOKEN(pDataType->getChild(offset+2), OBJECT) )
+ return DataType::CLOB;
+ else if ( cnt > 1 && SQL_ISTOKEN(pDataType->getChild(offset+1), VARYING) )
+ return DataType::VARCHAR;
+ else
+ return DataType::CHAR;
+ }
+ else if ( SQL_ISTOKEN (pDataType->getChild(offset), VARCHAR) )
+ return DataType::VARCHAR;
+ else if ( SQL_ISTOKENOR2 (pDataType->getChild(offset), CLOB, NCLOB) )
+ return DataType::CLOB;
+
+ OSL_FAIL("unrecognised character datatype");
+ return DataType::VARCHAR;
+ }
+}
+
+// Try to guess the type of an expression in simple cases.
+// Originally meant to be called only on a function call (hence the misnomer),
+// but now tries to do the best it can also in other cases.
+// Don't completely rely on fillFunctionInfo,
+// it won't look at the function's arguments to find the return type
+// (in particular, in the case of general_set_fct,
+// the return type is the type of the argument;
+// if that is (as is typical) a column reference,
+// it is the type of the column).
+// TODO: There is similar "guess the expression's type" code in several places:
+// SelectionBrowseBox.cxx: OSelectionBrowseBox::saveField
+// QueryDesignView.cxx: InstallFields, GetOrderCriteria, GetGroupCriteria
+// If possible, they should be factorised into this function
+// (which should then be renamed...)
+
+void OQueryDesignView::fillFunctionInfo( const ::connectivity::OSQLParseNode* pNode
+ ,const OUString& sFunctionTerm
+ ,OTableFieldDescRef& aInfo)
+{
+ // get the type of the expression, as far as easily possible
+ OQueryController& rController = static_cast<OQueryController&>(getController());
+ sal_Int32 nDataType = DataType::DOUBLE;
+ switch(pNode->getNodeType())
+ {
+ case SQLNodeType::Concat:
+ case SQLNodeType::String:
+ nDataType = DataType::VARCHAR;
+ break;
+ case SQLNodeType::IntNum:
+ nDataType = DataType::INTEGER;
+ break;
+ case SQLNodeType::ApproxNum:
+ nDataType = DataType::DOUBLE;
+ break;
+ case SQLNodeType::AccessDate:
+ nDataType = DataType::TIMESTAMP;
+ break;
+ case SQLNodeType::Equal:
+ case SQLNodeType::Less:
+ case SQLNodeType::Great:
+ case SQLNodeType::LessEq:
+ case SQLNodeType::GreatEq:
+ case SQLNodeType::NotEqual:
+ nDataType = DataType::BOOLEAN;
+ break;
+ case SQLNodeType::Name:
+ case SQLNodeType::ListRule:
+ case SQLNodeType::CommaListRule:
+ case SQLNodeType::Keyword:
+ case SQLNodeType::Punctuation:
+ OSL_FAIL("Unexpected SQL Node Type");
+ break;
+ case SQLNodeType::Rule:
+ switch(pNode->getKnownRuleID())
+ {
+ case OSQLParseNode::select_statement:
+ case OSQLParseNode::table_exp:
+ case OSQLParseNode::table_ref_commalist:
+ case OSQLParseNode::table_ref:
+ case OSQLParseNode::catalog_name:
+ case OSQLParseNode::schema_name:
+ case OSQLParseNode::table_name:
+ case OSQLParseNode::opt_column_commalist:
+ case OSQLParseNode::column_commalist:
+ case OSQLParseNode::column_ref_commalist:
+ case OSQLParseNode::column_ref:
+ case OSQLParseNode::opt_order_by_clause:
+ case OSQLParseNode::ordering_spec_commalist:
+ case OSQLParseNode::ordering_spec:
+ case OSQLParseNode::opt_asc_desc:
+ case OSQLParseNode::where_clause:
+ case OSQLParseNode::opt_where_clause:
+ case OSQLParseNode::opt_escape:
+ case OSQLParseNode::scalar_exp_commalist:
+ case OSQLParseNode::scalar_exp: // Seems to never be generated?
+ case OSQLParseNode::parameter_ref:
+ case OSQLParseNode::parameter:
+ case OSQLParseNode::range_variable:
+ case OSQLParseNode::delete_statement_positioned:
+ case OSQLParseNode::delete_statement_searched:
+ case OSQLParseNode::update_statement_positioned:
+ case OSQLParseNode::update_statement_searched:
+ case OSQLParseNode::assignment_commalist:
+ case OSQLParseNode::assignment:
+ case OSQLParseNode::insert_statement:
+ case OSQLParseNode::insert_atom_commalist:
+ case OSQLParseNode::insert_atom:
+ case OSQLParseNode::from_clause:
+ case OSQLParseNode::qualified_join:
+ case OSQLParseNode::cross_union:
+ case OSQLParseNode::select_sublist:
+ case OSQLParseNode::join_type:
+ case OSQLParseNode::named_columns_join:
+ case OSQLParseNode::joined_table:
+ case OSQLParseNode::sql_not:
+ case OSQLParseNode::manipulative_statement:
+ case OSQLParseNode::value_exp_commalist:
+ case OSQLParseNode::union_statement:
+ case OSQLParseNode::outer_join_type:
+ case OSQLParseNode::selection:
+ case OSQLParseNode::base_table_def:
+ case OSQLParseNode::base_table_element_commalist:
+ case OSQLParseNode::data_type:
+ case OSQLParseNode::column_def:
+ case OSQLParseNode::table_node:
+ case OSQLParseNode::as_clause:
+ case OSQLParseNode::opt_as:
+ case OSQLParseNode::op_column_commalist:
+ case OSQLParseNode::table_primary_as_range_column:
+ case OSQLParseNode::character_string_type:
+ case OSQLParseNode::comparison:
+ OSL_FAIL("Unexpected SQL RuleID");
+ break;
+ case OSQLParseNode::column:
+ case OSQLParseNode::column_val:
+ OSL_FAIL("Cannot guess column type");
+ break;
+ case OSQLParseNode::values_or_query_spec:
+ OSL_FAIL("Cannot guess VALUES type");
+ break;
+ case OSQLParseNode::derived_column:
+ OSL_FAIL("Cannot guess computed column type");
+ break;
+ case OSQLParseNode::subquery:
+ OSL_FAIL("Cannot guess subquery return type");
+ break;
+ case OSQLParseNode::search_condition:
+ case OSQLParseNode::comparison_predicate:
+ case OSQLParseNode::between_predicate:
+ case OSQLParseNode::like_predicate:
+ case OSQLParseNode::test_for_null:
+ case OSQLParseNode::boolean_term:
+ case OSQLParseNode::boolean_primary:
+ case OSQLParseNode::in_predicate:
+ case OSQLParseNode::existence_test:
+ case OSQLParseNode::unique_test:
+ case OSQLParseNode::all_or_any_predicate:
+ case OSQLParseNode::join_condition:
+ case OSQLParseNode::boolean_factor:
+ case OSQLParseNode::comparison_predicate_part_2:
+ case OSQLParseNode::parenthesized_boolean_value_expression:
+ case OSQLParseNode::other_like_predicate_part_2:
+ case OSQLParseNode::between_predicate_part_2:
+ nDataType = DataType::BOOLEAN;
+ break;
+ case OSQLParseNode::num_value_exp:
+ case OSQLParseNode::extract_exp:
+ case OSQLParseNode::term:
+ case OSQLParseNode::factor:
+ // Might by an integer or a float; take the most generic
+ nDataType = DataType::DOUBLE;
+ break;
+ case OSQLParseNode::value_exp_primary:
+ case OSQLParseNode::value_exp:
+ case OSQLParseNode::odbc_call_spec:
+ // Really, we don't know. Let the default.
+ break;
+ case OSQLParseNode::position_exp:
+ case OSQLParseNode::length_exp:
+ nDataType = DataType::INTEGER;
+ break;
+ case OSQLParseNode::char_value_exp:
+ case OSQLParseNode::char_value_fct:
+ case OSQLParseNode::fold:
+ case OSQLParseNode::char_substring_fct:
+ case OSQLParseNode::char_factor:
+ case OSQLParseNode::concatenation:
+ nDataType = DataType::VARCHAR;
+ break;
+ case OSQLParseNode::datetime_primary:
+ nDataType = DataType::TIMESTAMP;
+ break;
+ case OSQLParseNode::bit_value_fct:
+ nDataType = DataType::BINARY;
+ break;
+ case OSQLParseNode::general_set_fct: // May depend on argument; ignore that for now
+ case OSQLParseNode::set_fct_spec:
+ {
+ if (pNode->count() == 0)
+ {
+ // This is not a function call, no sense to continue with a function return type lookup
+ OSL_FAIL("Got leaf SQL node where non-leaf expected");
+ break;
+ }
+ const OSQLParseNode* pFunctionName = pNode->getChild(0);
+ if ( SQL_ISPUNCTUATION(pFunctionName,"{") )
+ {
+ if ( pNode->count() == 3 )
+ return fillFunctionInfo( pNode->getChild(1), sFunctionTerm, aInfo );
+ else
+ OSL_FAIL("ODBC escape not in recognised form");
+ break;
+ }
+ else
+ {
+ if ( SQL_ISRULEOR2(pNode,length_exp,char_value_fct) )
+ pFunctionName = pFunctionName->getChild(0);
+
+ OUString sFunctionName = pFunctionName->getTokenValue();
+ if ( sFunctionName.isEmpty() )
+ sFunctionName = OStringToOUString(OSQLParser::TokenIDToStr(pFunctionName->getTokenID()),RTL_TEXTENCODING_UTF8);
+
+ nDataType = OSQLParser::getFunctionReturnType(
+ sFunctionName
+ ,&rController.getParser().getContext());
+ }
+ break;
+ }
+ case OSQLParseNode::odbc_fct_spec:
+ {
+ if (pNode->count() != 2)
+ {
+ OSL_FAIL("interior of ODBC escape not in recognised shape");
+ break;
+ }
+
+ const OSQLParseNode* const pEscapeType = pNode->getChild(0);
+ if (SQL_ISTOKEN(pEscapeType, TS))
+ nDataType = DataType::TIMESTAMP;
+ else if (SQL_ISTOKEN(pEscapeType, D))
+ nDataType = DataType::DATE;
+ else if (SQL_ISTOKEN(pEscapeType, T))
+ nDataType = DataType::TIME;
+ else if (SQL_ISTOKEN(pEscapeType, FN))
+ return fillFunctionInfo( pNode->getChild(1), sFunctionTerm, aInfo );
+ else
+ OSL_FAIL("Unknown ODBC escape");
+ break;
+ }
+ case OSQLParseNode::cast_spec:
+ {
+ if ( pNode->count() != 6 || !SQL_ISTOKEN(pNode->getChild(3), AS) )
+ {
+ OSL_FAIL("CAST not in recognised shape");
+ break;
+ }
+ const OSQLParseNode *pCastTarget = pNode->getChild(4);
+ if ( SQL_ISTOKENOR2(pCastTarget, INTEGER, INT) )
+ nDataType = DataType::INTEGER;
+ else if ( SQL_ISTOKEN(pCastTarget, SMALLINT) )
+ nDataType = DataType::SMALLINT;
+ else if ( SQL_ISTOKEN(pCastTarget, BIGINT) )
+ nDataType = DataType::BIGINT;
+ else if ( SQL_ISTOKEN(pCastTarget, FLOAT) )
+ nDataType = DataType::FLOAT;
+ else if ( SQL_ISTOKEN(pCastTarget, REAL) )
+ nDataType = DataType::REAL;
+ else if ( SQL_ISTOKEN(pCastTarget, DOUBLE) )
+ nDataType = DataType::DOUBLE;
+ else if ( SQL_ISTOKEN(pCastTarget, BOOLEAN) )
+ nDataType = DataType::BOOLEAN;
+ else if ( SQL_ISTOKEN(pCastTarget, DATE) )
+ nDataType = DataType::DATE;
+ else if ( pCastTarget->count() > 0 )
+ {
+ const OSQLParseNode *pDataType = pCastTarget->getChild(0);
+ while (pDataType->count() > 0)
+ {
+ pCastTarget = pDataType;
+ pDataType = pDataType->getChild(0);
+ }
+ if ( SQL_ISTOKEN (pDataType, TIME) )
+ nDataType = DataType::TIME;
+ else if ( SQL_ISTOKEN (pDataType, TIMESTAMP) )
+ nDataType = DataType::TIMESTAMP;
+ else if ( SQL_ISTOKENOR3 (pDataType, CHARACTER, CHAR, NCHAR) )
+ nDataType = char_datatype(pCastTarget, 0);
+ else if ( SQL_ISTOKEN (pDataType, VARCHAR) )
+ nDataType = DataType::VARCHAR;
+ else if ( SQL_ISTOKEN (pDataType, CLOB) )
+ nDataType = DataType::CLOB;
+ else if ( SQL_ISTOKEN (pDataType, NATIONAL) )
+ nDataType = char_datatype(pCastTarget, 1);
+ else if ( SQL_ISTOKEN (pDataType, BINARY) )
+ {
+ if ( pCastTarget->count() > 2 && SQL_ISTOKEN(pCastTarget->getChild(1), LARGE) && SQL_ISTOKEN(pCastTarget->getChild(2), OBJECT) )
+ nDataType = DataType::BLOB;
+ else if ( pCastTarget->count() > 1 && SQL_ISTOKEN(pCastTarget->getChild(1), VARYING) )
+ nDataType = DataType::VARBINARY;
+ else
+ nDataType = DataType::BINARY;
+ }
+ else if ( SQL_ISTOKEN (pDataType, VARBINARY) )
+ nDataType = DataType::VARBINARY;
+ else if ( SQL_ISTOKEN (pDataType, BLOB) )
+ nDataType = DataType::BLOB;
+ else if ( SQL_ISTOKEN (pDataType, NUMERIC) )
+ nDataType = DataType::NUMERIC;
+ else if ( SQL_ISTOKENOR2 (pDataType, DECIMAL, DEC) )
+ nDataType = DataType::DECIMAL;
+ else if ( SQL_ISTOKEN (pDataType, FLOAT) )
+ nDataType = DataType::FLOAT;
+ else if ( SQL_ISTOKEN (pDataType, DOUBLE) )
+ nDataType = DataType::DOUBLE;
+ else if ( SQL_ISTOKEN (pDataType, INTERVAL) )
+ // Not in DataType published constant (because not in JDBC...)
+ nDataType = DataType::VARCHAR;
+ else
+ OSL_FAIL("Failed to decode CAST target");
+ }
+ else
+ OSL_FAIL("Could not decipher CAST target");
+ break;
+ }
+ default:
+ OSL_FAIL("Unknown SQL RuleID");
+ break;
+ }
+ break;
+ default:
+ OSL_FAIL("Unknown SQL Node Type");
+ break;
+ }
+
+ aInfo->SetDataType(nDataType);
+ aInfo->SetFieldType(TAB_NORMAL_FIELD);
+ aInfo->SetField(sFunctionTerm);
+ aInfo->SetTabWindow(nullptr);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/querydesign/QueryMoveTabWinUndoAct.cxx b/dbaccess/source/ui/querydesign/QueryMoveTabWinUndoAct.cxx
new file mode 100644
index 000000000..398732815
--- /dev/null
+++ b/dbaccess/source/ui/querydesign/QueryMoveTabWinUndoAct.cxx
@@ -0,0 +1,40 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "QueryMoveTabWinUndoAct.hxx"
+#include <JoinTableView.hxx>
+
+using namespace dbaui;
+void OJoinMoveTabWinUndoAct::TogglePosition()
+{
+ Point ptFrameScrollPos(m_pOwner->GetHScrollBar().GetThumbPos(),
+ m_pOwner->GetVScrollBar().GetThumbPos());
+ Point ptNext = m_pTabWin->GetPosPixel() + ptFrameScrollPos;
+
+ m_pTabWin->SetPosPixel(m_ptNextPosition - ptFrameScrollPos);
+
+ // it looks like ptFrameScrollPos is meaningless, then I subtract it here and add it to ptNext, and
+ // next time I subtract again...
+ // Albeit ptFrameScrollPos could have changed next time...
+ m_pOwner->EnsureVisible(m_pTabWin);
+
+ m_ptNextPosition = ptNext;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/querydesign/QueryMoveTabWinUndoAct.hxx b/dbaccess/source/ui/querydesign/QueryMoveTabWinUndoAct.hxx
new file mode 100644
index 000000000..e6b58956e
--- /dev/null
+++ b/dbaccess/source/ui/querydesign/QueryMoveTabWinUndoAct.hxx
@@ -0,0 +1,54 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "QueryDesignUndoAction.hxx"
+#include <strings.hrc>
+#include <JoinTableView.hxx>
+#include <TableWindow.hxx>
+#include <tools/gen.hxx>
+
+namespace dbaui
+{
+
+ // OQueryMoveTabWinUndoAct - Undo class for moving a TabWin
+ class OTableWindow;
+ class OJoinMoveTabWinUndoAct final : public OQueryDesignUndoAction
+ {
+ Point m_ptNextPosition;
+ VclPtr<OTableWindow> m_pTabWin;
+
+ void TogglePosition();
+
+ public:
+ OJoinMoveTabWinUndoAct(OJoinTableView* pOwner, const Point& ptOriginalPosition, OTableWindow* pTabWin);
+
+ virtual void Undo() override { TogglePosition(); }
+ virtual void Redo() override { TogglePosition(); }
+ };
+
+ inline OJoinMoveTabWinUndoAct::OJoinMoveTabWinUndoAct(OJoinTableView* pOwner, const Point& ptOriginalPosition, OTableWindow* pTabWin)
+ :OQueryDesignUndoAction(pOwner, STR_QUERY_UNDO_MOVETABWIN)
+ ,m_ptNextPosition(ptOriginalPosition)
+ ,m_pTabWin(pTabWin)
+ {
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/querydesign/QuerySizeTabWinUndoAct.hxx b/dbaccess/source/ui/querydesign/QuerySizeTabWinUndoAct.hxx
new file mode 100644
index 000000000..de244ccb5
--- /dev/null
+++ b/dbaccess/source/ui/querydesign/QuerySizeTabWinUndoAct.hxx
@@ -0,0 +1,70 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "QueryDesignUndoAction.hxx"
+#include <strings.hrc>
+#include <TableWindow.hxx>
+
+namespace dbaui
+{
+
+ // OQuerySizeTabWinUndoAct - undo class to change size of TabWins
+ class OTableWindow;
+ class OJoinSizeTabWinUndoAct final : public OQueryDesignUndoAction
+ {
+ Point m_ptNextPosition;
+ Size m_szNextSize;
+ VclPtr<OTableWindow> m_pTabWin;
+
+ inline void ToggleSizePosition();
+
+ public:
+ OJoinSizeTabWinUndoAct(OJoinTableView* pOwner, const Point& ptOriginalPos, const Size& szOriginalSize, OTableWindow* pTabWin);
+ // Boundary condition: while retrieving size/position scrolling is not allowed, meaning the position
+ // here returns physical and not logical coordinates
+ // (in contrary to QueryMoveTabWinUndoAct)
+
+ virtual void Undo() override { ToggleSizePosition(); }
+ virtual void Redo() override { ToggleSizePosition(); }
+ };
+
+ inline OJoinSizeTabWinUndoAct::OJoinSizeTabWinUndoAct(OJoinTableView* pOwner, const Point& ptOriginalPos, const Size& szOriginalSize, OTableWindow* pTabWin)
+ :OQueryDesignUndoAction(pOwner, STR_QUERY_UNDO_SIZETABWIN)
+ ,m_ptNextPosition(ptOriginalPos)
+ ,m_szNextSize(szOriginalSize)
+ ,m_pTabWin(pTabWin)
+ {
+ }
+
+ inline void OJoinSizeTabWinUndoAct::ToggleSizePosition()
+ {
+ Point ptNext = m_pTabWin->GetPosPixel();
+ Size szNext = m_pTabWin->GetSizePixel();
+
+ m_pOwner->Invalidate(InvalidateFlags::NoChildren);
+ m_pTabWin->SetPosSizePixel(m_ptNextPosition, m_szNextSize);
+ m_pOwner->Invalidate(InvalidateFlags::NoChildren);
+
+ m_ptNextPosition = ptNext;
+ m_szNextSize = szNext;
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/querydesign/QueryTabConnUndoAction.cxx b/dbaccess/source/ui/querydesign/QueryTabConnUndoAction.cxx
new file mode 100644
index 000000000..e3b6cd0e9
--- /dev/null
+++ b/dbaccess/source/ui/querydesign/QueryTabConnUndoAction.cxx
@@ -0,0 +1,117 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "QueryTabConnUndoAction.hxx"
+#include "QTableConnection.hxx"
+#include <QueryTableView.hxx>
+#include "QueryAddTabConnUndoAction.hxx"
+#include "QueryTabWinShowUndoAct.hxx"
+#include <strings.hrc>
+
+using namespace dbaui;
+
+OQueryTabConnUndoAction::~OQueryTabConnUndoAction()
+{
+ if (m_bOwnerOfConn)
+ { // I have the connection -> delete
+ m_pOwner->DeselectConn(m_pConnection);
+ m_pConnection.disposeAndClear();
+ }
+}
+
+OQueryTabConnUndoAction::OQueryTabConnUndoAction(OQueryTableView* pOwner, TranslateId pCommentID)
+ : OQueryDesignUndoAction(pOwner, pCommentID)
+ , m_pConnection(nullptr)
+ , m_bOwnerOfConn(false)
+{
+}
+
+OQueryAddTabConnUndoAction::OQueryAddTabConnUndoAction(OQueryTableView* pOwner)
+ : OQueryTabConnUndoAction(pOwner, STR_QUERY_UNDO_INSERTCONNECTION)
+{
+}
+
+void OQueryAddTabConnUndoAction::Undo()
+{
+ static_cast<OQueryTableView*>(m_pOwner.get())->DropConnection(m_pConnection);
+ SetOwnership(true);
+}
+
+void OQueryAddTabConnUndoAction::Redo()
+{
+ static_cast<OQueryTableView*>(m_pOwner.get())->GetConnection(m_pConnection);
+ SetOwnership(false);
+}
+
+OQueryDelTabConnUndoAction::OQueryDelTabConnUndoAction(OQueryTableView* pOwner)
+ : OQueryTabConnUndoAction(pOwner, STR_QUERY_UNDO_REMOVECONNECTION)
+{
+}
+
+void OQueryDelTabConnUndoAction::Undo()
+{
+ static_cast<OQueryTableView*>(m_pOwner.get())->GetConnection(m_pConnection);
+ SetOwnership(false);
+}
+
+void OQueryDelTabConnUndoAction::Redo()
+{
+ static_cast<OQueryTableView*>(m_pOwner.get())->DropConnection(m_pConnection);
+ SetOwnership(true);
+}
+
+OQueryTabWinShowUndoAct::OQueryTabWinShowUndoAct(OQueryTableView* pOwner)
+ : OQueryTabWinUndoAct(pOwner, STR_QUERY_UNDO_TABWINSHOW)
+{
+}
+
+OQueryTabWinShowUndoAct::~OQueryTabWinShowUndoAct() {}
+
+void OQueryTabWinShowUndoAct::Undo()
+{
+ static_cast<OQueryTableView*>(m_pOwner.get())->HideTabWin(m_pTabWin, this);
+ SetOwnership(true);
+}
+
+void OQueryTabWinShowUndoAct::Redo()
+{
+ static_cast<OQueryTableView*>(m_pOwner.get())->ShowTabWin(m_pTabWin, this, true);
+ SetOwnership(false);
+}
+
+OQueryTabWinDelUndoAct::OQueryTabWinDelUndoAct(OQueryTableView* pOwner)
+ : OQueryTabWinUndoAct(pOwner, STR_QUERY_UNDO_TABWINDELETE)
+{
+}
+
+OQueryTabWinDelUndoAct::~OQueryTabWinDelUndoAct() {}
+
+void OQueryTabWinDelUndoAct::Undo()
+{
+ static_cast<OQueryTableView*>(m_pOwner.get())->ShowTabWin(m_pTabWin, this, true);
+ SetOwnership(false);
+}
+
+void OQueryTabWinDelUndoAct::Redo()
+{
+ static_cast<OQueryTableView*>(m_pOwner.get())->HideTabWin(m_pTabWin, this);
+ SetOwnership(true);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/querydesign/QueryTabConnUndoAction.hxx b/dbaccess/source/ui/querydesign/QueryTabConnUndoAction.hxx
new file mode 100644
index 000000000..21077074e
--- /dev/null
+++ b/dbaccess/source/ui/querydesign/QueryTabConnUndoAction.hxx
@@ -0,0 +1,50 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "QueryDesignUndoAction.hxx"
+#include "QTableConnection.hxx"
+#include <JoinTableView.hxx>
+
+namespace dbaui
+{
+ class OQueryTableConnection;
+ class OQueryTableView;
+ class OQueryTabConnUndoAction : public OQueryDesignUndoAction
+ {
+ protected:
+ VclPtr<OQueryTableConnection> m_pConnection;
+ bool m_bOwnerOfConn;
+ // am I the only owner of the connection? (changes with every redo and undo)
+
+ public:
+ OQueryTabConnUndoAction(OQueryTableView* pOwner, TranslateId pCommentID);
+ virtual ~OQueryTabConnUndoAction() override;
+
+ virtual void Undo() override = 0;
+ virtual void Redo() override = 0;
+
+ void SetConnection(OQueryTableConnection* pConn) { m_pConnection = pConn; }
+ // now SetOwnership please
+ void SetOwnership(bool bTakeIt) { m_bOwnerOfConn = bTakeIt; }
+ };
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/querydesign/QueryTabWinShowUndoAct.hxx b/dbaccess/source/ui/querydesign/QueryTabWinShowUndoAct.hxx
new file mode 100644
index 000000000..95b740de9
--- /dev/null
+++ b/dbaccess/source/ui/querydesign/QueryTabWinShowUndoAct.hxx
@@ -0,0 +1,51 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include "QueryTabWinUndoAct.hxx"
+
+namespace dbaui
+{
+ // OQueryTabWinShowUndoAct - undo class to show a TabWins
+
+ class OQueryTabWinShowUndoAct : public OQueryTabWinUndoAct
+ {
+ public:
+ explicit OQueryTabWinShowUndoAct(OQueryTableView* pOwner);
+ virtual ~OQueryTabWinShowUndoAct() override;
+
+ virtual void Undo() override;
+ virtual void Redo() override;
+ };
+
+ // OQueryTabWinDelUndoAct - undo class to delete a TabWins
+
+ class OQueryTabWinDelUndoAct : public OQueryTabWinUndoAct
+ {
+ public:
+ explicit OQueryTabWinDelUndoAct(OQueryTableView* pOwner);
+ virtual ~OQueryTabWinDelUndoAct() override;
+
+ virtual void Undo() override;
+ virtual void Redo() override;
+ };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/querydesign/QueryTabWinUndoAct.cxx b/dbaccess/source/ui/querydesign/QueryTabWinUndoAct.cxx
new file mode 100644
index 000000000..2afe74db4
--- /dev/null
+++ b/dbaccess/source/ui/querydesign/QueryTabWinUndoAct.cxx
@@ -0,0 +1,112 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "QueryTabWinUndoAct.hxx"
+#include <osl/diagnose.h>
+#include "QTableWindow.hxx"
+#include "QueryDesignFieldUndoAct.hxx"
+#include <QueryTableView.hxx>
+
+using namespace dbaui;
+OQueryDesignFieldUndoAct::OQueryDesignFieldUndoAct(OSelectionBrowseBox* pSelBrwBox, TranslateId pCommentID)
+ : OCommentUndoAction(pCommentID)
+ , pOwner(pSelBrwBox)
+ , m_nColumnPosition(BROWSER_INVALIDID)
+{
+}
+
+OQueryDesignFieldUndoAct::~OQueryDesignFieldUndoAct()
+{
+ pOwner = nullptr;
+}
+
+OQueryTabWinUndoAct::OQueryTabWinUndoAct(OQueryTableView* pOwner, TranslateId pCommentID)
+ : OQueryDesignUndoAction(pOwner, pCommentID)
+ , m_pTabWin(nullptr)
+ , m_bOwnerOfObjects(false)
+{
+}
+
+OQueryTabWinUndoAct::~OQueryTabWinUndoAct()
+{
+ if (!m_bOwnerOfObjects)
+ return;
+
+ // I should take care to delete the window if I am the only owner
+ OSL_ENSURE(m_pTabWin != nullptr, "OQueryTabWinUndoAct::~OQueryTabWinUndoAct() : m_pTabWin must not be NULL");
+ OSL_ENSURE(!m_pTabWin->IsVisible(), "OQueryTabWinUndoAct::~OQueryTabWinUndoAct() : *m_pTabWin must not be visible");
+
+ if ( m_pTabWin )
+ m_pTabWin->clearListBox();
+ m_pTabWin.disposeAndClear();
+
+ // and of course the corresponding connections
+ for (auto & connection : m_vTableConnection)
+ {
+ m_pOwner->DeselectConn(connection);
+ connection.disposeAndClear();
+ }
+ m_vTableConnection.clear();
+}
+
+void OTabFieldCellModifiedUndoAct::Undo()
+{
+ pOwner->EnterUndoMode();
+ OSL_ENSURE(m_nColumnPosition != BROWSER_INVALIDID,"Column position was not set add the undo action!");
+ OSL_ENSURE(m_nColumnPosition < pOwner->GetColumnCount(),"Position outside the column count!");
+ if ( m_nColumnPosition != BROWSER_INVALIDID )
+ {
+ sal_uInt16 nColumnId = pOwner->GetColumnId(m_nColumnPosition);
+ OUString strNext = pOwner->GetCellContents(m_nCellIndex, nColumnId);
+ pOwner->SetCellContents(m_nCellIndex, nColumnId, m_strNextCellContents);
+ m_strNextCellContents = strNext;
+ }
+ pOwner->LeaveUndoMode();
+}
+
+void OTabFieldSizedUndoAct::Undo()
+{
+ pOwner->EnterUndoMode();
+ OSL_ENSURE(m_nColumnPosition != BROWSER_INVALIDID,"Column position was not set add the undo action!");
+ if ( m_nColumnPosition != BROWSER_INVALIDID )
+ {
+ sal_uInt16 nColumnId = pOwner->GetColumnId(m_nColumnPosition);
+ tools::Long nNextWidth = pOwner->GetColumnWidth(nColumnId);
+ pOwner->SetColWidth(nColumnId, m_nNextWidth);
+ m_nNextWidth = nNextWidth;
+ }
+ pOwner->LeaveUndoMode();
+}
+
+void OTabFieldMovedUndoAct::Undo()
+{
+ pOwner->EnterUndoMode();
+ OSL_ENSURE(m_nColumnPosition != BROWSER_INVALIDID,"Column position was not set add the undo action!");
+ if ( m_nColumnPosition != BROWSER_INVALIDID )
+ {
+ sal_uInt16 nId = pDescr->GetColumnId();
+ sal_uInt16 nOldPos = pOwner->GetColumnPos(nId);
+ pOwner->SetColumnPos(nId,m_nColumnPosition);
+ pOwner->ColumnMoved(nId,false);
+ m_nColumnPosition = nOldPos;
+ }
+ pOwner->LeaveUndoMode();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/querydesign/QueryTabWinUndoAct.hxx b/dbaccess/source/ui/querydesign/QueryTabWinUndoAct.hxx
new file mode 100644
index 000000000..9b4330542
--- /dev/null
+++ b/dbaccess/source/ui/querydesign/QueryTabWinUndoAct.hxx
@@ -0,0 +1,61 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "QueryDesignUndoAction.hxx"
+#include "QTableWindow.hxx"
+#include <TableConnection.hxx>
+#include <vector>
+
+namespace dbaui
+{
+ // OQueryTabWinUndoAct - undo base class for all which is concerned with insert/remove TabWins
+
+ class OQueryTableWindow;
+ class OTableConnection;
+ class OQueryTableView;
+ class OQueryTabWinUndoAct : public OQueryDesignUndoAction
+ {
+ protected:
+ std::vector<VclPtr<OTableConnection> > m_vTableConnection;
+ VclPtr<OQueryTableWindow> m_pTabWin;
+ bool m_bOwnerOfObjects;
+ // am I the only owner of the managed objects? (changes with every redo or undo)
+
+ public:
+ OQueryTabWinUndoAct(OQueryTableView* pOwner, TranslateId pCommentID);
+ virtual ~OQueryTabWinUndoAct() override;
+
+ void SetOwnership(bool bTakeIt) { m_bOwnerOfObjects = bTakeIt; }
+
+ virtual void Undo() override = 0;
+ virtual void Redo() override = 0;
+
+ // access to the TabWin
+ void SetTabWin(OQueryTableWindow* pTW) { m_pTabWin = pTW; }
+ // now SetOwnership should be invoked
+
+ std::vector<VclPtr<OTableConnection> >& GetTabConnList() { return m_vTableConnection; }
+
+ void InsertConnection( OTableConnection* pConnection ) { m_vTableConnection.push_back(pConnection); }
+ };
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/querydesign/QueryTableView.cxx b/dbaccess/source/ui/querydesign/QueryTableView.cxx
new file mode 100644
index 000000000..399697b09
--- /dev/null
+++ b/dbaccess/source/ui/querydesign/QueryTableView.cxx
@@ -0,0 +1,889 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <QueryTableView.hxx>
+#include <TableFieldDescription.hxx>
+#include <tools/diagnose_ex.h>
+#include <osl/diagnose.h>
+#include <helpids.h>
+#include "QTableWindow.hxx"
+#include "QTableConnection.hxx"
+#include "QTableConnectionData.hxx"
+#include <QueryDesignView.hxx>
+#include "QueryAddTabConnUndoAction.hxx"
+#include "QueryTabWinShowUndoAct.hxx"
+#include <browserids.hxx>
+#include <com/sun/star/sdbc/XConnection.hpp>
+#include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
+#include <com/sun/star/accessibility/AccessibleEventId.hpp>
+#include <JAccess.hxx>
+#include <com/sun/star/sdbcx/KeyType.hpp>
+#include <com/sun/star/container/XIndexAccess.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <connectivity/dbtools.hxx>
+#include <comphelper/sequence.hxx>
+#include "querydlg.hxx"
+#include <core_resource.hxx>
+#include <strings.hrc>
+#include <strings.hxx>
+
+using namespace dbaui;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::sdbcx;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::accessibility;
+
+namespace
+{
+ /** appends a new TabAdd Undo action at controller
+ @param _pView the view which we use
+ @param _pUndoAction the undo action which should be added
+ @param _pConnection the connection for which the undo action should be appended
+ @param _bOwner is the undo action the owner
+ */
+ void addUndoAction( OQueryTableView const * _pView,
+ std::unique_ptr<OQueryTabConnUndoAction> _pUndoAction,
+ OQueryTableConnection* _pConnection,
+ bool _bOwner = false)
+ {
+ _pUndoAction->SetOwnership(_bOwner);
+ _pUndoAction->SetConnection(_pConnection);
+ _pView->getDesignView()->getController().addUndoActionAndInvalidate(std::move(_pUndoAction));
+ }
+ /** openJoinDialog opens the join dialog with this connection data
+ @param _pView the view which we use
+ @param _pConnectionData the connection data
+
+ @return true when OK was pressed otherwise false
+ */
+ bool openJoinDialog(OQueryTableView* _pView,const TTableConnectionData::value_type& _pConnectionData,bool _bSelectableTables)
+ {
+ OQueryTableConnectionData* pData = static_cast< OQueryTableConnectionData*>(_pConnectionData.get());
+
+ DlgQryJoin aDlg(_pView,_pConnectionData,&_pView->GetTabWinMap(),_pView->getDesignView()->getController().getConnection(),_bSelectableTables);
+ bool bOk = aDlg.run() == RET_OK;
+ if( bOk )
+ {
+ pData->SetJoinType(aDlg.GetJoinType());
+ _pView->getDesignView()->getController().setModified(true);
+ }
+
+ return bOk;
+ }
+ /** connectionModified adds an undo action for the modified connection and forces a redraw
+ @param _pView the view which we use
+ @param _pConnection the connection which was modified
+ @param _bAddUndo true when an undo action should be appended
+ */
+ void connectionModified(OQueryTableView* _pView,
+ OTableConnection* _pConnection,
+ bool _bAddUndo)
+ {
+ OSL_ENSURE(_pConnection,"Invalid connection!");
+ _pConnection->UpdateLineList();
+
+ // add an undo action
+ if ( _bAddUndo )
+ addUndoAction( _pView,
+ std::make_unique<OQueryAddTabConnUndoAction>(_pView),
+ static_cast< OQueryTableConnection*>(_pConnection));
+ // redraw
+ _pConnection->RecalcLines();
+ // force an invalidation of the bounding rectangle
+ _pConnection->InvalidateConnection();
+
+ _pView->Invalidate(InvalidateFlags::NoChildren);
+ }
+ void addConnections(OQueryTableView* _pView,
+ const OQueryTableWindow& _rSource,
+ const OQueryTableWindow& _rDest,
+ const Reference<XNameAccess>& _rxSourceForeignKeyColumns)
+ {
+ if ( _rSource.GetData()->isQuery() || _rDest.GetData()->isQuery() )
+ // nothing to do if one of both denotes a query
+ return;
+
+ // we found a table in our view where we can insert some connections
+ // the key columns have a property called RelatedColumn
+ // build OQueryTableConnectionData
+ auto xNewConnData = std::make_shared<OQueryTableConnectionData>( _rSource.GetData(), _rDest.GetData() );
+
+ OUString sRelatedColumn;
+
+ // iterate through all foreignkey columns to create the connections
+ const Sequence<OUString> aKeyCols = _rxSourceForeignKeyColumns->getElementNames();
+ for(const OUString& rElement : aKeyCols)
+ {
+ Reference<XPropertySet> xColumn;
+ if ( !( _rxSourceForeignKeyColumns->getByName(rElement) >>= xColumn ) )
+ {
+ OSL_FAIL( "addConnections: invalid foreign key column!" );
+ continue;
+ }
+
+ xColumn->getPropertyValue(PROPERTY_RELATEDCOLUMN) >>= sRelatedColumn;
+
+ {
+ sal_Int32 nFindIndex = ::comphelper::findValue(_rSource.GetOriginalColumns()->getElementNames(),rElement);
+ if(nFindIndex != -1)
+ xNewConnData->SetFieldIndex(JTCS_FROM,nFindIndex+1);
+ else
+ OSL_FAIL("Column not found!");
+ }
+ // get the position inside the table
+ Reference<XNameAccess> xRefColumns = _rDest.GetOriginalColumns();
+ if(xRefColumns.is())
+ {
+ sal_Int32 nFindIndex = ::comphelper::findValue(xRefColumns->getElementNames(),sRelatedColumn);
+ if(nFindIndex != -1)
+ xNewConnData->SetFieldIndex(JTCS_TO,nFindIndex+1);
+ else
+ OSL_FAIL("Column not found!");
+ }
+ xNewConnData->AppendConnLine(rElement,sRelatedColumn);
+
+ // now add the Conn itself
+ ScopedVclPtrInstance< OQueryTableConnection > aNewConn(_pView, xNewConnData);
+ // referring to the local variable is not important, as NotifyQueryTabConn creates a new copy
+ // to add me (if not existent)
+ _pView->NotifyTabConnection(*aNewConn, false);
+ // don't create an Undo-Action for the new connection : the connection is
+ // covered by the Undo-Action for the tabwin, as the "Undo the insert" will
+ // automatically remove all connections adjacent to the win.
+ // (Because of this automatism we would have an ownership ambiguity for
+ // the connection data if we would insert the conn-Undo-Action)
+ }
+ }
+}
+
+OQueryTableView::OQueryTableView( vcl::Window* pParent,OQueryDesignView* pView)
+ : OJoinTableView( pParent,pView)
+{
+ SetHelpId(HID_CTL_QRYDGNTAB);
+}
+
+sal_Int32 OQueryTableView::CountTableAlias(const OUString& rName, sal_Int32& rMax)
+{
+ sal_Int32 nRet = 0;
+
+ OTableWindowMap::const_iterator aIter = GetTabWinMap().find(rName);
+ while(aIter != GetTabWinMap().end())
+ {
+ OUString aNewName = rName + "_" + OUString::number(++nRet);
+ aIter = GetTabWinMap().find(aNewName);
+ }
+
+ rMax = nRet;
+
+ return nRet;
+}
+
+void OQueryTableView::ReSync()
+{
+ TTableWindowData& rTabWinDataList = m_pView->getController().getTableWindowData();
+ OSL_ENSURE((getTableConnections().empty()) && (GetTabWinMap().empty()),
+ "before calling OQueryTableView::ReSync() please call ClearAll !");
+
+ // I need a collection of all window names that cannot be created so that I do not initialize connections for them.
+ std::vector<OUString> arrInvalidTables;
+
+ TTableWindowData::const_reverse_iterator aIter = rTabWinDataList.rbegin();
+ // Create the window and add it
+
+ for(;aIter != rTabWinDataList.rend();++aIter)
+ {
+ OQueryTableWindowData* pData = static_cast<OQueryTableWindowData*>(aIter->get());
+ VclPtr<OTableWindow> pTabWin = createWindow(*aIter);
+
+ // I don't use ShowTabWin as this adds the window data to the list of documents.
+ // This would be bad as I am getting them from there.
+ // Instead, I do it step by step
+ if (!pTabWin->Init())
+ {
+ // The initialisation has gone wrong, this TabWin is not available, so
+ // I must clean up the data and the document
+ pTabWin->clearListBox();
+ pTabWin.disposeAndClear();
+ arrInvalidTables.push_back(pData->GetAliasName());
+
+ rTabWinDataList.erase( std::remove(rTabWinDataList.begin(), rTabWinDataList.end(), *aIter), rTabWinDataList.end());
+ continue;
+ }
+
+ GetTabWinMap()[pData->GetAliasName()] = pTabWin; // add at the beginning as I am going backwards through the DataList
+ // Use the default if there is no position or size
+ if (!pData->HasPosition() && !pData->HasSize())
+ SetDefaultTabWinPosSize(pTabWin);
+
+ pTabWin->Show();
+ }
+
+ // Add the connections
+ TTableConnectionData& rTabConnDataList = m_pView->getController().getTableConnectionData();
+ TTableConnectionData::const_reverse_iterator aConIter = rTabConnDataList.rbegin();
+
+ for(;aConIter != rTabConnDataList.rend();++aConIter)
+ {
+ OQueryTableConnectionData* pTabConnData = static_cast<OQueryTableConnectionData*>(aConIter->get());
+
+ // do both tables for the connection exist ?
+ OUString strTabExistenceTest = pTabConnData->getReferencingTable()->GetWinName();
+ bool bInvalid = std::find(arrInvalidTables.begin(),arrInvalidTables.end(),strTabExistenceTest) != arrInvalidTables.end();
+ strTabExistenceTest = pTabConnData->getReferencedTable()->GetWinName();
+ bInvalid = bInvalid && std::find(arrInvalidTables.begin(),arrInvalidTables.end(),strTabExistenceTest) != arrInvalidTables.end();
+
+ if (bInvalid)
+ {
+ // no -> bad luck, no connection
+ rTabConnDataList.erase( std::remove(rTabConnDataList.begin(), rTabConnDataList.end(), *aConIter), rTabConnDataList.end());
+ continue;
+ }
+
+ // adds a new connection to join view and notifies our accessible and invalidates the controller
+ addConnection(VclPtr<OQueryTableConnection>::Create(this, *aConIter));
+ }
+}
+
+void OQueryTableView::ClearAll()
+{
+ OJoinTableView::ClearAll();
+
+ SetUpdateMode(true);
+ m_pView->getController().setModified(true);
+}
+
+VclPtr<OTableWindow> OQueryTableView::createWindow(const TTableWindowData::value_type& _pData)
+{
+ return VclPtr<OQueryTableWindow>::Create(this,_pData);
+}
+
+void OQueryTableView::NotifyTabConnection(const OQueryTableConnection& rNewConn, bool _bCreateUndoAction)
+{
+ // let's first check if I have the connection already
+ OQueryTableConnection* pTabConn = nullptr;
+ const auto& rConnections = getTableConnections();
+ auto aEnd = rConnections.end();
+ auto aIter = std::find( rConnections.begin(),
+ aEnd,
+ VclPtr<OTableConnection>(const_cast<OTableConnection*>(static_cast<const OTableConnection*>(&rNewConn)))
+ );
+ if(aIter == aEnd)
+ {
+ for (auto const& connection : rConnections)
+ {
+ if(*static_cast<OQueryTableConnection*>(connection.get()) == rNewConn)
+ {
+ pTabConn = static_cast<OQueryTableConnection*>(connection.get());
+ break;
+ }
+ }
+ }
+ else
+ pTabConn = static_cast<OQueryTableConnection*>((*aIter).get());
+
+ // no -> insert
+ if (pTabConn == nullptr)
+ {
+ // the new data ...
+ auto pNewData = std::static_pointer_cast<OQueryTableConnectionData>(rNewConn.GetData()->NewInstance());
+ pNewData->CopyFrom(*rNewConn.GetData());
+ VclPtrInstance<OQueryTableConnection> pNewConn(this, pNewData);
+ GetConnection(pNewConn);
+
+ connectionModified(this,pNewConn,_bCreateUndoAction);
+ }
+}
+
+std::shared_ptr<OTableWindowData> OQueryTableView::CreateImpl(const OUString& _rComposedName
+ ,const OUString& _sTableName
+ ,const OUString& _rWinName)
+{
+ return std::make_shared<OQueryTableWindowData>( _rComposedName, _sTableName,_rWinName );
+}
+
+void OQueryTableView::AddTabWin(const OUString& _rTableName, const OUString& _rAliasName, bool bNewTable)
+{
+ // this method has been inherited from the base class, linking back to the parent and which constructs
+ // an Alias and which passes on to my other AddTabWin
+
+ // pity _rTableName is fully qualified, OQueryDesignView expects a string which only
+ // contains schema and tables but no catalog.
+ Reference< XConnection> xConnection = m_pView->getController().getConnection();
+ if(!xConnection.is())
+ return;
+ try
+ {
+ Reference< XDatabaseMetaData > xMetaData = xConnection->getMetaData();
+ OUString sCatalog, sSchema, sTable;
+ ::dbtools::qualifiedNameComponents(xMetaData,
+ _rTableName,
+ sCatalog,
+ sSchema,
+ sTable,
+ ::dbtools::EComposeRule::InDataManipulation);
+ OUString sRealName(sSchema);
+ if (!sRealName.isEmpty())
+ sRealName += ".";
+ sRealName += sTable;
+
+ AddTabWin(_rTableName, sRealName, _rAliasName, bNewTable);
+ }
+ catch(SQLException&)
+ {
+ OSL_FAIL("qualifiedNameComponents");
+ }
+}
+
+// find the table which has a foreign key with this referencedTable name
+static Reference<XPropertySet> getKeyReferencedTo(const Reference<XIndexAccess>& _rxKeys,std::u16string_view _rReferencedTable)
+{
+ if(!_rxKeys.is())
+ return Reference<XPropertySet>();
+
+ // search the one and only primary key
+ const sal_Int32 nCount = _rxKeys->getCount();
+ for(sal_Int32 i=0;i<nCount ;++i)
+ {
+ Reference<XPropertySet> xKey(_rxKeys->getByIndex(i),UNO_QUERY);
+ if(xKey.is())
+ {
+ sal_Int32 nKeyType = 0;
+ xKey->getPropertyValue(PROPERTY_TYPE) >>= nKeyType;
+ if(KeyType::FOREIGN == nKeyType)
+ {
+ OUString sReferencedTable;
+ xKey->getPropertyValue(PROPERTY_REFERENCEDTABLE) >>= sReferencedTable;
+ // TODO check case
+ if(sReferencedTable == _rReferencedTable)
+ return xKey;
+ }
+ }
+ }
+ return Reference<XPropertySet>();
+}
+
+void OQueryTableView::AddTabWin(const OUString& _rComposedName, const OUString& _rTableName, const OUString& strAlias, bool bNewTable)
+{
+ OSL_ENSURE(!_rTableName.isEmpty() || !strAlias.isEmpty(), "OQueryTableView::AddTabWin : no tables or aliases !");
+ // If the table is not set, then it is a dummy window, but at least the alias must be set
+
+ // build a new data structure
+ // first check if this already has its data
+ bool bAppend = bNewTable;
+ TTableWindowData::value_type pNewTabWinData;
+ TTableWindowData& rWindowData = getDesignView()->getController().getTableWindowData();
+ bool bFoundElem = false;
+ for (auto const& elem : rWindowData)
+ {
+ pNewTabWinData = elem;
+ if (pNewTabWinData && pNewTabWinData->GetWinName() == strAlias && pNewTabWinData->GetComposedName() == _rComposedName && pNewTabWinData->GetTableName() == _rTableName)
+ {
+ bFoundElem = true;
+ break;
+ }
+ }
+ if ( !bAppend )
+ bAppend = !bFoundElem;
+ if ( bAppend )
+ pNewTabWinData = createTableWindowData(_rComposedName, _rTableName, strAlias);
+ // I do not need to add TabWinData to the DocShell list, ShowTabWin does that.
+
+ // Create a new window
+ VclPtr<OQueryTableWindow> pNewTabWin = static_cast<OQueryTableWindow*>(createWindow(pNewTabWinData).get());
+ // No need to initialize, as that happens in ShowTabWin
+
+ // New UndoAction
+ std::unique_ptr<OQueryTabWinShowUndoAct> pUndoAction(new OQueryTabWinShowUndoAct(this));
+ pUndoAction->SetTabWin(pNewTabWin); // Window
+ bool bSuccess = ShowTabWin(pNewTabWin, pUndoAction.get(), bAppend);
+ if(!bSuccess)
+ {
+ // reset table window
+ pUndoAction->SetTabWin(nullptr);
+ pUndoAction->SetOwnership(false);
+ return;
+ }
+
+ // Show the relations between the individual tables
+ OTableWindowMap& rTabWins = GetTabWinMap();
+ if(bNewTable && !rTabWins.empty() && !_rTableName.isEmpty())
+ {
+ modified();
+ if ( m_pAccessible )
+ m_pAccessible->notifyAccessibleEvent( AccessibleEventId::CHILD,
+ Any(),
+ Any(pNewTabWin->GetAccessible())
+ );
+
+ do {
+
+ if ( pNewTabWin->GetData()->isQuery() )
+ break;
+
+ try
+ {
+ // find relations between the table and the tables already inserted
+ Reference< XIndexAccess> xKeyIndex = pNewTabWin->GetData()->getKeys();
+ if ( !xKeyIndex.is() )
+ break;
+
+ Reference<XNameAccess> xFKeyColumns;
+ OUString aReferencedTable;
+ Reference<XColumnsSupplier> xColumnsSupplier;
+
+ const sal_Int32 nKeyCount = xKeyIndex->getCount();
+ for ( sal_Int32 i=0; i<nKeyCount ; ++i )
+ {
+ Reference< XPropertySet > xProp( xKeyIndex->getByIndex(i), UNO_QUERY_THROW );
+ xColumnsSupplier.set( xProp, UNO_QUERY_THROW );
+ xFKeyColumns.set( xColumnsSupplier->getColumns(), UNO_SET_THROW );
+
+ sal_Int32 nKeyType = 0;
+ xProp->getPropertyValue(PROPERTY_TYPE) >>= nKeyType;
+
+ switch ( nKeyType )
+ {
+ case KeyType::FOREIGN:
+ { // our new table has a foreign key
+ // so look if the referenced table is already in our list
+ xProp->getPropertyValue(PROPERTY_REFERENCEDTABLE) >>= aReferencedTable;
+ OSL_ENSURE(!aReferencedTable.isEmpty(),"Foreign key without referencedTableName");
+
+ OTableWindowMap::const_iterator aIter = rTabWins.find(aReferencedTable);
+ OTableWindowMap::const_iterator aEnd = rTabWins.end();
+ if(aIter == aEnd)
+ {
+ for(aIter = rTabWins.begin();aIter != aEnd;++aIter)
+ {
+ OQueryTableWindow* pTabWinTmp = static_cast<OQueryTableWindow*>(aIter->second.get());
+ OSL_ENSURE( pTabWinTmp,"TableWindow is null!" );
+ if ( pTabWinTmp != pNewTabWin && pTabWinTmp->GetComposedName() == aReferencedTable )
+ break;
+ }
+ }
+ if ( aIter != aEnd && pNewTabWin.get() != aIter->second.get() )
+ addConnections( this, *pNewTabWin, *static_cast<OQueryTableWindow*>(aIter->second.get()), xFKeyColumns );
+ }
+ break;
+
+ case KeyType::PRIMARY:
+ {
+ // we have a primary key so look in our list if there exists a key which this is referred to
+ for (auto const& tabWin : rTabWins)
+ {
+ OQueryTableWindow* pTabWinTmp = static_cast<OQueryTableWindow*>(tabWin.second.get());
+ if ( pTabWinTmp == pNewTabWin )
+ continue;
+
+ if ( pTabWinTmp->GetData()->isQuery() )
+ continue;
+
+ OSL_ENSURE(pTabWinTmp,"TableWindow is null!");
+ Reference< XPropertySet > xFKKey = getKeyReferencedTo( pTabWinTmp->GetData()->getKeys(), pNewTabWin->GetComposedName() );
+ if ( !xFKKey.is() )
+ continue;
+
+ Reference<XColumnsSupplier> xFKColumnsSupplier( xFKKey, UNO_QUERY_THROW );
+ Reference< XNameAccess > xTColumns( xFKColumnsSupplier->getColumns(), UNO_SET_THROW );
+ addConnections( this, *pTabWinTmp, *pNewTabWin, xTColumns );
+ }
+ }
+ break;
+ }
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+
+ } while ( false );
+ }
+
+ // My parent needs to be informed about the delete
+ m_pView->getController().addUndoActionAndInvalidate( std::move(pUndoAction) );
+}
+
+void OQueryTableView::AddConnection(const OJoinExchangeData& jxdSource, const OJoinExchangeData& jxdDest)
+{
+ OQueryTableWindow* pSourceWin = static_cast< OQueryTableWindow*>(jxdSource.pListBox->GetTabWin());
+ OQueryTableWindow* pDestWin = static_cast< OQueryTableWindow*>(jxdDest.pListBox->GetTabWin());
+
+ OUString aSourceFieldName, aDestFieldName;
+ weld::TreeView& rSourceTreeView = jxdSource.pListBox->get_widget();
+ aSourceFieldName = rSourceTreeView.get_text(jxdSource.nEntry);
+ weld::TreeView& rDestTreeView = jxdDest.pListBox->get_widget();
+ aDestFieldName = rDestTreeView.get_text(jxdDest.nEntry);
+
+ OTableConnection* pConn = GetTabConn(pSourceWin,pDestWin,true);
+ if ( !pConn )
+ {
+ // new data object
+ auto xNewConnectionData = std::make_shared<OQueryTableConnectionData>(pSourceWin->GetData(), pDestWin->GetData());
+
+ sal_uInt32 nSourceFieldIndex, nDestFieldIndex;
+
+ // Get name/position of both affected fields ...
+ // Source
+ nSourceFieldIndex = jxdSource.nEntry;
+ // Dest
+ nDestFieldIndex = jxdDest.nEntry;
+
+ // ... and set them
+ xNewConnectionData->SetFieldIndex(JTCS_FROM, nSourceFieldIndex);
+ xNewConnectionData->SetFieldIndex(JTCS_TO, nDestFieldIndex);
+
+ xNewConnectionData->AppendConnLine( aSourceFieldName,aDestFieldName );
+
+ ScopedVclPtrInstance< OQueryTableConnection > aNewConnection(this, xNewConnectionData);
+ NotifyTabConnection(*aNewConnection);
+ // As usual with NotifyTabConnection, using a local variable is fine because a copy is made
+ }
+ else
+ {
+ // the connection could point on the other side
+ if(pConn->GetSourceWin() == pDestWin)
+ {
+ OUString aTmp(aSourceFieldName);
+ aSourceFieldName = aDestFieldName;
+ aDestFieldName = aTmp;
+ }
+
+ pConn->GetData()->AppendConnLine( aSourceFieldName,aDestFieldName );
+
+ connectionModified(this,pConn,false);
+ }
+}
+
+void OQueryTableView::ConnDoubleClicked(VclPtr<OTableConnection>& rConnection)
+{
+ if (openJoinDialog(this, rConnection->GetData(), false))
+ {
+ connectionModified(this, rConnection, false);
+ SelectConn(rConnection);
+ }
+}
+
+void OQueryTableView::createNewConnection()
+{
+ TTableConnectionData::value_type pData = std::make_shared<OQueryTableConnectionData>();
+ if( !openJoinDialog(this,pData,true) )
+ return;
+
+ OTableWindowMap& rMap = GetTabWinMap();
+ OQueryTableWindow* pSourceWin = static_cast< OQueryTableWindow*>(rMap[pData->getReferencingTable()->GetWinName()].get());
+ OQueryTableWindow* pDestWin = static_cast< OQueryTableWindow*>(rMap[pData->getReferencedTable()->GetWinName()].get());
+ // first we have to look if the this connection already exists
+ OTableConnection* pConn = GetTabConn(pSourceWin,pDestWin,true);
+ bool bNew = true;
+ if ( pConn )
+ {
+ pConn->GetData()->CopyFrom( *pData );
+ bNew = false;
+ }
+ else
+ {
+ // create a new connection and append it
+ VclPtrInstance<OQueryTableConnection> pQConn(this, pData);
+ GetConnection(pQConn);
+ pConn = pQConn;
+ }
+ connectionModified(this,pConn,bNew);
+ if ( !bNew && pConn == GetSelectedConn() ) // our connection was selected before so we have to reselect it
+ SelectConn( pConn );
+}
+
+bool OQueryTableView::RemoveConnection(VclPtr<OTableConnection>& rConnection, bool /*_bDelete*/)
+{
+ VclPtr<OQueryTableConnection> xConnection(static_cast<OQueryTableConnection*>(rConnection.get()));
+
+ // we don't want that our connection will be deleted, we put it in the undo manager
+ bool bRet = OJoinTableView::RemoveConnection(rConnection, false);
+
+ // add undo action
+ addUndoAction(this,
+ std::make_unique<OQueryDelTabConnUndoAction>(this),
+ xConnection.get(),
+ true);
+
+ return bRet;
+}
+
+OQueryTableWindow* OQueryTableView::FindTable(const OUString& rAliasName)
+{
+ OSL_ENSURE(!rAliasName.isEmpty(), "OQueryTableView::FindTable : the AliasName should not be empty !");
+ // (it is harmless but does not make sense and indicates that there is probably an error in the caller)
+ OTableWindowMap::const_iterator aIter = GetTabWinMap().find(rAliasName);
+ if(aIter != GetTabWinMap().end())
+ return static_cast<OQueryTableWindow*>(aIter->second.get());
+ return nullptr;
+}
+
+bool OQueryTableView::FindTableFromField(const OUString& rFieldName, OTableFieldDescRef const & rInfo, sal_uInt16& rCnt)
+{
+ rCnt = 0;
+ for (auto const& tabWin : GetTabWinMap())
+ {
+ if(static_cast<OQueryTableWindow*>(tabWin.second.get())->ExistsField(rFieldName, rInfo))
+ ++rCnt;
+ }
+ // TODO JNA : what should we rCnt > 1?
+
+ return rCnt == 1;
+}
+
+bool OQueryTableView::ContainsTabWin(const OTableWindow& rTabWin)
+{
+
+ for (auto const& tabWin : GetTabWinMap())
+ {
+ if ( tabWin.second == &rTabWin )
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void OQueryTableView::RemoveTabWin(OTableWindow* pTabWin)
+{
+ OSL_ENSURE(pTabWin != nullptr, "OQueryTableView::RemoveTabWin : Window should not be NULL !");
+
+ if(!(pTabWin && ContainsTabWin(*pTabWin))) // #i122589# check if registered before deleting
+ return;
+
+ // I need my parent so it can be informed about the deletion
+ OQueryDesignView* pParent = static_cast<OQueryDesignView*>(getDesignView());
+
+ SfxUndoManager& rUndoMgr = m_pView->getController().GetUndoManager();
+ rUndoMgr.EnterListAction(DBA_RES(STR_QUERY_UNDO_TABWINDELETE) , OUString(), 0, ViewShellId(-1));
+
+ // add the Undo-Action
+ std::unique_ptr<OQueryTabWinDelUndoAct> pUndoAction(new OQueryTabWinDelUndoAct(this));
+ pUndoAction->SetTabWin(static_cast< OQueryTableWindow*>(pTabWin));
+
+ // and hide the window
+ HideTabWin(static_cast< OQueryTableWindow*>(pTabWin), pUndoAction.get());
+
+ // Undo Actions and delete the fields in SelectionBrowseBox
+ pParent->TableDeleted( static_cast< OQueryTableWindowData*>(pTabWin->GetData().get())->GetAliasName() );
+
+ m_pView->getController().addUndoActionAndInvalidate( std::move(pUndoAction) );
+ rUndoMgr.LeaveListAction();
+
+ modified();
+ if ( m_pAccessible )
+ m_pAccessible->notifyAccessibleEvent( AccessibleEventId::CHILD,
+ Any(pTabWin->GetAccessible()),
+ Any()
+ );
+}
+
+void OQueryTableView::EnsureVisible(const OTableWindow* pWin)
+{
+
+ Invalidate(InvalidateFlags::NoChildren);
+ OJoinTableView::EnsureVisible(pWin);
+}
+
+void OQueryTableView::GetConnection(OQueryTableConnection* pConn)
+{
+ // add to me and the document
+
+ addConnection( pConn );
+}
+
+void OQueryTableView::DropConnection(VclPtr<OQueryTableConnection> const & rConn)
+{
+ // Pay attention to the selection
+ // remove from me and the document
+ VclPtr<OTableConnection> xConn(rConn.get());
+ RemoveConnection(xConn, false);
+}
+
+void OQueryTableView::HideTabWin( OQueryTableWindow* pTabWin, OQueryTabWinUndoAct* pUndoAction )
+{
+ OTableWindowMap& rTabWins = GetTabWinMap();
+
+ // Window
+ // save the position in its data
+ getDesignView()->SaveTabWinUIConfig(pTabWin);
+ // (I need to go via the parent, as only the parent knows the position of the scrollbars)
+ // and then out of the TabWins list and hide
+ OTableWindowMap::const_iterator aIter = std::find_if(rTabWins.begin(), rTabWins.end(),
+ [&pTabWin](const OTableWindowMap::value_type& rEntry) { return rEntry.second == pTabWin; });
+ if (aIter != rTabWins.end())
+ rTabWins.erase( aIter );
+
+ pTabWin->Hide(); // do not destroy it, as it is still in the undo list!!
+
+ // the TabWin data must also be passed out of my responsibility
+ TTableWindowData& rTabWinDataList = m_pView->getController().getTableWindowData();
+ rTabWinDataList.erase( std::remove(rTabWinDataList.begin(), rTabWinDataList.end(), pTabWin->GetData()), rTabWinDataList.end());
+ // The data should not be destroyed as TabWin itself - which is still alive - needs them
+ // Either it goes back into my responsibility, (via ShowTabWin), then I add the data back,
+ // or the Undo-Action, which currently has full responsibility for the window
+ // and its data, gets destroyed and destroys both the window and its data
+
+ if (m_pLastFocusTabWin == pTabWin)
+ m_pLastFocusTabWin = nullptr;
+
+ // collect connections belonging to the window and pass to UndoAction
+ sal_Int16 nCnt = 0;
+ const auto& rTabConList = getTableConnections();
+ auto aIter2 = rTabConList.begin();
+ for(;aIter2 != rTabConList.end();)// the end may change
+ {
+ VclPtr<OTableConnection> xTmpEntry = *aIter2;
+ OQueryTableConnection* pTmpEntry = static_cast<OQueryTableConnection*>(xTmpEntry.get());
+ OSL_ENSURE(pTmpEntry,"OQueryTableConnection is null!");
+ if( pTmpEntry->GetAliasName(JTCS_FROM) == pTabWin->GetAliasName() ||
+ pTmpEntry->GetAliasName(JTCS_TO) == pTabWin->GetAliasName() )
+ {
+ // add to undo list
+ pUndoAction->InsertConnection(xTmpEntry);
+
+ // call base class because we append an undo action
+ // but this time we are in an undo action list
+ OJoinTableView::RemoveConnection(xTmpEntry, false);
+ aIter2 = rTabConList.begin();
+ ++nCnt;
+ }
+ else
+ ++aIter2;
+ }
+
+ if (nCnt)
+ InvalidateConnections();
+
+ m_pView->getController().InvalidateFeature(ID_BROWSER_ADDTABLE);
+
+ // inform the UndoAction that the window and connections belong to it
+ pUndoAction->SetOwnership(true);
+
+ // by doing so, we have modified the document
+ m_pView->getController().setModified( true );
+ m_pView->getController().InvalidateFeature(SID_BROWSER_CLEAR_QUERY);
+}
+
+bool OQueryTableView::ShowTabWin( OQueryTableWindow* pTabWin, OQueryTabWinUndoAct* pUndoAction, bool _bAppend )
+{
+
+ bool bSuccess = false;
+
+ if (pTabWin)
+ {
+ if (pTabWin->Init())
+ {
+ TTableWindowData::value_type pData = pTabWin->GetData();
+ OSL_ENSURE(pData != nullptr, "OQueryTableView::ShowTabWin : TabWin has no data !");
+ // If there is a position and size defined, we use them
+ if (pData->HasPosition() && pData->HasSize())
+ {
+ Size aSize(CalcZoom(pData->GetSize().Width()),CalcZoom(pData->GetSize().Height()));
+ pTabWin->SetPosSizePixel(pData->GetPosition(), aSize);
+ }
+ else
+ // else set a default position
+ SetDefaultTabWinPosSize(pTabWin);
+
+ // Show the window and add to the list
+ OUString sName = static_cast< OQueryTableWindowData*>(pData.get())->GetAliasName();
+ OSL_ENSURE(GetTabWinMap().find(sName) == GetTabWinMap().end(),"Alias name already in list!");
+ GetTabWinMap().emplace(sName,pTabWin);
+
+ pTabWin->Show();
+
+ pTabWin->PaintImmediately();
+ // We must call Update() in order to show the connections in the window correctly. This sounds strange,
+ // but the Listbox has an internal Member which is initialized when the Listbox is first shown (after the Listbox
+ // is filled in Init). This Member will eventually be needed for
+ // GetEntryPos, and then in turn by the Connection, when its starting point to the window must be determined.
+
+ // the Connections
+ auto rTableCon = pUndoAction->GetTabConnList();
+ for(const auto& conn : rTableCon)
+ addConnection(conn); // add all connections from the undo action
+
+ rTableCon.clear();
+
+ // and add the window's data to the list (of the document)
+ if(_bAppend)
+ m_pView->getController().getTableWindowData().push_back(pTabWin->GetData());
+
+ m_pView->getController().InvalidateFeature(ID_BROWSER_ADDTABLE);
+
+ // and inform the UndoAction that the window belongs to me
+ pUndoAction->SetOwnership(false);
+
+ bSuccess = true;
+ }
+ else
+ {
+ // Initialisation failed
+ // (for example when the Connection to the database is not available at the moment)
+ pTabWin->clearListBox();
+ pTabWin->disposeOnce();
+ }
+ }
+
+ // show that I have changed the document
+ if(!m_pView->getController().isReadOnly())
+ m_pView->getController().setModified( true );
+
+ m_pView->getController().InvalidateFeature(SID_BROWSER_CLEAR_QUERY);
+
+ return bSuccess;
+}
+
+void OQueryTableView::InsertField(const OTableFieldDescRef& rInfo)
+{
+ OSL_ENSURE(getDesignView() != nullptr, "OQueryTableView::InsertField : has no Parent !");
+ static_cast<OQueryDesignView*>(getDesignView())->InsertField(rInfo);
+}
+
+bool OQueryTableView::ExistsAVisitedConn(const OQueryTableWindow* pFrom) const
+{
+ for(const auto& conn : getTableConnections())
+ {
+ OQueryTableConnection* pTemp = static_cast<OQueryTableConnection*>(conn.get());
+ if (pTemp->IsVisited() &&
+ (pFrom == static_cast< OQueryTableWindow*>(pTemp->GetSourceWin()) || pFrom == static_cast< OQueryTableWindow*>(pTemp->GetDestWin())))
+ return true;
+ }
+
+ return false;
+}
+
+void OQueryTableView::onNoColumns_throw()
+{
+ OUString sError(DBA_RES(STR_STATEMENT_WITHOUT_RESULT_SET));
+ ::dbtools::throwSQLException( sError, ::dbtools::StandardSQLState::GENERAL_ERROR, nullptr );
+}
+
+bool OQueryTableView::suppressCrossNaturalJoin(const TTableConnectionData::value_type& _pData) const
+{
+ OQueryTableConnectionData* pQueryData = static_cast<OQueryTableConnectionData*>(_pData.get());
+ return pQueryData && (pQueryData->GetJoinType() == CROSS_JOIN);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/querydesign/QueryTextView.cxx b/dbaccess/source/ui/querydesign/QueryTextView.cxx
new file mode 100644
index 000000000..daeb6ee14
--- /dev/null
+++ b/dbaccess/source/ui/querydesign/QueryTextView.cxx
@@ -0,0 +1,177 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <svx/svxids.hrc>
+#include <QueryTextView.hxx>
+#include <querycontainerwindow.hxx>
+#include <helpids.h>
+#include <querycontroller.hxx>
+#include <sqledit.hxx>
+#include <undosqledit.hxx>
+
+using namespace dbaui;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+
+// end of temp classes
+OQueryTextView::OQueryTextView(OQueryContainerWindow* pParent, OQueryController& rController)
+ : InterimItemWindow(pParent, "dbaccess/ui/queryview.ui", "QueryView")
+ , m_rController(rController)
+ , m_xSQL(new SQLEditView(m_xBuilder->weld_scrolled_window("scrolledwindow", true)))
+ , m_xSQLEd(new weld::CustomWeld(*m_xBuilder, "sql", *m_xSQL))
+ , m_timerUndoActionCreation("dbaccess OQueryTextView m_timerUndoActionCreation")
+ , m_timerInvalidate("dbaccess OQueryTextView m_timerInvalidate")
+ , m_bStopTimer(false)
+{
+ m_xSQL->DisableInternalUndo();
+ m_xSQL->SetHelpId(HID_CTL_QRYSQLEDIT);
+ m_xSQL->SetModifyHdl(LINK(this, OQueryTextView, ModifyHdl));
+ m_xSQL->SetAcceptsTab(true);
+
+ m_timerUndoActionCreation.SetTimeout(1000);
+ m_timerUndoActionCreation.SetInvokeHandler(LINK(this, OQueryTextView, OnUndoActionTimer));
+
+ m_timerInvalidate.SetTimeout(200);
+ m_timerInvalidate.SetInvokeHandler(LINK(this, OQueryTextView, OnInvalidateTimer));
+ m_timerInvalidate.Start();
+}
+
+IMPL_LINK_NOARG(OQueryTextView, ModifyHdl, LinkParamNone*, void)
+{
+ if (m_timerUndoActionCreation.IsActive())
+ m_timerUndoActionCreation.Stop();
+ m_timerUndoActionCreation.Start();
+
+ if (!m_rController.isModified())
+ m_rController.setModified(true);
+
+ m_rController.InvalidateFeature(SID_SBA_QRY_EXECUTE);
+ m_rController.InvalidateFeature(SID_CUT);
+ m_rController.InvalidateFeature(SID_COPY);
+}
+
+IMPL_LINK_NOARG(OQueryTextView, OnUndoActionTimer, Timer*, void)
+{
+ OUString aText = m_xSQL->GetText();
+ if (aText == m_strOrigText)
+ return;
+
+ SfxUndoManager& rUndoMgr = m_rController.GetUndoManager();
+ std::unique_ptr<OSqlEditUndoAct> xUndoAct(new OSqlEditUndoAct(*this));
+
+ xUndoAct->SetOriginalText(m_strOrigText);
+ rUndoMgr.AddUndoAction(std::move(xUndoAct));
+
+ m_rController.InvalidateFeature(SID_UNDO);
+ m_rController.InvalidateFeature(SID_REDO);
+
+ m_strOrigText = aText;
+}
+
+IMPL_LINK_NOARG(OQueryTextView, OnInvalidateTimer, Timer*, void)
+{
+ m_rController.InvalidateFeature(SID_CUT);
+ m_rController.InvalidateFeature(SID_COPY);
+ if (!m_bStopTimer)
+ m_timerInvalidate.Start();
+}
+
+void OQueryTextView::startTimer()
+{
+ m_bStopTimer = false;
+ if (!m_timerInvalidate.IsActive())
+ m_timerInvalidate.Start();
+}
+
+void OQueryTextView::stopTimer()
+{
+ m_bStopTimer = true;
+ if (m_timerInvalidate.IsActive())
+ m_timerInvalidate.Stop();
+}
+
+OQueryTextView::~OQueryTextView() { disposeOnce(); }
+
+void OQueryTextView::dispose()
+{
+ if (m_timerUndoActionCreation.IsActive())
+ m_timerUndoActionCreation.Stop();
+
+ m_xSQLEd.reset();
+ m_xSQL.reset();
+ InterimItemWindow::dispose();
+}
+
+void OQueryTextView::GetFocus()
+{
+ if (m_xSQL)
+ {
+ m_xSQL->GrabFocus();
+ m_strOrigText = m_xSQL->GetText();
+ }
+ InterimItemWindow::GetFocus();
+}
+
+OUString OQueryTextView::getStatement() const { return m_xSQL->GetText(); }
+
+void OQueryTextView::clear()
+{
+ std::unique_ptr<OSqlEditUndoAct> xUndoAct(new OSqlEditUndoAct(*this));
+
+ xUndoAct->SetOriginalText(m_xSQL->GetText());
+ m_rController.addUndoActionAndInvalidate(std::move(xUndoAct));
+
+ SetSQLText(OUString());
+}
+
+void OQueryTextView::setStatement(const OUString& rsStatement) { SetSQLText(rsStatement); }
+
+OUString OQueryTextView::GetSQLText() const { return m_xSQL->GetText(); }
+
+void OQueryTextView::SetSQLText(const OUString& rNewText)
+{
+ if (m_timerUndoActionCreation.IsActive())
+ {
+ // create the trailing undo-actions
+ m_timerUndoActionCreation.Stop();
+ OnUndoActionTimer(nullptr);
+ }
+
+ m_xSQL->SetTextAndUpdate(rNewText);
+
+ m_strOrigText = rNewText;
+}
+
+void OQueryTextView::copy() { m_xSQL->Copy(); }
+
+bool OQueryTextView::isCutAllowed() const { return m_xSQL->HasSelection(); }
+
+void OQueryTextView::cut()
+{
+ m_xSQL->Cut();
+ m_rController.setModified(true);
+}
+
+void OQueryTextView::paste()
+{
+ m_xSQL->Paste();
+ m_rController.setModified(true);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/querydesign/QueryViewSwitch.cxx b/dbaccess/source/ui/querydesign/QueryViewSwitch.cxx
new file mode 100644
index 000000000..a51f2941a
--- /dev/null
+++ b/dbaccess/source/ui/querydesign/QueryViewSwitch.cxx
@@ -0,0 +1,292 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <QueryViewSwitch.hxx>
+#include <QueryDesignView.hxx>
+#include <QueryTextView.hxx>
+#include <querycontainerwindow.hxx>
+#include <adtabdlg.hxx>
+#include <querycontroller.hxx>
+
+using namespace dbaui;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+
+OQueryViewSwitch::OQueryViewSwitch(OQueryContainerWindow* _pParent, OQueryController& _rController,const Reference< XComponentContext >& _rxContext)
+: m_bAddTableDialogWasVisible(false)
+{
+
+ m_pTextView = VclPtr<OQueryTextView>::Create(_pParent, _rController);
+ m_pDesignView = VclPtr<OQueryDesignView>::Create( _pParent, _rController, _rxContext );
+}
+
+OQueryViewSwitch::~OQueryViewSwitch()
+{
+ // destroy children
+ m_pDesignView.disposeAndClear();
+ m_pTextView.disposeAndClear();
+}
+
+void OQueryViewSwitch::Construct()
+{
+ m_pDesignView->Construct( );
+}
+
+void OQueryViewSwitch::initialize()
+{
+ // initially be in SQL mode
+ m_pTextView->Show();
+ m_pDesignView->initialize();
+}
+
+bool OQueryViewSwitch::checkStatement()
+{
+ if(m_pTextView->IsVisible())
+ return true;
+ return m_pDesignView->checkStatement();
+}
+
+OUString OQueryViewSwitch::getStatement()
+{
+ if(m_pTextView->IsVisible())
+ return m_pTextView->getStatement();
+ return m_pDesignView->getStatement();
+}
+
+void OQueryViewSwitch::clear()
+{
+ if(m_pTextView->IsVisible())
+ m_pTextView->clear();
+ else
+ m_pDesignView->clear();
+}
+
+void OQueryViewSwitch::GrabFocus()
+{
+ if ( m_pTextView && m_pTextView->IsVisible() )
+ m_pTextView->GrabFocus();
+ else if ( m_pDesignView && m_pDesignView->IsVisible() )
+ m_pDesignView->GrabFocus();
+}
+
+void OQueryViewSwitch::setStatement(const OUString& _rsStatement)
+{
+ if(m_pTextView->IsVisible())
+ m_pTextView->setStatement(_rsStatement);
+}
+
+void OQueryViewSwitch::copy()
+{
+ if(m_pTextView->IsVisible())
+ m_pTextView->copy();
+ else
+ m_pDesignView->copy();
+}
+
+bool OQueryViewSwitch::isCutAllowed() const
+{
+ if(m_pTextView->IsVisible())
+ return m_pTextView->isCutAllowed();
+ return m_pDesignView->isCutAllowed();
+}
+
+bool OQueryViewSwitch::isCopyAllowed() const
+{
+ if(m_pTextView->IsVisible())
+ return true;
+ return m_pDesignView->isCopyAllowed();
+}
+
+bool OQueryViewSwitch::isPasteAllowed() const
+{
+ if(m_pTextView->IsVisible())
+ return true;
+ return m_pDesignView->isPasteAllowed();
+}
+
+void OQueryViewSwitch::cut()
+{
+ if(m_pTextView->IsVisible())
+ m_pTextView->cut();
+ else
+ m_pDesignView->cut();
+}
+
+void OQueryViewSwitch::paste()
+{
+ if(m_pTextView->IsVisible())
+ m_pTextView->paste();
+ else
+ m_pDesignView->paste();
+}
+
+OQueryContainerWindow* OQueryViewSwitch::getContainer() const
+{
+ vcl::Window* pDesignParent = getDesignView() ? getDesignView()->GetParent() : nullptr;
+ return static_cast< OQueryContainerWindow* >( pDesignParent );
+}
+
+void OQueryViewSwitch::impl_forceSQLView()
+{
+ OAddTableDlg* pAddTabDialog( getAddTableDialog() );
+
+ // hide the "Add Table" dialog
+ m_bAddTableDialogWasVisible = pAddTabDialog != nullptr;
+ if (m_bAddTableDialogWasVisible)
+ pAddTabDialog->response(RET_CLOSE);
+
+ // tell the views they're in/active
+ m_pDesignView->stopTimer();
+ m_pTextView->startTimer();
+
+ // set the most recent statement at the text view
+ m_pTextView->clear();
+ m_pTextView->setStatement(static_cast<OQueryController&>(m_pDesignView->getController()).getStatement());
+}
+
+void OQueryViewSwitch::forceInitialView()
+{
+ OQueryController& rQueryController( static_cast< OQueryController& >( m_pDesignView->getController() ) );
+ const bool bGraphicalDesign = rQueryController.isGraphicalDesign();
+ if ( !bGraphicalDesign )
+ impl_forceSQLView();
+ else
+ {
+ // tell the text view it's inactive now
+ m_pTextView->stopTimer();
+
+ // update the "Add Table" dialog
+ OAddTableDlg* pAddTabDialog( getAddTableDialog() );
+ if ( pAddTabDialog )
+ pAddTabDialog->Update();
+
+ // initialize the design view
+ m_pDesignView->initByFieldDescriptions( rQueryController.getFieldInformation() );
+
+ // tell the design view it's active now
+ m_pDesignView->startTimer();
+ }
+
+ impl_postViewSwitch( bGraphicalDesign, true );
+}
+
+bool OQueryViewSwitch::switchView( ::dbtools::SQLExceptionInfo* _pErrorInfo )
+{
+ bool bRet = true;
+ bool bGraphicalDesign = static_cast<OQueryController&>(m_pDesignView->getController()).isGraphicalDesign();
+
+ if ( !bGraphicalDesign )
+ {
+ impl_forceSQLView();
+ }
+ else
+ {
+ // tell the text view it's inactive now
+ m_pTextView->stopTimer();
+
+ // update the "Add Table" dialog
+ OAddTableDlg* pAddTabDialog( getAddTableDialog() );
+ if ( pAddTabDialog )
+ pAddTabDialog->Update();
+
+ // initialize the design view
+ bRet = m_pDesignView->initByParseIterator( _pErrorInfo );
+
+ // tell the design view it's active now
+ m_pDesignView->startTimer();
+ }
+
+ return impl_postViewSwitch( bGraphicalDesign, bRet );
+}
+
+bool OQueryViewSwitch::impl_postViewSwitch( const bool i_bGraphicalDesign, const bool i_bSuccess )
+{
+ if ( i_bSuccess )
+ {
+ m_pTextView->Show ( !i_bGraphicalDesign );
+ m_pDesignView->Show ( i_bGraphicalDesign );
+ OAddTableDlg* pAddTabDialog( getAddTableDialog() );
+ if ( pAddTabDialog )
+ if ( i_bGraphicalDesign && m_bAddTableDialogWasVisible )
+ m_pDesignView->getController().runDialogAsync();
+
+ GrabFocus();
+ }
+
+ OQueryContainerWindow* pContainer = getContainer();
+ if ( pContainer )
+ pContainer->Resize();
+
+ m_pDesignView->getController().ClearUndoManager();
+ m_pDesignView->getController().InvalidateAll();
+
+ return i_bSuccess;
+}
+
+OAddTableDlg* OQueryViewSwitch::getAddTableDialog()
+{
+ if ( !m_pDesignView )
+ return nullptr;
+ return m_pDesignView->getController().getAddTableDialog();
+}
+
+bool OQueryViewSwitch::isSlotEnabled(sal_Int32 _nSlotId)
+{
+ return m_pDesignView->isSlotEnabled(_nSlotId);
+}
+
+void OQueryViewSwitch::setSlotEnabled(sal_Int32 _nSlotId, bool _bEnable)
+{
+ m_pDesignView->setSlotEnabled(_nSlotId,_bEnable);
+}
+
+void OQueryViewSwitch::SaveUIConfig()
+{
+ if(m_pDesignView->IsVisible())
+ m_pDesignView->SaveUIConfig();
+}
+
+void OQueryViewSwitch::SetPosSizePixel( Point _rPt,Size _rSize)
+{
+ m_pDesignView->SetPosSizePixel( _rPt,_rSize);
+ m_pDesignView->Resize();
+ m_pTextView->SetPosSizePixel( _rPt,_rSize);
+}
+
+Reference< XComponentContext > const & OQueryViewSwitch::getORB() const
+{
+ return m_pDesignView->getORB();
+}
+
+void OQueryViewSwitch::reset()
+{
+ m_pDesignView->reset();
+ if ( !m_pDesignView->initByParseIterator( nullptr ) )
+ return;
+
+ switchView( nullptr );
+}
+
+void OQueryViewSwitch::setNoneVisibleRow(sal_Int32 _nRows)
+{
+ if(m_pDesignView)
+ m_pDesignView->setNoneVisibleRow(_nRows);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/querydesign/SelectionBrowseBox.cxx b/dbaccess/source/ui/querydesign/SelectionBrowseBox.cxx
new file mode 100644
index 000000000..414d6bbdc
--- /dev/null
+++ b/dbaccess/source/ui/querydesign/SelectionBrowseBox.cxx
@@ -0,0 +1,2720 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+
+#include <string_view>
+
+#include "SelectionBrowseBox.hxx"
+#include <com/sun/star/sdbc/XDatabaseMetaData.hpp>
+#include <com/sun/star/sdbc/DataType.hpp>
+#include <JoinExchange.hxx>
+#include <QueryDesignView.hxx>
+#include <querycontroller.hxx>
+#include <sqlbison.hxx>
+#include <QueryTableView.hxx>
+#include <browserids.hxx>
+#include <comphelper/stl_types.hxx>
+#include <comphelper/string.hxx>
+#include "TableFieldInfo.hxx"
+#include <core_resource.hxx>
+#include <strings.hrc>
+#include <strings.hxx>
+#include <helpids.h>
+#include "QTableWindow.hxx"
+#include <vcl/weld.hxx>
+#include <vcl/settings.hxx>
+#include "QueryDesignFieldUndoAct.hxx"
+#include <sqlmessage.hxx>
+#include <UITools.hxx>
+#include <o3tl/safeint.hxx>
+#include <osl/diagnose.h>
+#include <i18nlangtag/languagetag.hxx>
+#include <vcl/commandevent.hxx>
+#include <vcl/svapp.hxx>
+#include <tools/diagnose_ex.h>
+#include <o3tl/string_view.hxx>
+
+using namespace ::svt;
+using namespace ::dbaui;
+using namespace ::connectivity;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::util;
+using namespace ::com::sun::star::accessibility;
+
+#define DEFAULT_QUERY_COLS 20
+#define DEFAULT_SIZE GetTextWidth("0") * 30
+#define HANDLE_ID 0
+#define HANDLE_COLUMN_WIDTH 70
+#define SORT_COLUMN_NONE 0xFFFFFFFF
+
+namespace
+{
+ bool isFieldNameAsterisk(const OUString& _sFieldName )
+ {
+ bool bAsterisk = _sFieldName.isEmpty() || _sFieldName.toChar() == '*';
+ if ( !bAsterisk )
+ {
+ sal_Int32 nTokenCount = comphelper::string::getTokenCount(_sFieldName, '.');
+ if ( (nTokenCount == 2 && o3tl::getToken(_sFieldName,1,'.')[0] == '*' )
+ || (nTokenCount == 3 && o3tl::getToken(_sFieldName,2,'.')[0] == '*' ) )
+ {
+ bAsterisk = true;
+ }
+ }
+ return bAsterisk;
+ }
+ bool lcl_SupportsCoreSQLGrammar(const Reference< XConnection>& _xConnection)
+ {
+ bool bSupportsCoreGrammar = false;
+ if ( _xConnection.is() )
+ {
+ try
+ {
+ Reference< XDatabaseMetaData > xMetaData = _xConnection->getMetaData();
+ bSupportsCoreGrammar = xMetaData.is() && xMetaData->supportsCoreSQLGrammar();
+ }
+ catch(Exception&)
+ {
+ }
+ }
+ return bSupportsCoreGrammar;
+ }
+}
+
+OSelectionBrowseBox::OSelectionBrowseBox( vcl::Window* pParent )
+ :EditBrowseBox( pParent,EditBrowseBoxFlags::NO_HANDLE_COLUMN_CONTENT, WB_3DLOOK, BrowserMode::COLUMNSELECTION | BrowserMode::KEEPHIGHLIGHT | BrowserMode::HIDESELECT |
+ BrowserMode::HIDECURSOR | BrowserMode::HLINES | BrowserMode::VLINES )
+ ,m_timerInvalidate("dbaccess OSelectionBrowseBox m_timerInvalidate")
+ ,m_nSeekRow(0)
+ ,m_nMaxColumns(0)
+ ,m_aFunctionStrings(DBA_RES(STR_QUERY_FUNCTIONS))
+ ,m_nVisibleCount(0)
+ ,m_nLastSortColumn(SORT_COLUMN_NONE)
+ ,m_bOrderByUnRelated(true)
+ ,m_bGroupByUnRelated(true)
+ ,m_bStopTimer(false)
+ ,m_bWasEditing(false)
+ ,m_bDisableErrorBox(false)
+ ,m_bInUndoMode(false)
+{
+ SetHelpId(HID_CTL_QRYDGNCRIT);
+
+ m_nMode = BrowserMode::COLUMNSELECTION | BrowserMode::HIDESELECT
+ | BrowserMode::KEEPHIGHLIGHT | BrowserMode::HIDECURSOR
+ | BrowserMode::HLINES | BrowserMode::VLINES
+ | BrowserMode::HEADERBAR_NEW ;
+
+ m_pTextCell = VclPtr<EditControl>::Create(&GetDataWindow());
+ m_pVisibleCell = VclPtr<CheckBoxControl>::Create(&GetDataWindow());
+ m_pTableCell = VclPtr<ListBoxControl>::Create(&GetDataWindow());
+ m_pFieldCell = VclPtr<ComboBoxControl>::Create(&GetDataWindow());
+ m_pOrderCell = VclPtr<ListBoxControl>::Create(&GetDataWindow());
+ m_pFunctionCell = VclPtr<ListBoxControl>::Create(&GetDataWindow());
+
+ m_pVisibleCell->SetHelpId(HID_QRYDGN_ROW_VISIBLE);
+ m_pTableCell->SetHelpId(HID_QRYDGN_ROW_TABLE);
+ m_pFieldCell->SetHelpId(HID_QRYDGN_ROW_FIELD);
+ weld::ComboBox& rOrderBox = m_pOrderCell->get_widget();
+ m_pOrderCell->SetHelpId(HID_QRYDGN_ROW_ORDER);
+ m_pFunctionCell->SetHelpId(HID_QRYDGN_ROW_FUNCTION);
+
+ // switch off triState of css::form::CheckBox
+ m_pVisibleCell->EnableTriState( false );
+
+ vcl::Font aTitleFont = OutputDevice::GetDefaultFont( DefaultFontType::SANS_UNICODE,Window::GetSettings().GetLanguageTag().getLanguageType(),GetDefaultFontFlags::OnlyOne);
+ aTitleFont.SetFontSize(Size(0, 6));
+ SetTitleFont(aTitleFont);
+
+ const OUString aTxt(DBA_RES(STR_QUERY_SORTTEXT));
+ for (sal_Int32 nIdx {0}; nIdx>=0;)
+ rOrderBox.append_text(OUString(o3tl::getToken(aTxt, 0, ';', nIdx)));
+
+ m_bVisibleRow.insert(m_bVisibleRow.end(), BROW_ROW_CNT, true);
+
+ m_bVisibleRow[BROW_FUNCTION_ROW] = false; // first hide
+
+ m_timerInvalidate.SetTimeout(200);
+ m_timerInvalidate.SetInvokeHandler(LINK(this, OSelectionBrowseBox, OnInvalidateTimer));
+ m_timerInvalidate.Start();
+}
+
+OSelectionBrowseBox::~OSelectionBrowseBox()
+{
+ disposeOnce();
+}
+
+void OSelectionBrowseBox::dispose()
+{
+ m_pTextCell.disposeAndClear();
+ m_pVisibleCell.disposeAndClear();
+ m_pFieldCell.disposeAndClear();
+ m_pTableCell.disposeAndClear();
+ m_pOrderCell.disposeAndClear();
+ m_pFunctionCell.disposeAndClear();
+ ::svt::EditBrowseBox::dispose();
+}
+
+void OSelectionBrowseBox::initialize()
+{
+ Reference< XConnection> xConnection = static_cast<OQueryController&>(getDesignView()->getController()).getConnection();
+ if(xConnection.is())
+ {
+ const IParseContext& rContext = static_cast<OQueryController&>(getDesignView()->getController()).getParser().getContext();
+ const IParseContext::InternationalKeyCode eFunctions[] = {
+ IParseContext::InternationalKeyCode::Avg,IParseContext::InternationalKeyCode::Count,IParseContext::InternationalKeyCode::Max
+ ,IParseContext::InternationalKeyCode::Min,IParseContext::InternationalKeyCode::Sum
+ ,IParseContext::InternationalKeyCode::Every
+ ,IParseContext::InternationalKeyCode::Any
+ ,IParseContext::InternationalKeyCode::Some
+ ,IParseContext::InternationalKeyCode::StdDevPop
+ ,IParseContext::InternationalKeyCode::StdDevSamp
+ ,IParseContext::InternationalKeyCode::VarSamp
+ ,IParseContext::InternationalKeyCode::VarPop
+ ,IParseContext::InternationalKeyCode::Collect
+ ,IParseContext::InternationalKeyCode::Fusion
+ ,IParseContext::InternationalKeyCode::Intersection
+ };
+
+ OUString sGroup = m_aFunctionStrings.copy(m_aFunctionStrings.lastIndexOf(';')+1);
+ m_aFunctionStrings = m_aFunctionStrings.getToken(0, ';');
+
+ for (IParseContext::InternationalKeyCode eFunction : eFunctions)
+ {
+ m_aFunctionStrings += ";" + OStringToOUString(rContext.getIntlKeywordAscii(eFunction), RTL_TEXTENCODING_UTF8);
+ }
+ m_aFunctionStrings += ";" + sGroup;
+
+ // Aggregate functions in general available only with Core SQL
+ // We slip in a few optionals one, too.
+ if ( lcl_SupportsCoreSQLGrammar(xConnection) )
+ {
+ weld::ComboBox& rComboBox = m_pFunctionCell->get_widget();
+ for (sal_Int32 nIdx {0}; nIdx>=0;)
+ rComboBox.append_text(m_aFunctionStrings.getToken(0, ';', nIdx));
+ }
+ else // else only COUNT(*) and COUNT("table".*)
+ {
+ weld::ComboBox& rComboBox = m_pFunctionCell->get_widget();
+ rComboBox.append_text(m_aFunctionStrings.getToken(0, ';'));
+ rComboBox.append_text(m_aFunctionStrings.getToken(2, ';')); // 2 -> COUNT
+ }
+ try
+ {
+ Reference< XDatabaseMetaData > xMetaData = xConnection->getMetaData();
+ if ( xMetaData.is() )
+ {
+ m_bOrderByUnRelated = xMetaData->supportsOrderByUnrelated();
+ m_bGroupByUnRelated = xMetaData->supportsGroupByUnrelated();
+ }
+ }
+ catch(Exception&)
+ {
+ }
+ }
+
+ Init();
+}
+
+OQueryDesignView* OSelectionBrowseBox::getDesignView()
+{
+ OSL_ENSURE(static_cast<const OQueryDesignView*>(GetParent()),"Parent isn't an OQueryDesignView!");
+ return static_cast<OQueryDesignView*>(GetParent());
+}
+
+OQueryDesignView* OSelectionBrowseBox::getDesignView() const
+{
+ OSL_ENSURE(static_cast<const OQueryDesignView*>(GetParent()),"Parent isn't an OQueryDesignView!");
+ return static_cast<OQueryDesignView*>(GetParent());
+}
+
+namespace
+{
+ class OSelectionBrwBoxHeader : public ::svt::EditBrowserHeader
+ {
+ VclPtr<OSelectionBrowseBox> m_pBrowseBox;
+ protected:
+ virtual void Select() override;
+ public:
+ explicit OSelectionBrwBoxHeader(OSelectionBrowseBox* pParent);
+ virtual ~OSelectionBrwBoxHeader() override { disposeOnce(); }
+ virtual void dispose() override { m_pBrowseBox.clear(); ::svt::EditBrowserHeader::dispose(); }
+ };
+ OSelectionBrwBoxHeader::OSelectionBrwBoxHeader(OSelectionBrowseBox* pParent)
+ : ::svt::EditBrowserHeader(pParent,WB_BUTTONSTYLE|WB_DRAG)
+ ,m_pBrowseBox(pParent)
+ {
+ }
+
+ void OSelectionBrwBoxHeader::Select()
+ {
+ EditBrowserHeader::Select();
+ m_pBrowseBox->GrabFocus();
+
+ BrowserMode nMode = m_pBrowseBox->GetMode();
+ if ( 0 == m_pBrowseBox->GetSelectColumnCount() )
+ {
+ m_pBrowseBox->DeactivateCell();
+ // we are in the right mode if a row has been selected row
+ if ( nMode & BrowserMode::HIDESELECT )
+ {
+ nMode &= ~BrowserMode::HIDESELECT;
+ nMode |= BrowserMode::MULTISELECTION;
+ m_pBrowseBox->SetMode( nMode );
+ }
+ }
+ m_pBrowseBox->SelectColumnId( GetCurItemId() );
+ m_pBrowseBox->DeactivateCell();
+ }
+}
+
+VclPtr<BrowserHeader> OSelectionBrowseBox::imp_CreateHeaderBar(BrowseBox* /*pParent*/)
+{
+ return VclPtr<OSelectionBrwBoxHeader>::Create(this);
+}
+
+void OSelectionBrowseBox::ColumnMoved( sal_uInt16 nColId, bool _bCreateUndo )
+{
+ EditBrowseBox::ColumnMoved( nColId );
+ // swap the two columns
+ sal_uInt16 nNewPos = GetColumnPos( nColId );
+ OTableFields& rFields = getFields();
+ if ( rFields.size() > o3tl::make_unsigned(nNewPos-1) )
+ {
+ sal_uInt16 nOldPos = 0;
+ bool bFoundElem = false;
+ for (auto const& field : rFields)
+ {
+ if (field->GetColumnId() == nColId)
+ {
+ bFoundElem = true;
+ break;
+ }
+ ++nOldPos;
+ }
+
+ OSL_ENSURE( (nNewPos-1) != nOldPos && nOldPos < rFields.size(),"Old and new position are equal!");
+ if (bFoundElem)
+ {
+ OTableFieldDescRef pOldEntry = rFields[nOldPos];
+ rFields.erase(rFields.begin() + nOldPos);
+ rFields.insert(rFields.begin() + nNewPos - 1,pOldEntry);
+
+ // create the undo action
+ if ( !m_bInUndoMode && _bCreateUndo )
+ {
+ std::unique_ptr<OTabFieldMovedUndoAct> pUndoAct(new OTabFieldMovedUndoAct(this));
+ pUndoAct->SetColumnPosition( nOldPos + 1);
+ pUndoAct->SetTabFieldDescr(pOldEntry);
+
+ getDesignView()->getController().addUndoActionAndInvalidate(std::move(pUndoAct));
+ }
+ }
+ }
+ else
+ OSL_FAIL("Invalid column id!");
+}
+
+void OSelectionBrowseBox::Init()
+{
+
+ EditBrowseBox::Init();
+
+ // set the header bar
+ VclPtr<BrowserHeader> pNewHeaderBar = CreateHeaderBar(this);
+ pNewHeaderBar->SetMouseTransparent(false);
+
+ SetHeaderBar(pNewHeaderBar);
+ SetMode(m_nMode);
+
+ vcl::Font aFont( GetDataWindow().GetFont() );
+ aFont.SetWeight( WEIGHT_NORMAL );
+ GetDataWindow().SetFont( aFont );
+
+ Size aHeight;
+ const Control* pControls[] = { m_pTextCell,m_pVisibleCell,m_pTableCell,m_pFieldCell };
+
+ for (const Control* pControl : pControls)
+ {
+ const Size aTemp(pControl->GetOptimalSize());
+ if ( aTemp.Height() > aHeight.Height() )
+ aHeight.setHeight( aTemp.Height() );
+ }
+ SetDataRowHeight(aHeight.Height());
+ SetTitleLines(1);
+ // get number of visible rows
+ for(tools::Long i=0;i<BROW_ROW_CNT;i++)
+ {
+ if(m_bVisibleRow[i])
+ m_nVisibleCount++;
+ }
+ RowInserted(0, m_nVisibleCount, false);
+ try
+ {
+ Reference< XConnection> xConnection = static_cast<OQueryController&>(getDesignView()->getController()).getConnection();
+ if(xConnection.is())
+ {
+ Reference< XDatabaseMetaData > xMetaData = xConnection->getMetaData();
+ m_nMaxColumns = xMetaData.is() ? xMetaData->getMaxColumnsInSelect() : 0;
+
+ }
+ else
+ m_nMaxColumns = 0;
+ }
+ catch(const SQLException&)
+ {
+ TOOLS_WARN_EXCEPTION( "dbaccess", "Caught Exception when asking for database metadata options!");
+ m_nMaxColumns = 0;
+ }
+}
+
+void OSelectionBrowseBox::PreFill()
+{
+ SetUpdateMode(false);
+
+ if (GetCurRow() != 0)
+ GoToRow(0);
+
+ static_cast< OQueryController& >( getDesignView()->getController() ).clearFields();
+
+ DeactivateCell();
+
+ RemoveColumns();
+ InsertHandleColumn( HANDLE_COLUMN_WIDTH );
+ SetUpdateMode(true);
+}
+
+void OSelectionBrowseBox::ClearAll()
+{
+ SetUpdateMode(false);
+
+ OTableFields::const_reverse_iterator aIter = getFields().rbegin();
+ for ( ;aIter != getFields().rend(); ++aIter )
+ {
+ if ( !(*aIter)->IsEmpty() )
+ {
+ RemoveField( (*aIter)->GetColumnId() );
+ aIter = getFields().rbegin();
+ }
+ }
+ m_nLastSortColumn = SORT_COLUMN_NONE;
+ SetUpdateMode(true);
+}
+
+void OSelectionBrowseBox::SetReadOnly(bool bRO)
+{
+ if (bRO)
+ {
+ DeactivateCell();
+ m_nMode &= ~BrowserMode::HIDECURSOR;
+ SetMode(m_nMode);
+ }
+ else
+ {
+ m_nMode |= BrowserMode::HIDECURSOR;
+ SetMode(m_nMode);
+ ActivateCell();
+ }
+}
+
+CellController* OSelectionBrowseBox::GetController(sal_Int32 nRow, sal_uInt16 nColId)
+{
+ if ( nColId > getFields().size() )
+ return nullptr;
+ OTableFieldDescRef pEntry = getFields()[nColId-1];
+ OSL_ENSURE(pEntry.is(), "OSelectionBrowseBox::GetController : invalid FieldDescription !");
+
+ if (!pEntry.is())
+ return nullptr;
+
+ if (static_cast<OQueryController&>(getDesignView()->getController()).isReadOnly())
+ return nullptr;
+
+ sal_Int32 nCellIndex = GetRealRow(nRow);
+ switch (nCellIndex)
+ {
+ case BROW_FIELD_ROW:
+ return new ComboBoxCellController(m_pFieldCell);
+ case BROW_TABLE_ROW:
+ return new ListBoxCellController(m_pTableCell);
+ case BROW_VIS_ROW:
+ return new CheckBoxCellController(m_pVisibleCell);
+ case BROW_ORDER_ROW:
+ return new ListBoxCellController(m_pOrderCell);
+ case BROW_FUNCTION_ROW:
+ return new ListBoxCellController(m_pFunctionCell);
+ default:
+ return new EditCellController(m_pTextCell);
+ }
+}
+
+void OSelectionBrowseBox::InitController(CellControllerRef& /*rController*/, sal_Int32 nRow, sal_uInt16 nColId)
+{
+ OSL_ENSURE(nColId != BROWSER_INVALIDID,"An Invalid Id was set!");
+ if ( nColId == BROWSER_INVALIDID )
+ return;
+ sal_uInt16 nPos = GetColumnPos(nColId);
+ if ( nPos == 0 || nPos == BROWSER_INVALIDID || nPos > getFields().size() )
+ return;
+ OTableFieldDescRef pEntry = getFields()[nPos-1];
+ OSL_ENSURE(pEntry.is(), "OSelectionBrowseBox::InitController : invalid FieldDescription !");
+ sal_Int32 nCellIndex = GetRealRow(nRow);
+
+ switch (nCellIndex)
+ {
+ case BROW_FIELD_ROW:
+ {
+ weld::ComboBox& rComboBox = m_pFieldCell->get_widget();
+ rComboBox.clear();
+ rComboBox.set_entry_text(OUString());
+
+ OUString aField(pEntry->GetField());
+ OUString aTable(pEntry->GetAlias());
+
+ getDesignView()->fillValidFields(aTable, rComboBox);
+
+ // replace with alias.*
+ if (o3tl::trim(aField) == u"*")
+ {
+ aField = aTable + ".*";
+ }
+ rComboBox.set_entry_text(aField);
+ } break;
+ case BROW_TABLE_ROW:
+ {
+ weld::ComboBox& rComboBox = m_pTableCell->get_widget();
+ rComboBox.clear();
+ enableControl(pEntry, m_pTableCell);
+ if ( !pEntry->isCondition() )
+ {
+ for (auto const& tabWin : getDesignView()->getTableView()->GetTabWinMap())
+ rComboBox.append_text(static_cast<OQueryTableWindow*>(tabWin.second.get())->GetAliasName());
+
+ rComboBox.insert_text(0, DBA_RES(STR_QUERY_NOTABLE));
+ if (!pEntry->GetAlias().isEmpty())
+ rComboBox.set_active_text(pEntry->GetAlias());
+ else
+ rComboBox.set_active_text(DBA_RES(STR_QUERY_NOTABLE));
+ }
+ } break;
+ case BROW_VIS_ROW:
+ {
+ m_pVisibleCell->GetBox().set_active(pEntry->IsVisible());
+ m_pVisibleCell->GetBox().save_state();
+
+ enableControl(pEntry,m_pTextCell);
+
+ if(!pEntry->IsVisible() && pEntry->GetOrderDir() != ORDER_NONE && !m_bOrderByUnRelated)
+ {
+ // a column has to visible in order to show up in ORDER BY
+ pEntry->SetVisible();
+ m_pVisibleCell->GetBox().set_active(pEntry->IsVisible());
+ m_pVisibleCell->GetBox().save_state();
+ m_pVisibleCell->GetBox().set_sensitive(false);
+ OUString aMessage(DBA_RES(STR_QRY_ORDERBY_UNRELATED));
+ OQueryDesignView* paDView = getDesignView();
+ std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(paDView ? paDView->GetFrameWeld() : nullptr,
+ VclMessageType::Info, VclButtonsType::Ok,
+ aMessage));
+ xInfoBox->run();
+ }
+ } break;
+ case BROW_ORDER_ROW:
+ {
+ weld::ComboBox& rComboBox = m_pOrderCell->get_widget();
+ rComboBox.set_active(
+ sal::static_int_cast< sal_uInt16 >(pEntry->GetOrderDir()));
+ enableControl(pEntry,m_pOrderCell);
+ break;
+ }
+ case BROW_COLUMNALIAS_ROW:
+ setTextCellContext(pEntry,pEntry->GetFieldAlias(),HID_QRYDGN_ROW_ALIAS);
+ break;
+ case BROW_FUNCTION_ROW:
+ setFunctionCell(pEntry);
+ break;
+ default:
+ {
+ sal_uInt16 nIdx = sal_uInt16(nCellIndex - BROW_CRIT1_ROW);
+ setTextCellContext(pEntry,pEntry->GetCriteria( nIdx ),HID_QRYDGN_ROW_CRIT);
+ }
+ }
+ Controller()->SaveValue();
+}
+
+void OSelectionBrowseBox::notifyTableFieldChanged(const OUString& _sOldAlias, std::u16string_view _sAlias, bool& _bListAction, sal_uInt16 _nColumnId)
+{
+ appendUndoAction(_sOldAlias,_sAlias,BROW_TABLE_ROW,_bListAction);
+ if ( m_bVisibleRow[BROW_TABLE_ROW] )
+ RowModified(GetBrowseRow(BROW_TABLE_ROW), _nColumnId);
+}
+
+void OSelectionBrowseBox::notifyFunctionFieldChanged(const OUString& _sOldFunctionName, std::u16string_view _sFunctionName, bool& _bListAction, sal_uInt16 _nColumnId)
+{
+ appendUndoAction(_sOldFunctionName,_sFunctionName,BROW_FUNCTION_ROW,_bListAction);
+ if ( !m_bVisibleRow[BROW_FUNCTION_ROW] )
+ SetRowVisible(BROW_FUNCTION_ROW, true);
+ RowModified(GetBrowseRow(BROW_FUNCTION_ROW), _nColumnId);
+}
+
+void OSelectionBrowseBox::clearEntryFunctionField(const OUString& _sFieldName,OTableFieldDescRef const & _pEntry, bool& _bListAction,sal_uInt16 _nColumnId)
+{
+ if ( !(isFieldNameAsterisk( _sFieldName ) && (!_pEntry->isNoneFunction() || _pEntry->IsGroupBy())) )
+ return;
+
+ OUString sFunctionName;
+ GetFunctionName(SQL_TOKEN_COUNT,sFunctionName);
+ OUString sOldLocalizedFunctionName = _pEntry->GetFunction();
+ if ( sOldLocalizedFunctionName != sFunctionName || _pEntry->IsGroupBy() )
+ {
+ // append undo action for the function field
+ _pEntry->SetFunctionType(FKT_NONE);
+ _pEntry->SetFunction(OUString());
+ _pEntry->SetGroupBy(false);
+ notifyFunctionFieldChanged(sOldLocalizedFunctionName,_pEntry->GetFunction(),_bListAction,_nColumnId);
+ }
+}
+
+bool OSelectionBrowseBox::fillColumnRef(const OSQLParseNode* _pColumnRef, const Reference< XConnection >& _rxConnection, OTableFieldDescRef const & _pEntry, bool& _bListAction )
+{
+ OSL_ENSURE(_pColumnRef,"No valid parsenode!");
+ OUString sColumnName,sTableRange;
+ OSQLParseTreeIterator::getColumnRange(_pColumnRef,_rxConnection,sColumnName,sTableRange);
+ return fillColumnRef(sColumnName,sTableRange,_rxConnection->getMetaData(),_pEntry,_bListAction);
+}
+
+bool OSelectionBrowseBox::fillColumnRef(const OUString& _sColumnName, std::u16string_view _sTableRange, const Reference<XDatabaseMetaData>& _xMetaData, OTableFieldDescRef const & _pEntry, bool& _bListAction)
+{
+ bool bError = false;
+ ::comphelper::UStringMixEqual bCase(_xMetaData->supportsMixedCaseQuotedIdentifiers());
+ // check if the table name is the same
+ if ( !_sTableRange.empty() && (bCase(_pEntry->GetTable(),_sTableRange) || bCase(_pEntry->GetAlias(),_sTableRange)) )
+ { // a table was already inserted and the tables contains that column name
+
+ if ( !_pEntry->GetTabWindow() )
+ { // fill tab window
+ OUString sOldAlias = _pEntry->GetAlias();
+ if ( !fillEntryTable(_pEntry,_pEntry->GetTable()) )
+ fillEntryTable(_pEntry,_pEntry->GetAlias()); // only when the first failed
+ if ( !bCase(sOldAlias,_pEntry->GetAlias()) )
+ notifyTableFieldChanged(sOldAlias,_pEntry->GetAlias(),_bListAction,GetCurColumnId());
+ }
+ }
+ // check if the table window
+ OQueryTableWindow* pEntryTab = static_cast<OQueryTableWindow*>(_pEntry->GetTabWindow());
+ if ( !pEntryTab ) // no table found with this name so we have to travel through all tables
+ {
+ sal_uInt16 nTabCount = 0;
+ if ( !static_cast<OQueryTableView*>(getDesignView()->getTableView())->FindTableFromField(_sColumnName,_pEntry,nTabCount) ) // error occurred: column not in table window
+ {
+ OUString sErrorMsg(DBA_RES(RID_STR_FIELD_DOESNT_EXIST));
+ sErrorMsg = sErrorMsg.replaceFirst("$name$",_sColumnName);
+ OSQLErrorBox aWarning(GetFrameWeld(), sErrorMsg);
+ aWarning.run();
+ bError = true;
+ }
+ else
+ {
+ pEntryTab = static_cast<OQueryTableWindow*>(_pEntry->GetTabWindow());
+ notifyTableFieldChanged(OUString(),_pEntry->GetAlias(),_bListAction,GetCurColumnId());
+ }
+ }
+ if ( pEntryTab ) // here we got a valid table
+ _pEntry->SetField(_sColumnName);
+
+ return bError;
+}
+
+bool OSelectionBrowseBox::saveField(OUString& _sFieldName ,OTableFieldDescRef const & _pEntry, bool& _bListAction)
+{
+ bool bError = false;
+
+ OQueryController& rController = static_cast<OQueryController&>(getDesignView()->getController());
+
+ // first look if the name can be found in our tables
+ sal_uInt16 nTabCount = 0;
+ OUString sOldAlias = _pEntry->GetAlias();
+ if ( static_cast<OQueryTableView*>(getDesignView()->getTableView())->FindTableFromField(_sFieldName,_pEntry,nTabCount) )
+ {
+ // append undo action for the alias name
+ _pEntry->SetField(_sFieldName);
+ notifyTableFieldChanged(sOldAlias,_pEntry->GetAlias(),_bListAction,GetCurColumnId());
+ clearEntryFunctionField(_sFieldName,_pEntry,_bListAction,_pEntry->GetColumnId());
+ return bError;
+ }
+
+ Reference<XConnection> xConnection( rController.getConnection() );
+ Reference< XDatabaseMetaData > xMetaData;
+ if ( xConnection.is() )
+ xMetaData = xConnection->getMetaData();
+ OSL_ENSURE( xMetaData.is(), "OSelectionBrowseBox::saveField: invalid connection/meta data!" );
+ if ( !xMetaData.is() )
+ return true;
+
+ OUString sErrorMsg;
+ // second test if the name can be set as select columns in a pseudo statement
+ // we have to look which entries we should quote
+
+ const OUString sFieldAlias = _pEntry->GetFieldAlias();
+ ::connectivity::OSQLParser& rParser( rController.getParser() );
+ {
+ // automatically add parentheses around subqueries
+ OUString devnull;
+ std::unique_ptr<OSQLParseNode> pParseNode = rParser.parseTree( devnull, _sFieldName, true );
+ if (pParseNode == nullptr)
+ pParseNode = rParser.parseTree( devnull, _sFieldName );
+ if (pParseNode != nullptr && SQL_ISRULE(pParseNode, select_statement))
+ _sFieldName = "(" + _sFieldName + ")";
+ }
+
+ std::unique_ptr<OSQLParseNode> pParseNode;
+ {
+ // 4 passes in trying to interpret the field name
+ // - don't quote the field name, parse internationally
+ // - don't quote the field name, parse en-US
+ // - quote the field name, parse internationally
+ // - quote the field name, parse en-US
+ size_t nPass = 4;
+ OUString sQuotedFullFieldName(::dbtools::quoteName( xMetaData->getIdentifierQuoteString(), _sFieldName ));
+ OUString sFullFieldName(_sFieldName);
+
+ if ( _pEntry->isAggregateFunction() )
+ {
+ OSL_ENSURE(!_pEntry->GetFunction().isEmpty(),"No empty Function name allowed here! ;-(");
+ sQuotedFullFieldName = _pEntry->GetFunction() + "(" + sQuotedFullFieldName + ")";
+ sFullFieldName = _pEntry->GetFunction() + "(" + sFullFieldName + ")";
+ }
+
+ do
+ {
+ bool bQuote = ( nPass <= 2 );
+ bool bInternational = ( nPass % 2 ) == 0;
+
+ OUString sSql {"SELECT "};
+ if ( bQuote )
+ sSql += sQuotedFullFieldName;
+ else
+ sSql += sFullFieldName;
+
+ if ( !sFieldAlias.isEmpty() )
+ { // always quote the alias name: there cannot be a function in it
+ sSql += " " + ::dbtools::quoteName( xMetaData->getIdentifierQuoteString(), sFieldAlias );
+ }
+ sSql += " FROM x";
+
+ pParseNode = rParser.parseTree( sErrorMsg, sSql, bInternational );
+ }
+ while ( ( pParseNode == nullptr ) && ( --nPass > 0 ) );
+ }
+
+ if ( pParseNode == nullptr )
+ {
+ // something different which we have to check
+ OUString sErrorMessage( DBA_RES( STR_QRY_COLUMN_NOT_FOUND ) );
+ sErrorMessage = sErrorMessage.replaceFirst("$name$",_sFieldName);
+ OSQLErrorBox aWarning(GetFrameWeld(), sErrorMessage);
+ aWarning.run();
+
+ return true;
+ }
+
+ // we got a valid select column
+ // find what type of column has be inserted
+ ::connectivity::OSQLParseNode* pSelection = pParseNode->getChild(2);
+ if ( SQL_ISRULE(pSelection,selection) ) // we found the asterisk
+ {
+ _pEntry->SetField(_sFieldName);
+ clearEntryFunctionField(_sFieldName,_pEntry,_bListAction,_pEntry->GetColumnId());
+ }
+ else // travel through the select column parse node
+ {
+ OTableFieldDescRef aSelEntry = _pEntry;
+ sal_uInt16 nColumnId = aSelEntry->GetColumnId();
+
+ sal_uInt32 nCount = pSelection->count();
+ for (sal_uInt32 i = 0; i < nCount; ++i)
+ {
+ if ( i > 0 ) // may we have to append more than one field
+ {
+ sal_uInt16 nColumnPosition;
+ aSelEntry = FindFirstFreeCol(nColumnPosition);
+ if ( !aSelEntry.is() )
+ {
+ AppendNewCol();
+ aSelEntry = FindFirstFreeCol(nColumnPosition);
+ }
+ ++nColumnPosition;
+ nColumnId = GetColumnId(nColumnPosition);
+ }
+
+ ::connectivity::OSQLParseNode* pChild = pSelection->getChild( i );
+ OSL_ENSURE(SQL_ISRULE(pChild,derived_column), "No derived column found!");
+ // get the column alias
+ OUString sColumnAlias = OSQLParseTreeIterator::getColumnAlias(pChild);
+ if ( !sColumnAlias.isEmpty() ) // we found an as clause
+ {
+ OUString aSelectionAlias = aSelEntry->GetFieldAlias();
+ aSelEntry->SetFieldAlias( sColumnAlias );
+ // append undo
+ appendUndoAction(aSelectionAlias,aSelEntry->GetFieldAlias(),BROW_COLUMNALIAS_ROW,_bListAction);
+ if ( m_bVisibleRow[BROW_COLUMNALIAS_ROW] )
+ RowModified(GetBrowseRow(BROW_COLUMNALIAS_ROW), nColumnId);
+ }
+
+ ::connectivity::OSQLParseNode* pColumnRef = pChild->getChild(0);
+ if (
+ pColumnRef->getKnownRuleID() != OSQLParseNode::subquery &&
+ pColumnRef->count() == 3 &&
+ SQL_ISPUNCTUATION(pColumnRef->getChild(0),"(") &&
+ SQL_ISPUNCTUATION(pColumnRef->getChild(2),")")
+ )
+ pColumnRef = pColumnRef->getChild(1);
+
+ if ( SQL_ISRULE(pColumnRef,column_ref) ) // we found a valid column name or more column names
+ {
+ // look if we can find the corresponding table
+ bError = fillColumnRef( pColumnRef, xConnection, aSelEntry, _bListAction );
+
+ // we found a simple column so we must clear the function fields but only when the column name is '*'
+ // and the function is different to count
+ clearEntryFunctionField(_sFieldName,aSelEntry,_bListAction,nColumnId);
+ }
+ // do we have an aggregate function and only a function?
+ else if ( SQL_ISRULE(pColumnRef,general_set_fct) )
+ {
+ OUString sLocalizedFunctionName;
+ if ( GetFunctionName(pColumnRef->getChild(0)->getTokenID(),sLocalizedFunctionName) )
+ {
+ OUString sOldLocalizedFunctionName = aSelEntry->GetFunction();
+ aSelEntry->SetFunction(sLocalizedFunctionName);
+ sal_uInt32 nFunCount = pColumnRef->count() - 1;
+ sal_Int32 nFunctionType = FKT_AGGREGATE;
+ bool bQuote = false;
+ // may be there exists only one parameter which is a column, fill all information into our fields
+ if ( nFunCount == 4 && SQL_ISRULE(pColumnRef->getChild(3),column_ref) )
+ bError = fillColumnRef( pColumnRef->getChild(3), xConnection, aSelEntry, _bListAction );
+ else if ( nFunCount == 3 ) // we have a COUNT(*) here, so take the first table
+ bError = fillColumnRef( "*", std::u16string_view(), xMetaData, aSelEntry, _bListAction );
+ else
+ {
+ nFunctionType |= FKT_NUMERIC;
+ bQuote = true;
+ aSelEntry->SetDataType(DataType::DOUBLE);
+ aSelEntry->SetFieldType(TAB_NORMAL_FIELD);
+ }
+
+ // now parse the parameters
+ OUString sParameters;
+ for(sal_uInt32 function = 2; function < nFunCount; ++function) // we only want to parse the parameters of the function
+ pColumnRef->getChild(function)->parseNodeToStr( sParameters, xConnection, &rParser.getContext(), true, bQuote );
+
+ aSelEntry->SetFunctionType(nFunctionType);
+ aSelEntry->SetField(sParameters);
+ if ( aSelEntry->IsGroupBy() )
+ {
+ sOldLocalizedFunctionName = m_aFunctionStrings.copy(m_aFunctionStrings.lastIndexOf(';')+1);
+ aSelEntry->SetGroupBy(false);
+ }
+
+ // append undo action
+ notifyFunctionFieldChanged(sOldLocalizedFunctionName,sLocalizedFunctionName,_bListAction, nColumnId);
+ }
+ else
+ OSL_FAIL("Unsupported function inserted!");
+
+ }
+ else
+ {
+ // so we first clear the function field
+ clearEntryFunctionField(_sFieldName,aSelEntry,_bListAction,nColumnId);
+ OUString sFunction;
+ pColumnRef->parseNodeToStr( sFunction,
+ xConnection,
+ &rController.getParser().getContext(),
+ true); // quote is to true because we need quoted elements inside the function
+
+ getDesignView()->fillFunctionInfo(pColumnRef,sFunction,aSelEntry);
+
+ if( SQL_ISRULEOR3(pColumnRef, position_exp, extract_exp, fold) ||
+ SQL_ISRULEOR3(pColumnRef, char_substring_fct, length_exp, char_value_fct) )
+ // a calculation has been found ( can be calc and function )
+ {
+ // now parse the whole statement
+ sal_uInt32 nFunCount = pColumnRef->count();
+ OUString sParameters;
+ for(sal_uInt32 function = 0; function < nFunCount; ++function)
+ pColumnRef->getChild(function)->parseNodeToStr( sParameters, xConnection, &rParser.getContext(), true );
+
+ sOldAlias = aSelEntry->GetAlias();
+ sal_Int32 nNewFunctionType = aSelEntry->GetFunctionType() | FKT_NUMERIC | FKT_OTHER;
+ aSelEntry->SetFunctionType(nNewFunctionType);
+ aSelEntry->SetField(sParameters);
+ }
+ else
+ {
+ aSelEntry->SetFieldAlias(sColumnAlias);
+ if ( SQL_ISRULE(pColumnRef,set_fct_spec) )
+ aSelEntry->SetFunctionType(/*FKT_NUMERIC | */FKT_OTHER);
+ else
+ aSelEntry->SetFunctionType(FKT_NUMERIC | FKT_OTHER);
+ }
+
+ aSelEntry->SetAlias(OUString());
+ notifyTableFieldChanged(sOldAlias,aSelEntry->GetAlias(),_bListAction, nColumnId);
+ }
+
+ if ( i > 0 && !InsertField(aSelEntry,BROWSER_INVALIDID,true,false).is() ) // may we have to append more than one field
+ { // the field could not be inserted
+ OUString sErrorMessage( DBA_RES( RID_STR_FIELD_DOESNT_EXIST ) );
+ sErrorMessage = sErrorMessage.replaceFirst("$name$",aSelEntry->GetField());
+ OSQLErrorBox aWarning(GetFrameWeld(), sErrorMessage);
+ aWarning.run();
+ bError = true;
+ }
+ }
+ }
+
+ return bError;
+}
+
+bool OSelectionBrowseBox::SaveModified()
+{
+ OQueryController& rController = static_cast<OQueryController&>(getDesignView()->getController());
+ OTableFieldDescRef pEntry;
+ sal_uInt16 nCurrentColumnPos = GetColumnPos(GetCurColumnId());
+ if(getFields().size() > o3tl::make_unsigned(nCurrentColumnPos - 1))
+ pEntry = getEntry(nCurrentColumnPos - 1);
+
+ bool bWasEmpty = pEntry.is() && pEntry->IsEmpty();
+ bool bError = false;
+ bool bListAction = false;
+
+ if (pEntry.is() && Controller().is() && Controller()->IsValueChangedFromSaved())
+ {
+ // for the Undo-action
+ OUString strOldCellContents,sNewValue;
+ sal_Int32 nRow = GetRealRow(GetCurRow());
+ bool bAppendRow = false;
+ switch (nRow)
+ {
+ case BROW_VIS_ROW:
+ {
+ bool bOldValue = m_pVisibleCell->GetBox().get_saved_state() != TRISTATE_FALSE;
+ strOldCellContents
+ = bOldValue ? std::u16string_view(u"1") : std::u16string_view(u"0");
+ sNewValue
+ = !bOldValue ? std::u16string_view(u"1") : std::u16string_view(u"0");
+ }
+ if((m_bOrderByUnRelated || pEntry->GetOrderDir() == ORDER_NONE) &&
+ (m_bGroupByUnRelated || !pEntry->IsGroupBy()))
+ {
+ pEntry->SetVisible(m_pVisibleCell->GetBox().get_active());
+ }
+ else
+ {
+ pEntry->SetVisible();
+ m_pVisibleCell->GetBox().set_active(true);
+ }
+ break;
+
+ case BROW_FIELD_ROW:
+ {
+ weld::ComboBox& rComboBox = m_pFieldCell->get_widget();
+ OUString aFieldName(rComboBox.get_active_text());
+ try
+ {
+ if (aFieldName.isEmpty())
+ {
+ OTableFieldDescRef pNewEntry = new OTableFieldDesc();
+ pNewEntry->SetColumnId( pEntry->GetColumnId() );
+ std::replace(getFields().begin(),getFields().end(),pEntry,pNewEntry);
+ sal_uInt16 nCol = GetCurColumnId();
+ for (int i = 0; i < m_nVisibleCount; i++) // redraw column
+ RowModified(i,nCol);
+ }
+ else
+ {
+ strOldCellContents = pEntry->GetField();
+ bListAction = true;
+ if ( !m_bInUndoMode )
+ rController.GetUndoManager().EnterListAction(OUString(),OUString(),0,ViewShellId(-1));
+
+ sal_Int32 nPos = rComboBox.find_text(aFieldName);
+ OUString aAliasName = pEntry->GetAlias();
+ if ( nPos != -1 && aAliasName.isEmpty() && aFieldName.indexOf('.') >= 0 )
+ { // special case, we have a table field so we must cut the table name
+ OUString sTableAlias = aFieldName.getToken(0,'.');
+ pEntry->SetAlias(sTableAlias);
+ OUString sColumnName = aFieldName.copy(sTableAlias.getLength()+1);
+ const Reference<XConnection>& xConnection = rController.getConnection();
+ if ( !xConnection.is() )
+ return false;
+ bError = fillColumnRef( sColumnName, sTableAlias, xConnection->getMetaData(), pEntry, bListAction );
+ }
+ else
+ bError = true;
+
+ if ( bError )
+ bError = saveField(aFieldName,pEntry,bListAction);
+ }
+ }
+ catch(Exception&)
+ {
+ bError = true;
+ }
+ if ( bError )
+ {
+ sNewValue = aFieldName;
+ if ( !m_bInUndoMode )
+ static_cast<OQueryController&>(getDesignView()->getController()).GetUndoManager().LeaveListAction();
+ bListAction = false;
+ }
+ else
+ sNewValue = pEntry->GetField();
+ rController.InvalidateFeature( ID_BROWSER_QUERY_EXECUTE );
+ }
+ break;
+
+ case BROW_TABLE_ROW:
+ {
+ weld::ComboBox& rComboBox = m_pTableCell->get_widget();
+ OUString aAliasName = rComboBox.get_active_text();
+ strOldCellContents = pEntry->GetAlias();
+ if (rComboBox.get_active() != 0)
+ {
+ pEntry->SetAlias(aAliasName);
+ // we have to set the table name as well as the table window
+ OJoinTableView::OTableWindowMap& rTabWinList = getDesignView()->getTableView()->GetTabWinMap();
+ OJoinTableView::OTableWindowMap::const_iterator aIter = rTabWinList.find(aAliasName);
+ if(aIter != rTabWinList.end())
+ {
+ OQueryTableWindow* pEntryTab = static_cast<OQueryTableWindow*>(aIter->second.get());
+ if (pEntryTab)
+ {
+ pEntry->SetTable(pEntryTab->GetTableName());
+ pEntry->SetTabWindow(pEntryTab);
+ }
+ }
+ }
+ else
+ {
+ pEntry->SetAlias(OUString());
+ pEntry->SetTable(OUString());
+ pEntry->SetTabWindow(nullptr);
+ }
+ sNewValue = pEntry->GetAlias();
+
+ } break;
+
+ case BROW_ORDER_ROW:
+ {
+ strOldCellContents = OUString::number(static_cast<sal_uInt16>(pEntry->GetOrderDir()));
+ weld::ComboBox& rComboBox = m_pOrderCell->get_widget();
+ sal_Int32 nIdx = rComboBox.get_active();
+ if (nIdx == -1)
+ nIdx = 0;
+ pEntry->SetOrderDir(EOrderDir(nIdx));
+ if(!m_bOrderByUnRelated)
+ {
+ pEntry->SetVisible();
+ m_pVisibleCell->GetBox().set_active(true);
+ RowModified(GetBrowseRow(BROW_VIS_ROW), GetCurColumnId());
+ }
+ sNewValue = OUString::number(static_cast<sal_uInt16>(pEntry->GetOrderDir()));
+ } break;
+
+ case BROW_COLUMNALIAS_ROW:
+ strOldCellContents = pEntry->GetFieldAlias();
+ pEntry->SetFieldAlias(m_pTextCell->get_widget().get_text());
+ sNewValue = pEntry->GetFieldAlias();
+ break;
+ case BROW_FUNCTION_ROW:
+ {
+ strOldCellContents = pEntry->GetFunction();
+ weld::ComboBox& rComboBox = m_pFunctionCell->get_widget();
+ sal_Int32 nPos = rComboBox.get_active();
+ // these functions are only available in CORE
+ OUString sFunctionName = rComboBox.get_text(nPos);
+ std::u16string_view sGroupFunctionName = m_aFunctionStrings.subView(m_aFunctionStrings.lastIndexOf(';')+1);
+ bool bGroupBy = false;
+ if ( sGroupFunctionName == sFunctionName ) // check if the function name is GROUP
+ {
+ bGroupBy = true;
+
+ if ( !m_bGroupByUnRelated && !pEntry->IsVisible() )
+ {
+ // we have to change the visible flag, so we must append also an undo action
+ pEntry->SetVisible();
+ m_pVisibleCell->GetBox().set_active(true);
+ appendUndoAction("0",u"1",BROW_VIS_ROW,bListAction);
+ RowModified(GetBrowseRow(BROW_VIS_ROW), GetCurColumnId());
+ }
+
+ pEntry->SetFunction(OUString());
+ pEntry->SetFunctionType(pEntry->GetFunctionType() & ~FKT_AGGREGATE );
+ }
+ else if ( nPos ) // we found an aggregate function
+ {
+ pEntry->SetFunctionType(pEntry->GetFunctionType() | FKT_AGGREGATE );
+ pEntry->SetFunction(sFunctionName);
+ }
+ else
+ {
+ sFunctionName.clear();
+ pEntry->SetFunction(OUString());
+ pEntry->SetFunctionType(pEntry->GetFunctionType() & ~FKT_AGGREGATE );
+ }
+
+ pEntry->SetGroupBy(bGroupBy);
+
+ sNewValue = sFunctionName;
+ }
+ break;
+ default:
+ {
+ Reference< XConnection> xConnection = static_cast<OQueryController&>(getDesignView()->getController()).getConnection();
+ if(!xConnection.is())
+ break;
+
+ sal_uInt16 nIdx = sal_uInt16(nRow - BROW_CRIT1_ROW);
+ OUString aText = comphelper::string::stripStart(m_pTextCell->get_widget().get_text(), ' ');
+
+ OUString aCrit;
+ if(!aText.isEmpty())
+ {
+ OUString aErrorMsg;
+ Reference<XPropertySet> xColumn;
+ std::unique_ptr<OSQLParseNode> pParseNode = getDesignView()->getPredicateTreeFromEntry(pEntry,aText,aErrorMsg,xColumn);
+
+ if (pParseNode)
+ {
+ pParseNode->parseNodeToPredicateStr(aCrit,
+ xConnection,
+ static_cast<OQueryController&>(getDesignView()->getController()).getNumberFormatter(),
+ xColumn,
+ pEntry->GetAlias(),
+ getDesignView()->getLocale(),
+ getDesignView()->getDecimalSeparator(),
+ &(static_cast<OQueryController&>(getDesignView()->getController()).getParser().getContext()));
+ }
+ else
+ {
+ if(xColumn.is())
+ {
+ sal_Int32 nType = 0;
+ xColumn->getPropertyValue(PROPERTY_TYPE) >>= nType;
+ switch(nType)
+ {
+ case DataType::CHAR:
+ case DataType::VARCHAR:
+ case DataType::LONGVARCHAR:
+ case DataType::CLOB:
+ if(!aText.startsWith("'") || !aText.endsWith("'"))
+ {
+ aText = aText.replaceAll("'", "''");
+ aText = "'" + aText + "'";
+ }
+ break;
+ default:
+ ;
+ }
+ ::connectivity::OSQLParser& rParser = static_cast<OQueryController&>(getDesignView()->getController()).getParser();
+ pParseNode = rParser.predicateTree(aErrorMsg,
+ aText,
+ static_cast<OQueryController&>(getDesignView()->getController()).getNumberFormatter(),
+ xColumn);
+ if (pParseNode)
+ {
+ pParseNode->parseNodeToPredicateStr(aCrit,
+ xConnection,
+ static_cast<OQueryController&>(getDesignView()->getController()).getNumberFormatter(),
+ xColumn,
+ pEntry->GetAlias(),
+ getDesignView()->getLocale(),
+ getDesignView()->getDecimalSeparator(),
+ &(static_cast<OQueryController&>(getDesignView()->getController()).getParser().getContext()));
+ }
+ else
+ {
+ if ( !m_bDisableErrorBox )
+ {
+ OSQLWarningBox aWarning(GetFrameWeld(), aErrorMsg);
+ aWarning.run();
+ }
+ bError = true;
+ }
+ }
+ else
+ {
+ if ( !m_bDisableErrorBox )
+ {
+ OSQLWarningBox aWarning(GetFrameWeld(), aErrorMsg);
+ aWarning.run();
+ }
+ bError = true;
+ }
+ }
+ }
+ strOldCellContents = pEntry->GetCriteria(nIdx);
+ pEntry->SetCriteria(nIdx, aCrit);
+ sNewValue = pEntry->GetCriteria(nIdx);
+ if(!aCrit.isEmpty() && nRow >= (GetRowCount()-1))
+ bAppendRow = true;
+ }
+ }
+ if( !bError && Controller().is() )
+ Controller()->SaveValue();
+
+ RowModified(GetCurRow(), GetCurColumnId());
+
+ if ( bAppendRow )
+ {
+ RowInserted( GetRowCount()-1 );
+ m_bVisibleRow.push_back(true);
+ ++m_nVisibleCount;
+ }
+
+ if(!bError)
+ {
+ // and now the undo-action for the total
+ appendUndoAction(strOldCellContents,sNewValue,nRow);
+
+ }
+ }
+
+ // did I store data in a FieldDescription which was empty before and which is not empty anymore after the changes?
+ if ( pEntry.is() && bWasEmpty && !pEntry->IsEmpty() && !bError )
+ {
+ // Default to visible
+ pEntry->SetVisible();
+ appendUndoAction("0",u"1",BROW_VIS_ROW,bListAction);
+ RowModified(BROW_VIS_ROW, GetCurColumnId());
+
+ // if required add empty columns
+ sal_uInt16 nDummy;
+ CheckFreeColumns(nDummy);
+ }
+
+ if ( bListAction && !m_bInUndoMode )
+ static_cast<OQueryController&>(getDesignView()->getController()).GetUndoManager().LeaveListAction();
+
+ return pEntry != nullptr && !bError;
+}
+
+bool OSelectionBrowseBox::SeekRow(sal_Int32 nRow)
+{
+ m_nSeekRow = nRow;
+ return nRow < m_nVisibleCount;
+}
+
+void OSelectionBrowseBox::PaintCell(OutputDevice& rDev, const tools::Rectangle& rRect, sal_uInt16 nColumnId) const
+{
+ rDev.SetClipRegion(vcl::Region(rRect));
+
+ OTableFieldDescRef pEntry;
+ sal_uInt16 nPos = GetColumnPos(nColumnId);
+ if(getFields().size() > o3tl::make_unsigned(nPos - 1))
+ pEntry = getFields()[nPos - 1];
+
+ if (!pEntry.is())
+ return;
+
+ sal_Int32 nRow = GetRealRow(m_nSeekRow);
+ if (nRow == BROW_VIS_ROW)
+ PaintTristate(rRect, pEntry->IsVisible() ? TRISTATE_TRUE : TRISTATE_FALSE);
+ else
+ rDev.DrawText(rRect, GetCellText(nRow, nColumnId),DrawTextFlags::VCenter);
+
+ rDev.SetClipRegion( );
+}
+
+void OSelectionBrowseBox::PaintStatusCell(OutputDevice& rDev, const tools::Rectangle& rRect) const
+{
+ tools::Rectangle aRect(rRect);
+ aRect.TopLeft().AdjustY( -2 );
+ OUString aLabel(DBA_RES(STR_QUERY_HANDLETEXT));
+
+ // from BROW_CRIT2_ROW onwards all rows are shown "or"
+ sal_Int32 nToken = (m_nSeekRow >= GetBrowseRow(BROW_CRIT2_ROW))
+ ? BROW_CRIT2_ROW : GetRealRow(m_nSeekRow);
+ rDev.DrawText(aRect, aLabel.getToken(nToken, ';'),DrawTextFlags::VCenter);
+}
+
+void OSelectionBrowseBox::RemoveColumn(sal_uInt16 _nColumnId)
+{
+ OQueryController& rController = static_cast<OQueryController&>(getDesignView()->getController());
+
+ sal_uInt16 nPos = GetColumnPos(_nColumnId);
+ // the control should always have exactly one more column: the HandleColumn
+ OSL_ENSURE((nPos == 0) || (nPos <= getFields().size()), "OSelectionBrowseBox::RemoveColumn : invalid parameter nColId");
+ // ColId is synonymous to Position, and the condition should be valid
+
+ sal_uInt16 nCurCol = GetCurColumnId();
+ sal_Int32 nCurrentRow = GetCurRow();
+
+ DeactivateCell();
+
+ getFields().erase( getFields().begin() + (nPos - 1) );
+ OTableFieldDescRef pEntry = new OTableFieldDesc();
+ pEntry->SetColumnId(_nColumnId);
+ getFields().push_back(pEntry);
+
+ EditBrowseBox::RemoveColumn( _nColumnId );
+ InsertDataColumn( _nColumnId , OUString(), DEFAULT_SIZE );
+
+ // redraw
+ tools::Rectangle aInvalidRect = GetInvalidRect( _nColumnId );
+ Invalidate( aInvalidRect );
+
+ ActivateCell( nCurrentRow, nCurCol );
+
+ rController.setModified( true );
+
+ invalidateUndoRedo();
+}
+
+void OSelectionBrowseBox::RemoveField(sal_uInt16 nColumnId )
+{
+ OQueryController& rController = static_cast<OQueryController&>(getDesignView()->getController());
+
+ sal_uInt16 nPos = GetColumnPos(nColumnId);
+ OSL_ENSURE(getFields().size() > o3tl::make_unsigned(nPos-1),"ID is to great!");
+
+ OTableFieldDescRef pDesc = getEntry(static_cast<sal_uInt32>(nPos - 1)) ;
+ pDesc->SetColWidth( static_cast<sal_uInt16>(GetColumnWidth(nColumnId)) ); // was not stored this before
+
+ // trigger UndoAction
+ if ( !m_bInUndoMode )
+ {
+ std::unique_ptr<OTabFieldDelUndoAct> pUndoAction(new OTabFieldDelUndoAct( this ));
+ pUndoAction->SetTabFieldDescr(pDesc);
+ pUndoAction->SetColumnPosition(nPos);
+ rController.addUndoActionAndInvalidate( std::move(pUndoAction) );
+ }
+
+ RemoveColumn(nColumnId);
+
+ invalidateUndoRedo();
+}
+
+void OSelectionBrowseBox::adjustSelectionMode( bool _bClickedOntoHeader, bool _bClickedOntoHandleCol )
+{
+ // if a Header has been selected it should be shown otherwise not
+ if ( _bClickedOntoHeader )
+ {
+ if (0 == GetSelectColumnCount() )
+ // I am in the correct mode if a selected column exists
+ if ( BrowserMode::HIDESELECT == ( m_nMode & BrowserMode::HIDESELECT ) )
+ {
+ m_nMode &= ~BrowserMode::HIDESELECT;
+ m_nMode |= BrowserMode::MULTISELECTION;
+ SetMode( m_nMode );
+ }
+ }
+ else if ( BrowserMode::HIDESELECT != ( m_nMode & BrowserMode::HIDESELECT ) )
+ {
+ if ( GetSelectColumnCount() != 0 )
+ SetNoSelection();
+
+ if ( _bClickedOntoHandleCol )
+ {
+ m_nMode |= BrowserMode::HIDESELECT;
+ m_nMode &= ~BrowserMode::MULTISELECTION;
+ SetMode( m_nMode );
+ }
+ }
+}
+
+void OSelectionBrowseBox::MouseButtonDown(const BrowserMouseEvent& rEvt)
+{
+ if( rEvt.IsLeft() )
+ {
+ bool bOnHandle = HANDLE_ID == rEvt.GetColumnId();
+ bool bOnHeader = ( rEvt.GetRow() < 0 ) && !bOnHandle;
+ adjustSelectionMode( bOnHeader, bOnHandle );
+ }
+ EditBrowseBox::MouseButtonDown(rEvt);
+}
+
+void OSelectionBrowseBox::MouseButtonUp(const BrowserMouseEvent& rEvt)
+{
+ EditBrowseBox::MouseButtonUp( rEvt );
+ static_cast<OQueryController&>(getDesignView()->getController()).InvalidateFeature( ID_BROWSER_QUERY_EXECUTE );
+}
+
+void OSelectionBrowseBox::KeyInput( const KeyEvent& rEvt )
+{
+ if (IsColumnSelected(GetCurColumnId()))
+ {
+ if (rEvt.GetKeyCode().GetCode() == KEY_DELETE && // Delete rows
+ !rEvt.GetKeyCode().IsShift() &&
+ !rEvt.GetKeyCode().IsMod1())
+ {
+ RemoveField(GetCurColumnId());
+ return;
+ }
+ }
+ EditBrowseBox::KeyInput(rEvt);
+}
+
+sal_Int8 OSelectionBrowseBox::AcceptDrop( const BrowserAcceptDropEvent& rEvt )
+{
+ sal_Int8 nDropAction = DND_ACTION_NONE;
+ if ( rEvt.GetRow() >= -1 )
+ {
+ if ( IsEditing() )
+ {
+ // allow the asterisk again
+ m_bDisableErrorBox = true;
+ SaveModified();
+ m_bDisableErrorBox = false;
+ DeactivateCell();
+ }
+ // check if the format is already supported, if not deactivate the current cell and try again
+ if ( OJoinExchObj::isFormatAvailable(GetDataFlavors()) )
+ nDropAction = DND_ACTION_LINK;
+ }
+
+ return nDropAction;
+}
+
+sal_Int8 OSelectionBrowseBox::ExecuteDrop( const BrowserExecuteDropEvent& _rEvt )
+{
+
+ TransferableDataHelper aDropped(_rEvt.maDropEvent.Transferable);
+ if (!OJoinExchObj::isFormatAvailable(aDropped.GetDataFlavorExVector()))
+ {
+ OSL_FAIL("OSelectionBrowseBox::ExecuteDrop: this should never have passed AcceptDrop!");
+ return DND_ACTION_NONE;
+ }
+
+ // insert the field at the selected position
+ OJoinExchangeData jxdSource = OJoinExchObj::GetSourceDescription(_rEvt.maDropEvent.Transferable);
+ InsertField(jxdSource);
+
+ return DND_ACTION_LINK;
+}
+
+OTableFieldDescRef const & OSelectionBrowseBox::AppendNewCol( sal_uInt16 nCnt)
+{
+ // one or more can be created, but the first one will is not returned
+ sal_uInt32 nCount = getFields().size();
+ for (sal_uInt16 i=0 ; i<nCnt ; i++)
+ {
+ OTableFieldDescRef pEmptyEntry = new OTableFieldDesc();
+ getFields().push_back(pEmptyEntry);
+ sal_uInt16 nColumnId = sal::static_int_cast< sal_uInt16 >(getFields().size());
+ pEmptyEntry->SetColumnId( nColumnId );
+
+ InsertDataColumn( nColumnId , OUString(), DEFAULT_SIZE );
+ }
+
+ return getFields()[nCount];
+}
+
+void OSelectionBrowseBox::DeleteFields(const OUString& rAliasName)
+{
+ if (getFields().empty())
+ return;
+
+ sal_uInt16 nColId = GetCurColumnId();
+ sal_uInt32 nRow = GetCurRow();
+
+ bool bWasEditing = IsEditing();
+ if (bWasEditing)
+ DeactivateCell();
+
+ auto aIter = std::find_if(getFields().rbegin(), getFields().rend(),
+ [&rAliasName](const OTableFieldDescRef pEntry) { return pEntry->GetAlias() == rAliasName; });
+ if (aIter != getFields().rend())
+ {
+ sal_uInt16 nPos = sal::static_int_cast<sal_uInt16>(std::distance(aIter, getFields().rend()));
+ RemoveField( GetColumnId( nPos ) );
+ }
+
+ if (bWasEditing)
+ ActivateCell(nRow , nColId);
+}
+
+void OSelectionBrowseBox::SetColWidth(sal_uInt16 nColId, tools::Long nNewWidth)
+{
+ bool bWasEditing = IsEditing();
+ if (bWasEditing)
+ DeactivateCell();
+
+ // create the BaseClass
+ SetColumnWidth(nColId, nNewWidth);
+
+ // tell it the FieldDescription
+ OTableFieldDescRef pEntry = getEntry(GetColumnPos(nColId) - 1);
+ if (pEntry.is())
+ pEntry->SetColWidth(sal_uInt16(GetColumnWidth(nColId)));
+
+ if (bWasEditing)
+ ActivateCell(GetCurRow(), GetCurColumnId());
+}
+
+tools::Rectangle OSelectionBrowseBox::GetInvalidRect( sal_uInt16 nColId )
+{
+ // The rectangle is the full output area of the window
+ tools::Rectangle aInvalidRect( Point(0,0), GetOutputSizePixel() );
+
+ // now update the left side
+ tools::Rectangle aFieldRect(GetCellRect( 0, nColId )); // used instead of GetFieldRectPixel
+ aInvalidRect.SetLeft( aFieldRect.Left() );
+
+ return aInvalidRect;
+}
+
+void OSelectionBrowseBox::InsertColumn(const OTableFieldDescRef& pEntry, sal_uInt16& _nColumnPosition)
+{
+ // the control should have exactly one more column: the HandleColumn
+ OSL_ENSURE(_nColumnPosition == BROWSER_INVALIDID || (_nColumnPosition <= static_cast<tools::Long>(getFields().size())), "OSelectionBrowseBox::InsertColumn : invalid parameter nColId.");
+ // -1 means at the end. Count means at the end, others denotes a correct position
+
+ sal_uInt16 nCurCol = GetCurColumnId();
+ sal_Int32 nCurrentRow = GetCurRow();
+
+ DeactivateCell();
+
+ // remember the column id of the current position
+ sal_uInt16 nColumnId = GetColumnId(_nColumnPosition);
+ // put at the end of the list if too small or too big,
+ if ((_nColumnPosition == BROWSER_INVALIDID) || (_nColumnPosition >= getFields().size())) // append the field
+ {
+ if (FindFirstFreeCol(_nColumnPosition) == nullptr) // no more free columns
+ {
+ AppendNewCol();
+ _nColumnPosition = sal::static_int_cast< sal_uInt16 >(
+ getFields().size());
+ }
+ else
+ ++_nColumnPosition; // within the list
+ nColumnId = GetColumnId(_nColumnPosition);
+ pEntry->SetColumnId( nColumnId );
+ getFields()[ _nColumnPosition - 1] = pEntry;
+ }
+
+ // check if the column ids are identical, if not we have to move
+ if ( pEntry->GetColumnId() != nColumnId )
+ {
+ sal_uInt16 nOldPosition = GetColumnPos(pEntry->GetColumnId());
+ OSL_ENSURE( nOldPosition != 0,"Old position was 0. Not possible!");
+ SetColumnPos(pEntry->GetColumnId(),_nColumnPosition);
+ // we have to delete an empty field for the fields list, because the columns must have equal length
+ if ( nOldPosition > 0 && nOldPosition <= getFields().size() )
+ getFields()[nOldPosition - 1] = pEntry;
+
+ ColumnMoved(pEntry->GetColumnId(),false);
+ }
+
+ if ( pEntry->GetFunctionType() & FKT_AGGREGATE )
+ {
+ OUString sFunctionName = pEntry->GetFunction();
+ if ( GetFunctionName(sal_uInt32(-1),sFunctionName) )
+ pEntry->SetFunction(sFunctionName);
+ }
+
+ nColumnId = pEntry->GetColumnId();
+
+ SetColWidth(nColumnId,getDesignView()->getColWidth(GetColumnPos(nColumnId)-1));
+ // redraw
+ tools::Rectangle aInvalidRect = GetInvalidRect( nColumnId );
+ Invalidate( aInvalidRect );
+
+ ActivateCell( nCurrentRow, nCurCol );
+ static_cast<OQueryController&>(getDesignView()->getController()).setModified( true );
+
+ invalidateUndoRedo();
+}
+
+OTableFieldDescRef OSelectionBrowseBox::InsertField(const OJoinExchangeData& jxdSource)
+{
+ OQueryTableWindow* pSourceWin = static_cast<OQueryTableWindow*>(jxdSource.pListBox->GetTabWin());
+ if (!pSourceWin)
+ return nullptr;
+
+ // name and position of the selected field
+ weld::TreeView& rTreeView = jxdSource.pListBox->get_widget();
+ OUString aFieldName = rTreeView.get_text(jxdSource.nEntry);
+ sal_uInt32 nFieldIndex = jxdSource.nEntry;
+ OTableFieldInfo* pInf = weld::fromId<OTableFieldInfo*>(rTreeView.get_id(jxdSource.nEntry));
+
+ // construct DragInfo, such that I use the other InsertField
+ OTableFieldDescRef aInfo = new OTableFieldDesc(pSourceWin->GetTableName(),aFieldName);
+ aInfo->SetTabWindow(pSourceWin);
+ aInfo->SetFieldIndex(nFieldIndex);
+ aInfo->SetFieldType(pInf->GetKeyType());
+ aInfo->SetAlias(pSourceWin->GetAliasName());
+
+ aInfo->SetDataType(pInf->GetDataType());
+ aInfo->SetVisible();
+
+ return InsertField(aInfo);
+}
+
+OTableFieldDescRef OSelectionBrowseBox::InsertField(const OTableFieldDescRef& _rInfo, sal_uInt16 _nColumnPosition, bool bVis, bool bActivate)
+{
+
+ if(m_nMaxColumns && m_nMaxColumns <= FieldsCount())
+ return nullptr;
+ if (bActivate)
+ SaveModified();
+
+ // new column description
+ OTableFieldDescRef pEntry = _rInfo;
+ pEntry->SetVisible(bVis);
+
+ // insert column
+ InsertColumn( pEntry, _nColumnPosition );
+
+ if ( !m_bInUndoMode )
+ {
+ // trigger UndoAction
+ std::unique_ptr<OTabFieldCreateUndoAct> pUndoAction(new OTabFieldCreateUndoAct( this ));
+ pUndoAction->SetTabFieldDescr( pEntry );
+ pUndoAction->SetColumnPosition(_nColumnPosition);
+ getDesignView()->getController().addUndoActionAndInvalidate( std::move(pUndoAction) );
+ }
+
+ return pEntry;
+}
+
+sal_uInt16 OSelectionBrowseBox::FieldsCount()
+{
+ sal_uInt16 nCount = 0;
+ for (auto const& field : getFields())
+ {
+ if (field.is() && !field->IsEmpty())
+ ++nCount;
+ }
+
+ return nCount;
+}
+
+OTableFieldDescRef OSelectionBrowseBox::FindFirstFreeCol(sal_uInt16& _rColumnPosition )
+{
+
+ _rColumnPosition = BROWSER_INVALIDID;
+
+ for (auto const& field : getFields())
+ {
+ ++_rColumnPosition;
+ OTableFieldDescRef pEntry = field;
+ if ( pEntry.is() && pEntry->IsEmpty() )
+ return pEntry;
+ }
+
+ return nullptr;
+}
+
+void OSelectionBrowseBox::CheckFreeColumns(sal_uInt16& _rColumnPosition)
+{
+ if (FindFirstFreeCol(_rColumnPosition) == nullptr)
+ {
+ // it is full, so append a pack of columns
+ AppendNewCol(DEFAULT_QUERY_COLS);
+ OSL_VERIFY(FindFirstFreeCol(_rColumnPosition).is());
+ }
+}
+
+void OSelectionBrowseBox::AddGroupBy( const OTableFieldDescRef& rInfo )
+{
+ Reference< XConnection> xConnection = static_cast<OQueryController&>(getDesignView()->getController()).getConnection();
+ if(!xConnection.is())
+ return;
+ OSL_ENSURE(!rInfo->IsEmpty(),"AddGroupBy:: OTableFieldDescRef should not be empty!");
+ OTableFieldDescRef pEntry;
+ const Reference<XDatabaseMetaData> xMeta = xConnection->getMetaData();
+ const ::comphelper::UStringMixEqual bCase(xMeta.is() && xMeta->supportsMixedCaseQuotedIdentifiers());
+ //sal_Bool bAppend = sal_False;
+
+ bool bAllFieldsSearched = true;
+ for (auto const& field : getFields())
+ {
+ pEntry = field;
+ OSL_ENSURE(pEntry.is(),"OTableFieldDescRef was null!");
+
+ const OUString aField = pEntry->GetField();
+ const OUString aAlias = pEntry->GetAlias();
+
+ if (bCase(aField,rInfo->GetField()) &&
+ bCase(aAlias,rInfo->GetAlias()) &&
+ pEntry->GetFunctionType() == rInfo->GetFunctionType() &&
+ pEntry->GetFunction() == rInfo->GetFunction())
+ {
+ if ( pEntry->isNumericOrAggregateFunction() && rInfo->IsGroupBy() )
+ {
+ pEntry->SetGroupBy(false);
+ // we do want to consider that bAllFieldsSearched still true here
+ // bAllFieldsSearched = false;
+ break;
+ }
+ else
+ {
+ if ( !pEntry->IsGroupBy() && !pEntry->HasCriteria() ) // here we have a where condition which is no having clause
+ {
+ pEntry->SetGroupBy(rInfo->IsGroupBy());
+ if(!m_bGroupByUnRelated && pEntry->IsGroupBy())
+ pEntry->SetVisible();
+ bAllFieldsSearched = false;
+ break;
+ }
+ }
+
+ }
+ }
+
+ if (bAllFieldsSearched)
+ {
+ OTableFieldDescRef pTmp = InsertField(rInfo, BROWSER_INVALIDID, false, false );
+ if ( pTmp->isNumericOrAggregateFunction() && rInfo->IsGroupBy() ) // the GroupBy is inherited from rInfo
+ pTmp->SetGroupBy(false);
+ }
+}
+
+void OSelectionBrowseBox::DuplicateConditionLevel( const sal_uInt16 nLevel)
+{
+ const sal_uInt16 nNewLevel = nLevel +1;
+ for (auto const& field : getFields())
+ {
+ const OTableFieldDescRef& pEntry = field;
+ OUString sValue = pEntry->GetCriteria(nLevel);
+ if ( !sValue.isEmpty() )
+ {
+ pEntry->SetCriteria( nNewLevel, sValue);
+ if ( nNewLevel == (m_nVisibleCount-BROW_CRIT1_ROW-1) )
+ {
+ RowInserted( GetRowCount()-1 );
+ m_bVisibleRow.push_back(true);
+ ++m_nVisibleCount;
+ }
+ m_bVisibleRow[BROW_CRIT1_ROW + nNewLevel] = true;
+ }
+ }
+}
+
+void OSelectionBrowseBox::AddCondition( const OTableFieldDescRef& rInfo, const OUString& rValue, const sal_uInt16 nLevel,bool _bAddOrOnOneLine )
+{
+ Reference< XConnection> xConnection = static_cast<OQueryController&>(getDesignView()->getController()).getConnection();
+ if(!xConnection.is())
+ return;
+ OSL_ENSURE(rInfo.is() && !rInfo->IsEmpty(),"AddCondition:: OTableFieldDescRef should not be Empty!");
+
+ OTableFieldDescRef pLastEntry;
+ Reference<XDatabaseMetaData> xMeta = xConnection->getMetaData();
+ ::comphelper::UStringMixEqual bCase(xMeta.is() && xMeta->supportsMixedCaseQuotedIdentifiers());
+
+ bool bAllFieldsSearched = true;
+ for (auto const& field : getFields())
+ {
+ const OTableFieldDescRef& pEntry = field;
+ const OUString aField = pEntry->GetField();
+ const OUString aAlias = pEntry->GetAlias();
+
+ if (bCase(aField,rInfo->GetField()) &&
+ bCase(aAlias,rInfo->GetAlias()) &&
+ pEntry->GetFunctionType() == rInfo->GetFunctionType() &&
+ pEntry->GetFunction() == rInfo->GetFunction() &&
+ pEntry->IsGroupBy() == rInfo->IsGroupBy() )
+ {
+ if ( pEntry->isNumericOrAggregateFunction() && rInfo->IsGroupBy() )
+ pEntry->SetGroupBy(false);
+ else
+ {
+ if(!m_bGroupByUnRelated && pEntry->IsGroupBy())
+ pEntry->SetVisible();
+ }
+ if (pEntry->GetCriteria(nLevel).isEmpty() )
+ {
+ pEntry->SetCriteria( nLevel, rValue);
+ if(nLevel == (m_nVisibleCount-BROW_CRIT1_ROW-1))
+ {
+ RowInserted( GetRowCount()-1 );
+ m_bVisibleRow.push_back(true);
+ ++m_nVisibleCount;
+ }
+ m_bVisibleRow[BROW_CRIT1_ROW + nLevel] = true;
+ bAllFieldsSearched = false;
+ break;
+ }
+ if ( _bAddOrOnOneLine )
+ {
+ pLastEntry = pEntry;
+ }
+ }
+ }
+ if ( pLastEntry.is() )
+ {
+ OUString sCriteria = rValue;
+ OUString sOldCriteria = pLastEntry->GetCriteria( nLevel );
+ if ( !sOldCriteria.isEmpty() )
+ {
+ sCriteria = "( " + sOldCriteria + " OR " + rValue + " )";
+ }
+ pLastEntry->SetCriteria( nLevel, sCriteria);
+ if(nLevel == (m_nVisibleCount-BROW_CRIT1_ROW-1))
+ {
+ RowInserted( GetRowCount()-1 );
+ m_bVisibleRow.push_back(true);
+ ++m_nVisibleCount;
+ }
+ m_bVisibleRow[BROW_CRIT1_ROW + nLevel] = true;
+ }
+ else if (bAllFieldsSearched)
+ {
+ OTableFieldDescRef pTmp = InsertField(rInfo, BROWSER_INVALIDID, false, false );
+ if ( pTmp->isNumericOrAggregateFunction() && rInfo->IsGroupBy() ) // the GroupBy was inherited from rInfo
+ pTmp->SetGroupBy(false);
+ if ( pTmp.is() )
+ {
+ pTmp->SetCriteria( nLevel, rValue);
+ if(nLevel == (m_nVisibleCount-BROW_CRIT1_ROW-1))
+ {
+ RowInserted( GetRowCount()-1 );
+ m_bVisibleRow.push_back(true);
+ ++m_nVisibleCount;
+ }
+ }
+ }
+}
+
+void OSelectionBrowseBox::AddOrder( const OTableFieldDescRef& rInfo, const EOrderDir eDir, sal_uInt32 _nCurrentPos)
+{
+ if (_nCurrentPos == 0)
+ m_nLastSortColumn = SORT_COLUMN_NONE;
+
+ Reference< XConnection> xConnection = static_cast<OQueryController&>(getDesignView()->getController()).getConnection();
+ if(!xConnection.is())
+ return;
+ OSL_ENSURE(!rInfo->IsEmpty(),"AddOrder:: OTableFieldDescRef should not be Empty!");
+ OTableFieldDescRef pEntry;
+ Reference<XDatabaseMetaData> xMeta = xConnection->getMetaData();
+ ::comphelper::UStringMixEqual bCase(xMeta.is() && xMeta->supportsMixedCaseQuotedIdentifiers());
+
+ bool bAppend = false;
+ sal_uInt32 nPos = 0;
+ bool bAllFieldsSearched = true;
+ for (auto const& field : getFields())
+ {
+ pEntry = field;
+ OUString aField = pEntry->GetField();
+ OUString aAlias = pEntry->GetAlias();
+
+ if (bCase(aField,rInfo->GetField()) &&
+ bCase(aAlias,rInfo->GetAlias()))
+ {
+ bAppend = (m_nLastSortColumn != SORT_COLUMN_NONE) && (nPos <= m_nLastSortColumn);
+ if ( bAppend )
+ {
+ // we do want to consider that bAllFieldsSearched still true here
+ // bAllFieldsSearched = false;
+ break;
+ }
+ else
+ {
+ if ( !m_bOrderByUnRelated )
+ pEntry->SetVisible();
+ pEntry->SetOrderDir( eDir );
+ m_nLastSortColumn = nPos;
+ }
+ bAllFieldsSearched = false;
+ break;
+ }
+ ++nPos;
+ }
+
+ if (bAllFieldsSearched)
+ {
+ OTableFieldDescRef pTmp = InsertField(rInfo, BROWSER_INVALIDID, false, false );
+ if(pTmp.is())
+ {
+ m_nLastSortColumn = pTmp->GetColumnId() - 1;
+ if ( !m_bOrderByUnRelated && !bAppend )
+ pTmp->SetVisible();
+ pTmp->SetOrderDir( eDir );
+ }
+ }
+}
+
+bool OSelectionBrowseBox::Save()
+{
+ bool bRet = true;
+ if (IsModified())
+ bRet = SaveModified();
+ return bRet;
+}
+
+void OSelectionBrowseBox::CellModified()
+{
+ sal_Int32 nRow = GetRealRow(GetCurRow());
+ switch (nRow)
+ {
+ case BROW_VIS_ROW:
+ {
+ OTableFieldDescRef pEntry = getEntry(GetColumnPos(GetCurColumnId()) - 1);
+
+ weld::ComboBox& rComboBox = m_pOrderCell->get_widget();
+ sal_Int32 nIdx = rComboBox.get_active();
+ if(!m_bOrderByUnRelated && nIdx > 0 &&
+ nIdx != -1 &&
+ !pEntry->IsEmpty() &&
+ pEntry->GetOrderDir() != ORDER_NONE)
+ {
+ m_pVisibleCell->GetBox().set_active(true);
+ pEntry->SetVisible();
+ }
+ else
+ pEntry->SetVisible(m_pVisibleCell->GetBox().get_active());
+ }
+ break;
+ }
+ static_cast<OQueryController&>(getDesignView()->getController()).setModified( true );
+}
+
+void OSelectionBrowseBox::Fill()
+{
+ OSL_ENSURE(ColCount() >= 1, "OSelectionBrowseBox::Fill : please call only after inserting the handle column !");
+
+ sal_uInt16 nColCount = ColCount() - 1;
+ if (nColCount < DEFAULT_QUERY_COLS)
+ AppendNewCol(DEFAULT_QUERY_COLS - nColCount);
+}
+
+Size OSelectionBrowseBox::CalcOptimalSize( const Size& _rAvailable )
+{
+ Size aReturn( _rAvailable.Width(), GetTitleHeight() );
+
+ aReturn.AdjustHeight(( m_nVisibleCount ? m_nVisibleCount : 15 ) * GetDataRowHeight() );
+ aReturn.AdjustHeight(40 ); // just some space
+
+ return aReturn;
+}
+
+void OSelectionBrowseBox::Command(const CommandEvent& rEvt)
+{
+ switch (rEvt.GetCommand())
+ {
+ case CommandEventId::ContextMenu:
+ {
+ Point aMenuPos( rEvt.GetMousePosPixel() );
+
+ if (!rEvt.IsMouseEvent())
+ {
+ if ( 1 == GetSelectColumnCount() )
+ {
+ sal_uInt16 nSelId = GetColumnId(
+ sal::static_int_cast< sal_uInt16 >(
+ FirstSelectedColumn() ) );
+ ::tools::Rectangle aColRect( GetFieldRectPixel( 0, nSelId, false ) );
+
+ aMenuPos = aColRect.TopCenter();
+ }
+ else
+ {
+ EditBrowseBox::Command(rEvt);
+ return;
+ }
+ }
+
+ sal_uInt16 nColId = GetColumnId(GetColumnAtXPosPixel( aMenuPos.X() ));
+ sal_Int32 nRow = GetRowAtYPosPixel( aMenuPos.Y() );
+
+ if (nRow < 0 && nColId > HANDLE_ID )
+ {
+ if ( !IsColumnSelected( nColId ) )
+ {
+ adjustSelectionMode( true /* clicked onto a header */ , false /* not onto the handle col */ );
+ SelectColumnId( nColId );
+ }
+
+ if (!static_cast<OQueryController&>(getDesignView()->getController()).isReadOnly())
+ {
+ ::tools::Rectangle aRect(aMenuPos, Size(1, 1));
+ weld::Window* pPopupParent = weld::GetPopupParent(*this, aRect);
+ std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(pPopupParent, "dbaccess/ui/querycolmenu.ui"));
+ std::unique_ptr<weld::Menu> xContextMenu(xBuilder->weld_menu("menu"));
+ OString sIdent = xContextMenu->popup_at_rect(pPopupParent, aRect);
+ if (sIdent == "delete")
+ RemoveField(nColId);
+ else if (sIdent == "width")
+ adjustBrowseBoxColumnWidth( this, nColId );
+ }
+ }
+ else if(nRow >= 0 && nColId <= HANDLE_ID)
+ {
+ if (!static_cast<OQueryController&>(getDesignView()->getController()).isReadOnly())
+ {
+ ::tools::Rectangle aRect(aMenuPos, Size(1, 1));
+ weld::Window* pPopupParent = weld::GetPopupParent(*this, aRect);
+ std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(pPopupParent, "dbaccess/ui/queryfuncmenu.ui"));
+ std::unique_ptr<weld::Menu> xContextMenu(xBuilder->weld_menu("menu"));
+ xContextMenu->set_active("functions", m_bVisibleRow[BROW_FUNCTION_ROW]);
+ xContextMenu->set_active("tablename", m_bVisibleRow[BROW_TABLE_ROW]);
+ xContextMenu->set_active("alias", m_bVisibleRow[BROW_COLUMNALIAS_ROW]);
+ xContextMenu->set_active("distinct", static_cast<OQueryController&>(getDesignView()->getController()).isDistinct());
+
+ OString sIdent = xContextMenu->popup_at_rect(pPopupParent, aRect);
+ if (sIdent == "functions")
+ {
+ SetRowVisible(BROW_FUNCTION_ROW, !IsRowVisible(BROW_FUNCTION_ROW));
+ static_cast<OQueryController&>(getDesignView()->getController()).InvalidateFeature( SID_QUERY_VIEW_FUNCTIONS );
+ }
+ else if (sIdent == "tablename")
+ {
+ SetRowVisible(BROW_TABLE_ROW, !IsRowVisible(BROW_TABLE_ROW));
+ static_cast<OQueryController&>(getDesignView()->getController()).InvalidateFeature( SID_QUERY_VIEW_TABLES );
+ }
+ else if (sIdent == "alias")
+ {
+ SetRowVisible(BROW_COLUMNALIAS_ROW, !IsRowVisible(BROW_COLUMNALIAS_ROW));
+ static_cast<OQueryController&>(getDesignView()->getController()).InvalidateFeature( SID_QUERY_VIEW_ALIASES );
+ }
+ else if (sIdent == "distinct")
+ {
+ static_cast<OQueryController&>(getDesignView()->getController()).setDistinct(!static_cast<OQueryController&>(getDesignView()->getController()).isDistinct());
+ static_cast<OQueryController&>(getDesignView()->getController()).setModified( true );
+ static_cast<OQueryController&>(getDesignView()->getController()).InvalidateFeature( SID_QUERY_DISTINCT_VALUES );
+ }
+
+ static_cast<OQueryController&>(getDesignView()->getController()).setModified( true );
+ }
+ }
+ else
+ {
+ EditBrowseBox::Command(rEvt);
+ return;
+ }
+
+ [[fallthrough]];
+ }
+ default:
+ EditBrowseBox::Command(rEvt);
+ }
+}
+
+bool OSelectionBrowseBox::IsRowVisible(sal_uInt16 _nWhich) const
+{
+ OSL_ENSURE(_nWhich<(m_bVisibleRow.size()), "OSelectionBrowseBox::IsRowVisible : invalid parameter !");
+ return m_bVisibleRow[_nWhich];
+}
+
+void OSelectionBrowseBox::SetRowVisible(sal_uInt16 _nWhich, bool _bVis)
+{
+ OSL_ENSURE(_nWhich<m_bVisibleRow.size(), "OSelectionBrowseBox::SetRowVisible : invalid parameter !");
+
+ bool bWasEditing = IsEditing();
+ if (bWasEditing)
+ DeactivateCell();
+
+ // do this before removing or inserting rows, as this triggers ActivateCell-calls, which rely on m_bVisibleRow
+ m_bVisibleRow[_nWhich] = !m_bVisibleRow[_nWhich];
+
+ tools::Long nId = GetBrowseRow(_nWhich);
+ if (_bVis)
+ {
+ RowInserted(nId);
+ ++m_nVisibleCount;
+ }
+ else
+ {
+ RowRemoved(nId);
+ --m_nVisibleCount;
+ }
+
+ if (bWasEditing)
+ ActivateCell();
+}
+
+sal_Int32 OSelectionBrowseBox::GetBrowseRow(sal_Int32 nRowId) const
+{
+ sal_Int32 nCount(0);
+ for(sal_Int32 i = 0 ; i < nRowId ; ++i)
+ {
+ if ( m_bVisibleRow[i] )
+ ++nCount;
+ }
+ return nCount;
+}
+
+sal_Int32 OSelectionBrowseBox::GetRealRow(sal_Int32 nRowId) const
+{
+ sal_Int32 nErg=0,i;
+ const sal_Int32 nCount = m_bVisibleRow.size();
+ for(i=0;i < nCount; ++i)
+ {
+ if(m_bVisibleRow[i] && nErg++ == nRowId)
+ break;
+ }
+ OSL_ENSURE(nErg <= tools::Long(m_bVisibleRow.size()),"nErg cannot be greater than BROW_ROW_CNT!");
+ return i;
+}
+
+const tools::Long nVisibleRowMask[] =
+ {
+ 0x0001,
+ 0x0002,
+ 0x0004,
+ 0x0008,
+ 0x0010,
+ 0x0020,
+ 0x0040,
+ 0x0080,
+ 0x0100,
+ 0x0200,
+ 0x0400,
+ 0x0800
+ };
+sal_Int32 OSelectionBrowseBox::GetNoneVisibleRows() const
+{
+ sal_Int32 nErg(0);
+ // only the first 11 rows are interesting
+ sal_Int32 const nSize = SAL_N_ELEMENTS(nVisibleRowMask);
+ for(sal_Int32 i=0;i<nSize;i++)
+ {
+ if(!m_bVisibleRow[i])
+ nErg |= nVisibleRowMask[i];
+ }
+ return nErg;
+}
+
+void OSelectionBrowseBox::SetNoneVisibleRow(sal_Int32 nRows)
+{
+ // only the first 11 rows are interesting
+ sal_Int32 const nSize = SAL_N_ELEMENTS(nVisibleRowMask);
+ for(sal_Int32 i=0;i< nSize;i++)
+ m_bVisibleRow[i] = !(nRows & nVisibleRowMask[i]);
+}
+
+OUString OSelectionBrowseBox::GetCellText(sal_Int32 nRow, sal_uInt16 nColId) const
+{
+
+ sal_uInt16 nPos = GetColumnPos(nColId);
+ if ( nPos == 0 || nPos == BROWSER_INVALIDID || nPos > getFields().size() )
+ return OUString();
+
+ OTableFieldDescRef pEntry = getFields()[nPos-1];
+ OSL_ENSURE(pEntry != nullptr, "OSelectionBrowseBox::GetCellText : invalid column id, prepare for GPF ... ");
+ if ( pEntry->IsEmpty() )
+ return OUString();
+
+ OUString aText;
+ switch (nRow)
+ {
+ case BROW_TABLE_ROW:
+ aText = pEntry->GetAlias();
+ break;
+ case BROW_FIELD_ROW:
+ {
+ OUString aField = pEntry->GetField();
+ if (!aField.isEmpty() && aField[0] == '*') // * replace with alias.*
+ {
+ aField = pEntry->GetAlias();
+ if(!aField.isEmpty())
+ aField += ".";
+ aField += "*";
+ }
+ aText = aField;
+ } break;
+ case BROW_ORDER_ROW:
+ if (pEntry->GetOrderDir() != ORDER_NONE)
+ aText = DBA_RES(STR_QUERY_SORTTEXT).getToken(sal::static_int_cast< sal_uInt16 >(pEntry->GetOrderDir()), ';');
+ break;
+ case BROW_VIS_ROW:
+ break;
+ case BROW_COLUMNALIAS_ROW:
+ aText = pEntry->GetFieldAlias();
+ break;
+ case BROW_FUNCTION_ROW:
+ // we always show the group function at first
+ if ( pEntry->IsGroupBy() )
+ aText = m_aFunctionStrings.copy(m_aFunctionStrings.lastIndexOf(';')+1);
+ else if ( pEntry->isNumericOrAggregateFunction() )
+ aText = pEntry->GetFunction();
+ break;
+ default:
+ aText = pEntry->GetCriteria(sal_uInt16(nRow - BROW_CRIT1_ROW));
+ }
+ return aText;
+}
+
+bool OSelectionBrowseBox::GetFunctionName(sal_uInt32 _nFunctionTokenId, OUString& rFkt)
+{
+ weld::ComboBox& rComboBox = m_pFunctionCell->get_widget();
+ switch(_nFunctionTokenId)
+ {
+ case SQL_TOKEN_COUNT:
+ rFkt = (rComboBox.get_count() < 3) ? rComboBox.get_text(1) : rComboBox.get_text(2);
+ break;
+ case SQL_TOKEN_AVG:
+ rFkt = rComboBox.get_text(1);
+ break;
+ case SQL_TOKEN_MAX:
+ rFkt = rComboBox.get_text(3);
+ break;
+ case SQL_TOKEN_MIN:
+ rFkt = rComboBox.get_text(4);
+ break;
+ case SQL_TOKEN_SUM:
+ rFkt = rComboBox.get_text(5);
+ break;
+ case SQL_TOKEN_EVERY:
+ rFkt = rComboBox.get_text(6);
+ break;
+ case SQL_TOKEN_ANY:
+ rFkt = rComboBox.get_text(7);
+ break;
+ case SQL_TOKEN_SOME:
+ rFkt = rComboBox.get_text(8);
+ break;
+ case SQL_TOKEN_STDDEV_POP:
+ rFkt = rComboBox.get_text(9);
+ break;
+ case SQL_TOKEN_STDDEV_SAMP:
+ rFkt = rComboBox.get_text(10);
+ break;
+ case SQL_TOKEN_VAR_SAMP:
+ rFkt = rComboBox.get_text(11);
+ break;
+ case SQL_TOKEN_VAR_POP:
+ rFkt = rComboBox.get_text(12);
+ break;
+ case SQL_TOKEN_COLLECT:
+ rFkt = rComboBox.get_text(13);
+ break;
+ case SQL_TOKEN_FUSION:
+ rFkt = rComboBox.get_text(14);
+ break;
+ case SQL_TOKEN_INTERSECTION:
+ rFkt = rComboBox.get_text(15);
+ break;
+ default:
+ {
+ const sal_Int32 nStopIdx = m_aFunctionStrings.lastIndexOf(';'); // grouping is not counted
+ for (sal_Int32 nIdx {0}; nIdx<nStopIdx;)
+ {
+ const OUString sFunc {m_aFunctionStrings.getToken(0, ';', nIdx)};
+ if (rFkt.equalsIgnoreAsciiCase(sFunc))
+ {
+ rFkt = sFunc;
+ return true;
+ }
+ }
+ return false;
+ }
+ }
+
+ return true;
+}
+
+OUString OSelectionBrowseBox::GetCellContents(sal_Int32 nCellIndex, sal_uInt16 nColId)
+{
+ if ( GetCurColumnId() == nColId && !m_bInUndoMode )
+ SaveModified();
+
+ sal_uInt16 nPos = GetColumnPos(nColId);
+ OTableFieldDescRef pEntry = getFields()[nPos - 1];
+ OSL_ENSURE(pEntry != nullptr, "OSelectionBrowseBox::GetCellContents : invalid column id, prepare for GPF ... ");
+
+ switch (nCellIndex)
+ {
+ case BROW_VIS_ROW :
+ return OUString(pEntry->IsVisible() ? std::u16string_view(u"1") : std::u16string_view(u"0"));
+ case BROW_ORDER_ROW:
+ {
+ sal_Int32 nIdx = m_pOrderCell->get_widget().get_active();
+ if (nIdx == -1)
+ nIdx = 0;
+ return OUString::number(nIdx);
+ }
+ default:
+ return GetCellText(nCellIndex, nColId);
+ }
+}
+
+void OSelectionBrowseBox::SetCellContents(sal_Int32 nRow, sal_uInt16 nColId, const OUString& strNewText)
+{
+ bool bWasEditing = IsEditing() && (GetCurColumnId() == nColId) && IsRowVisible(static_cast<sal_uInt16>(nRow)) && (GetCurRow() == static_cast<sal_uInt16>(GetBrowseRow(nRow)));
+ if (bWasEditing)
+ DeactivateCell();
+
+ sal_uInt16 nPos = GetColumnPos(nColId);
+ OTableFieldDescRef pEntry = getEntry(nPos - 1);
+ OSL_ENSURE(pEntry != nullptr, "OSelectionBrowseBox::SetCellContents : invalid column id, prepare for GPF ... ");
+
+ switch (nRow)
+ {
+ case BROW_VIS_ROW:
+ pEntry->SetVisible(strNewText == "1");
+ break;
+ case BROW_FIELD_ROW:
+ pEntry->SetField(strNewText);
+ break;
+ case BROW_TABLE_ROW:
+ pEntry->SetAlias(strNewText);
+ break;
+ case BROW_ORDER_ROW:
+ {
+ sal_uInt16 nIdx = static_cast<sal_uInt16>(strNewText.toInt32());
+ pEntry->SetOrderDir(EOrderDir(nIdx));
+ } break;
+ case BROW_COLUMNALIAS_ROW:
+ pEntry->SetFieldAlias(strNewText);
+ break;
+ case BROW_FUNCTION_ROW:
+ {
+ std::u16string_view sGroupFunctionName = m_aFunctionStrings.subView(m_aFunctionStrings.lastIndexOf(';')+1);
+ pEntry->SetFunction(strNewText);
+ // first reset this two member
+ sal_Int32 nFunctionType = pEntry->GetFunctionType();
+ nFunctionType &= ~FKT_AGGREGATE;
+ pEntry->SetFunctionType(nFunctionType);
+ if ( pEntry->IsGroupBy() && !o3tl::equalsIgnoreAsciiCase(sGroupFunctionName, strNewText) )
+ pEntry->SetGroupBy(false);
+
+ if ( o3tl::equalsIgnoreAsciiCase(sGroupFunctionName, strNewText) )
+ pEntry->SetGroupBy(true);
+ else if ( !strNewText.isEmpty() )
+ {
+ nFunctionType |= FKT_AGGREGATE;
+ pEntry->SetFunctionType(nFunctionType);
+ }
+ } break;
+ default:
+ pEntry->SetCriteria(sal_uInt16(nRow - BROW_CRIT1_ROW), strNewText);
+ }
+
+ tools::Long nCellIndex = GetRealRow(nRow);
+ if(IsRowVisible(static_cast<sal_uInt16>(nRow)))
+ RowModified(nCellIndex, nColId);
+
+ // the appropriate field-description is now empty -> set Visible to sal_False (now it is consistent to normal empty rows)
+ if (pEntry->IsEmpty())
+ pEntry->SetVisible(false);
+
+ if (bWasEditing)
+ ActivateCell(nCellIndex, nColId);
+
+ static_cast<OQueryController&>(getDesignView()->getController()).setModified( true );
+}
+
+void OSelectionBrowseBox::ColumnResized(sal_uInt16 nColId)
+{
+ if (static_cast<OQueryController&>(getDesignView()->getController()).isReadOnly())
+ return;
+ // The resizing of columns can't be suppressed (BrowseBox doesn't support that) so we have to do this
+ // fake. It's not _that_ bad : the user may change column widths while in read-only mode to see all details
+ // but the changes aren't permanent ...
+
+ sal_uInt16 nPos = GetColumnPos(nColId);
+ OSL_ENSURE(nPos <= getFields().size(),"ColumnResized:: nColId should not be greater than List::count!");
+ OTableFieldDescRef pEntry = getEntry(nPos-1);
+ OSL_ENSURE(pEntry.is(), "OSelectionBrowseBox::ColumnResized : invalid FieldDescription !");
+ static_cast<OQueryController&>(getDesignView()->getController()).setModified( true );
+ EditBrowseBox::ColumnResized(nColId);
+
+ if ( pEntry.is())
+ {
+ if ( !m_bInUndoMode )
+ {
+ // create the undo action
+ std::unique_ptr<OTabFieldSizedUndoAct> pUndo(new OTabFieldSizedUndoAct(this));
+ pUndo->SetColumnPosition( nPos );
+ pUndo->SetOriginalWidth(pEntry->GetColWidth());
+ getDesignView()->getController().addUndoActionAndInvalidate(std::move(pUndo));
+ }
+ pEntry->SetColWidth(sal_uInt16(GetColumnWidth(nColId)));
+ }
+}
+
+sal_uInt32 OSelectionBrowseBox::GetTotalCellWidth(sal_Int32 nRowId, sal_uInt16 nColId)
+{
+ sal_uInt16 nPos = GetColumnPos(nColId);
+ OSL_ENSURE((nPos == 0) || (nPos <= getFields().size()), "OSelectionBrowseBox::GetTotalCellWidth : invalid parameter nColId");
+
+ OTableFieldDescRef pEntry = getFields()[nPos-1];
+ OSL_ENSURE(pEntry.is(), "OSelectionBrowseBox::GetTotalCellWidth : invalid FieldDescription !");
+
+ sal_Int32 nRow = GetRealRow(nRowId);
+ OUString strText(GetCellText(nRow, nColId));
+ return GetDataWindow().LogicToPixel(Size(GetDataWindow().GetTextWidth(strText),0)).Width();
+}
+
+bool OSelectionBrowseBox::isCutAllowed() const
+{
+ bool bCutAllowed = false;
+ sal_Int32 nRow = GetRealRow(GetCurRow());
+ switch (nRow)
+ {
+ case BROW_VIS_ROW:
+ case BROW_ORDER_ROW:
+ case BROW_TABLE_ROW:
+ case BROW_FUNCTION_ROW:
+ break;
+ case BROW_FIELD_ROW:
+ {
+ weld::ComboBox& rComboBox = m_pFieldCell->get_widget();
+ int nStartPos, nEndPos;
+ bCutAllowed = rComboBox.get_entry_selection_bounds(nStartPos, nEndPos);
+ break;
+ }
+ default:
+ {
+ weld::Entry& rEntry = m_pTextCell->get_widget();
+ int nStartPos, nEndPos;
+ bCutAllowed = rEntry.get_selection_bounds(nStartPos, nEndPos);
+ break;
+ }
+ }
+ return bCutAllowed;
+}
+
+void OSelectionBrowseBox::cut()
+{
+ sal_Int32 nRow = GetRealRow(GetCurRow());
+ switch (nRow)
+ {
+ case BROW_FIELD_ROW:
+ {
+ weld::ComboBox& rComboBox = m_pFieldCell->get_widget();
+ rComboBox.cut_entry_clipboard();
+ break;
+ }
+ default:
+ {
+ weld::Entry& rEntry = m_pTextCell->get_widget();
+ rEntry.cut_clipboard();
+ }
+ }
+ SaveModified();
+ RowModified(GetBrowseRow(nRow), GetCurColumnId());
+
+ invalidateUndoRedo();
+}
+
+void OSelectionBrowseBox::paste()
+{
+ sal_Int32 nRow = GetRealRow(GetCurRow());
+ switch (nRow)
+ {
+ case BROW_FIELD_ROW:
+ {
+ weld::ComboBox& rComboBox = m_pFieldCell->get_widget();
+ rComboBox.paste_entry_clipboard();
+ break;
+ }
+ default:
+ {
+ weld::Entry& rEntry = m_pTextCell->get_widget();
+ rEntry.paste_clipboard();
+ break;
+ }
+ }
+ RowModified(GetBrowseRow(nRow), GetCurColumnId());
+ invalidateUndoRedo();
+}
+
+bool OSelectionBrowseBox::isPasteAllowed() const
+{
+ bool bPasteAllowed = true;
+ sal_Int32 nRow = GetRealRow(GetCurRow());
+ switch (nRow)
+ {
+ case BROW_VIS_ROW:
+ case BROW_ORDER_ROW:
+ case BROW_TABLE_ROW:
+ case BROW_FUNCTION_ROW:
+ bPasteAllowed = false;
+ break;
+ }
+ return bPasteAllowed;
+}
+
+bool OSelectionBrowseBox::isCopyAllowed() const
+{
+ return isCutAllowed();
+}
+
+void OSelectionBrowseBox::copy()
+{
+ sal_Int32 nRow = GetRealRow(GetCurRow());
+ switch (nRow)
+ {
+ case BROW_FIELD_ROW:
+ {
+ weld::ComboBox& rComboBox = m_pFieldCell->get_widget();
+ rComboBox.copy_entry_clipboard();
+ break;
+ }
+ default:
+ {
+ weld::Entry& rEntry = m_pTextCell->get_widget();
+ rEntry.copy_clipboard();
+ break;
+ }
+ }
+}
+
+void OSelectionBrowseBox::appendUndoAction(const OUString& _rOldValue, std::u16string_view _rNewValue, sal_Int32 _nRow, bool& _bListAction)
+{
+ if ( !m_bInUndoMode && _rNewValue != _rOldValue )
+ {
+ if ( !_bListAction )
+ {
+ _bListAction = true;
+ static_cast<OQueryController&>(getDesignView()->getController()).GetUndoManager().EnterListAction(OUString(),OUString(),0,ViewShellId(-1));
+ }
+ appendUndoAction(_rOldValue,_rNewValue,_nRow);
+ }
+}
+
+void OSelectionBrowseBox::appendUndoAction(const OUString& _rOldValue,std::u16string_view _rNewValue,sal_Int32 _nRow)
+{
+ if ( !m_bInUndoMode && _rNewValue != _rOldValue )
+ {
+ std::unique_ptr<OTabFieldCellModifiedUndoAct> pUndoAct(new OTabFieldCellModifiedUndoAct(this));
+ pUndoAct->SetCellIndex(_nRow);
+ OSL_ENSURE(GetColumnPos(GetCurColumnId()) != BROWSER_INVALIDID,"Current position isn't valid!");
+ pUndoAct->SetColumnPosition( GetColumnPos(GetCurColumnId()) );
+ pUndoAct->SetCellContents(_rOldValue);
+ getDesignView()->getController().addUndoActionAndInvalidate(std::move(pUndoAct));
+ }
+}
+
+IMPL_LINK_NOARG(OSelectionBrowseBox, OnInvalidateTimer, Timer *, void)
+{
+ static_cast<OQueryController&>(getDesignView()->getController()).InvalidateFeature(SID_CUT);
+ static_cast<OQueryController&>(getDesignView()->getController()).InvalidateFeature(SID_COPY);
+ static_cast<OQueryController&>(getDesignView()->getController()).InvalidateFeature(SID_PASTE);
+ if(!m_bStopTimer)
+ m_timerInvalidate.Start();
+}
+
+void OSelectionBrowseBox::stopTimer()
+{
+ m_bStopTimer = true;
+ if (m_timerInvalidate.IsActive())
+ m_timerInvalidate.Stop();
+}
+
+void OSelectionBrowseBox::startTimer()
+{
+ m_bStopTimer = false;
+ if (!m_timerInvalidate.IsActive())
+ m_timerInvalidate.Start();
+}
+
+OTableFields& OSelectionBrowseBox::getFields() const
+{
+ OQueryController& rController = static_cast<OQueryController&>(getDesignView()->getController());
+ return rController.getTableFieldDesc();
+}
+
+void OSelectionBrowseBox::enableControl(const OTableFieldDescRef& _rEntry,Window* _pControl)
+{
+ bool bEnable = !_rEntry->isCondition();
+ _pControl->Enable(bEnable);
+ _pControl->EnableInput(bEnable);
+}
+
+void OSelectionBrowseBox::setTextCellContext(const OTableFieldDescRef& _rEntry,const OUString& _sText,const OString& _sHelpId)
+{
+ weld::Entry& rEntry = m_pTextCell->get_widget();
+ rEntry.set_text(_sText);
+ rEntry.save_value();
+ if (!m_pTextCell->HasFocus())
+ m_pTextCell->GrabFocus();
+
+ enableControl(_rEntry,m_pTextCell);
+
+ if (m_pTextCell->GetHelpId() != _sHelpId)
+ // as TextCell is used in various contexts I will delete the cached HelpText
+ m_pTextCell->SetHelpText(OUString());
+ m_pTextCell->SetHelpId(_sHelpId);
+}
+
+void OSelectionBrowseBox::invalidateUndoRedo()
+{
+ OQueryController& rController = static_cast<OQueryController&>(getDesignView()->getController());
+ rController.InvalidateFeature( ID_BROWSER_UNDO );
+ rController.InvalidateFeature( ID_BROWSER_REDO );
+ rController.InvalidateFeature( ID_BROWSER_QUERY_EXECUTE );
+}
+
+OTableFieldDescRef OSelectionBrowseBox::getEntry(OTableFields::size_type _nPos)
+{
+ // we have to check if we need a new entry at this position
+ OTableFields& aFields = getFields();
+ OSL_ENSURE(aFields.size() > _nPos,"ColID is to great!");
+
+ OTableFieldDescRef pEntry = aFields[_nPos];
+ OSL_ENSURE(pEntry.is(),"Invalid entry!");
+ if ( !pEntry.is() )
+ {
+ pEntry = new OTableFieldDesc();
+ pEntry->SetColumnId(
+ GetColumnId(sal::static_int_cast< sal_uInt16 >(_nPos+1)));
+ aFields[_nPos] = pEntry;
+ }
+ return pEntry;
+}
+
+void OSelectionBrowseBox::GetFocus()
+{
+ if(!IsEditing() && !m_bWasEditing)
+ ActivateCell();
+ EditBrowseBox::GetFocus();
+}
+
+void OSelectionBrowseBox::DeactivateCell(bool _bUpdate)
+{
+ m_bWasEditing = true;
+ EditBrowseBox::DeactivateCell(_bUpdate);
+ m_bWasEditing = false;
+}
+
+OUString OSelectionBrowseBox::GetRowDescription( sal_Int32 _nRow ) const
+{
+ OUString aLabel(DBA_RES(STR_QUERY_HANDLETEXT));
+
+ // from BROW_CRIT2_ROW onwards all rows are shown as "or"
+ sal_Int32 nToken = (_nRow >= GetBrowseRow(BROW_CRIT2_ROW))
+ ? BROW_CRIT2_ROW : GetRealRow(_nRow);
+ return aLabel.getToken(nToken, ';');
+}
+
+OUString OSelectionBrowseBox::GetAccessibleObjectName( AccessibleBrowseBoxObjType _eObjType,sal_Int32 _nPosition) const
+{
+ OUString sRetText;
+ switch( _eObjType )
+ {
+ case AccessibleBrowseBoxObjType::RowHeaderCell:
+ sRetText = GetRowDescription(_nPosition);
+ break;
+ default:
+ sRetText = EditBrowseBox::GetAccessibleObjectDescription(_eObjType,_nPosition);
+ }
+ return sRetText;
+}
+
+bool OSelectionBrowseBox::fillEntryTable(OTableFieldDescRef const & _pEntry,const OUString& _sTableName)
+{
+ bool bRet = false;
+ OJoinTableView::OTableWindowMap& rTabWinList = getDesignView()->getTableView()->GetTabWinMap();
+ OJoinTableView::OTableWindowMap::const_iterator aIter = rTabWinList.find(_sTableName);
+ if(aIter != rTabWinList.end())
+ {
+ OQueryTableWindow* pEntryTab = static_cast<OQueryTableWindow*>(aIter->second.get());
+ if (pEntryTab)
+ {
+ _pEntry->SetTable(pEntryTab->GetTableName());
+ _pEntry->SetTabWindow(pEntryTab);
+ bRet = true;
+ }
+ }
+ return bRet;
+}
+
+void OSelectionBrowseBox::setFunctionCell(OTableFieldDescRef const & _pEntry)
+{
+ Reference< XConnection> xConnection = static_cast<OQueryController&>(getDesignView()->getController()).getConnection();
+ if ( !xConnection.is() )
+ return;
+
+ // Aggregate functions in general only available with Core SQL
+ if ( lcl_SupportsCoreSQLGrammar(xConnection) )
+ {
+ sal_Int32 nIdx {0};
+ // if we have an asterisk, no other function than count is allowed
+ weld::ComboBox& rComboBox = m_pFunctionCell->get_widget();
+ rComboBox.clear();
+ rComboBox.append_text(m_aFunctionStrings.getToken(0, ';', nIdx));
+ if ( isFieldNameAsterisk(_pEntry->GetField()) )
+ rComboBox.append_text(m_aFunctionStrings.getToken(1, ';', nIdx)); // 2nd token: COUNT
+ else
+ {
+ const bool bSkipLastToken {_pEntry->isNumeric()};
+ while (nIdx>0)
+ {
+ const OUString sTok {m_aFunctionStrings.getToken(0, ';', nIdx)};
+ if (bSkipLastToken && nIdx<0)
+ break;
+ rComboBox.append_text(sTok);
+ }
+ }
+
+ if ( _pEntry->IsGroupBy() )
+ {
+ OSL_ENSURE(!_pEntry->isNumeric(),"Not allowed to combine group by and numeric values!");
+ rComboBox.set_active_text(rComboBox.get_text(rComboBox.get_count() - 1));
+ }
+ else if (rComboBox.find_text(_pEntry->GetFunction()) != -1)
+ rComboBox.set_active_text(_pEntry->GetFunction());
+ else
+ rComboBox.set_active(0);
+
+ enableControl(_pEntry, m_pFunctionCell);
+ }
+ else
+ {
+ // only COUNT(*) and COUNT("table".*) allowed
+ bool bCountRemoved = !isFieldNameAsterisk(_pEntry->GetField());
+ weld::ComboBox& rComboBox = m_pFunctionCell->get_widget();
+ if ( bCountRemoved )
+ rComboBox.remove(1);
+
+ if ( !bCountRemoved && rComboBox.get_count() < 2)
+ rComboBox.append_text(m_aFunctionStrings.getToken(2, ';')); // 2 -> COUNT
+
+ if (rComboBox.find_text(_pEntry->GetFunction()) != -1)
+ rComboBox.set_active_text(_pEntry->GetFunction());
+ else
+ rComboBox.set_active(0);
+ }
+}
+
+Reference< XAccessible > OSelectionBrowseBox::CreateAccessibleCell( sal_Int32 _nRow, sal_uInt16 _nColumnPos )
+{
+ OTableFieldDescRef pEntry;
+ if ( _nColumnPos != 0 && _nColumnPos != BROWSER_INVALIDID && _nColumnPos <= getFields().size() )
+ pEntry = getFields()[_nColumnPos - 1];
+
+ if ( _nRow == BROW_VIS_ROW && pEntry.is() )
+ return EditBrowseBox::CreateAccessibleCheckBoxCell( _nRow, _nColumnPos,pEntry->IsVisible() ? TRISTATE_TRUE : TRISTATE_FALSE );
+
+ return EditBrowseBox::CreateAccessibleCell( _nRow, _nColumnPos );
+}
+
+bool OSelectionBrowseBox::HasFieldByAliasName(std::u16string_view rFieldName, OTableFieldDescRef const & rInfo) const
+{
+ for (auto const& field : getFields())
+ {
+ if ( field->GetFieldAlias() == rFieldName )
+ {
+ *rInfo = *field;
+ return true;
+ }
+ }
+ return false;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/querydesign/SelectionBrowseBox.hxx b/dbaccess/source/ui/querydesign/SelectionBrowseBox.hxx
new file mode 100644
index 000000000..761870fb8
--- /dev/null
+++ b/dbaccess/source/ui/querydesign/SelectionBrowseBox.hxx
@@ -0,0 +1,324 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <sal/config.h>
+
+#include <string_view>
+
+#include <svtools/editbrowsebox.hxx>
+#include <TableFieldDescription.hxx>
+#include <TableWindowListBox.hxx>
+#include <QEnumTypes.hxx>
+#include <com/sun/star/sdbc/XConnection.hpp>
+
+namespace connectivity
+{
+ class OSQLParseNode;
+}
+
+namespace dbaui
+{
+#define BROW_FIELD_ROW 0
+#define BROW_COLUMNALIAS_ROW 1
+#define BROW_TABLE_ROW 2
+#define BROW_ORDER_ROW 3
+#define BROW_VIS_ROW 4
+#define BROW_FUNCTION_ROW 5
+#define BROW_CRIT1_ROW 6
+#define BROW_CRIT2_ROW 7
+#define BROW_CRIT3_ROW 8
+#define BROW_CRIT4_ROW 9
+#define BROW_CRIT5_ROW 10
+#define BROW_CRIT6_ROW 11
+#define BROW_ROW_CNT 12
+
+ class OQueryDesignView;
+ class OSelectionBrowseBox final : public ::svt::EditBrowseBox
+ {
+ friend class OQueryDesignView;
+ std::vector<bool> m_bVisibleRow; // at pos we find the RowId
+ Timer m_timerInvalidate;
+
+ sal_Int32 m_nSeekRow;
+ BrowserMode m_nMode; // remember the BrowseModes
+ VclPtr< ::svt::EditControl> m_pTextCell;
+ VclPtr< ::svt::CheckBoxControl> m_pVisibleCell;
+ VclPtr< ::svt::ComboBoxControl> m_pFieldCell;
+ VclPtr< ::svt::ListBoxControl> m_pFunctionCell;
+ VclPtr< ::svt::ListBoxControl> m_pTableCell;
+ VclPtr< ::svt::ListBoxControl> m_pOrderCell;
+
+ sal_Int32 m_nMaxColumns; // maximum number of columns in a Select-Statement
+
+ OUString m_aFunctionStrings;
+ sal_uInt16 m_nVisibleCount; // maximum number of visible rows
+ sal_uInt32 m_nLastSortColumn; // index of last (highest) sort column
+ bool m_bOrderByUnRelated;
+ bool m_bGroupByUnRelated;
+ bool m_bStopTimer;
+ bool m_bWasEditing;
+ bool m_bDisableErrorBox;
+ bool m_bInUndoMode;
+
+ DECL_LINK(OnInvalidateTimer, Timer*, void);
+ public:
+ explicit OSelectionBrowseBox( vcl::Window* pParent );
+ virtual ~OSelectionBrowseBox() override;
+ virtual void dispose() override;
+
+ void initialize();
+ OTableFieldDescRef InsertField( const OJoinExchangeData& jxdSource );
+ OTableFieldDescRef InsertField( const OTableFieldDescRef& rInfo, sal_uInt16 _nColumnPosition = BROWSER_INVALIDID, bool bVis=true, bool bActivate=true );
+ void InsertColumn( const OTableFieldDescRef& pEntry, sal_uInt16& _nColumnPosition );
+ void RemoveColumn( sal_uInt16 _nColumnId );
+ void DeleteFields( const OUString& rAliasName );
+
+ bool HasFieldByAliasName(std::u16string_view rFieldName, OTableFieldDescRef const & rInfo) const;
+
+ // AddGroupBy:: inserts a field with function == grouping. If the fields already exists and uses an aggregate function,
+ // the flag is not set
+ void AddGroupBy( const OTableFieldDescRef& rInfo );
+ void AddCondition( const OTableFieldDescRef& rInfo,
+ const OUString& rValue,
+ const sal_uInt16 nLevel,
+ bool _bAddOrOnOneLine );
+ void DuplicateConditionLevel( const sal_uInt16 nLevel);
+ void AddOrder(const OTableFieldDescRef& rInfo, const EOrderDir eDir, sal_uInt32 _nCurrentPos);
+ void ClearAll();
+ OTableFieldDescRef const & AppendNewCol( sal_uInt16 nCnt=1 );
+ bool Save();
+ OQueryDesignView* getDesignView();
+ OQueryDesignView* getDesignView() const;
+ sal_uInt16 FieldsCount();
+
+ void SetColWidth(sal_uInt16 nColId, tools::Long lNewWidth);
+ // unlike SetColumnWidth of the base class it checks an active cell in this column
+
+ OUString GetCellContents(sal_Int32 nCellIndex, sal_uInt16 nColId);
+ void SetCellContents(sal_Int32 nCellIndex, sal_uInt16 nColId, const OUString& strNewText);
+ // cell content (formatted as string) set/return
+ sal_Int32 GetNoneVisibleRows() const;
+ void SetNoneVisibleRow(sal_Int32 nRows);
+ bool IsRowVisible(sal_uInt16 _nWhich) const;
+ void SetRowVisible(sal_uInt16 _nWhich, bool _bVis);
+
+ void SetReadOnly(bool bRO);
+ // calculate an optimal size. Basically, this takes into account the number of visible rows.
+ Size CalcOptimalSize( const Size& _rAvailable );
+
+ // can the current content be cut
+ bool isPasteAllowed() const;
+ bool isCutAllowed() const;
+ bool isCopyAllowed() const;
+ void cut();
+ void paste();
+ void copy();
+
+ virtual void GetFocus() override;
+ virtual void DeactivateCell(bool bUpdate = true) override;
+ virtual void ColumnMoved( sal_uInt16 nColId ) override { ColumnMoved(nColId,true); }
+ void ColumnMoved( sal_uInt16 nColId, bool _bCreateUndo);
+
+ void Fill();
+ void PreFill();
+
+ /** Disables the generation of undo actions
+ */
+ void EnterUndoMode() { m_bInUndoMode = true; }
+ /** Enables the generation of undo actions
+ */
+ void LeaveUndoMode() { m_bInUndoMode = false; }
+
+ /** GetCellText returns the text at the given position
+ @param _nRow
+ the number of the row
+ @param _nColId
+ the ID of the column
+ @return
+ the text out of the cell
+ */
+ virtual OUString GetCellText(sal_Int32 _nRow, sal_uInt16 _nColId) const override;
+
+ /** returns the description of the row.
+ @param _nRow
+ The row number.
+ @return
+ The header text of the specified row.
+ */
+ virtual OUString GetRowDescription( sal_Int32 _nRow ) const override;
+
+ /** return the name of the specified object.
+ @param eObjType
+ The type to ask for
+ @param _nPosition
+ The position of a tablecell (index position), header bar column/row cell
+ @return
+ The name of the specified object.
+ */
+ virtual OUString GetAccessibleObjectName( AccessibleBrowseBoxObjType eObjType,sal_Int32 _nPosition = -1) const override;
+
+ // IAccessibleTableProvider
+ /** Creates the accessible object of a data table cell.
+ @param nRow The row index of the cell.
+ @param nColumnId The column ID of the cell.
+ @return The XAccessible interface of the specified cell. */
+ virtual css::uno::Reference< css::accessibility::XAccessible > CreateAccessibleCell( sal_Int32 nRow, sal_uInt16 nColumnId ) override;
+
+ private:
+ virtual bool SeekRow( sal_Int32 nRow ) override;
+
+ virtual void PaintStatusCell(OutputDevice& rDev, const tools::Rectangle& rRect) const override;
+ virtual void PaintCell(OutputDevice& rDev, const tools::Rectangle& rRect,
+ sal_uInt16 nColumnId ) const override;
+
+ virtual sal_Int8 AcceptDrop( const BrowserAcceptDropEvent& rEvt ) override;
+ virtual sal_Int8 ExecuteDrop( const BrowserExecuteDropEvent& rEvt ) override;
+ virtual void MouseButtonDown( const BrowserMouseEvent& rEvt ) override;
+ virtual void MouseButtonUp( const BrowserMouseEvent& rEvt ) override;
+ virtual void KeyInput( const KeyEvent& rEvt ) override;
+ virtual void Command(const CommandEvent& rEvt) override;
+
+ virtual ::svt::CellController* GetController(sal_Int32 nRow, sal_uInt16 nCol) override;
+ virtual void InitController(::svt::CellControllerRef& rController, sal_Int32 nRow, sal_uInt16 nCol) override;
+ virtual void CellModified() override;
+ virtual bool SaveModified() override;
+ virtual void Init() override;
+ virtual void ColumnResized( sal_uInt16 nColId ) override;
+
+ virtual sal_uInt32 GetTotalCellWidth(sal_Int32 nRow, sal_uInt16 nColId) override;
+
+ // if you want to have an own header ...
+ virtual VclPtr<BrowserHeader> imp_CreateHeaderBar(BrowseBox* pParent) override;
+
+ void stopTimer();
+ void startTimer();
+
+ OTableFieldDescRef FindFirstFreeCol(sal_uInt16& _rColumnPosition);
+
+ // rCol contains the number (in pOTableFieldDescList) of the first column, which itself tells it is empty
+ // if there are none, rCol is undefined and the returnvalue NULL
+ void CheckFreeColumns(sal_uInt16& _rColumnPosition);
+ // checks if empty columns are available, if not, a new pack is appended
+ // rCol contains the number of the first empty column (in pOTableFieldDescList)
+
+ void RemoveField( sal_uInt16 nId );
+ tools::Rectangle GetInvalidRect( sal_uInt16 nColId );
+ sal_Int32 GetRealRow(sal_Int32 nRow) const;
+ sal_Int32 GetBrowseRow(sal_Int32 nRowId) const;
+ bool GetFunctionName(sal_uInt32 _nFunctionTokenId, OUString& rFkt);
+ void appendUndoAction(const OUString& _rOldValue,std::u16string_view _rNewValue,sal_Int32 _nRow, bool& _bListAction);
+ void appendUndoAction(const OUString& _rOldValue,std::u16string_view _rNewValue,sal_Int32 _nRow);
+ OTableFields& getFields() const;
+ static void enableControl(const OTableFieldDescRef& _rEntry,Window* _pControl);
+ void setTextCellContext(const OTableFieldDescRef& _rEntry,const OUString& _sText,const OString& _sHelpId);
+ void invalidateUndoRedo();
+ OTableFieldDescRef getEntry(OTableFields::size_type _nPos);
+
+ void adjustSelectionMode( bool _bClickedOntoHeader, bool _bClickedOntoHandleCol );
+
+ /** save the field change in save modified
+ @param _sFieldName
+ The field name inserted by the user.
+ @param _pEntry
+ The entry which will contain the necessary entries.
+ @param _bListAction
+ Will be set to <TRUE/> when we are in a list action otherwise <FALSE/>
+ @return
+ <TRUE/> if an error occurred otherwise <FALSE/>
+ */
+ bool saveField(OUString& _sFieldName, OTableFieldDescRef const & _pEntry, bool& _bListAction);
+
+ /** sets the table window at the _pEntry
+ @param _pEntry
+ The entry where the window should be set.
+ @param _sTableName
+ The table name to search for.
+ @return
+ <TRUE/> if the table name was set otherwise <FALSE/>
+ */
+ bool fillEntryTable(OTableFieldDescRef const & _pEntry,const OUString& _sTableName);
+
+ /** uses the parse node to fill all information into the field
+ @param _pColumnRef
+ The parse node used to fill the info into the field.
+ @param _xMetaData
+ Use to parse the node to a string.
+ @param _pEntry
+ The entry which will contain the necessary entries.
+ @param _bListAction
+ Will be set to <TRUE/> when we are in a list action otherwise <FALSE/>
+ @return
+ <TRUE/> if an error occurred otherwise <FALSE/>
+ */
+ bool fillColumnRef( const ::connectivity::OSQLParseNode* _pColumnRef,
+ const css::uno::Reference< css::sdbc::XConnection >& _rxConnection,
+ OTableFieldDescRef const & _pEntry,
+ bool& _bListAction);
+ bool fillColumnRef( const OUString& _sColumnName,
+ std::u16string_view _sTableRange,
+ const css::uno::Reference< css::sdbc::XDatabaseMetaData >& _xMetaData,
+ OTableFieldDescRef const & _pEntry,
+ bool& _bListAction);
+
+ /** append an undo action for the table field
+ @param _sOldAlias
+ The old table alias.
+ @param _sAlias
+ The new alias name.
+ @param _bListAction
+ Will be set to <TRUE/> when we are in a list action otherwise <FALSE/>
+ */
+ void notifyTableFieldChanged(const OUString& _sOldAlias,std::u16string_view _sAlias, bool& _bListAction,sal_uInt16 _nColumnId);
+
+ /** append an undo action for the function field
+ @param _sOldFunctionName
+ The old value.
+ @param _sFunctionName
+ The new function name.
+ @param _bListAction
+ Will be set to <TRUE/> when we are in a list action otherwise <FALSE/>
+ */
+ void notifyFunctionFieldChanged(const OUString& _sOldFunctionName,std::u16string_view _sFunctionName, bool& _bListAction,sal_uInt16 _nColumnId);
+
+ /** clears the function fields of the submitted entry if it doesn't match the SQL standard and append an undo action.
+ E.q. AGGREGATE functions are only valid when the field name isn't an asterisk
+ @param _sFieldName
+ The field name.
+ @param _pEntry
+ The entry to be cleared
+ @param _bListAction
+ When <TRUE/> a list action will be created.
+ */
+ void clearEntryFunctionField(const OUString& _sFieldName,OTableFieldDescRef const & _pEntry, bool& _bListAction,sal_uInt16 _nColumnId);
+
+ /** remove or insert the necessary function types
+ @param _pEntry
+ The currently edited entry.
+ */
+ void setFunctionCell(OTableFieldDescRef const & _pEntry);
+
+ using ::svt::EditBrowseBox::AcceptDrop;
+ using ::svt::EditBrowseBox::ExecuteDrop;
+ using ::svt::EditBrowseBox::MouseButtonDown;
+ using ::svt::EditBrowseBox::MouseButtonUp;
+ };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/querydesign/TableConnection.cxx b/dbaccess/source/ui/querydesign/TableConnection.cxx
new file mode 100644
index 000000000..ada4b5990
--- /dev/null
+++ b/dbaccess/source/ui/querydesign/TableConnection.cxx
@@ -0,0 +1,190 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <TableConnection.hxx>
+#include <ConnectionLine.hxx>
+#include <TableConnectionData.hxx>
+#include <JoinTableView.hxx>
+
+using namespace dbaui;
+using namespace comphelper;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::accessibility;
+
+namespace dbaui
+{
+ OTableConnection::OTableConnection( OJoinTableView* _pContainer,const TTableConnectionData::value_type& _pTabConnData )
+ :Window(_pContainer)
+ ,m_pData( _pTabConnData )
+ ,m_pParent( _pContainer )
+ ,m_bSelected( false )
+ {
+ Init();
+ Show();
+ }
+
+ OTableConnection::OTableConnection( const OTableConnection& _rConn )
+ : VclReferenceBase()
+ ,Window(_rConn.m_pParent.get())
+ ,m_pData(_rConn.GetData()->NewInstance())
+ ,m_pParent(nullptr)
+ {
+ *this = _rConn;
+ }
+
+ void OTableConnection::Init()
+ {
+ // initialise linelist with defaults
+ OConnectionLineDataVec& rLineData = GetData()->GetConnLineDataList();
+ m_vConnLine.reserve(rLineData.size());
+ for (auto const& elem : rLineData)
+ m_vConnLine.emplace_back( new OConnectionLine(this, elem) );
+ }
+
+ void OTableConnection::clearLineData()
+ {
+ m_vConnLine.clear();
+ }
+ void OTableConnection::UpdateLineList()
+ {
+ // delete linelist
+ clearLineData();
+
+ Init();
+ }
+
+ OTableConnection& OTableConnection::operator=( const OTableConnection& rConn )
+ {
+ if( &rConn == this )
+ return *this;
+
+ // delete linelist
+ clearLineData();
+
+ // copy linelist
+ if(! rConn.GetConnLineList().empty() )
+ {
+ const std::vector<std::unique_ptr<OConnectionLine>>& rLine = rConn.GetConnLineList();
+ m_vConnLine.reserve(rLine.size());
+ for (auto const& elem : rLine)
+ m_vConnLine.emplace_back( new OConnectionLine(*elem));
+ }
+
+ // as the data are not mine, I also do not delete the old
+ m_pData->CopyFrom(*rConn.GetData());
+ // CopyFrom is virtual, therefore it is not a problem if m_pData is a derived type of OTableConnectionData
+
+ m_bSelected = rConn.m_bSelected;
+ m_pParent = rConn.m_pParent;
+
+ return *this;
+ }
+
+ void OTableConnection::RecalcLines()
+ {
+ // call RecalcLines on each line
+ for( const auto& pLine : m_vConnLine )
+ pLine->RecalcLine();
+ }
+ OTableWindow* OTableConnection::GetSourceWin() const
+ {
+ TTableWindowData::value_type pRef = GetData()->getReferencingTable();
+ OTableWindow* pRet = m_pParent->GetTabWindow( pRef->GetWinName() );
+ if ( !pRet )
+ {
+ pRet = m_pParent->GetTabWindow( pRef->GetComposedName() );
+ }
+ return pRet;
+ }
+ OTableWindow* OTableConnection::GetDestWin() const
+ {
+ TTableWindowData::value_type pRef = GetData()->getReferencedTable();
+ OTableWindow* pRet = m_pParent->GetTabWindow( pRef->GetWinName() );
+ if ( !pRet )
+ {
+ pRet = m_pParent->GetTabWindow( pRef->GetComposedName() );
+ }
+ return pRet;
+ }
+
+ void OTableConnection::Select()
+ {
+ m_bSelected = true;
+ m_pParent->Invalidate( GetBoundingRect(), InvalidateFlags::NoChildren);
+ }
+
+ void OTableConnection::Deselect()
+ {
+ m_bSelected = false;
+ InvalidateConnection();
+ }
+
+ bool OTableConnection::CheckHit( const Point& rMousePos ) const
+ {
+ // check if the point hit our line
+ return std::any_of(m_vConnLine.begin(),
+ m_vConnLine.end(),
+ [&rMousePos]
+ ( const std::unique_ptr<OConnectionLine> & pLine )
+ { return pLine->CheckHit( rMousePos ); } );
+ }
+
+ void OTableConnection::InvalidateConnection()
+ {
+ tools::Rectangle rcBounding = GetBoundingRect();
+ rcBounding.AdjustBottom(1 );
+ rcBounding.AdjustRight(1 );
+ // I believe Invalidate and Draw(Rectangle) do not behave consistent: in any case it
+ // could explain, why without the fake here when deleting a connection a dash remains at the lower end:
+ // Invalidate records obviously one pixel line less as Draw.
+ // Or everything works differently... in any case it works...
+ m_pParent->Invalidate( rcBounding, InvalidateFlags::NoChildren );
+ }
+
+ tools::Rectangle OTableConnection::GetBoundingRect() const
+ {
+ // determine all lines of the surrounding rectangle
+ tools::Rectangle aBoundingRect( Point(0,0), Point(0,0) );
+ tools::Rectangle aTempRect;
+ for (auto const& elem : m_vConnLine)
+ {
+ aTempRect = elem->GetBoundingRect();
+
+ // is the BoundingRect of this line valid?
+ if( (aTempRect.GetWidth()!=1) && (aTempRect.GetHeight()!=1) )
+ {
+ if( (aBoundingRect.GetWidth()==1) && (aBoundingRect.GetHeight()==1) )
+ aBoundingRect = aTempRect;
+ else
+ aBoundingRect.Union( aTempRect );
+ }
+ }
+
+ return aBoundingRect;
+ }
+
+ void OTableConnection::Draw(vcl::RenderContext& rRenderContext, const tools::Rectangle& /*rRect*/)
+ {
+ // Draw line
+ for( const auto& pLine : m_vConnLine )
+ pLine->Draw( &rRenderContext );
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/querydesign/TableConnectionData.cxx b/dbaccess/source/ui/querydesign/TableConnectionData.cxx
new file mode 100644
index 000000000..107d8a9d1
--- /dev/null
+++ b/dbaccess/source/ui/querydesign/TableConnectionData.cxx
@@ -0,0 +1,147 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <TableConnectionData.hxx>
+#include <osl/diagnose.h>
+
+using namespace dbaui;
+
+OTableConnectionData::OTableConnectionData()
+{
+ Init();
+}
+
+OTableConnectionData::OTableConnectionData(const TTableWindowData::value_type& _pReferencingTable
+ ,const TTableWindowData::value_type& _pReferencedTable )
+ :m_pReferencingTable(_pReferencingTable)
+ ,m_pReferencedTable(_pReferencedTable)
+{
+ Init();
+}
+
+void OTableConnectionData::Init()
+{
+ // initialise linedatalist with defaults
+ OSL_ENSURE(m_vConnLineData.empty(), "OTableConnectionData::Init() : call only with empty line list!");
+ ResetConnLines();
+ // this creates the defaults
+}
+
+OTableConnectionData::OTableConnectionData( const OTableConnectionData& rConnData )
+{
+ *this = rConnData;
+}
+
+void OTableConnectionData::CopyFrom(const OTableConnectionData& rSource)
+{
+ *this = rSource;
+ // here I revert to the (non-virtual) operator =, which only copies my members
+}
+
+OTableConnectionData::~OTableConnectionData()
+{
+ // delete LineDataList
+ OConnectionLineDataVec().swap(m_vConnLineData);
+}
+
+OTableConnectionData& OTableConnectionData::operator=( const OTableConnectionData& rConnData )
+{
+ if (&rConnData == this)
+ return *this;
+
+ m_pReferencingTable = rConnData.m_pReferencingTable;
+ m_pReferencedTable = rConnData.m_pReferencedTable;
+ m_aConnName = rConnData.m_aConnName;
+
+ // clear line list
+ ResetConnLines();
+
+ // and copy
+ for (auto const& elem : rConnData.GetConnLineDataList())
+ m_vConnLineData.push_back(new OConnectionLineData(*elem));
+
+ return *this;
+}
+
+void OTableConnectionData::SetConnLine( sal_uInt16 nIndex, const OUString& rSourceFieldName, const OUString& rDestFieldName )
+{
+ if (sal_uInt16(m_vConnLineData.size()) < nIndex)
+ return;
+
+ // == still allowed, this corresponds to an Append
+
+ if (m_vConnLineData.size() == nIndex)
+ {
+ AppendConnLine(rSourceFieldName, rDestFieldName);
+ return;
+ }
+
+ OConnectionLineDataRef pConnLineData = m_vConnLineData[nIndex];
+ OSL_ENSURE(pConnLineData != nullptr, "OTableConnectionData::SetConnLine : have invalid LineData object");
+
+ pConnLineData->SetSourceFieldName( rSourceFieldName );
+ pConnLineData->SetDestFieldName( rDestFieldName );
+}
+
+bool OTableConnectionData::AppendConnLine( const OUString& rSourceFieldName, const OUString& rDestFieldName )
+{
+ for (auto const& elem : m_vConnLineData)
+ {
+ if(elem->GetDestFieldName() == rDestFieldName && elem->GetSourceFieldName() == rSourceFieldName)
+ return true;
+ }
+ OConnectionLineDataRef pNew = new OConnectionLineData(rSourceFieldName, rDestFieldName);
+ if (!pNew.is())
+ return false;
+
+ m_vConnLineData.push_back(pNew);
+ return true;
+}
+
+void OTableConnectionData::ResetConnLines()
+{
+ OConnectionLineDataVec().swap(m_vConnLineData);
+}
+
+std::shared_ptr<OTableConnectionData> OTableConnectionData::NewInstance() const
+{
+ return std::make_shared<OTableConnectionData>();
+}
+
+OConnectionLineDataVec::size_type OTableConnectionData::normalizeLines()
+{
+ // remove empty lines
+ OConnectionLineDataVec::size_type nCount = m_vConnLineData.size();
+ OConnectionLineDataVec::size_type nRet = nCount;
+ for(OConnectionLineDataVec::size_type i = 0; i < nCount;)
+ {
+ if(m_vConnLineData[i]->GetSourceFieldName().isEmpty() && m_vConnLineData[i]->GetDestFieldName().isEmpty())
+ {
+ m_vConnLineData.erase(m_vConnLineData.begin()+i);
+ --nCount;
+ if (i < nRet)
+ nRet=i;
+ }
+ else
+ ++i;
+ }
+ return nRet;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/querydesign/TableFieldDescription.cxx b/dbaccess/source/ui/querydesign/TableFieldDescription.cxx
new file mode 100644
index 000000000..1e8604181
--- /dev/null
+++ b/dbaccess/source/ui/querydesign/TableFieldDescription.cxx
@@ -0,0 +1,196 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <TableFieldDescription.hxx>
+
+#include <osl/diagnose.h>
+#include <com/sun/star/sdbc/DataType.hpp>
+#include <comphelper/namedvaluecollection.hxx>
+
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::beans;
+using namespace comphelper;
+using namespace dbaui;
+
+OTableFieldDesc::OTableFieldDesc()
+ :m_pTabWindow(nullptr)
+ ,m_eDataType(1000)
+ ,m_eFunctionType( FKT_NONE )
+ ,m_eFieldType(TAB_NORMAL_FIELD)
+ ,m_eOrderDir( ORDER_NONE )
+ ,m_nIndex(0)
+ ,m_nColWidth(0)
+ ,m_nColumnId(sal_uInt16(-1))
+ ,m_bGroupBy(false)
+ ,m_bVisible(false)
+{
+}
+
+OTableFieldDesc::OTableFieldDesc(const OTableFieldDesc& rRS)
+ : ::salhelper::SimpleReferenceObject()
+ , m_pTabWindow(nullptr)
+{
+ *this = rRS;
+}
+
+OTableFieldDesc::OTableFieldDesc(const OUString& rT, const OUString& rF )
+ :m_pTabWindow(nullptr)
+ ,m_eDataType(1000)
+ ,m_eFunctionType( FKT_NONE )
+ ,m_eFieldType(TAB_NORMAL_FIELD)
+ ,m_eOrderDir( ORDER_NONE )
+ ,m_nIndex(0)
+ ,m_nColWidth(0)
+ ,m_nColumnId(sal_uInt16(-1))
+ ,m_bGroupBy(false)
+ ,m_bVisible(false)
+{
+ SetField( rF ); SetTable( rT );
+}
+
+OTableFieldDesc::~OTableFieldDesc()
+{
+}
+
+OTableFieldDesc& OTableFieldDesc::operator=( const OTableFieldDesc& rRS )
+{
+ if (&rRS == this)
+ return *this;
+
+ m_aCriteria = rRS.GetCriteria();
+ m_aTableName = rRS.GetTable();
+ m_aAliasName = rRS.GetAlias(); // table range
+ m_aFieldName = rRS.GetField(); // column
+ m_aFieldAlias = rRS.GetFieldAlias(); // column alias
+ m_aFunctionName = rRS.GetFunction();
+ m_pTabWindow = rRS.GetTabWindow();
+ m_eDataType = rRS.GetDataType();
+ m_eFunctionType = rRS.GetFunctionType();
+ m_eFieldType = rRS.GetFieldType();
+ m_eOrderDir = rRS.GetOrderDir();
+ m_nIndex = rRS.GetFieldIndex();
+ m_nColWidth = rRS.GetColWidth();
+ m_nColumnId = rRS.m_nColumnId;
+ m_bGroupBy = rRS.IsGroupBy();
+ m_bVisible = rRS.IsVisible();
+
+ return *this;
+}
+
+void OTableFieldDesc::SetCriteria( sal_uInt16 nIdx, const OUString& rCrit)
+{
+ if (nIdx < m_aCriteria.size())
+ m_aCriteria[nIdx] = rCrit;
+ else
+ {
+ m_aCriteria.insert(m_aCriteria.end(), nIdx - m_aCriteria.size(), OUString());
+ m_aCriteria.push_back(rCrit);
+ }
+}
+
+OUString OTableFieldDesc::GetCriteria( sal_uInt16 nIdx ) const
+{
+ OUString aRetStr;
+ if( nIdx < m_aCriteria.size())
+ aRetStr = m_aCriteria[nIdx];
+
+ return aRetStr;
+}
+
+namespace
+{
+ struct SelectPropertyValueAsString
+ {
+ OUString operator()( const PropertyValue& i_rPropValue ) const
+ {
+ OUString sValue;
+ OSL_VERIFY( i_rPropValue.Value >>= sValue );
+ return sValue;
+ }
+ };
+}
+
+void OTableFieldDesc::Load( const css::beans::PropertyValue& i_rSettings, const bool i_bIncludingCriteria )
+{
+
+ ::comphelper::NamedValueCollection aFieldDesc( i_rSettings.Value );
+ m_aAliasName = aFieldDesc.getOrDefault( "AliasName", m_aAliasName );
+ m_aTableName = aFieldDesc.getOrDefault( "TableName", m_aTableName );
+ m_aFieldName = aFieldDesc.getOrDefault( "FieldName", m_aFieldName );
+ m_aFieldAlias = aFieldDesc.getOrDefault( "FieldAlias", m_aFieldAlias );
+ m_aFunctionName = aFieldDesc.getOrDefault( "FunctionName", m_aFunctionName );
+ m_eDataType = aFieldDesc.getOrDefault( "DataType", m_eDataType );
+ m_eFunctionType = aFieldDesc.getOrDefault( "FunctionType", m_eFunctionType );
+ m_nColWidth = aFieldDesc.getOrDefault( "ColWidth", m_nColWidth );
+ m_bGroupBy = aFieldDesc.getOrDefault( "GroupBy", m_bGroupBy );
+ m_bVisible = aFieldDesc.getOrDefault( "Visible", m_bVisible );
+
+ m_eFieldType = static_cast< ETableFieldType >( aFieldDesc.getOrDefault( "FieldType", static_cast< sal_Int32 >( m_eFieldType ) ) );
+ m_eOrderDir = static_cast< EOrderDir >( aFieldDesc.getOrDefault( "OrderDir", static_cast< sal_Int32 >( m_eOrderDir ) ) );
+
+ if ( i_bIncludingCriteria )
+ {
+ const Sequence< PropertyValue > aCriteria( aFieldDesc.getOrDefault( "Criteria", Sequence< PropertyValue >() ) );
+ m_aCriteria.resize( aCriteria.getLength() );
+ std::transform(
+ aCriteria.begin(),
+ aCriteria.end(),
+ m_aCriteria.begin(),
+ SelectPropertyValueAsString()
+ );
+ }
+}
+
+void OTableFieldDesc::Save( ::comphelper::NamedValueCollection& o_rSettings, const bool i_bIncludingCriteria )
+{
+
+ o_rSettings.put( "AliasName", m_aAliasName );
+ o_rSettings.put( "TableName", m_aTableName );
+ o_rSettings.put( "FieldName", m_aFieldName );
+ o_rSettings.put( "FieldAlias", m_aFieldAlias );
+ o_rSettings.put( "FunctionName", m_aFunctionName );
+ o_rSettings.put( "DataType", m_eDataType );
+ o_rSettings.put( "FunctionType", m_eFunctionType );
+ o_rSettings.put( "FieldType", static_cast<sal_Int32>(m_eFieldType) );
+ o_rSettings.put( "OrderDir", static_cast<sal_Int32>(m_eOrderDir) );
+ o_rSettings.put( "ColWidth", m_nColWidth );
+ o_rSettings.put( "GroupBy", m_bGroupBy );
+ o_rSettings.put( "Visible", m_bVisible );
+
+ if ( !i_bIncludingCriteria )
+ return;
+
+ if ( m_aCriteria.empty() )
+ return;
+
+ sal_Int32 c = 0;
+ Sequence< PropertyValue > aCriteria( m_aCriteria.size() );
+ auto pCriteria = aCriteria.getArray();
+ for (auto const& criteria : m_aCriteria)
+ {
+ pCriteria[c].Name = "Criterion_" + OUString::number( c );
+ pCriteria[c].Value <<= criteria;
+ ++c;
+ }
+
+ o_rSettings.put( "Criteria", aCriteria );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/querydesign/TableFieldInfo.cxx b/dbaccess/source/ui/querydesign/TableFieldInfo.cxx
new file mode 100644
index 000000000..808862c11
--- /dev/null
+++ b/dbaccess/source/ui/querydesign/TableFieldInfo.cxx
@@ -0,0 +1,30 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "TableFieldInfo.hxx"
+
+using namespace dbaui;
+
+OTableFieldInfo::OTableFieldInfo()
+ : m_eFieldType(TAB_NORMAL_FIELD)
+ , m_eDataType(1000)
+{
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/querydesign/TableFieldInfo.hxx b/dbaccess/source/ui/querydesign/TableFieldInfo.hxx
new file mode 100644
index 000000000..e7d2c9b72
--- /dev/null
+++ b/dbaccess/source/ui/querydesign/TableFieldInfo.hxx
@@ -0,0 +1,43 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <QEnumTypes.hxx>
+#include <sal/types.h>
+
+namespace dbaui
+{
+ class OTableFieldInfo
+ {
+ private:
+ ETableFieldType m_eFieldType;
+ sal_Int32 m_eDataType;
+
+ public:
+ OTableFieldInfo();
+
+ ETableFieldType GetKeyType() const { return m_eFieldType; }
+ void SetKey(ETableFieldType bKey) { m_eFieldType = bKey; }
+ sal_Int32 GetDataType() const { return m_eDataType; }
+ void SetDataType(sal_Int32 eTyp) { m_eDataType = eTyp; }
+ };
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/querydesign/TableWindow.cxx b/dbaccess/source/ui/querydesign/TableWindow.cxx
new file mode 100644
index 000000000..b8afc951d
--- /dev/null
+++ b/dbaccess/source/ui/querydesign/TableWindow.cxx
@@ -0,0 +1,716 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <TableWindow.hxx>
+#include <TableWindowListBox.hxx>
+#include <TableWindowData.hxx>
+#include <imageprovider.hxx>
+#include <JoinController.hxx>
+#include <JoinTableView.hxx>
+#include <JoinDesignView.hxx>
+#include <osl/diagnose.h>
+#include <vcl/svapp.hxx>
+#include <vcl/settings.hxx>
+#include <vcl/commandevent.hxx>
+#include <vcl/event.hxx>
+#include <vcl/ptrstyle.hxx>
+#include <vcl/wall.hxx>
+#include <vcl/weldutils.hxx>
+#include <tools/diagnose_ex.h>
+
+#include <com/sun/star/container/XContainer.hpp>
+#include <com/sun/star/container/XNameAccess.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/sdb/application/DatabaseObject.hpp>
+#include <bitmaps.hlst>
+#include <TableWindowAccess.hxx>
+#include <connectivity/dbtools.hxx>
+
+using namespace dbaui;
+using namespace ::utl;
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::sdb;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::sdbcx;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::accessibility;
+
+namespace DatabaseObject = css::sdb::application::DatabaseObject;
+
+#define TABWIN_SIZING_AREA 4
+#define TABWIN_WIDTH_MIN 90
+#define TABWIN_HEIGHT_MIN 80
+
+namespace {
+
+void Draw3DBorder(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect)
+{
+ // Use the System Style-Settings for my colours
+ const StyleSettings& aSystemStyle = Application::GetSettings().GetStyleSettings();
+
+ // Black lines for bottom and right
+ rRenderContext.SetLineColor(aSystemStyle.GetDarkShadowColor());
+ rRenderContext.DrawLine(rRect.BottomLeft(), rRect.BottomRight());
+ rRenderContext.DrawLine(rRect.BottomRight(), rRect.TopRight());
+
+ // Dark grey lines over the black lines
+ rRenderContext.SetLineColor(aSystemStyle.GetShadowColor());
+ Point aEHvector(1, 1);
+ rRenderContext.DrawLine(rRect.BottomLeft() + Point(1, -1), rRect.BottomRight() - aEHvector);
+ rRenderContext.DrawLine(rRect.BottomRight() - aEHvector, rRect.TopRight() + Point(-1, 1));
+
+ // Light grey lines for top and left
+ rRenderContext.SetLineColor(aSystemStyle.GetLightColor());
+ rRenderContext.DrawLine(rRect.BottomLeft() + Point(1, -2), rRect.TopLeft() + aEHvector);
+ rRenderContext.DrawLine(rRect.TopLeft() + aEHvector, rRect.TopRight() + Point(-2, 1));
+}
+
+}
+
+OTableWindow::OTableWindow( vcl::Window* pParent, const TTableWindowData::value_type& pTabWinData )
+ : ::comphelper::OContainerListener(m_aMutex)
+ , Window( pParent, WB_3DLOOK|WB_MOVEABLE )
+ , m_xTitle( VclPtr<OTableWindowTitle>::Create(this) )
+ , m_pData( pTabWinData )
+ , m_nMoveCount(0)
+ , m_nMoveIncrement(1)
+ , m_nSizingFlags( SizingFlags::NONE )
+{
+ // Set position and size
+ if( GetData()->HasPosition() )
+ SetPosPixel( GetData()->GetPosition() );
+
+ if( GetData()->HasSize() )
+ SetSizePixel( GetData()->GetSize() );
+
+ // Set background
+ const StyleSettings& aSystemStyle = Application::GetSettings().GetStyleSettings();
+ SetBackground(Wallpaper(aSystemStyle.GetFaceColor()));
+ // Set the text colour even though there is no text,
+ // because derived classes might need it
+ SetTextColor(aSystemStyle.GetButtonTextColor());
+
+ EnableClipSiblings();
+}
+
+OTableWindow::~OTableWindow()
+{
+ disposeOnce();
+}
+
+void OTableWindow::dispose()
+{
+ if (m_xListBox)
+ {
+ OSL_ENSURE(m_xListBox->get_widget().n_children()==0,"Forgot to call EmptyListbox()!");
+ }
+ m_xListBox.disposeAndClear();
+ if ( m_pContainerListener.is() )
+ m_pContainerListener->dispose();
+
+ m_xTitle.disposeAndClear();
+ vcl::Window::dispose();
+}
+
+const OJoinTableView* OTableWindow::getTableView() const
+{
+ OSL_ENSURE(static_cast<OJoinTableView*>(GetParent()),"No OJoinTableView!");
+ return static_cast<OJoinTableView*>(GetParent());
+}
+
+OJoinTableView* OTableWindow::getTableView()
+{
+ OSL_ENSURE(static_cast<OJoinTableView*>(GetParent()),"No OJoinTableView!");
+ return static_cast<OJoinTableView*>(GetParent());
+}
+
+OJoinDesignView* OTableWindow::getDesignView()
+{
+ OSL_ENSURE(static_cast<OJoinDesignView*>(GetParent()->GetParent()->GetParent()),"No OJoinDesignView!");
+ return static_cast<OJoinDesignView*>(GetParent()->GetParent()->GetParent());
+}
+
+void OTableWindow::SetPosPixel( const Point& rNewPos )
+{
+ Point aNewPosData = rNewPos + getTableView()->GetScrollOffset();
+ GetData()->SetPosition( aNewPosData );
+ Window::SetPosPixel( rNewPos );
+}
+
+void OTableWindow::SetSizePixel( const Size& rNewSize )
+{
+ Size aOutSize(rNewSize);
+ if( aOutSize.Width() < TABWIN_WIDTH_MIN )
+ aOutSize.setWidth( TABWIN_WIDTH_MIN );
+ if( aOutSize.Height() < TABWIN_HEIGHT_MIN )
+ aOutSize.setHeight( TABWIN_HEIGHT_MIN );
+
+ GetData()->SetSize( aOutSize );
+ Window::SetSizePixel( aOutSize );
+}
+
+void OTableWindow::SetPosSizePixel( const Point& rNewPos, const Size& rNewSize )
+{
+ SetPosPixel( rNewPos );
+ SetSizePixel( rNewSize );
+}
+
+void OTableWindow::FillListBox()
+{
+ clearListBox();
+ weld::TreeView& rTreeView = m_xListBox->get_widget();
+ assert(!rTreeView.n_children());
+
+ if ( !m_pContainerListener.is() )
+ {
+ Reference< XContainer> xContainer(m_pData->getColumns(),UNO_QUERY);
+ if ( xContainer.is() )
+ m_pContainerListener = new ::comphelper::OContainerListenerAdapter(this,xContainer);
+ }
+
+ // mark all primary keys with special image
+ OUString aPrimKeyImage(BMP_PRIMARY_KEY);
+
+ if (GetData()->IsShowAll())
+ {
+ rTreeView.append(weld::toId(createUserData(nullptr,false)), OUString("*"));
+ }
+
+ Reference<XNameAccess> xPKeyColumns;
+ try
+ {
+ xPKeyColumns = dbtools::getPrimaryKeyColumns_throw(m_pData->getTable());
+ }
+ catch(Exception&)
+ {
+ TOOLS_WARN_EXCEPTION( "dbaccess", "");
+ }
+ try
+ {
+ Reference< XNameAccess > xColumns = m_pData->getColumns();
+ if( xColumns.is() )
+ {
+ Sequence< OUString> aColumns = xColumns->getElementNames();
+ const OUString* pIter = aColumns.getConstArray();
+ const OUString* pEnd = pIter + aColumns.getLength();
+
+ for (; pIter != pEnd; ++pIter)
+ {
+ bool bPrimaryKeyColumn = xPKeyColumns.is() && xPKeyColumns->hasByName( *pIter );
+
+ OUString sId;
+ Reference<XPropertySet> xColumn(xColumns->getByName(*pIter),UNO_QUERY);
+ if (xColumn.is())
+ sId = weld::toId(createUserData(xColumn, bPrimaryKeyColumn));
+
+ rTreeView.append(sId, *pIter);
+
+ // is this column in the primary key
+ if ( bPrimaryKeyColumn )
+ rTreeView.set_image(rTreeView.n_children() - 1, aPrimKeyImage);
+ }
+
+ }
+ }
+ catch(Exception&)
+ {
+ TOOLS_WARN_EXCEPTION( "dbaccess", "");
+ }
+}
+
+void* OTableWindow::createUserData(const Reference< XPropertySet>& /*_xColumn*/,bool /*_bPrimaryKey*/)
+{
+ return nullptr;
+}
+
+void OTableWindow::deleteUserData(void*& _pUserData)
+{
+ OSL_ENSURE(!_pUserData,"INVALID call. Need to delete the userclass!");
+ _pUserData = nullptr;
+}
+
+void OTableWindow::clearListBox()
+{
+ if ( !m_xListBox )
+ return;
+
+ weld::TreeView& rTreeView = m_xListBox->get_widget();
+ rTreeView.all_foreach([this, &rTreeView](weld::TreeIter& rEntry){
+ void* pUserData = weld::fromId<void*>(rTreeView.get_id(rEntry));
+ deleteUserData(pUserData);
+ return false;
+ });
+
+ rTreeView.clear();
+}
+
+void OTableWindow::impl_updateImage()
+{
+ weld::Image& rImage = m_xTitle->GetImage();
+ ImageProvider aImageProvider( getDesignView()->getController().getConnection() );
+ rImage.set_from_icon_name(aImageProvider.getImageId(GetComposedName(), m_pData->isQuery() ? DatabaseObject::QUERY : DatabaseObject::TABLE));
+ rImage.show();
+}
+
+bool OTableWindow::Init()
+{
+ // create list box if necessary
+ if ( !m_xListBox )
+ {
+ m_xListBox = VclPtr<OTableWindowListBox>::Create(this);
+ assert(m_xListBox && "OTableWindow::Init() : CreateListBox returned NULL !");
+ m_xListBox->get_widget().set_selection_mode(SelectionMode::Multiple);
+ }
+
+ // Set the title
+ weld::Label& rLabel = m_xTitle->GetLabel();
+ rLabel.set_label(m_pData->GetWinName());
+ rLabel.set_tooltip_text(GetComposedName());
+ m_xTitle->Show();
+
+ m_xListBox->Show();
+
+ // add the fields to the ListBox
+ FillListBox();
+ m_xListBox->get_widget().unselect_all();
+
+ impl_updateImage();
+
+ return true;
+}
+
+void OTableWindow::DataChanged(const DataChangedEvent& rDCEvt)
+{
+ if (rDCEvt.GetType() == DataChangedEventType::SETTINGS)
+ {
+ // In the worst-case the colours have changed so
+ // adapt myself to the new colours
+ const StyleSettings& aSystemStyle = Application::GetSettings().GetStyleSettings();
+ SetBackground(Wallpaper(aSystemStyle.GetFaceColor()));
+ SetTextColor(aSystemStyle.GetButtonTextColor());
+ }
+}
+
+void OTableWindow::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect)
+{
+ tools::Rectangle aRect(Point(0,0), GetOutputSizePixel());
+ Window::Paint(rRenderContext, rRect);
+ Draw3DBorder(rRenderContext, aRect);
+}
+
+tools::Rectangle OTableWindow::getSizingRect(const Point& _rPos,const Size& _rOutputSize) const
+{
+ tools::Rectangle aSizingRect( GetPosPixel(), GetSizePixel() );
+
+ if( m_nSizingFlags & SizingFlags::Top )
+ {
+ if( _rPos.Y() < 0 )
+ aSizingRect.SetTop( 0 );
+ else
+ aSizingRect.SetTop( _rPos.Y() );
+ }
+
+ if( m_nSizingFlags & SizingFlags::Bottom )
+ {
+ if( _rPos.Y() > _rOutputSize.Height() )
+ aSizingRect.SetBottom( _rOutputSize.Height() );
+ else
+ aSizingRect.SetBottom( _rPos.Y() );
+ }
+
+ if( m_nSizingFlags & SizingFlags::Right )
+ {
+ if( _rPos.X() > _rOutputSize.Width() )
+ aSizingRect.SetRight( _rOutputSize.Width() );
+ else
+ aSizingRect.SetRight( _rPos.X() );
+ }
+
+ if( m_nSizingFlags & SizingFlags::Left )
+ {
+ if( _rPos.X() < 0 )
+ aSizingRect.SetLeft( 0 );
+ else
+ aSizingRect.SetLeft( _rPos.X() );
+ }
+ return aSizingRect;
+}
+
+void OTableWindow::setSizingFlag(const Point& _rPos)
+{
+ Size aOutSize = GetOutputSizePixel();
+ // Set the flags when the mouse cursor is in the sizing area
+ m_nSizingFlags = SizingFlags::NONE;
+
+ if( _rPos.X() < TABWIN_SIZING_AREA )
+ m_nSizingFlags |= SizingFlags::Left;
+
+ if( _rPos.Y() < TABWIN_SIZING_AREA )
+ m_nSizingFlags |= SizingFlags::Top;
+
+ if( _rPos.X() > aOutSize.Width()-TABWIN_SIZING_AREA )
+ m_nSizingFlags |= SizingFlags::Right;
+
+ if( _rPos.Y() > aOutSize.Height()-TABWIN_SIZING_AREA )
+ m_nSizingFlags |= SizingFlags::Bottom;
+}
+
+void OTableWindow::MouseMove( const MouseEvent& rEvt )
+{
+ Window::MouseMove(rEvt);
+
+ OJoinTableView* pCont = getTableView();
+ if (pCont->getDesignView()->getController().isReadOnly())
+ return;
+
+ Point aPos = rEvt.GetPosPixel();
+ setSizingFlag(aPos);
+ PointerStyle aPointer = PointerStyle::Arrow;
+
+ // Set the mouse cursor when it is in the sizing area
+ if ( m_nSizingFlags == SizingFlags::Top ||
+ m_nSizingFlags == SizingFlags::Bottom )
+ aPointer = PointerStyle::SSize;
+ else if ( m_nSizingFlags == SizingFlags::Left ||
+ m_nSizingFlags ==SizingFlags::Right )
+ aPointer = PointerStyle::ESize;
+ else if ( m_nSizingFlags == (SizingFlags::Left | SizingFlags::Top) ||
+ m_nSizingFlags == (SizingFlags::Right | SizingFlags::Bottom) )
+ aPointer = PointerStyle::SESize;
+ else if ( m_nSizingFlags == (SizingFlags::Right | SizingFlags::Top) ||
+ m_nSizingFlags == (SizingFlags::Left | SizingFlags::Bottom) )
+ aPointer = PointerStyle::NESize;
+
+ SetPointer( aPointer );
+}
+
+void OTableWindow::MouseButtonDown( const MouseEvent& rEvt )
+{
+ // When resizing, the parent must be informed that
+ // the window size of its child has changed
+ if( m_nSizingFlags != SizingFlags::NONE )
+ getTableView()->BeginChildSizing( this, GetPointer() );
+
+ Window::MouseButtonDown( rEvt );
+}
+
+void OTableWindow::Resize()
+{
+ // The window must not disappear so we enforce a minimum size
+ Size aOutSize = GetOutputSizePixel();
+ aOutSize = Size(CalcZoom(aOutSize.Width()),CalcZoom(aOutSize.Height()));
+
+ tools::Long nTitleHeight = CalcZoom( GetTextHeight() )+ CalcZoom( 4 );
+
+ // Set the title and ListBox
+ tools::Long n5Pos = CalcZoom(5);
+ tools::Long nPositionX = n5Pos;
+ tools::Long nPositionY = n5Pos;
+
+ Size aPreferredSize = m_xTitle->get_preferred_size();
+ if (nTitleHeight < aPreferredSize.Height())
+ nTitleHeight = aPreferredSize.Height();
+
+ m_xTitle->SetPosSizePixel( Point( nPositionX, nPositionY ), Size( aOutSize.Width() - nPositionX - n5Pos, nTitleHeight ) );
+
+ tools::Long nTitleToList = CalcZoom( 3 );
+
+ m_xListBox->SetPosSizePixel(
+ Point( n5Pos, nPositionY + nTitleHeight + nTitleToList ),
+ Size( aOutSize.Width() - 2 * n5Pos, aOutSize.Height() - ( nPositionY + nTitleHeight + nTitleToList ) - n5Pos )
+ );
+
+ Window::Invalidate();
+}
+
+void OTableWindow::SetBoldTitle( bool bBold )
+{
+ weld::Label& rLabel = m_xTitle->GetLabel();
+ vcl::Font aFont = rLabel.get_font();
+ aFont.SetWeight(bBold ? WEIGHT_BOLD : WEIGHT_NORMAL);
+ rLabel.set_font(aFont);
+}
+
+void OTableWindow::GetFocus()
+{
+ Window::GetFocus();
+ // we have to forward the focus to our listbox to enable keystrokes
+ if(m_xListBox)
+ m_xListBox->GrabFocus();
+}
+
+void OTableWindow::setActive(bool _bActive)
+{
+ SetBoldTitle( _bActive );
+ if (_bActive || !m_xListBox)
+ return;
+
+ weld::TreeView& rTreeView = m_xListBox->get_widget();
+ if (rTreeView.get_selected_index() != -1)
+ rTreeView.unselect_all();
+}
+
+void OTableWindow::Remove()
+{
+ // Delete the window
+ OJoinTableView* pTabWinCont = getTableView();
+ VclPtr<OTableWindow> aHoldSelf(this); // keep ourselves alive during the RemoveTabWin process
+ pTabWinCont->RemoveTabWin( this );
+ pTabWinCont->Invalidate();
+}
+
+bool OTableWindow::ExistsAConn() const
+{
+ return getTableView()->ExistsAConn(this);
+}
+
+void OTableWindow::EnumValidFields(std::vector< OUString>& arrstrFields)
+{
+ arrstrFields.clear();
+ weld::TreeView& rTreeView = m_xListBox->get_widget();
+
+ // This default implementation counts every item in the ListBox ... for any other behaviour it must be over-written
+ rTreeView.all_foreach([&rTreeView, &arrstrFields](weld::TreeIter& rEntry){
+ arrstrFields.push_back(rTreeView.get_text(rEntry));
+ return false;
+ });
+}
+
+void OTableWindow::StateChanged( StateChangedType nType )
+{
+ Window::StateChanged( nType );
+
+ // FIXME RenderContext
+
+ if ( nType != StateChangedType::Zoom )
+ return;
+
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+
+ vcl::Font aFont = rStyleSettings.GetGroupFont();
+ if ( IsControlFont() )
+ aFont.Merge( GetControlFont() );
+ SetZoomedPointFont(*GetOutDev(), aFont);
+
+ m_xTitle->SetZoom(GetZoom());
+ m_xListBox->SetZoom(GetZoom());
+ Resize();
+ Invalidate();
+}
+
+Reference< XAccessible > OTableWindow::CreateAccessible()
+{
+ return new OTableWindowAccess(this);
+}
+
+void OTableWindow::Command(const CommandEvent& rEvt)
+{
+ switch (rEvt.GetCommand())
+ {
+ case CommandEventId::ContextMenu:
+ {
+ OJoinController& rController = getDesignView()->getController();
+ if(!rController.isReadOnly() && rController.isConnected())
+ {
+ Point ptWhere;
+ if ( rEvt.IsMouseEvent() )
+ ptWhere = rEvt.GetMousePosPixel();
+ else
+ {
+ weld::TreeView& rTreeView = m_xListBox->get_widget();
+ std::unique_ptr<weld::TreeIter> xCurrent = rTreeView.make_iterator();
+ if (rTreeView.get_cursor(xCurrent.get()))
+ ptWhere = rTreeView.get_row_area(*xCurrent).Center();
+ else
+ ptWhere = m_xTitle->GetPosPixel();
+ }
+
+ ::tools::Rectangle aRect(ptWhere, Size(1, 1));
+ weld::Window* pPopupParent = weld::GetPopupParent(*this, aRect);
+ std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(pPopupParent, "dbaccess/ui/jointablemenu.ui"));
+ std::unique_ptr<weld::Menu> xContextMenu(xBuilder->weld_menu("menu"));
+ if (!xContextMenu->popup_at_rect(pPopupParent, aRect).isEmpty())
+ Remove();
+ }
+ break;
+ }
+ default:
+ Window::Command(rEvt);
+ }
+}
+
+bool OTableWindow::PreNotify(NotifyEvent& rNEvt)
+{
+ bool bHandled = false;
+ switch (rNEvt.GetType())
+ {
+ case MouseNotifyEvent::KEYINPUT:
+ {
+ if ( getDesignView()->getController().isReadOnly() )
+ break;
+
+ const KeyEvent* pKeyEvent = rNEvt.GetKeyEvent();
+ const vcl::KeyCode& rCode = pKeyEvent->GetKeyCode();
+ if ( rCode.IsMod1() )
+ {
+ Point aStartPoint = GetPosPixel();
+ if ( rCode.IsShift() )
+ {
+ aStartPoint.setX( GetSizePixel().Width() );
+ aStartPoint.setY( GetSizePixel().Height() );
+ }
+
+ switch( rCode.GetCode() )
+ {
+ case KEY_DOWN:
+ bHandled = true;
+ aStartPoint.AdjustY(m_nMoveIncrement );
+ break;
+ case KEY_UP:
+ bHandled = true;
+ aStartPoint.AdjustY(-m_nMoveIncrement );
+ break;
+ case KEY_LEFT:
+ bHandled = true;
+ aStartPoint.AdjustX(-m_nMoveIncrement );
+ break;
+ case KEY_RIGHT:
+ bHandled = true;
+ aStartPoint.AdjustX(m_nMoveIncrement );
+ break;
+ }
+ if ( bHandled )
+ {
+ if ( rCode.IsShift() )
+ {
+ OJoinTableView* pView = getTableView();
+ Point ptOld = GetPosPixel();
+ Size aSize = pView->getRealOutputSize();
+ Size aNewSize(aStartPoint.X(),aStartPoint.Y());
+ if ( ((ptOld.X() + aNewSize.Width()) <= aSize.Width())
+ && ((ptOld.Y() + aNewSize.Height()) <= aSize.Height()) )
+ {
+ if ( aNewSize.Width() < TABWIN_WIDTH_MIN )
+ aNewSize.setWidth( TABWIN_WIDTH_MIN );
+ if ( aNewSize.Height() < TABWIN_HEIGHT_MIN )
+ aNewSize.setHeight( TABWIN_HEIGHT_MIN );
+
+ Size szOld = GetSizePixel();
+
+ aNewSize = Size(pView->CalcZoom(aNewSize.Width()),pView->CalcZoom(aNewSize.Height()));
+ SetPosSizePixel( ptOld, aNewSize );
+ pView->TabWinSized(this, ptOld, szOld);
+ Invalidate( InvalidateFlags::NoChildren );
+ }
+ }
+ else
+ {
+ // remember how often the user moved our window
+ ++m_nMoveCount;
+ if( m_nMoveCount == 5 )
+ m_nMoveIncrement = 10;
+ else if( m_nMoveCount > 15 )
+ m_nMoveCount = m_nMoveIncrement = 20;
+
+ Point aOldDataPoint = GetData()->GetPosition();
+ Point aNewDataPoint = aStartPoint + getTableView()->GetScrollOffset();
+ if ( aNewDataPoint.X() > -1 && aNewDataPoint.Y() > -1 )
+ {
+ OJoinTableView* pView = getTableView();
+ if ( pView->isMovementAllowed(aNewDataPoint, GetData()->GetSize()) )
+ {
+ SetPosPixel(aStartPoint);
+
+ // aNewDataPoint can not be used here because SetPosPixel reset it
+ pView->EnsureVisible(GetData()->GetPosition(), GetData()->GetSize());
+ pView->TabWinMoved(this,aOldDataPoint);
+ Invalidate(InvalidateFlags::NoChildren);
+ getDesignView()->getController().setModified( true );
+ }
+ else
+ {
+ m_nMoveCount = 0; // reset our movement count
+ m_nMoveIncrement = 1;
+ }
+ }
+ else
+ {
+ m_nMoveCount = 0; // reset our movement count
+ m_nMoveIncrement = 1;
+ }
+ }
+ m_nSizingFlags = SizingFlags::NONE;
+ }
+ else
+ {
+ m_nMoveCount = 0; // reset our movement count
+ m_nMoveIncrement = 1;
+ }
+ }
+ else
+ {
+ m_nMoveCount = 0; // reset our movement count
+ m_nMoveIncrement = 1;
+ }
+ break;
+ }
+ case MouseNotifyEvent::KEYUP:
+ {
+ const KeyEvent* pKeyEvent = rNEvt.GetKeyEvent();
+ const vcl::KeyCode& rCode = pKeyEvent->GetKeyCode();
+ sal_uInt16 nKeyCode = rCode.GetCode();
+ if ( rCode.IsMod2() && nKeyCode != KEY_UP && nKeyCode != KEY_DOWN && nKeyCode != KEY_LEFT && nKeyCode != KEY_RIGHT )
+ {
+ m_nMoveCount = 0; // reset our movement count
+ m_nMoveIncrement = 1;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ if (!bHandled)
+ return Window::PreNotify(rNEvt);
+ return true;
+}
+
+OUString OTableWindow::getTitle() const
+{
+ return m_xTitle->GetLabel().get_label();
+}
+
+void OTableWindow::_elementInserted( const container::ContainerEvent& /*_rEvent*/ )
+{
+ FillListBox();
+}
+
+void OTableWindow::_elementRemoved( const container::ContainerEvent& /*_rEvent*/ )
+{
+ FillListBox();
+}
+
+void OTableWindow::_elementReplaced( const container::ContainerEvent& /*_rEvent*/ )
+{
+ FillListBox();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/querydesign/TableWindowAccess.cxx b/dbaccess/source/ui/querydesign/TableWindowAccess.cxx
new file mode 100644
index 000000000..787d257b5
--- /dev/null
+++ b/dbaccess/source/ui/querydesign/TableWindowAccess.cxx
@@ -0,0 +1,250 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <TableWindowAccess.hxx>
+#include <TableWindow.hxx>
+#include <TableWindowListBox.hxx>
+#include <JoinTableView.hxx>
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <com/sun/star/accessibility/AccessibleRelationType.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <comphelper/sequence.hxx>
+#include <vcl/vclevent.hxx>
+
+namespace dbaui
+{
+ using namespace ::com::sun::star::accessibility;
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::beans;
+ using namespace ::com::sun::star::lang;
+ using namespace ::com::sun::star;
+
+ OTableWindowAccess::OTableWindowAccess(OTableWindow* _pTable)
+ :VCLXAccessibleComponent(_pTable->GetComponentInterface().is() ? _pTable->GetWindowPeer() : nullptr)
+ ,m_pTable(_pTable)
+ {
+ }
+ void SAL_CALL OTableWindowAccess::disposing()
+ {
+ m_pTable = nullptr;
+ VCLXAccessibleComponent::disposing();
+ }
+ void OTableWindowAccess::ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent )
+ {
+ if ( rVclWindowEvent.GetId() == VclEventId::ObjectDying )
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+ m_pTable = nullptr;
+ }
+
+ VCLXAccessibleComponent::ProcessWindowEvent( rVclWindowEvent );
+ }
+ Any SAL_CALL OTableWindowAccess::queryInterface( const Type& aType )
+ {
+ Any aRet(VCLXAccessibleComponent::queryInterface( aType ));
+ return aRet.hasValue() ? aRet : OTableWindowAccess_BASE::queryInterface( aType );
+ }
+ Sequence< Type > SAL_CALL OTableWindowAccess::getTypes( )
+ {
+ return ::comphelper::concatSequences(VCLXAccessibleComponent::getTypes(),OTableWindowAccess_BASE::getTypes());
+ }
+ OUString SAL_CALL OTableWindowAccess::getImplementationName()
+ {
+ return "org.openoffice.comp.dbu.TableWindowAccessibility";
+ }
+ Sequence< OUString > SAL_CALL OTableWindowAccess::getSupportedServiceNames()
+ {
+ return { "com.sun.star.accessibility.Accessible",
+ "com.sun.star.accessibility.AccessibleContext" };
+ }
+ // XAccessibleContext
+ sal_Int32 SAL_CALL OTableWindowAccess::getAccessibleChildCount( )
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+ sal_Int32 nCount = 0;
+ if(m_pTable)
+ {
+ ++nCount;
+ if(m_pTable->GetListBox())
+ ++nCount;
+ }
+ return nCount;
+ }
+ Reference< XAccessible > SAL_CALL OTableWindowAccess::getAccessibleChild( sal_Int32 i )
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+ Reference< XAccessible > aRet;
+ if (m_pTable && !m_pTable->isDisposed())
+ {
+ switch(i)
+ {
+ case 0:
+ {
+ VclPtr<OTableWindowTitle> xCtrl(m_pTable->GetTitleCtrl());
+ if (xCtrl)
+ aRet = xCtrl->GetAccessible();
+ break;
+ }
+ case 1:
+ {
+ VclPtr<OTableWindowListBox> xCtrl(m_pTable->GetListBox());
+ if (xCtrl)
+ aRet = xCtrl->GetAccessible();
+ break;
+ }
+ default:
+ throw IndexOutOfBoundsException();
+ }
+ }
+ return aRet;
+ }
+ sal_Int32 SAL_CALL OTableWindowAccess::getAccessibleIndexInParent( )
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+ sal_Int32 nIndex = -1;
+ if( m_pTable )
+ {
+ // search the position of our table window in the table window map
+ bool bFoundElem = false;
+ for (auto const& tabWin : m_pTable->getTableView()->GetTabWinMap())
+ {
+ if (tabWin.second == m_pTable)
+ {
+ bFoundElem = true;
+ break;
+ }
+ ++nIndex;
+ }
+ nIndex = bFoundElem? nIndex : -1;
+ }
+ return nIndex;
+ }
+ sal_Int16 SAL_CALL OTableWindowAccess::getAccessibleRole( )
+ {
+ return AccessibleRole::PANEL; // ? or may be an AccessibleRole::WINDOW
+ }
+ Reference< XAccessibleRelationSet > SAL_CALL OTableWindowAccess::getAccessibleRelationSet( )
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+ return this;
+ }
+ // XAccessibleComponent
+ Reference< XAccessible > SAL_CALL OTableWindowAccess::getAccessibleAtPoint( const awt::Point& _aPoint )
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+ Reference< XAccessible > aRet;
+ if(m_pTable && !m_pTable->isDisposed())
+ {
+ Point aPoint(_aPoint.X,_aPoint.Y);
+ tools::Rectangle aRect(m_pTable->GetDesktopRectPixel());
+ if( aRect.Contains(aPoint) )
+ aRet = this;
+ else if( m_pTable->GetListBox()->GetDesktopRectPixel().Contains(aPoint))
+ aRet = m_pTable->GetListBox()->GetAccessible();
+ }
+ return aRet;
+ }
+ Reference< XAccessible > OTableWindowAccess::getParentChild(sal_Int32 _nIndex)
+ {
+ Reference< XAccessible > xReturn;
+ Reference< XAccessible > xParent = getAccessibleParent();
+ if ( xParent.is() )
+ {
+ Reference< XAccessibleContext > xParentContext = xParent->getAccessibleContext();
+ if ( xParentContext.is() )
+ {
+ xReturn = xParentContext->getAccessibleChild(_nIndex);
+ }
+ }
+ return xReturn;
+ }
+
+ sal_Int32 SAL_CALL OTableWindowAccess::getRelationCount( )
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+ return m_pTable ? m_pTable->getTableView()->getConnectionCount(m_pTable) : sal_Int32(0);
+ }
+ AccessibleRelation SAL_CALL OTableWindowAccess::getRelation( sal_Int32 nIndex )
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+ if( nIndex < 0 || nIndex >= getRelationCount() )
+ throw IndexOutOfBoundsException();
+
+ AccessibleRelation aRet;
+ if( m_pTable )
+ {
+ OJoinTableView* pView = m_pTable->getTableView();
+ auto aIter = pView->getTableConnections(m_pTable) + nIndex;
+ aRet.TargetSet = { getParentChild(aIter - pView->getTableConnections().begin()) };
+ aRet.RelationType = AccessibleRelationType::CONTROLLER_FOR;
+ }
+ return aRet;
+ }
+ sal_Bool SAL_CALL OTableWindowAccess::containsRelation( sal_Int16 aRelationType )
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+ return AccessibleRelationType::CONTROLLER_FOR == aRelationType
+ && m_pTable && m_pTable->getTableView()->ExistsAConn(m_pTable);
+ }
+ AccessibleRelation SAL_CALL OTableWindowAccess::getRelationByType( sal_Int16 aRelationType )
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+ if( AccessibleRelationType::CONTROLLER_FOR == aRelationType && m_pTable)
+ {
+ OJoinTableView* pView = m_pTable->getTableView();
+ const auto& rConnectionList = pView->getTableConnections();
+
+ auto aIter = pView->getTableConnections(m_pTable);
+ auto aEnd = rConnectionList.end();
+ std::vector< Reference<XInterface> > aRelations;
+ aRelations.reserve(5); // just guessing
+ // TODO JNA aIter comes from pView->getTableConnections(m_pTable)
+ // and aEnd comes from pView->getTableConnections().end()
+ for (; aIter != aEnd ; ++aIter )
+ {
+ uno::Reference<uno::XInterface> xInterface(
+ getParentChild(aIter - rConnectionList.begin()));
+ aRelations.push_back(xInterface);
+ }
+
+ Sequence< Reference<XInterface> > aSeq(aRelations.data(), aRelations.size());
+ return AccessibleRelation(AccessibleRelationType::CONTROLLER_FOR,aSeq);
+ }
+ return AccessibleRelation();
+ }
+ OUString SAL_CALL OTableWindowAccess::getTitledBorderText( )
+ {
+ return getAccessibleName( );
+ }
+ OUString SAL_CALL OTableWindowAccess::getAccessibleName( )
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+ OUString sAccessibleName;
+ if ( m_pTable )
+ sAccessibleName = m_pTable->getTitle();
+ return sAccessibleName;
+ }
+ Reference< XAccessibleContext > SAL_CALL OTableWindowAccess::getAccessibleContext( )
+ {
+ return this;
+ }
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/querydesign/TableWindowData.cxx b/dbaccess/source/ui/querydesign/TableWindowData.cxx
new file mode 100644
index 000000000..d07c8214a
--- /dev/null
+++ b/dbaccess/source/ui/querydesign/TableWindowData.cxx
@@ -0,0 +1,135 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <TableWindowData.hxx>
+#include <osl/diagnose.h>
+#include <com/sun/star/sdb/XQueriesSupplier.hpp>
+#include <com/sun/star/sdbcx/XTablesSupplier.hpp>
+#include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
+#include <com/sun/star/sdbcx/XKeysSupplier.hpp>
+#include <com/sun/star/container/XNameAccess.hpp>
+#include <com/sun/star/container/XIndexAccess.hpp>
+#include <com/sun/star/lang/XComponent.hpp>
+
+using namespace dbaui;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::sdb;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::sdbcx;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::container;
+
+OTableWindowData::OTableWindowData( const Reference< XPropertySet>& _xTable
+ ,const OUString& _rComposedName
+ ,const OUString& rTableName
+ ,const OUString& rWinName )
+ :m_xTable(_xTable)
+ ,m_aTableName( rTableName )
+ ,m_aWinName( rWinName )
+ ,m_sComposedName(_rComposedName)
+ ,m_aPosition( Point(-1,-1) )
+ ,m_aSize( Size(-1,-1) )
+ ,m_bShowAll( true )
+ ,m_bIsQuery(false)
+ ,m_bIsValid(true)
+{
+ if( m_aWinName.isEmpty() )
+ m_aWinName = m_aTableName;
+
+ listen();
+}
+
+OTableWindowData::~OTableWindowData()
+{
+ Reference<XComponent> xComponent( m_xTable, UNO_QUERY );
+ if ( xComponent.is() )
+ stopComponentListening( xComponent );
+}
+
+bool OTableWindowData::HasPosition() const
+{
+ return ( (m_aPosition.X() != -1) && (m_aPosition.Y() != -1) );
+}
+
+bool OTableWindowData::HasSize() const
+{
+ return ( (m_aSize.Width() != -1) && (m_aSize.Height() !=-1) );
+}
+
+void OTableWindowData::_disposing( const css::lang::EventObject& /*_rSource*/ )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ // it doesn't matter which one was disposed
+ m_xColumns.clear();
+ m_xKeys.clear();
+ m_xTable.clear();
+}
+
+bool OTableWindowData::init(const Reference< XConnection >& _xConnection,bool _bAllowQueries)
+{
+ OSL_ENSURE(!m_xTable.is(),"We are already connected to a table!");
+
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ Reference< XQueriesSupplier > xSupQueries( _xConnection, UNO_QUERY_THROW );
+ Reference< XNameAccess > xQueries( xSupQueries->getQueries(), UNO_SET_THROW );
+ bool bIsKnownQuery = _bAllowQueries && xQueries->hasByName( m_sComposedName );
+
+ Reference< XTablesSupplier > xSupTables( _xConnection, UNO_QUERY_THROW );
+ Reference< XNameAccess > xTables( xSupTables->getTables(), UNO_SET_THROW );
+ bool bIsKnownTable = xTables->hasByName( m_sComposedName );
+
+ if ( bIsKnownQuery )
+ m_xTable.set( xQueries->getByName( m_sComposedName ), UNO_QUERY );
+ else if ( bIsKnownTable )
+ m_xTable.set( xTables->getByName( m_sComposedName ), UNO_QUERY );
+ else
+ m_bIsValid = false;
+
+ // if we survived so far, we know whether it's a query
+ m_bIsQuery = bIsKnownQuery;
+
+ listen();
+
+ Reference< XIndexAccess > xColumnsAsIndex( m_xColumns,UNO_QUERY );
+ return xColumnsAsIndex.is() && ( xColumnsAsIndex->getCount() > 0 );
+}
+
+void OTableWindowData::listen()
+{
+ if ( !m_xTable.is() )
+ return;
+
+ // listen for the object being disposed
+ Reference<XComponent> xComponent( m_xTable, UNO_QUERY );
+ if ( xComponent.is() )
+ startComponentListening( xComponent );
+
+ // obtain the columns
+ Reference< XColumnsSupplier > xColumnsSups( m_xTable, UNO_QUERY);
+ if ( xColumnsSups.is() )
+ m_xColumns = xColumnsSups->getColumns();
+
+ Reference<XKeysSupplier> xKeySup(m_xTable,UNO_QUERY);
+ if ( xKeySup.is() )
+ m_xKeys = xKeySup->getKeys();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/querydesign/TableWindowListBox.cxx b/dbaccess/source/ui/querydesign/TableWindowListBox.cxx
new file mode 100644
index 000000000..3066f8429
--- /dev/null
+++ b/dbaccess/source/ui/querydesign/TableWindowListBox.cxx
@@ -0,0 +1,292 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <TableWindowListBox.hxx>
+#include <TableWindow.hxx>
+#include <JoinController.hxx>
+#include <JoinExchange.hxx>
+#include <JoinTableView.hxx>
+#include <JoinDesignView.hxx>
+#include <osl/diagnose.h>
+#include <com/sun/star/sdbc/XDatabaseMetaData.hpp>
+#include <com/sun/star/sdbc/SQLException.hpp>
+#include <vcl/svapp.hxx>
+#include <vcl/commandevent.hxx>
+#include <o3tl/string_view.hxx>
+
+using namespace dbaui;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::datatransfer;
+
+OJoinExchangeData::OJoinExchangeData(OTableWindowListBox* pBox)
+ : pListBox(pBox)
+ , nEntry(pBox->get_widget().get_selected_index())
+{
+}
+
+OTableWindowListBox::OTableWindowListBox(OTableWindow* pParent)
+ : InterimItemWindow(pParent, "dbaccess/ui/tablelistbox.ui", "TableListBox")
+ , m_xTreeView(m_xBuilder->weld_tree_view("treeview"))
+ , m_xDragDropTargetHelper(new TableWindowListBoxHelper(*this, m_xTreeView->get_drop_target()))
+ , m_pTabWin(pParent)
+ , m_nDropEvent(nullptr)
+ , m_nUiEvent(nullptr)
+{
+ m_xTreeView->connect_row_activated(LINK(this, OTableWindowListBox, OnDoubleClick));
+ m_xTreeView->connect_visible_range_changed(LINK(this, OTableWindowListBox, ScrollHdl));
+ m_xTreeView->connect_popup_menu(LINK(this, OTableWindowListBox, CommandHdl));
+
+ m_xHelper.set(new OJoinExchObj);
+ rtl::Reference<TransferDataContainer> xHelper(m_xHelper);
+ m_xTreeView->enable_drag_source(xHelper, DND_ACTION_LINK);
+ m_xTreeView->connect_drag_begin(LINK(this, OTableWindowListBox, DragBeginHdl));
+}
+
+IMPL_LINK(OTableWindowListBox, CommandHdl, const CommandEvent&, rCEvt, bool)
+{
+ if (rCEvt.GetCommand() != CommandEventId::ContextMenu)
+ return false;
+ m_pTabWin->Command(rCEvt);
+ return true;
+}
+
+void OTableWindowListBox::dragFinished()
+{
+ // first show the error msg when existing
+ m_pTabWin->getDesignView()->getController().showError(
+ m_pTabWin->getDesignView()->getController().clearOccurredError());
+ // second look for ui activities which should happen after d&d
+ if (m_nUiEvent)
+ Application::RemoveUserEvent(m_nUiEvent);
+ m_nUiEvent
+ = Application::PostUserEvent(LINK(this, OTableWindowListBox, LookForUiHdl), nullptr, true);
+}
+
+OTableWindowListBox::~OTableWindowListBox() { disposeOnce(); }
+
+void OTableWindowListBox::dispose()
+{
+ if (m_nDropEvent)
+ Application::RemoveUserEvent(m_nDropEvent);
+ if (m_nUiEvent)
+ Application::RemoveUserEvent(m_nUiEvent);
+ m_pTabWin.clear();
+ m_xDragDropTargetHelper.reset();
+ m_xTreeView.reset();
+ InterimItemWindow::dispose();
+}
+
+int OTableWindowListBox::GetEntryFromText(std::u16string_view rEntryText)
+{
+ // iterate through the list
+ OJoinDesignView* pView = m_pTabWin->getDesignView();
+ OJoinController& rController = pView->getController();
+
+ try
+ {
+ bool bCase = false;
+ const Reference<XConnection>& xConnection = rController.getConnection();
+ if (xConnection.is())
+ {
+ Reference<XDatabaseMetaData> xMeta = xConnection->getMetaData();
+ if (xMeta.is())
+ bCase = xMeta->supportsMixedCaseQuotedIdentifiers();
+ }
+ for (int nEntry = 0, nCount = m_xTreeView->n_children(); nEntry < nCount; ++nEntry)
+ {
+ if (bCase ? rEntryText == m_xTreeView->get_text(nEntry)
+ : o3tl::equalsIgnoreAsciiCase(rEntryText, m_xTreeView->get_text(nEntry)))
+ return nEntry;
+ }
+ }
+ catch (SQLException&)
+ {
+ }
+
+ return -1;
+}
+
+IMPL_LINK_NOARG(OTableWindowListBox, ScrollHdl, weld::TreeView&, void)
+{
+ // connections of this table, if any, should be redrawn
+ m_pTabWin->getTableView()->Invalidate(InvalidateFlags::NoChildren);
+}
+
+IMPL_LINK(OTableWindowListBox, DragBeginHdl, bool&, rUnsetDragIcon, bool)
+{
+ rUnsetDragIcon = false;
+ if (m_xTreeView->get_selected_index() == -1)
+ {
+ // no drag without a field
+ return true;
+ }
+
+ OJoinTableView* pCont = m_pTabWin->getTableView();
+ if (!pCont->getDesignView()->getController().isReadOnly()
+ && pCont->getDesignView()->getController().isConnected())
+ {
+ // asterisk was not allowed to be copied to selection browsebox
+ bool bFirstNotAllowed = m_xTreeView->is_selected(0) && m_pTabWin->GetData()->IsShowAll();
+ // create a description of the source
+ OJoinExchangeData jxdSource(this);
+ // update the exchange object
+ m_xHelper->setDescriptors(jxdSource, bFirstNotAllowed);
+
+ return false;
+ }
+
+ return true;
+}
+
+sal_Int8 OTableWindowListBox::AcceptDrop(const AcceptDropEvent& _rEvt)
+{
+ // to enable the autoscroll when we're close to the edges
+ std::unique_ptr<weld::TreeIter> xEntry(m_xTreeView->make_iterator());
+ bool bHasDestRow = m_xTreeView->get_dest_row_at_pos(_rEvt.maPosPixel, xEntry.get(), true);
+
+ sal_Int8 nDND_Action = DND_ACTION_NONE;
+ // check the format
+ if (!OJoinExchObj::isFormatAvailable(
+ m_xDragDropTargetHelper->GetDataFlavorExVector(),
+ SotClipboardFormatId::SBA_TABID) // this means that the first entry is to be dragged
+ && OJoinExchObj::isFormatAvailable(m_xDragDropTargetHelper->GetDataFlavorExVector()))
+ { // don't drop into the window if it's the drag source itself
+
+ // remove the selection if the dragging operation is leaving the window
+ if (_rEvt.mbLeaving)
+ m_xTreeView->unselect_all();
+ else
+ {
+ if (!bHasDestRow)
+ return DND_ACTION_NONE;
+
+ // automatically select right entry when dragging
+ m_xTreeView->unselect_all();
+ m_xTreeView->select(*xEntry);
+
+ // one cannot drop on the first (*) entry
+ if (!(m_pTabWin->GetData()->IsShowAll()
+ && (m_xTreeView->get_iter_index_in_parent(*xEntry) == 0)))
+ nDND_Action = DND_ACTION_LINK;
+ }
+ }
+ return nDND_Action;
+}
+
+IMPL_LINK_NOARG(OTableWindowListBox, LookForUiHdl, void*, void)
+{
+ m_nUiEvent = nullptr;
+ m_pTabWin->getTableView()->lookForUiActivities();
+}
+
+IMPL_LINK_NOARG(OTableWindowListBox, DropHdl, void*, void)
+{
+ // create the connection
+ m_nDropEvent = nullptr;
+ OSL_ENSURE(m_pTabWin, "No TableWindow!");
+ try
+ {
+ OJoinTableView* pCont = m_pTabWin->getTableView();
+ OSL_ENSURE(pCont, "No QueryTableView!");
+ pCont->AddConnection(m_aDropInfo.aSource, m_aDropInfo.aDest);
+ }
+ catch (const SQLException& e)
+ {
+ // remember the exception so that we can show them later when d&d is finished
+ m_pTabWin->getDesignView()->getController().setErrorOccurred(
+ ::dbtools::SQLExceptionInfo(e));
+ }
+}
+
+sal_Int8 OTableWindowListBox::ExecuteDrop(const ExecuteDropEvent& _rEvt)
+{
+ TransferableDataHelper aDropped(_rEvt.maDropEvent.Transferable);
+ if (OJoinExchObj::isFormatAvailable(aDropped.GetDataFlavorExVector()))
+ { // don't drop into the window if it's the drag source itself
+ m_aDropInfo.aSource = OJoinExchangeData(this);
+ m_aDropInfo.aDest = OJoinExchObj::GetSourceDescription(_rEvt.maDropEvent.Transferable);
+
+ if (m_nDropEvent)
+ Application::RemoveUserEvent(m_nDropEvent);
+ m_nDropEvent
+ = Application::PostUserEvent(LINK(this, OTableWindowListBox, DropHdl), nullptr, true);
+
+ dragFinished();
+
+ return DND_ACTION_NONE;
+ }
+ return DND_ACTION_NONE;
+}
+
+void OTableWindowListBox::LoseFocus()
+{
+ if (m_pTabWin)
+ m_pTabWin->setActive(false);
+ InterimItemWindow::LoseFocus();
+}
+
+void OTableWindowListBox::GetFocus()
+{
+ if (m_pTabWin)
+ m_pTabWin->setActive();
+
+ if (m_xTreeView)
+ {
+ std::unique_ptr<weld::TreeIter> xCurrent = m_xTreeView->make_iterator();
+ if (m_xTreeView->get_cursor(xCurrent.get()))
+ {
+ m_xTreeView->unselect_all();
+ m_xTreeView->select(*xCurrent);
+ }
+ }
+
+ InterimItemWindow::GetFocus();
+}
+
+IMPL_LINK_NOARG(OTableWindowListBox, OnDoubleClick, weld::TreeView&, bool)
+{
+ // tell my parent
+ vcl::Window* pParent = Window::GetParent();
+ OSL_ENSURE(pParent != nullptr, "OTableWindowListBox::OnDoubleClick : have no Parent !");
+
+ std::unique_ptr<weld::TreeIter> xCurrent = m_xTreeView->make_iterator();
+ if (!m_xTreeView->get_cursor(xCurrent.get()))
+ return false;
+
+ static_cast<OTableWindow*>(pParent)->OnEntryDoubleClicked(*xCurrent);
+
+ return false;
+}
+
+void OTableWindowListBox::Command(const CommandEvent& rEvt)
+{
+ switch (rEvt.GetCommand())
+ {
+ case CommandEventId::ContextMenu:
+ {
+ static_cast<OTableWindow*>(Window::GetParent())->Command(rEvt);
+ break;
+ }
+ default:
+ InterimItemWindow::Command(rEvt);
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/querydesign/TableWindowTitle.cxx b/dbaccess/source/ui/querydesign/TableWindowTitle.cxx
new file mode 100644
index 000000000..50eb19c28
--- /dev/null
+++ b/dbaccess/source/ui/querydesign/TableWindowTitle.cxx
@@ -0,0 +1,97 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <TableWindowTitle.hxx>
+#include <TableWindow.hxx>
+#include <vcl/commandevent.hxx>
+#include <vcl/event.hxx>
+#include <TableWindowListBox.hxx>
+#include <TableConnection.hxx>
+#include <JoinController.hxx>
+
+using namespace dbaui;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::uno;
+OTableWindowTitle::OTableWindowTitle(OTableWindow* pParent)
+ : InterimItemWindow(pParent, "dbaccess/ui/tabletitle.ui", "TableTitle")
+ , m_pTabWin( pParent )
+ , m_xLabel(m_xBuilder->weld_label("label"))
+ , m_xImage(m_xBuilder->weld_image("image"))
+{
+ m_xLabel->connect_mouse_press(LINK(this, OTableWindowTitle, MousePressHdl));
+}
+
+OTableWindowTitle::~OTableWindowTitle()
+{
+ disposeOnce();
+}
+
+void OTableWindowTitle::dispose()
+{
+ m_xImage.reset();
+ m_xLabel.reset();
+ m_pTabWin.clear();
+ InterimItemWindow::dispose();
+}
+
+IMPL_LINK(OTableWindowTitle, MousePressHdl, const MouseEvent&, rEvt, bool)
+{
+ if (rEvt.IsLeft())
+ {
+ if( rEvt.GetClicks() == 2)
+ {
+ Size aSize(GetTextWidth(GetText()) + 20,
+ m_pTabWin->GetSizePixel().Height() - m_pTabWin->GetListBox()->GetSizePixel().Height());
+
+ weld::TreeView& rTreeView = m_pTabWin->GetListBox()->get_widget();
+ aSize.AdjustHeight(rTreeView.get_height_rows(rTreeView.n_children() + 2));
+ if (m_pTabWin->GetSizePixel() != aSize)
+ {
+ m_pTabWin->SetSizePixel(aSize);
+
+ OJoinTableView* pView = m_pTabWin->getTableView();
+ OSL_ENSURE(pView,"No OJoinTableView!");
+ for (auto& conn : pView->getTableConnections())
+ conn->RecalcLines();
+
+ pView->InvalidateConnections();
+ pView->getDesignView()->getController().setModified(true);
+ pView->Invalidate(InvalidateFlags::NoChildren);
+ }
+ }
+ else
+ {
+ Point aPos = rEvt.GetPosPixel();
+ aPos = OutputToScreenPixel( aPos );
+ OJoinTableView* pView = m_pTabWin->getTableView();
+ OSL_ENSURE(pView,"No OJoinTableView!");
+ pView->NotifyTitleClicked( static_cast<OTableWindow*>(GetParent()), aPos );
+ }
+ }
+ else if (rEvt.IsRight())
+ {
+ CommandEvent aCEvt(rEvt.GetPosPixel(), CommandEventId::ContextMenu, true);
+ // tdf#94709 - protect shutdown code-path.
+ VclPtr<OTableWindow> xTabWin(m_pTabWin);
+ xTabWin->Command(aCEvt);
+ }
+ return false;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/querydesign/class.jpg b/dbaccess/source/ui/querydesign/class.jpg
new file mode 100644
index 000000000..b1a3b6d27
--- /dev/null
+++ b/dbaccess/source/ui/querydesign/class.jpg
Binary files differ
diff --git a/dbaccess/source/ui/querydesign/limitboxcontroller.cxx b/dbaccess/source/ui/querydesign/limitboxcontroller.cxx
new file mode 100644
index 000000000..8b6884338
--- /dev/null
+++ b/dbaccess/source/ui/querydesign/limitboxcontroller.cxx
@@ -0,0 +1,322 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "limitboxcontroller.hxx"
+
+#include <com/sun/star/frame/XDispatchProvider.hpp>
+#include <com/sun/star/frame/XFrame.hpp>
+#include <com/sun/star/beans/PropertyValue.hpp>
+#include <com/sun/star/util/XURLTransformer.hpp>
+
+#include <comphelper/propertyvalue.hxx>
+#include <vcl/InterimItemWindow.hxx>
+#include <vcl/event.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/window.hxx>
+#include <toolkit/helper/vclunohelper.hxx>
+#include <cppuhelper/queryinterface.hxx>
+
+#include <core_resource.hxx>
+#include <strings.hrc>
+
+using namespace ::com::sun::star;
+
+namespace
+{
+
+/// Default values
+sal_Int64 const aDefLimitAry[] =
+{
+ 5,
+ 10,
+ 20,
+ 50
+};
+
+}
+
+namespace dbaui
+{
+
+/**
+ * Input box to add limit to an SQL query (maximum number of result's rows)
+ * This box is reachable on the Query Design Toolbar
+ */
+class LimitBox final : public InterimItemWindow
+{
+public:
+ LimitBox(vcl::Window* pParent, LimitBoxController* pCtrl)
+ : InterimItemWindow(pParent, "dbaccess/ui/limitbox.ui", "LimitBox")
+ , m_pControl( pCtrl )
+ , m_xWidget(m_xBuilder->weld_combo_box("limit"))
+ {
+ InitControlBase(m_xWidget.get());
+
+ LoadDefaultLimits();
+
+ m_xWidget->connect_key_press(LINK(this, LimitBox, KeyInputHdl));
+ m_xWidget->connect_entry_activate(LINK(this, LimitBox, ActivateHdl));
+ m_xWidget->connect_changed(LINK(this, LimitBox, ChangeHdl));
+ m_xWidget->connect_focus_out(LINK(this, LimitBox, FocusOutHdl));
+ m_xWidget->set_entry_width_chars(6);
+ SetSizePixel(m_xContainer->get_preferred_size());
+ }
+
+ virtual void dispose() override
+ {
+ m_xWidget.reset();
+ InterimItemWindow::dispose();
+ }
+
+ virtual ~LimitBox() override
+ {
+ disposeOnce();
+ }
+
+ void set_sensitive(bool bSensitive)
+ {
+ m_xWidget->set_sensitive(bSensitive);
+ }
+
+ void set_value(int nLimit)
+ {
+ if (nLimit < 0)
+ m_xWidget->set_active(0);
+ else
+ m_xWidget->set_entry_text(OUString::number(nLimit));
+ m_xWidget->save_value();
+ }
+
+private:
+ LimitBoxController* m_pControl;
+ std::unique_ptr<weld::ComboBox> m_xWidget;
+
+ DECL_LINK(KeyInputHdl, const KeyEvent&, bool);
+ DECL_LINK(ActivateHdl, weld::ComboBox&, bool);
+ DECL_LINK(ChangeHdl, weld::ComboBox&, void);
+ DECL_LINK(FocusOutHdl, weld::Widget&, void);
+
+ void Apply()
+ {
+ if (!m_xWidget->get_value_changed_from_saved())
+ return;
+ sal_Int64 nLimit;
+ OUString sActiveText = m_xWidget->get_active_text();
+ if (sActiveText == DBA_RES(STR_QUERY_LIMIT_ALL))
+ nLimit = -1;
+ else
+ {
+ nLimit = m_xWidget->get_active_text().toInt64();
+ if (nLimit < 0)
+ nLimit = -1;
+ }
+ set_value(nLimit);
+ m_pControl->dispatchCommand({ comphelper::makePropertyValue("DBLimit.Value", nLimit) });
+ }
+
+ ///Initialize entries
+ void LoadDefaultLimits()
+ {
+ m_xWidget->freeze();
+ m_xWidget->append_text(DBA_RES(STR_QUERY_LIMIT_ALL));
+ for (auto nIndex : aDefLimitAry)
+ {
+ m_xWidget->append_text(OUString::number(nIndex));
+ }
+ m_xWidget->thaw();
+ }
+};
+
+IMPL_LINK(LimitBox, KeyInputHdl, const KeyEvent&, rKEvt, bool)
+{
+ bool bHandled = false;
+ const sal_uInt16 nCode = rKEvt.GetKeyCode().GetCode();
+ switch (nCode)
+ {
+ case KEY_ESCAPE:
+ m_xWidget->set_entry_text(m_xWidget->get_saved_value());
+ bHandled = true;
+ break;
+ case KEY_RETURN:
+ {
+ bHandled = ActivateHdl(*m_xWidget);
+ break;
+ }
+ }
+ return bHandled || ChildKeyInput(rKEvt);
+}
+
+IMPL_LINK_NOARG(LimitBox, FocusOutHdl, weld::Widget&, void)
+{
+ if (!m_xWidget || m_xWidget->has_focus()) // comboboxes can be comprised of multiple widgets, ensure all have lost focus
+ return;
+ Apply();
+}
+
+IMPL_LINK(LimitBox, ChangeHdl, weld::ComboBox&, rComboBox, void)
+{
+ if (rComboBox.changed_by_direct_pick())
+ ActivateHdl(rComboBox);
+}
+
+IMPL_LINK_NOARG(LimitBox, ActivateHdl, weld::ComboBox&, bool)
+{
+ GrabFocusToDocument();
+ Apply();
+ return true;
+}
+
+LimitBoxController::LimitBoxController(
+ const uno::Reference< uno::XComponentContext >& rxContext ) :
+ svt::ToolboxController( rxContext,
+ uno::Reference< frame::XFrame >(),
+ ".uno:DBLimit" ),
+ m_xLimitBox( nullptr )
+{
+}
+
+LimitBoxController::~LimitBoxController()
+{
+}
+
+/// XInterface
+uno::Any SAL_CALL LimitBoxController::queryInterface( const uno::Type& aType )
+{
+ uno::Any a = ToolboxController::queryInterface( aType );
+ if ( a.hasValue() )
+ return a;
+
+ return ::cppu::queryInterface( aType, static_cast< lang::XServiceInfo* >( this ));
+}
+
+void SAL_CALL LimitBoxController::acquire() noexcept
+{
+ ToolboxController::acquire();
+}
+
+void SAL_CALL LimitBoxController::release() noexcept
+{
+ ToolboxController::release();
+}
+
+
+/// XServiceInfo
+OUString SAL_CALL LimitBoxController::getImplementationName()
+{
+ return "org.libreoffice.comp.dbu.LimitBoxController";
+}
+
+sal_Bool SAL_CALL LimitBoxController::supportsService(const OUString& _rServiceName)
+ {
+ const css::uno::Sequence< OUString > aSupported(getSupportedServiceNames());
+ for (const OUString& s : aSupported)
+ if (s == _rServiceName)
+ return true;
+
+ return false;
+ }
+
+css::uno::Sequence< OUString > SAL_CALL LimitBoxController::getSupportedServiceNames()
+{
+ return { "com.sun.star.frame.ToolbarController" };
+}
+
+/// XComponent
+void SAL_CALL LimitBoxController::dispose()
+{
+ svt::ToolboxController::dispose();
+
+ SolarMutexGuard aSolarMutexGuard;
+ m_xLimitBox.disposeAndClear();
+}
+
+/// XStatusListener
+void SAL_CALL LimitBoxController::statusChanged(
+ const frame::FeatureStateEvent& rEvent )
+{
+ if ( !m_xLimitBox )
+ return;
+
+ SolarMutexGuard aSolarMutexGuard;
+ if ( rEvent.FeatureURL.Path == "DBLimit" )
+ {
+ if ( rEvent.IsEnabled )
+ {
+ m_xLimitBox->set_sensitive(true);
+ sal_Int64 nLimit = 0;
+ if (rEvent.State >>= nLimit)
+ m_xLimitBox->set_value(nLimit);
+ }
+ else
+ m_xLimitBox->set_sensitive(false);
+ }
+}
+
+/// XToolbarController
+void SAL_CALL LimitBoxController::execute( sal_Int16 /*KeyModifier*/ )
+{
+}
+
+void SAL_CALL LimitBoxController::click()
+{
+}
+
+void SAL_CALL LimitBoxController::doubleClick()
+{
+}
+
+uno::Reference< awt::XWindow > SAL_CALL LimitBoxController::createPopupWindow()
+{
+ return uno::Reference< awt::XWindow >();
+}
+
+uno::Reference< awt::XWindow > SAL_CALL LimitBoxController::createItemWindow(
+ const uno::Reference< awt::XWindow >& xParent )
+{
+ uno::Reference< awt::XWindow > xItemWindow;
+
+ VclPtr<vcl::Window> pParent = VCLUnoHelper::GetWindow( xParent );
+ if ( pParent )
+ {
+ SolarMutexGuard aSolarMutexGuard;
+ m_xLimitBox = VclPtr<LimitBox>::Create(pParent, this);
+ xItemWindow = VCLUnoHelper::GetInterface(m_xLimitBox);
+ }
+
+ return xItemWindow;
+}
+
+void LimitBoxController::dispatchCommand(
+ const uno::Sequence< beans::PropertyValue >& rArgs )
+{
+ uno::Reference< frame::XDispatchProvider > xDispatchProvider( m_xFrame, uno::UNO_QUERY );
+ if ( xDispatchProvider.is() )
+ {
+ util::URL aURL;
+ uno::Reference< frame::XDispatch > xDispatch;
+ uno::Reference< util::XURLTransformer > xURLTransformer = getURLTransformer();
+
+ aURL.Complete = ".uno:DBLimit";
+ xURLTransformer->parseStrict( aURL );
+ xDispatch = xDispatchProvider->queryDispatch( aURL, OUString(), 0 );
+ if ( xDispatch.is() )
+ xDispatch->dispatch( aURL, rArgs );
+ }
+}
+
+} // dbaui namespace
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+org_libreoffice_comp_dbu_LimitBoxController_get_implementation(
+ css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const& )
+{
+ return cppu::acquire(new ::dbaui::LimitBoxController(context));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/querydesign/limitboxcontroller.hxx b/dbaccess/source/ui/querydesign/limitboxcontroller.hxx
new file mode 100644
index 000000000..af1e5a666
--- /dev/null
+++ b/dbaccess/source/ui/querydesign/limitboxcontroller.hxx
@@ -0,0 +1,65 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <connectivity/CommonTools.hxx>
+#include <svtools/toolboxcontroller.hxx>
+#include <vcl/vclptr.hxx>
+
+namespace dbaui
+{
+
+class LimitBox;
+
+/**
+ * A ToolboxController to paste LimitBox onto the Query Design Toolbar
+ * It is communicating with querycontroller and this channel make enable
+ * to set\get the value of limitbox when switching between views
+ */
+class LimitBoxController: public svt::ToolboxController,
+ public css::lang::XServiceInfo
+{
+ public:
+ explicit LimitBoxController(
+ const css::uno::Reference< css::uno::XComponentContext >& rxContext );
+ virtual ~LimitBoxController() override;
+
+ /// XInterface
+ virtual css::uno::Any SAL_CALL queryInterface( const css::uno::Type& aType ) override;
+ virtual void SAL_CALL acquire() noexcept override;
+ virtual void SAL_CALL release() noexcept override;
+
+ /// XServiceInfo
+ DECLARE_SERVICE_INFO();
+
+ /// XComponent
+ virtual void SAL_CALL dispose() override;
+
+ /// XStatusListener
+ virtual void SAL_CALL statusChanged( const css::frame::FeatureStateEvent& Event ) override;
+
+ /// XToolbarController
+ virtual void SAL_CALL execute( sal_Int16 KeyModifier ) override;
+ virtual void SAL_CALL click() override;
+ virtual void SAL_CALL doubleClick() override;
+ virtual css::uno::Reference< css::awt::XWindow > SAL_CALL createPopupWindow() override;
+ virtual css::uno::Reference< css::awt::XWindow > SAL_CALL createItemWindow( const css::uno::Reference< css::awt::XWindow >& Parent ) override;
+
+ void dispatchCommand( const css::uno::Sequence< css::beans::PropertyValue >& rArgs );
+ using svt::ToolboxController::dispatchCommand;
+
+ private:
+ VclPtr<LimitBox> m_xLimitBox;
+};
+
+} ///dbaui namespace
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/querydesign/querycontainerwindow.cxx b/dbaccess/source/ui/querydesign/querycontainerwindow.cxx
new file mode 100644
index 000000000..68b4c5c86
--- /dev/null
+++ b/dbaccess/source/ui/querydesign/querycontainerwindow.cxx
@@ -0,0 +1,222 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <querycontainerwindow.hxx>
+#include <QueryDesignView.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/settings.hxx>
+#include <JoinController.hxx>
+#include <toolkit/helper/vclunohelper.hxx>
+#include <strings.hxx>
+#include <sfx2/sfxsids.hrc>
+#include <vcl/event.hxx>
+#include <UITools.hxx>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/frame/Frame.hpp>
+#include <com/sun/star/util/XCloseable.hpp>
+
+namespace dbaui
+{
+
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::lang;
+ using namespace ::com::sun::star::frame;
+ using namespace ::com::sun::star::beans;
+
+ // OQueryContainerWindow
+ OQueryContainerWindow::OQueryContainerWindow(vcl::Window* pParent, OQueryController& _rController,const Reference< XComponentContext >& _rxContext)
+ :ODataView( pParent, _rController, _rxContext )
+ ,m_pViewSwitch(nullptr)
+ ,m_pBeamer(nullptr)
+ {
+ m_pViewSwitch = new OQueryViewSwitch( this, _rController, _rxContext );
+
+ m_pSplitter = VclPtr<Splitter>::Create(this,WB_VSCROLL);
+ m_pSplitter->Hide();
+ m_pSplitter->SetSplitHdl( LINK( this, OQueryContainerWindow, SplitHdl ) );
+ m_pSplitter->SetBackground( Wallpaper( Application::GetSettings().GetStyleSettings().GetDialogColor() ) );
+ }
+ OQueryContainerWindow::~OQueryContainerWindow()
+ {
+ disposeOnce();
+ }
+ void OQueryContainerWindow::dispose()
+ {
+ {
+ OQueryViewSwitch* pTemp = m_pViewSwitch;
+ m_pViewSwitch = nullptr;
+ delete pTemp;
+ }
+ if ( m_pBeamer )
+ ::dbaui::notifySystemWindow(this,m_pBeamer,::comphelper::mem_fun(&TaskPaneList::RemoveWindow));
+ m_pBeamer.clear();
+ if ( m_xBeamer.is() )
+ {
+ Reference< css::util::XCloseable > xCloseable(m_xBeamer,UNO_QUERY);
+ m_xBeamer = nullptr;
+ if(xCloseable.is())
+ xCloseable->close(false); // false - holds the ownership of this frame
+ }
+
+ m_pSplitter.disposeAndClear();
+ ODataView::dispose();
+ }
+ bool OQueryContainerWindow::switchView( ::dbtools::SQLExceptionInfo* _pErrorInfo )
+ {
+ return m_pViewSwitch->switchView( _pErrorInfo );
+ }
+
+ void OQueryContainerWindow::forceInitialView()
+ {
+ return m_pViewSwitch->forceInitialView();
+ }
+
+ void OQueryContainerWindow::resizeAll( const tools::Rectangle& _rPlayground )
+ {
+ tools::Rectangle aPlayground( _rPlayground );
+
+ if ( m_pBeamer && m_pBeamer->IsVisible() )
+ {
+ // calc pos and size of the splitter
+ Point aSplitPos = m_pSplitter->GetPosPixel();
+ Size aSplitSize = m_pSplitter->GetOutputSizePixel();
+ aSplitSize.setWidth( aPlayground.GetWidth() );
+
+ if ( aSplitPos.Y() <= aPlayground.Top() )
+ aSplitPos.setY( aPlayground.Top() + sal_Int32( aPlayground.GetHeight() * 0.2 ) );
+
+ if ( aSplitPos.Y() + aSplitSize.Height() > aPlayground.GetHeight() )
+ aSplitPos.setY( aPlayground.GetHeight() - aSplitSize.Height() );
+
+ // set pos and size of the splitter
+ m_pSplitter->SetPosSizePixel( aSplitPos, aSplitSize );
+ m_pSplitter->SetDragRectPixel( aPlayground );
+
+ // set pos and size of the beamer
+ Size aBeamerSize( aPlayground.GetWidth(), aSplitPos.Y() );
+ m_pBeamer->SetPosSizePixel( aPlayground.TopLeft(), aBeamerSize );
+
+ // shrink the playground by the size which is occupied by the beamer
+ aPlayground.SetTop( aSplitPos.Y() + aSplitSize.Height() );
+ }
+
+ ODataView::resizeAll( aPlayground );
+ }
+
+ void OQueryContainerWindow::resizeDocumentView( tools::Rectangle& _rPlayground )
+ {
+ m_pViewSwitch->SetPosSizePixel( _rPlayground.TopLeft(), Size( _rPlayground.GetWidth(), _rPlayground.GetHeight() ) );
+
+ ODataView::resizeDocumentView( _rPlayground );
+ }
+
+ void OQueryContainerWindow::GetFocus()
+ {
+ ODataView::GetFocus();
+ if(m_pViewSwitch)
+ m_pViewSwitch->GrabFocus();
+ }
+ IMPL_LINK_NOARG( OQueryContainerWindow, SplitHdl, Splitter*, void )
+ {
+ m_pSplitter->SetPosPixel( Point( m_pSplitter->GetPosPixel().X(),m_pSplitter->GetSplitPosPixel() ) );
+ Resize();
+ }
+
+ void OQueryContainerWindow::Construct()
+ {
+ m_pViewSwitch->Construct();
+ }
+
+ void OQueryContainerWindow::disposingPreview()
+ {
+ if ( m_pBeamer )
+ {
+ // here I know that we will be destroyed from the frame
+ ::dbaui::notifySystemWindow(this,m_pBeamer,::comphelper::mem_fun(&TaskPaneList::RemoveWindow));
+ m_pBeamer = nullptr;
+ m_xBeamer = nullptr;
+ m_pSplitter->Hide();
+ Resize();
+ }
+ }
+ bool OQueryContainerWindow::PreNotify( NotifyEvent& rNEvt )
+ {
+ if (rNEvt.GetType() == MouseNotifyEvent::GETFOCUS && m_pViewSwitch)
+ {
+ OJoinController& rController = m_pViewSwitch->getDesignView()->getController();
+ rController.InvalidateFeature(SID_CUT);
+ rController.InvalidateFeature(SID_COPY);
+ rController.InvalidateFeature(SID_PASTE);
+ }
+ return ODataView::PreNotify(rNEvt);
+ }
+ void OQueryContainerWindow::showPreview(const Reference<XFrame>& _xFrame)
+ {
+ if(m_pBeamer)
+ return;
+
+ m_pBeamer = VclPtr<OBeamer>::Create(this);
+
+ ::dbaui::notifySystemWindow(this,m_pBeamer,::comphelper::mem_fun(&TaskPaneList::AddWindow));
+
+ m_xBeamer = Frame::create( m_pViewSwitch->getORB() );
+ m_xBeamer->initialize( VCLUnoHelper::GetInterface ( m_pBeamer ) );
+
+ // notify layout manager to not create internal toolbars
+ try
+ {
+ Reference < XPropertySet > xLMPropSet(m_xBeamer->getLayoutManager(), UNO_QUERY);
+ if ( xLMPropSet.is() )
+ {
+ xLMPropSet->setPropertyValue( "AutomaticToolbars", Any( false ));
+ }
+ }
+ catch( Exception& )
+ {
+ }
+
+ m_xBeamer->setName(FRAME_NAME_QUERY_PREVIEW);
+
+ // append our frame
+ Reference < XFramesSupplier > xSup(_xFrame,UNO_QUERY);
+ Reference < XFrames > xFrames = xSup->getFrames();
+ xFrames->append( Reference<XFrame>(m_xBeamer,UNO_QUERY_THROW) );
+
+ Size aSize = GetOutputSizePixel();
+ Size aBeamer(aSize.Width(),sal_Int32(aSize.Height()*0.33));
+
+ const tools::Long nFrameHeight = LogicToPixel(Size(0, 3), MapMode(MapUnit::MapAppFont)).Height();
+ Point aPos(0,aBeamer.Height()+nFrameHeight);
+
+ m_pBeamer->SetPosSizePixel(Point(0,0),aBeamer);
+ m_pBeamer->Show();
+
+ m_pSplitter->SetPosSizePixel( Point(0,aBeamer.Height()), Size(aSize.Width(),nFrameHeight) );
+ // a default pos for the splitter, so that the listbox is about 80 (logical) pixels wide
+ m_pSplitter->SetSplitPosPixel( aBeamer.Height() );
+ m_pViewSwitch->SetPosSizePixel(aPos,Size(aBeamer.Width(),aSize.Height() - aBeamer.Height()-nFrameHeight));
+
+ m_pSplitter->Show();
+
+ Resize();
+ }
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/querydesign/querycontroller.cxx b/dbaccess/source/ui/querydesign/querycontroller.cxx
new file mode 100644
index 000000000..230cb7f6e
--- /dev/null
+++ b/dbaccess/source/ui/querydesign/querycontroller.cxx
@@ -0,0 +1,1790 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <browserids.hxx>
+#include <core_resource.hxx>
+#include <strings.hrc>
+#include <strings.hxx>
+#include <query.hrc>
+#include <stringconstants.hxx>
+#include <defaultobjectnamecheck.hxx>
+#include <dlgsave.hxx>
+#include <querycontainerwindow.hxx>
+#include <querycontroller.hxx>
+#include <QueryDesignView.hxx>
+#include <QueryTableView.hxx>
+#include <sqlmessage.hxx>
+#include <TableConnectionData.hxx>
+#include <TableFieldDescription.hxx>
+#include <UITools.hxx>
+#include <QueryPropertiesDialog.hxx>
+
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/container/XNameContainer.hpp>
+#include <com/sun/star/frame/FrameSearchFlag.hpp>
+#include <com/sun/star/lang/XSingleServiceFactory.hpp>
+#include <com/sun/star/sdb/CommandType.hpp>
+#include <com/sun/star/sdb/SQLContext.hpp>
+#include <com/sun/star/sdb/XQueriesSupplier.hpp>
+#include <com/sun/star/sdb/XQueryDefinitionsSupplier.hpp>
+#include <com/sun/star/sdb/XSQLQueryComposerFactory.hpp>
+#include <com/sun/star/sdbcx/XAppend.hpp>
+#include <com/sun/star/sdbcx/XDataDescriptorFactory.hpp>
+#include <com/sun/star/sdbcx/XDrop.hpp>
+#include <com/sun/star/sdbcx/XTablesSupplier.hpp>
+#include <com/sun/star/sdbcx/XViewsSupplier.hpp>
+#include <com/sun/star/ui/dialogs/XExecutableDialog.hpp>
+#include <com/sun/star/util/XCloseable.hpp>
+#include <com/sun/star/util/VetoException.hpp>
+#include <com/sun/star/ui/XUIElement.hpp>
+
+#include <comphelper/propertysequence.hxx>
+#include <comphelper/property.hxx>
+#include <comphelper/types.hxx>
+#include <connectivity/dbexception.hxx>
+#include <connectivity/dbtools.hxx>
+#include <cppuhelper/exc_hlp.hxx>
+#include <svl/undo.hxx>
+#include <toolkit/helper/vclunohelper.hxx>
+#include <tools/diagnose_ex.h>
+#include <osl/diagnose.h>
+#include <vcl/stdtext.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/weld.hxx>
+#include <osl/mutex.hxx>
+#include <o3tl/string_view.hxx>
+#include <memory>
+#include <vector>
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+org_openoffice_comp_dbu_OQueryDesign_get_implementation(
+ css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const& )
+{
+ return cppu::acquire(new ::dbaui::OQueryController(context));
+}
+
+namespace dbaui
+{
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::beans;
+ using namespace ::com::sun::star::frame;
+ using namespace ::com::sun::star::util;
+ using namespace ::com::sun::star::lang;
+
+ namespace {
+
+ class OViewController : public OQueryController
+ {
+ virtual OUString SAL_CALL getImplementationName() override
+ {
+ return "org.openoffice.comp.dbu.OViewDesign";
+ }
+ virtual Sequence< OUString> SAL_CALL getSupportedServiceNames() override
+ {
+ return { "com.sun.star.sdb.ViewDesign" };
+ }
+
+ public:
+ explicit OViewController(const Reference< XComponentContext >& _rM) : OQueryController(_rM){}
+ };
+
+ }
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+org_openoffice_comp_dbu_OViewDesign_get_implementation(
+ css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const& )
+{
+ return cppu::acquire(new ::dbaui::OViewController(context));
+}
+
+namespace dbaui
+{
+ using namespace ::connectivity;
+
+ namespace
+ {
+ OUString lcl_getObjectResourceString(TranslateId pResId, sal_Int32 _nCommandType)
+ {
+ OUString sMessageText = DBA_RES(pResId);
+ OUString sObjectType = DBA_RES(RSC_QUERY_OBJECT_TYPE[_nCommandType]);
+ sMessageText = sMessageText.replaceFirst( "$object$", sObjectType );
+ return sMessageText;
+ }
+ }
+
+using namespace ::com::sun::star::io;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::sdbcx;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::sdb;
+using namespace ::com::sun::star::ui;
+using namespace ::com::sun::star::ui::dialogs;
+using namespace ::com::sun::star::awt;
+using namespace ::dbtools;
+
+using namespace ::comphelper;
+
+namespace
+{
+ void ensureToolbars( OQueryController& _rController, bool _bDesign )
+ {
+ Reference< css::frame::XLayoutManager > xLayoutManager = OGenericUnoController::getLayoutManager( _rController.getFrame() );
+ if ( !xLayoutManager.is() )
+ return;
+
+ xLayoutManager->lock();
+ static constexpr OUStringLiteral s_sDesignToolbar = u"private:resource/toolbar/designobjectbar";
+ static constexpr OUStringLiteral s_sSqlToolbar = u"private:resource/toolbar/sqlobjectbar";
+ if ( _bDesign )
+ {
+ xLayoutManager->destroyElement( s_sSqlToolbar );
+ xLayoutManager->createElement( s_sDesignToolbar );
+ }
+ else
+ {
+ xLayoutManager->destroyElement( s_sDesignToolbar );
+ xLayoutManager->createElement( s_sSqlToolbar );
+ }
+ xLayoutManager->unlock();
+ xLayoutManager->doLayout();
+ }
+
+ /**
+ * The value of m_nLimit is updated when LimitBox loses its focus
+ * So in those case when execution needs recent data, grab the focus
+ * (e.g. execute SQL statement, change views)
+ */
+ void grabFocusFromLimitBox( OQueryController& _rController )
+ {
+ Reference< XLayoutManager > xLayoutManager = OGenericUnoController::getLayoutManager( _rController.getFrame() );
+ Reference< XUIElement > xUIElement = xLayoutManager->getElement("private:resource/toolbar/designobjectbar");
+ if (xUIElement.is())
+ {
+ Reference< XWindow > xWindow(xUIElement->getRealInterface(), css::uno::UNO_QUERY);
+ VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( xWindow );
+ if( pWindow && pWindow->HasChildPathFocus() )
+ {
+ pWindow->GrabFocusToDocument();
+ }
+ }
+ }
+}
+
+OUString SAL_CALL OQueryController::getImplementationName()
+{
+ return "org.openoffice.comp.dbu.OQueryDesign";
+}
+
+Sequence< OUString> SAL_CALL OQueryController::getSupportedServiceNames()
+{
+ return { "com.sun.star.sdb.QueryDesign" };
+}
+
+OQueryController::OQueryController(const Reference< XComponentContext >& _rM)
+ :OJoinController(_rM)
+ ,OQueryController_PBase( getBroadcastHelper() )
+ ,m_pParseContext( new svxform::OSystemParseContext )
+ ,m_aSqlParser( _rM, m_pParseContext.get() )
+ ,m_nLimit(-1)
+ ,m_nVisibleRows(0x400)
+ ,m_nSplitPos(-1)
+ ,m_nCommandType( CommandType::QUERY )
+ ,m_bGraphicalDesign(false)
+ ,m_bDistinct(false)
+ ,m_bEscapeProcessing(true)
+{
+ InvalidateAll();
+
+ registerProperty( PROPERTY_ACTIVECOMMAND, PROPERTY_ID_ACTIVECOMMAND, PropertyAttribute::READONLY | PropertyAttribute::BOUND,
+ &m_sStatement, cppu::UnoType<decltype(m_sStatement)>::get() );
+ registerProperty( PROPERTY_ESCAPE_PROCESSING, PROPERTY_ID_ESCAPE_PROCESSING, PropertyAttribute::READONLY | PropertyAttribute::BOUND,
+ &m_bEscapeProcessing, cppu::UnoType<decltype(m_bEscapeProcessing)>::get() );
+}
+
+OQueryController::~OQueryController()
+{
+ if ( !getBroadcastHelper().bDisposed && !getBroadcastHelper().bInDispose )
+ {
+ OSL_FAIL("Please check who doesn't dispose this component!");
+ // increment ref count to prevent double call of Dtor
+ osl_atomic_increment( &m_refCount );
+ dispose();
+ }
+}
+
+IMPLEMENT_FORWARD_XINTERFACE2( OQueryController, OJoinController, OQueryController_PBase )
+IMPLEMENT_FORWARD_XTYPEPROVIDER2( OQueryController, OJoinController, OQueryController_PBase )
+
+Reference< XPropertySetInfo > SAL_CALL OQueryController::getPropertySetInfo()
+{
+ Reference< XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) );
+ return xInfo;
+}
+
+void SAL_CALL OQueryController::getFastPropertyValue( Any& o_rValue, sal_Int32 i_nHandle ) const
+{
+ switch ( i_nHandle )
+ {
+ case PROPERTY_ID_CURRENT_QUERY_DESIGN:
+ {
+ ::comphelper::NamedValueCollection aCurrentDesign;
+ aCurrentDesign.put( "GraphicalDesign", isGraphicalDesign() );
+ aCurrentDesign.put( PROPERTY_ESCAPE_PROCESSING, m_bEscapeProcessing );
+
+ if ( isGraphicalDesign() )
+ {
+ getContainer()->SaveUIConfig();
+ saveViewSettings( aCurrentDesign, true );
+ aCurrentDesign.put( "Statement", m_sStatement );
+ }
+ else
+ {
+ aCurrentDesign.put( "Statement", getContainer()->getStatement() );
+ }
+
+ o_rValue <<= aCurrentDesign.getPropertyValues();
+ }
+ break;
+
+ default:
+ OPropertyContainer::getFastPropertyValue( o_rValue, i_nHandle );
+ break;
+ }
+}
+
+::cppu::IPropertyArrayHelper& OQueryController::getInfoHelper()
+{
+ return *getArrayHelper();
+}
+
+::cppu::IPropertyArrayHelper* OQueryController::createArrayHelper( ) const
+{
+ Sequence< Property > aProps;
+ describeProperties( aProps );
+
+ // one additional property:
+ const sal_Int32 nLength = aProps.getLength();
+ aProps.realloc( nLength + 1 );
+ auto pProps = aProps.getArray();
+ pProps[ nLength ] = Property(
+ "CurrentQueryDesign",
+ PROPERTY_ID_CURRENT_QUERY_DESIGN,
+ ::cppu::UnoType< Sequence< PropertyValue > >::get(),
+ PropertyAttribute::READONLY
+ );
+
+ std::sort(
+ pProps,
+ pProps + aProps.getLength(),
+ ::comphelper::PropertyCompareByName()
+ );
+
+ return new ::cppu::OPropertyArrayHelper(aProps);
+}
+
+void OQueryController::deleteIterator()
+{
+ if(m_pSqlIterator)
+ {
+ delete m_pSqlIterator->getParseTree();
+ m_pSqlIterator->dispose();
+ m_pSqlIterator.reset();
+ }
+}
+
+void OQueryController::disposing()
+{
+ OQueryController_PBase::disposing();
+
+ deleteIterator();
+
+ m_pParseContext.reset();
+
+ clearFields();
+ OTableFields().swap(m_vUnUsedFieldsDesc);
+
+ ::comphelper::disposeComponent(m_xComposer);
+ OJoinController::disposing();
+ OQueryController_PBase::disposing();
+}
+
+void OQueryController::clearFields()
+{
+ OTableFields().swap(m_vTableFieldDesc);
+}
+
+FeatureState OQueryController::GetState(sal_uInt16 _nId) const
+{
+ FeatureState aReturn;
+ aReturn.bEnabled = true;
+ // (disabled automatically)
+
+ switch (_nId)
+ {
+ case ID_BROWSER_EDITDOC:
+ if ( editingCommand() )
+ aReturn.bEnabled = false;
+ else if ( editingView() && !m_xAlterView.is() )
+ aReturn.bEnabled = false;
+ else
+ aReturn = OJoinController::GetState( _nId );
+ break;
+
+ case ID_BROWSER_ESCAPEPROCESSING:
+ aReturn.bChecked = !m_bEscapeProcessing;
+ aReturn.bEnabled = ( m_pSqlIterator != nullptr ) && !m_bGraphicalDesign;
+ break;
+ case SID_RELATION_ADD_RELATION:
+ aReturn.bEnabled = isEditable() && m_bGraphicalDesign && m_vTableData.size() > 1;
+ break;
+ case ID_BROWSER_SAVEASDOC:
+ aReturn.bEnabled = !editingCommand() && (!m_bGraphicalDesign || !(m_vTableFieldDesc.empty() || m_vTableData.empty()));
+ break;
+ case ID_BROWSER_SAVEDOC:
+ aReturn.bEnabled = isEditable() && (!m_bGraphicalDesign || !(m_vTableFieldDesc.empty() || m_vTableData.empty()));
+ break;
+ case SID_PRINTDOCDIRECT:
+ break;
+ case ID_BROWSER_CUT:
+ aReturn.bEnabled = isEditable() && getContainer() && getContainer()->isCutAllowed();
+ break;
+ case ID_BROWSER_COPY:
+ aReturn.bEnabled = getContainer() && getContainer()->isCopyAllowed();
+ break;
+ case ID_BROWSER_PASTE:
+ aReturn.bEnabled = isEditable() && getContainer() && getContainer()->isPasteAllowed();
+ break;
+ case ID_BROWSER_SQL:
+ aReturn.bEnabled = m_bEscapeProcessing && m_pSqlIterator;
+ aReturn.bChecked = m_bGraphicalDesign;
+ break;
+ case SID_BROWSER_CLEAR_QUERY:
+ aReturn.bEnabled = isEditable() && (!m_sStatement.isEmpty() || !m_vTableData.empty());
+ break;
+ case SID_QUERY_VIEW_FUNCTIONS:
+ case SID_QUERY_VIEW_TABLES:
+ case SID_QUERY_VIEW_ALIASES:
+ aReturn.bChecked = getContainer() && getContainer()->isSlotEnabled(_nId);
+ aReturn.bEnabled = m_bGraphicalDesign;
+ break;
+ case SID_QUERY_DISTINCT_VALUES:
+ aReturn.bEnabled = m_bGraphicalDesign && isEditable();
+ aReturn.bChecked = m_bDistinct;
+ break;
+ case SID_QUERY_LIMIT:
+ aReturn.bEnabled = m_bGraphicalDesign;
+ if( aReturn.bEnabled )
+ aReturn.aValue <<= m_nLimit;
+ break;
+ case SID_QUERY_PROP_DLG:
+ aReturn.bEnabled = m_bGraphicalDesign;
+ break;
+ case ID_BROWSER_QUERY_EXECUTE:
+ aReturn.bEnabled = true;
+ break;
+ case SID_DB_QUERY_PREVIEW:
+ aReturn.bEnabled = true;
+ aReturn.bChecked = getContainer() && getContainer()->getPreviewFrame().is();
+ break;
+#if OSL_DEBUG_LEVEL > 0
+ case ID_EDIT_QUERY_SQL:
+ break;
+ case ID_EDIT_QUERY_DESIGN:
+ break;
+#endif
+ case ID_BROWSER_ADDTABLE:
+ if ( !m_bGraphicalDesign )
+ {
+ aReturn.bEnabled = false;
+ break;
+ }
+ [[fallthrough]];
+ default:
+ aReturn = OJoinController::GetState(_nId);
+ break;
+ }
+ return aReturn;
+}
+
+void OQueryController::Execute(sal_uInt16 _nId, const Sequence< PropertyValue >& aArgs)
+{
+ switch(_nId)
+ {
+ case ID_BROWSER_ESCAPEPROCESSING:
+ setEscapeProcessing_fireEvent( !m_bEscapeProcessing );
+ if ( !editingView() )
+ setModified(true);
+ InvalidateFeature(ID_BROWSER_SQL);
+ break;
+ case ID_BROWSER_SAVEASDOC:
+ case ID_BROWSER_SAVEDOC:
+ grabFocusFromLimitBox(*this);
+ doSaveAsDoc(ID_BROWSER_SAVEASDOC == _nId);
+ break;
+ case SID_RELATION_ADD_RELATION:
+ {
+ OJoinDesignView* pView = getJoinView();
+ if( pView )
+ static_cast<OQueryTableView*>(pView->getTableView())->createNewConnection();
+ }
+ break;
+ case SID_PRINTDOCDIRECT:
+ break;
+ case ID_BROWSER_CUT:
+ getContainer()->cut();
+ break;
+ case ID_BROWSER_COPY:
+ getContainer()->copy();
+ break;
+ case ID_BROWSER_PASTE:
+ getContainer()->paste();
+ break;
+ case ID_BROWSER_SQL:
+ {
+ grabFocusFromLimitBox(*this);
+ if ( !getContainer()->checkStatement() )
+ break;
+ SQLExceptionInfo aError;
+ try
+ {
+ setStatement_fireEvent( getContainer()->getStatement() );
+ if(m_sStatement.isEmpty() && m_pSqlIterator)
+ {
+ // change the view of the data
+ delete m_pSqlIterator->getParseTree();
+ m_pSqlIterator->setParseTree(nullptr);
+ m_bGraphicalDesign = !m_bGraphicalDesign;
+ impl_setViewMode( &aError );
+ }
+ else
+ {
+ OUString aErrorMsg;
+ std::unique_ptr<::connectivity::OSQLParseNode> pNode = m_aSqlParser.parseTree(aErrorMsg,m_sStatement,m_bGraphicalDesign);
+ if ( pNode )
+ {
+ delete m_pSqlIterator->getParseTree();
+ m_pSqlIterator->setParseTree(pNode.release());
+ m_pSqlIterator->traverseAll();
+
+ if ( m_pSqlIterator->hasErrors() )
+ {
+ aError = m_pSqlIterator->getErrors();
+ }
+ else
+ {
+ const OSQLTables& rTabs = m_pSqlIterator->getTables();
+ if ( m_pSqlIterator->getStatementType() != OSQLStatementType::Select || rTabs.empty() )
+ {
+ aError = SQLException(
+ DBA_RES(STR_QRY_NOSELECT),
+ nullptr,
+ "S1000",
+ 1000,
+ Any()
+ );
+ }
+ else
+ {
+ // change the view of the data
+ m_bGraphicalDesign = !m_bGraphicalDesign;
+ OUString sNewStatement;
+ m_pSqlIterator->getParseTree()->parseNodeToStr( sNewStatement, getConnection() );
+ setStatement_fireEvent( sNewStatement );
+ getContainer()->SaveUIConfig();
+ m_vTableConnectionData.clear();
+ impl_setViewMode( &aError );
+ }
+ }
+ }
+ else
+ {
+ aError = SQLException(
+ DBA_RES(STR_QRY_SYNTAX),
+ nullptr,
+ "S1000",
+ 1000,
+ Any()
+ );
+ }
+ }
+ }
+ catch(const SQLException&)
+ {
+ aError = ::cppu::getCaughtException();
+ }
+ catch(const Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+
+ if ( aError.isValid() )
+ showError( aError );
+
+ if(m_bGraphicalDesign)
+ {
+ InvalidateFeature(ID_BROWSER_ADDTABLE);
+ InvalidateFeature(SID_RELATION_ADD_RELATION);
+ }
+ }
+ break;
+ case SID_BROWSER_CLEAR_QUERY:
+ {
+ GetUndoManager().EnterListAction(DBA_RES(STR_QUERY_UNDO_TABWINDELETE), OUString(), 0, ViewShellId(-1) );
+ getContainer()->clear();
+ GetUndoManager().LeaveListAction();
+
+ setStatement_fireEvent( OUString() );
+ if(m_bGraphicalDesign)
+ InvalidateFeature(ID_BROWSER_ADDTABLE);
+ }
+ break;
+ case SID_QUERY_VIEW_FUNCTIONS:
+ case SID_QUERY_VIEW_TABLES:
+ case SID_QUERY_VIEW_ALIASES:
+ getContainer()->setSlotEnabled(_nId,!getContainer()->isSlotEnabled(_nId));
+ setModified(true);
+ break;
+ case SID_QUERY_DISTINCT_VALUES:
+ m_bDistinct = !m_bDistinct;
+ setModified(true);
+ break;
+ case SID_QUERY_LIMIT:
+ if ( aArgs.hasElements() && aArgs[0].Name == "DBLimit.Value" )
+ {
+ aArgs[0].Value >>= m_nLimit;
+ setModified(true);
+ }
+ break;
+ case SID_QUERY_PROP_DLG:
+ grabFocusFromLimitBox(*this);
+ execute_QueryPropDlg();
+ break;
+ case ID_BROWSER_QUERY_EXECUTE:
+ grabFocusFromLimitBox(*this);
+ if ( getContainer()->checkStatement() )
+ executeQuery();
+ break;
+ case SID_DB_QUERY_PREVIEW:
+ try
+ {
+ Reference< css::util::XCloseable > xCloseFrame( getContainer()->getPreviewFrame(), UNO_QUERY );
+ if ( xCloseFrame.is() )
+ {
+ try
+ {
+ xCloseFrame->close( true );
+ }
+ catch(const Exception&)
+ {
+ OSL_FAIL( "OQueryController::Execute(SID_DB_QUERY_PREVIEW): *nobody* is expected to veto closing the preview frame!" );
+ }
+ }
+ else
+ Execute(ID_BROWSER_QUERY_EXECUTE,Sequence< PropertyValue >());
+ }
+ catch(const Exception&)
+ {
+ }
+ break;
+ default:
+ OJoinController::Execute(_nId,aArgs);
+ return; // else we would invalidate twice
+ }
+ InvalidateFeature(_nId);
+}
+
+void OQueryController::impl_showAutoSQLViewError( const css::uno::Any& _rErrorDetails )
+{
+ SQLContext aErrorContext;
+ aErrorContext.Message = lcl_getObjectResourceString( STR_ERROR_PARSING_STATEMENT, m_nCommandType );
+ aErrorContext.Context = *this;
+ aErrorContext.Details = lcl_getObjectResourceString( STR_INFO_OPENING_IN_SQL_VIEW, m_nCommandType );
+ aErrorContext.NextException = _rErrorDetails;
+ showError( aErrorContext );
+}
+
+void OQueryController::impl_setViewMode( ::dbtools::SQLExceptionInfo* _pErrorInfo )
+{
+ OSL_PRECOND( getContainer(), "OQueryController::impl_setViewMode: illegal call!" );
+
+ bool wasModified = isModified();
+
+ SQLExceptionInfo aError;
+ bool bSuccess = getContainer()->switchView( &aError );
+ if ( !bSuccess )
+ {
+ m_bGraphicalDesign = !m_bGraphicalDesign;
+ // restore old state
+ getContainer()->switchView( nullptr );
+ // don't pass &aError here, this would overwrite the error which the first switchView call
+ // returned in this location.
+ if ( _pErrorInfo )
+ *_pErrorInfo = aError;
+ else
+ showError( aError );
+ }
+ else
+ {
+ ensureToolbars( *this, m_bGraphicalDesign );
+ }
+
+ setModified( wasModified );
+}
+
+void OQueryController::impl_initialize()
+{
+ OJoinController::impl_initialize();
+
+ const NamedValueCollection& rArguments( getInitParams() );
+
+ OUString sCommand;
+ m_nCommandType = CommandType::QUERY;
+
+ // reading parameters:
+
+ // legacy parameters first (later overwritten by regular parameters)
+ OUString sIndependentSQLCommand;
+ if ( rArguments.get_ensureType( "IndependentSQLCommand", sIndependentSQLCommand ) )
+ {
+ OSL_FAIL( "OQueryController::impl_initialize: IndependentSQLCommand is regognized for compatibility only!" );
+ sCommand = sIndependentSQLCommand;
+ m_nCommandType = CommandType::COMMAND;
+ }
+
+ OUString sCurrentQuery;
+ if ( rArguments.get_ensureType( "CurrentQuery", sCurrentQuery ) )
+ {
+ OSL_FAIL( "OQueryController::impl_initialize: CurrentQuery is regognized for compatibility only!" );
+ sCommand = sCurrentQuery;
+ m_nCommandType = CommandType::QUERY;
+ }
+
+ bool bCreateView( false );
+ if ( rArguments.get_ensureType( "CreateView", bCreateView ) && bCreateView )
+ {
+ OSL_FAIL( "OQueryController::impl_initialize: CurrentQuery is regognized for compatibility only!" );
+ m_nCommandType = CommandType::TABLE;
+ }
+
+ // non-legacy parameters which overwrite the legacy parameters
+ rArguments.get_ensureType( PROPERTY_COMMAND, sCommand );
+ rArguments.get_ensureType( PROPERTY_COMMAND_TYPE, m_nCommandType );
+
+ // translate Command/Type into proper members
+ // TODO/Later: all this (including those members) should be hidden behind some abstract interface,
+ // which is implemented for all the three commands
+ switch ( m_nCommandType )
+ {
+ case CommandType::QUERY:
+ m_sName = sCommand;
+ break;
+ case CommandType::TABLE:
+ m_sName = sCommand;
+ break;
+ case CommandType::COMMAND:
+ setStatement_fireEvent( sCommand );
+ m_sName.clear();
+ break;
+ default:
+ OSL_FAIL( "OQueryController::impl_initialize: logic error in code!" );
+ throw RuntimeException();
+ }
+
+ // more legacy parameters
+ bool bGraphicalDesign( true );
+ if ( rArguments.get_ensureType( PROPERTY_QUERYDESIGNVIEW, bGraphicalDesign ) )
+ {
+ OSL_FAIL( "OQueryController::impl_initialize: QueryDesignView is regognized for compatibility only!" );
+ m_bGraphicalDesign = bGraphicalDesign;
+ }
+
+ // more non-legacy
+ rArguments.get_ensureType( PROPERTY_GRAPHICAL_DESIGN, m_bGraphicalDesign );
+
+ bool bEscapeProcessing( true );
+ if ( rArguments.get_ensureType( PROPERTY_ESCAPE_PROCESSING, bEscapeProcessing ) )
+ {
+ setEscapeProcessing_fireEvent( bEscapeProcessing );
+
+ OSL_ENSURE( m_bEscapeProcessing || !m_bGraphicalDesign, "OQueryController::impl_initialize: can't do the graphical design without escape processing!" );
+ if ( !m_bEscapeProcessing )
+ m_bGraphicalDesign = false;
+ }
+
+ // initial design
+ bool bForceInitialDesign = false;
+ Sequence< PropertyValue > aCurrentQueryDesignProps;
+ aCurrentQueryDesignProps = rArguments.getOrDefault( "CurrentQueryDesign", aCurrentQueryDesignProps );
+
+ if ( aCurrentQueryDesignProps.hasElements() )
+ {
+ ::comphelper::NamedValueCollection aCurrentQueryDesign( aCurrentQueryDesignProps );
+ if ( aCurrentQueryDesign.has( PROPERTY_GRAPHICAL_DESIGN ) )
+ {
+ aCurrentQueryDesign.get_ensureType( PROPERTY_GRAPHICAL_DESIGN, m_bGraphicalDesign );
+ }
+ if ( aCurrentQueryDesign.has( PROPERTY_ESCAPE_PROCESSING ) )
+ {
+ aCurrentQueryDesign.get_ensureType( PROPERTY_ESCAPE_PROCESSING, m_bEscapeProcessing );
+ }
+ if ( aCurrentQueryDesign.has( "Statement" ) )
+ {
+ OUString sStatement;
+ aCurrentQueryDesign.get_ensureType( "Statement", sStatement );
+ aCurrentQueryDesign.remove( "Statement" );
+ setStatement_fireEvent( sStatement );
+ }
+
+ loadViewSettings( aCurrentQueryDesign );
+
+ bForceInitialDesign = true;
+ }
+
+ if ( !ensureConnected() )
+ { // we have no connection so what else should we do
+ m_bGraphicalDesign = false;
+ if ( editingView() )
+ {
+ connectionLostMessage();
+ throw SQLException();
+ }
+ }
+
+ // check the view capabilities
+ if ( isConnected() && editingView() )
+ {
+ Reference< XViewsSupplier > xViewsSup( getConnection(), UNO_QUERY );
+ Reference< XNameAccess > xViews;
+ if ( xViewsSup.is() )
+ xViews = xViewsSup->getViews();
+
+ if ( !xViews.is() )
+ { // we can't create views so we ask if the user wants to create a query instead
+ m_nCommandType = CommandType::QUERY;
+ bool bClose = false;
+ {
+ OUString aTitle(DBA_RES(STR_QUERYDESIGN_NO_VIEW_SUPPORT));
+ OUString aMessage(DBA_RES(STR_QUERYDESIGN_NO_VIEW_ASK));
+ OSQLMessageBox aDlg(getFrameWeld(), aTitle, aMessage, MessBoxStyle::YesNo | MessBoxStyle::DefaultYes, MessageType::Query);
+ bClose = aDlg.run() == RET_NO;
+ }
+ if ( bClose )
+ throw VetoException();
+ }
+
+ // now if we are to edit an existing view, check whether this is possible
+ if ( !m_sName.isEmpty() )
+ {
+ Any aView( xViews->getByName( m_sName ) );
+ // will throw if there is no such view
+ if ( !( aView >>= m_xAlterView ) )
+ {
+ throw IllegalArgumentException(
+ DBA_RES(STR_NO_ALTER_VIEW_SUPPORT),
+ *this,
+ 1
+ );
+ }
+ }
+ }
+
+ OSL_ENSURE(getDataSource().is(),"OQueryController::impl_initialize: need a datasource!");
+
+ try
+ {
+ getContainer()->initialize();
+ impl_reset( bForceInitialDesign );
+
+ SQLExceptionInfo aError;
+ const bool bAttemptedGraphicalDesign = m_bGraphicalDesign;
+
+ if ( bForceInitialDesign )
+ {
+ getContainer()->forceInitialView();
+ }
+ else
+ {
+ impl_setViewMode( &aError );
+ }
+
+ if ( aError.isValid() && bAttemptedGraphicalDesign && !m_bGraphicalDesign )
+ {
+ // we tried initializing the graphical view, this failed, and we were automatically switched to SQL
+ // view => tell this to the user
+ if ( !editingView() )
+ {
+ impl_showAutoSQLViewError( aError.get() );
+ }
+ }
+
+ ClearUndoManager();
+
+ if ( m_bGraphicalDesign
+ && ( ( m_sName.isEmpty() && !editingCommand() )
+ || ( m_sStatement.isEmpty() && editingCommand() )
+ )
+ )
+ {
+ Application::PostUserEvent( LINK( this, OQueryController, OnExecuteAddTable ) );
+ }
+
+ setModified(false);
+ }
+ catch(const SQLException& e)
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ // we caught an exception so we switch to text only mode
+ {
+ m_bGraphicalDesign = false;
+ getContainer()->initialize();
+ OSQLMessageBox aBox(getFrameWeld(), e);
+ aBox.run();
+ }
+ throw;
+ }
+}
+
+void OQueryController::onLoadedMenu(const Reference< css::frame::XLayoutManager >& /*_xLayoutManager*/)
+{
+ ensureToolbars( *this, m_bGraphicalDesign );
+}
+
+OUString OQueryController::getPrivateTitle( ) const
+{
+ if ( m_sName.isEmpty() )
+ {
+ if ( !editingCommand() )
+ {
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( getMutex() );
+ OUString aDefaultName = DBA_RES(editingView() ? STR_VIEW_TITLE : STR_QRY_TITLE);
+ return o3tl::getToken(aDefaultName, 0, ' ') + OUString::number(getCurrentStartNumber());
+ }
+ }
+ return m_sName;
+}
+
+void OQueryController::setQueryComposer()
+{
+ if(!isConnected())
+ return;
+
+ Reference< XSQLQueryComposerFactory > xFactory(getConnection(), UNO_QUERY);
+ OSL_ENSURE(xFactory.is(),"Connection doesn't support a querycomposer");
+ if ( !(xFactory.is() && getContainer()) )
+ return;
+
+ try
+ {
+ m_xComposer = xFactory->createQueryComposer();
+ getContainer()->setStatement(m_sStatement);
+ }
+ catch(const Exception&)
+ {
+ m_xComposer = nullptr;
+ }
+ OSL_ENSURE(m_xComposer.is(),"No querycomposer available!");
+ Reference<XTablesSupplier> xTablesSup(getConnection(), UNO_QUERY);
+ deleteIterator();
+ m_pSqlIterator.reset(new ::connectivity::OSQLParseTreeIterator( getConnection(), xTablesSup->getTables(), m_aSqlParser ));
+}
+
+bool OQueryController::Construct(vcl::Window* pParent)
+{
+ // TODO: we have to check if we should create the text view or the design view
+
+ setView( VclPtr<OQueryContainerWindow>::Create( pParent, *this, getORB() ) );
+
+ return OJoinController::Construct(pParent);
+}
+
+OJoinDesignView* OQueryController::getJoinView()
+{
+ return getContainer()->getDesignView();
+}
+
+void OQueryController::describeSupportedFeatures()
+{
+ OJoinController::describeSupportedFeatures();
+ implDescribeSupportedFeature( ".uno:SaveAs", ID_BROWSER_SAVEASDOC, CommandGroup::DOCUMENT );
+ implDescribeSupportedFeature( ".uno:SbaNativeSql", ID_BROWSER_ESCAPEPROCESSING,CommandGroup::FORMAT );
+ implDescribeSupportedFeature( ".uno:DBViewFunctions", SID_QUERY_VIEW_FUNCTIONS, CommandGroup::VIEW );
+ implDescribeSupportedFeature( ".uno:DBViewTableNames", SID_QUERY_VIEW_TABLES, CommandGroup::VIEW );
+ implDescribeSupportedFeature( ".uno:DBViewAliases", SID_QUERY_VIEW_ALIASES, CommandGroup::VIEW );
+ implDescribeSupportedFeature( ".uno:DBDistinctValues", SID_QUERY_DISTINCT_VALUES, CommandGroup::FORMAT );
+ implDescribeSupportedFeature( ".uno:DBChangeDesignMode",ID_BROWSER_SQL, CommandGroup::VIEW );
+ implDescribeSupportedFeature( ".uno:DBClearQuery", SID_BROWSER_CLEAR_QUERY, CommandGroup::EDIT );
+ implDescribeSupportedFeature( ".uno:SbaExecuteSql", ID_BROWSER_QUERY_EXECUTE, CommandGroup::VIEW );
+ implDescribeSupportedFeature( ".uno:DBAddRelation", SID_RELATION_ADD_RELATION, CommandGroup::EDIT );
+ implDescribeSupportedFeature( ".uno:DBQueryPreview", SID_DB_QUERY_PREVIEW, CommandGroup::VIEW );
+ implDescribeSupportedFeature( ".uno:DBLimit", SID_QUERY_LIMIT, CommandGroup::FORMAT );
+ implDescribeSupportedFeature( ".uno:DBQueryPropertiesDialog", SID_QUERY_PROP_DLG, CommandGroup::FORMAT );
+
+#if OSL_DEBUG_LEVEL > 0
+ implDescribeSupportedFeature( ".uno:DBShowParseTree", ID_EDIT_QUERY_SQL );
+ implDescribeSupportedFeature( ".uno:DBMakeDisjunct", ID_EDIT_QUERY_DESIGN );
+#endif
+}
+
+void OQueryController::impl_onModifyChanged()
+{
+ OJoinController::impl_onModifyChanged();
+ InvalidateFeature(SID_BROWSER_CLEAR_QUERY);
+ InvalidateFeature(ID_BROWSER_SAVEASDOC);
+ InvalidateFeature(ID_BROWSER_QUERY_EXECUTE);
+}
+
+void SAL_CALL OQueryController::disposing( const EventObject& Source )
+{
+ SolarMutexGuard aGuard;
+
+ if ( getContainer() && Source.Source.is() )
+ {
+ if ( Source.Source == m_aCurrentFrame.getFrame() )
+ { // our frame is being disposed -> close the preview window (if we have one)
+ Reference< XFrame2 > xPreviewFrame( getContainer()->getPreviewFrame() );
+ ::comphelper::disposeComponent( xPreviewFrame );
+ }
+ else if ( Source.Source == getContainer()->getPreviewFrame() )
+ {
+ getContainer()->disposingPreview();
+ }
+ }
+
+ OJoinController_BASE::disposing(Source);
+}
+
+void OQueryController::reconnect(bool _bUI)
+{
+ deleteIterator();
+ ::comphelper::disposeComponent(m_xComposer);
+
+ OJoinController::reconnect( _bUI );
+
+ if (isConnected())
+ {
+ setQueryComposer();
+ }
+ else
+ {
+ if(m_bGraphicalDesign)
+ {
+ m_bGraphicalDesign = false;
+ // don't call Execute(SQL) because this changes the sql statement
+ impl_setViewMode( nullptr );
+ }
+ InvalidateAll();
+ }
+}
+
+void OQueryController::saveViewSettings( ::comphelper::NamedValueCollection& o_rViewSettings, const bool i_includingCriteria ) const
+{
+ saveTableWindows( o_rViewSettings );
+
+ ::comphelper::NamedValueCollection aAllFieldsData;
+ ::comphelper::NamedValueCollection aFieldData;
+ sal_Int32 i = 1;
+ for (auto const& fieldDesc : m_vTableFieldDesc)
+ {
+ if ( !fieldDesc->IsEmpty() )
+ {
+ aFieldData.clear();
+ fieldDesc->Save( aFieldData, i_includingCriteria );
+
+ const OUString sFieldSettingName = "Field" + OUString::number( i );
+ aAllFieldsData.put( sFieldSettingName, aFieldData.getPropertyValues() );
+ }
+ ++i;
+ }
+
+ o_rViewSettings.put( "Fields", aAllFieldsData.getPropertyValues() );
+ o_rViewSettings.put( "SplitterPosition", m_nSplitPos );
+ o_rViewSettings.put( "VisibleRows", m_nVisibleRows );
+}
+
+void OQueryController::loadViewSettings( const ::comphelper::NamedValueCollection& o_rViewSettings )
+{
+ loadTableWindows( o_rViewSettings );
+
+ m_nSplitPos = o_rViewSettings.getOrDefault( "SplitterPosition", m_nSplitPos );
+ m_nVisibleRows = o_rViewSettings.getOrDefault( "VisibleRows", m_nVisibleRows );
+ m_aFieldInformation = o_rViewSettings.getOrDefault( "Fields", m_aFieldInformation );
+}
+
+void OQueryController::execute_QueryPropDlg()
+{
+ QueryPropertiesDialog aQueryPropDlg(getContainer()->GetFrameWeld(), m_bDistinct, m_nLimit);
+
+ if (aQueryPropDlg.run() == RET_OK)
+ {
+ m_bDistinct = aQueryPropDlg.getDistinct();
+ m_nLimit = aQueryPropDlg.getLimit();
+ InvalidateFeature( SID_QUERY_DISTINCT_VALUES );
+ InvalidateFeature( SID_QUERY_LIMIT, nullptr, true );
+ }
+}
+
+sal_Int32 OQueryController::getColWidth(sal_uInt16 _nColPos) const
+{
+ if ( _nColPos < m_aFieldInformation.getLength() )
+ {
+ rtl::Reference<OTableFieldDesc> pField( new OTableFieldDesc());
+ pField->Load( m_aFieldInformation[ _nColPos ], false );
+ return pField->GetColWidth();
+ }
+ return 0;
+}
+
+Reference<XNameAccess> OQueryController::getObjectContainer() const
+{
+ Reference< XNameAccess > xElements;
+ if ( editingView() )
+ {
+ Reference< XViewsSupplier > xViewsSupp( getConnection(), UNO_QUERY );
+ if ( xViewsSupp.is() )
+ xElements = xViewsSupp->getViews();
+ }
+ else
+ {
+ Reference< XQueriesSupplier > xQueriesSupp( getConnection(), UNO_QUERY );
+ if ( xQueriesSupp.is() )
+ xElements = xQueriesSupp->getQueries();
+ else
+ {
+ Reference< XQueryDefinitionsSupplier > xQueryDefsSupp( getDataSource(), UNO_QUERY );
+ if ( xQueryDefsSupp.is() )
+ xElements = xQueryDefsSupp->getQueryDefinitions();
+ }
+ }
+
+ OSL_ENSURE( xElements.is(), "OQueryController::getObjectContainer: unable to obtain the container!" );
+ return xElements;
+}
+
+void OQueryController::executeQuery()
+{
+ // we don't need to check the connection here because we already check the composer
+ // which can't live without his connection
+ OUString sTranslatedStmt = translateStatement( false );
+
+ OUString sDataSourceName = getDataSourceName();
+ if ( sDataSourceName.isEmpty() || sTranslatedStmt.isEmpty() )
+ return;
+
+ try
+ {
+ getContainer()->showPreview( getFrame() );
+ InvalidateFeature(SID_DB_QUERY_PREVIEW);
+
+ URL aWantToDispatch;
+ aWantToDispatch.Complete = ".component:DB/DataSourceBrowser";
+
+ OUString sFrameName( FRAME_NAME_QUERY_PREVIEW );
+ sal_Int32 nSearchFlags = FrameSearchFlag::CHILDREN;
+
+ Reference< XDispatch> xDisp;
+ Reference< XDispatchProvider> xProv( getFrame()->findFrame( sFrameName, nSearchFlags ), UNO_QUERY );
+ if(!xProv.is())
+ {
+ xProv.set( getFrame(), UNO_QUERY );
+ if (xProv.is())
+ xDisp = xProv->queryDispatch(aWantToDispatch, sFrameName, nSearchFlags);
+ }
+ else
+ {
+ xDisp = xProv->queryDispatch(aWantToDispatch, sFrameName, FrameSearchFlag::SELF);
+ }
+ if (xDisp.is())
+ {
+ auto aProps(::comphelper::InitPropertySequence(
+ {
+ { PROPERTY_DATASOURCENAME, Any(sDataSourceName) },
+ { PROPERTY_COMMAND_TYPE, Any(CommandType::COMMAND) },
+ { PROPERTY_COMMAND, Any(sTranslatedStmt) },
+ { PROPERTY_ENABLE_BROWSER, Any(false) },
+ { PROPERTY_ACTIVE_CONNECTION, Any(getConnection()) },
+ { PROPERTY_UPDATE_CATALOGNAME, Any(m_sUpdateCatalogName) },
+ { PROPERTY_UPDATE_SCHEMANAME, Any(m_sUpdateSchemaName) },
+ { PROPERTY_UPDATE_TABLENAME, Any(OUString()) },
+ { PROPERTY_ESCAPE_PROCESSING, Any(m_bEscapeProcessing) }
+ }));
+
+ xDisp->dispatch(aWantToDispatch, aProps);
+ // check the state of the beamer
+ // be notified when the beamer frame is closed
+ Reference< XComponent > xComponent = getFrame()->findFrame( sFrameName, nSearchFlags );
+ if (xComponent.is())
+ {
+ OSL_ENSURE(Reference< XFrame >(xComponent, UNO_QUERY).get() == getContainer()->getPreviewFrame().get(),
+ "OQueryController::executeQuery: oops ... which window do I have here?");
+ Reference< XEventListener> xEvtL(static_cast<cppu::OWeakObject*>(this),UNO_QUERY);
+ xComponent->addEventListener(xEvtL);
+ }
+ }
+ else
+ {
+ OSL_FAIL("Couldn't create a beamer window!");
+ }
+ }
+ catch(const Exception&)
+ {
+ OSL_FAIL("Couldn't create a beamer window!");
+ }
+}
+
+bool OQueryController::askForNewName(const Reference<XNameAccess>& _xElements, bool _bSaveAs)
+{
+ OSL_ENSURE( !editingCommand(), "OQueryController::askForNewName: not to be called when designing an independent statement!" );
+ if ( editingCommand() )
+ return false;
+
+ OSL_PRECOND( _xElements.is(), "OQueryController::askForNewName: invalid container!" );
+ if ( !_xElements.is() )
+ return false;
+
+ bool bRet = true;
+ bool bNew = _bSaveAs || !_xElements->hasByName( m_sName );
+ if(bNew)
+ {
+ OUString aDefaultName;
+ if (!m_sName.isEmpty())
+ aDefaultName = m_sName;
+ else
+ {
+ OUString sName = DBA_RES(editingView() ? STR_VIEW_TITLE : STR_QRY_TITLE);
+ aDefaultName = ::dbtools::createUniqueName(_xElements, sName.getToken(0, ' '));
+ }
+
+ DynamicTableOrQueryNameCheck aNameChecker( getConnection(), CommandType::QUERY );
+ OSaveAsDlg aDlg(
+ getFrameWeld(),
+ m_nCommandType,
+ getORB(),
+ getConnection(),
+ aDefaultName,
+ aNameChecker,
+ SADFlags::NONE );
+
+ bRet = ( aDlg.run() == RET_OK );
+ if ( bRet )
+ {
+ m_sName = aDlg.getName();
+ if ( editingView() )
+ {
+ m_sUpdateCatalogName = aDlg.getCatalog();
+ m_sUpdateSchemaName = aDlg.getSchema();
+ }
+ }
+ }
+ return bRet;
+}
+
+bool OQueryController::doSaveAsDoc(bool _bSaveAs)
+{
+ OSL_ENSURE(isEditable(),"Slot ID_BROWSER_SAVEDOC should not be enabled!");
+ if ( !editingCommand() && !haveDataSource() )
+ {
+ OUString aMessage(DBA_RES(STR_DATASOURCE_DELETED));
+ OSQLWarningBox aBox(getFrameWeld(), aMessage);
+ aBox.run();
+ return false;
+ }
+
+ Reference< XNameAccess > xElements = getObjectContainer();
+ if ( !xElements.is() )
+ return false;
+
+ if ( !getContainer()->checkStatement() )
+ return false;
+
+ OUString sTranslatedStmt = translateStatement();
+ if ( editingCommand() )
+ {
+ setModified( false );
+ // this is all we need to do here. translateStatement implicitly set our m_sStatement, and
+ // notified it, and that's all
+ return true;
+ }
+
+ if ( sTranslatedStmt.isEmpty() )
+ return false;
+
+ // first we need a name for our query so ask the user
+ // did we get a name
+ OUString sOriginalName( m_sName );
+ if ( !askForNewName( xElements, _bSaveAs ) || m_sName.isEmpty() )
+ return false;
+
+ SQLExceptionInfo aInfo;
+ bool bSuccess = false;
+ bool bNew = false;
+ try
+ {
+ bNew = _bSaveAs
+ || ( !xElements->hasByName( m_sName ) );
+
+ Reference<XPropertySet> xQuery;
+ if ( bNew ) // just to make sure the query already exists
+ {
+ // drop the query, in case it already exists
+ if ( xElements->hasByName( m_sName ) )
+ {
+ Reference< XDrop > xNameCont( xElements, UNO_QUERY );
+ if ( xNameCont.is() )
+ xNameCont->dropByName( m_sName );
+ else
+ {
+ Reference< XNameContainer > xCont( xElements, UNO_QUERY );
+ if ( xCont.is() )
+ xCont->removeByName( m_sName );
+ }
+ }
+
+ // create a new (empty, uninitialized) query resp. view
+ Reference< XDataDescriptorFactory > xFact( xElements, UNO_QUERY );
+ if ( xFact.is() )
+ {
+ xQuery = xFact->createDataDescriptor();
+ // to set the name is only allowed when the query is new
+ xQuery->setPropertyValue( PROPERTY_NAME, Any( m_sName ) );
+ }
+ else
+ {
+ Reference< XSingleServiceFactory > xSingleFac( xElements, UNO_QUERY );
+ if ( xSingleFac.is() )
+ xQuery.set(xSingleFac->createInstance(), css::uno::UNO_QUERY);
+ }
+ }
+ else
+ {
+ xElements->getByName( m_sName ) >>= xQuery;
+ }
+ if ( !xQuery.is() )
+ throw RuntimeException();
+
+ // the new commands
+ if ( editingView() && !bNew )
+ {
+ OSL_ENSURE( xQuery == m_xAlterView, "OQueryController::doSaveAsDoc: already have another alterable view ...!?" );
+ m_xAlterView.set( xQuery, UNO_QUERY_THROW );
+ m_xAlterView->alterCommand( sTranslatedStmt );
+ }
+ else
+ { // we're creating a query, or a *new* view
+ xQuery->setPropertyValue( PROPERTY_COMMAND, Any( sTranslatedStmt ) );
+
+ if ( editingView() )
+ {
+ xQuery->setPropertyValue( PROPERTY_CATALOGNAME, Any( m_sUpdateCatalogName ) );
+ xQuery->setPropertyValue( PROPERTY_SCHEMANAME, Any( m_sUpdateSchemaName ) );
+ }
+
+ if ( editingQuery() )
+ {
+ xQuery->setPropertyValue( PROPERTY_UPDATE_TABLENAME, Any( OUString() ) );
+ xQuery->setPropertyValue( PROPERTY_ESCAPE_PROCESSING, css::uno::Any( m_bEscapeProcessing ) );
+
+ xQuery->setPropertyValue( PROPERTY_LAYOUTINFORMATION, getViewData() );
+ }
+ }
+
+ if ( bNew )
+ {
+ Reference< XAppend > xAppend( xElements, UNO_QUERY );
+ if ( xAppend.is() )
+ {
+ xAppend->appendByDescriptor( xQuery );
+ }
+ else
+ {
+ Reference< XNameContainer > xCont( xElements, UNO_QUERY );
+ if ( xCont.is() )
+ xCont->insertByName( m_sName, Any( xQuery ) );
+ }
+
+ if ( editingView() )
+ {
+ Reference< XPropertySet > xViewProps;
+ if ( xElements->hasByName( m_sName ) )
+ xViewProps.set( xElements->getByName( m_sName ), UNO_QUERY );
+
+ if ( !xViewProps.is() ) // correct name and try again
+ m_sName = ::dbtools::composeTableName( getMetaData(), xQuery, ::dbtools::EComposeRule::InDataManipulation, false );
+
+ OSL_ENSURE( xElements->hasByName( m_sName ), "OQueryController::doSaveAsDoc: newly created view does not exist!" );
+
+ if ( xElements->hasByName( m_sName ) )
+ m_xAlterView.set( xElements->getByName( m_sName ), UNO_QUERY );
+
+ // now check if our datasource has set a tablefilter and if so, append the new table name to it
+ ::dbaui::appendToFilter(getConnection(), m_sName, getORB(), getFrameWeld());
+ }
+ Reference< XTitleChangeListener> xEventListener(impl_getTitleHelper_throw(),UNO_QUERY);
+ if ( xEventListener.is() )
+ {
+ TitleChangedEvent aEvent;
+ xEventListener->titleChanged(aEvent);
+ }
+ releaseNumberForComponent();
+ }
+
+ setModified( false );
+ bSuccess = true;
+
+ }
+ catch(const SQLException&)
+ {
+ if ( !bNew )
+ m_sName = sOriginalName;
+ aInfo = SQLExceptionInfo( ::cppu::getCaughtException() );
+ }
+ catch(const Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ if ( !bNew )
+ m_sName = sOriginalName;
+ }
+
+ showError( aInfo );
+
+ // if we successfully saved a view we were creating, then close the designer
+ if ( bSuccess && editingView() && !m_xAlterView.is() )
+ {
+ closeTask();
+ }
+
+ if ( bSuccess && editingView() )
+ InvalidateFeature( ID_BROWSER_EDITDOC );
+
+ return bSuccess;
+}
+
+namespace {
+struct CommentStrip
+{
+ OUString maComment;
+ bool mbLastOnLine;
+ CommentStrip( const OUString& rComment, bool bLastOnLine )
+ : maComment( rComment), mbLastOnLine( bLastOnLine) {}
+};
+
+}
+
+/** Obtain all comments in a query.
+
+ See also delComment() implementation for OSQLParser::parseTree().
+ */
+static std::vector< CommentStrip > getComment( const OUString& rQuery )
+{
+ std::vector< CommentStrip > aRet;
+ // First a quick search if there is any "--" or "//" or "/*", if not then
+ // the whole copying loop is pointless.
+ if (rQuery.indexOf( "--" ) < 0 && rQuery.indexOf( "//" ) < 0 &&
+ rQuery.indexOf( "/*" ) < 0)
+ return aRet;
+
+ const sal_Unicode* pCopy = rQuery.getStr();
+ const sal_Int32 nQueryLen = rQuery.getLength();
+ bool bIsText1 = false; // "text"
+ bool bIsText2 = false; // 'text'
+ bool bComment2 = false; // /* comment */
+ bool bComment = false; // -- or // comment
+ OUStringBuffer aBuf;
+ for (sal_Int32 i=0; i < nQueryLen; ++i)
+ {
+ if (bComment2)
+ {
+ aBuf.append( &pCopy[i], 1);
+ if ((i+1) < nQueryLen)
+ {
+ if (pCopy[i]=='*' && pCopy[i+1]=='/')
+ {
+ bComment2 = false;
+ aBuf.append( &pCopy[++i], 1);
+ aRet.emplace_back( aBuf.makeStringAndClear(), false);
+ }
+ }
+ else
+ {
+ // comment can't close anymore, actually an error, but...
+ aRet.emplace_back( aBuf.makeStringAndClear(), false);
+ }
+ continue;
+ }
+ if (pCopy[i] == '\n' || i == nQueryLen-1)
+ {
+ if (bComment)
+ {
+ if (i == nQueryLen-1 && pCopy[i] != '\n')
+ aBuf.append( &pCopy[i], 1);
+ aRet.emplace_back( aBuf.makeStringAndClear(), true);
+ bComment = false;
+ }
+ else if (!aRet.empty())
+ aRet.back().mbLastOnLine = true;
+ }
+ else if (!bComment)
+ {
+ if (pCopy[i] == '\"' && !bIsText2)
+ bIsText1 = !bIsText1;
+ else if (pCopy[i] == '\'' && !bIsText1)
+ bIsText2 = !bIsText2;
+ if (!bIsText1 && !bIsText2 && (i+1) < nQueryLen)
+ {
+ if ((pCopy[i]=='-' && pCopy[i+1]=='-') || (pCopy[i]=='/' && pCopy[i+1]=='/'))
+ bComment = true;
+ else if (pCopy[i]=='/' && pCopy[i+1]=='*')
+ bComment2 = true;
+ }
+ }
+ if (bComment || bComment2)
+ aBuf.append( &pCopy[i], 1);
+ }
+ return aRet;
+}
+
+/** Concat/insert comments that were previously obtained with getComment().
+
+ NOTE: The current parser implementation does not preserve newlines, so all
+ comments are always appended to the entire query, also inline comments
+ that would need positioning anyway that can't be obtained after
+ recomposition. This is ugly but at least allows commented queries while
+ preserving the comments _somehow_.
+ */
+static OUString concatComment( const OUString& rQuery, const std::vector< CommentStrip >& rComments )
+{
+ // No comments => return query.
+ if (rComments.empty())
+ return rQuery;
+
+ const sal_Unicode* pBeg = rQuery.getStr();
+ const sal_Int32 nLen = rQuery.getLength();
+ const size_t nComments = rComments.size();
+ // Obtaining the needed size once should be faster than reallocating.
+ // Also add a blank or linefeed for each comment.
+ sal_Int32 nBufSize = nLen + nComments;
+ for (auto const& comment : rComments)
+ nBufSize += comment.maComment.getLength();
+ OUStringBuffer aBuf( nBufSize );
+ sal_Int32 nIndBeg = 0;
+ sal_Int32 nIndLF = rQuery.indexOf('\n');
+ size_t i = 0;
+ while (nIndLF >= 0 && i < nComments)
+ {
+ aBuf.append( pBeg + nIndBeg, nIndLF - nIndBeg);
+ do
+ {
+ aBuf.append( rComments[i].maComment);
+ } while (!rComments[i++].mbLastOnLine && i < nComments);
+ aBuf.append( pBeg + nIndLF, 1); // the LF
+ nIndBeg = nIndLF + 1;
+ nIndLF = (nIndBeg < nLen ? rQuery.indexOf( '\n', nIndBeg) : -1);
+ }
+ // Append remainder of query.
+ if (nIndBeg < nLen)
+ aBuf.append( pBeg + nIndBeg, nLen - nIndBeg);
+ // Append all remaining comments, preserve lines.
+ bool bNewLine = false;
+ for ( ; i < nComments; ++i)
+ {
+ if (!bNewLine)
+ aBuf.append( ' ');
+ aBuf.append( rComments[i].maComment);
+ if (rComments[i].mbLastOnLine)
+ {
+ aBuf.append( '\n');
+ bNewLine = true;
+ }
+ else
+ bNewLine = false;
+ }
+ return aBuf.makeStringAndClear();
+}
+
+OUString OQueryController::translateStatement( bool _bFireStatementChange )
+{
+ // now set the properties
+ setStatement_fireEvent( getContainer()->getStatement(), _bFireStatementChange );
+ OUString sTranslatedStmt;
+ if(!m_sStatement.isEmpty() && m_xComposer.is() && m_bEscapeProcessing)
+ {
+ try
+ {
+ OUString aErrorMsg;
+
+ std::vector< CommentStrip > aComments = getComment( m_sStatement);
+
+ std::unique_ptr<::connectivity::OSQLParseNode> pNode = m_aSqlParser.parseTree( aErrorMsg, m_sStatement, m_bGraphicalDesign );
+ if(pNode)
+ {
+ pNode->parseNodeToStr( sTranslatedStmt, getConnection() );
+ }
+
+ m_xComposer->setQuery(sTranslatedStmt);
+ sTranslatedStmt = m_xComposer->getComposedQuery();
+ sTranslatedStmt = concatComment( sTranslatedStmt, aComments);
+ }
+ catch(const SQLException& e)
+ {
+ ::dbtools::SQLExceptionInfo aInfo(e);
+ showError(aInfo);
+ // an error occurred so we clear the statement
+ sTranslatedStmt.clear();
+ }
+ }
+ else if(m_sStatement.isEmpty())
+ {
+ showError(SQLException(DBA_RES(STR_QRY_NOSELECT), nullptr, "S1000", 1000, Any()));
+ }
+ else
+ sTranslatedStmt = m_sStatement;
+
+ return sTranslatedStmt;
+}
+
+short OQueryController::saveModified()
+{
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( getMutex() );
+ short nRet = RET_YES;
+ if ( !isConnected() || !isModified() )
+ return nRet;
+
+ if ( !m_bGraphicalDesign
+ || ( !m_vTableFieldDesc.empty()
+ && !m_vTableData.empty()
+ )
+ )
+ {
+ OUString sMessageText( lcl_getObjectResourceString( STR_QUERY_SAVEMODIFIED, m_nCommandType ) );
+
+ std::unique_ptr<weld::MessageDialog> xQueryBox(Application::CreateMessageDialog(getFrameWeld(),
+ VclMessageType::Question, VclButtonsType::YesNo,
+ sMessageText));
+ xQueryBox->add_button(GetStandardText(StandardButtonType::Cancel), RET_CANCEL);
+ xQueryBox->set_default_response(RET_YES);
+
+ nRet = xQueryBox->run();
+ if ( ( nRet == RET_YES )
+ && !doSaveAsDoc( false )
+ )
+ {
+ nRet = RET_CANCEL;
+ }
+ }
+ return nRet;
+}
+
+void OQueryController::impl_reset( const bool i_bForceCurrentControllerSettings )
+{
+ bool bValid = false;
+
+ Sequence< PropertyValue > aLayoutInformation;
+ // get command from the query if a query name was supplied
+ if ( !i_bForceCurrentControllerSettings && !editingCommand() )
+ {
+ if ( !m_sName.isEmpty() )
+ {
+ Reference< XNameAccess > xQueries = getObjectContainer();
+ if ( xQueries.is() )
+ {
+ Reference< XPropertySet > xProp;
+ if( xQueries->hasByName( m_sName ) && ( xQueries->getByName( m_sName ) >>= xProp ) && xProp.is() )
+ {
+ OUString sNewStatement;
+ xProp->getPropertyValue( PROPERTY_COMMAND ) >>= sNewStatement;
+ setStatement_fireEvent( sNewStatement );
+
+ if ( editingQuery() )
+ {
+ bool bNewEscapeProcessing( true );
+ xProp->getPropertyValue( PROPERTY_ESCAPE_PROCESSING ) >>= bNewEscapeProcessing;
+ setEscapeProcessing_fireEvent( bNewEscapeProcessing );
+ }
+
+ m_bGraphicalDesign = m_bGraphicalDesign && m_bEscapeProcessing;
+ bValid = true;
+
+ try
+ {
+ if ( editingQuery() )
+ xProp->getPropertyValue( PROPERTY_LAYOUTINFORMATION ) >>= aLayoutInformation;
+ }
+ catch( const Exception& )
+ {
+ OSL_FAIL( "OQueryController::impl_reset: could not retrieve the layout information from the query!" );
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ bValid = true;
+ // assume that we got all necessary information during initialization
+ }
+
+ if ( bValid )
+ {
+ // load the layoutInformation
+ if ( aLayoutInformation.hasElements() )
+ {
+ try
+ {
+ loadViewSettings( aLayoutInformation );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+
+ if ( !m_sStatement.isEmpty() )
+ {
+ setQueryComposer();
+
+ bool bError( false );
+
+ if ( !m_pSqlIterator )
+ {
+ bError = true;
+ }
+ else if ( m_bEscapeProcessing )
+ {
+ OUString aErrorMsg;
+ std::unique_ptr< ::connectivity::OSQLParseNode > pNode(
+ m_aSqlParser.parseTree( aErrorMsg, m_sStatement, m_bGraphicalDesign ) );
+
+ if (pNode)
+ {
+ delete m_pSqlIterator->getParseTree();
+ m_pSqlIterator->setParseTree( pNode.release() );
+ m_pSqlIterator->traverseAll();
+ if ( m_pSqlIterator->hasErrors() )
+ {
+ if ( !i_bForceCurrentControllerSettings && m_bGraphicalDesign && !editingView() )
+ {
+ impl_showAutoSQLViewError( Any( m_pSqlIterator->getErrors() ) );
+ }
+ bError = true;
+ }
+ }
+ else
+ {
+ if ( !i_bForceCurrentControllerSettings && !editingView() )
+ {
+ OUString aTitle(DBA_RES(STR_SVT_SQL_SYNTAX_ERROR));
+ OSQLMessageBox aDlg(getFrameWeld(), aTitle, aErrorMsg);
+ aDlg.run();
+ }
+ bError = true;
+ }
+ }
+
+ if ( bError )
+ {
+ m_bGraphicalDesign = false;
+ if ( editingView() )
+ // if we're editing a view whose statement could not be parsed, default to "no escape processing"
+ setEscapeProcessing_fireEvent( false );
+ }
+ }
+ }
+
+ if(!m_pSqlIterator)
+ setQueryComposer();
+ OSL_ENSURE(m_pSqlIterator,"No SQLIterator set!");
+
+ getContainer()->setNoneVisibleRow(m_nVisibleRows);
+}
+
+void OQueryController::reset()
+{
+ impl_reset();
+ getContainer()->reset();
+ ClearUndoManager();
+}
+
+void OQueryController::setStatement_fireEvent( const OUString& _rNewStatement, bool _bFireStatementChange )
+{
+ Any aOldValue( m_sStatement );
+ m_sStatement = _rNewStatement;
+ Any aNewValue( m_sStatement );
+
+ sal_Int32 nHandle = PROPERTY_ID_ACTIVECOMMAND;
+ if ( _bFireStatementChange )
+ fire( &nHandle, &aNewValue, &aOldValue, 1, false );
+}
+
+void OQueryController::setEscapeProcessing_fireEvent( const bool _bEscapeProcessing )
+{
+ if ( _bEscapeProcessing == m_bEscapeProcessing )
+ return;
+
+ Any aOldValue( m_bEscapeProcessing );
+ m_bEscapeProcessing = _bEscapeProcessing;
+ Any aNewValue( m_bEscapeProcessing );
+
+ sal_Int32 nHandle = PROPERTY_ID_ESCAPE_PROCESSING;
+ fire( &nHandle, &aNewValue, &aOldValue, 1, false );
+}
+
+IMPL_LINK_NOARG( OQueryController, OnExecuteAddTable, void*, void )
+{
+ Execute( ID_BROWSER_ADDTABLE,Sequence<PropertyValue>() );
+}
+
+bool OQueryController::allowViews() const
+{
+ return true;
+}
+
+bool OQueryController::allowQueries() const
+{
+ OSL_ENSURE( getSdbMetaData().isConnected(), "OQueryController::allowQueries: illegal call!" );
+ if ( !getSdbMetaData().supportsSubqueriesInFrom() )
+ return false;
+
+ const NamedValueCollection& rArguments( getInitParams() );
+ sal_Int32 nCommandType = rArguments.getOrDefault( PROPERTY_COMMAND_TYPE, sal_Int32(CommandType::QUERY) );
+ bool bCreatingView = ( nCommandType == CommandType::TABLE );
+ return !bCreatingView;
+}
+
+Any SAL_CALL OQueryController::getViewData()
+{
+ ::osl::MutexGuard aGuard( getMutex() );
+
+ getContainer()->SaveUIConfig();
+
+ ::comphelper::NamedValueCollection aViewSettings;
+ saveViewSettings( aViewSettings, false );
+
+ return Any( aViewSettings.getPropertyValues() );
+}
+
+void SAL_CALL OQueryController::restoreViewData(const Any& /*Data*/)
+{
+ // TODO
+}
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/querydesign/querydlg.cxx b/dbaccess/source/ui/querydesign/querydlg.cxx
new file mode 100644
index 000000000..5a21998d9
--- /dev/null
+++ b/dbaccess/source/ui/querydesign/querydlg.cxx
@@ -0,0 +1,313 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "querydlg.hxx"
+#include <JoinController.hxx>
+#include <JoinDesignView.hxx>
+#include <strings.hrc>
+#include <tools/diagnose_ex.h>
+#include "QTableConnectionData.hxx"
+#include <core_resource.hxx>
+#include <QueryTableView.hxx>
+#include <com/sun/star/sdbc/XDatabaseMetaData.hpp>
+#include <com/sun/star/sdbc/SQLException.hpp>
+#include <RelationControl.hxx>
+
+#define ID_INNER_JOIN 1
+#define ID_LEFT_JOIN 2
+#define ID_RIGHT_JOIN 3
+#define ID_FULL_JOIN 4
+#define ID_CROSS_JOIN 5
+
+using namespace dbaui;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::sdbc;
+
+DlgQryJoin::DlgQryJoin(const OQueryTableView* pParent,
+ const TTableConnectionData::value_type& _pData,
+ const OJoinTableView::OTableWindowMap* _pTableMap,
+ const Reference< XConnection >& _xConnection,
+ bool _bAllowTableSelect)
+ : GenericDialogController(pParent->GetFrameWeld(), "dbaccess/ui/joindialog.ui", "JoinDialog")
+ , eJoinType(static_cast<OQueryTableConnectionData*>(_pData.get())->GetJoinType())
+ , m_pOrigConnData(_pData)
+ , m_xConnection(_xConnection)
+ , m_xML_HelpText(m_xBuilder->weld_label("helptext"))
+ , m_xPB_OK(m_xBuilder->weld_button("ok"))
+ , m_xLB_JoinType(m_xBuilder->weld_combo_box("type"))
+ , m_xCBNatural(m_xBuilder->weld_check_button("natural"))
+{
+ Size aSize(m_xML_HelpText->get_approximate_digit_width() * 44,
+ m_xML_HelpText->get_text_height() * 6);
+ //alternatively loop through the STR_QUERY_* strings with their STR_JOIN_TYPE_HINT
+ //suffix to find the longest entry at runtime
+ m_xML_HelpText->set_size_request(aSize.Width(), aSize.Height());
+
+ // Copy connection
+ m_pConnData = _pData->NewInstance();
+ m_pConnData->CopyFrom(*_pData);
+
+ m_xTableControl.reset(new OTableListBoxControl(m_xBuilder.get(), _pTableMap, this));
+
+ m_xCBNatural->set_active(static_cast<OQueryTableConnectionData*>(m_pConnData.get())->isNatural());
+
+ if( _bAllowTableSelect )
+ {
+ m_xTableControl->Init( m_pConnData );
+ m_xTableControl->fillListBoxes();
+ }
+ else
+ {
+ m_xTableControl->fillAndDisable(m_pConnData);
+ m_xTableControl->Init( m_pConnData );
+ }
+
+ m_xTableControl->lateUIInit();
+
+ bool bSupportFullJoin = false;
+ Reference<XDatabaseMetaData> xMeta;
+ try
+ {
+ xMeta = m_xConnection->getMetaData();
+ if ( xMeta.is() )
+ bSupportFullJoin = xMeta->supportsFullOuterJoins();
+ }
+ catch(SQLException&)
+ {
+ }
+ bool bSupportOuterJoin = false;
+ try
+ {
+ if ( xMeta.is() )
+ bSupportOuterJoin= xMeta->supportsOuterJoins();
+ }
+ catch(SQLException&)
+ {
+ }
+
+ setJoinType(eJoinType);
+
+ m_xPB_OK->connect_clicked(LINK(this, DlgQryJoin, OKClickHdl));
+
+ m_xLB_JoinType->connect_changed(LINK(this,DlgQryJoin,LBChangeHdl));
+ m_xCBNatural->connect_toggled(LINK(this,DlgQryJoin,NaturalToggleHdl));
+
+ if ( pParent->getDesignView()->getController().isReadOnly() )
+ {
+ m_xLB_JoinType->set_sensitive(false);
+ m_xCBNatural->set_sensitive(false);
+ m_xTableControl->Disable();
+ }
+ else
+ {
+ for (sal_Int32 i = 0; i < m_xLB_JoinType->get_count();)
+ {
+ const sal_Int32 nJoinTyp = m_xLB_JoinType->get_id(i).toInt32();
+ if ( !bSupportFullJoin && nJoinTyp == ID_FULL_JOIN )
+ m_xLB_JoinType->remove(i);
+ else if ( !bSupportOuterJoin && (nJoinTyp == ID_LEFT_JOIN || nJoinTyp == ID_RIGHT_JOIN) )
+ m_xLB_JoinType->remove(i);
+ else
+ ++i;
+ }
+
+ m_xTableControl->NotifyCellChange();
+ m_xTableControl->enableRelation(!static_cast<OQueryTableConnectionData*>(m_pConnData.get())->isNatural() && eJoinType != CROSS_JOIN );
+ }
+}
+
+DlgQryJoin::~DlgQryJoin()
+{
+}
+
+IMPL_LINK_NOARG( DlgQryJoin, LBChangeHdl, weld::ComboBox&, void )
+{
+ if (!m_xLB_JoinType->get_value_changed_from_saved())
+ return;
+
+ m_xLB_JoinType->save_value();
+ m_xML_HelpText->set_label(OUString());
+
+ m_xTableControl->enableRelation(true);
+
+ OUString sFirstWinName = m_pConnData->getReferencingTable()->GetWinName();
+ OUString sSecondWinName = m_pConnData->getReferencedTable()->GetWinName();
+ const EJoinType eOldJoinType = eJoinType;
+ TranslateId pResId;
+ const sal_Int32 nPos = m_xLB_JoinType->get_active();
+ const sal_Int32 nJoinType = m_xLB_JoinType->get_id(nPos).toInt32();
+ bool bAddHint = true;
+ switch ( nJoinType )
+ {
+ default:
+ case ID_INNER_JOIN:
+ pResId = STR_QUERY_INNER_JOIN;
+ bAddHint = false;
+ eJoinType = INNER_JOIN;
+ break;
+ case ID_LEFT_JOIN:
+ pResId = STR_QUERY_LEFTRIGHT_JOIN;
+ eJoinType = LEFT_JOIN;
+ break;
+ case ID_RIGHT_JOIN:
+ {
+ pResId = STR_QUERY_LEFTRIGHT_JOIN;
+ eJoinType = RIGHT_JOIN;
+ OUString sTemp = sFirstWinName;
+ sFirstWinName = sSecondWinName;
+ sSecondWinName = sTemp;
+ }
+ break;
+ case ID_FULL_JOIN:
+ pResId = STR_QUERY_FULL_JOIN;
+ eJoinType = FULL_JOIN;
+ break;
+ case ID_CROSS_JOIN:
+ {
+ pResId = STR_QUERY_CROSS_JOIN;
+ eJoinType = CROSS_JOIN;
+
+ m_pConnData->ResetConnLines();
+ m_xTableControl->lateInit();
+ m_xCBNatural->set_active(false);
+ m_xTableControl->enableRelation(false);
+ m_pConnData->AppendConnLine("","");
+ m_xPB_OK->set_sensitive(true);
+ }
+ break;
+ }
+
+ m_xCBNatural->set_sensitive(eJoinType != CROSS_JOIN);
+
+ if ( eJoinType != eOldJoinType && eOldJoinType == CROSS_JOIN )
+ {
+ m_pConnData->ResetConnLines();
+ }
+ if ( eJoinType != CROSS_JOIN )
+ {
+ m_xTableControl->NotifyCellChange();
+ NaturalToggleHdl(*m_xCBNatural);
+ }
+
+ m_xTableControl->Invalidate();
+
+ OUString sHelpText = DBA_RES(pResId);
+ if( nPos )
+ {
+ sHelpText = sHelpText.replaceFirst( "%1", sFirstWinName );
+ sHelpText = sHelpText.replaceFirst( "%2", sSecondWinName );
+ }
+ if ( bAddHint )
+ {
+ sHelpText += "\n" + DBA_RES( STR_JOIN_TYPE_HINT );
+ }
+
+ m_xML_HelpText->set_label( sHelpText );
+}
+
+IMPL_LINK_NOARG(DlgQryJoin, OKClickHdl, weld::Button&, void)
+{
+ m_pConnData->Update();
+ m_pOrigConnData->CopyFrom( *m_pConnData );
+
+ m_xDialog->response(RET_OK);
+}
+
+IMPL_LINK_NOARG(DlgQryJoin, NaturalToggleHdl, weld::Toggleable&, void)
+{
+ bool bChecked = m_xCBNatural->get_active();
+ static_cast<OQueryTableConnectionData*>(m_pConnData.get())->setNatural(bChecked);
+ m_xTableControl->enableRelation(!bChecked);
+ if ( !bChecked )
+ return;
+
+ m_pConnData->ResetConnLines();
+ try
+ {
+ Reference<XNameAccess> xReferencedTableColumns(m_pConnData->getReferencedTable()->getColumns());
+ Sequence< OUString> aSeq = m_pConnData->getReferencingTable()->getColumns()->getElementNames();
+ const OUString* pIter = aSeq.getConstArray();
+ const OUString* pEnd = pIter + aSeq.getLength();
+ for(;pIter != pEnd;++pIter)
+ {
+ if ( xReferencedTableColumns->hasByName(*pIter) )
+ m_pConnData->AppendConnLine(*pIter,*pIter);
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ m_xTableControl->NotifyCellChange();
+ m_xTableControl->Invalidate();
+}
+
+void DlgQryJoin::setValid(bool _bValid)
+{
+ m_xPB_OK->set_sensitive(_bValid || eJoinType == CROSS_JOIN );
+}
+
+void DlgQryJoin::notifyConnectionChange( )
+{
+ setJoinType( static_cast<OQueryTableConnectionData*>(m_pConnData.get())->GetJoinType() );
+ m_xCBNatural->set_active(static_cast<OQueryTableConnectionData*>(m_pConnData.get())->isNatural());
+ NaturalToggleHdl(*m_xCBNatural);
+}
+
+void DlgQryJoin::setJoinType(EJoinType _eNewJoinType)
+{
+ eJoinType = _eNewJoinType;
+ m_xCBNatural->set_sensitive(eJoinType != CROSS_JOIN);
+
+ sal_Int32 nJoinType = 0;
+ switch ( eJoinType )
+ {
+ default:
+ case INNER_JOIN:
+ nJoinType = ID_INNER_JOIN;
+ break;
+ case LEFT_JOIN:
+ nJoinType = ID_LEFT_JOIN;
+ break;
+ case RIGHT_JOIN:
+ nJoinType = ID_RIGHT_JOIN;
+ break;
+ case FULL_JOIN:
+ nJoinType = ID_FULL_JOIN;
+ break;
+ case CROSS_JOIN:
+ nJoinType = ID_CROSS_JOIN;
+ break;
+ }
+
+ const sal_Int32 nCount = m_xLB_JoinType->get_count();
+ for (sal_Int32 i = 0; i < nCount; ++i)
+ {
+ if (nJoinType == m_xLB_JoinType->get_id(i).toInt32())
+ {
+ m_xLB_JoinType->set_active(i);
+ break;
+ }
+ }
+
+ LBChangeHdl(*m_xLB_JoinType);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/querydesign/querydlg.hxx b/dbaccess/source/ui/querydesign/querydlg.hxx
new file mode 100644
index 000000000..3da416c6e
--- /dev/null
+++ b/dbaccess/source/ui/querydesign/querydlg.hxx
@@ -0,0 +1,77 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <vcl/weld.hxx>
+
+#include <QEnumTypes.hxx>
+
+#include <RelControliFace.hxx>
+#include <JoinTableView.hxx>
+
+
+namespace dbaui
+{
+ class OTableListBoxControl;
+ class OQueryTableView;
+ class DlgQryJoin final : public weld::GenericDialogController
+ , public IRelationControlInterface
+ {
+ EJoinType eJoinType;
+ TTableConnectionData::value_type m_pConnData; // contains left and right table
+ TTableConnectionData::value_type m_pOrigConnData;
+ css::uno::Reference< css::sdbc::XConnection > m_xConnection;
+
+ std::unique_ptr<weld::Label> m_xML_HelpText;
+ std::unique_ptr<weld::Button> m_xPB_OK;
+ std::unique_ptr<weld::ComboBox> m_xLB_JoinType;
+ std::unique_ptr<weld::CheckButton> m_xCBNatural;
+ std::unique_ptr<OTableListBoxControl> m_xTableControl;
+
+ DECL_LINK(OKClickHdl, weld::Button&, void);
+ DECL_LINK(LBChangeHdl, weld::ComboBox&, void);
+ DECL_LINK(NaturalToggleHdl, weld::Toggleable&, void);
+
+ /** setJoinType enables and set the new join type
+ @param _eNewJoinType the new jointype
+ */
+ void setJoinType(EJoinType _eNewJoinType);
+ public:
+ DlgQryJoin( const OQueryTableView * pParent,
+ const TTableConnectionData::value_type& pData,
+ const OJoinTableView::OTableWindowMap* _pTableMap,
+ const css::uno::Reference< css::sdbc::XConnection >& _xConnection,
+ bool _bAllowTableSelect);
+ virtual ~DlgQryJoin() override;
+ EJoinType GetJoinType() const { return eJoinType; };
+
+ /** setValid set the valid inside, can be used for OK buttons
+ @param _bValid true when the using control allows an update
+ */
+ virtual void setValid(bool _bValid) override;
+
+ /** notifyConnectionChange is callback which is called when the table selection has changed and a new connection exists
+ @param _pConnectionData the connection which exists between the new tables
+ */
+ virtual void notifyConnectionChange() override;
+ };
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/relationdesign/RTableConnection.cxx b/dbaccess/source/ui/relationdesign/RTableConnection.cxx
new file mode 100644
index 000000000..ba60ae546
--- /dev/null
+++ b/dbaccess/source/ui/relationdesign/RTableConnection.cxx
@@ -0,0 +1,117 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "RTableConnection.hxx"
+#include <RTableConnectionData.hxx>
+#include <RelationTableView.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/settings.hxx>
+#include <ConnectionLine.hxx>
+
+using namespace dbaui;
+ORelationTableConnection::ORelationTableConnection( ORelationTableView* pContainer,
+ const TTableConnectionData::value_type& pTabConnData )
+ :OTableConnection( pContainer, pTabConnData )
+{
+}
+
+ORelationTableConnection::ORelationTableConnection( const ORelationTableConnection& rConn )
+ : VclReferenceBase(), OTableConnection( rConn )
+{
+ // no own members, thus the base class functionality is enough
+}
+
+ORelationTableConnection& ORelationTableConnection::operator=( const ORelationTableConnection& rConn )
+{
+ // this doesn't change anything, since the base class tests this, too and I don't have my own members to copy
+ if (&rConn == this)
+ return *this;
+
+ OTableConnection::operator=( rConn );
+ return *this;
+}
+
+void ORelationTableConnection::Draw(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect )
+{
+ OTableConnection::Draw(rRenderContext, rRect);
+ ORelationTableConnectionData* pData = static_cast< ORelationTableConnectionData* >(GetData().get());
+ if (pData && (pData->GetCardinality() == Cardinality::Undefined))
+ return;
+
+ // search lines for top line
+ tools::Rectangle aBoundingRect;
+ tools::Long nTop = GetBoundingRect().Bottom();
+ tools::Long nTemp;
+
+ const OConnectionLine* pTopLine = nullptr;
+ const std::vector<std::unique_ptr<OConnectionLine>>& rConnLineList = GetConnLineList();
+
+ for (auto const& elem : rConnLineList)
+ {
+ if( elem->IsValid() )
+ {
+ aBoundingRect = elem->GetBoundingRect();
+ nTemp = aBoundingRect.Top();
+ if(nTemp < nTop)
+ {
+ nTop = nTemp;
+ pTopLine = elem.get();
+ }
+ }
+ }
+
+ // cardinality
+ if (!pTopLine)
+ return;
+
+ tools::Rectangle aSourcePos = pTopLine->GetSourceTextPos();
+ tools::Rectangle aDestPos = pTopLine->GetDestTextPos();
+
+ OUString aSourceText;
+ OUString aDestText;
+
+ switch (pData->GetCardinality())
+ {
+ case Cardinality::OneMany:
+ aSourceText = "1";
+ aDestText = "n";
+ break;
+
+ case Cardinality::ManyOne:
+ aSourceText = "n";
+ aDestText = "1";
+ break;
+
+ case Cardinality::OneOne:
+ aSourceText = "1";
+ aDestText = "1";
+ break;
+ default: break;
+ }
+
+ if (IsSelected())
+ rRenderContext.SetTextColor(Application::GetSettings().GetStyleSettings().GetHighlightColor());
+ else
+ rRenderContext.SetTextColor(Application::GetSettings().GetStyleSettings().GetWindowTextColor());
+
+ rRenderContext.DrawText(aSourcePos, aSourceText, DrawTextFlags::Clip | DrawTextFlags::Center | DrawTextFlags::Bottom);
+ rRenderContext.DrawText(aDestPos, aDestText, DrawTextFlags::Clip | DrawTextFlags::Center | DrawTextFlags::Bottom);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/relationdesign/RTableConnection.hxx b/dbaccess/source/ui/relationdesign/RTableConnection.hxx
new file mode 100644
index 000000000..0448d494f
--- /dev/null
+++ b/dbaccess/source/ui/relationdesign/RTableConnection.hxx
@@ -0,0 +1,40 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <TableConnection.hxx>
+
+namespace dbaui
+{
+ class ORelationTableView;
+ class ORelationTableConnection : public OTableConnection
+ {
+ public:
+ ORelationTableConnection( ORelationTableView* pContainer, const TTableConnectionData::value_type& pTabConnData );
+ ORelationTableConnection( const ORelationTableConnection& rConn );
+ // important comment to the CopyConstructor see OTableConnection(const OTableConnection&)
+
+ ORelationTableConnection& operator=( const ORelationTableConnection& rConn );
+
+ virtual void Draw(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect) override;
+ using OTableConnection::Draw;
+ };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/relationdesign/RTableConnectionData.cxx b/dbaccess/source/ui/relationdesign/RTableConnectionData.cxx
new file mode 100644
index 000000000..26b39b69c
--- /dev/null
+++ b/dbaccess/source/ui/relationdesign/RTableConnectionData.cxx
@@ -0,0 +1,398 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <RTableConnectionData.hxx>
+#include <com/sun/star/sdbc/KeyRule.hpp>
+#include <com/sun/star/sdbcx/KeyType.hpp>
+#include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
+#include <com/sun/star/sdbcx/XDataDescriptorFactory.hpp>
+#include <com/sun/star/sdbcx/XAppend.hpp>
+#include <com/sun/star/sdbcx/XDrop.hpp>
+#include <com/sun/star/container/XIndexAccess.hpp>
+#include <strings.hrc>
+#include <strings.hxx>
+#include <core_resource.hxx>
+#include <connectivity/dbexception.hxx>
+#include <connectivity/dbtools.hxx>
+#include <osl/diagnose.h>
+
+using namespace dbaui;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::sdbcx;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::lang;
+
+ORelationTableConnectionData::ORelationTableConnectionData()
+ :m_nUpdateRules(KeyRule::NO_ACTION)
+ ,m_nDeleteRules(KeyRule::NO_ACTION)
+ ,m_nCardinality(Cardinality::Undefined)
+{
+}
+
+ORelationTableConnectionData::ORelationTableConnectionData( const TTableWindowData::value_type& _pReferencingTable,
+ const TTableWindowData::value_type& _pReferencedTable,
+ const OUString& rConnName )
+ :OTableConnectionData( _pReferencingTable, _pReferencedTable )
+ ,m_nUpdateRules(KeyRule::NO_ACTION)
+ ,m_nDeleteRules(KeyRule::NO_ACTION)
+ ,m_nCardinality(Cardinality::Undefined)
+{
+ m_aConnName = rConnName;
+
+ if ( !m_aConnName.isEmpty() )
+ SetCardinality();
+}
+
+ORelationTableConnectionData::ORelationTableConnectionData( const ORelationTableConnectionData& rConnData )
+ :OTableConnectionData( rConnData )
+{
+ *this = rConnData;
+}
+
+ORelationTableConnectionData::~ORelationTableConnectionData()
+{
+}
+
+void ORelationTableConnectionData::DropRelation()
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ // delete relation
+ Reference< XIndexAccess> xKeys = getReferencingTable()->getKeys();
+ if( m_aConnName.isEmpty() || !xKeys.is() )
+ return;
+
+ const sal_Int32 nCount = xKeys->getCount();
+ for(sal_Int32 i = 0;i < nCount;++i)
+ {
+ Reference< XPropertySet> xKey(xKeys->getByIndex(i),UNO_QUERY);
+ OSL_ENSURE(xKey.is(),"Key is not valid!");
+ if(xKey.is())
+ {
+ OUString sName;
+ xKey->getPropertyValue(PROPERTY_NAME) >>= sName;
+ if(sName == m_aConnName)
+ {
+ Reference< XDrop> xDrop(xKeys,UNO_QUERY);
+ OSL_ENSURE(xDrop.is(),"can't drop key because we haven't a drop interface!");
+ if(xDrop.is())
+ xDrop->dropByIndex(i);
+ break;
+ }
+ }
+ }
+}
+
+void ORelationTableConnectionData::ChangeOrientation()
+{
+ // exchange Source- and DestFieldName of the lines
+ OUString sTempString;
+ for (auto const& elem : m_vConnLineData)
+ {
+ sTempString = elem->GetSourceFieldName();
+ elem->SetSourceFieldName( elem->GetDestFieldName() );
+ elem->SetDestFieldName( sTempString );
+ }
+
+ // adapt member
+ TTableWindowData::value_type pTemp = m_pReferencingTable;
+ m_pReferencingTable = m_pReferencedTable;
+ m_pReferencedTable = pTemp;
+}
+
+void ORelationTableConnectionData::SetCardinality()
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ m_nCardinality = Cardinality::Undefined;
+
+ if( IsSourcePrimKey() )
+ {
+ if( IsDestPrimKey() )
+ m_nCardinality = Cardinality::OneOne;
+ else
+ m_nCardinality = Cardinality::OneMany;
+ }
+
+ if( IsDestPrimKey() )
+ {
+ if( !IsSourcePrimKey() )
+ m_nCardinality = Cardinality::ManyOne;
+ }
+
+}
+
+bool ORelationTableConnectionData::checkPrimaryKey(const Reference< XPropertySet>& i_xTable,EConnectionSide _eEConnectionSide) const
+{
+ // check if Table has the primary key column depending on _eEConnectionSide
+ sal_uInt16 nPrimKeysCount = 0,
+ nValidLinesCount = 0;
+ const Reference< XNameAccess> xKeyColumns = dbtools::getPrimaryKeyColumns_throw(i_xTable);
+ if ( xKeyColumns.is() )
+ {
+ Sequence< OUString> aKeyColumns = xKeyColumns->getElementNames();
+ const OUString* pKeyIter = aKeyColumns.getConstArray();
+ const OUString* pKeyEnd = pKeyIter + aKeyColumns.getLength();
+
+ for(;pKeyIter != pKeyEnd;++pKeyIter)
+ {
+ for (auto const& elem : m_vConnLineData)
+ {
+ ++nValidLinesCount;
+ if ( elem->GetFieldName(_eEConnectionSide) == *pKeyIter )
+ {
+ ++nPrimKeysCount;
+ break;
+ }
+ }
+ }
+ if ( nPrimKeysCount != aKeyColumns.getLength() )
+ return false;
+ }
+ return nPrimKeysCount && nPrimKeysCount == nValidLinesCount;
+}
+
+void ORelationTableConnectionData::IsConnectionPossible()
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ // if the SourceFields are a PrimKey, it's only the orientation which is wrong
+ if ( IsSourcePrimKey() && !IsDestPrimKey() )
+ ChangeOrientation();
+}
+
+void ORelationTableConnectionData::CopyFrom(const OTableConnectionData& rSource)
+{
+ // retract to the (non-virtual) operator= like in the base class
+ *this = *static_cast<const ORelationTableConnectionData*>(&rSource);
+}
+
+ORelationTableConnectionData& ORelationTableConnectionData::operator=( const ORelationTableConnectionData& rConnData )
+{
+ if (&rConnData == this)
+ return *this;
+
+ OTableConnectionData::operator=( rConnData );
+ m_nUpdateRules = rConnData.GetUpdateRules();
+ m_nDeleteRules = rConnData.GetDeleteRules();
+ m_nCardinality = rConnData.GetCardinality();
+
+ return *this;
+}
+
+namespace dbaui
+{
+bool operator==(const ORelationTableConnectionData& lhs, const ORelationTableConnectionData& rhs)
+{
+ bool bEqual = (lhs.m_nUpdateRules == rhs.m_nUpdateRules)
+ && (lhs.m_nDeleteRules == rhs.m_nDeleteRules)
+ && (lhs.m_nCardinality == rhs.m_nCardinality)
+ && (lhs.getReferencingTable() == rhs.getReferencingTable())
+ && (lhs.getReferencedTable() == rhs.getReferencedTable())
+ && (lhs.m_aConnName == rhs.m_aConnName)
+ && (lhs.m_vConnLineData.size() == rhs.m_vConnLineData.size());
+
+ if ( bEqual )
+ {
+ sal_Int32 i = 0;
+ for (auto const& elem : lhs.m_vConnLineData)
+ {
+ if ( *(rhs.m_vConnLineData[i]) != *elem )
+ {
+ bEqual = false;
+ break;
+ }
+ ++i;
+ }
+ }
+ return bEqual;
+}
+
+}
+
+bool ORelationTableConnectionData::Update()
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ // delete old relation
+ {
+ DropRelation();
+ IsConnectionPossible();
+ }
+
+ // reassign the keys because the orientation could be changed
+ Reference<XPropertySet> xTableProp(getReferencingTable()->getTable());
+ Reference< XIndexAccess> xKeys ( getReferencingTable()->getKeys());
+
+ if ( !xKeys.is() )
+ return false;
+ // create new relation
+ Reference<XDataDescriptorFactory> xKeyFactory(xKeys,UNO_QUERY);
+ OSL_ENSURE(xKeyFactory.is(),"No XDataDescriptorFactory Interface!");
+ Reference<XAppend> xAppend(xKeyFactory,UNO_QUERY);
+ OSL_ENSURE(xAppend.is(),"No XAppend Interface!");
+
+ Reference<XPropertySet> xKey = xKeyFactory->createDataDescriptor();
+ OSL_ENSURE(xKey.is(),"Key is null!");
+ if ( xKey.is() && xTableProp.is() )
+ {
+ // build a foreign key name
+ OUString sSourceName;
+ xTableProp->getPropertyValue(PROPERTY_NAME) >>= sSourceName;
+ OUString sKeyName = sSourceName + getReferencedTable()->GetTableName();
+
+ xKey->setPropertyValue(PROPERTY_NAME,Any(sKeyName));
+ xKey->setPropertyValue(PROPERTY_TYPE,Any(KeyType::FOREIGN));
+ xKey->setPropertyValue(PROPERTY_REFERENCEDTABLE,Any(getReferencedTable()->GetTableName()));
+ xKey->setPropertyValue(PROPERTY_UPDATERULE, Any(GetUpdateRules()));
+ xKey->setPropertyValue(PROPERTY_DELETERULE, Any(GetDeleteRules()));
+ }
+
+ Reference<XColumnsSupplier> xColSup(xKey,UNO_QUERY);
+ if ( xColSup.is() )
+ {
+ Reference<XNameAccess> xColumns = xColSup->getColumns();
+ Reference<XDataDescriptorFactory> xColumnFactory(xColumns,UNO_QUERY);
+ Reference<XAppend> xColumnAppend(xColumns,UNO_QUERY);
+ if ( xColumnFactory.is() )
+ {
+ for (auto const& elem : m_vConnLineData)
+ {
+ if(!(elem->GetSourceFieldName().isEmpty() || elem->GetDestFieldName().isEmpty()))
+ {
+ Reference<XPropertySet> xColumn = xColumnFactory->createDataDescriptor();
+ if ( xColumn.is() )
+ {
+ xColumn->setPropertyValue(PROPERTY_NAME,Any(elem->GetSourceFieldName()));
+ xColumn->setPropertyValue(PROPERTY_RELATEDCOLUMN,Any(elem->GetDestFieldName()));
+ xColumnAppend->appendByDescriptor(xColumn);
+ }
+ }
+ }
+
+ if ( xColumns->hasElements() )
+ xAppend->appendByDescriptor(xKey);
+ }
+ // to get the key we have to reget it because after append it is no longer valid
+ }
+
+ // get the name of foreign key; search for columns
+ m_aConnName.clear();
+ xKey.clear();
+ bool bDropRelation = false;
+ for(sal_Int32 i=0;i<xKeys->getCount();++i)
+ {
+ xKeys->getByIndex(i) >>= xKey;
+ OSL_ENSURE(xKey.is(),"Key is not valid!");
+ if ( xKey.is() )
+ {
+ OUString sReferencedTable;
+ xKey->getPropertyValue(PROPERTY_REFERENCEDTABLE) >>= sReferencedTable;
+ if ( sReferencedTable == getReferencedTable()->GetTableName() )
+ {
+ xColSup.set(xKey,UNO_QUERY_THROW);
+ try
+ {
+ Reference<XNameAccess> xColumns = xColSup->getColumns();
+ Sequence< OUString> aNames = xColumns->getElementNames();
+ const OUString* pIter = aNames.getConstArray();
+ const OUString* pEnd = pIter + aNames.getLength();
+
+ Reference<XPropertySet> xColumn;
+ OUString sName,sRelatedColumn;
+ for ( ; pIter != pEnd ; ++pIter )
+ {
+ xColumn.set(xColumns->getByName(*pIter),UNO_QUERY_THROW);
+ xColumn->getPropertyValue(PROPERTY_NAME) >>= sName;
+ xColumn->getPropertyValue(PROPERTY_RELATEDCOLUMN) >>= sRelatedColumn;
+
+ bool bFoundElem = false;
+ for (auto const& elem : m_vConnLineData)
+ {
+ if( elem->GetSourceFieldName() == sName
+ && elem->GetDestFieldName() == sRelatedColumn )
+ {
+ bFoundElem = true;
+ break;
+ }
+ }
+ if (!bFoundElem)
+ break;
+ }
+ if ( pIter == pEnd )
+ {
+ xKey->getPropertyValue(PROPERTY_NAME) >>= sName;
+ m_aConnName = sName;
+ bDropRelation = !aNames.hasElements(); // the key contains no column, so it isn't valid and we have to drop it
+ //here we already know our column structure so we don't have to recreate the table connection data
+ xColSup.clear();
+ break;
+ }
+ }
+ catch(Exception&)
+ {
+ }
+ }
+ }
+ xKey.clear();
+ }
+ if ( bDropRelation )
+ {
+ DropRelation();
+ OUString sError(DBA_RES(STR_QUERY_REL_COULD_NOT_CREATE));
+ ::dbtools::throwGenericSQLException(sError,nullptr);
+ }
+
+ // The fields the relation marks may not be the same as our LineDatas mark after the relation has been updated
+ if ( xColSup.is() )
+ {
+ OConnectionLineDataVec().swap(m_vConnLineData);
+ Reference<XNameAccess> xColumns = xColSup->getColumns();
+ Sequence< OUString> aNames = xColumns->getElementNames();
+ const OUString* pIter = aNames.getConstArray();
+ const OUString* pEnd = pIter + aNames.getLength();
+
+ m_vConnLineData.reserve( aNames.getLength() );
+ Reference<XPropertySet> xColumn;
+ OUString sName,sRelatedColumn;
+
+ for(;pIter != pEnd;++pIter)
+ {
+ xColumns->getByName(*pIter) >>= xColumn;
+ if ( xColumn.is() )
+ {
+ OConnectionLineDataRef pNewData = new OConnectionLineData();
+
+ xColumn->getPropertyValue(PROPERTY_NAME) >>= sName;
+ xColumn->getPropertyValue(PROPERTY_RELATEDCOLUMN) >>= sRelatedColumn;
+
+ pNewData->SetSourceFieldName(sName);
+ pNewData->SetDestFieldName(sRelatedColumn);
+ m_vConnLineData.push_back(pNewData);
+ }
+ }
+ }
+ // NOTE : the caller is responsible for updating any other objects referencing the old LineDatas (for instance a ConnLine)
+
+ // determine cardinality
+ SetCardinality();
+
+ return true;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/relationdesign/RTableWindow.hxx b/dbaccess/source/ui/relationdesign/RTableWindow.hxx
new file mode 100644
index 000000000..25b8d05a1
--- /dev/null
+++ b/dbaccess/source/ui/relationdesign/RTableWindow.hxx
@@ -0,0 +1,40 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <TableWindow.hxx>
+
+namespace dbaui
+{
+ class ORelationTableWindow : public OTableWindow
+ {
+ public:
+ ORelationTableWindow( vcl::Window* pParent,const TTableWindowData::value_type& pTabWinData)
+ : OTableWindow(pParent, pTabWinData) {}
+
+ /** returns the name which should be used when displaying join or relations
+ @return
+ The composed name or the window name.
+ */
+ virtual OUString GetName() const override { return GetComposedName(); }
+ };
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/relationdesign/RelationController.cxx b/dbaccess/source/ui/relationdesign/RelationController.cxx
new file mode 100644
index 000000000..e35eebe96
--- /dev/null
+++ b/dbaccess/source/ui/relationdesign/RelationController.cxx
@@ -0,0 +1,548 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+
+#include <map>
+
+#include <strings.hrc>
+#include <strings.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/weld.hxx>
+#include <browserids.hxx>
+#include <comphelper/types.hxx>
+#include <core_resource.hxx>
+#include <connectivity/dbtools.hxx>
+#include <com/sun/star/sdbcx/XTablesSupplier.hpp>
+#include <com/sun/star/sdbcx/KeyType.hpp>
+#include <com/sun/star/sdbcx/XKeysSupplier.hpp>
+#include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
+#include <com/sun/star/sdbc/SQLException.hpp>
+#include <com/sun/star/sdbc/XRow.hpp>
+#include <connectivity/dbexception.hxx>
+#include <connectivity/dbmetadata.hxx>
+#include <sqlmessage.hxx>
+#include <RelationController.hxx>
+#include <TableWindowData.hxx>
+#include <UITools.hxx>
+#include <RTableConnectionData.hxx>
+#include <RelationTableView.hxx>
+#include <RelationDesignView.hxx>
+#include <tools/diagnose_ex.h>
+#include <osl/thread.hxx>
+#include <osl/mutex.hxx>
+
+#define MAX_THREADS 10
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+org_openoffice_comp_dbu_ORelationDesign_get_implementation(
+ css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const& )
+{
+ return cppu::acquire(new ::dbaui::ORelationController(context));
+}
+
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::io;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::frame;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::sdbcx;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::sdb;
+using namespace ::com::sun::star::ui::dialogs;
+using namespace ::com::sun::star::util;
+using namespace ::dbtools;
+using namespace ::dbaui;
+using namespace ::comphelper;
+using namespace ::osl;
+
+OUString SAL_CALL ORelationController::getImplementationName()
+{
+ return "org.openoffice.comp.dbu.ORelationDesign";
+}
+
+Sequence< OUString> SAL_CALL ORelationController::getSupportedServiceNames()
+{
+ return { "com.sun.star.sdb.RelationDesign" };
+}
+
+ORelationController::ORelationController(const Reference< XComponentContext >& _rM)
+ : OJoinController(_rM)
+ ,m_nThreadEvent(0)
+ ,m_bRelationsPossible(true)
+{
+ InvalidateAll();
+}
+
+ORelationController::~ORelationController()
+{
+}
+
+FeatureState ORelationController::GetState(sal_uInt16 _nId) const
+{
+ FeatureState aReturn;
+ aReturn.bEnabled = m_bRelationsPossible;
+ switch (_nId)
+ {
+ case SID_RELATION_ADD_RELATION:
+ aReturn.bEnabled = !m_vTableData.empty() && isConnected() && isEditable();
+ aReturn.bChecked = false;
+ break;
+ case ID_BROWSER_SAVEDOC:
+ aReturn.bEnabled = haveDataSource() && impl_isModified();
+ break;
+ default:
+ aReturn = OJoinController::GetState(_nId);
+ break;
+ }
+ return aReturn;
+}
+
+void ORelationController::Execute(sal_uInt16 _nId, const Sequence< PropertyValue >& aArgs)
+{
+ switch(_nId)
+ {
+ case ID_BROWSER_SAVEDOC:
+ {
+ OSL_ENSURE(isEditable(),"Slot ID_BROWSER_SAVEDOC should not be enabled!");
+ if(!::dbaui::checkDataSourceAvailable(::comphelper::getString(getDataSource()->getPropertyValue(PROPERTY_NAME)), getORB()))
+ {
+ OUString aMessage(DBA_RES(STR_DATASOURCE_DELETED));
+ OSQLWarningBox aWarning(getFrameWeld(), aMessage);
+ aWarning.run();
+ }
+ else
+ {
+ // now we save the layout information
+ // create the output stream
+ try
+ {
+ if ( haveDataSource() && getDataSource()->getPropertySetInfo()->hasPropertyByName(PROPERTY_LAYOUTINFORMATION) )
+ {
+ ::comphelper::NamedValueCollection aWindowsData;
+ saveTableWindows( aWindowsData );
+ getDataSource()->setPropertyValue( PROPERTY_LAYOUTINFORMATION, Any( aWindowsData.getPropertyValues() ) );
+ setModified(false);
+ }
+ }
+ catch ( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+ }
+ break;
+ case SID_RELATION_ADD_RELATION:
+ static_cast<ORelationTableView*>(static_cast<ORelationDesignView*>( getView() )->getTableView())->AddNewRelation();
+ break;
+ default:
+ OJoinController::Execute(_nId,aArgs);
+ return;
+ }
+ InvalidateFeature(_nId);
+}
+
+void ORelationController::impl_initialize()
+{
+ OJoinController::impl_initialize();
+
+ if( !getSdbMetaData().supportsRelations() )
+ {// check if this database supports relations
+
+ setEditable(false);
+ m_bRelationsPossible = false;
+ {
+ OUString sTitle(DBA_RES(STR_RELATIONDESIGN));
+ sTitle = sTitle.copy(3);
+ OSQLMessageBox aDlg(getFrameWeld(), sTitle, DBA_RES(STR_RELATIONDESIGN_NOT_AVAILABLE));
+ aDlg.run();
+ }
+ disconnect();
+ throw SQLException();
+ }
+
+ if(!m_bRelationsPossible)
+ InvalidateAll();
+
+ // we need a datasource
+ OSL_ENSURE(haveDataSource(),"ORelationController::initialize: need a datasource!");
+
+ Reference<XTablesSupplier> xSup(getConnection(),UNO_QUERY);
+ OSL_ENSURE(xSup.is(),"Connection isn't a XTablesSupplier!");
+ if(xSup.is())
+ m_xTables = xSup->getTables();
+ // load the layoutInformation
+ loadLayoutInformation();
+ try
+ {
+ loadData();
+ if ( !m_nThreadEvent )
+ Application::PostUserEvent(LINK(this, ORelationController, OnThreadFinished));
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+
+}
+
+OUString ORelationController::getPrivateTitle( ) const
+{
+ OUString sName = getDataSourceName();
+ return ::dbaui::getStrippedDatabaseName(getDataSource(),sName);
+}
+
+bool ORelationController::Construct(vcl::Window* pParent)
+{
+ setView( VclPtr<ORelationDesignView>::Create( pParent, *this, getORB() ) );
+ OJoinController::Construct(pParent);
+ return true;
+}
+
+short ORelationController::saveModified()
+{
+ short nSaved = RET_YES;
+ if(haveDataSource() && isModified())
+ {
+ std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(getFrameWeld(), "dbaccess/ui/designsavemodifieddialog.ui"));
+ std::unique_ptr<weld::MessageDialog> xQuery(xBuilder->weld_message_dialog("DesignSaveModifiedDialog"));
+ nSaved = xQuery->run();
+ if(nSaved == RET_YES)
+ Execute(ID_BROWSER_SAVEDOC,Sequence<PropertyValue>());
+ }
+ return nSaved;
+}
+
+void ORelationController::describeSupportedFeatures()
+{
+ OJoinController::describeSupportedFeatures();
+ implDescribeSupportedFeature( ".uno:DBAddRelation", SID_RELATION_ADD_RELATION, CommandGroup::EDIT );
+}
+
+namespace
+{
+ class RelationLoader : public ::osl::Thread
+ {
+ typedef std::map<OUString, std::shared_ptr<OTableWindowData>, ::comphelper::UStringMixLess> TTableDataHelper;
+ TTableDataHelper m_aTableData;
+ TTableConnectionData m_vTableConnectionData;
+ const Sequence< OUString> m_aTableList;
+ ORelationController* m_pParent;
+ const Reference< XDatabaseMetaData> m_xMetaData;
+ const Reference< XNameAccess > m_xTables;
+ const sal_Int32 m_nStartIndex;
+ const sal_Int32 m_nEndIndex;
+
+ public:
+ RelationLoader(ORelationController* _pParent
+ ,const Reference< XDatabaseMetaData>& _xMetaData
+ ,const Reference< XNameAccess >& _xTables
+ ,const Sequence< OUString>& _aTableList
+ ,const sal_Int32 _nStartIndex
+ ,const sal_Int32 _nEndIndex)
+ :m_aTableData(_xMetaData.is() && _xMetaData->supportsMixedCaseQuotedIdentifiers())
+ ,m_aTableList(_aTableList)
+ ,m_pParent(_pParent)
+ ,m_xMetaData(_xMetaData)
+ ,m_xTables(_xTables)
+ ,m_nStartIndex(_nStartIndex)
+ ,m_nEndIndex(_nEndIndex)
+ {
+ }
+
+ /// Working method which should be overridden.
+ virtual void SAL_CALL run() override;
+ virtual void SAL_CALL onTerminated() override;
+ protected:
+ virtual ~RelationLoader() override {}
+
+ void loadTableData(const Any& _aTable);
+ };
+
+ void SAL_CALL RelationLoader::run()
+ {
+ osl_setThreadName("RelationLoader");
+
+ for(sal_Int32 i = m_nStartIndex; i < m_nEndIndex; ++i)
+ {
+ OUString sCatalog,sSchema,sTable;
+ ::dbtools::qualifiedNameComponents(m_xMetaData,
+ m_aTableList[i],
+ sCatalog,
+ sSchema,
+ sTable,
+ ::dbtools::EComposeRule::InDataManipulation);
+ Any aCatalog;
+ if ( !sCatalog.isEmpty() )
+ aCatalog <<= sCatalog;
+
+ try
+ {
+ Reference< XResultSet > xResult = m_xMetaData->getImportedKeys(aCatalog, sSchema,sTable);
+ if ( xResult.is() && xResult->next() )
+ {
+ ::comphelper::disposeComponent(xResult);
+ loadTableData(m_xTables->getByName(m_aTableList[i]));
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+ }
+ void SAL_CALL RelationLoader::onTerminated()
+ {
+ m_pParent->mergeData(m_vTableConnectionData);
+ delete this;
+ }
+
+ void RelationLoader::loadTableData(const Any& _aTable)
+ {
+ Reference<XPropertySet> xTableProp(_aTable,UNO_QUERY);
+ const OUString sSourceName = ::dbtools::composeTableName( m_xMetaData, xTableProp, ::dbtools::EComposeRule::InTableDefinitions, false );
+ TTableDataHelper::const_iterator aFind = m_aTableData.find(sSourceName);
+ if ( aFind == m_aTableData.end() )
+ {
+ aFind = m_aTableData.emplace(sSourceName,std::make_shared<OTableWindowData>(xTableProp,sSourceName, sSourceName, OUString())).first;
+ aFind->second->ShowAll(false);
+ }
+ TTableWindowData::value_type pReferencingTable = aFind->second;
+ Reference<XIndexAccess> xKeys = pReferencingTable->getKeys();
+ const Reference<XKeysSupplier> xKeySup(xTableProp,UNO_QUERY);
+
+ if ( !xKeys.is() && xKeySup.is() )
+ {
+ xKeys = xKeySup->getKeys();
+ }
+
+ if ( !xKeys.is() )
+ return;
+
+ Reference<XPropertySet> xKey;
+ const sal_Int32 nCount = xKeys->getCount();
+ for(sal_Int32 i = 0 ; i < nCount ; ++i)
+ {
+ xKeys->getByIndex(i) >>= xKey;
+ sal_Int32 nKeyType = 0;
+ xKey->getPropertyValue(PROPERTY_TYPE) >>= nKeyType;
+ if ( KeyType::FOREIGN == nKeyType )
+ {
+ OUString sReferencedTable;
+ xKey->getPropertyValue(PROPERTY_REFERENCEDTABLE) >>= sReferencedTable;
+
+ // insert windows
+ TTableDataHelper::const_iterator aRefFind = m_aTableData.find(sReferencedTable);
+ if ( aRefFind == m_aTableData.end() )
+ {
+ if ( m_xTables->hasByName(sReferencedTable) )
+ {
+ Reference<XPropertySet> xReferencedTable(m_xTables->getByName(sReferencedTable),UNO_QUERY);
+ aRefFind = m_aTableData.emplace(sReferencedTable,std::make_shared<OTableWindowData>(xReferencedTable,sReferencedTable, sReferencedTable, OUString())).first;
+ aRefFind->second->ShowAll(false);
+ }
+ else
+ continue; // table name could not be found so we do not show this table relation
+ }
+ TTableWindowData::value_type pReferencedTable = aRefFind->second;
+
+ OUString sKeyName;
+ xKey->getPropertyValue(PROPERTY_NAME) >>= sKeyName;
+ // insert connection
+ auto xTabConnData = std::make_shared<ORelationTableConnectionData>( pReferencingTable, pReferencedTable, sKeyName );
+ m_vTableConnectionData.push_back(xTabConnData);
+ // insert columns
+ const Reference<XColumnsSupplier> xColsSup(xKey,UNO_QUERY);
+ OSL_ENSURE(xColsSup.is(),"Key is no XColumnsSupplier!");
+ const Reference<XNameAccess> xColumns = xColsSup->getColumns();
+ const Sequence< OUString> aNames = xColumns->getElementNames();
+ OUString sColumnName,sRelatedName;
+ for(sal_Int32 j=0;j<aNames.getLength();++j)
+ {
+ const Reference<XPropertySet> xPropSet(xColumns->getByName(aNames[j]),UNO_QUERY);
+ OSL_ENSURE(xPropSet.is(),"Invalid column found in KeyColumns!");
+ if ( xPropSet.is() )
+ {
+ xPropSet->getPropertyValue(PROPERTY_NAME) >>= sColumnName;
+ xPropSet->getPropertyValue(PROPERTY_RELATEDCOLUMN) >>= sRelatedName;
+ }
+ xTabConnData->SetConnLine( j, sColumnName, sRelatedName );
+ }
+ // set update/del flags
+ sal_Int32 nUpdateRule = 0;
+ sal_Int32 nDeleteRule = 0;
+ xKey->getPropertyValue(PROPERTY_UPDATERULE) >>= nUpdateRule;
+ xKey->getPropertyValue(PROPERTY_DELETERULE) >>= nDeleteRule;
+
+ xTabConnData->SetUpdateRules( nUpdateRule );
+ xTabConnData->SetDeleteRules( nDeleteRule );
+
+ // set cardinality
+ xTabConnData->SetCardinality();
+ }
+ }
+ }
+}
+
+void ORelationController::mergeData(const TTableConnectionData& _aConnectionData)
+{
+ ::osl::MutexGuard aGuard( getMutex() );
+
+ m_vTableConnectionData.insert( m_vTableConnectionData.end(), _aConnectionData.begin(), _aConnectionData.end() );
+ // here we are finished, so we can collect the table from connection data
+ for (auto const& elem : m_vTableConnectionData)
+ {
+ if ( !existsTable(elem->getReferencingTable()->GetComposedName()) )
+ {
+ m_vTableData.push_back(elem->getReferencingTable());
+ }
+ if ( !existsTable(elem->getReferencedTable()->GetComposedName()) )
+ {
+ m_vTableData.push_back(elem->getReferencedTable());
+ }
+ }
+ if ( m_nThreadEvent )
+ {
+ --m_nThreadEvent;
+ if ( !m_nThreadEvent )
+ Application::PostUserEvent(LINK(this, ORelationController, OnThreadFinished));
+ }
+}
+
+IMPL_LINK_NOARG( ORelationController, OnThreadFinished, void*, void )
+{
+ ::SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( getMutex() );
+ try
+ {
+ getView()->initialize(); // show the windows and fill with our information
+ getView()->Invalidate(InvalidateFlags::NoErase);
+ ClearUndoManager();
+ setModified(false); // and we are not modified yet
+
+ if(m_vTableData.empty())
+ Execute(ID_BROWSER_ADDTABLE,Sequence<PropertyValue>());
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ m_xWaitObject.reset();
+}
+
+void ORelationController::loadData()
+{
+ m_xWaitObject.reset(new weld::WaitObject(getFrameWeld()));
+ try
+ {
+ if ( !m_xTables.is() )
+ return;
+ DatabaseMetaData aMeta(getConnection());
+ // this may take some time
+ const Reference< XDatabaseMetaData> xMetaData = getConnection()->getMetaData();
+ const Sequence< OUString> aNames = m_xTables->getElementNames();
+ const sal_Int32 nCount = aNames.getLength();
+ if ( aMeta.supportsThreads() )
+ {
+ const sal_Int32 nMaxElements = (nCount / MAX_THREADS) +1;
+ sal_Int32 nStart = 0,nEnd = std::min(nMaxElements,nCount);
+ while(nStart != nEnd)
+ {
+ ++m_nThreadEvent;
+ RelationLoader* pThread = new RelationLoader(this,xMetaData,m_xTables,aNames,nStart,nEnd);
+ pThread->createSuspended();
+ pThread->setPriority(osl_Thread_PriorityBelowNormal);
+ pThread->resume();
+ nStart = nEnd;
+ nEnd += nMaxElements;
+ nEnd = std::min(nEnd,nCount);
+ }
+ }
+ else
+ {
+ RelationLoader* pThread = new RelationLoader(this,xMetaData,m_xTables,aNames,0,nCount);
+ pThread->run();
+ pThread->onTerminated();
+ }
+ }
+ catch(SQLException& e)
+ {
+ showError(SQLExceptionInfo(e));
+ }
+ catch(const Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+}
+
+TTableWindowData::value_type ORelationController::existsTable(std::u16string_view _rComposedTableName) const
+{
+ ::comphelper::UStringMixEqual bCase(true);
+ for (auto const& elem : m_vTableData)
+ {
+ if(bCase(elem->GetComposedName(),_rComposedTableName))
+ return elem;
+ }
+ return TTableWindowData::value_type();
+}
+
+void ORelationController::loadLayoutInformation()
+{
+ try
+ {
+ OSL_ENSURE(haveDataSource(),"We need a datasource from our connection!");
+ if ( haveDataSource() )
+ {
+ if ( getDataSource()->getPropertySetInfo()->hasPropertyByName(PROPERTY_LAYOUTINFORMATION) )
+ {
+ Sequence<PropertyValue> aWindows;
+ getDataSource()->getPropertyValue(PROPERTY_LAYOUTINFORMATION) >>= aWindows;
+ loadTableWindows(aWindows);
+ }
+ }
+ }
+ catch(Exception&)
+ {
+ }
+}
+
+void ORelationController::reset()
+{
+ loadLayoutInformation();
+ ODataView* pView = getView();
+ OSL_ENSURE(pView,"No current view!");
+ if(pView)
+ {
+ pView->initialize();
+ pView->Invalidate(InvalidateFlags::NoErase);
+ }
+}
+
+bool ORelationController::allowViews() const
+{
+ return false;
+}
+
+bool ORelationController::allowQueries() const
+{
+ return false;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/relationdesign/RelationDesignView.cxx b/dbaccess/source/ui/relationdesign/RelationDesignView.cxx
new file mode 100644
index 000000000..014579cf7
--- /dev/null
+++ b/dbaccess/source/ui/relationdesign/RelationDesignView.cxx
@@ -0,0 +1,74 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <RelationDesignView.hxx>
+#include <RelationTableView.hxx>
+#include <RelationController.hxx>
+#include <vcl/event.hxx>
+
+using namespace ::dbaui;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::container;
+
+ORelationDesignView::ORelationDesignView(vcl::Window* _pParent, ORelationController& _rController,const Reference< XComponentContext >& _rxContext)
+ :OJoinDesignView( _pParent, _rController, _rxContext )
+{
+}
+
+void ORelationDesignView::Construct()
+{
+ m_pTableView = VclPtr<ORelationTableView>::Create(m_pScrollWindow,this);
+ OJoinDesignView::Construct();
+}
+
+void ORelationDesignView::initialize()
+{
+ m_pTableView->clearLayoutInformation();
+ m_pTableView->ReSync();
+
+ OJoinDesignView::initialize();
+}
+
+bool ORelationDesignView::PreNotify( NotifyEvent& rNEvt )
+{
+ bool bDone = false;
+ if(rNEvt.GetType() == MouseNotifyEvent::GETFOCUS)
+ {
+ if(m_pTableView && !m_pTableView->HasChildPathFocus())
+ {
+ m_pTableView->GrabTabWinFocus();
+ bDone = true;
+ }
+ }
+ if(!bDone)
+ bDone = OJoinDesignView::PreNotify(rNEvt);
+ return bDone;
+}
+
+void ORelationDesignView::GetFocus()
+{
+ OJoinDesignView::GetFocus();
+ if ( m_pTableView && m_pTableView->IsVisible() && !m_pTableView->GetTabWinMap().empty() )
+ m_pTableView->GrabTabWinFocus();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/relationdesign/RelationTableView.cxx b/dbaccess/source/ui/relationdesign/RelationTableView.cxx
new file mode 100644
index 000000000..ea7b83146
--- /dev/null
+++ b/dbaccess/source/ui/relationdesign/RelationTableView.cxx
@@ -0,0 +1,410 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <RelationTableView.hxx>
+#include <core_resource.hxx>
+#include <browserids.hxx>
+#include <com/sun/star/sdbcx/XTablesSupplier.hpp>
+#include <com/sun/star/sdbc/XConnection.hpp>
+#include <com/sun/star/sdbc/SQLException.hpp>
+#include <com/sun/star/container/XContainer.hpp>
+#include <com/sun/star/container/XIndexAccess.hpp>
+#include <com/sun/star/container/XNameAccess.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <connectivity/dbtools.hxx>
+#include <tools/diagnose_ex.h>
+#include <helpids.h>
+#include <RelationDesignView.hxx>
+#include <JoinController.hxx>
+#include <TableWindow.hxx>
+#include <TableWindowData.hxx>
+#include "RTableConnection.hxx"
+#include <RTableConnectionData.hxx>
+#include <RelationDlg.hxx>
+#include <sqlmessage.hxx>
+#include <strings.hrc>
+#include <connectivity/dbexception.hxx>
+#include "RTableWindow.hxx"
+#include <JAccess.hxx>
+#include <vcl/stdtext.hxx>
+#include <com/sun/star/accessibility/AccessibleEventId.hpp>
+
+using namespace dbaui;
+using namespace ::dbtools;
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::sdbcx;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::accessibility;
+
+ORelationTableView::ORelationTableView( vcl::Window* pParent, ORelationDesignView* pView )
+ :OJoinTableView( pParent, pView )
+ , ::comphelper::OContainerListener(m_aMutex)
+ ,m_pExistingConnection(nullptr)
+ ,m_bInRemove(false)
+
+{
+ SetHelpId(HID_CTL_RELATIONTAB);
+}
+
+ORelationTableView::~ORelationTableView()
+{
+ disposeOnce();
+}
+
+void ORelationTableView::dispose()
+{
+ if ( m_pContainerListener.is() )
+ m_pContainerListener->dispose();
+ m_pExistingConnection.clear();
+ OJoinTableView::dispose();
+}
+
+void ORelationTableView::ReSync()
+{
+ if ( !m_pContainerListener.is() )
+ {
+ Reference< XConnection> xConnection = m_pView->getController().getConnection();
+ Reference< XTablesSupplier > xTableSupp( xConnection, UNO_QUERY_THROW );
+ Reference< XNameAccess > xTables = xTableSupp->getTables();
+ Reference< XContainer> xContainer(xTables,uno::UNO_QUERY);
+ if ( xContainer.is() )
+ m_pContainerListener = new ::comphelper::OContainerListenerAdapter(this,xContainer);
+ }
+ // Tables could have been hidden in the database, which are part of a relation. Or a table was in layout
+ // (quite often without a relation) and does not exist anymore. In both cases creation of TabWins will fail
+ // and all TabWinDatas and related ConnDates should be deleted.
+ std::vector< OUString> arrInvalidTables;
+
+ // create and insert windows
+ TTableWindowData& rTabWinDataList = m_pView->getController().getTableWindowData();
+ TTableWindowData::const_reverse_iterator aIter = rTabWinDataList.rbegin();
+ for(;aIter != rTabWinDataList.rend();++aIter)
+ {
+ TTableWindowData::value_type pData = *aIter;
+ VclPtr<OTableWindow> pTabWin = createWindow(pData);
+
+ if (!pTabWin->Init())
+ {
+ // initialisation failed, which means this TabWin is not available, therefore,
+ // it should be cleaned up, including its data in the document
+ pTabWin->clearListBox();
+ pTabWin.disposeAndClear();
+ arrInvalidTables.push_back(pData->GetTableName());
+
+ rTabWinDataList.erase( std::remove(rTabWinDataList.begin(), rTabWinDataList.end(), *aIter), rTabWinDataList.end());
+ continue;
+ }
+
+ GetTabWinMap()[pData->GetComposedName()] = pTabWin; // insert at the beginning, as the Datalist is walked through backward
+ // if there's no position or size contained in the data -> Default
+ if (!pData->HasPosition() && !pData->HasSize())
+ SetDefaultTabWinPosSize(pTabWin);
+
+ pTabWin->Show();
+ }
+
+ // insert connection
+ TTableConnectionData& rTabConnDataList = m_pView->getController().getTableConnectionData();
+ TTableConnectionData::const_reverse_iterator aConIter = rTabConnDataList.rbegin();
+
+ for(;aConIter != rTabConnDataList.rend();++aConIter)
+ {
+ ORelationTableConnectionData* pTabConnData = static_cast<ORelationTableConnectionData*>(aConIter->get());
+ if ( !arrInvalidTables.empty() )
+ {
+ // do the tables to the connection exist?
+ OUString strTabExistenceTest = pTabConnData->getReferencingTable()->GetTableName();
+ bool bInvalid = std::find(arrInvalidTables.begin(),arrInvalidTables.end(),strTabExistenceTest) != arrInvalidTables.end();
+ strTabExistenceTest = pTabConnData->getReferencedTable()->GetTableName();
+ bInvalid = bInvalid || std::find(arrInvalidTables.begin(),arrInvalidTables.end(),strTabExistenceTest) != arrInvalidTables.end();
+
+ if (bInvalid)
+ {
+ // no -> bad luck, the connection is gone
+ rTabConnDataList.erase( std::remove(rTabConnDataList.begin(), rTabConnDataList.end(), *aConIter), rTabConnDataList.end() );
+ continue;
+ }
+ }
+
+ addConnection( VclPtr<ORelationTableConnection>::Create(this, *aConIter), false );
+ }
+
+ if ( !GetTabWinMap().empty() )
+ GetTabWinMap().begin()->second->GrabFocus();
+}
+
+bool ORelationTableView::IsAddAllowed()
+{
+
+ return !m_pView->getController().isReadOnly();
+}
+
+void ORelationTableView::AddConnection(const OJoinExchangeData& jxdSource, const OJoinExchangeData& jxdDest)
+{
+ // Set LineDataObject based on selected fieldname
+ // check if relation already exists
+ OTableWindow* pSourceWin = jxdSource.pListBox->GetTabWin();
+ OTableWindow* pDestWin = jxdDest.pListBox->GetTabWin();
+
+ for(VclPtr<OTableConnection> const & pFirst : getTableConnections())
+ {
+ if((pFirst->GetSourceWin() == pSourceWin && pFirst->GetDestWin() == pDestWin) ||
+ (pFirst->GetSourceWin() == pDestWin && pFirst->GetDestWin() == pSourceWin))
+ {
+ m_pExistingConnection = pFirst;
+ break;
+ }
+ }
+ // insert table connection into view
+ TTableConnectionData::value_type pTabConnData = std::make_shared<ORelationTableConnectionData>(pSourceWin->GetData(),
+ pDestWin->GetData());
+
+ // the names of the affected fields
+ weld::TreeView& rSourceTreeView = jxdSource.pListBox->get_widget();
+ OUString sSourceFieldName = rSourceTreeView.get_text(jxdSource.nEntry);
+ weld::TreeView& rDestTreeView = jxdDest.pListBox->get_widget();
+ OUString sDestFieldName = rDestTreeView.get_text(jxdDest.nEntry);
+
+ // the number of PKey-Fields in the source
+ const Reference< XNameAccess> xPrimaryKeyColumns = getPrimaryKeyColumns_throw(pSourceWin->GetData()->getTable());
+ bool bAskUser = xPrimaryKeyColumns.is() && Reference< XIndexAccess>(xPrimaryKeyColumns,UNO_QUERY_THROW)->getCount() > 1;
+
+ pTabConnData->SetConnLine( 0, sSourceFieldName, sDestFieldName );
+
+ if ( bAskUser || m_pExistingConnection )
+ m_pCurrentlyTabConnData = pTabConnData; // this implies that we ask the user what to do
+ else
+ {
+ try
+ {
+ // hand over data to the database
+ if( pTabConnData->Update() )
+ {
+ // enter UI-object into ConnList
+ addConnection( VclPtr<ORelationTableConnection>::Create( this, pTabConnData ) );
+ }
+ }
+ catch(const SQLException&)
+ {
+ throw;
+ }
+ catch(const Exception&)
+ {
+ TOOLS_WARN_EXCEPTION( "dbaccess", "ORelationTableView::AddConnection");
+ }
+ }
+}
+
+void ORelationTableView::ConnDoubleClicked(VclPtr<OTableConnection>& rConnection)
+{
+ ORelationDialog aRelDlg(this, rConnection->GetData());
+ switch (aRelDlg.run())
+ {
+ case RET_OK:
+ // successfully updated
+ rConnection->UpdateLineList();
+ // The connection references 1 ConnData and n ConnLines, each ConnData references n LineDatas, each Line exactly 1 LineData
+ // As the Dialog and the ConnData->Update may have changed the LineDatas we have to restore the consistent state
+ break;
+
+ case RET_NO:
+ // tried at least one update, but did not succeed -> the original connection is lost
+ RemoveConnection(rConnection ,true);
+ break;
+
+ case RET_CANCEL:
+ // no break, as nothing happened and we don't need the code below
+ return;
+
+ }
+
+ Invalidate(InvalidateFlags::NoChildren);
+}
+
+void ORelationTableView::AddNewRelation()
+{
+
+ TTableConnectionData::value_type pNewConnData = std::make_shared<ORelationTableConnectionData>();
+ ORelationDialog aRelDlg(this, pNewConnData, true);
+
+ bool bSuccess = (aRelDlg.run() == RET_OK);
+ if (bSuccess)
+ {
+ // already updated by the dialog
+ // announce it to the document
+ addConnection( VclPtr<ORelationTableConnection>::Create(this, pNewConnData) );
+ }
+}
+
+bool ORelationTableView::RemoveConnection(VclPtr<OTableConnection>& rConn, bool /*_bDelete*/)
+{
+ ORelationTableConnectionData* pTabConnData = static_cast<ORelationTableConnectionData*>(rConn->GetData().get());
+ try
+ {
+ if (!m_bInRemove)
+ pTabConnData->DropRelation();
+ return OJoinTableView::RemoveConnection(rConn, true);
+ }
+ catch(SQLException& e)
+ {
+ getDesignView()->getController().showError(SQLExceptionInfo(e));
+ }
+ catch(Exception&)
+ {
+ TOOLS_WARN_EXCEPTION( "dbaccess", "ORelationTableView::RemoveConnection: Something other than SQLException occurred!");
+ }
+ return false;
+}
+
+void ORelationTableView::AddTabWin(const OUString& _rComposedName, const OUString& rWinName, bool /*bNewTable*/)
+{
+ OSL_ENSURE(!_rComposedName.isEmpty(),"There must be a table name supplied!");
+ OJoinTableView::OTableWindowMap::const_iterator aIter = GetTabWinMap().find(_rComposedName);
+
+ if(aIter != GetTabWinMap().end())
+ {
+ aIter->second->SetZOrder(nullptr, ZOrderFlags::First);
+ aIter->second->GrabFocus();
+ EnsureVisible(aIter->second);
+ // no new one
+ return;
+ }
+
+ // enter the new data structure into DocShell
+ TTableWindowData::value_type pNewTabWinData(createTableWindowData( _rComposedName, rWinName,rWinName ));
+ pNewTabWinData->ShowAll(false);
+
+ // link new window into the window list
+ VclPtr<OTableWindow> pNewTabWin = createWindow( pNewTabWinData );
+ if(pNewTabWin->Init())
+ {
+ m_pView->getController().getTableWindowData().push_back( pNewTabWinData);
+ // when we already have a table with this name insert the full qualified one instead
+ GetTabWinMap()[_rComposedName] = pNewTabWin;
+
+ SetDefaultTabWinPosSize( pNewTabWin );
+ pNewTabWin->Show();
+
+ modified();
+
+ if ( m_pAccessible )
+ m_pAccessible->notifyAccessibleEvent( AccessibleEventId::CHILD,
+ Any(),
+ Any(pNewTabWin->GetAccessible()));
+ }
+ else
+ {
+ pNewTabWin->clearListBox();
+ pNewTabWin.disposeAndClear();
+ }
+}
+
+void ORelationTableView::RemoveTabWin( OTableWindow* pTabWin )
+{
+ OSQLWarningBox aDlg(GetFrameWeld(), DBA_RES(STR_QUERY_REL_DELETE_WINDOW), MessBoxStyle::YesNo | MessBoxStyle::DefaultYes);
+ if (m_bInRemove || aDlg.run() == RET_YES)
+ {
+ m_pView->getController().ClearUndoManager();
+ OJoinTableView::RemoveTabWin( pTabWin );
+
+ m_pView->getController().InvalidateFeature(SID_RELATION_ADD_RELATION);
+ m_pView->getController().InvalidateFeature(ID_BROWSER_UNDO);
+ m_pView->getController().InvalidateFeature(ID_BROWSER_REDO);
+ }
+}
+
+void ORelationTableView::lookForUiActivities()
+{
+ if(m_pExistingConnection)
+ {
+ OUString sTitle(DBA_RES(STR_RELATIONDESIGN));
+ sTitle = sTitle.copy(3);
+ OSQLMessageBox aDlg(GetFrameWeld(), DBA_RES(STR_QUERY_REL_EDIT_RELATION), OUString(), MessBoxStyle::NONE);
+ aDlg.set_title(sTitle);
+ aDlg.add_button(DBA_RES(STR_QUERY_REL_EDIT), RET_OK);
+ aDlg.set_default_response(RET_OK);
+ aDlg.add_button(DBA_RES(STR_QUERY_REL_CREATE), RET_YES);
+ aDlg.add_button(GetStandardText(StandardButtonType::Cancel), RET_CANCEL);
+ sal_uInt16 nRet = aDlg.run();
+ if (nRet == RET_CANCEL)
+ {
+ m_pCurrentlyTabConnData.reset();
+ }
+ else if ( nRet == RET_OK ) // EDIT
+ {
+ ConnDoubleClicked(m_pExistingConnection);
+ m_pCurrentlyTabConnData.reset();
+ }
+ m_pExistingConnection = nullptr;
+ }
+ if(m_pCurrentlyTabConnData)
+ {
+ ORelationDialog aRelDlg(this, m_pCurrentlyTabConnData);
+ if (aRelDlg.run() == RET_OK)
+ {
+ // already updated by the dialog
+ addConnection( VclPtr<ORelationTableConnection>::Create( this, m_pCurrentlyTabConnData ) );
+ }
+ m_pCurrentlyTabConnData.reset();
+ }
+}
+
+VclPtr<OTableWindow> ORelationTableView::createWindow(const TTableWindowData::value_type& _pData)
+{
+ return VclPtr<ORelationTableWindow>::Create(this,_pData);
+}
+
+bool ORelationTableView::allowQueries() const
+{
+ return false;
+}
+
+void ORelationTableView::_elementInserted( const container::ContainerEvent& /*_rEvent*/ )
+{
+
+}
+
+void ORelationTableView::_elementRemoved( const container::ContainerEvent& _rEvent )
+{
+ m_bInRemove = true;
+ OUString sName;
+ if ( _rEvent.Accessor >>= sName )
+ {
+ OTableWindow* pTableWindow = GetTabWindow(sName);
+ if ( pTableWindow )
+ {
+ m_pView->getController().ClearUndoManager();
+ OJoinTableView::RemoveTabWin( pTableWindow );
+
+ m_pView->getController().InvalidateFeature(SID_RELATION_ADD_RELATION);
+ m_pView->getController().InvalidateFeature(ID_BROWSER_UNDO);
+ m_pView->getController().InvalidateFeature(ID_BROWSER_REDO);
+ }
+ }
+ m_bInRemove = false;
+}
+
+void ORelationTableView::_elementReplaced( const container::ContainerEvent& /*_rEvent*/ )
+{
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/tabledesign/FieldDescriptions.cxx b/dbaccess/source/ui/tabledesign/FieldDescriptions.cxx
new file mode 100644
index 000000000..d8dce84a0
--- /dev/null
+++ b/dbaccess/source/ui/tabledesign/FieldDescriptions.cxx
@@ -0,0 +1,639 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <FieldDescriptions.hxx>
+#include <tools/diagnose_ex.h>
+#include <strings.hxx>
+#include <com/sun/star/sdbc/ColumnValue.hpp>
+#include <comphelper/types.hxx>
+#include <comphelper/extract.hxx>
+#include <UITools.hxx>
+#include <com/sun/star/util/NumberFormat.hpp>
+
+#define DEFAULT_VARCHAR_PRECISION 100
+#define DEFAULT_OTHER_PRECISION 16
+#define DEFAULT_NUMERIC_PRECISION 5
+#define DEFAULT_NUMERIC_SCALE 0
+
+using namespace dbaui;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::util;
+
+OFieldDescription::OFieldDescription()
+ :m_nType(DataType::VARCHAR)
+ ,m_nPrecision(0)
+ ,m_nScale(0)
+ ,m_nIsNullable(ColumnValue::NULLABLE)
+ ,m_nFormatKey(0)
+ ,m_eHorJustify(SvxCellHorJustify::Standard)
+ ,m_bIsAutoIncrement(false)
+ ,m_bIsPrimaryKey(false)
+ ,m_bIsCurrency(false)
+ ,m_bHidden(false)
+{
+}
+
+OFieldDescription::OFieldDescription( const OFieldDescription& rDescr )
+ :m_aControlDefault(rDescr.m_aControlDefault)
+ ,m_aWidth(rDescr.m_aWidth)
+ ,m_aRelativePosition(rDescr.m_aRelativePosition)
+ ,m_pType(rDescr.m_pType)
+ ,m_xDest(rDescr.m_xDest)
+ ,m_xDestInfo(rDescr.m_xDestInfo)
+ ,m_sName(rDescr.m_sName)
+ ,m_sTypeName(rDescr.m_sTypeName)
+ ,m_sDescription(rDescr.m_sDescription)
+ ,m_sAutoIncrementValue(rDescr.m_sAutoIncrementValue)
+ ,m_nType(rDescr.m_nType)
+ ,m_nPrecision(rDescr.m_nPrecision)
+ ,m_nScale(rDescr.m_nScale)
+ ,m_nIsNullable(rDescr.m_nIsNullable)
+ ,m_nFormatKey(rDescr.m_nFormatKey)
+ ,m_eHorJustify(rDescr.m_eHorJustify)
+ ,m_bIsAutoIncrement(rDescr.m_bIsAutoIncrement)
+ ,m_bIsPrimaryKey(rDescr.m_bIsPrimaryKey)
+ ,m_bIsCurrency(rDescr.m_bIsCurrency)
+ ,m_bHidden(rDescr.m_bHidden)
+{
+}
+
+OFieldDescription::~OFieldDescription()
+{
+}
+
+OFieldDescription::OFieldDescription(const Reference< XPropertySet >& xAffectedCol,bool _bUseAsDest)
+ :m_nType(DataType::VARCHAR)
+ ,m_nPrecision(0)
+ ,m_nScale(0)
+ ,m_nIsNullable(ColumnValue::NULLABLE)
+ ,m_nFormatKey(0)
+ ,m_eHorJustify(SvxCellHorJustify::Standard)
+ ,m_bIsAutoIncrement(false)
+ ,m_bIsPrimaryKey(false)
+ ,m_bIsCurrency(false)
+ ,m_bHidden(false)
+{
+ OSL_ENSURE(xAffectedCol.is(),"PropertySet can not be null!");
+ if ( !xAffectedCol.is() )
+ return;
+
+ if ( _bUseAsDest )
+ {
+ m_xDest = xAffectedCol;
+ m_xDestInfo = xAffectedCol->getPropertySetInfo();
+ }
+ else
+ {
+ try
+ {
+ Reference<XPropertySetInfo> xPropSetInfo = xAffectedCol->getPropertySetInfo();
+ if(xPropSetInfo->hasPropertyByName(PROPERTY_NAME))
+ SetName(::comphelper::getString(xAffectedCol->getPropertyValue(PROPERTY_NAME)));
+ if(xPropSetInfo->hasPropertyByName(PROPERTY_DESCRIPTION))
+ SetDescription(::comphelper::getString(xAffectedCol->getPropertyValue(PROPERTY_DESCRIPTION)));
+ if(xPropSetInfo->hasPropertyByName(PROPERTY_HELPTEXT))
+ {
+ OUString sHelpText;
+ xAffectedCol->getPropertyValue(PROPERTY_HELPTEXT) >>= sHelpText;
+ SetHelpText(sHelpText);
+ }
+ if(xPropSetInfo->hasPropertyByName(PROPERTY_DEFAULTVALUE))
+ SetDefaultValue( xAffectedCol->getPropertyValue(PROPERTY_DEFAULTVALUE) );
+
+ if(xPropSetInfo->hasPropertyByName(PROPERTY_CONTROLDEFAULT))
+ SetControlDefault( xAffectedCol->getPropertyValue(PROPERTY_CONTROLDEFAULT) );
+
+ if(xPropSetInfo->hasPropertyByName(PROPERTY_AUTOINCREMENTCREATION))
+ SetAutoIncrementValue(::comphelper::getString(xAffectedCol->getPropertyValue(PROPERTY_AUTOINCREMENTCREATION)));
+ if(xPropSetInfo->hasPropertyByName(PROPERTY_TYPE))
+ SetTypeValue(::comphelper::getINT32(xAffectedCol->getPropertyValue(PROPERTY_TYPE)));
+ if (xPropSetInfo->hasPropertyByName(PROPERTY_TYPENAME))
+ SetTypeName(::comphelper::getString(xAffectedCol->getPropertyValue(PROPERTY_TYPENAME)));
+ if(xPropSetInfo->hasPropertyByName(PROPERTY_PRECISION))
+ SetPrecision(::comphelper::getINT32(xAffectedCol->getPropertyValue(PROPERTY_PRECISION)));
+ if(xPropSetInfo->hasPropertyByName(PROPERTY_SCALE))
+ SetScale(::comphelper::getINT32(xAffectedCol->getPropertyValue(PROPERTY_SCALE)));
+ if(xPropSetInfo->hasPropertyByName(PROPERTY_ISNULLABLE))
+ SetIsNullable(::comphelper::getINT32(xAffectedCol->getPropertyValue(PROPERTY_ISNULLABLE)));
+ if(xPropSetInfo->hasPropertyByName(PROPERTY_FORMATKEY))
+ {
+ const Any aValue = xAffectedCol->getPropertyValue(PROPERTY_FORMATKEY);
+ if ( aValue.hasValue() )
+ SetFormatKey(::comphelper::getINT32(aValue));
+ }
+ if(xPropSetInfo->hasPropertyByName(PROPERTY_RELATIVEPOSITION))
+ m_aRelativePosition = xAffectedCol->getPropertyValue(PROPERTY_RELATIVEPOSITION);
+ if(xPropSetInfo->hasPropertyByName(PROPERTY_WIDTH))
+ m_aWidth = xAffectedCol->getPropertyValue(PROPERTY_WIDTH);
+ if(xPropSetInfo->hasPropertyByName(PROPERTY_HIDDEN))
+ xAffectedCol->getPropertyValue(PROPERTY_HIDDEN) >>= m_bHidden;
+ if(xPropSetInfo->hasPropertyByName(PROPERTY_ALIGN))
+ {
+ const Any aValue = xAffectedCol->getPropertyValue(PROPERTY_ALIGN);
+ if ( aValue.hasValue() )
+ SetHorJustify( ::dbaui::mapTextJustify(::comphelper::getINT32(aValue)));
+ }
+ if(xPropSetInfo->hasPropertyByName(PROPERTY_ISAUTOINCREMENT))
+ SetAutoIncrement(::cppu::any2bool(xAffectedCol->getPropertyValue(PROPERTY_ISAUTOINCREMENT)));
+ }
+ catch(const Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+}
+
+void OFieldDescription::FillFromTypeInfo(const TOTypeInfoSP& _pType,bool _bForce,bool _bReset)
+{
+ TOTypeInfoSP pOldType = getTypeInfo();
+ if ( _pType == pOldType )
+ return;
+
+ // reset type depending information
+ if ( _bReset )
+ {
+ SetFormatKey(0);
+ SetControlDefault(Any());
+ }
+
+ bool bForce = _bForce || !pOldType || pOldType->nType != _pType->nType;
+ switch ( _pType->nType )
+ {
+ case DataType::CHAR:
+ case DataType::VARCHAR:
+ if ( bForce )
+ {
+ sal_Int32 nPrec = DEFAULT_VARCHAR_PRECISION;
+ if ( GetPrecision() )
+ nPrec = GetPrecision();
+ SetPrecision(std::min<sal_Int32>(nPrec,_pType->nPrecision));
+ }
+ break;
+ case DataType::TIMESTAMP:
+ if ( bForce && _pType->nMaximumScale)
+ {
+ SetScale(std::min<sal_Int32>(GetScale() ? GetScale() : DEFAULT_NUMERIC_SCALE,_pType->nMaximumScale));
+ }
+ break;
+ default:
+ if ( bForce )
+ {
+ sal_Int32 nPrec = DEFAULT_OTHER_PRECISION;
+ switch ( _pType->nType )
+ {
+ case DataType::BIT:
+ case DataType::BLOB:
+ case DataType::CLOB:
+ nPrec = _pType->nPrecision;
+ break;
+ default:
+ if ( GetPrecision() )
+ nPrec = GetPrecision();
+ break;
+ }
+
+ if ( _pType->nPrecision )
+ SetPrecision(std::min<sal_Int32>(nPrec ? nPrec : DEFAULT_NUMERIC_PRECISION,_pType->nPrecision));
+ if ( _pType->nMaximumScale )
+ SetScale(std::min<sal_Int32>(GetScale() ? GetScale() : DEFAULT_NUMERIC_SCALE,_pType->nMaximumScale));
+ }
+ }
+ if ( _pType->aCreateParams.isEmpty() )
+ {
+ SetPrecision(_pType->nPrecision);
+ SetScale(_pType->nMinimumScale);
+ }
+ if ( !_pType->bNullable && IsNullable() )
+ SetIsNullable(ColumnValue::NO_NULLS);
+ if ( !_pType->bAutoIncrement && IsAutoIncrement() )
+ SetAutoIncrement(false);
+ SetCurrency( _pType->bCurrency );
+ SetType(_pType);
+ SetTypeName(_pType->aTypeName);
+}
+
+void OFieldDescription::SetName(const OUString& _rName)
+{
+ try
+ {
+ if ( m_xDest.is() && m_xDestInfo->hasPropertyByName(PROPERTY_NAME) )
+ m_xDest->setPropertyValue(PROPERTY_NAME,Any(_rName));
+ else
+ m_sName = _rName;
+ }
+ catch(const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+}
+
+void OFieldDescription::SetHelpText(const OUString& _sHelpText)
+{
+ try
+ {
+ if ( m_xDest.is() && m_xDestInfo->hasPropertyByName(PROPERTY_HELPTEXT) )
+ m_xDest->setPropertyValue(PROPERTY_HELPTEXT,Any(_sHelpText));
+ else
+ m_sHelpText = _sHelpText;
+ }
+ catch(const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+}
+
+void OFieldDescription::SetDescription(const OUString& _rDescription)
+{
+ try
+ {
+ if ( m_xDest.is() && m_xDestInfo->hasPropertyByName(PROPERTY_DESCRIPTION) )
+ m_xDest->setPropertyValue(PROPERTY_DESCRIPTION,Any(_rDescription));
+ else
+ m_sDescription = _rDescription;
+ }
+ catch(const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+}
+
+void OFieldDescription::SetDefaultValue(const Any& _rDefaultValue)
+{
+ try
+ {
+ if ( m_xDest.is() && m_xDestInfo->hasPropertyByName(PROPERTY_DEFAULTVALUE) )
+ m_xDest->setPropertyValue(PROPERTY_DEFAULTVALUE, _rDefaultValue);
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+}
+
+void OFieldDescription::SetControlDefault(const Any& _rControlDefault)
+{
+ try
+ {
+ if ( m_xDest.is() && m_xDestInfo->hasPropertyByName(PROPERTY_CONTROLDEFAULT) )
+ m_xDest->setPropertyValue(PROPERTY_CONTROLDEFAULT, _rControlDefault);
+ else
+ m_aControlDefault = _rControlDefault;
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+}
+
+void OFieldDescription::SetAutoIncrementValue(const OUString& _sAutoIncValue)
+{
+ try
+ {
+ if ( m_xDest.is() && m_xDestInfo->hasPropertyByName(PROPERTY_AUTOINCREMENTCREATION) )
+ m_xDest->setPropertyValue(PROPERTY_AUTOINCREMENTCREATION,Any(_sAutoIncValue));
+ else
+ m_sAutoIncrementValue = _sAutoIncValue;
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+}
+
+void OFieldDescription::SetType(const TOTypeInfoSP& _pType)
+{
+ m_pType = _pType;
+ if ( !m_pType )
+ return;
+
+ try
+ {
+ if ( m_xDest.is() && m_xDestInfo->hasPropertyByName(PROPERTY_TYPE) )
+ m_xDest->setPropertyValue(PROPERTY_TYPE,Any(m_pType->nType));
+ else
+ m_nType = m_pType->nType;
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+}
+
+void OFieldDescription::SetTypeValue(sal_Int32 _nType)
+{
+ try
+ {
+ if ( m_xDest.is() && m_xDestInfo->hasPropertyByName(PROPERTY_TYPE) )
+ m_xDest->setPropertyValue(PROPERTY_TYPE,Any(_nType));
+ else
+ {
+ m_nType = _nType;
+ OSL_ENSURE(!m_pType,"Invalid call here!");
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+}
+
+void OFieldDescription::SetPrecision(sal_Int32 _rPrecision)
+{
+ try
+ {
+ if ( m_xDest.is() && m_xDestInfo->hasPropertyByName(PROPERTY_PRECISION) )
+ m_xDest->setPropertyValue(PROPERTY_PRECISION,Any(_rPrecision));
+ else
+ m_nPrecision = _rPrecision;
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+}
+
+void OFieldDescription::SetScale(sal_Int32 _rScale)
+{
+ try
+ {
+ if ( m_xDest.is() && m_xDestInfo->hasPropertyByName(PROPERTY_SCALE) )
+ m_xDest->setPropertyValue(PROPERTY_SCALE,Any(_rScale));
+ else
+ m_nScale = _rScale;
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+}
+
+void OFieldDescription::SetIsNullable(sal_Int32 _rIsNullable)
+{
+ try
+ {
+ if ( m_xDest.is() && m_xDestInfo->hasPropertyByName(PROPERTY_ISNULLABLE) )
+ m_xDest->setPropertyValue(PROPERTY_ISNULLABLE,Any(_rIsNullable));
+ else
+ m_nIsNullable = _rIsNullable;
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+}
+
+void OFieldDescription::SetFormatKey(sal_Int32 _rFormatKey)
+{
+ try
+ {
+ if ( m_xDest.is() && m_xDestInfo->hasPropertyByName(PROPERTY_FORMATKEY) )
+ m_xDest->setPropertyValue(PROPERTY_FORMATKEY,Any(_rFormatKey));
+ else
+ m_nFormatKey = _rFormatKey;
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+}
+
+void OFieldDescription::SetHorJustify(const SvxCellHorJustify& _rHorJustify)
+{
+ try
+ {
+ if ( m_xDest.is() && m_xDestInfo->hasPropertyByName(PROPERTY_ALIGN) )
+ m_xDest->setPropertyValue(PROPERTY_ALIGN,Any( dbaui::mapTextAlign(_rHorJustify)));
+ else
+ m_eHorJustify = _rHorJustify;
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+}
+
+void OFieldDescription::SetAutoIncrement(bool _bAuto)
+{
+ try
+ {
+ if ( m_xDest.is() && m_xDestInfo->hasPropertyByName(PROPERTY_ISAUTOINCREMENT) )
+ m_xDest->setPropertyValue(PROPERTY_ISAUTOINCREMENT,Any(_bAuto));
+ else
+ m_bIsAutoIncrement = _bAuto;
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+}
+
+void OFieldDescription::SetPrimaryKey(bool _bPKey)
+{
+ m_bIsPrimaryKey = _bPKey;
+ if ( _bPKey )
+ SetIsNullable(css::sdbc::ColumnValue::NO_NULLS);
+}
+
+void OFieldDescription::SetCurrency(bool _bIsCurrency)
+{
+ m_bIsCurrency = _bIsCurrency;
+}
+
+OUString OFieldDescription::GetName() const
+{
+ if ( m_xDest.is() && m_xDestInfo->hasPropertyByName(PROPERTY_NAME) )
+ return ::comphelper::getString(m_xDest->getPropertyValue(PROPERTY_NAME));
+ else
+ return m_sName;
+}
+
+OUString OFieldDescription::GetDescription() const
+{
+ if ( m_xDest.is() && m_xDestInfo->hasPropertyByName(PROPERTY_DESCRIPTION) )
+ return ::comphelper::getString(m_xDest->getPropertyValue(PROPERTY_DESCRIPTION));
+ else
+ return m_sDescription;
+}
+
+OUString OFieldDescription::GetHelpText() const
+{
+ if ( m_xDest.is() && m_xDestInfo->hasPropertyByName(PROPERTY_HELPTEXT) )
+ return ::comphelper::getString(m_xDest->getPropertyValue(PROPERTY_HELPTEXT));
+ else
+ return m_sHelpText;
+}
+
+css::uno::Any OFieldDescription::GetControlDefault() const
+{
+ if ( m_xDest.is() && m_xDestInfo->hasPropertyByName(PROPERTY_CONTROLDEFAULT) )
+ return m_xDest->getPropertyValue(PROPERTY_CONTROLDEFAULT);
+ else
+ return m_aControlDefault;
+}
+
+OUString OFieldDescription::GetAutoIncrementValue() const
+{
+ if ( m_xDest.is() && m_xDestInfo->hasPropertyByName(PROPERTY_AUTOINCREMENTCREATION) )
+ return ::comphelper::getString(m_xDest->getPropertyValue(PROPERTY_AUTOINCREMENTCREATION));
+ else
+ return m_sAutoIncrementValue;
+}
+
+sal_Int32 OFieldDescription::GetType() const
+{
+ if ( m_xDest.is() && m_xDestInfo->hasPropertyByName(PROPERTY_TYPE) )
+ return ::comphelper::getINT32(m_xDest->getPropertyValue(PROPERTY_TYPE));
+ else
+ return m_pType ? m_pType->nType : m_nType;
+}
+
+OUString OFieldDescription::GetTypeName() const
+{
+ if ( m_xDest.is() && m_xDestInfo->hasPropertyByName(PROPERTY_TYPENAME) )
+ return ::comphelper::getString(m_xDest->getPropertyValue(PROPERTY_TYPENAME));
+ else
+ return m_pType ? m_pType->aTypeName : m_sTypeName;
+}
+
+sal_Int32 OFieldDescription::GetPrecision() const
+{
+ sal_Int32 nPrec = m_nPrecision;
+ if ( m_xDest.is() && m_xDestInfo->hasPropertyByName(PROPERTY_PRECISION) )
+ nPrec = ::comphelper::getINT32(m_xDest->getPropertyValue(PROPERTY_PRECISION));
+
+ TOTypeInfoSP pTypeInfo = getTypeInfo();
+ if ( pTypeInfo )
+ {
+ switch ( pTypeInfo->nType )
+ {
+ case DataType::TINYINT:
+ case DataType::SMALLINT:
+ case DataType::INTEGER:
+ case DataType::BIGINT:
+ if ( !nPrec )
+ nPrec = pTypeInfo->nPrecision;
+ break;
+ }
+ }
+
+ return nPrec;
+}
+
+sal_Int32 OFieldDescription::GetScale() const
+{
+ if ( m_xDest.is() && m_xDestInfo->hasPropertyByName(PROPERTY_SCALE) )
+ return ::comphelper::getINT32(m_xDest->getPropertyValue(PROPERTY_SCALE));
+ else
+ return m_nScale;
+}
+
+sal_Int32 OFieldDescription::GetIsNullable() const
+{
+ if ( m_xDest.is() && m_xDestInfo->hasPropertyByName(PROPERTY_ISNULLABLE) )
+ return ::comphelper::getINT32(m_xDest->getPropertyValue(PROPERTY_ISNULLABLE));
+ else
+ return m_nIsNullable;
+}
+
+sal_Int32 OFieldDescription::GetFormatKey() const
+{
+ if ( m_xDest.is() && m_xDestInfo->hasPropertyByName(PROPERTY_FORMATKEY) )
+ return ::comphelper::getINT32(m_xDest->getPropertyValue(PROPERTY_FORMATKEY));
+ else
+ return m_nFormatKey;
+}
+
+SvxCellHorJustify OFieldDescription::GetHorJustify() const
+{
+ if ( m_xDest.is() && m_xDestInfo->hasPropertyByName(PROPERTY_ALIGN) )
+ return ::dbaui::mapTextJustify(::comphelper::getINT32(m_xDest->getPropertyValue(PROPERTY_ALIGN)));
+ else
+ return m_eHorJustify;
+}
+
+
+TOTypeInfoSP OFieldDescription::getSpecialTypeInfo() const
+{
+ TOTypeInfoSP pSpecialType = std::make_shared<OTypeInfo>();
+ *pSpecialType = *m_pType;
+ pSpecialType->nPrecision = GetPrecision();
+ pSpecialType->nMaximumScale = static_cast<sal_Int16>(GetScale());
+ pSpecialType->bAutoIncrement = IsAutoIncrement(); // http://dba.openoffice.org/issues/show_bug.cgi?id=115398 fixed by ludob
+ return pSpecialType;
+}
+
+bool OFieldDescription::IsAutoIncrement() const
+{
+ if ( m_xDest.is() && m_xDestInfo->hasPropertyByName(PROPERTY_ISAUTOINCREMENT) )
+ return ::cppu::any2bool(m_xDest->getPropertyValue(PROPERTY_ISAUTOINCREMENT));
+ else
+ return m_bIsAutoIncrement;
+}
+
+
+bool OFieldDescription::IsNullable() const
+{
+ if ( m_xDest.is() && m_xDestInfo->hasPropertyByName(PROPERTY_ISNULLABLE) )
+ return ::comphelper::getINT32(m_xDest->getPropertyValue(PROPERTY_ISNULLABLE)) == css::sdbc::ColumnValue::NULLABLE;
+ else
+ return m_nIsNullable == css::sdbc::ColumnValue::NULLABLE;
+}
+
+void OFieldDescription::SetTypeName(const OUString& _sTypeName)
+{
+ try
+ {
+ if ( m_xDest.is() && m_xDestInfo->hasPropertyByName(PROPERTY_TYPENAME) )
+ m_xDest->setPropertyValue(PROPERTY_TYPENAME,Any(_sTypeName));
+ else
+ m_sTypeName = _sTypeName;
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+}
+
+void OFieldDescription::copyColumnSettingsTo(const Reference< XPropertySet >& _rxColumn)
+{
+ if ( !_rxColumn.is() )
+ return;
+
+ Reference<XPropertySetInfo> xInfo = _rxColumn->getPropertySetInfo();
+
+ if ( GetFormatKey() != NumberFormat::ALL && xInfo->hasPropertyByName(PROPERTY_FORMATKEY) )
+ _rxColumn->setPropertyValue(PROPERTY_FORMATKEY,Any(GetFormatKey()));
+ if ( GetHorJustify() != SvxCellHorJustify::Standard && xInfo->hasPropertyByName(PROPERTY_ALIGN) )
+ _rxColumn->setPropertyValue(PROPERTY_ALIGN,Any(dbaui::mapTextAlign(GetHorJustify())));
+ if ( !GetHelpText().isEmpty() && xInfo->hasPropertyByName(PROPERTY_HELPTEXT) )
+ _rxColumn->setPropertyValue(PROPERTY_HELPTEXT,Any(GetHelpText()));
+ if ( GetControlDefault().hasValue() && xInfo->hasPropertyByName(PROPERTY_CONTROLDEFAULT) )
+ _rxColumn->setPropertyValue(PROPERTY_CONTROLDEFAULT,GetControlDefault());
+
+ if(xInfo->hasPropertyByName(PROPERTY_RELATIVEPOSITION))
+ _rxColumn->setPropertyValue(PROPERTY_RELATIVEPOSITION,m_aRelativePosition);
+ if(xInfo->hasPropertyByName(PROPERTY_WIDTH))
+ _rxColumn->setPropertyValue(PROPERTY_WIDTH,m_aWidth);
+ if(xInfo->hasPropertyByName(PROPERTY_HIDDEN))
+ _rxColumn->setPropertyValue(PROPERTY_HIDDEN,Any(m_bHidden));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/tabledesign/TEditControl.cxx b/dbaccess/source/ui/tabledesign/TEditControl.cxx
new file mode 100644
index 000000000..5f7809882
--- /dev/null
+++ b/dbaccess/source/ui/tabledesign/TEditControl.cxx
@@ -0,0 +1,1679 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "TEditControl.hxx"
+#include <com/sun/star/sdbc/ColumnValue.hpp>
+#include <com/sun/star/sdbc/SQLException.hpp>
+#include <com/sun/star/sdbc/XDatabaseMetaData.hpp>
+#include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
+#include <com/sun/star/util/XNumberFormatTypes.hpp>
+#include <core_resource.hxx>
+#include <strings.hrc>
+#include <strings.hxx>
+#include <helpids.h>
+#include <comphelper/types.hxx>
+#include <FieldDescControl.hxx>
+#include <FieldDescriptions.hxx>
+#include "TableUndo.hxx"
+#include <TableController.hxx>
+#include <connectivity/dbmetadata.hxx>
+#include <connectivity/dbtools.hxx>
+#include <SqlNameEdit.hxx>
+#include <TableRowExchange.hxx>
+#include <o3tl/safeint.hxx>
+#include <sot/storage.hxx>
+#include <svx/svxids.hrc>
+#include <UITools.hxx>
+#include "TableFieldControl.hxx"
+#include <dsntypes.hxx>
+#include <vcl/commandevent.hxx>
+#include <vcl/svapp.hxx>
+
+using namespace ::dbaui;
+using namespace ::comphelper;
+using namespace ::svt;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::io;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::util;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::sdbcx;
+using namespace ::com::sun::star::sdb;
+
+
+#define HANDLE_ID 0
+
+// default field widths
+#define FIELDNAME_WIDTH 100
+#define FIELDTYPE_WIDTH 150
+#define FIELDDESCR_WIDTH 300
+
+// Maximum length in description field
+#define MAX_DESCR_LEN 256
+
+OTableEditorCtrl::ClipboardInvalidator::ClipboardInvalidator(OTableEditorCtrl* _pOwner)
+: m_aInvalidateTimer("dbaccess ClipboardInvalidator")
+, m_pOwner(_pOwner)
+{
+
+ m_aInvalidateTimer.SetTimeout(500);
+ m_aInvalidateTimer.SetInvokeHandler(LINK(this, OTableEditorCtrl::ClipboardInvalidator, OnInvalidate));
+ m_aInvalidateTimer.Start();
+}
+
+OTableEditorCtrl::ClipboardInvalidator::~ClipboardInvalidator()
+{
+ m_aInvalidateTimer.Stop();
+}
+
+void OTableEditorCtrl::ClipboardInvalidator::Stop()
+{
+ m_aInvalidateTimer.Stop();
+}
+
+IMPL_LINK_NOARG(OTableEditorCtrl::ClipboardInvalidator, OnInvalidate, Timer *, void)
+{
+ m_pOwner->GetView()->getController().InvalidateFeature(SID_CUT);
+ m_pOwner->GetView()->getController().InvalidateFeature(SID_COPY);
+ m_pOwner->GetView()->getController().InvalidateFeature(SID_PASTE);
+}
+
+void OTableEditorCtrl::Init()
+{
+ OTableRowView::Init();
+
+ // Should it be opened ReadOnly?
+ bool bRead(GetView()->getController().isReadOnly());
+
+ SetReadOnly( bRead );
+
+ // Insert the columns
+ InsertDataColumn( FIELD_NAME, DBA_RES(STR_TAB_FIELD_COLUMN_NAME), FIELDNAME_WIDTH );
+
+ InsertDataColumn( FIELD_TYPE, DBA_RES(STR_TAB_FIELD_COLUMN_DATATYPE), FIELDTYPE_WIDTH );
+
+ ::dbaccess::ODsnTypeCollection aDsnTypes(GetView()->getController().getORB());
+ bool bShowColumnDescription = aDsnTypes.supportsColumnDescription(::comphelper::getString(GetView()->getController().getDataSource()->getPropertyValue(PROPERTY_URL)));
+ InsertDataColumn( HELP_TEXT, DBA_RES(STR_TAB_HELP_TEXT), bShowColumnDescription ? FIELDTYPE_WIDTH : FIELDDESCR_WIDTH );
+
+ if ( bShowColumnDescription )
+ {
+ InsertDataColumn( COLUMN_DESCRIPTION, DBA_RES(STR_COLUMN_DESCRIPTION), FIELDTYPE_WIDTH );
+ }
+
+ InitCellController();
+
+ // Insert the rows
+ RowInserted(0, m_pRowList->size());
+}
+
+OTableEditorCtrl::OTableEditorCtrl(vcl::Window* pWindow, OTableDesignView* pView)
+ :OTableRowView(pWindow)
+ ,m_pView(pView)
+ ,pNameCell(nullptr)
+ ,pTypeCell(nullptr)
+ ,pHelpTextCell(nullptr)
+ ,pDescrCell(nullptr)
+ ,pDescrWin(nullptr)
+ ,nCutEvent(nullptr)
+ ,nPasteEvent(nullptr)
+ ,nDeleteEvent(nullptr)
+ ,nInsNewRowsEvent(nullptr)
+ ,nInvalidateTypeEvent(nullptr)
+ ,m_eChildFocus(NONE)
+ ,nOldDataPos(-1)
+ ,bReadOnly(true)
+ ,m_aInvalidate(this)
+{
+ SetHelpId(HID_TABDESIGN_BACKGROUND);
+ GetDataWindow().SetHelpId(HID_CTL_TABLEEDIT);
+
+ m_pRowList = &GetView()->getController().getRows();
+ m_nDataPos = 0;
+}
+
+SfxUndoManager& OTableEditorCtrl::GetUndoManager() const
+{
+ return GetView()->getController().GetUndoManager();
+}
+
+
+void OTableEditorCtrl::SetReadOnly( bool bRead )
+{
+ // nothing to do?
+ if (bRead == IsReadOnly())
+ // This check is important, as the underlying Def may be unnecessarily locked or unlocked
+ // or worse, this action may not be reversed afterwards
+ return;
+
+ bReadOnly = bRead;
+
+ // Disable active cells
+ sal_Int32 nRow(GetCurRow());
+ sal_uInt16 nCol(GetCurColumnId());
+ DeactivateCell();
+
+ // Select the correct Browsers cursor
+ BrowserMode nMode(BrowserMode::COLUMNSELECTION | BrowserMode::MULTISELECTION | BrowserMode::KEEPHIGHLIGHT |
+ BrowserMode::HLINES | BrowserMode::VLINES|BrowserMode::AUTOSIZE_LASTCOL);
+ if( !bReadOnly )
+ nMode |= BrowserMode::HIDECURSOR;
+ SetMode(nMode);
+
+ if( !bReadOnly )
+ ActivateCell( nRow, nCol );
+}
+
+void OTableEditorCtrl::InitCellController()
+{
+ // Cell Field name
+ sal_Int32 nMaxTextLen = 0;
+ OUString sExtraNameChars;
+ Reference<XConnection> xCon;
+ try
+ {
+ xCon = GetView()->getController().getConnection();
+ Reference< XDatabaseMetaData> xMetaData = xCon.is() ? xCon->getMetaData() : Reference< XDatabaseMetaData>();
+
+ // length 0 is treated by Entry::set_max_length as unlimited
+ nMaxTextLen = xMetaData.is() ? xMetaData->getMaxColumnNameLength() : 0;
+
+ sExtraNameChars = xMetaData.is() ? xMetaData->getExtraNameCharacters() : OUString();
+
+ }
+ catch(SQLException&)
+ {
+ OSL_FAIL("getMaxColumnNameLength");
+ }
+
+ pNameCell = VclPtr<OSQLNameEditControl>::Create(&GetDataWindow(), sExtraNameChars);
+ pNameCell->get_widget().set_max_length(nMaxTextLen);
+ pNameCell->setCheck( isSQL92CheckEnabled(xCon) );
+
+ // Cell type
+ pTypeCell = VclPtr<ListBoxControl>::Create( &GetDataWindow() );
+
+ // Cell description
+ pDescrCell = VclPtr<EditControl>::Create(&GetDataWindow());
+ pDescrCell->get_widget().set_max_length(MAX_DESCR_LEN);
+
+ pHelpTextCell = VclPtr<EditControl>::Create(&GetDataWindow());
+ pHelpTextCell->get_widget().set_max_length(MAX_DESCR_LEN);
+
+ pNameCell->SetHelpId(HID_TABDESIGN_NAMECELL);
+ pTypeCell->SetHelpId(HID_TABDESIGN_TYPECELL);
+ pDescrCell->SetHelpId(HID_TABDESIGN_COMMENTCELL);
+ pHelpTextCell->SetHelpId(HID_TABDESIGN_HELPTEXT);
+
+ Size aHeight;
+ const Control* pControls[] = { pTypeCell,pDescrCell,pNameCell,pHelpTextCell};
+ for(const Control* pControl : pControls)
+ {
+ const Size aTemp(pControl->GetOptimalSize());
+ if ( aTemp.Height() > aHeight.Height() )
+ aHeight.setHeight( aTemp.Height() );
+ }
+ SetDataRowHeight(aHeight.Height());
+
+ ClearModified();
+}
+
+void OTableEditorCtrl::ClearModified()
+{
+ pNameCell->get_widget().save_value();
+ pDescrCell->get_widget().save_value();
+ pHelpTextCell->get_widget().save_value();
+ pTypeCell->get_widget().save_value();
+}
+
+OTableEditorCtrl::~OTableEditorCtrl()
+{
+ disposeOnce();
+}
+
+void OTableEditorCtrl::dispose()
+{
+ // Reset the Undo-Manager
+ GetUndoManager().Clear();
+
+ m_aInvalidate.Stop();
+
+ // Take possible Events from the queue
+ if( nCutEvent )
+ Application::RemoveUserEvent( nCutEvent );
+ if( nPasteEvent )
+ Application::RemoveUserEvent( nPasteEvent );
+ if( nDeleteEvent )
+ Application::RemoveUserEvent( nDeleteEvent );
+ if( nInsNewRowsEvent )
+ Application::RemoveUserEvent( nInsNewRowsEvent );
+ if( nInvalidateTypeEvent )
+ Application::RemoveUserEvent( nInvalidateTypeEvent );
+
+ // Delete the control types
+ pNameCell.disposeAndClear();
+ pTypeCell.disposeAndClear();
+ pDescrCell.disposeAndClear();
+ pHelpTextCell.disposeAndClear();
+ pDescrWin = nullptr;
+ m_pView.clear();
+ OTableRowView::dispose();
+}
+
+bool OTableEditorCtrl::SetDataPtr( sal_Int32 nRow )
+{
+ if(nRow == -1)
+ return false;
+
+ OSL_ENSURE(nRow < static_cast<tools::Long>(m_pRowList->size()),"Row is greater than size!");
+ if(nRow >= static_cast<tools::Long>(m_pRowList->size()))
+ return false;
+ pActRow = (*m_pRowList)[nRow];
+ return pActRow != nullptr;
+}
+
+bool OTableEditorCtrl::SeekRow(sal_Int32 _nRow)
+{
+ // Call the Base class to remember which row must be repainted
+ EditBrowseBox::SeekRow(_nRow);
+
+ m_nCurrentPos = _nRow;
+ return SetDataPtr(_nRow);
+}
+
+void OTableEditorCtrl::PaintCell(OutputDevice& rDev, const tools::Rectangle& rRect,
+ sal_uInt16 nColumnId ) const
+{
+ const OUString aText( GetCellText( m_nCurrentPos, nColumnId ));
+
+ rDev.Push( vcl::PushFlags::CLIPREGION );
+ rDev.SetClipRegion(vcl::Region(rRect));
+ rDev.DrawText( rRect, aText, DrawTextFlags::Left | DrawTextFlags::VCenter );
+ rDev.Pop();
+}
+
+CellController* OTableEditorCtrl::GetController(sal_Int32 nRow, sal_uInt16 nColumnId)
+{
+ // If EditorCtrl is ReadOnly, editing is forbidden
+ Reference<XPropertySet> xTable = GetView()->getController().getTable();
+ if (IsReadOnly() || ( xTable.is() &&
+ xTable->getPropertySetInfo()->hasPropertyByName(PROPERTY_TYPE) &&
+ ::comphelper::getString(xTable->getPropertyValue(PROPERTY_TYPE)) == "VIEW"))
+ return nullptr;
+
+ // If the row is ReadOnly, editing is forbidden
+ SetDataPtr( nRow );
+ if( pActRow->IsReadOnly() )
+ return nullptr;
+
+ OFieldDescription* pActFieldDescr = pActRow->GetActFieldDescr();
+ switch (nColumnId)
+ {
+ case FIELD_NAME:
+ return new EditCellController( pNameCell );
+ case FIELD_TYPE:
+ if (pActFieldDescr && !pActFieldDescr->GetName().isEmpty())
+ return new ListBoxCellController( pTypeCell );
+ else return nullptr;
+ case HELP_TEXT:
+ if (pActFieldDescr && !pActFieldDescr->GetName().isEmpty())
+ return new EditCellController( pHelpTextCell );
+ else
+ return nullptr;
+ case COLUMN_DESCRIPTION:
+ if (pActFieldDescr && !pActFieldDescr->GetName().isEmpty())
+ return new EditCellController( pDescrCell );
+ else
+ return nullptr;
+ default:
+ return nullptr;
+ }
+}
+
+void OTableEditorCtrl::InitController(CellControllerRef&, sal_Int32 nRow, sal_uInt16 nColumnId)
+{
+ SeekRow( nRow == -1 ? GetCurRow() : nRow);
+ OFieldDescription* pActFieldDescr = pActRow->GetActFieldDescr();
+ OUString aInitString;
+
+ switch (nColumnId)
+ {
+ case FIELD_NAME:
+ {
+ if( pActFieldDescr )
+ aInitString = pActFieldDescr->GetName();
+
+ weld::Entry& rEntry = pNameCell->get_widget();
+ rEntry.set_text(aInitString);
+ rEntry.save_value();
+ break;
+ }
+ case FIELD_TYPE:
+ {
+ if ( pActFieldDescr && pActFieldDescr->getTypeInfo() )
+ aInitString = pActFieldDescr->getTypeInfo()->aUIName;
+
+ // Set the ComboBox contents
+ weld::ComboBox& rTypeList = pTypeCell->get_widget();
+ rTypeList.clear();
+ if( !pActFieldDescr )
+ break;
+
+ const OTypeInfoMap& rTypeInfo = GetView()->getController().getTypeInfo();
+ for (auto const& elem : rTypeInfo)
+ rTypeList.append_text(elem.second->aUIName);
+ rTypeList.set_active_text(aInitString);
+ }
+
+ break;
+ case HELP_TEXT:
+ {
+ if( pActFieldDescr )
+ aInitString = pActFieldDescr->GetHelpText();
+ weld::Entry& rEntry = pHelpTextCell->get_widget();
+ rEntry.set_text(aInitString);
+ rEntry.save_value();
+ break;
+ }
+ case COLUMN_DESCRIPTION:
+ {
+ if( pActFieldDescr )
+ aInitString = pActFieldDescr->GetDescription();
+ weld::Entry& rEntry = pDescrCell->get_widget();
+ rEntry.set_text(aInitString);
+ rEntry.save_value();
+ break;
+ }
+ }
+}
+
+EditBrowseBox::RowStatus OTableEditorCtrl::GetRowStatus(sal_Int32 nRow) const
+{
+ const_cast<OTableEditorCtrl*>(this)->SetDataPtr( nRow );
+ if( !pActRow )
+ return EditBrowseBox::CLEAN;
+ if (nRow >= 0 && nRow == m_nDataPos)
+ {
+ if( pActRow->IsPrimaryKey() )
+ return EditBrowseBox::CURRENT_PRIMARYKEY;
+ return EditBrowseBox::CURRENT;
+ }
+ else
+ {
+ if( pActRow->IsPrimaryKey() )
+ return EditBrowseBox::PRIMARYKEY;
+ return EditBrowseBox::CLEAN;
+ }
+}
+
+void OTableEditorCtrl::SaveCurRow()
+{
+ if (GetFieldDescr(GetCurRow()) == nullptr)
+ // there is no data in the current row
+ return;
+ if (!SaveModified())
+ return;
+
+ SetDataPtr(GetCurRow());
+ pDescrWin->SaveData( pActRow->GetActFieldDescr() );
+}
+
+void OTableEditorCtrl::DisplayData(sal_Int32 nRow)
+{
+ // go to the correct cell
+ SetDataPtr(nRow);
+
+ // Disable Edit-Mode temporarily
+ bool bWasEditing = IsEditing();
+ if (bWasEditing)
+ DeactivateCell();
+
+ CellControllerRef aTemp;
+ InitController(aTemp, nRow, FIELD_NAME);
+ InitController(aTemp, nRow, FIELD_TYPE);
+ InitController(aTemp, nRow, COLUMN_DESCRIPTION);
+ InitController(aTemp, nRow, HELP_TEXT);
+
+ GoToRow(nRow);
+ // Update the Description-Window
+ GetView()->GetDescWin()->DisplayData(GetFieldDescr(nRow));
+ // redraw the row
+ RowModified(nRow);
+
+ // and re-enable edit mode
+ ActivateCell(nRow, GetCurColumnId());
+}
+
+void OTableEditorCtrl::CursorMoved()
+{
+ // New line?
+ m_nDataPos = GetCurRow();
+ if( m_nDataPos != nOldDataPos && m_nDataPos != -1)
+ {
+ CellControllerRef aTemp;
+ InitController(aTemp,m_nDataPos,FIELD_NAME);
+ InitController(aTemp,m_nDataPos,FIELD_TYPE);
+ InitController(aTemp,m_nDataPos,COLUMN_DESCRIPTION);
+ InitController(aTemp,m_nDataPos,HELP_TEXT);
+ }
+
+ OTableRowView::CursorMoved();
+}
+
+sal_Int32 OTableEditorCtrl::HasFieldName( std::u16string_view rFieldName )
+{
+
+ Reference<XConnection> xCon = GetView()->getController().getConnection();
+ Reference< XDatabaseMetaData> xMetaData = xCon.is() ? xCon->getMetaData() : Reference< XDatabaseMetaData>();
+
+ ::comphelper::UStringMixEqual bCase(!xMetaData.is() || xMetaData->supportsMixedCaseQuotedIdentifiers());
+
+ sal_Int32 nCount(0);
+ for (auto const& row : *m_pRowList)
+ {
+ OFieldDescription* pFieldDescr = row->GetActFieldDescr();
+ if( pFieldDescr && bCase(rFieldName,pFieldDescr->GetName()))
+ nCount++;
+ }
+ return nCount;
+}
+
+void OTableEditorCtrl::SaveData(sal_Int32 nRow, sal_uInt16 nColId)
+{
+ // Store the cell content
+ SetDataPtr( nRow == -1 ? GetCurRow() : nRow);
+ OFieldDescription* pActFieldDescr = pActRow->GetActFieldDescr();
+
+ switch( nColId)
+ {
+ // Store NameCell
+ case FIELD_NAME:
+ {
+ // If there is no name, do nothing
+ weld::Entry& rEntry = pNameCell->get_widget();
+ const OUString aName(rEntry.get_text());
+
+ if( aName.isEmpty() )
+ {
+ // If FieldDescr exists, the field is deleted and the old content restored
+ if (pActFieldDescr)
+ {
+ GetUndoManager().AddUndoAction(std::make_unique<OTableEditorTypeSelUndoAct>(this, nRow, FIELD_TYPE, pActFieldDescr->getTypeInfo()));
+ SwitchType(TOTypeInfoSP());
+ pActFieldDescr = pActRow->GetActFieldDescr();
+ }
+ else
+ return;
+ }
+ if(pActFieldDescr)
+ pActFieldDescr->SetName( aName );
+ rEntry.save_value();
+
+ break;
+ }
+
+ // Store the field type
+ case FIELD_TYPE:
+ break;
+
+ // Store DescrCell
+ case HELP_TEXT:
+ {
+ // if the current field description is NULL, set Default
+ weld::Entry& rEntry = pHelpTextCell->get_widget();
+ if( !pActFieldDescr )
+ {
+ rEntry.set_text(OUString());
+ rEntry.save_value();
+ }
+ else
+ pActFieldDescr->SetHelpText(rEntry.get_text());
+ break;
+ }
+ case COLUMN_DESCRIPTION:
+ {
+ // Set the default if the field description is null
+ weld::Entry& rEntry = pDescrCell->get_widget();
+ if( !pActFieldDescr )
+ {
+ rEntry.set_text(OUString());
+ rEntry.save_value();
+ }
+ else
+ pActFieldDescr->SetDescription(rEntry.get_text());
+ break;
+ }
+ case FIELD_PROPERTY_DEFAULT:
+ case FIELD_PROPERTY_REQUIRED:
+ case FIELD_PROPERTY_TEXTLEN:
+ case FIELD_PROPERTY_NUMTYPE:
+ case FIELD_PROPERTY_AUTOINC:
+ case FIELD_PROPERTY_LENGTH:
+ case FIELD_PROPERTY_SCALE:
+ case FIELD_PROPERTY_BOOL_DEFAULT:
+ pDescrWin->SaveData(pActFieldDescr);
+
+ if ( FIELD_PROPERTY_AUTOINC == nColId && pActFieldDescr->IsAutoIncrement() )
+ {
+ OTableController& rController = GetView()->getController();
+ if ( rController.isAutoIncrementPrimaryKey() )
+ {
+ pActFieldDescr->SetPrimaryKey( true );
+ InvalidateHandleColumn();
+ Invalidate();
+ }
+ }
+ break;
+ }
+}
+
+bool OTableEditorCtrl::SaveModified()
+{
+ sal_uInt16 nColId = GetCurColumnId();
+
+ switch( nColId )
+ {
+ // Field type
+ case FIELD_TYPE:
+ {
+ // Reset the type
+ resetType();
+ } break;
+ }
+
+ return true;
+}
+
+bool OTableEditorCtrl::CursorMoving(sal_Int32 nNewRow, sal_uInt16 nNewCol)
+{
+
+ if (!EditBrowseBox::CursorMoving(nNewRow, nNewCol))
+ return false;
+
+ // Called after SaveModified(), current row is still the old one
+ m_nDataPos = nNewRow;
+ nOldDataPos = GetCurRow();
+
+ // Reset the markers
+ InvalidateStatusCell( nOldDataPos );
+ InvalidateStatusCell( m_nDataPos );
+
+ // Store the data from the Property window
+ if( SetDataPtr(nOldDataPos) && pDescrWin)
+ pDescrWin->SaveData( pActRow->GetActFieldDescr() );
+
+ // Show new data in the Property window
+ if( SetDataPtr(m_nDataPos) && pDescrWin)
+ pDescrWin->DisplayData( pActRow->GetActFieldDescr() );
+
+ return true;
+}
+
+IMPL_LINK_NOARG( OTableEditorCtrl, InvalidateFieldType, void*, void )
+{
+ nInvalidateTypeEvent = nullptr;
+ Invalidate( GetFieldRectPixel(nOldDataPos, FIELD_TYPE) );
+}
+
+void OTableEditorCtrl::CellModified( sal_Int32 nRow, sal_uInt16 nColId )
+{
+
+ // If the description is null, use the default
+ if(nRow == -1)
+ nRow = GetCurRow();
+ SetDataPtr( nRow );
+ OFieldDescription* pActFieldDescr = pActRow->GetActFieldDescr();
+
+ OUString sActionDescription;
+ switch ( nColId )
+ {
+ case FIELD_NAME: sActionDescription = DBA_RES( STR_CHANGE_COLUMN_NAME ); break;
+ case FIELD_TYPE: sActionDescription = DBA_RES( STR_CHANGE_COLUMN_TYPE ); break;
+ case HELP_TEXT:
+ case COLUMN_DESCRIPTION: sActionDescription = DBA_RES( STR_CHANGE_COLUMN_DESCRIPTION ); break;
+ default: sActionDescription = DBA_RES( STR_CHANGE_COLUMN_ATTRIBUTE ); break;
+ }
+
+ GetUndoManager().EnterListAction( sActionDescription, OUString(), 0, ViewShellId(-1) );
+ if (!pActFieldDescr)
+ {
+ const OTypeInfoMap& rTypeInfoMap = GetView()->getController().getTypeInfo();
+ if ( !rTypeInfoMap.empty() )
+ {
+ OTypeInfoMap::const_iterator aTypeIter = rTypeInfoMap.find(DataType::VARCHAR);
+ if ( aTypeIter == rTypeInfoMap.end() )
+ aTypeIter = rTypeInfoMap.begin();
+ pActRow->SetFieldType( aTypeIter->second );
+ }
+ else
+ pActRow->SetFieldType( GetView()->getController().getTypeInfoFallBack() );
+
+ nInvalidateTypeEvent = Application::PostUserEvent( LINK(this, OTableEditorCtrl, InvalidateFieldType), nullptr, true );
+ pActFieldDescr = pActRow->GetActFieldDescr();
+ pDescrWin->DisplayData( pActFieldDescr );
+ GetUndoManager().AddUndoAction( std::make_unique<OTableEditorTypeSelUndoAct>(this, nRow, nColId+1, TOTypeInfoSP()) );
+ }
+
+ if( nColId != FIELD_TYPE )
+ GetUndoManager().AddUndoAction( std::make_unique<OTableDesignCellUndoAct>(this, nRow, nColId) );
+ else
+ {
+ GetUndoManager().AddUndoAction(std::make_unique<OTableEditorTypeSelUndoAct>(this, GetCurRow(), nColId, GetFieldDescr(GetCurRow())->getTypeInfo()));
+ resetType();
+ }
+
+ SaveData(nRow,nColId);
+ // SaveData could create an undo action as well
+ GetUndoManager().LeaveListAction();
+ RowModified(nRow);
+
+ // Set the Modify flag
+ GetView()->getController().setModified( true );
+ InvalidateFeatures();
+}
+
+void OTableEditorCtrl::resetType()
+{
+ sal_Int32 nPos = pTypeCell->get_widget().get_active();
+ if(nPos != -1)
+ SwitchType( GetView()->getController().getTypeInfo(nPos) );
+ else
+ SwitchType(TOTypeInfoSP());
+}
+
+void OTableEditorCtrl::CellModified()
+{
+ CellModified( GetCurRow(), GetCurColumnId() );
+}
+
+void OTableEditorCtrl::InvalidateFeatures()
+{
+ GetView()->getController().InvalidateFeature(SID_UNDO);
+ GetView()->getController().InvalidateFeature(SID_REDO);
+ GetView()->getController().InvalidateFeature(SID_SAVEDOC);
+}
+
+void OTableEditorCtrl::CopyRows()
+{
+ // set to the right row and save it
+ if( SetDataPtr(m_nDataPos) )
+ pDescrWin->SaveData( pActRow->GetActFieldDescr() );
+
+ // Copy selected rows to the ClipboardList
+ std::shared_ptr<OTableRow> pClipboardRow;
+ std::shared_ptr<OTableRow> pRow;
+ std::vector< std::shared_ptr<OTableRow> > vClipboardList;
+ vClipboardList.reserve(GetSelectRowCount());
+
+ for( tools::Long nIndex=FirstSelectedRow(); nIndex != SFX_ENDOFSELECTION; nIndex=NextSelectedRow() )
+ {
+ pRow = (*m_pRowList)[nIndex];
+ OSL_ENSURE(pRow,"OTableEditorCtrl::CopyRows: Row is NULL!");
+ if ( pRow && pRow->GetActFieldDescr() )
+ {
+ pClipboardRow = std::make_shared<OTableRow>( *pRow );
+ vClipboardList.push_back( pClipboardRow);
+ }
+ }
+ if(!vClipboardList.empty())
+ {
+ rtl::Reference<OTableRowExchange> pData = new OTableRowExchange(std::move(vClipboardList));
+ pData->CopyToClipboard(GetParent());
+ }
+}
+
+OUString OTableEditorCtrl::GenerateName( const OUString& rName )
+{
+ // Create a base name for appending numbers to
+ OUString aBaseName;
+ Reference<XConnection> xCon = GetView()->getController().getConnection();
+ Reference< XDatabaseMetaData> xMetaData = xCon.is() ? xCon->getMetaData() : Reference< XDatabaseMetaData>();
+
+ sal_Int32 nMaxTextLen(xMetaData.is() ? xMetaData->getMaxColumnNameLength() : 0);
+
+ if( (rName.getLength()+2) >nMaxTextLen )
+ aBaseName = rName.copy( 0, nMaxTextLen-2 );
+ else
+ aBaseName = rName;
+
+ // append a sequential number to the base name (up to 99)
+ OUString aFieldName( rName);
+ sal_Int32 i=1;
+ while( HasFieldName(aFieldName) )
+ {
+ aFieldName = aBaseName + OUString::number(i);
+ i++;
+ }
+
+ return aFieldName;
+}
+
+void OTableEditorCtrl::InsertRows( sal_Int32 nRow )
+{
+
+ std::vector< std::shared_ptr<OTableRow> > vInsertedUndoRedoRows; // need for undo/redo handling
+ // get rows from clipboard
+ TransferableDataHelper aTransferData(TransferableDataHelper::CreateFromSystemClipboard(GetParent()));
+ if(aTransferData.HasFormat(SotClipboardFormatId::SBA_TABED))
+ {
+ ::tools::SvRef<SotTempStream> aStreamRef;
+ bool bOk = aTransferData.GetSotStorageStream(SotClipboardFormatId::SBA_TABED,aStreamRef);
+ if (bOk && aStreamRef.is())
+ {
+ aStreamRef->Seek(STREAM_SEEK_TO_BEGIN);
+ aStreamRef->ResetError();
+ sal_Int32 nInsertRow = nRow;
+ std::shared_ptr<OTableRow> pRow;
+ sal_Int32 nSize = 0;
+ (*aStreamRef).ReadInt32( nSize );
+ vInsertedUndoRedoRows.reserve(nSize);
+ for(sal_Int32 i=0;i < nSize;++i)
+ {
+ pRow = std::make_shared<OTableRow>();
+ ReadOTableRow( *aStreamRef, *pRow );
+ pRow->SetReadOnly( false );
+ sal_Int32 nType = pRow->GetActFieldDescr()->GetType();
+ if ( pRow->GetActFieldDescr() )
+ pRow->GetActFieldDescr()->SetType(GetView()->getController().getTypeInfoByType(nType));
+ // Adjust the field names
+ pRow->GetActFieldDescr()->SetName( GenerateName( pRow->GetActFieldDescr()->GetName() ) );
+ pRow->SetPos(nInsertRow);
+ m_pRowList->insert( m_pRowList->begin()+nInsertRow,pRow );
+ vInsertedUndoRedoRows.push_back(std::make_shared<OTableRow>(*pRow));
+ nInsertRow++;
+ }
+ }
+ }
+ // RowInserted calls CursorMoved.
+ // The UI data should not be stored here.
+ RowInserted( nRow,vInsertedUndoRedoRows.size() );
+
+ // Create the Undo-Action
+ GetUndoManager().AddUndoAction( std::make_unique<OTableEditorInsUndoAct>(this, nRow, std::move(vInsertedUndoRedoRows)) );
+ GetView()->getController().setModified( true );
+ InvalidateFeatures();
+}
+
+void OTableEditorCtrl::DeleteRows()
+{
+ OSL_ENSURE(GetView()->getController().isDropAllowed(),"Call of DeleteRows not valid here. Please check isDropAllowed!");
+ // Create the Undo-Action
+ GetUndoManager().AddUndoAction( std::make_unique<OTableEditorDelUndoAct>(this) );
+
+ // Delete all marked rows
+ tools::Long nIndex = FirstSelectedRow();
+ nOldDataPos = nIndex;
+
+ while( nIndex != SFX_ENDOFSELECTION )
+ {
+ // Remove rows
+ m_pRowList->erase( m_pRowList->begin()+nIndex );
+ RowRemoved( nIndex );
+
+ // Insert the empty row at the end
+ m_pRowList->push_back( std::make_shared<OTableRow>());
+ RowInserted( GetRowCount()-1 );
+
+ nIndex = FirstSelectedRow();
+ }
+
+ // Force the current record to be displayed
+ m_nDataPos = GetCurRow();
+ InvalidateStatusCell( nOldDataPos );
+ InvalidateStatusCell( m_nDataPos );
+ SetDataPtr( m_nDataPos );
+ ActivateCell();
+ pDescrWin->DisplayData( pActRow->GetActFieldDescr() );
+ GetView()->getController().setModified( true );
+ InvalidateFeatures();
+}
+
+void OTableEditorCtrl::InsertNewRows( sal_Int32 nRow )
+{
+ OSL_ENSURE(GetView()->getController().isAddAllowed(),"Call of InsertNewRows not valid here. Please check isAppendAllowed!");
+ // Create Undo-Action
+ sal_Int32 nInsertRows = GetSelectRowCount();
+ if( !nInsertRows )
+ nInsertRows = 1;
+ GetUndoManager().AddUndoAction( std::make_unique<OTableEditorInsNewUndoAct>(this, nRow, nInsertRows) );
+ // Insert the number of selected rows
+ for( tools::Long i=nRow; i<(nRow+nInsertRows); i++ )
+ m_pRowList->insert( m_pRowList->begin()+i ,std::make_shared<OTableRow>());
+ RowInserted( nRow, nInsertRows );
+
+ GetView()->getController().setModified( true );
+ InvalidateFeatures();
+}
+
+void OTableEditorCtrl::SetControlText( sal_Int32 nRow, sal_uInt16 nColId, const OUString& rText )
+{
+ // Set the Browser Controls
+ if( nColId < FIELD_FIRST_VIRTUAL_COLUMN )
+ {
+ GoToRow( nRow );
+ GoToColumnId( nColId );
+ CellControllerRef xController = Controller();
+ if(xController.is())
+ xController->GetWindow().SetText( rText );
+ else
+ RowModified(nRow,nColId);
+ }
+
+ // Set the Tabpage controls
+ else
+ {
+ pDescrWin->SetControlText( nColId, rText );
+ }
+}
+
+void OTableEditorCtrl::SetCellData( sal_Int32 nRow, sal_uInt16 nColId, const TOTypeInfoSP& _pTypeInfo )
+{
+ // Relocate the current pointer
+ if( nRow == -1 )
+ nRow = GetCurRow();
+ OFieldDescription* pFieldDescr = GetFieldDescr( nRow );
+ if( !pFieldDescr && nColId != FIELD_TYPE)
+ return;
+
+ // Set individual fields
+ switch( nColId )
+ {
+ case FIELD_TYPE:
+ SwitchType( _pTypeInfo );
+ break;
+ default:
+ OSL_FAIL("OTableEditorCtrl::SetCellData: invalid column!");
+ }
+ SetControlText(nRow,nColId,_pTypeInfo ? _pTypeInfo->aUIName : OUString());
+}
+
+void OTableEditorCtrl::SetCellData( sal_Int32 nRow, sal_uInt16 nColId, const css::uno::Any& _rNewData )
+{
+ // Relocate the current pointer
+ if( nRow == -1 )
+ nRow = GetCurRow();
+ OFieldDescription* pFieldDescr = GetFieldDescr( nRow );
+ if( !pFieldDescr && nColId != FIELD_TYPE)
+ return;
+
+ OUString sValue;
+ // Set individual fields
+ switch( nColId )
+ {
+ case FIELD_NAME:
+ sValue = ::comphelper::getString(_rNewData);
+ pFieldDescr->SetName( sValue );
+ break;
+
+ case FIELD_TYPE:
+ OSL_FAIL("OTableEditorCtrl::SetCellData: invalid column!");
+ break;
+
+ case COLUMN_DESCRIPTION:
+ sValue = ::comphelper::getString(_rNewData);
+ pFieldDescr->SetDescription( sValue );
+ break;
+
+ case FIELD_PROPERTY_DEFAULT:
+ pFieldDescr->SetControlDefault( _rNewData );
+ sValue = GetView()->GetDescWin()->getGenPage()->getControlDefault(pFieldDescr);
+ break;
+
+ case FIELD_PROPERTY_REQUIRED:
+ {
+ sValue = ::comphelper::getString(_rNewData);
+ pFieldDescr->SetIsNullable( sValue.toInt32() );
+ }
+ break;
+
+ case FIELD_PROPERTY_TEXTLEN:
+ case FIELD_PROPERTY_LENGTH:
+ {
+ sValue = ::comphelper::getString(_rNewData);
+ pFieldDescr->SetPrecision( sValue.toInt32() );
+ }
+ break;
+
+ case FIELD_PROPERTY_NUMTYPE:
+ OSL_FAIL("OTableEditorCtrl::SetCellData: invalid column!");
+ break;
+
+ case FIELD_PROPERTY_AUTOINC:
+ {
+ sValue = ::comphelper::getString(_rNewData);
+ pFieldDescr->SetAutoIncrement(sValue == DBA_RES(STR_VALUE_YES));
+ }
+ break;
+ case FIELD_PROPERTY_SCALE:
+ {
+ sValue = ::comphelper::getString(_rNewData);
+ pFieldDescr->SetScale(sValue.toInt32());
+ }
+ break;
+
+ case FIELD_PROPERTY_BOOL_DEFAULT:
+ sValue = GetView()->GetDescWin()->BoolStringPersistent(::comphelper::getString(_rNewData));
+ pFieldDescr->SetControlDefault(Any(sValue));
+ break;
+
+ case FIELD_PROPERTY_FORMAT:
+ {
+ sValue = ::comphelper::getString(_rNewData);
+ pFieldDescr->SetFormatKey(sValue.toInt32());
+ }
+ break;
+ }
+
+ SetControlText(nRow,nColId,sValue);
+}
+
+Any OTableEditorCtrl::GetCellData( sal_Int32 nRow, sal_uInt16 nColId )
+{
+ OFieldDescription* pFieldDescr = GetFieldDescr( nRow );
+ if( !pFieldDescr )
+ return Any();
+
+ // Relocate the current pointer
+ if( nRow==-1 )
+ nRow = GetCurRow();
+ SetDataPtr( nRow );
+
+ static const OUString strYes(DBA_RES(STR_VALUE_YES));
+ static const OUString strNo(DBA_RES(STR_VALUE_NO));
+ OUString sValue;
+ // Read out the fields
+ switch( nColId )
+ {
+ case FIELD_NAME:
+ sValue = pFieldDescr->GetName();
+ break;
+
+ case FIELD_TYPE:
+ if ( pFieldDescr->getTypeInfo() )
+ sValue = pFieldDescr->getTypeInfo()->aUIName;
+ break;
+
+ case COLUMN_DESCRIPTION:
+ sValue = pFieldDescr->GetDescription();
+ break;
+ case HELP_TEXT:
+ sValue = pFieldDescr->GetHelpText();
+ break;
+
+ case FIELD_PROPERTY_DEFAULT:
+ return pFieldDescr->GetControlDefault();
+
+ case FIELD_PROPERTY_REQUIRED:
+ sValue = pFieldDescr->GetIsNullable() == ColumnValue::NULLABLE ? strYes : strNo;
+ break;
+
+ case FIELD_PROPERTY_TEXTLEN:
+ case FIELD_PROPERTY_LENGTH:
+ sValue = OUString::number(pFieldDescr->GetPrecision());
+ break;
+
+ case FIELD_PROPERTY_NUMTYPE:
+ OSL_FAIL("OTableEditorCtrl::GetCellData: invalid column!");
+ break;
+
+ case FIELD_PROPERTY_AUTOINC:
+ sValue = pFieldDescr->IsAutoIncrement() ? strYes : strNo;
+ break;
+
+ case FIELD_PROPERTY_SCALE:
+ sValue = OUString::number(pFieldDescr->GetScale());
+ break;
+
+ case FIELD_PROPERTY_BOOL_DEFAULT:
+ sValue = GetView()->GetDescWin()->BoolStringUI(::comphelper::getString(pFieldDescr->GetControlDefault()));
+ break;
+
+ case FIELD_PROPERTY_FORMAT:
+ sValue = OUString::number(pFieldDescr->GetFormatKey());
+ break;
+ }
+
+ return Any(sValue);
+}
+
+OUString OTableEditorCtrl::GetCellText( sal_Int32 nRow, sal_uInt16 nColId ) const
+{
+ OUString sCellText;
+ const_cast< OTableEditorCtrl* >( this )->GetCellData( nRow, nColId ) >>= sCellText;
+ return sCellText;
+}
+
+sal_uInt32 OTableEditorCtrl::GetTotalCellWidth(sal_Int32 nRow, sal_uInt16 nColId)
+{
+ return GetTextWidth(GetCellText(nRow, nColId)) + 2 * GetTextWidth("0");
+}
+
+OFieldDescription* OTableEditorCtrl::GetFieldDescr( sal_Int32 nRow )
+{
+ std::vector< std::shared_ptr<OTableRow> >::size_type nListCount(
+ m_pRowList->size());
+ if( (nRow<0) || (sal::static_int_cast< unsigned long >(nRow)>=nListCount) )
+ {
+ OSL_FAIL("(nRow<0) || (nRow>=nListCount)");
+ return nullptr;
+ }
+ std::shared_ptr<OTableRow> pRow = (*m_pRowList)[ nRow ];
+ if( !pRow )
+ return nullptr;
+ return pRow->GetActFieldDescr();
+}
+
+bool OTableEditorCtrl::IsCutAllowed()
+{
+ bool bIsCutAllowed = (GetView()->getController().isAddAllowed() && GetView()->getController().isDropAllowed()) ||
+ GetView()->getController().isAlterAllowed();
+
+ if (bIsCutAllowed)
+ {
+ int nStartPos, nEndPos;
+ switch(m_eChildFocus)
+ {
+ case DESCRIPTION:
+ {
+ weld::Entry& rEntry = pDescrCell->get_widget();
+ bIsCutAllowed = rEntry.get_selection_bounds(nStartPos, nEndPos);
+ break;
+ }
+ case HELPTEXT:
+ {
+ weld::Entry& rEntry = pHelpTextCell->get_widget();
+ bIsCutAllowed = rEntry.get_selection_bounds(nStartPos, nEndPos);
+ break;
+ }
+ case NAME:
+ {
+ weld::Entry& rEntry = pNameCell->get_widget();
+ bIsCutAllowed = rEntry.get_selection_bounds(nStartPos, nEndPos);
+ break;
+ }
+ case ROW:
+ bIsCutAllowed = IsCopyAllowed();
+ break;
+ default:
+ bIsCutAllowed = false;
+ break;
+ }
+ }
+
+ return bIsCutAllowed;
+}
+
+bool OTableEditorCtrl::IsCopyAllowed()
+{
+ bool bIsCopyAllowed = false;
+ int nStartPos, nEndPos;
+ if (m_eChildFocus == DESCRIPTION )
+ {
+ weld::Entry& rEntry = pDescrCell->get_widget();
+ bIsCopyAllowed = rEntry.get_selection_bounds(nStartPos, nEndPos);
+ }
+ else if(HELPTEXT == m_eChildFocus )
+ {
+ weld::Entry& rEntry = pHelpTextCell->get_widget();
+ bIsCopyAllowed = rEntry.get_selection_bounds(nStartPos, nEndPos);
+ }
+ else if(m_eChildFocus == NAME)
+ {
+ weld::Entry& rEntry = pNameCell->get_widget();
+ bIsCopyAllowed = rEntry.get_selection_bounds(nStartPos, nEndPos);
+ }
+ else if(m_eChildFocus == ROW)
+ {
+ Reference<XPropertySet> xTable = GetView()->getController().getTable();
+ if( !GetSelectRowCount() || (xTable.is() && ::comphelper::getString(xTable->getPropertyValue(PROPERTY_TYPE)) == "VIEW"))
+ return false;
+
+ // If one of the selected rows is empty, Copy is not possible
+ std::shared_ptr<OTableRow> pRow;
+ tools::Long nIndex = FirstSelectedRow();
+ while( nIndex != SFX_ENDOFSELECTION )
+ {
+ pRow = (*m_pRowList)[nIndex];
+ if( !pRow->GetActFieldDescr() )
+ return false;
+
+ nIndex = NextSelectedRow();
+ }
+
+ bIsCopyAllowed = true;
+ }
+
+ return bIsCopyAllowed;
+}
+
+bool OTableEditorCtrl::IsPasteAllowed() const
+{
+ bool bAllowed = GetView()->getController().isAddAllowed();
+ if ( bAllowed )
+ {
+ TransferableDataHelper aTransferData(TransferableDataHelper::CreateFromSystemClipboard(GetParent()));
+ bool bRowFormat = aTransferData.HasFormat(SotClipboardFormatId::SBA_TABED);
+ if ( m_eChildFocus == ROW )
+ bAllowed = bRowFormat;
+ else
+ bAllowed = !bRowFormat && aTransferData.HasFormat(SotClipboardFormatId::STRING);
+ }
+
+ return bAllowed;
+}
+
+void OTableEditorCtrl::cut()
+{
+ if(m_eChildFocus == NAME)
+ {
+ if(GetView()->getController().isAlterAllowed())
+ {
+ SaveData(-1,FIELD_NAME);
+ pNameCell->get_widget().cut_clipboard();
+ CellModified(-1,FIELD_NAME);
+ }
+ }
+ else if(m_eChildFocus == DESCRIPTION)
+ {
+ if(GetView()->getController().isAlterAllowed())
+ {
+ SaveData(-1,COLUMN_DESCRIPTION);
+ pDescrCell->get_widget().cut_clipboard();
+ CellModified(-1,COLUMN_DESCRIPTION);
+ }
+ }
+ else if(HELPTEXT == m_eChildFocus )
+ {
+ if(GetView()->getController().isAlterAllowed())
+ {
+ SaveData(-1,HELP_TEXT);
+ pHelpTextCell->get_widget().cut_clipboard();
+ CellModified(-1,HELP_TEXT);
+ }
+ }
+ else if(m_eChildFocus == ROW)
+ {
+ if (nCutEvent)
+ Application::RemoveUserEvent(nCutEvent);
+ nCutEvent = Application::PostUserEvent(LINK(this, OTableEditorCtrl, DelayedCut), nullptr, true);
+ }
+}
+
+void OTableEditorCtrl::copy()
+{
+ if (GetSelectRowCount())
+ OTableRowView::copy();
+ else if(m_eChildFocus == NAME)
+ {
+ weld::Entry& rEntry = pNameCell->get_widget();
+ rEntry.copy_clipboard();
+ }
+ else if(HELPTEXT == m_eChildFocus )
+ {
+ weld::Entry& rEntry = pHelpTextCell->get_widget();
+ rEntry.copy_clipboard();
+ }
+ else if(m_eChildFocus == DESCRIPTION )
+ {
+ weld::Entry& rEntry = pDescrCell->get_widget();
+ rEntry.copy_clipboard();
+ }
+}
+
+void OTableEditorCtrl::paste()
+{
+ TransferableDataHelper aTransferData(TransferableDataHelper::CreateFromSystemClipboard(GetParent()));
+ if(aTransferData.HasFormat(SotClipboardFormatId::SBA_TABED))
+ {
+ if( nPasteEvent )
+ Application::RemoveUserEvent( nPasteEvent );
+ nPasteEvent = Application::PostUserEvent( LINK(this, OTableEditorCtrl, DelayedPaste), nullptr, true );
+ }
+ else if(m_eChildFocus == NAME)
+ {
+ if(GetView()->getController().isAlterAllowed())
+ {
+ pNameCell->get_widget().paste_clipboard();
+ CellModified();
+ }
+ }
+ else if(HELPTEXT == m_eChildFocus )
+ {
+ if(GetView()->getController().isAlterAllowed())
+ {
+ pHelpTextCell->get_widget().paste_clipboard();
+ CellModified();
+ }
+ }
+ else if(m_eChildFocus == DESCRIPTION)
+ {
+ if(GetView()->getController().isAlterAllowed())
+ {
+ pDescrCell->get_widget().paste_clipboard();
+ CellModified();
+ }
+ }
+}
+
+bool OTableEditorCtrl::IsDeleteAllowed()
+{
+
+ return GetSelectRowCount() != 0 && GetView()->getController().isDropAllowed();
+}
+
+bool OTableEditorCtrl::IsInsertNewAllowed( sal_Int32 nRow )
+{
+
+ bool bInsertNewAllowed = GetView()->getController().isAddAllowed();
+ // If fields can be added, Paste in the new fields
+ if (bInsertNewAllowed && !GetView()->getController().isDropAllowed())
+ {
+ SetDataPtr(nRow);
+ if( GetActRow()->IsReadOnly() )
+ return false;
+ }
+
+ return bInsertNewAllowed;
+}
+
+bool OTableEditorCtrl::IsPrimaryKeyAllowed()
+{
+ if( !GetSelectRowCount() )
+ return false;
+
+ OTableController& rController = GetView()->getController();
+ if ( !rController.getSdbMetaData().supportsPrimaryKeys() )
+ return false;
+
+ Reference<XPropertySet> xTable = rController.getTable();
+ // Key must not be changed
+ // This applies only if the table is not new and not a css::sdbcx::View. Otherwise no DROP is executed
+
+ if(xTable.is() && ::comphelper::getString(xTable->getPropertyValue(PROPERTY_TYPE)) == "VIEW")
+ return false;
+ // If there is an empty field, no primary key
+ // The entry is only permitted if
+ // - there are no empty entries in the selection
+ // - No Memo or Image entries
+ // - DROP is not permitted (see above) and the column is not Required (not null flag is not set).
+ tools::Long nIndex = FirstSelectedRow();
+ std::shared_ptr<OTableRow> pRow;
+ while( nIndex != SFX_ENDOFSELECTION )
+ {
+ pRow = (*m_pRowList)[nIndex];
+ OFieldDescription* pFieldDescr = pRow->GetActFieldDescr();
+ if(!pFieldDescr)
+ return false;
+ else
+ {
+ // Memo and Image fields cannot be primary keys
+ // or if the column cannot be dropped and the Required flag is not set
+ // or if a css::sdbcx::View is available and the Required flag is not set
+ const TOTypeInfoSP& pTypeInfo = pFieldDescr->getTypeInfo();
+ if( pTypeInfo->nSearchType == ColumnSearch::NONE
+ || (pFieldDescr->IsNullable() && pRow->IsReadOnly())
+ )
+ return false;
+ }
+
+ nIndex = NextSelectedRow();
+ }
+
+ return true;
+}
+
+void OTableEditorCtrl::Command(const CommandEvent& rEvt)
+{
+ switch (rEvt.GetCommand())
+ {
+ case CommandEventId::ContextMenu:
+ {
+ Point aMenuPos( rEvt.GetMousePosPixel() );
+ if (!rEvt.IsMouseEvent())
+ {
+ if ( 1 == GetSelectColumnCount() )
+ {
+ sal_uInt16 nSelId = GetColumnId(
+ sal::static_int_cast< sal_uInt16 >(
+ FirstSelectedColumn() ) );
+ ::tools::Rectangle aColRect( GetFieldRectPixel( 0, nSelId, false ) );
+
+ aMenuPos = aColRect.TopCenter();
+ }
+ else if ( GetSelectRowCount() > 0 )
+ {
+ ::tools::Rectangle aColRect( GetFieldRectPixel( FirstSelectedRow(), HANDLE_ID ) );
+
+ aMenuPos = aColRect.TopCenter();
+ }
+ else
+ {
+ OTableRowView::Command(rEvt);
+ return;
+ }
+ }
+
+ // Show the Context menu
+ if( !IsReadOnly() )
+ {
+ sal_uInt16 nColId = GetColumnId(GetColumnAtXPosPixel(aMenuPos.X()));
+ sal_Int32 nRow = GetRowAtYPosPixel(aMenuPos.Y());
+
+ if ( HANDLE_ID != nColId )
+ {
+ if ( nRow < 0 && nColId != BROWSER_INVALIDID )
+ { // hit the header
+ if ( 3 != nColId )
+ { // 3 would mean the last column, and this last column is auto-sized
+ if ( !IsColumnSelected( nColId ) )
+ SelectColumnId( nColId );
+
+ ::tools::Rectangle aRect(aMenuPos, Size(1, 1));
+ weld::Window* pPopupParent = weld::GetPopupParent(*this, aRect);
+ std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(pPopupParent, "dbaccess/ui/querycolmenu.ui"));
+ std::unique_ptr<weld::Menu> xContextMenu(xBuilder->weld_menu("menu"));
+ xContextMenu->remove("delete");
+ xContextMenu->remove("separator");
+ if (xContextMenu->popup_at_rect(pPopupParent, aRect) == "width")
+ adjustBrowseBoxColumnWidth( this, nColId );
+ }
+ }
+ }
+ else
+ {
+ ::tools::Rectangle aRect(aMenuPos, Size(1, 1));
+ weld::Window* pPopupParent = weld::GetPopupParent(*this, aRect);
+ std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(pPopupParent, "dbaccess/ui/tabledesignrowmenu.ui"));
+ std::unique_ptr<weld::Menu> xContextMenu(xBuilder->weld_menu("menu"));
+
+ if (!IsCutAllowed())
+ xContextMenu->remove("cut");
+ if (!IsCopyAllowed())
+ xContextMenu->remove("copy");
+ if (!IsPasteAllowed())
+ xContextMenu->remove("paste");
+ if (!IsDeleteAllowed())
+ xContextMenu->remove("delete");
+ if (!IsPrimaryKeyAllowed())
+ xContextMenu->remove("primarykey");
+ if (!IsInsertNewAllowed(nRow))
+ xContextMenu->remove("insert");
+ xContextMenu->set_active("primarykey", IsRowSelected(GetCurRow()) && IsPrimaryKey());
+
+ if( SetDataPtr(m_nDataPos) )
+ pDescrWin->SaveData( pActRow->GetActFieldDescr() );
+
+ // All actions which change the number of rows must be run asynchronously
+ // otherwise there may be problems between the Context menu and the Browser
+ m_nDataPos = GetCurRow();
+ OString sIdent = xContextMenu->popup_at_rect(pPopupParent, aRect);
+ if (sIdent == "cut")
+ cut();
+ else if (sIdent == "copy")
+ copy();
+ else if (sIdent == "paste")
+ paste();
+ else if (sIdent == "delete")
+ {
+ if( nDeleteEvent )
+ Application::RemoveUserEvent( nDeleteEvent );
+ nDeleteEvent = Application::PostUserEvent( LINK(this, OTableEditorCtrl, DelayedDelete), nullptr, true );
+ }
+ else if (sIdent == "insert")
+ {
+ if( nInsNewRowsEvent )
+ Application::RemoveUserEvent( nInsNewRowsEvent );
+ nInsNewRowsEvent = Application::PostUserEvent( LINK(this, OTableEditorCtrl, DelayedInsNewRows), nullptr, true );
+ }
+ else if (sIdent == "primarykey")
+ {
+ SetPrimaryKey( !IsPrimaryKey() );
+ }
+ }
+ }
+ }
+ break;
+ default:
+ OTableRowView::Command(rEvt);
+ }
+
+}
+
+IMPL_LINK_NOARG( OTableEditorCtrl, DelayedCut, void*, void )
+{
+ nCutEvent = nullptr;
+ OTableRowView::cut();
+}
+
+IMPL_LINK_NOARG( OTableEditorCtrl, DelayedPaste, void*, void )
+{
+ nPasteEvent = nullptr;
+
+ sal_Int32 nPastePosition = GetView()->getController().getFirstEmptyRowPosition();
+ if ( !GetView()->getController().getTable().is() )
+ nPastePosition = GetSelectRowCount() ? FirstSelectedRow() : GetCurRow();
+
+ if (!IsInsertNewAllowed(nPastePosition))
+ { // Insertion is not allowed, only appending, so test if there are full cells after the PastePosition
+
+ auto aIter = std::find_if(m_pRowList->rbegin(), m_pRowList->rend(), [](const std::shared_ptr<OTableRow>& rxRow) {
+ return rxRow && rxRow->GetActFieldDescr() && !rxRow->GetActFieldDescr()->GetName().isEmpty(); });
+ auto nFreeFromPos = static_cast<sal_Int32>(std::distance(aIter, m_pRowList->rend())); // from here on there are only empty rows
+ if (nPastePosition < nFreeFromPos) // if at least one PastePosition is full, go right to the end
+ nPastePosition = nFreeFromPos;
+ }
+
+ OTableRowView::Paste( nPastePosition );
+ SetNoSelection();
+ GoToRow( nPastePosition );
+}
+
+IMPL_LINK_NOARG( OTableEditorCtrl, DelayedDelete, void*, void )
+{
+ nDeleteEvent = nullptr;
+ DeleteRows();
+}
+
+IMPL_LINK_NOARG( OTableEditorCtrl, DelayedInsNewRows, void*, void )
+{
+ nInsNewRowsEvent = nullptr;
+ sal_Int32 nPastePosition = GetView()->getController().getFirstEmptyRowPosition();
+ if ( !GetView()->getController().getTable().is() )
+ nPastePosition = GetSelectRowCount() ? FirstSelectedRow() : m_nDataPos;
+
+ InsertNewRows( nPastePosition );
+ SetNoSelection();
+ GoToRow( nPastePosition );
+}
+
+void OTableEditorCtrl::AdjustFieldDescription(OFieldDescription* _pFieldDesc,
+ MultiSelection& _rMultiSel,
+ sal_Int32 _nPos,
+ bool _bSet,
+ bool _bPrimaryKey)
+{
+ _pFieldDesc->SetPrimaryKey( _bPrimaryKey );
+ if(!_bSet && _pFieldDesc->getTypeInfo()->bNullable)
+ {
+ _pFieldDesc->SetIsNullable(ColumnValue::NO_NULLS);
+ _pFieldDesc->SetControlDefault(Any());
+ }
+ if ( _pFieldDesc->IsAutoIncrement() && !_bPrimaryKey )
+ {
+ OTableController& rController = GetView()->getController();
+ if ( rController.isAutoIncrementPrimaryKey() )
+ {
+ _pFieldDesc->SetAutoIncrement(false);
+ }
+ }
+ // update field description
+ pDescrWin->DisplayData(_pFieldDesc);
+
+ _rMultiSel.Insert( _nPos );
+ _rMultiSel.Select( _nPos );
+}
+
+void OTableEditorCtrl::SetPrimaryKey( bool bSet )
+{
+ // Delete any existing Primary Keys
+ MultiSelection aDeletedPrimKeys;
+ aDeletedPrimKeys.SetTotalRange( Range(0,GetRowCount()) );
+
+ sal_Int32 nRow = 0;
+ for (auto const& row : *m_pRowList)
+ {
+ OFieldDescription* pFieldDescr = row->GetActFieldDescr();
+ if( pFieldDescr && row->IsPrimaryKey() && (!bSet || !IsRowSelected(nRow)) )
+ {
+ AdjustFieldDescription(pFieldDescr,aDeletedPrimKeys,nRow,bSet,false);
+ }
+ ++nRow;
+ }
+
+ // Set the primary keys of the marked rows
+ MultiSelection aInsertedPrimKeys;
+ aInsertedPrimKeys.SetTotalRange( Range(0,GetRowCount()) );
+ if( bSet )
+ {
+ tools::Long nIndex = FirstSelectedRow();
+ while( nIndex != SFX_ENDOFSELECTION )
+ {
+ // Set the key
+ std::shared_ptr<OTableRow> pRow = (*m_pRowList)[nIndex];
+ OFieldDescription* pFieldDescr = pRow->GetActFieldDescr();
+ if(pFieldDescr)
+ AdjustFieldDescription(pFieldDescr,aInsertedPrimKeys,nIndex,false,true);
+
+ nIndex = NextSelectedRow();
+ }
+ }
+
+ GetUndoManager().AddUndoAction( std::make_unique<OPrimKeyUndoAct>(this, aDeletedPrimKeys, aInsertedPrimKeys) );
+
+ // Invalidate the handle-columns
+ InvalidateHandleColumn();
+
+ // Set the TableDocSh's ModifyFlag
+ GetView()->getController().setModified( true );
+ InvalidateFeatures();
+}
+
+bool OTableEditorCtrl::IsPrimaryKey()
+{
+ // Are all marked fields part of the Primary Key ?
+ tools::Long nPrimaryKeys = 0;
+ sal_Int32 nRow=0;
+ for (auto const& row : *m_pRowList)
+ {
+ if( IsRowSelected(nRow) && !row->IsPrimaryKey() )
+ return false;
+ if( row->IsPrimaryKey() )
+ ++nPrimaryKeys;
+ ++nRow;
+ }
+
+ // Are there any unselected fields that are part of the Key ?
+ return GetSelectRowCount() == nPrimaryKeys;
+}
+
+void OTableEditorCtrl::SwitchType( const TOTypeInfoSP& _pType )
+{
+ // if there is no assigned field name
+ sal_Int32 nRow(GetCurRow());
+ OFieldDescription* pActFieldDescr = GetFieldDescr( nRow );
+ if( pActFieldDescr )
+ // Store the old description
+ pDescrWin->SaveData( pActFieldDescr );
+
+ if ( nRow < 0 || o3tl::make_unsigned(nRow) > m_pRowList->size() )
+ return;
+ // Show the new description
+ std::shared_ptr<OTableRow> pRow = (*m_pRowList)[nRow];
+ pRow->SetFieldType( _pType, true );
+ if ( _pType )
+ {
+ weld::ComboBox& rTypeList = pTypeCell->get_widget();
+ const sal_Int32 nCurrentlySelected = rTypeList.get_active();
+
+ if ( ( nCurrentlySelected == -1 )
+ || ( GetView()->getController().getTypeInfo( nCurrentlySelected ) != _pType )
+ )
+ {
+ sal_Int32 nEntryPos = 0;
+ const OTypeInfoMap& rTypeInfo = GetView()->getController().getTypeInfo();
+ for (auto const& elem : rTypeInfo)
+ {
+ if(elem.second == _pType)
+ break;
+ ++nEntryPos;
+ }
+ if (nEntryPos < rTypeList.get_count())
+ rTypeList.set_active(nEntryPos);
+ }
+ }
+
+ pActFieldDescr = pRow->GetActFieldDescr();
+ if (pActFieldDescr != nullptr && !pActFieldDescr->GetFormatKey())
+ {
+ sal_Int32 nFormatKey = ::dbtools::getDefaultNumberFormat( pActFieldDescr->GetType(),
+ pActFieldDescr->GetScale(),
+ pActFieldDescr->IsCurrency(),
+ Reference< XNumberFormatTypes>(GetView()->getController().getNumberFormatter()->getNumberFormatsSupplier()->getNumberFormats(),UNO_QUERY),
+ GetView()->getLocale());
+
+ pActFieldDescr->SetFormatKey(nFormatKey);
+ }
+
+ pDescrWin->DisplayData( pActFieldDescr );
+}
+
+OTableDesignView* OTableEditorCtrl::GetView() const
+{
+ return m_pView;
+}
+
+void OTableEditorCtrl::DeactivateCell(bool bUpdate)
+{
+ OTableRowView::DeactivateCell(bUpdate);
+ // now we have to deactivate the field description
+ sal_Int32 nRow(GetCurRow());
+ if (pDescrWin)
+ pDescrWin->SetReadOnly(bReadOnly || !SetDataPtr(nRow) || GetActRow()->IsReadOnly());
+}
+
+bool OTableEditorCtrl::PreNotify( NotifyEvent& rNEvt )
+{
+ if (rNEvt.GetType() == MouseNotifyEvent::GETFOCUS)
+ {
+ if( pHelpTextCell && pHelpTextCell->HasChildPathFocus() )
+ m_eChildFocus = HELPTEXT;
+ else if( pDescrCell && pDescrCell->HasChildPathFocus() )
+ m_eChildFocus = DESCRIPTION;
+ else if(pNameCell && pNameCell->HasChildPathFocus() )
+ m_eChildFocus = NAME;
+ else
+ m_eChildFocus = ROW;
+ }
+
+ return OTableRowView::PreNotify(rNEvt);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/tabledesign/TEditControl.hxx b/dbaccess/source/ui/tabledesign/TEditControl.hxx
new file mode 100644
index 000000000..7b1d46781
--- /dev/null
+++ b/dbaccess/source/ui/tabledesign/TEditControl.hxx
@@ -0,0 +1,204 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <TableDesignControl.hxx>
+#include <TableDesignView.hxx>
+#include "TableFieldDescWin.hxx"
+#include <TableRow.hxx>
+#include <TypeInfo.hxx>
+
+class Edit;
+class SfxUndoManager;
+namespace dbaui
+{
+ class OSQLNameEditControl;
+
+ class OTableEditorCtrl : public OTableRowView
+ {
+ enum ChildFocusState
+ {
+ HELPTEXT,
+ DESCRIPTION,
+ NAME,
+ ROW,
+ NONE
+ };
+
+ std::vector< std::shared_ptr<OTableRow> >* m_pRowList;
+
+ VclPtr<OTableDesignView> m_pView;
+ VclPtr<OSQLNameEditControl> pNameCell;
+ VclPtr<::svt::ListBoxControl> pTypeCell;
+ VclPtr<::svt::EditControl> pHelpTextCell;
+ VclPtr<::svt::EditControl> pDescrCell;
+ OTableFieldDescWin* pDescrWin; // properties of one column
+
+ std::shared_ptr<OTableRow> pActRow;
+
+ ImplSVEvent * nCutEvent;
+ ImplSVEvent * nPasteEvent;
+ ImplSVEvent * nDeleteEvent;
+ ImplSVEvent * nInsNewRowsEvent;
+ ImplSVEvent * nInvalidateTypeEvent;
+ ChildFocusState m_eChildFocus;
+
+ tools::Long nOldDataPos;
+
+ bool bReadOnly;
+
+ // helper class
+ class ClipboardInvalidator final
+ {
+ private:
+ AutoTimer m_aInvalidateTimer;
+ VclPtr<OTableEditorCtrl> m_pOwner;
+
+ public:
+ explicit ClipboardInvalidator(OTableEditorCtrl*);
+ ~ClipboardInvalidator();
+ void Stop();
+
+ private:
+ DECL_LINK(OnInvalidate, Timer*, void);
+ };
+
+ friend class OTableEditorCtrl::ClipboardInvalidator;
+
+ ClipboardInvalidator m_aInvalidate;
+
+ protected:
+ virtual void Command( const CommandEvent& rEvt ) override;
+ virtual bool SeekRow(sal_Int32 nRow) override;
+ virtual void PaintCell(OutputDevice& rDev, const tools::Rectangle& rRect,
+ sal_uInt16 nColumnId ) const override;
+
+ virtual void CursorMoved() override;
+ virtual RowStatus GetRowStatus(sal_Int32 nRow) const override;
+
+ virtual ::svt::CellController* GetController(sal_Int32 nRow, sal_uInt16 nCol) override;
+ virtual void InitController(::svt::CellControllerRef& rController, sal_Int32 nRow, sal_uInt16 nCol) override;
+
+ virtual void CellModified() override;
+ virtual bool SaveModified() override; // is called before changing a cell (false prevents change)
+
+ virtual OUString GetCellText(sal_Int32 nRow, sal_uInt16 nColId) const override;
+ virtual sal_uInt32 GetTotalCellWidth(sal_Int32 nRow, sal_uInt16 nColId) override;
+
+ virtual void CopyRows() override;
+ virtual void InsertRows( sal_Int32 nRow ) override;
+ virtual void DeleteRows() override;
+ virtual void InsertNewRows( sal_Int32 nRow ) override;
+
+ virtual bool IsPrimaryKeyAllowed() override;
+ virtual bool IsInsertNewAllowed( sal_Int32 nRow ) override;
+ virtual bool IsDeleteAllowed() override;
+
+ void ClearModified();
+
+ void SetPrimaryKey( bool bSet );
+ bool IsPrimaryKey();
+
+ public:
+ explicit OTableEditorCtrl(vcl::Window* pParentWin, OTableDesignView* pView);
+ virtual ~OTableEditorCtrl() override;
+ virtual void dispose() override;
+ virtual bool CursorMoving(sal_Int32 nNewRow, sal_uInt16 nNewCol) override;
+ SfxUndoManager& GetUndoManager() const;
+
+ void SetDescrWin( OTableFieldDescWin* pWin )
+ {
+ pDescrWin = pWin;
+ if (pDescrWin && pActRow)
+ pDescrWin->DisplayData(pActRow->GetActFieldDescr());
+ }
+ void SaveCurRow();
+ void SwitchType( const TOTypeInfoSP& _pType );
+
+ /// force displaying of the given row
+ void DisplayData( sal_Int32 nRow );
+
+ virtual void SetCellData( sal_Int32 nRow, sal_uInt16 nColId, const TOTypeInfoSP& _pTypeInfo ) override;
+ virtual void SetCellData( sal_Int32 nRow, sal_uInt16 nColId, const css::uno::Any& _rSaveData ) override;
+ virtual css::uno::Any GetCellData( sal_Int32 nRow, sal_uInt16 nColId ) override;
+ virtual void SetControlText( sal_Int32 nRow, sal_uInt16 nColId, const OUString& rText ) override;
+
+ virtual OTableDesignView* GetView() const override;
+
+ std::vector< std::shared_ptr<OTableRow> >* GetRowList(){ return m_pRowList; }
+
+ const std::shared_ptr<OTableRow>& GetActRow() const { return pActRow; }
+ void CellModified( sal_Int32 nRow, sal_uInt16 nColId );
+ void SetReadOnly( bool bRead );
+
+ virtual void Init() override;
+ virtual void DeactivateCell(bool bUpdate = true) override;
+
+ bool IsCutAllowed();
+ bool IsCopyAllowed();
+ bool IsPasteAllowed() const;
+ bool IsReadOnly() const { return bReadOnly;}
+ OFieldDescription* GetFieldDescr( sal_Int32 nRow );
+
+ // Window overrides
+ virtual bool PreNotify( NotifyEvent& rNEvt ) override;
+
+ // IClipboardTest
+ virtual bool isCutAllowed() override { return IsCutAllowed(); }
+ virtual bool isCopyAllowed() override { return IsCopyAllowed(); }
+ virtual bool isPasteAllowed() override { return IsPasteAllowed(); }
+
+ virtual void cut() override;
+ virtual void copy() override;
+ virtual void paste() override;
+
+ private:
+ DECL_LINK( DelayedCut, void*, void );
+ DECL_LINK( DelayedPaste, void*, void );
+ DECL_LINK( DelayedDelete, void*, void );
+ DECL_LINK( DelayedInsNewRows, void*, void );
+ DECL_LINK( InvalidateFieldType, void*, void );
+
+ void InitCellController();
+ sal_Int32 HasFieldName( std::u16string_view rFieldName );
+ OUString GenerateName( const OUString& rName );
+ bool SetDataPtr( sal_Int32 nRow );
+
+ void SaveData(sal_Int32 nRow, sal_uInt16 nColumnId);
+ /** AdjustFieldDescription set the needed values for the description
+ @param _pFieldDesc the field description where to set the values
+ @param _rMultiSel contains the positions which changed for undo/redo
+ @param _nPos the current position
+ @param _bSet should a key be set
+ @param _bPrimaryKey which value should the pkey have
+ */
+ void AdjustFieldDescription( OFieldDescription* _pFieldDesc,
+ MultiSelection& _rMultiSel,
+ sal_Int32 _nPos,
+ bool _bSet,
+ bool _bPrimaryKey);
+ /** InvalidateFeatures invalidates the slots SID_UNDO | SID_REDO | SID_SAVEDOC
+ */
+ void InvalidateFeatures();
+
+ void resetType();
+ };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/tabledesign/TableController.cxx b/dbaccess/source/ui/tabledesign/TableController.cxx
new file mode 100644
index 000000000..07fe30a91
--- /dev/null
+++ b/dbaccess/source/ui/tabledesign/TableController.cxx
@@ -0,0 +1,1495 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <FieldDescriptions.hxx>
+#include "TEditControl.hxx"
+#include <TableController.hxx>
+#include <TableDesignView.hxx>
+#include <TableRow.hxx>
+#include <TypeInfo.hxx>
+#include <UITools.hxx>
+#include <browserids.hxx>
+#include <core_resource.hxx>
+#include <strings.hrc>
+#include <strings.hxx>
+#include <defaultobjectnamecheck.hxx>
+#include <dlgsave.hxx>
+#include <indexdialog.hxx>
+#include <sqlmessage.hxx>
+
+#include <com/sun/star/frame/XTitleChangeListener.hpp>
+#include <com/sun/star/sdb/CommandType.hpp>
+#include <com/sun/star/sdb/SQLContext.hpp>
+#include <com/sun/star/sdbc/ColumnValue.hpp>
+#include <com/sun/star/sdbc/SQLWarning.hpp>
+#include <com/sun/star/sdbcx/KeyType.hpp>
+#include <com/sun/star/sdbcx/XAlterTable.hpp>
+#include <com/sun/star/sdbcx/XAppend.hpp>
+#include <com/sun/star/sdbcx/XDataDescriptorFactory.hpp>
+#include <com/sun/star/sdbcx/XDrop.hpp>
+#include <com/sun/star/sdbcx/XIndexesSupplier.hpp>
+#include <com/sun/star/sdbcx/XTablesSupplier.hpp>
+
+#include <connectivity/dbexception.hxx>
+#include <connectivity/dbtools.hxx>
+#include <connectivity/dbmetadata.hxx>
+#include <cppuhelper/exc_hlp.hxx>
+#include <tools/diagnose_ex.h>
+#include <vcl/svapp.hxx>
+#include <vcl/weld.hxx>
+#include <o3tl/string_view.hxx>
+
+#include <algorithm>
+#include <functional>
+#include <set>
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+org_openoffice_comp_dbu_OTableDesign_get_implementation(
+ css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const& )
+{
+ return cppu::acquire(new ::dbaui::OTableController(context));
+}
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::io;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::frame;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::sdbcx;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::sdb;
+using namespace ::com::sun::star::ui;
+using namespace ::com::sun::star::util;
+using namespace ::dbtools;
+using namespace ::dbaui;
+using namespace ::comphelper;
+
+// number of columns when creating it from scratch
+#define NEWCOLS 128
+
+namespace
+{
+ void dropTable(const Reference<XNameAccess>& _rxTable,const OUString& _sTableName)
+ {
+ if ( _rxTable->hasByName(_sTableName) )
+ {
+ Reference<XDrop> xNameCont(_rxTable,UNO_QUERY);
+ OSL_ENSURE(xNameCont.is(),"No drop interface for tables!");
+ if ( xNameCont.is() )
+ xNameCont->dropByName(_sTableName);
+ }
+ }
+}
+
+OUString SAL_CALL OTableController::getImplementationName()
+{
+ return "org.openoffice.comp.dbu.OTableDesign";
+}
+
+Sequence< OUString> OTableController::getSupportedServiceNames()
+{
+ return { "com.sun.star.sdb.TableDesign" };
+}
+
+OTableController::OTableController(const Reference< XComponentContext >& _rM) : OTableController_BASE(_rM)
+ ,m_sTypeNames(DBA_RES(STR_TABLEDESIGN_DBFIELDTYPES))
+ ,m_bAllowAutoIncrementValue(false)
+ ,m_bNew(true)
+{
+
+ InvalidateAll();
+ m_pTypeInfo = std::make_shared<OTypeInfo>();
+ m_pTypeInfo->aUIName = m_sTypeNames.getToken(TYPE_OTHER, ';');
+}
+
+OTableController::~OTableController()
+{
+ m_aTypeInfoIndex.clear();
+ m_aTypeInfo.clear();
+
+}
+
+void OTableController::startTableListening()
+{
+ Reference< XComponent > xComponent(m_xTable, UNO_QUERY);
+ if (xComponent.is())
+ xComponent->addEventListener(static_cast<XModifyListener*>(this));
+}
+
+void OTableController::stopTableListening()
+{
+ Reference< XComponent > xComponent(m_xTable, UNO_QUERY);
+ if (xComponent.is())
+ xComponent->removeEventListener(static_cast<XModifyListener*>(this));
+}
+
+void OTableController::disposing()
+{
+ OTableController_BASE::disposing();
+ clearView();
+
+ m_vRowList.clear();
+}
+
+FeatureState OTableController::GetState(sal_uInt16 _nId) const
+{
+ FeatureState aReturn;
+ // disabled automatically
+
+ switch (_nId)
+ {
+ case ID_BROWSER_CLOSE:
+ aReturn.bEnabled = true;
+ break;
+ case ID_BROWSER_EDITDOC:
+ aReturn.bChecked = isEditable();
+ aReturn.bEnabled = true;
+ break;
+ case ID_BROWSER_SAVEDOC:
+ aReturn.bEnabled = isEditable() && std::any_of(m_vRowList.begin(),m_vRowList.end(),std::mem_fn(&OTableRow::isValid));
+ break;
+ case ID_BROWSER_SAVEASDOC:
+ aReturn.bEnabled = isConnected() && isEditable();
+ if ( aReturn.bEnabled )
+ {
+ aReturn.bEnabled = std::any_of(m_vRowList.begin(),m_vRowList.end(),
+ std::mem_fn(&OTableRow::isValid));
+ }
+ break;
+
+ case ID_BROWSER_CUT:
+ aReturn.bEnabled = isEditable() && getView() && static_cast<OTableDesignView*>(getView())->isCutAllowed();
+ break;
+ case ID_BROWSER_COPY:
+ aReturn.bEnabled = getView() && static_cast<OTableDesignView*>(getView())->isCopyAllowed();
+ break;
+ case ID_BROWSER_PASTE:
+ aReturn.bEnabled = isEditable() && getView() && static_cast<OTableDesignView*>(getView())->isPasteAllowed();
+ break;
+ case SID_INDEXDESIGN:
+ aReturn.bEnabled =
+ ( ( ((!m_bNew && impl_isModified()) || impl_isModified())
+ || Reference< XIndexesSupplier >(m_xTable, UNO_QUERY).is()
+ )
+ && isConnected()
+ );
+ if ( aReturn.bEnabled )
+ {
+ aReturn.bEnabled = std::any_of(m_vRowList.begin(),m_vRowList.end(),
+ std::mem_fn(&OTableRow::isValid));
+ }
+ break;
+ default:
+ aReturn = OTableController_BASE::GetState(_nId);
+ }
+ return aReturn;
+}
+
+void OTableController::Execute(sal_uInt16 _nId, const Sequence< PropertyValue >& aArgs)
+{
+ switch(_nId)
+ {
+ case ID_BROWSER_EDITDOC:
+ setEditable(!isEditable());
+ static_cast<OTableDesignView*>(getView())->setReadOnly(!isEditable());
+ InvalidateFeature(ID_BROWSER_SAVEDOC);
+ InvalidateFeature(ID_BROWSER_PASTE);
+ InvalidateFeature(SID_BROWSER_CLEAR_QUERY);
+ break;
+ case ID_BROWSER_SAVEASDOC:
+ doSaveDoc(true);
+ break;
+ case ID_BROWSER_SAVEDOC:
+ static_cast<OTableDesignView*>(getView())->GetEditorCtrl()->SaveCurRow();
+ doSaveDoc(false);
+ break;
+ case ID_BROWSER_CUT:
+ static_cast<OTableDesignView*>(getView())->cut();
+ break;
+ case ID_BROWSER_COPY:
+ static_cast<OTableDesignView*>(getView())->copy();
+ break;
+ case ID_BROWSER_PASTE:
+ static_cast<OTableDesignView*>(getView())->paste();
+ break;
+ case SID_INDEXDESIGN:
+ doEditIndexes();
+ break;
+ default:
+ OTableController_BASE::Execute(_nId,aArgs);
+ }
+ InvalidateFeature(_nId);
+}
+
+bool OTableController::doSaveDoc(bool _bSaveAs)
+{
+ if (!isConnected())
+ reconnect(true); // ask the user for a new connection
+ Reference<XTablesSupplier> xTablesSup(getConnection(),UNO_QUERY);
+
+ if (!xTablesSup.is())
+ {
+ OUString aMessage(DBA_RES(STR_TABLEDESIGN_CONNECTION_MISSING));
+ OSQLWarningBox aWarning(getFrameWeld(), aMessage);
+ aWarning.run();
+ return false;
+ }
+
+ // check if a column exists
+ // TODO
+
+ Reference<XNameAccess> xTables;
+ OUString sCatalog, sSchema;
+
+ bool bNew = m_sName.isEmpty();
+ bNew = bNew || m_bNew || _bSaveAs;
+
+ try
+ {
+ xTables = xTablesSup->getTables();
+ OSL_ENSURE(xTables.is(),"The tables can't be null!");
+ bNew = bNew || (xTables.is() && !xTables->hasByName(m_sName));
+
+ // first we need a name for our query so ask the user
+ if(bNew)
+ {
+ OUString aName = DBA_RES(STR_TBL_TITLE);
+ OUString aDefaultName = aName.getToken(0,' ');
+ aDefaultName = ::dbtools::createUniqueName(xTables,aDefaultName);
+
+ DynamicTableOrQueryNameCheck aNameChecker( getConnection(), CommandType::TABLE );
+ OSaveAsDlg aDlg(getFrameWeld(), CommandType::TABLE, getORB(), getConnection(), aDefaultName, aNameChecker, SADFlags::NONE);
+ if (aDlg.run() != RET_OK)
+ return false;
+
+ m_sName = aDlg.getName();
+ sCatalog = aDlg.getCatalog();
+ sSchema = aDlg.getSchema();
+ }
+
+ // did we get a name
+ if(m_sName.isEmpty())
+ return false;
+ }
+ catch(Exception&)
+ {
+ OSL_FAIL("OTableController::doSaveDoc: nothing is expected to happen here!");
+ }
+
+ bool bAlter = false;
+ bool bError = false;
+ SQLExceptionInfo aInfo;
+ try
+ {
+ // check the columns for double names
+ if(!checkColumns(bNew || !xTables->hasByName(m_sName)))
+ {
+ return false;
+ }
+
+ Reference<XPropertySet> xTable;
+ if(bNew || !xTables->hasByName(m_sName)) // just to make sure the table already exists
+ {
+ dropTable(xTables,m_sName);
+
+ Reference<XDataDescriptorFactory> xFact(xTables,UNO_QUERY);
+ OSL_ENSURE(xFact.is(),"OTableController::doSaveDoc: No XDataDescriptorFactory available!");
+ xTable = xFact->createDataDescriptor();
+ OSL_ENSURE(xTable.is(),"OTableController::doSaveDoc: Create query failed!");
+ // to set the name is only allowed when the query is new
+ xTable->setPropertyValue(PROPERTY_CATALOGNAME,Any(sCatalog));
+ xTable->setPropertyValue(PROPERTY_SCHEMANAME,Any(sSchema));
+ xTable->setPropertyValue(PROPERTY_NAME,Any(m_sName));
+
+ // now append the columns
+ Reference<XColumnsSupplier> xColSup(xTable,UNO_QUERY);
+ appendColumns(xColSup,bNew);
+ // now append the primary key
+ Reference<XKeysSupplier> xKeySup(xTable,UNO_QUERY);
+ appendPrimaryKey(xKeySup,bNew);
+ }
+ // now set the properties
+ if(bNew)
+ {
+ Reference<XAppend> xAppend(xTables,UNO_QUERY);
+ OSL_ENSURE(xAppend.is(),"OTableController::doSaveDoc: No XAppend Interface!");
+ xAppend->appendByDescriptor(xTable);
+
+ assignTable();
+ if(!m_xTable.is()) // correct name and try again
+ {
+ // it can be that someone inserted new data for us
+ m_sName = ::dbtools::composeTableName( getConnection()->getMetaData(), xTable, ::dbtools::EComposeRule::InDataManipulation, false );
+ assignTable();
+ }
+ // now check if our datasource has set a tablefilter and if append the new table name to it
+ ::dbaui::appendToFilter(getConnection(), m_sName, getORB(), getFrameWeld()); // we are not interested in the return value
+ Reference< frame::XTitleChangeListener> xEventListener(impl_getTitleHelper_throw(),UNO_QUERY);
+ if ( xEventListener.is() )
+ {
+ frame::TitleChangedEvent aEvent;
+ xEventListener->titleChanged(aEvent);
+ }
+ releaseNumberForComponent();
+ }
+ else if(m_xTable.is())
+ {
+ bAlter = true;
+ alterColumns();
+ }
+ reSyncRows();
+ }
+ catch(const SQLContext& e)
+ {
+ aInfo = SQLExceptionInfo(e);
+ }
+ catch(const SQLWarning& e)
+ {
+ aInfo = SQLExceptionInfo(e);
+ }
+ catch(const SQLException& e)
+ {
+ aInfo = SQLExceptionInfo(e);
+ }
+ catch(const ElementExistException& )
+ {
+ OUString sText( DBA_RES( STR_NAME_ALREADY_EXISTS ) );
+ sText = sText.replaceFirst( "#" , m_sName);
+ OSQLMessageBox aDlg(getFrameWeld(), DBA_RES( STR_ERROR_DURING_CREATION ), sText, MessBoxStyle::Ok, MessageType::Error);
+ aDlg.run();
+ bError = true;
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ bError = true;
+ }
+
+ if ( aInfo.isValid() )
+ aInfo.prepend( DBA_RES( STR_TABLEDESIGN_SAVE_ERROR ) );
+ showError(aInfo);
+
+ if (aInfo.isValid() || bError)
+ {
+ if(!bAlter || bNew)
+ {
+ m_sName.clear();
+ stopTableListening();
+ m_xTable = nullptr;
+ }
+ }
+ return ! (aInfo.isValid() || bError);
+}
+
+void OTableController::doEditIndexes()
+{
+ // table needs to be saved before editing indexes
+ if (m_bNew || isModified())
+ {
+ std::unique_ptr<weld::MessageDialog> xAsk(Application::CreateMessageDialog(getFrameWeld(),
+ VclMessageType::Question, VclButtonsType::YesNo,
+ DBA_RES(STR_QUERY_SAVE_TABLE_EDIT_INDEXES)));
+ if (RET_YES != xAsk->run())
+ return;
+
+ if (!doSaveDoc(false))
+ return;
+
+ OSL_ENSURE(!m_bNew && !isModified(), "OTableController::doEditIndexes: what the hell did doSaveDoc do?");
+ }
+
+ Reference< XNameAccess > xIndexes; // will be the keys of the table
+ Sequence< OUString > aFieldNames; // will be the column names of the table
+ try
+ {
+ // get the keys
+ Reference< XIndexesSupplier > xIndexesSupp(m_xTable, UNO_QUERY);
+ if (xIndexesSupp.is())
+ {
+ xIndexes = xIndexesSupp->getIndexes();
+ OSL_ENSURE(xIndexes.is(), "OTableController::doEditIndexes: no keys got from the indexes supplier!");
+ }
+ else
+ OSL_FAIL("OTableController::doEditIndexes: should never have reached this (no indexes supplier)!");
+
+ // get the field names
+ Reference< XColumnsSupplier > xColSupp(m_xTable, UNO_QUERY);
+ OSL_ENSURE(xColSupp.is(), "OTableController::doEditIndexes: no columns supplier!");
+ if (xColSupp.is())
+ {
+ Reference< XNameAccess > xCols = xColSupp->getColumns();
+ OSL_ENSURE(xCols.is(), "OTableController::doEditIndexes: no columns!");
+ if (xCols.is())
+ aFieldNames = xCols->getElementNames();
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+
+ if (!xIndexes.is())
+ return;
+
+ DbaIndexDialog aDialog(getFrameWeld(), aFieldNames, xIndexes, getConnection(), getORB());
+ if (RET_OK != aDialog.run())
+ return;
+
+}
+
+void OTableController::impl_initialize()
+{
+ try
+ {
+ OTableController_BASE::impl_initialize();
+
+ const NamedValueCollection& rArguments( getInitParams() );
+
+ rArguments.get_ensureType( PROPERTY_CURRENTTABLE, m_sName );
+
+ // read autoincrement value set in the datasource
+ ::dbaui::fillAutoIncrementValue(getDataSource(),m_bAllowAutoIncrementValue,m_sAutoIncrementValue);
+
+ assignTable();
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+
+ try
+ {
+ ::dbaui::fillTypeInfo(getConnection(),m_sTypeNames,m_aTypeInfo,m_aTypeInfoIndex); // fill the needed type information
+ }
+ catch(const SQLException&)
+ {
+ OSQLWarningBox aWarning(getFrameWeld(), DBA_RES( STR_NO_TYPE_INFO_AVAILABLE));
+ aWarning.run();
+ throw;
+ }
+ try
+ {
+ loadData(); // fill the column information from the table
+ getView()->initialize(); // show the windows and fill with our information
+ ClearUndoManager();
+ setModified(false); // and we are not modified yet
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+}
+
+bool OTableController::Construct(vcl::Window* pParent)
+{
+ setView( VclPtr<OTableDesignView>::Create( pParent, getORB(), *this ) );
+ OTableController_BASE::Construct(pParent);
+ return true;
+}
+
+sal_Bool SAL_CALL OTableController::suspend(sal_Bool /*_bSuspend*/)
+{
+ if ( getBroadcastHelper().bInDispose || getBroadcastHelper().bDisposed )
+ return true;
+
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( getMutex() );
+ if ( getView() && getView()->IsInModalMode() )
+ return false;
+ if ( getView() )
+ static_cast<OTableDesignView*>(getView())->GrabFocus();
+ bool bCheck = true;
+ if ( isModified() )
+ {
+ if ( std::any_of(m_vRowList.begin(),m_vRowList.end(),
+ std::mem_fn(&OTableRow::isValid)) )
+ {
+ std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(getFrameWeld(), "dbaccess/ui/tabledesignsavemodifieddialog.ui"));
+ std::unique_ptr<weld::MessageDialog> xQuery(xBuilder->weld_message_dialog("TableDesignSaveModifiedDialog"));
+ switch (xQuery->run())
+ {
+ case RET_YES:
+ Execute(ID_BROWSER_SAVEDOC,Sequence<PropertyValue>());
+ if ( isModified() )
+ bCheck = false; // when we save the table this must be false else some press cancel
+ break;
+ case RET_CANCEL:
+ bCheck = false;
+ break;
+ default:
+ break;
+ }
+ }
+ else if ( !m_bNew )
+ {
+ std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(getFrameWeld(), "dbaccess/ui/deleteallrowsdialog.ui"));
+ std::unique_ptr<weld::MessageDialog> xQuery(xBuilder->weld_message_dialog("DeleteAllRowsDialog"));
+ switch (xQuery->run())
+ {
+ case RET_YES:
+ {
+ try
+ {
+ Reference<XTablesSupplier> xTablesSup(getConnection(),UNO_QUERY);
+ Reference<XNameAccess> xTables = xTablesSup->getTables();
+ dropTable(xTables,m_sName);
+ }
+ catch(const Exception&)
+ {
+ OSL_FAIL("OTableController::suspend: nothing is expected to happen here!");
+ }
+
+ }
+ break;
+ case RET_CANCEL:
+ bCheck = false;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ return bCheck;
+}
+
+void OTableController::describeSupportedFeatures()
+{
+ OSingleDocumentController::describeSupportedFeatures();
+
+ implDescribeSupportedFeature( ".uno:Redo", ID_BROWSER_REDO, CommandGroup::EDIT );
+ implDescribeSupportedFeature( ".uno:Save", ID_BROWSER_SAVEDOC, CommandGroup::EDIT );
+ implDescribeSupportedFeature( ".uno:Undo", ID_BROWSER_UNDO, CommandGroup::EDIT );
+ implDescribeSupportedFeature( ".uno:NewDoc", SID_NEWDOC, CommandGroup::DOCUMENT );
+ implDescribeSupportedFeature( ".uno:SaveAs", ID_BROWSER_SAVEASDOC, CommandGroup::DOCUMENT );
+ implDescribeSupportedFeature( ".uno:DBIndexDesign", SID_INDEXDESIGN, CommandGroup::APPLICATION );
+ implDescribeSupportedFeature( ".uno:EditDoc", ID_BROWSER_EDITDOC, CommandGroup::EDIT );
+ implDescribeSupportedFeature( ".uno:GetUndoStrings", SID_GETUNDOSTRINGS );
+ implDescribeSupportedFeature( ".uno:GetRedoStrings", SID_GETREDOSTRINGS );
+}
+
+void OTableController::impl_onModifyChanged()
+{
+ OSingleDocumentController::impl_onModifyChanged();
+ InvalidateFeature( SID_INDEXDESIGN );
+}
+
+void SAL_CALL OTableController::disposing( const EventObject& _rSource )
+{
+ if ( _rSource.Source == m_xTable )
+ { // some deleted our table so we have a new one
+ stopTableListening();
+ m_xTable = nullptr;
+ m_bNew = true;
+ setModified(true);
+ }
+ else
+ OTableController_BASE::disposing( _rSource );
+}
+
+void OTableController::losingConnection( )
+{
+ // let the base class do its reconnect
+ OTableController_BASE::losingConnection( );
+
+ // remove from the table
+ Reference< XComponent > xComponent(m_xTable, UNO_QUERY);
+ if (xComponent.is())
+ {
+ Reference<XEventListener> xEvtL( static_cast< ::cppu::OWeakObject*>(this), UNO_QUERY);
+ xComponent->removeEventListener(xEvtL);
+ }
+ stopTableListening();
+ m_xTable = nullptr;
+ assignTable();
+ if(!m_xTable.is())
+ {
+ m_bNew = true;
+ setModified(true);
+ }
+ InvalidateAll();
+}
+
+TOTypeInfoSP OTableController::getTypeInfoByType(sal_Int32 _nDataType) const
+{
+ return queryTypeInfoByType(_nDataType,m_aTypeInfo);
+}
+
+void OTableController::appendColumns(Reference<XColumnsSupplier> const & _rxColSup, bool _bNew, bool _bKeyColumns)
+{
+ try
+ {
+ // now append the columns
+ OSL_ENSURE(_rxColSup.is(),"No columns supplier");
+ if(!_rxColSup.is())
+ return;
+ Reference<XNameAccess> xColumns = _rxColSup->getColumns();
+ OSL_ENSURE(xColumns.is(),"No columns");
+ Reference<XDataDescriptorFactory> xColumnFactory(xColumns,UNO_QUERY);
+
+ Reference<XAppend> xAppend(xColumns,UNO_QUERY);
+ OSL_ENSURE(xAppend.is(),"No XAppend Interface!");
+
+ for (auto const& row : m_vRowList)
+ {
+ OSL_ENSURE(row,"OTableRow is null!");
+ OFieldDescription* pField = row->GetActFieldDescr();
+ if ( !pField || (!_bNew && row->IsReadOnly() && !_bKeyColumns) )
+ continue;
+
+ Reference<XPropertySet> xColumn;
+ if(pField->IsPrimaryKey() || !_bKeyColumns)
+ xColumn = xColumnFactory->createDataDescriptor();
+ if(xColumn.is())
+ {
+ if(!_bKeyColumns)
+ ::dbaui::setColumnProperties(xColumn,pField);
+ else
+ xColumn->setPropertyValue(PROPERTY_NAME,Any(pField->GetName()));
+
+ xAppend->appendByDescriptor(xColumn);
+ xColumn = nullptr;
+ // now only the settings are missing
+ if(xColumns->hasByName(pField->GetName()))
+ {
+ xColumns->getByName(pField->GetName()) >>= xColumn;
+ if(xColumn.is())
+ pField->copyColumnSettingsTo(xColumn);
+ }
+ else
+ {
+ OSL_FAIL("OTableController::appendColumns: invalid field name!");
+ }
+
+ }
+ }
+ }
+ catch(const SQLException& )
+ {
+ showError( SQLExceptionInfo( ::cppu::getCaughtException() ) );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+}
+
+void OTableController::appendPrimaryKey(Reference<XKeysSupplier> const & _rxSup, bool _bNew)
+{
+ if(!_rxSup.is())
+ return; // the database doesn't support keys
+
+ OSL_ENSURE(_rxSup.is(),"No XKeysSupplier!");
+ Reference<XIndexAccess> xKeys = _rxSup->getKeys();
+ Reference<XPropertySet> xProp;
+ if (!xKeys.is())
+ return;
+ const sal_Int32 nCount = xKeys->getCount();
+ for(sal_Int32 i=0;i< nCount ;++i)
+ {
+ xKeys->getByIndex(i) >>= xProp;
+ sal_Int32 nKeyType = 0;
+ xProp->getPropertyValue(PROPERTY_TYPE) >>= nKeyType;
+ if(KeyType::PRIMARY == nKeyType)
+ {
+ return; // primary key already exists after appending a column
+ }
+ }
+ Reference<XDataDescriptorFactory> xKeyFactory(xKeys,UNO_QUERY);
+ OSL_ENSURE(xKeyFactory.is(),"No XDataDescriptorFactory Interface!");
+ if ( !xKeyFactory.is() )
+ return;
+ Reference<XAppend> xAppend(xKeyFactory,UNO_QUERY);
+ OSL_ENSURE(xAppend.is(),"No XAppend Interface!");
+
+ Reference<XPropertySet> xKey = xKeyFactory->createDataDescriptor();
+ OSL_ENSURE(xKey.is(),"Key is null!");
+ xKey->setPropertyValue(PROPERTY_TYPE,Any(KeyType::PRIMARY));
+
+ Reference<XColumnsSupplier> xColSup(xKey,UNO_QUERY);
+ if(xColSup.is())
+ {
+ appendColumns(xColSup,_bNew,true);
+ Reference<XNameAccess> xColumns = xColSup->getColumns();
+ if(xColumns->hasElements())
+ xAppend->appendByDescriptor(xKey);
+ }
+}
+
+void OTableController::loadData()
+{
+ // if the data structure already exists, empty it
+ m_vRowList.clear();
+
+ std::shared_ptr<OTableRow> pTabEdRow;
+ Reference< XDatabaseMetaData> xMetaData = getMetaData( );
+ // fill data structure with data from DataDefinitionObject
+ if(m_xTable.is() && xMetaData.is())
+ {
+ Reference<XColumnsSupplier> xColSup(m_xTable,UNO_QUERY);
+ OSL_ENSURE(xColSup.is(),"No XColumnsSupplier!");
+ Reference<XNameAccess> xColumns = xColSup->getColumns();
+ // ReadOnly-Flag
+ // For Drop no row may be editable
+ // For Add only the empty rows may be editable
+ // For Add and Drop all rows can be edited
+ // sal_Bool bReadOldRow = xMetaData->supportsAlterTableWithAddColumn() && xMetaData->supportsAlterTableWithDropColumn();
+ bool bIsAlterAllowed = isAlterAllowed();
+
+ const Sequence<OUString> aColNames = xColumns->getElementNames();
+ for(const OUString& rColumn : aColNames)
+ {
+ Reference<XPropertySet> xColumn;
+ xColumns->getByName(rColumn) >>= xColumn;
+ sal_Int32 nType = 0;
+ sal_Int32 nScale = 0;
+ sal_Int32 nPrecision = 0;
+ sal_Int32 nNullable = 0;
+ sal_Int32 nFormatKey = 0;
+ sal_Int32 nAlign = 0;
+
+ bool bIsAutoIncrement = false, bIsCurrency = false;
+ OUString sName,sDescription,sTypeName,sHelpText;
+ Any aControlDefault;
+
+ // get the properties from the column
+ xColumn->getPropertyValue(PROPERTY_NAME) >>= sName;
+ xColumn->getPropertyValue(PROPERTY_TYPENAME) >>= sTypeName;
+ xColumn->getPropertyValue(PROPERTY_ISNULLABLE) >>= nNullable;
+ xColumn->getPropertyValue(PROPERTY_ISAUTOINCREMENT) >>= bIsAutoIncrement;
+ xColumn->getPropertyValue(PROPERTY_ISCURRENCY) >>= bIsCurrency;
+ xColumn->getPropertyValue(PROPERTY_TYPE) >>= nType;
+ xColumn->getPropertyValue(PROPERTY_SCALE) >>= nScale;
+ xColumn->getPropertyValue(PROPERTY_PRECISION) >>= nPrecision;
+ xColumn->getPropertyValue(PROPERTY_DESCRIPTION) >>= sDescription;
+
+ if(xColumn->getPropertySetInfo()->hasPropertyByName(PROPERTY_HELPTEXT))
+ xColumn->getPropertyValue(PROPERTY_HELPTEXT) >>= sHelpText;
+
+ if(xColumn->getPropertySetInfo()->hasPropertyByName(PROPERTY_CONTROLDEFAULT))
+ aControlDefault = xColumn->getPropertyValue(PROPERTY_CONTROLDEFAULT);
+ if(xColumn->getPropertySetInfo()->hasPropertyByName(PROPERTY_FORMATKEY))
+ xColumn->getPropertyValue(PROPERTY_FORMATKEY) >>= nFormatKey;
+ if(xColumn->getPropertySetInfo()->hasPropertyByName(PROPERTY_ALIGN))
+ xColumn->getPropertyValue(PROPERTY_ALIGN) >>= nAlign;
+
+ pTabEdRow = std::make_shared<OTableRow>();
+ pTabEdRow->SetReadOnly(!bIsAlterAllowed);
+ // search for type
+ bool bForce;
+ TOTypeInfoSP pTypeInfo = ::dbaui::getTypeInfoFromType(m_aTypeInfo,nType,sTypeName,"x",nPrecision,nScale,bIsAutoIncrement,bForce);
+ if ( !pTypeInfo )
+ pTypeInfo = m_pTypeInfo;
+ pTabEdRow->SetFieldType( pTypeInfo, bForce );
+
+ OFieldDescription* pActFieldDescr = pTabEdRow->GetActFieldDescr();
+ OSL_ENSURE(pActFieldDescr, "OTableController::loadData: invalid field description generated by the table row!");
+ if ( pActFieldDescr )
+ {
+ pActFieldDescr->SetName(sName);
+ pActFieldDescr->SetFormatKey(nFormatKey);
+ pActFieldDescr->SetDescription(sDescription);
+ pActFieldDescr->SetHelpText(sHelpText);
+ pActFieldDescr->SetAutoIncrement(bIsAutoIncrement);
+ pActFieldDescr->SetHorJustify(dbaui::mapTextJustify(nAlign));
+ pActFieldDescr->SetCurrency(bIsCurrency);
+
+ // special data
+ pActFieldDescr->SetIsNullable(nNullable);
+ pActFieldDescr->SetControlDefault(aControlDefault);
+ pActFieldDescr->SetPrecision(nPrecision);
+ pActFieldDescr->SetScale(nScale);
+ }
+ m_vRowList.push_back( pTabEdRow);
+ }
+ // fill the primary key information
+ Reference<XNameAccess> xKeyColumns = getKeyColumns();
+ if(xKeyColumns.is())
+ {
+ const Sequence<OUString> aKeyColumnNames = xKeyColumns->getElementNames();
+ for(const OUString& rKeyColumn : aKeyColumnNames)
+ {
+ for(std::shared_ptr<OTableRow> const& pRow : m_vRowList)
+ {
+ if(pRow->GetActFieldDescr()->GetName() == rKeyColumn)
+ {
+ pRow->SetPrimaryKey(true);
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ // fill empty rows
+
+ OTypeInfoMap::const_iterator aTypeIter = m_aTypeInfo.find(DataType::VARCHAR);
+ if(aTypeIter == m_aTypeInfo.end())
+ aTypeIter = m_aTypeInfo.begin();
+
+ OSL_ENSURE(aTypeIter != m_aTypeInfo.end(),"We have no type information!");
+
+ bool bReadRow = !isAddAllowed();
+ for(sal_Int32 i=m_vRowList.size(); i < NEWCOLS; i++ )
+ {
+ pTabEdRow = std::make_shared<OTableRow>();
+ pTabEdRow->SetReadOnly(bReadRow);
+ m_vRowList.push_back( pTabEdRow);
+ }
+}
+
+Reference<XNameAccess> OTableController::getKeyColumns() const
+{
+ return getPrimaryKeyColumns_throw(m_xTable);
+}
+
+bool OTableController::checkColumns(bool _bNew)
+{
+ bool bOk = true;
+ bool bFoundPKey = false;
+ Reference< XDatabaseMetaData > xMetaData = getMetaData( );
+ DatabaseMetaData aMetaData( getConnection() );
+
+ ::comphelper::UStringMixEqual bCase(!xMetaData.is() || xMetaData->supportsMixedCaseQuotedIdentifiers());
+ std::vector< std::shared_ptr<OTableRow> >::const_iterator aIter = m_vRowList.begin();
+ std::vector< std::shared_ptr<OTableRow> >::const_iterator aEnd = m_vRowList.end();
+ for(;aIter != aEnd;++aIter)
+ {
+ OFieldDescription* pFieldDesc = (*aIter)->GetActFieldDescr();
+ if (pFieldDesc && !pFieldDesc->GetName().isEmpty())
+ {
+ bFoundPKey |= (*aIter)->IsPrimaryKey();
+ // first check for duplicate names
+ bool bDuplicateNameFound = std::any_of(aIter+1, aEnd,
+ [&bCase, &pFieldDesc](const std::shared_ptr<OTableRow>& rxRow) {
+ OFieldDescription* pCompareDesc = rxRow->GetActFieldDescr();
+ return pCompareDesc && bCase(pCompareDesc->GetName(),pFieldDesc->GetName());
+ });
+ if (bDuplicateNameFound)
+ {
+ OUString strMessage = DBA_RES(STR_TABLEDESIGN_DUPLICATE_NAME);
+ strMessage = strMessage.replaceFirst("$column$", pFieldDesc->GetName());
+ OSQLWarningBox aWarning(getFrameWeld(), strMessage);
+ aWarning.run();
+ return false;
+ }
+ }
+ }
+ if ( _bNew && !bFoundPKey && aMetaData.supportsPrimaryKeys() )
+ {
+ OUString sTitle(DBA_RES(STR_TABLEDESIGN_NO_PRIM_KEY_HEAD));
+ OUString sMsg(DBA_RES(STR_TABLEDESIGN_NO_PRIM_KEY));
+ OSQLMessageBox aBox(getFrameWeld(), sTitle,sMsg, MessBoxStyle::YesNoCancel | MessBoxStyle::DefaultYes);
+
+ switch (aBox.run())
+ {
+ case RET_YES:
+ {
+ auto pNewRow = std::make_shared<OTableRow>();
+ TOTypeInfoSP pTypeInfo = ::dbaui::queryPrimaryKeyType(m_aTypeInfo);
+ if ( !pTypeInfo )
+ break;
+
+ pNewRow->SetFieldType( pTypeInfo );
+ OFieldDescription* pActFieldDescr = pNewRow->GetActFieldDescr();
+
+ pActFieldDescr->SetAutoIncrement(false);
+ pActFieldDescr->SetIsNullable(ColumnValue::NO_NULLS);
+
+ pActFieldDescr->SetName( createUniqueName("ID" ));
+ pActFieldDescr->SetPrimaryKey( true );
+ m_vRowList.insert(m_vRowList.begin(),pNewRow);
+
+ static_cast<OTableDesignView*>(getView())->GetEditorCtrl()->Invalidate();
+ static_cast<OTableDesignView*>(getView())->GetEditorCtrl()->RowInserted(0);
+ }
+ break;
+ case RET_CANCEL:
+ bOk = false;
+ break;
+ }
+ }
+ return bOk;
+}
+
+void OTableController::alterColumns()
+{
+ Reference<XColumnsSupplier> xColSup(m_xTable,UNO_QUERY_THROW);
+
+ Reference<XNameAccess> xColumns = xColSup->getColumns();
+ Reference<XIndexAccess> xIdxColumns(xColumns,UNO_QUERY_THROW);
+ OSL_ENSURE(xColumns.is(),"No columns");
+ if ( !xColumns.is() )
+ return;
+ Reference<XAlterTable> xAlter(m_xTable,UNO_QUERY); // can be null
+
+ sal_Int32 nColumnCount = xIdxColumns->getCount();
+ Reference<XDrop> xDrop(xColumns,UNO_QUERY); // can be null
+ Reference<XAppend> xAppend(xColumns,UNO_QUERY); // can be null
+ Reference<XDataDescriptorFactory> xColumnFactory(xColumns,UNO_QUERY); // can be null
+
+ bool bReload = false; // refresh the data
+
+ // contains all columns names which are already handled those which are not in the list will be deleted
+ Reference< XDatabaseMetaData> xMetaData = getMetaData( );
+
+ std::set<OUString, comphelper::UStringMixLess> aColumns(
+ comphelper::UStringMixLess(
+ !xMetaData.is()
+ || xMetaData->supportsMixedCaseQuotedIdentifiers()));
+ std::vector< std::shared_ptr<OTableRow> >::const_iterator aIter = m_vRowList.begin();
+ std::vector< std::shared_ptr<OTableRow> >::const_iterator aEnd = m_vRowList.end();
+ // first look for columns where something other than the name changed
+ for(sal_Int32 nPos = 0;aIter != aEnd;++aIter,++nPos)
+ {
+ OSL_ENSURE(*aIter,"OTableRow is null!");
+ OFieldDescription* pField = (*aIter)->GetActFieldDescr();
+ if ( !pField )
+ continue;
+ if ( (*aIter)->IsReadOnly() )
+ {
+ aColumns.insert(pField->GetName());
+ continue;
+ }
+
+ Reference<XPropertySet> xColumn;
+ if ( xColumns->hasByName(pField->GetName()) )
+ {
+ aColumns.insert(pField->GetName());
+ xColumns->getByName(pField->GetName()) >>= xColumn;
+ OSL_ENSURE(xColumn.is(),"Column is null!");
+
+ sal_Int32 nType=0,nPrecision=0,nScale=0,nNullable=0;
+ bool bAutoIncrement = false;
+ OUString sTypeName,sDescription;
+
+ xColumn->getPropertyValue(PROPERTY_TYPE) >>= nType;
+ xColumn->getPropertyValue(PROPERTY_PRECISION) >>= nPrecision;
+ xColumn->getPropertyValue(PROPERTY_SCALE) >>= nScale;
+ xColumn->getPropertyValue(PROPERTY_ISNULLABLE) >>= nNullable;
+ xColumn->getPropertyValue(PROPERTY_ISAUTOINCREMENT) >>= bAutoIncrement;
+ xColumn->getPropertyValue(PROPERTY_DESCRIPTION) >>= sDescription;
+
+ try { xColumn->getPropertyValue(PROPERTY_TYPENAME) >>= sTypeName; }
+ catch( const Exception& )
+ {
+ OSL_FAIL( "no TypeName property?!" );
+ // since this is a last minute fix for #i41785#, I want to be on the safe side,
+ // and catch errors here as early as possible (instead of the whole process of altering
+ // the columns failing)
+ // Normally, sdbcx::Column objects are expected to have a TypeName property
+ }
+
+ // check if something changed
+ if((nType != pField->GetType() ||
+ sTypeName != pField->GetTypeName() ||
+ (nPrecision != pField->GetPrecision() && nPrecision ) ||
+ nScale != pField->GetScale() ||
+ nNullable != pField->GetIsNullable() ||
+ sDescription != pField->GetDescription() ||
+ bAutoIncrement != pField->IsAutoIncrement())&&
+ xColumnFactory.is())
+ {
+ Reference<XPropertySet> xNewColumn = xColumnFactory->createDataDescriptor();
+ ::dbaui::setColumnProperties(xNewColumn,pField);
+ // first try to alter the column
+ bool bNotOk = false;
+ try
+ {
+ // first try if we can alter the column
+ if(xAlter.is())
+ xAlter->alterColumnByName(pField->GetName(),xNewColumn);
+ }
+ catch(const SQLException&)
+ {
+ if(xDrop.is() && xAppend.is())
+ {
+ OUString aMessage( DBA_RES( STR_TABLEDESIGN_ALTER_ERROR ) );
+ aMessage = aMessage.replaceFirst( "$column$", pField->GetName() );
+
+ SQLExceptionInfo aError( ::cppu::getCaughtException() );
+ OSQLWarningBox aMsg(getFrameWeld(), aMessage, MessBoxStyle::YesNo | MessBoxStyle::DefaultYes , &aError);
+ bNotOk = aMsg.run() == RET_YES;
+ }
+ else
+ throw;
+ }
+ // if something went wrong or we can't alter columns
+ // drop and append a new one
+ if((!xAlter.is() || bNotOk) && xDrop.is() && xAppend.is())
+ {
+ xDrop->dropByName(pField->GetName());
+ try
+ {
+ xAppend->appendByDescriptor(xNewColumn);
+ }
+ catch(const SQLException&)
+ { // an error occurred so we try to reactivate the old one
+ xAppend->appendByDescriptor(xColumn);
+ throw;
+ }
+ }
+ // exceptions are caught outside
+ xNewColumn = nullptr;
+ if(xColumns->hasByName(pField->GetName()))
+ xColumns->getByName(pField->GetName()) >>= xColumn;
+ bReload = true;
+ }
+
+ }
+ else if(xColumnFactory.is() && xAlter.is() && nPos < nColumnCount)
+ { // we can't find the column so we could try it with the index before we drop and append a new column
+ try
+ {
+ Reference<XPropertySet> xNewColumn = xColumnFactory->createDataDescriptor();
+ ::dbaui::setColumnProperties(xNewColumn,pField);
+ xAlter->alterColumnByIndex(nPos,xNewColumn);
+ if(xColumns->hasByName(pField->GetName()))
+ { // ask for the append by name
+ aColumns.insert(pField->GetName());
+ xColumns->getByName(pField->GetName()) >>= xColumn;
+ if(xColumn.is())
+ pField->copyColumnSettingsTo(xColumn);
+ }
+ else
+ {
+ OSL_FAIL("OTableController::alterColumns: invalid column (2)!");
+ }
+ }
+ catch(const SQLException&)
+ { // we couldn't alter the column so we have to add new columns
+ SQLExceptionInfo aError( ::cppu::getCaughtException() );
+ bReload = true;
+ if(xDrop.is() && xAppend.is())
+ {
+ OUString aMessage(DBA_RES(STR_TABLEDESIGN_ALTER_ERROR));
+ aMessage = aMessage.replaceFirst("$column$",pField->GetName());
+ OSQLWarningBox aMsg(getFrameWeld(), aMessage, MessBoxStyle::YesNo | MessBoxStyle::DefaultYes, &aError);
+ if (aMsg.run() != RET_YES)
+ {
+ Reference<XPropertySet> xNewColumn(xIdxColumns->getByIndex(nPos),UNO_QUERY_THROW);
+ OUString sName;
+ xNewColumn->getPropertyValue(PROPERTY_NAME) >>= sName;
+ aColumns.insert(sName);
+ aColumns.insert(pField->GetName());
+ continue;
+ }
+ }
+ else
+ throw;
+ }
+ }
+ else
+ bReload = true;
+ }
+ // alter column settings
+
+ // first look for columns where something other than the name changed
+ for (auto const& row : m_vRowList)
+ {
+ OSL_ENSURE(row,"OTableRow is null!");
+ OFieldDescription* pField = row->GetActFieldDescr();
+ if ( !pField )
+ continue;
+ if ( row->IsReadOnly() )
+ {
+ aColumns.insert(pField->GetName());
+ continue;
+ }
+
+ Reference<XPropertySet> xColumn;
+ if ( xColumns->hasByName(pField->GetName()) )
+ {
+ xColumns->getByName(pField->GetName()) >>= xColumn;
+ Reference<XPropertySetInfo> xInfo = xColumn->getPropertySetInfo();
+ if ( xInfo->hasPropertyByName(PROPERTY_HELPTEXT) )
+ xColumn->setPropertyValue(PROPERTY_HELPTEXT,Any(pField->GetHelpText()));
+
+ if(xInfo->hasPropertyByName(PROPERTY_CONTROLDEFAULT))
+ xColumn->setPropertyValue(PROPERTY_CONTROLDEFAULT,pField->GetControlDefault());
+ if(xInfo->hasPropertyByName(PROPERTY_FORMATKEY))
+ xColumn->setPropertyValue(PROPERTY_FORMATKEY,Any(pField->GetFormatKey()));
+ if(xInfo->hasPropertyByName(PROPERTY_ALIGN))
+ xColumn->setPropertyValue(PROPERTY_ALIGN,Any(dbaui::mapTextAlign(pField->GetHorJustify())));
+ }
+ }
+ // second drop all columns which could be found by name
+ Reference<XNameAccess> xKeyColumns = getKeyColumns();
+ // now we have to look for the columns who could be deleted
+ if ( xDrop.is() )
+ {
+ const Sequence<OUString> aColNames = xColumns->getElementNames();
+ for(const OUString& rColumnName : aColNames)
+ {
+ if(aColumns.find(rColumnName) == aColumns.end()) // found a column to delete
+ {
+ if(xKeyColumns.is() && xKeyColumns->hasByName(rColumnName)) // check if this column is a member of the primary key
+ {
+ OUString aMsgT(DBA_RES(STR_TBL_COLUMN_IS_KEYCOLUMN));
+ aMsgT = aMsgT.replaceFirst("$column$",rColumnName);
+ OUString aTitle(DBA_RES(STR_TBL_COLUMN_IS_KEYCOLUMN_TITLE));
+ OSQLMessageBox aMsg(getFrameWeld(), aTitle, aMsgT, MessBoxStyle::YesNo| MessBoxStyle::DefaultYes);
+ if (aMsg.run() == RET_YES)
+ {
+ xKeyColumns = nullptr;
+ dropPrimaryKey();
+ }
+ else
+ {
+ bReload = true;
+ continue;
+ }
+ }
+ try
+ {
+ xDrop->dropByName(rColumnName);
+ }
+ catch (const SQLException&)
+ {
+ OUString sError( DBA_RES( STR_TABLEDESIGN_COULD_NOT_DROP_COL ) );
+ sError = sError.replaceFirst( "$column$", rColumnName );
+
+ SQLException aNewException;
+ aNewException.Message = sError;
+ aNewException.SQLState = "S1000";
+ aNewException.NextException = ::cppu::getCaughtException();
+
+ throw aNewException;
+ }
+ }
+ }
+ }
+
+ // third append the new columns
+ for(const auto& rxRow : m_vRowList)
+ {
+ OSL_ENSURE(rxRow,"OTableRow is null!");
+ OFieldDescription* pField = rxRow->GetActFieldDescr();
+ if ( !pField || rxRow->IsReadOnly() || aColumns.find(pField->GetName()) != aColumns.end() )
+ continue;
+
+ Reference<XPropertySet> xColumn;
+ if(!xColumns->hasByName(pField->GetName()))
+ {
+ if(xColumnFactory.is() && xAppend.is())
+ {// column not found by its name so we assume it is new
+ // Column is new
+ xColumn = xColumnFactory->createDataDescriptor();
+ ::dbaui::setColumnProperties(xColumn,pField);
+ xAppend->appendByDescriptor(xColumn);
+ if(xColumns->hasByName(pField->GetName()))
+ { // ask for the append by name
+ aColumns.insert(pField->GetName());
+ xColumns->getByName(pField->GetName()) >>= xColumn;
+ if(xColumn.is())
+ pField->copyColumnSettingsTo(xColumn);
+ }
+ else
+ {
+ OSL_FAIL("OTableController::alterColumns: invalid column!");
+ }
+ }
+ }
+ }
+
+ // check if we have to do something with the primary key
+ bool bNeedDropKey = false;
+ bool bNeedAppendKey = false;
+ if ( xKeyColumns.is() )
+ {
+ for(const auto& rxRow : m_vRowList)
+ {
+ OSL_ENSURE(rxRow,"OTableRow is null!");
+ OFieldDescription* pField = rxRow->GetActFieldDescr();
+ if ( !pField )
+ continue;
+
+ if ( pField->IsPrimaryKey()
+ && !xKeyColumns->hasByName( pField->GetName() )
+ )
+ { // new primary key column inserted which isn't already in the columns selection
+ bNeedDropKey = bNeedAppendKey = true;
+ break;
+ }
+ else if ( !pField->IsPrimaryKey()
+ && xKeyColumns->hasByName( pField->GetName() )
+ )
+ { // found a column which currently is in the primary key, but is marked not to be anymore
+ bNeedDropKey = bNeedAppendKey = true;
+ break;
+ }
+ }
+ }
+ else
+ { // no primary key available so we check if we should create one
+ bNeedAppendKey = true;
+ }
+
+ if ( bNeedDropKey && xKeyColumns.is() && xKeyColumns->getElementNames().hasElements() )
+ dropPrimaryKey();
+
+ if ( bNeedAppendKey )
+ {
+ Reference< XKeysSupplier > xKeySup( m_xTable, UNO_QUERY );
+ appendPrimaryKey( xKeySup ,false);
+ }
+
+ reSyncRows();
+
+ if ( bReload )
+ reload();
+}
+
+void OTableController::dropPrimaryKey()
+{
+ SQLExceptionInfo aInfo;
+ try
+ {
+ Reference<XKeysSupplier> xKeySup(m_xTable,UNO_QUERY);
+ Reference<XIndexAccess> xKeys;
+ if(xKeySup.is())
+ xKeys = xKeySup->getKeys();
+
+ if(xKeys.is())
+ {
+ Reference<XPropertySet> xProp;
+ for(sal_Int32 i=0;i< xKeys->getCount();++i)
+ {
+ xProp.set(xKeys->getByIndex(i),UNO_QUERY);
+ sal_Int32 nKeyType = 0;
+ xProp->getPropertyValue(PROPERTY_TYPE) >>= nKeyType;
+ if(KeyType::PRIMARY == nKeyType)
+ {
+ Reference<XDrop> xDrop(xKeys,UNO_QUERY);
+ xDrop->dropByIndex(i); // delete the key
+ break;
+ }
+ }
+ }
+ }
+ catch(const SQLContext& e)
+ {
+ aInfo = SQLExceptionInfo(e);
+ }
+ catch(const SQLWarning& e)
+ {
+ aInfo = SQLExceptionInfo(e);
+ }
+ catch(const SQLException& e)
+ {
+ aInfo = SQLExceptionInfo(e);
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+
+ showError(aInfo);
+}
+
+void OTableController::assignTable()
+{
+ // get the table
+ if(m_sName.isEmpty())
+ return;
+
+ Reference<XNameAccess> xNameAccess;
+ Reference<XTablesSupplier> xSup(getConnection(),UNO_QUERY);
+ if(!xSup.is())
+ return;
+
+ xNameAccess = xSup->getTables();
+ OSL_ENSURE(xNameAccess.is(),"no nameaccess for the queries!");
+
+ if(!xNameAccess->hasByName(m_sName))
+ return;
+
+ Reference<XPropertySet> xProp(xNameAccess->getByName(m_sName), css::uno::UNO_QUERY);
+ if (!xProp.is())
+ return;
+
+ m_xTable = xProp;
+ startTableListening();
+
+ // check if we set the table editable
+ Reference<XDatabaseMetaData> xMeta = getConnection()->getMetaData();
+ setEditable( xMeta.is() && !xMeta->isReadOnly() && (isAlterAllowed() || isDropAllowed() || isAddAllowed()) );
+ if(!isEditable())
+ {
+ for( const auto& rTableRow : m_vRowList )
+ {
+ rTableRow->SetReadOnly();
+ }
+ }
+ m_bNew = false;
+ // be notified when the table is in disposing
+ InvalidateAll();
+}
+
+bool OTableController::isAddAllowed() const
+{
+ Reference<XColumnsSupplier> xColsSup(m_xTable,UNO_QUERY);
+ bool bAddAllowed = !m_xTable.is();
+ if(xColsSup.is())
+ bAddAllowed = Reference<XAppend>(xColsSup->getColumns(),UNO_QUERY).is();
+
+ try
+ {
+ Reference< XDatabaseMetaData > xMetaData = getMetaData( );
+ bAddAllowed = bAddAllowed || ( xMetaData.is() && xMetaData->supportsAlterTableWithAddColumn());
+ }
+ catch(Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ bAddAllowed = false;
+ }
+
+ return bAddAllowed;
+}
+
+bool OTableController::isDropAllowed() const
+{
+ Reference<XColumnsSupplier> xColsSup(m_xTable,UNO_QUERY);
+ bool bDropAllowed = !m_xTable.is();
+ if(xColsSup.is())
+ {
+ Reference<XNameAccess> xNameAccess = xColsSup->getColumns();
+ bDropAllowed = Reference<XDrop>(xNameAccess,UNO_QUERY).is() && xNameAccess->hasElements();
+ }
+
+ Reference< XDatabaseMetaData> xMetaData = getMetaData( );
+ bDropAllowed = bDropAllowed || ( xMetaData.is() && xMetaData->supportsAlterTableWithDropColumn());
+
+ return bDropAllowed;
+}
+
+bool OTableController::isAlterAllowed() const
+{
+ bool bAllowed(!m_xTable.is() || Reference<XAlterTable>(m_xTable,UNO_QUERY).is());
+ return bAllowed;
+}
+
+void OTableController::reSyncRows()
+{
+ bool bAlterAllowed = isAlterAllowed();
+ bool bAddAllowed = isAddAllowed();
+ for (auto const& row : m_vRowList)
+ {
+ OSL_ENSURE(row,"OTableRow is null!");
+ OFieldDescription* pField = row->GetActFieldDescr();
+ if ( pField )
+ row->SetReadOnly(!bAlterAllowed);
+ else
+ row->SetReadOnly(!bAddAllowed);
+
+ }
+ static_cast<OTableDesignView*>(getView())->reSync(); // show the windows and fill with our information
+
+ ClearUndoManager();
+ setModified(false); // and we are not modified yet
+}
+
+OUString OTableController::createUniqueName(const OUString& _rName)
+{
+ OUString sName = _rName;
+ Reference< XDatabaseMetaData> xMetaData = getMetaData( );
+
+ ::comphelper::UStringMixEqual bCase(!xMetaData.is() || xMetaData->supportsMixedCaseQuotedIdentifiers());
+
+ auto lHasName = [&bCase, &sName](const std::shared_ptr<OTableRow>& rxRow) {
+ OFieldDescription* pFieldDesc = rxRow->GetActFieldDescr();
+ return pFieldDesc && !pFieldDesc->GetName().isEmpty() && bCase(sName, pFieldDesc->GetName());
+ };
+
+ sal_Int32 i = 0;
+ while(std::any_of(m_vRowList.begin(), m_vRowList.end(), lHasName))
+ {
+ // found a second name of _rName so we need another
+ sName = _rName + OUString::number(++i);
+ }
+ return sName;
+}
+
+OUString OTableController::getPrivateTitle() const
+{
+ OUString sTitle;
+ try
+ {
+ // get the table
+ if ( !m_sName.isEmpty() && getConnection().is() )
+ {
+ if ( m_xTable.is() )
+ sTitle = ::dbtools::composeTableName( getConnection()->getMetaData(), m_xTable, ::dbtools::EComposeRule::InDataManipulation, false );
+ else
+ sTitle = m_sName;
+ }
+ if ( sTitle.isEmpty() )
+ {
+ OUString aName = DBA_RES(STR_TBL_TITLE);
+ sTitle = o3tl::getToken(aName,0,' ') + OUString::number(getCurrentStartNumber());
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ return sTitle;
+}
+
+void OTableController::reload()
+{
+ loadData(); // fill the column information from the table
+ static_cast<OTableDesignView*>(getView())->reSync(); // show the windows and fill with our information
+ ClearUndoManager();
+ setModified(false); // and we are not modified yet
+ static_cast<OTableDesignView*>(getView())->Invalidate();
+}
+
+sal_Int32 OTableController::getFirstEmptyRowPosition()
+{
+ sal_Int32 nRet = 0;
+ bool bFoundElem = false;
+ for (auto const& row : m_vRowList)
+ {
+ if ( !row || !row->GetActFieldDescr() || row->GetActFieldDescr()->GetName().isEmpty() )
+ {
+ bFoundElem = true;
+ break;
+ }
+ ++nRet;
+ }
+ if (!bFoundElem)
+ {
+ bool bReadRow = !isAddAllowed();
+ auto pTabEdRow = std::make_shared<OTableRow>();
+ pTabEdRow->SetReadOnly(bReadRow);
+ nRet = m_vRowList.size();
+ m_vRowList.push_back( pTabEdRow);
+ }
+ return nRet;
+}
+
+bool OTableController::isAutoIncrementPrimaryKey() const
+{
+ return getSdbMetaData().isAutoIncrementPrimaryKey();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/tabledesign/TableDesignControl.cxx b/dbaccess/source/ui/tabledesign/TableDesignControl.cxx
new file mode 100644
index 000000000..1526682ed
--- /dev/null
+++ b/dbaccess/source/ui/tabledesign/TableDesignControl.cxx
@@ -0,0 +1,172 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <TableDesignControl.hxx>
+#include <TableDesignView.hxx>
+#include <TableController.hxx>
+#include <com/sun/star/util/URL.hpp>
+#include <com/sun/star/beans/PropertyValue.hpp>
+#include <vcl/commandevent.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/weldutils.hxx>
+#include <helpids.h>
+
+using namespace ::dbaui;
+using namespace ::svt;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::util;
+// Defines
+#define HANDLE_ID 0
+
+OTableRowView::OTableRowView(vcl::Window* pParent)
+ : EditBrowseBox(pParent, EditBrowseBoxFlags::NONE, WB_TABSTOP|WB_HIDE|WB_3DLOOK,
+ BrowserMode::COLUMNSELECTION | BrowserMode::MULTISELECTION |
+ BrowserMode::AUTOSIZE_LASTCOL | BrowserMode::KEEPHIGHLIGHT |
+ BrowserMode::HLINES | BrowserMode::VLINES)
+ , m_nDataPos(-1)
+ , m_nCurrentPos(-1)
+ , m_nCurUndoActId(0)
+{
+ SetHelpId(HID_TABDESIGN_BACKGROUND);
+ SetSizePixel(LogicToPixel(Size(40, 12), MapMode(MapUnit::MapAppFont)));
+}
+
+void OTableRowView::Init()
+{
+ EditBrowseBox::Init();
+
+ vcl::Font aFont( GetDataWindow().GetFont() );
+ aFont.SetWeight( WEIGHT_NORMAL );
+ GetDataWindow().SetFont( aFont );
+
+ // set font for the headings to light
+ aFont = GetFont();
+ aFont.SetWeight( WEIGHT_LIGHT );
+ SetFont(aFont);
+
+ // set up HandleColumn for at maximum 5 digits
+ InsertHandleColumn(static_cast<sal_uInt16>(GetTextWidth(OUString('0')) * 4)/*, sal_True */);
+
+ BrowserMode const nMode = BrowserMode::COLUMNSELECTION | BrowserMode::MULTISELECTION | BrowserMode::KEEPHIGHLIGHT |
+ BrowserMode::HLINES | BrowserMode::VLINES | BrowserMode::AUTOSIZE_LASTCOL;
+
+ SetMode(nMode);
+}
+
+void OTableRowView::KeyInput( const KeyEvent& rEvt )
+{
+ if (IsDeleteAllowed())
+ {
+ if (rEvt.GetKeyCode().GetCode() == KEY_DELETE && // Delete rows
+ !rEvt.GetKeyCode().IsShift() &&
+ !rEvt.GetKeyCode().IsMod1())
+ {
+ DeleteRows();
+ return;
+ }
+ if( rEvt.GetKeyCode().GetCode() == KEY_F2 )
+ {
+ css::util::URL aUrl;
+ aUrl.Complete = ".uno:DSBEditDoc";
+ GetView()->getController().dispatch( aUrl,Sequence< PropertyValue >() );
+ }
+ }
+ EditBrowseBox::KeyInput(rEvt);
+}
+
+void OTableRowView::Command(const CommandEvent& rEvt)
+{
+
+ switch (rEvt.GetCommand())
+ {
+ case CommandEventId::ContextMenu:
+ {
+ if (!rEvt.IsMouseEvent())
+ {
+ EditBrowseBox::Command(rEvt);
+ return;
+ }
+
+ sal_uInt16 nColId = GetColumnId(GetColumnAtXPosPixel(rEvt.GetMousePosPixel().X()));
+ sal_Int32 nRow = GetRowAtYPosPixel(rEvt.GetMousePosPixel().Y());
+
+ if ( nColId == HANDLE_ID )
+ {
+ ::tools::Rectangle aRect(rEvt.GetMousePosPixel(), Size(1, 1));
+ weld::Window* pPopupParent = weld::GetPopupParent(*this, aRect);
+ std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(pPopupParent, "dbaccess/ui/tabledesignrowmenu.ui"));
+ std::unique_ptr<weld::Menu> xContextMenu(xBuilder->weld_menu("menu"));
+ sal_Int32 nSelectRowCount = GetSelectRowCount();
+ xContextMenu->set_sensitive("cut", nSelectRowCount != 0);
+ xContextMenu->set_sensitive("copy", nSelectRowCount != 0);
+ OString sIdent = xContextMenu->popup_at_rect(pPopupParent, aRect);
+ if (sIdent == "cut")
+ cut();
+ else if (sIdent == "copy")
+ copy();
+ else if (sIdent == "insert")
+ {
+ InsertNewRows( nRow );
+ SetNoSelection();
+ GoToRow( nRow );
+ SeekRow( nRow );
+ }
+
+ return;
+ }
+
+ [[fallthrough]];
+ }
+ default:
+ EditBrowseBox::Command(rEvt);
+ }
+
+}
+
+void OTableRowView::cut()
+{
+ CopyRows();
+ DeleteRows();
+}
+
+void OTableRowView::copy()
+{
+ CopyRows();
+}
+
+void OTableRowView::paste()
+{
+ OSL_FAIL("OTableRowView::Paste : (pseudo-) abstract method called !");
+}
+
+void OTableRowView::Paste( sal_Int32 nRow )
+{
+ InsertRows( nRow );
+}
+
+EditBrowseBox::RowStatus OTableRowView::GetRowStatus(sal_Int32 nRow) const
+{
+ if (nRow >= 0 && m_nDataPos == nRow)
+ return CURRENT;
+ else
+ return CLEAN;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/tabledesign/TableDesignHelpBar.cxx b/dbaccess/source/ui/tabledesign/TableDesignHelpBar.cxx
new file mode 100644
index 000000000..f81123e55
--- /dev/null
+++ b/dbaccess/source/ui/tabledesign/TableDesignHelpBar.cxx
@@ -0,0 +1,62 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <TableDesignHelpBar.hxx>
+#include <helpids.h>
+
+using namespace dbaui;
+
+#define DETAILS_MIN_HELP_WIDTH 200
+
+OTableDesignHelpBar::OTableDesignHelpBar(std::unique_ptr<weld::TextView> xTextWin)
+ : m_xTextWin(std::move(xTextWin))
+{
+ m_xTextWin->set_size_request(DETAILS_MIN_HELP_WIDTH, -1);
+ m_xTextWin->set_help_id(HID_TAB_DESIGN_HELP_TEXT_FRAME);
+}
+
+void OTableDesignHelpBar::SetHelpText(const OUString& rText)
+{
+ if (!m_xTextWin)
+ return;
+ m_xTextWin->set_text(rText);
+}
+
+bool OTableDesignHelpBar::isCopyAllowed()
+{
+ int mStartPos, nEndPos;
+ return m_xTextWin && m_xTextWin->get_selection_bounds(mStartPos, nEndPos);
+}
+
+bool OTableDesignHelpBar::isCutAllowed() { return false; }
+
+bool OTableDesignHelpBar::isPasteAllowed() { return false; }
+
+void OTableDesignHelpBar::cut() {}
+
+void OTableDesignHelpBar::copy()
+{
+ if (!m_xTextWin)
+ return;
+ m_xTextWin->copy_clipboard();
+}
+
+void OTableDesignHelpBar::paste() {}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/tabledesign/TableDesignView.cxx b/dbaccess/source/ui/tabledesign/TableDesignView.cxx
new file mode 100644
index 000000000..f0570ddba
--- /dev/null
+++ b/dbaccess/source/ui/tabledesign/TableDesignView.cxx
@@ -0,0 +1,260 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <TableDesignView.hxx>
+#include <TableController.hxx>
+#include <helpids.h>
+#include <FieldDescriptions.hxx>
+#include "TEditControl.hxx"
+#include "TableFieldDescWin.hxx"
+#include <TableRow.hxx>
+#include <i18nlangtag/languagetag.hxx>
+#include <toolkit/helper/vclunohelper.hxx>
+#include <unotools/syslocale.hxx>
+#include <memory>
+
+using namespace ::dbaui;
+using namespace ::utl;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::datatransfer::clipboard;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::beans;
+
+OTableBorderWindow::OTableBorderWindow(OTableDesignView* pParent)
+ : InterimItemWindow(pParent, "dbaccess/ui/tableborderwindow.ui", "TableBorderWindow", false)
+ , m_xHorzSplitter(m_xBuilder->weld_paned("splitter"))
+ , m_xEditorParent(m_xBuilder->weld_container("editor"))
+ , m_xEditorParentWin(m_xEditorParent->CreateChildFrame())
+ , m_xEditorCtrl(VclPtr<OTableEditorCtrl>::Create(VCLUnoHelper::GetWindow(m_xEditorParentWin), pParent))
+ , m_xFieldDescParent(m_xBuilder->weld_container("fielddesc"))
+ , m_xFieldDescWin(new OTableFieldDescWin(m_xFieldDescParent.get(), pParent))
+{
+ SetStyle(GetStyle() | WB_DIALOGCONTROL);
+
+ m_xFieldDescWin->SetHelpId(HID_TAB_DESIGN_DESCWIN);
+
+ // set depending windows and controls
+ m_xEditorCtrl->SetDescrWin(m_xFieldDescWin.get());
+}
+
+OTableBorderWindow::~OTableBorderWindow()
+{
+ disposeOnce();
+}
+
+void OTableBorderWindow::dispose()
+{
+ // destroy children
+ m_xEditorCtrl.disposeAndClear();
+ m_xEditorParentWin->dispose();
+ m_xEditorParentWin.clear();
+ m_xEditorParent.reset();
+ m_xFieldDescWin.reset();
+ m_xFieldDescParent.reset();
+ m_xHorzSplitter.reset();
+ InterimItemWindow::dispose();
+}
+
+void OTableBorderWindow::Layout()
+{
+ // dimensions of parent window
+ auto nOutputHeight = GetSizePixel().Height();
+ auto nOldSplitPos = m_xHorzSplitter->get_position();
+ auto nSplitPos = nOldSplitPos;
+
+ // shift range of the splitter is the middle third of the output
+ auto nDragPosY = nOutputHeight/3;
+ auto nDragSizeHeight = nOutputHeight/3;
+ if (nSplitPos < nDragPosY || nSplitPos > nDragPosY + nDragSizeHeight)
+ nSplitPos = nDragPosY + nDragSizeHeight;
+
+ // set splitter
+ m_xHorzSplitter->set_position(nSplitPos);
+
+ InterimItemWindow::Layout();
+
+ if (nOldSplitPos != nSplitPos)
+ m_xHorzSplitter->set_position(nSplitPos);
+}
+
+void OTableBorderWindow::GetFocus()
+{
+ InterimItemWindow::GetFocus();
+
+ // forward the focus to the current cell of the editor control
+ if (m_xEditorCtrl)
+ m_xEditorCtrl->GrabFocus();
+}
+
+OTableDesignView::OTableDesignView( vcl::Window* pParent,
+ const Reference< XComponentContext >& _rxOrb,
+ OTableController& _rController
+ ) :
+ ODataView( pParent, _rController,_rxOrb )
+ ,m_rController( _rController )
+ ,m_eChildFocus(NONE)
+{
+
+ try
+ {
+ m_aLocale = SvtSysLocale().GetLanguageTag().getLocale();
+ }
+ catch(Exception&)
+ {
+ }
+
+ m_pWin = VclPtr<OTableBorderWindow>::Create(this);
+
+ m_pWin->GetDescWin()->connect_focus_in(LINK(this, OTableDesignView, FieldDescFocusIn));
+
+ m_pWin->Show();
+}
+
+OTableDesignView::~OTableDesignView()
+{
+ disposeOnce();
+}
+
+void OTableDesignView::dispose()
+{
+ m_pWin->Hide();
+ m_pWin.disposeAndClear();
+ ODataView::dispose();
+}
+
+void OTableDesignView::initialize()
+{
+ GetEditorCtrl()->Init();
+ GetDescWin()->Init();
+ // first call after the editctrl has been set
+
+ GetEditorCtrl()->Show();
+ GetDescWin()->Show();
+
+ GetEditorCtrl()->DisplayData(0);
+}
+
+void OTableDesignView::resizeDocumentView(tools::Rectangle& _rPlayground)
+{
+ m_pWin->SetPosSizePixel( _rPlayground.TopLeft(), _rPlayground.GetSize() );
+
+ // just for completeness: there is no space left, we occupied it all ...
+ _rPlayground.SetPos( _rPlayground.BottomRight() );
+ _rPlayground.SetSize( Size( 0, 0 ) );
+}
+
+IMPL_LINK_NOARG(OTableDesignView, FieldDescFocusIn, weld::Widget&, void)
+{
+ m_eChildFocus = DESCRIPTION;
+}
+
+bool OTableDesignView::PreNotify( NotifyEvent& rNEvt )
+{
+ if (rNEvt.GetType() == MouseNotifyEvent::GETFOCUS)
+ {
+ if( GetDescWin() && GetDescWin()->HasChildPathFocus() )
+ m_eChildFocus = DESCRIPTION;
+ else if ( GetEditorCtrl() && GetEditorCtrl()->HasChildPathFocus() )
+ m_eChildFocus = EDITOR;
+ else
+ m_eChildFocus = NONE;
+ }
+
+ return ODataView::PreNotify(rNEvt);
+}
+
+IClipboardTest* OTableDesignView::getActiveChild() const
+{
+ IClipboardTest* pTest = nullptr;
+ switch(m_eChildFocus)
+ {
+ case DESCRIPTION:
+ pTest = GetDescWin();
+ break;
+ case EDITOR:
+ pTest = GetEditorCtrl();
+ break;
+ case NONE:
+ break;
+ }
+ return pTest;
+}
+
+bool OTableDesignView::isCopyAllowed()
+{
+ IClipboardTest* pTest = getActiveChild();
+ return pTest && pTest->isCopyAllowed();
+}
+
+bool OTableDesignView::isCutAllowed()
+{
+ IClipboardTest* pTest = getActiveChild();
+ return pTest && pTest->isCutAllowed();
+}
+
+bool OTableDesignView::isPasteAllowed()
+{
+ IClipboardTest* pTest = getActiveChild();
+ return pTest && pTest->isPasteAllowed();
+}
+
+void OTableDesignView::copy()
+{
+ IClipboardTest* pTest = getActiveChild();
+ if ( pTest )
+ pTest->copy();
+}
+
+void OTableDesignView::cut()
+{
+ IClipboardTest* pTest = getActiveChild();
+ if ( pTest )
+ pTest->cut();
+}
+
+void OTableDesignView::paste()
+{
+ IClipboardTest* pTest = getActiveChild();
+ if ( pTest )
+ pTest->paste();
+}
+
+// set the view readonly or not
+void OTableDesignView::setReadOnly(bool _bReadOnly)
+{
+ GetDescWin()->SetReadOnly(_bReadOnly);
+ GetEditorCtrl()->SetReadOnly(_bReadOnly);
+}
+
+void OTableDesignView::reSync()
+{
+ GetEditorCtrl()->DeactivateCell();
+ std::shared_ptr<OTableRow> pRow = (*GetEditorCtrl()->GetRowList())[GetEditorCtrl()->GetCurRow()];
+ OFieldDescription* pFieldDescr = pRow ? pRow->GetActFieldDescr() : nullptr;
+ if ( pFieldDescr )
+ GetDescWin()->DisplayData(pFieldDescr);
+}
+
+void OTableDesignView::GetFocus()
+{
+ if ( GetEditorCtrl() )
+ GetEditorCtrl()->GrabFocus();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/tabledesign/TableFieldControl.cxx b/dbaccess/source/ui/tabledesign/TableFieldControl.cxx
new file mode 100644
index 000000000..aa04b914a
--- /dev/null
+++ b/dbaccess/source/ui/tabledesign/TableFieldControl.cxx
@@ -0,0 +1,154 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "TableFieldControl.hxx"
+#include <TableController.hxx>
+#include <TableDesignView.hxx>
+#include "TEditControl.hxx"
+#include <strings.hxx>
+#include <com/sun/star/sdbc/XDatabaseMetaData.hpp>
+#include <comphelper/types.hxx>
+#include <TypeInfo.hxx>
+
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::util;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::sdbc;
+using namespace dbaui;
+
+OTableFieldControl::OTableFieldControl(weld::Container* pParent, OTableDesignHelpBar* pHelpBar, OTableDesignView* pView)
+ : OFieldDescControl(pParent, pHelpBar)
+ , m_xView(pView)
+{
+}
+
+void OTableFieldControl::dispose()
+{
+ m_xView.clear();
+}
+
+OTableFieldControl::~OTableFieldControl()
+{
+ dispose();
+}
+
+void OTableFieldControl::CellModified(sal_Int32 nRow, sal_uInt16 nColId )
+{
+ GetCtrl()->CellModified(nRow,nColId);
+}
+
+OTableEditorCtrl* OTableFieldControl::GetCtrl() const
+{
+ assert(m_xView && "no view!");
+ return m_xView->GetEditorCtrl();
+}
+
+bool OTableFieldControl::IsReadOnly()
+{
+ bool bRead(GetCtrl()->IsReadOnly());
+ if( !bRead )
+ {
+ // The columns of a css::sdbcx::View could not be locked
+ Reference<XPropertySet> xTable = GetCtrl()->GetView()->getController().getTable();
+ if(xTable.is() && ::comphelper::getString(xTable->getPropertyValue(PROPERTY_TYPE)) == "VIEW")
+ bRead = true;
+ else
+ {
+ std::shared_ptr<OTableRow> pCurRow = GetCtrl()->GetActRow();
+ if( pCurRow )
+ bRead = pCurRow->IsReadOnly();
+ }
+ }
+ return bRead;
+}
+
+void OTableFieldControl::ActivateAggregate( EControlType eType )
+{
+ switch(eType)
+ {
+ case tpColumnName:
+ case tpType:
+ break;
+ default:
+ OFieldDescControl::ActivateAggregate(eType);
+ }
+}
+
+void OTableFieldControl::DeactivateAggregate( EControlType eType )
+{
+ switch(eType)
+ {
+ case tpColumnName:
+ case tpType:
+ break;
+ default:
+ OFieldDescControl::DeactivateAggregate(eType);
+ }
+}
+
+void OTableFieldControl::SetModified(bool bModified)
+{
+ GetCtrl()->GetView()->getController().setModified(bModified);
+}
+
+css::uno::Reference< css::sdbc::XConnection> OTableFieldControl::getConnection()
+{
+ return GetCtrl()->GetView()->getController().getConnection();
+}
+
+css::uno::Reference< css::sdbc::XDatabaseMetaData> OTableFieldControl::getMetaData()
+{
+ Reference<XConnection> xCon = GetCtrl()->GetView()->getController().getConnection();
+ if(!xCon.is())
+ return nullptr;
+ return xCon->getMetaData();
+}
+
+Reference< XNumberFormatter > OTableFieldControl::GetFormatter() const
+{
+ return GetCtrl()->GetView()->getController().getNumberFormatter();
+}
+
+TOTypeInfoSP OTableFieldControl::getTypeInfo(sal_Int32 _nPos)
+{
+ return GetCtrl()->GetView()->getController().getTypeInfo(_nPos);
+}
+
+const OTypeInfoMap* OTableFieldControl::getTypeInfo() const
+{
+ return &GetCtrl()->GetView()->getController().getTypeInfo();
+}
+
+Locale OTableFieldControl::GetLocale() const
+{
+ return GetCtrl()->GetView()->getLocale();
+}
+
+bool OTableFieldControl::isAutoIncrementValueEnabled() const
+{
+ return GetCtrl()->GetView()->getController().isAutoIncrementValueEnabled();
+}
+
+OUString OTableFieldControl::getAutoIncrementValue() const
+{
+ return GetCtrl()->GetView()->getController().getAutoIncrementValue();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/tabledesign/TableFieldControl.hxx b/dbaccess/source/ui/tabledesign/TableFieldControl.hxx
new file mode 100644
index 000000000..4a232f86c
--- /dev/null
+++ b/dbaccess/source/ui/tabledesign/TableFieldControl.hxx
@@ -0,0 +1,66 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <FieldDescControl.hxx>
+
+namespace dbaui
+{
+ class OTableEditorCtrl;
+ class OTableDesignHelpBar;
+ class OTableDesignView;
+
+ // OTableFieldControl
+ class OTableFieldControl : public OFieldDescControl
+ {
+ VclPtr<OTableDesignView> m_xView;
+
+ OTableEditorCtrl* GetCtrl() const;
+
+ void dispose();
+
+ protected:
+ virtual void ActivateAggregate( EControlType eType ) override;
+ virtual void DeactivateAggregate( EControlType eType ) override;
+ // are to be implemented by the derived classes
+ virtual void CellModified(sal_Int32 nRow, sal_uInt16 nColId ) override;
+ virtual bool IsReadOnly() override;
+ virtual void SetModified(bool bModified) override;
+ virtual css::uno::Reference< css::util::XNumberFormatter > GetFormatter() const override;
+
+ virtual css::lang::Locale GetLocale() const override;
+
+ virtual TOTypeInfoSP getTypeInfo(sal_Int32 _nPos) override;
+ virtual const OTypeInfoMap* getTypeInfo() const override;
+ virtual bool isAutoIncrementValueEnabled() const override;
+ virtual OUString getAutoIncrementValue() const override;
+
+ public:
+ OTableFieldControl(weld::Container* pParent, OTableDesignHelpBar* pHelpBar, OTableDesignView* pView);
+ virtual ~OTableFieldControl() override;
+
+ using OFieldDescControl::BoolStringPersistent;
+ using OFieldDescControl::BoolStringUI;
+
+ virtual css::uno::Reference< css::sdbc::XDatabaseMetaData> getMetaData() override;
+ virtual css::uno::Reference< css::sdbc::XConnection> getConnection() override;
+ };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/tabledesign/TableFieldDescWin.cxx b/dbaccess/source/ui/tabledesign/TableFieldDescWin.cxx
new file mode 100644
index 000000000..7e6c4f111
--- /dev/null
+++ b/dbaccess/source/ui/tabledesign/TableFieldDescWin.cxx
@@ -0,0 +1,140 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "TableFieldDescWin.hxx"
+#include <FieldDescriptions.hxx>
+#include <strings.hrc>
+#include <TableDesignHelpBar.hxx>
+#include <helpids.h>
+#include <core_resource.hxx>
+
+using namespace dbaui;
+
+OTableFieldDescWin::OTableFieldDescWin(weld::Container* pParent, OTableDesignView* pView)
+ : OChildWindow(pParent, "dbaccess/ui/fielddescpanel.ui", "FieldDescPanel")
+ , m_xHelpBar(new OTableDesignHelpBar(m_xBuilder->weld_text_view("textview")))
+ , m_xBox(m_xBuilder->weld_container("box"))
+ , m_xFieldControl(new OTableFieldControl(m_xBox.get(), m_xHelpBar.get(), pView))
+ , m_xHeader(m_xBuilder->weld_label("header"))
+ , m_eChildFocus(NONE)
+{
+ // Header
+ m_xHeader->set_label(DBA_RES(STR_TAB_PROPERTIES));
+
+ m_xFieldControl->SetHelpId(HID_TAB_DESIGN_FIELDCONTROL);
+
+ m_xHelpBar->connect_focus_in(LINK(this, OTableFieldDescWin, HelpFocusIn));
+ m_xFieldControl->connect_focus_in(LINK(this, OTableFieldDescWin, FieldFocusIn));
+}
+
+bool OTableFieldDescWin::HasChildPathFocus() const
+{
+ return m_xFieldControl->HasChildPathFocus() || m_xHelpBar->HasFocus();
+}
+
+OTableFieldDescWin::~OTableFieldDescWin()
+{
+}
+
+void OTableFieldDescWin::Init()
+{
+ m_xFieldControl->Init();
+}
+
+void OTableFieldDescWin::SetReadOnly( bool bRead )
+{
+ m_xFieldControl->SetReadOnly( bRead );
+}
+
+void OTableFieldDescWin::DisplayData( OFieldDescription* pFieldDescr )
+{
+ m_xFieldControl->DisplayData( pFieldDescr );
+}
+
+void OTableFieldDescWin::SaveData( OFieldDescription* pFieldDescr )
+{
+ m_xFieldControl->SaveData( pFieldDescr );
+}
+
+IClipboardTest* OTableFieldDescWin::getActiveChild() const
+{
+ IClipboardTest* pTest = nullptr;
+ switch(m_eChildFocus)
+ {
+ case DESCRIPTION:
+ pTest = m_xFieldControl.get();
+ break;
+ default:
+ pTest = m_xHelpBar.get();
+ break;
+ }
+ return pTest;
+}
+
+bool OTableFieldDescWin::isCopyAllowed()
+{
+ return getActiveChild() && getActiveChild()->isCopyAllowed();
+}
+
+bool OTableFieldDescWin::isCutAllowed()
+{
+ return getActiveChild() && getActiveChild()->isCutAllowed();
+}
+
+bool OTableFieldDescWin::isPasteAllowed()
+{
+ return getActiveChild() && getActiveChild()->isPasteAllowed();
+}
+
+void OTableFieldDescWin::cut()
+{
+ if (getActiveChild())
+ getActiveChild()->cut();
+}
+
+void OTableFieldDescWin::copy()
+{
+ if ( getActiveChild() )
+ getActiveChild()->copy();
+}
+
+void OTableFieldDescWin::paste()
+{
+ if (getActiveChild())
+ getActiveChild()->paste();
+}
+
+void OTableFieldDescWin::GrabFocus()
+{
+ m_xFieldControl->GrabFocus();
+}
+
+IMPL_LINK(OTableFieldDescWin, HelpFocusIn, weld::Widget&, rWidget, void)
+{
+ m_eChildFocus = HELP;
+ m_aFocusInHdl.Call(rWidget);
+}
+
+IMPL_LINK(OTableFieldDescWin, FieldFocusIn, weld::Widget&, rWidget, void)
+{
+ m_eChildFocus = DESCRIPTION;
+ m_aFocusInHdl.Call(rWidget);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/tabledesign/TableFieldDescWin.hxx b/dbaccess/source/ui/tabledesign/TableFieldDescWin.hxx
new file mode 100644
index 000000000..9f15c1e1b
--- /dev/null
+++ b/dbaccess/source/ui/tabledesign/TableFieldDescWin.hxx
@@ -0,0 +1,91 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <IClipBoardTest.hxx>
+#include <ChildWindow.hxx>
+#include "TableFieldControl.hxx"
+
+namespace dbaui
+{
+ class OTableDesignHelpBar;
+ class OTableDesignView;
+ class OFieldDescription;
+
+ class OTableFieldDescWin final : public OChildWindow
+ , public IClipboardTest
+ {
+ enum ChildFocusState
+ {
+ DESCRIPTION,
+ HELP,
+ NONE
+ };
+ private:
+ std::unique_ptr<OTableDesignHelpBar> m_xHelpBar;
+ std::unique_ptr<weld::Container> m_xBox;
+ std::unique_ptr<OTableFieldControl> m_xFieldControl;
+ std::unique_ptr<weld::Label> m_xHeader;
+ Link<weld::Widget&, void> m_aFocusInHdl;
+
+ ChildFocusState m_eChildFocus;
+
+ IClipboardTest* getActiveChild() const;
+
+ DECL_LINK(HelpFocusIn, weld::Widget&, void);
+ DECL_LINK(FieldFocusIn, weld::Widget&, void);
+
+ public:
+ explicit OTableFieldDescWin(weld::Container* pParent, OTableDesignView* pView);
+ virtual ~OTableFieldDescWin() override;
+
+ void Init();
+
+ void DisplayData( OFieldDescription* pFieldDescr );
+ void SaveData( OFieldDescription* pFieldDescr );
+ void SetReadOnly( bool bReadOnly );
+
+ void SetControlText( sal_uInt16 nControlId, const OUString& rText )
+ { m_xFieldControl->SetControlText(nControlId,rText); }
+
+ OUString BoolStringPersistent(std::u16string_view rUIString) const { return m_xFieldControl->BoolStringPersistent(rUIString); }
+ OUString BoolStringUI(const OUString& rPersistentString) const { return m_xFieldControl->BoolStringUI(rPersistentString); }
+
+ virtual bool HasChildPathFocus() const override;
+ virtual void GrabFocus() override;
+
+ // IClipboardTest
+ virtual bool isCutAllowed() override;
+ virtual bool isCopyAllowed() override;
+ virtual bool isPasteAllowed() override;
+
+ virtual void copy() override;
+ virtual void cut() override;
+ virtual void paste() override;
+
+ void connect_focus_in(const Link<weld::Widget&, void>& rLink)
+ {
+ m_aFocusInHdl = rLink;
+ }
+
+ OTableFieldControl* getGenPage() const { return m_xFieldControl.get(); }
+ };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/tabledesign/TableRow.cxx b/dbaccess/source/ui/tabledesign/TableRow.cxx
new file mode 100644
index 000000000..8f13193e1
--- /dev/null
+++ b/dbaccess/source/ui/tabledesign/TableRow.cxx
@@ -0,0 +1,183 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <TableRow.hxx>
+#include <tools/stream.hxx>
+#include <FieldDescriptions.hxx>
+#include <comphelper/types.hxx>
+
+using namespace dbaui;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::beans;
+
+OTableRow::OTableRow()
+ :m_pActFieldDescr( nullptr )
+ ,m_nPos( -1 )
+ ,m_bReadOnly( false )
+ ,m_bOwnsDescriptions(false)
+{
+}
+
+OTableRow::OTableRow( const OTableRow& rRow, tools::Long nPosition )
+ :m_pActFieldDescr(nullptr)
+ ,m_nPos( nPosition )
+ ,m_bReadOnly(rRow.IsReadOnly())
+ ,m_bOwnsDescriptions(false)
+{
+
+ OFieldDescription* pSrcField = rRow.GetActFieldDescr();
+ if(pSrcField)
+ {
+ m_pActFieldDescr = new OFieldDescription(*pSrcField);
+ m_bOwnsDescriptions = true;
+ }
+}
+
+OTableRow::~OTableRow()
+{
+ if(m_bOwnsDescriptions)
+ delete m_pActFieldDescr;
+}
+
+void OTableRow::SetPrimaryKey( bool bSet )
+{
+ if(m_pActFieldDescr)
+ m_pActFieldDescr->SetPrimaryKey(bSet);
+}
+
+bool OTableRow::IsPrimaryKey() const
+{
+ return m_pActFieldDescr && m_pActFieldDescr->IsPrimaryKey();
+}
+
+void OTableRow::SetFieldType( const TOTypeInfoSP& _pType, bool _bForce )
+{
+ if ( _pType )
+ {
+ if( !m_pActFieldDescr )
+ {
+ m_pActFieldDescr = new OFieldDescription();
+ m_bOwnsDescriptions = true;
+ }
+ m_pActFieldDescr->FillFromTypeInfo(_pType,_bForce,true);
+ }
+ else
+ {
+ delete m_pActFieldDescr;
+ m_pActFieldDescr = nullptr;
+ }
+}
+
+namespace dbaui
+{
+ SvStream& WriteOTableRow( SvStream& _rStr, const OTableRow& _rRow )
+ {
+ _rStr.WriteInt32( _rRow.m_nPos );
+ OFieldDescription* pFieldDesc = _rRow.GetActFieldDescr();
+ if(pFieldDesc)
+ {
+ _rStr.WriteInt32( 1 );
+ _rStr.WriteUniOrByteString(pFieldDesc->GetName(), _rStr.GetStreamCharSet());
+ _rStr.WriteUniOrByteString(pFieldDesc->GetDescription(), _rStr.GetStreamCharSet());
+ _rStr.WriteUniOrByteString(pFieldDesc->GetHelpText(), _rStr.GetStreamCharSet());
+ double nValue = 0.0;
+ Any aValue = pFieldDesc->GetControlDefault();
+ if ( aValue >>= nValue )
+ {
+ _rStr.WriteInt32( 1 );
+ _rStr.WriteDouble( nValue );
+ }
+ else
+ {
+ _rStr.WriteInt32( 2 );
+ _rStr.WriteUniOrByteString(::comphelper::getString(aValue), _rStr.GetStreamCharSet());
+ }
+
+ _rStr.WriteInt32( pFieldDesc->GetType() );
+
+ _rStr.WriteInt32( pFieldDesc->GetPrecision() );
+ _rStr.WriteInt32( pFieldDesc->GetScale() );
+ _rStr.WriteInt32( pFieldDesc->GetIsNullable() );
+ _rStr.WriteInt32( pFieldDesc->GetFormatKey() );
+ _rStr.WriteInt32( static_cast<sal_Int32>(pFieldDesc->GetHorJustify()) );
+ _rStr.WriteInt32( pFieldDesc->IsAutoIncrement() ? 1 : 0 );
+ _rStr.WriteInt32( pFieldDesc->IsPrimaryKey() ? 1 : 0 );
+ _rStr.WriteInt32( pFieldDesc->IsCurrency() ? 1 : 0 );
+ }
+ else
+ _rStr.WriteInt32( 0 );
+ return _rStr;
+ }
+ SvStream& ReadOTableRow( SvStream& _rStr, OTableRow& _rRow )
+ {
+ _rStr.ReadInt32( _rRow.m_nPos );
+ sal_Int32 nValue = 0;
+ _rStr.ReadInt32( nValue );
+ if ( !nValue )
+ return _rStr;
+ OFieldDescription* pFieldDesc = new OFieldDescription();
+ _rRow.m_pActFieldDescr = pFieldDesc;
+ pFieldDesc->SetName(_rStr.ReadUniOrByteString(_rStr.GetStreamCharSet()));
+ pFieldDesc->SetDescription(_rStr.ReadUniOrByteString(_rStr.GetStreamCharSet()));
+ pFieldDesc->SetHelpText(_rStr.ReadUniOrByteString(_rStr.GetStreamCharSet()));
+
+ _rStr.ReadInt32( nValue );
+ Any aControlDefault;
+ switch ( nValue )
+ {
+ case 1:
+ {
+ double nControlDefault;
+ _rStr.ReadDouble( nControlDefault );
+ aControlDefault <<= nControlDefault;
+ break;
+ }
+ case 2:
+ aControlDefault <<= _rStr.ReadUniOrByteString(_rStr.GetStreamCharSet());
+ break;
+ }
+
+ pFieldDesc->SetControlDefault(aControlDefault);
+
+ _rStr.ReadInt32( nValue );
+ pFieldDesc->SetTypeValue(nValue);
+
+ _rStr.ReadInt32( nValue );
+ pFieldDesc->SetPrecision(nValue);
+ _rStr.ReadInt32( nValue );
+ pFieldDesc->SetScale(nValue);
+ _rStr.ReadInt32( nValue );
+ pFieldDesc->SetIsNullable(nValue);
+ _rStr.ReadInt32( nValue );
+ pFieldDesc->SetFormatKey(nValue);
+ _rStr.ReadInt32( nValue );
+ pFieldDesc->SetHorJustify(static_cast<SvxCellHorJustify>(nValue));
+
+ _rStr.ReadInt32( nValue );
+ pFieldDesc->SetAutoIncrement(nValue != 0);
+ _rStr.ReadInt32( nValue );
+ pFieldDesc->SetPrimaryKey(nValue != 0);
+ _rStr.ReadInt32( nValue );
+ pFieldDesc->SetCurrency(nValue != 0);
+ return _rStr;
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/tabledesign/TableRowExchange.cxx b/dbaccess/source/ui/tabledesign/TableRowExchange.cxx
new file mode 100644
index 000000000..c56450ac1
--- /dev/null
+++ b/dbaccess/source/ui/tabledesign/TableRowExchange.cxx
@@ -0,0 +1,67 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <TableRowExchange.hxx>
+#include <sot/formats.hxx>
+#include <sot/storage.hxx>
+#include <TableRow.hxx>
+
+namespace dbaui
+{
+ constexpr sal_uInt32 FORMAT_OBJECT_ID_SBA_TABED = 1;
+
+ using namespace ::com::sun::star::uno;
+ OTableRowExchange::OTableRowExchange(std::vector< std::shared_ptr<OTableRow> >&& _rvTableRow)
+ : m_vTableRow(std::move(_rvTableRow))
+ {
+ }
+ bool OTableRowExchange::WriteObject( tools::SvRef<SotTempStream>& rxOStm, void* pUserObject, sal_uInt32 nUserObjectId, const css::datatransfer::DataFlavor& /*rFlavor*/ )
+ {
+ if(nUserObjectId == FORMAT_OBJECT_ID_SBA_TABED)
+ {
+ std::vector< std::shared_ptr<OTableRow> >* pRows = static_cast< std::vector< std::shared_ptr<OTableRow> >* >(pUserObject);
+ if(pRows)
+ {
+ (*rxOStm).WriteInt32( pRows->size() ); // first stream the size
+ for (auto const& row : *pRows)
+ WriteOTableRow(*rxOStm, *row);
+ return true;
+ }
+ }
+ return false;
+ }
+ void OTableRowExchange::AddSupportedFormats()
+ {
+ if ( !m_vTableRow.empty() )
+ AddFormat(SotClipboardFormatId::SBA_TABED);
+ }
+ bool OTableRowExchange::GetData( const css::datatransfer::DataFlavor& rFlavor, const OUString& /*rDestDoc*/ )
+ {
+ SotClipboardFormatId nFormat = SotExchange::GetFormat(rFlavor);
+ if(nFormat == SotClipboardFormatId::SBA_TABED)
+ return SetObject(&m_vTableRow,FORMAT_OBJECT_ID_SBA_TABED,rFlavor);
+ return false;
+ }
+ void OTableRowExchange::ObjectReleased()
+ {
+ m_vTableRow.clear();
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/tabledesign/TableUndo.cxx b/dbaccess/source/ui/tabledesign/TableUndo.cxx
new file mode 100644
index 000000000..d60756a2e
--- /dev/null
+++ b/dbaccess/source/ui/tabledesign/TableUndo.cxx
@@ -0,0 +1,352 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "TableUndo.hxx"
+#include <strings.hrc>
+#include "TEditControl.hxx"
+#include <TableRow.hxx>
+#include <TableController.hxx>
+#include <TableDesignView.hxx>
+#include <FieldDescriptions.hxx>
+#include <svx/svxids.hrc>
+
+using namespace dbaui;
+using namespace ::svt;
+
+
+OTableDesignUndoAct::OTableDesignUndoAct(OTableRowView* pOwner, TranslateId pCommentID)
+ : OCommentUndoAction(pCommentID)
+ , m_pTabDgnCtrl(pOwner)
+{
+ m_pTabDgnCtrl->m_nCurUndoActId++;
+}
+
+OTableDesignUndoAct::~OTableDesignUndoAct()
+{
+}
+
+void OTableDesignUndoAct::Undo()
+{
+ m_pTabDgnCtrl->m_nCurUndoActId--;
+
+ // doc has not been modified if first undo was reverted
+ if( m_pTabDgnCtrl->m_nCurUndoActId == 0 )
+ {
+ m_pTabDgnCtrl->GetView()->getController().setModified(false);
+ m_pTabDgnCtrl->GetView()->getController().InvalidateFeature(SID_SAVEDOC);
+ }
+}
+
+void OTableDesignUndoAct::Redo()
+{
+ m_pTabDgnCtrl->m_nCurUndoActId++;
+
+ // restore Modified-flag after Redo of first Undo-action
+ if( m_pTabDgnCtrl->m_nCurUndoActId > 0 )
+ {
+ m_pTabDgnCtrl->GetView()->getController().setModified(true);
+ m_pTabDgnCtrl->GetView()->getController().InvalidateFeature(SID_SAVEDOC);
+ }
+}
+
+OTableDesignCellUndoAct::OTableDesignCellUndoAct( OTableRowView* pOwner, sal_Int32 nRowID, sal_uInt16 nColumn ) :
+ OTableDesignUndoAct( pOwner ,STR_TABED_UNDO_CELLMODIFIED)
+ ,m_nCol( nColumn )
+ ,m_nRow( nRowID )
+{
+ // read text at position (m_nRow, m_nCol)
+ m_sOldText = m_pTabDgnCtrl->GetCellData( m_nRow, m_nCol );
+}
+
+OTableDesignCellUndoAct::~OTableDesignCellUndoAct()
+{
+}
+
+void OTableDesignCellUndoAct::Undo()
+{
+ // store text at old line and restore the old one
+ m_pTabDgnCtrl->ActivateCell( m_nRow, m_nCol );
+ m_sNewText = m_pTabDgnCtrl->GetCellData( m_nRow, m_nCol );
+ m_pTabDgnCtrl->SetCellData( m_nRow, m_nCol, m_sOldText );
+ // line has not been modified if the first Undo was reverted
+ if (m_pTabDgnCtrl->GetCurUndoActId() == 1)
+ {
+ CellControllerRef xController = m_pTabDgnCtrl->Controller();
+ if ( xController.is() )
+ xController->SaveValue();
+ m_pTabDgnCtrl->GetView()->getController().setModified(false);
+
+ }
+
+ OTableDesignUndoAct::Undo();
+}
+
+void OTableDesignCellUndoAct::Redo()
+{
+ // restore new text
+ m_pTabDgnCtrl->ActivateCell( m_nRow, m_nCol );
+ m_pTabDgnCtrl->SetCellData( m_nRow, m_nCol, m_sNewText );
+
+ OTableDesignUndoAct::Redo();
+}
+
+OTableEditorUndoAct::OTableEditorUndoAct(OTableEditorCtrl* pOwner, TranslateId pCommentID)
+ : OTableDesignUndoAct(pOwner, pCommentID)
+ , pTabEdCtrl(pOwner)
+{
+}
+
+OTableEditorUndoAct::~OTableEditorUndoAct()
+{
+}
+
+OTableEditorTypeSelUndoAct::OTableEditorTypeSelUndoAct( OTableEditorCtrl* pOwner, sal_Int32 nRowID, sal_uInt16 nColumn, const TOTypeInfoSP& _pOldType )
+ :OTableEditorUndoAct( pOwner ,STR_TABED_UNDO_TYPE_CHANGED)
+ ,m_nCol( nColumn )
+ ,m_nRow( nRowID )
+ ,m_pOldType( _pOldType )
+{
+}
+
+OTableEditorTypeSelUndoAct::~OTableEditorTypeSelUndoAct()
+{
+}
+
+void OTableEditorTypeSelUndoAct::Undo()
+{
+ // restore type
+ OFieldDescription* pFieldDesc = pTabEdCtrl->GetFieldDescr(m_nRow);
+ if(pFieldDesc)
+ m_pNewType = pFieldDesc->getTypeInfo();
+ else
+ m_pNewType = TOTypeInfoSP();
+ pTabEdCtrl->SetCellData(m_nRow,m_nCol,m_pOldType);
+ pTabEdCtrl->SwitchType( m_pOldType );
+
+ OTableEditorUndoAct::Undo();
+}
+
+void OTableEditorTypeSelUndoAct::Redo()
+{
+ // new type
+ pTabEdCtrl->GoToRowColumnId( m_nRow ,m_nCol);
+ pTabEdCtrl->SetCellData(m_nRow,m_nCol,m_pNewType);
+
+ OTableEditorUndoAct::Redo();
+}
+
+OTableEditorDelUndoAct::OTableEditorDelUndoAct( OTableEditorCtrl* pOwner) :
+ OTableEditorUndoAct( pOwner ,STR_TABED_UNDO_ROWDELETED)
+{
+ // fill DeletedRowList
+ std::vector< std::shared_ptr<OTableRow> >* pOriginalRows = pOwner->GetRowList();
+ sal_Int32 nIndex = pOwner->FirstSelectedRow();
+ std::shared_ptr<OTableRow> pOriginalRow;
+ std::shared_ptr<OTableRow> pNewRow;
+
+ while( nIndex != SFX_ENDOFSELECTION )
+ {
+ pOriginalRow = (*pOriginalRows)[nIndex];
+ pNewRow = std::make_shared<OTableRow>( *pOriginalRow, nIndex );
+ m_aDeletedRows.push_back( pNewRow);
+
+ nIndex = pOwner->NextSelectedRow();
+ }
+}
+
+OTableEditorDelUndoAct::~OTableEditorDelUndoAct()
+{
+ m_aDeletedRows.clear();
+}
+
+void OTableEditorDelUndoAct::Undo()
+{
+ // Insert the deleted line
+ sal_uLong nPos;
+
+ std::shared_ptr<OTableRow> pNewOrigRow;
+ std::vector< std::shared_ptr<OTableRow> >* pOriginalRows = pTabEdCtrl->GetRowList();
+
+ for (auto const& deletedRow : m_aDeletedRows)
+ {
+ pNewOrigRow = std::make_shared<OTableRow>( *deletedRow );
+ nPos = deletedRow->GetPos();
+ pOriginalRows->insert( pOriginalRows->begin()+nPos,pNewOrigRow);
+ }
+
+ pTabEdCtrl->DisplayData(pTabEdCtrl->GetCurRow());
+ pTabEdCtrl->Invalidate();
+ OTableEditorUndoAct::Undo();
+}
+
+void OTableEditorDelUndoAct::Redo()
+{
+ // delete line again
+ std::vector< std::shared_ptr<OTableRow> >* pOriginalRows = pTabEdCtrl->GetRowList();
+
+ for (auto const& deletedRow : m_aDeletedRows)
+ {
+ auto it = pOriginalRows->begin() + deletedRow->GetPos();
+ pOriginalRows->erase(it);
+ }
+
+ pTabEdCtrl->DisplayData(pTabEdCtrl->GetCurRow());
+ pTabEdCtrl->Invalidate();
+ OTableEditorUndoAct::Redo();
+}
+
+OTableEditorInsUndoAct::OTableEditorInsUndoAct( OTableEditorCtrl* pOwner,
+ tools::Long nInsertPosition ,
+ std::vector< std::shared_ptr<OTableRow> >&& _vInsertedRows)
+ :OTableEditorUndoAct( pOwner,STR_TABED_UNDO_ROWINSERTED )
+ ,m_vInsertedRows(std::move(_vInsertedRows))
+ ,m_nInsPos( nInsertPosition )
+{
+}
+
+OTableEditorInsUndoAct::~OTableEditorInsUndoAct()
+{
+ m_vInsertedRows.clear();
+}
+
+void OTableEditorInsUndoAct::Undo()
+{
+ // delete lines again
+ std::vector< std::shared_ptr<OTableRow> >* pOriginalRows = pTabEdCtrl->GetRowList();
+ pOriginalRows->erase(pOriginalRows->begin() + m_nInsPos, pOriginalRows->begin() + m_nInsPos + m_vInsertedRows.size());
+
+ pTabEdCtrl->RowRemoved( m_nInsPos, m_vInsertedRows.size() );
+ pTabEdCtrl->InvalidateHandleColumn();
+
+ OTableEditorUndoAct::Undo();
+}
+
+void OTableEditorInsUndoAct::Redo()
+{
+ // insert lines again
+ sal_Int32 nInsertRow = m_nInsPos;
+ std::shared_ptr<OTableRow> pRow;
+ std::vector< std::shared_ptr<OTableRow> >* pRowList = pTabEdCtrl->GetRowList();
+ for (auto const& insertedRow : m_vInsertedRows)
+ {
+ pRow = std::make_shared<OTableRow>( *insertedRow );
+ pRowList->insert( pRowList->begin()+nInsertRow ,pRow );
+ nInsertRow++;
+ }
+
+ pTabEdCtrl->RowInserted( m_nInsPos, m_vInsertedRows.size() );
+ pTabEdCtrl->InvalidateHandleColumn();
+
+ OTableEditorUndoAct::Redo();
+}
+
+OTableEditorInsNewUndoAct::OTableEditorInsNewUndoAct( OTableEditorCtrl* pOwner, sal_Int32 nInsertPosition, sal_Int32 nInsertedRows ) :
+ OTableEditorUndoAct( pOwner ,STR_TABED_UNDO_NEWROWINSERTED)
+ ,m_nInsPos( nInsertPosition )
+ ,m_nInsRows( nInsertedRows )
+{
+}
+
+OTableEditorInsNewUndoAct::~OTableEditorInsNewUndoAct()
+{
+}
+
+void OTableEditorInsNewUndoAct::Undo()
+{
+ // delete inserted lines
+ std::vector< std::shared_ptr<OTableRow> >* pOriginalRows = pTabEdCtrl->GetRowList();
+
+ pOriginalRows->erase(pOriginalRows->begin() + m_nInsPos, pOriginalRows->begin() + m_nInsPos + m_nInsRows);
+
+ pTabEdCtrl->RowRemoved( m_nInsPos, m_nInsRows );
+ pTabEdCtrl->InvalidateHandleColumn();
+
+ OTableEditorUndoAct::Undo();
+}
+
+void OTableEditorInsNewUndoAct::Redo()
+{
+ // insert lines again
+ std::vector< std::shared_ptr<OTableRow> >* pRowList = pTabEdCtrl->GetRowList();
+
+ for( tools::Long i=m_nInsPos; i<(m_nInsPos+m_nInsRows); i++ )
+ pRowList->insert( pRowList->begin()+i,std::make_shared<OTableRow>() );
+
+ pTabEdCtrl->RowInserted( m_nInsPos, m_nInsRows );
+ pTabEdCtrl->InvalidateHandleColumn();
+
+ OTableEditorUndoAct::Redo();
+}
+
+OPrimKeyUndoAct::OPrimKeyUndoAct( OTableEditorCtrl* pOwner, const MultiSelection& aDeletedKeys, const MultiSelection& aInsertedKeys) :
+ OTableEditorUndoAct( pOwner ,STR_TABLEDESIGN_UNDO_PRIMKEY)
+ ,m_aDelKeys( aDeletedKeys )
+ ,m_aInsKeys( aInsertedKeys )
+ ,m_pEditorCtrl( pOwner )
+{
+}
+
+OPrimKeyUndoAct::~OPrimKeyUndoAct()
+{
+}
+
+void OPrimKeyUndoAct::Undo()
+{
+ std::vector< std::shared_ptr<OTableRow> >* pRowList = pTabEdCtrl->GetRowList();
+ std::shared_ptr<OTableRow> pRow;
+ tools::Long nIndex;
+
+ // delete inserted keys
+ for( nIndex = m_aInsKeys.FirstSelected(); nIndex != tools::Long(SFX_ENDOFSELECTION); nIndex=m_aInsKeys.NextSelected() )
+ {
+ OSL_ENSURE(nIndex <= static_cast<tools::Long>(pRowList->size()),"Index for undo isn't valid!");
+ pRow = (*pRowList)[nIndex];
+ pRow->SetPrimaryKey( false );
+ }
+
+ // restore deleted keys
+ for( nIndex = m_aDelKeys.FirstSelected(); nIndex != tools::Long(SFX_ENDOFSELECTION); nIndex=m_aDelKeys.NextSelected() )
+ {
+ OSL_ENSURE(nIndex <= static_cast<tools::Long>(pRowList->size()),"Index for undo isn't valid!");
+ pRow = (*pRowList)[nIndex];
+ pRow->SetPrimaryKey( true );
+ }
+
+ m_pEditorCtrl->InvalidateHandleColumn();
+ OTableEditorUndoAct::Undo();
+}
+
+void OPrimKeyUndoAct::Redo()
+{
+ std::vector< std::shared_ptr<OTableRow> >* pRowList = pTabEdCtrl->GetRowList();
+ tools::Long nIndex;
+
+ // delete the deleted keys
+ for( nIndex = m_aDelKeys.FirstSelected(); nIndex != tools::Long(SFX_ENDOFSELECTION); nIndex=m_aDelKeys.NextSelected() )
+ (*pRowList)[nIndex]->SetPrimaryKey( false );
+
+ // restore the inserted keys
+ for( nIndex = m_aInsKeys.FirstSelected(); nIndex != tools::Long(SFX_ENDOFSELECTION); nIndex=m_aInsKeys.NextSelected() )
+ (*pRowList)[nIndex]->SetPrimaryKey( true );
+
+ m_pEditorCtrl->InvalidateHandleColumn();
+ OTableEditorUndoAct::Redo();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/tabledesign/TableUndo.hxx b/dbaccess/source/ui/tabledesign/TableUndo.hxx
new file mode 100644
index 000000000..5ad23b84f
--- /dev/null
+++ b/dbaccess/source/ui/tabledesign/TableUndo.hxx
@@ -0,0 +1,136 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <GeneralUndo.hxx>
+#include <tools/multisel.hxx>
+
+#include <vector>
+
+#include <com/sun/star/uno/Any.h>
+#include <TypeInfo.hxx>
+#include <vcl/vclptr.hxx>
+
+namespace dbaui
+{
+ class OTableRowView;
+ class OTableRow;
+ class OTableDesignUndoAct : public OCommentUndoAction
+ {
+ protected:
+ VclPtr<OTableRowView> m_pTabDgnCtrl;
+
+ virtual void Undo() override;
+ virtual void Redo() override;
+ public:
+ OTableDesignUndoAct(OTableRowView* pOwner, TranslateId pCommentID);
+ virtual ~OTableDesignUndoAct() override;
+ };
+
+ class OTableEditorCtrl;
+ class OTableEditorUndoAct : public OTableDesignUndoAct
+ {
+ protected:
+ VclPtr<OTableEditorCtrl> pTabEdCtrl;
+
+ public:
+ OTableEditorUndoAct(OTableEditorCtrl* pOwner, TranslateId pCommentID);
+ virtual ~OTableEditorUndoAct() override;
+ };
+
+ class OTableDesignCellUndoAct final : public OTableDesignUndoAct
+ {
+ sal_uInt16 m_nCol;
+ sal_Int32 m_nRow;
+ css::uno::Any m_sOldText;
+ css::uno::Any m_sNewText;
+
+ virtual void Undo() override;
+ virtual void Redo() override;
+ public:
+ OTableDesignCellUndoAct( OTableRowView* pOwner, sal_Int32 nRowID, sal_uInt16 nColumn );
+ virtual ~OTableDesignCellUndoAct() override;
+ };
+
+ class OTableEditorTypeSelUndoAct final : public OTableEditorUndoAct
+ {
+ sal_uInt16 m_nCol;
+ sal_Int32 m_nRow;
+ TOTypeInfoSP m_pOldType;
+ TOTypeInfoSP m_pNewType;
+
+ virtual void Undo() override;
+ virtual void Redo() override;
+ public:
+ OTableEditorTypeSelUndoAct( OTableEditorCtrl* pOwner, sal_Int32 nRowID, sal_uInt16 nColumn, const TOTypeInfoSP& _pOldType );
+ virtual ~OTableEditorTypeSelUndoAct() override;
+ };
+
+ class OTableEditorDelUndoAct final : public OTableEditorUndoAct
+ {
+ std::vector< std::shared_ptr<OTableRow> > m_aDeletedRows;
+
+ virtual void Undo() override;
+ virtual void Redo() override;
+ public:
+ explicit OTableEditorDelUndoAct( OTableEditorCtrl* pOwner );
+ virtual ~OTableEditorDelUndoAct() override;
+ };
+
+ class OTableEditorInsUndoAct final : public OTableEditorUndoAct
+ {
+ std::vector< std::shared_ptr<OTableRow> > m_vInsertedRows;
+ tools::Long m_nInsPos;
+
+ virtual void Undo() override;
+ virtual void Redo() override;
+ public:
+ OTableEditorInsUndoAct( OTableEditorCtrl* pOwner,
+ tools::Long nInsertPosition,
+ std::vector< std::shared_ptr<OTableRow> >&& _vInsertedRows);
+ virtual ~OTableEditorInsUndoAct() override;
+ };
+
+ class OTableEditorInsNewUndoAct final : public OTableEditorUndoAct
+ {
+ sal_Int32 m_nInsPos;
+ sal_Int32 m_nInsRows;
+
+ virtual void Undo() override;
+ virtual void Redo() override;
+ public:
+ OTableEditorInsNewUndoAct( OTableEditorCtrl* pOwner, sal_Int32 nInsertPosition, sal_Int32 nInsertedRows );
+ virtual ~OTableEditorInsNewUndoAct() override;
+ };
+
+ class OPrimKeyUndoAct final : public OTableEditorUndoAct
+ {
+ MultiSelection m_aDelKeys,
+ m_aInsKeys;
+ VclPtr<OTableEditorCtrl> m_pEditorCtrl;
+
+ virtual void Undo() override;
+ virtual void Redo() override;
+ public:
+ OPrimKeyUndoAct( OTableEditorCtrl* pOwner, const MultiSelection& aDeletedKeys, const MultiSelection& aInsertedKeys );
+ virtual ~OPrimKeyUndoAct() override;
+ };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/uno/AdvancedSettingsDlg.cxx b/dbaccess/source/ui/uno/AdvancedSettingsDlg.cxx
new file mode 100644
index 000000000..3d24cfc24
--- /dev/null
+++ b/dbaccess/source/ui/uno/AdvancedSettingsDlg.cxx
@@ -0,0 +1,117 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+
+#include <unoadmin.hxx>
+#include <advancedsettingsdlg.hxx>
+#include <comphelper/proparrhlp.hxx>
+#include <vcl/svapp.hxx>
+
+namespace dbaui
+{
+
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::lang;
+ using namespace ::com::sun::star::beans;
+
+ namespace {
+
+ // OAdvancedSettingsDialog
+ class OAdvancedSettingsDialog
+ :public ODatabaseAdministrationDialog
+ ,public ::comphelper::OPropertyArrayUsageHelper< OAdvancedSettingsDialog >
+ {
+
+ public:
+ explicit OAdvancedSettingsDialog(const css::uno::Reference< css::uno::XComponentContext >& _rxORB);
+
+ // XTypeProvider
+ virtual css::uno::Sequence<sal_Int8> SAL_CALL getImplementationId( ) override;
+
+ // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override;
+
+ // XPropertySet
+ virtual css::uno::Reference< css::beans::XPropertySetInfo> SAL_CALL getPropertySetInfo() override;
+ virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper() override;
+
+ // OPropertyArrayUsageHelper
+ virtual ::cppu::IPropertyArrayHelper* createArrayHelper( ) const override;
+ protected:
+ // OGenericUnoDialog overridables
+ virtual std::unique_ptr<weld::DialogController> createDialog(const css::uno::Reference<css::awt::XWindow>& rParent) override;
+ };
+
+ }
+
+ OAdvancedSettingsDialog::OAdvancedSettingsDialog(const Reference< XComponentContext >& _rxORB)
+ :ODatabaseAdministrationDialog(_rxORB)
+ {
+ }
+ Sequence<sal_Int8> SAL_CALL OAdvancedSettingsDialog::getImplementationId( )
+ {
+ return css::uno::Sequence<sal_Int8>();
+ }
+
+ OUString SAL_CALL OAdvancedSettingsDialog::getImplementationName()
+ {
+ return "org.openoffice.comp.dbu.OAdvancedSettingsDialog";
+ }
+
+ css::uno::Sequence<OUString> SAL_CALL OAdvancedSettingsDialog::getSupportedServiceNames()
+ {
+ return { "com.sun.star.sdb.AdvancedDatabaseSettingsDialog" };
+ }
+
+ Reference<XPropertySetInfo> SAL_CALL OAdvancedSettingsDialog::getPropertySetInfo()
+ {
+ Reference<XPropertySetInfo> xInfo( createPropertySetInfo( getInfoHelper() ) );
+ return xInfo;
+ }
+
+ ::cppu::IPropertyArrayHelper& OAdvancedSettingsDialog::getInfoHelper()
+ {
+ return *getArrayHelper();
+ }
+
+ ::cppu::IPropertyArrayHelper* OAdvancedSettingsDialog::createArrayHelper( ) const
+ {
+ Sequence< Property > aProps;
+ describeProperties(aProps);
+ return new ::cppu::OPropertyArrayHelper(aProps);
+ }
+
+ std::unique_ptr<weld::DialogController> OAdvancedSettingsDialog::createDialog(const css::uno::Reference<css::awt::XWindow>& rParent)
+ {
+ return std::make_unique<AdvancedSettingsDialog>(Application::GetFrameWeld(rParent), m_pDatasourceItems.get(),
+ m_aContext, m_aInitialSelection);
+ }
+
+} // namespace dbaui
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+org_openoffice_comp_dbu_OAdvancedSettingsDialog_get_implementation(
+ css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const& )
+{
+ return cppu::acquire(new ::dbaui::OAdvancedSettingsDialog(context));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/uno/ColumnControl.cxx b/dbaccess/source/ui/uno/ColumnControl.cxx
new file mode 100644
index 000000000..9295b9954
--- /dev/null
+++ b/dbaccess/source/ui/uno/ColumnControl.cxx
@@ -0,0 +1,146 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "ColumnControl.hxx"
+#include "ColumnPeer.hxx"
+#include <strings.hxx>
+#include <vcl/window.hxx>
+#include <com/sun/star/awt/PosSize.hpp>
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+com_sun_star_comp_dbu_OColumnControl_get_implementation(
+ css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const& )
+{
+ return cppu::acquire(new ::dbaui::OColumnControl(context));
+}
+
+namespace dbaui
+{
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::awt;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::sdbc;
+
+OColumnControl::OColumnControl(const Reference<XComponentContext>& rxContext)
+ : m_xContext(rxContext)
+{
+}
+
+OUString SAL_CALL OColumnControl::getImplementationName()
+{
+ return SERVICE_CONTROLDEFAULT;
+}
+sal_Bool SAL_CALL OColumnControl::supportsService(const OUString& _rServiceName)
+ {
+ const css::uno::Sequence< OUString > aSupported(getSupportedServiceNames());
+ for (const OUString& s : aSupported)
+ if (s == _rServiceName)
+ return true;
+
+ return false;
+ }
+css::uno::Sequence< OUString > SAL_CALL OColumnControl::getSupportedServiceNames()
+{
+ return { "com.sun.star.awt.UnoControl","com.sun.star.sdb.ColumnDescriptorControl" };
+}
+
+OUString OColumnControl::GetComponentServiceName() const
+{
+ return "com.sun.star.sdb.ColumnDescriptorControl";
+}
+
+void SAL_CALL OColumnControl::createPeer(const Reference< XToolkit >& /*rToolkit*/, const Reference< XWindowPeer >& rParentPeer)
+{
+ ::osl::ClearableMutexGuard aGuard( GetMutex() );
+ if ( getPeer().is() )
+ return;
+
+ mbCreatingPeer = true;
+
+ vcl::Window* pParentWin = nullptr;
+ if (rParentPeer.is())
+ {
+ VCLXWindow* pParent = comphelper::getFromUnoTunnel<VCLXWindow>(rParentPeer);
+ if (pParent)
+ pParentWin = pParent->GetWindow();
+ }
+
+ rtl::Reference<OColumnPeer> pPeer = new OColumnPeer( pParentWin, m_xContext );
+ OSL_ENSURE(pPeer != nullptr, "FmXGridControl::createPeer : imp_CreatePeer didn't return a peer !");
+ setPeer( pPeer );
+
+ UnoControlComponentInfos aComponentInfos(maComponentInfos);
+ Reference< XGraphics > xGraphics( mxGraphics );
+ Reference< XView > xV(getPeer(), UNO_QUERY);
+ Reference< XWindow > xW(getPeer(), UNO_QUERY);
+
+ aGuard.clear();
+
+ updateFromModel();
+
+ xV->setZoom( aComponentInfos.nZoomX, aComponentInfos.nZoomY );
+ setPosSize( aComponentInfos.nX, aComponentInfos.nY, aComponentInfos.nWidth, aComponentInfos.nHeight, css::awt::PosSize::POSSIZE );
+
+ Reference<XPropertySet> xProp(getModel(), UNO_QUERY);
+ if ( xProp.is() )
+ {
+ Reference<XConnection> xCon(xProp->getPropertyValue(PROPERTY_ACTIVE_CONNECTION),UNO_QUERY);
+ pPeer->setConnection(xCon);
+ Reference<XPropertySet> xColumn(xProp->getPropertyValue(PROPERTY_COLUMN),UNO_QUERY);
+ pPeer->setColumn(xColumn);
+ sal_Int32 nWidth = 50;
+ xProp->getPropertyValue(PROPERTY_EDIT_WIDTH) >>= nWidth;
+ pPeer->setEditWidth(nWidth);
+ }
+
+ if (aComponentInfos.bVisible)
+ xW->setVisible(true);
+
+ if (!aComponentInfos.bEnable)
+ xW->setEnable(false);
+
+ if (maWindowListeners.getLength())
+ xW->addWindowListener( &maWindowListeners );
+
+ if (maFocusListeners.getLength())
+ xW->addFocusListener( &maFocusListeners );
+
+ if (maKeyListeners.getLength())
+ xW->addKeyListener( &maKeyListeners );
+
+ if (maMouseListeners.getLength())
+ xW->addMouseListener( &maMouseListeners );
+
+ if (maMouseMotionListeners.getLength())
+ xW->addMouseMotionListener( &maMouseMotionListeners );
+
+ if (maPaintListeners.getLength())
+ xW->addPaintListener( &maPaintListeners );
+
+ Reference< css::awt::XView > xPeerView(getPeer(), UNO_QUERY);
+ xPeerView->setZoom( maComponentInfos.nZoomX, maComponentInfos.nZoomY );
+ xPeerView->setGraphics( xGraphics );
+
+ mbCreatingPeer = false;
+}
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/uno/ColumnControl.hxx b/dbaccess/source/ui/uno/ColumnControl.hxx
new file mode 100644
index 000000000..63f066512
--- /dev/null
+++ b/dbaccess/source/ui/uno/ColumnControl.hxx
@@ -0,0 +1,46 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <connectivity/CommonTools.hxx>
+#include <toolkit/controls/unocontrol.hxx>
+
+namespace com::sun::star::uno { class XComponentContext; }
+
+namespace dbaui
+{
+ class OColumnControl : public UnoControl
+ {
+ private:
+ css::uno::Reference< css::uno::XComponentContext> m_xContext;
+ public:
+ explicit OColumnControl(const css::uno::Reference< css::uno::XComponentContext>& rxContext);
+
+ // UnoControl
+ virtual OUString GetComponentServiceName() const override;
+
+ // XServiceInfo
+ DECLARE_SERVICE_INFO();
+
+ // css::awt::XControl
+ virtual void SAL_CALL createPeer(const css::uno::Reference< css::awt::XToolkit >& _rToolkit, const css::uno::Reference< css::awt::XWindowPeer >& Parent) override;
+ };
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/uno/ColumnModel.cxx b/dbaccess/source/ui/uno/ColumnModel.cxx
new file mode 100644
index 000000000..de83b6176
--- /dev/null
+++ b/dbaccess/source/ui/uno/ColumnModel.cxx
@@ -0,0 +1,180 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "ColumnModel.hxx"
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+
+#include <stringconstants.hxx>
+#include <strings.hxx>
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+com_sun_star_comp_dbu_OColumnControlModel_get_implementation(
+ css::uno::XComponentContext* , css::uno::Sequence<css::uno::Any> const& )
+{
+ return cppu::acquire(new ::dbaui::OColumnControlModel());
+}
+
+namespace dbaui
+{
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::awt;
+using namespace ::com::sun::star::io;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::util;
+
+OColumnControlModel::OColumnControlModel()
+ :OPropertyContainer(m_aBHelper)
+ ,OColumnControlModel_BASE(m_aMutex)
+ ,m_sDefaultControl(SERVICE_CONTROLDEFAULT)
+ ,m_bEnable(true)
+ ,m_nBorder(0)
+ ,m_nWidth(50)
+{
+ registerProperties();
+}
+
+OColumnControlModel::OColumnControlModel(const OColumnControlModel* _pSource)
+ :OPropertyContainer(m_aBHelper)
+ ,OColumnControlModel_BASE(m_aMutex)
+ ,m_sDefaultControl(_pSource->m_sDefaultControl)
+ ,m_aTabStop(_pSource->m_aTabStop)
+ ,m_bEnable(_pSource->m_bEnable)
+ ,m_nBorder(_pSource->m_nBorder)
+ ,m_nWidth(50)
+{
+ registerProperties();
+}
+
+OColumnControlModel::~OColumnControlModel()
+{
+ if ( !OColumnControlModel_BASE::rBHelper.bDisposed && !OColumnControlModel_BASE::rBHelper.bInDispose )
+ {
+ acquire();
+ dispose();
+ }
+}
+
+void OColumnControlModel::registerProperties()
+{
+ registerProperty( PROPERTY_ACTIVE_CONNECTION, PROPERTY_ID_ACTIVE_CONNECTION, PropertyAttribute::TRANSIENT | PropertyAttribute::BOUND,
+ &m_xConnection, cppu::UnoType<decltype(m_xConnection)>::get() );
+ Any a;
+ a <<= m_xColumn;
+ registerProperty( PROPERTY_COLUMN, PROPERTY_ID_COLUMN, PropertyAttribute::TRANSIENT | PropertyAttribute::BOUND,
+ &m_xColumn, cppu::UnoType<decltype(m_xColumn)>::get() );
+
+ registerMayBeVoidProperty( PROPERTY_TABSTOP, PROPERTY_ID_TABSTOP, PropertyAttribute::BOUND | PropertyAttribute::MAYBEVOID,
+ &m_aTabStop, ::cppu::UnoType<sal_Int16>::get() );
+ registerProperty( PROPERTY_DEFAULTCONTROL, PROPERTY_ID_DEFAULTCONTROL, PropertyAttribute::BOUND,
+ &m_sDefaultControl, cppu::UnoType<decltype(m_sDefaultControl)>::get() );
+ registerProperty( PROPERTY_ENABLED, PROPERTY_ID_ENABLED, PropertyAttribute::BOUND,
+ &m_bEnable, cppu::UnoType<decltype(m_bEnable)>::get() );
+ registerProperty( PROPERTY_BORDER, PROPERTY_ID_BORDER, PropertyAttribute::BOUND,
+ &m_nBorder, cppu::UnoType<decltype(m_nBorder)>::get() );
+ registerProperty( PROPERTY_EDIT_WIDTH, PROPERTY_ID_EDIT_WIDTH, PropertyAttribute::BOUND,
+ &m_nWidth, cppu::UnoType<decltype(m_nWidth)>::get() );
+}
+
+// XCloneable
+Reference< XCloneable > SAL_CALL OColumnControlModel::createClone( )
+{
+ return new OColumnControlModel( this );
+}
+
+css::uno::Sequence<sal_Int8> OColumnControlModel::getImplementationId()
+{
+ return css::uno::Sequence<sal_Int8>();
+}
+
+css::uno::Sequence< css::uno::Type > OColumnControlModel::getTypes()
+{
+ return ::comphelper::concatSequences(
+ OColumnControlModel_BASE::getTypes( ),
+ OPropertyContainer::getTypes( )
+ );
+}
+css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL OColumnControlModel::getPropertySetInfo()
+{
+ Reference< XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) );
+ return xInfo;
+}
+::cppu::IPropertyArrayHelper& OColumnControlModel::getInfoHelper()
+{
+ return *OColumnControlModel::getArrayHelper();
+}
+::cppu::IPropertyArrayHelper* OColumnControlModel::createArrayHelper( ) const
+{
+ css::uno::Sequence< css::beans::Property > aProps;
+ describeProperties(aProps);
+ return new ::cppu::OPropertyArrayHelper(aProps);
+}
+
+OUString SAL_CALL OColumnControlModel::getImplementationName()
+{
+ return "com.sun.star.comp.dbu.OColumnControlModel";
+}
+sal_Bool SAL_CALL OColumnControlModel::supportsService(const OUString& _rServiceName)
+ {
+ const css::uno::Sequence< OUString > aSupported(getSupportedServiceNames());
+ for (const OUString& s : aSupported)
+ if (s == _rServiceName)
+ return true;
+
+ return false;
+ }
+css::uno::Sequence< OUString > SAL_CALL OColumnControlModel::getSupportedServiceNames()
+{
+ return { "com.sun.star.awt.UnoControlModel","com.sun.star.sdb.ColumnDescriptorControlModel" };
+}
+IMPLEMENT_FORWARD_REFCOUNT( OColumnControlModel, OColumnControlModel_BASE )
+Any SAL_CALL OColumnControlModel::queryInterface( const Type& _rType )
+{
+ return OColumnControlModel_BASE::queryInterface( _rType );
+}
+
+// css::XAggregation
+Any SAL_CALL OColumnControlModel::queryAggregation( const Type& rType )
+{
+ Any aRet(OColumnControlModel_BASE::queryAggregation(rType));
+ if (!aRet.hasValue())
+ aRet = comphelper::OPropertyContainer::queryInterface(rType);
+ return aRet;
+}
+
+OUString SAL_CALL OColumnControlModel::getServiceName()
+{
+ return OUString();
+}
+
+void OColumnControlModel::write(const Reference<XObjectOutputStream>& /*_rxOutStream*/)
+{
+ // TODO
+}
+
+void OColumnControlModel::read(const Reference<XObjectInputStream>& /*_rxInStream*/)
+{
+ // TODO
+}
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/uno/ColumnModel.hxx b/dbaccess/source/ui/uno/ColumnModel.hxx
new file mode 100644
index 000000000..400d03652
--- /dev/null
+++ b/dbaccess/source/ui/uno/ColumnModel.hxx
@@ -0,0 +1,97 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <com/sun/star/awt/XControlModel.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/util/XCloneable.hpp>
+#include <com/sun/star/io/XPersistObject.hpp>
+#include <com/sun/star/sdbc/XConnection.hpp>
+#include <comphelper/proparrhlp.hxx>
+#include <comphelper/propertycontainer.hxx>
+#include <comphelper/broadcasthelper.hxx>
+#include <comphelper/uno3.hxx>
+#include <cppuhelper/compbase4.hxx>
+#include <connectivity/CommonTools.hxx>
+
+namespace dbaui
+{
+
+// OColumnControlModel
+typedef ::cppu::WeakAggComponentImplHelper4 < css::awt::XControlModel
+ , css::lang::XServiceInfo
+ , css::util::XCloneable
+ , css::io::XPersistObject
+ > OColumnControlModel_BASE;
+
+class OColumnControlModel;
+
+class OColumnControlModel : public ::comphelper::OMutexAndBroadcastHelper
+ ,public ::comphelper::OPropertyContainer
+ ,public ::comphelper::OPropertyArrayUsageHelper< OColumnControlModel >
+ ,public OColumnControlModel_BASE
+{
+
+// [properties]
+ css::uno::Reference< css::sdbc::XConnection> m_xConnection;
+ css::uno::Reference< css::beans::XPropertySet > m_xColumn;
+ OUString m_sDefaultControl;
+ css::uno::Any m_aTabStop;
+ bool m_bEnable;
+ sal_Int16 m_nBorder;
+ sal_Int32 m_nWidth;
+// [properties]
+
+ void registerProperties();
+protected:
+
+ virtual ~OColumnControlModel() override;
+ OColumnControlModel(const OColumnControlModel* _pSource);
+public:
+ explicit OColumnControlModel();
+
+// UNO binding
+ DECLARE_XINTERFACE( )
+
+// css::lang::XServiceInfo
+ DECLARE_SERVICE_INFO();
+
+ virtual css::uno::Sequence<css::uno::Type> SAL_CALL getTypes() override;
+ virtual css::uno::Sequence<sal_Int8> SAL_CALL getImplementationId() override;
+
+// css::uno::XAggregation
+ virtual css::uno::Any SAL_CALL queryAggregation( const css::uno::Type& aType ) override;
+
+// css::io::XPersistObject
+ virtual OUString SAL_CALL getServiceName() override;
+ virtual void SAL_CALL write(const css::uno::Reference< css::io::XObjectOutputStream>& _rxOutStream) override;
+ virtual void SAL_CALL read(const css::uno::Reference< css::io::XObjectInputStream>& _rxInStream) override;
+
+// OPropertyArrayUsageHelper
+ virtual css::uno::Reference< css::beans::XPropertySetInfo> SAL_CALL getPropertySetInfo() override;
+ virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper() override;
+ virtual ::cppu::IPropertyArrayHelper* createArrayHelper() const override;
+
+
+ virtual css::uno::Reference< css::util::XCloneable > SAL_CALL createClone( ) override;
+};
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/uno/ColumnPeer.cxx b/dbaccess/source/ui/uno/ColumnPeer.cxx
new file mode 100644
index 000000000..48f5fbce5
--- /dev/null
+++ b/dbaccess/source/ui/uno/ColumnPeer.cxx
@@ -0,0 +1,148 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "ColumnPeer.hxx"
+#include <ColumnControlWindow.hxx>
+#include <vcl/svapp.hxx>
+#include <strings.hxx>
+#include <FieldDescriptions.hxx>
+
+namespace dbaui
+{
+using namespace ::com::sun::star::awt;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::sdbc;
+
+OColumnPeer::OColumnPeer(vcl::Window* _pParent,const Reference<XComponentContext>& _rxContext)
+ :m_pActFieldDescr(nullptr)
+{
+ osl_atomic_increment( &m_refCount );
+ {
+ VclPtrInstance<OColumnControlTopLevel> pFieldControl(_pParent, _rxContext);
+ pFieldControl->SetComponentInterface(this);
+ pFieldControl->Show();
+ }
+ osl_atomic_decrement( &m_refCount );
+}
+
+void OColumnPeer::setEditWidth(sal_Int32 _nWidth)
+{
+ SolarMutexGuard aGuard;
+ VclPtr<OColumnControlTopLevel> pFieldControl = GetAs<OColumnControlTopLevel>();
+ if ( pFieldControl )
+ pFieldControl->GetControl().setEditWidth(_nWidth);
+}
+
+void OColumnPeer::setColumn(const Reference< XPropertySet>& _xColumn)
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr<OColumnControlTopLevel> pFieldControl = GetAs<OColumnControlTopLevel>();
+ if ( !pFieldControl )
+ return;
+
+ OColumnControlWindow& rControl = pFieldControl->GetControl();
+
+ if ( m_pActFieldDescr )
+ {
+ delete m_pActFieldDescr;
+ m_pActFieldDescr = nullptr;
+ }
+ if ( _xColumn.is() )
+ {
+ sal_Int32 nType = 0;
+ sal_Int32 nScale = 0;
+ sal_Int32 nPrecision = 0;
+ bool bAutoIncrement = false;
+ OUString sTypeName;
+
+ try
+ {
+ // get the properties from the column
+ _xColumn->getPropertyValue(PROPERTY_TYPENAME) >>= sTypeName;
+ _xColumn->getPropertyValue(PROPERTY_TYPE) >>= nType;
+ _xColumn->getPropertyValue(PROPERTY_SCALE) >>= nScale;
+ _xColumn->getPropertyValue(PROPERTY_PRECISION) >>= nPrecision;
+ _xColumn->getPropertyValue(PROPERTY_ISAUTOINCREMENT) >>= bAutoIncrement;
+ }
+ catch(const Exception&)
+ {
+ }
+
+ m_pActFieldDescr = new OFieldDescription(_xColumn,true);
+ // search for type
+ bool bForce;
+ TOTypeInfoSP pTypeInfo = ::dbaui::getTypeInfoFromType(*rControl.getTypeInfo(),nType,sTypeName,"x",nPrecision,nScale,bAutoIncrement,bForce);
+ if ( !pTypeInfo )
+ pTypeInfo = rControl.getDefaultTyp();
+
+ m_pActFieldDescr->FillFromTypeInfo(pTypeInfo,true,false);
+ m_xColumn = _xColumn;
+ }
+ rControl.DisplayData(m_pActFieldDescr);
+}
+
+void OColumnPeer::setConnection(const Reference< XConnection>& _xCon)
+{
+ SolarMutexGuard aGuard;
+ VclPtr<OColumnControlTopLevel> pFieldControl = GetAs<OColumnControlTopLevel>();
+ if ( pFieldControl )
+ pFieldControl->GetControl().setConnection(_xCon);
+}
+
+void OColumnPeer::setProperty( const OUString& _rPropertyName, const Any& Value)
+{
+ SolarMutexGuard aGuard;
+
+ if (_rPropertyName == PROPERTY_COLUMN)
+ {
+ Reference<XPropertySet> xProp(Value,UNO_QUERY);
+ setColumn(xProp);
+ }
+ else if (_rPropertyName == PROPERTY_ACTIVE_CONNECTION)
+ {
+ Reference<XConnection> xCon(Value,UNO_QUERY);
+ setConnection(xCon);
+ }
+ else
+ VCLXWindow::setProperty(_rPropertyName,Value);
+}
+
+Any OColumnPeer::getProperty( const OUString& _rPropertyName )
+{
+ Any aProp;
+ VclPtr<OColumnControlTopLevel> pFieldControl = GetAs<OColumnControlTopLevel>();
+ if (pFieldControl && _rPropertyName == PROPERTY_COLUMN)
+ {
+ aProp <<= m_xColumn;
+ }
+ else if (pFieldControl && _rPropertyName == PROPERTY_ACTIVE_CONNECTION)
+ {
+ aProp <<= pFieldControl->GetControl().getConnection();
+ }
+ else
+ aProp = VCLXWindow::getProperty(_rPropertyName);
+ return aProp;
+}
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/uno/ColumnPeer.hxx b/dbaccess/source/ui/uno/ColumnPeer.hxx
new file mode 100644
index 000000000..8a92a40cd
--- /dev/null
+++ b/dbaccess/source/ui/uno/ColumnPeer.hxx
@@ -0,0 +1,47 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <toolkit/awt/vclxwindow.hxx>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/sdbc/XConnection.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+
+namespace dbaui
+{
+ class OFieldDescription;
+ class OColumnPeer : public VCLXWindow
+ {
+ OFieldDescription* m_pActFieldDescr;
+ css::uno::Reference< css::beans::XPropertySet> m_xColumn;
+ public:
+
+ OColumnPeer(vcl::Window* _pParent
+ ,const css::uno::Reference< css::uno::XComponentContext>& _rxContext);
+
+ void setColumn(const css::uno::Reference< css::beans::XPropertySet>& _xColumn);
+ void setConnection(const css::uno::Reference< css::sdbc::XConnection>& _xCon);
+ void setEditWidth(sal_Int32 _nWidth);
+ // VCLXWindow
+ virtual void SAL_CALL setProperty( const OUString& PropertyName, const css::uno::Any& Value ) override;
+ virtual css::uno::Any SAL_CALL getProperty( const OUString& PropertyName ) override;
+ };
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/uno/DBTypeWizDlg.cxx b/dbaccess/source/ui/uno/DBTypeWizDlg.cxx
new file mode 100644
index 000000000..8c9d16596
--- /dev/null
+++ b/dbaccess/source/ui/uno/DBTypeWizDlg.cxx
@@ -0,0 +1,85 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "DBTypeWizDlg.hxx"
+#include <dbwiz.hxx>
+#include <vcl/svapp.hxx>
+
+using namespace dbaui;
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+org_openoffice_comp_dbu_ODBTypeWizDialog_get_implementation(
+ css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const& )
+{
+ return cppu::acquire(new ODBTypeWizDialog(context));
+}
+
+namespace dbaui
+{
+
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::lang;
+ using namespace ::com::sun::star::beans;
+
+ODBTypeWizDialog::ODBTypeWizDialog(const Reference< XComponentContext >& _rxORB)
+ :ODatabaseAdministrationDialog(_rxORB)
+{
+}
+
+Sequence<sal_Int8> SAL_CALL ODBTypeWizDialog::getImplementationId( )
+{
+ return css::uno::Sequence<sal_Int8>();
+}
+
+OUString SAL_CALL ODBTypeWizDialog::getImplementationName()
+{
+ return "org.openoffice.comp.dbu.ODBTypeWizDialog";
+}
+
+css::uno::Sequence<OUString> SAL_CALL ODBTypeWizDialog::getSupportedServiceNames()
+{
+ return { "com.sun.star.sdb.DataSourceTypeChangeDialog" };
+}
+
+Reference<XPropertySetInfo> SAL_CALL ODBTypeWizDialog::getPropertySetInfo()
+{
+ Reference<XPropertySetInfo> xInfo( createPropertySetInfo( getInfoHelper() ) );
+ return xInfo;
+}
+
+::cppu::IPropertyArrayHelper& ODBTypeWizDialog::getInfoHelper()
+{
+ return *getArrayHelper();
+}
+
+::cppu::IPropertyArrayHelper* ODBTypeWizDialog::createArrayHelper( ) const
+{
+ Sequence< Property > aProps;
+ describeProperties(aProps);
+ return new ::cppu::OPropertyArrayHelper(aProps);
+}
+
+std::unique_ptr<weld::DialogController> ODBTypeWizDialog::createDialog(const css::uno::Reference<css::awt::XWindow>& rParent)
+{
+ return std::make_unique<ODbTypeWizDialog>(Application::GetFrameWeld(rParent), m_pDatasourceItems.get(), m_aContext, m_aInitialSelection);
+}
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/uno/DBTypeWizDlg.hxx b/dbaccess/source/ui/uno/DBTypeWizDlg.hxx
new file mode 100644
index 000000000..093981a0e
--- /dev/null
+++ b/dbaccess/source/ui/uno/DBTypeWizDlg.hxx
@@ -0,0 +1,56 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <unoadmin.hxx>
+
+#include <comphelper/proparrhlp.hxx>
+
+namespace dbaui
+{
+class ODBTypeWizDialog final
+ :public ODatabaseAdministrationDialog
+ ,public ::comphelper::OPropertyArrayUsageHelper< ODBTypeWizDialog >
+{
+public:
+
+ explicit ODBTypeWizDialog(const css::uno::Reference< css::uno::XComponentContext >& _rxORB);
+
+ // XTypeProvider
+ virtual css::uno::Sequence<sal_Int8> SAL_CALL getImplementationId( ) override;
+
+ // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override;
+
+ // XPropertySet
+ virtual css::uno::Reference< css::beans::XPropertySetInfo> SAL_CALL getPropertySetInfo() override;
+ virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper() override;
+
+ // OPropertyArrayUsageHelper
+ virtual ::cppu::IPropertyArrayHelper* createArrayHelper( ) const override;
+private:
+ // OGenericUnoDialog overridables
+ virtual std::unique_ptr<weld::DialogController> createDialog(const css::uno::Reference<css::awt::XWindow>& rParent) override;
+};
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/uno/DBTypeWizDlgSetup.cxx b/dbaccess/source/ui/uno/DBTypeWizDlgSetup.cxx
new file mode 100644
index 000000000..63c3d6304
--- /dev/null
+++ b/dbaccess/source/ui/uno/DBTypeWizDlgSetup.cxx
@@ -0,0 +1,104 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "DBTypeWizDlgSetup.hxx"
+#include <dbwizsetup.hxx>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/ui/dialogs/ExecutableDialogResults.hpp>
+#include <vcl/svapp.hxx>
+
+using namespace dbaui;
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+org_openoffice_comp_dbu_ODBTypeWizDialogSetup_get_implementation(
+ css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const& )
+{
+ return cppu::acquire(new ODBTypeWizDialogSetup(context));
+}
+
+namespace dbaui
+{
+
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::lang;
+ using namespace ::com::sun::star::beans;
+ using namespace ::com::sun::star::sdbc;
+
+ODBTypeWizDialogSetup::ODBTypeWizDialogSetup(const Reference< XComponentContext >& _rxORB)
+ :ODatabaseAdministrationDialog(_rxORB)
+ ,m_bOpenDatabase(true)
+ ,m_bStartTableWizard(false)
+{
+ registerProperty("OpenDatabase", 3, PropertyAttribute::TRANSIENT,
+ &m_bOpenDatabase, cppu::UnoType<bool>::get());
+
+ registerProperty("StartTableWizard", 4, PropertyAttribute::TRANSIENT,
+ &m_bStartTableWizard, cppu::UnoType<bool>::get());
+}
+
+Sequence<sal_Int8> SAL_CALL ODBTypeWizDialogSetup::getImplementationId( )
+{
+ return css::uno::Sequence<sal_Int8>();
+}
+
+OUString SAL_CALL ODBTypeWizDialogSetup::getImplementationName()
+{
+ return "org.openoffice.comp.dbu.ODBTypeWizDialogSetup";
+}
+
+css::uno::Sequence<OUString> SAL_CALL ODBTypeWizDialogSetup::getSupportedServiceNames()
+{
+ return { "com.sun.star.sdb.DatabaseWizardDialog" };
+}
+
+Reference<XPropertySetInfo> SAL_CALL ODBTypeWizDialogSetup::getPropertySetInfo()
+{
+ return createPropertySetInfo( getInfoHelper() );
+}
+
+::cppu::IPropertyArrayHelper& ODBTypeWizDialogSetup::getInfoHelper()
+{
+ return *getArrayHelper();
+}
+
+::cppu::IPropertyArrayHelper* ODBTypeWizDialogSetup::createArrayHelper( ) const
+{
+ Sequence< Property > aProps;
+ describeProperties(aProps);
+ return new ::cppu::OPropertyArrayHelper(aProps);
+}
+
+std::unique_ptr<weld::DialogController> ODBTypeWizDialogSetup::createDialog(const css::uno::Reference<css::awt::XWindow>& rParent)
+{
+ return std::make_unique<ODbTypeWizDialogSetup>(Application::GetFrameWeld(rParent), m_pDatasourceItems.get(), m_aContext, m_aInitialSelection);
+}
+
+void ODBTypeWizDialogSetup::executedDialog(sal_Int16 nExecutionResult)
+{
+ if (nExecutionResult == css::ui::dialogs::ExecutableDialogResults::OK)
+ {
+ const ODbTypeWizDialogSetup* pDialog = static_cast<ODbTypeWizDialogSetup*>(m_xDialog.get());
+ m_bOpenDatabase = pDialog->IsDatabaseDocumentToBeOpened();
+ m_bStartTableWizard = pDialog->IsTableWizardToBeStarted();
+ }
+}
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/uno/DBTypeWizDlgSetup.hxx b/dbaccess/source/ui/uno/DBTypeWizDlgSetup.hxx
new file mode 100644
index 000000000..56bd9a08a
--- /dev/null
+++ b/dbaccess/source/ui/uno/DBTypeWizDlgSetup.hxx
@@ -0,0 +1,59 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <unoadmin.hxx>
+
+#include <comphelper/proparrhlp.hxx>
+
+namespace dbaui
+{
+class ODBTypeWizDialogSetup final
+ :public ODatabaseAdministrationDialog
+ ,public ::comphelper::OPropertyArrayUsageHelper< ODBTypeWizDialogSetup >
+{
+ bool m_bOpenDatabase;
+ bool m_bStartTableWizard;
+
+public:
+ explicit ODBTypeWizDialogSetup(const css::uno::Reference< css::uno::XComponentContext >& _rxORB);
+
+ // XTypeProvider
+ virtual css::uno::Sequence<sal_Int8> SAL_CALL getImplementationId( ) override;
+
+ // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override;
+
+ // XPropertySet
+ virtual css::uno::Reference< css::beans::XPropertySetInfo> SAL_CALL getPropertySetInfo() override;
+ virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper() override;
+
+ // OPropertyArrayUsageHelper
+ virtual ::cppu::IPropertyArrayHelper* createArrayHelper( ) const override;
+private:
+ // OGenericUnoDialog overridables
+ virtual std::unique_ptr<weld::DialogController> createDialog(const css::uno::Reference<css::awt::XWindow>& rParent) override;
+ virtual void executedDialog(sal_Int16 _nExecutionResult) override;
+};
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/uno/TableFilterDlg.cxx b/dbaccess/source/ui/uno/TableFilterDlg.cxx
new file mode 100644
index 000000000..cd01f2587
--- /dev/null
+++ b/dbaccess/source/ui/uno/TableFilterDlg.cxx
@@ -0,0 +1,85 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "TableFilterDlg.hxx"
+#include <TablesSingleDlg.hxx>
+#include <vcl/svapp.hxx>
+
+using namespace dbaui;
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+org_openoffice_comp_dbu_OTableFilterDialog_get_implementation(
+ css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const& )
+{
+ return cppu::acquire(new OTableFilterDialog(context));
+}
+
+namespace dbaui
+{
+
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::lang;
+ using namespace ::com::sun::star::beans;
+
+OTableFilterDialog::OTableFilterDialog(const Reference< XComponentContext >& _rxORB)
+ :ODatabaseAdministrationDialog(_rxORB)
+{
+}
+
+Sequence<sal_Int8> SAL_CALL OTableFilterDialog::getImplementationId( )
+{
+ return css::uno::Sequence<sal_Int8>();
+}
+
+OUString SAL_CALL OTableFilterDialog::getImplementationName()
+{
+ return "org.openoffice.comp.dbu.OTableFilterDialog";
+}
+
+css::uno::Sequence<OUString> SAL_CALL OTableFilterDialog::getSupportedServiceNames()
+{
+ return { "com.sun.star.sdb.TableFilterDialog" };
+}
+
+Reference<XPropertySetInfo> SAL_CALL OTableFilterDialog::getPropertySetInfo()
+{
+ Reference<XPropertySetInfo> xInfo( createPropertySetInfo( getInfoHelper() ) );
+ return xInfo;
+}
+
+::cppu::IPropertyArrayHelper& OTableFilterDialog::getInfoHelper()
+{
+ return *getArrayHelper();
+}
+
+::cppu::IPropertyArrayHelper* OTableFilterDialog::createArrayHelper( ) const
+{
+ Sequence< Property > aProps;
+ describeProperties(aProps);
+ return new ::cppu::OPropertyArrayHelper(aProps);
+}
+
+std::unique_ptr<weld::DialogController> OTableFilterDialog::createDialog(const css::uno::Reference<css::awt::XWindow>& rParent)
+{
+ return std::make_unique<OTableSubscriptionDialog>(Application::GetFrameWeld(rParent), m_pDatasourceItems.get(), m_aContext, m_aInitialSelection);
+}
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/uno/TableFilterDlg.hxx b/dbaccess/source/ui/uno/TableFilterDlg.hxx
new file mode 100644
index 000000000..7c16a7f26
--- /dev/null
+++ b/dbaccess/source/ui/uno/TableFilterDlg.hxx
@@ -0,0 +1,57 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <unoadmin.hxx>
+
+#include <comphelper/proparrhlp.hxx>
+
+namespace dbaui
+{
+
+class OTableFilterDialog final
+ :public ODatabaseAdministrationDialog
+ ,public ::comphelper::OPropertyArrayUsageHelper< OTableFilterDialog >
+{
+
+public:
+ explicit OTableFilterDialog(const css::uno::Reference< css::uno::XComponentContext >& _rxORB);
+
+ // XTypeProvider
+ virtual css::uno::Sequence<sal_Int8> SAL_CALL getImplementationId( ) override;
+
+ // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override;
+
+ // XPropertySet
+ virtual css::uno::Reference< css::beans::XPropertySetInfo> SAL_CALL getPropertySetInfo() override;
+ virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper() override;
+
+ // OPropertyArrayUsageHelper
+ virtual ::cppu::IPropertyArrayHelper* createArrayHelper( ) const override;
+private:
+ // OGenericUnoDialog overridables
+ virtual std::unique_ptr<weld::DialogController> createDialog(const css::uno::Reference<css::awt::XWindow>& rParent) override;
+};
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/uno/UserSettingsDlg.cxx b/dbaccess/source/ui/uno/UserSettingsDlg.cxx
new file mode 100644
index 000000000..7039c7396
--- /dev/null
+++ b/dbaccess/source/ui/uno/UserSettingsDlg.cxx
@@ -0,0 +1,85 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "UserSettingsDlg.hxx"
+#include <UserAdminDlg.hxx>
+#include <vcl/svapp.hxx>
+
+using namespace dbaui;
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+org_openoffice_comp_dbu_OUserSettingsDialog_get_implementation(
+ css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const& )
+{
+ return cppu::acquire(new OUserSettingsDialog(context));
+}
+
+namespace dbaui
+{
+
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::lang;
+ using namespace ::com::sun::star::beans;
+
+OUserSettingsDialog::OUserSettingsDialog(const Reference< XComponentContext >& _rxORB)
+ :ODatabaseAdministrationDialog(_rxORB)
+{
+}
+
+Sequence<sal_Int8> SAL_CALL OUserSettingsDialog::getImplementationId( )
+{
+ return css::uno::Sequence<sal_Int8>();
+}
+
+OUString SAL_CALL OUserSettingsDialog::getImplementationName()
+{
+ return "org.openoffice.comp.dbu.OUserSettingsDialog";
+}
+
+css::uno::Sequence<OUString> SAL_CALL OUserSettingsDialog::getSupportedServiceNames()
+{
+ return { "com.sun.star.sdb.UserAdministrationDialog" };
+}
+
+Reference<XPropertySetInfo> SAL_CALL OUserSettingsDialog::getPropertySetInfo()
+{
+ Reference<XPropertySetInfo> xInfo( createPropertySetInfo( getInfoHelper() ) );
+ return xInfo;
+}
+
+::cppu::IPropertyArrayHelper& OUserSettingsDialog::getInfoHelper()
+{
+ return *getArrayHelper();
+}
+
+::cppu::IPropertyArrayHelper* OUserSettingsDialog::createArrayHelper( ) const
+{
+ Sequence< Property > aProps;
+ describeProperties(aProps);
+ return new ::cppu::OPropertyArrayHelper(aProps);
+}
+
+std::unique_ptr<weld::DialogController> OUserSettingsDialog::createDialog(const css::uno::Reference<css::awt::XWindow>& rParent)
+{
+ return std::make_unique<OUserAdminDlg>(Application::GetFrameWeld(rParent), m_pDatasourceItems.get(), m_aContext, m_aInitialSelection, m_xActiveConnection);
+}
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/uno/UserSettingsDlg.hxx b/dbaccess/source/ui/uno/UserSettingsDlg.hxx
new file mode 100644
index 000000000..7e0780ea2
--- /dev/null
+++ b/dbaccess/source/ui/uno/UserSettingsDlg.hxx
@@ -0,0 +1,57 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <unoadmin.hxx>
+
+#include <comphelper/proparrhlp.hxx>
+
+namespace dbaui
+{
+// OUserSettingsDialog
+class OUserSettingsDialog final
+ :public ODatabaseAdministrationDialog
+ ,public ::comphelper::OPropertyArrayUsageHelper< OUserSettingsDialog >
+{
+
+public:
+ explicit OUserSettingsDialog(const css::uno::Reference< css::uno::XComponentContext >& _rxORB);
+
+ // XTypeProvider
+ virtual css::uno::Sequence<sal_Int8> SAL_CALL getImplementationId( ) override;
+
+ // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override;
+
+ // XPropertySet
+ virtual css::uno::Reference< css::beans::XPropertySetInfo> SAL_CALL getPropertySetInfo() override;
+ virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper() override;
+
+ // OPropertyArrayUsageHelper
+ virtual ::cppu::IPropertyArrayHelper* createArrayHelper( ) const override;
+private:
+ // OGenericUnoDialog overridables
+ virtual std::unique_ptr<weld::DialogController> createDialog(const css::uno::Reference<css::awt::XWindow>& rParent) override;
+};
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/uno/admindlg.cxx b/dbaccess/source/ui/uno/admindlg.cxx
new file mode 100644
index 000000000..3e524372e
--- /dev/null
+++ b/dbaccess/source/ui/uno/admindlg.cxx
@@ -0,0 +1,92 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "admindlg.hxx"
+#include <dbadmin.hxx>
+#include <vcl/svapp.hxx>
+
+using namespace dbaui;
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+org_openoffice_comp_dbu_ODatasourceAdministrationDialog_get_implementation(
+ css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const&)
+{
+ return cppu::acquire(new ODataSourcePropertyDialog(context));
+}
+
+namespace dbaui
+{
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::beans;
+
+ODataSourcePropertyDialog::ODataSourcePropertyDialog(const Reference<XComponentContext>& _rxORB)
+ : ODatabaseAdministrationDialog(_rxORB)
+{
+}
+
+Sequence<sal_Int8> SAL_CALL ODataSourcePropertyDialog::getImplementationId()
+{
+ return css::uno::Sequence<sal_Int8>();
+}
+
+OUString SAL_CALL ODataSourcePropertyDialog::getImplementationName()
+{
+ return "org.openoffice.comp.dbu.ODatasourceAdministrationDialog";
+}
+
+css::uno::Sequence<OUString> SAL_CALL ODataSourcePropertyDialog::getSupportedServiceNames()
+{
+ return { "com.sun.star.sdb.DatasourceAdministrationDialog" };
+}
+
+Reference<XPropertySetInfo> SAL_CALL ODataSourcePropertyDialog::getPropertySetInfo()
+{
+ Reference<XPropertySetInfo> xInfo(createPropertySetInfo(getInfoHelper()));
+ return xInfo;
+}
+
+::cppu::IPropertyArrayHelper& ODataSourcePropertyDialog::getInfoHelper()
+{
+ return *getArrayHelper();
+}
+
+::cppu::IPropertyArrayHelper* ODataSourcePropertyDialog::createArrayHelper() const
+{
+ Sequence<Property> aProps;
+ describeProperties(aProps);
+ return new ::cppu::OPropertyArrayHelper(aProps);
+}
+
+std::unique_ptr<weld::DialogController>
+ODataSourcePropertyDialog::createDialog(const css::uno::Reference<css::awt::XWindow>& rParent)
+{
+ std::unique_ptr<ODbAdminDialog> xDialog(new ODbAdminDialog(
+ Application::GetFrameWeld(rParent), m_pDatasourceItems.get(), m_aContext));
+
+ // the initial selection
+ if (m_aInitialSelection.hasValue())
+ xDialog->selectDataSource(m_aInitialSelection);
+
+ return xDialog;
+}
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/uno/admindlg.hxx b/dbaccess/source/ui/uno/admindlg.hxx
new file mode 100644
index 000000000..62faabf64
--- /dev/null
+++ b/dbaccess/source/ui/uno/admindlg.hxx
@@ -0,0 +1,56 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <unoadmin.hxx>
+
+#include <comphelper/proparrhlp.hxx>
+
+namespace dbaui
+{
+class ODataSourcePropertyDialog final
+ :public ODatabaseAdministrationDialog
+ ,public ::comphelper::OPropertyArrayUsageHelper< ODataSourcePropertyDialog >
+{
+public:
+
+ explicit ODataSourcePropertyDialog(const css::uno::Reference< css::uno::XComponentContext >& _rxORB);
+
+ // XTypeProvider
+ virtual css::uno::Sequence<sal_Int8> SAL_CALL getImplementationId( ) override;
+
+ // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override;
+
+ // XPropertySet
+ virtual css::uno::Reference< css::beans::XPropertySetInfo> SAL_CALL getPropertySetInfo() override;
+ virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper() override;
+
+ // OPropertyArrayUsageHelper
+ virtual ::cppu::IPropertyArrayHelper* createArrayHelper( ) const override;
+private:
+ // OGenericUnoDialog overridables
+ virtual std::unique_ptr<weld::DialogController> createDialog(const css::uno::Reference<css::awt::XWindow>& rParent) override;
+};
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/uno/composerdialogs.cxx b/dbaccess/source/ui/uno/composerdialogs.cxx
new file mode 100644
index 000000000..f4b8fe24a
--- /dev/null
+++ b/dbaccess/source/ui/uno/composerdialogs.cxx
@@ -0,0 +1,270 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "composerdialogs.hxx"
+
+#include <com/sun/star/awt/XWindow.hpp>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
+#include <queryfilter.hxx>
+#include <queryorder.hxx>
+#include <strings.hxx>
+#include <connectivity/dbtools.hxx>
+#include <tools/diagnose_ex.h>
+#include <osl/diagnose.h>
+#include <vcl/svapp.hxx>
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+com_sun_star_uno_comp_sdb_RowsetOrderDialog_get_implementation(
+ css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const& )
+{
+ return cppu::acquire(new ::dbaui::RowsetOrderDialog(context));
+}
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+com_sun_star_uno_comp_sdb_RowsetFilterDialog_get_implementation(
+ css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const& )
+{
+ return cppu::acquire(new ::dbaui::RowsetFilterDialog(context));
+}
+
+namespace dbaui
+{
+
+#define PROPERTY_ID_QUERYCOMPOSER 100
+#define PROPERTY_ID_ROWSET 101
+
+constexpr OUStringLiteral PROPERTY_QUERYCOMPOSER = u"QueryComposer";
+constexpr OUStringLiteral PROPERTY_ROWSET = u"RowSet";
+
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::lang;
+ using namespace ::com::sun::star::beans;
+ using namespace ::com::sun::star::container;
+ using namespace ::com::sun::star::sdbcx;
+ using namespace ::com::sun::star::sdbc;
+ using namespace ::com::sun::star::sdb;
+
+ // ComposerDialog
+ ComposerDialog::ComposerDialog(const Reference< XComponentContext >& _rxORB)
+ :OGenericUnoDialog( _rxORB )
+ {
+
+ registerProperty( PROPERTY_QUERYCOMPOSER, PROPERTY_ID_QUERYCOMPOSER, PropertyAttribute::TRANSIENT,
+ &m_xComposer, cppu::UnoType<decltype(m_xComposer)>::get() );
+ registerProperty( PROPERTY_ROWSET, PROPERTY_ID_ROWSET, PropertyAttribute::TRANSIENT,
+ &m_xRowSet, cppu::UnoType<decltype(m_xRowSet)>::get() );
+ }
+
+ ComposerDialog::~ComposerDialog()
+ {
+
+ }
+
+ css::uno::Sequence<sal_Int8> ComposerDialog::getImplementationId()
+ {
+ return css::uno::Sequence<sal_Int8>();
+ }
+
+ css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL ComposerDialog::getPropertySetInfo()
+ {
+ Reference< XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) );
+ return xInfo;
+ }
+ ::cppu::IPropertyArrayHelper& ComposerDialog::getInfoHelper()
+ {
+ return *ComposerDialog::getArrayHelper();
+ }
+ ::cppu::IPropertyArrayHelper* ComposerDialog::createArrayHelper( ) const
+ {
+ css::uno::Sequence< css::beans::Property > aProps;
+ describeProperties(aProps);
+ return new ::cppu::OPropertyArrayHelper(aProps);
+ }
+
+ std::unique_ptr<weld::DialogController> ComposerDialog::createDialog(const css::uno::Reference<css::awt::XWindow>& rParent)
+ {
+ // obtain all the objects needed for the dialog
+ Reference< XConnection > xConnection;
+ Reference< XNameAccess > xColumns;
+ try
+ {
+ // the connection the row set is working with
+ if ( !::dbtools::isEmbeddedInDatabase( m_xRowSet, xConnection ) )
+ {
+ Reference< XPropertySet > xRowsetProps( m_xRowSet, UNO_QUERY );
+ if ( xRowsetProps.is() )
+ xRowsetProps->getPropertyValue( PROPERTY_ACTIVE_CONNECTION ) >>= xConnection;
+ }
+
+ // fallback: if there is a connection and thus a row set, but no composer, create one
+ if ( xConnection.is() && !m_xComposer.is() )
+ m_xComposer = ::dbtools::getCurrentSettingsComposer( Reference< XPropertySet >( m_xRowSet, UNO_QUERY ), m_aContext, rParent );
+
+ // the columns of the row set
+ Reference< XColumnsSupplier > xSuppColumns( m_xRowSet, UNO_QUERY );
+ if ( xSuppColumns.is() )
+ xColumns = xSuppColumns->getColumns();
+
+ if ( !xColumns.is() || !xColumns->hasElements() )
+ { // perhaps the composer can supply us with columns? This is necessary for cases
+ // where the dialog is invoked for a rowset which is not yet loaded
+ // #i22878#
+ xSuppColumns.set(m_xComposer, css::uno::UNO_QUERY);
+ if ( xSuppColumns.is() )
+ xColumns = xSuppColumns->getColumns();
+ }
+
+ OSL_ENSURE( xColumns.is() && xColumns->hasElements(), "ComposerDialog::createDialog: not much fun without any columns!" );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+
+ if ( !xConnection.is() || !xColumns.is() || !m_xComposer.is() )
+ {
+ // can't create the dialog if I have improper settings
+ return nullptr;
+ }
+
+ return createComposerDialog(Application::GetFrameWeld(rParent), xConnection, xColumns);
+ }
+
+ // RowsetFilterDialog
+ RowsetFilterDialog::RowsetFilterDialog( const Reference< XComponentContext >& _rxORB )
+ :ComposerDialog( _rxORB )
+ {
+ }
+
+ OUString SAL_CALL RowsetFilterDialog::getImplementationName()
+ {
+ return "com.sun.star.uno.comp.sdb.RowsetFilterDialog";
+ }
+ sal_Bool SAL_CALL RowsetFilterDialog::supportsService(const OUString& _rServiceName)
+ {
+ const css::uno::Sequence< OUString > aSupported(getSupportedServiceNames());
+ for (const OUString& s : aSupported)
+ if (s == _rServiceName)
+ return true;
+
+ return false;
+ }
+ css::uno::Sequence< OUString > SAL_CALL RowsetFilterDialog::getSupportedServiceNames()
+ {
+ return { "com.sun.star.sdb.FilterDialog" };
+ }
+
+ std::unique_ptr<weld::GenericDialogController> RowsetFilterDialog::createComposerDialog(weld::Window* _pParent, const Reference< XConnection >& _rxConnection, const Reference< XNameAccess >& _rxColumns )
+ {
+ return std::make_unique<DlgFilterCrit>(_pParent, m_aContext, _rxConnection, m_xComposer, _rxColumns);
+ }
+
+ void SAL_CALL RowsetFilterDialog::initialize( const Sequence< Any >& aArguments )
+ {
+ if( aArguments.getLength() == 3 )
+ {
+ // this is the FilterDialog::createWithQuery method
+ Reference<css::sdb::XSingleSelectQueryComposer> xQueryComposer;
+ aArguments[0] >>= xQueryComposer;
+ Reference<css::sdbc::XRowSet> xRowSet;
+ aArguments[1] >>= xRowSet;
+ Reference<css::awt::XWindow> xParentWindow;
+ aArguments[2] >>= xParentWindow;
+ setPropertyValue( "QueryComposer", Any( xQueryComposer ) );
+ setPropertyValue( "RowSet", Any( xRowSet ) );
+ setPropertyValue( "ParentWindow", Any( xParentWindow ) );
+ }
+ else
+ ComposerDialog::initialize(aArguments);
+ }
+
+ void RowsetFilterDialog::executedDialog( sal_Int16 _nExecutionResult )
+ {
+ ComposerDialog::executedDialog( _nExecutionResult );
+
+ if ( _nExecutionResult && m_xDialog )
+ static_cast<DlgFilterCrit*>(m_xDialog.get())->BuildWherePart();
+ }
+
+ // RowsetOrderDialog
+ RowsetOrderDialog::RowsetOrderDialog( const Reference< XComponentContext >& _rxORB )
+ :ComposerDialog( _rxORB )
+ {
+ }
+
+ OUString SAL_CALL RowsetOrderDialog::getImplementationName()
+ {
+ return "com.sun.star.uno.comp.sdb.RowsetOrderDialog";
+ }
+ sal_Bool SAL_CALL RowsetOrderDialog::supportsService(const OUString& _rServiceName)
+ {
+ const css::uno::Sequence< OUString > aSupported(getSupportedServiceNames());
+ for (const OUString& s : aSupported)
+ if (s == _rServiceName)
+ return true;
+
+ return false;
+ }
+ css::uno::Sequence< OUString > SAL_CALL RowsetOrderDialog::getSupportedServiceNames()
+ {
+ return { "com.sun.star.sdb.OrderDialog" };
+ }
+
+ std::unique_ptr<weld::GenericDialogController> RowsetOrderDialog::createComposerDialog(weld::Window* pParent, const Reference< XConnection >& rxConnection, const Reference< XNameAccess >& rxColumns)
+ {
+ return std::make_unique<DlgOrderCrit>(pParent, rxConnection, m_xComposer, rxColumns);
+ }
+
+ void SAL_CALL RowsetOrderDialog::initialize( const Sequence< Any >& aArguments )
+ {
+ if (aArguments.getLength() == 2 || aArguments.getLength() == 3)
+ {
+ Reference<css::sdb::XSingleSelectQueryComposer> xQueryComposer;
+ aArguments[0] >>= xQueryComposer;
+ Reference<css::beans::XPropertySet> xRowSet;
+ aArguments[1] >>= xRowSet;
+ setPropertyValue( "QueryComposer", Any( xQueryComposer ) );
+ setPropertyValue( "RowSet", Any( xRowSet ) );
+ if (aArguments.getLength() == 3)
+ {
+ Reference<css::awt::XWindow> xParentWindow;
+ aArguments[2] >>= xParentWindow;
+ setPropertyValue("ParentWindow", Any(xParentWindow));
+ }
+ }
+ else
+ ComposerDialog::initialize(aArguments);
+ }
+
+ void RowsetOrderDialog::executedDialog( sal_Int16 _nExecutionResult )
+ {
+ ComposerDialog::executedDialog( _nExecutionResult );
+
+ if ( !m_xDialog )
+ return;
+
+ if ( _nExecutionResult )
+ static_cast<DlgOrderCrit*>(m_xDialog.get())->BuildOrderPart();
+ else if ( m_xComposer.is() )
+ m_xComposer->setOrder(static_cast<DlgOrderCrit*>(m_xDialog.get())->GetOriginalOrder());
+ }
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/uno/composerdialogs.hxx b/dbaccess/source/ui/uno/composerdialogs.hxx
new file mode 100644
index 000000000..4e71b1c64
--- /dev/null
+++ b/dbaccess/source/ui/uno/composerdialogs.hxx
@@ -0,0 +1,123 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <com/sun/star/container/XNameAccess.hpp>
+#include <com/sun/star/sdbc/XConnection.hpp>
+#include <com/sun/star/sdb/XSingleSelectQueryComposer.hpp>
+#include <com/sun/star/sdbc/XRowSet.hpp>
+
+#include <comphelper/proparrhlp.hxx>
+#include <connectivity/CommonTools.hxx>
+#include <svtools/genericunodialog.hxx>
+
+namespace dbaui
+{
+
+ // ComposerDialog
+ class ComposerDialog;
+ typedef ::comphelper::OPropertyArrayUsageHelper< ComposerDialog > ComposerDialog_PBASE;
+
+ class ComposerDialog
+ :public svt::OGenericUnoDialog
+ ,public ComposerDialog_PBASE
+ {
+ protected:
+ // <properties>
+ css::uno::Reference< css::sdb::XSingleSelectQueryComposer >
+ m_xComposer;
+ css::uno::Reference< css::sdbc::XRowSet >
+ m_xRowSet;
+ // </properties>
+
+ protected:
+ explicit ComposerDialog(const css::uno::Reference< css::uno::XComponentContext >& _rxORB);
+ virtual ~ComposerDialog() override;
+
+ public:
+ virtual css::uno::Sequence<sal_Int8> SAL_CALL getImplementationId() override;
+
+ virtual css::uno::Reference< css::beans::XPropertySetInfo> SAL_CALL getPropertySetInfo() override;
+ virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper() override;
+ virtual ::cppu::IPropertyArrayHelper* createArrayHelper() const override;
+
+ protected:
+ // own overridables
+ virtual std::unique_ptr<weld::GenericDialogController> createComposerDialog(
+ weld::Window* _pParent,
+ const css::uno::Reference< css::sdbc::XConnection >& _rxConnection,
+ const css::uno::Reference< css::container::XNameAccess >& _rxColumns
+ ) = 0;
+
+ private:
+ // OGenericUnoDialog overridables
+ virtual std::unique_ptr<weld::DialogController> createDialog(const css::uno::Reference<css::awt::XWindow>& rParent) override;
+ };
+
+ // RowsetFilterDialog
+ class RowsetFilterDialog : public ComposerDialog
+ {
+ public:
+ explicit RowsetFilterDialog(
+ const css::uno::Reference< css::uno::XComponentContext >& _rxORB
+ );
+
+ DECLARE_SERVICE_INFO();
+
+ protected:
+ // own overridables
+ virtual std::unique_ptr<weld::GenericDialogController> createComposerDialog(
+ weld::Window* _pParent,
+ const css::uno::Reference< css::sdbc::XConnection >& _rxConnection,
+ const css::uno::Reference< css::container::XNameAccess >& _rxColumns
+ ) override;
+
+ // OGenericUnoDialog overridables
+ virtual void executedDialog( sal_Int16 _nExecutionResult ) override;
+ virtual void SAL_CALL initialize( const css::uno::Sequence< css::uno::Any >& aArguments ) override;
+
+ };
+
+ // RowsetOrderDialog
+ class RowsetOrderDialog : public ComposerDialog
+ {
+ public:
+ explicit RowsetOrderDialog(
+ const css::uno::Reference< css::uno::XComponentContext >& _rxORB
+ );
+
+ DECLARE_SERVICE_INFO();
+
+ protected:
+ // own overridables
+ virtual std::unique_ptr<weld::GenericDialogController> createComposerDialog(
+ weld::Window* _pParent,
+ const css::uno::Reference< css::sdbc::XConnection >& _rxConnection,
+ const css::uno::Reference< css::container::XNameAccess >& _rxColumns
+ ) override;
+
+ // OGenericUnoDialog overridables
+ virtual void executedDialog( sal_Int16 _nExecutionResult ) override;
+ virtual void SAL_CALL initialize( const css::uno::Sequence< css::uno::Any >& aArguments ) override;
+ };
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/uno/copytablewizard.cxx b/dbaccess/source/ui/uno/copytablewizard.cxx
new file mode 100644
index 000000000..09ec99415
--- /dev/null
+++ b/dbaccess/source/ui/uno/copytablewizard.cxx
@@ -0,0 +1,1579 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <memory>
+#include <strings.hrc>
+#include <strings.hxx>
+#include <core_resource.hxx>
+#include <WCopyTable.hxx>
+
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/sdb/application/XCopyTableWizard.hpp>
+#include <com/sun/star/sdb/application/CopyTableContinuation.hpp>
+#include <com/sun/star/sdb/application/CopyTableOperation.hpp>
+#include <com/sun/star/ucb/AlreadyInitializedException.hpp>
+#include <com/sun/star/lang/NotInitializedException.hpp>
+#include <com/sun/star/sdbc/XDataSource.hpp>
+#include <com/sun/star/sdbc/DataType.hpp>
+#include <com/sun/star/container/XNameAccess.hpp>
+#include <com/sun/star/container/XChild.hpp>
+#include <com/sun/star/task/InteractionHandler.hpp>
+#include <com/sun/star/frame/XModel.hpp>
+#include <com/sun/star/sdb/DatabaseContext.hpp>
+#include <com/sun/star/sdb/XDocumentDataSource.hpp>
+#include <com/sun/star/sdb/XCompletedConnection.hpp>
+#include <com/sun/star/sdb/CommandType.hpp>
+#include <com/sun/star/sdbcx/XTablesSupplier.hpp>
+#include <com/sun/star/sdb/XQueriesSupplier.hpp>
+#include <com/sun/star/lang/DisposedException.hpp>
+#include <com/sun/star/sdb/XSingleSelectQueryComposer.hpp>
+#include <com/sun/star/sdbc/XParameters.hpp>
+#include <com/sun/star/sdbc/XRow.hpp>
+#include <com/sun/star/sdbcx/XRowLocate.hpp>
+#include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp>
+#include <com/sun/star/sdb/SQLContext.hpp>
+#include <com/sun/star/sdbc/DriverManager.hpp>
+#include <com/sun/star/sdbc/ConnectionPool.hpp>
+
+#include <comphelper/processfactory.hxx>
+#include <comphelper/interaction.hxx>
+#include <comphelper/namedvaluecollection.hxx>
+#include <comphelper/proparrhlp.hxx>
+#include <connectivity/dbexception.hxx>
+#include <connectivity/dbtools.hxx>
+#include <cppuhelper/exc_hlp.hxx>
+#include <cppuhelper/implbase.hxx>
+#include <comphelper/interfacecontainer3.hxx>
+#include <o3tl/safeint.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <sal/log.hxx>
+#include <svtools/genericunodialog.hxx>
+#include <toolkit/helper/vclunohelper.hxx>
+#include <tools/diagnose_ex.h>
+#include <unotools/sharedunocomponent.hxx>
+#include <vcl/svapp.hxx>
+
+namespace dbaui
+{
+
+ using ::com::sun::star::uno::Reference;
+ using ::com::sun::star::uno::XInterface;
+ using ::com::sun::star::uno::UNO_QUERY;
+ using ::com::sun::star::uno::UNO_QUERY_THROW;
+ using ::com::sun::star::uno::UNO_SET_THROW;
+ using ::com::sun::star::uno::Exception;
+ using ::com::sun::star::uno::RuntimeException;
+ using ::com::sun::star::uno::Any;
+ using ::com::sun::star::uno::Sequence;
+ using ::com::sun::star::uno::XComponentContext;
+ using ::com::sun::star::beans::XPropertySetInfo;
+ using ::com::sun::star::lang::XMultiServiceFactory;
+ using ::com::sun::star::beans::Property;
+ using ::com::sun::star::sdb::application::XCopyTableWizard;
+ using ::com::sun::star::sdb::application::XCopyTableListener;
+ using ::com::sun::star::sdb::application::CopyTableRowEvent;
+ using ::com::sun::star::beans::Optional;
+ using ::com::sun::star::lang::IllegalArgumentException;
+ using ::com::sun::star::ucb::AlreadyInitializedException;
+ using ::com::sun::star::beans::XPropertySet;
+ using ::com::sun::star::lang::NotInitializedException;
+ using ::com::sun::star::lang::XServiceInfo;
+ using ::com::sun::star::sdbc::XConnection;
+ using ::com::sun::star::sdbc::XDataSource;
+ using ::com::sun::star::container::XNameAccess;
+ using ::com::sun::star::container::XChild;
+ using ::com::sun::star::task::InteractionHandler;
+ using ::com::sun::star::task::XInteractionHandler;
+ using ::com::sun::star::frame::XModel;
+ using ::com::sun::star::sdb::DatabaseContext;
+ using ::com::sun::star::sdb::XDatabaseContext;
+ using ::com::sun::star::sdb::XDocumentDataSource;
+ using ::com::sun::star::sdb::XCompletedConnection;
+ using ::com::sun::star::lang::WrappedTargetException;
+ using ::com::sun::star::sdbcx::XTablesSupplier;
+ using ::com::sun::star::sdb::XQueriesSupplier;
+ using ::com::sun::star::lang::DisposedException;
+ using ::com::sun::star::sdbc::XPreparedStatement;
+ using ::com::sun::star::sdb::XSingleSelectQueryComposer;
+ using ::com::sun::star::sdbc::XDatabaseMetaData;
+ using ::com::sun::star::sdbcx::XColumnsSupplier;
+ using ::com::sun::star::sdbc::XParameters;
+ using ::com::sun::star::sdbc::XResultSet;
+ using ::com::sun::star::sdbc::XRow;
+ using ::com::sun::star::sdbcx::XRowLocate;
+ using ::com::sun::star::sdbc::XResultSetMetaDataSupplier;
+ using ::com::sun::star::sdbc::XResultSetMetaData;
+ using ::com::sun::star::sdbc::SQLException;
+ using ::com::sun::star::sdb::SQLContext;
+ using ::com::sun::star::sdbc::ConnectionPool;
+ using ::com::sun::star::sdbc::XDriverManager;
+ using ::com::sun::star::sdbc::DriverManager;
+ using ::com::sun::star::beans::PropertyValue;
+
+ namespace CopyTableOperation = ::com::sun::star::sdb::application::CopyTableOperation;
+ namespace CopyTableContinuation = ::com::sun::star::sdb::application::CopyTableContinuation;
+ namespace CommandType = ::com::sun::star::sdb::CommandType;
+ namespace DataType = ::com::sun::star::sdbc::DataType;
+
+ typedef ::utl::SharedUNOComponent< XConnection > SharedConnection;
+
+ // CopyTableWizard
+ typedef ::svt::OGenericUnoDialog CopyTableWizard_DialogBase;
+ typedef ::cppu::ImplInheritanceHelper< CopyTableWizard_DialogBase
+ , XCopyTableWizard
+ > CopyTableWizard_Base;
+
+ namespace {
+
+ class CopyTableWizard
+ :public CopyTableWizard_Base
+ ,public ::comphelper::OPropertyArrayUsageHelper< CopyTableWizard >
+ {
+ public:
+ // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override;
+
+ // XCopyTableWizard
+ virtual ::sal_Int16 SAL_CALL getOperation() override;
+ virtual void SAL_CALL setOperation( ::sal_Int16 _operation ) override;
+ virtual OUString SAL_CALL getDestinationTableName() override;
+ virtual void SAL_CALL setDestinationTableName( const OUString& _destinationTableName ) override;
+ virtual Optional< OUString > SAL_CALL getCreatePrimaryKey() override;
+ virtual void SAL_CALL setCreatePrimaryKey( const Optional< OUString >& _newPrimaryKey ) override;
+ virtual sal_Bool SAL_CALL getUseHeaderLineAsColumnNames() override;
+ virtual void SAL_CALL setUseHeaderLineAsColumnNames( sal_Bool _bUseHeaderLineAsColumnNames ) override;
+ virtual void SAL_CALL addCopyTableListener( const Reference< XCopyTableListener >& Listener ) override;
+ virtual void SAL_CALL removeCopyTableListener( const Reference< XCopyTableListener >& Listener ) override;
+
+ // XCopyTableWizard::XExecutableDialog
+ virtual void SAL_CALL setTitle( const OUString& aTitle ) override;
+ virtual ::sal_Int16 SAL_CALL execute( ) override;
+
+ // XInitialization
+ virtual void SAL_CALL initialize( const Sequence< Any >& aArguments ) override;
+
+ // XPropertySet
+ virtual Reference< XPropertySetInfo > SAL_CALL getPropertySetInfo() override;
+ virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper() override;
+
+ // OPropertyArrayUsageHelper
+ virtual ::cppu::IPropertyArrayHelper* createArrayHelper( ) const override;
+
+ public:
+ ::osl::Mutex& getMutex() { return m_aMutex; }
+ bool isInitialized() const { return m_xSourceConnection.is() && m_pSourceObject && m_xDestConnection.is(); }
+
+ explicit CopyTableWizard( const Reference< XComponentContext >& _rxORB );
+ virtual ~CopyTableWizard() override;
+
+ protected:
+ // OGenericUnoDialog overridables
+ virtual std::unique_ptr<weld::DialogController> createDialog(const css::uno::Reference<css::awt::XWindow>& rParent) override;
+ virtual void executedDialog( sal_Int16 _nExecutionResult ) override;
+
+ private:
+ /// ensures our current attribute values are reflected in the dialog
+ void impl_attributesToDialog_nothrow( OCopyTableWizard& _rDialog ) const;
+
+ /// ensures the current dialog settings are reflected in our attributes
+ void impl_dialogToAttributes_nothrow( const OCopyTableWizard& _rDialog );
+
+ /** returns our typed dialog
+
+ @throws css::uno::RuntimeException
+ if we don't have a dialog at the moment the method is called
+ */
+ OCopyTableWizard&
+ impl_getDialog_throw();
+
+ /** ensures the given argument sequence contains a valid data access descriptor at the given position
+ @param _rAllArgs
+ the arguments as passed to ->initialize
+ @param _nArgPos
+ the position within ->_rAllArgs which contains the data access descriptor
+ @param _out_rxConnection
+ will, upon successful return, contain the connection for the data source
+ @param _out_rxDocInteractionHandler
+ will, upon successful return, contain the interaction handler which could
+ be deduced from database document described by the descriptor, if any.
+ (It is possible that the descriptor does not allow to deduce a database document,
+ in which case <code>_out_rxDocInteractionHandler</code> will be <NULL/>.)
+ @return the data access descriptor
+ */
+ Reference< XPropertySet >
+ impl_ensureDataAccessDescriptor_throw(
+ const Sequence< Any >& _rAllArgs,
+ const sal_Int16 _nArgPos,
+ SharedConnection& _out_rxConnection,
+ Reference< XInteractionHandler >& _out_rxDocInteractionHandler
+ ) const;
+
+ /** extracts the source object (table or query) described by the given descriptor,
+ relative to m_xSourceConnection
+ */
+ std::unique_ptr< ICopyTableSourceObject >
+ impl_extractSourceObject_throw(
+ const Reference< XPropertySet >& _rxDescriptor,
+ sal_Int32& _out_rCommandType
+ ) const;
+
+ /** extracts the result set to copy records from, and the selection-related aspects, if any.
+
+ Effectively, this method extracts m_xSourceResultSet, m_aSourceSelection, and m_bSourceSelectionBookmarks.
+
+ If an inconsistent/insufficient sub set of those properties is present in the descriptor, and exception
+ is thrown.
+ */
+ void impl_extractSourceResultSet_throw(
+ const Reference< XPropertySet >& i_rDescriptor
+ );
+
+ /** checks whether the given copy source descriptor contains settings which are not
+ supported (yet)
+
+ Throws an IllegalArgumentException if the descriptor contains a valid setting, which is
+ not yet supported.
+ */
+ void impl_checkForUnsupportedSettings_throw(
+ const Reference< XPropertySet >& _rxSourceDescriptor ) const;
+
+ /** obtains the connection described by the given data access descriptor
+
+ If needed and possible, the method will ask the user, using the interaction
+ handler associated with the database described by the descriptor.
+
+ All errors are handled with the InteractionHandler associated with the data source,
+ if there is one. Else, they will be silenced (but asserted in non-product builds).
+
+ @param _rxDataSourceDescriptor
+ the data access descriptor describing the data source whose connection
+ should be obtained. Must not be <NULL/>.
+ @param _out_rxDocInteractionHandler
+ the interaction handler which could be deduced from the descriptor
+
+ @throws RuntimeException
+ if anything goes seriously wrong.
+ */
+ SharedConnection
+ impl_extractConnection_throw(
+ const Reference< XPropertySet >& _rxDataSourceDescriptor,
+ Reference< XInteractionHandler >& _out_rxDocInteractionHandler
+ ) const;
+
+ /** actually copies the table
+
+ This method is called after the dialog has been successfully executed.
+ */
+ void impl_doCopy_nothrow();
+
+ /** creates the INSERT INTO statement
+ @param _xTable The destination table.
+ */
+ OUString impl_getServerSideCopyStatement_throw( const Reference< XPropertySet >& _xTable );
+
+ /** creates the statement which, when executed, will produce the source data to copy
+
+ If the source object refers to a query which contains parameters, those parameters
+ are filled in, using an interaction handler.
+ */
+ ::utl::SharedUNOComponent< XPreparedStatement >
+ impl_createSourceStatement_throw() const;
+
+ /** copies the data rows from the given source result set to the given destination table
+ */
+ void impl_copyRows_throw(
+ const Reference< XResultSet >& _rxSourceResultSet,
+ const Reference< XPropertySet >& _rxDestTable
+ );
+
+ /** processes an error which occurred during copying
+
+ First, all listeners are ask. If a listener tells to cancel or continue copying, this is reported to the
+ method's caller. If a listener tells to ask the user, this is done, and the user's decision is
+ reported to the method's caller.
+
+ @return
+ <TRUE/> if and only if copying should be continued.
+ */
+ bool impl_processCopyError_nothrow(
+ const CopyTableRowEvent& _rEvent );
+
+private:
+ Reference<XComponentContext> m_xContext;
+
+ // attributes
+ sal_Int16 m_nOperation;
+ OUString m_sDestinationTable;
+ Optional< OUString > m_aPrimaryKeyName;
+ bool m_bUseHeaderLineAsColumnNames;
+
+ // source
+ SharedConnection m_xSourceConnection;
+ sal_Int32 m_nCommandType;
+ std::unique_ptr< ICopyTableSourceObject >
+ m_pSourceObject;
+ Reference< XResultSet > m_xSourceResultSet;
+ Sequence< Any > m_aSourceSelection;
+ bool m_bSourceSelectionBookmarks;
+
+ // destination
+ SharedConnection m_xDestConnection;
+
+ // other
+ Reference< XInteractionHandler > m_xInteractionHandler;
+ ::comphelper::OInterfaceContainerHelper3<XCopyTableListener>
+ m_aCopyTableListeners;
+ sal_Int16 m_nOverrideExecutionResult;
+ };
+
+// MethodGuard
+class CopyTableAccessGuard
+{
+public:
+ explicit CopyTableAccessGuard( CopyTableWizard& _rWizard )
+ :m_rWizard( _rWizard )
+ {
+ m_rWizard.getMutex().acquire();
+ if ( !m_rWizard.isInitialized() )
+ throw NotInitializedException();
+ }
+
+ ~CopyTableAccessGuard()
+ {
+ m_rWizard.getMutex().release();
+ }
+
+private:
+ CopyTableWizard& m_rWizard;
+};
+
+}
+
+CopyTableWizard::CopyTableWizard( const Reference< XComponentContext >& _rxORB )
+ :CopyTableWizard_Base( _rxORB )
+ ,m_xContext( _rxORB )
+ ,m_nOperation( CopyTableOperation::CopyDefinitionAndData )
+ ,m_aPrimaryKeyName( false, "ID" )
+ ,m_bUseHeaderLineAsColumnNames( true )
+ ,m_nCommandType( CommandType::COMMAND )
+ ,m_bSourceSelectionBookmarks( true )
+ ,m_aCopyTableListeners( m_aMutex )
+ ,m_nOverrideExecutionResult( -1 )
+{
+}
+
+CopyTableWizard::~CopyTableWizard()
+{
+ acquire();
+
+ // protect some members whose dtor might potentially throw
+ try { m_xSourceConnection.clear(); }
+ catch( const Exception& ) { DBG_UNHANDLED_EXCEPTION("dbaccess"); }
+ try { m_xDestConnection.clear(); }
+ catch( const Exception& ) { DBG_UNHANDLED_EXCEPTION("dbaccess"); }
+
+ // TODO: shouldn't we have explicit disposal support? If a listener is registered
+ // at our instance, and perhaps holds this our instance by a hard ref, then we'll never
+ // be destroyed.
+ // However, adding XComponent support to the GenericUNODialog probably requires
+ // some thinking - would it break existing clients which do not call a dispose, then?
+}
+
+OUString SAL_CALL CopyTableWizard::getImplementationName()
+{
+ return "org.openoffice.comp.dbu.CopyTableWizard";
+}
+
+css::uno::Sequence<OUString> SAL_CALL CopyTableWizard::getSupportedServiceNames()
+{
+ return { "com.sun.star.sdb.application.CopyTableWizard" };
+}
+
+Reference< XPropertySetInfo > SAL_CALL CopyTableWizard::getPropertySetInfo()
+{
+ Reference< XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) );
+ return xInfo;
+}
+
+::sal_Int16 SAL_CALL CopyTableWizard::getOperation()
+{
+ CopyTableAccessGuard aGuard( *this );
+ return m_nOperation;
+}
+
+void SAL_CALL CopyTableWizard::setOperation( ::sal_Int16 _operation )
+{
+ CopyTableAccessGuard aGuard( *this );
+
+ if ( ( _operation != CopyTableOperation::CopyDefinitionAndData )
+ && ( _operation != CopyTableOperation::CopyDefinitionOnly )
+ && ( _operation != CopyTableOperation::CreateAsView )
+ && ( _operation != CopyTableOperation::AppendData )
+ )
+ throw IllegalArgumentException( OUString(), *this, 1 );
+
+ if ( ( _operation == CopyTableOperation::CreateAsView )
+ && !OCopyTableWizard::supportsViews( m_xDestConnection )
+ )
+ throw IllegalArgumentException(
+ DBA_RES( STR_CTW_NO_VIEWS_SUPPORT ),
+ *this,
+ 1
+ );
+
+ m_nOperation = _operation;
+}
+
+OUString SAL_CALL CopyTableWizard::getDestinationTableName()
+{
+ CopyTableAccessGuard aGuard( *this );
+ return m_sDestinationTable;
+}
+
+void SAL_CALL CopyTableWizard::setDestinationTableName( const OUString& _destinationTableName )
+{
+ CopyTableAccessGuard aGuard( *this );
+ m_sDestinationTable = _destinationTableName;
+}
+
+Optional< OUString > SAL_CALL CopyTableWizard::getCreatePrimaryKey()
+{
+ CopyTableAccessGuard aGuard( *this );
+ return m_aPrimaryKeyName;
+}
+
+void SAL_CALL CopyTableWizard::setCreatePrimaryKey( const Optional< OUString >& _newPrimaryKey )
+{
+ CopyTableAccessGuard aGuard( *this );
+
+ if ( _newPrimaryKey.IsPresent && !OCopyTableWizard::supportsPrimaryKey( m_xDestConnection ) )
+ throw IllegalArgumentException(
+ DBA_RES( STR_CTW_NO_PRIMARY_KEY_SUPPORT ),
+ *this,
+ 1
+ );
+
+ m_aPrimaryKeyName = _newPrimaryKey;
+}
+
+sal_Bool SAL_CALL CopyTableWizard::getUseHeaderLineAsColumnNames()
+{
+ CopyTableAccessGuard aGuard( *this );
+ return m_bUseHeaderLineAsColumnNames;
+}
+
+void SAL_CALL CopyTableWizard::setUseHeaderLineAsColumnNames( sal_Bool _bUseHeaderLineAsColumnNames )
+{
+ CopyTableAccessGuard aGuard( *this );
+ m_bUseHeaderLineAsColumnNames = _bUseHeaderLineAsColumnNames;
+}
+
+void SAL_CALL CopyTableWizard::addCopyTableListener( const Reference< XCopyTableListener >& _rxListener )
+{
+ CopyTableAccessGuard aGuard( *this );
+ if ( _rxListener.is() )
+ m_aCopyTableListeners.addInterface( _rxListener );
+}
+
+void SAL_CALL CopyTableWizard::removeCopyTableListener( const Reference< XCopyTableListener >& _rxListener )
+{
+ CopyTableAccessGuard aGuard( *this );
+ if ( _rxListener.is() )
+ m_aCopyTableListeners.removeInterface( _rxListener );
+}
+
+void SAL_CALL CopyTableWizard::setTitle( const OUString& _rTitle )
+{
+ CopyTableAccessGuard aGuard( *this );
+ CopyTableWizard_DialogBase::setTitle( _rTitle );
+}
+
+::sal_Int16 SAL_CALL CopyTableWizard::execute( )
+{
+ CopyTableAccessGuard aGuard( *this );
+
+ m_nOverrideExecutionResult = -1;
+ sal_Int16 nExecutionResult = CopyTableWizard_DialogBase::execute();
+ if ( m_nOverrideExecutionResult )
+ nExecutionResult = m_nOverrideExecutionResult;
+
+ return nExecutionResult;
+}
+
+OCopyTableWizard& CopyTableWizard::impl_getDialog_throw()
+{
+ OCopyTableWizard* pWizard = dynamic_cast<OCopyTableWizard*>(m_xDialog.get());
+ if ( !pWizard )
+ throw DisposedException( OUString(), *this );
+ return *pWizard;
+}
+
+void CopyTableWizard::impl_attributesToDialog_nothrow( OCopyTableWizard& _rDialog ) const
+{
+ // primary key column
+ _rDialog.setCreatePrimaryKey( m_aPrimaryKeyName.IsPresent, m_aPrimaryKeyName.Value );
+ _rDialog.setUseHeaderLine(m_bUseHeaderLineAsColumnNames);
+
+ // everything else was passed at construction time already
+}
+
+void CopyTableWizard::impl_dialogToAttributes_nothrow( const OCopyTableWizard& _rDialog )
+{
+ m_aPrimaryKeyName.IsPresent = _rDialog.shouldCreatePrimaryKey();
+ if ( m_aPrimaryKeyName.IsPresent )
+ m_aPrimaryKeyName.Value = _rDialog.getPrimaryKeyName();
+ else
+ m_aPrimaryKeyName.Value.clear();
+
+ m_sDestinationTable = _rDialog.getName();
+
+ m_nOperation = _rDialog.getOperation();
+ m_bUseHeaderLineAsColumnNames = _rDialog.UseHeaderLine();
+}
+
+namespace
+{
+ /** tries to obtain the InteractionHandler associated with a given data source
+
+ If the data source is a sdb-level data source, it will have a DatabaseDocument associated
+ with it. This document may have an InteractionHandler used while loading it.
+
+ @throws RuntimeException
+ if it occurs during invoking any of the data source's methods, or if any of the involved
+ components violates its contract by not providing the required interfaces
+ */
+ Reference< XInteractionHandler > lcl_getInteractionHandler_throw( const Reference< XDataSource >& _rxDataSource, const Reference< XInteractionHandler >& _rFallback )
+ {
+ Reference< XInteractionHandler > xHandler( _rFallback );
+
+ // try to obtain the document model
+ Reference< XModel > xDocumentModel;
+ Reference< XDocumentDataSource > xDocDataSource( _rxDataSource, UNO_QUERY );
+ if ( xDocDataSource.is() )
+ xDocumentModel.set( xDocDataSource->getDatabaseDocument(), UNO_QUERY_THROW );
+
+ // see whether the document model can provide a handler
+ if ( xDocumentModel.is() )
+ {
+ xHandler = ::comphelper::NamedValueCollection::getOrDefault( xDocumentModel->getArgs(), u"InteractionHandler", xHandler );
+ }
+
+ return xHandler;
+ }
+ /** tries to obtain the InteractionHandler associated with a given connection
+
+ If the connection belongs to a sdb-level data source, then this data source
+ is examined for an interaction handler. Else, <NULL/> is returned.
+
+ @throws RuntimeException
+ if it occurs during invoking any of the data source's methods, or if any of the involved
+ components violates its contract by not providing the required interfaces
+ */
+ Reference< XInteractionHandler > lcl_getInteractionHandler_throw( const Reference< XConnection >& _rxConnection, const Reference< XInteractionHandler >& _rFallback )
+ {
+ // try whether there is a data source which the connection belongs to
+ Reference< XDataSource > xDataSource;
+ Reference< XChild > xAsChild( _rxConnection, UNO_QUERY );
+ if ( xAsChild.is() )
+ xDataSource.set(xAsChild->getParent(), css::uno::UNO_QUERY);
+
+ if ( xDataSource.is() )
+ return lcl_getInteractionHandler_throw( xDataSource, _rFallback );
+
+ return _rFallback;
+ }
+}
+
+Reference< XPropertySet > CopyTableWizard::impl_ensureDataAccessDescriptor_throw(
+ const Sequence< Any >& _rAllArgs, const sal_Int16 _nArgPos, SharedConnection& _out_rxConnection,
+ Reference< XInteractionHandler >& _out_rxDocInteractionHandler ) const
+{
+ Reference< XPropertySet > xDescriptor;
+ _rAllArgs[ _nArgPos ] >>= xDescriptor;
+
+ // the descriptor must be non-NULL, of course
+ bool bIsValid = xDescriptor.is();
+
+ // it must support the proper service
+ if ( bIsValid )
+ {
+ Reference< XServiceInfo > xSI( xDescriptor, UNO_QUERY );
+ bIsValid = ( xSI.is()
+ && xSI->supportsService( "com.sun.star.sdb.DataAccessDescriptor" ) );
+ }
+
+ // it must be able to provide a connection
+ if ( bIsValid )
+ {
+ _out_rxConnection = impl_extractConnection_throw( xDescriptor, _out_rxDocInteractionHandler );
+ bIsValid = _out_rxConnection.is();
+ }
+
+ if ( !bIsValid )
+ {
+ throw IllegalArgumentException(
+ DBA_RES( STR_CTW_INVALID_DATA_ACCESS_DESCRIPTOR ),
+ *const_cast< CopyTableWizard* >( this ),
+ _nArgPos + 1
+ );
+ }
+
+ return xDescriptor;
+}
+
+namespace
+{
+ bool lcl_hasNonEmptyStringValue_throw( const Reference< XPropertySet >& _rxDescriptor,
+ const Reference< XPropertySetInfo >& rxPSI, const OUString& _rPropertyName )
+ {
+ OUString sValue;
+ if ( rxPSI->hasPropertyByName( _rPropertyName ) )
+ {
+ OSL_VERIFY( _rxDescriptor->getPropertyValue( _rPropertyName ) >>= sValue );
+ }
+ return !sValue.isEmpty();
+ }
+}
+
+void CopyTableWizard::impl_checkForUnsupportedSettings_throw( const Reference< XPropertySet >& _rxSourceDescriptor ) const
+{
+ OSL_PRECOND( _rxSourceDescriptor.is(), "CopyTableWizard::impl_checkForUnsupportedSettings_throw: illegal argument!" );
+ Reference< XPropertySetInfo > xPSI( _rxSourceDescriptor->getPropertySetInfo(), UNO_SET_THROW );
+ OUString sUnsupportedSetting;
+
+ const OUString aSettings[] = {
+ OUString(PROPERTY_FILTER), OUString(PROPERTY_ORDER), OUString(PROPERTY_HAVING_CLAUSE), OUString(PROPERTY_GROUP_BY)
+ };
+ for (const auto & aSetting : aSettings)
+ {
+ if ( lcl_hasNonEmptyStringValue_throw( _rxSourceDescriptor, xPSI, aSetting ) )
+ {
+ sUnsupportedSetting = aSetting;
+ break;
+ }
+ }
+
+ if ( !sUnsupportedSetting.isEmpty() )
+ {
+ OUString sMessage(
+ DBA_RES(STR_CTW_ERROR_UNSUPPORTED_SETTING).
+ replaceFirst("$name$", sUnsupportedSetting));
+ throw IllegalArgumentException(
+ sMessage,
+ *const_cast< CopyTableWizard* >( this ),
+ 1
+ );
+ }
+
+}
+
+std::unique_ptr< ICopyTableSourceObject > CopyTableWizard::impl_extractSourceObject_throw( const Reference< XPropertySet >& _rxDescriptor, sal_Int32& _out_rCommandType ) const
+{
+ OSL_PRECOND( _rxDescriptor.is() && m_xSourceConnection.is(), "CopyTableWizard::impl_extractSourceObject_throw: illegal arguments!" );
+
+ Reference< XPropertySetInfo > xPSI( _rxDescriptor->getPropertySetInfo(), UNO_SET_THROW );
+ if ( !xPSI->hasPropertyByName( PROPERTY_COMMAND )
+ || !xPSI->hasPropertyByName( PROPERTY_COMMAND_TYPE )
+ )
+ throw IllegalArgumentException("Expecting a table or query specification.",
+ // TODO: resource
+ *const_cast< CopyTableWizard* >( this ), 1);
+
+ OUString sCommand;
+ _out_rCommandType = CommandType::COMMAND;
+ OSL_VERIFY( _rxDescriptor->getPropertyValue( PROPERTY_COMMAND ) >>= sCommand );
+ OSL_VERIFY( _rxDescriptor->getPropertyValue( PROPERTY_COMMAND_TYPE ) >>= _out_rCommandType );
+
+ std::unique_ptr< ICopyTableSourceObject > pSourceObject;
+ Reference< XNameAccess > xContainer;
+ switch ( _out_rCommandType )
+ {
+ case CommandType::TABLE:
+ {
+ Reference< XTablesSupplier > xSuppTables( m_xSourceConnection.getTyped(), UNO_QUERY );
+ if ( xSuppTables.is() )
+ xContainer.set( xSuppTables->getTables(), UNO_SET_THROW );
+ }
+ break;
+ case CommandType::QUERY:
+ {
+ Reference< XQueriesSupplier > xSuppQueries( m_xSourceConnection.getTyped(), UNO_QUERY );
+ if ( xSuppQueries.is() )
+ xContainer.set( xSuppQueries->getQueries(), UNO_SET_THROW );
+ }
+ break;
+ default:
+ throw IllegalArgumentException(
+ DBA_RES( STR_CTW_ONLY_TABLES_AND_QUERIES_SUPPORT ),
+ *const_cast< CopyTableWizard* >( this ),
+ 1
+ );
+ }
+
+ if ( xContainer.is() )
+ {
+ pSourceObject.reset( new ObjectCopySource( m_xSourceConnection,
+ Reference< XPropertySet >( xContainer->getByName( sCommand ), UNO_QUERY_THROW ) ) );
+ }
+ else
+ {
+ // our source connection is an SDBC level connection only, not a SDBCX level one
+ // Which means it cannot provide the to-be-copied object as component.
+
+ if ( _out_rCommandType == CommandType::QUERY )
+ // we cannot copy a query if the connection cannot provide it ...
+ throw IllegalArgumentException(
+ DBA_RES( STR_CTW_ERROR_NO_QUERY ),
+ *const_cast< CopyTableWizard* >( this ),
+ 1
+ );
+ pSourceObject.reset( new NamedTableCopySource( m_xSourceConnection, sCommand ) );
+ }
+
+ return pSourceObject;
+}
+
+void CopyTableWizard::impl_extractSourceResultSet_throw( const Reference< XPropertySet >& i_rDescriptor )
+{
+ Reference< XPropertySetInfo > xPSI( i_rDescriptor->getPropertySetInfo(), UNO_SET_THROW );
+
+ // extract relevant settings
+ if ( xPSI->hasPropertyByName( PROPERTY_RESULT_SET ) )
+ m_xSourceResultSet.set( i_rDescriptor->getPropertyValue( PROPERTY_RESULT_SET ), UNO_QUERY );
+
+ if ( xPSI->hasPropertyByName( PROPERTY_SELECTION ) )
+ OSL_VERIFY( i_rDescriptor->getPropertyValue( PROPERTY_SELECTION ) >>= m_aSourceSelection );
+
+ if ( xPSI->hasPropertyByName( PROPERTY_BOOKMARK_SELECTION ) )
+ OSL_VERIFY( i_rDescriptor->getPropertyValue( PROPERTY_BOOKMARK_SELECTION ) >>= m_bSourceSelectionBookmarks );
+
+ // sanity checks
+ const bool bHasResultSet = m_xSourceResultSet.is();
+ const bool bHasSelection = m_aSourceSelection.hasElements();
+ if ( bHasSelection && !bHasResultSet )
+ throw IllegalArgumentException("A result set is needed when specifying a selection to copy.",
+ // TODO: resource
+ *this, 1);
+
+ if ( bHasSelection && m_bSourceSelectionBookmarks )
+ {
+ Reference< XRowLocate > xRowLocate( m_xSourceResultSet, UNO_QUERY );
+ if ( !xRowLocate.is() )
+ {
+ ::dbtools::throwGenericSQLException(
+ DBA_RES(STR_CTW_COPY_SOURCE_NEEDS_BOOKMARKS),
+ *this
+ );
+ }
+ }
+}
+
+SharedConnection CopyTableWizard::impl_extractConnection_throw( const Reference< XPropertySet >& _rxDataSourceDescriptor,
+ Reference< XInteractionHandler >& _out_rxDocInteractionHandler ) const
+{
+ SharedConnection xConnection;
+
+ OSL_PRECOND( _rxDataSourceDescriptor.is(), "CopyTableWizard::impl_extractConnection_throw: no descriptor!" );
+ if ( !_rxDataSourceDescriptor.is() )
+ return xConnection;
+
+ Reference< XInteractionHandler > xInteractionHandler;
+
+ do
+ {
+ Reference< XPropertySetInfo > xPSI( _rxDataSourceDescriptor->getPropertySetInfo(), UNO_SET_THROW );
+
+ // if there's an ActiveConnection, use it
+ if ( xPSI->hasPropertyByName( PROPERTY_ACTIVE_CONNECTION ) )
+ {
+ Reference< XConnection > xPure;
+ OSL_VERIFY( _rxDataSourceDescriptor->getPropertyValue( PROPERTY_ACTIVE_CONNECTION ) >>= xPure );
+ xConnection.reset( xPure, SharedConnection::NoTakeOwnership );
+ }
+ if ( xConnection.is() )
+ {
+ xInteractionHandler = lcl_getInteractionHandler_throw( xConnection.getTyped(), m_xInteractionHandler );
+ SAL_WARN_IF( !xInteractionHandler.is(), "dbaccess.ui", "CopyTableWizard::impl_extractConnection_throw: lcl_getInteractionHandler_throw returned nonsense!" );
+ break;
+ }
+
+ // there could be a DataSourceName or a DatabaseLocation, describing the css.sdb.DataSource
+ OUString sDataSource, sDatabaseLocation;
+ if ( xPSI->hasPropertyByName( PROPERTY_DATASOURCENAME ) )
+ OSL_VERIFY( _rxDataSourceDescriptor->getPropertyValue( PROPERTY_DATASOURCENAME ) >>= sDataSource );
+ if ( xPSI->hasPropertyByName( PROPERTY_DATABASE_LOCATION ) )
+ OSL_VERIFY( _rxDataSourceDescriptor->getPropertyValue( PROPERTY_DATABASE_LOCATION ) >>= sDatabaseLocation );
+
+ // need a DatabaseContext for loading the data source
+ Reference< XDatabaseContext > xDatabaseContext = DatabaseContext::create( m_xContext );
+ Reference< XDataSource > xDataSource;
+ if ( !sDataSource.isEmpty() )
+ xDataSource.set( xDatabaseContext->getByName( sDataSource ), UNO_QUERY_THROW );
+ if ( !xDataSource.is() && !sDatabaseLocation.isEmpty() )
+ xDataSource.set( xDatabaseContext->getByName( sDatabaseLocation ), UNO_QUERY_THROW );
+
+ if ( xDataSource.is() )
+ {
+ // first, try connecting with completion
+ xInteractionHandler = lcl_getInteractionHandler_throw( xDataSource, m_xInteractionHandler );
+ SAL_WARN_IF( !xInteractionHandler.is(), "dbaccess.ui", "CopyTableWizard::impl_extractConnection_throw: lcl_getInteractionHandler_throw returned nonsense!" );
+ if ( xInteractionHandler.is() )
+ {
+ Reference< XCompletedConnection > xInteractiveConnection( xDataSource, UNO_QUERY );
+ if ( xInteractiveConnection.is() )
+ xConnection.reset( xInteractiveConnection->connectWithCompletion( xInteractionHandler ), SharedConnection::TakeOwnership );
+ }
+
+ // interactively connecting was not successful or possible -> connect without interaction
+ if ( !xConnection.is() )
+ {
+ xConnection.reset( xDataSource->getConnection( OUString(), OUString() ), SharedConnection::TakeOwnership );
+ }
+ }
+
+ if ( xConnection.is() )
+ break;
+
+ // finally, there could be a ConnectionResource/ConnectionInfo
+ OUString sConnectionResource;
+ Sequence< PropertyValue > aConnectionInfo;
+ if ( xPSI->hasPropertyByName( PROPERTY_CONNECTION_RESOURCE ) )
+ OSL_VERIFY( _rxDataSourceDescriptor->getPropertyValue( PROPERTY_CONNECTION_RESOURCE ) >>= sConnectionResource );
+ if ( xPSI->hasPropertyByName( PROPERTY_CONNECTION_INFO ) )
+ OSL_VERIFY( _rxDataSourceDescriptor->getPropertyValue( PROPERTY_CONNECTION_INFO ) >>= aConnectionInfo );
+
+ Reference< XDriverManager > xDriverManager;
+ try {
+ xDriverManager.set( ConnectionPool::create( m_xContext ), UNO_QUERY_THROW );
+ } catch( const Exception& ) { }
+ if ( !xDriverManager.is() )
+ // no connection pool installed
+ xDriverManager.set( DriverManager::create( m_xContext ), UNO_QUERY_THROW );
+
+ if ( aConnectionInfo.hasElements() )
+ xConnection.set( xDriverManager->getConnectionWithInfo( sConnectionResource, aConnectionInfo ), UNO_SET_THROW );
+ else
+ xConnection.set( xDriverManager->getConnection( sConnectionResource ), UNO_SET_THROW );
+ }
+ while ( false );
+
+ if ( xInteractionHandler != m_xInteractionHandler )
+ _out_rxDocInteractionHandler = xInteractionHandler;
+
+ return xConnection;
+}
+
+::utl::SharedUNOComponent< XPreparedStatement > CopyTableWizard::impl_createSourceStatement_throw() const
+{
+ OSL_PRECOND( m_xSourceConnection.is(), "CopyTableWizard::impl_createSourceStatement_throw: illegal call!" );
+ if ( !m_xSourceConnection.is() )
+ throw RuntimeException( "CopyTableWizard::impl_createSourceStatement_throw: illegal call!", *const_cast< CopyTableWizard* >( this ));
+
+ ::utl::SharedUNOComponent< XPreparedStatement > xStatement;
+ switch ( m_nCommandType )
+ {
+ case CommandType::TABLE:
+ xStatement.set( m_pSourceObject->getPreparedSelectStatement(), UNO_SET_THROW );
+ break;
+
+ case CommandType::QUERY:
+ {
+ OUString sQueryCommand( m_pSourceObject->getSelectStatement() );
+ xStatement.set( m_pSourceObject->getPreparedSelectStatement(), UNO_SET_THROW );
+
+ // check whether we have to fill in parameter values
+ // create and fill a composer
+
+ Reference< XMultiServiceFactory > xFactory( m_xSourceConnection, UNO_QUERY );
+ ::utl::SharedUNOComponent< XSingleSelectQueryComposer > xComposer;
+ if ( xFactory.is() )
+ // note: connections below the sdb-level are allowed to not support the XMultiServiceFactory interface
+ xComposer.set( xFactory->createInstance( SERVICE_NAME_SINGLESELECTQUERYCOMPOSER ), UNO_QUERY );
+
+ if ( xComposer.is() )
+ {
+ xComposer->setQuery( sQueryCommand );
+
+ Reference< XParameters > xStatementParams( xStatement, UNO_QUERY );
+ OSL_ENSURE( xStatementParams.is(), "CopyTableWizard::impl_createSourceStatement_throw: no access to the statement's parameters!" );
+ // the statement should be a css.sdbc.PreparedStatement (this is what
+ // we created), and a prepared statement is required to support XParameters
+ if ( xStatementParams.is() )
+ {
+ OSL_ENSURE( m_xInteractionHandler.is(),
+ "CopyTableWizard::impl_createSourceStatement_throw: no interaction handler for the parameters request!" );
+ // we should always have an interaction handler - as last fallback, we create an own one in ::initialize
+
+ if ( m_xInteractionHandler.is() )
+ ::dbtools::askForParameters( xComposer, xStatementParams, m_xSourceConnection, m_xInteractionHandler );
+ }
+ }
+ }
+ break;
+
+ default:
+ // this should not have survived initialization phase
+ throw RuntimeException("No case matched, this should not have survived the initialization phase", *const_cast< CopyTableWizard* >( this ));
+ }
+
+ return xStatement;
+}
+
+namespace
+{
+ class ValueTransfer
+ {
+ public:
+ ValueTransfer( std::vector< sal_Int32 > _rColTypes,
+ const Reference< XRow >& _rxSource, const Reference< XParameters >& _rxDest )
+ :m_ColTypes( std::move(_rColTypes) )
+ ,m_xSource( _rxSource )
+ ,m_xDest( _rxDest )
+ {
+ }
+
+ template< typename VALUE_TYPE >
+ void transferValue( sal_Int32 _nSourcePos, sal_Int32 _nDestPos,
+ VALUE_TYPE ( SAL_CALL XRow::*_pGetter )( sal_Int32 ),
+ void (SAL_CALL XParameters::*_pSetter)( sal_Int32, VALUE_TYPE ) )
+ {
+ VALUE_TYPE value( (m_xSource.get()->*_pGetter)( _nSourcePos ) );
+ if ( m_xSource->wasNull() )
+ m_xDest->setNull( _nDestPos, m_ColTypes[ _nSourcePos ] );
+ else
+ (m_xDest.get()->*_pSetter)( _nDestPos, value );
+ }
+
+ template< typename VALUE_TYPE >
+ void transferComplexValue( sal_Int32 _nSourcePos, sal_Int32 _nDestPos,
+ VALUE_TYPE ( SAL_CALL XRow::*_pGetter )( sal_Int32 ),
+ void (SAL_CALL XParameters::*_pSetter)( sal_Int32, const VALUE_TYPE& ) )
+ {
+ const VALUE_TYPE value( (m_xSource.get()->*_pGetter)( _nSourcePos ) );
+ if ( m_xSource->wasNull() )
+ m_xDest->setNull( _nDestPos, m_ColTypes[ _nSourcePos ] );
+ else
+ (m_xDest.get()->*_pSetter)( _nDestPos, value );
+ }
+ private:
+ const std::vector< sal_Int32 > m_ColTypes;
+ const Reference< XRow > m_xSource;
+ const Reference< XParameters > m_xDest;
+ };
+}
+
+bool CopyTableWizard::impl_processCopyError_nothrow( const CopyTableRowEvent& _rEvent )
+{
+ try
+ {
+ ::comphelper::OInterfaceIteratorHelper3 aIter( m_aCopyTableListeners );
+ while ( aIter.hasMoreElements() )
+ {
+ Reference< XCopyTableListener > xListener( aIter.next() );
+ sal_Int16 nListenerChoice = xListener->copyRowError( _rEvent );
+ switch ( nListenerChoice )
+ {
+ case CopyTableContinuation::Proceed: return true; // continue copying
+ case CopyTableContinuation::CallNextHandler: continue; // continue the loop, ask next listener
+ case CopyTableContinuation::Cancel: return false; // cancel copying
+ case CopyTableContinuation::AskUser: break; // stop asking the listeners, ask the user
+
+ default:
+ SAL_WARN("dbaccess.ui", "CopyTableWizard::impl_processCopyError_nothrow: invalid listener response!" );
+ // ask next listener
+ continue;
+ }
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+
+ // no listener felt responsible for the error, or a listener told to ask the user
+
+ try
+ {
+ SQLContext aError;
+ aError.Context = *this;
+ aError.Message = DBA_RES(STR_ERROR_OCCURRED_WHILE_COPYING);
+
+ ::dbtools::SQLExceptionInfo aInfo( _rEvent.Error );
+ if ( aInfo.isValid() )
+ aError.NextException = _rEvent.Error;
+ else
+ {
+ // a non-SQL exception happened
+ Exception aException;
+ OSL_VERIFY( _rEvent.Error >>= aException );
+ SQLContext aContext;
+ aContext.Context = aException.Context;
+ aContext.Message = aException.Message;
+ aContext.Details = _rEvent.Error.getValueTypeName();
+ aError.NextException <<= aContext;
+ }
+
+ ::rtl::Reference< ::comphelper::OInteractionRequest > xRequest( new ::comphelper::OInteractionRequest( Any( aError ) ) );
+
+ ::rtl::Reference< ::comphelper::OInteractionApprove > xYes = new ::comphelper::OInteractionApprove;
+ xRequest->addContinuation( xYes );
+ xRequest->addContinuation( new ::comphelper::OInteractionDisapprove );
+
+ OSL_ENSURE( m_xInteractionHandler.is(),
+ "CopyTableWizard::impl_processCopyError_nothrow: we always should have an interaction handler!" );
+ if ( m_xInteractionHandler.is() )
+ m_xInteractionHandler->handle( xRequest );
+
+ if ( xYes->wasSelected() )
+ // continue copying
+ return true;
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+
+ // cancel copying
+ return false;
+}
+
+void CopyTableWizard::impl_copyRows_throw( const Reference< XResultSet >& _rxSourceResultSet,
+ const Reference< XPropertySet >& _rxDestTable )
+{
+ OSL_PRECOND( m_xDestConnection.is(), "CopyTableWizard::impl_copyRows_throw: illegal call!" );
+ if ( !m_xDestConnection.is() )
+ throw RuntimeException( "m_xDestConnection is set to null, CopyTableWizard::impl_copyRows_throw: illegal call!", *this );
+
+ Reference< XDatabaseMetaData > xDestMetaData( m_xDestConnection->getMetaData(), UNO_SET_THROW );
+
+ const OCopyTableWizard& rWizard = impl_getDialog_throw();
+ ODatabaseExport::TPositions aColumnPositions = rWizard.GetColumnPositions();
+ const bool bShouldCreatePrimaryKey = rWizard.shouldCreatePrimaryKey();
+
+ Reference< XRow > xRow ( _rxSourceResultSet, UNO_QUERY_THROW );
+ Reference< XRowLocate > xRowLocate ( _rxSourceResultSet, UNO_QUERY_THROW );
+
+ Reference< XResultSetMetaDataSupplier > xSuppResMeta( _rxSourceResultSet, UNO_QUERY_THROW );
+ Reference< XResultSetMetaData> xMeta( xSuppResMeta->getMetaData() );
+
+ // we need a vector which all types
+ sal_Int32 nCount = xMeta->getColumnCount();
+ std::vector< sal_Int32 > aSourceColTypes;
+ aSourceColTypes.reserve( nCount + 1 );
+ aSourceColTypes.push_back( -1 ); // just to avoid an every time i-1 call
+
+ std::vector< sal_Int32 > aSourcePrec;
+ aSourcePrec.reserve( nCount + 1 );
+ aSourcePrec.push_back( -1 ); // just to avoid an every time i-1 call
+
+ for ( sal_Int32 k=1; k <= nCount; ++k )
+ {
+ aSourceColTypes.push_back( xMeta->getColumnType( k ) );
+ aSourcePrec.push_back( xMeta->getPrecision( k ) );
+ }
+
+ // now create, fill and execute the prepared statement
+ Reference< XPreparedStatement > xStatement( ODatabaseExport::createPreparedStatment( xDestMetaData, _rxDestTable, aColumnPositions ), UNO_SET_THROW );
+ Reference< XParameters > xStatementParams( xStatement, UNO_QUERY_THROW );
+
+ const bool bSelectedRecordsOnly = m_aSourceSelection.hasElements();
+ const Any* pSelectedRow = m_aSourceSelection.getConstArray();
+ const Any* pSelEnd = pSelectedRow + m_aSourceSelection.getLength();
+
+ sal_Int32 nRowCount = 0;
+ bool bContinue = false;
+
+ CopyTableRowEvent aCopyEvent;
+ aCopyEvent.Source = *this;
+ aCopyEvent.SourceData = _rxSourceResultSet;
+
+ do // loop as long as there are more rows or the selection ends
+ {
+ bContinue = false;
+ if ( bSelectedRecordsOnly )
+ {
+ if ( pSelectedRow != pSelEnd )
+ {
+ if ( m_bSourceSelectionBookmarks )
+ {
+ bContinue = xRowLocate->moveToBookmark( *pSelectedRow );
+ }
+ else
+ {
+ sal_Int32 nPos = 0;
+ OSL_VERIFY( *pSelectedRow >>= nPos );
+ bContinue = _rxSourceResultSet->absolute( nPos );
+ }
+ ++pSelectedRow;
+ }
+ }
+ else
+ bContinue = _rxSourceResultSet->next();
+
+ if ( !bContinue )
+ {
+ break;
+ }
+
+ ++nRowCount;
+
+ aCopyEvent.Error.clear();
+ try
+ {
+ bool bInsertedPrimaryKey = false;
+ // notify listeners
+ m_aCopyTableListeners.notifyEach( &XCopyTableListener::copyingRow, aCopyEvent );
+
+ sal_Int32 nSourceColumn( 1 );
+ ValueTransfer aTransfer( aSourceColTypes, xRow, xStatementParams );
+
+ for ( auto const& rColumnPos : aColumnPositions )
+ {
+ sal_Int32 nDestColumn = rColumnPos.first;
+ if ( nDestColumn == COLUMN_POSITION_NOT_FOUND )
+ {
+ ++nSourceColumn;
+ // otherwise we don't get the correct value when only the 2nd source column was selected
+ continue;
+ }
+
+ if ( bShouldCreatePrimaryKey && !bInsertedPrimaryKey )
+ {
+ xStatementParams->setInt( 1, nRowCount );
+ ++nSourceColumn;
+ bInsertedPrimaryKey = true;
+ continue;
+ }
+
+ if ( ( nSourceColumn < 1 ) || ( o3tl::make_unsigned(nSourceColumn) >= aSourceColTypes.size() ) )
+ { // ( we have to check here against 1 because the parameters are 1 based)
+ ::dbtools::throwSQLException("Internal error: invalid column type index.",
+ ::dbtools::StandardSQLState::INVALID_DESCRIPTOR_INDEX, *this);
+ }
+
+ switch ( aSourceColTypes[ nSourceColumn ] )
+ {
+ case DataType::DOUBLE:
+ case DataType::REAL:
+ aTransfer.transferValue( nSourceColumn, nDestColumn, &XRow::getDouble, &XParameters::setDouble );
+ break;
+
+ case DataType::CHAR:
+ case DataType::VARCHAR:
+ case DataType::LONGVARCHAR:
+ case DataType::DECIMAL:
+ case DataType::NUMERIC:
+ aTransfer.transferComplexValue( nSourceColumn, nDestColumn, &XRow::getString, &XParameters::setString );
+ break;
+
+ case DataType::BIGINT:
+ aTransfer.transferValue( nSourceColumn, nDestColumn, &XRow::getLong, &XParameters::setLong );
+ break;
+
+ case DataType::FLOAT:
+ aTransfer.transferValue( nSourceColumn, nDestColumn, &XRow::getFloat, &XParameters::setFloat );
+ break;
+
+ case DataType::LONGVARBINARY:
+ case DataType::BINARY:
+ case DataType::VARBINARY:
+ aTransfer.transferComplexValue( nSourceColumn, nDestColumn, &XRow::getBytes, &XParameters::setBytes );
+ break;
+
+ case DataType::DATE:
+ aTransfer.transferComplexValue( nSourceColumn, nDestColumn, &XRow::getDate, &XParameters::setDate );
+ break;
+
+ case DataType::TIME:
+ aTransfer.transferComplexValue( nSourceColumn, nDestColumn, &XRow::getTime, &XParameters::setTime );
+ break;
+
+ case DataType::TIMESTAMP:
+ aTransfer.transferComplexValue( nSourceColumn, nDestColumn, &XRow::getTimestamp, &XParameters::setTimestamp );
+ break;
+
+ case DataType::BIT:
+ if ( aSourcePrec[nSourceColumn] > 1 )
+ {
+ aTransfer.transferComplexValue( nSourceColumn, nDestColumn, &XRow::getBytes, &XParameters::setBytes );
+ break;
+ }
+ [[fallthrough]];
+ case DataType::BOOLEAN:
+ aTransfer.transferValue( nSourceColumn, nDestColumn, &XRow::getBoolean, &XParameters::setBoolean );
+ break;
+
+ case DataType::TINYINT:
+ aTransfer.transferValue( nSourceColumn, nDestColumn, &XRow::getByte, &XParameters::setByte );
+ break;
+
+ case DataType::SMALLINT:
+ aTransfer.transferValue( nSourceColumn, nDestColumn, &XRow::getShort, &XParameters::setShort );
+ break;
+
+ case DataType::INTEGER:
+ aTransfer.transferValue( nSourceColumn, nDestColumn, &XRow::getInt, &XParameters::setInt );
+ break;
+
+ case DataType::BLOB:
+ aTransfer.transferComplexValue( nSourceColumn, nDestColumn, &XRow::getBlob, &XParameters::setBlob );
+ break;
+
+ case DataType::CLOB:
+ aTransfer.transferComplexValue( nSourceColumn, nDestColumn, &XRow::getClob, &XParameters::setClob );
+ break;
+
+ default:
+ {
+ OUString aMessage( DBA_RES( STR_CTW_UNSUPPORTED_COLUMN_TYPE ) );
+
+ aMessage = aMessage.replaceFirst( "$type$", OUString::number( aSourceColTypes[ nSourceColumn ] ) );
+ aMessage = aMessage.replaceFirst( "$pos$", OUString::number( nSourceColumn ) );
+
+ ::dbtools::throwSQLException(
+ aMessage,
+ ::dbtools::StandardSQLState::INVALID_SQL_DATA_TYPE,
+ *this
+ );
+ }
+ }
+ ++nSourceColumn;
+ }
+ xStatement->executeUpdate();
+
+ // notify listeners
+ m_aCopyTableListeners.notifyEach( &XCopyTableListener::copiedRow, aCopyEvent );
+ }
+ catch( const Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("dbaccess", "");
+ aCopyEvent.Error = ::cppu::getCaughtException();
+ }
+
+ if ( aCopyEvent.Error.hasValue() )
+ bContinue = impl_processCopyError_nothrow( aCopyEvent );
+ }
+ while( bContinue );
+}
+
+void CopyTableWizard::impl_doCopy_nothrow()
+{
+ Any aError;
+
+ try
+ {
+ OCopyTableWizard& rWizard( impl_getDialog_throw() );
+
+ weld::WaitObject aWO(rWizard.getDialog());
+ Reference< XPropertySet > xTable;
+
+ switch ( rWizard.getOperation() )
+ {
+ case CopyTableOperation::CopyDefinitionOnly:
+ case CopyTableOperation::CopyDefinitionAndData:
+ {
+ xTable = rWizard.createTable();
+
+ if( !xTable.is() )
+ {
+ SAL_WARN("dbaccess.ui", "CopyTableWizard::impl_doCopy_nothrow: createTable should throw here, shouldn't it?" );
+ break;
+ }
+
+ if( CopyTableOperation::CopyDefinitionOnly == rWizard.getOperation() )
+ break;
+
+ [[fallthrough]];
+ }
+
+ case CopyTableOperation::AppendData:
+ {
+ // note that the CopyDefinitionAndData case falls through to here.
+ assert((rWizard.getOperation() == CopyTableOperation::CopyDefinitionAndData) ||
+ (rWizard.getOperation() == CopyTableOperation::AppendData));
+ assert((rWizard.getOperation() == CopyTableOperation::CopyDefinitionAndData) == xTable.is());
+ if ( !xTable.is() )
+ {
+ assert(rWizard.getOperation() == CopyTableOperation::AppendData);
+ xTable = rWizard.getTable();
+ if ( !xTable.is() )
+ {
+ SAL_WARN("dbaccess.ui", "CopyTableWizard::impl_doCopy_nothrow: getTable should throw here, shouldn't it?" );
+ break;
+ }
+ }
+
+ ::utl::SharedUNOComponent< XPreparedStatement > xSourceStatement;
+ ::utl::SharedUNOComponent< XResultSet > xSourceResultSet;
+
+ if ( m_xSourceResultSet.is() )
+ {
+ xSourceResultSet.reset( m_xSourceResultSet, ::utl::SharedUNOComponent< XResultSet >::NoTakeOwnership );
+ }
+ else
+ {
+ const bool bIsSameConnection = ( m_xSourceConnection.getTyped() == m_xDestConnection.getTyped() );
+ const bool bIsTable = ( CommandType::TABLE == m_nCommandType );
+ bool bDone = false;
+ if ( bIsSameConnection && bIsTable )
+ {
+ // try whether the server supports copying via SQL
+ try
+ {
+ m_xDestConnection->createStatement()->executeUpdate( impl_getServerSideCopyStatement_throw(xTable) );
+ bDone = true;
+ }
+ catch( const Exception& )
+ {
+ // this is allowed.
+ }
+ }
+
+ if ( !bDone )
+ {
+ xSourceStatement.set( impl_createSourceStatement_throw(), UNO_SET_THROW );
+ xSourceResultSet.set( xSourceStatement->executeQuery(), UNO_SET_THROW );
+ }
+ }
+
+ if ( xSourceResultSet.is() )
+ impl_copyRows_throw( xSourceResultSet, xTable );
+
+ // tdf#119962
+ const Reference< XDatabaseMetaData > xDestMetaData( m_xDestConnection->getMetaData(), UNO_SET_THROW );
+ OUString sDatabaseDest = xDestMetaData->getDatabaseProductName().toAsciiLowerCase();
+ // If we created a new primary key, then it won't necessarily be an IDENTITY column
+ const bool bShouldCreatePrimaryKey = rWizard.shouldCreatePrimaryKey();
+ if ( !bShouldCreatePrimaryKey && ((sDatabaseDest.indexOf("hsql") != -1) || (sDatabaseDest.indexOf("firebird") != -1)) )
+ {
+ const OUString sComposedTableName = ::dbtools::composeTableName( xDestMetaData, xTable, ::dbtools::EComposeRule::InDataManipulation, true );
+
+ OUString aSchema,aTable;
+ xTable->getPropertyValue("SchemaName") >>= aSchema;
+ xTable->getPropertyValue("Name") >>= aTable;
+ Any aCatalog = xTable->getPropertyValue("CatalogName");
+
+ const Reference< XResultSet > xResultPKCL(xDestMetaData->getPrimaryKeys(aCatalog,aSchema,aTable));
+ Reference< XRow > xRowPKCL(xResultPKCL, UNO_QUERY_THROW);
+ OUString sPKCL;
+ if ( xRowPKCL.is() )
+ {
+ if (xResultPKCL->next())
+ {
+ sPKCL = xRowPKCL->getString(4);
+ }
+ }
+
+ if (!sPKCL.isEmpty())
+ {
+ OUString strSql = "SELECT MAX(\"" + sPKCL + "\") FROM " + sComposedTableName;
+
+ Reference< XResultSet > xResultMAXNUM(m_xDestConnection->createStatement()->executeQuery(strSql));
+ Reference< XRow > xRow(xResultMAXNUM, UNO_QUERY_THROW);
+
+ sal_Int64 maxVal = -1L;
+ if (xResultMAXNUM->next())
+ {
+ maxVal = xRow->getLong(1);
+ }
+
+ if (maxVal > 0L)
+ {
+ strSql = "ALTER TABLE " + sComposedTableName + " ALTER \"" + sPKCL + "\" RESTART WITH " + OUString::number(maxVal + 1);
+
+ m_xDestConnection->createStatement()->execute(strSql);
+ }
+ }
+ }
+ }
+ break;
+
+ case CopyTableOperation::CreateAsView:
+ rWizard.createView();
+ break;
+
+ default:
+ SAL_WARN("dbaccess.ui", "CopyTableWizard::impl_doCopy_nothrow: What operation, please?" );
+ break;
+ }
+ }
+ catch( const Exception& )
+ {
+ aError = ::cppu::getCaughtException();
+
+ // silence the error of the user cancelling the parameter's dialog
+ SQLException aSQLError;
+ if ( ( aError >>= aSQLError ) && ( aSQLError.ErrorCode == ::dbtools::ParameterInteractionCancelled ) )
+ {
+ aError.clear();
+ m_nOverrideExecutionResult = RET_CANCEL;
+ }
+ }
+
+ if ( aError.hasValue() && m_xInteractionHandler.is() )
+ {
+ try
+ {
+ ::rtl::Reference< ::comphelper::OInteractionRequest > xRequest( new ::comphelper::OInteractionRequest( aError ) );
+ m_xInteractionHandler->handle( xRequest );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+}
+
+OUString CopyTableWizard::impl_getServerSideCopyStatement_throw(const Reference< XPropertySet >& _xTable)
+{
+ const Reference<XColumnsSupplier> xDestColsSup(_xTable,UNO_QUERY_THROW);
+ const Sequence< OUString> aDestColumnNames = xDestColsSup->getColumns()->getElementNames();
+ const Reference< XDatabaseMetaData > xDestMetaData( m_xDestConnection->getMetaData(), UNO_SET_THROW );
+ const OUString sQuote = xDestMetaData->getIdentifierQuoteString();
+ OUStringBuffer sColumns;
+ // 1st check if the columns matching
+ for ( auto const & rColumnPositionPair : impl_getDialog_throw().GetColumnPositions() )
+ {
+ if ( COLUMN_POSITION_NOT_FOUND != rColumnPositionPair.second )
+ {
+ if ( !sColumns.isEmpty() )
+ sColumns.append(",");
+ sColumns.append(sQuote + aDestColumnNames[rColumnPositionPair.second - 1] + sQuote);
+ }
+ }
+ const OUString sComposedTableName = ::dbtools::composeTableName( xDestMetaData, _xTable, ::dbtools::EComposeRule::InDataManipulation, true );
+ OUString sSql("INSERT INTO " + sComposedTableName + " ( " + sColumns + " ) " + m_pSourceObject->getSelectStatement());
+
+ return sSql;
+}
+
+void SAL_CALL CopyTableWizard::initialize( const Sequence< Any >& _rArguments )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ if ( isInitialized() )
+ throw AlreadyInitializedException( OUString(), *this );
+
+ sal_Int32 nArgCount( _rArguments.getLength() );
+ if ( ( nArgCount != 2 ) && ( nArgCount != 3 ) )
+ throw IllegalArgumentException(
+ DBA_RES( STR_CTW_ILLEGAL_PARAMETER_COUNT ),
+ *this,
+ 1
+ );
+
+ try
+ {
+ if ( nArgCount == 3 )
+ { // ->createWithInteractionHandler
+ if ( !( _rArguments[2] >>= m_xInteractionHandler ) )
+ throw IllegalArgumentException(
+ DBA_RES( STR_CTW_ERROR_INVALID_INTERACTIONHANDLER ),
+ *this,
+ 3
+ );
+ }
+ if ( !m_xInteractionHandler.is() )
+ m_xInteractionHandler = InteractionHandler::createWithParent(m_xContext, nullptr);
+
+ Reference< XInteractionHandler > xSourceDocHandler;
+ Reference< XPropertySet > xSourceDescriptor( impl_ensureDataAccessDescriptor_throw( _rArguments, 0, m_xSourceConnection, xSourceDocHandler ) );
+ impl_checkForUnsupportedSettings_throw( xSourceDescriptor );
+ m_pSourceObject = impl_extractSourceObject_throw( xSourceDescriptor, m_nCommandType );
+ impl_extractSourceResultSet_throw( xSourceDescriptor );
+
+ Reference< XInteractionHandler > xDestDocHandler;
+ impl_ensureDataAccessDescriptor_throw( _rArguments, 1, m_xDestConnection, xDestDocHandler );
+
+ if ( xDestDocHandler.is() && !m_xInteractionHandler.is() )
+ m_xInteractionHandler = xDestDocHandler;
+
+ Reference< XPropertySet > xInteractionHandler(m_xInteractionHandler, UNO_QUERY);
+ if (xInteractionHandler.is())
+ {
+ Any aParentWindow(xInteractionHandler->getPropertyValue("ParentWindow"));
+ aParentWindow >>= m_xParent;
+ }
+ }
+ catch( const RuntimeException& ) { throw; }
+ catch( const SQLException& ) { throw; }
+ catch( const Exception& )
+ {
+ throw WrappedTargetException(
+ DBA_RES( STR_CTW_ERROR_DURING_INITIALIZATION ),
+ *this,
+ ::cppu::getCaughtException()
+ );
+ }
+}
+
+::cppu::IPropertyArrayHelper& CopyTableWizard::getInfoHelper()
+{
+ return *getArrayHelper();
+}
+
+::cppu::IPropertyArrayHelper* CopyTableWizard::createArrayHelper( ) const
+{
+ Sequence< Property > aProps;
+ describeProperties( aProps );
+ return new ::cppu::OPropertyArrayHelper( aProps );
+}
+
+std::unique_ptr<weld::DialogController> CopyTableWizard::createDialog(const css::uno::Reference<css::awt::XWindow>& rParent)
+{
+ OSL_PRECOND( isInitialized(), "CopyTableWizard::createDialog: not initialized!" );
+ // this should have been prevented in ::execute already
+
+ auto xWizard = std::make_unique<OCopyTableWizard>(
+ Application::GetFrameWeld(rParent),
+ m_sDestinationTable,
+ m_nOperation,
+ *m_pSourceObject,
+ m_xSourceConnection.getTyped(),
+ m_xDestConnection.getTyped(),
+ m_xContext,
+ m_xInteractionHandler);
+
+ impl_attributesToDialog_nothrow(*xWizard);
+
+ return xWizard;
+}
+
+void CopyTableWizard::executedDialog( sal_Int16 _nExecutionResult )
+{
+ CopyTableWizard_DialogBase::executedDialog( _nExecutionResult );
+
+ if ( _nExecutionResult == RET_OK )
+ impl_doCopy_nothrow();
+
+ // do this after impl_doCopy_nothrow: The attributes may change during copying, for instance
+ // if the user entered an unqualified table name
+ impl_dialogToAttributes_nothrow( impl_getDialog_throw() );
+}
+
+} // namespace dbaui
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+org_openoffice_comp_dbu_CopyTableWizard_get_implementation(
+ css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const& )
+{
+ return cppu::acquire(new ::dbaui::CopyTableWizard(context));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/uno/dbinteraction.cxx b/dbaccess/source/ui/uno/dbinteraction.cxx
new file mode 100644
index 000000000..ad7480c1a
--- /dev/null
+++ b/dbaccess/source/ui/uno/dbinteraction.cxx
@@ -0,0 +1,387 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "dbinteraction.hxx"
+#include <tools/diagnose_ex.h>
+#include <osl/diagnose.h>
+#include <connectivity/dbexception.hxx>
+#include <sqlmessage.hxx>
+#include <com/sun/star/task/InteractionHandler.hpp>
+#include <com/sun/star/task/XInteractionApprove.hpp>
+#include <com/sun/star/task/XInteractionDisapprove.hpp>
+#include <com/sun/star/task/XInteractionRetry.hpp>
+#include <com/sun/star/task/XInteractionAbort.hpp>
+#include <com/sun/star/sdb/XInteractionSupplyParameters.hpp>
+#include <com/sun/star/sdb/XInteractionDocumentSave.hpp>
+#include <sfx2/QuerySaveDocument.hxx>
+#include <paramdialog.hxx>
+#include <vcl/svapp.hxx>
+#include <CollectionView.hxx>
+#include <comphelper/sequenceashashmap.hxx>
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+com_sun_star_comp_dbaccess_DatabaseInteractionHandler_get_implementation(
+ css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const& )
+{
+ return cppu::acquire(new ::dbaui::SQLExceptionInteractionHandler(context));
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+com_sun_star_comp_dbaccess_LegacyInteractionHandler_get_implementation(
+ css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const& )
+{
+ return cppu::acquire(new ::dbaui::LegacyInteractionHandler(context));
+}
+
+namespace dbaui
+{
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::ucb;
+ using namespace ::com::sun::star::sdb;
+ using namespace ::com::sun::star::lang;
+ using namespace ::com::sun::star::task;
+ using namespace ::com::sun::star::beans;
+ using namespace ::dbtools;
+
+ // BasicInteractionHandler
+ BasicInteractionHandler::BasicInteractionHandler( const Reference< XComponentContext >& rxContext, const bool i_bFallbackToGeneric )
+ :m_xContext( rxContext )
+ ,m_bFallbackToGeneric( i_bFallbackToGeneric )
+ {
+ OSL_ENSURE( !m_bFallbackToGeneric,
+ "BasicInteractionHandler::BasicInteractionHandler: enabling legacy behavior, there should be no clients of this anymore!" );
+ }
+
+ void SAL_CALL BasicInteractionHandler::initialize(const Sequence<Any>& rArgs)
+ {
+ comphelper::SequenceAsHashMap aMap(rArgs);
+ m_xParentWindow.set(aMap.getValue("Parent"), UNO_QUERY);
+ }
+
+ sal_Bool SAL_CALL BasicInteractionHandler::handleInteractionRequest( const Reference< XInteractionRequest >& i_rRequest )
+ {
+ return impl_handle_throw( i_rRequest );
+ }
+
+ void SAL_CALL BasicInteractionHandler::handle( const Reference< XInteractionRequest >& i_rRequest )
+ {
+ impl_handle_throw( i_rRequest );
+ }
+
+ bool BasicInteractionHandler::impl_handle_throw( const Reference< XInteractionRequest >& i_Request )
+ {
+ Any aRequest( i_Request->getRequest() );
+ OSL_ENSURE(aRequest.hasValue(), "BasicInteractionHandler::handle: invalid request!");
+ if ( !aRequest.hasValue() )
+ // no request -> no handling
+ return false;
+
+ Sequence< Reference< XInteractionContinuation > > aContinuations( i_Request->getContinuations() );
+
+ // try to extract an SQLException (or one of its derived members
+ SQLExceptionInfo aInfo( aRequest );
+ if ( aInfo.isValid() )
+ {
+ implHandle( aInfo, aContinuations );
+ return true;
+ }
+
+ ParametersRequest aParamRequest;
+ if ( aRequest >>= aParamRequest )
+ {
+ implHandle( aParamRequest, aContinuations );
+ return true;
+ }
+
+ DocumentSaveRequest aDocuRequest;
+ if ( aRequest >>= aDocuRequest )
+ {
+ implHandle( aDocuRequest, aContinuations );
+ return true;
+ }
+
+ if ( m_bFallbackToGeneric )
+ return implHandleUnknown( i_Request );
+
+ return false;
+ }
+
+ void BasicInteractionHandler::implHandle(const ParametersRequest& _rParamRequest, const Sequence< Reference< XInteractionContinuation > >& _rContinuations)
+ {
+ SolarMutexGuard aGuard;
+ // want to open a dialog...
+
+ sal_Int32 nAbortPos = getContinuation(ABORT, _rContinuations);
+ sal_Int32 nParamPos = getContinuation(SUPPLY_PARAMETERS, _rContinuations);
+
+ Reference< XInteractionSupplyParameters > xParamCallback;
+ if (-1 != nParamPos)
+ xParamCallback.set(_rContinuations[nParamPos], UNO_QUERY);
+ OSL_ENSURE(xParamCallback.is(), "BasicInteractionHandler::implHandle(ParametersRequest): can't set the parameters without an appropriate interaction handler!s");
+
+ OParameterDialog aDlg(Application::GetFrameWeld(m_xParentWindow), _rParamRequest.Parameters, _rParamRequest.Connection, m_xContext);
+ sal_Int16 nResult = aDlg.run();
+ try
+ {
+ switch (nResult)
+ {
+ case RET_OK:
+ if (xParamCallback.is())
+ {
+ xParamCallback->setParameters(aDlg.getValues());
+ xParamCallback->select();
+ }
+ break;
+ default:
+ if (-1 != nAbortPos)
+ _rContinuations[nAbortPos]->select();
+ break;
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+
+ void BasicInteractionHandler::implHandle(const SQLExceptionInfo& _rSqlInfo, const Sequence< Reference< XInteractionContinuation > >& _rContinuations)
+ {
+ SolarMutexGuard aGuard;
+ // want to open a dialog...
+
+ sal_Int32 nApprovePos = getContinuation(APPROVE, _rContinuations);
+ sal_Int32 nDisapprovePos = getContinuation(DISAPPROVE, _rContinuations);
+ sal_Int32 nAbortPos = getContinuation(ABORT, _rContinuations);
+ sal_Int32 nRetryPos = getContinuation(RETRY, _rContinuations);
+
+ // determine the style of the dialog, dependent on the present continuation types
+ MessBoxStyle nDialogStyle = MessBoxStyle::NONE;
+ bool bHaveCancel = nAbortPos != -1;
+ // "approve" means "Yes", "disapprove" means "No"
+ // VCL only supports having both (which makes sense ...)
+ if ( ( nApprovePos != -1 ) || ( nDisapprovePos != -1 ) )
+ nDialogStyle = ( bHaveCancel ? MessBoxStyle::YesNoCancel : MessBoxStyle::YesNo ) | MessBoxStyle::DefaultYes;
+ else
+ {
+ // if there's no yes/no, then use a default OK button
+ nDialogStyle = ( bHaveCancel ? MessBoxStyle::OkCancel : MessBoxStyle::Ok ) | MessBoxStyle::DefaultOk;
+ }
+
+ // If there's a "Retry" continuation, have a "Retry" button
+ if ( nRetryPos != -1 )
+ {
+ nDialogStyle = MessBoxStyle::RetryCancel | MessBoxStyle::DefaultRetry;
+ }
+
+ // execute the dialog
+ OSQLMessageBox aDialog(nullptr, _rSqlInfo, nDialogStyle);
+ // TODO: need a way to specify the parent window
+ sal_Int16 nResult = aDialog.run();
+ try
+ {
+ switch (nResult)
+ {
+ case RET_YES:
+ case RET_OK:
+ if ( nApprovePos != -1 )
+ _rContinuations[ nApprovePos ]->select();
+ else
+ OSL_ENSURE( nResult != RET_YES, "BasicInteractionHandler::implHandle: no handler for YES!" );
+ break;
+
+ case RET_NO:
+ if ( nDisapprovePos != -1 )
+ _rContinuations[ nDisapprovePos ]->select();
+ else
+ OSL_FAIL( "BasicInteractionHandler::implHandle: no handler for NO!" );
+ break;
+
+ case RET_CANCEL:
+ if ( nAbortPos != -1 )
+ _rContinuations[ nAbortPos ]->select();
+ else if ( nDisapprovePos != -1 )
+ _rContinuations[ nDisapprovePos ]->select();
+ else
+ OSL_FAIL( "BasicInteractionHandler::implHandle: no handler for CANCEL!" );
+ break;
+ case RET_RETRY:
+ if ( nRetryPos != -1 )
+ _rContinuations[ nRetryPos ]->select();
+ else
+ OSL_FAIL( "BasicInteractionHandler::implHandle: where does the RETRY come from?" );
+ break;
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+ void BasicInteractionHandler::implHandle(const DocumentSaveRequest& _rDocuRequest, const Sequence< Reference< XInteractionContinuation > >& _rContinuations)
+ {
+ SolarMutexGuard aGuard;
+ // want to open a dialog...
+
+ sal_Int32 nApprovePos = getContinuation(APPROVE, _rContinuations);
+ sal_Int32 nDisApprovePos = getContinuation(DISAPPROVE, _rContinuations);
+ sal_Int32 nAbortPos = getContinuation(ABORT, _rContinuations);
+
+ short nRet = RET_YES;
+ if ( -1 != nApprovePos )
+ {
+ // ask whether it should be saved
+ nRet = ExecuteQuerySaveDocument(Application::GetFrameWeld(m_xParentWindow), _rDocuRequest.Name);
+ }
+
+ if ( RET_CANCEL == nRet )
+ {
+ if (-1 != nAbortPos)
+ _rContinuations[nAbortPos]->select();
+ return;
+ }
+ else if ( RET_YES == nRet )
+ {
+ sal_Int32 nDocuPos = getContinuation(SUPPLY_DOCUMENTSAVE, _rContinuations);
+
+ if (-1 != nDocuPos)
+ {
+ Reference< XInteractionDocumentSave > xCallback(_rContinuations[nDocuPos], UNO_QUERY);
+ OSL_ENSURE(xCallback.is(), "BasicInteractionHandler::implHandle(DocumentSaveRequest): can't save document without an appropriate interaction handler!s");
+
+ OCollectionView aDlg(Application::GetFrameWeld(m_xParentWindow), _rDocuRequest.Content, _rDocuRequest.Name, m_xContext);
+ sal_Int16 nResult = aDlg.run();
+ try
+ {
+ switch (nResult)
+ {
+ case RET_OK:
+ if (xCallback.is())
+ {
+ xCallback->setName(aDlg.getName(), aDlg.getSelectedFolder());
+ xCallback->select();
+ }
+ break;
+ default:
+ if (-1 != nAbortPos)
+ _rContinuations[nAbortPos]->select();
+ break;
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+ else if ( -1 != nApprovePos )
+ _rContinuations[nApprovePos]->select();
+ }
+ else if ( -1 != nDisApprovePos )
+ _rContinuations[nDisApprovePos]->select();
+ }
+
+ bool BasicInteractionHandler::implHandleUnknown( const Reference< XInteractionRequest >& _rxRequest )
+ {
+ if ( m_xContext.is() )
+ {
+ Reference< XInteractionHandler2 > xFallbackHandler(
+ InteractionHandler::createWithParent(m_xContext, nullptr) );
+ xFallbackHandler->handle( _rxRequest );
+ return true;
+ }
+ return false;
+ }
+
+ sal_Int32 BasicInteractionHandler::getContinuation(Continuation _eCont, const Sequence< Reference< XInteractionContinuation > >& _rContinuations)
+ {
+ const Reference< XInteractionContinuation >* pContinuations = _rContinuations.getConstArray();
+ for (sal_Int32 i=0; i<_rContinuations.getLength(); ++i, ++pContinuations)
+ {
+ switch (_eCont)
+ {
+ case APPROVE:
+ if (Reference< XInteractionApprove >(*pContinuations, UNO_QUERY).is())
+ return i;
+ break;
+ case DISAPPROVE:
+ if (Reference< XInteractionDisapprove >(*pContinuations, UNO_QUERY).is())
+ return i;
+ break;
+ case RETRY:
+ if (Reference< XInteractionRetry >(*pContinuations, UNO_QUERY).is())
+ return i;
+ break;
+ case ABORT:
+ if (Reference< XInteractionAbort >(*pContinuations, UNO_QUERY).is())
+ return i;
+ break;
+ case SUPPLY_PARAMETERS:
+ if (Reference< XInteractionSupplyParameters >(*pContinuations, UNO_QUERY).is())
+ return i;
+ break;
+ case SUPPLY_DOCUMENTSAVE:
+ if (Reference< XInteractionDocumentSave >(*pContinuations, UNO_QUERY).is())
+ return i;
+ break;
+ }
+ }
+
+ return -1;
+ }
+
+ // SQLExceptionInteractionHandler
+ OUString SAL_CALL SQLExceptionInteractionHandler::getImplementationName()
+ {
+ return "com.sun.star.comp.dbaccess.DatabaseInteractionHandler";
+ }
+ sal_Bool SAL_CALL SQLExceptionInteractionHandler::supportsService(const OUString& _rServiceName)
+ {
+ const css::uno::Sequence< OUString > aSupported(getSupportedServiceNames());
+ for (const OUString& s : aSupported)
+ if (s == _rServiceName)
+ return true;
+
+ return false;
+ }
+ css::uno::Sequence< OUString > SAL_CALL SQLExceptionInteractionHandler::getSupportedServiceNames()
+ {
+ return { "com.sun.star.sdb.DatabaseInteractionHandler" };
+ }
+
+ // LegacyInteractionHandler
+ OUString SAL_CALL LegacyInteractionHandler::getImplementationName()
+ {
+ return "com.sun.star.comp.dbaccess.LegacyInteractionHandler";
+ }
+ sal_Bool SAL_CALL LegacyInteractionHandler::supportsService(const OUString& _rServiceName)
+ {
+ const css::uno::Sequence< OUString > aSupported(getSupportedServiceNames());
+ for (const OUString& s : aSupported)
+ if (s == _rServiceName)
+ return true;
+
+ return false;
+ }
+ css::uno::Sequence< OUString > SAL_CALL LegacyInteractionHandler::getSupportedServiceNames()
+ {
+ return { "com.sun.star.sdb.InteractionHandler" };
+ }
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/uno/dbinteraction.hxx b/dbaccess/source/ui/uno/dbinteraction.hxx
new file mode 100644
index 000000000..fdb0dbd2c
--- /dev/null
+++ b/dbaccess/source/ui/uno/dbinteraction.hxx
@@ -0,0 +1,168 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <cppuhelper/implbase.hxx>
+#include <connectivity/CommonTools.hxx>
+
+#include <com/sun/star/awt/XWindow.hpp>
+#include <com/sun/star/lang/XInitialization.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/task/XInteractionHandler2.hpp>
+#include <com/sun/star/sdb/ParametersRequest.hpp>
+#include <com/sun/star/sdb/DocumentSaveRequest.hpp>
+
+namespace com::sun::star::uno { class XComponentContext; }
+
+namespace dbtools
+{
+ class SQLExceptionInfo;
+}
+
+namespace dbaui
+{
+
+ // BasicInteractionHandler
+ typedef ::cppu::WeakImplHelper< css::lang::XServiceInfo
+ , css::lang::XInitialization
+ , css::task::XInteractionHandler2
+ > BasicInteractionHandler_Base;
+ /** implements an <type scope="com.sun.star.task">XInteractionHandler</type> for
+ database related interaction requests.
+ <p/>
+ Supported interaction requests by now (specified by an exception: The appropriate exception
+ has to be returned by the getRequest method of the object implementing the
+ <type scope="com.sun.star.task">XInteractionRequest</type> interface.
+ <ul>
+ <li><b><type scope="com.sun.star.sdbc">SQLException</type></b>: requests to display a
+ standard error dialog for the (maybe chained) exception given</li>
+ </ul>
+ */
+ class BasicInteractionHandler
+ :public BasicInteractionHandler_Base
+ {
+ css::uno::Reference< css::awt::XWindow > m_xParentWindow;
+ const css::uno::Reference< css::uno::XComponentContext >
+ m_xContext;
+ const bool m_bFallbackToGeneric;
+
+ public:
+ BasicInteractionHandler(
+ const css::uno::Reference< css::uno::XComponentContext >& rxContext,
+ const bool i_bFallbackToGeneric
+ );
+
+ // XInitialization
+ virtual void SAL_CALL initialize( const css::uno::Sequence< css::uno::Any >& rArgs ) override;
+
+ // XInteractionHandler2
+ virtual sal_Bool SAL_CALL handleInteractionRequest( const css::uno::Reference< css::task::XInteractionRequest >& Request ) override;
+
+ // XInteractionHandler
+ virtual void SAL_CALL handle( const css::uno::Reference< css::task::XInteractionRequest >& Request ) override;
+
+ protected:
+ bool
+ impl_handle_throw( const css::uno::Reference< css::task::XInteractionRequest >& i_Request );
+
+ /// handle SQLExceptions (and derived classes)
+ static void implHandle(
+ const ::dbtools::SQLExceptionInfo& _rSqlInfo,
+ const css::uno::Sequence< css::uno::Reference< css::task::XInteractionContinuation > >& _rContinuations);
+
+ /// handle parameter requests
+ void implHandle(
+ const css::sdb::ParametersRequest& _rParamRequest,
+ const css::uno::Sequence< css::uno::Reference< css::task::XInteractionContinuation > >& _rContinuations);
+
+ /// handle document save requests
+ void implHandle(
+ const css::sdb::DocumentSaveRequest& _rParamRequest,
+ const css::uno::Sequence< css::uno::Reference< css::task::XInteractionContinuation > >& _rContinuations);
+
+ /// handles requests which are not SDB-specific
+ bool implHandleUnknown(
+ const css::uno::Reference< css::task::XInteractionRequest >& _rxRequest );
+
+ /// known continuation types
+ enum Continuation
+ {
+ APPROVE,
+ DISAPPROVE,
+ RETRY,
+ ABORT,
+ SUPPLY_PARAMETERS,
+ SUPPLY_DOCUMENTSAVE
+ };
+ /** check if a given continuation sequence contains a given continuation type<p/>
+ @return the index within <arg>_rContinuations</arg> of the first occurrence of a continuation
+ of the requested type, -1 of no such continuation exists
+ */
+ static sal_Int32 getContinuation(
+ Continuation _eCont,
+ const css::uno::Sequence< css::uno::Reference< css::task::XInteractionContinuation > >& _rContinuations);
+ };
+
+ // SQLExceptionInteractionHandler
+ class SQLExceptionInteractionHandler : public BasicInteractionHandler
+ {
+ public:
+ explicit SQLExceptionInteractionHandler(
+ const css::uno::Reference< css::uno::XComponentContext >& rxContext
+ )
+ :BasicInteractionHandler( rxContext, false )
+ {
+ }
+
+ // XServiceInfo
+ DECLARE_SERVICE_INFO();
+ };
+
+ // SQLExceptionInteractionHandler
+ /** an implementation for the legacy css.sdb.InteractionHandler
+
+ css.sdb.InteractionHandler is deprecated, as it does not only handle database related interactions,
+ but also delegates all kind of unknown requests to a css.task.InteractionHandler.
+
+ In today's architecture, there's only one central css.task.InteractionHandler, which is to be used
+ for all requests. Depending on configuration information, it decides which handler implementation
+ to delegate a request to.
+
+ SQLExceptionInteractionHandler is the delegatee which handles only database related interactions.
+ LegacyInteractionHandler is the version which first checks for a database related interaction, and
+ forwards everything else to the css.task.InteractionHandler.
+ */
+ class LegacyInteractionHandler : public BasicInteractionHandler
+ {
+ public:
+ explicit LegacyInteractionHandler(
+ const css::uno::Reference< css::uno::XComponentContext >& rxContext
+ )
+ :BasicInteractionHandler( rxContext, true )
+ {
+ }
+
+ // XServiceInfo
+ DECLARE_SERVICE_INFO();
+ };
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/uno/textconnectionsettings_uno.cxx b/dbaccess/source/ui/uno/textconnectionsettings_uno.cxx
new file mode 100644
index 000000000..5b1636f90
--- /dev/null
+++ b/dbaccess/source/ui/uno/textconnectionsettings_uno.cxx
@@ -0,0 +1,268 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <textconnectionsettings.hxx>
+#include <unoadmin.hxx>
+#include <stringconstants.hxx>
+#include <propertystorage.hxx>
+
+#include <com/sun/star/beans/XPropertySetInfo.hpp>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/sdb/XTextConnectionSettings.hpp>
+
+#include <comphelper/proparrhlp.hxx>
+#include <connectivity/CommonTools.hxx>
+#include <toolkit/helper/vclunohelper.hxx>
+#include <vcl/svapp.hxx>
+#include <cppuhelper/implbase.hxx>
+
+namespace dbaui
+{
+
+ using ::com::sun::star::uno::Reference;
+ using ::com::sun::star::uno::XInterface;
+ using ::com::sun::star::uno::Any;
+ using ::com::sun::star::uno::XComponentContext;
+ using ::com::sun::star::beans::XPropertySetInfo;
+ using ::com::sun::star::uno::Sequence;
+ using ::com::sun::star::beans::Property;
+
+ namespace PropertyAttribute = ::com::sun::star::beans::PropertyAttribute;
+
+ // OTextConnectionSettingsDialog
+
+ namespace {
+
+ class OTextConnectionSettingsDialog;
+
+ }
+
+ typedef ::cppu::ImplInheritanceHelper< ODatabaseAdministrationDialog
+ , css::sdb::XTextConnectionSettings
+ > OTextConnectionSettingsDialog_BASE;
+ typedef ::comphelper::OPropertyArrayUsageHelper< OTextConnectionSettingsDialog > OTextConnectionSettingsDialog_PBASE;
+
+ namespace {
+
+ class OTextConnectionSettingsDialog
+ :public OTextConnectionSettingsDialog_BASE
+ ,public OTextConnectionSettingsDialog_PBASE
+ {
+ PropertyValues m_aPropertyValues;
+
+ public:
+ explicit OTextConnectionSettingsDialog( const Reference<XComponentContext>& _rContext );
+
+ virtual css::uno::Sequence<sal_Int8> SAL_CALL getImplementationId() override;
+
+ DECLARE_SERVICE_INFO();
+ virtual css::uno::Reference< css::beans::XPropertySetInfo> SAL_CALL getPropertySetInfo() override;
+ virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper() override;
+ virtual ::cppu::IPropertyArrayHelper* createArrayHelper() const override;
+
+
+ virtual void SAL_CALL setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const Any& rValue ) override;
+ virtual sal_Bool SAL_CALL convertFastPropertyValue( Any& rConvertedValue, Any& rOldValue, sal_Int32 nHandle, const Any& rValue) override;
+ virtual void SAL_CALL getFastPropertyValue( Any& rValue, sal_Int32 nHandle ) const override;
+
+ // Overrides to resolve inheritance ambiguity
+ virtual void SAL_CALL setPropertyValue(const OUString& p1, const css::uno::Any& p2) override
+ { ODatabaseAdministrationDialog::setPropertyValue(p1, p2); }
+ virtual css::uno::Any SAL_CALL getPropertyValue(const OUString& p1) override
+ { return ODatabaseAdministrationDialog::getPropertyValue(p1); }
+ virtual void SAL_CALL addPropertyChangeListener(const OUString& p1, const css::uno::Reference<css::beans::XPropertyChangeListener>& p2) override
+ { ODatabaseAdministrationDialog::addPropertyChangeListener(p1, p2); }
+ virtual void SAL_CALL removePropertyChangeListener(const OUString& p1, const css::uno::Reference<css::beans::XPropertyChangeListener>& p2) override
+ { ODatabaseAdministrationDialog::removePropertyChangeListener(p1, p2); }
+ virtual void SAL_CALL addVetoableChangeListener(const OUString& p1, const css::uno::Reference<css::beans::XVetoableChangeListener>& p2) override
+ { ODatabaseAdministrationDialog::addVetoableChangeListener(p1, p2); }
+ virtual void SAL_CALL removeVetoableChangeListener(const OUString& p1, const css::uno::Reference<css::beans::XVetoableChangeListener>& p2) override
+ { ODatabaseAdministrationDialog::removeVetoableChangeListener(p1, p2); }
+ virtual void SAL_CALL setTitle(const OUString& p1) override
+ { ODatabaseAdministrationDialog::setTitle(p1); }
+ virtual sal_Int16 SAL_CALL execute() override
+ { return ODatabaseAdministrationDialog::execute(); }
+
+ protected:
+ // OGenericUnoDialog overridables
+ virtual std::unique_ptr<weld::DialogController> createDialog(const css::uno::Reference<css::awt::XWindow>& rParent) override;
+ using OTextConnectionSettingsDialog_BASE::getFastPropertyValue;
+ };
+
+ }
+
+ // OTextConnectionSettingsDialog
+ OTextConnectionSettingsDialog::OTextConnectionSettingsDialog( const Reference<XComponentContext>& _rContext )
+ :OTextConnectionSettingsDialog_BASE( _rContext )
+ {
+ TextConnectionSettingsDialog::bindItemStorages( *m_pDatasourceItems, m_aPropertyValues );
+ }
+
+ css::uno::Sequence<sal_Int8>
+ OTextConnectionSettingsDialog::getImplementationId()
+ {
+ return css::uno::Sequence<sal_Int8>();
+ }
+
+ OUString SAL_CALL OTextConnectionSettingsDialog::getImplementationName()
+ {
+ return "com.sun.star.comp.dbaccess.OTextConnectionSettingsDialog";
+ }
+ sal_Bool SAL_CALL OTextConnectionSettingsDialog::supportsService(const OUString& _rServiceName)
+ {
+ const css::uno::Sequence< OUString > aSupported(getSupportedServiceNames());
+ for (const OUString& s : aSupported)
+ if (s == _rServiceName)
+ return true;
+
+ return false;
+ }
+ css::uno::Sequence< OUString > SAL_CALL OTextConnectionSettingsDialog::getSupportedServiceNames()
+ {
+ return { "com.sun.star.sdb.TextConnectionSettings" };
+ }
+
+ Reference< XPropertySetInfo > SAL_CALL OTextConnectionSettingsDialog::getPropertySetInfo()
+ {
+ return createPropertySetInfo( getInfoHelper() );
+ }
+
+ ::cppu::IPropertyArrayHelper& OTextConnectionSettingsDialog::getInfoHelper()
+ {
+ return *getArrayHelper();
+ }
+
+ ::cppu::IPropertyArrayHelper* OTextConnectionSettingsDialog::createArrayHelper( ) const
+ {
+ Sequence< Property > aProps;
+ describeProperties( aProps );
+
+ // in addition to the properties registered by the base class, we have
+ // more properties which are not even handled by the PropertyContainer implementation,
+ // but whose values are stored in our item set
+ sal_Int32 nProp = aProps.getLength();
+ aProps.realloc( nProp + 6 );
+ auto pProps = aProps.getArray();
+
+ pProps[ nProp++ ] = Property(
+ "HeaderLine",
+ PROPERTY_ID_HEADER_LINE,
+ ::cppu::UnoType< sal_Bool >::get(),
+ PropertyAttribute::TRANSIENT
+ );
+
+ pProps[ nProp++ ] = Property(
+ "FieldDelimiter",
+ PROPERTY_ID_FIELD_DELIMITER,
+ ::cppu::UnoType< OUString >::get(),
+ PropertyAttribute::TRANSIENT
+ );
+
+ pProps[ nProp++ ] = Property(
+ "StringDelimiter",
+ PROPERTY_ID_STRING_DELIMITER,
+ ::cppu::UnoType< OUString >::get(),
+ PropertyAttribute::TRANSIENT
+ );
+
+ pProps[ nProp++ ] = Property(
+ "DecimalDelimiter",
+ PROPERTY_ID_DECIMAL_DELIMITER,
+ ::cppu::UnoType< OUString >::get(),
+ PropertyAttribute::TRANSIENT
+ );
+
+ pProps[ nProp++ ] = Property(
+ "ThousandDelimiter",
+ PROPERTY_ID_THOUSAND_DELIMITER,
+ ::cppu::UnoType< OUString >::get(),
+ PropertyAttribute::TRANSIENT
+ );
+
+ pProps[ nProp++ ] = Property(
+ "CharSet",
+ PROPERTY_ID_ENCODING,
+ ::cppu::UnoType< OUString >::get(),
+ PropertyAttribute::TRANSIENT
+ );
+
+ return new ::cppu::OPropertyArrayHelper( aProps );
+ }
+
+ std::unique_ptr<weld::DialogController> OTextConnectionSettingsDialog::createDialog(const css::uno::Reference<css::awt::XWindow>& rParent)
+ {
+ return std::make_unique<TextConnectionSettingsDialog>(Application::GetFrameWeld(rParent), *m_pDatasourceItems);
+ }
+
+ void SAL_CALL OTextConnectionSettingsDialog::setFastPropertyValue_NoBroadcast( sal_Int32 _nHandle, const Any& _rValue )
+ {
+ PropertyValues::const_iterator pos = m_aPropertyValues.find( _nHandle );
+ if ( pos != m_aPropertyValues.end() )
+ {
+ pos->second->setPropertyValue( _rValue );
+ }
+ else
+ {
+ OTextConnectionSettingsDialog::setFastPropertyValue_NoBroadcast( _nHandle, _rValue );
+ }
+ }
+
+ sal_Bool SAL_CALL OTextConnectionSettingsDialog::convertFastPropertyValue( Any& _rConvertedValue, Any& _rOldValue, sal_Int32 _nHandle, const Any& _rValue)
+ {
+ bool bModified = false;
+
+ PropertyValues::const_iterator pos = m_aPropertyValues.find( _nHandle );
+ if ( pos != m_aPropertyValues.end() )
+ {
+ // we're lazy here ...
+ _rConvertedValue = _rValue;
+ pos->second->getPropertyValue( _rOldValue );
+ bModified = true;
+ }
+ else
+ {
+ bModified = OTextConnectionSettingsDialog::convertFastPropertyValue( _rConvertedValue, _rOldValue, _nHandle, _rValue );
+ }
+
+ return bModified;
+ }
+
+ void SAL_CALL OTextConnectionSettingsDialog::getFastPropertyValue( Any& _rValue, sal_Int32 _nHandle ) const
+ {
+ PropertyValues::const_iterator pos = m_aPropertyValues.find( _nHandle );
+ if ( pos != m_aPropertyValues.end() )
+ {
+ pos->second->getPropertyValue( _rValue );
+ }
+ else
+ {
+ OTextConnectionSettingsDialog::getFastPropertyValue( _rValue, _nHandle );
+ }
+ }
+
+} // namespace dbaui
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+com_sun_star_comp_dbaccess_OTextConnectionSettingsDialog_get_implementation(
+ css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const& )
+{
+ return cppu::acquire(static_cast<dbaui::ODatabaseAdministrationDialog*>(new ::dbaui::OTextConnectionSettingsDialog(context)));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/uno/unoDirectSql.cxx b/dbaccess/source/ui/uno/unoDirectSql.cxx
new file mode 100644
index 000000000..7b3a4cc6c
--- /dev/null
+++ b/dbaccess/source/ui/uno/unoDirectSql.cxx
@@ -0,0 +1,149 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+
+#include "unoDirectSql.hxx"
+#include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
+#include <com/sun/star/connection/XConnection.hpp>
+#include <com/sun/star/beans/PropertyValue.hpp>
+#include <directsql.hxx>
+#include <datasourceconnector.hxx>
+#include <strings.hxx>
+#include <tools/diagnose_ex.h>
+#include <vcl/svapp.hxx>
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+com_sun_star_comp_sdb_DirectSQLDialog_get_implementation(
+ css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const& )
+{
+ return cppu::acquire(new ::dbaui::ODirectSQLDialog(context));
+}
+
+namespace dbaui
+{
+
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::lang;
+ using namespace ::com::sun::star::beans;
+ using namespace ::com::sun::star::container;
+ using namespace ::com::sun::star::sdbcx;
+ using namespace ::com::sun::star::sdbc;
+
+ // ODirectSQLDialog
+ ODirectSQLDialog::ODirectSQLDialog(const Reference< XComponentContext >& _rxORB)
+ :ODirectSQLDialog_BASE( _rxORB )
+ {
+
+ }
+
+ ODirectSQLDialog::~ODirectSQLDialog()
+ {
+
+ }
+
+ css::uno::Sequence<sal_Int8> ODirectSQLDialog::getImplementationId()
+ {
+ return css::uno::Sequence<sal_Int8>();
+ }
+
+ OUString SAL_CALL ODirectSQLDialog::getImplementationName()
+ {
+ return "com.sun.star.comp.sdb.DirectSQLDialog";
+ }
+ sal_Bool SAL_CALL ODirectSQLDialog::supportsService(const OUString& _rServiceName)
+ {
+ const css::uno::Sequence< OUString > aSupported(getSupportedServiceNames());
+ for (const OUString& s : aSupported)
+ if (s == _rServiceName)
+ return true;
+
+ return false;
+ }
+ css::uno::Sequence< OUString > SAL_CALL ODirectSQLDialog::getSupportedServiceNames( )
+ {
+ return { SERVICE_SDB_DIRECTSQLDIALOG };
+ }
+
+ css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL ODirectSQLDialog::getPropertySetInfo()
+ {
+ Reference< XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) );
+ return xInfo;
+ }
+ ::cppu::IPropertyArrayHelper& ODirectSQLDialog::getInfoHelper()
+ {
+ return *ODirectSQLDialog::getArrayHelper();
+ }
+ ::cppu::IPropertyArrayHelper* ODirectSQLDialog::createArrayHelper( ) const
+ {
+ css::uno::Sequence< css::beans::Property > aProps;
+ describeProperties(aProps);
+ return new ::cppu::OPropertyArrayHelper(aProps);
+ }
+
+
+ std::unique_ptr<weld::DialogController> ODirectSQLDialog::createDialog(const css::uno::Reference<css::awt::XWindow>& rParent)
+ {
+ // obtain all the objects needed for the dialog
+ Reference< XConnection > xConnection = m_xActiveConnection;
+ weld::Window* pParent = Application::GetFrameWeld(rParent);
+ if ( !xConnection.is() )
+ {
+ try
+ {
+ // the connection the row set is working with
+ ODatasourceConnector aDSConnector(m_aContext, pParent);
+ xConnection = aDSConnector.connect( m_sInitialSelection, nullptr );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+ if (!xConnection.is())
+ {
+ // can't create the dialog if I have improper settings
+ return nullptr;
+ }
+
+ return std::make_unique<DirectSQLDialog>(pParent, xConnection);
+ }
+
+ void ODirectSQLDialog::implInitialize(const Any& _rValue)
+ {
+ PropertyValue aProperty;
+ if (_rValue >>= aProperty)
+ {
+ if (aProperty.Name == "InitialSelection")
+ {
+ OSL_VERIFY( aProperty.Value >>= m_sInitialSelection );
+ return;
+ }
+ else if (aProperty.Name == "ActiveConnection")
+ {
+ m_xActiveConnection.set( aProperty.Value, UNO_QUERY );
+ OSL_ENSURE( m_xActiveConnection.is(), "ODirectSQLDialog::implInitialize: invalid connection!" );
+ return;
+ }
+ }
+ ODirectSQLDialog_BASE::implInitialize(_rValue);
+ }
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/uno/unoDirectSql.hxx b/dbaccess/source/ui/uno/unoDirectSql.hxx
new file mode 100644
index 000000000..c83f975d6
--- /dev/null
+++ b/dbaccess/source/ui/uno/unoDirectSql.hxx
@@ -0,0 +1,61 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <svtools/genericunodialog.hxx>
+#include <com/sun/star/sdbc/XConnection.hpp>
+#include <comphelper/proparrhlp.hxx>
+#include <connectivity/CommonTools.hxx>
+
+namespace dbaui
+{
+
+ // ODirectSQLDialog
+ class ODirectSQLDialog;
+ typedef ::svt::OGenericUnoDialog ODirectSQLDialog_BASE;
+ typedef ::comphelper::OPropertyArrayUsageHelper< ODirectSQLDialog > ODirectSQLDialog_PBASE;
+
+ class ODirectSQLDialog
+ :public ODirectSQLDialog_BASE
+ ,public ODirectSQLDialog_PBASE
+ {
+ OUString m_sInitialSelection;
+ css::uno::Reference< css::sdbc::XConnection > m_xActiveConnection;
+ public:
+ explicit ODirectSQLDialog(const css::uno::Reference< css::uno::XComponentContext >& _rxORB);
+ virtual ~ODirectSQLDialog() override;
+
+ virtual css::uno::Sequence<sal_Int8> SAL_CALL getImplementationId() override;
+
+ DECLARE_SERVICE_INFO();
+
+ virtual css::uno::Reference< css::beans::XPropertySetInfo> SAL_CALL getPropertySetInfo() override;
+ virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper() override;
+ virtual ::cppu::IPropertyArrayHelper* createArrayHelper() const override;
+
+ protected:
+ // OGenericUnoDialog overridables
+ virtual std::unique_ptr<weld::DialogController> createDialog(const css::uno::Reference<css::awt::XWindow>& rParent) override;
+ virtual void implInitialize(const css::uno::Any& _rValue) override;
+ };
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/uno/unoadmin.cxx b/dbaccess/source/ui/uno/unoadmin.cxx
new file mode 100644
index 000000000..3d863b92e
--- /dev/null
+++ b/dbaccess/source/ui/uno/unoadmin.cxx
@@ -0,0 +1,71 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <unoadmin.hxx>
+#include <dbadmin.hxx>
+
+#include <osl/mutex.hxx>
+
+
+namespace dbaui
+{
+
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::lang;
+ using namespace ::com::sun::star::beans;
+
+ODatabaseAdministrationDialog::ODatabaseAdministrationDialog(const Reference< XComponentContext >& _rxORB)
+ :ODatabaseAdministrationDialogBase(_rxORB)
+ ,m_pItemPoolDefaults(nullptr)
+{
+ m_pCollection.reset( new ::dbaccess::ODsnTypeCollection(_rxORB) );
+ ODbAdminDialog::createItemSet(m_pDatasourceItems, m_pItemPool, m_pItemPoolDefaults, m_pCollection.get());
+}
+
+ODatabaseAdministrationDialog::~ODatabaseAdministrationDialog()
+{
+ ::osl::MutexGuard aGuard(m_aMutex);
+ if (m_xDialog)
+ destroyDialog();
+ ODbAdminDialog::destroyItemSet(m_pDatasourceItems, m_pItemPool, m_pItemPoolDefaults);
+}
+
+void ODatabaseAdministrationDialog::implInitialize(const Any& _rValue)
+{
+ PropertyValue aProperty;
+ if (_rValue >>= aProperty)
+ {
+ if (aProperty.Name == "InitialSelection")
+ {
+ m_aInitialSelection = aProperty.Value;
+ }
+ else if (aProperty.Name == "ActiveConnection")
+ {
+ m_xActiveConnection.set(aProperty.Value,UNO_QUERY);
+ }
+ else
+ ODatabaseAdministrationDialogBase::implInitialize(_rValue);
+ }
+ else
+ ODatabaseAdministrationDialogBase::implInitialize(_rValue);
+}
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/uno/unosqlmessage.cxx b/dbaccess/source/ui/uno/unosqlmessage.cxx
new file mode 100644
index 000000000..39364ba25
--- /dev/null
+++ b/dbaccess/source/ui/uno/unosqlmessage.cxx
@@ -0,0 +1,144 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sqlmessage.hxx>
+#include <unosqlmessage.hxx>
+#include <stringconstants.hxx>
+#include <strings.hxx>
+#include <comphelper/propertysequence.hxx>
+#include <connectivity/dbexception.hxx>
+#include <vcl/svapp.hxx>
+#include <com/sun/star/awt/XWindow.hpp>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/sdbc/SQLException.hpp>
+
+using namespace dbaui;
+using namespace dbtools;
+
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::sdb;
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+org_openoffice_comp_dbu_OSQLMessageDialog_get_implementation(
+ css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const& )
+{
+ return cppu::acquire(new OSQLMessageDialog(context));
+}
+
+namespace dbaui
+{
+
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::lang;
+ using namespace ::com::sun::star::beans;
+
+OSQLMessageDialog::OSQLMessageDialog(const Reference< XComponentContext >& _rxORB)
+ :OSQLMessageDialogBase(_rxORB)
+{
+ registerMayBeVoidProperty(PROPERTY_SQLEXCEPTION, PROPERTY_ID_SQLEXCEPTION, PropertyAttribute::TRANSIENT | PropertyAttribute::MAYBEVOID,
+ &m_aException, ::cppu::UnoType<SQLException>::get());
+ registerProperty( PROPERTY_HELP_URL, PROPERTY_ID_HELP_URL, PropertyAttribute::TRANSIENT,
+ &m_sHelpURL, cppu::UnoType<decltype(m_sHelpURL)>::get() );
+}
+
+Sequence<sal_Int8> SAL_CALL OSQLMessageDialog::getImplementationId( )
+{
+ return css::uno::Sequence<sal_Int8>();
+}
+
+OUString SAL_CALL OSQLMessageDialog::getImplementationName()
+{
+ return "org.openoffice.comp.dbu.OSQLMessageDialog";
+}
+
+css::uno::Sequence<OUString> SAL_CALL OSQLMessageDialog::getSupportedServiceNames()
+{
+ return { "com.sun.star.sdb.ErrorMessageDialog" };
+}
+
+void OSQLMessageDialog::initialize(Sequence<Any> const & args)
+{
+ OUString title;
+ Reference< css::awt::XWindow > parentWindow;
+
+ if ((args.getLength() == 3) && (args[0] >>= title) && (args[1] >>= parentWindow)) {
+ Sequence<Any> s(comphelper::InitAnyPropertySequence(
+ {
+ {"Title", Any(title)},
+ {"ParentWindow", Any(parentWindow)},
+ {"SQLException", args[2]}
+ }));
+ OGenericUnoDialog::initialize(s);
+ } else {
+ OGenericUnoDialog::initialize(args);
+ }
+}
+
+sal_Bool SAL_CALL OSQLMessageDialog::convertFastPropertyValue( Any& _rConvertedValue, Any& _rOldValue, sal_Int32 _nHandle, const Any& _rValue)
+{
+ switch (_nHandle)
+ {
+ case PROPERTY_ID_SQLEXCEPTION:
+ {
+ SQLExceptionInfo aInfo(_rValue);
+ if (!aInfo.isValid())
+ throw IllegalArgumentException();
+
+ _rOldValue = m_aException;
+ _rConvertedValue = aInfo.get();
+
+ return true;
+ // always assume "modified", don't bother with comparing the two values
+ }
+ default:
+ return OSQLMessageDialogBase::convertFastPropertyValue(_rConvertedValue, _rOldValue, _nHandle, _rValue);
+ }
+}
+
+Reference<XPropertySetInfo> SAL_CALL OSQLMessageDialog::getPropertySetInfo()
+{
+ Reference<XPropertySetInfo> xInfo( createPropertySetInfo( getInfoHelper() ) );
+ return xInfo;
+}
+
+::cppu::IPropertyArrayHelper& OSQLMessageDialog::getInfoHelper()
+{
+ return *getArrayHelper();
+}
+
+::cppu::IPropertyArrayHelper* OSQLMessageDialog::createArrayHelper( ) const
+{
+ Sequence< Property > aProps;
+ describeProperties(aProps);
+ return new ::cppu::OPropertyArrayHelper(aProps);
+}
+
+std::unique_ptr<weld::DialogController> OSQLMessageDialog::createDialog(const css::uno::Reference<css::awt::XWindow>& rParent)
+{
+ weld::Window* pParent = Application::GetFrameWeld(rParent);
+ if ( m_aException.hasValue() )
+ return std::make_unique<OSQLMessageBox>(pParent, SQLExceptionInfo(m_aException), MessBoxStyle::Ok | MessBoxStyle::DefaultOk, m_sHelpURL);
+
+ OSL_FAIL("OSQLMessageDialog::createDialog : You should use the SQLException property to specify the error to display!");
+ return std::make_unique<OSQLMessageBox>(pParent, SQLException());
+}
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/uiconfig/dbapp/menubar/menubar.xml b/dbaccess/uiconfig/dbapp/menubar/menubar.xml
new file mode 100644
index 000000000..7038a6360
--- /dev/null
+++ b/dbaccess/uiconfig/dbapp/menubar/menubar.xml
@@ -0,0 +1,164 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+<menu:menubar xmlns:menu="http://openoffice.org/2001/menu" menu:id="menubar">
+ <menu:menu menu:id=".uno:PickList">
+ <menu:menupopup>
+ <menu:menuitem menu:id=".uno:AddDirect"/>
+ <menu:menuitem menu:id=".uno:Open"/>
+ <menu:menuitem menu:id=".uno:RecentFileList"/>
+ <menu:menuitem menu:id=".uno:CloseDoc"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:AutoPilotMenu" menu:style="text"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:Save"/>
+ <menu:menuitem menu:id=".uno:SaveAs"/>
+ <menu:menuitem menu:id=".uno:SaveAll" menu:style="text"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:CheckOut" menu:style="text"/>
+ <menu:menuitem menu:id=".uno:CancelCheckOut" menu:style="text"/>
+ <menu:menuitem menu:id=".uno:CheckIn" menu:style="text"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:ExportTo"/>
+ <menu:menu menu:id=".uno:SendToMenu">
+ <menu:menupopup>
+ <menu:menuitem menu:id=".uno:SendMail" menu:style="text"/>
+ <menu:menuitem menu:id=".uno:DBSendReportAsMail" menu:style="text"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:DBSendReportToWriter" menu:style="text"/>
+ </menu:menupopup>
+ </menu:menu>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:Quit"/>
+ </menu:menupopup>
+ </menu:menu>
+ <menu:menu menu:id=".uno:EditMenu">
+ <menu:menupopup>
+ <menu:menuitem menu:id=".uno:Undo"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:Cut"/>
+ <menu:menuitem menu:id=".uno:Copy"/>
+ <menu:menuitem menu:id=".uno:Paste"/>
+ <menu:menuitem menu:id=".uno:PasteSpecial"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:SelectAll" menu:style="text"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:DBOpen"/>
+ <menu:menuitem menu:id=".uno:DBEdit"/>
+ <menu:menuitem menu:id=".uno:DBDelete"/>
+ <menu:menuitem menu:id=".uno:DBRename"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:DBConvertToView"/>
+ <menu:menuitem menu:id=".uno:DBEditSqlView"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:DBNewFormAutoPilotWithPreSelection"/>
+ <menu:menuitem menu:id=".uno:DBNewReportWithPreSelection"/>
+ <menu:menuitem menu:id=".uno:DBNewReportAutoPilotWithPreSelection"/>
+ <menu:menuseparator/>
+ <menu:menu menu:id=".uno:DBDatabasePropertiesMenu">
+ <menu:menupopup>
+ <menu:menuitem menu:id=".uno:DBDSProperties"/>
+ <menu:menuitem menu:id=".uno:DBDSConnectionType"/>
+ <menu:menuitem menu:id=".uno:DBDSAdvancedSettings"/>
+ </menu:menupopup>
+ </menu:menu>
+ </menu:menupopup>
+ </menu:menu>
+ <menu:menu menu:id=".uno:ViewMenu">
+ <menu:menupopup>
+ <menu:menuitem menu:id=".uno:DBViewTables" menu:style="radio"/>
+ <menu:menuitem menu:id=".uno:DBViewQueries" menu:style="radio"/>
+ <menu:menuitem menu:id=".uno:DBViewForms" menu:style="radio"/>
+ <menu:menuitem menu:id=".uno:DBViewReports" menu:style="radio"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:AvailableToolbars" menu:style="text"/>
+ <menu:menuitem menu:id=".uno:StatusBarVisible" menu:style="text"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:Sortup"/>
+ <menu:menuitem menu:id=".uno:SortDown"/>
+ <menu:menuitem menu:id=".uno:DBRefreshTables"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:DBPreview"/>
+ </menu:menupopup>
+ </menu:menu>
+ <menu:menu menu:id=".uno:InsertMenu">
+ <menu:menupopup>
+ <menu:menuitem menu:id=".uno:DBNewForm"/>
+ <menu:menuitem menu:id=".uno:DBNewReport"/>
+ <menu:menuitem menu:id=".uno:DBNewReportAutoPilot"/>
+ <menu:menuitem menu:id=".uno:DBNewQuery"/>
+ <menu:menuitem menu:id=".uno:DBNewQuerySql"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:DBNewTable"/>
+ <menu:menuitem menu:id=".uno:DBNewView"/>
+ <menu:menuitem menu:id=".uno:DBNewViewSQL"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:DBNewFolder"/>
+ </menu:menupopup>
+ </menu:menu>
+ <menu:menu menu:id=".uno:ToolsMenu">
+ <menu:menupopup>
+ <menu:menuitem menu:id=".uno:DBRelationDesign"/>
+ <menu:menuitem menu:id=".uno:DBUserAdmin"/>
+ <menu:menuitem menu:id=".uno:DBTableFilter"/>
+ <menu:menuitem menu:id=".uno:DBDirectSQL"/>
+ <menu:menuseparator/>
+ <menu:menu menu:id=".uno:MacrosMenu">
+ <menu:menupopup>
+ <menu:menuitem menu:id=".uno:MacroRecorder"/>
+ <menu:menuitem menu:id=".uno:RunMacro"/>
+ <menu:menuitem menu:id=".uno:BasicIDEAppear"/>
+ <menu:menuitem menu:id=".uno:ScriptOrganizer"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:MacroSignature"/>
+ <menu:menuitem menu:id=".uno:MacroOrganizer?TabId:short=1"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:OpenXMLFilterSettings"/>
+ </menu:menupopup>
+ </menu:menu>
+ <menu:menuitem menu:id="service:com.sun.star.deployment.ui.PackageManagerDialog" menu:style="text"/>
+ <menu:menuitem menu:id=".uno:ConfigureDialog" menu:style="text"/>
+ <menu:menuitem menu:id=".uno:OptionsTreeDialog"/>
+ </menu:menupopup>
+ </menu:menu>
+ <menu:menu menu:id=".uno:WindowList">
+ <menu:menupopup>
+ <menu:menuitem menu:id=".uno:CloseWin"/>
+ <menu:menuseparator/>
+ </menu:menupopup>
+ </menu:menu>
+ <menu:menu menu:id=".uno:HelpMenu">
+ <menu:menupopup>
+ <menu:menuitem menu:id=".uno:HelpIndex"/>
+ <menu:menuitem menu:id=".uno:ExtendedHelp"/>
+ <menu:menuitem menu:id=".uno:Documentation"/>
+ <menu:menuitem menu:id=".uno:TipOfTheDay"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:QuestionAnswers"/>
+ <menu:menuitem menu:id=".uno:SendFeedback"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:SafeMode"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:GetInvolved"/>
+ <menu:menuitem menu:id=".uno:Donation"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:ShowLicense"/>
+ <menu:menuitem menu:id=".uno:About"/>
+ </menu:menupopup>
+ </menu:menu>
+</menu:menubar>
diff --git a/dbaccess/uiconfig/dbapp/popupmenu/edit.xml b/dbaccess/uiconfig/dbapp/popupmenu/edit.xml
new file mode 100644
index 000000000..539b9e74c
--- /dev/null
+++ b/dbaccess/uiconfig/dbapp/popupmenu/edit.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+-->
+<menu:menupopup xmlns:menu="http://openoffice.org/2001/menu">
+ <menu:menuitem menu:id=".uno:Copy"/>
+ <menu:menuitem menu:id=".uno:Paste"/>
+ <menu:menuitem menu:id=".uno:PasteSpecial"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:SelectAll"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:DBDelete"/>
+ <menu:menuitem menu:id=".uno:DBRename"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:DBConvertToView"/>
+ <menu:menuitem menu:id=".uno:DBNewFormAutoPilotWithPreSelection"/>
+ <menu:menuitem menu:id=".uno:DBNewReportAutoPilotWithPreSelection"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:DBOpen"/>
+ <menu:menuitem menu:id=".uno:DBEdit"/>
+ <menu:menuitem menu:id=".uno:DBEditSqlView"/>
+ <menu:menuseparator/>
+ <menu:menu menu:id=".uno:DBDatabasePropertiesMenu">
+ <menu:menupopup>
+ <menu:menuitem menu:id=".uno:DBDSProperties"/>
+ <menu:menuitem menu:id=".uno:DBDSConnectionType"/>
+ <menu:menuitem menu:id=".uno:DBDSAdvancedSettings"/>
+ </menu:menupopup>
+ </menu:menu>
+</menu:menupopup>
diff --git a/dbaccess/uiconfig/dbapp/popupmenu/new.xml b/dbaccess/uiconfig/dbapp/popupmenu/new.xml
new file mode 100644
index 000000000..fd9a23a9d
--- /dev/null
+++ b/dbaccess/uiconfig/dbapp/popupmenu/new.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+-->
+<menu:menupopup xmlns:menu="http://openoffice.org/2001/menu">
+ <menu:menuitem menu:id=".uno:DBNewForm"/>
+ <menu:menuitem menu:id=".uno:DBNewReport"/>
+ <menu:menuitem menu:id=".uno:DBNewReportAutoPilot"/>
+ <menu:menuitem menu:id=".uno:DBNewQuery"/>
+ <menu:menuitem menu:id=".uno:DBNewQuerySql"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:DBNewTable"/>
+ <menu:menuitem menu:id=".uno:DBNewView"/>
+ <menu:menuitem menu:id=".uno:DBNewViewSQL"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:DBNewFolder"/>
+</menu:menupopup>
diff --git a/dbaccess/uiconfig/dbapp/popupmenu/preview.xml b/dbaccess/uiconfig/dbapp/popupmenu/preview.xml
new file mode 100644
index 000000000..eb58afdb9
--- /dev/null
+++ b/dbaccess/uiconfig/dbapp/popupmenu/preview.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+-->
+<menu:menupopup xmlns:menu="http://openoffice.org/2001/menu">
+ <menu:menuitem menu:id=".uno:DBDisablePreview" menu:style="radio"/>
+ <menu:menuitem menu:id=".uno:DBShowDocInfoPreview" menu:style="radio"/>
+ <menu:menuitem menu:id=".uno:DBShowDocPreview" menu:style="radio"/>
+</menu:menupopup>
diff --git a/dbaccess/uiconfig/dbapp/statusbar/statusbar.xml b/dbaccess/uiconfig/dbapp/statusbar/statusbar.xml
new file mode 100644
index 000000000..8e4801d50
--- /dev/null
+++ b/dbaccess/uiconfig/dbapp/statusbar/statusbar.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE statusbar:statusbar PUBLIC "-//OpenOffice.org//DTD OfficeDocument 1.0//EN" "statusbar.dtd">
+<!--
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ -->
+<statusbar:statusbar xmlns:statusbar="http://openoffice.org/2001/statusbar" xmlns:xlink="http://www.w3.org/1999/xlink">
+ <statusbar:statusbaritem xlink:href=".uno:DBStatusType" statusbar:align="left" statusbar:autosize="true" statusbar:width="50"/>
+ <statusbar:statusbaritem xlink:href=".uno:DBStatusDBName" statusbar:align="left" statusbar:autosize="true" statusbar:width="70"/>
+ <statusbar:statusbaritem xlink:href=".uno:DBStatusUserName" statusbar:align="left" statusbar:autosize="true" statusbar:width="70"/>
+ <statusbar:statusbaritem xlink:href=".uno:DBStatusHostName" statusbar:align="left" statusbar:autosize="true" statusbar:width="70"/>
+</statusbar:statusbar>
diff --git a/dbaccess/uiconfig/dbapp/toolbar/formobjectbar.xml b/dbaccess/uiconfig/dbapp/toolbar/formobjectbar.xml
new file mode 100644
index 000000000..78e698df3
--- /dev/null
+++ b/dbaccess/uiconfig/dbapp/toolbar/formobjectbar.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE toolbar:toolbar PUBLIC "-//OpenOffice.org//DTD OfficeDocument 1.0//EN" "toolbar.dtd">
+<!--
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ -->
+<toolbar:toolbar xmlns:toolbar="http://openoffice.org/2001/toolbar" xmlns:xlink="http://www.w3.org/1999/xlink">
+ <toolbar:toolbaritem xlink:href=".uno:DBNewForm"/>
+ <toolbar:toolbaritem xlink:href=".uno:DBFormOpen"/>
+ <toolbar:toolbaritem xlink:href=".uno:DBFormEdit"/>
+ <toolbar:toolbarseparator/>
+ <toolbar:toolbaritem xlink:href=".uno:DBFormDelete"/>
+ <toolbar:toolbaritem xlink:href=".uno:DBFormRename"/>
+ <toolbar:toolbarseparator/>
+ <toolbar:toolbaritem xlink:href=".uno:DBNewFormAutoPilotWithPreSelection" toolbar:visible="false"/>
+ <toolbar:toolbaritem xlink:href=".uno:DBNewReportWithPreSelection" toolbar:visible="false"/>
+ <toolbar:toolbaritem xlink:href=".uno:DBNewReportAutoPilotWithPreSelection" toolbar:visible="false"/>
+</toolbar:toolbar>
diff --git a/dbaccess/uiconfig/dbapp/toolbar/queryobjectbar.xml b/dbaccess/uiconfig/dbapp/toolbar/queryobjectbar.xml
new file mode 100644
index 000000000..9733036ea
--- /dev/null
+++ b/dbaccess/uiconfig/dbapp/toolbar/queryobjectbar.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE toolbar:toolbar PUBLIC "-//OpenOffice.org//DTD OfficeDocument 1.0//EN" "toolbar.dtd">
+<!--
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ -->
+<toolbar:toolbar xmlns:toolbar="http://openoffice.org/2001/toolbar" xmlns:xlink="http://www.w3.org/1999/xlink">
+ <toolbar:toolbaritem xlink:href=".uno:DBNewQuery"/>
+ <toolbar:toolbaritem xlink:href=".uno:DBNewQuerySql"/>
+ <toolbar:toolbaritem xlink:href=".uno:DBQueryOpen"/>
+ <toolbar:toolbaritem xlink:href=".uno:DBQueryEdit"/>
+ <toolbar:toolbarseparator/>
+ <toolbar:toolbaritem xlink:href=".uno:DBQueryDelete"/>
+ <toolbar:toolbaritem xlink:href=".uno:DBQueryRename"/>
+ <toolbar:toolbarseparator/>
+ <toolbar:toolbaritem xlink:href=".uno:DBNewFormAutoPilotWithPreSelection" toolbar:visible="false"/>
+ <toolbar:toolbaritem xlink:href=".uno:DBNewReportWithPreSelection" toolbar:visible="false"/>
+ <toolbar:toolbaritem xlink:href=".uno:DBNewReportAutoPilotWithPreSelection" toolbar:visible="false"/>
+</toolbar:toolbar>
diff --git a/dbaccess/uiconfig/dbapp/toolbar/reportobjectbar.xml b/dbaccess/uiconfig/dbapp/toolbar/reportobjectbar.xml
new file mode 100644
index 000000000..a8cd8c834
--- /dev/null
+++ b/dbaccess/uiconfig/dbapp/toolbar/reportobjectbar.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE toolbar:toolbar PUBLIC "-//OpenOffice.org//DTD OfficeDocument 1.0//EN" "toolbar.dtd">
+<!--
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ -->
+<toolbar:toolbar xmlns:toolbar="http://openoffice.org/2001/toolbar" xmlns:xlink="http://www.w3.org/1999/xlink">
+ <toolbar:toolbaritem xlink:href=".uno:DBNewReport"/>
+ <toolbar:toolbaritem xlink:href=".uno:DBNewReportAutoPilot"/>
+ <toolbar:toolbaritem xlink:href=".uno:DBReportOpen"/>
+ <toolbar:toolbaritem xlink:href=".uno:DBReportEdit"/>
+ <toolbar:toolbarseparator/>
+ <toolbar:toolbaritem xlink:href=".uno:DBReportDelete"/>
+ <toolbar:toolbaritem xlink:href=".uno:DBReportRename"/>
+ <toolbar:toolbarseparator/>
+ <toolbar:toolbaritem xlink:href=".uno:DBNewFormAutoPilotWithPreSelection" toolbar:visible="false"/>
+ <toolbar:toolbaritem xlink:href=".uno:DBNewReportWithPreSelection" toolbar:visible="false"/>
+ <toolbar:toolbaritem xlink:href=".uno:DBNewReportAutoPilotWithPreSelection" toolbar:visible="false"/>
+</toolbar:toolbar>
diff --git a/dbaccess/uiconfig/dbapp/toolbar/tableobjectbar.xml b/dbaccess/uiconfig/dbapp/toolbar/tableobjectbar.xml
new file mode 100644
index 000000000..b852d03a2
--- /dev/null
+++ b/dbaccess/uiconfig/dbapp/toolbar/tableobjectbar.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE toolbar:toolbar PUBLIC "-//OpenOffice.org//DTD OfficeDocument 1.0//EN" "toolbar.dtd">
+<!--
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ -->
+<toolbar:toolbar xmlns:toolbar="http://openoffice.org/2001/toolbar" xmlns:xlink="http://www.w3.org/1999/xlink">
+ <toolbar:toolbaritem xlink:href=".uno:DBNewTable"/>
+ <toolbar:toolbaritem xlink:href=".uno:DBTableOpen"/>
+ <toolbar:toolbaritem xlink:href=".uno:DBTableEdit"/>
+ <toolbar:toolbarseparator/>
+ <toolbar:toolbaritem xlink:href=".uno:DBTableDelete"/>
+ <toolbar:toolbaritem xlink:href=".uno:DBTableRename"/>
+ <toolbar:toolbarseparator/>
+ <toolbar:toolbaritem xlink:href=".uno:DBNewFormAutoPilotWithPreSelection" toolbar:visible="false"/>
+ <toolbar:toolbaritem xlink:href=".uno:DBNewReportWithPreSelection" toolbar:visible="false"/>
+ <toolbar:toolbaritem xlink:href=".uno:DBNewReportAutoPilotWithPreSelection" toolbar:visible="false"/>
+</toolbar:toolbar>
diff --git a/dbaccess/uiconfig/dbapp/toolbar/toolbar.xml b/dbaccess/uiconfig/dbapp/toolbar/toolbar.xml
new file mode 100644
index 000000000..62c48f1c4
--- /dev/null
+++ b/dbaccess/uiconfig/dbapp/toolbar/toolbar.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE toolbar:toolbar PUBLIC "-//OpenOffice.org//DTD OfficeDocument 1.0//EN" "toolbar.dtd">
+<!--
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ -->
+<toolbar:toolbar xmlns:toolbar="http://openoffice.org/2001/toolbar" xmlns:xlink="http://www.w3.org/1999/xlink">
+ <toolbar:toolbaritem xlink:href=".uno:OpenUrl" toolbar:visible="false"/>
+ <toolbar:toolbaritem xlink:href=".uno:AddDirect"/>
+ <toolbar:toolbaritem xlink:href=".uno:Open"/>
+ <toolbar:toolbaritem xlink:href=".uno:Save"/>
+ <toolbar:toolbarseparator/>
+ <toolbar:toolbaritem xlink:href=".uno:Copy"/>
+ <toolbar:toolbaritem xlink:href=".uno:Paste"/>
+ <toolbar:toolbarseparator/>
+ <toolbar:toolbaritem xlink:href=".uno:Sortup"/>
+ <toolbar:toolbaritem xlink:href=".uno:SortDown"/>
+ <toolbar:toolbarseparator/>
+ <toolbar:toolbaritem xlink:href=".uno:DBNewForm"/>
+ <toolbar:toolbarseparator/>
+ <toolbar:toolbaritem xlink:href=".uno:HelpIndex"/>
+ <toolbar:toolbaritem xlink:href=".uno:ExtendedHelp" toolbar:visible="false"/>
+</toolbar:toolbar>
diff --git a/dbaccess/uiconfig/dbbrowser/menubar/compat.xml b/dbaccess/uiconfig/dbbrowser/menubar/compat.xml
new file mode 100644
index 000000000..1e224627c
--- /dev/null
+++ b/dbaccess/uiconfig/dbbrowser/menubar/compat.xml
@@ -0,0 +1 @@
+<compat/>
diff --git a/dbaccess/uiconfig/dbbrowser/menubar/preserve.txt b/dbaccess/uiconfig/dbbrowser/menubar/preserve.txt
new file mode 100644
index 000000000..268db482c
--- /dev/null
+++ b/dbaccess/uiconfig/dbbrowser/menubar/preserve.txt
@@ -0,0 +1 @@
+Needed for compatibility reasons. \ No newline at end of file
diff --git a/dbaccess/uiconfig/dbbrowser/popupmenu/explorer.xml b/dbaccess/uiconfig/dbbrowser/popupmenu/explorer.xml
new file mode 100644
index 000000000..3be0c047a
--- /dev/null
+++ b/dbaccess/uiconfig/dbbrowser/popupmenu/explorer.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+-->
+<menu:menupopup xmlns:menu="http://openoffice.org/2001/menu">
+ <menu:menuitem menu:id=".uno:DSBEditDB"/>
+ <menu:menuitem menu:id=".uno:DSBCloseConnection"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:Copy"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:DSBAdministrate"/>
+</menu:menupopup>
diff --git a/dbaccess/uiconfig/dbbrowser/popupmenu/refreshdata.xml b/dbaccess/uiconfig/dbbrowser/popupmenu/refreshdata.xml
new file mode 100644
index 000000000..216c6c53c
--- /dev/null
+++ b/dbaccess/uiconfig/dbbrowser/popupmenu/refreshdata.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+-->
+<menu:menupopup xmlns:menu="http://openoffice.org/2001/menu">
+ <menu:menuitem menu:id=".uno:Refresh"/>
+ <menu:menuitem menu:id=".uno:DBRebuildData"/>
+</menu:menupopup>
diff --git a/dbaccess/uiconfig/dbbrowser/toolbar/toolbar.xml b/dbaccess/uiconfig/dbbrowser/toolbar/toolbar.xml
new file mode 100644
index 000000000..3f73d9a58
--- /dev/null
+++ b/dbaccess/uiconfig/dbbrowser/toolbar/toolbar.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE toolbar:toolbar PUBLIC "-//OpenOffice.org//DTD OfficeDocument 1.0//EN" "toolbar.dtd">
+<!--
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ -->
+<toolbar:toolbar xmlns:toolbar="http://openoffice.org/2001/toolbar" xmlns:xlink="http://www.w3.org/1999/xlink">
+ <toolbar:toolbaritem xlink:href=".uno:RecSave"/>
+ <toolbar:toolbarseparator/>
+ <toolbar:toolbaritem xlink:href=".uno:DSBEditDoc"/>
+ <toolbar:toolbarseparator/>
+ <toolbar:toolbaritem xlink:href=".uno:Cut"/>
+ <toolbar:toolbaritem xlink:href=".uno:Copy"/>
+ <toolbar:toolbaritem xlink:href=".uno:Paste"/>
+ <toolbar:toolbarseparator/>
+ <toolbar:toolbaritem xlink:href=".uno:RecUndo"/>
+ <toolbar:toolbarseparator/>
+ <toolbar:toolbaritem xlink:href=".uno:RecSearch"/>
+ <toolbar:toolbarseparator/>
+ <toolbar:toolbaritem xlink:href=".uno:Refresh"/>
+ <toolbar:toolbarseparator/>
+ <toolbar:toolbaritem xlink:href=".uno:OrderCrit"/>
+ <toolbar:toolbaritem xlink:href=".uno:Sortup"/>
+ <toolbar:toolbaritem xlink:href=".uno:SortDown"/>
+ <toolbar:toolbarseparator/>
+ <toolbar:toolbaritem xlink:href=".uno:AutoFilter"/>
+ <toolbar:toolbaritem xlink:href=".uno:FormFiltered"/>
+ <toolbar:toolbaritem xlink:href=".uno:FilterCrit"/>
+ <toolbar:toolbarseparator/>
+ <toolbar:toolbaritem xlink:href=".uno:RemoveFilterSort"/>
+ <toolbar:toolbarseparator/>
+ <toolbar:toolbaritem xlink:href=".uno:DSBInsertColumns"/>
+ <toolbar:toolbaritem xlink:href=".uno:DSBInsertContent"/>
+ <toolbar:toolbaritem xlink:href=".uno:DSBFormLetter"/>
+ <toolbar:toolbaritem xlink:href=".uno:DSBDocumentDataSource"/>
+ <toolbar:toolbaritem xlink:href=".uno:DSBrowserExplorer"/>
+</toolbar:toolbar>
diff --git a/dbaccess/uiconfig/dbquery/menubar/menubar.xml b/dbaccess/uiconfig/dbquery/menubar/menubar.xml
new file mode 100644
index 000000000..8227446b4
--- /dev/null
+++ b/dbaccess/uiconfig/dbquery/menubar/menubar.xml
@@ -0,0 +1,119 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+<menu:menubar xmlns:menu="http://openoffice.org/2001/menu" menu:id="menubar">
+ <menu:menu menu:id=".uno:PickList">
+ <menu:menupopup>
+ <menu:menuitem menu:id=".uno:AddDirect"/>
+ <menu:menuitem menu:id=".uno:Open"/>
+ <menu:menuitem menu:id=".uno:CloseDoc"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:AutoPilotMenu" menu:style="text"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:Save"/>
+ <menu:menuitem menu:id=".uno:SaveAs"/>
+ <menu:menuitem menu:id=".uno:SaveAll" menu:style="text"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:CheckOut" menu:style="text"/>
+ <menu:menuitem menu:id=".uno:CancelCheckOut" menu:style="text"/>
+ <menu:menuitem menu:id=".uno:CheckIn" menu:style="text"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:Quit"/>
+ </menu:menupopup>
+ </menu:menu>
+ <menu:menu menu:id=".uno:EditMenu">
+ <menu:menupopup>
+ <menu:menuitem menu:id=".uno:Undo"/>
+ <menu:menuitem menu:id=".uno:Redo"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:Cut"/>
+ <menu:menuitem menu:id=".uno:Copy"/>
+ <menu:menuitem menu:id=".uno:Paste"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:SbaExecuteSql"/>
+ <menu:menuitem menu:id=".uno:SbaNativeSql"/>
+ <menu:menuitem menu:id=".uno:DBClearQuery"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:DBQueryPropertiesDialog"/>
+ </menu:menupopup>
+ </menu:menu>
+ <menu:menu menu:id=".uno:ViewMenu">
+ <menu:menupopup>
+ <menu:menuitem menu:id=".uno:DBChangeDesignMode"/>
+ <menu:menuitem menu:id=".uno:DBQueryPreview"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:AvailableToolbars"/>
+ <menu:menuitem menu:id=".uno:StatusBarVisible"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:DBViewFunctions"/>
+ <menu:menuitem menu:id=".uno:DBViewTableNames"/>
+ <menu:menuitem menu:id=".uno:DBViewAliases"/>
+ </menu:menupopup>
+ </menu:menu>
+ <menu:menu menu:id=".uno:InsertMenu">
+ <menu:menupopup>
+ <menu:menuitem menu:id=".uno:DBAddRelation"/>
+ <menu:menuitem menu:id=".uno:AddTable"/>
+ </menu:menupopup>
+ </menu:menu>
+ <menu:menu menu:id=".uno:ToolsMenu">
+ <menu:menupopup>
+ <menu:menu menu:id=".uno:MacrosMenu">
+ <menu:menupopup>
+ <menu:menuitem menu:id=".uno:MacroRecorder"/>
+ <menu:menuitem menu:id=".uno:RunMacro"/>
+ <menu:menuitem menu:id=".uno:BasicIDEAppear"/>
+ <menu:menuitem menu:id=".uno:ScriptOrganizer"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:MacroSignature"/>
+ <menu:menuitem menu:id=".uno:MacroOrganizer?TabId:short=1"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:OpenXMLFilterSettings"/>
+ </menu:menupopup>
+ </menu:menu>
+ <menu:menuitem menu:id="service:com.sun.star.deployment.ui.PackageManagerDialog" menu:style="text"/>
+ <menu:menuitem menu:id=".uno:ConfigureDialog" menu:style="text"/>
+ <menu:menuitem menu:id=".uno:OptionsTreeDialog"/>
+ </menu:menupopup>
+ </menu:menu>
+ <menu:menu menu:id=".uno:WindowList">
+ <menu:menupopup>
+ <menu:menuitem menu:id=".uno:CloseWin"/>
+ <menu:menuseparator/>
+ </menu:menupopup>
+ </menu:menu>
+ <menu:menu menu:id=".uno:HelpMenu">
+ <menu:menupopup>
+ <menu:menuitem menu:id=".uno:HelpIndex"/>
+ <menu:menuitem menu:id=".uno:ExtendedHelp"/>
+ <menu:menuitem menu:id=".uno:Documentation"/>
+ <menu:menuitem menu:id=".uno:TipOfTheDay"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:QuestionAnswers"/>
+ <menu:menuitem menu:id=".uno:SendFeedback"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:SafeMode"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:GetInvolved"/>
+ <menu:menuitem menu:id=".uno:Donation"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:ShowLicense"/>
+ <menu:menuitem menu:id=".uno:About"/>
+ </menu:menupopup>
+ </menu:menu>
+</menu:menubar>
diff --git a/dbaccess/uiconfig/dbquery/toolbar/designobjectbar.xml b/dbaccess/uiconfig/dbquery/toolbar/designobjectbar.xml
new file mode 100644
index 000000000..af8b850d4
--- /dev/null
+++ b/dbaccess/uiconfig/dbquery/toolbar/designobjectbar.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE toolbar:toolbar PUBLIC "-//OpenOffice.org//DTD OfficeDocument 1.0//EN" "toolbar.dtd">
+<!--
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ -->
+<toolbar:toolbar xmlns:toolbar="http://openoffice.org/2001/toolbar" xmlns:xlink="http://www.w3.org/1999/xlink">
+ <toolbar:toolbaritem xlink:href=".uno:AddTable"/>
+ <toolbar:toolbarseparator/>
+ <toolbar:toolbaritem xlink:href=".uno:DBViewFunctions"/>
+ <toolbar:toolbaritem xlink:href=".uno:DBViewTableNames"/>
+ <toolbar:toolbaritem xlink:href=".uno:DBViewAliases"/>
+ <toolbar:toolbaritem xlink:href=".uno:DBDistinctValues"/>
+ <toolbar:toolbaritem xlink:href=".uno:DBLimit"/>
+ <toolbar:toolbaritem xlink:href=".uno:DBQueryPropertiesDialog"/>
+</toolbar:toolbar>
diff --git a/dbaccess/uiconfig/dbquery/toolbar/sqlobjectbar.xml b/dbaccess/uiconfig/dbquery/toolbar/sqlobjectbar.xml
new file mode 100644
index 000000000..c6898fd26
--- /dev/null
+++ b/dbaccess/uiconfig/dbquery/toolbar/sqlobjectbar.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE toolbar:toolbar PUBLIC "-//OpenOffice.org//DTD OfficeDocument 1.0//EN" "toolbar.dtd">
+<!--
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ -->
+<toolbar:toolbar xmlns:toolbar="http://openoffice.org/2001/toolbar" xmlns:xlink="http://www.w3.org/1999/xlink">
+ <toolbar:toolbaritem xlink:href=".uno:SbaNativeSql"/>
+</toolbar:toolbar> \ No newline at end of file
diff --git a/dbaccess/uiconfig/dbquery/toolbar/toolbar.xml b/dbaccess/uiconfig/dbquery/toolbar/toolbar.xml
new file mode 100644
index 000000000..55480895c
--- /dev/null
+++ b/dbaccess/uiconfig/dbquery/toolbar/toolbar.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE toolbar:toolbar PUBLIC "-//OpenOffice.org//DTD OfficeDocument 1.0//EN" "toolbar.dtd">
+<!--
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ -->
+<toolbar:toolbar xmlns:toolbar="http://openoffice.org/2001/toolbar" xmlns:xlink="http://www.w3.org/1999/xlink">
+ <toolbar:toolbaritem xlink:href=".uno:Save"/>
+ <toolbar:toolbaritem xlink:href=".uno:SaveAs" toolbar:visible="false"/>
+ <toolbar:toolbaritem xlink:href=".uno:EditDoc"/>
+ <toolbar:toolbarseparator/>
+ <toolbar:toolbaritem xlink:href=".uno:Cut"/>
+ <toolbar:toolbaritem xlink:href=".uno:Copy"/>
+ <toolbar:toolbaritem xlink:href=".uno:Paste"/>
+ <toolbar:toolbarseparator/>
+ <toolbar:toolbaritem xlink:href=".uno:Undo"/>
+ <toolbar:toolbaritem xlink:href=".uno:Redo"/>
+ <toolbar:toolbarseparator/>
+ <toolbar:toolbaritem xlink:href=".uno:SbaExecuteSql"/>
+ <toolbar:toolbaritem xlink:href=".uno:DBChangeDesignMode"/>
+ <toolbar:toolbarseparator/>
+ <toolbar:toolbaritem xlink:href=".uno:DBClearQuery"/>
+ <toolbar:toolbarseparator/>
+ <toolbar:toolbaritem xlink:href=".uno:CloseDoc"/>
+</toolbar:toolbar>
diff --git a/dbaccess/uiconfig/dbrelation/menubar/menubar.xml b/dbaccess/uiconfig/dbrelation/menubar/menubar.xml
new file mode 100644
index 000000000..6e3df781e
--- /dev/null
+++ b/dbaccess/uiconfig/dbrelation/menubar/menubar.xml
@@ -0,0 +1,103 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ -->
+<menu:menubar xmlns:menu="http://openoffice.org/2001/menu" menu:id="menubar">
+ <menu:menu menu:id=".uno:PickList">
+ <menu:menupopup>
+ <menu:menuitem menu:id=".uno:AddDirect"/>
+ <menu:menuitem menu:id=".uno:Open"/>
+ <menu:menuitem menu:id=".uno:RecentFileList"/>
+ <menu:menuitem menu:id=".uno:CloseDoc"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:AutoPilotMenu" menu:style="text"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:Save"/>
+ <menu:menuitem menu:id=".uno:SaveAll" menu:style="text"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:CheckOut" menu:style="text"/>
+ <menu:menuitem menu:id=".uno:CancelCheckOut" menu:style="text"/>
+ <menu:menuitem menu:id=".uno:CheckIn" menu:style="text"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:Quit"/>
+ </menu:menupopup>
+ </menu:menu>
+ <menu:menu menu:id=".uno:EditMenu">
+ <menu:menupopup>
+ <menu:menuitem menu:id=".uno:Undo"/>
+ <menu:menuitem menu:id=".uno:Redo"/>
+ </menu:menupopup>
+ </menu:menu>
+ <menu:menu menu:id=".uno:ViewMenu">
+ <menu:menupopup>
+ <menu:menuitem menu:id=".uno:AvailableToolbars" menu:style="text"/>
+ <menu:menuitem menu:id=".uno:StatusBarVisible" menu:style="text"/>
+ </menu:menupopup>
+ </menu:menu>
+ <menu:menu menu:id=".uno:InsertMenu">
+ <menu:menupopup>
+ <menu:menuitem menu:id=".uno:DBAddRelation"/>
+ <menu:menuitem menu:id=".uno:AddTable"/>
+ </menu:menupopup>
+ </menu:menu>
+ <menu:menu menu:id=".uno:ToolsMenu">
+ <menu:menupopup>
+ <menu:menu menu:id=".uno:MacrosMenu">
+ <menu:menupopup>
+ <menu:menuitem menu:id=".uno:MacroRecorder"/>
+ <menu:menuitem menu:id=".uno:RunMacro"/>
+ <menu:menuitem menu:id=".uno:BasicIDEAppear"/>
+ <menu:menuitem menu:id=".uno:ScriptOrganizer"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:MacroSignature"/>
+ <menu:menuitem menu:id=".uno:MacroOrganizer?TabId:short=1"/>
+ <menu:menuitem menu:id=".uno:ScriptOrganizer"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:OpenXMLFilterSettings"/>
+ </menu:menupopup>
+ </menu:menu>
+ <menu:menuitem menu:id="service:com.sun.star.deployment.ui.PackageManagerDialog" menu:style="text"/>
+ <menu:menuitem menu:id=".uno:ConfigureDialog" menu:style="text"/>
+ <menu:menuitem menu:id=".uno:OptionsTreeDialog"/>
+ </menu:menupopup>
+ </menu:menu>
+ <menu:menu menu:id=".uno:WindowList">
+ <menu:menupopup>
+ <menu:menuitem menu:id=".uno:CloseWin"/>
+ <menu:menuseparator/>
+ </menu:menupopup>
+ </menu:menu>
+ <menu:menu menu:id=".uno:HelpMenu">
+ <menu:menupopup>
+ <menu:menuitem menu:id=".uno:HelpIndex"/>
+ <menu:menuitem menu:id=".uno:ExtendedHelp"/>
+ <menu:menuitem menu:id=".uno:Documentation"/>
+ <menu:menuitem menu:id=".uno:TipOfTheDay"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:QuestionAnswers"/>
+ <menu:menuitem menu:id=".uno:SendFeedback"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:SafeMode"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:GetInvolved"/>
+ <menu:menuitem menu:id=".uno:Donation"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:ShowLicense"/>
+ <menu:menuitem menu:id=".uno:About"/>
+ </menu:menupopup>
+ </menu:menu>
+</menu:menubar>
diff --git a/dbaccess/uiconfig/dbrelation/toolbar/toolbar.xml b/dbaccess/uiconfig/dbrelation/toolbar/toolbar.xml
new file mode 100644
index 000000000..a01cb895c
--- /dev/null
+++ b/dbaccess/uiconfig/dbrelation/toolbar/toolbar.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE toolbar:toolbar PUBLIC "-//OpenOffice.org//DTD OfficeDocument 1.0//EN" "toolbar.dtd">
+<!--
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ -->
+<toolbar:toolbar xmlns:toolbar="http://openoffice.org/2001/toolbar" xmlns:xlink="http://www.w3.org/1999/xlink">
+ <toolbar:toolbaritem xlink:href=".uno:Save"/>
+ <toolbar:toolbaritem xlink:href=".uno:EditDoc" toolbar:visible="false"/>
+ <toolbar:toolbarseparator/>
+ <toolbar:toolbaritem xlink:href=".uno:Undo"/>
+ <toolbar:toolbaritem xlink:href=".uno:Redo"/>
+ <toolbar:toolbarseparator/>
+ <toolbar:toolbaritem xlink:href=".uno:AddTable"/>
+ <toolbar:toolbaritem xlink:href=".uno:DBAddRelation"/>
+ <toolbar:toolbarseparator/>
+ <toolbar:toolbaritem xlink:href=".uno:CloseDoc"/>
+</toolbar:toolbar>
diff --git a/dbaccess/uiconfig/dbtable/menubar/menubar.xml b/dbaccess/uiconfig/dbtable/menubar/menubar.xml
new file mode 100644
index 000000000..bbd4a7428
--- /dev/null
+++ b/dbaccess/uiconfig/dbtable/menubar/menubar.xml
@@ -0,0 +1,103 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+<menu:menubar xmlns:menu="http://openoffice.org/2001/menu" menu:id="menubar">
+ <menu:menu menu:id=".uno:PickList">
+ <menu:menupopup>
+ <menu:menuitem menu:id=".uno:AddDirect"/>
+ <menu:menuitem menu:id=".uno:Open"/>
+ <menu:menuitem menu:id=".uno:RecentFileList"/>
+ <menu:menuitem menu:id=".uno:CloseDoc"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:AutoPilotMenu" menu:style="text"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:Save"/>
+ <menu:menuitem menu:id=".uno:SaveAs"/>
+ <menu:menuitem menu:id=".uno:SaveAll" menu:style="text"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:CheckOut" menu:style="text"/>
+ <menu:menuitem menu:id=".uno:CancelCheckOut" menu:style="text"/>
+ <menu:menuitem menu:id=".uno:CheckIn" menu:style="text"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:Quit"/>
+ </menu:menupopup>
+ </menu:menu>
+ <menu:menu menu:id=".uno:EditMenu">
+ <menu:menupopup>
+ <menu:menuitem menu:id=".uno:Undo"/>
+ <menu:menuitem menu:id=".uno:Redo"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:Cut"/>
+ <menu:menuitem menu:id=".uno:Copy"/>
+ <menu:menuitem menu:id=".uno:Paste"/>
+ </menu:menupopup>
+ </menu:menu>
+ <menu:menu menu:id=".uno:ViewMenu">
+ <menu:menupopup>
+ <menu:menuitem menu:id=".uno:AvailableToolbars" menu:style="text"/>
+ <menu:menuitem menu:id=".uno:StatusBarVisible" menu:style="text"/>
+ </menu:menupopup>
+ </menu:menu>
+ <menu:menu menu:id=".uno:ToolsMenu">
+ <menu:menupopup>
+ <menu:menuitem menu:id=".uno:DBIndexDesign"/>
+ <menu:menuseparator/>
+ <menu:menu menu:id=".uno:MacrosMenu">
+ <menu:menupopup>
+ <menu:menuitem menu:id=".uno:MacroRecorder"/>
+ <menu:menuitem menu:id=".uno:RunMacro"/>
+ <menu:menuitem menu:id=".uno:BasicIDEAppear"/>
+ <menu:menuitem menu:id=".uno:ScriptOrganizer"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:MacroSignature"/>
+ <menu:menuitem menu:id=".uno:MacroOrganizer?TabId:short=1"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:OpenXMLFilterSettings"/>
+ </menu:menupopup>
+ </menu:menu>
+ <menu:menuitem menu:id="service:com.sun.star.deployment.ui.PackageManagerDialog" menu:style="text"/>
+ <menu:menuitem menu:id=".uno:ConfigureDialog" menu:style="text"/>
+ <menu:menuitem menu:id=".uno:OptionsTreeDialog"/>
+ </menu:menupopup>
+ </menu:menu>
+ <menu:menu menu:id=".uno:WindowList">
+ <menu:menupopup>
+ <menu:menuitem menu:id=".uno:CloseWin"/>
+ <menu:menuseparator/>
+ </menu:menupopup>
+ </menu:menu>
+ <menu:menu menu:id=".uno:HelpMenu">
+ <menu:menupopup>
+ <menu:menuitem menu:id=".uno:HelpIndex"/>
+ <menu:menuitem menu:id=".uno:ExtendedHelp"/>
+ <menu:menuitem menu:id=".uno:Documentation"/>
+ <menu:menuitem menu:id=".uno:TipOfTheDay"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:QuestionAnswers"/>
+ <menu:menuitem menu:id=".uno:SendFeedback"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:SafeMode"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:GetInvolved"/>
+ <menu:menuitem menu:id=".uno:Donation"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:ShowLicense"/>
+ <menu:menuitem menu:id=".uno:About"/>
+ </menu:menupopup>
+ </menu:menu>
+</menu:menubar>
diff --git a/dbaccess/uiconfig/dbtable/toolbar/toolbar.xml b/dbaccess/uiconfig/dbtable/toolbar/toolbar.xml
new file mode 100644
index 000000000..2d5825cb4
--- /dev/null
+++ b/dbaccess/uiconfig/dbtable/toolbar/toolbar.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE toolbar:toolbar PUBLIC "-//OpenOffice.org//DTD OfficeDocument 1.0//EN" "toolbar.dtd">
+<!--
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ -->
+<toolbar:toolbar xmlns:toolbar="http://openoffice.org/2001/toolbar" xmlns:xlink="http://www.w3.org/1999/xlink">
+ <toolbar:toolbaritem xlink:href=".uno:Save"/>
+ <toolbar:toolbaritem xlink:href=".uno:SaveAs" toolbar:visible="false"/>
+ <toolbar:toolbaritem xlink:href=".uno:EditDoc" toolbar:visible="false"/>
+ <toolbar:toolbarseparator/>
+ <toolbar:toolbaritem xlink:href=".uno:Cut"/>
+ <toolbar:toolbaritem xlink:href=".uno:Copy"/>
+ <toolbar:toolbaritem xlink:href=".uno:Paste"/>
+ <toolbar:toolbarseparator/>
+ <toolbar:toolbaritem xlink:href=".uno:Undo"/>
+ <toolbar:toolbaritem xlink:href=".uno:Redo"/>
+ <toolbar:toolbarseparator/>
+ <toolbar:toolbaritem xlink:href=".uno:DBIndexDesign"/>
+ <toolbar:toolbarseparator/>
+ <toolbar:toolbaritem xlink:href=".uno:CloseDoc"/>
+</toolbar:toolbar>
diff --git a/dbaccess/uiconfig/dbtdata/menubar/menubar.xml b/dbaccess/uiconfig/dbtdata/menubar/menubar.xml
new file mode 100644
index 000000000..bbf379953
--- /dev/null
+++ b/dbaccess/uiconfig/dbtdata/menubar/menubar.xml
@@ -0,0 +1,128 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+<menu:menubar xmlns:menu="http://openoffice.org/2001/menu" menu:id="menubar">
+ <menu:menu menu:id=".uno:PickList">
+ <menu:menupopup>
+ <menu:menuitem menu:id=".uno:AddDirect"/>
+ <menu:menuitem menu:id=".uno:Open"/>
+ <menu:menuitem menu:id=".uno:RecentFileList"/>
+ <menu:menuitem menu:id=".uno:CloseDoc"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:AutoPilotMenu" menu:style="text"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:Save"/>
+ <menu:menuitem menu:id=".uno:SaveAs"/>
+ <menu:menuitem menu:id=".uno:SaveAll" menu:style="text"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:CheckOut" menu:style="text"/>
+ <menu:menuitem menu:id=".uno:CancelCheckOut" menu:style="text"/>
+ <menu:menuitem menu:id=".uno:CheckIn" menu:style="text"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:Quit"/>
+ </menu:menupopup>
+ </menu:menu>
+ <menu:menu menu:id=".uno:EditMenu">
+ <menu:menupopup>
+ <menu:menuitem menu:id=".uno:FormSlots/undoRecord"/>
+ <menu:menuitem menu:id=".uno:Redo"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:Cut"/>
+ <menu:menuitem menu:id=".uno:Copy"/>
+ <menu:menuitem menu:id=".uno:Paste"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:RecSearch"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:FormSlots/saveRecord"/>
+ <menu:menuitem menu:id=".uno:FormSlots/deleteRecord"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:DSBEditDoc"/>
+ </menu:menupopup>
+ </menu:menu>
+ <menu:menu menu:id=".uno:ViewMenu">
+ <menu:menupopup>
+ <menu:menuitem menu:id=".uno:AvailableToolbars" menu:style="text"/>
+ <menu:menuitem menu:id=".uno:StatusBarVisible" menu:style="text"/>
+ </menu:menupopup>
+ </menu:menu>
+ <menu:menu menu:id=".uno:InsertMenu">
+ <menu:menupopup>
+ <menu:menuitem menu:id=".uno:FormSlots/insertRecord"/>
+ </menu:menupopup>
+ </menu:menu>
+ <menu:menu menu:id=".uno:DataMenu">
+ <menu:menupopup>
+ <menu:menuitem menu:id=".uno:Refresh"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:OrderCrit"/>
+ <menu:menuitem menu:id=".uno:Sortup"/>
+ <menu:menuitem menu:id=".uno:SortDown"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:AutoFilter"/>
+ <menu:menuitem menu:id=".uno:FormFiltered"/>
+ <menu:menuitem menu:id=".uno:FilterCrit"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:RemoveFilterSort"/>
+ </menu:menupopup>
+ </menu:menu>
+ <menu:menu menu:id=".uno:ToolsMenu">
+ <menu:menupopup>
+ <menu:menu menu:id=".uno:MacrosMenu">
+ <menu:menupopup>
+ <menu:menuitem menu:id=".uno:MacroRecorder"/>
+ <menu:menuitem menu:id=".uno:RunMacro"/>
+ <menu:menuitem menu:id=".uno:BasicIDEAppear"/>
+ <menu:menuitem menu:id=".uno:ScriptOrganizer"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:MacroSignature"/>
+ <menu:menuitem menu:id=".uno:MacroOrganizer?TabId:short=1"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:OpenXMLFilterSettings"/>
+ </menu:menupopup>
+ </menu:menu>
+ <menu:menuitem menu:id="service:com.sun.star.deployment.ui.PackageManagerDialog" menu:style="text"/>
+ <menu:menuitem menu:id=".uno:ConfigureDialog" menu:style="text"/>
+ <menu:menuitem menu:id=".uno:OptionsTreeDialog"/>
+ </menu:menupopup>
+ </menu:menu>
+ <menu:menu menu:id=".uno:WindowList">
+ <menu:menupopup>
+ <menu:menuitem menu:id=".uno:CloseWin"/>
+ <menu:menuseparator/>
+ </menu:menupopup>
+ </menu:menu>
+ <menu:menu menu:id=".uno:HelpMenu">
+ <menu:menupopup>
+ <menu:menuitem menu:id=".uno:HelpIndex"/>
+ <menu:menuitem menu:id=".uno:ExtendedHelp"/>
+ <menu:menuitem menu:id=".uno:Documentation"/>
+ <menu:menuitem menu:id=".uno:TipOfTheDay"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:QuestionAnswers"/>
+ <menu:menuitem menu:id=".uno:SendFeedback"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:SafeMode"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:GetInvolved"/>
+ <menu:menuitem menu:id=".uno:Donation"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:ShowLicense"/>
+ <menu:menuitem menu:id=".uno:About"/>
+ </menu:menupopup>
+ </menu:menu>
+</menu:menubar>
diff --git a/dbaccess/uiconfig/dbtdata/popupmenu/refreshdata.xml b/dbaccess/uiconfig/dbtdata/popupmenu/refreshdata.xml
new file mode 100644
index 000000000..216c6c53c
--- /dev/null
+++ b/dbaccess/uiconfig/dbtdata/popupmenu/refreshdata.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+-->
+<menu:menupopup xmlns:menu="http://openoffice.org/2001/menu">
+ <menu:menuitem menu:id=".uno:Refresh"/>
+ <menu:menuitem menu:id=".uno:DBRebuildData"/>
+</menu:menupopup>
diff --git a/dbaccess/uiconfig/dbtdata/toolbar/toolbar.xml b/dbaccess/uiconfig/dbtdata/toolbar/toolbar.xml
new file mode 100644
index 000000000..7d925ff89
--- /dev/null
+++ b/dbaccess/uiconfig/dbtdata/toolbar/toolbar.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE toolbar:toolbar PUBLIC "-//OpenOffice.org//DTD OfficeDocument 1.0//EN" "toolbar.dtd">
+<!--
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ -->
+<toolbar:toolbar xmlns:toolbar="http://openoffice.org/2001/toolbar" xmlns:xlink="http://www.w3.org/1999/xlink">
+ <toolbar:toolbaritem xlink:href=".uno:RecSave"/>
+ <toolbar:toolbaritem xlink:href=".uno:DSBEditDoc"/>
+ <toolbar:toolbarseparator/>
+ <toolbar:toolbaritem xlink:href=".uno:Cut"/>
+ <toolbar:toolbaritem xlink:href=".uno:Copy"/>
+ <toolbar:toolbaritem xlink:href=".uno:Paste"/>
+ <toolbar:toolbarseparator/>
+ <toolbar:toolbaritem xlink:href=".uno:RecUndo"/>
+ <toolbar:toolbarseparator/>
+ <toolbar:toolbaritem xlink:href=".uno:RecSearch"/>
+ <toolbar:toolbarseparator/>
+ <toolbar:toolbaritem xlink:href=".uno:Refresh"/>
+ <toolbar:toolbarseparator/>
+ <toolbar:toolbaritem xlink:href=".uno:OrderCrit"/>
+ <toolbar:toolbaritem xlink:href=".uno:Sortup"/>
+ <toolbar:toolbaritem xlink:href=".uno:SortDown"/>
+ <toolbar:toolbarseparator/>
+ <toolbar:toolbaritem xlink:href=".uno:AutoFilter"/>
+ <toolbar:toolbaritem xlink:href=".uno:FormFiltered"/>
+ <toolbar:toolbaritem xlink:href=".uno:FilterCrit"/>
+ <toolbar:toolbarseparator/>
+ <toolbar:toolbaritem xlink:href=".uno:RemoveFilterSort"/>
+ <toolbar:toolbarseparator/>
+ <toolbar:toolbaritem xlink:href=".uno:CloseDoc"/>
+</toolbar:toolbar>
diff --git a/dbaccess/uiconfig/ui/admindialog.ui b/dbaccess/uiconfig/ui/admindialog.ui
new file mode 100644
index 000000000..bb02d9530
--- /dev/null
+++ b/dbaccess/uiconfig/ui/admindialog.ui
@@ -0,0 +1,162 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface domain="dba">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkDialog" id="AdminDialog">
+ <property name="can_focus">False</property>
+ <property name="border_width">6</property>
+ <property name="title" translatable="yes" context="admindialog|AdminDialog">Database Properties</property>
+ <property name="resizable">False</property>
+ <property name="modal">True</property>
+ <property name="default_width">0</property>
+ <property name="default_height">0</property>
+ <property name="type_hint">dialog</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child internal-child="vbox">
+ <object class="GtkBox" id="dialog-vbox1">
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox" id="dialog-action_area1">
+ <property name="can_focus">False</property>
+ <property name="layout_style">end</property>
+ <child>
+ <object class="GtkButton" id="reset">
+ <property name="label" translatable="yes" context="stock">_Reset</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="ok">
+ <property name="label" translatable="yes" context="stock">_OK</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="has_default">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="cancel">
+ <property name="label" translatable="yes" context="stock">_Cancel</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="help">
+ <property name="label" translatable="yes" context="stock">_Help</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">3</property>
+ <property name="secondary">True</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkNotebook" id="tabcontrol">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="scrollable">True</property>
+ <property name="enable_popup">True</property>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel" id="advanced">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="admindialog|advanced">Advanced Properties</property>
+ <property name="xalign">0.5</property>
+ </object>
+ <packing>
+ <property name="tab_fill">False</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="101">reset</action-widget>
+ <action-widget response="-5">ok</action-widget>
+ <action-widget response="-6">cancel</action-widget>
+ <action-widget response="-11">help</action-widget>
+ </action-widgets>
+ </object>
+</interface>
diff --git a/dbaccess/uiconfig/ui/advancedsettingsdialog.ui b/dbaccess/uiconfig/ui/advancedsettingsdialog.ui
new file mode 100644
index 000000000..a783e1b17
--- /dev/null
+++ b/dbaccess/uiconfig/ui/advancedsettingsdialog.ui
@@ -0,0 +1,210 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface domain="dba">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkDialog" id="AdvancedSettingsDialog">
+ <property name="can_focus">False</property>
+ <property name="border_width">6</property>
+ <property name="title" translatable="yes" context="advancedsettingsdialog|AdvancedSettingsDialog">Advanced Settings</property>
+ <property name="resizable">False</property>
+ <property name="modal">True</property>
+ <property name="default_width">0</property>
+ <property name="default_height">0</property>
+ <property name="type_hint">dialog</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child internal-child="vbox">
+ <object class="GtkBox" id="dialog-vbox1">
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox" id="dialog-action_area1">
+ <property name="can_focus">False</property>
+ <property name="layout_style">end</property>
+ <child>
+ <object class="GtkButton" id="reset">
+ <property name="label" translatable="yes" context="stock">_Reset</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="no_show_all">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="ok">
+ <property name="label" translatable="yes" context="stock">_OK</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="has_default">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="cancel">
+ <property name="label" translatable="yes" context="stock">_Cancel</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="help">
+ <property name="label" translatable="yes" context="stock">_Help</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">3</property>
+ <property name="secondary">True</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkNotebook" id="tabcontrol">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="scrollable">True</property>
+ <property name="enable_popup">True</property>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel" id="generated">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="advancedsettingsdialog|generated">Generated Values</property>
+ </object>
+ <packing>
+ <property name="tab_fill">False</property>
+ </packing>
+ </child>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel" id="special">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="advancedsettingsdialog|special">Special Settings</property>
+ <property name="xalign">0.5</property>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ <property name="tab_fill">False</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="101">reset</action-widget>
+ <action-widget response="-5">ok</action-widget>
+ <action-widget response="-6">cancel</action-widget>
+ <action-widget response="-11">help</action-widget>
+ </action-widgets>
+ </object>
+</interface>
diff --git a/dbaccess/uiconfig/ui/appborderwindow.ui b/dbaccess/uiconfig/ui/appborderwindow.ui
new file mode 100644
index 000000000..d8112e895
--- /dev/null
+++ b/dbaccess/uiconfig/ui/appborderwindow.ui
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.36.0 -->
+<interface domain="dba">
+ <requires lib="gtk+" version="3.20"/>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="AppBorderWindow">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="column_spacing">6</property>
+ <child>
+ <object class="GtkBox" id="panel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="hexpand">False</property>
+ <property name="vexpand">True</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="detail">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSeparator">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_top">3</property>
+ <property name="margin_bottom">3</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ </object>
+</interface>
diff --git a/dbaccess/uiconfig/ui/appdetailwindow.ui b/dbaccess/uiconfig/ui/appdetailwindow.ui
new file mode 100644
index 000000000..89ac1c425
--- /dev/null
+++ b/dbaccess/uiconfig/ui/appdetailwindow.ui
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.36.0 -->
+<interface domain="dba">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkBox" id="AppDetailWindow">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkPaned" id="splitter">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="orientation">vertical</property>
+ <property name="wide_handle">True</property>
+ <child>
+ <object class="GtkBox" id="tasks">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="resize">True</property>
+ <property name="shrink">False</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="container">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="resize">True</property>
+ <property name="shrink">True</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+</interface>
diff --git a/dbaccess/uiconfig/ui/applycolpage.ui b/dbaccess/uiconfig/ui/applycolpage.ui
new file mode 100644
index 000000000..cfcb23259
--- /dev/null
+++ b/dbaccess/uiconfig/ui/applycolpage.ui
@@ -0,0 +1,243 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface domain="dba">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkImage" id="image1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon_name">dbaccess/res/all_right.png</property>
+ </object>
+ <object class="GtkImage" id="image2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon_name">dbaccess/res/one_right.png</property>
+ </object>
+ <object class="GtkImage" id="image3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon_name">dbaccess/res/one_left.png</property>
+ </object>
+ <object class="GtkImage" id="image4">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon_name">dbaccess/res/all_left.png</property>
+ </object>
+ <object class="GtkTreeStore" id="liststore1">
+ <columns>
+ <!-- column-name text -->
+ <column type="gchararray"/>
+ <!-- column-name id -->
+ <column type="gchararray"/>
+ </columns>
+ </object>
+ <object class="GtkTreeStore" id="liststore2">
+ <columns>
+ <!-- column-name text -->
+ <column type="gchararray"/>
+ <!-- column-name id -->
+ <column type="gchararray"/>
+ </columns>
+ </object>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="ApplyColPage">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="border_width">6</property>
+ <child>
+ <object class="GtkFrame" id="frame1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="column_spacing">12</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <child>
+ <object class="GtkScrolledWindow">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="shadow_type">in</property>
+ <child>
+ <object class="GtkTreeView" id="from">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="model">liststore1</property>
+ <property name="headers_visible">False</property>
+ <property name="search_column">1</property>
+ <property name="show_expanders">False</property>
+ <child internal-child="selection">
+ <object class="GtkTreeSelection" id="Macro Library List-selection2"/>
+ </child>
+ <child>
+ <object class="GtkTreeViewColumn" id="treeviewcolumn5">
+ <property name="resizable">True</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkCellRendererText" id="cellrenderer4"/>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkScrolledWindow">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="shadow_type">in</property>
+ <child>
+ <object class="GtkTreeView" id="to">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="model">liststore2</property>
+ <property name="headers_visible">False</property>
+ <property name="search_column">1</property>
+ <property name="show_expanders">False</property>
+ <child internal-child="selection">
+ <object class="GtkTreeSelection" id="Macro Library List-selection1"/>
+ </child>
+ <child>
+ <object class="GtkTreeViewColumn" id="treeviewcolumn6">
+ <property name="resizable">True</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkCellRendererText" id="cellrenderer7"/>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButtonBox" id="buttonbox1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="valign">center</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <property name="layout_style">start</property>
+ <child>
+ <object class="GtkButton" id="colrh">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="image">image2</property>
+ <property name="always-show-image">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="colsrh">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="image">image1</property>
+ <property name="always-show-image">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="collh">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="image">image3</property>
+ <property name="always-show-image">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="colslh">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="image">image4</property>
+ <property name="always-show-image">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="applycolpage|label1">Existing Columns</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ </object>
+ <object class="GtkSizeGroup">
+ <widgets>
+ <widget name="from"/>
+ <widget name="to"/>
+ </widgets>
+ </object>
+</interface>
diff --git a/dbaccess/uiconfig/ui/appswapwindow.ui b/dbaccess/uiconfig/ui/appswapwindow.ui
new file mode 100644
index 000000000..daa5f9379
--- /dev/null
+++ b/dbaccess/uiconfig/ui/appswapwindow.ui
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.36.0 -->
+<interface domain="dba">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkBox" id="AppSwapWindow">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="vexpand">True</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="border_width">12</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkScrolledWindow" id="scroll">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="hscrollbar_policy">never</property>
+ <property name="vscrollbar_policy">never</property>
+ <child>
+ <object class="GtkViewport">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <child>
+ <object class="GtkDrawingArea" id="valueset">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="events">GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_STRUCTURE_MASK</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+</interface>
diff --git a/dbaccess/uiconfig/ui/authentificationpage.ui b/dbaccess/uiconfig/ui/authentificationpage.ui
new file mode 100644
index 000000000..f301a02bb
--- /dev/null
+++ b/dbaccess/uiconfig/ui/authentificationpage.ui
@@ -0,0 +1,123 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface domain="dba">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkBox" id="AuthentificationPage">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="border_width">6</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkLabel" id="header">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="margin_bottom">12</property>
+ <property name="label" translatable="yes" context="authentificationpage|header">Set up the user authentication</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="helptext">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_bottom">6</property>
+ <property name="label" translatable="yes" context="authentificationpage|helptext">Some databases require you to enter a user name.</property>
+ <property name="wrap">True</property>
+ <property name="width_chars">72</property>
+ <property name="max_width_chars">72</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="row_spacing">2</property>
+ <property name="column_spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="generalUserNameLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="label" translatable="yes" context="authentificationpage|generalUserNameLabel">_User name</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">generalUserNameEntry</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="generalUserNameEntry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="truncate-multiline">True</property>
+ <property name="activates_default">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="passRequiredCheckbutton">
+ <property name="label" translatable="yes" context="authentificationpage|passRequiredCheckbutton">Password re_quired</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="testConnectionButton">
+ <property name="label" translatable="yes" context="authentificationpage|testConnectionButton">_Test Connection</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="receives_default">True</property>
+ <property name="halign">end</property>
+ <property name="use_underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ </object>
+</interface>
diff --git a/dbaccess/uiconfig/ui/autocharsetpage.ui b/dbaccess/uiconfig/ui/autocharsetpage.ui
new file mode 100644
index 000000000..85a00baff
--- /dev/null
+++ b/dbaccess/uiconfig/ui/autocharsetpage.ui
@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.18.3 -->
+<interface domain="dba">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkBox" id="AutoCharset">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="border_width">6</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkFrame" id="frame1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <object class="GtkBox" id="box1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="spacing">12</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <child>
+ <object class="GtkLabel" id="charsetlabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="autocharsetpage|charsetlabel">_Character set:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">charset</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="charset">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="charsetheader">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="autocharsetpage|charsetheader">Data Conversion</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+</interface>
diff --git a/dbaccess/uiconfig/ui/choosedatasourcedialog.ui b/dbaccess/uiconfig/ui/choosedatasourcedialog.ui
new file mode 100644
index 000000000..914751d58
--- /dev/null
+++ b/dbaccess/uiconfig/ui/choosedatasourcedialog.ui
@@ -0,0 +1,181 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface domain="dba">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkTreeStore" id="liststore2">
+ <columns>
+ <!-- column-name text -->
+ <column type="gchararray"/>
+ <!-- column-name id -->
+ <column type="gchararray"/>
+ </columns>
+ </object>
+ <object class="GtkDialog" id="ChooseDataSourceDialog">
+ <property name="can_focus">False</property>
+ <property name="border_width">6</property>
+ <property name="title" translatable="yes" context="choosedatasourcedialog|ChooseDataSourceDialog">Data Source</property>
+ <property name="resizable">False</property>
+ <property name="modal">True</property>
+ <property name="default_width">0</property>
+ <property name="default_height">0</property>
+ <property name="type_hint">dialog</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child internal-child="vbox">
+ <object class="GtkBox" id="dialog-vbox1">
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox" id="dialog-action_area1">
+ <property name="can_focus">False</property>
+ <property name="layout_style">end</property>
+ <child>
+ <object class="GtkButton" id="ok">
+ <property name="label" translatable="yes" context="stock">_OK</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="has_default">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="cancel">
+ <property name="label" translatable="yes" context="stock">_Cancel</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="help">
+ <property name="label" translatable="yes" context="stock">_Help</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ <property name="secondary">True</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="organize">
+ <property name="label" translatable="yes" context="choosedatasourcedialog|organize">Or_ganize...</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="no_show_all">True</property>
+ <property name="use_underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">3</property>
+ <property name="secondary">True</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="row_spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="label1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="choosedatasourcedialog|label1">Choose a data source:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">treeview</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkScrolledWindow">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="shadow_type">in</property>
+ <child>
+ <object class="GtkTreeView" id="treeview">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="model">liststore2</property>
+ <property name="headers_visible">False</property>
+ <property name="search_column">0</property>
+ <property name="show_expanders">False</property>
+ <child internal-child="selection">
+ <object class="GtkTreeSelection" id="Macro Library List-selection2"/>
+ </child>
+ <child>
+ <object class="GtkTreeViewColumn" id="treeviewcolumn5">
+ <property name="resizable">True</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkCellRendererText" id="cellrenderer4"/>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="-5">ok</action-widget>
+ <action-widget response="-6">cancel</action-widget>
+ <action-widget response="-11">help</action-widget>
+ <action-widget response="101">organize</action-widget>
+ </action-widgets>
+ </object>
+</interface>
diff --git a/dbaccess/uiconfig/ui/colcontrolbox.ui b/dbaccess/uiconfig/ui/colcontrolbox.ui
new file mode 100644
index 000000000..5f02fbc7c
--- /dev/null
+++ b/dbaccess/uiconfig/ui/colcontrolbox.ui
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.36.0 -->
+<interface domain="dba">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkBox" id="ColControlBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+</interface>
diff --git a/dbaccess/uiconfig/ui/collectionviewdialog.ui b/dbaccess/uiconfig/ui/collectionviewdialog.ui
new file mode 100644
index 000000000..865837134
--- /dev/null
+++ b/dbaccess/uiconfig/ui/collectionviewdialog.ui
@@ -0,0 +1,267 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface domain="dba">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkImage" id="image1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon_name">res/fp015.png</property>
+ </object>
+ <object class="GtkImage" id="image2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon_name">res/fp010.png</property>
+ </object>
+ <object class="GtkTreeStore" id="liststore1">
+ <columns>
+ <!-- column-name text -->
+ <column type="gchararray"/>
+ <!-- column-name id -->
+ <column type="gchararray"/>
+ </columns>
+ </object>
+ <object class="GtkDialog" id="CollectionView">
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="border_width">6</property>
+ <property name="title" translatable="yes" context="collectionviewdialog|CollectionView">Save</property>
+ <property name="modal">True</property>
+ <property name="default_width">0</property>
+ <property name="default_height">0</property>
+ <property name="type_hint">dialog</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child internal-child="vbox">
+ <object class="GtkBox" id="dialog-vbox1">
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox" id="dialog-action_area1">
+ <property name="can_focus">False</property>
+ <property name="layout_style">end</property>
+ <child>
+ <object class="GtkButton" id="ok">
+ <property name="label" translatable="yes" context="collectionviewdialog|ok">_Save</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="has_default">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="cancel">
+ <property name="label" translatable="yes" context="stock">_Cancel</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="help">
+ <property name="label" translatable="yes" context="stock">_Help</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ <property name="secondary">True</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="box1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkBox" id="box2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="spacing">3</property>
+ <child>
+ <object class="GtkLabel" id="currentPathLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="valign">start</property>
+ <property name="hexpand">True</property>
+ <property name="ellipsize">middle</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="newFolderButton">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="focus_on_click">False</property>
+ <property name="can_default">True</property>
+ <property name="receives_default">True</property>
+ <property name="tooltip_text" translatable="yes" context="collectionviewdialog|newFolderButton|tooltip_text">Create New Directory</property>
+ <property name="image">image1</property>
+ <property name="always_show_image">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="upButton">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="receives_default">True</property>
+ <property name="tooltip_text" translatable="yes" context="collectionviewdialog|upButton|tooltip_text">Up One Level</property>
+ <property name="image">image2</property>
+ <property name="always_show_image">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkScrolledWindow">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="vexpand">True</property>
+ <property name="shadow_type">in</property>
+ <child>
+ <object class="GtkTreeView" id="viewTreeview">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="vexpand">True</property>
+ <property name="model">liststore1</property>
+ <property name="headers_clickable">False</property>
+ <property name="search_column">1</property>
+ <property name="show_expanders">False</property>
+ <child internal-child="selection">
+ <object class="GtkTreeSelection" id="Macro Library List-selection2"/>
+ </child>
+ <child>
+ <object class="GtkTreeViewColumn" id="treeviewcolumn5">
+ <property name="resizable">True</property>
+ <property name="title" translatable="yes" context="collectionviewdialog|columntitle">Folder Name</property>
+ <child>
+ <object class="GtkCellRendererText" id="cellrenderer4"/>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="box3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkLabel" id="fileNameLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="collectionviewdialog|fileNameLabel">File _name:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">fileNameEntry</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="fileNameEntry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="truncate-multiline">True</property>
+ <property name="activates_default">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="-5">ok</action-widget>
+ <action-widget response="-6">cancel</action-widget>
+ <action-widget response="-11">help</action-widget>
+ </action-widgets>
+ </object>
+</interface>
diff --git a/dbaccess/uiconfig/ui/colwidthdialog.ui b/dbaccess/uiconfig/ui/colwidthdialog.ui
new file mode 100644
index 000000000..0889e3dc4
--- /dev/null
+++ b/dbaccess/uiconfig/ui/colwidthdialog.ui
@@ -0,0 +1,172 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.36.0 -->
+<interface domain="dba">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkAdjustment" id="adjustment1">
+ <property name="lower">0.1</property>
+ <property name="upper">200</property>
+ <property name="value">2.27</property>
+ <property name="step_increment">1</property>
+ <property name="page_increment">10</property>
+ </object>
+ <object class="GtkDialog" id="ColWidthDialog">
+ <property name="can_focus">False</property>
+ <property name="border_width">6</property>
+ <property name="title" translatable="yes" context="colwidthdialog|ColWidthDialog">Column Width</property>
+ <property name="resizable">False</property>
+ <property name="modal">True</property>
+ <property name="default_width">0</property>
+ <property name="default_height">0</property>
+ <property name="type_hint">dialog</property>
+ <child internal-child="vbox">
+ <object class="GtkBox" id="dialog-vbox1">
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox" id="dialog-action_area1">
+ <property name="can_focus">False</property>
+ <property name="layout_style">end</property>
+ <child>
+ <object class="GtkButton" id="ok">
+ <property name="label" translatable="yes" context="stock">_OK</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="has_default">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="cancel">
+ <property name="label" translatable="yes" context="stock">_Cancel</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="help">
+ <property name="label" translatable="yes" context="stock">_Help</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ <property name="secondary">True</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="valign">start</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="row_spacing">6</property>
+ <property name="column_spacing">12</property>
+ <child>
+ <object class="GtkLabel" id="label1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="colwidthdialog|label1">_Width:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">value</property>
+ <property name="xalign">1</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="value">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="activates_default">True</property>
+ <property name="adjustment">adjustment1</property>
+ <property name="digits">2</property>
+ <property name="truncate-multiline">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="value-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="colwidthdialog|extended_tip|value">Enter the column width that you want to use.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="automatic">
+ <property name="label" translatable="yes" context="colwidthdialog|automatic">_Automatic</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="automatic-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="colwidthdialog|extended_tip|automatic">Automatically adjusts the column width based on the current font.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="-5">ok</action-widget>
+ <action-widget response="-6">cancel</action-widget>
+ <action-widget response="-11">help</action-widget>
+ </action-widgets>
+ <child type="titlebar">
+ <placeholder/>
+ </child>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="ColWidthDialog-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="colwidthdialog|extended_tip|ColWidthDialog">Changes the width of the current column, or the selected columns.</property>
+ </object>
+ </child>
+ </object>
+</interface>
diff --git a/dbaccess/uiconfig/ui/connectionpage.ui b/dbaccess/uiconfig/ui/connectionpage.ui
new file mode 100644
index 000000000..cfac643b9
--- /dev/null
+++ b/dbaccess/uiconfig/ui/connectionpage.ui
@@ -0,0 +1,299 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface domain="dba">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkBox" id="ConnectionPage">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="border_width">6</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkFrame" id="frame1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="valign">start</property>
+ <property name="hexpand">True</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="row_spacing">6</property>
+ <property name="column_spacing">12</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <child>
+ <object class="GtkLabel" id="browseurllabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="label" translatable="yes" context="connectionpage|browseurllabel">Path to the dBASE files:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">browseurl</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="create">
+ <property name="label" translatable="yes" context="connectionpage|create">_Create New</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_underline">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="browse">
+ <property name="label" translatable="yes" context="connectionpage|browse">_Browse…</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_underline">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkEntry" id="browseurl">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="truncate-multiline">True</property>
+ <property name="hexpand">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="browselabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="generalLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="connectionpage|generalLabel">General</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFrame" id="frame2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="valign">start</property>
+ <property name="hexpand">True</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="row_spacing">6</property>
+ <property name="column_spacing">12</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <child>
+ <object class="GtkLabel" id="userNameLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="connectionpage|userNameLabel">_User name:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">userNameEntry</property>
+ <property name="xalign">1</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="userNameEntry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="truncate-multiline">True</property>
+ <property name="hexpand">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="passCheckbutton">
+ <property name="label" translatable="yes" context="connectionpage|passCheckbutton">Password required</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="userlabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="connectionpage|userlabel">User Authentication</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFrame" id="frame3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="valign">start</property>
+ <property name="hexpand">True</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <object class="GtkBox" id="box1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="spacing">12</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <child>
+ <object class="GtkLabel" id="javaDriverLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="connectionpage|javaDriverLabel">_JDBC driver class:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">driverEntry</property>
+ <property name="xalign">1</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="driverEntry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="truncate-multiline">True</property>
+ <property name="hexpand">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="driverButton">
+ <property name="label" translatable="yes" context="connectionpage|driverButton">Test Class</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="JDBCLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="connectionpage|JDBCLabel">JDBC Properties</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="connectionButton">
+ <property name="label" translatable="yes" context="connectionpage|connectionButton">Test Connection</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="halign">end</property>
+ <property name="valign">end</property>
+ <property name="vexpand">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ </object>
+</interface>
diff --git a/dbaccess/uiconfig/ui/copytablepage.ui b/dbaccess/uiconfig/ui/copytablepage.ui
new file mode 100644
index 000000000..c6eea4f00
--- /dev/null
+++ b/dbaccess/uiconfig/ui/copytablepage.ui
@@ -0,0 +1,232 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface domain="dba">
+ <requires lib="gtk+" version="3.20"/>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="CopyTablePage">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="border_width">6</property>
+ <property name="row_spacing">6</property>
+ <child>
+ <object class="GtkFrame" id="frame1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="row_spacing">6</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <child>
+ <object class="GtkRadioButton" id="defdata">
+ <property name="label" translatable="yes" context="copytablepage|defdata">De_finition and data</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="def">
+ <property name="label" translatable="yes" context="copytablepage|def">Def_inition</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">defdata</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="view">
+ <property name="label" translatable="yes" context="copytablepage|view">A_s table view</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">defdata</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="data">
+ <property name="label" translatable="yes" context="copytablepage|data">Append _data</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">defdata</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="firstline">
+ <property name="label" translatable="yes" context="copytablepage|firstline">Use first _line as column names</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">4</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="primarykey">
+ <property name="label" translatable="yes" context="copytablepage|primarykey">Crea_te new field as primary key</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">5</property>
+ </packing>
+ </child>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="column_spacing">12</property>
+ <property name="margin-start">12</property>
+ <child>
+ <object class="GtkLabel" id="keynamelabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="copytablepage|keynamelabel">Name:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">keyname</property>
+ <property name="xalign">1</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="keyname">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="truncate-multiline">True</property>
+ <property name="activates_default">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">6</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="infoLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="copytablepage|infoLabel">Existing data fields can be set as primary key on the type formatting step (third page) of the wizard.</property>
+ <property name="wrap">True</property>
+ <property name="width_chars">72</property>
+ <property name="max_width_chars">72</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">7</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="copytablepage|label1">Options</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="column_spacing">12</property>
+ <child>
+ <object class="GtkLabel" id="label2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="copytablepage|label2">Ta_ble name:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">name</property>
+ <property name="xalign">1</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="name">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="truncate-multiline">True</property>
+ <property name="activates_default">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ </object>
+</interface>
diff --git a/dbaccess/uiconfig/ui/dbaseindexdialog.ui b/dbaccess/uiconfig/ui/dbaseindexdialog.ui
new file mode 100644
index 000000000..644a4e1c9
--- /dev/null
+++ b/dbaccess/uiconfig/ui/dbaseindexdialog.ui
@@ -0,0 +1,393 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface domain="dba">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkImage" id="image1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon_name">dbaccess/res/one_left.png</property>
+ </object>
+ <object class="GtkImage" id="image2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon_name">dbaccess/res/one_left.png</property>
+ </object>
+ <object class="GtkImage" id="image3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon_name">dbaccess/res/one_right.png</property>
+ </object>
+ <object class="GtkImage" id="image4">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon_name">dbaccess/res/all_right.png</property>
+ </object>
+ <object class="GtkTreeStore" id="liststore1">
+ <columns>
+ <!-- column-name text -->
+ <column type="gchararray"/>
+ <!-- column-name id -->
+ <column type="gchararray"/>
+ </columns>
+ </object>
+ <object class="GtkTreeStore" id="liststore2">
+ <columns>
+ <!-- column-name text -->
+ <column type="gchararray"/>
+ <!-- column-name id -->
+ <column type="gchararray"/>
+ </columns>
+ </object>
+ <object class="GtkDialog" id="DBaseIndexDialog">
+ <property name="can_focus">False</property>
+ <property name="border_width">6</property>
+ <property name="title" translatable="yes" context="dbaseindexdialog|DBaseIndexDialog">Indexes</property>
+ <property name="modal">True</property>
+ <property name="default_width">0</property>
+ <property name="default_height">0</property>
+ <property name="type_hint">dialog</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child internal-child="vbox">
+ <object class="GtkBox" id="dialog-vbox1">
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox" id="dialog-action_area1">
+ <property name="can_focus">False</property>
+ <property name="layout_style">end</property>
+ <child>
+ <object class="GtkButton" id="ok">
+ <property name="label" translatable="yes" context="stock">_OK</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="has_default">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="cancel">
+ <property name="label" translatable="yes" context="stock">_Cancel</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="help">
+ <property name="label" translatable="yes" context="stock">_Help</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ <property name="secondary">True</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="row_spacing">12</property>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="column_spacing">12</property>
+ <child>
+ <object class="GtkLabel" id="label1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="dbaseindexdialog|label1">_Table:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">table</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="table">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="has_entry">True</property>
+ <child internal-child="entry">
+ <object class="GtkEntry" id="comboboxtext-entry">
+ <property name="can_focus">True</property>
+ <property name="truncate-multiline">True</property>
+ <property name="activates_default">True</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFrame" id="frame">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="row_spacing">6</property>
+ <property name="column_spacing">12</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <child>
+ <object class="GtkLabel" id="label3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="dbaseindexdialog|label3">T_able indexes</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">tableindex</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label4">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="dbaseindexdialog|label4">_Free indexes</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">freeindex</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkScrolledWindow" id="tableindexwin">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="shadow_type">in</property>
+ <child>
+ <object class="GtkTreeView" id="tableindex">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="model">liststore1</property>
+ <property name="headers_visible">False</property>
+ <property name="headers_clickable">False</property>
+ <property name="search_column">0</property>
+ <property name="show_expanders">False</property>
+ <child internal-child="selection">
+ <object class="GtkTreeSelection" id="treeview-selection1"/>
+ </child>
+ <child>
+ <object class="GtkTreeViewColumn" id="treeviewcolumn1">
+ <child>
+ <object class="GtkCellRendererText" id="cellrenderertext1"/>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkScrolledWindow" id="freeindexwin">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="shadow_type">in</property>
+ <child>
+ <object class="GtkTreeView" id="freeindex">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="model">liststore2</property>
+ <property name="headers_visible">False</property>
+ <property name="headers_clickable">False</property>
+ <property name="search_column">0</property>
+ <property name="show_expanders">False</property>
+ <child internal-child="selection">
+ <object class="GtkTreeSelection" id="treeview-selection2"/>
+ </child>
+ <child>
+ <object class="GtkTreeViewColumn" id="treeviewcolumn2">
+ <child>
+ <object class="GtkCellRendererText" id="cellrenderertext2"/>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButtonBox" id="buttonbox1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="valign">center</property>
+ <property name="vexpand">True</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <property name="layout_style">start</property>
+ <child>
+ <object class="GtkButton" id="add">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="image">image1</property>
+ <property name="always-show-image">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="addall">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="image">image2</property>
+ <property name="always-show-image">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="remove">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="image">image3</property>
+ <property name="always-show-image">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="removeall">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="image">image4</property>
+ <property name="always-show-image">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="dbaseindexdialog|label2">Assignment</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="-5">ok</action-widget>
+ <action-widget response="-6">cancel</action-widget>
+ <action-widget response="-11">help</action-widget>
+ </action-widgets>
+ </object>
+</interface>
diff --git a/dbaccess/uiconfig/ui/dbasepage.ui b/dbaccess/uiconfig/ui/dbasepage.ui
new file mode 100644
index 000000000..d65f291cd
--- /dev/null
+++ b/dbaccess/uiconfig/ui/dbasepage.ui
@@ -0,0 +1,157 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface domain="dba">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkBox" id="DbasePage">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="border_width">6</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkFrame" id="frame1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <object class="GtkBox" id="box1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="spacing">12</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <child>
+ <object class="GtkLabel" id="charsetlabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="dbasepage|charsetlabel">_Character set:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">charset</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="charset">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="charsetheader">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="dbasepage|charsetheader">Data Conversion</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFrame" id="frame2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <object class="GtkBox" id="box2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <child>
+ <object class="GtkCheckButton" id="showDelRowsCheckbutton">
+ <property name="label" translatable="yes" context="dbasepage|showDelRowsCheckbutton">Display deleted records as well</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="specMessageLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="dbasepage|specMessageLabel">Note: When deleted, and thus inactive, records are displayed, you will not be able to delete records from the data source.</property>
+ <property name="wrap">True</property>
+ <property name="width_chars">72</property>
+ <property name="max_width_chars">72</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="dbasepage|label1">Optional Settings</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="indiciesButton">
+ <property name="label" translatable="yes" context="dbasepage|indiciesButton">Indexes...</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="halign">end</property>
+ <property name="valign">end</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+</interface>
diff --git a/dbaccess/uiconfig/ui/dbtreelist.ui b/dbaccess/uiconfig/ui/dbtreelist.ui
new file mode 100644
index 000000000..aa875dd74
--- /dev/null
+++ b/dbaccess/uiconfig/ui/dbtreelist.ui
@@ -0,0 +1,104 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.38.2 -->
+<interface domain="dba">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkTreeStore" id="liststore1">
+ <columns>
+ <!-- column-name expander -->
+ <column type="GdkPixbuf"/>
+ <!-- column-name check1 -->
+ <column type="gboolean"/>
+ <!-- column-name text -->
+ <column type="gchararray"/>
+ <!-- column-name id -->
+ <column type="gchararray"/>
+ <!-- column-name checkvis1 -->
+ <column type="gboolean"/>
+ <!-- column-name checktri1 -->
+ <column type="gboolean"/>
+ <!-- column-name weight1 -->
+ <column type="gint"/>
+ </columns>
+ </object>
+ <object class="GtkBox" id="DBTreeList">
+ <property name="can-focus">False</property>
+ <property name="no-show-all">True</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="border-width">0</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkScrolledWindow">
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <child>
+ <object class="GtkTreeView" id="treeview">
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">True</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="model">liststore1</property>
+ <property name="headers-visible">False</property>
+ <property name="reorderable">True</property>
+ <property name="search-column">2</property>
+ <property name="enable-tree-lines">True</property>
+ <child internal-child="selection">
+ <object class="GtkTreeSelection" id="Macro Library List-selection2"/>
+ </child>
+ <child>
+ <object class="GtkTreeViewColumn" id="treeviewcolumn8">
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkCellRendererPixbuf" id="cellrenderertext5"/>
+ <attributes>
+ <attribute name="pixbuf">0</attribute>
+ </attributes>
+ </child>
+ <child>
+ <object class="GtkCellRendererToggle" id="cellrenderer5"/>
+ <attributes>
+ <attribute name="visible">4</attribute>
+ <attribute name="active">1</attribute>
+ <attribute name="inconsistent">5</attribute>
+ </attributes>
+ </child>
+ <child>
+ <object class="GtkCellRendererText" id="cellrenderertext6"/>
+ <attributes>
+ <attribute name="text">2</attribute>
+ <attribute name="weight">6</attribute>
+ </attributes>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="statusbar">
+ <property name="can-focus">False</property>
+ <property name="no-show-all">True</property>
+ <property name="xalign">0</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="statusbar-atkobject">
+ <property name="AtkObject::accessible-role" translatable="no">static</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+</interface>
diff --git a/dbaccess/uiconfig/ui/dbwizconnectionpage.ui b/dbaccess/uiconfig/ui/dbwizconnectionpage.ui
new file mode 100644
index 000000000..07c46bc0d
--- /dev/null
+++ b/dbaccess/uiconfig/ui/dbwizconnectionpage.ui
@@ -0,0 +1,137 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface domain="dba">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkBox" id="ConnectionPage">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="border_width">6</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkLabel" id="header">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="margin_bottom">12</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="helptext">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_bottom">6</property>
+ <property name="label" translatable="yes" context="dbwizconnectionpage|helptext">label</property>
+ <property name="wrap">True</property>
+ <property name="width_chars">72</property>
+ <property name="max_width_chars">72</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="row_spacing">6</property>
+ <property name="column_spacing">12</property>
+ <child>
+ <object class="GtkLabel" id="browseurllabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="label" translatable="yes" context="dbwizconnectionpage|browseurllabel">Path to the dBASE files:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">browseurl</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="create">
+ <property name="label" translatable="yes" context="dbwizconnectionpage|create">_Create New</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_underline">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="browse">
+ <property name="label" translatable="yes" context="dbwizconnectionpage|browse">_Browse…</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_underline">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <child>
+ <object class="GtkEntry" id="browseurl">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="truncate-multiline">True</property>
+ <property name="activates_default">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="browselabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+</interface>
diff --git a/dbaccess/uiconfig/ui/dbwizmysqlintropage.ui b/dbaccess/uiconfig/ui/dbwizmysqlintropage.ui
new file mode 100644
index 000000000..64f5a3488
--- /dev/null
+++ b/dbaccess/uiconfig/ui/dbwizmysqlintropage.ui
@@ -0,0 +1,142 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface domain="dba">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkBox" id="DBWizMysqlIntroPage">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="border_width">6</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkFrame" id="frame1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <object class="GtkBox" id="box1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <property name="margin-top">6</property>
+ <child>
+ <object class="GtkLabel" id="label2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="dbwizmysqlintropage|label2">You can connect to a MySQL database using either ODBC or JDBC.
+Please contact your system administrator if you are unsure about the following settings.</property>
+ <property name="wrap">True</property>
+ <property name="width_chars">72</property>
+ <property name="max_width_chars">72</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFrame" id="frame2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <object class="GtkBox" id="box2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <child>
+ <object class="GtkRadioButton" id="odbc">
+ <property name="label" translatable="yes" context="dbwizmysqlintropage|odbc">Connect using ODBC (Open Database Connectivity)</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">jdbc</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="jdbc">
+ <property name="label" translatable="yes" context="dbwizmysqlintropage|jdbc">Connect using JDBC (Java Database Connectivity)</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="directly">
+ <property name="label" translatable="yes" context="dbwizmysqlintropage|directly">Connect directly (using MariaDB C connector)</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">jdbc</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="dbwizmysqlintropage|label1">How do you want to connect to your MySQL database?</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="header">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="dbwizmysqlintropage|header">Set Up a Connection to a MySQL/MariaDB Database</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+</interface>
diff --git a/dbaccess/uiconfig/ui/dbwizmysqlnativepage.ui b/dbaccess/uiconfig/ui/dbwizmysqlnativepage.ui
new file mode 100644
index 000000000..b2537b2fd
--- /dev/null
+++ b/dbaccess/uiconfig/ui/dbwizmysqlnativepage.ui
@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface domain="dba">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkBox" id="DBWizMysqlNativePage">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="border_width">6</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkFrame" id="frame1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <object class="GtkBox" id="box1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <property name="margin-top">6</property>
+ <child>
+ <object class="GtkLabel" id="helptext">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="label" translatable="yes" context="dbwizmysqlnativepage|helptext">Please enter the required information to connect to a MySQL/MariaDB database.</property>
+ <property name="wrap">True</property>
+ <property name="width_chars">72</property>
+ <property name="max_width_chars">72</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="MySQLSettingsContainer">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="header">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="dbwizmysqlnativepage|header">Set Up a Connection to a MySQL/MariaDB Database</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+</interface>
diff --git a/dbaccess/uiconfig/ui/dbwizspreadsheetpage.ui b/dbaccess/uiconfig/ui/dbwizspreadsheetpage.ui
new file mode 100644
index 000000000..bc2752520
--- /dev/null
+++ b/dbaccess/uiconfig/ui/dbwizspreadsheetpage.ui
@@ -0,0 +1,169 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface domain="dba">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkBox" id="DBWizSpreadsheetPage">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="border_width">6</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkFrame" id="frame1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <object class="GtkBox" id="box1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <property name="margin-top">6</property>
+ <child>
+ <object class="GtkLabel" id="helptext">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="hexpand">True</property>
+ <property name="wrap">True</property>
+ <property name="width_chars">72</property>
+ <property name="max_width_chars">72</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="row_spacing">6</property>
+ <property name="column_spacing">6</property>
+ <child>
+ <object class="GtkButton" id="browse">
+ <property name="label" translatable="yes" context="dbwizspreadsheetpage|browse">Browse</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="create">
+ <property name="label" translatable="yes" context="dbwizspreadsheetpage|create">Create New</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="browseurllabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="hexpand">True</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">browseurl</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ <property name="width">3</property>
+ </packing>
+ </child>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <child>
+ <object class="GtkEntry" id="browseurl">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="truncate-multiline">True</property>
+ <property name="activates_default">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="browselabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="passwordrequired">
+ <property name="label" translatable="yes" context="dbwizspreadsheetpage|passwordrequired">_Password required</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
+ <property name="width">3</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="header">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+</interface>
diff --git a/dbaccess/uiconfig/ui/dbwiztextpage.ui b/dbaccess/uiconfig/ui/dbwiztextpage.ui
new file mode 100644
index 000000000..17b84019f
--- /dev/null
+++ b/dbaccess/uiconfig/ui/dbwiztextpage.ui
@@ -0,0 +1,171 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface domain="dba">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkBox" id="DBWizTextPage">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="border_width">6</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkFrame" id="frame1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <object class="GtkBox" id="box1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <property name="margin-top">6</property>
+ <child>
+ <object class="GtkLabel" id="helptext">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="hexpand">True</property>
+ <property name="wrap">True</property>
+ <property name="width_chars">72</property>
+ <property name="max_width_chars">72</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="row_spacing">6</property>
+ <property name="column_spacing">6</property>
+ <child>
+ <object class="GtkButton" id="browse">
+ <property name="label" translatable="yes" context="dbwiztextpage|browse">Browse</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="create">
+ <property name="label" translatable="yes" context="dbwiztextpage|create">Create New</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="browseurllabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="hexpand">True</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">browseurl</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ <property name="width">3</property>
+ </packing>
+ </child>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <child>
+ <object class="GtkEntry" id="browseurl">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="truncate-multiline">True</property>
+ <property name="hexpand">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="browselabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="header">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="TextPageContainer">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+</interface>
diff --git a/dbaccess/uiconfig/ui/deleteallrowsdialog.ui b/dbaccess/uiconfig/ui/deleteallrowsdialog.ui
new file mode 100644
index 000000000..1c42f9926
--- /dev/null
+++ b/dbaccess/uiconfig/ui/deleteallrowsdialog.ui
@@ -0,0 +1,81 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.18.3 -->
+<interface domain="dba">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkMessageDialog" id="DeleteAllRowsDialog">
+ <property name="can_focus">False</property>
+ <property name="resizable">False</property>
+ <property name="modal">True</property>
+ <property name="type_hint">dialog</property>
+ <property name="skip_taskbar_hint">True</property>
+ <property name="message_type">question</property>
+ <property name="text" translatable="yes" context="deleteallrowsdialog|DeleteAllRowsDialog">You are trying to delete all the columns in the table. A table cannot exist without columns. Should the table be deleted from the database? If not, the table will remain unchanged.</property>
+ <child internal-child="vbox">
+ <object class="GtkBox" id="messagedialog-vbox">
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox" id="messagedialog-action_area">
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkButton" id="no">
+ <property name="label" translatable="yes" context="stock">_No</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="yes">
+ <property name="label" translatable="yes" context="stock">_Yes</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="has_default">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="cancel">
+ <property name="label" translatable="yes" context="stock">_Cancel</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="-9">no</action-widget>
+ <action-widget response="-8">yes</action-widget>
+ <action-widget response="-6">cancel</action-widget>
+ </action-widgets>
+ </object>
+</interface>
diff --git a/dbaccess/uiconfig/ui/designsavemodifieddialog.ui b/dbaccess/uiconfig/ui/designsavemodifieddialog.ui
new file mode 100644
index 000000000..57e781bb6
--- /dev/null
+++ b/dbaccess/uiconfig/ui/designsavemodifieddialog.ui
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.18.3 -->
+<interface domain="dba">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkMessageDialog" id="DesignSaveModifiedDialog">
+ <property name="can_focus">False</property>
+ <property name="resizable">False</property>
+ <property name="modal">True</property>
+ <property name="type_hint">dialog</property>
+ <property name="skip_taskbar_hint">True</property>
+ <property name="message_type">question</property>
+ <property name="text" translatable="yes" context="designsavemodifieddialog|DesignSaveModifiedDialog">Do you want to save the changes?</property>
+ <property name="secondary_text" translatable="yes" context="designsavemodifieddialog|DesignSaveModifiedDialog">The relation design has been changed.</property>
+ <child internal-child="vbox">
+ <object class="GtkBox" id="messagedialog-vbox">
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox" id="messagedialog-action_area">
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkButton" id="no">
+ <property name="label" translatable="yes" context="stock">_No</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="yes">
+ <property name="label" translatable="yes" context="stock">_Yes</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="has_default">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="cancel">
+ <property name="label" translatable="yes" context="stock">_Cancel</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="-9">no</action-widget>
+ <action-widget response="-8">yes</action-widget>
+ <action-widget response="-6">cancel</action-widget>
+ </action-widgets>
+ </object>
+</interface>
diff --git a/dbaccess/uiconfig/ui/detailwindow.ui b/dbaccess/uiconfig/ui/detailwindow.ui
new file mode 100644
index 000000000..080e86927
--- /dev/null
+++ b/dbaccess/uiconfig/ui/detailwindow.ui
@@ -0,0 +1,178 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.36.0 -->
+<interface domain="dba">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkMenu" id="menu">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ </object>
+ <object class="GtkBox" id="DetailWindow">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="border_width">12</property>
+ <property name="spacing">6</property>
+ <property name="homogeneous">True</property>
+ <child>
+ <object class="GtkBox" id="box">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="column_spacing">6</property>
+ <child>
+ <object class="GtkSeparator" id="separator">
+ <property name="can_focus">False</property>
+ <property name="no_show_all">True</property>
+ <property name="orientation">vertical</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="row_spacing">6</property>
+ <child>
+ <object class="GtkScrolledWindow">
+ <property name="name">monoborder</property>
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="border_width">0</property>
+ <property name="shadow_type">in</property>
+ <child>
+ <object class="GtkViewport">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkDrawingArea" id="preview">
+ <property name="can_focus">False</property>
+ <property name="no_show_all">True</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkDrawingArea" id="infopreview">
+ <property name="can_focus">False</property>
+ <property name="no_show_all">True</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="tablepreview">
+ <property name="can_focus">False</property>
+ <property name="no_show_all">True</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkMenuButton" id="disablepreview">
+ <property name="label">label</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="no_show_all">True</property>
+ <property name="halign">end</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <property name="popup">menu</property>
+ <property name="use_popover">False</property>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+</interface>
diff --git a/dbaccess/uiconfig/ui/directsqldialog.ui b/dbaccess/uiconfig/ui/directsqldialog.ui
new file mode 100644
index 000000000..c1c06f40a
--- /dev/null
+++ b/dbaccess/uiconfig/ui/directsqldialog.ui
@@ -0,0 +1,335 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.38.2 -->
+<interface domain="dba">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkDialog" id="DirectSQLDialog">
+ <property name="can-focus">False</property>
+ <property name="border-width">6</property>
+ <property name="title" translatable="yes" context="directsqldialog|DirectSQLDialog">Execute SQL Statement</property>
+ <property name="resizable">False</property>
+ <property name="modal">True</property>
+ <property name="type-hint">dialog</property>
+ <child internal-child="vbox">
+ <object class="GtkBox" id="dialog-vbox1">
+ <property name="can-focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox" id="dialog-action_area1">
+ <property name="can-focus">False</property>
+ <property name="layout-style">end</property>
+ <child>
+ <object class="GtkButton" id="help">
+ <property name="label" translatable="yes" context="stock">_Help</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="can-default">True</property>
+ <property name="receives-default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ <property name="secondary">True</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="close">
+ <property name="label" translatable="yes" context="stock">_Close</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="can-default">True</property>
+ <property name="receives-default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack-type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFrame" id="frame1">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="label-xalign">0</property>
+ <property name="shadow-type">none</property>
+ <child>
+ <!-- n-columns=1 n-rows=5 -->
+ <object class="GtkGrid" id="grid1">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="row-spacing">6</property>
+ <child>
+ <object class="GtkScrolledWindow" id="scrolledwindow">
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="border-width">0</property>
+ <property name="hscrollbar-policy">never</property>
+ <property name="vscrollbar-policy">always</property>
+ <property name="shadow-type">in</property>
+ <child>
+ <object class="GtkViewport">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <child>
+ <object class="GtkDrawingArea" id="sql">
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="events">GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_FOCUS_CHANGE_MASK | GDK_STRUCTURE_MASK</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="sql-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="directsqldialog|extended_tip|sql">Enter the SQL administration command that you want to run.</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="sql_label">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label" translatable="yes" context="directsqldialog|sql_label">_Command to execute:</property>
+ <property name="use-underline">True</property>
+ <property name="mnemonic-widget">sql</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <!-- n-columns=2 n-rows=2 -->
+ <object class="GtkGrid" id="grid2">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="column-spacing">12</property>
+ <child>
+ <object class="GtkCheckButton" id="directsql">
+ <property name="label" translatable="yes" context="directsqldialog|directsql">Run SQL command _directly</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="directsql-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="directsqldialog|extended_tip|directsql">Execute the SQL command directly without escape processing.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">0</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="showoutput">
+ <property name="label" translatable="yes" context="directsqldialog|showoutput">_Show output of "select" statements</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="showoutput-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="directsqldialog|extended_tip|showoutput">Show the result of the SQL SELECT command in the Output box.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="execute">
+ <property name="label" translatable="yes" context="directsqldialog|execute">_Execute</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="can-default">True</property>
+ <property name="has-default">True</property>
+ <property name="receives-default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="sqlhistory">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="sqlhistory-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="directsqldialog|extended_tip|sqlhistory">Lists the previously executed SQL commands. To run a command again, click the command, and then click Execute.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">4</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="sqlhistory_label">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label" translatable="yes" context="directsqldialog|sqlhistory_label">_Previous commands:</property>
+ <property name="use-underline">True</property>
+ <property name="mnemonic-widget">sqlhistory</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">3</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label1">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label" translatable="yes" context="directsqldialog|label1">SQL Command</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFrame" id="frame2">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label-xalign">0</property>
+ <property name="shadow-type">none</property>
+ <child>
+ <object class="GtkScrolledWindow" id="scrolledwindow2">
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <property name="shadow-type">in</property>
+ <child>
+ <object class="GtkTextView" id="status">
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="editable">False</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="status-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="directsqldialog|extended_tip|status">Displays the results, including errors, of the SQL command that you ran.</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label2">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label" translatable="yes" context="directsqldialog|label2">Status</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFrame" id="frame3">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label-xalign">0</property>
+ <property name="shadow-type">none</property>
+ <child>
+ <object class="GtkScrolledWindow" id="scrolledwindow1">
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <property name="shadow-type">in</property>
+ <child>
+ <object class="GtkTextView" id="output">
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="editable">False</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="output-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="directsqldialog|extended_tip|output">Displays the results of the SQL command that you ran.</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label3">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label" translatable="yes" context="directsqldialog|label3">Output</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="-11">help</action-widget>
+ <action-widget response="-7">close</action-widget>
+ </action-widgets>
+ </object>
+</interface>
diff --git a/dbaccess/uiconfig/ui/emptypage.ui b/dbaccess/uiconfig/ui/emptypage.ui
new file mode 100644
index 000000000..257a5224c
--- /dev/null
+++ b/dbaccess/uiconfig/ui/emptypage.ui
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface domain="dba">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkBox" id="EmptyPage">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="border_width">6</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+</interface>
diff --git a/dbaccess/uiconfig/ui/fielddescpage.ui b/dbaccess/uiconfig/ui/fielddescpage.ui
new file mode 100644
index 000000000..b6b7ad90b
--- /dev/null
+++ b/dbaccess/uiconfig/ui/fielddescpage.ui
@@ -0,0 +1,429 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface domain="dba">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkAdjustment" id="adjustment1">
+ <property name="upper">100</property>
+ <property name="step_increment">1</property>
+ <property name="page_increment">10</property>
+ </object>
+ <object class="GtkAdjustment" id="adjustment2">
+ <property name="upper">100</property>
+ <property name="step_increment">1</property>
+ <property name="page_increment">10</property>
+ </object>
+ <object class="GtkAdjustment" id="adjustment3">
+ <property name="upper">100</property>
+ <property name="step_increment">1</property>
+ <property name="page_increment">10</property>
+ </object>
+ <object class="GtkAdjustment" id="adjustment4">
+ <property name="upper">100</property>
+ <property name="step_increment">1</property>
+ <property name="page_increment">10</property>
+ </object>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="FieldDescPage">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="border_width">6</property>
+ <child>
+ <object class="GtkScrolledWindow" id="scrolledwindow">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="shadow_type">in</property>
+ <child>
+ <object class="GtkViewport" id="viewport1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="border_width">6</property>
+ <property name="row_spacing">6</property>
+ <property name="column_spacing">12</property>
+ <child>
+ <object class="GtkLabel" id="ColumnNameText">
+ <property name="can_focus">False</property>
+ <property name="no_show_all">True</property>
+ <property name="label" translatable="yes" context="fielddescpage|STR_TAB_FIELD_NAME">Field name</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">ColumnName</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="ColumnName">
+ <property name="can_focus">True</property>
+ <property name="no_show_all">True</property>
+ <property name="truncate-multiline">True</property>
+ <property name="hexpand">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="AutoIncrementValueText">
+ <property name="can_focus">False</property>
+ <property name="no_show_all">True</property>
+ <property name="label" translatable="yes" context="fielddescpage|STR_AUTOINCREMENT_VALUE">A_uto-increment statement</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">AutoIncrementValue</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="AutoIncrementValue">
+ <property name="can_focus">True</property>
+ <property name="no_show_all">True</property>
+ <property name="hexpand">True</property>
+ <property name="truncate-multiline">True</property>
+ <property name="adjustment">adjustment2</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="DefaultValueText">
+ <property name="can_focus">False</property>
+ <property name="no_show_all">True</property>
+ <property name="label" translatable="yes" context="fielddescpage|STR_DEFAULT_VALUE">_Default value</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">DefaultValue</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">9</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="DefaultValue">
+ <property name="can_focus">True</property>
+ <property name="no_show_all">True</property>
+ <property name="truncate-multiline">True</property>
+ <property name="hexpand">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">9</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="FormatTextText">
+ <property name="can_focus">False</property>
+ <property name="no_show_all">True</property>
+ <property name="label" translatable="yes" context="fielddescpage|STR_DEFAULT_VALUE">Format example</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">FormatText</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">10</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="box1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkEntry" id="FormatText">
+ <property name="can_focus">True</property>
+ <property name="no_show_all">True</property>
+ <property name="truncate-multiline">True</property>
+ <property name="hexpand">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="FormatButton">
+ <property name="label" translatable="yes" context="fielddescpage|STR_BUTTON_FORMAT">_Format Field</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="no_show_all">True</property>
+ <property name="use_underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">10</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="LengthText">
+ <property name="can_focus">False</property>
+ <property name="no_show_all">True</property>
+ <property name="label" translatable="yes" context="fielddescpage|STR_LENGTH">_Length</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">Length</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">7</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="Length">
+ <property name="can_focus">True</property>
+ <property name="no_show_all">True</property>
+ <property name="hexpand">True</property>
+ <property name="truncate-multiline">True</property>
+ <property name="adjustment">adjustment1</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">7</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="TextLengthText">
+ <property name="can_focus">False</property>
+ <property name="no_show_all">True</property>
+ <property name="label" translatable="yes" context="fielddescpage|STR_LENGTH">_Length</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">TextLength</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">6</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="TextLength">
+ <property name="can_focus">True</property>
+ <property name="no_show_all">True</property>
+ <property name="hexpand">True</property>
+ <property name="truncate-multiline">True</property>
+ <property name="adjustment">adjustment3</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">6</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="ScaleText">
+ <property name="can_focus">False</property>
+ <property name="no_show_all">True</property>
+ <property name="label" translatable="yes" context="fielddescpage|STR_LENGTH">Decimal _places</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">Scale</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">8</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="Scale">
+ <property name="can_focus">True</property>
+ <property name="no_show_all">True</property>
+ <property name="hexpand">True</property>
+ <property name="truncate-multiline">True</property>
+ <property name="adjustment">adjustment4</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">8</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="RequiredText">
+ <property name="can_focus">False</property>
+ <property name="no_show_all">True</property>
+ <property name="label" translatable="yes" context="fielddescpage|STR_FIELD_REQUIRED">_Entry required</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">Required</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">5</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="Required">
+ <property name="can_focus">False</property>
+ <property name="no_show_all">True</property>
+ <property name="hexpand">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">5</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="AutoIncrementText">
+ <property name="can_focus">False</property>
+ <property name="no_show_all">True</property>
+ <property name="label" translatable="yes" context="fielddescpage|STR_FIELD_AUTOINCREMENT">_AutoValue</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">AutoIncrement</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="AutoIncrement">
+ <property name="can_focus">False</property>
+ <property name="no_show_all">True</property>
+ <property name="hexpand">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="BoolDefaultText">
+ <property name="can_focus">False</property>
+ <property name="no_show_all">True</property>
+ <property name="label" translatable="yes" context="fielddescpage|STR_FIELD_REQUIRED">_Default value</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">BoolDefault</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">11</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="BoolDefault">
+ <property name="can_focus">False</property>
+ <property name="no_show_all">True</property>
+ <property name="hexpand">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">11</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="NumTypeText">
+ <property name="can_focus">False</property>
+ <property name="no_show_all">True</property>
+ <property name="label" translatable="yes" context="fielddescpage|STR_NUMERIC_TYPE">_Type</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">NumType</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">4</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="NumType">
+ <property name="can_focus">False</property>
+ <property name="no_show_all">True</property>
+ <property name="hexpand">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">4</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="TypeText">
+ <property name="can_focus">False</property>
+ <property name="no_show_all">True</property>
+ <property name="label" translatable="yes" context="fielddescpage|STR_TAB_FIELD_DATATYPE">Field _type</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">Type</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="Type">
+ <property name="can_focus">False</property>
+ <property name="no_show_all">True</property>
+ <property name="hexpand">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ </object>
+ <object class="GtkSizeGroup">
+ <widgets>
+ <widget name="ColumnName"/>
+ <widget name="AutoIncrementValue"/>
+ <widget name="DefaultValue"/>
+ <widget name="box1"/>
+ <widget name="Length"/>
+ <widget name="TextLength"/>
+ <widget name="Scale"/>
+ <widget name="Required"/>
+ <widget name="AutoIncrement"/>
+ <widget name="BoolDefault"/>
+ <widget name="NumType"/>
+ <widget name="Type"/>
+ </widgets>
+ </object>
+</interface>
diff --git a/dbaccess/uiconfig/ui/fielddescpanel.ui b/dbaccess/uiconfig/ui/fielddescpanel.ui
new file mode 100644
index 000000000..1d59d51bb
--- /dev/null
+++ b/dbaccess/uiconfig/ui/fielddescpanel.ui
@@ -0,0 +1,87 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.36.0 -->
+<interface domain="dba">
+ <requires lib="gtk+" version="3.20"/>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="FieldDescPanel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="row_spacing">6</property>
+ <property name="column_spacing">12</property>
+ <child>
+ <object class="GtkLabel" id="header">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSeparator">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <child>
+ <object class="GtkScrolledWindow">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="tooltip_text" translatable="yes" context="designhelpbox|textview-tooltip">Field Properties Help</property>
+ <property name="border_width">6</property>
+ <property name="shadow_type">in</property>
+ <child>
+ <object class="GtkTextView" id="textview">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="editable">False</property>
+ <property name="wrap_mode">word</property>
+ <property name="accepts_tab">False</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="box">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ </object>
+</interface>
diff --git a/dbaccess/uiconfig/ui/fielddialog.ui b/dbaccess/uiconfig/ui/fielddialog.ui
new file mode 100644
index 000000000..6382468f9
--- /dev/null
+++ b/dbaccess/uiconfig/ui/fielddialog.ui
@@ -0,0 +1,235 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface domain="dba">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkDialog" id="FieldDialog">
+ <property name="name">-1</property>
+ <property name="can_focus">False</property>
+ <property name="border_width">6</property>
+ <property name="title" translatable="yes" context="fielddialog|FieldDialog">Field Format</property>
+ <property name="resizable">False</property>
+ <property name="modal">True</property>
+ <property name="default_width">0</property>
+ <property name="default_height">0</property>
+ <property name="type_hint">dialog</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child internal-child="vbox">
+ <object class="GtkBox" id="dialog-vbox1">
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox" id="dialog-action_area1">
+ <property name="can_focus">False</property>
+ <property name="layout_style">end</property>
+ <child>
+ <object class="GtkButton" id="reset">
+ <property name="label" translatable="yes" context="stock">_Reset</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="ok">
+ <property name="label" translatable="yes" context="stock">_OK</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="has_default">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="cancel">
+ <property name="label" translatable="yes" context="stock">_Cancel</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="help">
+ <property name="label" translatable="yes" context="stock">_Help</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">3</property>
+ <property name="secondary">True</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="box1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkNotebook" id="tabcontrol">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="scrollable">True</property>
+ <property name="enable_popup">True</property>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel" id="format">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="fielddialog|format">Format</property>
+ </object>
+ <packing>
+ <property name="tab_fill">False</property>
+ </packing>
+ </child>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel" id="alignment">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="fielddialog|alignment">Alignment</property>
+ <property name="xalign">0.5</property>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ <property name="tab_fill">False</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="alttitle">
+ <property name="can_focus">False</property>
+ <property name="no_show_all">True</property>
+ <property name="label" translatable="yes" context="fielddialog|alttitle">Table Format</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="101">reset</action-widget>
+ <action-widget response="-5">ok</action-widget>
+ <action-widget response="-6">cancel</action-widget>
+ <action-widget response="-11">help</action-widget>
+ </action-widgets>
+ </object>
+</interface>
diff --git a/dbaccess/uiconfig/ui/finalpagewizard.ui b/dbaccess/uiconfig/ui/finalpagewizard.ui
new file mode 100644
index 000000000..f391ad0e5
--- /dev/null
+++ b/dbaccess/uiconfig/ui/finalpagewizard.ui
@@ -0,0 +1,171 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface domain="dba">
+ <requires lib="gtk+" version="3.20"/>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="PageFinal">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="border_width">6</property>
+ <property name="orientation">vertical</property>
+ <property name="row_spacing">12</property>
+ <child>
+ <object class="GtkLabel" id="headerText">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="finalpagewizard|headerText">Decide How to Proceed After Saving the Database</property>
+ <property name="single_line_mode">True</property>
+ <property name="xalign">0</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="row_spacing">12</property>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="row_spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="helpText">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="finalpagewizard|helpText">Do you want the wizard to register the database in %PRODUCTNAME?</property>
+ <property name="wrap">True</property>
+ <property name="width_chars">72</property>
+ <property name="max_width_chars">72</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="yesregister">
+ <property name="label" translatable="yes" context="finalpagewizard|yesregister">_Yes, register the database for me</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="margin-start">12</property>
+ <property name="use_underline">True</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="noregister">
+ <property name="label" translatable="yes" context="finalpagewizard|noregister">N_o, do not register the database</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="margin-start">12</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">yesregister</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="row_spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="additionalText">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="finalpagewizard|additionalText">After the database file has been saved, what do you want to do?</property>
+ <property name="wrap">True</property>
+ <property name="width_chars">72</property>
+ <property name="max_width_chars">72</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="openediting">
+ <property name="label" translatable="yes" context="finalpagewizard|openediting">Open the database for editing</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="margin-start">12</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="usewizard">
+ <property name="label" translatable="yes" context="finalpagewizard|usewizard">Create tables using the table wizard</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="margin-start">12</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="finishText">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="finalpagewizard|finishText">Click 'Finish' to save the database.</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ </object>
+</interface>
diff --git a/dbaccess/uiconfig/ui/generalpagedialog.ui b/dbaccess/uiconfig/ui/generalpagedialog.ui
new file mode 100644
index 000000000..d40cd025b
--- /dev/null
+++ b/dbaccess/uiconfig/ui/generalpagedialog.ui
@@ -0,0 +1,86 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.18.3 -->
+<interface domain="dba">
+ <requires lib="gtk+" version="3.20"/>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="PageGeneral">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="border_width">16</property>
+ <property name="row_spacing">6</property>
+ <property name="column_spacing">12</property>
+ <child>
+ <object class="GtkLabel" id="datasourceTypePre">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0</property>
+ <property name="label" translatable="yes" context="generalpagedialog|datasourceTypePre">Select the type of database to which you want to establish a connection.</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">datasourceTypePre</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="datasourceTypeLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin-start">48</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes" context="generalpagedialog|datasourceTypeLabel">Database _type:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">datasourceType</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="datasourceType">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="hexpand">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="datasourceTypeHelp">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_top">6</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0</property>
+ <property name="label" translatable="yes" context="generalpagedialog|datasourceTypeHelp">On the following pages, you can make detailed settings for the connection.
+
+The new settings you make will overwrite your existing settings.</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">datasourceTypeHelp</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="specialMessage">
+ <property name="can_focus">False</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">3</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ </object>
+</interface>
diff --git a/dbaccess/uiconfig/ui/generalpagewizard.ui b/dbaccess/uiconfig/ui/generalpagewizard.ui
new file mode 100644
index 000000000..5abb1a7ec
--- /dev/null
+++ b/dbaccess/uiconfig/ui/generalpagewizard.ui
@@ -0,0 +1,277 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.38.2 -->
+<interface domain="dba">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkImage" id="image1">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="icon-name">document-open</property>
+ </object>
+ <!-- n-columns=1 n-rows=12 -->
+ <object class="GtkGrid" id="PageGeneral">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="border-width">6</property>
+ <property name="orientation">vertical</property>
+ <property name="row-spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="headerText">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label" translatable="yes" context="generalpagewizard|headerText">Welcome to the %PRODUCTNAME Database Wizard</property>
+ <property name="single-line-mode">True</property>
+ <property name="xalign">0</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="helpText">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="label" translatable="yes" context="generalpagewizard|helpText">Use the Database Wizard to create a new database, open an existing database file, or connect to a database stored on a server.</property>
+ <property name="wrap">True</property>
+ <property name="width-chars">72</property>
+ <property name="max-width-chars">72</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="sourceTypeHeader">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label" translatable="yes" context="generalpagewizard|sourceTypeHeader">What do you want to do?</property>
+ <property name="wrap">True</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="createDatabase">
+ <property name="label" translatable="yes" context="generalpagewizard|createDatabase">Create a n_ew database</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="has-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="margin-start">12</property>
+ <property name="use-underline">True</property>
+ <property name="active">True</property>
+ <property name="draw-indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="createDatabase-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="generalpagewizard|extended_tip|createDatabase">Select to create a new database.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="embeddeddbBox">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="margin-start">24</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkLabel" id="embeddeddbLabel">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label" translatable="yes" context="generalpagewizard|embeddeddbLabel">_Embedded database:</property>
+ <property name="use-underline">True</property>
+ <property name="mnemonic-widget">embeddeddbList</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="embeddeddbList">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">5</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="openExistingDatabase">
+ <property name="label" translatable="yes" context="generalpagewizard|openExistingDatabase">Open an existing database _file</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="margin-start">12</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ <property name="group">createDatabase</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="openExistingDatabase-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="generalpagewizard|extended_tip|openExistingDatabase">Select to open a database file from a list of recently used files or from a file selection dialog.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">6</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="docListBox">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="margin-start">24</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkLabel" id="docListLabel">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label" translatable="yes" context="generalpagewizard|docListLabel">_Recently used:</property>
+ <property name="use-underline">True</property>
+ <property name="mnemonic-widget">documentList</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="documentList">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="hexpand">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="docListBox-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="generalpagewizard|extended_tip|docListBox">Select a database file to open from the list of recently used files. Click Finish to open the file immediately and to exit the wizard.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">7</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="openDatabase">
+ <property name="label" translatable="yes" context="generalpagewizard|openDatabase">Open</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">True</property>
+ <property name="halign">start</property>
+ <property name="margin-start">24</property>
+ <property name="image">image1</property>
+ <property name="use-underline">True</property>
+ <property name="always-show-image">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="openDatabase-atkobject">
+ <property name="AtkObject::accessible-name" translatable="yes" context="generalpagewizard|extended_tip|openDatabase">Opens a file selection dialog where you can select a database file. Click Open or OK in the file selection dialog to open the file immediately and to exit the wizard.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">8</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="connectDatabase">
+ <property name="label" translatable="yes" context="generalpagewizard|connectDatabase">Connect to an e_xisting database</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="margin-start">12</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ <property name="group">createDatabase</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="connectDatabase-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="generalpagewizard|extended_tip|connectDatabase">Select to create a database document for an existing database connection.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">9</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="datasourceType">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="halign">start</property>
+ <property name="margin-start">24</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="datasourceType-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="generalpagewizard|extended_tip|datasourceType">Select the database type for the existing database connection.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">10</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="specialMessage">
+ <property name="can-focus">False</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">11</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="noembeddeddbLabel">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label" translatable="yes" context="generalpagewizard|noembeddeddbLabel">It is not possible to create a new database, because neither HSQLDB, nor Firebird is
+available in this setup.</property>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">4</property>
+ </packing>
+ </child>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="PageGeneral-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="generalpagewizard|extended_tip|PageGeneral">The Database Wizard creates a database file that contains information about a database.</property>
+ </object>
+ </child>
+ </object>
+</interface>
diff --git a/dbaccess/uiconfig/ui/generalspecialjdbcdetailspage.ui b/dbaccess/uiconfig/ui/generalspecialjdbcdetailspage.ui
new file mode 100644
index 000000000..faca85637
--- /dev/null
+++ b/dbaccess/uiconfig/ui/generalspecialjdbcdetailspage.ui
@@ -0,0 +1,244 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface domain="dba">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkAdjustment" id="adjustment1">
+ <property name="upper">65535</property>
+ <property name="step_increment">1</property>
+ <property name="page_increment">10</property>
+ </object>
+ <object class="GtkBox" id="GeneralSpecialJDBCDetails">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="border_width">6</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkFrame" id="frame2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="row_spacing">6</property>
+ <property name="column_spacing">12</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <child>
+ <object class="GtkLabel" id="label2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="generalspecialjdbcdetailspage|label2">_Host name:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">hostNameEntry</property>
+ <property name="xalign">1</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="generalspecialjdbcdetailspage|label3">_Port number:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">portNumberSpinbutton</property>
+ <property name="xalign">1</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="hostNameEntry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="truncate-multiline">True</property>
+ <property name="activates_default">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="socketLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="generalspecialjdbcdetailspage|socketLabel">Socket:</property>
+ <property name="xalign">1</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">socketEntry</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="driverClassLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="generalspecialjdbcdetailspage|driverClassLabel">MySQL JDBC d_river class:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">jdbcDriverClassEntry</property>
+ <property name="xalign">1</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="jdbcDriverClassEntry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="truncate-multiline">True</property>
+ <property name="activates_default">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="testDriverClassButton">
+ <property name="label" translatable="yes" context="generalspecialjdbcdetailspage|testDriverClassButton">Test Class</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="top_attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="socketEntry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="truncate-multiline">True</property>
+ <property name="activates_default">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="portNumberSpinbutton">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="truncate-multiline">True</property>
+ <property name="adjustment">adjustment1</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="generalspecialjdbcdetailspage|label1">Connection Settings</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFrame" id="frame1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <object class="GtkBox" id="box1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="spacing">12</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <child>
+ <object class="GtkLabel" id="charsetlabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="generalspecialjdbcdetailspage|charsetlabel">_Character set:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">charset</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="charset">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="charsetheader">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="generalspecialjdbcdetailspage|charsetheader">Data Conversion</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+</interface>
diff --git a/dbaccess/uiconfig/ui/generatedvaluespage.ui b/dbaccess/uiconfig/ui/generatedvaluespage.ui
new file mode 100644
index 000000000..6bf18c9f8
--- /dev/null
+++ b/dbaccess/uiconfig/ui/generatedvaluespage.ui
@@ -0,0 +1,146 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface domain="dba">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkFrame" id="GeneratedValuesPage">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="border_width">6</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="row_spacing">12</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <child>
+ <object class="GtkCheckButton" id="autoretrieve">
+ <property name="label" translatable="yes" context="generatedvaluespage|autoretrieve">Re_trieve generated values</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="row_spacing">12</property>
+ <property name="margin-start">12</property>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="row_spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="statementft">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="generatedvaluespage|statementft">_Auto-increment statement:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">statement</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="statement">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="activates_default">True</property>
+ <property name="truncate-multiline">True</property>
+ <property name="width_chars">34</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid4">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="row_spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="queryft">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="generatedvaluespage|queryft">_Query of generated values:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">query</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="query">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="activates_default">True</property>
+ <property name="truncate-multiline">True</property>
+ <property name="width_chars">34</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="generatedvaluespage|label1">Settings</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+</interface>
diff --git a/dbaccess/uiconfig/ui/indexdesigndialog.ui b/dbaccess/uiconfig/ui/indexdesigndialog.ui
new file mode 100644
index 000000000..837b29c86
--- /dev/null
+++ b/dbaccess/uiconfig/ui/indexdesigndialog.ui
@@ -0,0 +1,342 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface domain="dba">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkTreeStore" id="liststore1">
+ <columns>
+ <!-- column-name expander -->
+ <column type="GdkPixbuf"/>
+ <!-- column-name text -->
+ <column type="gchararray"/>
+ <!-- column-name id -->
+ <column type="gchararray"/>
+ </columns>
+ </object>
+ <object class="GtkDialog" id="IndexDesignDialog">
+ <property name="can_focus">False</property>
+ <property name="border_width">6</property>
+ <property name="title" translatable="yes" context="indexdesigndialog|IndexDesignDialog">Indexes</property>
+ <property name="resizable">False</property>
+ <property name="type_hint">dialog</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child internal-child="vbox">
+ <object class="GtkBox" id="dialog-vbox1">
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">2</property>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox" id="dialog-action_area1">
+ <property name="can_focus">False</property>
+ <property name="layout_style">end</property>
+ <child>
+ <object class="GtkButton" id="close">
+ <property name="label" translatable="yes" context="stock">_Close</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="help">
+ <property name="label" translatable="yes" context="stock">_Help</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ <property name="secondary">True</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="box1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkToolbar" id="ACTIONS">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <child>
+ <object class="GtkToolButton" id="ID_INDEX_NEW">
+ <property name="visible">True</property>
+ <property name="valign">start</property>
+ <property name="label" translatable="yes" context="indexdesigndialog|ID_INDEX_NEW">New Index</property>
+ <property name="use_underline">True</property>
+ <property name="icon_name">dbaccess/res/sc036.png</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">True</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToolButton" id="ID_INDEX_DROP">
+ <property name="visible">True</property>
+ <property name="valign">start</property>
+ <property name="label" translatable="yes" context="indexdesigndialog|ID_INDEX_DROP">Delete Current Index</property>
+ <property name="use_underline">True</property>
+ <property name="icon_name">dbaccess/res/sc037.png</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">True</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToolButton" id="ID_INDEX_RENAME">
+ <property name="visible">True</property>
+ <property name="valign">start</property>
+ <property name="label" translatable="yes" context="indexdesigndialog|ID_INDEX_RENAME">Rename Current Index</property>
+ <property name="use_underline">True</property>
+ <property name="icon_name">dbaccess/res/sc038.png</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">True</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToolButton" id="ID_INDEX_SAVE">
+ <property name="visible">True</property>
+ <property name="valign">start</property>
+ <property name="label" translatable="yes" context="indexdesigndialog|ID_INDEX_SAVE">Save Current Index</property>
+ <property name="use_underline">True</property>
+ <property name="icon_name">dbaccess/res/sc039.png</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">True</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToolButton" id="ID_INDEX_RESET">
+ <property name="visible">True</property>
+ <property name="valign">start</property>
+ <property name="label" translatable="yes" context="indexdesigndialog|ID_INDEX_RESET">Reset Current Index</property>
+ <property name="use_underline">True</property>
+ <property name="icon_name">dbaccess/res/sc040.png</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">True</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="row_spacing">6</property>
+ <property name="column_spacing">12</property>
+ <child>
+ <object class="GtkScrolledWindow">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="shadow_type">in</property>
+ <child>
+ <object class="GtkTreeView" id="INDEX_LIST">
+ <property name="width_request">-1</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="model">liststore1</property>
+ <property name="headers_visible">False</property>
+ <property name="search_column">1</property>
+ <property name="enable_tree_lines">True</property>
+ <child internal-child="selection">
+ <object class="GtkTreeSelection" id="Macro Library List-selection1"/>
+ </child>
+ <child>
+ <object class="GtkTreeViewColumn" id="treeviewcolumn2">
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkCellRendererPixbuf" id="cellrenderertext4"/>
+ <attributes>
+ <attribute name="pixbuf">0</attribute>
+ </attributes>
+ </child>
+ <child>
+ <object class="GtkCellRendererText" id="cellrenderertext2">
+ <property name="editable">True</property>
+ </object>
+ <attributes>
+ <attribute name="text">1</attribute>
+ </attributes>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFrame" id="frame1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid5">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="row_spacing">6</property>
+ <property name="column_spacing">12</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <child>
+ <object class="GtkLabel" id="DESC_LABEL">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="label" translatable="yes" context="indexdesigndialog|DESC_LABEL">Index identifier:</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="DESCRIPTION">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="UNIQUE">
+ <property name="label" translatable="yes" context="indexdesigndialog|UNIQUE">_Unique</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="halign">start</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="FIELDS_LABEL">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="label" translatable="yes" context="indexdesigndialog|FIELDS_LABEL">Fields:</property>
+ <property name="use_underline">True</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="FIELDS">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">3</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="INDEX_DETAILS">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="indexdesigndialog|INDEX_DETAILS">Index Details</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="-7">close</action-widget>
+ <action-widget response="-11">help</action-widget>
+ </action-widgets>
+ </object>
+</interface>
diff --git a/dbaccess/uiconfig/ui/jdbcconnectionpage.ui b/dbaccess/uiconfig/ui/jdbcconnectionpage.ui
new file mode 100644
index 000000000..906385de1
--- /dev/null
+++ b/dbaccess/uiconfig/ui/jdbcconnectionpage.ui
@@ -0,0 +1,206 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface domain="dba">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkBox" id="JDBCConnectionPage">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="border_width">6</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkLabel" id="header">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="margin_bottom">6</property>
+ <property name="label" translatable="yes" context="jdbcconnectionpage|header">Set Up a Connection to a JDBC Database</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="helptext">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="jdbcconnectionpage|helptext">Please enter the required information to connect to a JDBC database. Please contact your system administrator if you are unsure about the following settings.</property>
+ <property name="wrap">True</property>
+ <property name="width_chars">72</property>
+ <property name="max_width_chars">72</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="row_spacing">6</property>
+ <property name="column_spacing">12</property>
+ <child>
+ <object class="GtkLabel" id="browseurllabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="label" translatable="yes" context="jdbcconnectionpage|browseurllabel">Path to the dBASE files:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">browseurl</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="create">
+ <property name="label" translatable="yes" context="jdbcconnectionpage|create">_Create New</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_underline">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="browse">
+ <property name="label" translatable="yes" context="jdbcconnectionpage|browse">_Browse…</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_underline">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkEntry" id="browseurl">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="truncate-multiline">True</property>
+ <property name="activates_default">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="browselabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="box">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="jdbcLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="label" translatable="yes" context="jdbcconnectionpage|jdbcLabel">JDBC d_river class:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">jdbcEntry</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="box1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkEntry" id="jdbcEntry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="truncate-multiline">True</property>
+ <property name="activates_default">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="jdbcButton">
+ <property name="label" translatable="yes" context="jdbcconnectionpage|jdbcButton">_Test Class</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ </object>
+</interface>
diff --git a/dbaccess/uiconfig/ui/joindialog.ui b/dbaccess/uiconfig/ui/joindialog.ui
new file mode 100644
index 000000000..857a77563
--- /dev/null
+++ b/dbaccess/uiconfig/ui/joindialog.ui
@@ -0,0 +1,312 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface domain="dba">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkDialog" id="JoinDialog">
+ <property name="can_focus">False</property>
+ <property name="border_width">6</property>
+ <property name="title" translatable="yes" context="joindialog|JoinDialog">Join Properties</property>
+ <property name="resizable">False</property>
+ <property name="modal">True</property>
+ <property name="default_width">0</property>
+ <property name="default_height">0</property>
+ <property name="type_hint">dialog</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child internal-child="vbox">
+ <object class="GtkBox" id="dialog-vbox1">
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox" id="dialog-action_area1">
+ <property name="can_focus">False</property>
+ <property name="layout_style">end</property>
+ <child>
+ <object class="GtkButton" id="ok">
+ <property name="label" translatable="yes" context="stock">_OK</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="has_default">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="cancel">
+ <property name="label" translatable="yes" context="stock">_Cancel</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="help">
+ <property name="label" translatable="yes" context="stock">_Help</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ <property name="secondary">True</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="row_spacing">12</property>
+ <child>
+ <object class="GtkFrame" id="frame1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="column_spacing">12</property>
+ <property name="column_homogeneous">True</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <child>
+ <object class="GtkComboBoxText" id="table1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="table2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="joindialog|label1">Tables Involved</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFrame" id="frame2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid4">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="row_spacing">6</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <child>
+ <object class="GtkLabel" id="helptext">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="wrap">True</property>
+ <property name="width_chars">48</property>
+ <property name="max_width_chars">48</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="relations">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="joindialog|label2">Fields Involved</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFrame" id="frame5">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid7">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="row_spacing">6</property>
+ <property name="column_spacing">12</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <child>
+ <object class="GtkLabel" id="label5">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="label" translatable="yes" context="joindialog|label5">_Type:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">type</property>
+ <property name="xalign">1</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="type">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <items>
+ <item id="1" translatable="yes" context="joindialog|liststore1">Inner join</item>
+ <item id="2" translatable="yes" context="joindialog|liststore1">Left join</item>
+ <item id="3" translatable="yes" context="joindialog|liststore1">Right join</item>
+ <item id="4" translatable="yes" context="joindialog|liststore1">Full (outer) join</item>
+ <item id="5" translatable="yes" context="joindialog|liststore1">Cross join</item>
+ </items>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="natural">
+ <property name="label" translatable="yes" context="joindialog|natural">Natural</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label6">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="joindialog|label6">Options</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="-5">ok</action-widget>
+ <action-widget response="-6">cancel</action-widget>
+ <action-widget response="-11">help</action-widget>
+ </action-widgets>
+ </object>
+ <object class="GtkSizeGroup" id="sizegroup1">
+ <widgets>
+ <widget name="table1"/>
+ <widget name="label5"/>
+ </widgets>
+ </object>
+ <object class="GtkSizeGroup" id="sizegroup2">
+ <widgets>
+ <widget name="table2"/>
+ <widget name="type"/>
+ </widgets>
+ </object>
+</interface>
diff --git a/dbaccess/uiconfig/ui/jointablemenu.ui b/dbaccess/uiconfig/ui/jointablemenu.ui
new file mode 100644
index 000000000..2d651933b
--- /dev/null
+++ b/dbaccess/uiconfig/ui/jointablemenu.ui
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.20.0 -->
+<interface domain="dba">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkMenu" id="menu">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkMenuItem" id="delete">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="jointablemenu|delete">_Delete</property>
+ <property name="use_underline">True</property>
+ </object>
+ </child>
+ </object>
+</interface>
diff --git a/dbaccess/uiconfig/ui/joinviewmenu.ui b/dbaccess/uiconfig/ui/joinviewmenu.ui
new file mode 100644
index 000000000..bf6b0562e
--- /dev/null
+++ b/dbaccess/uiconfig/ui/joinviewmenu.ui
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.20.0 -->
+<interface domain="dba">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkMenu" id="menu">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkMenuItem" id="delete">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="joinviewmenu|delete">_Delete</property>
+ <property name="use_underline">True</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkMenuItem" id="edit">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="joinviewmenu|edit">Edit...</property>
+ <property name="use_underline">True</property>
+ </object>
+ </child>
+ </object>
+</interface>
diff --git a/dbaccess/uiconfig/ui/keymenu.ui b/dbaccess/uiconfig/ui/keymenu.ui
new file mode 100644
index 000000000..d86af7dbf
--- /dev/null
+++ b/dbaccess/uiconfig/ui/keymenu.ui
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.20.0 -->
+<interface domain="dba">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkMenu" id="menu">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkCheckMenuItem" id="primarykey">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="keymenu|primarykey">Primary Key</property>
+ <property name="use_underline">True</property>
+ </object>
+ </child>
+ </object>
+</interface>
diff --git a/dbaccess/uiconfig/ui/ldapconnectionpage.ui b/dbaccess/uiconfig/ui/ldapconnectionpage.ui
new file mode 100644
index 000000000..c02c7bdb9
--- /dev/null
+++ b/dbaccess/uiconfig/ui/ldapconnectionpage.ui
@@ -0,0 +1,189 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface domain="dba">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkAdjustment" id="adjustment1">
+ <property name="upper">1000000000000</property>
+ <property name="step_increment">1</property>
+ <property name="page_increment">10</property>
+ </object>
+ <object class="GtkBox" id="LDAPConnectionPage">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="border_width">6</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="header">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="margin_bottom">6</property>
+ <property name="label" translatable="yes" context="ldapconnectionpage|header">Set Up a Connection to an LDAP Directory</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="helpLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="ldapconnectionpage|helpLabel">Please enter the required information to connect to an LDAP directory. Please contact your system administrator if you are unsure about the following settings.</property>
+ <property name="wrap">True</property>
+ <property name="width_chars">72</property>
+ <property name="max_width_chars">72</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="row_spacing">6</property>
+ <property name="column_spacing">12</property>
+ <child>
+ <object class="GtkLabel" id="hostNameLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="ldapconnectionpage|hostNameLabel">_Server:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">hostNameEntry</property>
+ <property name="xalign">1</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="portNumLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="ldapconnectionpage|portNumLabel">_Port number:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">portNumEntry</property>
+ <property name="xalign">1</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="hostNameEntry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="truncate-multiline">True</property>
+ <property name="activates_default">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="box1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkSpinButton" id="portNumEntry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="activates_default">True</property>
+ <property name="truncate-multiline">True</property>
+ <property name="adjustment">adjustment1</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="portNumDefLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="ldapconnectionpage|portNumDefLabel">Default: 389</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="baseDNLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="ldapconnectionpage|baseDNLabel">Base _DN:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">baseDNEntry</property>
+ <property name="xalign">1</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="baseDNEntry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="truncate-multiline">True</property>
+ <property name="activates_default">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="useSSLCheckbutton">
+ <property name="label" translatable="yes" context="ldapconnectionpage|useSSLCheckbutton">Use _secure connection (TLS/SSL)</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ </object>
+</interface>
diff --git a/dbaccess/uiconfig/ui/ldappage.ui b/dbaccess/uiconfig/ui/ldappage.ui
new file mode 100644
index 000000000..8cd5bc8b8
--- /dev/null
+++ b/dbaccess/uiconfig/ui/ldappage.ui
@@ -0,0 +1,158 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface domain="dba">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkAdjustment" id="adjustment1">
+ <property name="upper">65535</property>
+ <property name="step_increment">1</property>
+ <property name="page_increment">10</property>
+ </object>
+ <object class="GtkAdjustment" id="adjustment2">
+ <property name="upper">65535</property>
+ <property name="step_increment">1</property>
+ <property name="page_increment">10</property>
+ </object>
+ <object class="GtkBox" id="LDAP">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="border_width">6</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkFrame" id="frame1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="row_spacing">6</property>
+ <property name="column_spacing">12</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <child>
+ <object class="GtkLabel" id="label1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="ldappage|label1">_Base DN:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">baseDNEntry</property>
+ <property name="xalign">1</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="baseDNEntry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="truncate-multiline">True</property>
+ <property name="activates_default">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="useSSLCheckbutton">
+ <property name="label" translatable="yes" context="ldappage|useSSLCheckbutton">Use secure connection (TLS/SSL)</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="ldappage|label2">_Port number:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">portNumberSpinbutton</property>
+ <property name="xalign">1</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="portNumberSpinbutton">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="activates_default">True</property>
+ <property name="truncate-multiline">True</property>
+ <property name="adjustment">adjustment1</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="ldappage|label3">Maximum number of _records:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">LDAPRowCountspinbutton</property>
+ <property name="xalign">1</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="LDAPRowCountspinbutton">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="activates_default">True</property>
+ <property name="truncate-multiline">True</property>
+ <property name="adjustment">adjustment2</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">3</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="charsetheader">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="ldappage|charsetheader">Connection Settings</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+</interface>
diff --git a/dbaccess/uiconfig/ui/limitbox.ui b/dbaccess/uiconfig/ui/limitbox.ui
new file mode 100644
index 000000000..c32f464e1
--- /dev/null
+++ b/dbaccess/uiconfig/ui/limitbox.ui
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface domain="dba">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkBox" id="LimitBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkComboBoxText" id="limit">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="has_entry">True</property>
+ <child internal-child="entry">
+ <object class="GtkEntry">
+ <property name="truncate-multiline">True</property>
+ <property name="can_focus">True</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+</interface>
diff --git a/dbaccess/uiconfig/ui/migrwarndlg.ui b/dbaccess/uiconfig/ui/migrwarndlg.ui
new file mode 100644
index 000000000..5f0d26671
--- /dev/null
+++ b/dbaccess/uiconfig/ui/migrwarndlg.ui
@@ -0,0 +1,81 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface domain="dba">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkMessageDialog" id="MigrationWarnDialog">
+ <property name="can_focus">False</property>
+ <property name="title" translatable="yes" context="migrationwarndialog|MigrationWarnDialog">Confirm Migration</property>
+ <property name="resizable">False</property>
+ <property name="modal">True</property>
+ <property name="type_hint">dialog</property>
+ <property name="text" translatable="yes" context="migrationwarndialog|MigrationWarnDialog">The document contains embedded HSQL data, which is deprecated.</property>
+ <property name="secondary_text" translatable="yes" context="migrationwarndialog|MigrationWarnDialog">Would you like to migrate to Firebird now?</property>
+ <child internal-child="vbox">
+ <object class="GtkBox" id="messagedialog-vbox">
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox" id="messagedialog-action_area">
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkButton" id="yes">
+ <property name="label" translatable="yes" context="stock">_Yes</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="no">
+ <property name="label" translatable="yes" context="migrationwarndialog|later">_Later</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="has_default">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLinkButton" id="link">
+ <property name="label" translatable="yes" context="migrationwarndialog|link">Click for important information about migration.</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="relief">none</property>
+ <property name="uri">https://wiki.documentfoundation.org/Documentation/HowTo/MigrateFromHSQLDB</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="-5">yes</action-widget>
+ <action-widget response="-6">no</action-widget>
+ </action-widgets>
+ </object>
+</interface>
diff --git a/dbaccess/uiconfig/ui/mysqlnativepage.ui b/dbaccess/uiconfig/ui/mysqlnativepage.ui
new file mode 100644
index 000000000..a533f6ca7
--- /dev/null
+++ b/dbaccess/uiconfig/ui/mysqlnativepage.ui
@@ -0,0 +1,197 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface domain="dba">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkBox" id="MysqlNativePage">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="border_width">6</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkFrame" id="connectionframe">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <object class="GtkBox" id="MySQLSettingsContainer">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="orientation">vertical</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="connectionheader">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="mysqlnativepage|connectionheader">Connection Settings</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFrame" id="userframe">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="row_spacing">6</property>
+ <property name="column_spacing">12</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <child>
+ <object class="GtkLabel" id="usernamelabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="mysqlnativepage|usernamelabel">_User name:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">username</property>
+ <property name="xalign">1</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="username">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="truncate-multiline">True</property>
+ <property name="activates_default">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="passwordrequired">
+ <property name="label" translatable="yes" context="mysqlnativepage|passwordrequired">Password required</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="userheader">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="mysqlnativepage|userheader">User Authentication</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFrame" id="charsetframe">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <object class="GtkBox" id="box1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="valign">start</property>
+ <property name="spacing">12</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <child>
+ <object class="GtkLabel" id="charsetlabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="mysqlnativepage|charsetlabel">_Character set:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">charset</property>
+ <property name="xalign">1</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="charset">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="charsetheader">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="mysqlnativepage|charsetheader">Data Conversion</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+</interface>
diff --git a/dbaccess/uiconfig/ui/mysqlnativesettings.ui b/dbaccess/uiconfig/ui/mysqlnativesettings.ui
new file mode 100644
index 000000000..61805941d
--- /dev/null
+++ b/dbaccess/uiconfig/ui/mysqlnativesettings.ui
@@ -0,0 +1,262 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface domain="dba">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkAdjustment" id="adjustment1">
+ <property name="upper">65535</property>
+ <property name="step_increment">1</property>
+ <property name="page_increment">10</property>
+ </object>
+ <object class="GtkBox" id="MysqlNativeSettings">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="border_width">6</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkBox" id="box1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkLabel" id="dbnamelabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="label" translatable="yes" context="mysqlnativesettings|dbnamelabel">_Database name:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">dbname</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="dbname">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="truncate-multiline">True</property>
+ <property name="activates_default">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid4">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="row_spacing">6</property>
+ <child>
+ <object class="GtkRadioButton" id="hostport">
+ <property name="label" translatable="yes" context="mysqlnativesettings|hostport">Se_rver/port</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="row_spacing">6</property>
+ <property name="column_spacing">12</property>
+ <property name="margin-start">12</property>
+ <child>
+ <object class="GtkLabel" id="serverlabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="mysqlnativesettings|serverlabel">_Server:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">server</property>
+ <property name="xalign">1</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="portlabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="mysqlnativesettings|portlabel">_Port:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">port</property>
+ <property name="xalign">1</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="server">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="truncate-multiline">True</property>
+ <property name="activates_default">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="defaultport">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="label" translatable="yes" context="mysqlnativesettings|defaultport">Default: 3306</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="port">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="activates_default">True</property>
+ <property name="adjustment">adjustment1</property>
+ <property name="truncate-multiline">True</property>
+ <property name="numeric">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="row_spacing">6</property>
+ <property name="column_spacing">12</property>
+ <child>
+ <object class="GtkRadioButton" id="socketlabel">
+ <property name="label" translatable="yes" context="mysqlnativesettings|socketlabel">So_cket:</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">hostport</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="socket">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="truncate-multiline">True</property>
+ <property name="activates_default">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="row_spacing">6</property>
+ <property name="column_spacing">12</property>
+ <child>
+ <object class="GtkRadioButton" id="namedpipelabel">
+ <property name="label" translatable="yes" context="mysqlnativesettings|namedpipelabel">Named p_ipe:</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">hostport</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="namedpipe">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="truncate-multiline">True</property>
+ <property name="activates_default">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">4</property>
+ </packing>
+ </child>
+ </object>
+</interface>
diff --git a/dbaccess/uiconfig/ui/namematchingpage.ui b/dbaccess/uiconfig/ui/namematchingpage.ui
new file mode 100644
index 000000000..d06ff1b3d
--- /dev/null
+++ b/dbaccess/uiconfig/ui/namematchingpage.ui
@@ -0,0 +1,305 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface domain="dba">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkTreeStore" id="liststore1">
+ <columns>
+ <!-- column-name check1 -->
+ <column type="gboolean"/>
+ <!-- column-name text -->
+ <column type="gchararray"/>
+ <!-- column-name id -->
+ <column type="gchararray"/>
+ <!-- column-name checkvis1 -->
+ <column type="gboolean"/>
+ <!-- column-name checktri1 -->
+ <column type="gboolean"/>
+ </columns>
+ </object>
+ <object class="GtkTreeStore" id="liststore2">
+ <columns>
+ <!-- column-name text -->
+ <column type="gchararray"/>
+ <!-- column-name id -->
+ <column type="gchararray"/>
+ </columns>
+ </object>
+ <object class="GtkBox" id="NameMatching">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="border_width">6</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkButtonBox" id="buttonbox1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <property name="layout_style">center</property>
+ <child>
+ <object class="GtkButton" id="up">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="down">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="all">
+ <property name="label" translatable="yes" context="namematchingpage|all">_All</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="none">
+ <property name="label" translatable="yes" context="namematchingpage|none">Non_e</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="box1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="leftlabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="label" translatable="yes" context="namematchingpage|leftlabel">Source table: </property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">left</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkScrolledWindow">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="shadow_type">in</property>
+ <child>
+ <object class="GtkTreeView" id="left">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="model">liststore1</property>
+ <property name="headers_visible">False</property>
+ <property name="search_column">1</property>
+ <property name="show_expanders">False</property>
+ <child internal-child="selection">
+ <object class="GtkTreeSelection" id="Macro Library List-selection2"/>
+ </child>
+ <child>
+ <object class="GtkTreeViewColumn" id="treeviewcolumn5">
+ <property name="resizable">True</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkCellRendererToggle" id="cellrenderer5"/>
+ <attributes>
+ <attribute name="visible">3</attribute>
+ <attribute name="active">0</attribute>
+ <attribute name="inconsistent">4</attribute>
+ </attributes>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkTreeViewColumn" id="treeviewcolumn9">
+ <property name="resizable">True</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkCellRendererText" id="cellrenderer4"/>
+ <attributes>
+ <attribute name="text">1</attribute>
+ </attributes>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="box2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="rightlabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="label" translatable="yes" context="namematchingpage|rightlabel">Destination table: </property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">right</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkScrolledWindow">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="shadow_type">in</property>
+ <child>
+ <object class="GtkTreeView" id="right">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="model">liststore2</property>
+ <property name="headers_visible">False</property>
+ <property name="search_column">0</property>
+ <property name="show_expanders">False</property>
+ <child internal-child="selection">
+ <object class="GtkTreeSelection" id="Macro Library List-selection1"/>
+ </child>
+ <child>
+ <object class="GtkTreeViewColumn" id="treeviewcolumn7">
+ <property name="resizable">True</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkCellRendererText" id="cellrenderer7"/>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButtonBox" id="buttonbox2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <property name="layout_style">center</property>
+ <child>
+ <object class="GtkButton" id="up_right">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="down_right">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ </object>
+</interface>
diff --git a/dbaccess/uiconfig/ui/odbcpage.ui b/dbaccess/uiconfig/ui/odbcpage.ui
new file mode 100644
index 000000000..a32e4ad53
--- /dev/null
+++ b/dbaccess/uiconfig/ui/odbcpage.ui
@@ -0,0 +1,165 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface domain="dba">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkBox" id="ODBC">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="border_width">6</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkFrame" id="frame1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <object class="GtkBox" id="box1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="spacing">12</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <child>
+ <object class="GtkLabel" id="charsetlabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="odbcpage|charsetlabel">_Character set:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">charset</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="charset">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="charsetheader">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="odbcpage|charsetheader">Data Conversion</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFrame" id="frame2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <object class="GtkBox" id="box2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <child>
+ <object class="GtkBox" id="box3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkLabel" id="optionslabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="odbcpage|optionslabel">ODBC _options:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">options</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="options">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="truncate-multiline">True</property>
+ <property name="activates_default">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="useCatalogCheckbutton">
+ <property name="label" translatable="yes" context="odbcpage|useCatalogCheckbutton">Use catalog for file-based databases</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="odbcpage|label1">Optional Settings</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+</interface>
diff --git a/dbaccess/uiconfig/ui/parametersdialog.ui b/dbaccess/uiconfig/ui/parametersdialog.ui
new file mode 100644
index 000000000..0f1192cfb
--- /dev/null
+++ b/dbaccess/uiconfig/ui/parametersdialog.ui
@@ -0,0 +1,232 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface domain="dba">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkTreeStore" id="liststore1">
+ <columns>
+ <!-- column-name text -->
+ <column type="gchararray"/>
+ <!-- column-name id -->
+ <column type="gchararray"/>
+ </columns>
+ </object>
+ <object class="GtkDialog" id="Parameters">
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="border_width">6</property>
+ <property name="title" translatable="yes" context="parametersdialog|Parameters">Parameter Input</property>
+ <property name="modal">True</property>
+ <property name="default_width">0</property>
+ <property name="default_height">0</property>
+ <property name="type_hint">dialog</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child internal-child="vbox">
+ <object class="GtkBox" id="dialog-vbox1">
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox" id="dialog-action_area1">
+ <property name="can_focus">False</property>
+ <property name="layout_style">end</property>
+ <child>
+ <object class="GtkButton" id="ok">
+ <property name="label" translatable="yes" context="stock">_OK</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="has_default">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="cancel">
+ <property name="label" translatable="yes" context="stock">_Cancel</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="help">
+ <property name="label" translatable="yes" context="stock">_Help</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ <property name="secondary">True</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFrame" id="frame1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <object class="GtkBox" id="box1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <child>
+ <object class="GtkScrolledWindow">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="shadow_type">in</property>
+ <child>
+ <object class="GtkTreeView" id="allParamTreeview">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="model">liststore1</property>
+ <property name="headers_visible">False</property>
+ <property name="headers_clickable">False</property>
+ <property name="search_column">0</property>
+ <property name="show_expanders">False</property>
+ <child internal-child="selection">
+ <object class="GtkTreeSelection" id="treeview-selection1"/>
+ </child>
+ <child>
+ <object class="GtkTreeViewColumn" id="treeviewcolumn1">
+ <child>
+ <object class="GtkCellRendererText" id="cellrenderertext1"/>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="label" translatable="yes" context="parametersdialog|label2">_Value:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">paramEntry</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="box2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkEntry" id="paramEntry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="truncate-multiline">True</property>
+ <property name="activates_default">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="next">
+ <property name="label" translatable="yes" context="parametersdialog|next">_Next</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="parametersdialog|label1">_Parameters</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">allParamTreeview</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="-5">ok</action-widget>
+ <action-widget response="-6">cancel</action-widget>
+ <action-widget response="-11">help</action-widget>
+ </action-widgets>
+ </object>
+</interface>
diff --git a/dbaccess/uiconfig/ui/password.ui b/dbaccess/uiconfig/ui/password.ui
new file mode 100644
index 000000000..6f577dbb0
--- /dev/null
+++ b/dbaccess/uiconfig/ui/password.ui
@@ -0,0 +1,208 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface domain="dba">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkDialog" id="PasswordDialog">
+ <property name="can_focus">False</property>
+ <property name="border_width">6</property>
+ <property name="title" translatable="yes" context="password|PasswordDialog">Change Password</property>
+ <property name="modal">True</property>
+ <property name="default_width">0</property>
+ <property name="default_height">0</property>
+ <property name="type_hint">dialog</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child internal-child="vbox">
+ <object class="GtkBox" id="dialog-vbox1">
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox" id="dialog-action_area1">
+ <property name="can_focus">False</property>
+ <property name="layout_style">end</property>
+ <child>
+ <object class="GtkButton" id="ok">
+ <property name="label" translatable="yes" context="stock">_OK</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="has_default">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="cancel">
+ <property name="label" translatable="yes" context="stock">_Cancel</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="help">
+ <property name="label" translatable="yes" context="stock">_Help</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ <property name="secondary">True</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFrame" id="userframe">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="row_spacing">6</property>
+ <property name="column_spacing">12</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <child>
+ <object class="GtkEntry" id="oldpassword">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="visibility">False</property>
+ <property name="activates_default">True</property>
+ <property name="truncate-multiline">True</property>
+ <property name="input_purpose">password</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="newpassword">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="visibility">False</property>
+ <property name="activates_default">True</property>
+ <property name="truncate-multiline">True</property>
+ <property name="input_purpose">password</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="password|label2">Old p_assword:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">oldpassword</property>
+ <property name="xalign">1</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="password|label3">_Password:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">newpassword</property>
+ <property name="xalign">1</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label4">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="password|label4">_Confirm password:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">confirmpassword</property>
+ <property name="xalign">1</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="confirmpassword">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="visibility">False</property>
+ <property name="activates_default">True</property>
+ <property name="truncate-multiline">True</property>
+ <property name="input_purpose">password</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="password|label1">User “$name$: $”</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="-5">ok</action-widget>
+ <action-widget response="-6">cancel</action-widget>
+ <action-widget response="-11">help</action-widget>
+ </action-widgets>
+ </object>
+</interface>
diff --git a/dbaccess/uiconfig/ui/querycolmenu.ui b/dbaccess/uiconfig/ui/querycolmenu.ui
new file mode 100644
index 000000000..c7b99b689
--- /dev/null
+++ b/dbaccess/uiconfig/ui/querycolmenu.ui
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.20.0 -->
+<interface domain="dba">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkMenu" id="menu">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkMenuItem" id="width">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="querycolmenu|width">Column _Width...</property>
+ <property name="use_underline">True</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkSeparatorMenuItem" id="separator">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkMenuItem" id="delete">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="querycolmenu|delete">_Delete</property>
+ <property name="use_underline">True</property>
+ </object>
+ </child>
+ </object>
+</interface>
diff --git a/dbaccess/uiconfig/ui/queryfilterdialog.ui b/dbaccess/uiconfig/ui/queryfilterdialog.ui
new file mode 100644
index 000000000..4ce05dc10
--- /dev/null
+++ b/dbaccess/uiconfig/ui/queryfilterdialog.ui
@@ -0,0 +1,388 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.36.0 -->
+<interface domain="dba">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkDialog" id="QueryFilterDialog">
+ <property name="can_focus">False</property>
+ <property name="border_width">6</property>
+ <property name="title" translatable="yes" context="queryfilterdialog|QueryFilterDialog">Standard Filter</property>
+ <property name="modal">True</property>
+ <property name="default_width">0</property>
+ <property name="default_height">0</property>
+ <property name="type_hint">dialog</property>
+ <child internal-child="vbox">
+ <object class="GtkBox" id="dialog-vbox1">
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox" id="dialog-action_area1">
+ <property name="can_focus">False</property>
+ <property name="layout_style">end</property>
+ <child>
+ <object class="GtkButton" id="ok">
+ <property name="label" translatable="yes" context="stock">_OK</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="has_default">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="cancel">
+ <property name="label" translatable="yes" context="stock">_Cancel</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="help">
+ <property name="label" translatable="yes" context="stock">_Help</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ <property name="secondary">True</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFrame" id="frame1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="row_spacing">6</property>
+ <property name="column_spacing">12</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <child>
+ <object class="GtkLabel" id="label2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="queryfilterdialog|label2">Operator</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label5">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="queryfilterdialog|label5">Field name</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label6">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="queryfilterdialog|label6">Condition</property>
+ </object>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="field1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="active">0</property>
+ <items>
+ <item translatable="yes" context="queryfilterdialog|field1">- none -</item>
+ </items>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="field1-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="queryfilterdialog|extended_tip|field1">Specifies the field names from the current table to set them in the argument.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="cond1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="active">0</property>
+ <items>
+ <item translatable="yes" context="queryfilterdialog|cond1">=</item>
+ <item translatable="yes" context="queryfilterdialog|cond1">&lt;&gt;</item>
+ <item translatable="yes" context="queryfilterdialog|cond1">&lt;</item>
+ <item translatable="yes" context="queryfilterdialog|cond1">&lt;=</item>
+ <item translatable="yes" context="queryfilterdialog|cond1">&gt;</item>
+ <item translatable="yes" context="queryfilterdialog|cond1">&gt;=</item>
+ <item translatable="yes" context="queryfilterdialog|cond1">like</item>
+ <item translatable="yes" context="queryfilterdialog|cond1">not like</item>
+ <item translatable="yes" context="queryfilterdialog|cond1">null</item>
+ <item translatable="yes" context="queryfilterdialog|cond1">not null</item>
+ </items>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="cond1-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="queryfilterdialog|extended_tip|cond1">Specifies the comparative operators through which the entries in the Field name and Value fields can be linked.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="field2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="active">0</property>
+ <items>
+ <item translatable="yes" context="queryfilterdialog|field2">- none -</item>
+ </items>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="field2-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="queryfilterdialog|extended_tip|field2">Specifies the field names from the current table to set them in the argument.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="field3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="active">0</property>
+ <items>
+ <item translatable="yes" context="queryfilterdialog|field3">- none -</item>
+ </items>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="field3-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="queryfilterdialog|extended_tip|field3">Specifies the field names from the current table to set them in the argument.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="cond2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="active">0</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="cond2-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="queryfilterdialog|extended_tip|cond2">Specifies the comparative operators through which the entries in the Field name and Value fields can be linked.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="cond3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="active">0</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="cond3-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="queryfilterdialog|extended_tip|cond3">Specifies the comparative operators through which the entries in the Field name and Value fields can be linked.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="top_attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label7">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="queryfilterdialog|label7">Value</property>
+ </object>
+ <packing>
+ <property name="left_attach">3</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="value1">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="activates_default">True</property>
+ <property name="truncate-multiline">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="value1-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="queryfilterdialog|extended_tip|value1">Specifies a value to filter the field.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">3</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="value2">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="activates_default">True</property>
+ <property name="truncate-multiline">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="value2-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="queryfilterdialog|extended_tip|value2">Specifies a value to filter the field.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">3</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="value3">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="activates_default">True</property>
+ <property name="truncate-multiline">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="value3-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="queryfilterdialog|extended_tip|value3">Specifies a value to filter the field.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">3</property>
+ <property name="top_attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="op2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="active">0</property>
+ <items>
+ <item translatable="yes" context="queryfilterdialog|op2">AND</item>
+ <item translatable="yes" context="queryfilterdialog|op2">OR</item>
+ </items>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="op2-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="queryfilterdialog|extended_tip|op2">For the following arguments, you can choose between the logical operators AND / OR.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="op3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="active">0</property>
+ <items>
+ <item translatable="yes" context="queryfilterdialog|op3">AND</item>
+ <item translatable="yes" context="queryfilterdialog|op3">OR</item>
+ </items>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="op3-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="queryfilterdialog|extended_tip|op3">For the following arguments, you can choose between the logical operators AND / OR.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="queryfilterdialog|label1">Criteria</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="-5">ok</action-widget>
+ <action-widget response="-6">cancel</action-widget>
+ <action-widget response="-11">help</action-widget>
+ </action-widgets>
+ <child type="titlebar">
+ <placeholder/>
+ </child>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="QueryFilterDialog-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="queryfilterdialog|extended_tip|QueryFilterDialog">Allows you to set the filtering options.</property>
+ </object>
+ </child>
+ </object>
+</interface>
diff --git a/dbaccess/uiconfig/ui/queryfuncmenu.ui b/dbaccess/uiconfig/ui/queryfuncmenu.ui
new file mode 100644
index 000000000..38b61edbe
--- /dev/null
+++ b/dbaccess/uiconfig/ui/queryfuncmenu.ui
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.20.0 -->
+<interface domain="dba">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkMenu" id="menu">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkMenuItem" id="functions">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="queryfuncmenu|functions">Functions</property>
+ <property name="use_underline">True</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkSeparatorMenuItem" id="menuitem1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkMenuItem" id="tablename">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="queryfuncmenu|tablename">Table Name</property>
+ <property name="use_underline">True</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkMenuItem" id="alias">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="queryfuncmenu|alias">Alias</property>
+ <property name="use_underline">True</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkSeparatorMenuItem" id="menuitem2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkMenuItem" id="distinct">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="queryfuncmenu|distinct">Distinct Values</property>
+ <property name="use_underline">True</property>
+ </object>
+ </child>
+ </object>
+</interface>
diff --git a/dbaccess/uiconfig/ui/querypropertiesdialog.ui b/dbaccess/uiconfig/ui/querypropertiesdialog.ui
new file mode 100644
index 000000000..1b4e72170
--- /dev/null
+++ b/dbaccess/uiconfig/ui/querypropertiesdialog.ui
@@ -0,0 +1,207 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.36.0 -->
+<interface domain="dba">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkDialog" id="QueryPropertiesDialog">
+ <property name="can_focus">False</property>
+ <property name="border_width">6</property>
+ <property name="title" translatable="yes" context="querypropertiesdialog|QueryPropertiesDialog">Query Properties</property>
+ <property name="resizable">False</property>
+ <property name="modal">True</property>
+ <property name="type_hint">dialog</property>
+ <child internal-child="vbox">
+ <object class="GtkBox" id="dialog-vbox1">
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox" id="dialog-action_area1">
+ <property name="can_focus">False</property>
+ <property name="layout_style">end</property>
+ <child>
+ <object class="GtkButton" id="ok">
+ <property name="label" translatable="yes" context="stock">_OK</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="has_default">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="cancel">
+ <property name="label" translatable="yes" context="stock">_Cancel</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="help">
+ <property name="label" translatable="yes" context="stock">_Help</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ <property name="secondary">True</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="row_spacing">6</property>
+ <property name="column_spacing">12</property>
+ <child>
+ <object class="GtkLabel" id="limit-label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="querypropertiesdialog|limit-label">Limit:</property>
+ <property name="xalign">1</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButtonBox" id="distinct-buttons">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="layout_style">start</property>
+ <child>
+ <object class="GtkRadioButton" id="distinct">
+ <property name="label" translatable="yes" context="querypropertiesdialog|distinct">Yes</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="distinct-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="querypropertiesdialog|extended_tip|distinct">Use distinct values in query.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="nondistinct">
+ <property name="label" translatable="yes" context="querypropertiesdialog|nondistinct">No</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">distinct</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="nondistinct-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="querypropertiesdialog|extended_tip|nondistinct">Not use distinct values in query.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="distinctvalues">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="querypropertiesdialog|distinctvalues">Distinct values:</property>
+ <property name="xalign">1</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="limitbox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="has_entry">True</property>
+ <child internal-child="entry">
+ <object class="GtkEntry">
+ <property name="can_focus">True</property>
+ <property name="truncate-multiline">True</property>
+ <property name="activates_default">True</property>
+ </object>
+ </child>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="limitbox-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="querypropertiesdialog|extended_tip|limitbox">Adds a Limit to set the maximum number of records to return.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="-5">ok</action-widget>
+ <action-widget response="-6">cancel</action-widget>
+ <action-widget response="-11">help</action-widget>
+ </action-widgets>
+ <child type="titlebar">
+ <placeholder/>
+ </child>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="QueryPropertiesDialog-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="querypropertiesdialog|extended_tip|QueryPropertiesDialog">In the Query Properties dialog you can set two properties of the SQL Query, i.e. whether to return distinct values, and whether to limit the result set.</property>
+ </object>
+ </child>
+ </object>
+</interface>
diff --git a/dbaccess/uiconfig/ui/queryview.ui b/dbaccess/uiconfig/ui/queryview.ui
new file mode 100644
index 000000000..ed31cfc34
--- /dev/null
+++ b/dbaccess/uiconfig/ui/queryview.ui
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.36.0 -->
+<interface domain="dba">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkBox" id="QueryView">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <child>
+ <object class="GtkScrolledWindow" id="scrolledwindow">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="border_width">0</property>
+ <property name="hscrollbar-policy">never</property>
+ <property name="vscrollbar-policy">always</property>
+ <property name="shadow_type">in</property>
+ <child>
+ <object class="GtkViewport">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkDrawingArea" id="sql">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="events">GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_FOCUS_CHANGE_MASK | GDK_STRUCTURE_MASK</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+</interface>
diff --git a/dbaccess/uiconfig/ui/relationdialog.ui b/dbaccess/uiconfig/ui/relationdialog.ui
new file mode 100644
index 000000000..d337b8ed1
--- /dev/null
+++ b/dbaccess/uiconfig/ui/relationdialog.ui
@@ -0,0 +1,431 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface domain="dba">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkDialog" id="RelationDialog">
+ <property name="can_focus">False</property>
+ <property name="border_width">6</property>
+ <property name="title" translatable="yes" context="relationdialog|RelationDialog">Relations</property>
+ <property name="resizable">False</property>
+ <property name="modal">True</property>
+ <property name="default_width">0</property>
+ <property name="default_height">0</property>
+ <property name="type_hint">dialog</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child internal-child="vbox">
+ <object class="GtkBox" id="dialog-vbox1">
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox" id="dialog-action_area1">
+ <property name="can_focus">False</property>
+ <property name="layout_style">end</property>
+ <child>
+ <object class="GtkButton" id="ok">
+ <property name="label" translatable="yes" context="stock">_OK</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="has_default">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="cancel">
+ <property name="label" translatable="yes" context="stock">_Cancel</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="help">
+ <property name="label" translatable="yes" context="stock">_Help</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ <property name="secondary">True</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="row_spacing">12</property>
+ <child>
+ <object class="GtkFrame" id="frame1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="column_spacing">12</property>
+ <property name="column_homogeneous">True</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <child>
+ <object class="GtkComboBoxText" id="table1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="table2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="relationdialog|label1">Tables Involved</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFrame" id="frame2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <object class="GtkBox" id="relations">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="relationdialog|label2">Fields Involved</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="column_spacing">12</property>
+ <child>
+ <object class="GtkFrame" id="frame3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid5">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="row_spacing">6</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <child>
+ <object class="GtkRadioButton" id="addaction">
+ <property name="label" translatable="yes" context="relationdialog|addaction">_No action</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="addcascade">
+ <property name="label" translatable="yes" context="relationdialog|addcascade">_Update cascade</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">addaction</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="addnull">
+ <property name="label" translatable="yes" context="relationdialog|addnull">_Set NULL</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">addaction</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="adddefault">
+ <property name="label" translatable="yes" context="relationdialog|adddefault">Set _default</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">addaction</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">3</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="relationdialog|label3">Update Options</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFrame" id="frame4">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid6">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="row_spacing">6</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <child>
+ <object class="GtkRadioButton" id="delaction">
+ <property name="label" translatable="yes" context="relationdialog|delaction">_No action</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="delcascade">
+ <property name="label" translatable="yes" context="relationdialog|delcascade">Delete _cascade</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">delaction</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="delnull">
+ <property name="label" translatable="yes" context="relationdialog|delnull">_Set NULL</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">delaction</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="deldefault">
+ <property name="label" translatable="yes" context="relationdialog|deldefault">Set _default</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">delaction</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">3</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label4">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="relationdialog|label4">Delete Options</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="-5">ok</action-widget>
+ <action-widget response="-6">cancel</action-widget>
+ <action-widget response="-11">help</action-widget>
+ </action-widgets>
+ </object>
+ <object class="GtkSizeGroup" id="sizegroup1">
+ <widgets>
+ <widget name="table1"/>
+ <widget name="label4"/>
+ </widgets>
+ </object>
+ <object class="GtkSizeGroup" id="sizegroup2">
+ <widgets>
+ <widget name="table2"/>
+ </widgets>
+ </object>
+ <object class="GtkListStore" id="liststore1">
+ <columns>
+ <!-- column-name gchararray1 -->
+ <column type="gchararray"/>
+ <!-- column-name gint1 -->
+ <column type="gint"/>
+ </columns>
+ <data>
+ <row>
+ <col id="0" translatable="yes" context="relationdialog|liststore1">Inner join</col>
+ <col id="1">1</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes" context="relationdialog|liststore1">Left join</col>
+ <col id="1">2</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes" context="relationdialog|liststore1">Right join</col>
+ <col id="1">3</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes" context="relationdialog|liststore1">Full (outer) join</col>
+ <col id="1">4</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes" context="relationdialog|liststore1">Cross join</col>
+ <col id="1">5</col>
+ </row>
+ </data>
+ </object>
+</interface>
diff --git a/dbaccess/uiconfig/ui/rowheightdialog.ui b/dbaccess/uiconfig/ui/rowheightdialog.ui
new file mode 100644
index 000000000..30493191d
--- /dev/null
+++ b/dbaccess/uiconfig/ui/rowheightdialog.ui
@@ -0,0 +1,172 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.36.0 -->
+<interface domain="dba">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkAdjustment" id="adjustment1">
+ <property name="lower">0.1</property>
+ <property name="upper">160</property>
+ <property name="value">2.27</property>
+ <property name="step_increment">1</property>
+ <property name="page_increment">10</property>
+ </object>
+ <object class="GtkDialog" id="RowHeightDialog">
+ <property name="can_focus">False</property>
+ <property name="border_width">6</property>
+ <property name="title" translatable="yes" context="rowheightdialog|RowHeightDialog">Row Height</property>
+ <property name="resizable">False</property>
+ <property name="modal">True</property>
+ <property name="default_width">0</property>
+ <property name="default_height">0</property>
+ <property name="type_hint">dialog</property>
+ <child internal-child="vbox">
+ <object class="GtkBox" id="dialog-vbox1">
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox" id="dialog-action_area1">
+ <property name="can_focus">False</property>
+ <property name="layout_style">end</property>
+ <child>
+ <object class="GtkButton" id="ok">
+ <property name="label" translatable="yes" context="stock">_OK</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="has_default">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="cancel">
+ <property name="label" translatable="yes" context="stock">_Cancel</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="help">
+ <property name="label" translatable="yes" context="stock">_Help</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ <property name="secondary">True</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="valign">start</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="row_spacing">6</property>
+ <property name="column_spacing">12</property>
+ <child>
+ <object class="GtkLabel" id="label1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="rowheightdialog|label1">_Height:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">value</property>
+ <property name="xalign">1</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="value">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="activates_default">True</property>
+ <property name="adjustment">adjustment1</property>
+ <property name="digits">2</property>
+ <property name="truncate-multiline">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="value-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="rowheightdialog|extended_tip|value">Enter the row height that you want to use.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="automatic">
+ <property name="label" translatable="yes" context="rowheightdialog|automatic">_Automatic</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="automatic-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="rowheightdialog|extended_tip|automatic">Adjusts the row height to the size based on the default template. Existing contents may be shown vertically cropped. The height no longer increases automatically when you enter larger contents.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="-5">ok</action-widget>
+ <action-widget response="-6">cancel</action-widget>
+ <action-widget response="-11">help</action-widget>
+ </action-widgets>
+ <child type="titlebar">
+ <placeholder/>
+ </child>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="RowHeightDialog-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="rowheightdialog|extended_tip|RowHeightDialog">Changes the height of the current row, or the selected rows.</property>
+ </object>
+ </child>
+ </object>
+</interface>
diff --git a/dbaccess/uiconfig/ui/savedialog.ui b/dbaccess/uiconfig/ui/savedialog.ui
new file mode 100644
index 000000000..79b7fde35
--- /dev/null
+++ b/dbaccess/uiconfig/ui/savedialog.ui
@@ -0,0 +1,208 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface domain="dba">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkDialog" id="SaveDialog">
+ <property name="can_focus">False</property>
+ <property name="border_width">6</property>
+ <property name="title" translatable="yes" context="savedialog|SaveDialog">Save As</property>
+ <property name="resizable">False</property>
+ <property name="modal">True</property>
+ <property name="default_width">0</property>
+ <property name="default_height">0</property>
+ <property name="type_hint">dialog</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child internal-child="vbox">
+ <object class="GtkBox" id="dialog-vbox1">
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox" id="dialog-action_area1">
+ <property name="can_focus">False</property>
+ <property name="layout_style">end</property>
+ <child>
+ <object class="GtkButton" id="ok">
+ <property name="label" translatable="yes" context="stock">_OK</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="has_default">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="cancel">
+ <property name="label" translatable="yes" context="stock">_Cancel</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="help">
+ <property name="label" translatable="yes" context="stock">_Help</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ <property name="secondary">True</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="row_spacing">6</property>
+ <property name="column_spacing">12</property>
+ <child>
+ <object class="GtkLabel" id="descriptionft">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="savedialog|descriptionft">Please enter a name for the object to be created:</property>
+ <property name="wrap">True</property>
+ <property name="max_width_chars">52</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="catalogft">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="savedialog|catalogft">_Catalog:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">catalog</property>
+ <property name="xalign">1</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="schemaft">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="savedialog|schemaft">_Schema:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">schema</property>
+ <property name="xalign">1</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="titleft">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">title</property>
+ <property name="xalign">1</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="title">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="truncate-multiline">True</property>
+ <property name="activates_default">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="catalog">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="has_entry">True</property>
+ <child internal-child="entry">
+ <object class="GtkEntry">
+ <property name="can_focus">True</property>
+ <property name="truncate-multiline">True</property>
+ <property name="activates_default">True</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="schema">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="has_entry">True</property>
+ <child internal-child="entry">
+ <object class="GtkEntry">
+ <property name="can_focus">True</property>
+ <property name="truncate-multiline">True</property>
+ <property name="activates_default">True</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="-5">ok</action-widget>
+ <action-widget response="-6">cancel</action-widget>
+ <action-widget response="-11">help</action-widget>
+ </action-widgets>
+ </object>
+</interface>
diff --git a/dbaccess/uiconfig/ui/saveindexdialog.ui b/dbaccess/uiconfig/ui/saveindexdialog.ui
new file mode 100644
index 000000000..861ce90fc
--- /dev/null
+++ b/dbaccess/uiconfig/ui/saveindexdialog.ui
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.18.3 -->
+<interface domain="dba">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkMessageDialog" id="SaveIndexDialog">
+ <property name="can_focus">False</property>
+ <property name="title" translatable="yes" context="saveindexdialog|SaveIndexDialog">Exit Index Design</property>
+ <property name="resizable">False</property>
+ <property name="modal">True</property>
+ <property name="type_hint">dialog</property>
+ <property name="skip_taskbar_hint">True</property>
+ <property name="message_type">question</property>
+ <property name="text" translatable="yes" context="saveindexdialog|SaveIndexDialog">Do you want to save the changes made to the current index?</property>
+ <child internal-child="vbox">
+ <object class="GtkBox" id="messagedialog-vbox">
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox" id="messagedialog-action_area">
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkButton" id="no">
+ <property name="label" translatable="yes" context="stock">_No</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="yes">
+ <property name="label" translatable="yes" context="stock">_Yes</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="has_default">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="cancel">
+ <property name="label" translatable="yes" context="stock">_Cancel</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="-9">no</action-widget>
+ <action-widget response="-8">yes</action-widget>
+ <action-widget response="-6">cancel</action-widget>
+ </action-widgets>
+ </object>
+</interface>
diff --git a/dbaccess/uiconfig/ui/savemodifieddialog.ui b/dbaccess/uiconfig/ui/savemodifieddialog.ui
new file mode 100644
index 000000000..b90b4dd9a
--- /dev/null
+++ b/dbaccess/uiconfig/ui/savemodifieddialog.ui
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.18.3 -->
+<interface domain="dba">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkMessageDialog" id="SaveModifiedDialog">
+ <property name="can_focus">False</property>
+ <property name="resizable">False</property>
+ <property name="modal">True</property>
+ <property name="type_hint">dialog</property>
+ <property name="skip_taskbar_hint">True</property>
+ <property name="message_type">question</property>
+ <property name="text" translatable="yes" context="savemodifieddialog|SaveModifiedDialog">Do you want to save the changes?</property>
+ <property name="secondary_text" translatable="yes" context="savemodifieddialog|SaveModifiedDialog">The current record has been changed.</property>
+ <child internal-child="vbox">
+ <object class="GtkBox" id="messagedialog-vbox">
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox" id="messagedialog-action_area">
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkButton" id="no">
+ <property name="label" translatable="yes" context="stock">_No</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="yes">
+ <property name="label" translatable="yes" context="stock">_Yes</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="has_default">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="cancel">
+ <property name="label" translatable="yes" context="stock">_Cancel</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="-9">no</action-widget>
+ <action-widget response="-8">yes</action-widget>
+ <action-widget response="-6">cancel</action-widget>
+ </action-widgets>
+ </object>
+</interface>
diff --git a/dbaccess/uiconfig/ui/sortdialog.ui b/dbaccess/uiconfig/ui/sortdialog.ui
new file mode 100644
index 000000000..5b88fc62c
--- /dev/null
+++ b/dbaccess/uiconfig/ui/sortdialog.ui
@@ -0,0 +1,270 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.36.0 -->
+<interface domain="dba">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkDialog" id="SortDialog">
+ <property name="can_focus">False</property>
+ <property name="border_width">6</property>
+ <property name="title" translatable="yes" context="sortdialog|SortDialog">Sort Order</property>
+ <property name="resizable">False</property>
+ <property name="modal">True</property>
+ <property name="default_width">0</property>
+ <property name="default_height">0</property>
+ <property name="type_hint">dialog</property>
+ <child internal-child="vbox">
+ <object class="GtkBox" id="dialog-vbox1">
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox" id="dialog-action_area1">
+ <property name="can_focus">False</property>
+ <property name="layout_style">end</property>
+ <child>
+ <object class="GtkButton" id="ok">
+ <property name="label" translatable="yes" context="stock">_OK</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="has_default">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="cancel">
+ <property name="label" translatable="yes" context="stock">_Cancel</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="help">
+ <property name="label" translatable="yes" context="stock">_Help</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ <property name="secondary">True</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFrame" id="frame1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="row_spacing">6</property>
+ <property name="column_spacing">12</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <child>
+ <object class="GtkLabel" id="label2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="sortdialog|label2">Operator</property>
+ <property name="ellipsize">end</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="sortdialog|label3">and then</property>
+ <property name="ellipsize">end</property>
+ <property name="xalign">1</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label4">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="sortdialog|label4">and then</property>
+ <property name="ellipsize">end</property>
+ <property name="xalign">1</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label5">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="sortdialog|label5">Field name</property>
+ <property name="ellipsize">end</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label6">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="sortdialog|label6">Order</property>
+ <property name="ellipsize">end</property>
+ </object>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="field1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="value1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <items>
+ <item translatable="yes" context="sortdialog|value1">ascending</item>
+ <item translatable="yes" context="sortdialog|value1">descending</item>
+ </items>
+ </object>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="field2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="field3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="value2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <items>
+ <item translatable="yes" context="sortdialog|value2">ascending</item>
+ <item translatable="yes" context="sortdialog|value2">descending</item>
+ </items>
+ </object>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="value3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <items>
+ <item translatable="yes" context="sortdialog|value3">ascending</item>
+ <item translatable="yes" context="sortdialog|value3">descending</item>
+ </items>
+ </object>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="top_attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="sortdialog|label1">Sort Order</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="-5">ok</action-widget>
+ <action-widget response="-6">cancel</action-widget>
+ <action-widget response="-11">help</action-widget>
+ </action-widgets>
+ <child type="titlebar">
+ <placeholder/>
+ </child>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="SortDialog-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="sortdialog|extended_tip|SortDialog">Specifies the sort criteria for the data display.</property>
+ </object>
+ </child>
+ </object>
+</interface>
diff --git a/dbaccess/uiconfig/ui/specialjdbcconnectionpage.ui b/dbaccess/uiconfig/ui/specialjdbcconnectionpage.ui
new file mode 100644
index 000000000..0605fb00b
--- /dev/null
+++ b/dbaccess/uiconfig/ui/specialjdbcconnectionpage.ui
@@ -0,0 +1,234 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface domain="dba">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkAdjustment" id="adjustment1">
+ <property name="upper">1000000000000</property>
+ <property name="step_increment">1</property>
+ <property name="page_increment">10</property>
+ </object>
+ <object class="GtkBox" id="SpecialJDBCConnectionPage">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="border_width">6</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkLabel" id="header">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="margin_bottom">6</property>
+ <property name="label" translatable="yes" context="specialjdbcconnectionpage|header">Set up connection to a MySQL/MariaDB database using JDBC</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="helpLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="specialjdbcconnectionpage|helpLabel">Please enter the required information to connect to a MySQL/MariaDB database using JDBC. Note that a JDBC driver class must be installed on your system and registered with %PRODUCTNAME. Please contact your system administrator if you are unsure about the following settings. </property>
+ <property name="wrap">True</property>
+ <property name="width_chars">72</property>
+ <property name="max_width_chars">72</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="row_spacing">6</property>
+ <property name="column_spacing">12</property>
+ <child>
+ <object class="GtkLabel" id="dbNameLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="specialjdbcconnectionpage|dbNameLabel">_Database name:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">dbNameEntry</property>
+ <property name="xalign">1</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="hostNameLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="specialjdbcconnectionpage|hostNameLabel">_Server:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">hostNameEntry</property>
+ <property name="xalign">1</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="portNumLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="specialjdbcconnectionpage|portNumLabel">_Port number:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">portNumEntry</property>
+ <property name="xalign">1</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="dbNameEntry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="truncate-multiline">True</property>
+ <property name="activates_default">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="hostNameEntry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="truncate-multiline">True</property>
+ <property name="activates_default">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="box1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkSpinButton" id="portNumEntry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="activates_default">True</property>
+ <property name="truncate-multiline">True</property>
+ <property name="adjustment">adjustment1</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="portNumDefLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="specialjdbcconnectionpage|portNumDefLabel">Default: 3306</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="row_spacing">6</property>
+ <property name="column_spacing">12</property>
+ <child>
+ <object class="GtkLabel" id="jdbcDriverLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="label" translatable="yes" context="specialjdbcconnectionpage|jdbcDriverLabel">MySQL/MariaDB JDBC d_river class:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">jdbcDriverEntry</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="jdbcDriverEntry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="truncate-multiline">True</property>
+ <property name="activates_default">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="testDriverButton">
+ <property name="label" translatable="yes" context="specialjdbcconnectionpage|testDriverButton">_Test Class</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_underline">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ </object>
+</interface>
diff --git a/dbaccess/uiconfig/ui/specialsettingspage.ui b/dbaccess/uiconfig/ui/specialsettingspage.ui
new file mode 100644
index 000000000..9281d4cd4
--- /dev/null
+++ b/dbaccess/uiconfig/ui/specialsettingspage.ui
@@ -0,0 +1,414 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.38.2 -->
+<interface domain="dba">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkAdjustment" id="adjustment1">
+ <property name="upper">1000000</property>
+ <property name="step-increment">1</property>
+ <property name="page-increment">10</property>
+ </object>
+ <object class="GtkBox" id="SpecialSettingsPage">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="border-width">6</property>
+ <child>
+ <!-- n-columns=1 n-rows=17 -->
+ <object class="GtkGrid" id="grid1">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="row-spacing">6</property>
+ <child>
+ <object class="GtkCheckButton" id="usesql92">
+ <property name="label" translatable="yes" context="specialsettingspage|usesql92">Use SQL92 naming constraints</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="no-show-all">True</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="usesql92-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="specialsettingspage|extended_tip|usesql92">Only allows characters that conform to the SQL92 naming convention in a name in a data source. All other characters are rejected. Each name must begin with a lowercase letter, an uppercase letter, or an underscore ( _ ). The remaining characters can be ASCII letters, numbers, and underscores.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="append">
+ <property name="label" translatable="yes" context="specialsettingspage|append">Append the table alias name on SELECT statements</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="no-show-all">True</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="append-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="specialsettings|extended_tip|append">Appends the alias to the table name in SELECT statements.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="useas">
+ <property name="label" translatable="yes" context="specialsettingspage|useas">Use keyword AS before table alias names</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="no-show-all">True</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="useas-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="specialsettingspage|extended_tip|useas">Some databases use the keyword "AS" between a name and its alias, while other databases use a whitespace. Enable this option to insert AS before the alias.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="useoj">
+ <property name="label" translatable="yes" context="specialsettingspage|useoj">Use Outer Join syntax '{oj }'</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="no-show-all">True</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="useoj-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="specialsettingsoage|extended_tip|useoj">Use escape sequences for outer joins. The syntax for this escape sequence is {oj outer-join}</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="ignoreprivs">
+ <property name="label" translatable="yes" context="specialsettingspage|ignoreprivs">Ignore the privileges from the database driver</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="no-show-all">True</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="ignoreprivs-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="specialsettingspage|extended_tip|ignoreprivs">Ignores access privileges that are provided by the database driver.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">4</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="replaceparams">
+ <property name="label" translatable="yes" context="specialsettingspage|replaceparams">Replace named parameters with '?'</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="no-show-all">True</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="replaceparams-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="specialsettingspage|extended_tip|replaceparams">Replaces named parameters in a data source with a question mark (?).</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">5</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="displayver">
+ <property name="label" translatable="yes" context="specialsettingspage|displayver">Display version columns (when available)</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="no-show-all">True</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="displayver-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="specialsettingspage|extended_tip|displayver">Displays the internal version number of the record in the database table.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">6</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="usecatalogname">
+ <property name="label" translatable="yes" context="specialsettingspage|usecatalogname">Use catalog name in SELECT statements</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="no-show-all">True</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="usecatalogname-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="specialsettingspage|extended_tip|usecatalogname">Uses the current data source of the catalog. This option is useful when the ODBC data source is a database server. Do not select this option if the ODBC data source is a dBASE driver.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">7</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="useschemaname">
+ <property name="label" translatable="yes" context="specialsettingspage|useschemaname">Use schema name in SELECT statements</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="no-show-all">True</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="useschemaname-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="specialsettingspage|extended_tip|useschemaname">Allows you to use the schema name in SELECT statements.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">8</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="createindex">
+ <property name="label" translatable="yes" context="specialsettingspage|createindex">Create index with ASC or DESC statement</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="no-show-all">True</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="createindex-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="specialsettingspage|extended_tip|createindex">Creates an index with ASC or DESC statements.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">9</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="eol">
+ <property name="label" translatable="yes" context="specialsettingspage|eol">End text lines with CR+LF</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="no-show-all">True</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="eol-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="specialsettingspage|extended_tip|eol">Select to use the CR + LF code pair to end every text line (preferred for DOS and Windows operating systems).</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">10</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="ignorecurrency">
+ <property name="label" translatable="yes" context="specialsettingspage|ignorecurrency">Ignore currency field information</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="no-show-all">True</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="ignorecurrency-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="specialsettingspage|extended_tip|ignorecurrency">Only for Oracle JDBC connections. When enabled it specifies that no column is treated as a currency field. The field type returned from the database driver is discarded.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">11</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="inputchecks">
+ <property name="label" translatable="yes" context="specialsettingspage|inputchecks">Form data input checks for required fields</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="no-show-all">True</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="inputchecks-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="specialsettingspage|extended_tip|inputchecks">When you enter a new record or update an existing record in a form, and you leave a field empty which is bound to a database column which requires input, then you will see a message complaining about the empty field.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">12</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="useodbcliterals">
+ <property name="label" translatable="yes" context="specialsettingspage|useodbcliterals">Use ODBC conformant date/time literals</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="no-show-all">True</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="useodbcliterals-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="specialsettingspage|extended_tip|useodbcliterals">Use date/time literals that conform to ODBC standard.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">13</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="primarykeys">
+ <property name="label" translatable="yes" context="specialsettingspage|primarykeys">Supports primary keys</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="no-show-all">True</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="primarykeys-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="specialsettingspage|extended_tip|primarykeys">Enable to overrule Base's heuristics used to detect whether the database supports primary keys.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">14</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="resulttype">
+ <property name="label" translatable="yes" context="specialsettingspage|resulttype">Respect the result set type from the database driver</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="no-show-all">True</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="resulttype-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="specialsettingspage|extended_tip|resulttype">Use the database driver different scroll capabilities of a result set.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">15</property>
+ </packing>
+ </child>
+ <child>
+ <!-- n-columns=2 n-rows=2 -->
+ <object class="GtkGrid" id="grid2">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="row-spacing">6</property>
+ <property name="column-spacing">12</property>
+ <child>
+ <object class="GtkLabel" id="comparisonft">
+ <property name="can-focus">False</property>
+ <property name="no-show-all">True</property>
+ <property name="label" translatable="yes" context="specialsettingspage|comparisonft">Comparison of Boolean values:</property>
+ <property name="use-underline">True</property>
+ <property name="mnemonic-widget">comparison</property>
+ <property name="xalign">1</property>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="comparison">
+ <property name="can-focus">False</property>
+ <property name="no-show-all">True</property>
+ <items>
+ <item translatable="yes" context="specialsettingspage|comparison">Default</item>
+ <item translatable="yes" context="specialsettingspage|comparison">SQL</item>
+ <item translatable="yes" context="specialsettingspage|comparison">Mixed</item>
+ <item translatable="yes" context="specialsettingspage|comparison">MS Access</item>
+ </items>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="comparison-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="specialsettingspage|extended_tip|comparison">Select the type of Boolean comparison that you want to use.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="rowsft">
+ <property name="can-focus">False</property>
+ <property name="no-show-all">True</property>
+ <property name="label" translatable="yes" context="specialsettingspage|rowsft">Rows to scan column types:</property>
+ <property name="use-underline">True</property>
+ <property name="mnemonic-widget">rows</property>
+ <property name="xalign">1</property>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="rows">
+ <property name="can-focus">True</property>
+ <property name="no-show-all">True</property>
+ <property name="activates-default">True</property>
+ <property name="truncate-multiline">True</property>
+ <property name="adjustment">adjustment1</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="rows-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="specialsettingspage|extended_tip|rows">Select the number of rows to let the driver detect the data type.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">16</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+</interface>
diff --git a/dbaccess/uiconfig/ui/sqlexception.ui b/dbaccess/uiconfig/ui/sqlexception.ui
new file mode 100644
index 000000000..07547e86a
--- /dev/null
+++ b/dbaccess/uiconfig/ui/sqlexception.ui
@@ -0,0 +1,180 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.20.2 -->
+<interface domain="dba">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkTreeStore" id="liststore1">
+ <columns>
+ <!-- column-name image -->
+ <column type="GdkPixbuf"/>
+ <!-- column-name text -->
+ <column type="gchararray"/>
+ <!-- column-name id -->
+ <column type="gchararray"/>
+ </columns>
+ </object>
+ <object class="GtkDialog" id="SQLExceptionDialog">
+ <property name="can_focus">False</property>
+ <property name="border_width">6</property>
+ <property name="title" translatable="yes" context="sqlexception|SQLExceptionDialog">Error Details</property>
+ <property name="modal">True</property>
+ <property name="default_width">0</property>
+ <property name="default_height">0</property>
+ <property name="type_hint">dialog</property>
+ <child internal-child="vbox">
+ <object class="GtkBox" id="dialog-vbox1">
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox" id="dialog-action_area1">
+ <property name="can_focus">False</property>
+ <property name="layout_style">end</property>
+ <child>
+ <object class="GtkButton" id="ok">
+ <property name="label" translatable="yes" context="stock">_OK</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="has_default">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="row_spacing">6</property>
+ <property name="column_spacing">12</property>
+ <child>
+ <object class="GtkLabel" id="label2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="sqlexception|label2">Error _list:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">list</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="sqlexception|label3">_Description:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">description</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkScrolledWindow" id="scrolledwindow1">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="shadow_type">in</property>
+ <child>
+ <object class="GtkTextView" id="description">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="editable">False</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkScrolledWindow" id="scrolledwindow2">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="shadow_type">in</property>
+ <child>
+ <object class="GtkTreeView" id="list">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="model">liststore1</property>
+ <property name="headers_visible">False</property>
+ <property name="headers_clickable">False</property>
+ <property name="search_column">0</property>
+ <property name="show_expanders">False</property>
+ <child internal-child="selection">
+ <object class="GtkTreeSelection" id="treeview-selection1"/>
+ </child>
+ <child>
+ <object class="GtkTreeViewColumn" id="treeviewcolumn1">
+ <child>
+ <object class="GtkCellRendererPixbuf" id="cellrenderertext1"/>
+ <attributes>
+ <attribute name="pixbuf">0</attribute>
+ </attributes>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkTreeViewColumn" id="treeviewcolumn2">
+ <child>
+ <object class="GtkCellRendererText" id="cellrenderertext2"/>
+ <attributes>
+ <attribute name="text">1</attribute>
+ </attributes>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="-5">ok</action-widget>
+ </action-widgets>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+</interface>
diff --git a/dbaccess/uiconfig/ui/tableborderwindow.ui b/dbaccess/uiconfig/ui/tableborderwindow.ui
new file mode 100644
index 000000000..ec87715fc
--- /dev/null
+++ b/dbaccess/uiconfig/ui/tableborderwindow.ui
@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.36.0 -->
+<interface domain="dba">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkBox" id="TableBorderWindow">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkSeparator">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_top">3</property>
+ <property name="margin_bottom">3</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkPaned" id="splitter">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="orientation">vertical</property>
+ <property name="wide_handle">True</property>
+ <child>
+ <object class="GtkBox" id="editor">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="resize">True</property>
+ <property name="shrink">True</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="fielddesc">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="resize">True</property>
+ <property name="shrink">True</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+</interface>
diff --git a/dbaccess/uiconfig/ui/tabledesignrowmenu.ui b/dbaccess/uiconfig/ui/tabledesignrowmenu.ui
new file mode 100644
index 000000000..d17e60062
--- /dev/null
+++ b/dbaccess/uiconfig/ui/tabledesignrowmenu.ui
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.20.0 -->
+<interface domain="dba">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkMenu" id="menu">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkMenuItem" id="cut">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="tabledesignrowmenu|cut">Cu_t</property>
+ <property name="use_underline">True</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkMenuItem" id="copy">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="tabledesignrowmenu|copy">_Copy</property>
+ <property name="use_underline">True</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkMenuItem" id="paste">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="tabledesignrowmenu|paste">_Paste</property>
+ <property name="use-underline">True</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkMenuItem" id="delete">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="tabledesignrowmenu|delete">_Delete</property>
+ <property name="use-underline">True</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkMenuItem" id="insert">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="tabledesignrowmenu|insert">Insert Rows</property>
+ <property name="use-underline">True</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkSeparatorMenuItem" id="menuitem1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkCheckMenuItem" id="primarykey">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="tabledesignrowmenu|primarykey">Primary Key</property>
+ <property name="use-underline">True</property>
+ </object>
+ </child>
+ </object>
+</interface>
diff --git a/dbaccess/uiconfig/ui/tabledesignsavemodifieddialog.ui b/dbaccess/uiconfig/ui/tabledesignsavemodifieddialog.ui
new file mode 100644
index 000000000..ea0fdd5b0
--- /dev/null
+++ b/dbaccess/uiconfig/ui/tabledesignsavemodifieddialog.ui
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.18.3 -->
+<interface domain="dba">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkMessageDialog" id="TableDesignSaveModifiedDialog">
+ <property name="can_focus">False</property>
+ <property name="resizable">False</property>
+ <property name="modal">True</property>
+ <property name="type_hint">dialog</property>
+ <property name="skip_taskbar_hint">True</property>
+ <property name="message_type">question</property>
+ <property name="text" translatable="yes" context="tabledesignsavemodifieddialog|TableDesignSaveModifiedDialog">Do you want to save the changes?</property>
+ <property name="secondary_text" translatable="yes" context="tabledesignsavemodifieddialog|TableDesignSaveModifiedDialog">The table has been changed.</property>
+ <child internal-child="vbox">
+ <object class="GtkBox" id="messagedialog-vbox">
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox" id="messagedialog-action_area">
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkButton" id="no">
+ <property name="label" translatable="yes" context="stock">_No</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="yes">
+ <property name="label" translatable="yes" context="stock">_Yes</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="has_default">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="cancel">
+ <property name="label" translatable="yes" context="stock">_Cancel</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="-9">no</action-widget>
+ <action-widget response="-8">yes</action-widget>
+ <action-widget response="-6">cancel</action-widget>
+ </action-widgets>
+ </object>
+</interface>
diff --git a/dbaccess/uiconfig/ui/tablelistbox.ui b/dbaccess/uiconfig/ui/tablelistbox.ui
new file mode 100644
index 000000000..8484dcde4
--- /dev/null
+++ b/dbaccess/uiconfig/ui/tablelistbox.ui
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.36.0 -->
+<interface domain="dba">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkTreeStore" id="liststore1">
+ <columns>
+ <!-- column-name expander -->
+ <column type="GdkPixbuf"/>
+ <!-- column-name text -->
+ <column type="gchararray"/>
+ <!-- column-name id -->
+ <column type="gchararray"/>
+ </columns>
+ </object>
+ <object class="GtkBox" id="TableListBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="border_width">0</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkScrolledWindow">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="shadow_type">in</property>
+ <child>
+ <object class="GtkTreeView" id="treeview">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="model">liststore1</property>
+ <property name="headers_visible">False</property>
+ <property name="reorderable">True</property>
+ <property name="search_column">1</property>
+ <property name="show-expanders">False</property>
+ <child internal-child="selection">
+ <object class="GtkTreeSelection" id="Macro Library List-selection1"/>
+ </child>
+ <child>
+ <object class="GtkTreeViewColumn" id="treeviewcolumn2">
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkCellRendererPixbuf" id="cellrenderertext4"/>
+ <attributes>
+ <attribute name="pixbuf">0</attribute>
+ </attributes>
+ </child>
+ <child>
+ <object class="GtkCellRendererText" id="cellrenderertext2"/>
+ <attributes>
+ <attribute name="text">1</attribute>
+ </attributes>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+</interface>
diff --git a/dbaccess/uiconfig/ui/tablesfilterdialog.ui b/dbaccess/uiconfig/ui/tablesfilterdialog.ui
new file mode 100644
index 000000000..06e71b181
--- /dev/null
+++ b/dbaccess/uiconfig/ui/tablesfilterdialog.ui
@@ -0,0 +1,90 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface domain="dba">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkDialog" id="TablesFilterDialog">
+ <property name="can_focus">False</property>
+ <property name="border_width">6</property>
+ <property name="title" translatable="yes" context="tablesfilterdialog|TablesFilterDialog">Tables Filter</property>
+ <property name="resizable">False</property>
+ <property name="modal">True</property>
+ <property name="default_width">0</property>
+ <property name="default_height">0</property>
+ <property name="type_hint">dialog</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child internal-child="vbox">
+ <object class="GtkBox" id="dialog-vbox1">
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox" id="dialog-action_area1">
+ <property name="can_focus">False</property>
+ <property name="layout_style">end</property>
+ <child>
+ <object class="GtkButton" id="ok">
+ <property name="label" translatable="yes" context="stock">_OK</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="has_default">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="cancel">
+ <property name="label" translatable="yes" context="stock">_Cancel</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="help">
+ <property name="label" translatable="yes" context="stock">_Help</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ <property name="secondary">True</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="-5">ok</action-widget>
+ <action-widget response="-6">cancel</action-widget>
+ <action-widget response="-11">help</action-widget>
+ </action-widgets>
+ </object>
+</interface>
diff --git a/dbaccess/uiconfig/ui/tablesfilterpage.ui b/dbaccess/uiconfig/ui/tablesfilterpage.ui
new file mode 100644
index 000000000..1d7a082c3
--- /dev/null
+++ b/dbaccess/uiconfig/ui/tablesfilterpage.ui
@@ -0,0 +1,125 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface domain="dba">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkTreeStore" id="liststore2">
+ <columns>
+ <!-- column-name expander -->
+ <column type="GdkPixbuf"/>
+ <!-- column-name check1 -->
+ <column type="gboolean"/>
+ <!-- column-name text -->
+ <column type="gchararray"/>
+ <!-- column-name id -->
+ <column type="gchararray"/>
+ <!-- column-name checkvis1 -->
+ <column type="gboolean"/>
+ <!-- column-name checktri1 -->
+ <column type="gboolean"/>
+ <!-- column-name weight1 -->
+ <column type="gint"/>
+ </columns>
+ </object>
+ <object class="GtkFrame" id="TablesFilterPage">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid10">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="row_spacing">6</property>
+ <property name="column_spacing">18</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <child>
+ <object class="GtkLabel" id="label2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="tablesfilterpage|label2">Mark the tables that should be visible for the applications.</property>
+ <property name="wrap">True</property>
+ <property name="max_width_chars">56</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkScrolledWindow">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="shadow_type">in</property>
+ <child>
+ <object class="GtkTreeView" id="treeview">
+ <property name="width_request">-1</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="model">liststore2</property>
+ <property name="headers_visible">False</property>
+ <property name="search_column">2</property>
+ <property name="enable_tree_lines">True</property>
+ <property name="show_expanders">True</property>
+ <child internal-child="selection">
+ <object class="GtkTreeSelection" id="Macro Library List-selection2"/>
+ </child>
+ <child>
+ <object class="GtkTreeViewColumn" id="treeviewcolumn8">
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkCellRendererPixbuf" id="cellrenderertext5"/>
+ <attributes>
+ <attribute name="pixbuf">0</attribute>
+ </attributes>
+ </child>
+ <child>
+ <object class="GtkCellRendererToggle" id="cellrenderer5"/>
+ <attributes>
+ <attribute name="visible">4</attribute>
+ <attribute name="active">1</attribute>
+ <attribute name="inconsistent">5</attribute>
+ </attributes>
+ </child>
+ <child>
+ <object class="GtkCellRendererText" id="cellrenderertext6"/>
+ <attributes>
+ <attribute name="text">2</attribute>
+ <attribute name="weight">6</attribute>
+ </attributes>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="tablesfilterpage|label1">Tables and Table Filter</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+</interface>
diff --git a/dbaccess/uiconfig/ui/tablesjoindialog.ui b/dbaccess/uiconfig/ui/tablesjoindialog.ui
new file mode 100644
index 000000000..342eda62c
--- /dev/null
+++ b/dbaccess/uiconfig/ui/tablesjoindialog.ui
@@ -0,0 +1,271 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface domain="dba">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkTreeStore" id="liststore1">
+ <columns>
+ <!-- column-name expander -->
+ <column type="GdkPixbuf"/>
+ <!-- column-name text -->
+ <column type="gchararray"/>
+ <!-- column-name id -->
+ <column type="gchararray"/>
+ </columns>
+ </object>
+ <object class="GtkTreeStore" id="liststore2">
+ <columns>
+ <!-- column-name expander -->
+ <column type="GdkPixbuf"/>
+ <!-- column-name text -->
+ <column type="gchararray"/>
+ <!-- column-name id -->
+ <column type="gchararray"/>
+ <!-- column-name weight -->
+ <column type="gint"/>
+ </columns>
+ </object>
+ <object class="GtkDialog" id="TablesJoinDialog">
+ <property name="can_focus">False</property>
+ <property name="border_width">6</property>
+ <property name="resizable">False</property>
+ <property name="default_width">0</property>
+ <property name="default_height">0</property>
+ <property name="type_hint">dialog</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child internal-child="vbox">
+ <object class="GtkBox" id="dialog-vbox1">
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox" id="dialog-action_area1">
+ <property name="can_focus">False</property>
+ <property name="layout_style">end</property>
+ <child>
+ <object class="GtkButton" id="add">
+ <property name="label" translatable="yes" context="stock">_Add</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="has_default">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="close">
+ <property name="label" translatable="yes" context="stock">_Close</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="help">
+ <property name="label" translatable="yes" context="stock">_Help</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ <property name="secondary">True</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="row_spacing">6</property>
+ <child>
+ <object class="GtkRadioButton" id="tables">
+ <property name="label" translatable="yes" context="tablesjoindialog|tables">Tables</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="queries">
+ <property name="label" translatable="yes" context="tablesjoindialog|queries">Queries</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">tables</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkScrolledWindow">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="shadow_type">in</property>
+ <child>
+ <object class="GtkTreeView" id="tablelist">
+ <property name="width_request">-1</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="model">liststore2</property>
+ <property name="headers_visible">False</property>
+ <property name="search_column">1</property>
+ <property name="show_expanders">True</property>
+ <property name="enable_tree_lines">True</property>
+ <child internal-child="selection">
+ <object class="GtkTreeSelection" id="Macro Library List-selection2"/>
+ </child>
+ <child>
+ <object class="GtkTreeViewColumn" id="treeviewcolumn8">
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkCellRendererPixbuf" id="cellrenderertext5"/>
+ <attributes>
+ <attribute name="pixbuf">0</attribute>
+ </attributes>
+ </child>
+ <child>
+ <object class="GtkCellRendererText" id="cellrenderertext6"/>
+ <attributes>
+ <attribute name="text">1</attribute>
+ <attribute name="weight">3</attribute>
+ </attributes>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="title">
+ <property name="can_focus">False</property>
+ <property name="no_show_all">True</property>
+ <property name="label" translatable="yes" context="tablesjoindialog|title">Add Tables</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">4</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="alttitle">
+ <property name="can_focus">False</property>
+ <property name="no_show_all">True</property>
+ <property name="label" translatable="yes" context="tablesjoindialog|alttitle">Add Table or Query</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">5</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkScrolledWindow">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="shadow_type">in</property>
+ <child>
+ <object class="GtkTreeView" id="querylist">
+ <property name="width_request">-1</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="model">liststore1</property>
+ <property name="headers_visible">False</property>
+ <property name="search_column">1</property>
+ <property name="show_expanders">False</property>
+ <property name="enable_tree_lines">True</property>
+ <child internal-child="selection">
+ <object class="GtkTreeSelection" id="Macro Library List-selection3"/>
+ </child>
+ <child>
+ <object class="GtkTreeViewColumn" id="treeviewcolumn18">
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkCellRendererPixbuf" id="cellrenderertext15"/>
+ <attributes>
+ <attribute name="pixbuf">0</attribute>
+ </attributes>
+ </child>
+ <child>
+ <object class="GtkCellRendererText" id="cellrenderertext16"/>
+ <attributes>
+ <attribute name="text">1</attribute>
+ </attributes>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">3</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="101">add</action-widget>
+ <action-widget response="-7">close</action-widget>
+ <action-widget response="-11">help</action-widget>
+ </action-widgets>
+ </object>
+</interface>
diff --git a/dbaccess/uiconfig/ui/tabletitle.ui b/dbaccess/uiconfig/ui/tabletitle.ui
new file mode 100644
index 000000000..3e1275e36
--- /dev/null
+++ b/dbaccess/uiconfig/ui/tabletitle.ui
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.38.2 -->
+<interface domain="dba">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkBox" id="TableTitle">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkImage" id="image">
+ <property name="can-focus">False</property>
+ <property name="no-show-all">True</property>
+ <property name="icon-name">missing-image</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="events">GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_STRUCTURE_MASK</property>
+ <property name="hexpand">True</property>
+ <property name="label">label</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+</interface>
diff --git a/dbaccess/uiconfig/ui/taskwindow.ui b/dbaccess/uiconfig/ui/taskwindow.ui
new file mode 100644
index 000000000..e7c54cd56
--- /dev/null
+++ b/dbaccess/uiconfig/ui/taskwindow.ui
@@ -0,0 +1,174 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.36.0 -->
+<interface domain="dba">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkTreeStore" id="liststore1">
+ <columns>
+ <!-- column-name expander -->
+ <column type="GdkPixbuf"/>
+ <!-- column-name text -->
+ <column type="gchararray"/>
+ <!-- column-name id -->
+ <column type="gchararray"/>
+ </columns>
+ </object>
+ <object class="GtkBox" id="TaskWindow">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="border_width">12</property>
+ <property name="spacing">6</property>
+ <property name="homogeneous">True</property>
+ <child>
+ <object class="GtkScrolledWindow">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <child>
+ <object class="GtkTreeView" id="treeview">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="model">liststore1</property>
+ <property name="headers_visible">False</property>
+ <property name="search_column">1</property>
+ <property name="hover_selection">True</property>
+ <property name="enable_tree_lines">True</property>
+ <property name="activate_on_single_click">True</property>
+ <child internal-child="selection">
+ <object class="GtkTreeSelection" id="Macro Library List-selection1"/>
+ </child>
+ <child>
+ <object class="GtkTreeViewColumn" id="treeviewcolumn2">
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkCellRendererPixbuf" id="cellrenderertext4"/>
+ <attributes>
+ <attribute name="pixbuf">0</attribute>
+ </attributes>
+ </child>
+ <child>
+ <object class="GtkCellRendererText" id="cellrenderertext2"/>
+ <attributes>
+ <attribute name="text">1</attribute>
+ </attributes>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="column_spacing">6</property>
+ <child>
+ <object class="GtkSeparator" id="separator">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="row_spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="description">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="taskwindow|STR_DESCRIPTION">Description</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">helptext</property>
+ <property name="xalign">0</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkScrolledWindow">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="hscrollbar_policy">external</property>
+ <property name="vscrollbar_policy">external</property>
+ <child>
+ <object class="GtkTextView" id="helptext">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="editable">False</property>
+ <property name="wrap_mode">word</property>
+ <property name="cursor_visible">False</property>
+ <property name="accepts_tab">False</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="helptext-atkobject">
+ <property name="AtkObject::accessible-role">static</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+</interface>
diff --git a/dbaccess/uiconfig/ui/textconnectionsettings.ui b/dbaccess/uiconfig/ui/textconnectionsettings.ui
new file mode 100644
index 000000000..4d3e498a2
--- /dev/null
+++ b/dbaccess/uiconfig/ui/textconnectionsettings.ui
@@ -0,0 +1,105 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface domain="dba">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkDialog" id="TextConnectionSettingsDialog">
+ <property name="can_focus">False</property>
+ <property name="border_width">6</property>
+ <property name="title" translatable="yes" context="textconnectionsettings|TextConnectionSettingsDialog">Text Connection Settings</property>
+ <property name="resizable">False</property>
+ <property name="modal">True</property>
+ <property name="default_width">0</property>
+ <property name="default_height">0</property>
+ <property name="type_hint">dialog</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child internal-child="vbox">
+ <object class="GtkBox" id="dialog-vbox1">
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox" id="dialog-action_area1">
+ <property name="can_focus">False</property>
+ <property name="layout_style">end</property>
+ <child>
+ <object class="GtkButton" id="ok">
+ <property name="label" translatable="yes" context="stock">_OK</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="has_default">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="cancel">
+ <property name="label" translatable="yes" context="stock">_Cancel</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="help">
+ <property name="label" translatable="yes" context="stock">_Help</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ <property name="secondary">True</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="TextPageContainer">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="-5">ok</action-widget>
+ <action-widget response="-6">cancel</action-widget>
+ <action-widget response="-11">help</action-widget>
+ </action-widgets>
+ </object>
+</interface>
diff --git a/dbaccess/uiconfig/ui/textpage.ui b/dbaccess/uiconfig/ui/textpage.ui
new file mode 100644
index 000000000..e09028819
--- /dev/null
+++ b/dbaccess/uiconfig/ui/textpage.ui
@@ -0,0 +1,385 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface domain="dba">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkBox" id="TextPage">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="border_width">6</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkFrame" id="extensionframe">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="row_spacing">6</property>
+ <property name="column_spacing">12</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <child>
+ <object class="GtkRadioButton" id="textfile">
+ <property name="label" translatable="yes" context="textpage|textfile">Plain text files (*.txt)</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ <property name="width">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="csvfile">
+ <property name="label" translatable="yes" context="textpage|csvfile">Comma-separated value files (*.csv)</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">textfile</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ <property name="width">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="custom">
+ <property name="label" translatable="yes" context="textpage|custom">Custom:</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">textfile</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="extension">
+ <property name="visible">True</property>
+ <property name="sensitive">False</property>
+ <property name="can_focus">True</property>
+ <property name="vexpand">True</property>
+ <property name="truncate-multiline">True</property>
+ <property name="activates_default">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="example">
+ <property name="visible">True</property>
+ <property name="sensitive">False</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="textpage|example">Custom: *.abc</property>
+ </object>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="extensionheader">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="textpage|extensionheader">Specify the Type of Files You Want to Access</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFrame" id="formatframe">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="row_spacing">6</property>
+ <property name="column_spacing">12</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <child>
+ <object class="GtkCheckButton" id="containsheaders">
+ <property name="label" translatable="yes" context="textpage|containsheaders">_Text contains headers</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="hexpand">True</property>
+ <property name="use_underline">True</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">4</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="fieldlabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="textpage|fieldlabel">Field separator:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">fieldseparator</property>
+ <property name="xalign">1</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="textlabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="textpage|textlabel">Text separator:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">textseparator</property>
+ <property name="xalign">1</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="decimallabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="textpage|decimallabel">Decimal separator:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">decimalseparator</property>
+ <property name="xalign">1</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="thousandslabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="textpage|thousandslabel">Thousands separator:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">thousandsseparator</property>
+ <property name="xalign">1</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="fieldseparator">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="has_entry">True</property>
+ <child internal-child="entry">
+ <object class="GtkEntry" id="comboboxtext-entry2">
+ <property name="can_focus">True</property>
+ <property name="truncate-multiline">True</property>
+ <property name="activates_default">True</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="textseparator">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="has_entry">True</property>
+ <child internal-child="entry">
+ <object class="GtkEntry" id="comboboxtext-entry4">
+ <property name="can_focus">True</property>
+ <property name="truncate-multiline">True</property>
+ <property name="activates_default">True</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="decimalseparator">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="has_entry">True</property>
+ <items>
+ <item translatable="yes" context="textpage|decimalseparator">.</item>
+ <item translatable="yes" context="textpage|decimalseparator">,</item>
+ <item translatable="yes" context="textpage|decimalseparator">;</item>
+ <item translatable="yes" context="textpage|decimalseparator">:</item>
+ </items>
+ <child internal-child="entry">
+ <object class="GtkEntry" id="comboboxtext-entry6">
+ <property name="can_focus">True</property>
+ <property name="truncate-multiline">True</property>
+ <property name="activates_default">True</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="thousandsseparator">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="has_entry">True</property>
+ <items>
+ <item translatable="yes" context="textpage|thousandsseparator">.</item>
+ <item translatable="yes" context="textpage|thousandsseparator">,</item>
+ </items>
+ <child internal-child="entry">
+ <object class="GtkEntry" id="comboboxtext-entry8">
+ <property name="can_focus">True</property>
+ <property name="truncate-multiline">True</property>
+ <property name="activates_default">True</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">3</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="formatlabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="textpage|formatlabel">Row Format</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFrame" id="charsetframe">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <object class="GtkBox" id="box1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="spacing">12</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <child>
+ <object class="GtkLabel" id="charsetlabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="label" translatable="yes" context="textpage|charsetlabel">_Character set:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">charset</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="charset">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="charsetheader">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="textpage|charsetheader">Data Conversion</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+</interface>
diff --git a/dbaccess/uiconfig/ui/titlewindow.ui b/dbaccess/uiconfig/ui/titlewindow.ui
new file mode 100644
index 000000000..a622cac68
--- /dev/null
+++ b/dbaccess/uiconfig/ui/titlewindow.ui
@@ -0,0 +1,90 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.36.0 -->
+<interface domain="dba">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkBox" id="TitleWindow">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="vexpand">True</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkScrolledWindow">
+ <property name="name">monoborder</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hscrollbar_policy">never</property>
+ <property name="vscrollbar_policy">never</property>
+ <property name="shadow_type">in</property>
+ <child>
+ <object class="GtkViewport">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="border_width">1</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="titleparent">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin-start">1</property>
+ <property name="margin-end">1</property>
+ <child>
+ <object class="GtkLabel" id="title">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">0</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <property name="margin-bottom">6</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="box">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+</interface>
diff --git a/dbaccess/uiconfig/ui/typeselectpage.ui b/dbaccess/uiconfig/ui/typeselectpage.ui
new file mode 100644
index 000000000..8104ddb7a
--- /dev/null
+++ b/dbaccess/uiconfig/ui/typeselectpage.ui
@@ -0,0 +1,208 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface domain="dba">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkAdjustment" id="adjustment1">
+ <property name="upper">100</property>
+ <property name="step_increment">1</property>
+ <property name="page_increment">10</property>
+ </object>
+ <object class="GtkTreeStore" id="liststore1">
+ <columns>
+ <!-- column-name image -->
+ <column type="GdkPixbuf"/>
+ <!-- column-name text -->
+ <column type="gchararray"/>
+ <!-- column-name id -->
+ <column type="gchararray"/>
+ </columns>
+ </object>
+ <object class="GtkBox" id="TypeSelect">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="border_width">6</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkScrolledWindow">
+ <property name="width_request">150</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="vexpand">True</property>
+ <property name="shadow_type">in</property>
+ <child>
+ <object class="GtkTreeView" id="columnnames">
+ <property name="width_request">150</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="vexpand">True</property>
+ <property name="model">liststore1</property>
+ <property name="headers_visible">False</property>
+ <property name="search_column">1</property>
+ <property name="show_expanders">False</property>
+ <child internal-child="selection">
+ <object class="GtkTreeSelection" id="Macro Library List-selection2"/>
+ </child>
+ <child>
+ <object class="GtkTreeViewColumn" id="treeviewcolumn5">
+ <property name="resizable">True</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkCellRendererPixbuf" id="cellrenderertext1"/>
+ <attributes>
+ <attribute name="pixbuf">0</attribute>
+ </attributes>
+ </child>
+ <child>
+ <object class="GtkCellRendererText" id="cellrenderer4"/>
+ <attributes>
+ <attribute name="text">1</attribute>
+ </attributes>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="box1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkFrame" id="frame1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <object class="GtkBox" id="control_container">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="orientation">vertical</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="columns">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="typeselectpage|columns">Column Information</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFrame" id="frame2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="row_spacing">6</property>
+ <property name="column_spacing">12</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <child>
+ <object class="GtkLabel" id="autolabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="label" translatable="yes" context="typeselectpage|autolabel">Lines (ma_x.):</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">auto</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="autobutton">
+ <property name="label" translatable="yes" context="typeselectpage|autobutton">_Auto</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_underline">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="auto">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="activates_default">True</property>
+ <property name="truncate-multiline">True</property>
+ <property name="adjustment">adjustment1</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="autotype">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="typeselectpage|autotype">Automatic Type Recognition</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+</interface>
diff --git a/dbaccess/uiconfig/ui/useradmindialog.ui b/dbaccess/uiconfig/ui/useradmindialog.ui
new file mode 100644
index 000000000..4b68795c4
--- /dev/null
+++ b/dbaccess/uiconfig/ui/useradmindialog.ui
@@ -0,0 +1,161 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface domain="dba">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkDialog" id="UserAdminDialog">
+ <property name="can_focus">False</property>
+ <property name="border_width">6</property>
+ <property name="title" translatable="yes" context="useradmindialog|UserAdminDialog">User Administration</property>
+ <property name="resizable">False</property>
+ <property name="modal">True</property>
+ <property name="default_width">0</property>
+ <property name="default_height">0</property>
+ <property name="type_hint">dialog</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child internal-child="vbox">
+ <object class="GtkBox" id="dialog-vbox1">
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox" id="dialog-action_area1">
+ <property name="can_focus">False</property>
+ <property name="layout_style">end</property>
+ <child>
+ <object class="GtkButton" id="reset">
+ <property name="label" translatable="yes" context="stock">_Reset</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="ok">
+ <property name="label" translatable="yes" context="stock">_OK</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="has_default">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="cancel">
+ <property name="label" translatable="yes" context="stock">_Cancel</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="help">
+ <property name="label" translatable="yes" context="stock">_Help</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">3</property>
+ <property name="secondary">True</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkNotebook" id="tabcontrol">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="scrollable">True</property>
+ <property name="enable_popup">True</property>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel" id="settings">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="useradmindialog|settings">User Settings</property>
+ <property name="xalign">0.5</property>
+ </object>
+ <packing>
+ <property name="tab_fill">False</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="101">reset</action-widget>
+ <action-widget response="-5">ok</action-widget>
+ <action-widget response="-6">cancel</action-widget>
+ <action-widget response="-11">help</action-widget>
+ </action-widgets>
+ </object>
+</interface>
diff --git a/dbaccess/uiconfig/ui/useradminpage.ui b/dbaccess/uiconfig/ui/useradminpage.ui
new file mode 100644
index 000000000..4d649ea90
--- /dev/null
+++ b/dbaccess/uiconfig/ui/useradminpage.ui
@@ -0,0 +1,183 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface domain="dba">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkBox" id="UserAdminPage">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="border_width">6</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkFrame" id="frame1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <object class="GtkBox" id="box1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <property name="margin-top">6</property>
+ <child>
+ <object class="GtkBox" id="box2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkLabel" id="label3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="hexpand">True</property>
+ <property name="label" translatable="yes" context="useradminpage|label3">Us_er:</property>
+ <property name="use_underline">True</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="user">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="box3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkButton" id="add">
+ <property name="label" translatable="yes" context="useradminpage|add">_Add User...</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="changepass">
+ <property name="label" translatable="yes" context="useradminpage|changepass">Change _Password...</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="delete">
+ <property name="label" translatable="yes" context="useradminpage|delete">_Delete User...</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="useradminpage|label1">User Selection</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFrame" id="frame2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <object class="GtkBox" id="table">
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="visible">True</property>
+ <property name="height_request">150</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="margin-top">6</property>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="useradminpage|label2">Access Rights for Selected User</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+</interface>
diff --git a/dbaccess/uiconfig/ui/userdetailspage.ui b/dbaccess/uiconfig/ui/userdetailspage.ui
new file mode 100644
index 000000000..c0916ce09
--- /dev/null
+++ b/dbaccess/uiconfig/ui/userdetailspage.ui
@@ -0,0 +1,225 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface domain="dba">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkAdjustment" id="adjustment1">
+ <property name="upper">65535</property>
+ <property name="step_increment">1</property>
+ <property name="page_increment">10</property>
+ </object>
+ <object class="GtkBox" id="UserDetailsPage">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="border_width">6</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkFrame" id="frame2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="row_spacing">6</property>
+ <property name="column_spacing">12</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <child>
+ <object class="GtkLabel" id="hostnameft">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="label" translatable="yes" context="userdetailspage|hostnameft">_Host name:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">hostname</property>
+ <property name="ellipsize">end</property>
+ <property name="xalign">1</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="portnumberft">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="label" translatable="yes" context="userdetailspage|portnumberft">_Port number:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">portnumber</property>
+ <property name="xalign">1</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="hostname">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="truncate-multiline">True</property>
+ <property name="activates_default">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="portnumber">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="activates_default">True</property>
+ <property name="truncate-multiline">True</property>
+ <property name="adjustment">adjustment1</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="usecatalog">
+ <property name="label" translatable="yes" context="userdetailspage|usecatalog">_Use catalog</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">3</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="optionslabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="label" translatable="yes" context="userdetailspage|optionslabel">_Driver settings:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">options</property>
+ <property name="xalign">1</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="options">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="truncate-multiline">True</property>
+ <property name="activates_default">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="userdetailspage|label1">Connection Settings</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFrame" id="frame1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <object class="GtkBox" id="box1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="spacing">12</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <child>
+ <object class="GtkLabel" id="charsetlabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="userdetailspage|charsetlabel">_Character set:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">charset</property>
+ <property name="xalign">1</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="charset">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="charsetheader">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="userdetailspage|charsetheader">Data Conversion</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <object class="GtkSizeGroup" id="sizegroup1">
+ <widgets>
+ <widget name="hostnameft"/>
+ <widget name="portnumberft"/>
+ <widget name="optionslabel"/>
+ <widget name="charsetlabel"/>
+ </widgets>
+ </object>
+</interface>
diff --git a/dbaccess/util/dba.component b/dbaccess/util/dba.component
new file mode 100644
index 000000000..e41165bf1
--- /dev/null
+++ b/dbaccess/util/dba.component
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ -->
+
+<component loader="com.sun.star.loader.SharedLibrary" environment="@CPPU_ENV@"
+ xmlns="http://openoffice.org/2010/uno-components">
+ <implementation name="com.sun.star.comp.dbaccess.DatabaseDataProvider"
+ constructor="com_sun_star_comp_dbaccess_DatabaseDataProvider_get_implementation">
+ <service name="com.sun.star.chart2.data.DatabaseDataProvider"/>
+ </implementation>
+ <implementation name="com.sun.star.comp.dba.DataAccessDescriptorFactory"
+ constructor="com_sun_star_comp_dba_DataAccessDescriptorFactory"
+ single-instance="true">
+ <singleton name="com.sun.star.sdb.DataAccessDescriptorFactory"/>
+ </implementation>
+ <implementation name="com.sun.star.comp.dba.OCommandDefinition"
+ constructor="com_sun_star_comp_dba_OCommandDefinition">
+ <service name="com.sun.star.sdb.CommandDefinition"/>
+ <service name="com.sun.star.sdb.QueryDefinition"/>
+ </implementation>
+ <implementation name="com.sun.star.comp.dba.OComponentDefinition"
+ constructor="com_sun_star_comp_dba_OComponentDefinition">
+ <service name="com.sun.star.sdb.TableDefinition"/>
+ </implementation>
+ <implementation name="com.sun.star.comp.dba.ODatabaseContext"
+ constructor="com_sun_star_comp_dba_ODatabaseContext_get_implementation" single-instance="true">
+ <service name="com.sun.star.sdb.DatabaseContext"/>
+ </implementation>
+ <implementation name="com.sun.star.comp.dba.ODatabaseDocument"
+ constructor="com_sun_star_comp_dba_ODatabaseDocument">
+ <service name="com.sun.star.document.OfficeDocument"/>
+ <service name="com.sun.star.sdb.OfficeDatabaseDocument"/>
+ </implementation>
+ <implementation name="com.sun.star.comp.dba.ODatabaseSource"
+ constructor="com_sun_star_comp_dba_ODatabaseSource">
+ <service name="com.sun.star.sdb.DataSource"/>
+ <service name="com.sun.star.sdb.DocumentDataSource"/>
+ </implementation>
+ <implementation name="com.sun.star.comp.dba.ORowSet"
+ constructor="com_sun_star_comp_dba_ORowSet_get_implementation">
+ <service name="com.sun.star.sdb.ResultSet"/>
+ <service name="com.sun.star.sdb.RowSet"/>
+ <service name="com.sun.star.sdbc.ResultSet"/>
+ <service name="com.sun.star.sdbc.RowSet"/>
+ <service name="com.sun.star.sdbcx.ResultSet"/>
+ </implementation>
+</component>
diff --git a/dbaccess/util/dbu.component b/dbaccess/util/dbu.component
new file mode 100644
index 000000000..4c131dacd
--- /dev/null
+++ b/dbaccess/util/dbu.component
@@ -0,0 +1,130 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ -->
+
+<component loader="com.sun.star.loader.SharedLibrary" environment="@CPPU_ENV@"
+ xmlns="http://openoffice.org/2010/uno-components">
+ <implementation name="com.sun.star.comp.dbaccess.DatabaseInteractionHandler"
+ constructor="com_sun_star_comp_dbaccess_DatabaseInteractionHandler_get_implementation">
+ <service name="com.sun.star.sdb.DatabaseInteractionHandler"/>
+ </implementation>
+ <implementation name="com.sun.star.comp.dbaccess.LegacyInteractionHandler"
+ constructor="com_sun_star_comp_dbaccess_LegacyInteractionHandler_get_implementation">
+ <service name="com.sun.star.sdb.InteractionHandler"/>
+ </implementation>
+ <implementation
+ name="com.sun.star.comp.dbaccess.OTextConnectionSettingsDialog"
+ constructor="com_sun_star_comp_dbaccess_OTextConnectionSettingsDialog_get_implementation">
+ <service name="com.sun.star.sdb.TextConnectionSettings"/>
+ </implementation>
+ <implementation name="com.sun.star.comp.dbu.OColumnControl"
+ constructor="com_sun_star_comp_dbu_OColumnControl_get_implementation">
+ <service name="com.sun.star.sdb.ColumnDescriptorControl"/>
+ </implementation>
+ <implementation name="com.sun.star.comp.dbu.OColumnControlModel"
+ constructor="com_sun_star_comp_dbu_OColumnControlModel_get_implementation">
+ <service name="com.sun.star.sdb.ColumnDescriptorControlModel"/>
+ </implementation>
+ <implementation name="com.sun.star.comp.dbu.SbaXGridControl"
+ constructor="com_sun_star_comp_dbu_SbaXGridControl_get_implementation">
+ <service name="com.sun.star.form.control.GridControl"/>
+ <service name="com.sun.star.form.control.InteractionGridControl"/>
+ </implementation>
+ <implementation name="com.sun.star.comp.sdb.DirectSQLDialog"
+ constructor="com_sun_star_comp_sdb_DirectSQLDialog_get_implementation">
+ <service name="org.openoffice.comp.dbu.DirectSqlDialog"/>
+ </implementation>
+ <implementation name="com.sun.star.uno.comp.sdb.RowsetFilterDialog"
+ constructor="com_sun_star_uno_comp_sdb_RowsetFilterDialog_get_implementation">
+ <service name="com.sun.star.sdb.FilterDialog"/>
+ </implementation>
+ <implementation name="com.sun.star.uno.comp.sdb.RowsetOrderDialog"
+ constructor="com_sun_star_uno_comp_sdb_RowsetOrderDialog_get_implementation">
+ <service name="com.sun.star.sdb.OrderDialog"/>
+ </implementation>
+ <implementation name="org.openoffice.comp.dbu.CopyTableWizard"
+ constructor="org_openoffice_comp_dbu_CopyTableWizard_get_implementation">
+ <service name="com.sun.star.sdb.application.CopyTableWizard"/>
+ </implementation>
+ <implementation name="org.openoffice.comp.dbu.DBContentLoader"
+ constructor="org_openoffice_comp_dbu_DBContentLoader_get_implementation">
+ <service name="com.sun.star.frame.FrameLoader"/>
+ <service name="com.sun.star.sdb.ContentLoader"/>
+ </implementation>
+ <implementation name="org.openoffice.comp.dbu.OAdvancedSettingsDialog"
+ constructor="org_openoffice_comp_dbu_OAdvancedSettingsDialog_get_implementation">
+ <service name="com.sun.star.sdb.AdvancedDatabaseSettingsDialog"/>
+ </implementation>
+ <implementation name="org.openoffice.comp.dbu.OApplicationController"
+ constructor="org_openoffice_comp_dbu_OApplicationController_get_implementation">
+ <service name="com.sun.star.sdb.application.DefaultViewController"/>
+ </implementation>
+ <implementation name="org.openoffice.comp.dbu.ODBTypeWizDialog"
+ constructor="org_openoffice_comp_dbu_ODBTypeWizDialog_get_implementation">
+ <service name="com.sun.star.sdb.DataSourceTypeChangeDialog"/>
+ </implementation>
+ <implementation name="org.openoffice.comp.dbu.ODBTypeWizDialogSetup"
+ constructor="org_openoffice_comp_dbu_ODBTypeWizDialogSetup_get_implementation">
+ <service name="com.sun.star.sdb.DatabaseWizardDialog"/>
+ </implementation>
+ <implementation
+ name="org.openoffice.comp.dbu.ODatasourceAdministrationDialog"
+ constructor="org_openoffice_comp_dbu_ODatasourceAdministrationDialog_get_implementation">
+ <service name="com.sun.star.sdb.DatasourceAdministrationDialog"/>
+ </implementation>
+ <implementation name="org.openoffice.comp.dbu.ODatasourceBrowser"
+ constructor="org_openoffice_comp_dbu_ODatasourceBrowser_get_implementation">
+ <service name="com.sun.star.sdb.DataSourceBrowser"/>
+ </implementation>
+ <implementation name="org.openoffice.comp.dbu.OFormGridView"
+ constructor="org_openoffice_comp_dbu_OFormGridView_get_implementation">
+ <service name="com.sun.star.sdb.FormGridView"/>
+ </implementation>
+ <implementation name="org.openoffice.comp.dbu.OQueryDesign"
+ constructor="org_openoffice_comp_dbu_OQueryDesign_get_implementation">
+ <service name="com.sun.star.sdb.QueryDesign"/>
+ </implementation>
+ <implementation name="org.openoffice.comp.dbu.ORelationDesign"
+ constructor="org_openoffice_comp_dbu_ORelationDesign_get_implementation">
+ <service name="com.sun.star.sdb.RelationDesign"/>
+ </implementation>
+ <implementation name="org.openoffice.comp.dbu.OSQLMessageDialog"
+ constructor="org_openoffice_comp_dbu_OSQLMessageDialog_get_implementation">
+ <service name="com.sun.star.sdb.ErrorMessageDialog"/>
+ </implementation>
+ <implementation name="org.openoffice.comp.dbu.OTableDesign"
+ constructor="org_openoffice_comp_dbu_OTableDesign_get_implementation">
+ <service name="com.sun.star.sdb.TableDesign"/>
+ </implementation>
+ <implementation name="org.openoffice.comp.dbu.OTableFilterDialog"
+ constructor="org_openoffice_comp_dbu_OTableFilterDialog_get_implementation">
+ <service name="com.sun.star.sdb.TableFilterDialog"/>
+ </implementation>
+ <implementation name="org.openoffice.comp.dbu.OUserSettingsDialog"
+ constructor="org_openoffice_comp_dbu_OUserSettingsDialog_get_implementation">
+ <service name="com.sun.star.sdb.UserAdministrationDialog"/>
+ </implementation>
+ <implementation name="org.openoffice.comp.dbu.OViewDesign"
+ constructor="org_openoffice_comp_dbu_OViewDesign_get_implementation">
+ <service name="com.sun.star.sdb.ViewDesign"/>
+ </implementation>
+ <implementation name="org.libreoffice.comp.dbu.LimitBoxController"
+ constructor="org_libreoffice_comp_dbu_LimitBoxController_get_implementation">
+ <service name="com.sun.star.frame.ToolbarController"/>
+ </implementation>
+</component>
diff --git a/dbaccess/util/sdbt.component b/dbaccess/util/sdbt.component
new file mode 100644
index 000000000..e0425967d
--- /dev/null
+++ b/dbaccess/util/sdbt.component
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ -->
+
+<component loader="com.sun.star.loader.SharedLibrary" environment="@CPPU_ENV@"
+ xmlns="http://openoffice.org/2010/uno-components">
+ <implementation name="com.sun.star.comp.dbaccess.ConnectionTools"
+ constructor="com_sun_star_comp_dbaccess_ConnectionTools_get_implementation">
+ <service name="com.sun.star.sdb.tools.ConnectionTools"/>
+ </implementation>
+</component>
diff --git a/dbaccess/win32/source/odbcconfig/odbcconfig.cxx b/dbaccess/win32/source/odbcconfig/odbcconfig.cxx
new file mode 100644
index 000000000..0cc48725c
--- /dev/null
+++ b/dbaccess/win32/source/odbcconfig/odbcconfig.cxx
@@ -0,0 +1,111 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#if !defined WIN32_LEAN_AND_MEAN
+# define WIN32_LEAN_AND_MEAN
+#endif
+#include <windows.h>
+#include <odbcinst.h>
+
+// displays the error text for the last error (GetLastError), and returns this error value
+static int displayLastError()
+{
+ DWORD dwError = GetLastError();
+
+ LPVOID lpMsgBuf = nullptr;
+ FormatMessageW(
+ FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
+ nullptr,
+ dwError,
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
+ reinterpret_cast<LPWSTR>(&lpMsgBuf),
+ 0,
+ nullptr
+ );
+
+ // Display the string.
+ MessageBoxW( nullptr, static_cast<LPCWSTR>(lpMsgBuf), nullptr, MB_OK | MB_ICONERROR );
+
+ // Free the buffer.
+ HeapFree( GetProcessHeap(), 0, lpMsgBuf );
+
+ return dwError;
+}
+
+/** registers the window class for our application's main window
+*/
+static bool registerWindowClass( HINSTANCE _hAppInstance )
+{
+ WNDCLASSEXW wcx;
+
+ wcx.cbSize = sizeof(wcx); // size of structure
+ wcx.style = CS_HREDRAW | CS_VREDRAW; // redraw if size changes
+ wcx.lpfnWndProc = DefWindowProcW; // points to window procedure
+ wcx.cbClsExtra = 0; // no extra class memory
+ wcx.cbWndExtra = 0; // no extra window memory
+ wcx.hInstance = _hAppInstance; // handle to instance
+ wcx.hIcon = nullptr; // predefined app. icon
+ wcx.hCursor = nullptr; // predefined arrow
+ wcx.hbrBackground = nullptr; // no background brush
+ wcx.lpszMenuName = nullptr; // name of menu resource
+ wcx.lpszClassName = L"ODBCConfigMainClass"; // name of window class
+ wcx.hIconSm = nullptr; // small class icon
+
+ return ( !!RegisterClassExW( &wcx ) );
+}
+
+/// initializes the application instances
+static HWND initInstance( HINSTANCE _hAppInstance )
+{
+ HWND hWindow = CreateWindowW(
+ L"ODBCConfigMainClass", // name of window class
+ L"ODBC Config Wrapper", // title-bar string
+ WS_OVERLAPPEDWINDOW, // top-level window
+ CW_USEDEFAULT, // default horizontal position
+ CW_USEDEFAULT, // default vertical position
+ CW_USEDEFAULT, // default width
+ CW_USEDEFAULT, // default height
+ nullptr, // no owner window
+ nullptr, // use class menu
+ _hAppInstance, // handle to application instance
+ nullptr); // no window-creation data
+
+ // don't show the window, we only need it as parent handle for the
+ // SQLManageDataSources function
+ return hWindow;
+}
+
+// main window function
+extern "C" int APIENTRY wWinMain( HINSTANCE _hAppInstance, HINSTANCE, LPWSTR, int )
+{
+ if ( !registerWindowClass( _hAppInstance ) )
+ return FALSE;
+
+ HWND hAppWindow = initInstance( _hAppInstance );
+ if ( !IsWindow( hAppWindow ) )
+ return displayLastError();
+
+ if (!SQLManageDataSources(hAppWindow))
+ return displayLastError();
+
+ return 0;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */