LibreOffice Module cui (master)  1
SvxToolbarConfigPage.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
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/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
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 .
18  */
19 
20 #include <sal/config.h>
21 #include <sal/log.hxx>
22 
23 #include <vcl/event.hxx>
24 #include <vcl/weld.hxx>
25 #include <vcl/svapp.hxx>
26 #include <vcl/commandevent.hxx>
27 
28 #include <sfx2/sfxsids.hrc>
29 #include <svl/stritem.hxx>
30 #include <tools/diagnose_ex.h>
31 
32 #include <algorithm>
33 #include <helpids.h>
34 #include <strings.hrc>
35 
36 #include <cfg.hxx>
37 #include <SvxToolbarConfigPage.hxx>
38 #include <SvxConfigPageHelper.hxx>
39 #include <dialmgr.hxx>
40 
42 
43 #include <dlgname.hxx>
44 
46  weld::DialogController* pController,
47  const SfxItemSet& rSet)
48  : SvxConfigPage(pPage, pController, rSet)
49 {
50  m_xGearBtn = m_xBuilder->weld_menu_button("toolbargearbtn");
51  m_xGearBtn->show();
53 
54  m_xContentsListBox.reset(
55  new SvxToolbarEntriesListBox(m_xBuilder->weld_tree_view("toolcontents"), this));
56  m_xDropTargetHelper.reset(
57  new SvxConfigPageFunctionDropTarget(*this, m_xContentsListBox->get_widget()));
58 
59  weld::TreeView& rTreeView = m_xContentsListBox->get_widget();
60  Size aSize(m_xFunctions->get_size_request());
61  rTreeView.set_size_request(aSize.Width(), aSize.Height());
62 
63  rTreeView.set_hexpand(true);
64  rTreeView.set_vexpand(true);
66  rTreeView.show();
67 
68  rTreeView.connect_changed(LINK(this, SvxToolbarConfigPage, SelectToolbarEntry));
69  rTreeView.connect_popup_menu(LINK(this, SvxToolbarConfigPage, ContentContextMenuHdl));
70 
71  m_xFunctions->get_widget().connect_popup_menu(
72  LINK(this, SvxToolbarConfigPage, FunctionContextMenuHdl));
73 
75  m_xSaveInListBox->set_help_id(HID_SVX_SAVE_IN);
79 
80  m_xCommandCategoryListBox->connect_changed(LINK(this, SvxToolbarConfigPage, SelectCategory));
81 
82  m_xGearBtn->connect_selected(LINK(this, SvxToolbarConfigPage, GearHdl));
83 
84  m_xMoveUpButton->connect_clicked(LINK(this, SvxToolbarConfigPage, MoveHdl));
85  m_xMoveDownButton->connect_clicked(LINK(this, SvxToolbarConfigPage, MoveHdl));
86  // Always enable Up and Down buttons
87  // added for issue i53677 by shizhoubo
88  m_xMoveDownButton->set_sensitive(true);
89  m_xMoveUpButton->set_sensitive(true);
90 
91  m_xAddCommandButton->connect_clicked(LINK(this, SvxToolbarConfigPage, AddCommandHdl));
92  m_xRemoveCommandButton->connect_clicked(LINK(this, SvxToolbarConfigPage, RemoveCommandHdl));
93 
94  m_xInsertBtn->connect_selected(LINK(this, SvxToolbarConfigPage, InsertHdl));
95  m_xModifyBtn->connect_selected(LINK(this, SvxToolbarConfigPage, ModifyItemHdl));
96  m_xResetBtn->connect_clicked(LINK(this, SvxToolbarConfigPage, ResetToolbarHdl));
97 
98  // "Insert Submenu" is irrelevant to the toolbars
99  m_xInsertBtn->remove_item("insertsubmenu");
100 
101  // Gear menu's "Move" action is irrelevant to the toolbars
102  m_xGearBtn->set_item_sensitive("toolbar_gear_move", false);
103 
104  // default toolbar to select is standardbar unless a different one
105  // has been passed in
107  m_aURLToSelect += "standardbar";
108 
109  const SfxPoolItem* pItem = rSet.GetItem(rSet.GetPool()->GetWhich(SID_CONFIG));
110 
111  if (pItem)
112  {
113  OUString text = static_cast<const SfxStringItem*>(pItem)->GetValue();
114  if (text.startsWith(ITEM_TOOLBAR_URL))
115  {
116  m_aURLToSelect = text.copy(0);
117  }
118  }
119 }
120 
122 {
123  // regenerate with the current ordering within the list
124  SvxEntries* pEntries = GetTopLevelSelection()->GetEntries();
125  pEntries->clear();
126 
127  for (int i = 0; i < m_xContentsListBox->n_children(); ++i)
128  pEntries->push_back(
129  reinterpret_cast<SvxConfigEntry*>(m_xContentsListBox->get_id(i).toInt64()));
130 
133 
134  SvxConfigEntry* pToolbar = GetTopLevelSelection();
135  if (pToolbar)
136  static_cast<ToolbarSaveInData*>(GetSaveInData())->ApplyToolbar(pToolbar);
137 }
138 
140 {
141  for (int i = 0, nCount = m_xSaveInListBox->get_count(); i < nCount; ++i)
142  {
144  = reinterpret_cast<ToolbarSaveInData*>(m_xSaveInListBox->get_id(i).toInt64());
145  delete pData;
146  }
147  m_xSaveInListBox->clear();
148 }
149 
151 {
152  const sal_Int32 nSelectionPos = m_xTopLevelListBox->get_active();
153  ToolbarSaveInData* pSaveInData = static_cast<ToolbarSaveInData*>(GetSaveInData());
154  pSaveInData->RemoveToolbar(GetTopLevelSelection());
155 
156  int nCount = m_xTopLevelListBox->get_count();
157  if (nCount > 1)
158  {
159  // select next entry after the one being deleted
160  // selection position is indexed from 0 so need to
161  // subtract one from the entry count
162  if (nSelectionPos != nCount - 1)
163  {
164  m_xTopLevelListBox->set_active(nSelectionPos + 1);
165  }
166  else
167  {
168  m_xTopLevelListBox->set_active(nSelectionPos - 1);
169  }
170  SelectElement();
171 
172  // and now remove the entry
173  m_xTopLevelListBox->remove(nSelectionPos);
174  }
175  else
176  {
178  }
179 }
180 
182 {
183  int nActEntry = m_xContentsListBox->get_selected_index();
184 
185  if (nActEntry == -1)
186  return;
187 
188  // get currently selected entry
189  SvxConfigEntry* pEntry
190  = reinterpret_cast<SvxConfigEntry*>(m_xContentsListBox->get_id(nActEntry).toInt64());
191 
192  SvxConfigEntry* pToolbar = GetTopLevelSelection();
193 
194  // remove entry from the list for this toolbar
195  SvxConfigPageHelper::RemoveEntry(pToolbar->GetEntries(), pEntry);
196 
197  // remove toolbar entry from UI
198  m_xContentsListBox->remove(nActEntry);
199 
200  // delete data for toolbar entry
201  delete pEntry;
202 
203  static_cast<ToolbarSaveInData*>(GetSaveInData())->ApplyToolbar(pToolbar);
205 
206  // if this is the last entry in the toolbar and it is a user
207  // defined toolbar pop up a dialog asking the user if they
208  // want to delete the toolbar
209  if (m_xContentsListBox->n_children() == 0 && GetTopLevelSelection()->IsDeletable())
210  {
211  std::unique_ptr<weld::MessageDialog> xQueryBox(Application::CreateMessageDialog(
212  GetFrameWeld(), VclMessageType::Question, VclButtonsType::YesNo,
213  CuiResId(RID_SXVSTR_CONFIRM_DELETE_TOOLBAR)));
214  if (xQueryBox->run() == RET_YES)
215  {
217  }
218  }
219 }
220 
221 IMPL_LINK(SvxToolbarConfigPage, MoveHdl, weld::Button&, rButton, void)
222 {
223  MoveEntry(&rButton == m_xMoveUpButton.get());
224 }
225 
227 {
228  SvxConfigPage::MoveEntry(bMoveUp);
229 
230  // Apply change to currently selected toolbar
231  SvxConfigEntry* pToolbar = GetTopLevelSelection();
232  if (pToolbar)
233  static_cast<ToolbarSaveInData*>(GetSaveInData())->ApplyToolbar(pToolbar);
234  else
235  {
236  SAL_WARN("cui.customize", "SvxToolbarConfigPage::MoveEntry(): no entry");
238  }
239 }
240 
242 {
243  // ensure that the UI is cleared before populating it
244  m_xTopLevelListBox->clear();
245  m_xContentsListBox->clear();
246 
248 
249  sal_Int32 nPos = 0;
250  if (!m_aURLToSelect.isEmpty())
251  {
252  for (sal_Int32 i = 0, nCount = m_xTopLevelListBox->get_count(); i < nCount; ++i)
253  {
255  = reinterpret_cast<SvxConfigEntry*>(m_xTopLevelListBox->get_id(i).toInt64());
256 
257  if (pData->GetCommand().equals(m_aURLToSelect))
258  {
259  nPos = i;
260  break;
261  }
262  }
263 
264  // in future select the default toolbar: Standard
266  m_aURLToSelect += "standardbar";
267  }
268 
269  m_xTopLevelListBox->set_active(nPos);
270  SelectElement();
271 
273  m_aModuleId);
274  m_xCommandCategoryListBox->categorySelected(m_xFunctions.get(), OUString(), GetSaveInData());
275  SelectFunctionHdl(m_xFunctions->get_widget());
276 }
277 
279  const css::uno::Reference<css::ui::XUIConfigurationManager>& xCfgMgr,
280  const css::uno::Reference<css::ui::XUIConfigurationManager>& xParentCfgMgr,
281  const OUString& aModuleId, bool bDocConfig)
282 {
283  return static_cast<SaveInData*>(
284  new ToolbarSaveInData(xCfgMgr, xParentCfgMgr, aModuleId, bDocConfig));
285 }
286 
288 {
289  UpdateButtonStates();
290 }
291 
292 IMPL_LINK(SvxToolbarConfigPage, GearHdl, const OString&, rIdent, void)
293 {
294  SvxConfigEntry* pCurrentToolbar = GetTopLevelSelection();
295 
296  if (rIdent == "toolbar_gear_add")
297  {
298  OUString prefix = CuiResId(RID_SVXSTR_NEW_TOOLBAR);
299 
300  OUString aNewName
301  = SvxConfigPageHelper::generateCustomName(prefix, GetSaveInData()->GetEntries());
302 
303  OUString aNewURL = SvxConfigPageHelper::generateCustomURL(GetSaveInData()->GetEntries());
304 
305  SvxNewToolbarDialog aNameDialog(GetFrameWeld(), aNewName);
306 
307  // Reflect the actual m_xSaveInListBox into the new toolbar dialog
308  for (int i = 0, nCount = m_xSaveInListBox->get_count(); i < nCount; ++i)
309  aNameDialog.m_xSaveInListBox->append_text(m_xSaveInListBox->get_text(i));
310 
311  aNameDialog.m_xSaveInListBox->set_active(m_xSaveInListBox->get_active());
312 
313  if (aNameDialog.run() == RET_OK)
314  {
315  aNewName = aNameDialog.GetName();
316 
317  // Where to save the new toolbar? (i.e. Modulewise or documentwise)
318  int nInsertPos = aNameDialog.m_xSaveInListBox->get_active();
319 
320  ToolbarSaveInData* pData = reinterpret_cast<ToolbarSaveInData*>(
321  m_xSaveInListBox->get_id(nInsertPos).toInt64());
322 
323  if (GetSaveInData() != pData)
324  {
325  m_xSaveInListBox->set_active(nInsertPos);
326  SelectSaveInLocation(*m_xSaveInListBox);
327  }
328 
329  SvxConfigEntry* pToolbar = new SvxConfigEntry(aNewName, aNewURL, true, false);
330 
331  pToolbar->SetUserDefined();
332  pToolbar->SetMain();
333 
334  pData->CreateToolbar(pToolbar);
335 
336  OUString sId(OUString::number(reinterpret_cast<sal_Int64>(pToolbar)));
337  m_xTopLevelListBox->append(sId, pToolbar->GetName());
338  m_xTopLevelListBox->set_active_id(sId);
339  SelectElement();
340 
341  pData->SetModified();
342  }
343  }
344  else if (rIdent == "toolbar_gear_delete")
345  {
346  if (pCurrentToolbar && pCurrentToolbar->IsDeletable())
347  {
348  DeleteSelectedTopLevel();
349  UpdateButtonStates();
350  }
351  }
352  else if (rIdent == "toolbar_gear_rename")
353  {
354  sal_Int32 nSelectionPos = m_xTopLevelListBox->get_active();
355  SvxConfigEntry* pToolbar = reinterpret_cast<SvxConfigEntry*>(
356  m_xTopLevelListBox->get_id(nSelectionPos).toInt64());
357  ToolbarSaveInData* pSaveInData = static_cast<ToolbarSaveInData*>(GetSaveInData());
358 
359  //Rename the toolbar
360  OUString sCurrentName(SvxConfigPageHelper::stripHotKey(pToolbar->GetName()));
361  OUString sDesc = CuiResId(RID_SVXSTR_LABEL_NEW_NAME);
362 
363  SvxNameDialog aNameDialog(GetFrameWeld(), sCurrentName, sDesc);
365  aNameDialog.set_title(CuiResId(RID_SVXSTR_RENAME_TOOLBAR));
366 
367  if (aNameDialog.run() == RET_OK)
368  {
369  OUString sNewName = aNameDialog.GetName();
370 
371  if (sCurrentName == sNewName)
372  return;
373 
374  pToolbar->SetName(sNewName);
375  pSaveInData->ApplyToolbar(pToolbar);
376 
377  // have to use remove and insert to change the name
378  m_xTopLevelListBox->remove(nSelectionPos);
379  OUString sId(OUString::number(reinterpret_cast<sal_Int64>(pToolbar)));
380  m_xTopLevelListBox->insert(nSelectionPos, sNewName, &sId, nullptr, nullptr);
381  m_xTopLevelListBox->set_active_id(sId);
382  }
383  }
384  else if (rIdent == "toolbar_gear_iconOnly" || rIdent == "toolbar_gear_textOnly"
385  || rIdent == "toolbar_gear_iconAndText")
386  {
387  ToolbarSaveInData* pSaveInData = static_cast<ToolbarSaveInData*>(GetSaveInData());
388 
389  if (pCurrentToolbar == nullptr || pSaveInData == nullptr)
390  {
391  SAL_WARN("cui.customize", "NULL toolbar or savein data");
392  return;
393  }
394 
395  sal_Int32 nStyle = 0;
396  if (rIdent == "toolbar_gear_iconOnly")
397  nStyle = 0;
398  else if (rIdent == "toolbar_gear_textOnly")
399  nStyle = 1;
400  else if (rIdent == "toolbar_gear_iconAndText")
401  nStyle = 2;
402 
403  pCurrentToolbar->SetStyle(nStyle);
404  pSaveInData->SetSystemStyle(m_xFrame, pCurrentToolbar->GetCommand(), nStyle);
405 
406  SelectElement();
407  }
408  else
409  {
410  //This block should never be reached
411  SAL_WARN("cui.customize", "Unknown gear menu option: " << rIdent);
412  return;
413  }
414 }
415 
417 {
418  OUString aSearchTerm(m_xSearchEdit->get_text());
419 
420  m_xCommandCategoryListBox->categorySelected(m_xFunctions.get(), aSearchTerm, GetSaveInData());
421 
422  SelectFunctionHdl(m_xFunctions->get_widget());
423 }
424 
425 IMPL_LINK_NOARG(SvxToolbarConfigPage, AddCommandHdl, weld::Button&, void) { AddFunction(); }
426 
428 {
429  DeleteSelectedContent();
430 }
431 
432 IMPL_LINK(SvxToolbarConfigPage, InsertHdl, const OString&, rIdent, void)
433 {
434  if (rIdent == "insertseparator")
435  {
436  // Get the currently selected toolbar
437  SvxConfigEntry* pToolbar = GetTopLevelSelection();
438 
439  SvxConfigEntry* pNewEntryData = new SvxConfigEntry;
440  pNewEntryData->SetUserDefined();
441 
442  int nPos = AppendEntry(pNewEntryData, -1);
443  InsertEntryIntoUI(pNewEntryData, m_xContentsListBox->get_widget(), nPos);
444 
445  static_cast<ToolbarSaveInData*>(GetSaveInData())->ApplyToolbar(pToolbar);
446 
447  UpdateButtonStates();
448  }
449  else
450  {
451  //This block should never be reached
452  SAL_WARN("cui.customize", "Unknown insert option: " << rIdent);
453  return;
454  }
455 }
456 
457 IMPL_LINK(SvxToolbarConfigPage, ModifyItemHdl, const OString&, rIdent, void)
458 {
459  bool bNeedsApply = false;
460 
461  // get currently selected toolbar
462  SvxConfigEntry* pToolbar = GetTopLevelSelection();
463 
464  if (rIdent.isEmpty() || pToolbar == nullptr)
465  {
466  SAL_WARN("cui.customize", "No toolbar selected, or empty rIdent!");
467  return;
468  }
469 
470  if (rIdent == "renameItem")
471  {
472  int nActEntry = m_xContentsListBox->get_selected_index();
473  SvxConfigEntry* pEntry
474  = reinterpret_cast<SvxConfigEntry*>(m_xContentsListBox->get_id(nActEntry).toInt64());
475 
476  OUString aNewName(SvxConfigPageHelper::stripHotKey(pEntry->GetName()));
477  OUString aDesc = CuiResId(RID_SVXSTR_LABEL_NEW_NAME);
478 
479  SvxNameDialog aNameDialog(GetFrameWeld(), aNewName, aDesc);
481  aNameDialog.set_title(CuiResId(RID_SVXSTR_RENAME_TOOLBAR));
482 
483  if (aNameDialog.run() == RET_OK)
484  {
485  aNewName = aNameDialog.GetName();
486 
487  if (aNewName.isEmpty()) // tdf#80758 - Accelerator character ("~") is passed as
488  pEntry->SetName("~"); // the button name in case of empty values.
489  else
490  pEntry->SetName(aNewName);
491 
492  m_xContentsListBox->set_text(nActEntry, aNewName, 0);
493  bNeedsApply = true;
494  }
495  }
496  else if (rIdent == "changeIcon")
497  {
498  int nActEntry = m_xContentsListBox->get_selected_index();
499  SvxConfigEntry* pEntry
500  = reinterpret_cast<SvxConfigEntry*>(m_xContentsListBox->get_id(nActEntry).toInt64());
501 
502  SvxIconSelectorDialog aIconDialog(GetFrameWeld(), GetSaveInData()->GetImageManager(),
503  GetSaveInData()->GetParentImageManager());
504 
505  if (aIconDialog.run() == RET_OK)
506  {
507  css::uno::Reference<css::graphic::XGraphic> newgraphic = aIconDialog.GetSelectedIcon();
508 
509  if (newgraphic.is())
510  {
511  css::uno::Sequence<css::uno::Reference<css::graphic::XGraphic>> aGraphicSeq(1);
512 
513  css::uno::Sequence<OUString> aURLSeq{ pEntry->GetCommand() };
514 
515  if (!pEntry->GetBackupGraphic().is())
516  {
517  css::uno::Reference<css::graphic::XGraphic> backup
518  = SvxConfigPageHelper::GetGraphic(GetSaveInData()->GetImageManager(),
519  aURLSeq[0]);
520 
521  if (backup.is())
522  {
523  pEntry->SetBackupGraphic(backup);
524  }
525  }
526 
527  aGraphicSeq[0] = newgraphic;
528  try
529  {
530  GetSaveInData()->GetImageManager()->replaceImages(
531  SvxConfigPageHelper::GetImageType(), aURLSeq, aGraphicSeq);
532 
533  m_xContentsListBox->remove(nActEntry);
534 
535  OUString sId(OUString::number(reinterpret_cast<sal_Int64>(pEntry)));
536  m_xContentsListBox->insert(nActEntry, sId);
537  m_xContentsListBox->set_toggle(nActEntry, pEntry->IsVisible() ? TRISTATE_TRUE
538  : TRISTATE_FALSE);
539  InsertEntryIntoUI(pEntry, m_xContentsListBox->get_widget(), nActEntry);
540 
541  m_xContentsListBox->select(nActEntry);
542  m_xContentsListBox->scroll_to_row(nActEntry);
543 
544  GetSaveInData()->PersistChanges(GetSaveInData()->GetImageManager());
545  }
546  catch (const css::uno::Exception&)
547  {
548  TOOLS_WARN_EXCEPTION("cui.customize", "Error replacing image");
549  }
550  }
551  }
552  }
553  else if (rIdent == "resetIcon")
554  {
555  int nActEntry = m_xContentsListBox->get_selected_index();
556  SvxConfigEntry* pEntry
557  = reinterpret_cast<SvxConfigEntry*>(m_xContentsListBox->get_id(nActEntry).toInt64());
558 
559  css::uno::Reference<css::graphic::XGraphic> backup = pEntry->GetBackupGraphic();
560 
561  css::uno::Sequence<css::uno::Reference<css::graphic::XGraphic>> aGraphicSeq(1);
562  aGraphicSeq[0] = backup;
563 
564  css::uno::Sequence<OUString> aURLSeq{ pEntry->GetCommand() };
565 
566  try
567  {
568  GetSaveInData()->GetImageManager()->replaceImages(SvxConfigPageHelper::GetImageType(),
569  aURLSeq, aGraphicSeq);
570 
571  m_xContentsListBox->remove(nActEntry);
572 
573  OUString sId(OUString::number(reinterpret_cast<sal_Int64>(pEntry)));
574  m_xContentsListBox->insert(nActEntry, sId);
575  m_xContentsListBox->set_toggle(nActEntry,
576  pEntry->IsVisible() ? TRISTATE_TRUE : TRISTATE_FALSE);
577  InsertEntryIntoUI(pEntry, m_xContentsListBox->get_widget(), nActEntry);
578 
579  m_xContentsListBox->select(nActEntry);
580  m_xContentsListBox->scroll_to_row(nActEntry);
581 
582  // reset backup in entry
583  pEntry->SetBackupGraphic(css::uno::Reference<css::graphic::XGraphic>());
584 
585  GetSaveInData()->PersistChanges(GetSaveInData()->GetImageManager());
586  }
587  catch (const css::uno::Exception&)
588  {
589  TOOLS_WARN_EXCEPTION("cui.customize", "Error resetting image");
590  }
591  }
592  else if (rIdent == "restoreItem")
593  {
594  int nActEntry = m_xContentsListBox->get_selected_index();
595  SvxConfigEntry* pEntry
596  = reinterpret_cast<SvxConfigEntry*>(m_xContentsListBox->get_id(nActEntry).toInt64());
597 
598  ToolbarSaveInData* pSaveInData = static_cast<ToolbarSaveInData*>(GetSaveInData());
599 
600  OUString aSystemName = pSaveInData->GetSystemUIName(pEntry->GetCommand());
601 
602  if (!pEntry->GetName().equals(aSystemName))
603  {
604  pEntry->SetName(aSystemName);
605  m_xContentsListBox->set_text(nActEntry, SvxConfigPageHelper::stripHotKey(aSystemName),
606  0);
607  bNeedsApply = true;
608  }
609 
610  css::uno::Sequence<OUString> aURLSeq{ pEntry->GetCommand() };
611 
612  try
613  {
614  GetSaveInData()->GetImageManager()->removeImages(SvxConfigPageHelper::GetImageType(),
615  aURLSeq);
616 
617  // reset backup in entry
618  pEntry->SetBackupGraphic(css::uno::Reference<css::graphic::XGraphic>());
619 
620  GetSaveInData()->PersistChanges(GetSaveInData()->GetImageManager());
621 
622  m_xContentsListBox->remove(nActEntry);
623 
624  OUString sId(OUString::number(reinterpret_cast<sal_Int64>(pEntry)));
625  m_xContentsListBox->insert(nActEntry, sId);
626  m_xContentsListBox->set_toggle(nActEntry,
627  pEntry->IsVisible() ? TRISTATE_TRUE : TRISTATE_FALSE);
628  InsertEntryIntoUI(pEntry, m_xContentsListBox->get_widget(), nActEntry);
629 
630  m_xContentsListBox->select(nActEntry);
631  m_xContentsListBox->scroll_to_row(nActEntry);
632 
633  bNeedsApply = true;
634  }
635  catch (const css::uno::Exception&)
636  {
637  TOOLS_WARN_EXCEPTION("cui.customize", "Error restoring image");
638  }
639  }
640  else
641  {
642  //This block should never be reached
643  SAL_WARN("cui.customize", "Unknown insert option: " << rIdent);
644  return;
645  }
646 
647  if (bNeedsApply)
648  {
649  static_cast<ToolbarSaveInData*>(GetSaveInData())->ApplyToolbar(pToolbar);
650  UpdateButtonStates();
651  }
652 }
653 
655 {
656  sal_Int32 nSelectionPos = m_xTopLevelListBox->get_active();
657 
658  SvxConfigEntry* pToolbar
659  = reinterpret_cast<SvxConfigEntry*>(m_xTopLevelListBox->get_id(nSelectionPos).toInt64());
660 
661  std::unique_ptr<weld::MessageDialog> xQueryBox(Application::CreateMessageDialog(
662  GetFrameWeld(), VclMessageType::Question, VclButtonsType::YesNo,
663  CuiResId(RID_SVXSTR_CONFIRM_RESTORE_DEFAULT)));
664  if (xQueryBox->run() == RET_YES)
665  {
666  ToolbarSaveInData* pSaveInData = static_cast<ToolbarSaveInData*>(GetSaveInData());
667 
668  pSaveInData->RestoreToolbar(pToolbar);
669 
670  SelectElement();
671  }
672 }
673 
675 {
676  SvxConfigEntry* pToolbar = GetTopLevelSelection();
677  int selection = m_xContentsListBox->get_selected_index();
678 
679  bool bIsSeparator
680  = selection != -1
681  && reinterpret_cast<SvxConfigEntry*>(m_xContentsListBox->get_id(selection).toInt64())
682  ->IsSeparator();
683  bool bIsValidSelection = (m_xContentsListBox->n_children() != 0 && selection != -1);
684 
685  m_xMoveUpButton->set_sensitive(bIsValidSelection);
686  m_xMoveDownButton->set_sensitive(bIsValidSelection);
687 
688  m_xRemoveCommandButton->set_sensitive(bIsValidSelection);
689 
690  m_xModifyBtn->set_sensitive(bIsValidSelection && !bIsSeparator);
691 
692  // Handle the gear button
693  // "toolbar_gear_add" option is always enabled
694  m_xGearBtn->set_item_sensitive("toolbar_gear_delete", pToolbar && pToolbar->IsDeletable());
695  m_xGearBtn->set_item_sensitive("toolbar_gear_rename", pToolbar && pToolbar->IsRenamable());
696 }
697 
699 {
700  OUString msg = CuiResId(RID_SVXSTR_CONFIRM_TOOLBAR_RESET);
701 
702  OUString saveInName = m_xSaveInListBox->get_active_text();
703 
704  OUString label = SvxConfigPageHelper::replaceSaveInName(msg, saveInName);
705 
706  std::unique_ptr<weld::MessageDialog> xQueryBox(Application::CreateMessageDialog(
707  GetFrameWeld(), VclMessageType::Question, VclButtonsType::YesNo, label));
708  return xQueryBox->run();
709 }
710 
712 {
713  m_xContentsListBox->clear();
714 
715  SvxConfigEntry* pToolbar = GetTopLevelSelection();
716  if (pToolbar == nullptr)
717  {
718  //TODO: Disable related buttons
719  m_xInsertBtn->set_sensitive(false);
720  m_xResetBtn->set_sensitive(false);
721  m_xGearBtn->set_sensitive(false);
722 
723  return;
724  }
725  else
726  {
727  m_xInsertBtn->set_sensitive(true);
728  m_xResetBtn->set_sensitive(true);
729  m_xGearBtn->set_sensitive(true);
730  }
731 
732  switch (pToolbar->GetStyle())
733  {
734  case 0:
735  {
736  m_xGearBtn->set_item_active("toolbar_gear_iconOnly", true);
737  break;
738  }
739  case 1:
740  {
741  m_xGearBtn->set_item_active("toolbar_gear_textOnly", true);
742  break;
743  }
744  case 2:
745  {
746  m_xGearBtn->set_item_active("toolbar_gear_iconAndText", true);
747  break;
748  }
749  }
750 
751  int i = 0;
752  SvxEntries* pEntries = pToolbar->GetEntries();
753  for (auto const& entry : *pEntries)
754  {
755  OUString sId(OUString::number(reinterpret_cast<sal_Int64>(entry)));
756  m_xContentsListBox->insert(i, sId);
757  if (entry->IsBinding() && !entry->IsSeparator())
758  m_xContentsListBox->set_toggle(i, entry->IsVisible() ? TRISTATE_TRUE : TRISTATE_FALSE);
759  InsertEntryIntoUI(entry, m_xContentsListBox->get_widget(), i);
760  ++i;
761  }
762 
764 }
765 
767 {
768  SvxConfigEntry* pToolbar = GetTopLevelSelection();
769 
770  if (pToolbar == nullptr)
771  return;
772 
773  // Add the command to the contents listbox of the selected toolbar
774  int nNewLBEntry = SvxConfigPage::AddFunction(nTarget, true /*bAllowDuplicates*/);
775 
776  if (nNewLBEntry == -1)
777  return;
778 
779  SvxConfigEntry* pEntry
780  = reinterpret_cast<SvxConfigEntry*>(m_xContentsListBox->get_id(nNewLBEntry).toInt64());
781 
782  if (pEntry->IsBinding()) //TODO sep ?
783  {
784  pEntry->SetVisible(true);
785  m_xContentsListBox->set_toggle(nNewLBEntry, TRISTATE_TRUE);
786  }
787 
788  InsertEntryIntoUI(pEntry, m_xContentsListBox->get_widget(), nNewLBEntry);
789 
790  // Changes are not visible on the toolbar until this point
791  // TODO: Figure out a way to show the changes on the toolbar, but revert if
792  // the dialog is closed by pressing "Cancel"
793  // get currently selected toolbar and apply change
794  if (pToolbar != nullptr)
795  {
796  static_cast<ToolbarSaveInData*>(GetSaveInData())->ApplyToolbar(pToolbar);
797  }
798 }
799 
800 SvxToolbarEntriesListBox::SvxToolbarEntriesListBox(std::unique_ptr<weld::TreeView> xParent,
802  : SvxMenuEntriesListBox(std::move(xParent), pPg)
803 {
804  m_xControl->connect_toggled(LINK(this, SvxToolbarEntriesListBox, CheckButtonHdl));
805  m_xControl->connect_key_press(
806  Link<const KeyEvent&, bool>()); //acknowledge we first remove the old one
807  m_xControl->connect_key_press(
808  LINK(this, SvxToolbarEntriesListBox, KeyInputHdl)); // then add the new one
809 }
810 
812 
814 {
815  SvxConfigEntry* pEntryData
816  = reinterpret_cast<SvxConfigEntry*>(m_xControl->get_id(nRow).toInt64());
817 
818  if (pEntryData->IsBinding())
819  {
820  pEntryData->SetVisible(m_xControl->get_toggle(nRow) == TRISTATE_TRUE);
821 
823 
824  ToolbarSaveInData* pToolbarSaveInData
825  = static_cast<ToolbarSaveInData*>(m_pPage->GetSaveInData());
826 
827  pToolbarSaveInData->ApplyToolbar(pToolbar);
828  }
829 }
830 
831 IMPL_LINK(SvxToolbarEntriesListBox, CheckButtonHdl, const weld::TreeView::iter_col&, rRowCol, void)
832 {
833  ChangedVisibility(m_xControl->get_iter_index_in_parent(rRowCol.first));
834 }
835 
836 IMPL_LINK(SvxToolbarEntriesListBox, KeyInputHdl, const KeyEvent&, rKeyEvent, bool)
837 {
838  // space key will change visibility of toolbar items
839  if (rKeyEvent.GetKeyCode() == KEY_SPACE)
840  {
841  int nRow = m_xControl->get_selected_index();
842  SvxConfigEntry* pEntryData
843  = reinterpret_cast<SvxConfigEntry*>(m_xControl->get_id(nRow).toInt64());
844  if (pEntryData->IsBinding() && !pEntryData->IsSeparator())
845  {
846  m_xControl->set_toggle(nRow, m_xControl->get_toggle(nRow) == TRISTATE_TRUE
848  : TRISTATE_TRUE);
849  ChangedVisibility(nRow);
850  }
851  return true;
852  }
853  return SvxMenuEntriesListBox::KeyInputHdl(rKeyEvent);
854 }
855 
856 IMPL_LINK(SvxToolbarConfigPage, ContentContextMenuHdl, const CommandEvent&, rCEvt, bool)
857 {
858  if (rCEvt.GetCommand() != CommandEventId::ContextMenu)
859  return false;
860 
861  weld::TreeView& rTreeView = m_xContentsListBox->get_widget();
862 
863  // Select clicked entry
864  std::unique_ptr<weld::TreeIter> xIter(rTreeView.make_iterator());
865  if (!rTreeView.get_dest_row_at_pos(rCEvt.GetMousePosPixel(), xIter.get(), false))
866  return false;
867  rTreeView.select(*xIter);
868  SelectToolbarEntry(rTreeView);
869 
870  int nSelectIndex = m_xContentsListBox->get_selected_index();
871 
872  bool bIsSeparator
873  = nSelectIndex != -1
874  && reinterpret_cast<SvxConfigEntry*>(m_xContentsListBox->get_id(nSelectIndex).toInt64())
875  ->IsSeparator();
876  bool bIsValidSelection = (m_xContentsListBox->n_children() != 0 && nSelectIndex != -1);
877 
878  std::unique_ptr<weld::Builder> xBuilder(
879  Application::CreateBuilder(&rTreeView, "cui/ui/entrycontextmenu.ui"));
880  auto xContextMenu = xBuilder->weld_menu("menu");
881  xContextMenu->set_visible("add", false);
882  xContextMenu->set_visible("remove", bIsValidSelection);
883  xContextMenu->set_visible("rename", bIsValidSelection && !bIsSeparator);
884  xContextMenu->set_visible("changeIcon", bIsValidSelection && !bIsSeparator);
885  xContextMenu->set_visible("resetIcon", bIsValidSelection && !bIsSeparator);
886  xContextMenu->set_visible("restoreDefault", bIsValidSelection && !bIsSeparator);
887  OString sCommand(xContextMenu->popup_at_rect(
888  &rTreeView, tools::Rectangle(rCEvt.GetMousePosPixel(), Size(1, 1))));
889 
890  if (sCommand == "remove")
891  RemoveCommandHdl(*m_xRemoveCommandButton);
892  else if (sCommand == "rename")
893  ModifyItemHdl("renameItem");
894  else if (sCommand == "changeIcon")
895  ModifyItemHdl("changeIcon");
896  else if (sCommand == "resetIcon")
897  ModifyItemHdl("resetIcon");
898  else if (sCommand == "restoreDefault")
899  ModifyItemHdl("restoreItem");
900  else if (!sCommand.isEmpty())
901  SAL_WARN("cui.customize", "Unknown context menu action: " << sCommand);
902  return true;
903 }
904 
905 IMPL_LINK(SvxToolbarConfigPage, FunctionContextMenuHdl, const CommandEvent&, rCEvt, bool)
906 {
907  if (rCEvt.GetCommand() != CommandEventId::ContextMenu)
908  return false;
909 
910  weld::TreeView& rTreeView = m_xFunctions->get_widget();
911 
912  // Select clicked entry
913  std::unique_ptr<weld::TreeIter> xIter(rTreeView.make_iterator());
914  if (!rTreeView.get_dest_row_at_pos(rCEvt.GetMousePosPixel(), xIter.get(), false))
915  return false;
916  rTreeView.select(*xIter);
917  SelectFunctionHdl(rTreeView);
918  std::unique_ptr<weld::Builder> xBuilder(
919  Application::CreateBuilder(&rTreeView, "cui/ui/entrycontextmenu.ui"));
920  auto xContextMenu = xBuilder->weld_menu("menu");
921  xContextMenu->set_visible("add", true);
922  xContextMenu->set_visible("remove", false);
923  xContextMenu->set_visible("rename", false);
924  xContextMenu->set_visible("changeIcon", false);
925  xContextMenu->set_visible("resetIcon", false);
926  xContextMenu->set_visible("restoreDefault", false);
927  OString sCommand(xContextMenu->popup_at_rect(
928  &rTreeView, tools::Rectangle(rCEvt.GetMousePosPixel(), Size(1, 1))));
929 
930  if (sCommand == "add")
931  AddCommandHdl(*m_xAddCommandButton);
932  else if (!sCommand.isEmpty())
933  SAL_WARN("cui.customize", "Unknown context menu action: " << sCommand);
934  return true;
935 }
936 
937 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
void RemoveToolbar(SvxConfigEntry *pToolbar)
Definition: cfg.cxx:2449
std::unique_ptr< CuiConfigFunctionListBox > m_xFunctions
Definition: cfg.hxx:388
SvxEntries * GetEntries() const
Definition: cfg.hxx:289
std::unique_ptr< weld::Button > m_xResetBtn
Definition: cfg.hxx:415
void AddFunction(int nTarget=-1)
void set_title(const OUString &rTitle)
const OUString & GetName() const
Definition: cfg.hxx:277
static OUString generateCustomURL(SvxEntries *entries)
Generates a custom resource URL for a new toolbar.
std::unique_ptr< weld::MenuButton > m_xModifyBtn
Definition: cfg.hxx:413
bool IsVisible() const
Definition: cfg.hxx:306
std::unique_ptr< CommandCategoryListBox > m_xCommandCategoryListBox
Definition: cfg.hxx:387
OUString m_aURLToSelect
the ResourceURL to select when opening the dialog
Definition: cfg.hxx:380
virtual ~SvxToolbarConfigPage() override
static OUString stripHotKey(const OUString &str)
std::unique_ptr< ContentProperties > pData
std::string GetValue
Reference< XControl > m_xControl
void SetModified(bool bValue=true)
Definition: cfg.hxx:298
std::unique_ptr< SvxConfigPageFunctionDropTarget > m_xDropTargetHelper
Definition: cfg.hxx:405
OUString GetSystemUIName(const OUString &rResourceURL)
Definition: cfg.cxx:2037
css::uno::Reference< css::frame::XFrame > m_xFrame
Definition: cfg.hxx:382
SvxConfigEntry * GetTopLevelSelection()
Definition: cfg.hxx:493
static sal_Int16 GetImageType()
std::unique_ptr< weld::Button > m_xRemoveCommandButton
Definition: cfg.hxx:419
css::uno::Reference< css::lang::XComponent > m_xFrame
void SetBackupGraphic(css::uno::Reference< css::graphic::XGraphic > const &graphic)
Definition: cfg.hxx:308
static weld::Builder * CreateBuilder(weld::Widget *pParent, const OUString &rUIFile, bool bMobile=false)
virtual void MoveEntry(bool bMoveUp)
Definition: cfg.cxx:1625
constexpr sal_uInt16 KEY_SPACE
OUString GetName() const
Definition: dlgname.hxx:39
std::unique_ptr< SvxMenuEntriesListBox > m_xContentsListBox
Definition: cfg.hxx:404
TRISTATE_TRUE
void ReloadTopLevelListBox(SvxConfigEntry const *pSelection=nullptr)
Definition: cfg.cxx:1323
Dialog for editing a name.
Definition: dlgname.hxx:24
static css::uno::Reference< css::graphic::XGraphic > GetGraphic(const css::uno::Reference< css::ui::XImageManager > &xImageManager, const OUString &rCommandURL)
#define HID_SVX_CONFIG_TOOLBAR_CONTENTS
Definition: helpids.h:27
virtual std::unique_ptr< TreeIter > make_iterator(const TreeIter *pOrig=nullptr) const =0
std::vector< SvxConfigEntry * > SvxEntries
Definition: cfg.hxx:61
std::unique_ptr< weld::ComboBox > m_xTopLevelListBox
Definition: cfg.hxx:401
bool IsRenamable() const
Definition: cfg.cxx:1883
const OUString & GetCommand() const
Definition: cfg.hxx:275
void DeleteSelectedContent() override
#define HID_SVX_CONFIG_RENAME_TOOLBAR
Definition: helpids.h:34
void connect_changed(const Link< TreeView &, void > &rLink)
Reference< XNameAccess > m_xContainer
RET_YES
virtual void show()=0
bool IsBinding() const
Definition: cfg.hxx:286
OUString GetName() const
Definition: cfg.hxx:605
std::unique_ptr< weld::TreeView > m_xControl
Definition: cfg.hxx:321
std::pair< const TreeIter &, int > iter_col
int nCount
static void RemoveEntry(SvxEntries *pEntries, SvxConfigEntry const *pChildEntry)
static OUString replaceSaveInName(const OUString &rMessage, std::u16string_view rSaveInName)
void SetName(const OUString &rStr)
Definition: cfg.hxx:278
void SetMain()
Definition: cfg.hxx:292
virtual void set_help_id(const OString &rName)=0
virtual void set_vexpand(bool bExpand)=0
SaveInData * CreateSaveInData(const css::uno::Reference< css::ui::XUIConfigurationManager > &, const css::uno::Reference< css::ui::XUIConfigurationManager > &, const OUString &aModuleId, bool docConfig) override
static OUString generateCustomName(const OUString &prefix, SvxEntries *entries, sal_Int32 suffix=1)
virtual void SelectElement() override
IMPL_LINK(SvxToolbarConfigPage, MoveHdl, weld::Button &, rButton, void)
exports com.sun.star. text
const css::uno::Reference< css::graphic::XGraphic > & GetBackupGraphic() const
Definition: cfg.hxx:311
#define TOOLS_WARN_EXCEPTION(area, stream)
virtual bool get_dest_row_at_pos(const Point &rPos, weld::TreeIter *pResult, bool bDnDMode)=0
void SetSystemStyle(const OUString &rResourceURL, sal_Int32 nStyle)
Definition: cfg.cxx:1998
int i
void SetUserDefined(bool bOn=true)
Definition: cfg.hxx:283
#define HID_SVX_CONFIG_RENAME_TOOLBAR_ITEM
Definition: helpids.h:35
#define HID_SVX_TOPLEVELLISTBOX
Definition: helpids.h:39
virtual void ListModified() override
TRISTATE_FALSE
std::unique_ptr< weld::ComboBox > m_xSaveInListBox
Definition: cfg.hxx:600
void SetVisible(bool b)
Definition: cfg.hxx:305
void SetStyle(sal_Int32 style)
Definition: cfg.hxx:315
virtual void set_hexpand(bool bExpand)=0
void set_help_id(const OString &rHelpId)
SfxItemPool * GetPool() const
#define HID_SVX_CONFIG_TOOLBAR
Definition: helpids.h:26
OUString CuiResId(const char *pKey)
Definition: cuiresmgr.cxx:23
std::unique_ptr< weld::MenuButton > m_xInsertBtn
Definition: cfg.hxx:412
sal_Int32 GetStyle() const
Definition: cfg.hxx:314
void RestoreToolbar(SvxConfigEntry *pToolbar)
Definition: cfg.cxx:2472
virtual void select(int pos)=0
weld::Window * GetFrameWeld() const
void UpdateButtonStates() override
void InsertEntryIntoUI(SvxConfigEntry *pNewEntryData, weld::TreeView &rTreeView, int nPos, bool bMenu=false)
Definition: cfg.cxx:1541
sal_uInt16 GetWhich(sal_uInt16 nSlot, bool bDeep=true) const
void SetModified(bool bValue=true)
Definition: cfg.hxx:125
int AddFunction(int nTarget, bool bAllowDuplicates)
Definition: cfg.cxx:1398
RET_OK
bool IsDeletable() const
Definition: cfg.cxx:1878
IMPL_LINK_NOARG(SvxToolbarConfigPage, SelectToolbarEntry, weld::TreeView &, void)
SvxToolbarConfigPage(weld::Container *pPage, weld::DialogController *pController, const SfxItemSet &rItemSet)
virtual short run()
Reference< XComponentContext > getProcessComponentContext()
constexpr char16_t ITEM_TOOLBAR_URL[]
Definition: cfg.hxx:54
void CreateToolbar(SvxConfigEntry *pToolbar)
Definition: cfg.cxx:2422
#define HID_SVX_SAVE_IN
Definition: helpids.h:38
virtual ~SvxToolbarEntriesListBox() override
std::unique_ptr< weld::ComboBox > m_xSaveInListBox
Definition: cfg.hxx:410
void ApplyToolbar(css::uno::Reference< css::container::XIndexContainer > const &rNewToolbarBar, css::uno::Reference< css::lang::XSingleComponentFactory > &rFactory, SvxConfigEntry const *pToolbar)
SvxConfigPage * m_pPage
Definition: cfg.hxx:323
OUString sId
std::unique_ptr< weld::TextView > m_xDescriptionField
Definition: cfg.hxx:392
std::unique_ptr< weld::Button > m_xMoveDownButton
Definition: cfg.hxx:408
#define SAL_WARN(area, stream)
#define HID_SVX_DOWN_TOOLBAR_ITEM
Definition: helpids.h:37
css::uno::Reference< css::graphic::XGraphic > GetSelectedIcon()
Definition: cfg.cxx:2791
void DeleteSelectedTopLevel() override
bool IsSeparator() const
Definition: cfg.hxx:287
std::unique_ptr< weld::Button > m_xMoveUpButton
Definition: cfg.hxx:407
def label(st)
OUString m_aModuleId
Definition: cfg.hxx:383
#define HID_SVX_DESCFIELD
Definition: helpids.h:40
std::unique_ptr< weld::MenuButton > m_xGearBtn
Definition: cfg.hxx:403
virtual void set_size_request(int nWidth, int nHeight)=0
const SfxPoolItem * GetItem(sal_uInt16 nWhich, bool bSearchInParent=true) const
void MoveEntry(bool bMoveUp) override
virtual void connect_popup_menu(const Link< const CommandEvent &, bool > &rLink)
weld::Window * GetFrameWeld(const SfxFrame *pFrame)
SvxToolbarEntriesListBox(std::unique_ptr< weld::TreeView > xControl, SvxToolbarConfigPage *pPg)
SaveInData * GetSaveInData()
Definition: cfg.hxx:474
static weld::MessageDialog * CreateMessageDialog(weld::Widget *pParent, VclMessageType eMessageType, VclButtonsType eButtonType, const OUString &rPrimaryMessage, bool bMobile=false)
sal_uInt16 nPos
#define HID_SVX_UP_TOOLBAR_ITEM
Definition: helpids.h:36
std::unique_ptr< weld::Button > m_xAddCommandButton
Definition: cfg.hxx:418