LCOV - code coverage report
Current view: top level - libreoffice/sc/source/ui/dbgui - tpsort.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 0 473 0.0 %
Date: 2012-12-17 Functions: 0 37 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       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/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      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 .
      18             :  */
      19             : 
      20             : 
      21             : #undef SC_DLLIMPLEMENTATION
      22             : 
      23             : #include <vcl/msgbox.hxx>
      24             : #include <i18npool/languagetag.hxx>
      25             : #include <svtools/collatorres.hxx>
      26             : #include <unotools/collatorwrapper.hxx>
      27             : #include <unotools/localedatawrapper.hxx>
      28             : #include <comphelper/processfactory.hxx>
      29             : 
      30             : #include "scitems.hxx"
      31             : #include "uiitems.hxx"
      32             : #include "viewdata.hxx"
      33             : #include "document.hxx"
      34             : #include "global.hxx"
      35             : #include "globalnames.hxx"
      36             : #include "dbdata.hxx"
      37             : #include "userlist.hxx"
      38             : #include "rangeutl.hxx"
      39             : #include "scresid.hxx"
      40             : #include "sc.hrc"       // -> Slot IDs
      41             : #include "globstr.hrc"
      42             : 
      43             : #include "sortkeydlg.hxx"
      44             : 
      45             : #include "sortdlg.hxx"
      46             : #include "sortdlg.hrc"
      47             : 
      48             : #define _TPSORT_CXX
      49             : #include "tpsort.hxx"
      50             : #undef _TPSORT_CXX
      51             : 
      52             : using namespace com::sun::star;
      53             : 
      54             : // -----------------------------------------------------------------------
      55             : 
      56             : /*
      57             :  * Since the settings on the second Tab Page (Options) effects
      58             :  * the first Tab Page, there must be a way for it to communicate with the
      59             :  * other Page.
      60             :  *
      61             :  * At the moment this problem is solved through using two data members of the
      62             :  * Tab Pages. If a page is enabled / disabled, it compares this data member
      63             :  * with its own state (-> Activate() / Deactivate()).
      64             :  *
      65             :  * In the meantime the class SfxTabPage offers the following method:
      66             :  *
      67             :  * virtual sal_Bool HasExchangeSupport() const; -> return sal_True;
      68             :  * virtual void ActivatePage(const SfxItemSet &);
      69             :  * virtual int  DeactivatePage(SfxItemSet * = 0);
      70             :  *
      71             :  * This still needs to be changed!
      72             :  */
      73             : 
      74             : //========================================================================
      75             : //========================================================================
      76             : // Sort Criteria Tab page
      77             : 
      78           0 : ScTabPageSortFields::ScTabPageSortFields(Window* pParent,
      79             :                                           const SfxItemSet& rArgSet)
      80             :     : SfxTabPage(pParent, "SortCriteriaPage",
      81             :         "modules/scalc/ui/sortcriteriapage.ui", rArgSet)
      82             :     ,
      83             :         //
      84             :         aStrUndefined   ( SC_RESSTR( SCSTR_UNDEFINED ) ),
      85             :         aStrColumn      ( SC_RESSTR( SCSTR_COLUMN ) ),
      86             :         aStrRow         ( SC_RESSTR( SCSTR_ROW ) ),
      87             :         //
      88           0 :         nWhichSort      ( rArgSet.GetPool()->GetWhich( SID_SORT ) ),
      89           0 :         pDlg            ( (ScSortDlg*)(GetParentDialog()) ),
      90             :         pViewData       ( NULL ),
      91             :         aSortData       ( ((const ScSortItem&)
      92           0 :                            rArgSet.Get( nWhichSort )).
      93           0 :                                 GetSortData() ),
      94             :         nFieldCount     ( 0 ),
      95             :         nSortKeyCount   ( DEFSORT ),
      96             :         bHasHeader      ( false ),
      97             :         bSortByRows     ( false ),
      98           0 :         maSortKeyCtrl   ( this, maSortKeyItems )
      99             : {
     100           0 :     Init();
     101           0 :     SetExchangeSupport();
     102           0 : }
     103             : 
     104           0 : void ScTabPageSortFields::SetPosSizePixel(const Point& rAllocPos, const Size& rAllocation)
     105             : {
     106           0 :     SfxTabPage::SetPosSizePixel(rAllocPos, rAllocation);
     107           0 :     maSortKeyCtrl.setScrollRange();
     108           0 : }
     109             : 
     110           0 : void ScTabPageSortFields::SetSizePixel(const Size& rAllocation)
     111             : {
     112           0 :     SfxTabPage::SetSizePixel(rAllocation);
     113           0 :     maSortKeyCtrl.setScrollRange();
     114           0 : }
     115             : 
     116           0 : void ScTabPageSortFields::SetPosPixel(const Point& rAllocPos)
     117             : {
     118           0 :     SfxTabPage::SetPosPixel(rAllocPos);
     119           0 :     maSortKeyCtrl.setScrollRange();
     120           0 : }
     121             : 
     122             : // -----------------------------------------------------------------------
     123             : 
     124           0 : ScTabPageSortFields::~ScTabPageSortFields()
     125             : {
     126           0 : }
     127             : 
     128             : // -----------------------------------------------------------------------
     129             : 
     130           0 : void ScTabPageSortFields::Init()
     131             : {
     132             :     const ScSortItem& rSortItem = (const ScSortItem&)
     133           0 :                                   GetItemSet().Get( nWhichSort );
     134             : 
     135           0 :     pViewData = rSortItem.GetViewData();
     136             :     OSL_ENSURE( pViewData, "ViewData not found!" );
     137             : 
     138           0 :     nFieldArr.push_back( 0 );
     139           0 :     nFirstCol = 0;
     140           0 :     nFirstRow = 0;
     141             : 
     142             :     // Create three sort key dialogs by default
     143           0 :     for ( sal_uInt16 i=0; i<nSortKeyCount; i++ )
     144             :     {
     145           0 :         maSortKeyCtrl.AddSortKey(i+1);
     146           0 :         maSortKeyItems[i].m_pLbSort->SetSelectHdl( LINK( this, ScTabPageSortFields, SelectHdl ) );
     147             :     }
     148           0 : }
     149             : 
     150             : // -----------------------------------------------------------------------
     151             : 
     152           0 : SfxTabPage* ScTabPageSortFields::Create( Window*    pParent,
     153             :                                          const SfxItemSet&  rArgSet )
     154             : {
     155           0 :     return ( new ScTabPageSortFields( pParent, rArgSet ) );
     156             : }
     157             : 
     158             : // -----------------------------------------------------------------------
     159             : 
     160           0 : void ScTabPageSortFields::Reset( const SfxItemSet& /* rArgSet */ )
     161             : {
     162           0 :     bSortByRows = aSortData.bByRow;
     163           0 :     bHasHeader  = aSortData.bHasHeader;
     164             : 
     165           0 :     if ( maSortKeyItems[0].m_pLbSort->GetEntryCount() == 0 )
     166           0 :         FillFieldLists(0);
     167             : 
     168             :     // ListBox selection:
     169           0 :     if ( aSortData.maKeyState[0].bDoSort )
     170             :     {
     171           0 :         for ( sal_uInt16 i=0; i<nSortKeyCount; i++ )
     172             :         {
     173           0 :             if ( i < aSortData.maKeyState.size() && aSortData.maKeyState[i].bDoSort )
     174             :             {
     175           0 :                 maSortKeyItems[i].m_pLbSort->SelectEntryPos( GetFieldSelPos(
     176           0 :                                     aSortData.maKeyState[i].nField ) );
     177             : 
     178           0 :                 (aSortData.maKeyState[i].bAscending)
     179           0 :                     ? maSortKeyItems[i].m_pBtnUp->Check()
     180           0 :                     : maSortKeyItems[i].m_pBtnDown->Check();
     181             :             }
     182             :             else
     183             :             {
     184           0 :                 maSortKeyItems[i].m_pLbSort->SelectEntryPos( 0 ); // Select none
     185           0 :                 maSortKeyItems[i].m_pBtnUp->Check();
     186             :             }
     187             :         }
     188             : 
     189             :         // Enable or disable field depending on preceding Listbox selection
     190           0 :         maSortKeyItems[0].EnableField();
     191           0 :         for ( sal_uInt16 i=1; i<nSortKeyCount; i++ )
     192           0 :             if ( maSortKeyItems[i - 1].m_pLbSort->GetSelectEntryPos() == 0 )
     193           0 :                 maSortKeyItems[i].DisableField();
     194             :             else
     195           0 :                 maSortKeyItems[i].EnableField();
     196             : 
     197             :     }
     198             :     else
     199             :     {
     200           0 :         SCCOL  nCol = pViewData->GetCurX();
     201             : 
     202           0 :         if( nCol < aSortData.nCol1 )
     203           0 :             nCol = aSortData.nCol1;
     204           0 :         else if( nCol > aSortData.nCol2 )
     205           0 :             nCol = aSortData.nCol2;
     206             : 
     207           0 :         sal_uInt16  nSort1Pos = nCol - aSortData.nCol1+1;
     208             : 
     209           0 :         maSortKeyItems[0].m_pLbSort->SelectEntryPos( nSort1Pos );
     210           0 :         for ( sal_uInt16 i=1; i<nSortKeyCount; i++ )
     211           0 :             maSortKeyItems[i].m_pLbSort->SelectEntryPos( 0 );
     212             : 
     213           0 :         for ( sal_uInt16 i=0; i<nSortKeyCount; i++ )
     214           0 :             maSortKeyItems[i].m_pBtnUp->Check();
     215             : 
     216             : 
     217           0 :         maSortKeyItems[0].EnableField();
     218           0 :         maSortKeyItems[1].EnableField();
     219           0 :         for ( sal_uInt16 i=2; i<nSortKeyCount; i++ )
     220           0 :             maSortKeyItems[i].DisableField();
     221             :     }
     222             : 
     223           0 :     if ( pDlg )
     224             :     {
     225           0 :         pDlg->SetByRows ( bSortByRows );
     226           0 :         pDlg->SetHeaders( bHasHeader );
     227             :     }
     228           0 : }
     229             : 
     230             : // -----------------------------------------------------------------------
     231             : 
     232           0 : sal_Bool ScTabPageSortFields::FillItemSet( SfxItemSet& rArgSet )
     233             : {
     234           0 :     ScSortParam aNewSortData = aSortData;
     235             : 
     236           0 :     if (pDlg)
     237             :     {
     238           0 :         const SfxItemSet* pExample = pDlg->GetExampleSet();
     239             :         const SfxPoolItem* pItem;
     240           0 :         if ( pExample && pExample->GetItemState( nWhichSort, sal_True, &pItem ) == SFX_ITEM_SET )
     241             :         {
     242           0 :             ScSortParam aTempData = static_cast<const ScSortItem*>(pItem)->GetSortData();
     243           0 :             aTempData.maKeyState = aNewSortData.maKeyState;
     244           0 :             aNewSortData = aTempData;
     245             :         }
     246             :     }
     247           0 :     std::vector<sal_uInt16>  nSortPos;
     248             : 
     249           0 :     for ( sal_uInt16 i=0; i<nSortKeyCount; i++ )
     250             :     {
     251           0 :         nSortPos.push_back( maSortKeyItems[i].m_pLbSort->GetSelectEntryPos() );
     252             : 
     253           0 :         if ( nSortPos[i] == LISTBOX_ENTRY_NOTFOUND ) nSortPos[i] = 0;
     254             :     }
     255             : 
     256           0 :     if( nSortKeyCount >= aNewSortData.maKeyState.size() )
     257           0 :         aNewSortData.maKeyState.resize(nSortKeyCount);
     258             : 
     259           0 :     if ( nSortPos[0] > 0 )
     260             :     {
     261           0 :         for ( sal_uInt16 i=0; i<nSortKeyCount; i++ )
     262           0 :             aNewSortData.maKeyState[i].bDoSort = (nSortPos[i] > 0);
     263             : 
     264             :         // If the "OK" was selected on the Options page while the sort
     265             :         // direction was changed, then the first field (i.e. nFieldArr[0])
     266             :         // of the respective direction is chosen as the sorting criterion:
     267           0 :         if ( bSortByRows != pDlg->GetByRows() )
     268             :         {
     269           0 :             for ( sal_uInt16 i=0; i<nSortKeyCount; i++ )
     270           0 :                 aNewSortData.maKeyState[i].nField = ( bSortByRows ?
     271             :                         static_cast<SCCOLROW>(nFirstRow) :
     272           0 :                         static_cast<SCCOLROW>(nFirstCol) );
     273             :         }
     274             :         else
     275             :         {
     276           0 :            for ( sal_uInt16 i=0; i<nSortKeyCount; i++ )
     277           0 :                aNewSortData.maKeyState[i].nField = nFieldArr[nSortPos[i]];
     278             :         }
     279             : 
     280           0 :         for ( sal_uInt16 i=0; i<nSortKeyCount; i++ )
     281           0 :             aNewSortData.maKeyState[i].bAscending = maSortKeyItems[i].m_pBtnUp->IsChecked();
     282             : 
     283             :         // bHasHeader is in ScTabPageSortOptions::FillItemSet, where it belongs
     284             :     }
     285             :     else
     286             :     {
     287           0 :         for ( sal_uInt16 i=0; i<nSortKeyCount; i++ )
     288           0 :             aNewSortData.maKeyState[i].bDoSort = false;
     289             :     }
     290             : 
     291           0 :     rArgSet.Put( ScSortItem( SCITEM_SORTDATA, NULL, &aNewSortData ) );
     292             : 
     293           0 :     return sal_True;
     294             : }
     295             : 
     296             : // -----------------------------------------------------------------------
     297             : 
     298             : // for data exchange without dialogue detour:
     299           0 : void ScTabPageSortFields::ActivatePage( const SfxItemSet& rSet )
     300             : {
     301             :     // Refresh local copy with shared data
     302           0 :     aSortData = static_cast<const ScSortItem&>(rSet.Get( SCITEM_SORTDATA )).GetSortData();
     303           0 :     if ( pDlg )
     304             :     {
     305           0 :         if ( bHasHeader  != pDlg->GetHeaders()
     306           0 :              || bSortByRows != pDlg->GetByRows() )
     307             :         {
     308           0 :             std::vector<sal_uInt16> nCurSel;
     309           0 :             for ( sal_uInt16 i=0; i<nSortKeyCount; i++ )
     310           0 :                 nCurSel.push_back( maSortKeyItems[i].m_pLbSort->GetSelectEntryPos() );
     311             : 
     312           0 :             bHasHeader  = pDlg->GetHeaders();
     313           0 :             bSortByRows = pDlg->GetByRows();
     314           0 :             FillFieldLists(0);
     315             : 
     316           0 :             for ( sal_uInt16 i=0; i<nSortKeyCount; i++ )
     317           0 :                 maSortKeyItems[i].m_pLbSort->SelectEntryPos( nCurSel[i] );
     318             :         }
     319             :     }
     320           0 : }
     321             : 
     322             : // -----------------------------------------------------------------------
     323             : 
     324           0 : int ScTabPageSortFields::DeactivatePage( SfxItemSet* pSetP )
     325             : {
     326           0 :     if ( pDlg )
     327             :     {
     328           0 :         if ( bHasHeader != pDlg->GetHeaders() )
     329           0 :             pDlg->SetHeaders( bHasHeader );
     330             : 
     331           0 :         if ( bSortByRows != pDlg->GetByRows() )
     332           0 :             pDlg->SetByRows( bSortByRows );
     333             :     }
     334             : 
     335           0 :     if ( pSetP )
     336           0 :         FillItemSet( *pSetP );
     337             : 
     338           0 :     return SfxTabPage::LEAVE_PAGE;
     339             : }
     340             : 
     341             : // -----------------------------------------------------------------------
     342             : 
     343           0 : void ScTabPageSortFields::FillFieldLists( sal_uInt16 nStartField )
     344             : {
     345           0 :     if ( pViewData )
     346             :     {
     347           0 :         ScDocument* pDoc = pViewData->GetDocument();
     348             : 
     349           0 :         if ( pDoc )
     350             :         {
     351           0 :             for ( sal_uInt16 i=nStartField; i<nSortKeyCount; i++ )
     352             :             {
     353           0 :                 maSortKeyItems[i].m_pLbSort->Clear();
     354           0 :                 maSortKeyItems[i].m_pLbSort->InsertEntry( aStrUndefined, 0 );
     355             :             }
     356             : 
     357           0 :             SCCOL   nFirstSortCol   = aSortData.nCol1;
     358           0 :             SCROW   nFirstSortRow   = aSortData.nRow1;
     359           0 :             SCTAB   nTab        = pViewData->GetTabNo();
     360           0 :             sal_uInt16  i           = 1;
     361             : 
     362           0 :             if ( bSortByRows )
     363             :             {
     364           0 :                 rtl::OUString  aFieldName;
     365           0 :                 SCCOL   nMaxCol = aSortData.nCol2;
     366             :                 SCCOL   col;
     367             : 
     368           0 :                 for ( col=nFirstSortCol; col<=nMaxCol && i<SC_MAXFIELDS; col++ )
     369             :                 {
     370           0 :                     pDoc->GetString( col, nFirstSortRow, nTab, aFieldName );
     371           0 :                     if ( !bHasHeader || aFieldName.isEmpty() )
     372             :                     {
     373           0 :                         rtl::OUStringBuffer aBuf;
     374           0 :                         aBuf.append(aStrColumn);
     375           0 :                         aFieldName = aBuf.makeStringAndClear().replaceAll("%1", ScColToAlpha( col ));
     376             :                     }
     377           0 :                     nFieldArr.push_back( col );
     378             : 
     379           0 :                     for ( sal_uInt16 j=nStartField; j<nSortKeyCount; j++ )
     380           0 :                         maSortKeyItems[j].m_pLbSort->InsertEntry( aFieldName, i );
     381             : 
     382           0 :                     i++;
     383           0 :                 }
     384             :             }
     385             :             else
     386             :             {
     387           0 :                 rtl::OUString  aFieldName;
     388           0 :                 SCROW   nMaxRow = aSortData.nRow2;
     389             :                 SCROW   row;
     390             : 
     391           0 :                 for ( row=nFirstSortRow; row<=nMaxRow && i<SC_MAXFIELDS; row++ )
     392             :                 {
     393           0 :                     pDoc->GetString( nFirstSortCol, row, nTab, aFieldName );
     394           0 :                     if ( !bHasHeader || aFieldName.isEmpty() )
     395             :                     {
     396           0 :                         rtl::OUStringBuffer aBuf;
     397           0 :                         rtl::OUStringBuffer tempBuf;
     398             : 
     399           0 :                         aBuf.append(aStrRow);
     400           0 :                         tempBuf.append(row+1 );
     401           0 :                         aFieldName = aBuf.makeStringAndClear().replaceAll("%1", tempBuf.makeStringAndClear());
     402             :                     }
     403           0 :                     nFieldArr.push_back( row );
     404             : 
     405           0 :                     for ( sal_uInt16 j=nStartField; j<nSortKeyCount; j++ )
     406           0 :                         maSortKeyItems[j].m_pLbSort->InsertEntry( aFieldName, i );
     407             : 
     408           0 :                     i++;
     409           0 :                 }
     410             :             }
     411           0 :             nFieldCount = i;
     412             :         }
     413             :     }
     414           0 : }
     415             : 
     416             : //------------------------------------------------------------------------
     417             : 
     418           0 : sal_uInt16 ScTabPageSortFields::GetFieldSelPos( SCCOLROW nField )
     419             : {
     420           0 :     sal_uInt16  nFieldPos   = 0;
     421           0 :     sal_Bool    bFound      = false;
     422             : 
     423           0 :     for ( sal_uInt16 n=1; n<nFieldCount && !bFound; n++ )
     424             :     {
     425           0 :         if ( nFieldArr[n] == nField )
     426             :         {
     427           0 :             nFieldPos = n;
     428           0 :             bFound = sal_True;
     429             :         }
     430             :     }
     431             : 
     432           0 :     return nFieldPos;
     433             : }
     434             : 
     435             : // -----------------------------------------------------------------------
     436             : // Handler:
     437             : //---------
     438             : 
     439           0 : IMPL_LINK( ScTabPageSortFields, SelectHdl, ListBox *, pLb )
     440             : {
     441           0 :     rtl::OUString aSelEntry = pLb->GetSelectEntry();
     442           0 :     ScSortKeyItems::iterator pIter;
     443           0 :     sal_uInt16 nSortKeyIndex = nSortKeyCount;
     444             : 
     445             :     // If last listbox is enabled add one item
     446           0 :     if ( maSortKeyItems.back().m_pLbSort == pLb )
     447           0 :         if ( aSelEntry != aStrUndefined )
     448             :         {
     449             :             // Extend local SortParam copy
     450           0 :             const ScSortKeyState atempKeyState = { false, 0, true };
     451           0 :             aSortData.maKeyState.push_back( atempKeyState );
     452             : 
     453             :             // Add Sort Key Item
     454           0 :             ++nSortKeyCount;
     455           0 :             maSortKeyCtrl.AddSortKey( nSortKeyCount );
     456           0 :             maSortKeyItems[nSortKeyIndex].m_pLbSort->SetSelectHdl( LINK( this, ScTabPageSortFields, SelectHdl ) );
     457             : 
     458           0 :             FillFieldLists( nSortKeyIndex );
     459             : 
     460             :             // Set Status
     461           0 :             maSortKeyItems[nSortKeyIndex].m_pBtnUp->Check();
     462           0 :             maSortKeyItems[nSortKeyIndex].m_pLbSort->SelectEntryPos( 0 );
     463           0 :             return 0;
     464             :         }
     465             : 
     466             :     // Find selected listbox
     467           0 :     for ( pIter = maSortKeyItems.begin(); pIter != maSortKeyItems.end(); ++pIter )
     468             :     {
     469           0 :         if ( pIter->m_pLbSort == pLb ) break;
     470             :     }
     471             : 
     472             :     // If not selecting the last Listbox, modify the succeeding ones
     473           0 :     ++pIter;
     474           0 :     if ( std::distance(maSortKeyItems.begin(), pIter) < nSortKeyCount )
     475             :     {
     476           0 :         if ( aSelEntry == aStrUndefined )
     477             :         {
     478           0 :             for ( ; pIter != maSortKeyItems.end(); ++pIter )
     479             :             {
     480           0 :                 pIter->m_pLbSort->SelectEntryPos( 0 );
     481             : 
     482           0 :                 if ( pIter->m_pFlSort->IsEnabled() )
     483           0 :                     pIter->DisableField();
     484             :             }
     485             :         }
     486             :         else
     487             :         {
     488           0 :             if ( !pIter->m_pFlSort->IsEnabled() )
     489           0 :                     pIter->EnableField();
     490             :         }
     491             :      }
     492           0 :     return 0;
     493             : }
     494             : 
     495             : //========================================================================
     496             : // Sort option Tab Page:
     497             : //========================================================================
     498             : 
     499           0 : ScTabPageSortOptions::ScTabPageSortOptions( Window*             pParent,
     500             :                                             const SfxItemSet&   rArgSet )
     501             :     : SfxTabPage(pParent, "SortOptionsPage",
     502             :         "modules/scalc/ui/sortoptionspage.ui", rArgSet)
     503             :     , aStrRowLabel(SC_RESSTR(SCSTR_ROW_LABEL))
     504             :     , aStrColLabel(SC_RESSTR(SCSTR_COL_LABEL))
     505             :     , aStrUndefined(SC_RESSTR(SCSTR_UNDEFINED))
     506           0 :     , nWhichSort(rArgSet.GetPool()->GetWhich(SID_SORT))
     507           0 :     , aSortData(((const ScSortItem&)rArgSet.Get(nWhichSort)).GetSortData())
     508             :     , pViewData(NULL)
     509             :     , pDoc(NULL)
     510           0 :     , pDlg((ScSortDlg*)(GetParentDialog()))
     511             :     , pColRes( NULL )
     512           0 :     , pColWrap( NULL )
     513             : {
     514           0 :     get(m_pBtnCase, "case");
     515           0 :     get(m_pBtnHeader, "header");
     516           0 :     get(m_pBtnFormats, "formats");
     517           0 :     get(m_pBtnNaturalSort, "naturalsort");
     518           0 :     get(m_pBtnCopyResult, "copyresult");
     519           0 :     get(m_pLbOutPos, "outarealb");
     520           0 :     get(m_pEdOutPos, "outareaed");
     521           0 :     get(m_pBtnSortUser, "sortuser");
     522           0 :     get(m_pLbSortUser, "sortuserlb");
     523           0 :     get(m_pFtAlgorithm, "algorithmft");
     524           0 :     get(m_pLbAlgorithm, "algorithmlb");
     525           0 :     get(m_pBtnTopDown, "topdown");
     526           0 :     get(m_pBtnLeftRight, "leftright");
     527           0 :     get(m_pLbLanguage, "language");
     528           0 :     Init();
     529           0 :     SetExchangeSupport();
     530             : 
     531           0 :     m_pLbOutPos->SetAccessibleRelationLabeledBy(m_pBtnCopyResult);
     532           0 :     m_pLbOutPos->SetAccessibleName(m_pBtnCopyResult->GetText());
     533           0 :     m_pEdOutPos->SetAccessibleRelationLabeledBy(m_pBtnCopyResult);
     534           0 :     m_pEdOutPos->SetAccessibleName(m_pBtnCopyResult->GetText());
     535           0 :     m_pLbSortUser->SetAccessibleRelationLabeledBy(m_pBtnSortUser);
     536           0 :     m_pLbSortUser->SetAccessibleName(m_pBtnSortUser->GetText());
     537           0 : }
     538             : 
     539             : // -----------------------------------------------------------------------
     540             : 
     541           0 : ScTabPageSortOptions::~ScTabPageSortOptions()
     542             : {
     543           0 :     sal_uInt16 nEntries = m_pLbOutPos->GetEntryCount();
     544             : 
     545           0 :     for ( sal_uInt16 i=1; i<nEntries; i++ )
     546           0 :         delete (rtl::OUString*)m_pLbOutPos->GetEntryData( i );
     547             : 
     548           0 :     delete pColRes;
     549           0 :     delete pColWrap;        //! not if from document
     550           0 : }
     551             : 
     552             : // -----------------------------------------------------------------------
     553             : 
     554           0 : void ScTabPageSortOptions::Init()
     555             : {
     556             :     //  CollatorResource has user-visible names for sort algorithms
     557           0 :     pColRes = new CollatorResource();
     558             : 
     559             :     //! use CollatorWrapper from document?
     560           0 :     pColWrap = new CollatorWrapper( comphelper::getProcessComponentContext() );
     561             : 
     562             :     const ScSortItem&   rSortItem = (const ScSortItem&)
     563           0 :                                     GetItemSet().Get( nWhichSort );
     564             : 
     565           0 :     m_pLbOutPos->SetSelectHdl    ( LINK( this, ScTabPageSortOptions, SelOutPosHdl ) );
     566           0 :     m_pBtnCopyResult->SetClickHdl( LINK( this, ScTabPageSortOptions, EnableHdl ) );
     567           0 :     m_pBtnSortUser->SetClickHdl  ( LINK( this, ScTabPageSortOptions, EnableHdl ) );
     568           0 :     m_pBtnTopDown->SetClickHdl   ( LINK( this, ScTabPageSortOptions, SortDirHdl ) );
     569           0 :     m_pBtnLeftRight->SetClickHdl ( LINK( this, ScTabPageSortOptions, SortDirHdl ) );
     570           0 :     m_pLbLanguage->SetSelectHdl  ( LINK( this, ScTabPageSortOptions, FillAlgorHdl ) );
     571             : 
     572           0 :     pViewData = rSortItem.GetViewData();
     573           0 :     pDoc      = pViewData ? pViewData->GetDocument() : NULL;
     574             : 
     575             :     OSL_ENSURE( pViewData, "ViewData not found! :-/" );
     576             : 
     577             : 
     578           0 :     if ( pViewData && pDoc )
     579             :     {
     580           0 :         String          theArea;
     581           0 :         ScDBCollection* pDBColl     = pDoc->GetDBCollection();
     582           0 :         rtl::OUString          theDbArea;
     583           0 :         const SCTAB     nCurTab     = pViewData->GetTabNo();
     584           0 :         rtl::OUString          theDbName   = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(STR_DB_LOCAL_NONAME));
     585           0 :         const formula::FormulaGrammar::AddressConvention eConv = pDoc->GetAddressConvention();
     586             : 
     587           0 :         m_pLbOutPos->Clear();
     588           0 :         m_pLbOutPos->InsertEntry( aStrUndefined, 0 );
     589           0 :         m_pLbOutPos->Disable();
     590             : 
     591           0 :         ScAreaNameIterator aIter( pDoc );
     592           0 :         rtl::OUString aName;
     593           0 :         ScRange aRange;
     594           0 :         rtl::OUString aRefStr;
     595           0 :         while ( aIter.Next( aName, aRange ) )
     596             :         {
     597           0 :             sal_uInt16 nInsert = m_pLbOutPos->InsertEntry( aName );
     598             : 
     599           0 :             aRange.aStart.Format( aRefStr, SCA_ABS_3D, pDoc, eConv );
     600           0 :             m_pLbOutPos->SetEntryData( nInsert, new rtl::OUString( aRefStr ) );
     601             :         }
     602             : 
     603           0 :         m_pLbOutPos->SelectEntryPos( 0 );
     604           0 :         m_pEdOutPos->SetText( EMPTY_STRING );
     605             : 
     606             :         // Check whether the field that is passed on is a database field:
     607             : 
     608           0 :         ScAddress aScAddress( aSortData.nCol1, aSortData.nRow1, nCurTab );
     609             :         ScRange( aScAddress,
     610             :                  ScAddress( aSortData.nCol2, aSortData.nRow2, nCurTab )
     611           0 :                ).Format( theArea, SCR_ABS, pDoc, eConv );
     612             : 
     613           0 :         if ( pDBColl )
     614             :         {
     615             :             ScDBData* pDBData
     616             :                     = pDBColl->GetDBAtArea( nCurTab,
     617             :                                             aSortData.nCol1, aSortData.nRow1,
     618           0 :                                             aSortData.nCol2, aSortData.nRow2 );
     619           0 :             if ( pDBData )
     620             :             {
     621           0 :                 theDbName = pDBData->GetName();
     622           0 :                 m_pBtnHeader->Check( pDBData->HasHeader() );
     623             :             }
     624             :         }
     625             : 
     626           0 :         theArea.AppendAscii(RTL_CONSTASCII_STRINGPARAM(" ("));
     627           0 :         theArea += theDbName;
     628           0 :         theArea += ')';
     629             : 
     630           0 :         m_pBtnHeader->SetText( aStrColLabel );
     631             :     }
     632             : 
     633           0 :     FillUserSortListBox();
     634             : 
     635             :     //  get available languages
     636             : 
     637           0 :     m_pLbLanguage->SetLanguageList( LANG_LIST_ALL | LANG_LIST_ONLY_KNOWN, false );
     638           0 :     m_pLbLanguage->InsertLanguage( LANGUAGE_SYSTEM );
     639           0 : }
     640             : 
     641             : // -----------------------------------------------------------------------
     642             : 
     643           0 : SfxTabPage* ScTabPageSortOptions::Create(
     644             :                                             Window*             pParent,
     645             :                                             const SfxItemSet&   rArgSet )
     646             : {
     647           0 :     return ( new ScTabPageSortOptions( pParent, rArgSet ) );
     648             : }
     649             : 
     650             : // -----------------------------------------------------------------------
     651             : 
     652           0 : void ScTabPageSortOptions::Reset( const SfxItemSet& /* rArgSet */ )
     653             : {
     654           0 :     if ( aSortData.bUserDef )
     655             :     {
     656           0 :         m_pBtnSortUser->Check( sal_True );
     657           0 :         m_pLbSortUser->Enable();
     658           0 :         m_pLbSortUser->SelectEntryPos( aSortData.nUserIndex );
     659             :     }
     660             :     else
     661             :     {
     662           0 :         m_pBtnSortUser->Check( false );
     663           0 :         m_pLbSortUser->Disable();
     664           0 :         m_pLbSortUser->SelectEntryPos( 0 );
     665             :     }
     666             : 
     667           0 :     m_pBtnCase->Check          ( aSortData.bCaseSens );
     668           0 :     m_pBtnFormats->Check       ( aSortData.bIncludePattern );
     669           0 :     m_pBtnHeader->Check        ( aSortData.bHasHeader );
     670           0 :     m_pBtnNaturalSort->Check   ( aSortData.bNaturalSort );
     671             : 
     672           0 :     if ( aSortData.bByRow )
     673             :     {
     674           0 :         m_pBtnTopDown->Check();
     675           0 :         m_pBtnHeader->SetText( aStrColLabel );
     676             :     }
     677             :     else
     678             :     {
     679           0 :         m_pBtnLeftRight->Check();
     680           0 :         m_pBtnHeader->SetText( aStrRowLabel );
     681             :     }
     682             : 
     683           0 :     LanguageType eLang = LanguageTag( aSortData.aCollatorLocale ).getLanguageType( false);
     684           0 :     if ( eLang == LANGUAGE_DONTKNOW )
     685           0 :         eLang = LANGUAGE_SYSTEM;
     686           0 :     m_pLbLanguage->SelectLanguage( eLang );
     687           0 :     FillAlgorHdl(m_pLbLanguage);               // get algorithms, select default
     688           0 :     if ( !aSortData.aCollatorAlgorithm.isEmpty() )
     689           0 :         m_pLbAlgorithm->SelectEntry( pColRes->GetTranslation( aSortData.aCollatorAlgorithm ) );
     690             : 
     691           0 :     if ( pDoc && !aSortData.bInplace )
     692             :     {
     693           0 :         rtl::OUString aStr;
     694           0 :         sal_uInt16 nFormat = (aSortData.nDestTab != pViewData->GetTabNo())
     695             :                             ? SCR_ABS_3D
     696           0 :                             : SCR_ABS;
     697             : 
     698             :         theOutPos.Set( aSortData.nDestCol,
     699             :                        aSortData.nDestRow,
     700           0 :                        aSortData.nDestTab );
     701             : 
     702           0 :         theOutPos.Format( aStr, nFormat, pDoc, pDoc->GetAddressConvention() );
     703           0 :         m_pBtnCopyResult->Check();
     704           0 :         m_pLbOutPos->Enable();
     705           0 :         m_pEdOutPos->Enable();
     706           0 :         m_pEdOutPos->SetText( aStr );
     707           0 :         EdOutPosModHdl(m_pEdOutPos);
     708           0 :         m_pEdOutPos->GrabFocus();
     709           0 :         m_pEdOutPos->SetSelection( Selection( 0, SELECTION_MAX ) );
     710             :     }
     711             :     else
     712             :     {
     713           0 :         m_pBtnCopyResult->Check( false );
     714           0 :         m_pLbOutPos->Disable();
     715           0 :         m_pEdOutPos->Disable();
     716           0 :         m_pEdOutPos->SetText( EMPTY_STRING );
     717             :     }
     718           0 : }
     719             : 
     720             : // -----------------------------------------------------------------------
     721             : 
     722           0 : sal_Bool ScTabPageSortOptions::FillItemSet( SfxItemSet& rArgSet )
     723             : {
     724             :     // Create local copy of ScParam
     725           0 :     ScSortParam aNewSortData = aSortData;
     726             : 
     727           0 :     if (pDlg)
     728             :     {
     729           0 :         const SfxItemSet* pExample = pDlg->GetExampleSet();
     730             :         const SfxPoolItem* pItem;
     731           0 :         if ( pExample && pExample->GetItemState( nWhichSort, sal_True, &pItem ) == SFX_ITEM_SET )
     732           0 :             aNewSortData = static_cast<const ScSortItem*>(pItem)->GetSortData();
     733             :     }
     734           0 :     aNewSortData.bByRow          = m_pBtnTopDown->IsChecked();
     735           0 :     aNewSortData.bHasHeader      = m_pBtnHeader->IsChecked();
     736           0 :     aNewSortData.bCaseSens       = m_pBtnCase->IsChecked();
     737           0 :     aNewSortData.bNaturalSort    = m_pBtnNaturalSort->IsChecked();
     738           0 :     aNewSortData.bIncludePattern = m_pBtnFormats->IsChecked();
     739           0 :     aNewSortData.bInplace        = !m_pBtnCopyResult->IsChecked();
     740           0 :     aNewSortData.nDestCol        = theOutPos.Col();
     741           0 :     aNewSortData.nDestRow        = theOutPos.Row();
     742           0 :     aNewSortData.nDestTab        = theOutPos.Tab();
     743           0 :     aNewSortData.bUserDef        = m_pBtnSortUser->IsChecked();
     744           0 :     aNewSortData.nUserIndex      = (m_pBtnSortUser->IsChecked())
     745           0 :                                    ? m_pLbSortUser->GetSelectEntryPos()
     746           0 :                                    : 0;
     747             : 
     748             :     // get locale
     749           0 :     LanguageType eLang = m_pLbLanguage->GetSelectLanguage();
     750           0 :     aNewSortData.aCollatorLocale = LanguageTag( eLang ).getLocale( false );
     751             : 
     752             :     // get algorithm
     753           0 :     rtl::OUString sAlg;
     754           0 :     if ( eLang != LANGUAGE_SYSTEM )
     755             :     {
     756             :         uno::Sequence<rtl::OUString> aAlgos = pColWrap->listCollatorAlgorithms(
     757           0 :                 aNewSortData.aCollatorLocale );
     758           0 :         sal_uInt16 nSel = m_pLbAlgorithm->GetSelectEntryPos();
     759           0 :         if ( nSel < aAlgos.getLength() )
     760           0 :             sAlg = aAlgos[nSel];
     761             :     }
     762           0 :     aNewSortData.aCollatorAlgorithm = sAlg;
     763             : 
     764           0 :     rArgSet.Put( ScSortItem( SCITEM_SORTDATA, &aNewSortData ) );
     765             : 
     766           0 :     return sal_True;
     767             : }
     768             : 
     769             : // -----------------------------------------------------------------------
     770             : 
     771             : // for data exchange without dialogue detour:
     772           0 : void ScTabPageSortOptions::ActivatePage( const SfxItemSet& rSet )
     773             : {
     774             :     // Refresh local copy with shared data
     775           0 :     aSortData = static_cast<const ScSortItem&>(rSet.Get( SCITEM_SORTDATA )).GetSortData();
     776           0 :     if ( pDlg )
     777             :     {
     778           0 :         if ( m_pBtnHeader->IsChecked() != pDlg->GetHeaders() )
     779             :         {
     780           0 :             m_pBtnHeader->Check( pDlg->GetHeaders() );
     781             :         }
     782             : 
     783           0 :         if ( m_pBtnTopDown->IsChecked() != pDlg->GetByRows() )
     784             :         {
     785           0 :             m_pBtnTopDown->Check( pDlg->GetByRows() );
     786           0 :             m_pBtnLeftRight->Check( !pDlg->GetByRows() );
     787             :         }
     788             : 
     789           0 :         m_pBtnHeader->SetText( (pDlg->GetByRows())
     790             :                             ? aStrColLabel
     791           0 :                             : aStrRowLabel );
     792             :     }
     793           0 : }
     794             : 
     795             : // -----------------------------------------------------------------------
     796             : 
     797           0 : int ScTabPageSortOptions::DeactivatePage( SfxItemSet* pSetP )
     798             : {
     799           0 :     sal_Bool bPosInputOk = sal_True;
     800             : 
     801           0 :     if ( m_pBtnCopyResult->IsChecked() )
     802             :     {
     803           0 :         String      thePosStr = m_pEdOutPos->GetText();
     804           0 :         ScAddress   thePos;
     805           0 :         xub_StrLen  nColonPos = thePosStr.Search( ':' );
     806             : 
     807           0 :         if ( STRING_NOTFOUND != nColonPos )
     808           0 :             thePosStr.Erase( nColonPos );
     809             : 
     810           0 :         if ( pViewData )
     811             :         {
     812             :             //  visible table is default for input without table
     813             :             //  must be changed to GetRefTabNo when sorting has RefInput!
     814           0 :             thePos.SetTab( pViewData->GetTabNo() );
     815             :         }
     816             : 
     817           0 :         sal_uInt16 nResult = thePos.Parse( thePosStr, pDoc, pDoc->GetAddressConvention() );
     818             : 
     819           0 :         bPosInputOk = ( SCA_VALID == (nResult & SCA_VALID) );
     820             : 
     821           0 :         if ( !bPosInputOk )
     822             :         {
     823             :             ErrorBox( this, WinBits( WB_OK | WB_DEF_OK ),
     824           0 :                      ScGlobal::GetRscString( STR_INVALID_TABREF )
     825           0 :                     ).Execute();
     826           0 :             m_pEdOutPos->GrabFocus();
     827           0 :             m_pEdOutPos->SetSelection( Selection( 0, SELECTION_MAX ) );
     828           0 :             theOutPos.Set(0,0,0);
     829             :         }
     830             :         else
     831             :         {
     832           0 :             m_pEdOutPos->SetText( thePosStr );
     833           0 :             theOutPos = thePos;
     834           0 :         }
     835             :     }
     836             : 
     837           0 :     if ( pDlg && bPosInputOk )
     838             :     {
     839           0 :         pDlg->SetHeaders( m_pBtnHeader->IsChecked() );
     840           0 :         pDlg->SetByRows ( m_pBtnTopDown->IsChecked() );
     841             :     }
     842             : 
     843           0 :     if ( pSetP && bPosInputOk )
     844           0 :         FillItemSet( *pSetP );
     845             : 
     846           0 :     return bPosInputOk ? SfxTabPage::LEAVE_PAGE : SfxTabPage::KEEP_PAGE;
     847             : }
     848             : 
     849             : // -----------------------------------------------------------------------
     850             : 
     851           0 : void ScTabPageSortOptions::FillUserSortListBox()
     852             : {
     853           0 :     ScUserList* pUserLists = ScGlobal::GetUserList();
     854             : 
     855           0 :     m_pLbSortUser->Clear();
     856           0 :     if ( pUserLists )
     857             :     {
     858           0 :         size_t nCount = pUserLists->size();
     859           0 :         if ( nCount > 0 )
     860           0 :             for ( size_t i=0; i<nCount; ++i )
     861           0 :                 m_pLbSortUser->InsertEntry( (*pUserLists)[i]->GetString() );
     862             :     }
     863           0 : }
     864             : 
     865             : // -----------------------------------------------------------------------
     866             : // Handler:
     867             : 
     868           0 : IMPL_LINK( ScTabPageSortOptions, EnableHdl, CheckBox *, pBox )
     869             : {
     870           0 :     if (pBox == m_pBtnCopyResult)
     871             :     {
     872           0 :         if ( pBox->IsChecked() )
     873             :         {
     874           0 :             m_pLbOutPos->Enable();
     875           0 :             m_pEdOutPos->Enable();
     876           0 :             m_pEdOutPos->GrabFocus();
     877             :         }
     878             :         else
     879             :         {
     880           0 :             m_pLbOutPos->Disable();
     881           0 :             m_pEdOutPos->Disable();
     882             :         }
     883             :     }
     884           0 :     else if (pBox == m_pBtnSortUser)
     885             :     {
     886           0 :         if ( pBox->IsChecked() )
     887             :         {
     888           0 :             m_pLbSortUser->Enable();
     889           0 :             m_pLbSortUser->GrabFocus();
     890             :         }
     891             :         else
     892           0 :             m_pLbSortUser->Disable();
     893             :     }
     894           0 :     return 0;
     895             : }
     896             : 
     897             : // -----------------------------------------------------------------------
     898             : 
     899           0 : IMPL_LINK( ScTabPageSortOptions, SelOutPosHdl, ListBox *, pLb )
     900             : {
     901           0 :     if (pLb == m_pLbOutPos)
     902             :     {
     903           0 :         rtl::OUString  aString;
     904           0 :         sal_uInt16  nSelPos = m_pLbOutPos->GetSelectEntryPos();
     905             : 
     906           0 :         if ( nSelPos > 0 )
     907           0 :             aString = *(String*)m_pLbOutPos->GetEntryData( nSelPos );
     908             : 
     909           0 :         m_pEdOutPos->SetText( aString );
     910             :     }
     911           0 :     return 0;
     912             : }
     913             : 
     914             : // -----------------------------------------------------------------------
     915             : 
     916           0 : IMPL_LINK( ScTabPageSortOptions, SortDirHdl, RadioButton *, pBtn )
     917             : {
     918           0 :     if (pBtn == m_pBtnTopDown)
     919             :     {
     920           0 :         m_pBtnHeader->SetText( aStrColLabel );
     921             :     }
     922           0 :     else if (pBtn == m_pBtnLeftRight)
     923             :     {
     924           0 :         m_pBtnHeader->SetText( aStrRowLabel );
     925             :     }
     926           0 :     return 0;
     927             : }
     928             : 
     929             : // -----------------------------------------------------------------------
     930             : 
     931           0 : void ScTabPageSortOptions::EdOutPosModHdl( Edit* pEd )
     932             : {
     933           0 :     if (pEd == m_pEdOutPos)
     934             :     {
     935           0 :        String  theCurPosStr = m_pEdOutPos->GetText();
     936           0 :         sal_uInt16  nResult = ScAddress().Parse( theCurPosStr, pDoc, pDoc->GetAddressConvention() );
     937             : 
     938           0 :         if ( SCA_VALID == (nResult & SCA_VALID) )
     939             :         {
     940           0 :             String* pStr    = NULL;
     941           0 :             sal_Bool    bFound  = false;
     942           0 :             sal_uInt16  i       = 0;
     943           0 :             sal_uInt16  nCount  = m_pLbOutPos->GetEntryCount();
     944             : 
     945           0 :             for ( i=2; i<nCount && !bFound; i++ )
     946             :             {
     947           0 :                 pStr = (String*)m_pLbOutPos->GetEntryData( i );
     948           0 :                 bFound = (theCurPosStr == *pStr);
     949             :             }
     950             : 
     951           0 :             if ( bFound )
     952           0 :                 m_pLbOutPos->SelectEntryPos( --i );
     953             :             else
     954           0 :                 m_pLbOutPos->SelectEntryPos( 0 );
     955           0 :         }
     956             :     }
     957           0 : }
     958             : 
     959             : // -----------------------------------------------------------------------
     960             : 
     961           0 : IMPL_LINK_NOARG(ScTabPageSortOptions, FillAlgorHdl)
     962             : {
     963           0 :     m_pLbAlgorithm->SetUpdateMode( false );
     964           0 :     m_pLbAlgorithm->Clear();
     965             : 
     966           0 :     LanguageType eLang = m_pLbLanguage->GetSelectLanguage();
     967           0 :     if ( eLang == LANGUAGE_SYSTEM )
     968             :     {
     969             :         //  for LANGUAGE_SYSTEM no algorithm can be selected because
     970             :         //  it wouldn't necessarily exist for other languages
     971             :         //  -> leave list box empty if LANGUAGE_SYSTEM is selected
     972           0 :         m_pFtAlgorithm->Enable( false );           // nothing to select
     973           0 :         m_pLbAlgorithm->Enable( false );           // nothing to select
     974             :     }
     975             :     else
     976             :     {
     977           0 :         lang::Locale aLocale( LanguageTag( eLang ).getLocale());
     978           0 :         uno::Sequence<rtl::OUString> aAlgos = pColWrap->listCollatorAlgorithms( aLocale );
     979             : 
     980           0 :         long nCount = aAlgos.getLength();
     981           0 :         const rtl::OUString* pArray = aAlgos.getConstArray();
     982           0 :         for (long i=0; i<nCount; i++)
     983             :         {
     984           0 :             String sAlg = pArray[i];
     985           0 :             String sUser = pColRes->GetTranslation( sAlg );
     986           0 :             m_pLbAlgorithm->InsertEntry( sUser, LISTBOX_APPEND );
     987           0 :         }
     988           0 :         m_pLbAlgorithm->SelectEntryPos( 0 );       // first entry is default
     989           0 :         m_pFtAlgorithm->Enable( nCount > 1 );      // enable only if there is a choice
     990           0 :         m_pLbAlgorithm->Enable( nCount > 1 );      // enable only if there is a choice
     991             :     }
     992             : 
     993           0 :     m_pLbAlgorithm->SetUpdateMode( sal_True );
     994           0 :     return 0;
     995           0 : }
     996             : 
     997             : 
     998             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10