870 lines
29 KiB
C++
870 lines
29 KiB
C++
/* -*- 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 .
|
|
*/
|
|
|
|
#undef SC_DLLIMPLEMENTATION
|
|
|
|
#include <vcl/svapp.hxx>
|
|
#include <vcl/weld.hxx>
|
|
#include <i18nlangtag/languagetag.hxx>
|
|
#include <svtools/collatorres.hxx>
|
|
#include <unotools/collatorwrapper.hxx>
|
|
#include <comphelper/processfactory.hxx>
|
|
#include <osl/diagnose.h>
|
|
|
|
#include <scitems.hxx>
|
|
#include <uiitems.hxx>
|
|
#include <viewdata.hxx>
|
|
#include <document.hxx>
|
|
#include <global.hxx>
|
|
#include <dbdata.hxx>
|
|
#include <userlist.hxx>
|
|
#include <rangeutl.hxx>
|
|
#include <scresid.hxx>
|
|
#include <sc.hrc>
|
|
#include <strings.hrc>
|
|
#include <globstr.hrc>
|
|
|
|
#include <sortkeydlg.hxx>
|
|
|
|
#include <sortdlg.hxx>
|
|
|
|
#include <tpsort.hxx>
|
|
|
|
using namespace com::sun::star;
|
|
|
|
/*
|
|
* Since the settings on the second Tab Page (Options) effects
|
|
* the first Tab Page, there must be a way for it to communicate with the
|
|
* other Page.
|
|
*
|
|
* At the moment this problem is solved through using two data members of the
|
|
* Tab Pages. If a page is enabled / disabled, it compares this data member
|
|
* with its own state (-> Activate() / Deactivate()).
|
|
*
|
|
* In the meantime the class SfxTabPage offers the following method:
|
|
*
|
|
* virtual sal_Bool HasExchangeSupport() const; -> return sal_True;
|
|
* virtual void ActivatePage(const SfxItemSet &);
|
|
* virtual int DeactivatePage(SfxItemSet * = 0);
|
|
*
|
|
* This still needs to be changed!
|
|
*/
|
|
|
|
// Sort Criteria Tab page
|
|
|
|
ScTabPageSortFields::ScTabPageSortFields(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rArgSet)
|
|
: SfxTabPage(pPage, pController, u"modules/scalc/ui/sortcriteriapage.ui"_ustr, u"SortCriteriaPage"_ustr, &rArgSet)
|
|
,
|
|
|
|
m_aIdle("ScTabPageSortFields Scroll To End Idle"),
|
|
aStrUndefined ( ScResId( SCSTR_UNDEFINED ) ),
|
|
aStrColumn ( ScResId( SCSTR_COLUMN ) ),
|
|
aStrRow ( ScResId( SCSTR_ROW ) ),
|
|
aStrRowLabel ( ScResId( SCSTR_ROW_LABEL ) ),
|
|
aStrColLabel ( ScResId( SCSTR_COL_LABEL ) ),
|
|
|
|
nWhichSort ( rArgSet.GetPool()->GetWhichIDFromSlotID( SID_SORT ) ),
|
|
pViewData ( nullptr ),
|
|
aSortData ( rArgSet.Get( nWhichSort ).GetSortData() ),
|
|
nFieldCount ( 0 ),
|
|
// show actual size of the sorting keys without limiting them to the default size
|
|
nSortKeyCount(std::max(aSortData.GetSortKeyCount(), static_cast<sal_uInt16>(DEFSORT)))
|
|
|
|
, m_xTop(m_xBuilder->weld_container(u"TopWindow"_ustr))
|
|
, m_xBtnHeader(m_xBuilder->weld_check_button(u"cbHeader"_ustr))
|
|
, m_xBtnTopDown(m_xBuilder->weld_radio_button(u"rbTopDown"_ustr))
|
|
, m_xBtnLeftRight(m_xBuilder->weld_radio_button(u"rbLeftRight"_ustr))
|
|
, m_xScrolledWindow(m_xBuilder->weld_scrolled_window(u"SortCriteriaPage"_ustr))
|
|
, m_xBox(m_xBuilder->weld_container(u"SortKeyWindow"_ustr))
|
|
, m_aSortWin(m_xBox.get())
|
|
{
|
|
// tdf#147722 set some nominal small default height so the height adapts
|
|
// to all the other contents and the natural height of this widget isn't
|
|
// an input into the overall size
|
|
m_xScrolledWindow->set_size_request(-1, 42);
|
|
|
|
Init();
|
|
|
|
m_aIdle.SetInvokeHandler(LINK(this, ScTabPageSortFields, ScrollToEndHdl));
|
|
|
|
SetExchangeSupport();
|
|
}
|
|
|
|
ScTabPageSortFields::~ScTabPageSortFields()
|
|
{
|
|
m_aSortWin.m_aSortKeyItems.clear();
|
|
m_xBox.reset();
|
|
m_xScrolledWindow.reset();
|
|
}
|
|
|
|
void ScTabPageSortFields::Init()
|
|
{
|
|
// Check whether the field that is passed on is a database field:
|
|
ScDocument* pDoc = pViewData ? &pViewData->GetDocument() : nullptr;
|
|
if ( pDoc )
|
|
{
|
|
ScDBCollection* pDBColl = pDoc->GetDBCollection();
|
|
const SCTAB nCurTab = pViewData->GetTabNo();
|
|
if ( pDBColl )
|
|
{
|
|
ScDBData* pDBData
|
|
= pDBColl->GetDBAtArea( nCurTab,
|
|
aSortData.nCol1, aSortData.nRow1,
|
|
aSortData.nCol2, aSortData.nRow2 );
|
|
if ( pDBData )
|
|
{
|
|
m_xBtnHeader->set_active(pDBData->HasHeader());
|
|
}
|
|
}
|
|
}
|
|
m_xBtnHeader->set_label(aStrColLabel);
|
|
|
|
Link<weld::Toggleable&,void> aLink = LINK(this, ScTabPageSortFields, SortDirHdl );
|
|
m_xBtnTopDown->connect_toggled( aLink );
|
|
m_xBtnLeftRight->connect_toggled( aLink );
|
|
m_xBtnHeader->connect_toggled( aLink );
|
|
|
|
const ScSortItem& rSortItem = GetItemSet().Get( nWhichSort );
|
|
|
|
pViewData = rSortItem.GetViewData();
|
|
OSL_ENSURE( pViewData, "ViewData not found!" );
|
|
|
|
nFieldArr.push_back( 0 );
|
|
|
|
// Create three sort key dialogs by default
|
|
for ( sal_uInt16 i=0; i<nSortKeyCount; i++ )
|
|
{
|
|
AddSortKey(i+1);
|
|
m_aSortWin.m_aSortKeyItems[i]->m_xLbSort->connect_changed(LINK(this, ScTabPageSortFields, SelectHdl));
|
|
}
|
|
}
|
|
|
|
std::unique_ptr<SfxTabPage> ScTabPageSortFields::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* pArgSet)
|
|
{
|
|
return std::make_unique<ScTabPageSortFields>(pPage, pController, *pArgSet);
|
|
}
|
|
|
|
void ScTabPageSortFields::Reset( const SfxItemSet* /* rArgSet */ )
|
|
{
|
|
m_xBtnHeader->set_active( aSortData.bHasHeader );
|
|
m_xBtnTopDown->set_active( aSortData.bByRow );
|
|
m_xBtnLeftRight->set_active( !aSortData.bByRow );
|
|
|
|
if (m_aSortWin.m_aSortKeyItems[0]->m_xLbSort->get_count() == 0)
|
|
FillFieldLists(0);
|
|
|
|
// ListBox selection:
|
|
if (!aSortData.maKeyState.empty() && aSortData.maKeyState[0].bDoSort)
|
|
{
|
|
// Make sure that the all sort keys are reset
|
|
for ( sal_uInt16 i=nSortKeyCount; i<aSortData.GetSortKeyCount(); i++ )
|
|
{
|
|
AddSortKey(i+1);
|
|
m_aSortWin.m_aSortKeyItems[i]->m_xLbSort->connect_changed( LINK( this,
|
|
ScTabPageSortFields, SelectHdl ) );
|
|
}
|
|
nSortKeyCount = aSortData.GetSortKeyCount();
|
|
FillFieldLists(0);
|
|
|
|
for ( sal_uInt16 i=0; i<nSortKeyCount; i++ )
|
|
{
|
|
if (aSortData.maKeyState[i].bDoSort )
|
|
{
|
|
m_aSortWin.m_aSortKeyItems[i]->m_xLbSort->set_active( GetFieldSelPos(
|
|
aSortData.maKeyState[i].nField ) );
|
|
(aSortData.maKeyState[i].bAscending)
|
|
? m_aSortWin.m_aSortKeyItems[i]->m_xBtnUp->set_active(true)
|
|
: m_aSortWin.m_aSortKeyItems[i]->m_xBtnDown->set_active(true);
|
|
}
|
|
else
|
|
{
|
|
m_aSortWin.m_aSortKeyItems[i]->m_xLbSort->set_active(0); // Select none
|
|
m_aSortWin.m_aSortKeyItems[i]->m_xBtnUp->set_active(true);
|
|
}
|
|
}
|
|
|
|
// Enable or disable field depending on preceding Listbox selection
|
|
m_aSortWin.m_aSortKeyItems[0]->EnableField();
|
|
for ( sal_uInt16 i=1; i<nSortKeyCount; i++ )
|
|
if ( m_aSortWin.m_aSortKeyItems[i - 1]->m_xLbSort->get_active() == 0 )
|
|
m_aSortWin.m_aSortKeyItems[i]->DisableField();
|
|
else
|
|
m_aSortWin.m_aSortKeyItems[i]->EnableField();
|
|
}
|
|
else
|
|
{
|
|
SCCOL nCol = pViewData->GetCurX();
|
|
|
|
if( nCol < aSortData.nCol1 )
|
|
nCol = aSortData.nCol1;
|
|
else if( nCol > aSortData.nCol2 )
|
|
nCol = aSortData.nCol2;
|
|
|
|
sal_uInt16 nSort1Pos = nCol - aSortData.nCol1+1;
|
|
|
|
m_aSortWin.m_aSortKeyItems[0]->m_xLbSort->set_active(nSort1Pos);
|
|
for ( sal_uInt16 i=1; i<nSortKeyCount; i++ )
|
|
m_aSortWin.m_aSortKeyItems[i]->m_xLbSort->set_active(0);
|
|
|
|
for ( sal_uInt16 i=0; i<nSortKeyCount; i++ )
|
|
m_aSortWin.m_aSortKeyItems[i]->m_xBtnUp->set_active(true);
|
|
|
|
m_aSortWin.m_aSortKeyItems[0]->EnableField();
|
|
m_aSortWin.m_aSortKeyItems[1]->EnableField();
|
|
for ( sal_uInt16 i=2; i<nSortKeyCount; i++ )
|
|
m_aSortWin.m_aSortKeyItems[i]->DisableField();
|
|
}
|
|
|
|
// Make sure that there is always a last undefined sort key
|
|
if (m_aSortWin.m_aSortKeyItems[nSortKeyCount - 1]->m_xLbSort->get_active() > 0)
|
|
SetLastSortKey( nSortKeyCount );
|
|
}
|
|
|
|
bool ScTabPageSortFields::FillItemSet( SfxItemSet* rArgSet )
|
|
{
|
|
ScSortParam aNewSortData = aSortData;
|
|
|
|
const SfxItemSet* pExample = GetDialogExampleSet();
|
|
if (pExample)
|
|
{
|
|
if (const ScSortItem* pItem = pExample->GetItemIfSet(nWhichSort))
|
|
{
|
|
ScSortParam aTempData = pItem->GetSortData();
|
|
aTempData.maKeyState = aNewSortData.maKeyState;
|
|
aNewSortData = aTempData;
|
|
}
|
|
}
|
|
aNewSortData.bByRow = m_xBtnTopDown->get_active();
|
|
aNewSortData.bHasHeader = m_xBtnHeader->get_active();
|
|
|
|
std::vector<sal_Int32> nSortPos;
|
|
|
|
for ( sal_uInt16 i=0; i<nSortKeyCount; i++ )
|
|
{
|
|
nSortPos.push_back(m_aSortWin.m_aSortKeyItems[i]->m_xLbSort->get_active());
|
|
if (nSortPos[i] == -1) nSortPos[i] = 0;
|
|
}
|
|
|
|
if( nSortKeyCount >= aNewSortData.GetSortKeyCount() )
|
|
aNewSortData.maKeyState.resize(nSortKeyCount);
|
|
|
|
if ( nSortPos[0] > 0 )
|
|
{
|
|
for ( sal_uInt16 i=0; i<nSortKeyCount; i++ )
|
|
{
|
|
aNewSortData.maKeyState[i].bDoSort = (nSortPos[i] > 0);
|
|
aNewSortData.maKeyState[i].nField = nFieldArr[nSortPos[i]];
|
|
aNewSortData.maKeyState[i].bAscending = m_aSortWin.m_aSortKeyItems[i]->m_xBtnUp->get_active();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for ( sal_uInt16 i=0; i<nSortKeyCount; i++ )
|
|
aNewSortData.maKeyState[i].bDoSort = false;
|
|
}
|
|
|
|
rArgSet->Put( ScSortItem( SCITEM_SORTDATA, nullptr, &aNewSortData ) );
|
|
|
|
return true;
|
|
}
|
|
|
|
// for data exchange without dialogue detour:
|
|
void ScTabPageSortFields::ActivatePage( const SfxItemSet& rSet )
|
|
{
|
|
// Refresh local copy with shared data
|
|
aSortData = rSet.Get( SCITEM_SORTDATA ).GetSortData();
|
|
|
|
m_xBtnHeader->set_active( aSortData.bHasHeader );
|
|
m_xBtnTopDown->set_active( aSortData.bByRow );
|
|
m_xBtnLeftRight->set_active( !aSortData.bByRow );
|
|
}
|
|
|
|
DeactivateRC ScTabPageSortFields::DeactivatePage( SfxItemSet* pSetP )
|
|
{
|
|
if ( pSetP )
|
|
FillItemSet( pSetP );
|
|
|
|
return DeactivateRC::LeavePage;
|
|
}
|
|
|
|
void ScTabPageSortFields::FillFieldLists( sal_uInt16 nStartField )
|
|
{
|
|
if ( !pViewData )
|
|
return;
|
|
|
|
ScDocument& rDoc = pViewData->GetDocument();
|
|
|
|
for (sal_uInt16 j = nStartField; j < nSortKeyCount; ++j)
|
|
{
|
|
m_aSortWin.m_aSortKeyItems[j]->m_xLabel->set_label(aSortData.bByRow ? aStrColumn : aStrRow);
|
|
m_aSortWin.m_aSortKeyItems[j]->m_xLbSort->clear();
|
|
m_aSortWin.m_aSortKeyItems[j]->m_xLbSort->freeze();
|
|
m_aSortWin.m_aSortKeyItems[j]->m_xLbSort->append_text(aStrUndefined);
|
|
}
|
|
|
|
SCCOL nFirstSortCol = aSortData.nCol1;
|
|
SCROW nFirstSortRow = aSortData.nRow1;
|
|
SCTAB nTab = pViewData->GetTabNo();
|
|
sal_uInt16 i = 1;
|
|
nFieldArr.clear();
|
|
nFieldArr.push_back(0);
|
|
|
|
if ( aSortData.bByRow )
|
|
{
|
|
OUString aFieldName;
|
|
SCCOL nMaxCol = rDoc.ClampToAllocatedColumns(nTab, aSortData.nCol2);
|
|
SCCOL col;
|
|
|
|
for ( col=nFirstSortCol; col<=nMaxCol && i<SC_MAXFIELDS(rDoc.GetSheetLimits()); col++ )
|
|
{
|
|
aFieldName = rDoc.GetString(col, nFirstSortRow, nTab);
|
|
if ( !aSortData.bHasHeader || aFieldName.isEmpty() )
|
|
aFieldName = ScColToAlpha( col );
|
|
nFieldArr.push_back( col );
|
|
|
|
for ( sal_uInt16 j=nStartField; j<nSortKeyCount; j++ )
|
|
m_aSortWin.m_aSortKeyItems[j]->m_xLbSort->insert_text(i, aFieldName);
|
|
|
|
i++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
OUString aFieldName;
|
|
SCROW nMaxRow = aSortData.nRow2;
|
|
SCROW row;
|
|
|
|
for ( row=nFirstSortRow; row<=nMaxRow && i<SC_MAXFIELDS(rDoc.GetSheetLimits()); row++ )
|
|
{
|
|
aFieldName = rDoc.GetString(nFirstSortCol, row, nTab);
|
|
if ( !aSortData.bHasHeader || aFieldName.isEmpty() )
|
|
aFieldName = OUString::number( row+1);
|
|
nFieldArr.push_back( row );
|
|
|
|
for ( sal_uInt16 j=nStartField; j<nSortKeyCount; j++ )
|
|
m_aSortWin.m_aSortKeyItems[j]->m_xLbSort->insert_text(i, aFieldName);
|
|
|
|
i++;
|
|
}
|
|
}
|
|
|
|
for (sal_uInt16 j=nStartField; j < nSortKeyCount; ++j)
|
|
{
|
|
m_aSortWin.m_aSortKeyItems[j]->m_xLbSort->thaw();
|
|
}
|
|
|
|
nFieldCount = i;
|
|
}
|
|
|
|
sal_uInt16 ScTabPageSortFields::GetFieldSelPos( SCCOLROW nField )
|
|
{
|
|
sal_uInt16 nFieldPos = 0;
|
|
bool bFound = false;
|
|
|
|
for ( sal_uInt16 n=1; n<nFieldCount && !bFound; n++ )
|
|
{
|
|
if ( nFieldArr[n] == nField )
|
|
{
|
|
nFieldPos = n;
|
|
bFound = true;
|
|
}
|
|
}
|
|
|
|
return nFieldPos;
|
|
}
|
|
|
|
void ScTabPageSortFields::SetLastSortKey( sal_uInt16 nItem )
|
|
{
|
|
// Extend local SortParam copy
|
|
const ScSortKeyState atempKeyState = { 0, false, true, ScColorSortMode::None, Color() };
|
|
aSortData.maKeyState.push_back( atempKeyState );
|
|
|
|
// Add Sort Key Item
|
|
++nSortKeyCount;
|
|
AddSortKey( nSortKeyCount );
|
|
m_aSortWin.m_aSortKeyItems[nItem]->m_xLbSort->connect_changed(
|
|
LINK( this, ScTabPageSortFields, SelectHdl ) );
|
|
|
|
FillFieldLists( nItem );
|
|
|
|
// Set Status
|
|
m_aSortWin.m_aSortKeyItems[nItem]->m_xBtnUp->set_active(true);
|
|
m_aSortWin.m_aSortKeyItems[nItem]->m_xLbSort->set_active(0);
|
|
}
|
|
|
|
// Handler:
|
|
|
|
IMPL_LINK_NOARG(ScTabPageSortFields, SortDirHdl, weld::Toggleable&, void)
|
|
{
|
|
if ( (m_xBtnTopDown->get_active() != aSortData.bByRow) || (m_xBtnHeader->get_active() != aSortData.bHasHeader))
|
|
{
|
|
if (m_xBtnTopDown->get_active())
|
|
m_xBtnHeader->set_label(aStrColLabel);
|
|
else
|
|
m_xBtnHeader->set_label(aStrRowLabel);
|
|
|
|
aSortData.bByRow = m_xBtnTopDown->get_active();
|
|
aSortData.bHasHeader = m_xBtnHeader->get_active();
|
|
|
|
// remember selection
|
|
std::vector<sal_uInt16> nCurSel;
|
|
for ( sal_uInt16 i=0; i<nSortKeyCount; i++ )
|
|
nCurSel.push_back( m_aSortWin.m_aSortKeyItems[i]->m_xLbSort->get_active() );
|
|
|
|
FillFieldLists(0);
|
|
|
|
for ( sal_uInt16 i=0; i<nSortKeyCount; i++ )
|
|
m_aSortWin.m_aSortKeyItems[i]->m_xLbSort->set_active(nCurSel[i]);
|
|
}
|
|
}
|
|
|
|
IMPL_LINK( ScTabPageSortFields, SelectHdl, weld::ComboBox&, rLb, void )
|
|
{
|
|
OUString aSelEntry = rLb.get_active_text();
|
|
ScSortKeyItems::iterator pIter;
|
|
|
|
// If last listbox is enabled add one item
|
|
if (m_aSortWin.m_aSortKeyItems.back()->m_xLbSort.get() == &rLb)
|
|
{
|
|
if ( aSelEntry != aStrUndefined )
|
|
{
|
|
SetLastSortKey( nSortKeyCount );
|
|
return;
|
|
}
|
|
}
|
|
|
|
// Find selected listbox
|
|
pIter = std::find_if(m_aSortWin.m_aSortKeyItems.begin(), m_aSortWin.m_aSortKeyItems.end(),
|
|
[&rLb](const ScSortKeyItems::value_type& rItem) { return rItem->m_xLbSort.get() == &rLb; });
|
|
|
|
if (pIter == m_aSortWin.m_aSortKeyItems.end())
|
|
return;
|
|
|
|
// If not selecting the last Listbox, modify the succeeding ones
|
|
++pIter;
|
|
if ( std::distance(m_aSortWin.m_aSortKeyItems.begin(), pIter) >= nSortKeyCount )
|
|
return;
|
|
|
|
if ( aSelEntry == aStrUndefined )
|
|
{
|
|
for ( ; pIter != m_aSortWin.m_aSortKeyItems.end(); ++pIter )
|
|
{
|
|
(*pIter)->m_xLbSort->set_active(0);
|
|
|
|
(*pIter)->DisableField();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
(*pIter)->EnableField();
|
|
}
|
|
}
|
|
|
|
IMPL_LINK_NOARG(ScTabPageSortFields, ScrollToEndHdl, Timer*, void)
|
|
{
|
|
m_xScrolledWindow->vadjustment_set_value(m_xScrolledWindow->vadjustment_get_upper());
|
|
}
|
|
|
|
void ScTabPageSortFields::AddSortKey( sal_uInt16 nItem )
|
|
{
|
|
m_aSortWin.AddSortKey(nItem);
|
|
m_aIdle.Start();
|
|
}
|
|
|
|
// Sort option Tab Page:
|
|
|
|
ScTabPageSortOptions::ScTabPageSortOptions(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rArgSet)
|
|
: SfxTabPage(pPage, pController, u"modules/scalc/ui/sortoptionspage.ui"_ustr, u"SortOptionsPage"_ustr, &rArgSet)
|
|
, aStrUndefined(ScResId(SCSTR_UNDEFINED))
|
|
, aStrCommentsRowLabel(ScResId(SCSTR_NOTES_ROW_LABEL))
|
|
, aStrCommentsColLabel(ScResId(SCSTR_NOTES_COL_LABEL))
|
|
, aStrImgRowLabel(ScResId(SCSTR_IMAGES_ROW_LABEL))
|
|
, aStrImgColLabel(ScResId(SCSTR_IMAGES_COL_LABEL))
|
|
, nWhichSort(rArgSet.GetPool()->GetWhichIDFromSlotID(SID_SORT))
|
|
, aSortData(rArgSet.Get(nWhichSort).GetSortData())
|
|
, pViewData(nullptr)
|
|
, pDoc(nullptr)
|
|
, m_xBtnCase(m_xBuilder->weld_check_button(u"case"_ustr))
|
|
, m_xBtnFormats(m_xBuilder->weld_check_button(u"formats"_ustr))
|
|
, m_xBtnNaturalSort(m_xBuilder->weld_check_button(u"naturalsort"_ustr))
|
|
, m_xBtnCopyResult(m_xBuilder->weld_check_button(u"copyresult"_ustr))
|
|
, m_xLbOutPos(m_xBuilder->weld_combo_box(u"outarealb"_ustr))
|
|
, m_xEdOutPos(m_xBuilder->weld_entry(u"outareaed"_ustr))
|
|
, m_xBtnSortUser(m_xBuilder->weld_check_button(u"sortuser"_ustr))
|
|
, m_xLbSortUser(m_xBuilder->weld_combo_box(u"sortuserlb"_ustr))
|
|
, m_xLbLanguage(new SvxLanguageBox(m_xBuilder->weld_combo_box(u"language"_ustr)))
|
|
, m_xFtAlgorithm(m_xBuilder->weld_label(u"algorithmft"_ustr))
|
|
, m_xLbAlgorithm(m_xBuilder->weld_combo_box(u"algorithmlb"_ustr))
|
|
, m_xBtnIncComments(m_xBuilder->weld_check_button(u"includenotes"_ustr))
|
|
, m_xBtnIncImages(m_xBuilder->weld_check_button(u"includeimages"_ustr))
|
|
{
|
|
m_xLbSortUser->set_size_request(m_xLbSortUser->get_approximate_digit_width() * 50, -1);
|
|
m_xLbSortUser->set_accessible_description(ScResId(STR_A11Y_DESC_SORTUSER));
|
|
Init();
|
|
SetExchangeSupport();
|
|
}
|
|
|
|
void ScTabPageSortOptions::Init()
|
|
{
|
|
// CollatorResource has user-visible names for sort algorithms
|
|
m_xColRes.reset(new CollatorResource);
|
|
|
|
//! use CollatorWrapper from document?
|
|
m_oColWrap.emplace(comphelper::getProcessComponentContext());
|
|
|
|
const ScSortItem& rSortItem = GetItemSet().Get( nWhichSort );
|
|
|
|
m_xLbOutPos->connect_changed( LINK( this, ScTabPageSortOptions, SelOutPosHdl ) );
|
|
m_xBtnCopyResult->connect_toggled( LINK( this, ScTabPageSortOptions, EnableHdl ) );
|
|
m_xBtnSortUser->connect_toggled( LINK( this, ScTabPageSortOptions, EnableHdl ) );
|
|
m_xLbLanguage->connect_changed( LINK( this, ScTabPageSortOptions, FillAlgorHdl ) );
|
|
|
|
pViewData = rSortItem.GetViewData();
|
|
pDoc = pViewData ? &pViewData->GetDocument() : nullptr;
|
|
|
|
OSL_ENSURE( pViewData, "ViewData not found! :-/" );
|
|
|
|
if ( pViewData && pDoc )
|
|
{
|
|
const formula::FormulaGrammar::AddressConvention eConv = pDoc->GetAddressConvention();
|
|
|
|
m_xLbOutPos->clear();
|
|
m_xLbOutPos->append_text(aStrUndefined);
|
|
m_xLbOutPos->set_sensitive(false);
|
|
|
|
ScAreaNameIterator aIter( *pDoc );
|
|
OUString aName;
|
|
ScRange aRange;
|
|
while ( aIter.Next( aName, aRange ) )
|
|
{
|
|
OUString aRefStr(aRange.aStart.Format(ScRefFlags::ADDR_ABS_3D, pDoc, eConv));
|
|
m_xLbOutPos->append(aRefStr, aName);
|
|
}
|
|
|
|
m_xLbOutPos->set_active(0);
|
|
m_xEdOutPos->set_text(OUString());
|
|
}
|
|
|
|
m_xBtnIncComments->set_label(aStrCommentsColLabel);
|
|
m_xBtnIncImages->set_label(aStrImgColLabel);
|
|
|
|
FillUserSortListBox();
|
|
|
|
// get available languages
|
|
|
|
m_xLbLanguage->SetLanguageList( SvxLanguageListFlags::ALL | SvxLanguageListFlags::ONLY_KNOWN, false );
|
|
m_xLbLanguage->InsertLanguage( LANGUAGE_SYSTEM );
|
|
}
|
|
|
|
std::unique_ptr<SfxTabPage> ScTabPageSortOptions::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rArgSet)
|
|
{
|
|
return std::make_unique<ScTabPageSortOptions>(pPage, pController, *rArgSet);
|
|
}
|
|
|
|
void ScTabPageSortOptions::Reset( const SfxItemSet* /* rArgSet */ )
|
|
{
|
|
if ( aSortData.bUserDef )
|
|
{
|
|
m_xBtnSortUser->set_active(true);
|
|
m_xLbSortUser->set_sensitive(true);
|
|
m_xLbSortUser->set_active(aSortData.nUserIndex);
|
|
}
|
|
else
|
|
{
|
|
m_xBtnSortUser->set_active(false);
|
|
m_xLbSortUser->set_sensitive(false);
|
|
m_xLbSortUser->set_active(0);
|
|
}
|
|
|
|
m_xBtnCase->set_active( aSortData.bCaseSens );
|
|
m_xBtnFormats->set_active( aSortData.aDataAreaExtras.mbCellFormats );
|
|
m_xBtnNaturalSort->set_active( aSortData.bNaturalSort );
|
|
m_xBtnIncComments->set_active( aSortData.aDataAreaExtras.mbCellNotes );
|
|
m_xBtnIncImages->set_active( aSortData.aDataAreaExtras.mbCellDrawObjects );
|
|
|
|
LanguageType eLang = LanguageTag::convertToLanguageType( aSortData.aCollatorLocale, false);
|
|
if ( eLang == LANGUAGE_DONTKNOW )
|
|
eLang = LANGUAGE_SYSTEM;
|
|
m_xLbLanguage->set_active_id(eLang);
|
|
FillAlgor(); // get algorithms, select default
|
|
if ( !aSortData.aCollatorAlgorithm.isEmpty() )
|
|
m_xLbAlgorithm->set_active_text(m_xColRes->GetTranslation(aSortData.aCollatorAlgorithm));
|
|
|
|
if ( pDoc && !aSortData.bInplace )
|
|
{
|
|
ScRefFlags nFormat = (aSortData.nDestTab != pViewData->GetTabNo())
|
|
? ScRefFlags::RANGE_ABS_3D
|
|
: ScRefFlags::RANGE_ABS;
|
|
|
|
theOutPos.Set( aSortData.nDestCol,
|
|
aSortData.nDestRow,
|
|
aSortData.nDestTab );
|
|
|
|
OUString aStr(theOutPos.Format(nFormat, pDoc, pDoc->GetAddressConvention()));
|
|
m_xBtnCopyResult->set_active(true);
|
|
m_xLbOutPos->set_sensitive(true);
|
|
m_xEdOutPos->set_sensitive(true);
|
|
m_xEdOutPos->set_text( aStr );
|
|
EdOutPosModHdl();
|
|
m_xEdOutPos->grab_focus();
|
|
m_xEdOutPos->select_region(0, -1);
|
|
}
|
|
else
|
|
{
|
|
m_xBtnCopyResult->set_active( false );
|
|
m_xLbOutPos->set_sensitive(false);
|
|
m_xEdOutPos->set_sensitive(false);
|
|
m_xEdOutPos->set_text( OUString() );
|
|
}
|
|
}
|
|
|
|
bool ScTabPageSortOptions::FillItemSet( SfxItemSet* rArgSet )
|
|
{
|
|
// Create local copy of ScParam
|
|
ScSortParam aNewSortData = aSortData;
|
|
|
|
const SfxItemSet* pExample = GetDialogExampleSet();
|
|
if (pExample)
|
|
{
|
|
if (const ScSortItem* pSortItem = pExample->GetItemIfSet(nWhichSort))
|
|
aNewSortData = pSortItem->GetSortData();
|
|
}
|
|
aNewSortData.bCaseSens = m_xBtnCase->get_active();
|
|
aNewSortData.bNaturalSort = m_xBtnNaturalSort->get_active();
|
|
aNewSortData.aDataAreaExtras.mbCellNotes = m_xBtnIncComments->get_active();
|
|
aNewSortData.aDataAreaExtras.mbCellDrawObjects = m_xBtnIncImages->get_active();
|
|
aNewSortData.aDataAreaExtras.mbCellFormats = m_xBtnFormats->get_active();
|
|
aNewSortData.bInplace = !m_xBtnCopyResult->get_active();
|
|
aNewSortData.nDestCol = theOutPos.Col();
|
|
aNewSortData.nDestRow = theOutPos.Row();
|
|
aNewSortData.nDestTab = theOutPos.Tab();
|
|
aNewSortData.bUserDef = m_xBtnSortUser->get_active();
|
|
aNewSortData.nUserIndex = (m_xBtnSortUser->get_active())
|
|
? m_xLbSortUser->get_active()
|
|
: 0;
|
|
|
|
// get locale
|
|
LanguageType eLang = m_xLbLanguage->get_active_id();
|
|
aNewSortData.aCollatorLocale = LanguageTag::convertToLocale( eLang, false);
|
|
|
|
// get algorithm
|
|
OUString sAlg;
|
|
if ( eLang != LANGUAGE_SYSTEM )
|
|
{
|
|
uno::Sequence<OUString> aAlgos = m_oColWrap->listCollatorAlgorithms(
|
|
aNewSortData.aCollatorLocale );
|
|
const int nSel = m_xLbAlgorithm->get_active();
|
|
if ( nSel < aAlgos.getLength() )
|
|
sAlg = aAlgos[nSel];
|
|
}
|
|
aNewSortData.aCollatorAlgorithm = sAlg;
|
|
|
|
rArgSet->Put( ScSortItem( SCITEM_SORTDATA, &aNewSortData ) );
|
|
|
|
return true;
|
|
}
|
|
|
|
// for data exchange without dialogue detour:
|
|
void ScTabPageSortOptions::ActivatePage( const SfxItemSet& rSet )
|
|
{
|
|
// Refresh local copy with shared data
|
|
aSortData = rSet.Get( SCITEM_SORTDATA ).GetSortData();
|
|
ScSortDlg* pDlg = static_cast<ScSortDlg*>(GetDialogController());
|
|
if (!pDlg)
|
|
return;
|
|
|
|
if (aSortData.bByRow)
|
|
{
|
|
m_xBtnIncComments->set_label(aStrCommentsRowLabel);
|
|
m_xBtnIncImages->set_label(aStrImgRowLabel);
|
|
}
|
|
else
|
|
{
|
|
m_xBtnIncComments->set_label(aStrCommentsColLabel);
|
|
m_xBtnIncImages->set_label(aStrImgColLabel);
|
|
}
|
|
}
|
|
|
|
DeactivateRC ScTabPageSortOptions::DeactivatePage( SfxItemSet* pSetP )
|
|
{
|
|
bool bPosInputOk = true;
|
|
|
|
if ( m_xBtnCopyResult->get_active() )
|
|
{
|
|
OUString thePosStr = m_xEdOutPos->get_text();
|
|
ScAddress thePos;
|
|
sal_Int32 nColonPos = thePosStr.indexOf( ':' );
|
|
|
|
if ( -1 != nColonPos )
|
|
thePosStr = thePosStr.copy( 0, nColonPos );
|
|
|
|
if ( pViewData )
|
|
{
|
|
// visible table is default for input without table
|
|
// must be changed to GetRefTabNo when sorting has RefInput!
|
|
thePos.SetTab( pViewData->GetTabNo() );
|
|
}
|
|
|
|
ScRefFlags nResult = thePos.Parse( thePosStr, *pDoc, pDoc->GetAddressConvention() );
|
|
|
|
bPosInputOk = (nResult & ScRefFlags::VALID) == ScRefFlags::VALID;
|
|
|
|
if ( !bPosInputOk )
|
|
{
|
|
std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(GetFrameWeld(),
|
|
VclMessageType::Warning, VclButtonsType::Ok,
|
|
ScResId(STR_INVALID_TABREF)));
|
|
xBox->run();
|
|
m_xEdOutPos->grab_focus();
|
|
m_xEdOutPos->select_region(0, -1);
|
|
theOutPos.Set(0,0,0);
|
|
}
|
|
else
|
|
{
|
|
m_xEdOutPos->set_text(thePosStr);
|
|
theOutPos = thePos;
|
|
}
|
|
}
|
|
|
|
if ( pSetP && bPosInputOk )
|
|
FillItemSet( pSetP );
|
|
|
|
return bPosInputOk ? DeactivateRC::LeavePage : DeactivateRC::KeepPage;
|
|
}
|
|
|
|
void ScTabPageSortOptions::FillUserSortListBox()
|
|
{
|
|
ScUserList& rUserLists = ScGlobal::GetUserList();
|
|
|
|
m_xLbSortUser->clear();
|
|
size_t nCount = rUserLists.size();
|
|
for (size_t i=0; i<nCount; ++i)
|
|
m_xLbSortUser->append_text(rUserLists[i].GetString());
|
|
}
|
|
|
|
// Handler:
|
|
|
|
IMPL_LINK( ScTabPageSortOptions, EnableHdl, weld::Toggleable&, rButton, void )
|
|
{
|
|
if (&rButton == m_xBtnCopyResult.get())
|
|
{
|
|
if (rButton.get_active())
|
|
{
|
|
m_xLbOutPos->set_sensitive(true);
|
|
m_xEdOutPos->set_sensitive(true);
|
|
m_xEdOutPos->grab_focus();
|
|
}
|
|
else
|
|
{
|
|
m_xLbOutPos->set_sensitive(false);
|
|
m_xEdOutPos->set_sensitive(false);
|
|
}
|
|
}
|
|
else if (&rButton == m_xBtnSortUser.get())
|
|
{
|
|
if (rButton.get_active())
|
|
{
|
|
m_xLbSortUser->set_sensitive(true);
|
|
m_xLbSortUser->grab_focus();
|
|
}
|
|
else
|
|
m_xLbSortUser->set_sensitive(false);
|
|
}
|
|
}
|
|
|
|
IMPL_LINK(ScTabPageSortOptions, SelOutPosHdl, weld::ComboBox&, rLb, void)
|
|
{
|
|
if (&rLb == m_xLbOutPos.get())
|
|
{
|
|
OUString aString;
|
|
const int nSelPos = m_xLbOutPos->get_active();
|
|
|
|
if (nSelPos > 0)
|
|
aString = m_xLbOutPos->get_id(nSelPos);
|
|
|
|
m_xEdOutPos->set_text(aString);
|
|
}
|
|
}
|
|
|
|
void ScTabPageSortOptions::EdOutPosModHdl()
|
|
{
|
|
OUString theCurPosStr = m_xEdOutPos->get_text();
|
|
ScRefFlags nResult = ScAddress().Parse( theCurPosStr, *pDoc, pDoc->GetAddressConvention() );
|
|
|
|
if ( (nResult & ScRefFlags::VALID) != ScRefFlags::VALID )
|
|
return;
|
|
|
|
bool bFound = false;
|
|
sal_Int32 i = 0;
|
|
const int nCount = m_xLbOutPos->get_count();
|
|
|
|
for ( i=2; i<nCount && !bFound; i++ )
|
|
{
|
|
OUString aStr = m_xLbOutPos->get_id(i);
|
|
bFound = (theCurPosStr == aStr);
|
|
}
|
|
|
|
if ( bFound )
|
|
m_xLbOutPos->set_active(--i);
|
|
else
|
|
m_xLbOutPos->set_active(0);
|
|
}
|
|
|
|
void ScTabPageSortOptions::FillAlgor()
|
|
{
|
|
tools::Long nCount = 0;
|
|
|
|
m_xLbAlgorithm->freeze();
|
|
m_xLbAlgorithm->clear();
|
|
|
|
LanguageType eLang = m_xLbLanguage->get_active_id();
|
|
if ( eLang == LANGUAGE_SYSTEM )
|
|
{
|
|
// for LANGUAGE_SYSTEM no algorithm can be selected because
|
|
// it wouldn't necessarily exist for other languages
|
|
// -> leave list box empty if LANGUAGE_SYSTEM is selected
|
|
m_xFtAlgorithm->set_sensitive( false ); // nothing to select
|
|
m_xLbAlgorithm->set_sensitive( false ); // nothing to select
|
|
}
|
|
else
|
|
{
|
|
lang::Locale aLocale( LanguageTag::convertToLocale( eLang ));
|
|
const uno::Sequence<OUString> aAlgos = m_oColWrap->listCollatorAlgorithms( aLocale );
|
|
|
|
nCount = aAlgos.getLength();
|
|
for (const OUString& sAlg : aAlgos)
|
|
{
|
|
OUString sUser = m_xColRes->GetTranslation( sAlg );
|
|
m_xLbAlgorithm->append_text(sUser);
|
|
}
|
|
}
|
|
|
|
m_xLbAlgorithm->thaw();
|
|
|
|
m_xLbAlgorithm->set_active(nCount ? 0 : -1); // first entry is default
|
|
m_xFtAlgorithm->set_sensitive(nCount > 1); // enable only if there is a choice
|
|
m_xLbAlgorithm->set_sensitive(nCount > 1); // enable only if there is a choice
|
|
}
|
|
|
|
IMPL_LINK_NOARG(ScTabPageSortOptions, FillAlgorHdl, weld::ComboBox&, void)
|
|
{
|
|
FillAlgor();
|
|
}
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|