/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
namespace
{
OUString lcl_getSelectedDataSource( const weld::ComboBox& dataSourceCombo )
{
OUString selectedDataSource = dataSourceCombo.get_active_text(); if (dataSourceCombo.find_text(selectedDataSource) == -1)
{ // none of the pre-selected entries -> assume a path to a database document
OFileNotation aFileNotation( selectedDataSource, OFileNotation::N_SYSTEM );
selectedDataSource = aFileNotation.get( OFileNotation::N_URL );
} return selectedDataSource;
}
// = IAssignmentData
class IAssignmentData
{ public: virtual ~IAssignmentData();
/// the data source to use for the address book virtual OUString getDatasourceName() const = 0;
/// the command to use for the address book virtual OUString getCommand() const = 0;
/// checks whether or not there is an assignment for a given logical field virtualbool hasFieldAssignment(const OUString& _rLogicalName) = 0; /// retrieves the assignment for a given logical field virtual OUString getFieldAssignment(const OUString& _rLogicalName) = 0;
/// set the assignment for a given logical field virtualvoid setFieldAssignment(const OUString& _rLogicalName, const OUString& _rAssignment) = 0;
void AssignmentPersistentData::setFieldAssignment(const OUString& _rLogicalName, const OUString& _rAssignment)
{ if (_rAssignment.isEmpty())
{ if (hasFieldAssignment(_rLogicalName))
{ // the assignment exists but it should be reset
clearFieldAssignment(_rLogicalName);
} return;
}
// just set the new value bool bSuccess =
SetSetProperties(sDescriptionNodePath, aNewFieldDescription);
DBG_ASSERT(bSuccess, "AssignmentPersistentData::setFieldAssignment: could not commit the changes a field!");
}
void AssignmentPersistentData::clearFieldAssignment(const OUString& _rLogicalName)
{ if (!hasFieldAssignment(_rLogicalName)) // nothing to do return;
/// when working transient, we need the data source
Reference< XDataSource >
m_xTransientDataSource; /// current scroll pos in the field list
sal_Int32 nFieldScrollPos; /// indicates that we've an odd field number. This member is for efficiency only, it's redundant. bool bOddFieldNumber : 1; /// indicates that we're working with the real persistent configuration bool bWorkingPersistent : 1;
/// the strings to use as labels for the field selection listboxes
std::vector<OUString> aFieldLabels; // the current field assignment
std::vector<OUString> aFieldAssignments; /// the logical field names
std::vector<OUString> aLogicalFieldNames;
// for the moment, we have a hard coded list of all known fields. // A better solution would be to store all known field translations in the configuration, which could be // extensible by the user in an arbitrary way. // But for the moment we need a quick solution ... // (the main thing would be to store the translations to use here in the user interface, besides that, the code // should be adjustable with a rather small effort.)
// force an even number of known fields
m_pImpl->bOddFieldNumber = (m_pImpl->aFieldLabels.size() % 2) != 0; if (m_pImpl->bOddFieldNumber)
m_pImpl->aFieldLabels.emplace_back();
// limit the scrollbar range accordingly
sal_Int32 nOverallFieldPairs = m_pImpl->aFieldLabels.size() / 2;
m_xFieldScroller->vadjustment_configure(0, 0, nOverallFieldPairs,
1, FIELD_PAIRS_VISIBLE - 1, FIELD_PAIRS_VISIBLE);
// reset the current field assignments
m_pImpl->aFieldAssignments.resize(m_pImpl->aFieldLabels.size()); // (empty strings mean "no assignment")
for (autoconst& logicalFieldName : m_pImpl->aLogicalFieldNames)
{ if ( m_pImpl->pConfigData->hasFieldAssignment(logicalFieldName) )
{ // the user gave us an assignment for this field
pPair->ProgrammaticName = logicalFieldName;
pPair->Alias = m_pImpl->pConfigData->getFieldAssignment(logicalFieldName);
++pPair;
}
}
m_xDatasource->set_entry_text(sName);
m_xTable->set_entry_text(m_pImpl->pConfigData->getCommand()); // we ignore the CommandType: only tables are supported
// the logical names for the fields // AddressBookSourceDialog::loadConfiguration: inconsistence between field names and field assignments!
assert(m_pImpl->aLogicalFieldNames.size() == m_pImpl->aFieldAssignments.size());
auto aAssignment = m_pImpl->aFieldAssignments.begin(); for (autoconst& logicalFieldName : m_pImpl->aLogicalFieldNames)
{
*aAssignment = m_pImpl->pConfigData->getFieldAssignment(logicalFieldName);
++aAssignment;
}
}
void AddressBookSourceDialog::initializeDatasources()
{ if (!m_xDatabaseContext.is())
{
DBG_ASSERT(m_xORB.is(), "AddressBookSourceDialog::initializeDatasources: no service factory!"); if (!m_xORB.is()) return;
// fill the datasources listbox try
{ const css::uno::Sequence<OUString> aElementNames = m_xDatabaseContext->getElementNames(); for (const OUString& rDatasourceName : aElementNames)
m_xDatasource->append_text(rDatasourceName);
} catch(Exception&)
{
TOOLS_WARN_EXCEPTION( "svtools", "AddressBookSourceDialog::initializeDatasources: caught an exception while asking for the data source names!");
}
}
void AddressBookSourceDialog::resetTables()
{ if (!m_xDatabaseContext.is()) return;
weld::WaitObject aWaitCursor(m_xDialog.get());
// no matter what we do here, we handled the currently selected data source (no matter if successful or not)
m_xDatasource->save_value();
// create an interaction handler (may be needed for connecting)
Reference< XInteractionHandler > xHandler; try
{
xHandler.set(
InteractionHandler::createWithParent(m_xORB, m_xDialog->GetXWindow()),
UNO_QUERY_THROW );
} catch(const Exception&) { } if (!xHandler.is())
{
ShowServiceNotAvailableError(m_xDialog.get(), u"com.sun.star.task.InteractionHandler", true); return;
}
// the currently selected table
OUString sOldTable = m_xTable->get_active_text();
m_xTable->clear();
m_xCurrentDatasourceTables= nullptr;
// get the tables of the connection
Sequence< OUString > aTableNames;
Any aException; try
{
Reference< XCompletedConnection > xDS; if ( m_pImpl->bWorkingPersistent )
{
OUString sSelectedDS = lcl_getSelectedDataSource(*m_xDatasource);
// get the data source the user has chosen and let it build a connection
INetURLObject aURL( sSelectedDS ); if ( aURL.GetProtocol() != INetProtocol::NotValid || m_xDatabaseContext->hasByName(sSelectedDS) )
m_xDatabaseContext->getByName( sSelectedDS ) >>= xDS;
} else
{
xDS.set(m_pImpl->m_xTransientDataSource, css::uno::UNO_QUERY);
}
// build the connection
Reference< XConnection > xConn; if (xDS.is())
xConn = xDS->connectWithCompletion(xHandler);
// get the table names
Reference< XTablesSupplier > xSupplTables(xConn, UNO_QUERY); if (xSupplTables.is())
{
m_xCurrentDatasourceTables = xSupplTables->getTables(); if (m_xCurrentDatasourceTables.is())
aTableNames = m_xCurrentDatasourceTables->getElementNames();
}
} catch(const SQLContext& e) { aException <<= e; } catch(const SQLWarning& e) { aException <<= e; } catch(const SQLException& e) { aException <<= e; } catch(Exception&)
{
OSL_FAIL("AddressBookSourceDialog::resetTables: could not retrieve the table!");
}
if (aException.hasValue())
{
Reference< XInteractionRequest > xRequest = new OInteractionRequest(aException); try
{
xHandler->handle(xRequest);
} catch(Exception&) { } return;
}
bool bKnowOldTable = false; // fill the table list for (const OUString& rTableName : aTableNames)
{
m_xTable->append_text(rTableName); if (rTableName == sOldTable)
bKnowOldTable = true;
}
// set the old table, if the new data source knows a table with this name, too. Else reset the tables edit field. if (!bKnowOldTable)
sOldTable.clear();
m_xTable->set_entry_text(sOldTable);
// the one entry for "no selection"
pListbox->append_text(m_sNoFieldSelection); // as it's entry data, set the index of the list box in our array
pListbox->set_id(0, OUString::number(i));
// the field names for (const OUString& rColumnName : aColumnNames)
pListbox->append_text(rColumnName);
if (!aInitialSelection->isEmpty() && (aColumnNameSet.end() != aColumnNameSet.find(*aInitialSelection))) // we can select the entry as specified in our field assignment array
pListbox->set_active_text(*aInitialSelection); else // try to restore the selection if (aColumnNameSet.end() != aColumnNameSet.find(sSaveSelection)) // the old selection is a valid column name
pListbox->set_active_text(sSaveSelection); else // select the <none> entry
pListbox->set_active(0);
}
// adjust m_pImpl->aFieldAssignments for (auto & fieldAssignment : m_pImpl->aFieldAssignments) if (!fieldAssignment.isEmpty()) if (aColumnNameSet.end() == aColumnNameSet.find(fieldAssignment))
fieldAssignment.clear();
}
IMPL_LINK(AddressBookSourceDialog, OnFieldSelect, weld::ComboBox&, rListbox, void)
{ // the index of the affected list box in our array
sal_Int32 nListBoxIndex = rListbox.get_id(0).toInt32();
DBG_ASSERT(nListBoxIndex >= 0 && nListBoxIndex < FIELD_CONTROLS_VISIBLE, "AddressBookSourceDialog::OnFieldScroll: invalid list box entry!");
// update the array where we remember the field selections if (0 == rListbox.get_active()) // it's the "no field selection" entry
m_pImpl->aFieldAssignments[m_pImpl->nFieldScrollPos * 2 + nListBoxIndex].clear(); else // it's a regular field entry
m_pImpl->aFieldAssignments[m_pImpl->nFieldScrollPos * 2 + nListBoxIndex] = rListbox.get_active_text();
}
void AddressBookSourceDialog::implScrollFields(sal_Int32 _nPos, bool _bAdjustFocus, bool _bAdjustScrollbar)
{ if (_nPos == m_pImpl->nFieldScrollPos) // nothing to do return;
// loop through our field control rows and do some adjustments // for the new texts auto pLeftLabelControl = m_pImpl->pFieldLabels.begin(); auto pRightLabelControl = pLeftLabelControl+1; auto pLeftColumnLabel = m_pImpl->aFieldLabels.cbegin() + 2 * _nPos; auto pRightColumnLabel = pLeftColumnLabel + 1;
// for the focus movement and the selection scroll auto pLeftListControl = m_pImpl->pFields.begin(); auto pRightListControl = pLeftListControl + 1;
// for the focus movement
sal_Int32 nOldFocusRow = -1;
sal_Int32 nOldFocusColumn = 0;
// for the selection scroll auto pLeftAssignment = m_pImpl->aFieldAssignments.cbegin() + 2 * _nPos; auto pRightAssignment = pLeftAssignment + 1;
// the new texts of the label controls
(*pLeftLabelControl)->set_label(*pLeftColumnLabel);
(*pRightLabelControl)->set_label(*pRightColumnLabel);
// we may have to hide the controls in the right column, if we have no label text for it // (which means we have an odd number of fields, though we forced our internal arrays to // be even-sized for easier handling) // (If sometimes we support an arbitrary number of field assignments, we would have to care for // an invisible left hand side column, too. But right now, the left hand side controls are always // visible) bool bHideRightColumn = pRightColumnLabel->isEmpty();
(*pRightLabelControl)->set_visible(!bHideRightColumn);
(*pRightListControl)->set_visible(!bHideRightColumn); // the new selections of the listboxes
implSelectField(pLeftListControl->get(), *pLeftAssignment);
implSelectField(pRightListControl->get(), *pRightAssignment);
// increment ... if ( i < FIELD_PAIRS_VISIBLE - 1 )
{ // (not in the very last round, here the +=2 could result in an invalid // iterator position, which causes an abort in a non-product version
pLeftLabelControl += 2;
pRightLabelControl += 2;
pLeftColumnLabel += 2;
pRightColumnLabel += 2;
if (_bAdjustFocus && (nOldFocusRow >= 0))
{ // we have to adjust the focus and one of the list boxes has the focus
sal_Int32 nDelta = m_pImpl->nFieldScrollPos - _nPos; // the new row for the focus
sal_Int32 nNewFocusRow = nOldFocusRow + nDelta; // normalize
nNewFocusRow = std::min(nNewFocusRow, sal_Int32(FIELD_PAIRS_VISIBLE - 1), ::std::less< sal_Int32 >());
nNewFocusRow = std::max(nNewFocusRow, sal_Int32(0), ::std::less< sal_Int32 >()); // set the new focus (in the same column)
m_pImpl->pFields[nNewFocusRow * 2 + nOldFocusColumn]->grab_focus();
}
m_pImpl->nFieldScrollPos = _nPos;
if (_bAdjustScrollbar)
m_xFieldScroller->vadjustment_set_value(m_pImpl->nFieldScrollPos);
}
void AddressBookSourceDialog::implSelectField(weld::ComboBox* pBox, const OUString& rText)
{ if (!rText.isEmpty()) // a valid field name
pBox->set_active_text(rText); else // no selection for this item
pBox->set_active(0);
}
// AddressBookSourceDialog::loadConfiguration: inconsistence between field names and field assignments!
assert(m_pImpl->aLogicalFieldNames.size() == m_pImpl->aFieldAssignments.size());
// set the field assignments auto aAssignment = m_pImpl->aFieldAssignments.cbegin(); for (autoconst& logicalFieldName : m_pImpl->aLogicalFieldNames)
{
m_pImpl->pConfigData->setFieldAssignment(logicalFieldName, *aAssignment);
++aAssignment;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.