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
, "dbaccess/ui/detailwindow.ui", "DetailWindow")
124 , m_rBorderWin(rBorderWin
)
125 , m_xBox(m_xBuilder
->weld_container("box"))
126 , m_xFL(m_xBuilder
->weld_widget("separator"))
127 , m_xMBPreview(m_xBuilder
->weld_menu_button("disablepreview"))
128 , m_xPreview(new OPreviewWindow
)
129 , m_xPreviewWin(new weld::CustomWeld(*m_xBuilder
, "preview", *m_xPreview
))
130 , m_xDocumentInfo(new ODocumentInfoPreview
)
131 , m_xDocumentInfoWin(new weld::CustomWeld(*m_xBuilder
, "infopreview", *m_xDocumentInfo
))
132 , m_xTablePreview(m_xBuilder
->weld_container("tablepreview"))
133 , m_ePreviewMode(ePreviewMode
)
135 m_xContainer
->set_stack_background();
137 auto aProperties
= vcl::CommandInfoProvider::GetCommandProperties(".uno:DBDisablePreview",
138 "com.sun.star.sdb.OfficeDatabaseDocument");
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 const OUString
* pIter
= _aNames
.getConstArray();
387 const OUString
* pEnd
= pIter
+ _aNames
.getLength();
388 for(;pIter
!= pEnd
;++pIter
)
390 auto xEntry
= rTree
.getListBox().GetEntryPosByName(*pIter
);
393 rTreeView
.select(*xEntry
);
397 OUString
OAppDetailPageHelper::getQualifiedName(const weld::TreeIter
* _pEntry
) const
399 int nPos
= getVisibleControlIndex();
400 OUString sComposedName
;
402 if ( nPos
>= E_ELEMENT_TYPE_COUNT
)
403 return sComposedName
;
405 OSL_ENSURE(m_aLists
[nPos
],"Tables tree view is NULL! -> GPF");
406 DBTreeViewBase
& rTree
= *m_aLists
[nPos
];
407 weld::TreeView
& rTreeView
= rTree
.GetWidget();
409 std::unique_ptr
<weld::TreeIter
> xEntry(rTreeView
.make_iterator(_pEntry
));
412 if (!rTreeView
.get_selected(xEntry
.get()))
417 return sComposedName
;
419 if ( getElementType() == E_TABLE
)
421 const OTableTreeListBox
& rTableTreeListBox
= static_cast<const OTableTreeListBox
&>(m_aLists
[nPos
]->getListBox());
422 sComposedName
= rTableTreeListBox
.getQualifiedTableName(*xEntry
);
426 sComposedName
= rTreeView
.get_text(*xEntry
);
427 bool bParent
= rTreeView
.iter_parent(*xEntry
);
430 sComposedName
= rTreeView
.get_text(*xEntry
) + "/" + sComposedName
;
431 bParent
= rTreeView
.iter_parent(*xEntry
);
435 return sComposedName
;
438 ElementType
OAppDetailPageHelper::getElementType() const
440 int nPos
= getVisibleControlIndex();
441 return static_cast<ElementType
>(nPos
);
444 sal_Int32
OAppDetailPageHelper::getSelectionCount()
446 sal_Int32 nCount
= 0;
447 int nPos
= getVisibleControlIndex();
448 if ( nPos
< E_ELEMENT_TYPE_COUNT
)
450 DBTreeViewBase
& rTree
= *m_aLists
[nPos
];
451 weld::TreeView
& rTreeView
= rTree
.GetWidget();
452 nCount
= rTreeView
.count_selected_rows();
457 sal_Int32
OAppDetailPageHelper::getElementCount() const
459 sal_Int32 nCount
= 0;
460 int nPos
= getVisibleControlIndex();
461 if ( nPos
< E_ELEMENT_TYPE_COUNT
)
463 DBTreeViewBase
& rTree
= *m_aLists
[nPos
];
464 weld::TreeView
& rTreeView
= rTree
.GetWidget();
465 nCount
= rTreeView
.n_children();
470 bool OAppDetailPageHelper::isLeaf(const weld::TreeView
& rTreeView
, const weld::TreeIter
& rEntry
)
472 sal_Int32 nEntryType
= rTreeView
.get_id(rEntry
).toInt32();
473 return !( ( nEntryType
== DatabaseObjectContainer::TABLES
)
474 || ( nEntryType
== DatabaseObjectContainer::CATALOG
)
475 || ( nEntryType
== DatabaseObjectContainer::SCHEMA
)
476 || ( nEntryType
== DatabaseObjectContainer::FORMS_FOLDER
)
477 || ( nEntryType
== DatabaseObjectContainer::REPORTS_FOLDER
));
480 bool OAppDetailPageHelper::isALeafSelected() const
482 int nPos
= getVisibleControlIndex();
483 bool bLeafSelected
= false;
484 if ( nPos
< E_ELEMENT_TYPE_COUNT
)
486 DBTreeViewBase
& rTree
= *m_aLists
[nPos
];
487 weld::TreeView
& rTreeView
= rTree
.GetWidget();
488 rTreeView
.selected_foreach([&rTreeView
, &bLeafSelected
](weld::TreeIter
& rEntry
){
489 bLeafSelected
= isLeaf(rTreeView
, rEntry
);
490 return bLeafSelected
;
493 return bLeafSelected
;
496 std::unique_ptr
<weld::TreeIter
> OAppDetailPageHelper::getEntry( const Point
& _aPosPixel
) const
498 std::unique_ptr
<weld::TreeIter
> xReturn
;
499 int nPos
= getVisibleControlIndex();
500 if ( nPos
< E_ELEMENT_TYPE_COUNT
)
502 DBTreeViewBase
& rTree
= *m_aLists
[nPos
];
503 weld::TreeView
& rTreeView
= rTree
.GetWidget();
504 xReturn
= rTreeView
.make_iterator();
505 if (!rTreeView
.get_dest_row_at_pos(_aPosPixel
, xReturn
.get(), false))
511 void OAppDetailPageHelper::createTablesPage(const Reference
< XConnection
>& _xConnection
)
513 OSL_ENSURE(_xConnection
.is(),"Connection is NULL! -> GPF");
515 if ( !m_aLists
[E_TABLE
] )
517 m_aLists
[E_TABLE
].reset(new DBTableTreeView(m_xBox
.get()));
518 setupTree(*m_aLists
[E_TABLE
]);
519 m_aLists
[E_TABLE
]->GetWidget().set_help_id(HID_APP_TABLE_TREE
);
522 weld::TreeView
& rTreeView
= m_aLists
[E_TABLE
]->GetWidget();
523 if (!rTreeView
.n_children())
525 static_cast<OTableTreeListBox
&>(m_aLists
[E_TABLE
]->getListBox()).UpdateTableList(_xConnection
);
527 std::unique_ptr
<weld::TreeIter
> xFirst(rTreeView
.make_iterator());
528 if (rTreeView
.get_iter_first(*xFirst
))
529 rTreeView
.expand_row(*xFirst
);
530 rTreeView
.unselect_all();
533 setDetailPage(*m_aLists
[E_TABLE
]);
536 OUString
OAppDetailPageHelper::getElementIcons(ElementType _eType
)
538 sal_Int32
nDatabaseObjectType( 0 );
541 case E_FORM
: nDatabaseObjectType
= DatabaseObject::FORM
; break;
542 case E_REPORT
: nDatabaseObjectType
= DatabaseObject::REPORT
; break;
543 case E_QUERY
: nDatabaseObjectType
= DatabaseObject::QUERY
; break;
545 OSL_FAIL( "OAppDetailPageHelper::GetElementIcons: invalid element type!" );
549 return ImageProvider::getDefaultImageResourceID(nDatabaseObjectType
);
552 void OAppDetailPageHelper::createPage(ElementType _eType
,const Reference
< XNameAccess
>& _xContainer
)
554 OSL_ENSURE(E_TABLE
!= _eType
,"E_TABLE isn't allowed.");
560 sHelpId
= HID_APP_FORM_TREE
;
563 sHelpId
= HID_APP_REPORT_TREE
;
566 sHelpId
= HID_APP_QUERY_TREE
;
569 OSL_FAIL("Illegal call!");
571 OUString sImageId
= getElementIcons(_eType
);
573 if ( !m_aLists
[_eType
] )
575 m_aLists
[_eType
] = createSimpleTree(sHelpId
, _eType
);
578 if ( !m_aLists
[_eType
] )
581 weld::TreeView
& rTreeView
= m_aLists
[_eType
]->GetWidget();
582 if (!rTreeView
.n_children() && _xContainer
.is())
584 rTreeView
.make_unsorted();
585 fillNames( _xContainer
, _eType
, sImageId
, nullptr );
586 rTreeView
.make_sorted();
588 rTreeView
.unselect_all();
590 setDetailPage(*m_aLists
[_eType
]);
593 void OAppDetailPageHelper::setDetailPage(DBTreeViewBase
& rTreeView
)
595 bool bHasFocus
= false;
597 DBTreeViewBase
* pCurrent
= getCurrentView();
600 weld::Widget
& rCurrent
= pCurrent
->GetWidget();
601 bHasFocus
= rCurrent
.has_focus();
605 showPreview(nullptr);
608 m_xMBPreview
->show();
609 switchPreview(m_ePreviewMode
,true);
612 rTreeView
.GetWidget().grab_focus();
617 namespace DatabaseObjectContainer
= ::com::sun::star::sdb::application::DatabaseObjectContainer
;
619 sal_Int32
lcl_getFolderIndicatorForType( const ElementType _eType
)
621 const sal_Int32 nFolderIndicator
=
622 ( _eType
== E_FORM
) ? DatabaseObjectContainer::FORMS_FOLDER
623 : ( _eType
== E_REPORT
) ? DatabaseObjectContainer::REPORTS_FOLDER
: -1;
624 return nFolderIndicator
;
628 void OAppDetailPageHelper::fillNames( const Reference
< XNameAccess
>& _xContainer
, const ElementType _eType
,
629 const OUString
& rImageId
, const weld::TreeIter
* _pParent
)
631 OSL_ENSURE(_xContainer
.is(),"Data source is NULL! -> GPF");
632 OSL_ENSURE( ( _eType
>= E_TABLE
) && ( _eType
< E_ELEMENT_TYPE_COUNT
), "OAppDetailPageHelper::fillNames: invalid type!" );
634 DBTreeViewBase
* pList
= m_aLists
[_eType
].get();
635 OSL_ENSURE( pList
, "OAppDetailPageHelper::fillNames: you really should create the list before calling this!" );
639 if ( !(_xContainer
.is() && _xContainer
->hasElements()) )
642 weld::TreeView
& rTreeView
= pList
->GetWidget();
644 std::unique_ptr
<weld::TreeIter
> xRet
= rTreeView
.make_iterator();
645 const sal_Int32 nFolderIndicator
= lcl_getFolderIndicatorForType( _eType
);
647 Sequence
< OUString
> aSeq
= _xContainer
->getElementNames();
648 const OUString
* pIter
= aSeq
.getConstArray();
649 const OUString
* pEnd
= pIter
+ aSeq
.getLength();
650 for(;pIter
!= pEnd
;++pIter
)
652 Reference
<XNameAccess
> xSubElements(_xContainer
->getByName(*pIter
),UNO_QUERY
);
653 if ( xSubElements
.is() )
655 OUString
sId(OUString::number(nFolderIndicator
));
657 rTreeView
.insert(_pParent
, -1, nullptr, &sId
, nullptr, nullptr, false, xRet
.get());
658 rTreeView
.set_text(*xRet
, *pIter
, 0);
659 rTreeView
.set_text_emphasis(*xRet
, false, 0);
660 getBorderWin().getView()->getAppController().containerFound( Reference
< XContainer
>( xSubElements
, UNO_QUERY
) );
661 fillNames( xSubElements
, _eType
, rImageId
, xRet
.get());
665 rTreeView
.insert(_pParent
, -1, nullptr, nullptr, nullptr, nullptr, false, xRet
.get());
666 rTreeView
.set_text(*xRet
, *pIter
, 0);
667 rTreeView
.set_text_emphasis(*xRet
, false, 0);
668 rTreeView
.set_image(*xRet
, rImageId
);
673 std::unique_ptr
<DBTreeViewBase
> OAppDetailPageHelper::createSimpleTree(const OString
& rHelpId
, ElementType eType
)
675 const bool bSQLType
= eType
== E_TABLE
|| eType
== E_QUERY
;
676 std::unique_ptr
<DBTreeViewBase
> xTreeView(new DBTreeView(m_xBox
.get(), bSQLType
));
677 xTreeView
->GetWidget().set_help_id(rHelpId
);
678 setupTree(*xTreeView
);
682 void OAppDetailPageHelper::setupTree(DBTreeViewBase
& rDBTreeView
)
684 weld::WaitObject
aWaitCursor(m_rBorderWin
.GetFrameWeld());
686 rDBTreeView
.getListBox().setCopyHandler(LINK(this, OAppDetailPageHelper
, OnCopyEntry
));
687 rDBTreeView
.getListBox().setPasteHandler(LINK(this, OAppDetailPageHelper
, OnPasteEntry
));
688 rDBTreeView
.getListBox().setDeleteHandler(LINK(this, OAppDetailPageHelper
, OnDeleteEntry
));
690 weld::TreeView
& rTreeView
= rDBTreeView
.GetWidget();
691 rTreeView
.make_sorted();
692 rTreeView
.set_selection_mode(SelectionMode::Multiple
);
693 // an arbitrary small size it's allowed to shrink to
694 rTreeView
.set_size_request(42, 42);
696 rTreeView
.connect_row_activated(LINK(this, OAppDetailPageHelper
, OnEntryDoubleClick
));
698 rDBTreeView
.getListBox().SetSelChangeHdl(LINK(this, OAppDetailPageHelper
, OnEntrySelChange
));
700 rDBTreeView
.getListBox().setControlActionListener(&getBorderWin().getView()->getAppController());
701 rDBTreeView
.getListBox().setContextMenuProvider(&getBorderWin().getView()->getAppController());
704 void OAppDetailPageHelper::clearPages()
706 showPreview(nullptr);
707 for (auto& rpBox
: m_aLists
)
710 rpBox
->GetWidget().clear();
714 bool OAppDetailPageHelper::isFilled() const
717 for (; i
< E_ELEMENT_TYPE_COUNT
&& !m_aLists
[i
]; ++i
)
719 return i
!= E_ELEMENT_TYPE_COUNT
;
722 void OAppDetailPageHelper::elementReplaced(ElementType eType
,
723 const OUString
& rOldName
,
724 const OUString
& rNewName
)
726 DBTreeViewBase
* pTreeView
= getCurrentView();
730 weld::TreeView
& rTreeView
= pTreeView
->GetWidget();
731 rTreeView
.make_unsorted();
736 static_cast<OTableTreeListBox
&>(pTreeView
->getListBox()).removedTable(rOldName
);
737 static_cast<OTableTreeListBox
&>(pTreeView
->getListBox()).addedTable(rNewName
);
741 std::unique_ptr
<weld::TreeIter
> xIter(rTreeView
.make_iterator());
742 if (rTreeView
.get_iter_first(*xIter
) && lcl_findEntry_impl(pTreeView
->getListBox(), rOldName
, *xIter
))
743 rTreeView
.set_text(*xIter
, rNewName
);
749 std::unique_ptr
<weld::TreeIter
> xIter(rTreeView
.make_iterator());
750 if (rTreeView
.get_iter_first(*xIter
) && lcl_findEntry(pTreeView
->getListBox(), rOldName
, *xIter
))
751 rTreeView
.set_text(*xIter
, rNewName
);
755 OSL_FAIL("Invalid element type");
758 rTreeView
.make_sorted();
761 std::unique_ptr
<weld::TreeIter
> OAppDetailPageHelper::elementAdded(ElementType _eType
,const OUString
& _rName
, const Any
& _rObject
)
763 std::unique_ptr
<weld::TreeIter
> xRet
;
764 DBTreeViewBase
* pTreeView
= m_aLists
[_eType
].get();
767 weld::TreeView
& rTreeView
= pTreeView
->GetWidget();
768 rTreeView
.make_unsorted();
769 if (_eType
== E_TABLE
)
771 xRet
= static_cast<OTableTreeListBox
&>(pTreeView
->getListBox()).addedTable( _rName
);
775 std::unique_ptr
<weld::TreeIter
> xEntry
;
776 Reference
<XChild
> xChild(_rObject
,UNO_QUERY
);
777 if ( xChild
.is() && E_QUERY
!= _eType
)
779 Reference
<XContent
> xContent(xChild
->getParent(),UNO_QUERY
);
782 OUString sName
= xContent
->getIdentifier()->getContentIdentifier();
783 std::unique_ptr
<weld::TreeIter
> xIter(rTreeView
.make_iterator());
784 if (rTreeView
.get_iter_first(*xIter
) && lcl_findEntry(pTreeView
->getListBox(), sName
, *xIter
))
785 xEntry
= std::move(xIter
);
789 OUString sImageId
= getElementIcons(_eType
);
790 Reference
<XNameAccess
> xContainer(_rObject
,UNO_QUERY
);
791 if ( xContainer
.is() )
793 const sal_Int32 nFolderIndicator
= lcl_getFolderIndicatorForType( _eType
);
794 OUString
sId(OUString::number(nFolderIndicator
));
796 xRet
= rTreeView
.make_iterator();
797 rTreeView
.insert(xEntry
.get(), -1, nullptr, &sId
, nullptr, nullptr, false, xRet
.get());
798 rTreeView
.set_text(*xRet
, _rName
, 0);
799 rTreeView
.set_text_emphasis(*xRet
, false, 0);
800 fillNames(xContainer
, _eType
, sImageId
, xRet
.get());
804 xRet
= rTreeView
.make_iterator();
805 rTreeView
.insert(xEntry
.get(), -1, nullptr, nullptr, nullptr, nullptr, false, xRet
.get());
806 rTreeView
.set_text(*xRet
, _rName
, 0);
807 rTreeView
.set_text_emphasis(*xRet
, false, 0);
808 rTreeView
.set_image(*xRet
, sImageId
);
811 rTreeView
.make_sorted();
815 void OAppDetailPageHelper::elementRemoved( ElementType _eType
,const OUString
& _rName
)
817 DBTreeViewBase
* pTreeView
= getCurrentView();
821 weld::TreeView
& rTreeView
= pTreeView
->GetWidget();
826 // we don't need to clear the table here, it is already done by the dispose listener
827 static_cast<OTableTreeListBox
&>(pTreeView
->getListBox()).removedTable(_rName
);
831 std::unique_ptr
<weld::TreeIter
> xIter(rTreeView
.make_iterator());
832 if (rTreeView
.get_iter_first(*xIter
) && lcl_findEntry_impl(pTreeView
->getListBox(), _rName
, *xIter
))
833 rTreeView
.remove(*xIter
);
839 std::unique_ptr
<weld::TreeIter
> xIter(rTreeView
.make_iterator());
840 if (rTreeView
.get_iter_first(*xIter
) && lcl_findEntry(pTreeView
->getListBox(), _rName
, *xIter
))
841 rTreeView
.remove(*xIter
);
845 OSL_FAIL("Invalid element type");
847 if (!rTreeView
.n_children())
848 showPreview(nullptr);
851 IMPL_LINK(OAppDetailPageHelper
, OnEntryDoubleClick
, weld::TreeView
&, rTreeView
, bool)
853 return getBorderWin().getView()->getAppController().onEntryDoubleClick(rTreeView
);
856 IMPL_LINK_NOARG(OAppDetailPageHelper
, OnEntrySelChange
, LinkParamNone
*, void)
858 getBorderWin().getView()->getAppController().onSelectionChanged();
861 IMPL_LINK_NOARG( OAppDetailPageHelper
, OnCopyEntry
, LinkParamNone
*, void )
863 getBorderWin().getView()->getAppController().onCopyEntry();
866 IMPL_LINK_NOARG( OAppDetailPageHelper
, OnPasteEntry
, LinkParamNone
*, void )
868 getBorderWin().getView()->getAppController().onPasteEntry();
871 IMPL_LINK_NOARG( OAppDetailPageHelper
, OnDeleteEntry
, LinkParamNone
*, void )
873 getBorderWin().getView()->getAppController().onDeleteEntry();
876 bool OAppDetailPageHelper::isPreviewEnabled() const
878 return m_ePreviewMode
!= PreviewMode::NONE
;
883 OUString
stripTrailingDots(std::u16string_view rStr
)
885 return OUString(comphelper::string::stripEnd(rStr
, '.'));
889 void OAppDetailPageHelper::switchPreview(PreviewMode _eMode
,bool _bForce
)
891 if ( !(m_ePreviewMode
!= _eMode
|| _bForce
) )
894 m_ePreviewMode
= _eMode
;
896 getBorderWin().getView()->getAppController().previewChanged(static_cast<sal_Int32
>(m_ePreviewMode
));
899 switch ( m_ePreviewMode
)
901 case PreviewMode::NONE
:
902 aCommand
= ".uno:DBDisablePreview";
904 case PreviewMode::Document
:
905 aCommand
= ".uno:DBShowDocPreview";
907 case PreviewMode::DocumentInfo
:
908 if ( getBorderWin().getView()->getAppController().isCommandEnabled(SID_DB_APP_VIEW_DOCINFO_PREVIEW
) )
909 aCommand
= ".uno:DBShowDocInfoPreview";
912 m_ePreviewMode
= PreviewMode::NONE
;
913 aCommand
= ".uno:DBDisablePreview";
918 auto aProperties
= vcl::CommandInfoProvider::GetCommandProperties(aCommand
, "com.sun.star.sdb.OfficeDatabaseDocument");
919 OUString aCommandLabel
= vcl::CommandInfoProvider::GetLabelForCommand(aProperties
);
920 m_xMBPreview
->set_label(stripTrailingDots(aCommandLabel
));
922 // simulate a selectionChanged event at the controller, to force the preview to be updated
923 if ( isPreviewEnabled() )
925 DBTreeViewBase
* pCurrent
= getCurrentView();
926 if (pCurrent
&& pCurrent
->GetWidget().get_selected(nullptr))
928 getBorderWin().getView()->getAppController().onSelectionChanged();
933 m_xTablePreview
->hide();
935 m_xDocumentInfo
->Hide();
939 void OAppDetailPageHelper::showPreview(const Reference
< XContent
>& _xContent
)
941 if ( !isPreviewEnabled() )
944 m_xTablePreview
->hide();
946 weld::WaitObject
aWaitCursor(m_rBorderWin
.GetFrameWeld());
949 Reference
<XCommandProcessor
> xContent(_xContent
,UNO_QUERY
);
952 css::ucb::Command aCommand
;
953 if ( m_ePreviewMode
== PreviewMode::Document
)
954 aCommand
.Name
= "preview";
956 aCommand
.Name
= "getDocumentInfo";
958 Any aPreview
= xContent
->execute(aCommand
,xContent
->createCommandIdentifier(),Reference
< XCommandEnvironment
>());
959 if ( m_ePreviewMode
== PreviewMode::Document
)
961 m_xDocumentInfo
->Hide();
965 Sequence
< sal_Int8
> aBmpSequence
;
966 if ( aPreview
>>= aBmpSequence
)
968 SvMemoryStream
aData( aBmpSequence
.getArray(),
969 aBmpSequence
.getLength(),
972 GraphicConverter::Import(aData
,aGraphic
);
974 m_xPreview
->setGraphic( aGraphic
);
975 m_xPreview
->Invalidate();
980 m_xDocumentInfo
->clear();
981 m_xDocumentInfo
->Show();
982 Reference
<document::XDocumentProperties
> xProp(
983 aPreview
, UNO_QUERY
);
985 m_xDocumentInfo
->fill(xProp
);
991 m_xDocumentInfo
->Hide();
994 catch( const Exception
& )
996 DBG_UNHANDLED_EXCEPTION("dbaccess");
1000 void OAppDetailPageHelper::showPreview( const OUString
& _sDataSourceName
,
1001 const OUString
& _sName
,
1004 if ( !isPreviewEnabled() )
1007 weld::WaitObject
aWaitCursor(m_rBorderWin
.GetFrameWeld());
1009 m_xDocumentInfo
->Hide();
1010 m_xTablePreview
->show();
1011 if ( !m_xFrame
.is() )
1015 m_xFrame
= Frame::create( getBorderWin().getView()->getORB() );
1016 m_xFrame
->initialize( m_xWindow
);
1018 // no layout manager (and thus no toolbars) in the preview
1019 // Must be called after initialize ... but before any other call to this frame.
1020 // Otherwise frame throws "life time exceptions" as e.g. NON_INITIALIZED
1021 m_xFrame
->setLayoutManager( Reference
< XLayoutManager
>() );
1023 Reference
<XFramesSupplier
> xSup(getBorderWin().getView()->getAppController().getXController()->getFrame(),UNO_QUERY
);
1026 Reference
<XFrames
> xFrames
= xSup
->getFrames();
1027 xFrames
->append( Reference
<XFrame
>(m_xFrame
,UNO_QUERY_THROW
));
1030 catch(const Exception
&)
1035 Reference
< XDatabaseDocumentUI
> xApplication( getBorderWin().getView()->getAppController().getXController(), UNO_QUERY
);
1036 std::unique_ptr
< DatabaseObjectView
> pDispatcher( new ResultSetBrowser(
1037 getBorderWin().getView()->getORB(),
1038 xApplication
, nullptr, _bTable
1040 pDispatcher
->setTargetFrame( Reference
<XFrame
>(m_xFrame
,UNO_QUERY_THROW
) );
1042 ::comphelper::NamedValueCollection aArgs
;
1043 aArgs
.put( "Preview", true );
1044 aArgs
.put( "ReadOnly", true );
1045 aArgs
.put( "AsTemplate", false );
1046 aArgs
.put( PROPERTY_SHOWMENU
, false );
1048 Reference
< XController
> xPreview( pDispatcher
->openExisting( Any( _sDataSourceName
), _sName
, aArgs
), UNO_QUERY
);
1049 bool bClearPreview
= !xPreview
.is();
1051 // clear the preview when the query or table could not be loaded
1052 if ( !bClearPreview
)
1054 Reference
< XTabController
> xTabController( xPreview
, UNO_QUERY
);
1055 bClearPreview
= !xTabController
.is();
1056 if ( !bClearPreview
)
1058 Reference
< XLoadable
> xLoadable( xTabController
->getModel(), UNO_QUERY
);
1059 bClearPreview
= !( xLoadable
.is() && xLoadable
->isLoaded() );
1062 if ( bClearPreview
)
1063 showPreview(nullptr);
1068 class MenuStatusListener final
: public ::cppu::WeakImplHelper
<css::frame::XStatusListener
>
1070 weld::MenuButton
& m_rMBPreview
;
1072 MenuStatusListener(weld::MenuButton
& rMBPreview
)
1073 : m_rMBPreview(rMBPreview
)
1077 virtual void SAL_CALL
statusChanged( const css::frame::FeatureStateEvent
&rEvent
) override
1079 if (!rEvent
.IsEnabled
)
1081 const OUString
&rURL
= rEvent
.FeatureURL
.Complete
;
1082 m_rMBPreview
.remove_item(rURL
.toUtf8());
1086 virtual void SAL_CALL
disposing( const css::lang::EventObject
& /*rSource*/) override
1092 IMPL_LINK_NOARG(OAppDetailPageHelper
, OnDropdownClickHdl
, weld::Toggleable
&, void)
1094 if (!m_xMBPreview
->get_active())
1097 m_xMBPreview
->clear();
1100 css::uno::Reference
<css::uno::XComponentContext
> xContext(getBorderWin().getView()->getORB());
1101 css::uno::Reference
<css::frame::XUIControllerFactory
> xPopupMenuFactory(css::frame::thePopupMenuControllerFactory::get(xContext
));
1102 if (!xPopupMenuFactory
.is())
1105 auto xFrame
= getBorderWin().getView()->getAppController().getFrame();
1107 css::uno::Sequence
<css::uno::Any
> aArgs
{
1108 css::uno::Any(comphelper::makePropertyValue("InToolbar", true)),
1109 css::uno::Any(comphelper::makePropertyValue("ModuleIdentifier", OUString("com.sun.star.sdb.OfficeDatabaseDocument"))),
1110 css::uno::Any(comphelper::makePropertyValue("Frame", xFrame
)) };
1112 css::uno::Reference
<css::frame::XPopupMenuController
> xPopupController
1113 (xPopupMenuFactory
->createInstanceWithArgumentsAndContext(".uno:DBPreview", aArgs
, xContext
), css::uno::UNO_QUERY
);
1115 if (!xPopupController
.is())
1118 css::uno::Reference
<css::awt::XPopupMenu
> xPopupMenu(css::awt::PopupMenu::create(xContext
));
1119 xPopupController
->setPopupMenu(xPopupMenu
);
1121 css::util::URL aTargetURL
;
1122 Reference
<XDispatchProvider
> xDispatchProvider(xFrame
, css::uno::UNO_QUERY
);
1124 css::uno::Reference
<css::frame::XStatusListener
> xStatusListener(new MenuStatusListener(*m_xMBPreview
));
1126 for (int i
= 0, nCount
= xPopupMenu
->getItemCount(); i
< nCount
; ++i
)
1128 auto nItemId
= xPopupMenu
->getItemId(i
);
1129 // in practice disabled items are initially enabled so this doesn't have an effect and
1130 // an status update is needed to query the enabled/disabled state
1131 if (!xPopupMenu
->isItemEnabled(nItemId
))
1134 aTargetURL
.Complete
= xPopupMenu
->getCommand(nItemId
);
1136 auto aProperties
= vcl::CommandInfoProvider::GetCommandProperties(aTargetURL
.Complete
,
1137 "com.sun.star.sdb.OfficeDatabaseDocument");
1138 m_xMBPreview
->append_item(aTargetURL
.Complete
, vcl::CommandInfoProvider::GetLabelForCommand(aProperties
));
1140 // Add/remove status listener to get a status update once so we can remove any disabled items from the menu
1141 auto xDispatch
= xDispatchProvider
->queryDispatch(aTargetURL
, "_self",
1142 css::frame::FrameSearchFlag::SELF
);
1145 xDispatch
->addStatusListener(xStatusListener
, aTargetURL
);
1146 xDispatch
->removeStatusListener(xStatusListener
, aTargetURL
);
1150 css::uno::Reference
<css::lang::XComponent
> xComponent(xPopupController
, css::uno::UNO_QUERY
);
1151 if (xComponent
.is())
1152 xComponent
->dispose();
1155 IMPL_LINK(OAppDetailPageHelper
, MenuSelectHdl
, const OString
&, rIdent
, void)
1157 if (rIdent
.isEmpty())
1160 css::util::URL aURL
;
1161 aURL
.Complete
= OUString::fromUtf8(rIdent
);
1163 Reference
<XDispatchProvider
> xProvider(getBorderWin().getView()->getAppController().getFrame(), UNO_QUERY
);
1164 Reference
<XDispatch
> xDisp
= xProvider
->queryDispatch(aURL
, "_self", 0);
1165 xDisp
->dispatch(aURL
, css::uno::Sequence
<css::beans::PropertyValue
>());
1167 m_xMBPreview
->set_label(stripTrailingDots(m_xMBPreview
->get_item_label(rIdent
)));
1170 OPreviewWindow::OPreviewWindow()
1174 bool OPreviewWindow::ImplGetGraphicCenterRect(const vcl::RenderContext
& rRenderContext
, const Graphic
& rGraphic
, tools::Rectangle
& rResultRect
) const
1176 const Size
aWinSize( GetOutputSizePixel() );
1177 Size
aNewSize(rRenderContext
.LogicToPixel(rGraphic
.GetPrefSize(), rGraphic
.GetPrefMapMode()));
1180 if( aNewSize
.Width() && aNewSize
.Height() )
1182 // scale to fit window
1183 const double fGrfWH
= static_cast<double>(aNewSize
.Width()) / aNewSize
.Height();
1184 const double fWinWH
= static_cast<double>(aWinSize
.Width()) / aWinSize
.Height();
1186 if ( fGrfWH
< fWinWH
)
1188 aNewSize
.setWidth( static_cast<tools::Long
>( aWinSize
.Height() * fGrfWH
) );
1189 aNewSize
.setHeight( aWinSize
.Height() );
1193 aNewSize
.setWidth( aWinSize
.Width() );
1194 aNewSize
.setHeight( static_cast<tools::Long
>( aWinSize
.Width() / fGrfWH
) );
1197 const Point
aNewPos( ( aWinSize
.Width() - aNewSize
.Width() ) >> 1,
1198 ( aWinSize
.Height() - aNewSize
.Height() ) >> 1 );
1200 rResultRect
= tools::Rectangle( aNewPos
, aNewSize
);
1207 void OPreviewWindow::Paint(vcl::RenderContext
& rRenderContext
, const tools::Rectangle
& /*rRect*/)
1209 if (ImplGetGraphicCenterRect(rRenderContext
, m_aGraphicObj
.GetGraphic(), m_aPreviewRect
))
1211 const Point
aPos(m_aPreviewRect
.TopLeft());
1212 const Size
aSize(m_aPreviewRect
.GetSize());
1214 if (m_aGraphicObj
.IsAnimated())
1215 m_aGraphicObj
.StartAnimation(rRenderContext
, aPos
, aSize
);
1217 m_aGraphicObj
.Draw(rRenderContext
, aPos
, aSize
);
1221 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */