tdf#130857 qt weld: Implement QtInstanceWidget::strip_mnemonic
[LibreOffice.git] / sc / source / ui / dbgui / consdlg.cxx
blob09d0dea25ca24b5ca1e8cd786022e4d18ac6f3c7
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 <sfx2/dispatch.hxx>
22 #include <tabvwsh.hxx>
23 #include <uiitems.hxx>
24 #include <dbdata.hxx>
25 #include <rangenam.hxx>
26 #include <rangeutl.hxx>
27 #include <reffact.hxx>
28 #include <document.hxx>
29 #include <scresid.hxx>
31 #include <globstr.hrc>
32 #include <strings.hrc>
34 #include <consdlg.hxx>
35 #include <o3tl/safeint.hxx>
36 #include <vcl/svapp.hxx>
37 #include <vcl/weld.hxx>
39 namespace
41 void INFOBOX(weld::Window* pWindow, TranslateId id)
43 std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(pWindow,
44 VclMessageType::Info, VclButtonsType::Ok,
45 ScResId(id)));
46 xInfoBox->run();
50 class ScAreaData
52 public:
53 ScAreaData()
57 void Set( const OUString& rName, const OUString& rArea )
59 aStrName = rName;
60 aStrArea = rArea;
63 OUString aStrName;
64 OUString aStrArea;
67 ScConsolidateDlg::ScConsolidateDlg(SfxBindings* pB, SfxChildWindow* pCW, weld::Window* pParent,
68 const SfxItemSet& rArgSet)
70 : ScAnyRefDlgController(pB, pCW, pParent, u"modules/scalc/ui/consolidatedialog.ui"_ustr, u"ConsolidateDialog"_ustr)
71 , aStrUndefined ( ScResId( SCSTR_UNDEFINED ) )
72 , theConsData ( static_cast<const ScConsolidateItem&>(
73 rArgSet.Get( rArgSet.GetPool()->
74 GetWhichIDFromSlotID( SID_CONSOLIDATE ) )
75 ).GetData() )
76 , rViewData ( static_cast<ScTabViewShell*>(SfxViewShell::Current())->
77 GetViewData() )
78 , rDoc ( static_cast<ScTabViewShell*>(SfxViewShell::Current())->
79 GetViewData().GetDocument() )
80 , nAreaDataCount ( 0 )
81 , nWhichCons ( rArgSet.GetPool()->GetWhichIDFromSlotID( SID_CONSOLIDATE ) )
82 , bDlgLostFocus ( false )
83 , m_xLbFunc(m_xBuilder->weld_combo_box(u"func"_ustr))
84 , m_xLbConsAreas(m_xBuilder->weld_tree_view(u"consareas"_ustr))
85 , m_xLbDataArea(m_xBuilder->weld_combo_box(u"lbdataarea"_ustr))
86 , m_xEdDataArea(new formula::RefEdit(m_xBuilder->weld_entry(u"eddataarea"_ustr)))
87 , m_xRbDataArea(new formula::RefButton(m_xBuilder->weld_button(u"rbdataarea"_ustr)))
88 , m_xLbDestArea(m_xBuilder->weld_combo_box(u"lbdestarea"_ustr))
89 , m_xEdDestArea(new formula::RefEdit(m_xBuilder->weld_entry(u"eddestarea"_ustr)))
90 , m_xRbDestArea(new formula::RefButton(m_xBuilder->weld_button(u"rbdestarea"_ustr)))
91 , m_xExpander(m_xBuilder->weld_expander(u"more"_ustr))
92 , m_xBtnByRow(m_xBuilder->weld_check_button(u"byrow"_ustr))
93 , m_xBtnByCol(m_xBuilder->weld_check_button(u"bycol"_ustr))
94 , m_xBtnRefs(m_xBuilder->weld_check_button(u"refs"_ustr))
95 , m_xBtnOk(m_xBuilder->weld_button(u"ok"_ustr))
96 , m_xBtnCancel(m_xBuilder->weld_button(u"cancel"_ustr))
97 , m_xBtnAdd(m_xBuilder->weld_button(u"add"_ustr))
98 , m_xBtnRemove(m_xBuilder->weld_button(u"delete"_ustr))
99 , m_xDataFT(m_xBuilder->weld_label(u"ftdataarea"_ustr))
100 , m_xDestFT(m_xBuilder->weld_label(u"ftdestarea"_ustr))
102 m_pRefInputEdit = m_xEdDataArea.get();
103 Init();
106 ScConsolidateDlg::~ScConsolidateDlg()
110 void ScConsolidateDlg::Init()
112 OUString aStr;
113 sal_uInt16 i=0;
115 m_xRbDataArea->SetReferences(this, m_xEdDataArea.get());
116 m_xEdDataArea->SetReferences(this, m_xDataFT.get());
117 m_xRbDestArea->SetReferences(this, m_xEdDestArea.get());
118 m_xEdDestArea->SetReferences(this, m_xDestFT.get());
120 m_xEdDataArea->SetGetFocusHdl( LINK( this, ScConsolidateDlg, GetEditFocusHdl ) );
121 m_xEdDestArea->SetGetFocusHdl( LINK( this, ScConsolidateDlg, GetEditFocusHdl ) );
122 m_xLbDataArea->connect_focus_in( LINK( this, ScConsolidateDlg, GetFocusHdl ) );
123 m_xLbDestArea->connect_focus_in( LINK( this, ScConsolidateDlg, GetFocusHdl ) );
124 m_xEdDataArea->SetModifyHdl( LINK( this, ScConsolidateDlg, ModifyHdl ) );
125 m_xEdDestArea->SetModifyHdl( LINK( this, ScConsolidateDlg, ModifyHdl ) );
126 m_xLbConsAreas->connect_selection_changed(LINK(this, ScConsolidateDlg, SelectTVHdl));
127 m_xLbDataArea->connect_changed( LINK( this, ScConsolidateDlg, SelectCBHdl ) );
128 m_xLbDestArea->connect_changed( LINK( this, ScConsolidateDlg, SelectCBHdl ) );
129 m_xBtnOk->connect_clicked( LINK( this, ScConsolidateDlg, OkHdl ) );
130 m_xBtnCancel->connect_clicked( LINK( this, ScConsolidateDlg, ClickHdl ) );
131 m_xBtnAdd->connect_clicked( LINK( this, ScConsolidateDlg, ClickHdl ) );
132 m_xBtnRemove->connect_clicked( LINK( this, ScConsolidateDlg, ClickHdl ) );
134 m_xBtnAdd->set_sensitive(false);
135 m_xBtnRemove->set_sensitive(false);
137 m_xBtnByRow->set_active( theConsData.bByRow );
138 m_xBtnByCol->set_active( theConsData.bByCol );
139 m_xBtnRefs->set_active( theConsData.bReferenceData );
141 m_xLbFunc->set_active( FuncToLbPos( theConsData.eFunction ) );
143 m_xLbConsAreas->set_selection_mode(SelectionMode::Multiple);
144 m_xLbConsAreas->set_size_request(m_xLbConsAreas->get_approximate_digit_width() * 16,
145 m_xLbConsAreas->get_height_rows(5));
147 // read consolidation areas
148 m_xLbConsAreas->clear();
149 const formula::FormulaGrammar::AddressConvention eConv = rDoc.GetAddressConvention();
150 for ( i=0; i<theConsData.nDataAreaCount; i++ )
152 const ScArea& rArea = theConsData.pDataAreas[i];
153 if ( rArea.nTab < rDoc.GetTableCount() )
155 aStr = ScRange( rArea.nColStart, rArea.nRowStart, rArea.nTab,
156 rArea.nColEnd, rArea.nRowEnd, rArea.nTab ).Format( rDoc,
157 ScRefFlags::RANGE_ABS_3D, eConv );
158 m_xLbConsAreas->append_text(aStr);
162 if ( theConsData.nTab < rDoc.GetTableCount() )
164 aStr = ScAddress( theConsData.nCol, theConsData.nRow, theConsData.nTab
165 ).Format( ScRefFlags::ADDR_ABS_3D, &rDoc, eConv );
166 m_xEdDestArea->SetText( aStr );
168 else
169 m_xEdDestArea->SetText(OUString());
171 // Use the ScAreaData helper class to save those range names from the
172 // RangeNames and database ranges that appear in the ListBoxes.
174 ScRangeName* pRangeNames = rDoc.GetRangeName();
175 ScDBCollection* pDbNames = rDoc.GetDBCollection();
176 size_t nRangeCount = pRangeNames ? pRangeNames->size() : 0;
177 size_t nDbCount = pDbNames ? pDbNames->getNamedDBs().size() : 0;
179 nAreaDataCount = nRangeCount+nDbCount;
180 pAreaData = nullptr;
182 if ( nAreaDataCount > 0 )
184 pAreaData.reset( new ScAreaData[nAreaDataCount] );
186 OUString aStrName;
187 sal_uInt16 nAt = 0;
188 ScRange aRange;
189 ScAreaNameIterator aIter( rDoc );
190 while ( aIter.Next( aStrName, aRange ) )
192 OUString aStrArea(aRange.Format(rDoc, ScRefFlags::ADDR_ABS_3D, eConv));
193 pAreaData[nAt++].Set( aStrName, aStrArea );
197 FillAreaLists();
198 ModifyHdl( *m_xEdDestArea );
199 m_xLbDataArea->set_active( 0 );
200 m_xEdDataArea->SetText(OUString());
201 m_xEdDataArea->GrabFocus();
203 //aFlSep.SetStyle( aFlSep.GetStyle() | WB_VERT );
205 //@BugID 54702 enable/disable only in base class
206 //SFX_APPWINDOW->set_sensitive(true);
209 void ScConsolidateDlg::FillAreaLists()
211 m_xLbDataArea->clear();
212 m_xLbDestArea->clear();
213 m_xLbDataArea->append_text( aStrUndefined );
214 m_xLbDestArea->append_text( aStrUndefined );
216 if ( pAreaData && (nAreaDataCount > 0) )
218 for ( size_t i=0;
219 (i<nAreaDataCount) && (!pAreaData[i].aStrName.isEmpty());
220 i++ )
222 m_xLbDataArea->append_text(pAreaData[i].aStrName);
223 m_xLbDestArea->append_text(pAreaData[i].aStrName);
228 // Handover of a range within a table that has been selected by the mouse.
229 // This range is then shown in the reference window as new selection.
231 void ScConsolidateDlg::SetReference( const ScRange& rRef, ScDocument& rDocP )
233 if ( !m_pRefInputEdit )
234 return;
236 if ( rRef.aStart != rRef.aEnd )
237 RefInputStart( m_pRefInputEdit );
239 OUString aStr;
240 ScRefFlags nFmt = ScRefFlags::RANGE_ABS_3D; //!!! nCurTab is still missing
241 const formula::FormulaGrammar::AddressConvention eConv = rDocP.GetAddressConvention();
243 if ( rRef.aStart.Tab() != rRef.aEnd.Tab() )
244 nFmt |= ScRefFlags::TAB2_3D;
246 if ( m_pRefInputEdit == m_xEdDataArea.get())
247 aStr = rRef.Format(rDocP, nFmt, eConv);
248 else if ( m_pRefInputEdit == m_xEdDestArea.get() )
249 aStr = rRef.aStart.Format(nFmt, &rDocP, eConv);
251 m_pRefInputEdit->SetRefString( aStr );
252 ModifyHdl( *m_pRefInputEdit );
255 void ScConsolidateDlg::Close()
257 DoClose( ScConsolidateDlgWrapper::GetChildWindowId() );
260 void ScConsolidateDlg::SetActive()
262 if ( bDlgLostFocus )
264 bDlgLostFocus = false;
266 if ( m_pRefInputEdit )
268 m_pRefInputEdit->GrabFocus();
269 ModifyHdl( *m_pRefInputEdit );
272 else
273 m_xDialog->grab_focus();
275 RefInputDone();
278 void ScConsolidateDlg::Deactivate()
280 bDlgLostFocus = true;
283 bool ScConsolidateDlg::VerifyEdit( formula::RefEdit* pEd )
285 if (pEd != m_xEdDataArea.get() && pEd != m_xEdDestArea.get())
286 return false;
288 SCTAB nTab = rViewData.GetTabNo();
289 bool bEditOk = false;
290 OUString theCompleteStr;
291 const formula::FormulaGrammar::AddressConvention eConv = rDoc.GetAddressConvention();
293 if ( pEd == m_xEdDataArea.get() )
295 bEditOk = ScRangeUtil::IsAbsArea( pEd->GetText(), rDoc,
296 nTab, &theCompleteStr, nullptr, nullptr, eConv );
298 else if ( pEd == m_xEdDestArea.get() )
300 OUString aPosStr;
302 ScRangeUtil::CutPosString( pEd->GetText(), aPosStr );
303 bEditOk = ScRangeUtil::IsAbsPos( aPosStr, rDoc,
304 nTab, &theCompleteStr, nullptr, eConv );
307 if ( bEditOk )
308 pEd->SetText( theCompleteStr );
310 return bEditOk;
313 // Handler:
315 IMPL_LINK( ScConsolidateDlg, GetEditFocusHdl, formula::RefEdit&, rControl, void )
317 m_pRefInputEdit = &rControl;
320 IMPL_LINK( ScConsolidateDlg, GetFocusHdl, weld::Widget&, rControl, void )
322 if (&rControl == m_xLbDataArea.get())
323 m_pRefInputEdit = m_xEdDataArea.get();
324 else if (&rControl == m_xLbDestArea.get())
325 m_pRefInputEdit = m_xEdDestArea.get();
328 IMPL_LINK_NOARG(ScConsolidateDlg, OkHdl, weld::Button&, void)
330 const sal_Int32 nDataAreaCount = m_xLbConsAreas->n_children();
332 if ( nDataAreaCount > 0 )
334 ScRefAddress aDestAddress;
335 SCTAB nTab = rViewData.GetTabNo();
336 OUString aDestPosStr( m_xEdDestArea->GetText() );
337 const formula::FormulaGrammar::AddressConvention eConv = rDoc.GetAddressConvention();
339 if ( ScRangeUtil::IsAbsPos( aDestPosStr, rDoc, nTab, nullptr, &aDestAddress, eConv ) )
341 ScConsolidateParam theOutParam( theConsData );
342 std::unique_ptr<ScArea[]> pDataAreas(new ScArea[nDataAreaCount]);
344 for ( sal_Int32 i=0; i<nDataAreaCount; ++i )
346 ScRangeUtil::MakeArea(m_xLbConsAreas->get_text(i),
347 pDataAreas[i], rDoc, nTab, eConv);
350 theOutParam.nCol = aDestAddress.Col();
351 theOutParam.nRow = aDestAddress.Row();
352 theOutParam.nTab = aDestAddress.Tab();
353 theOutParam.eFunction = LbPosToFunc( m_xLbFunc->get_active() );
354 theOutParam.bByCol = m_xBtnByCol->get_active();
355 theOutParam.bByRow = m_xBtnByRow->get_active();
356 theOutParam.bReferenceData = m_xBtnRefs->get_active();
357 theOutParam.SetAreas( std::move(pDataAreas), nDataAreaCount );
359 ScConsolidateItem aOutItem( nWhichCons, &theOutParam );
361 SetDispatcherLock( false );
362 SwitchToDocument();
363 GetBindings().GetDispatcher()->ExecuteList(SID_CONSOLIDATE,
364 SfxCallMode::SLOT | SfxCallMode::RECORD,
365 { &aOutItem });
366 response(RET_OK);
368 else
370 INFOBOX(m_xDialog.get(), STR_INVALID_TABREF);
371 m_xEdDestArea->GrabFocus();
374 else
375 response(RET_CANCEL); // no area defined -> Cancel
378 IMPL_LINK( ScConsolidateDlg, ClickHdl, weld::Button&, rBtn, void )
380 if ( &rBtn == m_xBtnCancel.get() )
381 response(RET_CANCEL);
382 else if ( &rBtn == m_xBtnAdd.get() )
384 if ( !m_xEdDataArea->GetText().isEmpty() )
386 OUString aNewEntry( m_xEdDataArea->GetText() );
387 std::unique_ptr<ScArea[]> ppAreas;
388 sal_uInt16 nAreaCount = 0;
389 const formula::FormulaGrammar::AddressConvention eConv = rDoc.GetAddressConvention();
391 if ( ScRangeUtil::IsAbsTabArea( aNewEntry, &rDoc, &ppAreas, &nAreaCount, true, eConv ) )
393 // IsAbsTabArea() creates an array of ScArea pointers,
394 // which have been created dynamically as well.
395 // These objects need to be deleted here.
397 for ( sal_uInt16 i=0; i<nAreaCount; i++ )
399 const ScArea& rArea = ppAreas[i];
400 OUString aNewArea = ScRange( rArea.nColStart, rArea.nRowStart, rArea.nTab,
401 rArea.nColEnd, rArea.nRowEnd, rArea.nTab
402 ).Format(rDoc, ScRefFlags::RANGE_ABS_3D, eConv);
404 if (m_xLbConsAreas->find_text(aNewArea) == -1)
406 m_xLbConsAreas->append_text( aNewArea );
410 else if ( VerifyEdit( m_xEdDataArea.get() ) )
412 OUString aNewArea( m_xEdDataArea->GetText() );
414 if (m_xLbConsAreas->find_text(aNewArea) == -1)
415 m_xLbConsAreas->append_text(aNewArea);
416 else
417 INFOBOX(m_xDialog.get(), STR_AREA_ALREADY_INSERTED);
419 else
421 INFOBOX(m_xDialog.get(), STR_INVALID_TABREF);
422 m_xEdDataArea->GrabFocus();
426 else if ( &rBtn == m_xBtnRemove.get() )
428 std::vector<int> aSelectedRows(m_xLbConsAreas->get_selected_rows());
429 std::sort(aSelectedRows.begin(), aSelectedRows.end());
430 for (auto it = aSelectedRows.rbegin(); it != aSelectedRows.rend(); ++it)
431 m_xLbConsAreas->remove(*it);
432 m_xBtnRemove->set_sensitive(false);
436 IMPL_LINK( ScConsolidateDlg, SelectTVHdl, weld::TreeView&, rLb, void )
438 if (rLb.get_selected_index() != -1)
439 m_xBtnRemove->set_sensitive(true);
440 else
441 m_xBtnRemove->set_sensitive(false);
444 IMPL_LINK( ScConsolidateDlg, SelectCBHdl, weld::ComboBox&, rLb, void )
446 formula::RefEdit* pEd = (&rLb == m_xLbDataArea.get()) ? m_xEdDataArea.get() : m_xEdDestArea.get();
447 const sal_Int32 nSelPos = rLb.get_active();
449 if ( (nSelPos > 0)
450 && (nAreaDataCount > 0)
451 && (pAreaData != nullptr) )
453 if ( o3tl::make_unsigned(nSelPos) <= nAreaDataCount )
455 OUString aString( pAreaData[nSelPos-1].aStrArea );
457 if ( &rLb == m_xLbDestArea.get() )
458 ScRangeUtil::CutPosString( aString, aString );
460 pEd->SetText( aString );
462 if ( pEd == m_xEdDataArea.get() )
463 m_xBtnAdd->set_sensitive(true);
466 else
468 pEd->SetText( OUString() );
469 if ( pEd == m_xEdDataArea.get() )
470 m_xBtnAdd->set_sensitive(true);
474 IMPL_LINK( ScConsolidateDlg, ModifyHdl, formula::RefEdit&, rEd, void )
476 if ( &rEd == m_xEdDataArea.get() )
478 OUString aAreaStr( rEd.GetText() );
479 if ( !aAreaStr.isEmpty() )
480 m_xBtnAdd->set_sensitive(true);
481 else
482 m_xBtnAdd->set_sensitive(false);
484 else if ( &rEd == m_xEdDestArea.get() )
486 m_xLbDestArea->set_active(0);
490 // TODO: generalize!
491 // Resource of the ListBox and these two conversion methods are also in
492 // tpsubt and everywhere, where StarCalc functions are selectable.
494 ScSubTotalFunc ScConsolidateDlg::LbPosToFunc( sal_Int32 nPos )
496 switch ( nPos )
498 case 2: return SUBTOTAL_FUNC_AVE;
499 case 6: return SUBTOTAL_FUNC_CNT;
500 case 1: return SUBTOTAL_FUNC_CNT2;
501 case 3: return SUBTOTAL_FUNC_MAX;
502 case 4: return SUBTOTAL_FUNC_MIN;
503 case 5: return SUBTOTAL_FUNC_PROD;
504 case 7: return SUBTOTAL_FUNC_STD;
505 case 8: return SUBTOTAL_FUNC_STDP;
506 case 9: return SUBTOTAL_FUNC_VAR;
507 case 10: return SUBTOTAL_FUNC_VARP;
508 case 0:
509 default:
510 return SUBTOTAL_FUNC_SUM;
514 sal_Int32 ScConsolidateDlg::FuncToLbPos( ScSubTotalFunc eFunc )
516 switch ( eFunc )
518 case SUBTOTAL_FUNC_AVE: return 2;
519 case SUBTOTAL_FUNC_CNT: return 6;
520 case SUBTOTAL_FUNC_CNT2: return 1;
521 case SUBTOTAL_FUNC_MAX: return 3;
522 case SUBTOTAL_FUNC_MIN: return 4;
523 case SUBTOTAL_FUNC_PROD: return 5;
524 case SUBTOTAL_FUNC_STD: return 7;
525 case SUBTOTAL_FUNC_STDP: return 8;
526 case SUBTOTAL_FUNC_VAR: return 9;
527 case SUBTOTAL_FUNC_VARP: return 10;
528 case SUBTOTAL_FUNC_NONE:
529 case SUBTOTAL_FUNC_SUM:
530 default:
531 return 0;
535 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */