1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 .
21 #include <sal/config.h>
25 #include <comphelper/string.hxx>
26 #include <unotools/charclass.hxx>
27 #include <vcl/svapp.hxx>
28 #include <vcl/weld.hxx>
29 #include <o3tl/string_view.hxx>
31 #include <reffact.hxx>
32 #include <document.hxx>
33 #include <globstr.hrc>
34 #include <scresid.hxx>
35 #include <rangenam.hxx>
36 #include <globalnames.hxx>
37 #include <dbnamdlg.hxx>
38 #include <dbdocfun.hxx>
42 void ERRORBOX(weld::Window
* pParent
, const OUString
& rString
)
44 std::unique_ptr
<weld::MessageDialog
> xBox(Application::CreateMessageDialog(pParent
,
45 VclMessageType::Warning
, VclButtonsType::Ok
,
54 DBSaveData( formula::RefEdit
& rEd
, weld::CheckButton
& rHdr
, weld::CheckButton
& rTot
, weld::CheckButton
& rSize
, weld::CheckButton
& rFmt
,
55 weld::CheckButton
& rStrip
, ScRange
& rArea
)
75 formula::RefEdit
& rEdAssign
;
76 weld::CheckButton
& rBtnHeader
;
77 weld::CheckButton
& rBtnTotals
;
78 weld::CheckButton
& rBtnSize
;
79 weld::CheckButton
& rBtnFormat
;
80 weld::CheckButton
& rBtnStrip
;
94 void DBSaveData::Save()
97 aStr
= rEdAssign
.GetText();
98 bHeader
= rBtnHeader
.get_active();
99 bTotals
= rBtnTotals
.get_active();
100 bSize
= rBtnSize
.get_active();
101 bFormat
= rBtnFormat
.get_active();
102 bStrip
= rBtnStrip
.get_active();
106 void DBSaveData::Restore()
111 rEdAssign
.SetText( aStr
);
112 rBtnHeader
.set_active ( bHeader
);
113 rBtnTotals
.set_active ( bTotals
);
114 rBtnSize
.set_active ( bSize
);
115 rBtnFormat
.set_active ( bFormat
);
116 rBtnStrip
.set_active ( bStrip
);
121 static std::unique_ptr
<DBSaveData
> xSaveObj
;
123 ScDbNameDlg::ScDbNameDlg(SfxBindings
* pB
, SfxChildWindow
* pCW
, weld::Window
* pParent
,
124 ScViewData
& rViewData
)
125 : ScAnyRefDlgController(pB
, pCW
, pParent
,
126 u
"modules/scalc/ui/definedatabaserangedialog.ui"_ustr
, u
"DefineDatabaseRangeDialog"_ustr
)
127 , m_rViewData(rViewData
)
128 , rDoc(rViewData
.GetDocument())
129 , bRefInputMode(false)
130 , aAddrDetails(rDoc
.GetAddressConvention(), 0, 0)
131 , aLocalDbCol(*(rDoc
.GetDBCollection()))
132 , m_xEdName(m_xBuilder
->weld_entry_tree_view(u
"entrygrid"_ustr
, u
"entry"_ustr
, u
"entry-list"_ustr
))
133 , m_xAssignFrame(m_xBuilder
->weld_frame(u
"RangeFrame"_ustr
))
134 , m_xEdAssign(new formula::RefEdit(m_xBuilder
->weld_entry(u
"assign"_ustr
)))
135 , m_xRbAssign(new formula::RefButton(m_xBuilder
->weld_button(u
"assignrb"_ustr
)))
136 , m_xOptions(m_xBuilder
->weld_widget(u
"Options"_ustr
))
137 , m_xBtnHeader(m_xBuilder
->weld_check_button(u
"ContainsColumnLabels"_ustr
))
138 , m_xBtnTotals(m_xBuilder
->weld_check_button(u
"ContainsTotalsRow"_ustr
))
139 , m_xBtnDoSize(m_xBuilder
->weld_check_button(u
"InsertOrDeleteCells"_ustr
))
140 , m_xBtnKeepFmt(m_xBuilder
->weld_check_button(u
"KeepFormatting"_ustr
))
141 , m_xBtnStripData(m_xBuilder
->weld_check_button(u
"DontSaveImportedData"_ustr
))
142 , m_xFTSource(m_xBuilder
->weld_label(u
"Source"_ustr
))
143 , m_xFTOperations(m_xBuilder
->weld_label(u
"Operations"_ustr
))
144 , m_xBtnOk(m_xBuilder
->weld_button(u
"ok"_ustr
))
145 , m_xBtnCancel(m_xBuilder
->weld_button(u
"cancel"_ustr
))
146 , m_xBtnAdd(m_xBuilder
->weld_button(u
"add"_ustr
))
147 , m_xBtnRemove(m_xBuilder
->weld_button(u
"delete"_ustr
))
148 , m_xModifyPB(m_xBuilder
->weld_button(u
"modify"_ustr
))
149 , m_xInvalidFT(m_xBuilder
->weld_label(u
"invalid"_ustr
))
150 , m_xFrameLabel(m_xAssignFrame
->weld_label_widget())
151 , m_xExpander(m_xBuilder
->weld_expander(u
"more"_ustr
))
153 m_xEdName
->set_height_request_by_rows(4);
154 m_xEdAssign
->SetReferences(this, m_xFrameLabel
.get());
155 m_xRbAssign
->SetReferences(this, m_xEdAssign
.get());
156 aStrAdd
= m_xBtnAdd
->get_label();
157 aStrModify
= m_xModifyPB
->get_label();
158 aStrInvalid
= m_xInvalidFT
->get_label();
160 // so that the strings in the resource can stay with fixed texts:
161 aStrSource
= m_xFTSource
->get_label();
162 aStrOperations
= m_xFTOperations
->get_label();
164 xSaveObj
.reset(new DBSaveData( *m_xEdAssign
, *m_xBtnHeader
, *m_xBtnTotals
,
165 *m_xBtnDoSize
, *m_xBtnKeepFmt
, *m_xBtnStripData
, theCurArea
));
169 ScDbNameDlg::~ScDbNameDlg()
174 void ScDbNameDlg::Init()
176 m_xBtnHeader
->set_active(true); // Default: with column headers
177 m_xBtnTotals
->set_active( false ); // Default: without totals row
178 m_xBtnDoSize
->set_active(true);
179 m_xBtnKeepFmt
->set_active(true);
181 m_xBtnOk
->connect_clicked ( LINK( this, ScDbNameDlg
, OkBtnHdl
) );
182 m_xBtnCancel
->connect_clicked ( LINK( this, ScDbNameDlg
, CancelBtnHdl
) );
183 m_xBtnAdd
->connect_clicked ( LINK( this, ScDbNameDlg
, AddBtnHdl
) );
184 m_xBtnRemove
->connect_clicked ( LINK( this, ScDbNameDlg
, RemoveBtnHdl
) );
185 m_xEdName
->connect_changed( LINK( this, ScDbNameDlg
, NameModifyHdl
) );
186 m_xEdAssign
->SetModifyHdl ( LINK( this, ScDbNameDlg
, AssModifyHdl
) );
198 ScDBCollection
* pDBColl
= rDoc
.GetDBCollection();
200 m_rViewData
.GetSimpleArea( nStartCol
, nStartRow
, nStartTab
,
201 nEndCol
, nEndRow
, nEndTab
);
203 theCurArea
= ScRange( nStartCol
, nStartRow
, nStartTab
, nEndCol
, nEndRow
, nEndTab
);
205 theAreaStr
= theCurArea
.Format(rDoc
, ScRefFlags::RANGE_ABS_3D
, aAddrDetails
);
209 // determine if the defined DB area has been marked:
210 ScDBData
* pDBData
= pDBColl
->GetDBAtCursor( nStartCol
, nStartRow
, nStartTab
, ScDBDataPortion::TOP_LEFT
);
213 ScAddress
& rStart
= theCurArea
.aStart
;
214 ScAddress
& rEnd
= theCurArea
.aEnd
;
221 pDBData
->GetArea( nTab
, nCol1
, nRow1
, nCol2
, nRow2
);
223 if ( (rStart
.Tab() == nTab
)
224 && (rStart
.Col() == nCol1
) && (rStart
.Row() == nRow1
)
225 && (rEnd
.Col() == nCol2
) && (rEnd
.Row() == nRow2
) )
227 OUString aDBName
= pDBData
->GetName();
228 if ( aDBName
!= STR_DB_LOCAL_NONAME
)
229 m_xEdName
->set_entry_text(aDBName
);
231 m_xBtnHeader
->set_active( pDBData
->HasHeader() );
232 m_xBtnTotals
->set_active( pDBData
->HasTotals() );
233 m_xBtnDoSize
->set_active( pDBData
->IsDoSize() );
234 m_xBtnKeepFmt
->set_active( pDBData
->IsKeepFmt() );
235 m_xBtnStripData
->set_active( pDBData
->IsStripData() );
236 SetInfoStrings( pDBData
);
241 m_xEdAssign
->SetText( theAreaStr
);
242 m_xEdName
->grab_focus();
245 NameModifyHdl( *m_xEdName
);
249 void ScDbNameDlg::SetInfoStrings( const ScDBData
* pDBData
)
251 OUStringBuffer
aBuf(aStrSource
);
254 aBuf
.append(" " + pDBData
->GetSourceString());
256 m_xFTSource
->set_label(aBuf
.makeStringAndClear());
258 aBuf
.append(aStrOperations
);
261 aBuf
.append(" " + pDBData
->GetOperations());
263 m_xFTOperations
->set_label(aBuf
.makeStringAndClear());
266 // Transfer of a table area selected with the mouse, which is then displayed
267 // as a new selection in the reference window.
269 void ScDbNameDlg::SetReference( const ScRange
& rRef
, ScDocument
& rDocP
)
271 if (!m_xEdAssign
->GetWidget()->get_sensitive())
274 if ( rRef
.aStart
!= rRef
.aEnd
)
275 RefInputStart(m_xEdAssign
.get());
279 OUString
aRefStr(theCurArea
.Format(rDocP
, ScRefFlags::RANGE_ABS_3D
, aAddrDetails
));
280 m_xEdAssign
->SetRefString( aRefStr
);
281 m_xOptions
->set_sensitive(true);
282 m_xBtnAdd
->set_sensitive(true);
287 void ScDbNameDlg::Close()
289 DoClose( ScDbNameDlgWrapper::GetChildWindowId() );
292 void ScDbNameDlg::SetActive()
294 m_xEdAssign
->GrabFocus();
296 // No NameModifyHdl, because otherwise areas can not be changed
297 // (the old content would be displayed again after the reference selection is pulled)
298 // (the selected DB name has not changed either)
303 void ScDbNameDlg::UpdateNames()
305 typedef ScDBCollection::NamedDBs DBsType
;
307 const DBsType
& rDBs
= aLocalDbCol
.getNamedDBs();
312 m_xEdAssign
->SetText( OUString() );
316 for (const auto& rxDB
: rDBs
)
317 m_xEdName
->append_text(rxDB
->GetName());
321 m_xBtnAdd
->set_label( aStrAdd
);
322 m_xBtnAdd
->set_sensitive(false);
323 m_xBtnRemove
->set_sensitive(false);
329 void ScDbNameDlg::UpdateDBData( const OUString
& rStrName
)
332 const ScDBData
* pData
= aLocalDbCol
.getNamedDBs().findByUpperName(ScGlobal::getCharClass().uppercase(rStrName
));
342 pData
->GetArea( nTab
, nColStart
, nRowStart
, nColEnd
, nRowEnd
);
343 theCurArea
= ScRange( ScAddress( nColStart
, nRowStart
, nTab
),
344 ScAddress( nColEnd
, nRowEnd
, nTab
) );
345 OUString
theArea(theCurArea
.Format(rDoc
, ScRefFlags::RANGE_ABS_3D
, aAddrDetails
));
346 m_xEdAssign
->SetText( theArea
);
347 m_xBtnAdd
->set_label( aStrModify
);
348 m_xBtnHeader
->set_active( pData
->HasHeader() );
349 m_xBtnTotals
->set_active( pData
->HasTotals() );
350 m_xBtnDoSize
->set_active( pData
->IsDoSize() );
351 m_xBtnKeepFmt
->set_active( pData
->IsKeepFmt() );
352 m_xBtnStripData
->set_active( pData
->IsStripData() );
353 SetInfoStrings( pData
);
356 m_xBtnAdd
->set_label( aStrModify
);
357 m_xBtnAdd
->set_sensitive(true);
358 m_xBtnRemove
->set_sensitive(true);
359 m_xOptions
->set_sensitive(true);
362 bool ScDbNameDlg::IsRefInputMode() const
364 return bRefInputMode
;
369 IMPL_LINK_NOARG(ScDbNameDlg
, OkBtnHdl
, weld::Button
&, void)
372 AddBtnHdl(*m_xBtnAdd
);
374 // Pass the changes and the remove list to the view: both are
375 // transferred as a reference only, so that no dead memory can
376 // be created at this point:
379 ScDBDocFunc
aFunc(*m_rViewData
.GetDocShell());
380 aFunc
.ModifyAllDBData(aLocalDbCol
, aRemoveList
);
385 IMPL_LINK_NOARG(ScDbNameDlg
, CancelBtnHdl
, weld::Button
&, void)
387 response(RET_CANCEL
);
390 IMPL_LINK_NOARG(ScDbNameDlg
, AddBtnHdl
, weld::Button
&, void)
392 OUString aNewName
= comphelper::string::strip(m_xEdName
->get_active_text(), ' ');
393 OUString aNewArea
= m_xEdAssign
->GetText();
395 if ( aNewName
.isEmpty() || aNewArea
.isEmpty() )
398 if (ScRangeData::IsNameValid(aNewName
, rDoc
) == ScRangeData::IsNameValidType::NAME_VALID
399 && aNewName
!= STR_DB_LOCAL_NONAME
)
401 // because editing can be done now, parsing is needed first
403 OUString aText
= m_xEdAssign
->GetText();
404 if ( aTmpRange
.ParseAny( aText
, rDoc
, aAddrDetails
) & ScRefFlags::VALID
)
406 theCurArea
= aTmpRange
;
407 ScAddress aStart
= theCurArea
.aStart
;
408 ScAddress aEnd
= theCurArea
.aEnd
;
410 ScDBData
* pOldEntry
= aLocalDbCol
.getNamedDBs().findByUpperName(ScGlobal::getCharClass().uppercase(aNewName
));
415 pOldEntry
->MoveTo( aStart
.Tab(), aStart
.Col(), aStart
.Row(),
416 aEnd
.Col(), aEnd
.Row() );
417 pOldEntry
->SetByRow( true );
418 pOldEntry
->SetHeader( m_xBtnHeader
->get_active() );
419 pOldEntry
->SetTotals( m_xBtnTotals
->get_active() );
420 pOldEntry
->SetDoSize( m_xBtnDoSize
->get_active() );
421 pOldEntry
->SetKeepFmt( m_xBtnKeepFmt
->get_active() );
422 pOldEntry
->SetStripData( m_xBtnStripData
->get_active() );
428 std::unique_ptr
<ScDBData
> pNewEntry(new ScDBData( aNewName
, aStart
.Tab(),
429 aStart
.Col(), aStart
.Row(),
430 aEnd
.Col(), aEnd
.Row(),
431 true, m_xBtnHeader
->get_active(),
432 m_xBtnTotals
->get_active() ));
433 pNewEntry
->SetDoSize( m_xBtnDoSize
->get_active() );
434 pNewEntry
->SetKeepFmt( m_xBtnKeepFmt
->get_active() );
435 pNewEntry
->SetStripData( m_xBtnStripData
->get_active() );
437 bool ins
= aLocalDbCol
.getNamedDBs().insert(std::move(pNewEntry
));
438 assert(ins
); (void)ins
;
443 m_xEdName
->set_entry_text( OUString() );
444 m_xEdName
->grab_focus();
445 m_xBtnAdd
->set_label( aStrAdd
);
446 m_xBtnAdd
->set_sensitive(false);
447 m_xBtnRemove
->set_sensitive(false);
448 m_xEdAssign
->SetText( OUString() );
449 m_xBtnHeader
->set_active(true); // Default: with column headers
450 m_xBtnTotals
->set_active( false ); // Default: without totals row
451 m_xBtnDoSize
->set_active( false );
452 m_xBtnKeepFmt
->set_active( false );
453 m_xBtnStripData
->set_active( false );
454 SetInfoStrings( nullptr ); // empty
455 theCurArea
= ScRange();
458 NameModifyHdl( *m_xEdName
);
462 ERRORBOX(m_xDialog
.get(), aStrInvalid
);
463 m_xEdAssign
->SelectAll();
464 m_xEdAssign
->GrabFocus();
470 ERRORBOX(m_xDialog
.get(), ScResId(STR_INVALIDNAME
));
471 m_xEdName
->select_entry_region(0, -1);
472 m_xEdName
->grab_focus();
481 const OUString
& mrName
;
483 explicit FindByName(const OUString
& rName
) : mrName(rName
) {}
484 bool operator() (std::unique_ptr
<ScDBData
> const& p
) const
486 return p
->GetName() == mrName
;
492 IMPL_LINK_NOARG(ScDbNameDlg
, RemoveBtnHdl
, weld::Button
&, void)
494 OUString aStrEntry
= m_xEdName
->get_active_text();
495 ScDBCollection::NamedDBs
& rDBs
= aLocalDbCol
.getNamedDBs();
496 ScDBCollection::NamedDBs::iterator itr
=
497 ::std::find_if(rDBs
.begin(), rDBs
.end(), FindByName(aStrEntry
));
499 if (itr
== rDBs
.end())
502 OUString aStrDelMsg
= ScResId( STR_QUERY_DELENTRY
);
503 OUString sMsg
{ o3tl::getToken(aStrDelMsg
, 0, '#') + aStrEntry
+ o3tl::getToken(aStrDelMsg
, 1, '#') };
504 std::unique_ptr
<weld::MessageDialog
> xQueryBox(Application::CreateMessageDialog(m_xDialog
.get(),
505 VclMessageType::Question
, VclButtonsType::YesNo
,
507 xQueryBox
->set_default_response(RET_YES
);
508 if (RET_YES
!= xQueryBox
->run())
512 SCCOL nColStart
, nColEnd
;
513 SCROW nRowStart
, nRowEnd
;
514 (*itr
)->GetArea( nTab
, nColStart
, nRowStart
, nColEnd
, nRowEnd
);
515 aRemoveList
.emplace_back( ScAddress( nColStart
, nRowStart
, nTab
),
516 ScAddress( nColEnd
, nRowEnd
, nTab
) );
522 m_xEdName
->set_entry_text( OUString() );
523 m_xEdName
->grab_focus();
524 m_xBtnAdd
->set_label( aStrAdd
);
525 m_xBtnAdd
->set_sensitive(false);
526 m_xBtnRemove
->set_sensitive(false);
527 m_xEdAssign
->SetText( OUString() );
528 theCurArea
= ScRange();
529 m_xBtnHeader
->set_active(true); // Default: with column headers
530 m_xBtnTotals
->set_active( false ); // Default: without totals row
531 m_xBtnDoSize
->set_active( false );
532 m_xBtnKeepFmt
->set_active( false );
533 m_xBtnStripData
->set_active( false );
534 SetInfoStrings( nullptr ); // empty
537 NameModifyHdl( *m_xEdName
);
540 IMPL_LINK_NOARG(ScDbNameDlg
, NameModifyHdl
, weld::ComboBox
&, void)
542 OUString theName
= m_xEdName
->get_active_text();
543 bool bNameFound
= m_xEdName
->find_text(theName
) != -1;
545 if ( theName
.isEmpty() )
547 if (m_xBtnAdd
->get_label() != aStrAdd
)
548 m_xBtnAdd
->set_label( aStrAdd
);
549 m_xBtnAdd
->set_sensitive(false);
550 m_xBtnRemove
->set_sensitive(false);
551 m_xAssignFrame
->set_sensitive(false);
552 m_xOptions
->set_sensitive(false);
554 //xSaveObj->Restore();
555 //@BugID 54702 enable/disable in the base class only
556 //SFX_APPWINDOW->Disable(sal_False); //! general method in ScAnyRefDlg
557 bRefInputMode
= false;
563 if (m_xBtnAdd
->get_label() != aStrModify
)
564 m_xBtnAdd
->set_label( aStrModify
);
571 UpdateDBData( theName
);
575 if (m_xBtnAdd
->get_label() != aStrAdd
)
576 m_xBtnAdd
->set_label( aStrAdd
);
581 if ( !m_xEdAssign
->GetText().isEmpty() )
583 m_xBtnAdd
->set_sensitive(true);
584 m_xOptions
->set_sensitive(true);
588 m_xBtnAdd
->set_sensitive(false);
589 m_xOptions
->set_sensitive(false);
591 m_xBtnRemove
->set_sensitive(false);
594 m_xAssignFrame
->set_sensitive(true);
596 //@BugID 54702 enable/disable in the base class only
597 //SFX_APPWINDOW->set_sensitive(true);
598 bRefInputMode
= true;
602 IMPL_LINK_NOARG(ScDbNameDlg
, AssModifyHdl
, formula::RefEdit
&, void)
604 // parse here for Save(), etc.
607 OUString aText
= m_xEdAssign
->GetText();
608 if ( aTmpRange
.ParseAny( aText
, rDoc
, aAddrDetails
) & ScRefFlags::VALID
)
609 theCurArea
= aTmpRange
;
611 if (!aText
.isEmpty() && !m_xEdName
->get_active_text().isEmpty())
613 m_xBtnAdd
->set_sensitive(true);
614 m_xBtnHeader
->set_sensitive(true);
615 m_xBtnTotals
->set_sensitive(true);
616 m_xBtnDoSize
->set_sensitive(true);
617 m_xBtnKeepFmt
->set_sensitive(true);
618 m_xBtnStripData
->set_sensitive(true);
619 m_xFTSource
->set_sensitive(true);
620 m_xFTOperations
->set_sensitive(true);
624 m_xBtnAdd
->set_sensitive(false);
625 m_xBtnHeader
->set_sensitive(false);
626 m_xBtnTotals
->set_sensitive(false);
627 m_xBtnDoSize
->set_sensitive(false);
628 m_xBtnKeepFmt
->set_sensitive(false);
629 m_xBtnStripData
->set_sensitive(false);
630 m_xFTSource
->set_sensitive(false);
631 m_xFTOperations
->set_sensitive(false);
635 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */