Version 6.4.0.0.beta1, tag libreoffice-6.4.0.0.beta1
[LibreOffice.git] / cui / source / customize / SvxMenuConfigPage.cxx
blobf560a25f1632796cf71aac3972c473cf86dc6485
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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>
21 #include <sal/log.hxx>
23 #include <vcl/commandinfoprovider.hxx>
24 #include <vcl/weld.hxx>
25 #include <vcl/svapp.hxx>
27 #include <algorithm>
28 #include <strings.hrc>
29 #include <helpids.h>
31 #include <cfg.hxx>
32 #include <SvxMenuConfigPage.hxx>
33 #include <SvxConfigPageHelper.hxx>
34 #include <dialmgr.hxx>
36 #include <comphelper/processfactory.hxx>
37 #include <com/sun/star/ui/ImageType.hpp>
39 #include <dlgname.hxx>
41 SvxMenuConfigPage::SvxMenuConfigPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet, bool bIsMenuBar)
42 : SvxConfigPage(pPage, pController, rSet)
43 , m_bIsMenuBar(bIsMenuBar)
45 m_xGearBtn = m_xBuilder->weld_menu_button("menugearbtn");
46 m_xGearBtn->show();
47 m_xContentsListBox.reset(new SvxMenuEntriesListBox(m_xBuilder->weld_tree_view("menucontents"), this));
48 weld::TreeView& rTreeView = m_xContentsListBox->get_widget();
49 rTreeView.connect_size_allocate(LINK(this, SvxMenuConfigPage, MenuEntriesSizeAllocHdl));
50 Size aSize(m_xFunctions->get_size_request());
51 rTreeView.set_size_request(aSize.Width(), aSize.Height());
52 MenuEntriesSizeAllocHdl(aSize);
53 rTreeView.set_hexpand(true);
54 rTreeView.set_vexpand(true);
55 rTreeView.show();
57 rTreeView.connect_changed(
58 LINK( this, SvxMenuConfigPage, SelectMenuEntry ) );
60 rTreeView.connect_model_changed(LINK(this, SvxMenuConfigPage, ListModifiedHdl));
62 m_xGearBtn->connect_selected(LINK(this, SvxMenuConfigPage, GearHdl));
64 m_xCommandCategoryListBox->connect_changed(LINK(this, SvxMenuConfigPage, SelectCategory));
66 m_xMoveUpButton->connect_clicked( LINK( this, SvxConfigPage, MoveHdl) );
67 m_xMoveDownButton->connect_clicked( LINK( this, SvxConfigPage, MoveHdl) );
69 m_xAddCommandButton->connect_clicked( LINK( this, SvxMenuConfigPage, AddCommandHdl ) );
70 m_xRemoveCommandButton->connect_clicked( LINK( this, SvxMenuConfigPage, RemoveCommandHdl ) );
72 m_xInsertBtn->connect_selected(
73 LINK( this, SvxMenuConfigPage, InsertHdl ) );
74 m_xModifyBtn->connect_selected(
75 LINK( this, SvxMenuConfigPage, ModifyItemHdl ) );
76 m_xResetBtn->connect_clicked(
77 LINK( this, SvxMenuConfigPage, ResetMenuHdl ) );
79 // These operations are not possible on menus/context menus yet
80 m_xModifyBtn->remove_item("changeIcon");
81 m_xModifyBtn->remove_item("resetIcon");
82 m_xModifyBtn->remove_item("restoreItem");
84 if ( !bIsMenuBar )
86 //TODO: Remove this when the gear button is implemented for context menus
87 m_xGearBtn->set_sensitive(false);
88 m_xGearBtn->hide();
90 else
92 // TODO: Remove this when it is possible to reset menubar menus individually
93 m_xResetBtn->set_sensitive(false);
97 IMPL_LINK_NOARG(SvxMenuConfigPage, ListModifiedHdl, weld::TreeView&, void)
99 // regenerate with the current ordering within the list
100 SvxEntries* pEntries = GetTopLevelSelection()->GetEntries();
101 pEntries->clear();
103 for (int i = 0; i < m_xContentsListBox->n_children(); ++i)
104 pEntries->push_back(reinterpret_cast<SvxConfigEntry*>(m_xContentsListBox->get_id(i).toInt64()));
106 GetSaveInData()->SetModified();
107 GetTopLevelSelection()->SetModified();
108 UpdateButtonStates();
111 IMPL_LINK(SvxMenuConfigPage, MenuEntriesSizeAllocHdl, const Size&, rSize, void)
113 weld::TreeView& rTreeView = m_xContentsListBox->get_widget();
114 std::vector<int> aWidths;
116 int nExpectedSize = 16;
118 int nStandardImageColWidth = rTreeView.get_checkbox_column_width();
119 int nMargin = nStandardImageColWidth - nExpectedSize;
120 if (nMargin < 16)
121 nMargin = 16;
123 if (SvxConfigPageHelper::GetImageType() & css::ui::ImageType::SIZE_LARGE)
124 nExpectedSize = 24;
125 else if (SvxConfigPageHelper::GetImageType() & css::ui::ImageType::SIZE_32)
126 nExpectedSize = 32;
128 int nImageColWidth = nExpectedSize + nMargin;
130 aWidths.push_back(nImageColWidth);
131 aWidths.push_back(rSize.Width() - (nImageColWidth + nStandardImageColWidth));
132 rTreeView.set_column_fixed_widths(aWidths);
135 SvxMenuConfigPage::~SvxMenuConfigPage()
137 for (int i = 0, nCount = m_xSaveInListBox->get_count(); i < nCount; ++i)
138 delete reinterpret_cast<SaveInData*>(m_xSaveInListBox->get_id(i).toInt64());
139 m_xSaveInListBox->clear();
142 // Populates the Menu combo box
143 void SvxMenuConfigPage::Init()
145 // ensure that the UI is cleared before populating it
146 m_xTopLevelListBox->clear();
147 m_xContentsListBox->clear();
149 ReloadTopLevelListBox();
151 m_xTopLevelListBox->set_active(0);
152 SelectElement();
154 m_xCommandCategoryListBox->Init(
155 comphelper::getProcessComponentContext(),
156 m_xFrame,
157 vcl::CommandInfoProvider::GetModuleIdentifier(m_xFrame));
158 m_xCommandCategoryListBox->categorySelected(m_xFunctions.get(), OUString(), GetSaveInData());
161 IMPL_LINK_NOARG(SvxMenuConfigPage, SelectMenuEntry, weld::TreeView&, void)
163 UpdateButtonStates();
166 void SvxMenuConfigPage::UpdateButtonStates()
168 // Disable Up and Down buttons depending on current selection
169 int selection = m_xContentsListBox->get_selected_index();
171 bool bIsSeparator =
172 selection != -1 && reinterpret_cast<SvxConfigEntry*>(m_xContentsListBox->get_id(selection).toInt64())->IsSeparator();
173 bool bIsValidSelection =
174 !(m_xContentsListBox->n_children() == 0 || selection == -1);
176 m_xMoveUpButton->set_sensitive(
177 bIsValidSelection && selection != 0 );
178 m_xMoveDownButton->set_sensitive(
179 bIsValidSelection && selection != m_xContentsListBox->n_children() - 1);
181 m_xRemoveCommandButton->set_sensitive( bIsValidSelection );
183 m_xModifyBtn->set_sensitive( bIsValidSelection && !bIsSeparator);
185 // If there is no top level selection (menu), then everything working on the right box
186 // which contains the functions of the selected menu/toolbar needs to be disabled
187 SvxConfigEntry* pMenuData = GetTopLevelSelection();
189 m_xInsertBtn->set_sensitive(pMenuData != nullptr);
191 m_xAddCommandButton->set_sensitive(pMenuData != nullptr);
192 m_xRemoveCommandButton->set_sensitive(pMenuData != nullptr);
194 //Handle the gear button
195 if (pMenuData && m_bIsMenuBar)
197 // Add option (gear_add) will always be enabled
198 m_xGearBtn->set_item_sensitive( "menu_gear_delete", pMenuData->IsDeletable() );
199 m_xGearBtn->set_item_sensitive( "menu_gear_rename", pMenuData->IsRenamable() );
200 m_xGearBtn->set_item_sensitive( "menu_gear_move", pMenuData->IsMovable() );
204 void SvxMenuConfigPage::DeleteSelectedTopLevel()
206 SvxConfigEntry* pMenuData = GetTopLevelSelection();
208 SvxEntries* pParentEntries =
209 FindParentForChild( GetSaveInData()->GetEntries(), pMenuData );
211 SvxConfigPageHelper::RemoveEntry( pParentEntries, pMenuData );
212 delete pMenuData;
214 ReloadTopLevelListBox();
216 GetSaveInData()->SetModified( );
219 void SvxMenuConfigPage::DeleteSelectedContent()
221 int nActEntry = m_xContentsListBox->get_selected_index();
223 if (nActEntry != -1)
225 // get currently selected menu entry
226 SvxConfigEntry* pMenuEntry =
227 reinterpret_cast<SvxConfigEntry*>(m_xContentsListBox->get_id(nActEntry).toInt64());
229 // get currently selected menu
230 SvxConfigEntry* pMenu = GetTopLevelSelection();
232 // remove menu entry from the list for this menu
233 SvxConfigPageHelper::RemoveEntry( pMenu->GetEntries(), pMenuEntry );
235 // remove menu entry from UI
236 m_xContentsListBox->remove(nActEntry);
238 // if this is a submenu entry, redraw the menus list box
239 if ( pMenuEntry->IsPopup() )
241 ReloadTopLevelListBox();
244 // delete data for menu entry
245 delete pMenuEntry;
247 GetSaveInData()->SetModified();
248 pMenu->SetModified();
252 short SvxMenuConfigPage::QueryReset()
254 OUString msg = CuiResId( RID_SVXSTR_CONFIRM_MENU_RESET );
256 OUString saveInName = m_xSaveInListBox->get_active_text();
258 OUString label = SvxConfigPageHelper::replaceSaveInName( msg, saveInName );
260 std::unique_ptr<weld::MessageDialog> xQueryBox(Application::CreateMessageDialog(GetFrameWeld(),
261 VclMessageType::Question, VclButtonsType::YesNo,
262 label));
263 return xQueryBox->run();
266 void SvxMenuConfigPage::SelectElement()
268 m_xContentsListBox->clear();
270 SvxConfigEntry* pMenuData = GetTopLevelSelection();
272 if ( pMenuData )
274 SvxEntries* pEntries = pMenuData->GetEntries();
276 int i = 0;
277 for (auto const& entry : *pEntries)
279 OUString sId(OUString::number(reinterpret_cast<sal_Int64>(entry)));
280 m_xContentsListBox->insert(i, sId);
281 InsertEntryIntoUI(entry, i, 0);
282 ++i;
286 UpdateButtonStates();
289 IMPL_LINK(SvxMenuConfigPage, GearHdl, const OString&, rIdent, void)
291 if (rIdent == "menu_gear_add")
293 SvxMainMenuOrganizerDialog aDialog(GetFrameWeld(),
294 GetSaveInData()->GetEntries(), nullptr, true );
296 if (aDialog.run() == RET_OK)
298 GetSaveInData()->SetEntries(aDialog.ReleaseEntries());
299 ReloadTopLevelListBox(aDialog.GetSelectedEntry());
300 GetSaveInData()->SetModified();
303 else if (rIdent == "menu_gear_delete")
305 DeleteSelectedTopLevel();
307 else if (rIdent == "menu_gear_rename")
309 SvxConfigEntry* pMenuData = GetTopLevelSelection();
311 OUString sCurrentName( SvxConfigPageHelper::stripHotKey( pMenuData->GetName() ) );
312 OUString sDesc = CuiResId( RID_SVXSTR_LABEL_NEW_NAME );
314 SvxNameDialog aNameDialog(GetFrameWeld(), sCurrentName, sDesc);
315 aNameDialog.set_help_id(HID_SVX_CONFIG_RENAME_MENU);
316 aNameDialog.set_title(CuiResId(RID_SVXSTR_RENAME_MENU));
318 if ( aNameDialog.run() == RET_OK )
320 OUString sNewName = aNameDialog.GetName();
322 if ( sCurrentName == sNewName )
323 return;
325 pMenuData->SetName( sNewName );
327 ReloadTopLevelListBox();
329 GetSaveInData()->SetModified();
332 else if (rIdent == "menu_gear_move")
334 SvxConfigEntry* pMenuData = GetTopLevelSelection();
336 SvxMainMenuOrganizerDialog aDialog(GetFrameWeld(), GetSaveInData()->GetEntries(),
337 pMenuData, false );
338 if (aDialog.run() == RET_OK)
340 GetSaveInData()->SetEntries(aDialog.ReleaseEntries());
342 ReloadTopLevelListBox();
344 GetSaveInData()->SetModified();
347 else
349 //This block should never be reached
350 SAL_WARN("cui.customize", "Unknown gear menu option: " << rIdent);
351 return;
354 UpdateButtonStates();
357 IMPL_LINK_NOARG(SvxMenuConfigPage, SelectCategory, weld::ComboBox&, void)
359 OUString aSearchTerm( m_xSearchEdit->get_text() );
361 m_xCommandCategoryListBox->categorySelected(m_xFunctions.get(), aSearchTerm, GetSaveInData());
364 IMPL_LINK_NOARG( SvxMenuConfigPage, AddCommandHdl, weld::Button&, void )
366 int nPos = AddFunction(-1, /*bAllowDuplicates*/false);
367 if (nPos == -1)
368 return;
369 SvxConfigEntry* pEntry =
370 reinterpret_cast<SvxConfigEntry*>(m_xContentsListBox->get_id(nPos).toInt64());
371 InsertEntryIntoUI(pEntry, nPos, 0);
374 IMPL_LINK_NOARG( SvxMenuConfigPage, RemoveCommandHdl, weld::Button&, void )
376 DeleteSelectedContent();
377 if ( GetSaveInData()->IsModified() )
379 UpdateButtonStates();
383 IMPL_LINK(SvxMenuConfigPage, InsertHdl, const OString&, rIdent, void)
385 if (rIdent == "insertseparator")
387 SvxConfigEntry* pNewEntryData = new SvxConfigEntry;
388 pNewEntryData->SetUserDefined();
389 int nPos = AppendEntry(pNewEntryData, -1);
390 InsertEntryIntoUI(pNewEntryData, nPos, 0);
392 else if (rIdent == "insertsubmenu")
394 OUString aNewName;
395 OUString aDesc = CuiResId( RID_SVXSTR_SUBMENU_NAME );
397 SvxNameDialog aNameDialog(GetFrameWeld(), aNewName, aDesc);
398 aNameDialog.set_help_id(HID_SVX_CONFIG_NAME_SUBMENU);
399 aNameDialog.set_title(CuiResId( RID_SVXSTR_ADD_SUBMENU));
401 if (aNameDialog.run() == RET_OK)
403 aNewName = aNameDialog.GetName();
405 SvxConfigEntry* pNewEntryData =
406 new SvxConfigEntry( aNewName, aNewName, true, /*bParentData*/false );
407 pNewEntryData->SetName( aNewName );
408 pNewEntryData->SetUserDefined();
410 int nPos = AppendEntry(pNewEntryData, -1);
411 InsertEntryIntoUI(pNewEntryData, nPos, 0);
413 ReloadTopLevelListBox();
415 m_xContentsListBox->scroll_to_row(nPos);
416 m_xContentsListBox->select(nPos);
418 GetSaveInData()->SetModified();
422 else
424 //This block should never be reached
425 SAL_WARN("cui.customize", "Unknown insert option: " << rIdent);
426 return;
429 if ( GetSaveInData()->IsModified() )
431 UpdateButtonStates();
435 IMPL_LINK(SvxMenuConfigPage, ModifyItemHdl, const OString&, rIdent, void)
437 if (rIdent == "renameItem")
439 int nActEntry = m_xContentsListBox->get_selected_index();
440 SvxConfigEntry* pEntry =
441 reinterpret_cast<SvxConfigEntry*>(m_xContentsListBox->get_id(nActEntry).toInt64());
443 OUString aNewName( SvxConfigPageHelper::stripHotKey( pEntry->GetName() ) );
444 OUString aDesc = CuiResId( RID_SVXSTR_LABEL_NEW_NAME );
446 SvxNameDialog aNameDialog(GetFrameWeld(), aNewName, aDesc);
447 aNameDialog.set_help_id(HID_SVX_CONFIG_RENAME_MENU_ITEM);
448 aNameDialog.set_title(CuiResId(RID_SVXSTR_RENAME_MENU));
450 if (aNameDialog.run() == RET_OK)
452 aNewName = aNameDialog.GetName();
454 pEntry->SetName( aNewName );
455 m_xContentsListBox->set_text(nActEntry, aNewName, 1);
457 GetSaveInData()->SetModified();
458 GetTopLevelSelection()->SetModified();
461 else
463 //This block should never be reached
464 SAL_WARN("cui.customize", "Unknown insert option: " << rIdent);
465 return;
468 if ( GetSaveInData()->IsModified() )
470 UpdateButtonStates();
474 IMPL_LINK_NOARG(SvxMenuConfigPage, ResetMenuHdl, weld::Button&, void)
476 SvxConfigEntry* pMenuData = GetTopLevelSelection();
478 if (pMenuData == nullptr)
480 SAL_WARN("cui.customize", "RHB top level selection is null. A menu must be selected to reset!");
481 return;
484 std::unique_ptr<weld::MessageDialog> xQueryBox(Application::CreateMessageDialog(GetFrameWeld(),
485 VclMessageType::Question, VclButtonsType::YesNo,
486 CuiResId(RID_SVXSTR_CONFIRM_RESTORE_DEFAULT_MENU)));
488 // Resetting individual top-level menus is not possible at the moment.
489 // So we are resetting only if it is a context menu
490 if (!m_bIsMenuBar && xQueryBox->run() == RET_YES)
492 sal_Int32 nPos = m_xTopLevelListBox->get_active();
493 ContextMenuSaveInData* pSaveInData = static_cast< ContextMenuSaveInData* >(GetSaveInData());
495 pSaveInData->ResetContextMenu(pMenuData);
497 // ensure that the UI is cleared before populating it
498 m_xTopLevelListBox->clear();
499 m_xContentsListBox->clear();
501 ReloadTopLevelListBox();
503 // Reselect the reset menu
504 m_xTopLevelListBox->set_active(nPos);
505 SelectElement();
509 SaveInData* SvxMenuConfigPage::CreateSaveInData(
510 const css::uno::Reference< css::ui::XUIConfigurationManager >& xCfgMgr,
511 const css::uno::Reference< css::ui::XUIConfigurationManager >& xParentCfgMgr,
512 const OUString& aModuleId,
513 bool bDocConfig )
515 if ( !m_bIsMenuBar )
516 return static_cast< SaveInData* >( new ContextMenuSaveInData( xCfgMgr, xParentCfgMgr, aModuleId, bDocConfig ) );
518 return static_cast< SaveInData* >( new MenuSaveInData( xCfgMgr, xParentCfgMgr, aModuleId, bDocConfig ) );
521 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */