LibreOffice Module dbaccess (master) 1
tabletree.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20#include <core_resource.hxx>
21#include <tabletree.hxx>
22#include <imageprovider.hxx>
23#include <strings.hrc>
25#include <com/sun/star/sdb/application/DatabaseObject.hpp>
26#include <com/sun/star/sdb/application/DatabaseObjectContainer.hpp>
27#include <com/sun/star/sdbcx/XViewsSupplier.hpp>
28#include <com/sun/star/sdbcx/XTablesSupplier.hpp>
29#include <com/sun/star/sdbc/SQLException.hpp>
30#include <com/sun/star/sdbc/XRow.hpp>
32#include <osl/diagnose.h>
34
35#include <algorithm>
36
37namespace dbaui
38{
39
40using namespace ::com::sun::star::uno;
41using namespace ::com::sun::star::sdb;
42using namespace ::com::sun::star::lang;
43using namespace ::com::sun::star::sdbc;
44using namespace ::com::sun::star::sdbcx;
45using namespace ::com::sun::star::container;
46using namespace ::com::sun::star::sdb::application;
47
48using namespace ::dbtools;
49using namespace ::comphelper;
50
51namespace DatabaseObject = ::com::sun::star::sdb::application::DatabaseObject;
52namespace DatabaseObjectContainer = ::com::sun::star::sdb::application::DatabaseObjectContainer;
53
54// OTableTreeListBox
55OTableTreeListBox::OTableTreeListBox(std::unique_ptr<weld::TreeView> xTreeView, bool bShowToggles)
56 : TreeListBox(std::move(xTreeView), true)
57 , m_xImageProvider(new ImageProvider)
58 , m_bVirtualRoot(false)
59 , m_bNoEmptyFolders(false)
60 , m_bShowToggles(bShowToggles)
61{
63 m_xTreeView->enable_toggle_buttons(weld::ColumnToggleType::Check);
64}
65
67{
68 sal_Int32 nEntryType = m_xTreeView->get_id(rEntry).toInt32();
69 return ( nEntryType == DatabaseObjectContainer::TABLES )
70 || ( nEntryType == DatabaseObjectContainer::CATALOG )
71 || ( nEntryType == DatabaseObjectContainer::SCHEMA );
72}
73
75{
76 m_xConnection = _rxConnection;
77 m_xImageProvider.reset( new ImageProvider( m_xConnection ) );
78}
79
81{
82 Sequence< OUString > sTables, sViews;
83
84 OUString sCurrentActionError;
85 try
86 {
87 Reference< XTablesSupplier > xTableSupp( _rxConnection, UNO_QUERY_THROW );
88 sCurrentActionError = DBA_RES(STR_NOTABLEINFO);
89
90 Reference< XNameAccess > xTables,xViews;
91
92 Reference< XViewsSupplier > xViewSupp( _rxConnection, UNO_QUERY );
93 if ( xViewSupp.is() )
94 {
95 xViews = xViewSupp->getViews();
96 if (xViews.is())
97 sViews = xViews->getElementNames();
98 }
99
100 xTables = xTableSupp->getTables();
101 if (xTables.is())
102 sTables = xTables->getElementNames();
103 }
104 catch(RuntimeException&)
105 {
106 TOOLS_WARN_EXCEPTION( "dbaccess", "OTableTreeListBox::UpdateTableList");
107 }
108 catch ( const SQLException& )
109 {
110 throw;
111 }
112 catch(Exception&)
113 {
114 css::uno::Any anyEx = cppu::getCaughtException();
115 // a non-SQLException exception occurred ... simply throw an SQLException
116 throw SQLException(sCurrentActionError, nullptr, "", 0, anyEx);
117 }
118
119 UpdateTableList( _rxConnection, sTables, sViews );
120}
121
122namespace
123{
124 struct OViewSetter
125 {
126 const Sequence< OUString> m_aViews;
128
129 OViewSetter(const Sequence< OUString>& _rViews,bool _bCase) : m_aViews(_rViews),m_aEqualFunctor(_bCase){}
130 OTableTreeListBox::TNames::value_type operator() (const OUString& name)
131 {
132 OTableTreeListBox::TNames::value_type aRet;
133 aRet.first = name;
134 aRet.second = std::any_of(m_aViews.begin(), m_aViews.end(),
135 [this, &name](const OUString& lhs)
136 { return m_aEqualFunctor(lhs, name); } );
137
138 return aRet;
139 }
140 };
141
142}
143
145 const Reference< XConnection >& _rxConnection,
146 const Sequence< OUString>& _rTables,
147 const Sequence< OUString>& _rViews
148 )
149{
150 TNames aTables;
151 aTables.resize(_rTables.getLength());
152 try
153 {
154 Reference< XDatabaseMetaData > xMeta( _rxConnection->getMetaData(), UNO_SET_THROW );
155 std::transform( _rTables.begin(), _rTables.end(),
156 aTables.begin(), OViewSetter( _rViews, xMeta->supportsMixedCaseQuotedIdentifiers() ) );
157 }
158 catch(Exception&)
159 {
160 DBG_UNHANDLED_EXCEPTION("dbaccess");
161 }
162 UpdateTableList( _rxConnection, aTables );
163}
164
165namespace
166{
167 std::vector< OUString > lcl_getMetaDataStrings_throw( const Reference< XResultSet >& _rxMetaDataResult, sal_Int32 _nColumnIndex )
168 {
169 std::vector< OUString > aStrings;
170 Reference< XRow > xRow( _rxMetaDataResult, UNO_QUERY_THROW );
171 while ( _rxMetaDataResult->next() )
172 aStrings.push_back( xRow->getString( _nColumnIndex ) );
173 return aStrings;
174 }
175
176 bool lcl_shouldDisplayEmptySchemasAndCatalogs( const Reference< XConnection >& _rxConnection )
177 {
178 ::dbtools::DatabaseMetaData aMetaData( _rxConnection );
179 return aMetaData.displayEmptyTableFolders();
180 }
181}
182
183void OTableTreeListBox::UpdateTableList( const Reference< XConnection >& _rxConnection, const TNames& _rTables )
184{
185 implOnNewConnection( _rxConnection );
186
187 // throw away all the old stuff
188 m_xTreeView->clear();
189 m_xTreeView->make_unsorted();
190
191 try
192 {
193 if (haveVirtualRoot())
194 {
195 OUString sRootEntryText;
196 if ( std::none_of(_rTables.begin(),_rTables.end(),
197 [] (const TNames::value_type& name) { return !name.second; }) )
198 sRootEntryText = DBA_RES(STR_ALL_TABLES);
199 else if ( std::none_of(_rTables.begin(),_rTables.end(),
200 [] (const TNames::value_type& name) { return name.second; }) )
201 sRootEntryText = DBA_RES(STR_ALL_VIEWS);
202 else
203 sRootEntryText = DBA_RES(STR_ALL_TABLES_AND_VIEWS);
204 OUString sId(OUString::number(DatabaseObjectContainer::TABLES));
205 OUString sImageId = ImageProvider::getFolderImageId(DatabaseObject::TABLE);
206 std::unique_ptr<weld::TreeIter> xRet(m_xTreeView->make_iterator());
207 m_xTreeView->insert(nullptr, -1, nullptr, &sId, nullptr, nullptr, false, xRet.get());
208 m_xTreeView->set_image(*xRet, sImageId, -1);
209 if (m_bShowToggles)
210 m_xTreeView->set_toggle(*xRet, TRISTATE_FALSE);
211 m_xTreeView->set_text(*xRet, sRootEntryText, 0);
212 m_xTreeView->set_text_emphasis(*xRet, false, 0);
213 }
214
215 if ( _rTables.empty() )
216 // nothing to do (besides inserting the root entry)
217 return;
218
219 // get the table/view names
220 Reference< XDatabaseMetaData > xMeta( _rxConnection->getMetaData(), UNO_SET_THROW );
221 for (auto const& table : _rTables)
222 {
223 // add the entry
224 implAddEntry(xMeta, table.first, false);
225 }
226
227 if ( !m_bNoEmptyFolders && lcl_shouldDisplayEmptySchemasAndCatalogs( _rxConnection ) )
228 {
229 bool bSupportsCatalogs = xMeta->supportsCatalogsInDataManipulation();
230 bool bSupportsSchemas = xMeta->supportsSchemasInDataManipulation();
231
232 if ( bSupportsCatalogs || bSupportsSchemas )
233 {
234 // we display empty catalogs if the DB supports catalogs, and they're noted at the beginning of a
235 // composed name. Otherwise, we display empty schematas. (also see the tree structure explained in
236 // implAddEntry)
237 bool bCatalogs = bSupportsCatalogs && xMeta->isCatalogAtStart();
238
239 std::vector< OUString > aFolderNames( lcl_getMetaDataStrings_throw(
240 bCatalogs ? xMeta->getCatalogs() : xMeta->getSchemas(), 1 ) );
241 sal_Int32 nFolderType = bCatalogs ? DatabaseObjectContainer::CATALOG : DatabaseObjectContainer::SCHEMA;
242
243 OUString sImageId = ImageProvider::getFolderImageId(DatabaseObject::TABLE);
244
245 std::unique_ptr<weld::TreeIter> xRootEntry(getAllObjectsEntry());
246 std::unique_ptr<weld::TreeIter> xRet(m_xTreeView->make_iterator());
247 for (auto const& folderName : aFolderNames)
248 {
249 std::unique_ptr<weld::TreeIter> xFolder(GetEntryPosByName(folderName, xRootEntry.get()));
250 if (!xFolder)
251 {
252 OUString sId(OUString::number(nFolderType));
253 m_xTreeView->insert(xRootEntry.get(), -1, nullptr, &sId, nullptr, nullptr, false, xRet.get());
254 m_xTreeView->set_image(*xRet, sImageId, -1);
255 if (m_bShowToggles)
256 m_xTreeView->set_toggle(*xRet, TRISTATE_FALSE);
257 m_xTreeView->set_text(*xRet, folderName, 0);
258 m_xTreeView->set_text_emphasis(*xRet, false, 0);
259 }
260 }
261 }
262 }
263 }
264 catch ( const Exception& )
265 {
266 DBG_UNHANDLED_EXCEPTION("dbaccess");
267 }
268
269 m_xTreeView->make_sorted();
270}
271
273{
274 return m_xTreeView->get_text_emphasis(rEntry, 0);
275}
276
278{
279 if (!m_bShowToggles)
280 return;
281 m_xTreeView->set_toggle(rEntry, TRISTATE_TRUE);
283}
284
285std::unique_ptr<weld::TreeIter> OTableTreeListBox::getAllObjectsEntry() const
286{
287 if (!haveVirtualRoot())
288 return nullptr;
289 auto xRet = m_xTreeView->make_iterator();
290 if (!m_xTreeView->get_iter_first(*xRet))
291 return nullptr;
292 return xRet;
293}
294
296{
297 if (!m_bShowToggles)
298 return;
299 TriState eState = m_xTreeView->get_toggle(rEntry);
300 OSL_ENSURE(TRISTATE_INDET != eState, "OTableTreeListBox::CheckButtonHdl: user action which lead to TRISTATE?");
301
302 if (m_xTreeView->iter_has_child(rEntry)) // if it has children, check those too
303 {
304 std::unique_ptr<weld::TreeIter> xChildEntry(m_xTreeView->make_iterator(&rEntry));
305 std::unique_ptr<weld::TreeIter> xSiblingEntry(m_xTreeView->make_iterator(&rEntry));
306 bool bChildEntry = m_xTreeView->iter_next(*xChildEntry);
307 bool bSiblingEntry = m_xTreeView->iter_next_sibling(*xSiblingEntry);
308 while (bChildEntry && (!bSiblingEntry || !xChildEntry->equal(*xSiblingEntry)))
309 {
310 m_xTreeView->set_toggle(*xChildEntry, eState);
311 bChildEntry = m_xTreeView->iter_next(*xChildEntry);
312 }
313 }
314
315 if (m_xTreeView->is_selected(rEntry))
316 {
317 m_xTreeView->selected_foreach([this, eState](weld::TreeIter& rSelected){
318 m_xTreeView->set_toggle(rSelected, eState);
319 if (m_xTreeView->iter_has_child(rSelected)) // if it has children, check those too
320 {
321 std::unique_ptr<weld::TreeIter> xChildEntry(m_xTreeView->make_iterator(&rSelected));
322 std::unique_ptr<weld::TreeIter> xSiblingEntry(m_xTreeView->make_iterator(&rSelected));
323 bool bChildEntry = m_xTreeView->iter_next(*xChildEntry);
324 bool bSiblingEntry = m_xTreeView->iter_next_sibling(*xSiblingEntry);
325 while (bChildEntry && (!bSiblingEntry || !xChildEntry->equal(*xSiblingEntry)))
326 {
327 m_xTreeView->set_toggle(*xChildEntry, eState);
328 bChildEntry = m_xTreeView->iter_next(*xChildEntry);
329 }
330 }
331 return false;
332 });
333 }
334
335 CheckButtons();
336
337 // if an entry has children, it makes a difference if the entry is checked
338 // because all children are checked or if the user checked it explicitly.
339 // So we track explicit (un)checking
340 implEmphasize(rEntry, eState == TRISTATE_TRUE);
341}
342
343void OTableTreeListBox::implEmphasize(const weld::TreeIter& rEntry, bool _bChecked, bool _bUpdateDescendants, bool _bUpdateAncestors)
344{
345 // special emphasizing handling for the "all objects" entry
346 bool bAllObjectsEntryAffected = haveVirtualRoot() && (getAllObjectsEntry()->equal(rEntry));
347 if ( m_xTreeView->iter_has_child(rEntry) // the entry has children
348 || bAllObjectsEntryAffected // or it is the "all objects" entry
349 )
350 {
351 m_xTreeView->set_text_emphasis(rEntry, _bChecked, 0);
352 }
353
354 if (_bUpdateDescendants)
355 {
356 std::unique_ptr<weld::TreeIter> xChild(m_xTreeView->make_iterator(&rEntry));
357 // remove the mark for all children of the checked entry
358 bool bChildLoop = m_xTreeView->iter_children(*xChild);
359 while (bChildLoop)
360 {
361 if (m_xTreeView->iter_has_child(*xChild))
362 implEmphasize(*xChild, false, true, false);
363 bChildLoop = m_xTreeView->iter_next_sibling(*xChild);
364 }
365 }
366
367 if (_bUpdateAncestors)
368 {
369 std::unique_ptr<weld::TreeIter> xParent(m_xTreeView->make_iterator(&rEntry));
370 // remove the mark for all ancestors of the entry
371 if (m_xTreeView->iter_parent(*xParent))
372 implEmphasize(*xParent, false, false);
373 }
374}
375
376std::unique_ptr<weld::TreeIter> OTableTreeListBox::implAddEntry(
377 const Reference< XDatabaseMetaData >& _rxMeta,
378 const OUString& _rTableName,
379 bool _bCheckName
380 )
381{
382 OSL_PRECOND( _rxMeta.is(), "OTableTreeListBox::implAddEntry: invalid meta data!" );
383 if ( !_rxMeta.is() )
384 return nullptr;
385
386 // split the complete name into its components
387 OUString sCatalog, sSchema, sName;
388 qualifiedNameComponents( _rxMeta, _rTableName, sCatalog, sSchema, sName, ::dbtools::EComposeRule::InDataManipulation );
389
390 std::unique_ptr<weld::TreeIter> xParentEntry(getAllObjectsEntry());
391
392 // if the DB uses catalog at the start of identifiers, then our hierarchy is
393 // catalog
394 // +- schema
395 // +- table
396 // else it is
397 // schema
398 // +- catalog
399 // +- table
400 bool bCatalogAtStart = _rxMeta->isCatalogAtStart();
401 const OUString& rFirstName = bCatalogAtStart ? sCatalog : sSchema;
402 const sal_Int32 nFirstFolderType = bCatalogAtStart ? DatabaseObjectContainer::CATALOG : DatabaseObjectContainer::SCHEMA;
403 const OUString& rSecondName = bCatalogAtStart ? sSchema : sCatalog;
404 const sal_Int32 nSecondFolderType = bCatalogAtStart ? DatabaseObjectContainer::SCHEMA : DatabaseObjectContainer::CATALOG;
405
406 if ( !rFirstName.isEmpty() )
407 {
408 std::unique_ptr<weld::TreeIter> xFolder(GetEntryPosByName(rFirstName, xParentEntry.get()));
409 if (!xFolder)
410 {
411 xFolder = m_xTreeView->make_iterator();
412 OUString sId(OUString::number(nFirstFolderType));
413 OUString sImageId = ImageProvider::getFolderImageId(DatabaseObject::TABLE);
414 m_xTreeView->insert(xParentEntry.get(), -1, nullptr, &sId, nullptr, nullptr, false, xFolder.get());
415 m_xTreeView->set_image(*xFolder, sImageId, -1);
416 if (m_bShowToggles)
417 m_xTreeView->set_toggle(*xFolder, TRISTATE_FALSE);
418 m_xTreeView->set_text(*xFolder, rFirstName, 0);
419 m_xTreeView->set_text_emphasis(*xFolder, false, 0);
420 }
421 xParentEntry = std::move(xFolder);
422 }
423
424 if ( !rSecondName.isEmpty() )
425 {
426 std::unique_ptr<weld::TreeIter> xFolder(GetEntryPosByName(rSecondName, xParentEntry.get()));
427 if (!xFolder)
428 {
429 xFolder = m_xTreeView->make_iterator();
430 OUString sId(OUString::number(nSecondFolderType));
431 OUString sImageId = ImageProvider::getFolderImageId(DatabaseObject::TABLE);
432 m_xTreeView->insert(xParentEntry.get(), -1, nullptr, &sId, nullptr, nullptr, false, xFolder.get());
433 m_xTreeView->set_image(*xFolder, sImageId, -1);
434 if (m_bShowToggles)
435 m_xTreeView->set_toggle(*xFolder, TRISTATE_FALSE);
436 m_xTreeView->set_text(*xFolder, rSecondName, 0);
437 m_xTreeView->set_text_emphasis(*xFolder, false, 0);
438 }
439 xParentEntry = std::move(xFolder);
440 }
441
442 if (!_bCheckName || !GetEntryPosByName(sName, xParentEntry.get()))
443 {
444 std::unique_ptr<weld::TreeIter> xEntry = m_xTreeView->make_iterator();
445 m_xTreeView->insert(xParentEntry.get(), -1, nullptr, nullptr, nullptr, nullptr, false, xEntry.get());
446
447 auto xGraphic = m_xImageProvider->getXGraphic(_rTableName, DatabaseObject::TABLE);
448 if (xGraphic.is())
449 m_xTreeView->set_image(*xEntry, xGraphic, -1);
450 else
451 {
452 OUString sImageId(m_xImageProvider->getImageId(_rTableName, DatabaseObject::TABLE));
453 m_xTreeView->set_image(*xEntry, sImageId, -1);
454 }
455 if (m_bShowToggles)
456 m_xTreeView->set_toggle(*xEntry, TRISTATE_FALSE);
457 m_xTreeView->set_text(*xEntry, sName, 0);
458 m_xTreeView->set_text_emphasis(*xEntry, false, 0);
459
460 return xEntry;
461 }
462
463 return nullptr;
464}
465
466NamedDatabaseObject OTableTreeListBox::describeObject(const weld::TreeIter& rEntry)
467{
468 NamedDatabaseObject aObject;
469
470 sal_Int32 nEntryType = m_xTreeView->get_id(rEntry).toInt32();
471
472 if ( nEntryType == DatabaseObjectContainer::TABLES )
473 {
474 aObject.Type = DatabaseObjectContainer::TABLES;
475 }
476 else if ( ( nEntryType == DatabaseObjectContainer::CATALOG )
477 || ( nEntryType == DatabaseObjectContainer::SCHEMA )
478 )
479 {
480 // nothing useful to be done
481 }
482 else
483 {
484 aObject.Type = DatabaseObject::TABLE;
485 aObject.Name = getQualifiedTableName(rEntry);
486 }
487
488 return aObject;
489}
490
491std::unique_ptr<weld::TreeIter> OTableTreeListBox::addedTable(const OUString& rName)
492{
493 try
494 {
496 if ( impl_getAndAssertMetaData( xMeta ) )
497 return implAddEntry( xMeta, rName );
498 }
499 catch( const Exception& )
500 {
501 DBG_UNHANDLED_EXCEPTION("dbaccess");
502 }
503 return nullptr;
504}
505
506bool OTableTreeListBox::impl_getAndAssertMetaData( Reference< XDatabaseMetaData >& _out_rMetaData ) const
507{
508 if ( m_xConnection.is() )
509 _out_rMetaData = m_xConnection->getMetaData();
510 OSL_PRECOND( _out_rMetaData.is(), "OTableTreeListBox::impl_getAndAssertMetaData: invalid current connection!" );
511 return _out_rMetaData.is();
512}
513
514OUString OTableTreeListBox::getQualifiedTableName(const weld::TreeIter& rEntry) const
515{
516 OSL_PRECOND( !isFolderEntry(rEntry), "OTableTreeListBox::getQualifiedTableName: folder entries not allowed here!" );
517
518 try
519 {
521 if ( !impl_getAndAssertMetaData( xMeta ) )
522 return OUString();
523
524 OUString sCatalog;
525 OUString sSchema;
526 OUString sTable;
527
528 std::unique_ptr<weld::TreeIter> xSchema(m_xTreeView->make_iterator(&rEntry));
529 bool bSchema = m_xTreeView->iter_parent(*xSchema);
530 if (bSchema)
531 {
532 std::unique_ptr<weld::TreeIter> xCatalog(m_xTreeView->make_iterator(xSchema.get()));
533 bool bCatalog = m_xTreeView->iter_parent(*xCatalog);
534 if ( bCatalog
535 || ( xMeta->supportsCatalogsInDataManipulation()
536 && !xMeta->supportsSchemasInDataManipulation()
537 ) // here we support catalog but no schema
538 )
539 {
540 if (!bCatalog)
541 {
542 xCatalog = std::move(xSchema);
543 bSchema = false;
544 }
545 sCatalog = m_xTreeView->get_text(*xCatalog);
546 }
547 if (bSchema)
548 sSchema = m_xTreeView->get_text(*xSchema);
549 }
550 sTable = m_xTreeView->get_text(rEntry);
551
552 return ::dbtools::composeTableName( xMeta, sCatalog, sSchema, sTable, false, ::dbtools::EComposeRule::InDataManipulation );
553 }
554 catch( const Exception& )
555 {
556 DBG_UNHANDLED_EXCEPTION("dbaccess");
557 }
558 return OUString();
559}
560
561std::unique_ptr<weld::TreeIter> OTableTreeListBox::getEntryByQualifiedName(const OUString& rName)
562{
563 try
564 {
566 if ( !impl_getAndAssertMetaData( xMeta ) )
567 return nullptr;
568
569 // split the complete name into its components
570 OUString sCatalog, sSchema, sName;
571 qualifiedNameComponents(xMeta, rName, sCatalog, sSchema, sName,::dbtools::EComposeRule::InDataManipulation);
572
573 std::unique_ptr<weld::TreeIter> xParent(getAllObjectsEntry());
574 std::unique_ptr<weld::TreeIter> xCat;
575 std::unique_ptr<weld::TreeIter> xSchema;
576 if (!sCatalog.isEmpty())
577 {
578 xCat = GetEntryPosByName(sCatalog);
579 if (xCat)
580 xParent = std::move(xCat);
581 }
582
583 if (!sSchema.isEmpty())
584 {
585 xSchema = GetEntryPosByName(sSchema, xParent.get());
586 if (xSchema)
587 xParent = std::move(xSchema);
588 }
589
590 return GetEntryPosByName(sName, xParent.get());
591 }
592 catch( const Exception& )
593 {
594 DBG_UNHANDLED_EXCEPTION("dbaccess");
595 }
596 return nullptr;
597}
598
599void OTableTreeListBox::removedTable(const OUString& rName)
600{
601 try
602 {
603 std::unique_ptr<weld::TreeIter> xEntry = getEntryByQualifiedName(rName);
604 if (xEntry)
605 m_xTreeView->remove(*xEntry);
606 }
607 catch( const Exception& )
608 {
609 DBG_UNHANDLED_EXCEPTION("dbaccess");
610 }
611}
612
613void OTableTreeListBox::CheckButtons()
614{
615 if (!m_bShowToggles)
616 return;
617
618 auto xEntry(m_xTreeView->make_iterator());
619 if (!m_xTreeView->get_iter_first(*xEntry))
620 return;
621
622 do
623 {
624 implDetermineState(*xEntry);
625 } while (m_xTreeView->iter_next_sibling(*xEntry));
626}
627
628TriState OTableTreeListBox::implDetermineState(const weld::TreeIter& rEntry)
629{
630 if (!m_bShowToggles)
631 return TRISTATE_FALSE;
632
633 TriState eState = m_xTreeView->get_toggle(rEntry);
634 if (!m_xTreeView->iter_has_child(rEntry))
635 // nothing to do in this bottom-up routine if there are no children ...
636 return eState;
637
638 // loop through the children and check their states
639 sal_uInt16 nCheckedChildren = 0;
640 sal_uInt16 nChildrenOverall = 0;
641
642 std::unique_ptr<weld::TreeIter> xChild(m_xTreeView->make_iterator(&rEntry));
643 bool bChildLoop = m_xTreeView->iter_children(*xChild);
644 while (bChildLoop)
645 {
646 TriState eChildState = implDetermineState(*xChild);
647 if (eChildState == TRISTATE_INDET)
648 break;
649 if (eChildState == TRISTATE_TRUE)
650 ++nCheckedChildren;
651 ++nChildrenOverall;
652 bChildLoop = m_xTreeView->iter_next_sibling(*xChild);
653 }
654
655 if (bChildLoop)
656 {
657 // we did not finish the loop because at least one of the children is in tristate
658 eState = TRISTATE_INDET;
659
660 // but this means that we did not finish all the siblings of pChildLoop,
661 // so their checking may be incorrect at the moment
662 // -> correct this
663 while (bChildLoop)
664 {
665 implDetermineState(*xChild);
666 bChildLoop = m_xTreeView->iter_next_sibling(*xChild);
667 }
668 }
669 else
670 {
671 // none if the children are in tristate
672 if (nCheckedChildren)
673 {
674 // we have at least one child checked
675 if (nCheckedChildren != nChildrenOverall)
676 {
677 // not all children are checked
678 eState = TRISTATE_INDET;
679 }
680 else
681 {
682 // all children are checked
683 eState = TRISTATE_TRUE;
684 }
685 }
686 else
687 {
688 // no children are checked
689 eState = TRISTATE_FALSE;
690 }
691 }
692
693 // finally set the entry to the state we just determined
694 m_xTreeView->set_toggle(rEntry, eState);
695
696 return eState;
697}
698
699DBTableTreeView::DBTableTreeView(weld::Container* pContainer)
700 : DBTreeViewBase(pContainer)
701{
702 m_xTreeListBox.reset(new OTableTreeListBox(m_xBuilder->weld_tree_view("treeview"), /*bShowToggles*/false));
703}
704
705} // namespace dbaui
706
707/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
OptionalString sSchema
OptionalString sCatalog
OptionalString sName
std::unique_ptr< weld::Builder > m_xBuilder
std::unique_ptr< TreeListBox > m_xTreeListBox
std::vector< TTableViewName > TNames
Definition: tabletree.hxx:50
void checkWildcard(const weld::TreeIter &rEntry)
does a wildcard check of the given entry
Definition: tabletree.cxx:277
void UpdateTableList(const css::uno::Reference< css::sdbc::XConnection > &_rxConnection)
fill the table list with the tables belonging to the connection described by the parameters
OTableTreeListBox(std::unique_ptr< weld::TreeView > xTreeView, bool bShowToggles)
Definition: tabletree.cxx:55
bool haveVirtualRoot() const
Definition: tabletree.hxx:126
bool isWildcardChecked(const weld::TreeIter &rEntry)
determine if the given entry is 'wildcard checked'
Definition: tabletree.cxx:272
void checkedButton_noBroadcast(const weld::TreeIter &rEntry)
Definition: tabletree.cxx:295
css::uno::Reference< css::sdbc::XConnection > m_xConnection
Definition: tabletree.hxx:37
std::unique_ptr< weld::TreeIter > getAllObjectsEntry() const
Definition: tabletree.cxx:285
void implOnNewConnection(const css::uno::Reference< css::sdbc::XConnection > &_rxConnection)
Definition: tabletree.cxx:74
std::unique_ptr< weld::TreeIter > implAddEntry(const css::uno::Reference< css::sdbc::XDatabaseMetaData > &_rxMeta, const OUString &_rTableName, bool _bCheckName=true)
adds the given entry to our list @precond our image provider must already have been reset to the conn...
Definition: tabletree.cxx:376
std::unique_ptr< ImageProvider > m_xImageProvider
Definition: tabletree.hxx:39
bool isFolderEntry(const weld::TreeIter &rEntry) const
determines whether the given entry denotes a tables folder
Definition: tabletree.cxx:66
std::unique_ptr< weld::TreeIter > GetEntryPosByName(std::u16string_view rName, const weld::TreeIter *pStart=nullptr, const IEntryFilter *pFilter=nullptr) const
std::unique_ptr< weld::TreeView > m_xTreeView
#define DBA_RES(id)
const bool bCatalogs
#define TOOLS_WARN_EXCEPTION(area, stream)
#define DBG_UNHANDLED_EXCEPTION(...)
TriState
TRISTATE_FALSE
TRISTATE_INDET
TRISTATE_TRUE
const char * name
@ table
@ Exception
Any SAL_CALL getCaughtException()
void qualifiedNameComponents(const Reference< XDatabaseMetaData > &_rxConnMetaData, const OUString &_rQualifiedName, OUString &_rCatalog, OUString &_rSchema, OUString &_rName, EComposeRule _eComposeRule)
Reference< XConnection > m_xConnection
Definition: objectnames.cxx:79
::comphelper::UStringMixEqual m_aEqualFunctor
Definition: tabletree.cxx:127
const Sequence< OUString > m_aViews
Definition: tabletree.cxx:126
OUString sId
Definition: unodatbr.cxx:1040