Files
odfstudio/cui/source/customize/SvxMenuConfigPage.cxx
T
Noel Grandin d704ce2504 fix build in SvxMenuConfigPage
mid-air patch collision

Change-Id: I183362aee3192893836eeb8138671a7fbe2da604
2018-03-13 14:30:24 +02:00

538 lines
17 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice:
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
#include <sal/config.h>
#include <cassert>
#include <stdlib.h>
#include <time.h>
#include <typeinfo>
#include <vcl/commandinfoprovider.hxx>
#include <vcl/help.hxx>
#include <vcl/weld.hxx>
#include <vcl/decoview.hxx>
#include <vcl/toolbox.hxx>
#include <vcl/scrbar.hxx>
#include <vcl/virdev.hxx>
#include <vcl/settings.hxx>
#include <sfx2/app.hxx>
#include <sfx2/sfxdlg.hxx>
#include <sfx2/viewfrm.hxx>
#include <sfx2/viewsh.hxx>
#include <sfx2/msg.hxx>
#include <sfx2/msgpool.hxx>
#include <sfx2/minfitem.hxx>
#include <sfx2/objsh.hxx>
#include <sfx2/request.hxx>
#include <sfx2/filedlghelper.hxx>
#include <svl/stritem.hxx>
#include <svtools/miscopt.hxx>
#include <svtools/svlbitm.hxx>
#include <svtools/treelistentry.hxx>
#include <svtools/viewdataentry.hxx>
#include <tools/diagnose_ex.h>
#include <algorithm>
#include <strings.hrc>
#include <helpids.h>
#include <acccfg.hxx>
#include <cfg.hxx>
#include <SvxMenuConfigPage.hxx>
#include <SvxConfigPageHelper.hxx>
#include "eventdlg.hxx"
#include <dialmgr.hxx>
#include <comphelper/documentinfo.hxx>
#include <comphelper/processfactory.hxx>
#include <comphelper/random.hxx>
#include <unotools/configmgr.hxx>
#include <o3tl/make_unique.hxx>
#include <com/sun/star/embed/ElementModes.hpp>
#include <com/sun/star/embed/FileSystemStorageFactory.hpp>
#include <com/sun/star/frame/UnknownModuleException.hpp>
#include <com/sun/star/frame/XFrames.hpp>
#include <com/sun/star/frame/XLayoutManager.hpp>
#include <com/sun/star/frame/FrameSearchFlag.hpp>
#include <com/sun/star/frame/ModuleManager.hpp>
#include <com/sun/star/frame/XController.hpp>
#include <com/sun/star/frame/Desktop.hpp>
#include <com/sun/star/frame/theUICommandDescription.hpp>
#include <com/sun/star/graphic/GraphicProvider.hpp>
#include <com/sun/star/io/IOException.hpp>
#include <com/sun/star/lang/IllegalAccessException.hpp>
#include <com/sun/star/ui/ItemType.hpp>
#include <com/sun/star/ui/ItemStyle.hpp>
#include <com/sun/star/ui/ImageManager.hpp>
#include <com/sun/star/ui/theModuleUIConfigurationManagerSupplier.hpp>
#include <com/sun/star/ui/XUIConfiguration.hpp>
#include <com/sun/star/ui/XUIConfigurationListener.hpp>
#include <com/sun/star/ui/XUIConfigurationManagerSupplier.hpp>
#include <com/sun/star/ui/XUIConfigurationPersistence.hpp>
#include <com/sun/star/ui/XUIConfigurationStorage.hpp>
#include <com/sun/star/ui/XModuleUIConfigurationManager.hpp>
#include <com/sun/star/ui/XUIElement.hpp>
#include <com/sun/star/ui/UIElementType.hpp>
#include <com/sun/star/ui/ImageType.hpp>
#include <com/sun/star/ui/theWindowStateConfiguration.hpp>
#include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp>
#include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
#include <com/sun/star/ui/dialogs/XFilePickerControlAccess.hpp>
#include <com/sun/star/util/thePathSettings.hpp>
#include <dlgname.hxx>
SvxMenuConfigPage::SvxMenuConfigPage(vcl::Window *pParent, const SfxItemSet& rSet, bool bIsMenuBar)
: SvxConfigPage(pParent, rSet)
, m_bIsMenuBar( bIsMenuBar )
{
m_pContentsListBox = VclPtr<SvxMenuEntriesListBox>::Create(m_pEntries, this);
m_pContentsListBox->set_grid_left_attach(0);
m_pContentsListBox->set_grid_top_attach(0);
m_pContentsListBox->set_hexpand(true);
m_pContentsListBox->set_vexpand(true);
m_pContentsListBox->Show();
m_pTopLevelListBox->SetSelectHdl(
LINK( this, SvxMenuConfigPage, SelectMenu ) );
m_pContentsListBox->SetSelectHdl(
LINK( this, SvxMenuConfigPage, SelectMenuEntry ) );
m_pGearBtn->SetSelectHdl(
LINK( this, SvxMenuConfigPage, GearHdl ) );
m_pCommandCategoryListBox->SetSelectHdl(
LINK( this, SvxMenuConfigPage, SelectCategory ) );
m_pMoveUpButton->SetClickHdl ( LINK( this, SvxConfigPage, MoveHdl) );
m_pMoveDownButton->SetClickHdl ( LINK( this, SvxConfigPage, MoveHdl) );
m_pAddCommandButton->SetClickHdl( LINK( this, SvxMenuConfigPage, AddCommandHdl ) );
m_pRemoveCommandButton->SetClickHdl( LINK( this, SvxMenuConfigPage, RemoveCommandHdl ) );
m_pInsertBtn->SetSelectHdl(
LINK( this, SvxMenuConfigPage, InsertHdl ) );
m_pModifyBtn->SetSelectHdl(
LINK( this, SvxMenuConfigPage, ModifyItemHdl ) );
m_pResetBtn->SetClickHdl(
LINK( this, SvxMenuConfigPage, ResetMenuHdl ) );
PopupMenu* pPopup = m_pModifyBtn->GetPopupMenu();
// These operations are not possible on menus/context menus yet
pPopup->EnableItem( pPopup->GetItemId("changeIcon"), false );
pPopup->EnableItem( pPopup->GetItemId("resetIcon"), false );
pPopup->EnableItem( pPopup->GetItemId("restoreItem"), false );
pPopup->RemoveDisabledEntries();
if ( !bIsMenuBar )
{
//TODO: Remove this when the gear button is implemented for context menus
m_pGearBtn->Disable();
m_pGearBtn->Hide();
}
else
{
// TODO: Remove this when it is possible to reset menubar menus individually
m_pResetBtn->Disable();
}
}
SvxMenuConfigPage::~SvxMenuConfigPage()
{
disposeOnce();
}
// Populates the Menu combo box
void SvxMenuConfigPage::Init()
{
// ensure that the UI is cleared before populating it
m_pTopLevelListBox->Clear();
m_pContentsListBox->Clear();
ReloadTopLevelListBox();
m_pTopLevelListBox->SelectEntryPos(0);
m_pTopLevelListBox->GetSelectHdl().Call(*m_pTopLevelListBox);
m_pCommandCategoryListBox->Init(
comphelper::getProcessComponentContext(),
m_xFrame,
vcl::CommandInfoProvider::GetModuleIdentifier(m_xFrame));
m_pCommandCategoryListBox->categorySelected( m_pFunctions, OUString(), GetSaveInData() );
}
void SvxMenuConfigPage::dispose()
{
for ( sal_Int32 i = 0 ; i < m_pSaveInListBox->GetEntryCount(); ++i )
{
delete static_cast<SaveInData*>(m_pSaveInListBox->GetEntryData( i ));
}
m_pSaveInListBox->Clear();
SvxConfigPage::dispose();
}
IMPL_LINK_NOARG( SvxMenuConfigPage, SelectMenuEntry, SvTreeListBox *, void )
{
UpdateButtonStates();
}
void SvxMenuConfigPage::UpdateButtonStates()
{
// Disable Up and Down buttons depending on current selection
SvTreeListEntry* selection = m_pContentsListBox->GetCurEntry();
bool bIsSeparator =
selection && static_cast<SvxConfigEntry*>(selection->GetUserData())->IsSeparator();
bool bIsValidSelection =
!(m_pContentsListBox->GetEntryCount() == 0 || selection == nullptr);
m_pMoveUpButton->Enable(
bIsValidSelection && selection != m_pContentsListBox->First() );
m_pMoveDownButton->Enable(
bIsValidSelection && selection != m_pContentsListBox->Last() );
m_pRemoveCommandButton->Enable( bIsValidSelection );
m_pModifyBtn->Enable( bIsValidSelection && !bIsSeparator);
//Handle the gear button
if (m_bIsMenuBar)
{
SvxConfigEntry* pMenuData = GetTopLevelSelection();
PopupMenu* pGearPopup = m_pGearBtn->GetPopupMenu();
// Add option (gear_add) will always be enabled
pGearPopup->EnableItem( "gear_delete", pMenuData->IsDeletable() );
pGearPopup->EnableItem( "gear_rename", pMenuData->IsRenamable() );
pGearPopup->EnableItem( "gear_move", pMenuData->IsMovable() );
}
}
void SvxMenuConfigPage::DeleteSelectedTopLevel()
{
SvxConfigEntry* pMenuData = GetTopLevelSelection();
SvxEntries* pParentEntries =
FindParentForChild( GetSaveInData()->GetEntries(), pMenuData );
SvxConfigPageHelper::RemoveEntry( pParentEntries, pMenuData );
delete pMenuData;
ReloadTopLevelListBox();
GetSaveInData()->SetModified( );
}
void SvxMenuConfigPage::DeleteSelectedContent()
{
SvTreeListEntry *pActEntry = m_pContentsListBox->FirstSelected();
if ( pActEntry != nullptr )
{
// get currently selected menu entry
SvxConfigEntry* pMenuEntry =
static_cast<SvxConfigEntry*>(pActEntry->GetUserData());
// get currently selected menu
SvxConfigEntry* pMenu = GetTopLevelSelection();
// remove menu entry from the list for this menu
SvxConfigPageHelper::RemoveEntry( pMenu->GetEntries(), pMenuEntry );
// remove menu entry from UI
m_pContentsListBox->GetModel()->Remove( pActEntry );
// if this is a submenu entry, redraw the menus list box
if ( pMenuEntry->IsPopup() )
{
ReloadTopLevelListBox();
}
// delete data for menu entry
delete pMenuEntry;
GetSaveInData()->SetModified();
pMenu->SetModified();
}
}
short SvxMenuConfigPage::QueryReset()
{
OUString msg = CuiResId( RID_SVXSTR_CONFIRM_MENU_RESET );
OUString saveInName = m_pSaveInListBox->GetEntry(
m_pSaveInListBox->GetSelectedEntryPos() );
OUString label = SvxConfigPageHelper::replaceSaveInName( msg, saveInName );
std::unique_ptr<weld::MessageDialog> xQueryBox(Application::CreateMessageDialog(GetFrameWeld(),
VclMessageType::Question, VclButtonsType::YesNo,
label));
return xQueryBox->run();
}
IMPL_LINK_NOARG( SvxMenuConfigPage, SelectMenu, ListBox&, void )
{
m_pContentsListBox->Clear();
SvxConfigEntry* pMenuData = GetTopLevelSelection();
if ( pMenuData )
{
SvxEntries* pEntries = pMenuData->GetEntries();
for (auto const& entry : *pEntries)
{
InsertEntryIntoUI(entry);
}
}
UpdateButtonStates();
}
IMPL_LINK( SvxMenuConfigPage, GearHdl, MenuButton *, pButton, void )
{
OString sIdent = pButton->GetCurItemIdent();
if (sIdent == "gear_add")
{
VclPtrInstance<SvxMainMenuOrganizerDialog> pDialog(
nullptr, GetSaveInData()->GetEntries(), nullptr, true );
if ( pDialog->Execute() == RET_OK )
{
GetSaveInData()->SetEntries( pDialog->ReleaseEntries() );
ReloadTopLevelListBox( pDialog->GetSelectedEntry() );
GetSaveInData()->SetModified();
}
}
else if (sIdent == "gear_delete")
{
DeleteSelectedTopLevel();
}
else if (sIdent == "gear_rename")
{
SvxConfigEntry* pMenuData = GetTopLevelSelection();
OUString sCurrentName( SvxConfigPageHelper::stripHotKey( pMenuData->GetName() ) );
OUString sDesc = CuiResId( RID_SVXSTR_LABEL_NEW_NAME );
SvxNameDialog aNameDialog( GetFrameWeld(), sCurrentName, sDesc );
aNameDialog.set_help_id( HID_SVX_CONFIG_RENAME_MENU );
aNameDialog.set_title( CuiResId( RID_SVXSTR_RENAME_MENU ) );
if ( aNameDialog.run() == RET_OK )
{
OUString sNewName = aNameDialog.GetName();
if ( sCurrentName == sNewName )
return;
pMenuData->SetName( sNewName );
ReloadTopLevelListBox();
GetSaveInData()->SetModified();
}
}
else if (sIdent == "gear_move")
{
SvxConfigEntry* pMenuData = GetTopLevelSelection();
VclPtrInstance<SvxMainMenuOrganizerDialog> pDialog(
this, GetSaveInData()->GetEntries(), pMenuData, false );
if ( pDialog->Execute() == RET_OK )
{
GetSaveInData()->SetEntries( pDialog->ReleaseEntries() );
ReloadTopLevelListBox();
GetSaveInData()->SetModified();
}
}
else
{
//This block should never be reached
SAL_WARN("cui.customize", "Unknown gear menu option: " << sIdent);
return;
}
UpdateButtonStates();
}
IMPL_LINK_NOARG( SvxMenuConfigPage, SelectCategory, ListBox&, void )
{
OUString aSearchTerm( m_pSearchEdit->GetText() );
m_pCommandCategoryListBox->categorySelected( m_pFunctions, aSearchTerm, GetSaveInData() );
}
IMPL_LINK_NOARG( SvxMenuConfigPage, AddCommandHdl, Button *, void )
{
AddFunction();
}
IMPL_LINK_NOARG( SvxMenuConfigPage, RemoveCommandHdl, Button *, void )
{
DeleteSelectedContent();
if ( GetSaveInData()->IsModified() )
{
UpdateButtonStates();
}
}
IMPL_LINK( SvxMenuConfigPage, InsertHdl, MenuButton *, pButton, void )
{
OString sIdent = pButton->GetCurItemIdent();
if (sIdent == "insertseparator")
{
SvxConfigEntry* pNewEntryData = new SvxConfigEntry;
pNewEntryData->SetUserDefined();
InsertEntry( pNewEntryData );
}
else if (sIdent == "insertsubmenu")
{
OUString aNewName;
OUString aDesc = CuiResId( RID_SVXSTR_SUBMENU_NAME );
SvxNameDialog aNameDialog(GetFrameWeld(), aNewName, aDesc);
aNameDialog.set_help_id(HID_SVX_CONFIG_NAME_SUBMENU);
aNameDialog.set_title(CuiResId( RID_SVXSTR_ADD_SUBMENU));
if (aNameDialog.run() == RET_OK)
{
aNewName = aNameDialog.GetName();
SvxConfigEntry* pNewEntryData =
new SvxConfigEntry( aNewName, aNewName, true, /*bParentData*/false );
pNewEntryData->SetName( aNewName );
pNewEntryData->SetUserDefined();
InsertEntry( pNewEntryData );
ReloadTopLevelListBox();
GetSaveInData()->SetModified();
}
}
else
{
//This block should never be reached
SAL_WARN("cui.customize", "Unknown insert option: " << sIdent);
return;
}
if ( GetSaveInData()->IsModified() )
{
UpdateButtonStates();
}
}
IMPL_LINK( SvxMenuConfigPage, ModifyItemHdl, MenuButton *, pButton, void )
{
OString sIdent = pButton->GetCurItemIdent();
SAL_WARN("cui.customize", "sIdent: " << sIdent);
if (sIdent == "renameItem")
{
SvTreeListEntry* pActEntry = m_pContentsListBox->GetCurEntry();
SvxConfigEntry* pEntry =
static_cast<SvxConfigEntry*>(pActEntry->GetUserData());
OUString aNewName( SvxConfigPageHelper::stripHotKey( pEntry->GetName() ) );
OUString aDesc = CuiResId( RID_SVXSTR_LABEL_NEW_NAME );
SvxNameDialog aNameDialog(GetFrameWeld(), aNewName, aDesc);
aNameDialog.set_help_id(HID_SVX_CONFIG_RENAME_MENU_ITEM);
aNameDialog.set_title(CuiResId(RID_SVXSTR_RENAME_MENU));
if (aNameDialog.run() == RET_OK)
{
aNewName = aNameDialog.GetName();
pEntry->SetName( aNewName );
m_pContentsListBox->SetEntryText( pActEntry, aNewName );
GetSaveInData()->SetModified();
GetTopLevelSelection()->SetModified();
}
}
else
{
//This block should never be reached
SAL_WARN("cui.customize", "Unknown insert option: " << sIdent);
return;
}
if ( GetSaveInData()->IsModified() )
{
UpdateButtonStates();
}
}
IMPL_LINK_NOARG( SvxMenuConfigPage, ResetMenuHdl, Button *, void )
{
SvxConfigEntry* pMenuData = GetTopLevelSelection();
std::unique_ptr<weld::MessageDialog> xQueryBox(Application::CreateMessageDialog(GetFrameWeld(),
VclMessageType::Question, VclButtonsType::YesNo,
CuiResId(RID_SVXSTR_CONFIRM_RESTORE_DEFAULT_MENU)));
// Resetting individual top-level menus is not possible at the moment.
// So we are resetting only if it is a context menu
if (!m_bIsMenuBar && xQueryBox->run() == RET_YES)
{
sal_Int32 nPos = m_pTopLevelListBox->GetSelectedEntryPos();
ContextMenuSaveInData* pSaveInData = static_cast< ContextMenuSaveInData* >(GetSaveInData());
pSaveInData->ResetContextMenu(pMenuData);
// ensure that the UI is cleared before populating it
m_pTopLevelListBox->Clear();
m_pContentsListBox->Clear();
ReloadTopLevelListBox();
// Reselect the resetted menu
m_pTopLevelListBox->SelectEntryPos(nPos);
m_pTopLevelListBox->GetSelectHdl().Call(*m_pTopLevelListBox);
}
}
SaveInData* SvxMenuConfigPage::CreateSaveInData(
const css::uno::Reference< css::ui::XUIConfigurationManager >& xCfgMgr,
const css::uno::Reference< css::ui::XUIConfigurationManager >& xParentCfgMgr,
const OUString& aModuleId,
bool bDocConfig )
{
if ( !m_bIsMenuBar )
return static_cast< SaveInData* >( new ContextMenuSaveInData( xCfgMgr, xParentCfgMgr, aModuleId, bDocConfig ) );
return static_cast< SaveInData* >( new MenuSaveInData( xCfgMgr, xParentCfgMgr, aModuleId, bDocConfig ) );
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */