1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include "AppDetailPageHelper.hxx"
21 #include <comphelper/diagnose_ex.hxx>
22 #include <tabletree.hxx>
23 #include <dbtreelistbox.hxx>
24 #include <com/sun/star/awt/PopupMenu.hpp>
25 #include <com/sun/star/awt/XTabController.hpp>
26 #include <com/sun/star/container/XChild.hpp>
27 #include <com/sun/star/container/XContainer.hpp>
28 #include <com/sun/star/form/XLoadable.hpp>
29 #include <com/sun/star/frame/thePopupMenuControllerFactory.hpp>
30 #include <com/sun/star/frame/XLayoutManager.hpp>
31 #include <com/sun/star/frame/Frame.hpp>
32 #include <com/sun/star/frame/FrameSearchFlag.hpp>
33 #include <com/sun/star/frame/XFrames.hpp>
34 #include <com/sun/star/frame/XFramesSupplier.hpp>
35 #include <com/sun/star/frame/XPopupMenuController.hpp>
36 #include <com/sun/star/sdb/application/XDatabaseDocumentUI.hpp>
37 #include <com/sun/star/sdb/application/DatabaseObject.hpp>
38 #include <com/sun/star/sdb/application/DatabaseObjectContainer.hpp>
39 #include <com/sun/star/sdbc/XConnection.hpp>
40 #include <com/sun/star/ucb/XCommandEnvironment.hpp>
41 #include <com/sun/star/ucb/XCommandProcessor.hpp>
42 #include <com/sun/star/ucb/Command.hpp>
43 #include <com/sun/star/util/XCloseable.hpp>
44 #include <comphelper/propertyvalue.hxx>
45 #include <comphelper/string.hxx>
46 #include <o3tl/string_view.hxx>
47 #include "AppView.hxx"
49 #include <strings.hxx>
50 #include <dbaccess_slotid.hrc>
51 #include <databaseobjectview.hxx>
52 #include <imageprovider.hxx>
53 #include <vcl/commandinfoprovider.hxx>
54 #include <vcl/cvtgrf.hxx>
55 #include <tools/stream.hxx>
56 #include "AppController.hxx"
58 #include <com/sun/star/document/XDocumentProperties.hpp>
62 using namespace ::dbaui
;
63 using namespace ::com::sun::star::container
;
64 using namespace ::com::sun::star::uno
;
65 using namespace ::com::sun::star::ucb
;
66 using namespace ::com::sun::star::frame
;
67 using namespace ::com::sun::star::form
;
68 using namespace ::com::sun::star::sdb
;
69 using namespace ::com::sun::star::sdb::application
;
70 using namespace ::com::sun::star::sdbc
;
71 using namespace ::com::sun::star::beans
;
72 using namespace ::com::sun::star
;
73 using ::com::sun::star::awt::XTabController
;
77 namespace DatabaseObject
= css::sdb::application::DatabaseObject
;
78 namespace DatabaseObjectContainer
= css::sdb::application::DatabaseObjectContainer
;
83 bool lcl_findEntry_impl(const TreeListBox
& rTree
, std::u16string_view rName
, weld::TreeIter
& rIter
)
87 std::u16string_view
sName( o3tl::getToken(rName
,0,'/',nIndex
) );
89 const weld::TreeView
& rTreeView
= rTree
.GetWidget();
93 if (rTreeView
.get_text(rIter
) == sName
)
97 sName
= o3tl::getToken(rName
,0,'/',nIndex
);
98 bEntry
= rTreeView
.iter_children(rIter
);
107 bEntry
= rTreeView
.iter_next_sibling(rIter
);
114 bool lcl_findEntry(const TreeListBox
& rTree
, std::u16string_view rName
, weld::TreeIter
& rIter
)
116 sal_Int32 nIndex
= 0;
117 std::u16string_view sErase
= o3tl::getToken(rName
,0,'/',nIndex
); // we don't want to have the "private:forms" part
118 return nIndex
!= -1 && lcl_findEntry_impl(rTree
, rName
.substr(sErase
.size() + 1), rIter
);
122 OAppDetailPageHelper::OAppDetailPageHelper(weld::Container
* pParent
, OAppBorderWindow
& rBorderWin
, PreviewMode ePreviewMode
)
123 : OChildWindow(pParent
, u
"dbaccess/ui/detailwindow.ui"_ustr
, u
"DetailWindow"_ustr
)
124 , m_rBorderWin(rBorderWin
)
125 , m_xBox(m_xBuilder
->weld_container(u
"box"_ustr
))
126 , m_xFL(m_xBuilder
->weld_widget(u
"separator"_ustr
))
127 , m_xMBPreview(m_xBuilder
->weld_menu_button(u
"disablepreview"_ustr
))
128 , m_xPreview(new OPreviewWindow
)
129 , m_xPreviewWin(new weld::CustomWeld(*m_xBuilder
, u
"preview"_ustr
, *m_xPreview
))
130 , m_xDocumentInfo(new ODocumentInfoPreview
)
131 , m_xDocumentInfoWin(new weld::CustomWeld(*m_xBuilder
, u
"infopreview"_ustr
, *m_xDocumentInfo
))
132 , m_xTablePreview(m_xBuilder
->weld_container(u
"tablepreview"_ustr
))
133 , m_ePreviewMode(ePreviewMode
)
135 m_xContainer
->set_stack_background();
137 auto aProperties
= vcl::CommandInfoProvider::GetCommandProperties(u
".uno:DBDisablePreview"_ustr
,
138 u
"com.sun.star.sdb.OfficeDatabaseDocument"_ustr
);
139 m_xMBPreview
->set_label(vcl::CommandInfoProvider::GetLabelForCommand(aProperties
));
140 m_xMBPreview
->set_help_id(HID_APP_VIEW_PREVIEW_CB
);
142 m_xMBPreview
->connect_selected(LINK(this, OAppDetailPageHelper
, MenuSelectHdl
));
143 m_xMBPreview
->connect_toggled(LINK(this, OAppDetailPageHelper
, OnDropdownClickHdl
));
145 m_xPreview
->SetHelpId(HID_APP_VIEW_PREVIEW_1
);
147 m_xTablePreview
->set_help_id(HID_APP_VIEW_PREVIEW_2
);
148 m_xDocumentInfo
->SetHelpId(HID_APP_VIEW_PREVIEW_3
);
150 m_xWindow
= m_xTablePreview
->CreateChildFrame();
153 OAppDetailPageHelper::~OAppDetailPageHelper()
157 Reference
< ::util::XCloseable
> xCloseable(m_xFrame
,UNO_QUERY
);
158 if ( xCloseable
.is() )
159 xCloseable
->close(true);
162 catch(const Exception
&)
164 TOOLS_WARN_EXCEPTION( "dbaccess", "Exception thrown while disposing preview frame!");
167 for (auto& rpBox
: m_aLists
)
174 m_xWindow
->dispose();
177 m_xTablePreview
.reset();
178 m_xDocumentInfoWin
.reset();
179 m_xDocumentInfo
.reset();
180 m_xPreviewWin
.reset();
182 m_xMBPreview
.reset();
187 int OAppDetailPageHelper::getVisibleControlIndex() const
190 for (; i
< E_ELEMENT_TYPE_COUNT
; ++i
)
192 if (m_aLists
[i
] && m_aLists
[i
]->get_visible())
198 void OAppDetailPageHelper::selectAll()
200 int nPos
= getVisibleControlIndex();
201 if (nPos
< E_ELEMENT_TYPE_COUNT
)
203 m_aLists
[nPos
]->GetWidget().select_all();
207 void OAppDetailPageHelper::GrabFocus()
209 int nPos
= getVisibleControlIndex();
210 if (nPos
< E_ELEMENT_TYPE_COUNT
)
211 m_aLists
[nPos
]->GetWidget().grab_focus();
212 else if (m_xMBPreview
&& m_xMBPreview
->get_visible())
213 m_xMBPreview
->grab_focus();
216 bool OAppDetailPageHelper::HasChildPathFocus() const
218 int nPos
= getVisibleControlIndex();
219 if (nPos
< E_ELEMENT_TYPE_COUNT
&& m_aLists
[nPos
]->GetWidget().has_focus())
221 return m_xMBPreview
&& m_xMBPreview
->has_focus();
224 void OAppDetailPageHelper::sort(int nPos
, bool bAscending
)
226 assert(m_aLists
[nPos
] && "List can not be NULL! ->GPF");
227 m_aLists
[nPos
]->GetWidget().set_sort_order(bAscending
);
230 bool OAppDetailPageHelper::isSortUp() const
232 bool bAscending
= false;
234 int nPos
= getVisibleControlIndex();
235 if (nPos
< E_ELEMENT_TYPE_COUNT
)
236 bAscending
= m_aLists
[nPos
]->GetWidget().get_sort_order();
241 void OAppDetailPageHelper::sortDown()
243 int nPos
= getVisibleControlIndex();
244 if ( nPos
< E_ELEMENT_TYPE_COUNT
)
248 void OAppDetailPageHelper::sortUp()
250 int nPos
= getVisibleControlIndex();
251 if ( nPos
< E_ELEMENT_TYPE_COUNT
)
255 void OAppDetailPageHelper::getSelectionElementNames(std::vector
<OUString
>& rNames
) const
257 int nPos
= getVisibleControlIndex();
258 if ( nPos
>= E_ELEMENT_TYPE_COUNT
)
261 DBTreeViewBase
& rTree
= *m_aLists
[nPos
];
262 weld::TreeView
& rTreeView
= rTree
.GetWidget();
263 sal_Int32 nCount
= rTreeView
.n_children();
264 rNames
.reserve(nCount
);
265 ElementType eType
= getElementType();
267 rTreeView
.selected_foreach([this, eType
, &rTreeView
, &rNames
](weld::TreeIter
& rEntry
){
268 if ( eType
== E_TABLE
)
270 if (!rTreeView
.iter_has_child(rEntry
))
271 rNames
.push_back(getQualifiedName(&rEntry
));
275 OUString sName
= rTreeView
.get_text(rEntry
);
276 std::unique_ptr
<weld::TreeIter
> xParent(rTreeView
.make_iterator(&rEntry
));
277 bool bParent
= rTreeView
.iter_parent(*xParent
);
280 sName
= rTreeView
.get_text(*xParent
) + "/" + sName
;
281 bParent
= rTreeView
.iter_parent(*xParent
);
283 rNames
.push_back(sName
);
290 void OAppDetailPageHelper::describeCurrentSelectionForControl(const weld::TreeView
& rControl
, Sequence
< NamedDatabaseObject
>& out_rSelectedObjects
)
292 for (size_t i
=0; i
< E_ELEMENT_TYPE_COUNT
; ++i
)
294 if (&m_aLists
[i
]->GetWidget() == &rControl
)
296 describeCurrentSelectionForType(static_cast<ElementType
>(i
), out_rSelectedObjects
);
300 OSL_FAIL( "OAppDetailPageHelper::describeCurrentSelectionForControl: invalid control!" );
303 void OAppDetailPageHelper::describeCurrentSelectionForType(const ElementType eType
, Sequence
< NamedDatabaseObject
>& _out_rSelectedObjects
)
305 OSL_ENSURE( eType
< E_ELEMENT_TYPE_COUNT
, "OAppDetailPageHelper::describeCurrentSelectionForType: invalid type!" );
306 DBTreeViewBase
* pList
= ( eType
< E_ELEMENT_TYPE_COUNT
) ? m_aLists
[eType
].get() : nullptr;
307 OSL_ENSURE( pList
, "OAppDetailPageHelper::describeCurrentSelectionForType: "
308 "You really should ensure this type has already been viewed before!" );
312 std::vector
< NamedDatabaseObject
> aSelected
;
314 weld::TreeView
& rTreeView
= pList
->GetWidget();
315 rTreeView
.selected_foreach([pList
, eType
, &rTreeView
, &aSelected
](weld::TreeIter
& rEntry
){
316 NamedDatabaseObject aObject
;
321 OTableTreeListBox
& rTableTree
= static_cast<OTableTreeListBox
&>(pList
->getListBox());
322 aObject
= rTableTree
.describeObject(rEntry
);
326 aObject
.Type
= DatabaseObject::QUERY
;
327 aObject
.Name
= rTreeView
.get_text(rEntry
);
332 OUString sName
= rTreeView
.get_text(rEntry
);
333 std::unique_ptr
<weld::TreeIter
> xParent(rTreeView
.make_iterator(&rEntry
));
334 bool bParent
= rTreeView
.iter_parent(*xParent
);
337 sName
= rTreeView
.get_text(*xParent
) + "/" + sName
;
338 bParent
= rTreeView
.iter_parent(*xParent
);
341 if (isLeaf(rTreeView
, rEntry
))
342 aObject
.Type
= (eType
== E_FORM
) ? DatabaseObject::FORM
: DatabaseObject::REPORT
;
344 aObject
.Type
= (eType
== E_FORM
) ? DatabaseObjectContainer::FORMS_FOLDER
: DatabaseObjectContainer::REPORTS_FOLDER
;
345 aObject
.Name
= sName
;
349 OSL_FAIL( "OAppDetailPageHelper::describeCurrentSelectionForType: unexpected type!" );
353 if (!aObject
.Name
.isEmpty())
354 aSelected
.push_back(aObject
);
359 _out_rSelectedObjects
= comphelper::containerToSequence(aSelected
);
362 vcl::Window
* OAppDetailPageHelper::getMenuParent() const
364 return &m_rBorderWin
;
367 void OAppDetailPageHelper::adjustMenuPosition(const weld::TreeView
& rControl
, ::Point
& rPos
) const
369 int x
, y
, width
, height
;
370 if (rControl
.get_extents_relative_to(m_rBorderWin
.getTopLevel(), x
, y
, width
, height
))
377 void OAppDetailPageHelper::selectElements(const Sequence
< OUString
>& _aNames
)
379 int nPos
= getVisibleControlIndex();
380 if ( nPos
>= E_ELEMENT_TYPE_COUNT
)
383 DBTreeViewBase
& rTree
= *m_aLists
[nPos
];
384 weld::TreeView
& rTreeView
= rTree
.GetWidget();
385 rTreeView
.unselect_all();
386 for (auto& name
: _aNames
)
388 auto xEntry
= rTree
.getListBox().GetEntryPosByName(name
);
391 rTreeView
.select(*xEntry
);
395 OUString
OAppDetailPageHelper::getQualifiedName(const weld::TreeIter
* _pEntry
) const
397 int nPos
= getVisibleControlIndex();
398 OUString sComposedName
;
400 if ( nPos
>= E_ELEMENT_TYPE_COUNT
)
401 return sComposedName
;
403 OSL_ENSURE(m_aLists
[nPos
],"Tables tree view is NULL! -> GPF");
404 DBTreeViewBase
& rTree
= *m_aLists
[nPos
];
405 weld::TreeView
& rTreeView
= rTree
.GetWidget();
407 std::unique_ptr
<weld::TreeIter
> xEntry(rTreeView
.make_iterator(_pEntry
));
410 if (!rTreeView
.get_selected(xEntry
.get()))
415 return sComposedName
;
417 if ( getElementType() == E_TABLE
)
419 const OTableTreeListBox
& rTableTreeListBox
= static_cast<const OTableTreeListBox
&>(m_aLists
[nPos
]->getListBox());
420 sComposedName
= rTableTreeListBox
.getQualifiedTableName(*xEntry
);
424 sComposedName
= rTreeView
.get_text(*xEntry
);
425 bool bParent
= rTreeView
.iter_parent(*xEntry
);
428 sComposedName
= rTreeView
.get_text(*xEntry
) + "/" + sComposedName
;
429 bParent
= rTreeView
.iter_parent(*xEntry
);
433 return sComposedName
;
436 ElementType
OAppDetailPageHelper::getElementType() const
438 int nPos
= getVisibleControlIndex();
439 return static_cast<ElementType
>(nPos
);
442 sal_Int32
OAppDetailPageHelper::getSelectionCount()
444 sal_Int32 nCount
= 0;
445 int nPos
= getVisibleControlIndex();
446 if ( nPos
< E_ELEMENT_TYPE_COUNT
)
448 DBTreeViewBase
& rTree
= *m_aLists
[nPos
];
449 weld::TreeView
& rTreeView
= rTree
.GetWidget();
450 nCount
= rTreeView
.count_selected_rows();
455 sal_Int32
OAppDetailPageHelper::getElementCount() const
457 sal_Int32 nCount
= 0;
458 int nPos
= getVisibleControlIndex();
459 if ( nPos
< E_ELEMENT_TYPE_COUNT
)
461 DBTreeViewBase
& rTree
= *m_aLists
[nPos
];
462 weld::TreeView
& rTreeView
= rTree
.GetWidget();
463 nCount
= rTreeView
.n_children();
468 bool OAppDetailPageHelper::isLeaf(const weld::TreeView
& rTreeView
, const weld::TreeIter
& rEntry
)
470 sal_Int32 nEntryType
= rTreeView
.get_id(rEntry
).toInt32();
471 return !( ( nEntryType
== DatabaseObjectContainer::TABLES
)
472 || ( nEntryType
== DatabaseObjectContainer::CATALOG
)
473 || ( nEntryType
== DatabaseObjectContainer::SCHEMA
)
474 || ( nEntryType
== DatabaseObjectContainer::FORMS_FOLDER
)
475 || ( nEntryType
== DatabaseObjectContainer::REPORTS_FOLDER
));
478 bool OAppDetailPageHelper::isALeafSelected() const
480 int nPos
= getVisibleControlIndex();
481 bool bLeafSelected
= false;
482 if ( nPos
< E_ELEMENT_TYPE_COUNT
)
484 DBTreeViewBase
& rTree
= *m_aLists
[nPos
];
485 weld::TreeView
& rTreeView
= rTree
.GetWidget();
486 rTreeView
.selected_foreach([&rTreeView
, &bLeafSelected
](weld::TreeIter
& rEntry
){
487 bLeafSelected
= isLeaf(rTreeView
, rEntry
);
488 return bLeafSelected
;
491 return bLeafSelected
;
494 std::unique_ptr
<weld::TreeIter
> OAppDetailPageHelper::getEntry( const Point
& _aPosPixel
) const
496 std::unique_ptr
<weld::TreeIter
> xReturn
;
497 int nPos
= getVisibleControlIndex();
498 if ( nPos
< E_ELEMENT_TYPE_COUNT
)
500 DBTreeViewBase
& rTree
= *m_aLists
[nPos
];
501 weld::TreeView
& rTreeView
= rTree
.GetWidget();
502 xReturn
= rTreeView
.make_iterator();
503 if (!rTreeView
.get_dest_row_at_pos(_aPosPixel
, xReturn
.get(), false))
509 void OAppDetailPageHelper::createTablesPage(const Reference
< XConnection
>& _xConnection
)
511 OSL_ENSURE(_xConnection
.is(),"Connection is NULL! -> GPF");
513 if ( !m_aLists
[E_TABLE
] )
515 m_aLists
[E_TABLE
].reset(new DBTableTreeView(m_xBox
.get()));
516 setupTree(*m_aLists
[E_TABLE
]);
517 m_aLists
[E_TABLE
]->GetWidget().set_help_id(HID_APP_TABLE_TREE
);
520 weld::TreeView
& rTreeView
= m_aLists
[E_TABLE
]->GetWidget();
521 if (!rTreeView
.n_children())
523 static_cast<OTableTreeListBox
&>(m_aLists
[E_TABLE
]->getListBox()).UpdateTableList(_xConnection
);
525 std::unique_ptr
<weld::TreeIter
> xFirst(rTreeView
.make_iterator());
526 if (rTreeView
.get_iter_first(*xFirst
))
527 rTreeView
.expand_row(*xFirst
);
528 rTreeView
.unselect_all();
531 setDetailPage(*m_aLists
[E_TABLE
]);
534 OUString
OAppDetailPageHelper::getElementIcons(ElementType _eType
)
536 sal_Int32
nDatabaseObjectType( 0 );
539 case E_FORM
: nDatabaseObjectType
= DatabaseObject::FORM
; break;
540 case E_REPORT
: nDatabaseObjectType
= DatabaseObject::REPORT
; break;
541 case E_QUERY
: nDatabaseObjectType
= DatabaseObject::QUERY
; break;
543 OSL_FAIL( "OAppDetailPageHelper::GetElementIcons: invalid element type!" );
547 return ImageProvider::getDefaultImageResourceID(nDatabaseObjectType
);
550 void OAppDetailPageHelper::createPage(ElementType _eType
,const Reference
< XNameAccess
>& _xContainer
)
552 OSL_ENSURE(E_TABLE
!= _eType
,"E_TABLE isn't allowed.");
558 sHelpId
= HID_APP_FORM_TREE
;
561 sHelpId
= HID_APP_REPORT_TREE
;
564 sHelpId
= HID_APP_QUERY_TREE
;
567 OSL_FAIL("Illegal call!");
569 OUString sImageId
= getElementIcons(_eType
);
571 if ( !m_aLists
[_eType
] )
573 m_aLists
[_eType
] = createSimpleTree(sHelpId
, _eType
);
576 if ( !m_aLists
[_eType
] )
579 weld::TreeView
& rTreeView
= m_aLists
[_eType
]->GetWidget();
580 if (!rTreeView
.n_children() && _xContainer
.is())
582 rTreeView
.make_unsorted();
583 fillNames( _xContainer
, _eType
, sImageId
, nullptr );
584 rTreeView
.make_sorted();
586 rTreeView
.unselect_all();
588 setDetailPage(*m_aLists
[_eType
]);
591 void OAppDetailPageHelper::setDetailPage(DBTreeViewBase
& rTreeView
)
593 bool bHasFocus
= false;
595 DBTreeViewBase
* pCurrent
= getCurrentView();
598 weld::Widget
& rCurrent
= pCurrent
->GetWidget();
599 bHasFocus
= rCurrent
.has_focus();
603 showPreview(nullptr);
606 m_xMBPreview
->show();
607 switchPreview(m_ePreviewMode
,true);
610 rTreeView
.GetWidget().grab_focus();
615 namespace DatabaseObjectContainer
= ::com::sun::star::sdb::application::DatabaseObjectContainer
;
617 sal_Int32
lcl_getFolderIndicatorForType( const ElementType _eType
)
619 const sal_Int32 nFolderIndicator
=
620 ( _eType
== E_FORM
) ? DatabaseObjectContainer::FORMS_FOLDER
621 : ( _eType
== E_REPORT
) ? DatabaseObjectContainer::REPORTS_FOLDER
: -1;
622 return nFolderIndicator
;
626 void OAppDetailPageHelper::fillNames( const Reference
< XNameAccess
>& _xContainer
, const ElementType _eType
,
627 const OUString
& rImageId
, const weld::TreeIter
* _pParent
)
629 OSL_ENSURE(_xContainer
.is(),"Data source is NULL! -> GPF");
630 OSL_ENSURE( ( _eType
>= E_TABLE
) && ( _eType
< E_ELEMENT_TYPE_COUNT
), "OAppDetailPageHelper::fillNames: invalid type!" );
632 DBTreeViewBase
* pList
= m_aLists
[_eType
].get();
633 OSL_ENSURE( pList
, "OAppDetailPageHelper::fillNames: you really should create the list before calling this!" );
637 if ( !(_xContainer
.is() && _xContainer
->hasElements()) )
640 weld::TreeView
& rTreeView
= pList
->GetWidget();
642 std::unique_ptr
<weld::TreeIter
> xRet
= rTreeView
.make_iterator();
643 const sal_Int32 nFolderIndicator
= lcl_getFolderIndicatorForType( _eType
);
645 for (auto& name
: _xContainer
->getElementNames())
647 Reference
<XNameAccess
> xSubElements(_xContainer
->getByName(name
), UNO_QUERY
);
648 if ( xSubElements
.is() )
650 OUString
sId(OUString::number(nFolderIndicator
));
652 rTreeView
.insert(_pParent
, -1, nullptr, &sId
, nullptr, nullptr, false, xRet
.get());
653 rTreeView
.set_text(*xRet
, name
, 0);
654 rTreeView
.set_text_emphasis(*xRet
, false, 0);
655 getBorderWin().getView()->getAppController().containerFound( Reference
< XContainer
>( xSubElements
, UNO_QUERY
) );
656 fillNames( xSubElements
, _eType
, rImageId
, xRet
.get());
660 rTreeView
.insert(_pParent
, -1, nullptr, nullptr, nullptr, nullptr, false, xRet
.get());
661 rTreeView
.set_text(*xRet
, name
, 0);
662 rTreeView
.set_text_emphasis(*xRet
, false, 0);
663 rTreeView
.set_image(*xRet
, rImageId
);
668 std::unique_ptr
<DBTreeViewBase
> OAppDetailPageHelper::createSimpleTree(const OUString
& rHelpId
, ElementType eType
)
670 const bool bSQLType
= eType
== E_TABLE
|| eType
== E_QUERY
;
671 std::unique_ptr
<DBTreeViewBase
> xTreeView(new DBTreeView(m_xBox
.get(), bSQLType
));
672 xTreeView
->GetWidget().set_help_id(rHelpId
);
673 setupTree(*xTreeView
);
677 void OAppDetailPageHelper::setupTree(DBTreeViewBase
& rDBTreeView
)
679 weld::WaitObject
aWaitCursor(m_rBorderWin
.GetFrameWeld());
681 rDBTreeView
.getListBox().setCopyHandler(LINK(this, OAppDetailPageHelper
, OnCopyEntry
));
682 rDBTreeView
.getListBox().setPasteHandler(LINK(this, OAppDetailPageHelper
, OnPasteEntry
));
683 rDBTreeView
.getListBox().setDeleteHandler(LINK(this, OAppDetailPageHelper
, OnDeleteEntry
));
685 weld::TreeView
& rTreeView
= rDBTreeView
.GetWidget();
686 rTreeView
.make_sorted();
687 rTreeView
.set_selection_mode(SelectionMode::Multiple
);
688 // an arbitrary small size it's allowed to shrink to
689 rTreeView
.set_size_request(42, 42);
691 rTreeView
.connect_row_activated(LINK(this, OAppDetailPageHelper
, OnEntryDoubleClick
));
693 rDBTreeView
.getListBox().SetSelChangeHdl(LINK(this, OAppDetailPageHelper
, OnEntrySelChange
));
695 rDBTreeView
.getListBox().setControlActionListener(&getBorderWin().getView()->getAppController());
696 rDBTreeView
.getListBox().setContextMenuProvider(&getBorderWin().getView()->getAppController());
699 void OAppDetailPageHelper::clearPages()
701 showPreview(nullptr);
702 for (auto& rpBox
: m_aLists
)
705 rpBox
->GetWidget().clear();
709 bool OAppDetailPageHelper::isFilled() const
712 for (; i
< E_ELEMENT_TYPE_COUNT
&& !m_aLists
[i
]; ++i
)
714 return i
!= E_ELEMENT_TYPE_COUNT
;
717 void OAppDetailPageHelper::elementReplaced(ElementType eType
,
718 const OUString
& rOldName
,
719 const OUString
& rNewName
)
721 DBTreeViewBase
* pTreeView
= getCurrentView();
725 weld::TreeView
& rTreeView
= pTreeView
->GetWidget();
726 rTreeView
.make_unsorted();
731 static_cast<OTableTreeListBox
&>(pTreeView
->getListBox()).removedTable(rOldName
);
732 static_cast<OTableTreeListBox
&>(pTreeView
->getListBox()).addedTable(rNewName
);
736 std::unique_ptr
<weld::TreeIter
> xIter(rTreeView
.make_iterator());
737 if (rTreeView
.get_iter_first(*xIter
) && lcl_findEntry_impl(pTreeView
->getListBox(), rOldName
, *xIter
))
738 rTreeView
.set_text(*xIter
, rNewName
);
744 std::unique_ptr
<weld::TreeIter
> xIter(rTreeView
.make_iterator());
745 if (rTreeView
.get_iter_first(*xIter
) && lcl_findEntry(pTreeView
->getListBox(), rOldName
, *xIter
))
746 rTreeView
.set_text(*xIter
, rNewName
);
750 OSL_FAIL("Invalid element type");
753 rTreeView
.make_sorted();
756 std::unique_ptr
<weld::TreeIter
> OAppDetailPageHelper::elementAdded(ElementType _eType
,const OUString
& _rName
, const Any
& _rObject
)
758 std::unique_ptr
<weld::TreeIter
> xRet
;
759 DBTreeViewBase
* pTreeView
= _eType
!= E_NONE
? m_aLists
[_eType
].get() : nullptr;
762 weld::TreeView
& rTreeView
= pTreeView
->GetWidget();
763 rTreeView
.make_unsorted();
764 if (_eType
== E_TABLE
)
766 xRet
= static_cast<OTableTreeListBox
&>(pTreeView
->getListBox()).addedTable( _rName
);
770 std::unique_ptr
<weld::TreeIter
> xEntry
;
771 Reference
<XChild
> xChild(_rObject
,UNO_QUERY
);
772 if ( xChild
.is() && E_QUERY
!= _eType
)
774 Reference
<XContent
> xContent(xChild
->getParent(),UNO_QUERY
);
777 OUString sName
= xContent
->getIdentifier()->getContentIdentifier();
778 std::unique_ptr
<weld::TreeIter
> xIter(rTreeView
.make_iterator());
779 if (rTreeView
.get_iter_first(*xIter
) && lcl_findEntry(pTreeView
->getListBox(), sName
, *xIter
))
780 xEntry
= std::move(xIter
);
784 OUString sImageId
= getElementIcons(_eType
);
785 Reference
<XNameAccess
> xContainer(_rObject
,UNO_QUERY
);
786 if ( xContainer
.is() )
788 const sal_Int32 nFolderIndicator
= lcl_getFolderIndicatorForType( _eType
);
789 OUString
sId(OUString::number(nFolderIndicator
));
791 xRet
= rTreeView
.make_iterator();
792 rTreeView
.insert(xEntry
.get(), -1, nullptr, &sId
, nullptr, nullptr, false, xRet
.get());
793 rTreeView
.set_text(*xRet
, _rName
, 0);
794 rTreeView
.set_text_emphasis(*xRet
, false, 0);
795 fillNames(xContainer
, _eType
, sImageId
, xRet
.get());
799 xRet
= rTreeView
.make_iterator();
800 rTreeView
.insert(xEntry
.get(), -1, nullptr, nullptr, nullptr, nullptr, false, xRet
.get());
801 rTreeView
.set_text(*xRet
, _rName
, 0);
802 rTreeView
.set_text_emphasis(*xRet
, false, 0);
803 rTreeView
.set_image(*xRet
, sImageId
);
806 rTreeView
.make_sorted();
810 void OAppDetailPageHelper::elementRemoved( ElementType _eType
,const OUString
& _rName
)
812 DBTreeViewBase
* pTreeView
= getCurrentView();
816 weld::TreeView
& rTreeView
= pTreeView
->GetWidget();
821 // we don't need to clear the table here, it is already done by the dispose listener
822 static_cast<OTableTreeListBox
&>(pTreeView
->getListBox()).removedTable(_rName
);
826 std::unique_ptr
<weld::TreeIter
> xIter(rTreeView
.make_iterator());
827 if (rTreeView
.get_iter_first(*xIter
) && lcl_findEntry_impl(pTreeView
->getListBox(), _rName
, *xIter
))
828 rTreeView
.remove(*xIter
);
834 std::unique_ptr
<weld::TreeIter
> xIter(rTreeView
.make_iterator());
835 if (rTreeView
.get_iter_first(*xIter
) && lcl_findEntry(pTreeView
->getListBox(), _rName
, *xIter
))
836 rTreeView
.remove(*xIter
);
840 OSL_FAIL("Invalid element type");
842 if (!rTreeView
.n_children())
843 showPreview(nullptr);
846 IMPL_LINK(OAppDetailPageHelper
, OnEntryDoubleClick
, weld::TreeView
&, rTreeView
, bool)
848 return getBorderWin().getView()->getAppController().onEntryDoubleClick(rTreeView
);
851 IMPL_LINK_NOARG(OAppDetailPageHelper
, OnEntrySelChange
, LinkParamNone
*, void)
853 getBorderWin().getView()->getAppController().onSelectionChanged();
856 IMPL_LINK_NOARG( OAppDetailPageHelper
, OnCopyEntry
, LinkParamNone
*, void )
858 getBorderWin().getView()->getAppController().onCopyEntry();
861 IMPL_LINK_NOARG( OAppDetailPageHelper
, OnPasteEntry
, LinkParamNone
*, void )
863 getBorderWin().getView()->getAppController().onPasteEntry();
866 IMPL_LINK_NOARG( OAppDetailPageHelper
, OnDeleteEntry
, LinkParamNone
*, void )
868 getBorderWin().getView()->getAppController().onDeleteEntry();
871 bool OAppDetailPageHelper::isPreviewEnabled() const
873 return m_ePreviewMode
!= PreviewMode::NONE
;
878 OUString
stripTrailingDots(std::u16string_view rStr
)
880 return OUString(comphelper::string::stripEnd(rStr
, '.'));
884 void OAppDetailPageHelper::switchPreview(PreviewMode _eMode
,bool _bForce
)
886 if ( !(m_ePreviewMode
!= _eMode
|| _bForce
) )
889 m_ePreviewMode
= _eMode
;
891 getBorderWin().getView()->getAppController().previewChanged(static_cast<sal_Int32
>(m_ePreviewMode
));
894 switch ( m_ePreviewMode
)
896 case PreviewMode::NONE
:
897 aCommand
= ".uno:DBDisablePreview";
899 case PreviewMode::Document
:
900 aCommand
= ".uno:DBShowDocPreview";
902 case PreviewMode::DocumentInfo
:
903 if ( getBorderWin().getView()->getAppController().isCommandEnabled(SID_DB_APP_VIEW_DOCINFO_PREVIEW
) )
904 aCommand
= ".uno:DBShowDocInfoPreview";
907 m_ePreviewMode
= PreviewMode::NONE
;
908 aCommand
= ".uno:DBDisablePreview";
913 auto aProperties
= vcl::CommandInfoProvider::GetCommandProperties(aCommand
, u
"com.sun.star.sdb.OfficeDatabaseDocument"_ustr
);
914 OUString aCommandLabel
= vcl::CommandInfoProvider::GetLabelForCommand(aProperties
);
915 m_xMBPreview
->set_label(stripTrailingDots(aCommandLabel
));
917 // simulate a selectionChanged event at the controller, to force the preview to be updated
918 if ( isPreviewEnabled() )
920 DBTreeViewBase
* pCurrent
= getCurrentView();
921 if (pCurrent
&& pCurrent
->GetWidget().get_selected(nullptr))
923 getBorderWin().getView()->getAppController().onSelectionChanged();
928 m_xTablePreview
->hide();
930 m_xDocumentInfo
->Hide();
934 void OAppDetailPageHelper::showPreview(const Reference
< XContent
>& _xContent
)
936 if ( !isPreviewEnabled() )
939 m_xTablePreview
->hide();
941 weld::WaitObject
aWaitCursor(m_rBorderWin
.GetFrameWeld());
944 Reference
<XCommandProcessor
> xContent(_xContent
,UNO_QUERY
);
947 css::ucb::Command aCommand
;
948 if ( m_ePreviewMode
== PreviewMode::Document
)
949 aCommand
.Name
= "preview";
951 aCommand
.Name
= "getDocumentInfo";
953 Any aPreview
= xContent
->execute(aCommand
,xContent
->createCommandIdentifier(),Reference
< XCommandEnvironment
>());
954 if ( m_ePreviewMode
== PreviewMode::Document
)
956 m_xDocumentInfo
->Hide();
960 Sequence
< sal_Int8
> aBmpSequence
;
961 if ( aPreview
>>= aBmpSequence
)
963 SvMemoryStream
aData( aBmpSequence
.getArray(),
964 aBmpSequence
.getLength(),
967 GraphicConverter::Import(aData
,aGraphic
);
969 m_xPreview
->setGraphic( aGraphic
);
970 m_xPreview
->Invalidate();
975 m_xDocumentInfo
->clear();
976 m_xDocumentInfo
->Show();
977 Reference
<document::XDocumentProperties
> xProp(
978 aPreview
, UNO_QUERY
);
980 m_xDocumentInfo
->fill(xProp
);
986 m_xDocumentInfo
->Hide();
989 catch( const Exception
& )
991 DBG_UNHANDLED_EXCEPTION("dbaccess");
995 void OAppDetailPageHelper::showPreview( const OUString
& _sDataSourceName
,
996 const OUString
& _sName
,
999 if ( !isPreviewEnabled() )
1002 weld::WaitObject
aWaitCursor(m_rBorderWin
.GetFrameWeld());
1004 m_xDocumentInfo
->Hide();
1005 m_xTablePreview
->show();
1006 if ( !m_xFrame
.is() )
1010 m_xFrame
= Frame::create( getBorderWin().getView()->getORB() );
1011 m_xFrame
->initialize( m_xWindow
);
1013 // no layout manager (and thus no toolbars) in the preview
1014 // Must be called after initialize ... but before any other call to this frame.
1015 // Otherwise frame throws "life time exceptions" as e.g. NON_INITIALIZED
1016 m_xFrame
->setLayoutManager( Reference
< XLayoutManager
>() );
1018 Reference
<XFramesSupplier
> xSup(getBorderWin().getView()->getAppController().getXController()->getFrame(),UNO_QUERY
);
1021 Reference
<XFrames
> xFrames
= xSup
->getFrames();
1022 xFrames
->append( Reference
<XFrame
>(m_xFrame
,UNO_QUERY_THROW
));
1025 catch(const Exception
&)
1030 Reference
< XDatabaseDocumentUI
> xApplication( getBorderWin().getView()->getAppController().getXController(), UNO_QUERY
);
1031 std::unique_ptr
< DatabaseObjectView
> pDispatcher( new ResultSetBrowser(
1032 getBorderWin().getView()->getORB(),
1033 xApplication
, nullptr, _bTable
1035 pDispatcher
->setTargetFrame( Reference
<XFrame
>(m_xFrame
,UNO_QUERY_THROW
) );
1037 ::comphelper::NamedValueCollection aArgs
;
1038 aArgs
.put( u
"Preview"_ustr
, true );
1039 aArgs
.put( u
"ReadOnly"_ustr
, true );
1040 aArgs
.put( u
"AsTemplate"_ustr
, false );
1041 aArgs
.put( PROPERTY_SHOWMENU
, false );
1043 Reference
< XController
> xPreview( pDispatcher
->openExisting( Any( _sDataSourceName
), _sName
, aArgs
), UNO_QUERY
);
1044 bool bClearPreview
= !xPreview
.is();
1046 // clear the preview when the query or table could not be loaded
1047 if ( !bClearPreview
)
1049 Reference
< XTabController
> xTabController( xPreview
, UNO_QUERY
);
1050 bClearPreview
= !xTabController
.is();
1051 if ( !bClearPreview
)
1053 Reference
< XLoadable
> xLoadable( xTabController
->getModel(), UNO_QUERY
);
1054 bClearPreview
= !( xLoadable
.is() && xLoadable
->isLoaded() );
1057 if ( bClearPreview
)
1058 showPreview(nullptr);
1063 class MenuStatusListener final
: public ::cppu::WeakImplHelper
<css::frame::XStatusListener
>
1065 weld::MenuButton
& m_rMBPreview
;
1067 MenuStatusListener(weld::MenuButton
& rMBPreview
)
1068 : m_rMBPreview(rMBPreview
)
1072 virtual void SAL_CALL
statusChanged( const css::frame::FeatureStateEvent
&rEvent
) override
1074 if (!rEvent
.IsEnabled
)
1076 const OUString
&rURL
= rEvent
.FeatureURL
.Complete
;
1077 m_rMBPreview
.remove_item(rURL
);
1081 virtual void SAL_CALL
disposing( const css::lang::EventObject
& /*rSource*/) override
1087 IMPL_LINK_NOARG(OAppDetailPageHelper
, OnDropdownClickHdl
, weld::Toggleable
&, void)
1089 if (!m_xMBPreview
->get_active())
1092 m_xMBPreview
->clear();
1095 css::uno::Reference
<css::uno::XComponentContext
> xContext(getBorderWin().getView()->getORB());
1096 css::uno::Reference
<css::frame::XUIControllerFactory
> xPopupMenuFactory(css::frame::thePopupMenuControllerFactory::get(xContext
));
1097 if (!xPopupMenuFactory
.is())
1100 auto xFrame
= getBorderWin().getView()->getAppController().getFrame();
1102 css::uno::Sequence
<css::uno::Any
> aArgs
{
1103 css::uno::Any(comphelper::makePropertyValue(u
"InToolbar"_ustr
, true)),
1104 css::uno::Any(comphelper::makePropertyValue(u
"ModuleIdentifier"_ustr
, u
"com.sun.star.sdb.OfficeDatabaseDocument"_ustr
)),
1105 css::uno::Any(comphelper::makePropertyValue(u
"Frame"_ustr
, xFrame
)) };
1107 css::uno::Reference
<css::frame::XPopupMenuController
> xPopupController
1108 (xPopupMenuFactory
->createInstanceWithArgumentsAndContext(u
".uno:DBPreview"_ustr
, aArgs
, xContext
), css::uno::UNO_QUERY
);
1110 if (!xPopupController
.is())
1113 css::uno::Reference
<css::awt::XPopupMenu
> xPopupMenu(css::awt::PopupMenu::create(xContext
));
1114 xPopupController
->setPopupMenu(xPopupMenu
);
1116 css::util::URL aTargetURL
;
1117 Reference
<XDispatchProvider
> xDispatchProvider(xFrame
, css::uno::UNO_QUERY
);
1119 css::uno::Reference
<css::frame::XStatusListener
> xStatusListener(new MenuStatusListener(*m_xMBPreview
));
1121 for (int i
= 0, nCount
= xPopupMenu
->getItemCount(); i
< nCount
; ++i
)
1123 auto nItemId
= xPopupMenu
->getItemId(i
);
1124 // in practice disabled items are initially enabled so this doesn't have an effect and
1125 // an status update is needed to query the enabled/disabled state
1126 if (!xPopupMenu
->isItemEnabled(nItemId
))
1129 aTargetURL
.Complete
= xPopupMenu
->getCommand(nItemId
);
1131 auto aProperties
= vcl::CommandInfoProvider::GetCommandProperties(aTargetURL
.Complete
,
1132 u
"com.sun.star.sdb.OfficeDatabaseDocument"_ustr
);
1133 m_xMBPreview
->append_item(aTargetURL
.Complete
, vcl::CommandInfoProvider::GetLabelForCommand(aProperties
));
1135 // Add/remove status listener to get a status update once so we can remove any disabled items from the menu
1136 auto xDispatch
= xDispatchProvider
->queryDispatch(aTargetURL
, u
"_self"_ustr
,
1137 css::frame::FrameSearchFlag::SELF
);
1140 xDispatch
->addStatusListener(xStatusListener
, aTargetURL
);
1141 xDispatch
->removeStatusListener(xStatusListener
, aTargetURL
);
1145 css::uno::Reference
<css::lang::XComponent
> xComponent(xPopupController
, css::uno::UNO_QUERY
);
1146 if (xComponent
.is())
1147 xComponent
->dispose();
1150 IMPL_LINK(OAppDetailPageHelper
, MenuSelectHdl
, const OUString
&, rIdent
, void)
1152 if (rIdent
.isEmpty())
1155 css::util::URL aURL
;
1156 aURL
.Complete
= rIdent
;
1158 Reference
<XDispatchProvider
> xProvider(getBorderWin().getView()->getAppController().getFrame(), UNO_QUERY
);
1159 Reference
<XDispatch
> xDisp
= xProvider
->queryDispatch(aURL
, u
"_self"_ustr
, 0);
1160 xDisp
->dispatch(aURL
, css::uno::Sequence
<css::beans::PropertyValue
>());
1162 m_xMBPreview
->set_label(stripTrailingDots(m_xMBPreview
->get_item_label(rIdent
)));
1165 OPreviewWindow::OPreviewWindow()
1169 bool OPreviewWindow::ImplGetGraphicCenterRect(const vcl::RenderContext
& rRenderContext
, const Graphic
& rGraphic
, tools::Rectangle
& rResultRect
) const
1171 const Size
aWinSize( GetOutputSizePixel() );
1172 Size
aNewSize(rRenderContext
.LogicToPixel(rGraphic
.GetPrefSize(), rGraphic
.GetPrefMapMode()));
1175 if( aNewSize
.Width() && aNewSize
.Height() )
1177 // scale to fit window
1178 const double fGrfWH
= static_cast<double>(aNewSize
.Width()) / aNewSize
.Height();
1179 const double fWinWH
= static_cast<double>(aWinSize
.Width()) / aWinSize
.Height();
1181 if ( fGrfWH
< fWinWH
)
1183 aNewSize
.setWidth( static_cast<tools::Long
>( aWinSize
.Height() * fGrfWH
) );
1184 aNewSize
.setHeight( aWinSize
.Height() );
1188 aNewSize
.setWidth( aWinSize
.Width() );
1189 aNewSize
.setHeight( static_cast<tools::Long
>( aWinSize
.Width() / fGrfWH
) );
1192 const Point
aNewPos( ( aWinSize
.Width() - aNewSize
.Width() ) >> 1,
1193 ( aWinSize
.Height() - aNewSize
.Height() ) >> 1 );
1195 rResultRect
= tools::Rectangle( aNewPos
, aNewSize
);
1202 void OPreviewWindow::Paint(vcl::RenderContext
& rRenderContext
, const tools::Rectangle
& /*rRect*/)
1204 if (ImplGetGraphicCenterRect(rRenderContext
, m_aGraphicObj
.GetGraphic(), m_aPreviewRect
))
1206 const Point
aPos(m_aPreviewRect
.TopLeft());
1207 const Size
aSize(m_aPreviewRect
.GetSize());
1209 if (m_aGraphicObj
.IsAnimated())
1210 m_aGraphicObj
.StartAnimation(rRenderContext
, aPos
, aSize
);
1212 m_aGraphicObj
.Draw(rRenderContext
, aPos
, aSize
);
1216 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */