Gtk-WARNING gtktreestore.c:1047: Invalid column number 1 added to iter
[LibreOffice.git] / chart2 / source / controller / dialogs / tp_DataSource.cxx
blob4cc12689ebc909cf52b541007fe29f2796694faf
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 "tp_DataSource.hxx"
21 #include <strings.hrc>
22 #include <ResId.hxx>
23 #include <ChartType.hxx>
24 #include <ChartTypeTemplateProvider.hxx>
25 #include <ChartTypeTemplate.hxx>
26 #include <ChartModel.hxx>
27 #include <RangeSelectionHelper.hxx>
28 #include <DataSeries.hxx>
29 #include <DataSeriesHelper.hxx>
30 #include <ControllerLockGuard.hxx>
31 #include <DataSourceHelper.hxx>
32 #include <LabeledDataSequence.hxx>
33 #include "DialogModel.hxx"
34 #include <o3tl/safeint.hxx>
35 #include <TabPageNotifiable.hxx>
36 #include <com/sun/star/chart2/data/XDataProvider.hpp>
38 #include <comphelper/diagnose_ex.hxx>
40 using namespace ::com::sun::star;
41 using namespace ::com::sun::star::chart2;
43 using ::com::sun::star::uno::Reference;
45 namespace
48 constexpr OUString lcl_aLabelRole( u"label"_ustr );
50 void lcl_UpdateCurrentRange(weld::TreeView& rOutListBox, const OUString & rRole,
51 const OUString& rRange)
53 int nEntry = rOutListBox.get_selected_index();
54 if (nEntry != -1)
56 rOutListBox.set_text(nEntry, ::chart::DialogModel::ConvertRoleFromInternalToUI(rRole), 0);
57 rOutListBox.set_text(nEntry, rRange, 1);
58 ::chart::SeriesEntry* pEntry = weld::fromId<::chart::SeriesEntry*>(rOutListBox.get_id(nEntry));
59 pEntry->m_sRole = rRole;
63 bool lcl_UpdateCurrentSeriesName(weld::TreeView& rOutListBox)
65 int nEntry = rOutListBox.get_selected_index();
66 if (nEntry == -1)
67 return false;
69 bool bResult = false;
70 ::chart::SeriesEntry * pEntry = weld::fromId<::chart::SeriesEntry*>(rOutListBox.get_id(nEntry));
71 if (pEntry->m_xDataSeries.is() && pEntry->m_xChartType.is())
73 OUString aLabel(pEntry->m_xDataSeries->getLabelForRole(
74 pEntry->m_xChartType->getRoleOfSequenceForSeriesLabel()));
75 if (!aLabel.isEmpty())
77 rOutListBox.set_text(nEntry, aLabel);
78 bResult = true;
81 return bResult;
84 OUString lcl_GetSelectedRole(const weld::TreeView& rRoleListBox, bool bUITranslated = false)
86 int nEntry = rRoleListBox.get_selected_index();
87 if (nEntry != -1)
89 if (bUITranslated)
90 return rRoleListBox.get_text(nEntry);
91 ::chart::SeriesEntry* pEntry = weld::fromId<::chart::SeriesEntry*>(rRoleListBox.get_id(nEntry));
92 return pEntry->m_sRole;
94 return OUString();
97 OUString lcl_GetSelectedRolesRange( const weld::TreeView& rRoleListBox )
99 OUString aResult;
100 int nEntry = rRoleListBox.get_selected_index();
101 if (nEntry != -1)
102 aResult = rRoleListBox.get_text(nEntry, 1);
103 return aResult;
106 OUString lcl_GetSequenceNameForLabel(const ::chart::SeriesEntry* pEntry)
108 OUString aResult(u"values-y"_ustr);
109 if (pEntry && pEntry->m_xChartType.is())
110 aResult = pEntry->m_xChartType->getRoleOfSequenceForSeriesLabel();
111 return aResult;
114 void lcl_addLSequenceToDataSource(
115 const uno::Reference< chart2::data::XLabeledDataSequence > & xLSequence,
116 const Reference< ::chart::DataSeries > & xSource )
118 if( xSource.is())
120 std::vector< uno::Reference< chart2::data::XLabeledDataSequence > > aData = xSource->getDataSequences2();
121 aData.push_back( xLSequence );
122 xSource->setData( aData );
126 uno::Reference< chart2::data::XLabeledDataSequence > lcl_findLSequenceWithOnlyLabel(
127 const rtl::Reference< ::chart::DataSeries > & xDataSource )
129 uno::Reference< chart2::data::XLabeledDataSequence > xResult;
131 for( uno::Reference< chart2::data::XLabeledDataSequence > const & labeledDataSeq : xDataSource->getDataSequences2() )
133 // no values are set but a label exists
134 if( ! labeledDataSeq->getValues().is() &&
135 labeledDataSeq->getLabel().is())
137 xResult = labeledDataSeq;
138 break;
142 return xResult;
145 } // anonymous namespace
147 namespace chart
150 DataSourceTabPage::DataSourceTabPage(weld::Container* pPage, weld::DialogController* pController,
151 DialogModel & rDialogModel,
152 ChartTypeTemplateProvider* pTemplateProvider,
153 bool bHideDescription /* = false */)
154 : ::vcl::OWizardPage(pPage, pController, u"modules/schart/ui/tp_DataSource.ui"_ustr, u"tp_DataSource"_ustr)
155 , m_pTemplateProvider(pTemplateProvider)
156 , m_rDialogModel(rDialogModel)
157 , m_pCurrentRangeChoosingField( nullptr )
158 , m_bIsDirty( false )
159 , m_pTabPageNotifiable(dynamic_cast<TabPageNotifiable*>(pController))
160 , m_xFT_CAPTION(m_xBuilder->weld_label(u"FT_CAPTION_FOR_WIZARD"_ustr))
161 , m_xFT_SERIES(m_xBuilder->weld_label(u"FT_SERIES"_ustr))
162 , m_xLB_SERIES(m_xBuilder->weld_tree_view(u"LB_SERIES"_ustr))
163 , m_xBTN_ADD(m_xBuilder->weld_button(u"BTN_ADD"_ustr))
164 , m_xBTN_REMOVE(m_xBuilder->weld_button(u"BTN_REMOVE"_ustr))
165 , m_xBTN_UP(m_xBuilder->weld_button(u"BTN_UP"_ustr))
166 , m_xBTN_DOWN(m_xBuilder->weld_button(u"BTN_DOWN"_ustr))
167 , m_xFT_ROLE(m_xBuilder->weld_label(u"FT_ROLE"_ustr))
168 , m_xLB_ROLE(m_xBuilder->weld_tree_view(u"LB_ROLE"_ustr))
169 , m_xFT_RANGE(m_xBuilder->weld_label(u"FT_RANGE"_ustr))
170 , m_xEDT_RANGE(m_xBuilder->weld_entry(u"EDT_RANGE"_ustr))
171 , m_xIMB_RANGE_MAIN(m_xBuilder->weld_button(u"IMB_RANGE_MAIN"_ustr))
172 , m_xFT_CATEGORIES(m_xBuilder->weld_label(u"FT_CATEGORIES"_ustr))
173 , m_xFT_DATALABELS(m_xBuilder->weld_label(u"FT_DATALABELS"_ustr))
174 , m_xEDT_CATEGORIES(m_xBuilder->weld_entry(u"EDT_CATEGORIES"_ustr))
175 , m_xIMB_RANGE_CAT(m_xBuilder->weld_button(u"IMB_RANGE_CAT"_ustr))
177 m_xLB_SERIES->set_size_request(m_xLB_SERIES->get_approximate_digit_width() * 25,
178 m_xLB_SERIES->get_height_rows(10));
179 m_xLB_ROLE->set_size_request(m_xLB_ROLE->get_approximate_digit_width() * 60,
180 m_xLB_ROLE->get_height_rows(5));
181 m_xFT_CAPTION->set_visible(!bHideDescription);
183 m_aFixedTextRange = m_xFT_RANGE->get_label();
184 SetPageTitle(SchResId(STR_OBJECT_DATASERIES_PLURAL));
186 // set handlers
187 m_xLB_SERIES->connect_selection_changed(
188 LINK(this, DataSourceTabPage, SeriesSelectionChangedHdl));
189 m_xLB_ROLE->connect_selection_changed(LINK(this, DataSourceTabPage, RoleSelectionChangedHdl));
191 m_xIMB_RANGE_MAIN->connect_clicked(LINK(this, DataSourceTabPage, MainRangeButtonClickedHdl));
192 m_xIMB_RANGE_CAT->connect_clicked(LINK(this, DataSourceTabPage, CategoriesRangeButtonClickedHdl));
194 m_xBTN_ADD->connect_clicked(LINK(this, DataSourceTabPage, AddButtonClickedHdl));
195 m_xBTN_REMOVE->connect_clicked(LINK(this, DataSourceTabPage, RemoveButtonClickedHdl));
197 m_xBTN_UP->connect_clicked(LINK(this, DataSourceTabPage, UpButtonClickedHdl));
198 m_xBTN_DOWN->connect_clicked(LINK(this, DataSourceTabPage, DownButtonClickedHdl));
200 m_xEDT_RANGE->connect_changed(LINK(this, DataSourceTabPage, RangeModifiedHdl));
201 m_xEDT_CATEGORIES->connect_changed(LINK( this, DataSourceTabPage, RangeModifiedHdl));
203 // init controls
204 std::vector<int> aWidths { o3tl::narrowing<int>(m_xLB_ROLE->get_approximate_digit_width() * 20) };
205 m_xLB_ROLE->set_column_fixed_widths(aWidths);
206 m_xLB_ROLE->show();
208 updateControlsFromDialogModel();
210 // select first series
211 if (m_xLB_SERIES->n_children())
212 m_xLB_SERIES->select(0);
215 void DataSourceTabPage::InsertRoleLBEntry(const OUString& rRole, const OUString& rRange)
217 m_aEntries.emplace_back(new SeriesEntry);
218 SeriesEntry* pEntry = m_aEntries.back().get();
219 pEntry->m_sRole = rRole;
220 m_xLB_ROLE->append(weld::toId(pEntry),
221 ::chart::DialogModel::ConvertRoleFromInternalToUI(rRole));
222 m_xLB_ROLE->set_text(m_xLB_ROLE->n_children() - 1, rRange, 1);
225 DataSourceTabPage::~DataSourceTabPage()
229 void DataSourceTabPage::Activate()
231 OWizardPage::Activate();
232 updateControlsFromDialogModel();
233 m_xLB_SERIES->grab_focus();
236 void DataSourceTabPage::initializePage()
240 void DataSourceTabPage::Deactivate()
242 commitPage();
243 vcl::OWizardPage::Deactivate();
246 void DataSourceTabPage::commitPage()
248 commitPage(::vcl::WizardTypes::eFinish);
251 bool DataSourceTabPage::commitPage( ::vcl::WizardTypes::CommitPageReason /*eReason*/ )
253 //ranges may have been edited in the meanwhile (dirty is true in that case here)
254 if( isValid() )
256 updateModelFromControl();
257 return true; //return false if this page should not be left
259 else
260 return false;
263 bool DataSourceTabPage::isRangeFieldContentValid(weld::Entry& rEdit )
265 OUString aRange(rEdit.get_text());
266 bool bIsValid = aRange.isEmpty() ||
267 m_rDialogModel.getRangeSelectionHelper()->verifyCellRange(aRange);
268 rEdit.set_message_type(bIsValid ? weld::EntryMessageType::Normal : weld::EntryMessageType::Error);
269 return bIsValid;
272 bool DataSourceTabPage::isValid()
274 bool bRoleRangeValid = true;
275 bool bCategoriesRangeValid = true;
276 bool bHasSelectedEntry = (m_xLB_SERIES->get_selected_index() != -1);
278 if (bHasSelectedEntry)
279 bRoleRangeValid = isRangeFieldContentValid(*m_xEDT_RANGE);
280 if (m_xEDT_CATEGORIES->get_sensitive())
281 bCategoriesRangeValid = isRangeFieldContentValid( *m_xEDT_CATEGORIES );
282 bool bValid = ( bRoleRangeValid && bCategoriesRangeValid );
284 if( m_pTabPageNotifiable )
286 if( bValid )
287 m_pTabPageNotifiable->setValidPage( this );
288 else
289 m_pTabPageNotifiable->setInvalidPage( this );
292 return bValid;
295 void DataSourceTabPage::setDirty()
297 m_bIsDirty = true;
300 void DataSourceTabPage::updateControlsFromDialogModel()
302 // series
303 fillSeriesListBox();
304 SeriesSelectionChangedHdl(*m_xLB_SERIES);
306 // categories
307 m_xEDT_CATEGORIES->set_text(m_rDialogModel.getCategoriesRange());
309 updateControlState();
312 void DataSourceTabPage::fillSeriesListBox()
314 rtl::Reference< DataSeries > xSelected;
315 SeriesEntry* pEntry = nullptr;
316 int nEntry = m_xLB_SERIES->get_selected_index();
317 if (nEntry != -1)
319 pEntry = weld::fromId<SeriesEntry*>(m_xLB_SERIES->get_id(nEntry));
320 xSelected = pEntry->m_xDataSeries;
323 bool bHasSelectedEntry = (pEntry != nullptr);
324 int nSelectedEntry = -1;
326 m_xLB_SERIES->freeze();
327 m_xLB_SERIES->clear();
329 std::vector< DialogModel::tSeriesWithChartTypeByName > aSeries(
330 m_rDialogModel.getAllDataSeriesWithLabel() );
332 sal_Int32 nUnnamedSeriesIndex = 1;
333 nEntry = 0;
334 for (auto const& series : aSeries)
336 OUString aLabel(series.first);
337 if (aLabel.isEmpty())
339 if( nUnnamedSeriesIndex > 1 )
341 OUString aResString(::chart::SchResId( STR_DATA_UNNAMED_SERIES_WITH_INDEX ));
343 // replace index of unnamed series
344 static constexpr OUString aReplacementStr( u"%NUMBER"_ustr );
345 sal_Int32 nIndex = aResString.indexOf( aReplacementStr );
346 if( nIndex != -1 )
347 aLabel = aResString.replaceAt(
348 nIndex, aReplacementStr.getLength(),
349 OUString::number(nUnnamedSeriesIndex));
351 if( aLabel.isEmpty() )
352 aLabel = ::chart::SchResId( STR_DATA_UNNAMED_SERIES );
354 ++nUnnamedSeriesIndex;
357 m_aEntries.emplace_back(new SeriesEntry);
358 pEntry = m_aEntries.back().get();
359 pEntry->m_xDataSeries = series.second.first;
360 pEntry->m_xChartType = series.second.second;
361 m_xLB_SERIES->append(weld::toId(pEntry), aLabel);
362 if (bHasSelectedEntry && series.second.first == xSelected)
363 nSelectedEntry = nEntry;
364 ++nEntry;
367 m_xLB_SERIES->thaw();
369 if (bHasSelectedEntry && nSelectedEntry != -1)
370 m_xLB_SERIES->select(nSelectedEntry);
373 void DataSourceTabPage::fillRoleListBox()
375 int nSeriesEntry = m_xLB_SERIES->get_selected_index();
376 SeriesEntry* pSeriesEntry = nullptr;
377 if (nSeriesEntry != -1)
378 pSeriesEntry = weld::fromId<SeriesEntry*>(m_xLB_SERIES->get_id(nSeriesEntry));
379 bool bHasSelectedEntry = (pSeriesEntry != nullptr);
381 int nRoleIndex = m_xLB_ROLE->get_selected_index();
382 if (!bHasSelectedEntry)
383 return;
385 DialogModel::tRolesWithRanges aRoles(
386 DialogModel::getRolesWithRanges(
387 pSeriesEntry->m_xDataSeries,
388 lcl_GetSequenceNameForLabel( pSeriesEntry ),
389 pSeriesEntry->m_xChartType ));
391 // fill role list
392 m_xLB_ROLE->freeze();
393 m_xLB_ROLE->clear();
395 for (auto const& elemRole : aRoles)
397 InsertRoleLBEntry(elemRole.first, elemRole.second);
400 m_xLB_ROLE->thaw();
402 // series may contain no roles, check listbox size before selecting entries
403 if (m_xLB_ROLE->n_children() > 0)
405 if (nRoleIndex == -1 || nRoleIndex >= m_xLB_ROLE->n_children())
406 nRoleIndex = 0;
407 m_xLB_ROLE->select(nRoleIndex);
411 void DataSourceTabPage::updateControlState()
413 int nSeriesEntry = m_xLB_SERIES->get_selected_index();
414 bool bHasSelectedSeries = nSeriesEntry != -1;
415 bool bHasValidRole = false;
416 bool bHasRangeChooser = m_rDialogModel.getRangeSelectionHelper()->hasRangeSelection();
418 if( bHasSelectedSeries )
420 int nRoleEntry = m_xLB_ROLE->get_selected_index();
421 bHasValidRole = nRoleEntry != -1;
424 m_xBTN_ADD->set_sensitive(true);
425 m_xBTN_REMOVE->set_sensitive(bHasSelectedSeries);
427 m_xBTN_UP->set_sensitive(bHasSelectedSeries && (nSeriesEntry != 0));
428 m_xBTN_DOWN->set_sensitive(bHasSelectedSeries && (nSeriesEntry != m_xLB_SERIES->n_children() - 1));
430 bool bHasCategories = m_rDialogModel.isCategoryDiagram();
432 m_xFT_DATALABELS->set_visible(!bHasCategories);
433 m_xFT_CATEGORIES->set_visible( bHasCategories);
434 bool bShowIB = bHasRangeChooser;
436 m_xIMB_RANGE_CAT->set_visible(bShowIB);
438 m_xFT_ROLE->set_sensitive(bHasSelectedSeries);
439 m_xLB_ROLE->set_sensitive(bHasSelectedSeries);
441 m_xFT_RANGE->set_sensitive(bHasValidRole);
442 m_xEDT_RANGE->set_sensitive(bHasValidRole);
444 m_xFT_SERIES->set_sensitive(true);
445 m_xLB_SERIES->set_sensitive(true);
447 m_xIMB_RANGE_MAIN->set_visible(bShowIB);
449 isValid();
452 IMPL_LINK_NOARG(DataSourceTabPage, SeriesSelectionChangedHdl, weld::TreeView&, void)
454 m_rDialogModel.startControllerLockTimer();
455 if (m_xLB_SERIES->get_selected_index() != -1)
457 fillRoleListBox();
458 RoleSelectionChangedHdl(*m_xLB_ROLE);
460 updateControlState();
463 IMPL_LINK_NOARG(DataSourceTabPage, RoleSelectionChangedHdl, weld::TreeView&, void)
465 m_rDialogModel.startControllerLockTimer();
466 int nEntry = m_xLB_ROLE->get_selected_index();
467 if (nEntry == -1)
468 return;
470 OUString aSelectedRoleUI = lcl_GetSelectedRole( *m_xLB_ROLE, true );
471 OUString aSelectedRange = lcl_GetSelectedRolesRange( *m_xLB_ROLE );
473 // replace role in fixed text label
474 static constexpr OUString aReplacementStr( u"%VALUETYPE"_ustr );
475 sal_Int32 nIndex = m_aFixedTextRange.indexOf( aReplacementStr );
476 if( nIndex != -1 )
478 m_xFT_RANGE->set_label(
479 m_aFixedTextRange.replaceAt(
480 nIndex, aReplacementStr.getLength(), aSelectedRoleUI ));
483 m_xEDT_RANGE->set_text(aSelectedRange);
484 isValid();
487 IMPL_LINK_NOARG(DataSourceTabPage, MainRangeButtonClickedHdl, weld::Button&, void)
489 OSL_ASSERT( m_pCurrentRangeChoosingField == nullptr );
490 m_pCurrentRangeChoosingField = m_xEDT_RANGE.get();
491 if (!m_xEDT_RANGE->get_text().isEmpty() &&
492 !updateModelFromControl( m_pCurrentRangeChoosingField))
493 return;
495 int nEntry = m_xLB_SERIES->get_selected_index();
496 bool bHasSelectedEntry = (nEntry != -1);
498 OUString aSelectedRolesRange = lcl_GetSelectedRolesRange(*m_xLB_ROLE);
500 if (bHasSelectedEntry && (m_xLB_ROLE->get_selected_index() != -1))
502 OUString aUIStr(SchResId(STR_DATA_SELECT_RANGE_FOR_SERIES));
504 // replace role
505 OUString aReplacement( u"%VALUETYPE"_ustr );
506 sal_Int32 nIndex = aUIStr.indexOf( aReplacement );
507 if( nIndex != -1 )
509 aUIStr = aUIStr.replaceAt( nIndex, aReplacement.getLength(),
510 lcl_GetSelectedRole( *m_xLB_ROLE, true ));
512 // replace series name
513 aReplacement = "%SERIESNAME";
514 nIndex = aUIStr.indexOf( aReplacement );
515 if( nIndex != -1 )
517 aUIStr = aUIStr.replaceAt(nIndex, aReplacement.getLength(),
518 m_xLB_SERIES->get_text(nEntry));
521 enableRangeChoosing(true, m_pDialogController);
522 m_rDialogModel.getRangeSelectionHelper()->chooseRange( aSelectedRolesRange, aUIStr, *this );
524 else
525 m_pCurrentRangeChoosingField = nullptr;
528 IMPL_LINK_NOARG(DataSourceTabPage, CategoriesRangeButtonClickedHdl, weld::Button&, void)
530 OSL_ASSERT( m_pCurrentRangeChoosingField == nullptr );
531 m_pCurrentRangeChoosingField = m_xEDT_CATEGORIES.get();
532 if( !m_xEDT_CATEGORIES->get_text().isEmpty() &&
533 ! updateModelFromControl( m_pCurrentRangeChoosingField ))
534 return;
536 OUString aStr(SchResId(m_xFT_CATEGORIES->get_visible() ? STR_DATA_SELECT_RANGE_FOR_CATEGORIES : STR_DATA_SELECT_RANGE_FOR_DATALABELS));
537 enableRangeChoosing(true, m_pDialogController);
538 m_rDialogModel.getRangeSelectionHelper()->chooseRange(
539 m_rDialogModel.getCategoriesRange(), aStr, *this );
542 IMPL_LINK_NOARG(DataSourceTabPage, AddButtonClickedHdl, weld::Button&, void)
544 m_rDialogModel.startControllerLockTimer();
545 int nEntry = m_xLB_SERIES->get_selected_index();
546 rtl::Reference< DataSeries > xSeriesToInsertAfter;
547 rtl::Reference< ChartType > xChartTypeForNewSeries;
548 if( m_pTemplateProvider )
549 m_rDialogModel.setTemplate( m_pTemplateProvider->getCurrentTemplate());
551 if (nEntry != -1)
553 ::chart::SeriesEntry* pEntry = weld::fromId<::chart::SeriesEntry*>(m_xLB_SERIES->get_id(nEntry));
554 xSeriesToInsertAfter = pEntry->m_xDataSeries;
555 xChartTypeForNewSeries = pEntry->m_xChartType;
557 else
559 std::vector< rtl::Reference< ChartType > > aCntVec(
560 m_rDialogModel.getAllDataSeriesContainers());
561 if( ! aCntVec.empty())
562 xChartTypeForNewSeries = aCntVec.front();
564 OSL_ENSURE( xChartTypeForNewSeries.is(), "Cannot insert new series" );
566 m_rDialogModel.insertSeriesAfter( xSeriesToInsertAfter, xChartTypeForNewSeries );
567 setDirty();
569 fillSeriesListBox();
570 // note the box was cleared and refilled, so nEntry is invalid now
572 int nSelEntry = m_xLB_SERIES->get_selected_index();
573 if (nSelEntry != -1)
575 ++nSelEntry;
576 if (nSelEntry < m_xLB_SERIES->n_children())
577 m_xLB_SERIES->select(nSelEntry);
579 SeriesSelectionChangedHdl(*m_xLB_SERIES);
582 IMPL_LINK_NOARG(DataSourceTabPage, RemoveButtonClickedHdl, weld::Button&, void)
584 m_rDialogModel.startControllerLockTimer();
585 int nEntry = m_xLB_SERIES->get_selected_index();
586 if (nEntry == -1)
587 return;
589 SeriesEntry* pEntry = weld::fromId<::chart::SeriesEntry*>(m_xLB_SERIES->get_id(nEntry));
590 rtl::Reference< DataSeries > xNewSelSeries;
591 SeriesEntry * pNewSelEntry = nullptr;
592 if (nEntry + 1 < m_xLB_SERIES->n_children())
593 pNewSelEntry = weld::fromId<::chart::SeriesEntry*>(m_xLB_SERIES->get_id(nEntry + 1));
594 else if (nEntry > 0)
595 pNewSelEntry = weld::fromId<::chart::SeriesEntry*>(m_xLB_SERIES->get_id(nEntry - 1));
596 if (pNewSelEntry)
597 xNewSelSeries = pNewSelEntry->m_xDataSeries;
599 m_rDialogModel.deleteSeries( pEntry->m_xDataSeries, pEntry->m_xChartType );
600 setDirty();
602 m_xLB_SERIES->remove(nEntry);
603 fillSeriesListBox();
605 // select previous or next series
606 if (xNewSelSeries.is())
608 for (int i = 0; i < m_xLB_SERIES->n_children(); ++i)
610 pEntry = weld::fromId<::chart::SeriesEntry*>(m_xLB_SERIES->get_id(i));
611 if (pEntry->m_xDataSeries == xNewSelSeries)
613 m_xLB_SERIES->select(i);
614 break;
618 SeriesSelectionChangedHdl(*m_xLB_SERIES);
621 IMPL_LINK_NOARG(DataSourceTabPage, UpButtonClickedHdl, weld::Button&, void)
623 m_rDialogModel.startControllerLockTimer();
625 int nEntry = m_xLB_SERIES->get_selected_index();
626 SeriesEntry* pEntry = nullptr;
627 if (nEntry != -1)
628 pEntry = weld::fromId<SeriesEntry*>(m_xLB_SERIES->get_id(nEntry));
630 bool bHasSelectedEntry = (pEntry != nullptr);
632 if (bHasSelectedEntry)
634 m_rDialogModel.moveSeries( pEntry->m_xDataSeries, DialogModel::MoveDirection::Up );
635 setDirty();
636 fillSeriesListBox();
637 SeriesSelectionChangedHdl(*m_xLB_SERIES);
641 IMPL_LINK_NOARG(DataSourceTabPage, DownButtonClickedHdl, weld::Button&, void)
643 m_rDialogModel.startControllerLockTimer();
645 int nEntry = m_xLB_SERIES->get_selected_index();
646 SeriesEntry* pEntry = nullptr;
647 if (nEntry != -1)
648 pEntry = weld::fromId<SeriesEntry*>(m_xLB_SERIES->get_id(nEntry));
650 bool bHasSelectedEntry = (pEntry != nullptr);
652 if (bHasSelectedEntry)
654 m_rDialogModel.moveSeries( pEntry->m_xDataSeries, DialogModel::MoveDirection::Down );
655 setDirty();
656 fillSeriesListBox();
657 SeriesSelectionChangedHdl(*m_xLB_SERIES);
661 IMPL_LINK(DataSourceTabPage, RangeModifiedHdl, weld::Entry&, rEdit, void)
663 // note: isValid sets the color of the edit field
664 if( isRangeFieldContentValid( rEdit ))
666 setDirty();
667 updateModelFromControl( &rEdit );
668 if (&rEdit == m_xEDT_RANGE.get())
670 if( ! lcl_UpdateCurrentSeriesName( *m_xLB_SERIES ))
671 fillSeriesListBox();
675 // enable/disable OK button
676 isValid();
679 void DataSourceTabPage::listeningFinished(
680 const OUString & rNewRange )
682 // rNewRange becomes invalid after removing the listener
683 OUString aRange( rNewRange );
685 m_rDialogModel.startControllerLockTimer();
687 // stop listening
688 m_rDialogModel.getRangeSelectionHelper()->stopRangeListening();
690 // change edit field
691 if( m_pCurrentRangeChoosingField )
693 m_pCurrentRangeChoosingField->set_text(aRange);
694 m_pCurrentRangeChoosingField->grab_focus();
697 if (m_pCurrentRangeChoosingField == m_xEDT_RANGE.get())
699 m_xEDT_RANGE->set_text(aRange);
700 setDirty();
702 else if (m_pCurrentRangeChoosingField == m_xEDT_CATEGORIES.get())
704 m_xEDT_CATEGORIES->set_text(aRange);
705 setDirty();
708 updateModelFromControl(m_pCurrentRangeChoosingField);
709 if (!lcl_UpdateCurrentSeriesName(*m_xLB_SERIES))
710 fillSeriesListBox();
712 m_pCurrentRangeChoosingField = nullptr;
714 updateControlState();
715 enableRangeChoosing(false, m_pDialogController);
718 void DataSourceTabPage::disposingRangeSelection()
720 m_rDialogModel.getRangeSelectionHelper()->stopRangeListening( false );
723 bool DataSourceTabPage::updateModelFromControl(const weld::Entry* pField)
725 if (!m_bIsDirty)
726 return true;
728 ControllerLockGuardUNO aLockedControllers( m_rDialogModel.getChartModel() );
730 // @todo: validity check of field content
731 bool bResult = true;
732 bool bAll = (pField == nullptr);
733 Reference< data::XDataProvider > xDataProvider( m_rDialogModel.getDataProvider());
735 if (bAll || (pField == m_xEDT_CATEGORIES.get()))
737 uno::Reference< chart2::data::XLabeledDataSequence > xLabeledSeq( m_rDialogModel.getCategories() );
738 if( xDataProvider.is())
740 OUString aRange(m_xEDT_CATEGORIES->get_text());
741 if (!aRange.isEmpty())
743 // create or change categories
744 if( !xLabeledSeq.is())
746 xLabeledSeq = DataSourceHelper::createLabeledDataSequence();
747 m_rDialogModel.setCategories( xLabeledSeq );
751 xLabeledSeq->setValues( xDataProvider->createDataSequenceByRangeRepresentation( aRange ));
753 catch( const uno::Exception & )
755 // should work as validation should have happened before
756 DBG_UNHANDLED_EXCEPTION("chart2");
759 else if( xLabeledSeq.is())
761 // clear existing categories
762 xLabeledSeq.clear();
763 m_rDialogModel.setCategories( xLabeledSeq );
768 int nSeriesEntry = m_xLB_SERIES->get_selected_index();
769 SeriesEntry* pSeriesEntry = nullptr;
770 if (nSeriesEntry != -1)
771 pSeriesEntry = weld::fromId<SeriesEntry*>(m_xLB_SERIES->get_id(nSeriesEntry));
772 bool bHasSelectedEntry = (pSeriesEntry != nullptr);
774 if( bHasSelectedEntry )
776 if( bAll || (pField == m_xEDT_RANGE.get()) )
780 OUString aSelectedRole = lcl_GetSelectedRole( *m_xLB_ROLE );
781 OUString aRange(m_xEDT_RANGE->get_text());
782 OUString aSequenceRole( aSelectedRole );
783 bool bIsLabel = (aSequenceRole == lcl_aLabelRole );
784 OUString aSequenceNameForLabel( lcl_GetSequenceNameForLabel( pSeriesEntry ));
786 if( bIsLabel )
787 aSequenceRole = aSequenceNameForLabel;
789 uno::Reference< chart2::data::XLabeledDataSequence > xLabeledSeq =
790 DataSeriesHelper::getDataSequenceByRole( pSeriesEntry->m_xDataSeries, aSequenceRole );
792 if( xDataProvider.is())
794 if( bIsLabel )
796 if( ! xLabeledSeq.is())
798 // check if there is already an "orphan" label sequence
799 xLabeledSeq = lcl_findLSequenceWithOnlyLabel( pSeriesEntry->m_xDataSeries );
800 if( ! xLabeledSeq.is())
802 // no corresponding labeled data sequence for label found
803 xLabeledSeq = DataSourceHelper::createLabeledDataSequence();
804 lcl_addLSequenceToDataSource( xLabeledSeq, pSeriesEntry->m_xDataSeries );
807 if( xLabeledSeq.is())
809 if( !aRange.isEmpty())
811 Reference< data::XDataSequence > xNewSeq;
814 xNewSeq.set( xDataProvider->createDataSequenceByRangeRepresentation( aRange ));
816 catch( const uno::Exception & )
818 // should work as validation should have happened before
819 DBG_UNHANDLED_EXCEPTION("chart2");
821 if( xNewSeq.is())
823 // update range name by the full string provided
824 // by the data provider. E.g. "a1" might become
825 // "$Sheet1.$A$1"
826 aRange = xNewSeq->getSourceRangeRepresentation();
827 Reference< beans::XPropertySet > xProp( xNewSeq, uno::UNO_QUERY_THROW );
828 xProp->setPropertyValue( u"Role"_ustr , uno::Any( lcl_aLabelRole ));
830 //Labels should always include hidden cells, regardless of the setting chosen
831 xProp->setPropertyValue( u"IncludeHiddenCells"_ustr, uno::Any(true));
832 xLabeledSeq->setLabel( xNewSeq );
835 else
837 xLabeledSeq->setLabel( Reference< data::XDataSequence >());
841 else
843 if( !aRange.isEmpty())
845 Reference< data::XDataSequence > xNewSeq;
848 xNewSeq.set( xDataProvider->createDataSequenceByRangeRepresentation( aRange ));
850 catch( const uno::Exception & )
852 // should work as validation should have happened before
853 DBG_UNHANDLED_EXCEPTION("chart2");
855 if( xNewSeq.is())
857 // update range name by the full string provided
858 // by the data provider. E.g. "a1:e1" might become
859 // "$Sheet1.$A$1:$E$1"
860 aRange = xNewSeq->getSourceRangeRepresentation();
862 Reference< beans::XPropertySet > xProp( xNewSeq, uno::UNO_QUERY_THROW );
863 xProp->setPropertyValue( u"Role"_ustr , uno::Any( aSelectedRole ));
864 if( !xLabeledSeq.is())
866 if( aSelectedRole == aSequenceNameForLabel )
867 xLabeledSeq = lcl_findLSequenceWithOnlyLabel( pSeriesEntry->m_xDataSeries );
868 if( ! xLabeledSeq.is())
870 xLabeledSeq = DataSourceHelper::createLabeledDataSequence();
871 lcl_addLSequenceToDataSource( xLabeledSeq, pSeriesEntry->m_xDataSeries );
874 xLabeledSeq->setValues( xNewSeq );
880 lcl_UpdateCurrentRange( *m_xLB_ROLE, aSelectedRole, aRange );
882 catch( const uno::Exception & )
884 DBG_UNHANDLED_EXCEPTION("chart2");
885 bResult = false;
890 // update View
891 // @todo remove this when automatic view updates from calc, writer and own data sequences are available
892 if( bResult )
896 if( m_rDialogModel.getChartModel() )
897 m_rDialogModel.getChartModel()->setModified( true );
898 const DialogModelTimeBasedInfo& rInfo = m_rDialogModel.getTimeBasedInfo();
899 if(rInfo.bTimeBased)
901 m_rDialogModel.setTimeBasedRange(rInfo.bTimeBased, rInfo.nStart, rInfo.nEnd);
904 catch( const uno::Exception & )
906 DBG_UNHANDLED_EXCEPTION("chart2");
910 return bResult;
913 } // namespace chart
915 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */