/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include class DBSaveData; static DBSaveData* pSaveObj = nullptr; namespace { void ERRORBOX(weld::Window* pParent, const OUString& rString) { std::unique_ptr xBox(Application::CreateMessageDialog(pParent, VclMessageType::Warning, VclButtonsType::Ok, rString)); xBox->run(); } } // class DBSaveData class DBSaveData { public: DBSaveData( Edit& rEd, CheckBox& rHdr, CheckBox& rTot, CheckBox& rSize, CheckBox& rFmt, CheckBox& rStrip, ScRange& rArea ) : rEdAssign(rEd) , rBtnHeader(rHdr) , rBtnTotals(rTot) , rBtnSize(rSize) , rBtnFormat(rFmt) , rBtnStrip(rStrip) , rCurArea(rArea) , bHeader(false) , bTotals(false) , bSize(false) , bFormat(false) , bStrip(false) , bDirty(false) { } void Save(); void Restore(); private: Edit& rEdAssign; CheckBox& rBtnHeader; CheckBox& rBtnTotals; CheckBox& rBtnSize; CheckBox& rBtnFormat; CheckBox& rBtnStrip; ScRange& rCurArea; OUString aStr; ScRange aArea; bool bHeader:1; bool bTotals:1; bool bSize:1; bool bFormat:1; bool bStrip:1; bool bDirty:1; }; void DBSaveData::Save() { aArea = rCurArea; aStr = rEdAssign.GetText(); bHeader = rBtnHeader.IsChecked(); bTotals = rBtnTotals.IsChecked(); bSize = rBtnSize.IsChecked(); bFormat = rBtnFormat.IsChecked(); bStrip = rBtnStrip.IsChecked(); bDirty = true; } void DBSaveData::Restore() { if ( bDirty ) { rCurArea = aArea; rEdAssign.SetText( aStr ); rBtnHeader.Check ( bHeader ); rBtnTotals.Check ( bTotals ); rBtnSize.Check ( bSize ); rBtnFormat.Check ( bFormat ); rBtnStrip.Check ( bStrip ); bDirty = false; } } // class ScDbNameDlg ScDbNameDlg::ScDbNameDlg(SfxBindings* pB, SfxChildWindow* pCW, vcl::Window* pParent, ScViewData* ptrViewData) : ScAnyRefDlg(pB, pCW, pParent, "DefineDatabaseRangeDialog", "modules/scalc/ui/definedatabaserangedialog.ui") , pViewData(ptrViewData) , pDoc(ptrViewData->GetDocument()) , bRefInputMode(false) , aAddrDetails(pDoc->GetAddressConvention(), 0, 0) , aLocalDbCol(*(pDoc->GetDBCollection())) { get(m_pEdName, "entry"); m_pEdName->set_height_request(m_pEdName->GetOptimalSize().Height() + m_pEdName->GetTextHeight() * 8); get(m_pEdAssign, "assign"); get(m_pAssignFrame, "RangeFrame"); m_pEdAssign->SetReferences(this, m_pAssignFrame->get_label_widget()); get(m_pRbAssign, "assignrb"); m_pRbAssign->SetReferences(this, m_pEdAssign); get(m_pOptions, "Options"); get(m_pBtnHeader, "ContainsColumnLabels"); get(m_pBtnTotals, "ContainsTotalsRow"); get(m_pBtnDoSize, "InsertOrDeleteCells"); get(m_pBtnKeepFmt, "KeepFormatting"); get(m_pBtnStripData, "DontSaveImportedData"); get(m_pFTSource, "Source"); get(m_pFTOperations, "Operations"); get(m_pBtnOk, "ok"); get(m_pBtnCancel, "cancel"); get(m_pBtnAdd, "add"); aStrAdd = m_pBtnAdd->GetText(); aStrModify = get("modify")->GetText(); get(m_pBtnRemove, "delete"); aStrInvalid = get("invalid")->GetText(); m_pFTSource->SetStyle(m_pFTSource->GetStyle() | WB_NOLABEL); m_pFTOperations->SetStyle(m_pFTOperations->GetStyle() | WB_NOLABEL); // so that the strings in the resource can stay with fixed texts: aStrSource = m_pFTSource->GetText(); aStrOperations = m_pFTOperations->GetText(); pSaveObj = new DBSaveData( *m_pEdAssign, *m_pBtnHeader, *m_pBtnTotals, *m_pBtnDoSize, *m_pBtnKeepFmt, *m_pBtnStripData, theCurArea ); Init(); } ScDbNameDlg::~ScDbNameDlg() { disposeOnce(); } void ScDbNameDlg::dispose() { DELETEZ( pSaveObj ); m_pEdName.clear(); m_pAssignFrame.clear(); m_pEdAssign.clear(); m_pRbAssign.clear(); m_pOptions.clear(); m_pBtnHeader.clear(); m_pBtnTotals.clear(); m_pBtnDoSize.clear(); m_pBtnKeepFmt.clear(); m_pBtnStripData.clear(); m_pFTSource.clear(); m_pFTOperations.clear(); m_pBtnOk.clear(); m_pBtnCancel.clear(); m_pBtnAdd.clear(); m_pBtnRemove.clear(); ScAnyRefDlg::dispose(); } void ScDbNameDlg::Init() { m_pBtnHeader->Check(); // Default: with column headers m_pBtnTotals->Check( false ); // Default: without totals row m_pBtnDoSize->Check(); m_pBtnKeepFmt->Check(); m_pBtnOk->SetClickHdl ( LINK( this, ScDbNameDlg, OkBtnHdl ) ); m_pBtnCancel->SetClickHdl ( LINK( this, ScDbNameDlg, CancelBtnHdl ) ); m_pBtnAdd->SetClickHdl ( LINK( this, ScDbNameDlg, AddBtnHdl ) ); m_pBtnRemove->SetClickHdl ( LINK( this, ScDbNameDlg, RemoveBtnHdl ) ); m_pEdName->SetModifyHdl ( LINK( this, ScDbNameDlg, NameModifyHdl ) ); m_pEdAssign->SetModifyHdl ( LINK( this, ScDbNameDlg, AssModifyHdl ) ); UpdateNames(); OUString theAreaStr; if ( pViewData && pDoc ) { SCCOL nStartCol = 0; SCROW nStartRow = 0; SCTAB nStartTab = 0; SCCOL nEndCol = 0; SCROW nEndRow = 0; SCTAB nEndTab = 0; ScDBCollection* pDBColl = pDoc->GetDBCollection(); ScDBData* pDBData = nullptr; pViewData->GetSimpleArea( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab ); theCurArea = ScRange( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab); theAreaStr = theCurArea.Format(ScRefFlags::RANGE_ABS_3D, pDoc, aAddrDetails); if ( pDBColl ) { // determine if the defined DB area has been marked: pDBData = pDBColl->GetDBAtCursor( nStartCol, nStartRow, nStartTab, ScDBDataPortion::TOP_LEFT ); if ( pDBData ) { ScAddress& rStart = theCurArea.aStart; ScAddress& rEnd = theCurArea.aEnd; SCCOL nCol1; SCCOL nCol2; SCROW nRow1; SCROW nRow2; SCTAB nTab; pDBData->GetArea( nTab, nCol1, nRow1, nCol2, nRow2 ); if ( (rStart.Tab() == nTab) && (rStart.Col() == nCol1) && (rStart.Row() == nRow1) && (rEnd.Col() == nCol2) && (rEnd.Row() == nRow2 ) ) { OUString aDBName = pDBData->GetName(); if ( aDBName != STR_DB_LOCAL_NONAME ) m_pEdName->SetText(aDBName); m_pBtnHeader->Check( pDBData->HasHeader() ); m_pBtnTotals->Check( pDBData->HasTotals() ); m_pBtnDoSize->Check( pDBData->IsDoSize() ); m_pBtnKeepFmt->Check( pDBData->IsKeepFmt() ); m_pBtnStripData->Check( pDBData->IsStripData() ); SetInfoStrings( pDBData ); } } } } m_pEdAssign->SetText( theAreaStr ); m_pEdName->GrabFocus(); bSaved = true; pSaveObj->Save(); NameModifyHdl( *m_pEdName ); } void ScDbNameDlg::SetInfoStrings( const ScDBData* pDBData ) { OUStringBuffer aBuf; aBuf.append(aStrSource); if (pDBData) { aBuf.append(' '); aBuf.append(pDBData->GetSourceString()); } m_pFTSource->SetText(aBuf.makeStringAndClear()); aBuf.append(aStrOperations); if (pDBData) { aBuf.append(' '); aBuf.append(pDBData->GetOperations()); } m_pFTOperations->SetText(aBuf.makeStringAndClear()); } // Transfer of a table area selected with the mouse, which is then displayed // as a new selection in the reference window. void ScDbNameDlg::SetReference( const ScRange& rRef, ScDocument* pDocP ) { if ( m_pEdAssign->IsEnabled() ) { if ( rRef.aStart != rRef.aEnd ) RefInputStart(m_pEdAssign); theCurArea = rRef; OUString aRefStr(theCurArea.Format(ScRefFlags::RANGE_ABS_3D, pDocP, aAddrDetails)); m_pEdAssign->SetRefString( aRefStr ); m_pOptions->Enable(); m_pBtnAdd->Enable(); bSaved = true; pSaveObj->Save(); } } bool ScDbNameDlg::Close() { return DoClose( ScDbNameDlgWrapper::GetChildWindowId() ); } void ScDbNameDlg::SetActive() { m_pEdAssign->GrabFocus(); // No NameModifyHdl, because otherwise areas can not be changed // (the old content would be displayed again after the reference selection is pulled) // (the selected DB name has not changed either) RefInputDone(); } void ScDbNameDlg::UpdateNames() { typedef ScDBCollection::NamedDBs DBsType; const DBsType& rDBs = aLocalDbCol.getNamedDBs(); m_pEdName->SetUpdateMode( false ); m_pEdName->Clear(); m_pEdAssign->SetText( EMPTY_OUSTRING ); if (!rDBs.empty()) { DBsType::const_iterator itr = rDBs.begin(), itrEnd = rDBs.end(); for (; itr != itrEnd; ++itr) m_pEdName->InsertEntry((*itr)->GetName()); } else { m_pBtnAdd->SetText( aStrAdd ); m_pBtnAdd->Disable(); m_pBtnRemove->Disable(); } m_pEdName->SetUpdateMode( true ); m_pEdName->Invalidate(); } void ScDbNameDlg::UpdateDBData( const OUString& rStrName ) { const ScDBData* pData = aLocalDbCol.getNamedDBs().findByUpperName(ScGlobal::pCharClass->uppercase(rStrName)); if ( pData ) { SCCOL nColStart = 0; SCROW nRowStart = 0; SCCOL nColEnd = 0; SCROW nRowEnd = 0; SCTAB nTab = 0; pData->GetArea( nTab, nColStart, nRowStart, nColEnd, nRowEnd ); theCurArea = ScRange( ScAddress( nColStart, nRowStart, nTab ), ScAddress( nColEnd, nRowEnd, nTab ) ); OUString theArea(theCurArea.Format(ScRefFlags::RANGE_ABS_3D, pDoc, aAddrDetails)); m_pEdAssign->SetText( theArea ); m_pBtnAdd->SetText( aStrModify ); m_pBtnHeader->Check( pData->HasHeader() ); m_pBtnTotals->Check( pData->HasTotals() ); m_pBtnDoSize->Check( pData->IsDoSize() ); m_pBtnKeepFmt->Check( pData->IsKeepFmt() ); m_pBtnStripData->Check( pData->IsStripData() ); SetInfoStrings( pData ); } m_pBtnAdd->SetText( aStrModify ); m_pBtnAdd->Enable(); m_pBtnRemove->Enable(); m_pOptions->Enable(); } bool ScDbNameDlg::IsRefInputMode() const { return bRefInputMode; } // Handler: IMPL_LINK_NOARG(ScDbNameDlg, OkBtnHdl, Button*, void) { AddBtnHdl( nullptr ); // Pass the changes and the remove list to the view: both are // transferred as a reference only, so that no dead memory can // be created at this point: if ( pViewData ) { ScDBDocFunc aFunc(*pViewData->GetDocShell()); aFunc.ModifyAllDBData(aLocalDbCol, aRemoveList); } Close(); } IMPL_LINK_NOARG(ScDbNameDlg, CancelBtnHdl, Button*, void) { Close(); } IMPL_LINK_NOARG(ScDbNameDlg, AddBtnHdl, Button*, void) { OUString aNewName = comphelper::string::strip(m_pEdName->GetText(), ' '); OUString aNewArea = m_pEdAssign->GetText(); if ( !aNewName.isEmpty() && !aNewArea.isEmpty() ) { if ( ScRangeData::IsNameValid( aNewName, pDoc ) == ScRangeData::NAME_VALID && aNewName != STR_DB_LOCAL_NONAME ) { // because editing can be done now, parsing is needed first ScRange aTmpRange; OUString aText = m_pEdAssign->GetText(); if ( aTmpRange.ParseAny( aText, pDoc, aAddrDetails ) & ScRefFlags::VALID ) { theCurArea = aTmpRange; ScAddress aStart = theCurArea.aStart; ScAddress aEnd = theCurArea.aEnd; ScDBData* pOldEntry = aLocalDbCol.getNamedDBs().findByUpperName(ScGlobal::pCharClass->uppercase(aNewName)); if (pOldEntry) { // modify area pOldEntry->MoveTo( aStart.Tab(), aStart.Col(), aStart.Row(), aEnd.Col(), aEnd.Row() ); pOldEntry->SetByRow( true ); pOldEntry->SetHeader( m_pBtnHeader->IsChecked() ); pOldEntry->SetTotals( m_pBtnTotals->IsChecked() ); pOldEntry->SetDoSize( m_pBtnDoSize->IsChecked() ); pOldEntry->SetKeepFmt( m_pBtnKeepFmt->IsChecked() ); pOldEntry->SetStripData( m_pBtnStripData->IsChecked() ); } else { // insert new area ScDBData* pNewEntry = new ScDBData( aNewName, aStart.Tab(), aStart.Col(), aStart.Row(), aEnd.Col(), aEnd.Row(), true, m_pBtnHeader->IsChecked(), m_pBtnTotals->IsChecked() ); pNewEntry->SetDoSize( m_pBtnDoSize->IsChecked() ); pNewEntry->SetKeepFmt( m_pBtnKeepFmt->IsChecked() ); pNewEntry->SetStripData( m_pBtnStripData->IsChecked() ); bool ins = aLocalDbCol.getNamedDBs().insert(pNewEntry); assert(ins); (void)ins; } UpdateNames(); m_pEdName->SetText( EMPTY_OUSTRING ); m_pEdName->GrabFocus(); m_pBtnAdd->SetText( aStrAdd ); m_pBtnAdd->Disable(); m_pBtnRemove->Disable(); m_pEdAssign->SetText( EMPTY_OUSTRING ); m_pBtnHeader->Check(); // Default: with column headers m_pBtnTotals->Check( false ); // Default: without totals row m_pBtnDoSize->Check( false ); m_pBtnKeepFmt->Check( false ); m_pBtnStripData->Check( false ); SetInfoStrings( nullptr ); // empty theCurArea = ScRange(); bSaved = true; pSaveObj->Save(); NameModifyHdl( *m_pEdName ); } else { ERRORBOX(GetFrameWeld(), aStrInvalid); m_pEdAssign->SetSelection( Selection( 0, SELECTION_MAX ) ); m_pEdAssign->GrabFocus(); } } else { ERRORBOX(GetFrameWeld(), ScGlobal::GetRscString(STR_INVALIDNAME)); m_pEdName->SetSelection( Selection( 0, SELECTION_MAX ) ); m_pEdName->GrabFocus(); } } } namespace { class FindByName { const OUString& mrName; public: explicit FindByName(const OUString& rName) : mrName(rName) {} bool operator() (std::unique_ptr const& p) const { return p->GetName() == mrName; } }; } IMPL_LINK_NOARG(ScDbNameDlg, RemoveBtnHdl, Button*, void) { OUString aStrEntry = m_pEdName->GetText(); ScDBCollection::NamedDBs& rDBs = aLocalDbCol.getNamedDBs(); ScDBCollection::NamedDBs::iterator itr = ::std::find_if(rDBs.begin(), rDBs.end(), FindByName(aStrEntry)); if (itr != rDBs.end()) { OUString aStrDelMsg = ScGlobal::GetRscString( STR_QUERY_DELENTRY ); OUStringBuffer aBuf; aBuf.append(aStrDelMsg.getToken(0, '#')); aBuf.append(aStrEntry); aBuf.append(aStrDelMsg.getToken(1, '#')); ScopedVclPtrInstance< QueryBox > aBox(this, MessBoxStyle::YesNo|MessBoxStyle::DefaultYes, aBuf.makeStringAndClear()); if (RET_YES == aBox->Execute()) { SCTAB nTab; SCCOL nColStart, nColEnd; SCROW nRowStart, nRowEnd; (*itr)->GetArea( nTab, nColStart, nRowStart, nColEnd, nRowEnd ); aRemoveList.emplace_back( ScAddress( nColStart, nRowStart, nTab ), ScAddress( nColEnd, nRowEnd, nTab ) ); rDBs.erase(itr); UpdateNames(); m_pEdName->SetText( EMPTY_OUSTRING ); m_pEdName->GrabFocus(); m_pBtnAdd->SetText( aStrAdd ); m_pBtnAdd->Disable(); m_pBtnRemove->Disable(); m_pEdAssign->SetText( EMPTY_OUSTRING ); theCurArea = ScRange(); m_pBtnHeader->Check(); // Default: with column headers m_pBtnTotals->Check( false ); // Default: without totals row m_pBtnDoSize->Check( false ); m_pBtnKeepFmt->Check( false ); m_pBtnStripData->Check( false ); SetInfoStrings( nullptr ); // empty bSaved=false; pSaveObj->Restore(); NameModifyHdl( *m_pEdName ); } } } IMPL_LINK_NOARG(ScDbNameDlg, NameModifyHdl, Edit&, void) { OUString theName = m_pEdName->GetText(); bool bNameFound = (COMBOBOX_ENTRY_NOTFOUND != m_pEdName->GetEntryPos( theName )); if ( theName.isEmpty() ) { if (m_pBtnAdd->GetText() != aStrAdd) m_pBtnAdd->SetText( aStrAdd ); m_pBtnAdd->Disable(); m_pBtnRemove->Disable(); m_pAssignFrame->Disable(); m_pOptions->Disable(); //bSaved=sal_False; //pSaveObj->Restore(); //@BugID 54702 enable/disable in the base class only //SFX_APPWINDOW->Disable(sal_False); //! general method in ScAnyRefDlg bRefInputMode = false; } else { if ( bNameFound ) { if (m_pBtnAdd->GetText() != aStrModify) m_pBtnAdd->SetText( aStrModify ); if(!bSaved) { bSaved = true; pSaveObj->Save(); } UpdateDBData( theName ); } else { if (m_pBtnAdd->GetText() != aStrAdd) m_pBtnAdd->SetText( aStrAdd ); bSaved=false; pSaveObj->Restore(); if ( !m_pEdAssign->GetText().isEmpty() ) { m_pBtnAdd->Enable(); m_pOptions->Enable(); } else { m_pBtnAdd->Disable(); m_pOptions->Disable(); } m_pBtnRemove->Disable(); } m_pAssignFrame->Enable(); //@BugID 54702 enable/disable in the base class only //SFX_APPWINDOW->Enable(); bRefInputMode = true; } } IMPL_LINK_NOARG(ScDbNameDlg, AssModifyHdl, Edit&, void) { // parse here for Save(), etc. ScRange aTmpRange; OUString aText = m_pEdAssign->GetText(); if ( aTmpRange.ParseAny( aText, pDoc, aAddrDetails ) & ScRefFlags::VALID ) theCurArea = aTmpRange; if (!aText.isEmpty() && !m_pEdName->GetText().isEmpty()) { m_pBtnAdd->Enable(); m_pBtnHeader->Enable(); m_pBtnTotals->Enable(); m_pBtnDoSize->Enable(); m_pBtnKeepFmt->Enable(); m_pBtnStripData->Enable(); m_pFTSource->Enable(); m_pFTOperations->Enable(); } else { m_pBtnAdd->Disable(); m_pBtnHeader->Disable(); m_pBtnTotals->Disable(); m_pBtnDoSize->Disable(); m_pBtnKeepFmt->Disable(); m_pBtnStripData->Disable(); m_pFTSource->Disable(); m_pFTOperations->Disable(); } } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */