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