summaryrefslogtreecommitdiffstats
path: root/dbaccess/source/ui
diff options
context:
space:
mode:
Diffstat (limited to 'dbaccess/source/ui')
-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
360 files changed, 98972 insertions, 0 deletions
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: */