LibreOffice Module chart2 (master) 1
tp_DataSource.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 "tp_DataSource.hxx"
21#include <strings.hrc>
22#include <ResId.hxx>
23#include <ChartType.hxx>
25#include <ChartTypeTemplate.hxx>
26#include <ChartModel.hxx>
28#include <DataSeries.hxx>
29#include <DataSeriesHelper.hxx>
31#include <DataSourceHelper.hxx>
33#include "DialogModel.hxx"
34#include <o3tl/safeint.hxx>
35#include <TabPageNotifiable.hxx>
36#include <com/sun/star/chart2/XDataSeries.hpp>
37#include <com/sun/star/chart2/data/XDataProvider.hpp>
38
40
41using namespace ::com::sun::star;
42using namespace ::com::sun::star::chart2;
43
44using ::com::sun::star::uno::Reference;
45
46namespace
47{
48
49constexpr OUStringLiteral lcl_aLabelRole( u"label" );
50
51void lcl_UpdateCurrentRange(weld::TreeView& rOutListBox, const OUString & rRole,
52 const OUString& rRange)
53{
54 int nEntry = rOutListBox.get_selected_index();
55 if (nEntry != -1)
56 {
58 rOutListBox.set_text(nEntry, rRange, 1);
59 ::chart::SeriesEntry* pEntry = weld::fromId<::chart::SeriesEntry*>(rOutListBox.get_id(nEntry));
60 pEntry->m_sRole = rRole;
61 }
62}
63
64bool lcl_UpdateCurrentSeriesName(weld::TreeView& rOutListBox)
65{
66 int nEntry = rOutListBox.get_selected_index();
67 if (nEntry == -1)
68 return false;
69
70 bool bResult = false;
71 ::chart::SeriesEntry * pEntry = weld::fromId<::chart::SeriesEntry*>(rOutListBox.get_id(nEntry));
72 if (pEntry->m_xDataSeries.is() && pEntry->m_xChartType.is())
73 {
74 OUString aLabel(pEntry->m_xDataSeries->getLabelForRole(
75 pEntry->m_xChartType->getRoleOfSequenceForSeriesLabel()));
76 if (!aLabel.isEmpty())
77 {
78 rOutListBox.set_text(nEntry, aLabel);
79 bResult = true;
80 }
81 }
82 return bResult;
83}
84
85OUString lcl_GetSelectedRole(const weld::TreeView& rRoleListBox, bool bUITranslated = false)
86{
87 int nEntry = rRoleListBox.get_selected_index();
88 if (nEntry != -1)
89 {
90 if (bUITranslated)
91 return rRoleListBox.get_text(nEntry);
92 ::chart::SeriesEntry* pEntry = weld::fromId<::chart::SeriesEntry*>(rRoleListBox.get_id(nEntry));
93 return pEntry->m_sRole;
94 }
95 return OUString();
96}
97
98OUString lcl_GetSelectedRolesRange( const weld::TreeView& rRoleListBox )
99{
100 OUString aResult;
101 int nEntry = rRoleListBox.get_selected_index();
102 if (nEntry != -1)
103 aResult = rRoleListBox.get_text(nEntry, 1);
104 return aResult;
105}
106
107OUString lcl_GetSequenceNameForLabel(const ::chart::SeriesEntry* pEntry)
108{
109 OUString aResult("values-y");
110 if (pEntry && pEntry->m_xChartType.is())
111 aResult = pEntry->m_xChartType->getRoleOfSequenceForSeriesLabel();
112 return aResult;
113}
114
115void lcl_enableRangeChoosing(bool bEnable, weld::DialogController* pDialog)
116{
117 if (!pDialog)
118 return;
119 weld::Dialog* pDlg = pDialog->getDialog();
120 pDlg->set_modal(!bEnable);
121 pDlg->set_visible(!bEnable);
122}
123
124void lcl_addLSequenceToDataSource(
125 const uno::Reference< chart2::data::XLabeledDataSequence > & xLSequence,
126 const Reference< ::chart::DataSeries > & xSource )
127{
128 if( xSource.is())
129 {
130 std::vector< uno::Reference< chart2::data::XLabeledDataSequence > > aData = xSource->getDataSequences2();
131 aData.push_back( xLSequence );
132 xSource->setData( aData );
133 }
134}
135
136uno::Reference< chart2::data::XLabeledDataSequence > lcl_findLSequenceWithOnlyLabel(
137 const rtl::Reference< ::chart::DataSeries > & xDataSource )
138{
139 uno::Reference< chart2::data::XLabeledDataSequence > xResult;
140
141 for( uno::Reference< chart2::data::XLabeledDataSequence > const & labeledDataSeq : xDataSource->getDataSequences2() )
142 {
143 // no values are set but a label exists
144 if( ! labeledDataSeq->getValues().is() &&
145 labeledDataSeq->getLabel().is())
146 {
147 xResult = labeledDataSeq;
148 break;
149 }
150 }
151
152 return xResult;
153}
154
155} // anonymous namespace
156
157namespace chart
158{
159
161 DialogModel & rDialogModel,
162 ChartTypeTemplateProvider* pTemplateProvider,
163 bool bHideDescription /* = false */)
164 : ::vcl::OWizardPage(pPage, pController, "modules/schart/ui/tp_DataSource.ui", "tp_DataSource")
165 , m_pTemplateProvider(pTemplateProvider)
166 , m_rDialogModel(rDialogModel)
167 , m_pCurrentRangeChoosingField( nullptr )
168 , m_bIsDirty( false )
169 , m_pTabPageNotifiable(dynamic_cast<TabPageNotifiable*>(pController))
170 , m_xFT_CAPTION(m_xBuilder->weld_label("FT_CAPTION_FOR_WIZARD"))
171 , m_xFT_SERIES(m_xBuilder->weld_label("FT_SERIES"))
172 , m_xLB_SERIES(m_xBuilder->weld_tree_view("LB_SERIES"))
173 , m_xBTN_ADD(m_xBuilder->weld_button("BTN_ADD"))
174 , m_xBTN_REMOVE(m_xBuilder->weld_button("BTN_REMOVE"))
175 , m_xBTN_UP(m_xBuilder->weld_button("BTN_UP"))
176 , m_xBTN_DOWN(m_xBuilder->weld_button("BTN_DOWN"))
177 , m_xFT_ROLE(m_xBuilder->weld_label("FT_ROLE"))
178 , m_xLB_ROLE(m_xBuilder->weld_tree_view("LB_ROLE"))
179 , m_xFT_RANGE(m_xBuilder->weld_label("FT_RANGE"))
180 , m_xEDT_RANGE(m_xBuilder->weld_entry("EDT_RANGE"))
181 , m_xIMB_RANGE_MAIN(m_xBuilder->weld_button("IMB_RANGE_MAIN"))
182 , m_xFT_CATEGORIES(m_xBuilder->weld_label("FT_CATEGORIES"))
183 , m_xFT_DATALABELS(m_xBuilder->weld_label("FT_DATALABELS"))
184 , m_xEDT_CATEGORIES(m_xBuilder->weld_entry("EDT_CATEGORIES"))
185 , m_xIMB_RANGE_CAT(m_xBuilder->weld_button("IMB_RANGE_CAT"))
186{
187 m_xLB_SERIES->set_size_request(m_xLB_SERIES->get_approximate_digit_width() * 25,
188 m_xLB_SERIES->get_height_rows(10));
189 m_xLB_ROLE->set_size_request(m_xLB_ROLE->get_approximate_digit_width() * 60,
190 m_xLB_ROLE->get_height_rows(5));
191 m_xFT_CAPTION->set_visible(!bHideDescription);
192
193 m_aFixedTextRange = m_xFT_RANGE->get_label();
194 SetPageTitle(SchResId(STR_OBJECT_DATASERIES_PLURAL));
195
196 // set handlers
197 m_xLB_SERIES->connect_changed(LINK(this, DataSourceTabPage, SeriesSelectionChangedHdl));
198 m_xLB_ROLE->connect_changed(LINK(this, DataSourceTabPage, RoleSelectionChangedHdl));
199
200 m_xIMB_RANGE_MAIN->connect_clicked(LINK(this, DataSourceTabPage, MainRangeButtonClickedHdl));
201 m_xIMB_RANGE_CAT->connect_clicked(LINK(this, DataSourceTabPage, CategoriesRangeButtonClickedHdl));
202
203 m_xBTN_ADD->connect_clicked(LINK(this, DataSourceTabPage, AddButtonClickedHdl));
204 m_xBTN_REMOVE->connect_clicked(LINK(this, DataSourceTabPage, RemoveButtonClickedHdl));
205
206 m_xBTN_UP->connect_clicked(LINK(this, DataSourceTabPage, UpButtonClickedHdl));
207 m_xBTN_DOWN->connect_clicked(LINK(this, DataSourceTabPage, DownButtonClickedHdl));
208
209 m_xEDT_RANGE->connect_changed(LINK(this, DataSourceTabPage, RangeModifiedHdl));
210 m_xEDT_CATEGORIES->connect_changed(LINK( this, DataSourceTabPage, RangeModifiedHdl));
211
212 // init controls
213 std::vector<int> aWidths { o3tl::narrowing<int>(m_xLB_ROLE->get_approximate_digit_width() * 20) };
214 m_xLB_ROLE->set_column_fixed_widths(aWidths);
215 m_xLB_ROLE->show();
216
218
219 // select first series
220 if (m_xLB_SERIES->n_children())
221 m_xLB_SERIES->select(0);
222}
223
224void DataSourceTabPage::InsertRoleLBEntry(const OUString& rRole, const OUString& rRange)
225{
226 m_aEntries.emplace_back(new SeriesEntry);
227 SeriesEntry* pEntry = m_aEntries.back().get();
228 pEntry->m_sRole = rRole;
229 m_xLB_ROLE->append(weld::toId(pEntry),
231 m_xLB_ROLE->set_text(m_xLB_ROLE->n_children() - 1, rRange, 1);
232}
233
235{
236}
237
239{
240 OWizardPage::Activate();
242 m_xLB_SERIES->grab_focus();
243}
244
246{
247}
248
250{
251 commitPage();
253}
254
256{
257 commitPage(::vcl::WizardTypes::eFinish);
258}
259
261{
262 //ranges may have been edited in the meanwhile (dirty is true in that case here)
263 if( isValid() )
264 {
266 return true; //return false if this page should not be left
267 }
268 else
269 return false;
270}
271
273{
274 OUString aRange(rEdit.get_text());
275 bool bIsValid = aRange.isEmpty() ||
276 m_rDialogModel.getRangeSelectionHelper()->verifyCellRange(aRange);
278 return bIsValid;
279}
280
282{
283 bool bRoleRangeValid = true;
284 bool bCategoriesRangeValid = true;
285 bool bHasSelectedEntry = (m_xLB_SERIES->get_selected_index() != -1);
286
287 if (bHasSelectedEntry)
288 bRoleRangeValid = isRangeFieldContentValid(*m_xEDT_RANGE);
289 if (m_xEDT_CATEGORIES->get_sensitive())
290 bCategoriesRangeValid = isRangeFieldContentValid( *m_xEDT_CATEGORIES );
291 bool bValid = ( bRoleRangeValid && bCategoriesRangeValid );
292
294 {
295 if( bValid )
296 m_pTabPageNotifiable->setValidPage( this );
297 else
298 m_pTabPageNotifiable->setInvalidPage( this );
299 }
300
301 return bValid;
302}
303
305{
306 m_bIsDirty = true;
307}
308
310{
311 // series
313 SeriesSelectionChangedHdl(*m_xLB_SERIES);
314
315 // categories
317
319}
320
322{
324 SeriesEntry* pEntry = nullptr;
325 int nEntry = m_xLB_SERIES->get_selected_index();
326 if (nEntry != -1)
327 {
328 pEntry = weld::fromId<SeriesEntry*>(m_xLB_SERIES->get_id(nEntry));
329 xSelected = pEntry->m_xDataSeries;
330 }
331
332 bool bHasSelectedEntry = (pEntry != nullptr);
333 int nSelectedEntry = -1;
334
335 m_xLB_SERIES->freeze();
336 m_xLB_SERIES->clear();
337
338 std::vector< DialogModel::tSeriesWithChartTypeByName > aSeries(
340
341 sal_Int32 nUnnamedSeriesIndex = 1;
342 nEntry = 0;
343 for (auto const& series : aSeries)
344 {
345 OUString aLabel(series.first);
346 if (aLabel.isEmpty())
347 {
348 if( nUnnamedSeriesIndex > 1 )
349 {
350 OUString aResString(::chart::SchResId( STR_DATA_UNNAMED_SERIES_WITH_INDEX ));
351
352 // replace index of unnamed series
353 static constexpr OUStringLiteral aReplacementStr( u"%NUMBER" );
354 sal_Int32 nIndex = aResString.indexOf( aReplacementStr );
355 if( nIndex != -1 )
356 aLabel = aResString.replaceAt(
357 nIndex, aReplacementStr.getLength(),
358 OUString::number(nUnnamedSeriesIndex));
359 }
360 if( aLabel.isEmpty() )
361 aLabel = ::chart::SchResId( STR_DATA_UNNAMED_SERIES );
362
363 ++nUnnamedSeriesIndex;
364 }
365
366 m_aEntries.emplace_back(new SeriesEntry);
367 pEntry = m_aEntries.back().get();
368 pEntry->m_xDataSeries = series.second.first;
369 pEntry->m_xChartType = series.second.second;
370 m_xLB_SERIES->append(weld::toId(pEntry), aLabel);
371 if (bHasSelectedEntry && series.second.first == xSelected)
372 nSelectedEntry = nEntry;
373 ++nEntry;
374 }
375
376 m_xLB_SERIES->thaw();
377
378 if (bHasSelectedEntry && nSelectedEntry != -1)
379 m_xLB_SERIES->select(nSelectedEntry);
380}
381
383{
384 int nSeriesEntry = m_xLB_SERIES->get_selected_index();
385 SeriesEntry* pSeriesEntry = nullptr;
386 if (nSeriesEntry != -1)
387 pSeriesEntry = weld::fromId<SeriesEntry*>(m_xLB_SERIES->get_id(nSeriesEntry));
388 bool bHasSelectedEntry = (pSeriesEntry != nullptr);
389
390 int nRoleIndex = m_xLB_ROLE->get_selected_index();
391 if (!bHasSelectedEntry)
392 return;
393
396 pSeriesEntry->m_xDataSeries,
397 lcl_GetSequenceNameForLabel( pSeriesEntry ),
398 pSeriesEntry->m_xChartType ));
399
400 // fill role list
401 m_xLB_ROLE->freeze();
402 m_xLB_ROLE->clear();
403
404 for (auto const& elemRole : aRoles)
405 {
406 InsertRoleLBEntry(elemRole.first, elemRole.second);
407 }
408
409 m_xLB_ROLE->thaw();
410
411 // series may contain no roles, check listbox size before selecting entries
412 if (m_xLB_ROLE->n_children() > 0)
413 {
414 if (nRoleIndex == -1 || nRoleIndex >= m_xLB_ROLE->n_children())
415 nRoleIndex = 0;
416 m_xLB_ROLE->select(nRoleIndex);
417 }
418}
419
421{
422 int nSeriesEntry = m_xLB_SERIES->get_selected_index();
423 bool bHasSelectedSeries = nSeriesEntry != -1;
424 bool bHasValidRole = false;
425 bool bHasRangeChooser = m_rDialogModel.getRangeSelectionHelper()->hasRangeSelection();
426
427 if( bHasSelectedSeries )
428 {
429 int nRoleEntry = m_xLB_ROLE->get_selected_index();
430 bHasValidRole = nRoleEntry != -1;
431 }
432
433 m_xBTN_ADD->set_sensitive(true);
434 m_xBTN_REMOVE->set_sensitive(bHasSelectedSeries);
435
436 m_xBTN_UP->set_sensitive(bHasSelectedSeries && (nSeriesEntry != 0));
437 m_xBTN_DOWN->set_sensitive(bHasSelectedSeries && (nSeriesEntry != m_xLB_SERIES->n_children() - 1));
438
439 bool bHasCategories = m_rDialogModel.isCategoryDiagram();
440
441 m_xFT_DATALABELS->set_visible(!bHasCategories);
442 m_xFT_CATEGORIES->set_visible( bHasCategories);
443 bool bShowIB = bHasRangeChooser;
444
445 m_xIMB_RANGE_CAT->set_visible(bShowIB);
446
447 m_xFT_ROLE->set_sensitive(bHasSelectedSeries);
448 m_xLB_ROLE->set_sensitive(bHasSelectedSeries);
449
450 m_xFT_RANGE->set_sensitive(bHasValidRole);
451 m_xEDT_RANGE->set_sensitive(bHasValidRole);
452
453 m_xFT_SERIES->set_sensitive(true);
454 m_xLB_SERIES->set_sensitive(true);
455
456 m_xIMB_RANGE_MAIN->set_visible(bShowIB);
457
458 isValid();
459}
460
461IMPL_LINK_NOARG(DataSourceTabPage, SeriesSelectionChangedHdl, weld::TreeView&, void)
462{
463 m_rDialogModel.startControllerLockTimer();
464 if (m_xLB_SERIES->get_selected_index() != -1)
465 {
466 fillRoleListBox();
467 RoleSelectionChangedHdl(*m_xLB_ROLE);
468 }
469 updateControlState();
470}
471
472IMPL_LINK_NOARG(DataSourceTabPage, RoleSelectionChangedHdl, weld::TreeView&, void)
473{
474 m_rDialogModel.startControllerLockTimer();
475 int nEntry = m_xLB_ROLE->get_selected_index();
476 if (nEntry == -1)
477 return;
478
479 OUString aSelectedRoleUI = lcl_GetSelectedRole( *m_xLB_ROLE, true );
480 OUString aSelectedRange = lcl_GetSelectedRolesRange( *m_xLB_ROLE );
481
482 // replace role in fixed text label
483 static constexpr OUStringLiteral aReplacementStr( u"%VALUETYPE" );
484 sal_Int32 nIndex = m_aFixedTextRange.indexOf( aReplacementStr );
485 if( nIndex != -1 )
486 {
487 m_xFT_RANGE->set_label(
488 m_aFixedTextRange.replaceAt(
489 nIndex, aReplacementStr.getLength(), aSelectedRoleUI ));
490 }
491
492 m_xEDT_RANGE->set_text(aSelectedRange);
493 isValid();
494}
495
496IMPL_LINK_NOARG(DataSourceTabPage, MainRangeButtonClickedHdl, weld::Button&, void)
497{
498 OSL_ASSERT( m_pCurrentRangeChoosingField == nullptr );
499 m_pCurrentRangeChoosingField = m_xEDT_RANGE.get();
500 if (!m_xEDT_RANGE->get_text().isEmpty() &&
501 !updateModelFromControl( m_pCurrentRangeChoosingField))
502 return;
503
504 int nEntry = m_xLB_SERIES->get_selected_index();
505 bool bHasSelectedEntry = (nEntry != -1);
506
507 OUString aSelectedRolesRange = lcl_GetSelectedRolesRange(*m_xLB_ROLE);
508
509 if (bHasSelectedEntry && (m_xLB_ROLE->get_selected_index() != -1))
510 {
511 OUString aUIStr(SchResId(STR_DATA_SELECT_RANGE_FOR_SERIES));
512
513 // replace role
514 OUString aReplacement( "%VALUETYPE" );
515 sal_Int32 nIndex = aUIStr.indexOf( aReplacement );
516 if( nIndex != -1 )
517 {
518 aUIStr = aUIStr.replaceAt( nIndex, aReplacement.getLength(),
519 lcl_GetSelectedRole( *m_xLB_ROLE, true ));
520 }
521 // replace series name
522 aReplacement = "%SERIESNAME";
523 nIndex = aUIStr.indexOf( aReplacement );
524 if( nIndex != -1 )
525 {
526 aUIStr = aUIStr.replaceAt(nIndex, aReplacement.getLength(),
527 m_xLB_SERIES->get_text(nEntry));
528 }
529
530 lcl_enableRangeChoosing(true, m_pDialogController);
531 m_rDialogModel.getRangeSelectionHelper()->chooseRange( aSelectedRolesRange, aUIStr, *this );
532 }
533 else
534 m_pCurrentRangeChoosingField = nullptr;
535}
536
537IMPL_LINK_NOARG(DataSourceTabPage, CategoriesRangeButtonClickedHdl, weld::Button&, void)
538{
539 OSL_ASSERT( m_pCurrentRangeChoosingField == nullptr );
540 m_pCurrentRangeChoosingField = m_xEDT_CATEGORIES.get();
541 if( !m_xEDT_CATEGORIES->get_text().isEmpty() &&
542 ! updateModelFromControl( m_pCurrentRangeChoosingField ))
543 return;
544
545 OUString aStr(SchResId(m_xFT_CATEGORIES->get_visible() ? STR_DATA_SELECT_RANGE_FOR_CATEGORIES : STR_DATA_SELECT_RANGE_FOR_DATALABELS));
546 lcl_enableRangeChoosing(true, m_pDialogController);
547 m_rDialogModel.getRangeSelectionHelper()->chooseRange(
548 m_rDialogModel.getCategoriesRange(), aStr, *this );
549}
550
551IMPL_LINK_NOARG(DataSourceTabPage, AddButtonClickedHdl, weld::Button&, void)
552{
553 m_rDialogModel.startControllerLockTimer();
554 int nEntry = m_xLB_SERIES->get_selected_index();
555 rtl::Reference< DataSeries > xSeriesToInsertAfter;
556 rtl::Reference< ChartType > xChartTypeForNewSeries;
557 if( m_pTemplateProvider )
558 m_rDialogModel.setTemplate( m_pTemplateProvider->getCurrentTemplate());
559
560 if (nEntry != -1)
561 {
562 ::chart::SeriesEntry* pEntry = weld::fromId<::chart::SeriesEntry*>(m_xLB_SERIES->get_id(nEntry));
563 xSeriesToInsertAfter = pEntry->m_xDataSeries;
564 xChartTypeForNewSeries = pEntry->m_xChartType;
565 }
566 else
567 {
568 std::vector< rtl::Reference< ChartType > > aCntVec(
569 m_rDialogModel.getAllDataSeriesContainers());
570 if( ! aCntVec.empty())
571 xChartTypeForNewSeries = aCntVec.front();
572 }
573 OSL_ENSURE( xChartTypeForNewSeries.is(), "Cannot insert new series" );
574
575 m_rDialogModel.insertSeriesAfter( xSeriesToInsertAfter, xChartTypeForNewSeries );
576 setDirty();
577
578 fillSeriesListBox();
579 // note the box was cleared and refilled, so nEntry is invalid now
580
581 int nSelEntry = m_xLB_SERIES->get_selected_index();
582 if (nSelEntry != -1)
583 {
584 ++nSelEntry;
585 if (nSelEntry < m_xLB_SERIES->n_children())
586 m_xLB_SERIES->select(nSelEntry);
587 }
588 SeriesSelectionChangedHdl(*m_xLB_SERIES);
589}
590
591IMPL_LINK_NOARG(DataSourceTabPage, RemoveButtonClickedHdl, weld::Button&, void)
592{
593 m_rDialogModel.startControllerLockTimer();
594 int nEntry = m_xLB_SERIES->get_selected_index();
595 if (nEntry == -1)
596 return;
597
598 SeriesEntry* pEntry = weld::fromId<::chart::SeriesEntry*>(m_xLB_SERIES->get_id(nEntry));
599 rtl::Reference< DataSeries > xNewSelSeries;
600 SeriesEntry * pNewSelEntry = nullptr;
601 if (nEntry + 1 < m_xLB_SERIES->n_children())
602 pNewSelEntry = weld::fromId<::chart::SeriesEntry*>(m_xLB_SERIES->get_id(nEntry + 1));
603 else if (nEntry > 0)
604 pNewSelEntry = weld::fromId<::chart::SeriesEntry*>(m_xLB_SERIES->get_id(nEntry - 1));
605 if (pNewSelEntry)
606 xNewSelSeries = pNewSelEntry->m_xDataSeries;
607
608 m_rDialogModel.deleteSeries( pEntry->m_xDataSeries, pEntry->m_xChartType );
609 setDirty();
610
611 m_xLB_SERIES->remove(nEntry);
612 fillSeriesListBox();
613
614 // select previous or next series
615 if (xNewSelSeries.is())
616 {
617 for (int i = 0; i < m_xLB_SERIES->n_children(); ++i)
618 {
619 pEntry = weld::fromId<::chart::SeriesEntry*>(m_xLB_SERIES->get_id(i));
620 if (pEntry->m_xDataSeries == xNewSelSeries)
621 {
622 m_xLB_SERIES->select(i);
623 break;
624 }
625 }
626 }
627 SeriesSelectionChangedHdl(*m_xLB_SERIES);
628}
629
631{
632 m_rDialogModel.startControllerLockTimer();
633
634 int nEntry = m_xLB_SERIES->get_selected_index();
635 SeriesEntry* pEntry = nullptr;
636 if (nEntry != -1)
637 pEntry = weld::fromId<SeriesEntry*>(m_xLB_SERIES->get_id(nEntry));
638
639 bool bHasSelectedEntry = (pEntry != nullptr);
640
641 if (bHasSelectedEntry)
642 {
643 m_rDialogModel.moveSeries( pEntry->m_xDataSeries, DialogModel::MoveDirection::Up );
644 setDirty();
645 fillSeriesListBox();
646 SeriesSelectionChangedHdl(*m_xLB_SERIES);
647 }
648}
649
650IMPL_LINK_NOARG(DataSourceTabPage, DownButtonClickedHdl, weld::Button&, void)
651{
652 m_rDialogModel.startControllerLockTimer();
653
654 int nEntry = m_xLB_SERIES->get_selected_index();
655 SeriesEntry* pEntry = nullptr;
656 if (nEntry != -1)
657 pEntry = weld::fromId<SeriesEntry*>(m_xLB_SERIES->get_id(nEntry));
658
659 bool bHasSelectedEntry = (pEntry != nullptr);
660
661 if (bHasSelectedEntry)
662 {
663 m_rDialogModel.moveSeries( pEntry->m_xDataSeries, DialogModel::MoveDirection::Down );
664 setDirty();
665 fillSeriesListBox();
666 SeriesSelectionChangedHdl(*m_xLB_SERIES);
667 }
668}
669
670IMPL_LINK(DataSourceTabPage, RangeModifiedHdl, weld::Entry&, rEdit, void)
671{
672 // note: isValid sets the color of the edit field
673 if( isRangeFieldContentValid( rEdit ))
674 {
675 setDirty();
676 updateModelFromControl( &rEdit );
677 if (&rEdit == m_xEDT_RANGE.get())
678 {
679 if( ! lcl_UpdateCurrentSeriesName( *m_xLB_SERIES ))
680 fillSeriesListBox();
681 }
682 }
683
684 // enable/disable OK button
685 isValid();
686}
687
689 const OUString & rNewRange )
690{
691 // rNewRange becomes invalid after removing the listener
692 OUString aRange( rNewRange );
693
695
696 // stop listening
697 m_rDialogModel.getRangeSelectionHelper()->stopRangeListening();
698
699 // change edit field
701 {
704 }
705
707 {
708 m_xEDT_RANGE->set_text(aRange);
709 setDirty();
710 }
712 {
713 m_xEDT_CATEGORIES->set_text(aRange);
714 setDirty();
715 }
716
718 if (!lcl_UpdateCurrentSeriesName(*m_xLB_SERIES))
720
722
724 lcl_enableRangeChoosing(false, m_pDialogController);
725}
726
728{
729 m_rDialogModel.getRangeSelectionHelper()->stopRangeListening( false );
730}
731
733{
734 if (!m_bIsDirty)
735 return true;
736
738
739 // @todo: validity check of field content
740 bool bResult = true;
741 bool bAll = (pField == nullptr);
743
744 if (bAll || (pField == m_xEDT_CATEGORIES.get()))
745 {
747 if( xDataProvider.is())
748 {
749 OUString aRange(m_xEDT_CATEGORIES->get_text());
750 if (!aRange.isEmpty())
751 {
752 // create or change categories
753 if( !xLabeledSeq.is())
754 {
756 m_rDialogModel.setCategories( xLabeledSeq );
757 }
758 try
759 {
760 xLabeledSeq->setValues( xDataProvider->createDataSequenceByRangeRepresentation( aRange ));
761 }
762 catch( const uno::Exception & )
763 {
764 // should work as validation should have happened before
765 DBG_UNHANDLED_EXCEPTION("chart2");
766 }
767 }
768 else if( xLabeledSeq.is())
769 {
770 // clear existing categories
771 xLabeledSeq.set(nullptr);
772 m_rDialogModel.setCategories( xLabeledSeq );
773 }
774 }
775 }
776
777 int nSeriesEntry = m_xLB_SERIES->get_selected_index();
778 SeriesEntry* pSeriesEntry = nullptr;
779 if (nSeriesEntry != -1)
780 pSeriesEntry = weld::fromId<SeriesEntry*>(m_xLB_SERIES->get_id(nSeriesEntry));
781 bool bHasSelectedEntry = (pSeriesEntry != nullptr);
782
783 if( bHasSelectedEntry )
784 {
785 if( bAll || (pField == m_xEDT_RANGE.get()) )
786 {
787 try
788 {
789 OUString aSelectedRole = lcl_GetSelectedRole( *m_xLB_ROLE );
790 OUString aRange(m_xEDT_RANGE->get_text());
791 OUString aSequenceRole( aSelectedRole );
792 bool bIsLabel = (aSequenceRole == lcl_aLabelRole );
793 OUString aSequenceNameForLabel( lcl_GetSequenceNameForLabel( pSeriesEntry ));
794
795 if( bIsLabel )
796 aSequenceRole = aSequenceNameForLabel;
797
799 DataSeriesHelper::getDataSequenceByRole( pSeriesEntry->m_xDataSeries, aSequenceRole );
800
801 if( xDataProvider.is())
802 {
803 if( bIsLabel )
804 {
805 if( ! xLabeledSeq.is())
806 {
807 // check if there is already an "orphan" label sequence
808 xLabeledSeq = lcl_findLSequenceWithOnlyLabel( pSeriesEntry->m_xDataSeries );
809 if( ! xLabeledSeq.is())
810 {
811 // no corresponding labeled data sequence for label found
813 lcl_addLSequenceToDataSource( xLabeledSeq, pSeriesEntry->m_xDataSeries );
814 }
815 }
816 if( xLabeledSeq.is())
817 {
818 if( !aRange.isEmpty())
819 {
821 try
822 {
823 xNewSeq.set( xDataProvider->createDataSequenceByRangeRepresentation( aRange ));
824 }
825 catch( const uno::Exception & )
826 {
827 // should work as validation should have happened before
828 DBG_UNHANDLED_EXCEPTION("chart2");
829 }
830 if( xNewSeq.is())
831 {
832 // update range name by the full string provided
833 // by the data provider. E.g. "a1" might become
834 // "$Sheet1.$A$1"
835 aRange = xNewSeq->getSourceRangeRepresentation();
836 Reference< beans::XPropertySet > xProp( xNewSeq, uno::UNO_QUERY_THROW );
837 xProp->setPropertyValue( "Role" , uno::Any( OUString(lcl_aLabelRole) ));
838
839 //Labels should always include hidden cells, regardless of the setting chosen
840 xProp->setPropertyValue( "IncludeHiddenCells", uno::Any(true));
841 xLabeledSeq->setLabel( xNewSeq );
842 }
843 }
844 else
845 {
846 xLabeledSeq->setLabel( Reference< data::XDataSequence >());
847 }
848 }
849 }
850 else
851 {
852 if( !aRange.isEmpty())
853 {
855 try
856 {
857 xNewSeq.set( xDataProvider->createDataSequenceByRangeRepresentation( aRange ));
858 }
859 catch( const uno::Exception & )
860 {
861 // should work as validation should have happened before
862 DBG_UNHANDLED_EXCEPTION("chart2");
863 }
864 if( xNewSeq.is())
865 {
866 // update range name by the full string provided
867 // by the data provider. E.g. "a1:e1" might become
868 // "$Sheet1.$A$1:$E$1"
869 aRange = xNewSeq->getSourceRangeRepresentation();
870
871 Reference< beans::XPropertySet > xProp( xNewSeq, uno::UNO_QUERY_THROW );
872 xProp->setPropertyValue( "Role" , uno::Any( aSelectedRole ));
873 if( !xLabeledSeq.is())
874 {
875 if( aSelectedRole == aSequenceNameForLabel )
876 xLabeledSeq = lcl_findLSequenceWithOnlyLabel( pSeriesEntry->m_xDataSeries );
877 if( ! xLabeledSeq.is())
878 {
880 lcl_addLSequenceToDataSource( xLabeledSeq, pSeriesEntry->m_xDataSeries );
881 }
882 }
883 xLabeledSeq->setValues( xNewSeq );
884 }
885 }
886 }
887 }
888
889 lcl_UpdateCurrentRange( *m_xLB_ROLE, aSelectedRole, aRange );
890 }
891 catch( const uno::Exception & )
892 {
893 DBG_UNHANDLED_EXCEPTION("chart2");
894 bResult = false;
895 }
896 }
897 }
898
899 // update View
900 // @todo remove this when automatic view updates from calc, writer and own data sequences are available
901 if( bResult )
902 {
903 try
904 {
906 m_rDialogModel.getChartModel()->setModified( true );
908 if(rInfo.bTimeBased)
909 {
911 }
912 }
913 catch( const uno::Exception & )
914 {
915 DBG_UNHANDLED_EXCEPTION("chart2");
916 }
917 }
918
919 return bResult;
920}
921
922} // namespace chart
923
924/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
void SetPageTitle(const OUString &rPageTitle)
virtual void Deactivate()
weld::DialogController * m_pDialogController
This guard calls lockControllers at the given Model in the CTOR and unlockControllers in the DTOR.
static rtl::Reference< LabeledDataSequence > createLabeledDataSequence()
bool isRangeFieldContentValid(weld::Entry &rEdit)
std::unique_ptr< weld::Label > m_xFT_SERIES
TabPageNotifiable * m_pTabPageNotifiable
virtual void initializePage() override
virtual void listeningFinished(const OUString &rNewRange) override
std::unique_ptr< weld::Label > m_xFT_CAPTION
std::unique_ptr< weld::Button > m_xBTN_UP
std::unique_ptr< weld::Button > m_xBTN_REMOVE
std::unique_ptr< weld::TreeView > m_xLB_SERIES
std::unique_ptr< weld::Button > m_xBTN_ADD
std::unique_ptr< weld::Label > m_xFT_RANGE
std::unique_ptr< weld::Entry > m_xEDT_CATEGORIES
std::unique_ptr< weld::Entry > m_xEDT_RANGE
bool updateModelFromControl(const weld::Entry *pField=nullptr)
updates the internal data according to the content of the given edit field.
std::unique_ptr< weld::Button > m_xIMB_RANGE_MAIN
std::unique_ptr< weld::Label > m_xFT_CATEGORIES
std::vector< std::unique_ptr< SeriesEntry > > m_aEntries
std::unique_ptr< weld::Button > m_xBTN_DOWN
virtual void Deactivate() override
weld::Entry * m_pCurrentRangeChoosingField
std::unique_ptr< weld::Label > m_xFT_DATALABELS
virtual void Activate() override
std::unique_ptr< weld::Button > m_xIMB_RANGE_CAT
std::unique_ptr< weld::Label > m_xFT_ROLE
DataSourceTabPage(weld::Container *pPage, weld::DialogController *pController, DialogModel &rDialogModel, ChartTypeTemplateProvider *pTemplateProvider, bool bHideDescription=false)
virtual void disposingRangeSelection() override
virtual ~DataSourceTabPage() override
void InsertRoleLBEntry(const OUString &rRole, const OUString &rRange)
std::unique_ptr< weld::TreeView > m_xLB_ROLE
const rtl::Reference<::chart::ChartModel > & getChartModel() const
bool isCategoryDiagram() const
void setCategories(const css::uno::Reference< css::chart2::data::XLabeledDataSequence > &xCategories)
std::vector< tSeriesWithChartTypeByName > getAllDataSeriesWithLabel() const
void setTimeBasedRange(bool bTimeBased, sal_Int32 nStart, sal_Int32 nEnd) const
std::map< OUString, OUString > tRolesWithRanges
Definition: DialogModel.hxx:77
css::uno::Reference< css::chart2::data::XDataProvider > getDataProvider() const
static OUString ConvertRoleFromInternalToUI(const OUString &rRoleString)
std::shared_ptr< RangeSelectionHelper > const & getRangeSelectionHelper() const
void startControllerLockTimer()
css::uno::Reference< css::chart2::data::XLabeledDataSequence > getCategories() const
static tRolesWithRanges getRolesWithRanges(const css::uno::Reference< css::chart2::XDataSeries > &xSeries, const OUString &aRoleOfSequenceForLabel, const rtl::Reference< ::chart::ChartType > &xChartType)
const DialogModelTimeBasedInfo & getTimeBasedInfo() const
OUString getCategoriesRange() const
rtl::Reference< ::chart::ChartType > m_xChartType
the chart type that contains the series (via XDataSeriesContainer)
rtl::Reference< ::chart::DataSeries > m_xDataSeries
the corresponding data series
virtual Dialog * getDialog()=0
virtual void set_text(const OUString &rText)=0
virtual void set_message_type(EntryMessageType eType)=0
virtual OUString get_text() const=0
virtual void set_text(int row, const OUString &rText, int col=-1)=0
virtual OUString get_text(int row, int col=-1) const=0
virtual int get_selected_index() const=0
virtual OUString get_id(int pos) const=0
virtual void grab_focus()=0
virtual void set_visible(bool visible)
virtual void set_modal(bool bModal)=0
#define DBG_UNHANDLED_EXCEPTION(...)
float u
sal_Int32 nIndex
aStr
constexpr OUStringLiteral aData
OOO_DLLPUBLIC_CHARTTOOLS css::uno::Reference< css::chart2::data::XLabeledDataSequence > getDataSequenceByRole(const css::uno::Reference< css::chart2::data::XDataSource > &xSource, const OUString &aRole, bool bMatchPrefix=false)
Retrieves the data sequence in the given data source that matches the given role.
static Reference< chart2::data::XLabeledDataSequence > lcl_findLSequenceWithOnlyLabel(const Sequence< Reference< chart2::data::XLabeledDataSequence > > &rDataSequences)
Definition: DataSeries.cxx:557
OUString OOO_DLLPUBLIC_CHARTTOOLS SchResId(TranslateId aId)
Definition: ResId.cxx:24
IMPL_LINK(StackingResourceGroup, StackingChangeHdl, weld::Toggleable &, rRadio, void)
IMPL_LINK_NOARG(SplinePropertiesDialog, SplineTypeListBoxHdl, weld::ComboBox &, void)
int i
OUString toId(const void *pValue)
OUString aLabel