bump product version to 6.4.0.3
[LibreOffice.git] / cui / source / customize / SvxMenuConfigPage.cxx
blob7289b3506a7c6e3eace1e4e5081e331dac9fbc24
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 m_xDropTargetHelper.reset(new SvxConfigPageFunctionDropTarget(*this, rTreeView));
50 rTreeView.connect_size_allocate(LINK(this, SvxMenuConfigPage, MenuEntriesSizeAllocHdl));
51 Size aSize(m_xFunctions->get_size_request());
52 rTreeView.set_size_request(aSize.Width(), aSize.Height());
53 MenuEntriesSizeAllocHdl(aSize);
54 rTreeView.set_hexpand(true);
55 rTreeView.set_vexpand(true);
56 rTreeView.show();
58 rTreeView.connect_changed(
59 LINK( this, SvxMenuConfigPage, SelectMenuEntry ) );
61 m_xGearBtn->connect_selected(LINK(this, SvxMenuConfigPage, GearHdl));
63 m_xCommandCategoryListBox->connect_changed(LINK(this, SvxMenuConfigPage, SelectCategory));
65 m_xMoveUpButton->connect_clicked( LINK( this, SvxConfigPage, MoveHdl) );
66 m_xMoveDownButton->connect_clicked( LINK( this, SvxConfigPage, MoveHdl) );
68 m_xAddCommandButton->connect_clicked( LINK( this, SvxMenuConfigPage, AddCommandHdl ) );
69 m_xRemoveCommandButton->connect_clicked( LINK( this, SvxMenuConfigPage, RemoveCommandHdl ) );
71 m_xInsertBtn->connect_selected(
72 LINK( this, SvxMenuConfigPage, InsertHdl ) );
73 m_xModifyBtn->connect_selected(
74 LINK( this, SvxMenuConfigPage, ModifyItemHdl ) );
75 m_xResetBtn->connect_clicked(
76 LINK( this, SvxMenuConfigPage, ResetMenuHdl ) );
78 // These operations are not possible on menus/context menus yet
79 m_xModifyBtn->remove_item("changeIcon");
80 m_xModifyBtn->remove_item("resetIcon");
81 m_xModifyBtn->remove_item("restoreItem");
83 if ( !bIsMenuBar )
85 //TODO: Remove this when the gear button is implemented for context menus
86 m_xGearBtn->set_sensitive(false);
87 m_xGearBtn->hide();
89 else
91 // TODO: Remove this when it is possible to reset menubar menus individually
92 m_xResetBtn->set_sensitive(false);
96 void SvxMenuConfigPage::ListModified()
98 // regenerate with the current ordering within the list
99 SvxEntries* pEntries = GetTopLevelSelection()->GetEntries();
100 pEntries->clear();
102 for (int i = 0; i < m_xContentsListBox->n_children(); ++i)
103 pEntries->push_back(reinterpret_cast<SvxConfigEntry*>(m_xContentsListBox->get_id(i).toInt64()));
105 GetSaveInData()->SetModified();
106 GetTopLevelSelection()->SetModified();
107 UpdateButtonStates();
110 IMPL_LINK(SvxMenuConfigPage, MenuEntriesSizeAllocHdl, const Size&, rSize, void)
112 weld::TreeView& rTreeView = m_xContentsListBox->get_widget();
113 std::vector<int> aWidths;
115 int nExpectedSize = 16;
117 int nStandardImageColWidth = rTreeView.get_checkbox_column_width();
118 int nMargin = nStandardImageColWidth - nExpectedSize;
119 if (nMargin < 16)
120 nMargin = 16;
122 if (SvxConfigPageHelper::GetImageType() & css::ui::ImageType::SIZE_LARGE)
123 nExpectedSize = 24;
124 else if (SvxConfigPageHelper::GetImageType() & css::ui::ImageType::SIZE_32)
125 nExpectedSize = 32;
127 int nImageColWidth = nExpectedSize + nMargin;
129 aWidths.push_back(nImageColWidth);
130 aWidths.push_back(rSize.Width() - (nImageColWidth + nStandardImageColWidth));
131 rTreeView.set_column_fixed_widths(aWidths);
134 SvxMenuConfigPage::~SvxMenuConfigPage()
136 for (int i = 0, nCount = m_xSaveInListBox->get_count(); i < nCount; ++i)
137 delete reinterpret_cast<SaveInData*>(m_xSaveInListBox->get_id(i).toInt64());
138 m_xSaveInListBox->clear();
141 // Populates the Menu combo box
142 void SvxMenuConfigPage::Init()
144 // ensure that the UI is cleared before populating it
145 m_xTopLevelListBox->clear();
146 m_xContentsListBox->clear();
148 ReloadTopLevelListBox();
150 m_xTopLevelListBox->set_active(0);
151 SelectElement();
153 m_xCommandCategoryListBox->Init(
154 comphelper::getProcessComponentContext(),
155 m_xFrame, m_aModuleId);
156 m_xCommandCategoryListBox->categorySelected(m_xFunctions.get(), OUString(), GetSaveInData());
159 IMPL_LINK_NOARG(SvxMenuConfigPage, SelectMenuEntry, weld::TreeView&, void)
161 UpdateButtonStates();
164 void SvxMenuConfigPage::UpdateButtonStates()
166 // Disable Up and Down buttons depending on current selection
167 int selection = m_xContentsListBox->get_selected_index();
169 bool bIsSeparator =
170 selection != -1 && reinterpret_cast<SvxConfigEntry*>(m_xContentsListBox->get_id(selection).toInt64())->IsSeparator();
171 bool bIsValidSelection =
172 !(m_xContentsListBox->n_children() == 0 || selection == -1);
174 m_xMoveUpButton->set_sensitive(
175 bIsValidSelection && selection != 0 );
176 m_xMoveDownButton->set_sensitive(
177 bIsValidSelection && selection != m_xContentsListBox->n_children() - 1);
179 m_xRemoveCommandButton->set_sensitive( bIsValidSelection );
181 m_xModifyBtn->set_sensitive( bIsValidSelection && !bIsSeparator);
183 // If there is no top level selection (menu), then everything working on the right box
184 // which contains the functions of the selected menu/toolbar needs to be disabled
185 SvxConfigEntry* pMenuData = GetTopLevelSelection();
187 m_xInsertBtn->set_sensitive(pMenuData != nullptr);
189 m_xAddCommandButton->set_sensitive(pMenuData != nullptr);
190 m_xRemoveCommandButton->set_sensitive(pMenuData != nullptr);
192 //Handle the gear button
193 if (pMenuData && m_bIsMenuBar)
195 // Add option (gear_add) will always be enabled
196 m_xGearBtn->set_item_sensitive( "menu_gear_delete", pMenuData->IsDeletable() );
197 m_xGearBtn->set_item_sensitive( "menu_gear_rename", pMenuData->IsRenamable() );
198 m_xGearBtn->set_item_sensitive( "menu_gear_move", pMenuData->IsMovable() );
202 void SvxMenuConfigPage::DeleteSelectedTopLevel()
204 SvxConfigEntry* pMenuData = GetTopLevelSelection();
206 SvxEntries* pParentEntries =
207 FindParentForChild( GetSaveInData()->GetEntries(), pMenuData );
209 SvxConfigPageHelper::RemoveEntry( pParentEntries, pMenuData );
210 delete pMenuData;
212 ReloadTopLevelListBox();
214 GetSaveInData()->SetModified( );
217 void SvxMenuConfigPage::DeleteSelectedContent()
219 int nActEntry = m_xContentsListBox->get_selected_index();
221 if (nActEntry != -1)
223 // get currently selected menu entry
224 SvxConfigEntry* pMenuEntry =
225 reinterpret_cast<SvxConfigEntry*>(m_xContentsListBox->get_id(nActEntry).toInt64());
227 // get currently selected menu
228 SvxConfigEntry* pMenu = GetTopLevelSelection();
230 // remove menu entry from the list for this menu
231 SvxConfigPageHelper::RemoveEntry( pMenu->GetEntries(), pMenuEntry );
233 // remove menu entry from UI
234 m_xContentsListBox->remove(nActEntry);
236 // if this is a submenu entry, redraw the menus list box
237 if ( pMenuEntry->IsPopup() )
239 ReloadTopLevelListBox();
242 // delete data for menu entry
243 delete pMenuEntry;
245 GetSaveInData()->SetModified();
246 pMenu->SetModified();
250 short SvxMenuConfigPage::QueryReset()
252 OUString msg = CuiResId( RID_SVXSTR_CONFIRM_MENU_RESET );
254 OUString saveInName = m_xSaveInListBox->get_active_text();
256 OUString label = SvxConfigPageHelper::replaceSaveInName( msg, saveInName );
258 std::unique_ptr<weld::MessageDialog> xQueryBox(Application::CreateMessageDialog(GetFrameWeld(),
259 VclMessageType::Question, VclButtonsType::YesNo,
260 label));
261 return xQueryBox->run();
264 void SvxMenuConfigPage::SelectElement()
266 weld::TreeView& rTreeView = m_xContentsListBox->get_widget();
268 SvxConfigEntry* pMenuData = GetTopLevelSelection();
269 if (!pMenuData)
270 rTreeView.clear();
271 else
273 SvxEntries* pEntries = pMenuData->GetEntries();
275 rTreeView.bulk_insert_for_each(pEntries->size(), [this, &rTreeView, pEntries](weld::TreeIter& rIter, int nIdx) {
276 auto const& entry = (*pEntries)[nIdx];
277 OUString sId(OUString::number(reinterpret_cast<sal_Int64>(entry)));
278 rTreeView.set_id(rIter, sId);
279 InsertEntryIntoUI(entry, rTreeView, rIter, 0);
283 UpdateButtonStates();
286 IMPL_LINK(SvxMenuConfigPage, GearHdl, const OString&, rIdent, void)
288 if (rIdent == "menu_gear_add")
290 SvxMainMenuOrganizerDialog aDialog(GetFrameWeld(),
291 GetSaveInData()->GetEntries(), nullptr, true );
293 if (aDialog.run() == RET_OK)
295 GetSaveInData()->SetEntries(aDialog.ReleaseEntries());
296 ReloadTopLevelListBox(aDialog.GetSelectedEntry());
297 GetSaveInData()->SetModified();
300 else if (rIdent == "menu_gear_delete")
302 DeleteSelectedTopLevel();
304 else if (rIdent == "menu_gear_rename")
306 SvxConfigEntry* pMenuData = GetTopLevelSelection();
308 OUString sCurrentName( SvxConfigPageHelper::stripHotKey( pMenuData->GetName() ) );
309 OUString sDesc = CuiResId( RID_SVXSTR_LABEL_NEW_NAME );
311 SvxNameDialog aNameDialog(GetFrameWeld(), sCurrentName, sDesc);
312 aNameDialog.set_help_id(HID_SVX_CONFIG_RENAME_MENU);
313 aNameDialog.set_title(CuiResId(RID_SVXSTR_RENAME_MENU));
315 if ( aNameDialog.run() == RET_OK )
317 OUString sNewName = aNameDialog.GetName();
319 if ( sCurrentName == sNewName )
320 return;
322 pMenuData->SetName( sNewName );
324 ReloadTopLevelListBox();
326 GetSaveInData()->SetModified();
329 else if (rIdent == "menu_gear_move")
331 SvxConfigEntry* pMenuData = GetTopLevelSelection();
333 SvxMainMenuOrganizerDialog aDialog(GetFrameWeld(), GetSaveInData()->GetEntries(),
334 pMenuData, false );
335 if (aDialog.run() == RET_OK)
337 GetSaveInData()->SetEntries(aDialog.ReleaseEntries());
339 ReloadTopLevelListBox();
341 GetSaveInData()->SetModified();
344 else
346 //This block should never be reached
347 SAL_WARN("cui.customize", "Unknown gear menu option: " << rIdent);
348 return;
351 UpdateButtonStates();
354 IMPL_LINK_NOARG(SvxMenuConfigPage, SelectCategory, weld::ComboBox&, void)
356 OUString aSearchTerm( m_xSearchEdit->get_text() );
358 m_xCommandCategoryListBox->categorySelected(m_xFunctions.get(), aSearchTerm, GetSaveInData());
361 IMPL_LINK_NOARG( SvxMenuConfigPage, AddCommandHdl, weld::Button&, void )
363 int nPos = AddFunction(-1, /*bAllowDuplicates*/false);
364 if (nPos == -1)
365 return;
366 weld::TreeView& rTreeView = m_xContentsListBox->get_widget();
367 SvxConfigEntry* pEntry =
368 reinterpret_cast<SvxConfigEntry*>(rTreeView.get_id(nPos).toInt64());
369 InsertEntryIntoUI(pEntry, rTreeView, nPos, 0);
372 IMPL_LINK_NOARG( SvxMenuConfigPage, RemoveCommandHdl, weld::Button&, void )
374 DeleteSelectedContent();
375 if ( GetSaveInData()->IsModified() )
377 UpdateButtonStates();
381 IMPL_LINK(SvxMenuConfigPage, InsertHdl, const OString&, rIdent, void)
383 weld::TreeView& rTreeView = m_xContentsListBox->get_widget();
384 if (rIdent == "insertseparator")
386 SvxConfigEntry* pNewEntryData = new SvxConfigEntry;
387 pNewEntryData->SetUserDefined();
388 int nPos = AppendEntry(pNewEntryData, -1);
389 InsertEntryIntoUI(pNewEntryData, rTreeView, nPos, 0);
391 else if (rIdent == "insertsubmenu")
393 OUString aNewName;
394 OUString aDesc = CuiResId( RID_SVXSTR_SUBMENU_NAME );
396 SvxNameDialog aNameDialog(GetFrameWeld(), aNewName, aDesc);
397 aNameDialog.set_help_id(HID_SVX_CONFIG_NAME_SUBMENU);
398 aNameDialog.set_title(CuiResId( RID_SVXSTR_ADD_SUBMENU));
400 if (aNameDialog.run() == RET_OK)
402 aNewName = aNameDialog.GetName();
404 SvxConfigEntry* pNewEntryData =
405 new SvxConfigEntry( aNewName, aNewName, true, /*bParentData*/false );
406 pNewEntryData->SetName( aNewName );
407 pNewEntryData->SetUserDefined();
409 int nPos = AppendEntry(pNewEntryData, -1);
410 InsertEntryIntoUI(pNewEntryData, rTreeView, nPos, 0);
412 ReloadTopLevelListBox();
414 m_xContentsListBox->scroll_to_row(nPos);
415 m_xContentsListBox->select(nPos);
417 GetSaveInData()->SetModified();
421 else
423 //This block should never be reached
424 SAL_WARN("cui.customize", "Unknown insert option: " << rIdent);
425 return;
428 if ( GetSaveInData()->IsModified() )
430 UpdateButtonStates();
434 IMPL_LINK(SvxMenuConfigPage, ModifyItemHdl, const OString&, rIdent, void)
436 if (rIdent == "renameItem")
438 int nActEntry = m_xContentsListBox->get_selected_index();
439 SvxConfigEntry* pEntry =
440 reinterpret_cast<SvxConfigEntry*>(m_xContentsListBox->get_id(nActEntry).toInt64());
442 OUString aNewName( SvxConfigPageHelper::stripHotKey( pEntry->GetName() ) );
443 OUString aDesc = CuiResId( RID_SVXSTR_LABEL_NEW_NAME );
445 SvxNameDialog aNameDialog(GetFrameWeld(), aNewName, aDesc);
446 aNameDialog.set_help_id(HID_SVX_CONFIG_RENAME_MENU_ITEM);
447 aNameDialog.set_title(CuiResId(RID_SVXSTR_RENAME_MENU));
449 if (aNameDialog.run() == RET_OK)
451 aNewName = aNameDialog.GetName();
453 pEntry->SetName( aNewName );
454 m_xContentsListBox->set_text(nActEntry, aNewName, 1);
456 GetSaveInData()->SetModified();
457 GetTopLevelSelection()->SetModified();
460 else
462 //This block should never be reached
463 SAL_WARN("cui.customize", "Unknown insert option: " << rIdent);
464 return;
467 if ( GetSaveInData()->IsModified() )
469 UpdateButtonStates();
473 IMPL_LINK_NOARG(SvxMenuConfigPage, ResetMenuHdl, weld::Button&, void)
475 SvxConfigEntry* pMenuData = GetTopLevelSelection();
477 if (pMenuData == nullptr)
479 SAL_WARN("cui.customize", "RHB top level selection is null. A menu must be selected to reset!");
480 return;
483 std::unique_ptr<weld::MessageDialog> xQueryBox(Application::CreateMessageDialog(GetFrameWeld(),
484 VclMessageType::Question, VclButtonsType::YesNo,
485 CuiResId(RID_SVXSTR_CONFIRM_RESTORE_DEFAULT_MENU)));
487 // Resetting individual top-level menus is not possible at the moment.
488 // So we are resetting only if it is a context menu
489 if (!m_bIsMenuBar && xQueryBox->run() == RET_YES)
491 sal_Int32 nPos = m_xTopLevelListBox->get_active();
492 ContextMenuSaveInData* pSaveInData = static_cast< ContextMenuSaveInData* >(GetSaveInData());
494 pSaveInData->ResetContextMenu(pMenuData);
496 // ensure that the UI is cleared before populating it
497 m_xTopLevelListBox->clear();
498 m_xContentsListBox->clear();
500 ReloadTopLevelListBox();
502 // Reselect the reset menu
503 m_xTopLevelListBox->set_active(nPos);
504 SelectElement();
508 SaveInData* SvxMenuConfigPage::CreateSaveInData(
509 const css::uno::Reference< css::ui::XUIConfigurationManager >& xCfgMgr,
510 const css::uno::Reference< css::ui::XUIConfigurationManager >& xParentCfgMgr,
511 const OUString& aModuleId,
512 bool bDocConfig )
514 if ( !m_bIsMenuBar )
515 return static_cast< SaveInData* >( new ContextMenuSaveInData( xCfgMgr, xParentCfgMgr, aModuleId, bDocConfig ) );
517 return static_cast< SaveInData* >( new MenuSaveInData( xCfgMgr, xParentCfgMgr, aModuleId, bDocConfig ) );
520 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */