office-gobmx/svtools/source/dialogs/filedlg2.cxx
2011-11-27 13:24:31 -06:00

1326 lines
40 KiB
C++
Raw Blame History

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* Copyright 2000, 2010 Oracle and/or its affiliates.
*
* OpenOffice.org - a multi-platform office productivity suite
*
* This file is part of OpenOffice.org.
*
* OpenOffice.org is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License version 3
* only, as published by the Free Software Foundation.
*
* OpenOffice.org is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License version 3 for more details
* (a copy is included in the LICENSE file that accompanied this code).
*
* You should have received a copy of the GNU Lesser General Public License
* version 3 along with OpenOffice.org. If not, see
* <http://www.openoffice.org/license.html>
* for a copy of the LGPLv3 License.
*
************************************************************************/
#include <vcl/svapp.hxx>
#include <vcl/button.hxx>
#include <vcl/fixed.hxx>
#include <vcl/edit.hxx>
#include <vcl/lstbox.hxx>
#include <svtools/svtdata.hxx>
#include <filedlg2.hxx>
#include <svtools/filedlg.hxx>
#include <svtools/filedlg2.hrc>
#include <vcl/msgbox.hxx>
#include <osl/security.hxx>
#include <comphelper/string.hxx>
#include <svtools/stdctrl.hxx>
#ifdef _MSC_VER
#pragma optimize ("", off)
#endif
#include <svtools/helpid.hrc>
using namespace com::sun::star;
using namespace com::sun::star::uno;
typedef ::std::vector< UniString* > UniStringList;
#define STD_BTN_WIDTH 80
#define STD_BTN_HEIGHT 26
#ifndef UNX
#define ALLFILES "*.*"
#else
#define ALLFILES "*"
#endif
// #define STD_BTN_WIDTH 90
// #define STD_BTN_HEIGHT 35
#define INITCONTROL( p, ControlClass, nBits, aPos, aSize, aTitel, rHelpId ) \
p = new ControlClass( GetPathDialog(), WinBits( nBits ) ); \
p->SetHelpId( rHelpId ); \
p->SetPosSizePixel( aPos, aSize ); \
p->SetText( aTitel ); \
p->Show();
inline sal_Bool IsPrintable( sal_Unicode c )
{
return c >= 32 && c != 127 ? sal_True : sal_False;
}
long
KbdListBox::PreNotify( NotifyEvent& rNEvt )
{
if ( rNEvt.GetType() == EVENT_KEYINPUT )
{
KeyEvent aKeyEvt = *rNEvt.GetKeyEvent();
sal_Unicode cCharCode = aKeyEvt.GetCharCode();
if ( IsPrintable ( cCharCode ) )
{
sal_uInt16 nCurrentPos = GetSelectEntryPos();
sal_uInt16 nEntries = GetEntryCount();
for ( sal_uInt16 i = 1; i < nEntries; i++ )
{
UniString aEntry = GetEntry ( (i + nCurrentPos) % nEntries );
aEntry.EraseLeadingChars( ' ' );
aEntry.ToUpperAscii();
UniString aCompare( cCharCode );
aCompare.ToUpperAscii();
if ( aEntry.CompareTo( aCompare, 1 ) == COMPARE_EQUAL )
{
SelectEntryPos ( (i + nCurrentPos) % nEntries );
break;
}
}
}
else
if ( aKeyEvt.GetKeyCode().GetCode() == KEY_RETURN )
{
DoubleClick();
}
}
return ListBox::PreNotify ( rNEvt );
}
ImpPathDialog::ImpPathDialog( PathDialog* pDlg, RESOURCE_TYPE nType, sal_Bool bCreateDir )
{
pSvPathDialog = pDlg;
nDirCount = 0;
// initialize Controls if not used as a base class
if ( nType == WINDOW_PATHDIALOG )
{
InitControls();
if( pNewDirBtn )
pNewDirBtn->Enable( bCreateDir );
}
pDlg->SetHelpId( HID_FILEDLG_PATHDLG );
}
ImpPathDialog::~ImpPathDialog()
{
delete pEdit;
delete pDirTitel;
delete pDirList;
delete pDirPath;
delete pDriveList;
delete pDriveTitle;
delete pLoadBtn;
delete pOkBtn;
delete pCancelBtn;
delete pNewDirBtn;
# if defined(UNX)
delete pHomeBtn;
# endif
}
void ImpPathDialog::InitControls()
{
PathDialog* pDlg = GetPathDialog();
pDlg->SetText( UniString( SvtResId( STR_FILEDLG_SELECT ) ) );
Size a3Siz = pDlg->LogicToPixel( Size( 3, 3 ), MAP_APPFONT );
Size a6Siz = pDlg->LogicToPixel( Size( 6, 6 ), MAP_APPFONT );
Size aBtnSiz = pDlg->LogicToPixel( Size( 50, 14 ), MAP_APPFONT );
Size aFTSiz = pDlg->LogicToPixel( Size( 142, 10 ), MAP_APPFONT );
Size aEDSiz = pDlg->LogicToPixel( Size( 142, 12 ), MAP_APPFONT );
Point aPnt( a6Siz.Width(), a6Siz.Height() );
long nLbH1 = pDlg->LogicToPixel( Size( 0, 93 ), MAP_APPFONT ).Height();
long nH = 0;
UniString aEmptyStr;
INITCONTROL( pDirTitel, FixedText, 0,
aPnt, aFTSiz, UniString( SvtResId( STR_FILEDLG_DIR ) ), HID_FILEDLG_DIR );
aPnt.Y() += aFTSiz.Height() + a3Siz.Height();
INITCONTROL( pEdit, Edit, WB_BORDER, aPnt, aEDSiz, aPath.GetFull(), HID_FILEDLG_EDIT );
aPnt.Y() += aEDSiz.Height() + a3Siz.Height();
#ifndef UNX
long nLbH2 = pDlg->LogicToPixel( Size( 0, 60 ), MAP_APPFONT ).Height();
INITCONTROL( pDirList, KbdListBox, WB_AUTOHSCROLL | WB_BORDER,
aPnt, Size( aEDSiz.Width(), nLbH1 ), aEmptyStr, HID_FILEDLG_DIRS );
aPnt.Y() += nLbH1 + a6Siz.Height();
INITCONTROL( pDriveTitle, FixedText, 0,
aPnt, aFTSiz, UniString( SvtResId( STR_FILEDLG_DRIVES ) ), HID_FILEDLG_DRIVE );
aPnt.Y() += aFTSiz.Height() + a3Siz.Height();
INITCONTROL( pDriveList, ListBox, WB_DROPDOWN,
aPnt, Size( aEDSiz.Width(), nLbH2 ), aEmptyStr, HID_FILEDLG_DRIVES );
nH = aPnt.Y() + aEDSiz.Height() + a6Siz.Height();
#else
long nNewH = nLbH1 + 3 * a3Siz.Height() +
aFTSiz.Height() + aEDSiz.Height();
INITCONTROL( pDirList, KbdListBox, WB_AUTOHSCROLL | WB_BORDER,
aPnt, Size( aEDSiz.Width(), nNewH ), aEmptyStr, HID_FILEDLG_DIRS );
nH = aPnt.Y() + nNewH + a6Siz.Height();
pDriveTitle = NULL;
pDriveList = NULL;
#endif
long nExtraWidth = pDlg->GetTextWidth( String( RTL_CONSTASCII_USTRINGPARAM( "(W)" ) ) )+10;
String aOkStr = Button::GetStandardText( BUTTON_OK );
long nTextWidth = pDlg->GetTextWidth( aOkStr )+nExtraWidth;
if( nTextWidth > aBtnSiz.Width() )
aBtnSiz.Width() = nTextWidth;
String aCancelStr = Button::GetStandardText( BUTTON_CANCEL );
nTextWidth = pDlg->GetTextWidth( aCancelStr )+nExtraWidth;
if( nTextWidth > aBtnSiz.Width() )
aBtnSiz.Width() = nTextWidth;
String aNewDirStr( SvtResId( STR_FILEDLG_NEWDIR ) );
nTextWidth = pDlg->GetTextWidth( aNewDirStr )+nExtraWidth;
if( nTextWidth > aBtnSiz.Width() )
aBtnSiz.Width() = nTextWidth;
#if defined(UNX)
String aHomeDirStr( SvtResId( STR_FILEDLG_HOME ) );
nTextWidth = pDlg->GetTextWidth( aHomeDirStr )+nExtraWidth;
if( nTextWidth > aBtnSiz.Width() )
aBtnSiz.Width() = nTextWidth;
#endif
aPnt.X() = 2 * a6Siz.Width() + aEDSiz.Width();
aPnt.Y() = a6Siz.Height();
INITCONTROL( pOkBtn, PushButton, WB_DEFBUTTON,
aPnt, aBtnSiz, aOkStr, "" );
aPnt.Y() += aBtnSiz.Height() + a3Siz.Height();
INITCONTROL( pCancelBtn, CancelButton, 0,
aPnt, aBtnSiz, aCancelStr, "" );
aPnt.Y() += aBtnSiz.Height() + a3Siz.Height();
INITCONTROL( pNewDirBtn, PushButton, WB_DEFBUTTON,
aPnt, aBtnSiz, aNewDirStr, HID_FILEDLG_NEWDIR );
#if defined(UNX)
aPnt.Y() += aBtnSiz.Height() + a3Siz.Height();
INITCONTROL( pHomeBtn, PushButton, WB_DEFBUTTON,
aPnt, aBtnSiz, aHomeDirStr, HID_FILEDLG_HOME );
#else
pHomeBtn = NULL;
#endif
pDirPath = 0;
pLoadBtn = 0;
// Dialogbreite == OKBtn-Position + OKBtn-Breite + Rand
long nW = aPnt.X() + aBtnSiz.Width() + a6Siz.Width();
pDlg->SetOutputSizePixel( Size( nW, nH ) ); // Groesse ggf. auch Resource wird geplaettet?
if (pDirList)
pDirList->SetDoubleClickHdl(LINK( this, ImpPathDialog, DblClickHdl) );
if (pDirList)
pDirList->SetSelectHdl( LINK( this, ImpPathDialog, SelectHdl ) );
if (pDriveList)
pDriveList->SetSelectHdl( LINK( this, ImpPathDialog, SelectHdl ) );
if (pOkBtn)
pOkBtn->SetClickHdl( LINK( this, ImpPathDialog, ClickHdl) );
if (pCancelBtn)
pCancelBtn->SetClickHdl( LINK( this, ImpPathDialog, ClickHdl) );
if (pHomeBtn)
pHomeBtn->SetClickHdl( LINK( this, ImpPathDialog, ClickHdl) );
if (pNewDirBtn)
pNewDirBtn->SetClickHdl( LINK( this, ImpPathDialog, ClickHdl) );
nOwnChilds = pDlg->GetChildCount();
}
IMPL_LINK( ImpPathDialog, SelectHdl, ListBox *, p )
{
if( p == pDriveList )
{
UniString aDrive( pDriveList->GetSelectEntry(), 0, 2);
aDrive += '\\';
SetPath( aDrive );
}
else
if( p == pDirList )
{
// isolate the pure name of the entry
// removing trainling stuff and leading spaces
UniString aEntry( pDirList->GetSelectEntry() );
aEntry.EraseLeadingChars( ' ' );
sal_uInt16 nPos = aEntry.Search( '/' );
aEntry.Erase( nPos );
// build the absolute path to the selected item
DirEntry aNewPath;
aNewPath.ToAbs();
sal_uInt16 nCurPos = pDirList->GetSelectEntryPos();
// Wird nach oben gewechselt
if( nCurPos < nDirCount )
aNewPath = aNewPath[nDirCount-nCurPos-1];
else
aNewPath += aEntry;
pEdit->SetText( aNewPath.GetFull() );
}
return 0;
}
IMPL_LINK( ImpPathDialog, ClickHdl, Button*, pBtn )
{
if ( pBtn == pOkBtn || pBtn == pLoadBtn )
{
DirEntry aFile( pEdit->GetText() );
// Existiert File / File ueberschreiben
if( IsFileOk( aFile ) )
{
// Ja, dann kompletten Pfad mit Filenamen merken und Dialog beenden
aPath = aFile;
aPath.ToAbs();
GetPathDialog()->EndDialog( sal_True );
}
else
{
DirEntry aCheck( aPath );
aCheck += aFile;
if( aCheck.Exists() )
{
aCheck.ToAbs();
SetPath( aCheck.GetFull() );
pEdit->SetSelection( Selection( 0x7FFFFFFF, 0x7FFFFFFF ) );
}
}
}
else
if ( pBtn == pCancelBtn )
{
GetPathDialog()->EndDialog( sal_False );
}
else
if ( pBtn == pHomeBtn )
{
::rtl::OUString aHomeDir;
osl::Security aSecurity;
if ( aSecurity.getHomeDir( aHomeDir ) )
{
DirEntry aFile ( aHomeDir );
if ( IsFileOk( aFile ) )
{
aFile.ToAbs();
SetPath( aFile.GetFull() );
}
}
}
else
if ( pBtn == pNewDirBtn )
{
DirEntry aFile( pEdit->GetText() );
if( ! aFile.Exists() && ! FileStat( aFile ).IsKind( FSYS_KIND_WILD ) )
aFile.MakeDir();
if( IsFileOk ( aFile ) )
{
aFile.ToAbs();
SetPath( aFile.GetFull() );
}
}
return 0;
}
IMPL_LINK( ImpPathDialog, DblClickHdl, ListBox*, pBox )
{
// isolate the pure name of the entry
// removing trainling stuff and leading spaces
UniString aEntry( pBox->GetSelectEntry() );
aEntry.EraseLeadingChars( ' ' );
sal_uInt16 nPos = aEntry.Search( '/' );
aEntry.Erase( nPos );
// build the absolute path to the selected item
DirEntry aNewPath;
aNewPath.ToAbs();
if( pBox == pDirList )
{
sal_uInt16 nCurPos = pDirList->GetSelectEntryPos();
// Wenn es schon das aktuelle ist, dann mache nichts
if( nCurPos == nDirCount-1 )
return 0;
// Wird nach oben gewechselt
if( nCurPos < nDirCount )
aNewPath = aNewPath[nDirCount-nCurPos-1];
else
aNewPath += aEntry;
}
else
aNewPath += aEntry;
pSvPathDialog->EnterWait();
if( FileStat( aNewPath ).GetKind() & FSYS_KIND_DIR )
{
// Neuen Pfad setzen und Listboxen updaten
aPath = aNewPath;
if( !aPath.SetCWD( sal_True ) )
{
ErrorBox aBox( GetPathDialog(),
WB_OK_CANCEL | WB_DEF_OK,
UniString( SvtResId( STR_FILEDLG_CANTCHDIR ) ) );
if( aBox.Execute() == RET_CANCEL )
GetPathDialog()->EndDialog( sal_False );
}
UpdateEntries( sal_True );
}
pSvPathDialog->LeaveWait();
return 0;
}
void ImpPathDialog::UpdateEntries( const sal_Bool )
{
UniString aTabString;
DirEntry aTmpPath;
aTmpPath.ToAbs();
nDirCount = aTmpPath.Level();
pDirList->SetUpdateMode( sal_False );
pDirList->Clear();
for( sal_uInt16 i = nDirCount; i > 0; i-- )
{
UniString aName( aTabString );
aName += aTmpPath[i-1].GetName();
pDirList->InsertEntry( aName );
aTabString.AppendAscii( " ", 2 );
}
// scan the directory
DirEntry aCurrent;
aCurrent.ToAbs();
Dir aDir( aCurrent, FSYS_KIND_DIR|FSYS_KIND_FILE );
sal_uInt16 nEntries = aDir.Count();
if( nEntries )
{
UniStringList aSortDirList;
const comphelper::string::NaturalStringSorter& rSorter =
::vcl::unohelper::getNaturalStringSorterForAppLocale();
for ( sal_uInt16 n = 0; n < nEntries; n++ )
{
DirEntry& rEntry = aDir[n];
UniString aName( rEntry.GetName() );
if( aName.Len() && ( aName.GetChar(0) != '.' ) && rEntry.Exists() )
{
if( FileStat( rEntry ).GetKind() & FSYS_KIND_DIR )
{
size_t l = 0;
for( l = 0; l < aSortDirList.size(); l++ )
if( rSorter.compare( *aSortDirList[ l ], aName ) > 0 )
break;
if ( l < aSortDirList.size() ) {
UniStringList::iterator it = aSortDirList.begin();
::std::advance( it, l );
aSortDirList.insert( it, new UniString( aName ) );
} else {
aSortDirList.push_back( new UniString( aName ) );
}
}
}
}
for( size_t l = 0; l < aSortDirList.size(); l++ )
{
UniString aEntryStr( aTabString );
aEntryStr += *aSortDirList[ l ];
pDirList->InsertEntry( aEntryStr );
delete aSortDirList[ l ];
}
}
UpdateDirs( aTmpPath );
}
void ImpPathDialog::UpdateDirs( const DirEntry& rTmpPath )
{
pDirList->SelectEntryPos( nDirCount-1 );
pDirList->SetTopEntry( nDirCount > 1
? nDirCount - 2
: nDirCount - 1 );
pDirList->SetUpdateMode( sal_True );
pDirList->Invalidate();
pDirList->Update();
UniString aDirName = rTmpPath.GetFull();
if( pDirPath )
pDirPath->SetText( aDirName );
else
pEdit->SetText( aDirName );
}
sal_Bool ImpPathDialog::IsFileOk( const DirEntry& rDirEntry )
{
if( FileStat( rDirEntry ).GetKind() & (FSYS_KIND_WILD | FSYS_KIND_DEV) )
return sal_False;
else
{
// Datei vorhanden ?
if( ! rDirEntry.Exists() )
{
UniString aQueryTxt( SvtResId( STR_FILEDLG_ASKNEWDIR ) );
aQueryTxt.SearchAndReplaceAscii( "%s", rDirEntry.GetFull() );
QueryBox aQuery( GetPathDialog(),
WB_YES_NO | WB_DEF_YES,
aQueryTxt );
if( aQuery.Execute() == RET_YES )
rDirEntry.MakeDir();
else
return sal_False;
}
if( !FileStat( rDirEntry ).IsKind( FSYS_KIND_DIR ) )
{
UniString aBoxText( SvtResId( STR_FILEDLG_CANTOPENDIR ) );
aBoxText.AppendAscii( "\n[" );
aBoxText += rDirEntry.GetFull();
aBoxText.AppendAscii( "]" );
InfoBox aBox( GetPathDialog(), aBoxText );
aBox.Execute();
return sal_False;
}
}
return GetPathDialog()->OK() != 0;
}
void ImpPathDialog::PreExecute()
{
// Neues Verzeichnis setzen und Listboxen updaten
aPath.SetCWD( sal_True );
UpdateEntries( sal_True );
// Zusaetzliche Buttons anordnen
Point aPos;
Size aSize;
long nDY;
if( pLoadBtn )
{
aPos = pLoadBtn->GetPosPixel();
aSize = pLoadBtn->GetSizePixel();
nDY = pLoadBtn->GetSizePixel().Height() * 2;
}
else
{
aPos = pCancelBtn->GetPosPixel();
aSize = pCancelBtn->GetSizePixel();
nDY = pCancelBtn->GetPosPixel().Y() - pOkBtn->GetPosPixel().Y();
}
// Standard-Controls anpassen
long nMaxWidth = 0;
// Maximale Breite ermitteln
sal_uInt16 nChilds = GetPathDialog()->GetChildCount();
sal_uInt16 n;
for ( n = nOwnChilds; n < nChilds; n++ )
{
Window* pChild = GetPathDialog()->GetChild( n );
pChild = pChild->GetWindow( WINDOW_CLIENT );
if( pChild->GetType() != WINDOW_WINDOW )
{
long nWidth = pChild->GetTextWidth( pChild->GetText() ) + 12;
if( nMaxWidth < nWidth )
nMaxWidth = nWidth;
nWidth = pChild->GetSizePixel().Width();
if( nMaxWidth < nWidth )
nMaxWidth = nWidth;
}
}
if( nMaxWidth > aSize.Width() )
{
Size aDlgSize = GetPathDialog()->GetOutputSizePixel();
GetPathDialog()->SetOutputSizePixel( Size( aDlgSize.Width()+nMaxWidth-aSize.Width(), aDlgSize.Height() ) );
aSize.Width() = nMaxWidth;
if( pOkBtn )
pOkBtn->SetSizePixel( aSize );
if( pCancelBtn )
pCancelBtn->SetSizePixel( aSize );
if( pLoadBtn )
pLoadBtn->SetSizePixel( aSize );
}
else
nMaxWidth = aSize.Width();
for ( n = nOwnChilds; n < nChilds; n++ )
{
Window* pChild = GetPathDialog()->GetChild( n );
pChild = pChild->GetWindow( WINDOW_CLIENT );
if( pChild->GetType() != WINDOW_WINDOW )
{
aPos.Y() += nDY;
pChild->SetPosSizePixel( aPos, aSize );
}
else
{
Size aDlgSize = GetPathDialog()->GetOutputSizePixel();
long nExtra = Min( aDlgSize.Height(), (long)160);
GetPathDialog()->SetOutputSizePixel( Size( aDlgSize.Width()+nExtra, aDlgSize.Height() ) );
Size aSz( nExtra, nExtra );
aSz.Width() -= 8;
aSz.Height() -= 8;
Point aCtrlPos( aDlgSize.Width() + 2, (aDlgSize.Height()-aSz.Height())/2 );
pChild->SetPosSizePixel( aCtrlPos, aSz );
}
}
// Laufwerke-LB fuellen
if( pDriveList )
{
DirEntry aTmpDirEntry;
Dir aDir( aTmpDirEntry, FSYS_KIND_BLOCK );
sal_uInt16 nCount = aDir.Count(), i;
for( i = 0; i < nCount; ++i )
{
DirEntry& rEntry = aDir[i];
UniString aStr = rEntry.GetFull( FSYS_STYLE_HOST, sal_False );
UniString aVolume = rEntry.GetVolume() ;
aStr.ToUpperAscii();
if ( aVolume.Len() )
{
aStr += ' ';
aStr += aVolume;
}
pDriveList->InsertEntry( aStr );
}
UniString aPathStr = aPath.GetFull();
for ( i = 0; i < pDriveList->GetEntryCount(); ++i )
{
UniString aEntry = pDriveList->GetEntry(i);
xub_StrLen nLen = aEntry.Len();
nLen = nLen > 2 ? 2 : nLen;
if ( aEntry.CompareIgnoreCaseToAscii( aPathStr, nLen ) == COMPARE_EQUAL )
{
pDriveList->SelectEntryPos(i);
break;
}
}
}
}
void ImpPathDialog::PostExecute()
{
}
void ImpPathDialog::SetPath( UniString const & rPath )
{
aPath = DirEntry( rPath );
pSvPathDialog->EnterWait();
DirEntry aFile( rPath );
// Falls der Pfad eine Wildcard oder einen Filenamen enthaelt
// -> abschneiden und merken
if( FileStat( aFile ).GetKind() & (FSYS_KIND_FILE | FSYS_KIND_WILD) || !aFile.Exists() )
aFile.CutName();
// Neue Maske und neues Verzeichnis setzen, und Listboxen updaten
pEdit->SetText( rPath );
aFile.SetCWD( sal_True );
UpdateEntries( sal_True );
pSvPathDialog->LeaveWait();
}
void ImpPathDialog::SetPath( Edit const & rEdit )
{
UniString aPresetText = rEdit.GetText();
if( aPresetText.Len() )
SetPath( aPresetText );
}
UniString ImpPathDialog::GetPath() const
{
DirEntry aFile( pEdit->GetText() );
aFile.ToAbs();
return aFile.GetFull();
}
ImpFileDialog::ImpFileDialog( PathDialog* pDlg, WinBits nWinBits, RESOURCE_TYPE nType ) :
ImpPathDialog( pDlg, nType, sal_False )
{
bOpen = (nWinBits & WB_SAVEAS) == 0;
SvtResId aSvtResId = bOpen ? STR_FILEDLG_OPEN : STR_FILEDLG_SAVE;
// Titel setzen
GetFileDialog()->SetText( UniString( aSvtResId ) );
nDirCount = 0;
// initialize Controls if not used as a base class
if ( nType == WINDOW_FILEDIALOG )
InitControls();
pDlg->SetHelpId( HID_FILEDLG_OPENDLG );
}
ImpFileDialog::~ImpFileDialog()
{
for ( size_t i = 0, n = aFilterList.size(); i < n; ++i ) {
delete aFilterList[ i ];
}
aFilterList.clear();
delete pFileTitel;
if (pFileList && ( pFileList != pDirList ) )
delete pFileList;
delete pTypeTitel;
delete pTypeList;
}
void ImpFileDialog::InitControls()
{
UniString aEmptyStr;
const int nW = 160;
const int nH = 48; // Um den Dialog in eine akzeptable Form zu bringen
INITCONTROL( pFileTitel, FixedText, 0,
Point(10, 12), Size(nW, 18), UniString( SvtResId( STR_FILEDLG_FILE ) ), HID_FILEDLG_FILE );
INITCONTROL( pEdit, Edit, WB_BORDER,
Point(10, 31), Size(nW, 20), aEmptyStr, HID_FILEDLG_EDIT ); // aMask()
INITCONTROL( pFileList, ListBox, WB_SORT | WB_AUTOHSCROLL | WB_BORDER,
Point(10, 58), Size(nW, 180-nH), aEmptyStr, HID_FILEDLG_FILES );
INITCONTROL( pDirTitel, FixedText, 0,
Point(nW+20, 12), Size(nW, 18), UniString( SvtResId( STR_FILEDLG_DIR ) ), HID_FILEDLG_DIR );
INITCONTROL( pDirPath, FixedInfo, WB_PATHELLIPSIS,
Point(nW+20, 33), Size(nW, 20), aPath.GetFull(), HID_FILEDLG_PATH );
INITCONTROL( pDirList, KbdListBox, WB_AUTOHSCROLL | WB_BORDER,
Point(nW+20, 58), Size(nW, 180-nH ), aEmptyStr, HID_FILEDLG_DIRS );
INITCONTROL( pTypeTitel, FixedText, 0,
Point(10, 246-nH), Size(nW, 18), UniString( SvtResId( STR_FILEDLG_TYPE ) ), HID_FILEDLG_TYPE );
#ifndef UNX
INITCONTROL( pTypeList, ListBox, WB_DROPDOWN,
Point(10, 265-nH ), Size(nW, 100 ), aEmptyStr, HID_FILEDLG_TYPES );
INITCONTROL( pDriveTitle, FixedText, 0,
Point(nW+20, 246-nH), Size(nW, 18), UniString( SvtResId( STR_FILEDLG_DRIVES ) ), HID_FILEDLG_DRIVE );
INITCONTROL( pDriveList, ListBox, WB_DROPDOWN,
Point(nW+20, 265-nH ), Size(nW, 100 ), aEmptyStr, HID_FILEDLG_DRIVES );
pNewDirBtn = NULL;
pHomeBtn = NULL;
#else
INITCONTROL( pTypeList, ListBox, WB_DROPDOWN,
Point(10, 265-nH ), Size(2*nW+20, 100 ), aEmptyStr, HID_FILEDLG_TYPES );
pDriveTitle = NULL;
pDriveList = NULL;
pNewDirBtn = NULL;
pHomeBtn = NULL;
#endif
const long nButtonStartX = 2*nW+20+15;
INITCONTROL( pOkBtn, PushButton, WB_DEFBUTTON,
Point(nButtonStartX, 10), Size(STD_BTN_WIDTH, STD_BTN_HEIGHT),
Button::GetStandardText( BUTTON_OK ), "" );
INITCONTROL( pCancelBtn, CancelButton, 0,
Point(nButtonStartX, 45 ), Size(STD_BTN_WIDTH, STD_BTN_HEIGHT),
Button::GetStandardText( BUTTON_CANCEL ), "" );
pLoadBtn = 0;
GetFileDialog()->SetOutputSizePixel( Size(nButtonStartX+STD_BTN_WIDTH+10, 298-nH) );
nOwnChilds = GetPathDialog()->GetChildCount();
// Handler setzen
if (pDriveList)
pDriveList->SetSelectHdl( LINK( this, ImpFileDialog, SelectHdl ) );
if (pDirList)
pDirList->SetDoubleClickHdl(LINK( this, ImpFileDialog, DblClickHdl) );
if (pOkBtn)
pOkBtn->SetClickHdl( LINK( this, ImpFileDialog, ClickHdl) );
if (pCancelBtn)
pCancelBtn->SetClickHdl( LINK( this, ImpFileDialog, ClickHdl) );
if( pFileList )
{
pFileList->SetSelectHdl( LINK( this, ImpFileDialog, SelectHdl ) );
pFileList->SetDoubleClickHdl( LINK( this, ImpFileDialog, DblClickHdl ) );
}
if( pTypeList )
pTypeList->SetSelectHdl( LINK( this, ImpFileDialog, DblClickHdl ) );
}
IMPL_LINK( ImpFileDialog, SelectHdl, ListBox *, p )
{
if( p == pDriveList )
{
UniString aDrive ( pDriveList->GetSelectEntry(), 0, 2);
aDrive += '\\';
SetPath( aDrive );
}
else if (p == pFileList)
{
// Ausgewaehltes File in das Edit stellen
pEdit->SetText( pFileList->GetSelectEntry() );
GetFileDialog()->FileSelect();
}
return 0;
}
IMPL_LINK( ImpFileDialog, DblClickHdl, ListBox *, pBox )
{
// isolate the pure name of the entry
// removing trailing stuff and leading spaces
UniString aEntry( pBox->GetSelectEntry() );
aEntry.EraseLeadingChars( ' ' );
sal_uInt16 nPos = aEntry.Search( '/' );
aEntry.Erase( nPos );
// build the absolute path to the selected item
DirEntry aNewPath;
aNewPath.ToAbs();
if( ( pDirList != pFileList ) && ( pBox == pDirList ) )
{
// SVLOOK
sal_uInt16 nCurPos = pDirList->GetSelectEntryPos();
// Wenn es schon das aktuelle ist, dann mache nichts
if( nCurPos == nDirCount-1 )
return 0;
// Wird nach oben gewechselt
if( nCurPos < nDirCount )
aNewPath = aNewPath[nDirCount-nCurPos-1];
else
aNewPath += aEntry;
}
else
{
// non-SVLOOK
if( aEntry == UniString( SvtResId( STR_FILEDLG_GOUP ) ) )
aEntry.AssignAscii( ".." );
aNewPath += aEntry;
}
if( pBox == pFileList )
{
DirEntry aFile( aEntry );
// Abfrage, ob File ueberschrieben werden soll...
if( !FileStat(aFile).IsKind(FSYS_KIND_DIR) && IsFileOk( aFile ) )
{
// dann kompletten Pfad mit Filenamen merken und Dialog beenden
aPath = aNewPath;
GetFileDialog()->EndDialog( sal_True );
}
}
GetFileDialog()->EnterWait();
UniString aFull = aNewPath.GetFull();
if( ( ( pBox == pDirList ) && ( pDirList != pFileList ) ) ||
( ( pDirList == pFileList ) && FileStat( aNewPath ).GetKind() & FSYS_KIND_DIR ) )
{
// Neuen Pfad setzen und Listboxen updaten
aPath = aNewPath;
if( !aPath.SetCWD( sal_True ) )
{
if( ErrorBox( GetFileDialog(), WB_OK_CANCEL|WB_DEF_OK,
UniString( SvtResId( STR_FILEDLG_CANTCHDIR ) ) ).Execute() == RET_CANCEL )
{
GetFileDialog()->EndDialog( sal_False );
}
}
UpdateEntries( sal_True );
GetFileDialog()->FileSelect();
}
if( pBox == pTypeList )
{
// Neue Maske setzen, und Listboxen updaten
size_t nCurPos = pTypeList->GetSelectEntryPos();
if( nCurPos+1 > aFilterList.size() )
aMask.setGlob(UniString::CreateFromAscii( ALLFILES ));
else
{
UniString aFilterListMask = aFilterList[ nCurPos ]->aMask;
aMask = WildCard( aFilterListMask, ';' );
}
pEdit->SetText( aMask.getGlob() );
UpdateEntries( sal_False );
GetFileDialog()->FilterSelect();
}
GetFileDialog()->LeaveWait();
return 0;
}
IMPL_LINK( ImpFileDialog, ClickHdl, Button*, pBtn )
{
if( ( pBtn == pOkBtn ) || ( pBtn == pLoadBtn ) )
{
DirEntry aFile( pEdit->GetText() );
// Existiert File / File ueberschreiben
if( IsFileOk( aFile ) )
{
// Ja, dann kompletten Pfad mit Filenamen merken und Dialog beenden
aPath = aFile;
aPath.ToAbs();
GetFileDialog()->EndDialog( sal_True );
}
else
{
GetFileDialog()->EnterWait();
// Falls der Pfad eine Wildcard oder einen Filenamen enthaelt
// -> abschneiden und merken
if( FileStat( aFile ).GetKind() & (FSYS_KIND_FILE | FSYS_KIND_WILD) || !aFile.Exists() )
{
aMask.setGlob(aFile.CutName());
}
// Neue Maske und neues Verzeichnis setzen, und Listboxen updaten
pEdit->SetText( aMask.getGlob() );
aFile.SetCWD( sal_True );
UpdateEntries( sal_True );
GetFileDialog()->LeaveWait();
}
}
else if( pBtn == pCancelBtn )
GetFileDialog()->EndDialog( sal_False );
return 0;
}
void ImpFileDialog::UpdateEntries( const sal_Bool bWithDirs )
{
GetFileDialog()->EnterWait();
UniString aTabString;
DirEntry aTmpPath;
aTmpPath.ToAbs();
nDirCount = aTmpPath.Level();
if( pFileList )
{
pFileList->SetUpdateMode( sal_False );
pFileList->Clear();
}
if( bWithDirs && (pDirList != pFileList) )
{
pDirList->SetUpdateMode( sal_False );
pDirList->Clear();
for( sal_uInt16 i = nDirCount; i > 0; i-- )
{
UniString aEntryStr( aTabString );
aEntryStr += aTmpPath[i-1].GetName();
pDirList->InsertEntry( aEntryStr );
aTabString.AppendAscii( " ", 2 );
}
}
// for the combined box insert a '..'
// (this happens only if WB_3DLOOK is not set)
if( pDirList == pFileList && nDirCount != 1 )
pFileList->InsertEntry( UniString( SvtResId( STR_FILEDLG_GOUP ) ) );
// scan the directory
DirEntry aCurrent;
aCurrent.ToAbs();
Dir aDir( aCurrent, FSYS_KIND_DIR|FSYS_KIND_FILE );
sal_uInt16 nEntries = aDir.Count();
// TempMask, weil Vergleich case-sensitiv
sal_Bool bMatchCase = sal_False; //aCurrent.IsCaseSensitive();
UniString aWildCard( aMask.getGlob() );
if ( !bMatchCase )
aWildCard.ToLowerAscii();
WildCard aTmpMask( aWildCard, ';' );
if ( nEntries )
{
UniStringList aSortDirList;
const comphelper::string::NaturalStringSorter& rSorter =
::vcl::unohelper::getNaturalStringSorterForAppLocale();
for ( sal_uInt16 n = 0; n < nEntries; n++ )
{
DirEntry& rEntry = aDir[n];
UniString aName( rEntry.GetName() );
if( aName.Len() &&
( ( ( aName.GetChar(0) != '.' ) ||
( ( aName.GetChar(0) == '.' ) && aMask.getGlob()[0] == '.' ) )
&& rEntry.Exists() ) )
{
FileStat aFileStat( rEntry );
UniString aTmpName( aName );
if ( !bMatchCase )
aTmpName.ToLowerAscii();
if( ( aFileStat.GetKind() & FSYS_KIND_FILE ) && aTmpMask.Matches( aTmpName ) )
{
if( pFileList )
pFileList->InsertEntry( aName );
}
else if( bWithDirs && ( aFileStat.GetKind() & FSYS_KIND_DIR ) )
{
if( pDirList == pFileList )
{
UniString aEntryStr( aName );
aEntryStr += '/';
pDirList->InsertEntry( aEntryStr );
}
else
{
size_t l = 0;
for( l = 0; l < aSortDirList.size(); l++ )
if( rSorter.compare( *aSortDirList[ l ], aName ) > 0 )
break;
if ( l < aSortDirList.size() ) {
UniStringList::iterator it = aSortDirList.begin();
::std::advance( it, l );
aSortDirList.insert( it, new UniString( aName ) );
} else {
aSortDirList.push_back( new UniString( aName ) );
}
}
}
}
}
for( size_t l = 0; l < aSortDirList.size(); l++ )
{
UniString aEntryStr( aTabString );
aEntryStr += *aSortDirList[ l ];
pDirList->InsertEntry( aEntryStr );
delete aSortDirList[ l ];
}
}
if( bWithDirs )
UpdateDirs( aTmpPath );
if( pFileList )
{
if ( pDirList == pFileList && nDirCount > 1 )
pFileList->SelectEntryPos( 1 );
else
pFileList->SetNoSelection();
pFileList->SetUpdateMode( sal_True );
pFileList->Invalidate();
pFileList->Update();
}
if( pDriveList )
{
if( pDirList->GetEntryCount() > 0 )
{
UniString aStr( pDirList->GetEntry( 0 ) );
aStr.Erase( 2 );
aStr.ToLowerAscii();
pDriveList->SelectEntry( aStr );
}
}
GetFileDialog()->LeaveWait();
}
sal_Bool ImpFileDialog::IsFileOk( const DirEntry& rDirEntry )
{
if( FileStat( rDirEntry ).GetKind() & (FSYS_KIND_WILD | FSYS_KIND_DEV) )
return sal_False;
if( FileStat( rDirEntry ).GetKind() & FSYS_KIND_DIR )
{
if( pFileList )
return sal_False;
}
else if( bOpen )
{
// Datei vorhanden ?
if( !FileStat( rDirEntry ).IsKind( FSYS_KIND_FILE ) )
{
UniString aErrorString( SvtResId( STR_FILEDLG_CANTOPENFILE ) );
aErrorString.AppendAscii( "\n[" );
aErrorString += rDirEntry.GetFull();
aErrorString += ']';
InfoBox aBox( GetFileDialog(),
aErrorString );
aBox.Execute();
return sal_False;
}
}
else
{
// Datei vorhanden ?
if( FileStat( ExtendFileName( rDirEntry ) ).IsKind( FSYS_KIND_FILE ) )
{
UniString aQueryString( SvtResId( STR_FILEDLG_OVERWRITE ) );
aQueryString.AppendAscii( "\n[" );
aQueryString += rDirEntry.GetFull();
aQueryString += ']';
QueryBox aBox( GetFileDialog(),
WinBits( WB_YES_NO | WB_DEF_NO ),
aQueryString );
if( aBox.Execute() != RET_YES )
return sal_False;
}
}
return GetFileDialog()->OK() != 0;
}
void ImpFileDialog::SetPath( UniString const & rPath )
{
aPath = DirEntry( rPath );
GetFileDialog()->EnterWait();
DirEntry aFile( rPath );
// Falls der Pfad eine Wildcard oder einen Filenamen enthaelt
// -> abschneiden und merken
if( FileStat( aFile ).GetKind() & (FSYS_KIND_FILE | FSYS_KIND_WILD) || !aFile.Exists() )
{
aMask.setGlob(aFile.CutName());
// Neue Maske und neues Verzeichnis setzen, und Listboxen updaten
if( pDirList )
pEdit->SetText( aMask.getGlob() );
else
pEdit->SetText( rPath );
}
aFile.SetCWD( sal_True );
UpdateEntries( sal_True );
GetFileDialog()->LeaveWait();
}
void ImpFileDialog::SetPath( Edit const& rEdit )
{
UniString aPresetText = rEdit.GetText();
if( aPresetText.Len() )
SetPath( aPresetText );
}
void ImpFileDialog::AddFilter( const UniString& rFilter, const UniString& rMask )
{
aFilterList.push_back( new ImpFilterItem( rFilter, rMask ) );
if( pTypeList )
pTypeList->InsertEntry( rFilter, LISTBOX_APPEND );
if( !GetCurFilter().Len() )
SetCurFilter( rFilter );
}
void ImpFileDialog::SetCurFilter( const UniString& rFilter )
{
if( !pTypeList )
return;
for ( size_t i = 0, n = aFilterList.size(); i < n; ++i ) {
if ( aFilterList[ i ]->aName == rFilter ) {
pTypeList->SelectEntryPos( sal_uInt16( i ) );
return;
}
}
pTypeList->SetNoSelection();
}
UniString ImpFileDialog::GetCurFilter() const
{
UniString aFilter;
if ( pTypeList )
aFilter = pTypeList->GetSelectEntry();
return aFilter;
}
void ImpFileDialog::PreExecute()
{
// ListBoxen erst unmittelbar vor Execute fuellen
// (damit vor Execute der Pfad umgesetzt werden kann, ohne das immer die
// Listboxen sofort upgedatet werden)
GetFileDialog()->EnterWait();
// Wenn kein Filter vorhanden, dann auch keine FilterBox
if( pTypeList && !pTypeList->GetEntryCount() )
{
// pTypeList->InsertEntry( "* (all files)" );
pTypeTitel->Disable();
pTypeList->Disable();
}
if( pTypeList )
{
sal_uInt16 nCurType = pTypeList->GetSelectEntryPos();
if( nCurType < aFilterList.size() )
{
UniString aFilterListMask = aFilterList[ nCurType ]->aMask;
if( aFilterListMask.Search( ';' ) == STRING_NOTFOUND ) // kein ; in der Maske
aMask = WildCard( aFilterListMask, '\0' );
else // ; in der Maske, muss in der Wildcard beruecksichtigt werden
aMask = WildCard( aFilterListMask, ';' );
}
else
aMask.setGlob(UniString::CreateFromAscii( ALLFILES ));
}
else
aMask.setGlob(UniString::CreateFromAscii( ALLFILES ));
// Neue Maske setzen
if( pEdit->GetText().Len() == 0 )
pEdit->SetText( aMask.getGlob() );
ImpPathDialog::PreExecute();
GetFileDialog()->LeaveWait();
}
UniString ImpFileDialog::GetPath() const
{
DirEntry aFile( pEdit->GetText() );
return ExtendFileName( aFile );
}
UniString ImpFileDialog::ExtendFileName( DirEntry aEntry ) const
{
aEntry.ToAbs();
// das ganze Theater hier ohnehin nur machen, wenn Dateiname
// ohne Extension angegeben wurde
if( !aEntry.GetExtension().Len() )
{
UniString aPostfix; // hier kommt die ausgesuchte Extension herein
// ist ein Filter mit Extension gesetzt?
sal_uInt16 nChosenFilterPos = pTypeList->GetSelectEntryPos();
if( nChosenFilterPos != LISTBOX_ENTRY_NOTFOUND )
{
UniString aExtensionMask = GetFileDialog()->GetFilterType( nChosenFilterPos );
// aExtension ist z.B. *.sdw, alles bis einschliesslich Punkt abschneiden
UniString aExtension = aExtensionMask.Copy( aExtensionMask.Search( '.' )+1 );
// hat der Filter ueberhaupt eine Extension
if( aExtension.Len() )
{
// keine Wildcards enthalten?
if( ( aExtension.Search( '*' ) == STRING_NOTFOUND ) &&
( aExtension.Search( '?' ) == STRING_NOTFOUND ) )
{
// OK, Filter hat Extension ohne Wildcards -> verwenden
aPostfix = aExtension;
}
else
{
// Filter hat Extension mit Wildcards (z.B. *.*) -> nicht verwenden
aPostfix.Erase();
}
}
else
{
// Filter hatte keine Extension (schwer vorstellbar) -> nichts anhaengen
aPostfix.Erase();
}
}
else
{
// kein Filter gefunden (merkw<6B>rdig) -> Default-Extension anhaengen
aPostfix = GetFileDialog()->GetDefaultExt();
}
// jetzt kann es mit dem Anhaengen losgehen
const sal_Unicode* pExt = aPostfix.GetBuffer();
while( *pExt == '*' || *pExt == '?' )
pExt++;
if( *pExt )
{
UniString aName = aEntry.GetName();
if( *pExt != '.' )
aName += '.';
aName += pExt;
aEntry.SetName( aName );
}
}
return aEntry.GetFull();
}
void ImpSvFileDlg::CreateDialog( PathDialog* pSvDlg, WinBits nStyle, RESOURCE_TYPE nType, sal_Bool bCreate )
{
delete pDlg;
if ( nType == WINDOW_PATHDIALOG )
pDlg = new ImpPathDialog( pSvDlg, nType, bCreate );
else
pDlg = new ImpFileDialog( pSvDlg, nStyle, nType );
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */