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 <sal/config.h>
22 #include <vcl/commandinfoprovider.hxx>
23 #include <vcl/event.hxx>
24 #include <vcl/weld.hxx>
25 #include <vcl/svapp.hxx>
31 #include <strings.hrc>
34 #include <SvxNotebookbarConfigPage.hxx>
35 #include <SvxConfigPageHelper.hxx>
36 #include <dialmgr.hxx>
37 #include <libxml/parser.h>
38 #include <osl/file.hxx>
39 #include <CustomNotebookbarGenerator.hxx>
40 #include <sfx2/notebookbar/SfxNotebookBar.hxx>
41 #include <unotools/configmgr.hxx>
42 #include <comphelper/processfactory.hxx>
43 #include <com/sun/star/frame/theUICommandDescription.hpp>
44 #include <com/sun/star/ui/ImageType.hpp>
46 namespace uno
= com::sun::star::uno
;
47 namespace frame
= com::sun::star::frame
;
48 namespace lang
= com::sun::star::lang
;
49 namespace container
= com::sun::star::container
;
50 namespace beans
= com::sun::star::beans
;
51 namespace graphic
= com::sun::star::graphic
;
53 static bool isCategoryAvailable(const OUString
& sClassId
, const OUString
& sUIItemId
,
54 const OUString
& sActiveCategory
, bool& isCategory
)
56 if (sUIItemId
== sActiveCategory
)
58 else if ((sClassId
== "GtkMenu" || sClassId
== "GtkGrid") && sUIItemId
!= sActiveCategory
)
66 static OUString
charToString(const char* cString
)
68 return OUString(cString
, strlen(cString
), RTL_TEXTENCODING_UTF8
);
71 static OUString
getFileName(const OUString
& aFileName
)
73 if (aFileName
== "notebookbar.ui")
75 else if (aFileName
== "notebookbar_compact.ui")
76 return "TabbedCompact";
77 else if (aFileName
== "notebookbar_groupedbar_full.ui")
79 else if (aFileName
== "notebookbar_groupedbar_compact.ui")
80 return "GroupedbarCompact";
85 static OUString
getModuleId(const OUString
& sModuleName
)
87 if (sModuleName
== "Writer")
88 return "com.sun.star.text.TextDocument";
89 else if (sModuleName
== "Draw")
90 return "com.sun.star.drawing.DrawingDocument";
91 else if (sModuleName
== "Impress")
92 return "com.sun.star.presentation.PresentationDocument";
93 else if (sModuleName
== "Calc")
94 return "com.sun.star.sheet.SpreadsheetDocument";
99 SvxNotebookbarConfigPage::SvxNotebookbarConfigPage(weld::Container
* pPage
,
100 weld::DialogController
* pController
,
101 const SfxItemSet
& rSet
)
102 : SvxConfigPage(pPage
, pController
, rSet
)
104 m_xCommandCategoryListBox
->set_visible(false);
105 m_xDescriptionFieldLb
->set_visible(false);
106 m_xSearchEdit
->set_visible(false);
107 m_xDescriptionField
->set_visible(false);
108 m_xMoveUpButton
->set_visible(false);
109 m_xMoveDownButton
->set_visible(false);
110 m_xAddCommandButton
->set_visible(false);
111 m_xRemoveCommandButton
->set_visible(false);
112 m_xLeftFunctionLabel
->set_visible(false);
113 m_xSearchLabel
->set_visible(false);
114 m_xCategoryLabel
->set_visible(false);
115 m_xInsertBtn
->set_visible(false);
116 m_xModifyBtn
->set_visible(false);
117 m_xResetBtn
->set_visible(false);
118 m_xCustomizeLabel
->set_visible(false);
120 weld::TreeView
& rCommandCategoryBox
= m_xFunctions
->get_widget();
121 rCommandCategoryBox
.hide();
123 m_xContentsListBox
.reset(
124 new SvxNotebookbarEntriesListBox(m_xBuilder
->weld_tree_view("toolcontents"), this));
125 m_xDropTargetHelper
.reset(
126 new SvxConfigPageFunctionDropTarget(*this, m_xContentsListBox
->get_widget()));
127 std::vector
<int> aWidths
;
128 weld::TreeView
& rTreeView
= m_xContentsListBox
->get_widget();
129 Size
aSize(m_xFunctions
->get_size_request());
130 rTreeView
.set_size_request(aSize
.Width(), aSize
.Height());
132 int nExpectedSize
= 16;
134 int nStandardImageColWidth
= rTreeView
.get_checkbox_column_width();
135 int nMargin
= nStandardImageColWidth
- nExpectedSize
;
139 if (SvxConfigPageHelper::GetImageType() & css::ui::ImageType::SIZE_LARGE
)
141 else if (SvxConfigPageHelper::GetImageType() & css::ui::ImageType::SIZE_32
)
144 int nImageColWidth
= nExpectedSize
+ nMargin
;
146 aWidths
.push_back(nStandardImageColWidth
);
147 aWidths
.push_back(nImageColWidth
);
148 rTreeView
.set_column_fixed_widths(aWidths
);
150 rTreeView
.set_hexpand(true);
151 rTreeView
.set_vexpand(true);
152 rTreeView
.set_help_id(HID_SVX_CONFIG_NOTEBOOKBAR_CONTENTS
);
156 SvxNotebookbarConfigPage::~SvxNotebookbarConfigPage() {}
158 void SvxNotebookbarConfigPage::DeleteSelectedTopLevel() {}
160 void SvxNotebookbarConfigPage::DeleteSelectedContent() {}
162 void SvxNotebookbarConfigPage::Init()
164 m_xTopLevelListBox
->clear();
165 m_xContentsListBox
->clear();
166 m_xSaveInListBox
->clear();
167 CustomNotebookbarGenerator::createCustomizedUIFile();
168 OUString sNotebookbarInterface
= getFileName(m_sFileName
);
171 = utl::ConfigManager::getProductName() + " " + m_sAppName
+ " - " + sNotebookbarInterface
;
172 OUString sSaveInListBoxID
= notebookbarTabScope
;
174 m_xSaveInListBox
->append(sSaveInListBoxID
, sScopeName
);
175 m_xSaveInListBox
->set_active_id(sSaveInListBoxID
);
177 m_xTopLevelListBox
->append("NotebookBar", "All Commands");
178 m_xTopLevelListBox
->set_active_id("NotebookBar");
182 SaveInData
* SvxNotebookbarConfigPage::CreateSaveInData(
183 const css::uno::Reference
<css::ui::XUIConfigurationManager
>& xCfgMgr
,
184 const css::uno::Reference
<css::ui::XUIConfigurationManager
>& xParentCfgMgr
,
185 const OUString
& aModuleId
, bool bDocConfig
)
187 return static_cast<SaveInData
*>(
188 new ToolbarSaveInData(xCfgMgr
, xParentCfgMgr
, aModuleId
, bDocConfig
));
191 void SvxNotebookbarConfigPage::UpdateButtonStates() {}
193 short SvxNotebookbarConfigPage::QueryReset()
195 OUString msg
= CuiResId(RID_SVXSTR_CONFIRM_TOOLBAR_RESET
);
197 OUString saveInName
= m_xSaveInListBox
->get_active_text();
199 OUString label
= SvxConfigPageHelper::replaceSaveInName(msg
, saveInName
);
201 std::unique_ptr
<weld::MessageDialog
> xQueryBox(Application::CreateMessageDialog(
202 GetFrameWeld(), VclMessageType::Question
, VclButtonsType::YesNo
, label
));
203 int nValue
= xQueryBox
->run();
204 if (nValue
== RET_YES
)
206 OUString sOriginalUIPath
= CustomNotebookbarGenerator::getOriginalUIPath();
207 OUString sCustomizedUIPath
= CustomNotebookbarGenerator::getCustomizedUIPath();
208 osl::File::copy(sOriginalUIPath
, sCustomizedUIPath
);
209 OUString sNotebookbarInterface
= getFileName(m_sFileName
);
210 Sequence
<OUString
> sSequenceEntries
;
211 CustomNotebookbarGenerator::setCustomizedUIItem(sSequenceEntries
, sNotebookbarInterface
);
212 OUString sUIPath
= "modules/s" + m_sAppName
.toAsciiLowerCase() + "/ui/";
213 sfx2::SfxNotebookBar::ReloadNotebookBar(sUIPath
);
218 void SvxConfigPage::InsertEntryIntoNotebookbarTabUI(const OUString
& sClassId
,
219 const OUString
& sUIItemId
,
220 const OUString
& sUIItemCommand
,
221 weld::TreeView
& rTreeView
,
222 weld::TreeIter
& rIter
, int nStartCol
)
224 css::uno::Reference
<css::container::XNameAccess
> m_xCommandToLabelMap
,
225 m_xGlobalCommandToLabelMap
;
226 uno::Reference
<uno::XComponentContext
> xContext
= ::comphelper::getProcessComponentContext();
227 uno::Reference
<container::XNameAccess
> xNameAccess(
228 css::frame::theUICommandDescription::get(xContext
));
230 uno::Sequence
<beans::PropertyValue
> aPropSeq
, aGlobalPropSeq
;
232 xNameAccess
->getByName("com.sun.star.text.GlobalDocument") >>= m_xGlobalCommandToLabelMap
;
233 xNameAccess
->getByName(getModuleId(m_sAppName
)) >>= m_xCommandToLabelMap
;
237 uno::Any aModuleVal
= m_xCommandToLabelMap
->getByName(sUIItemCommand
);
239 aModuleVal
>>= aPropSeq
;
241 catch (container::NoSuchElementException
&)
247 uno::Any aGlobalVal
= m_xGlobalCommandToLabelMap
->getByName(sUIItemCommand
);
248 aGlobalVal
>>= aGlobalPropSeq
;
250 catch (container::NoSuchElementException
&)
255 for (sal_Int32 i
= 0; i
< aPropSeq
.getLength(); ++i
)
256 if (aPropSeq
[i
].Name
== "Name")
257 aPropSeq
[i
].Value
>>= aLabel
;
258 if (aLabel
.isEmpty())
259 for (sal_Int32 i
= 0; i
< aGlobalPropSeq
.getLength(); ++i
)
260 if (aGlobalPropSeq
[i
].Name
== "Name")
261 aGlobalPropSeq
[i
].Value
>>= aLabel
;
263 OUString aName
= SvxConfigPageHelper::stripHotKey(aLabel
);
265 if (sClassId
== "GtkSeparatorMenuItem" || sClassId
== "GtkSeparator")
267 OUString sDataInTree
= "--------------------------------------------";
268 rTreeView
.set_text(rIter
, sDataInTree
, nStartCol
+ 1);
274 auto xImage
= GetSaveInData()->GetImage(sUIItemCommand
);
276 rTreeView
.set_image(rIter
, xImage
, nStartCol
);
277 rTreeView
.set_text(rIter
, aName
, nStartCol
+ 1);
278 rTreeView
.set_id(rIter
, sUIItemId
);
282 void SvxNotebookbarConfigPage::getNodeValue(xmlNode
* pNodePtr
, NotebookbarEntries
& aNodeEntries
)
284 pNodePtr
= pNodePtr
->xmlChildrenNode
;
287 if (!(xmlStrcmp(pNodePtr
->name
, reinterpret_cast<const xmlChar
*>("property"))))
289 xmlChar
* UriValue
= xmlGetProp(pNodePtr
, reinterpret_cast<const xmlChar
*>("name"));
290 if (!(xmlStrcmp(UriValue
, reinterpret_cast<const xmlChar
*>("visible"))))
292 xmlChar
* aValue
= xmlNodeGetContent(pNodePtr
);
293 const char* cVisibleValue
= reinterpret_cast<const char*>(aValue
);
294 aNodeEntries
.sVisibleValue
= charToString(cVisibleValue
);
297 if (!(xmlStrcmp(UriValue
, reinterpret_cast<const xmlChar
*>("action_name"))))
299 xmlChar
* aValue
= xmlNodeGetContent(pNodePtr
);
300 const char* cActionName
= reinterpret_cast<const char*>(aValue
);
301 aNodeEntries
.sActionName
= charToString(cActionName
);
306 pNodePtr
= pNodePtr
->next
;
310 void SvxNotebookbarConfigPage::searchNodeandAttribute(std::vector
<NotebookbarEntries
>& aEntries
,
311 std::vector
<CategoriesEntries
>& aCategoryList
,
312 OUString
& sActiveCategory
,
313 CategoriesEntries
& aCurItemEntry
,
314 xmlNode
* pNodePtr
, bool isCategory
)
316 pNodePtr
= pNodePtr
->xmlChildrenNode
;
319 if (pNodePtr
->type
== XML_ELEMENT_NODE
)
321 const char* cNodeName
= reinterpret_cast<const char*>(pNodePtr
->name
);
322 if (strcmp(cNodeName
, "object") == 0)
326 xmlChar
* UriValue
= xmlGetProp(pNodePtr
, reinterpret_cast<const xmlChar
*>("id"));
327 const char* cUIItemID
= reinterpret_cast<const char*>(UriValue
);
328 OUString sUIItemId
= charToString(cUIItemID
);
331 UriValue
= xmlGetProp(pNodePtr
, reinterpret_cast<const xmlChar
*>("class"));
332 const char* cClassId
= reinterpret_cast<const char*>(UriValue
);
333 OUString sClassId
= charToString(cClassId
);
336 CategoriesEntries aCategoryEntry
;
337 if (sClassId
== "sfxlo-PriorityHBox")
339 aCategoryEntry
.sDisplayName
= sUIItemId
;
340 aCategoryEntry
.sUIItemId
= sUIItemId
;
341 aCategoryEntry
.sClassType
= sClassId
;
342 aCategoryList
.push_back(aCategoryEntry
);
344 aCurItemEntry
= aCategoryEntry
;
346 else if (sClassId
== "sfxlo-PriorityMergedHBox")
348 aCategoryEntry
.sDisplayName
= aCurItemEntry
.sDisplayName
+ " | " + sUIItemId
;
349 aCategoryEntry
.sUIItemId
= sUIItemId
;
350 aCategoryEntry
.sClassType
= sClassId
;
352 if (aCurItemEntry
.sClassType
== sClassId
)
355 aCategoryEntry
.sDisplayName
356 = aCurItemEntry
.sDisplayName
.getToken(rPos
, ' ', rPos
) + " | "
359 aCategoryList
.push_back(aCategoryEntry
);
360 aCurItemEntry
= aCategoryEntry
;
362 else if (sClassId
== "svtlo-ManagedMenuButton")
365 sSecondVal
= sUIItemId
.getToken(rPos
, ':', rPos
);
366 if (!sSecondVal
.isEmpty())
368 aCategoryEntry
.sDisplayName
369 = aCurItemEntry
.sDisplayName
+ " | " + sSecondVal
;
370 aCategoryEntry
.sUIItemId
= sSecondVal
;
371 aCategoryList
.push_back(aCategoryEntry
);
375 NotebookbarEntries nodeEntries
;
376 if (isCategoryAvailable(sClassId
, sUIItemId
, sActiveCategory
, isCategory
)
380 if (sClassId
== "GtkMenuItem" || sClassId
== "GtkToolButton"
381 || sClassId
== "GtkMenuToolButton"
382 || (sClassId
== "svtlo-ManagedMenuButton" && sSecondVal
.isEmpty()))
384 nodeEntries
.sClassId
= sClassId
;
385 nodeEntries
.sUIItemId
= sUIItemId
;
386 nodeEntries
.sDisplayName
= sUIItemId
;
388 getNodeValue(pNodePtr
, nodeEntries
);
389 aEntries
.push_back(nodeEntries
);
391 else if (sClassId
== "GtkSeparatorMenuItem" || sClassId
== "GtkSeparator")
393 nodeEntries
.sClassId
= sClassId
;
394 nodeEntries
.sUIItemId
= sUIItemId
;
395 nodeEntries
.sDisplayName
= "Null";
396 nodeEntries
.sVisibleValue
= "Null";
397 nodeEntries
.sActionName
= "Null";
398 aEntries
.push_back(nodeEntries
);
400 else if (sClassId
== "sfxlo-PriorityHBox"
401 || sClassId
== "sfxlo-PriorityMergedHBox"
402 || sClassId
== "svtlo-ManagedMenuButton")
404 nodeEntries
.sClassId
= sClassId
;
405 nodeEntries
.sUIItemId
= sUIItemId
;
406 nodeEntries
.sDisplayName
407 = aCategoryList
[aCategoryList
.size() - 1].sDisplayName
;
408 nodeEntries
.sVisibleValue
= "Null";
409 nodeEntries
.sActionName
= "Null";
410 aEntries
.push_back(nodeEntries
);
414 searchNodeandAttribute(aEntries
, aCategoryList
, sActiveCategory
, aCurItemEntry
,
415 pNodePtr
, isCategory
);
417 pNodePtr
= pNodePtr
->next
;
421 void SvxNotebookbarConfigPage::FillFunctionsList(xmlNodePtr pRootNodePtr
,
422 std::vector
<NotebookbarEntries
>& aEntries
,
423 std::vector
<CategoriesEntries
>& aCategoryList
,
424 OUString
& sActiveCategory
)
426 CategoriesEntries aCurItemEntry
;
427 searchNodeandAttribute(aEntries
, aCategoryList
, sActiveCategory
, aCurItemEntry
, pRootNodePtr
,
431 void SvxNotebookbarConfigPage::SelectElement()
433 OString sUIFileUIPath
= CustomNotebookbarGenerator::getSystemPath(
434 CustomNotebookbarGenerator::getCustomizedUIPath());
435 xmlDocPtr pDoc
= xmlParseFile(sUIFileUIPath
.getStr());
436 xmlNodePtr pNodePtr
= xmlDocGetRootElement(pDoc
);
438 std::vector
<NotebookbarEntries
> aEntries
;
439 std::vector
<CategoriesEntries
> aCategoryList
;
440 OUString sActiveCategory
= m_xTopLevelListBox
->get_active_id();
441 FillFunctionsList(pNodePtr
, aEntries
, aCategoryList
, sActiveCategory
);
443 if (m_xTopLevelListBox
->get_count() == 1)
445 for (std::size_t nIdx
= 0; nIdx
< aCategoryList
.size(); nIdx
++)
446 m_xTopLevelListBox
->append(aCategoryList
[nIdx
].sUIItemId
,
447 aCategoryList
[nIdx
].sDisplayName
);
449 unsigned long nStart
= 0;
450 if (aEntries
[nStart
].sClassId
== "sfxlo-PriorityHBox"
451 || aEntries
[nStart
].sClassId
== "sfxlo-PriorityMergedHBox")
454 std::vector
<NotebookbarEntries
> aTempEntries
;
455 for (std::size_t nIdx
= nStart
; nIdx
< aEntries
.size(); nIdx
++)
457 if (aEntries
[nIdx
].sClassId
== "svtlo-ManagedMenuButton")
459 aTempEntries
.push_back(aEntries
[nIdx
]);
460 std::vector
<NotebookbarEntries
> aGtkEntries
;
462 sActiveCategory
= aEntries
[nIdx
].sUIItemId
.getToken(rPos
, ':', rPos
);
463 FillFunctionsList(pNodePtr
, aGtkEntries
, aCategoryList
, sActiveCategory
);
464 for (std::size_t Idx
= 0; Idx
< aGtkEntries
.size(); Idx
++)
465 aTempEntries
.push_back(aGtkEntries
[Idx
]);
469 aTempEntries
.push_back(aEntries
[nIdx
]);
472 aEntries
= aTempEntries
;
473 aTempEntries
.clear();
475 weld::TreeView
& rTreeView
= m_xContentsListBox
->get_widget();
476 rTreeView
.bulk_insert_for_each(
477 aEntries
.size(), [this, &rTreeView
, &aEntries
](weld::TreeIter
& rIter
, int nIdx
) {
478 OUString
sId(OUString::number(nIdx
));
479 rTreeView
.set_id(rIter
, sId
);
480 if (aEntries
[nIdx
].sActionName
!= "Null")
482 if (aEntries
[nIdx
].sVisibleValue
== "True")
484 rTreeView
.set_toggle(rIter
, TRISTATE_TRUE
, 0);
488 rTreeView
.set_toggle(rIter
, TRISTATE_FALSE
, 0);
491 InsertEntryIntoNotebookbarTabUI(aEntries
[nIdx
].sClassId
, aEntries
[nIdx
].sDisplayName
,
492 aEntries
[nIdx
].sActionName
, rTreeView
, rIter
, 1);
503 SvxNotebookbarEntriesListBox::SvxNotebookbarEntriesListBox(std::unique_ptr
<weld::TreeView
> xParent
,
505 : SvxMenuEntriesListBox(std::move(xParent
), pPg
)
507 m_xControl
->connect_toggled(LINK(this, SvxNotebookbarEntriesListBox
, CheckButtonHdl
));
508 m_xControl
->connect_key_press(Link
<const KeyEvent
&, bool>());
509 m_xControl
->connect_key_press(LINK(this, SvxNotebookbarEntriesListBox
, KeyInputHdl
));
512 SvxNotebookbarEntriesListBox::~SvxNotebookbarEntriesListBox() {}
514 static void EditRegistryFile(const OUString
& sUIItemId
, const OUString
& sSetEntry
,
515 const OUString
& sNotebookbarInterface
)
518 Sequence
<OUString
> aOldEntries
519 = CustomNotebookbarGenerator::getCustomizedUIItem(sNotebookbarInterface
);
520 Sequence
<OUString
> aNewEntries(aOldEntries
.getLength() + 1);
521 for (int nIdx
= 0; nIdx
< aOldEntries
.getLength(); nIdx
++)
524 OUString sFirstValue
= aOldEntries
[nIdx
].getToken(rPos
, ',', rPos
);
525 if (sFirstValue
== sUIItemId
)
527 aOldEntries
[nIdx
] = sSetEntry
;
531 aNewEntries
[nIdx
] = aOldEntries
[nIdx
];
536 aNewEntries
[aOldEntries
.getLength()] = sSetEntry
;
537 CustomNotebookbarGenerator::setCustomizedUIItem(aNewEntries
, sNotebookbarInterface
);
541 CustomNotebookbarGenerator::setCustomizedUIItem(aOldEntries
, sNotebookbarInterface
);
545 void SvxNotebookbarEntriesListBox::ChangedVisibility(int nRow
)
547 OUString sUIItemId
= m_xControl
->get_selected_id();
548 OUString sNotebookbarInterface
= getFileName(m_pPage
->GetFileName());
551 if (m_xControl
->get_toggle(nRow
, 0) == TRISTATE_TRUE
)
555 OUString sSetEntries
= sUIItemId
+ ",visible," + sVisible
;
556 Sequence
<OUString
> sSeqOfEntries(1);
557 sSeqOfEntries
[0] = sSetEntries
;
558 EditRegistryFile(sUIItemId
, sSetEntries
, sNotebookbarInterface
);
559 CustomNotebookbarGenerator::modifyCustomizedUIFile(sSeqOfEntries
);
560 OUString sUIPath
= "modules/s" + m_pPage
->GetAppName().toAsciiLowerCase() + "/ui/";
561 sfx2::SfxNotebookBar::ReloadNotebookBar(sUIPath
);
564 IMPL_LINK(SvxNotebookbarEntriesListBox
, CheckButtonHdl
, const row_col
&, rRowCol
, void)
566 ChangedVisibility(rRowCol
.first
);
569 IMPL_LINK(SvxNotebookbarEntriesListBox
, KeyInputHdl
, const KeyEvent
&, rKeyEvent
, bool)
571 if (rKeyEvent
.GetKeyCode() == KEY_SPACE
)
573 int nRow
= m_xControl
->get_selected_index();
574 m_xControl
->set_toggle(
575 nRow
, m_xControl
->get_toggle(nRow
, 0) == TRISTATE_TRUE
? TRISTATE_FALSE
: TRISTATE_TRUE
,
577 ChangedVisibility(nRow
);
580 return SvxMenuEntriesListBox::KeyInputHdl(rKeyEvent
);
583 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */