Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/LibreOffice/dbaccess/source/ui/control/   (Office von Apache Version 25.8.3.2©)  Datei vom 5.10.2025 mit Größe 24 kB image not shown  

Quelle  tabletree.cxx   Sprache: C

 
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   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 <comphelper/diagnose_ex.hxx>
#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::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, u""_ustr, 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, falsetruefalse);
            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, falsefalse);
    }
}

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 );
    }
    catchconst 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 );
    }
    catchconst 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());
    }
    catchconst 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);
    }
    catchconst 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(u"treeview"_ustr), /*bShowToggles*/false));
}

}   // namespace dbaui

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Messung V0.5
C=95 H=98 G=96

¤ Dauer der Verarbeitung: 0.3 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

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.