Drop ScGlobal::GetEmptyOUString() and EMPTY_OUSTRING
[LibreOffice.git] / sc / source / ui / dbgui / dbnamdlg.cxx
bloba0f6f209347c1716ac04b4f459265565b608b712
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 <memory>
21 #include <sal/config.h>
23 #include <cassert>
25 #include <comphelper/string.hxx>
26 #include <unotools/charclass.hxx>
27 #include <vcl/svapp.hxx>
28 #include <vcl/weld.hxx>
30 #include <reffact.hxx>
31 #include <document.hxx>
32 #include <globstr.hrc>
33 #include <scresid.hxx>
34 #include <rangenam.hxx>
35 #include <globalnames.hxx>
36 #include <dbnamdlg.hxx>
37 #include <dbdocfun.hxx>
39 namespace {
41 class DBSaveData;
45 static std::unique_ptr<DBSaveData> xSaveObj;
47 namespace
49 void ERRORBOX(weld::Window* pParent, const OUString& rString)
51 std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(pParent,
52 VclMessageType::Warning, VclButtonsType::Ok,
53 rString));
54 xBox->run();
58 class DBSaveData
60 public:
61 DBSaveData( formula::RefEdit& rEd, weld::CheckButton& rHdr, weld::CheckButton& rTot, weld::CheckButton& rSize, weld::CheckButton& rFmt,
62 weld::CheckButton& rStrip, ScRange& rArea )
63 : rEdAssign(rEd)
64 , rBtnHeader(rHdr)
65 , rBtnTotals(rTot)
66 , rBtnSize(rSize)
67 , rBtnFormat(rFmt)
68 , rBtnStrip(rStrip)
69 , rCurArea(rArea)
70 , bHeader(false)
71 , bTotals(false)
72 , bSize(false)
73 , bFormat(false)
74 , bStrip(false)
75 , bDirty(false)
78 void Save();
79 void Restore();
81 private:
82 formula::RefEdit& rEdAssign;
83 weld::CheckButton& rBtnHeader;
84 weld::CheckButton& rBtnTotals;
85 weld::CheckButton& rBtnSize;
86 weld::CheckButton& rBtnFormat;
87 weld::CheckButton& rBtnStrip;
88 ScRange& rCurArea;
89 OUString aStr;
90 ScRange aArea;
91 bool bHeader:1;
92 bool bTotals:1;
93 bool bSize:1;
94 bool bFormat:1;
95 bool bStrip:1;
96 bool bDirty:1;
101 void DBSaveData::Save()
103 aArea = rCurArea;
104 aStr = rEdAssign.GetText();
105 bHeader = rBtnHeader.get_active();
106 bTotals = rBtnTotals.get_active();
107 bSize = rBtnSize.get_active();
108 bFormat = rBtnFormat.get_active();
109 bStrip = rBtnStrip.get_active();
110 bDirty = true;
113 void DBSaveData::Restore()
115 if ( bDirty )
117 rCurArea = aArea;
118 rEdAssign.SetText( aStr );
119 rBtnHeader.set_active ( bHeader );
120 rBtnTotals.set_active ( bTotals );
121 rBtnSize.set_active ( bSize );
122 rBtnFormat.set_active ( bFormat );
123 rBtnStrip.set_active ( bStrip );
124 bDirty = false;
129 ScDbNameDlg::ScDbNameDlg(SfxBindings* pB, SfxChildWindow* pCW, weld::Window* pParent,
130 ScViewData& rViewData)
131 : ScAnyRefDlgController(pB, pCW, pParent,
132 "modules/scalc/ui/definedatabaserangedialog.ui", "DefineDatabaseRangeDialog")
133 , m_rViewData(rViewData)
134 , rDoc(rViewData.GetDocument())
135 , bRefInputMode(false)
136 , aAddrDetails(rDoc.GetAddressConvention(), 0, 0)
137 , aLocalDbCol(*(rDoc.GetDBCollection()))
138 , m_xEdName(m_xBuilder->weld_entry_tree_view("entrygrid", "entry", "entry-list"))
139 , m_xAssignFrame(m_xBuilder->weld_frame("RangeFrame"))
140 , m_xEdAssign(new formula::RefEdit(m_xBuilder->weld_entry("assign")))
141 , m_xRbAssign(new formula::RefButton(m_xBuilder->weld_button("assignrb")))
142 , m_xOptions(m_xBuilder->weld_widget("Options"))
143 , m_xBtnHeader(m_xBuilder->weld_check_button("ContainsColumnLabels"))
144 , m_xBtnTotals(m_xBuilder->weld_check_button("ContainsTotalsRow"))
145 , m_xBtnDoSize(m_xBuilder->weld_check_button("InsertOrDeleteCells"))
146 , m_xBtnKeepFmt(m_xBuilder->weld_check_button("KeepFormatting"))
147 , m_xBtnStripData(m_xBuilder->weld_check_button("DontSaveImportedData"))
148 , m_xFTSource(m_xBuilder->weld_label("Source"))
149 , m_xFTOperations(m_xBuilder->weld_label("Operations"))
150 , m_xBtnOk(m_xBuilder->weld_button("ok"))
151 , m_xBtnCancel(m_xBuilder->weld_button("cancel"))
152 , m_xBtnAdd(m_xBuilder->weld_button("add"))
153 , m_xBtnRemove(m_xBuilder->weld_button("delete"))
154 , m_xModifyPB(m_xBuilder->weld_button("modify"))
155 , m_xInvalidFT(m_xBuilder->weld_label("invalid"))
156 , m_xFrameLabel(m_xAssignFrame->weld_label_widget())
157 , m_xExpander(m_xBuilder->weld_expander("more"))
159 m_xEdName->set_height_request_by_rows(4);
160 m_xEdAssign->SetReferences(this, m_xFrameLabel.get());
161 m_xRbAssign->SetReferences(this, m_xEdAssign.get());
162 aStrAdd = m_xBtnAdd->get_label();
163 aStrModify = m_xModifyPB->get_label();
164 aStrInvalid = m_xInvalidFT->get_label();
166 // so that the strings in the resource can stay with fixed texts:
167 aStrSource = m_xFTSource->get_label();
168 aStrOperations = m_xFTOperations->get_label();
170 xSaveObj.reset(new DBSaveData( *m_xEdAssign, *m_xBtnHeader, *m_xBtnTotals,
171 *m_xBtnDoSize, *m_xBtnKeepFmt, *m_xBtnStripData, theCurArea ));
172 Init();
175 ScDbNameDlg::~ScDbNameDlg()
177 xSaveObj.reset();
180 void ScDbNameDlg::Init()
182 m_xBtnHeader->set_active(true); // Default: with column headers
183 m_xBtnTotals->set_active( false ); // Default: without totals row
184 m_xBtnDoSize->set_active(true);
185 m_xBtnKeepFmt->set_active(true);
187 m_xBtnOk->connect_clicked ( LINK( this, ScDbNameDlg, OkBtnHdl ) );
188 m_xBtnCancel->connect_clicked ( LINK( this, ScDbNameDlg, CancelBtnHdl ) );
189 m_xBtnAdd->connect_clicked ( LINK( this, ScDbNameDlg, AddBtnHdl ) );
190 m_xBtnRemove->connect_clicked ( LINK( this, ScDbNameDlg, RemoveBtnHdl ) );
191 m_xEdName->connect_changed( LINK( this, ScDbNameDlg, NameModifyHdl ) );
192 m_xEdAssign->SetModifyHdl ( LINK( this, ScDbNameDlg, AssModifyHdl ) );
193 UpdateNames();
195 OUString theAreaStr;
197 SCCOL nStartCol = 0;
198 SCROW nStartRow = 0;
199 SCTAB nStartTab = 0;
200 SCCOL nEndCol = 0;
201 SCROW nEndRow = 0;
202 SCTAB nEndTab = 0;
204 ScDBCollection* pDBColl = rDoc.GetDBCollection();
206 m_rViewData.GetSimpleArea( nStartCol, nStartRow, nStartTab,
207 nEndCol, nEndRow, nEndTab );
209 theCurArea = ScRange( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab);
211 theAreaStr = theCurArea.Format(rDoc, ScRefFlags::RANGE_ABS_3D, aAddrDetails);
213 if ( pDBColl )
215 // determine if the defined DB area has been marked:
216 ScDBData* pDBData = pDBColl->GetDBAtCursor( nStartCol, nStartRow, nStartTab, ScDBDataPortion::TOP_LEFT );
217 if ( pDBData )
219 ScAddress& rStart = theCurArea.aStart;
220 ScAddress& rEnd = theCurArea.aEnd;
221 SCCOL nCol1;
222 SCCOL nCol2;
223 SCROW nRow1;
224 SCROW nRow2;
225 SCTAB nTab;
227 pDBData->GetArea( nTab, nCol1, nRow1, nCol2, nRow2 );
229 if ( (rStart.Tab() == nTab)
230 && (rStart.Col() == nCol1) && (rStart.Row() == nRow1)
231 && (rEnd.Col() == nCol2) && (rEnd.Row() == nRow2 ) )
233 OUString aDBName = pDBData->GetName();
234 if ( aDBName != STR_DB_LOCAL_NONAME )
235 m_xEdName->set_entry_text(aDBName);
237 m_xBtnHeader->set_active( pDBData->HasHeader() );
238 m_xBtnTotals->set_active( pDBData->HasTotals() );
239 m_xBtnDoSize->set_active( pDBData->IsDoSize() );
240 m_xBtnKeepFmt->set_active( pDBData->IsKeepFmt() );
241 m_xBtnStripData->set_active( pDBData->IsStripData() );
242 SetInfoStrings( pDBData );
247 m_xEdAssign->SetText( theAreaStr );
248 m_xEdName->grab_focus();
249 bSaved = true;
250 xSaveObj->Save();
251 NameModifyHdl( *m_xEdName );
252 bInvalid = false;
255 void ScDbNameDlg::SetInfoStrings( const ScDBData* pDBData )
257 OUStringBuffer aBuf;
258 aBuf.append(aStrSource);
259 if (pDBData)
261 aBuf.append(' ');
262 aBuf.append(pDBData->GetSourceString());
264 m_xFTSource->set_label(aBuf.makeStringAndClear());
266 aBuf.append(aStrOperations);
267 if (pDBData)
269 aBuf.append(' ');
270 aBuf.append(pDBData->GetOperations());
272 m_xFTOperations->set_label(aBuf.makeStringAndClear());
275 // Transfer of a table area selected with the mouse, which is then displayed
276 // as a new selection in the reference window.
278 void ScDbNameDlg::SetReference( const ScRange& rRef, ScDocument& rDocP )
280 if (!m_xEdAssign->GetWidget()->get_sensitive())
281 return;
283 if ( rRef.aStart != rRef.aEnd )
284 RefInputStart(m_xEdAssign.get());
286 theCurArea = rRef;
288 OUString aRefStr(theCurArea.Format(rDocP, ScRefFlags::RANGE_ABS_3D, aAddrDetails));
289 m_xEdAssign->SetRefString( aRefStr );
290 m_xOptions->set_sensitive(true);
291 m_xBtnAdd->set_sensitive(true);
292 bSaved = true;
293 xSaveObj->Save();
296 void ScDbNameDlg::Close()
298 DoClose( ScDbNameDlgWrapper::GetChildWindowId() );
301 void ScDbNameDlg::SetActive()
303 m_xEdAssign->GrabFocus();
305 // No NameModifyHdl, because otherwise areas can not be changed
306 // (the old content would be displayed again after the reference selection is pulled)
307 // (the selected DB name has not changed either)
309 RefInputDone();
312 void ScDbNameDlg::UpdateNames()
314 typedef ScDBCollection::NamedDBs DBsType;
316 const DBsType& rDBs = aLocalDbCol.getNamedDBs();
318 m_xEdName->freeze();
320 m_xEdName->clear();
321 m_xEdAssign->SetText( OUString() );
323 if (!rDBs.empty())
325 for (const auto& rxDB : rDBs)
326 m_xEdName->append_text(rxDB->GetName());
328 else
330 m_xBtnAdd->set_label( aStrAdd );
331 m_xBtnAdd->set_sensitive(false);
332 m_xBtnRemove->set_sensitive(false);
335 m_xEdName->thaw();
338 void ScDbNameDlg::UpdateDBData( const OUString& rStrName )
341 const ScDBData* pData = aLocalDbCol.getNamedDBs().findByUpperName(ScGlobal::getCharClass().uppercase(rStrName));
343 if ( pData )
345 SCCOL nColStart = 0;
346 SCROW nRowStart = 0;
347 SCCOL nColEnd = 0;
348 SCROW nRowEnd = 0;
349 SCTAB nTab = 0;
351 pData->GetArea( nTab, nColStart, nRowStart, nColEnd, nRowEnd );
352 theCurArea = ScRange( ScAddress( nColStart, nRowStart, nTab ),
353 ScAddress( nColEnd, nRowEnd, nTab ) );
354 OUString theArea(theCurArea.Format(rDoc, ScRefFlags::RANGE_ABS_3D, aAddrDetails));
355 m_xEdAssign->SetText( theArea );
356 m_xBtnAdd->set_label( aStrModify );
357 m_xBtnHeader->set_active( pData->HasHeader() );
358 m_xBtnTotals->set_active( pData->HasTotals() );
359 m_xBtnDoSize->set_active( pData->IsDoSize() );
360 m_xBtnKeepFmt->set_active( pData->IsKeepFmt() );
361 m_xBtnStripData->set_active( pData->IsStripData() );
362 SetInfoStrings( pData );
365 m_xBtnAdd->set_label( aStrModify );
366 m_xBtnAdd->set_sensitive(true);
367 m_xBtnRemove->set_sensitive(true);
368 m_xOptions->set_sensitive(true);
371 bool ScDbNameDlg::IsRefInputMode() const
373 return bRefInputMode;
376 // Handler:
378 IMPL_LINK_NOARG(ScDbNameDlg, OkBtnHdl, weld::Button&, void)
380 bInvalid = false;
381 AddBtnHdl(*m_xBtnAdd);
383 // Pass the changes and the remove list to the view: both are
384 // transferred as a reference only, so that no dead memory can
385 // be created at this point:
386 if (!bInvalid)
388 ScDBDocFunc aFunc(*m_rViewData.GetDocShell());
389 aFunc.ModifyAllDBData(aLocalDbCol, aRemoveList);
390 response(RET_OK);
394 IMPL_LINK_NOARG(ScDbNameDlg, CancelBtnHdl, weld::Button&, void)
396 response(RET_CANCEL);
399 IMPL_LINK_NOARG(ScDbNameDlg, AddBtnHdl, weld::Button&, void)
401 OUString aNewName = comphelper::string::strip(m_xEdName->get_active_text(), ' ');
402 OUString aNewArea = m_xEdAssign->GetText();
404 if ( aNewName.isEmpty() || aNewArea.isEmpty() )
405 return;
407 if (ScRangeData::IsNameValid(aNewName, rDoc) == ScRangeData::IsNameValidType::NAME_VALID
408 && aNewName != STR_DB_LOCAL_NONAME)
410 // because editing can be done now, parsing is needed first
411 ScRange aTmpRange;
412 OUString aText = m_xEdAssign->GetText();
413 if ( aTmpRange.ParseAny( aText, rDoc, aAddrDetails ) & ScRefFlags::VALID )
415 theCurArea = aTmpRange;
416 ScAddress aStart = theCurArea.aStart;
417 ScAddress aEnd = theCurArea.aEnd;
419 ScDBData* pOldEntry = aLocalDbCol.getNamedDBs().findByUpperName(ScGlobal::getCharClass().uppercase(aNewName));
420 if (pOldEntry)
422 // modify area
424 pOldEntry->MoveTo( aStart.Tab(), aStart.Col(), aStart.Row(),
425 aEnd.Col(), aEnd.Row() );
426 pOldEntry->SetByRow( true );
427 pOldEntry->SetHeader( m_xBtnHeader->get_active() );
428 pOldEntry->SetTotals( m_xBtnTotals->get_active() );
429 pOldEntry->SetDoSize( m_xBtnDoSize->get_active() );
430 pOldEntry->SetKeepFmt( m_xBtnKeepFmt->get_active() );
431 pOldEntry->SetStripData( m_xBtnStripData->get_active() );
433 else
435 // insert new area
437 std::unique_ptr<ScDBData> pNewEntry(new ScDBData( aNewName, aStart.Tab(),
438 aStart.Col(), aStart.Row(),
439 aEnd.Col(), aEnd.Row(),
440 true, m_xBtnHeader->get_active(),
441 m_xBtnTotals->get_active() ));
442 pNewEntry->SetDoSize( m_xBtnDoSize->get_active() );
443 pNewEntry->SetKeepFmt( m_xBtnKeepFmt->get_active() );
444 pNewEntry->SetStripData( m_xBtnStripData->get_active() );
446 bool ins = aLocalDbCol.getNamedDBs().insert(std::move(pNewEntry));
447 assert(ins); (void)ins;
450 UpdateNames();
452 m_xEdName->set_entry_text( OUString() );
453 m_xEdName->grab_focus();
454 m_xBtnAdd->set_label( aStrAdd );
455 m_xBtnAdd->set_sensitive(false);
456 m_xBtnRemove->set_sensitive(false);
457 m_xEdAssign->SetText( OUString() );
458 m_xBtnHeader->set_active(true); // Default: with column headers
459 m_xBtnTotals->set_active( false ); // Default: without totals row
460 m_xBtnDoSize->set_active( false );
461 m_xBtnKeepFmt->set_active( false );
462 m_xBtnStripData->set_active( false );
463 SetInfoStrings( nullptr ); // empty
464 theCurArea = ScRange();
465 bSaved = true;
466 xSaveObj->Save();
467 NameModifyHdl( *m_xEdName );
469 else
471 ERRORBOX(m_xDialog.get(), aStrInvalid);
472 m_xEdAssign->SelectAll();
473 m_xEdAssign->GrabFocus();
474 bInvalid = true;
477 else
479 ERRORBOX(m_xDialog.get(), ScResId(STR_INVALIDNAME));
480 m_xEdName->select_entry_region(0, -1);
481 m_xEdName->grab_focus();
482 bInvalid = true;
486 namespace {
488 class FindByName
490 const OUString& mrName;
491 public:
492 explicit FindByName(const OUString& rName) : mrName(rName) {}
493 bool operator() (std::unique_ptr<ScDBData> const& p) const
495 return p->GetName() == mrName;
501 IMPL_LINK_NOARG(ScDbNameDlg, RemoveBtnHdl, weld::Button&, void)
503 OUString aStrEntry = m_xEdName->get_active_text();
504 ScDBCollection::NamedDBs& rDBs = aLocalDbCol.getNamedDBs();
505 ScDBCollection::NamedDBs::iterator itr =
506 ::std::find_if(rDBs.begin(), rDBs.end(), FindByName(aStrEntry));
508 if (itr == rDBs.end())
509 return;
511 OUString aStrDelMsg = ScResId( STR_QUERY_DELENTRY );
512 OUString sMsg{ aStrDelMsg.getToken(0, '#') + aStrEntry + aStrDelMsg.getToken(1, '#') };
513 std::unique_ptr<weld::MessageDialog> xQueryBox(Application::CreateMessageDialog(m_xDialog.get(),
514 VclMessageType::Question, VclButtonsType::YesNo,
515 sMsg));
516 xQueryBox->set_default_response(RET_YES);
517 if (RET_YES != xQueryBox->run())
518 return;
520 SCTAB nTab;
521 SCCOL nColStart, nColEnd;
522 SCROW nRowStart, nRowEnd;
523 (*itr)->GetArea( nTab, nColStart, nRowStart, nColEnd, nRowEnd );
524 aRemoveList.emplace_back( ScAddress( nColStart, nRowStart, nTab ),
525 ScAddress( nColEnd, nRowEnd, nTab ) );
527 rDBs.erase(itr);
529 UpdateNames();
531 m_xEdName->set_entry_text( OUString() );
532 m_xEdName->grab_focus();
533 m_xBtnAdd->set_label( aStrAdd );
534 m_xBtnAdd->set_sensitive(false);
535 m_xBtnRemove->set_sensitive(false);
536 m_xEdAssign->SetText( OUString() );
537 theCurArea = ScRange();
538 m_xBtnHeader->set_active(true); // Default: with column headers
539 m_xBtnTotals->set_active( false ); // Default: without totals row
540 m_xBtnDoSize->set_active( false );
541 m_xBtnKeepFmt->set_active( false );
542 m_xBtnStripData->set_active( false );
543 SetInfoStrings( nullptr ); // empty
544 bSaved=false;
545 xSaveObj->Restore();
546 NameModifyHdl( *m_xEdName );
549 IMPL_LINK_NOARG(ScDbNameDlg, NameModifyHdl, weld::ComboBox&, void)
551 OUString theName = m_xEdName->get_active_text();
552 bool bNameFound = m_xEdName->find_text(theName) != -1;
554 if ( theName.isEmpty() )
556 if (m_xBtnAdd->get_label() != aStrAdd)
557 m_xBtnAdd->set_label( aStrAdd );
558 m_xBtnAdd->set_sensitive(false);
559 m_xBtnRemove->set_sensitive(false);
560 m_xAssignFrame->set_sensitive(false);
561 m_xOptions->set_sensitive(false);
562 //bSaved=sal_False;
563 //xSaveObj->Restore();
564 //@BugID 54702 enable/disable in the base class only
565 //SFX_APPWINDOW->Disable(sal_False); //! general method in ScAnyRefDlg
566 bRefInputMode = false;
568 else
570 if ( bNameFound )
572 if (m_xBtnAdd->get_label() != aStrModify)
573 m_xBtnAdd->set_label( aStrModify );
575 if(!bSaved)
577 bSaved = true;
578 xSaveObj->Save();
580 UpdateDBData( theName );
582 else
584 if (m_xBtnAdd->get_label() != aStrAdd)
585 m_xBtnAdd->set_label( aStrAdd );
587 bSaved=false;
588 xSaveObj->Restore();
590 if ( !m_xEdAssign->GetText().isEmpty() )
592 m_xBtnAdd->set_sensitive(true);
593 m_xOptions->set_sensitive(true);
595 else
597 m_xBtnAdd->set_sensitive(false);
598 m_xOptions->set_sensitive(false);
600 m_xBtnRemove->set_sensitive(false);
603 m_xAssignFrame->set_sensitive(true);
605 //@BugID 54702 enable/disable in the base class only
606 //SFX_APPWINDOW->set_sensitive(true);
607 bRefInputMode = true;
611 IMPL_LINK_NOARG(ScDbNameDlg, AssModifyHdl, formula::RefEdit&, void)
613 // parse here for Save(), etc.
615 ScRange aTmpRange;
616 OUString aText = m_xEdAssign->GetText();
617 if ( aTmpRange.ParseAny( aText, rDoc, aAddrDetails ) & ScRefFlags::VALID )
618 theCurArea = aTmpRange;
620 if (!aText.isEmpty() && !m_xEdName->get_active_text().isEmpty())
622 m_xBtnAdd->set_sensitive(true);
623 m_xBtnHeader->set_sensitive(true);
624 m_xBtnTotals->set_sensitive(true);
625 m_xBtnDoSize->set_sensitive(true);
626 m_xBtnKeepFmt->set_sensitive(true);
627 m_xBtnStripData->set_sensitive(true);
628 m_xFTSource->set_sensitive(true);
629 m_xFTOperations->set_sensitive(true);
631 else
633 m_xBtnAdd->set_sensitive(false);
634 m_xBtnHeader->set_sensitive(false);
635 m_xBtnTotals->set_sensitive(false);
636 m_xBtnDoSize->set_sensitive(false);
637 m_xBtnKeepFmt->set_sensitive(false);
638 m_xBtnStripData->set_sensitive(false);
639 m_xFTSource->set_sensitive(false);
640 m_xFTOperations->set_sensitive(false);
644 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */