Coverage Report

Created: 2026-03-31 11:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/svx/source/gallery2/galmisc.cxx
Line
Count
Source
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
#include <sal/config.h>
21
22
#include <sot/storage.hxx>
23
#include <unotools/streamwrap.hxx>
24
#include <comphelper/processfactory.hxx>
25
#include <comphelper/string.hxx>
26
#include <ucbhelper/content.hxx>
27
#include <com/sun/star/ucb/ContentCreationException.hpp>
28
#include <tools/urlobj.hxx>
29
#include <vcl/graphicfilter.hxx>
30
#include <svl/itempool.hxx>
31
#include <sfx2/docfile.hxx>
32
#include <vcl/svapp.hxx>
33
#include <vcl/window.hxx>
34
#include <svx/svdpage.hxx>
35
#include <svx/dialmgr.hxx>
36
#include <svx/svdograf.hxx>
37
#include <svx/fmmodel.hxx>
38
#include <svx/unomodel.hxx>
39
#include "codec.hxx"
40
#include <svx/strings.hrc>
41
#include <svx/galtheme.hxx>
42
#include <svx/galmisc.hxx>
43
#include <osl/diagnose.h>
44
#include <com/sun/star/awt/XProgressMonitor.hpp>
45
#include <com/sun/star/ucb/TransferInfo.hpp>
46
#include <com/sun/star/ucb/NameClash.hpp>
47
#include <memory>
48
49
using namespace ::com::sun::star;
50
51
GalleryGraphicImportRet GalleryGraphicImport( const INetURLObject& rURL, Graphic& rGraphic,
52
                             OUString& rFilterName )
53
0
{
54
0
    GalleryGraphicImportRet  nRet = GalleryGraphicImportRet::IMPORT_NONE;
55
0
    SfxMedium   aMedium( rURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ), StreamMode::READ );
56
57
0
    aMedium.Download();
58
59
0
    SvStream* pIStm = aMedium.GetInStream();
60
61
0
    if( pIStm )
62
0
    {
63
0
        GraphicFilter& rGraphicFilter = GraphicFilter::GetGraphicFilter();
64
0
        sal_uInt16              nFormat;
65
66
0
        if( !rGraphicFilter.ImportGraphic( rGraphic, rURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ), *pIStm, GRFILTER_FORMAT_DONTKNOW, &nFormat ) )
67
0
        {
68
0
            rFilterName = rGraphicFilter.GetImportFormatName( nFormat );
69
0
            nRet = GalleryGraphicImportRet::IMPORT_FILE;
70
0
        }
71
0
    }
72
73
0
    return nRet;
74
0
}
75
76
bool GallerySvDrawImport( SvStream& rIStm, SdrModel& rModel )
77
0
{
78
0
    sal_uInt32  nVersion;
79
0
    bool        bRet = false;
80
81
0
    if( GalleryCodec::IsCoded( rIStm, nVersion ) )
82
0
    {
83
0
        SvMemoryStream  aMemStm( 65535, 65535 );
84
0
        GalleryCodec    aCodec( rIStm );
85
86
0
        aCodec.Read( aMemStm );
87
0
        aMemStm.Seek( 0 );
88
89
0
        if ( 2 == nVersion )
90
0
        {
91
            // recall to read as XML
92
0
            bRet = GallerySvDrawImport( aMemStm, rModel );
93
0
        }
94
0
    }
95
0
    else
96
0
    {
97
        // read as XML
98
0
        uno::Reference< io::XInputStream > xInputStream( new utl::OInputStreamWrapper( rIStm ) );
99
100
0
        rModel.GetItemPool().SetDefaultMetric( MapUnit::Map100thMM );
101
0
        uno::Reference< lang::XComponent > xComponent;
102
103
0
        bRet = SvxDrawingLayerImport( &rModel, xInputStream, xComponent, "com.sun.star.comp.Draw.XMLOasisImporter" );
104
0
        if( !bRet || (rModel.GetPageCount() == 0) )
105
0
        {
106
0
            rIStm.Seek(0);
107
0
            bRet = SvxDrawingLayerImport( &rModel, xInputStream, xComponent, "com.sun.star.comp.Draw.XMLImporter" );
108
0
        }
109
110
0
    }
111
112
0
    return bRet;
113
0
}
114
115
bool CreateIMapGraphic( const FmFormModel& rModel, Graphic& rGraphic, ImageMap& rImageMap )
116
0
{
117
0
    if (! rModel.GetPageCount() )
118
0
        return false;
119
120
0
    const SdrPage*      pPage = rModel.GetPage( 0 );
121
0
    const SdrObject*    pObj = pPage->GetObj( 0 );
122
123
0
    if ( pPage->GetObjCount() != 1 )
124
0
        return false;
125
0
    auto pGrafObj = dynamic_cast<const SdrGrafObj*>( pObj);
126
0
    if (!pGrafObj)
127
0
        return false;
128
129
0
    bool bRet = false;
130
0
    const sal_uInt16 nCount = pObj->GetUserDataCount();
131
132
    // Exist in the user data an IMap information?
133
0
    for ( sal_uInt16 i = 0; i < nCount; i++ )
134
0
    {
135
0
        const SdrObjUserData* pUserData = pObj->GetUserData( i );
136
137
0
        if ( ( pUserData->GetInventor() == SdrInventor::SgaImap ) && ( pUserData->GetId() == ID_IMAPINFO ) )
138
0
        {
139
0
            rGraphic = pGrafObj->GetGraphic();
140
0
            rImageMap = static_cast<const SgaIMapInfo*>( pUserData )->GetImageMap();
141
0
            bRet = true;
142
0
            break;
143
0
        }
144
0
    }
145
146
0
    return bRet;
147
0
}
148
149
OUString GetReducedString( const INetURLObject& rURL, sal_Int32 nMaxLen )
150
0
{
151
0
    OUString aReduced( rURL.GetMainURL( INetURLObject::DecodeMechanism::Unambiguous ) );
152
153
0
    aReduced = aReduced.copy(aReduced.lastIndexOf('/')+1);
154
155
0
    if( INetProtocol::PrivSoffice != rURL.GetProtocol() )
156
0
    {
157
0
        sal_Unicode     aDelimiter;
158
0
        const OUString  aPath( rURL.getFSysPath( FSysStyle::Detect, &aDelimiter ) );
159
0
        const OUString  aName( aReduced );
160
161
0
        if( aPath.getLength() > nMaxLen )
162
0
        {
163
0
            sal_Int32 nPathPrefixLen = nMaxLen - aName.getLength() - 4;
164
165
0
            if (nPathPrefixLen >= 0)
166
0
            {
167
0
                aReduced = OUString::Concat(aPath.subView(0, nPathPrefixLen)) + "..."
168
0
                    + OUStringChar(aDelimiter) + aName;
169
0
            }
170
0
            else
171
0
            {
172
0
                aReduced += "..." + OUStringChar(aDelimiter) + "..."
173
0
                    + aName.subView( aName.getLength() - (nMaxLen - 7) );
174
0
            }
175
0
        }
176
0
        else
177
0
            aReduced = aPath;
178
0
    }
179
180
0
    return aReduced;
181
0
}
182
183
OUString GetSvDrawStreamNameFromURL( const INetURLObject& rSvDrawObjURL )
184
0
{
185
0
    OUString aRet;
186
187
0
    if( rSvDrawObjURL.GetProtocol() == INetProtocol::PrivSoffice &&
188
0
        comphelper::string::getTokenCount(rSvDrawObjURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ), '/') == 3 )
189
0
    {
190
0
        aRet = rSvDrawObjURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ).getToken( 2, '/' );
191
0
    }
192
193
0
    return aRet;
194
0
}
195
196
bool FileExists( const INetURLObject& rURL )
197
0
{
198
0
    bool bRet = false;
199
200
0
    if( rURL.GetProtocol() != INetProtocol::NotValid )
201
0
    {
202
0
        try
203
0
        {
204
0
            ::ucbhelper::Content        aCnt( rURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ), uno::Reference< ucb::XCommandEnvironment >(), comphelper::getProcessComponentContext() );
205
0
            OUString    aTitle;
206
207
0
            aCnt.getPropertyValue(u"Title"_ustr) >>= aTitle;
208
0
            bRet = ( !aTitle.isEmpty() );
209
0
        }
210
0
        catch( const ucb::ContentCreationException& )
211
0
        {
212
0
        }
213
0
        catch( const uno::RuntimeException& )
214
0
        {
215
0
        }
216
0
        catch( const uno::Exception& )
217
0
        {
218
0
        }
219
0
    }
220
221
0
    return bRet;
222
0
}
223
224
bool CreateDir( const INetURLObject& rURL )
225
0
{
226
0
    bool bRet = FileExists( rURL );
227
228
0
    if( !bRet )
229
0
    {
230
0
        try
231
0
        {
232
0
            uno::Reference< ucb::XCommandEnvironment >  aCmdEnv;
233
0
            INetURLObject                           aParentURL( rURL );
234
0
            aParentURL.removeSegment();
235
0
            ::ucbhelper::Content                    aParent( aParentURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ), aCmdEnv, comphelper::getProcessComponentContext() );
236
0
            uno::Sequence< OUString >               aProps{ u"Title"_ustr };
237
0
            uno::Sequence< uno::Any >               aValues{ uno::Any(rURL.GetLastName()) };
238
239
0
            ::ucbhelper::Content aContent( rURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ), aCmdEnv, comphelper::getProcessComponentContext() );
240
0
            bRet = aParent.insertNewContent( u"application/vnd.sun.staroffice.fsys-folder"_ustr, aProps, aValues, aContent );
241
0
        }
242
0
        catch( const ucb::ContentCreationException& )
243
0
        {
244
0
        }
245
0
        catch( const uno::RuntimeException& )
246
0
        {
247
0
        }
248
0
        catch( const uno::Exception& )
249
0
        {
250
0
        }
251
0
    }
252
253
0
    return bRet;
254
0
}
255
256
bool CopyFile(  const INetURLObject& rSrcURL, const INetURLObject& rDstURL )
257
0
{
258
0
    bool bRet = false;
259
260
0
    try
261
0
    {
262
0
        ::ucbhelper::Content aDestPath( rDstURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ), uno::Reference< ucb::XCommandEnvironment >(), comphelper::getProcessComponentContext() );
263
264
0
        aDestPath.executeCommand( u"transfer"_ustr,
265
0
                                  uno::Any( ucb::TransferInfo( false, rSrcURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ),
266
0
                                                rDstURL.GetLastName(), ucb::NameClash::OVERWRITE ) ) );
267
0
        bRet = true;
268
0
    }
269
0
    catch( const ucb::ContentCreationException& )
270
0
    {
271
0
    }
272
0
    catch( const uno::RuntimeException& )
273
0
    {
274
0
    }
275
0
    catch( const uno::Exception& )
276
0
    {
277
0
    }
278
279
0
    return bRet;
280
0
}
281
282
bool KillFile( const INetURLObject& rURL )
283
0
{
284
0
    bool bRet = FileExists( rURL );
285
286
0
    if( bRet )
287
0
    {
288
0
        try
289
0
        {
290
0
            ::ucbhelper::Content aCnt( rURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ), uno::Reference< ucb::XCommandEnvironment >(), comphelper::getProcessComponentContext() );
291
0
            aCnt.executeCommand( u"delete"_ustr, uno::Any( true ) );
292
0
        }
293
0
        catch( const ucb::ContentCreationException& )
294
0
        {
295
0
            bRet = false;
296
0
        }
297
0
        catch( const uno::RuntimeException& )
298
0
        {
299
0
            bRet = false;
300
0
        }
301
0
        catch( const uno::Exception& )
302
0
        {
303
0
            bRet = false;
304
0
        }
305
0
    }
306
307
0
    return bRet;
308
0
}
309
310
311
GalleryProgress::GalleryProgress( const GraphicFilter* pFilter )
312
0
{
313
314
0
    uno::Reference< lang::XMultiServiceFactory > xMgr( ::comphelper::getProcessServiceFactory() );
315
316
0
    uno::Reference< awt::XProgressMonitor > xMonitor( xMgr->createInstance( u"com.sun.star.awt.XProgressMonitor"_ustr ),
317
0
                                                      uno::UNO_QUERY );
318
319
0
    if ( !xMonitor.is() )
320
0
        return;
321
322
0
    mxProgressBar = xMonitor;
323
324
0
    OUString aProgressText;
325
326
0
    if( pFilter )
327
0
    {
328
0
        aProgressText = SvxResId(RID_SVXSTR_GALLERY_FILTER);
329
//          pFilter->SetUpdatePercentHdl( LINK( this, GalleryProgress, Update ) );     // sj: progress wasn't working up from SO7 at all
330
//                                                                                     // so I am removing this. The gallery progress should
331
//                                                                                     // be changed to use the XStatusIndicator instead of XProgressMonitor
332
0
    }
333
0
    else
334
0
        aProgressText = "Gallery";
335
336
0
    xMonitor->addText( u"Gallery"_ustr, aProgressText, false ) ;
337
0
    mxProgressBar->setRange( 0, GALLERY_PROGRESS_RANGE );
338
0
}
339
340
GalleryProgress::~GalleryProgress()
341
0
{
342
0
}
343
344
void GalleryProgress::Update( sal_Int32 nVal, sal_Int32 nMaxVal )
345
0
{
346
0
    if( mxProgressBar.is() && nMaxVal )
347
0
        mxProgressBar->setValue( std::min<sal_Int32>( static_cast<double>(nVal) / nMaxVal * GALLERY_PROGRESS_RANGE,
348
0
                                                      GALLERY_PROGRESS_RANGE ) );
349
0
}
350
351
352
GalleryTransferable::GalleryTransferable( GalleryTheme* pTheme, sal_uInt32 nObjectPos, bool bLazy ) :
353
0
    mpTheme( pTheme ),
354
0
    meObjectKind( pTheme ? mpTheme->GetObjectKind(nObjectPos) : SgaObjKind::NONE),
355
0
    mnObjectPos( nObjectPos )
356
0
{
357
358
0
    InitData( bLazy );
359
0
}
360
361
void GalleryTransferable::SelectObject(sal_uInt32 nObjectPos)
362
0
{
363
0
    if (nObjectPos == mnObjectPos)
364
0
        return;
365
0
    ClearFormats();
366
0
    mnObjectPos = nObjectPos;
367
0
    meObjectKind = mpTheme ? mpTheme->GetObjectKind(mnObjectPos) : SgaObjKind::NONE;
368
0
    ObjectReleased();
369
0
    InitData(true);
370
0
}
371
372
GalleryTransferable::~GalleryTransferable()
373
0
{
374
0
}
375
376
void GalleryTransferable::InitData( bool bLazy )
377
0
{
378
0
    switch( meObjectKind )
379
0
    {
380
0
        case SgaObjKind::SvDraw:
381
0
        {
382
0
            if( !bLazy )
383
0
            {
384
0
                if( !mpGraphicObject )
385
0
                {
386
0
                    Graphic aGraphic;
387
388
0
                    if (mpTheme && mpTheme->GetGraphic(mnObjectPos, aGraphic))
389
0
                        mpGraphicObject.reset(new GraphicObject( std::move(aGraphic) ));
390
0
                }
391
392
0
                if( !mxModelStream )
393
0
                {
394
0
                    mxModelStream = SotTempStream::Create( u""_ustr );
395
0
                    mxModelStream->SetBufferSize( 16348 );
396
397
0
                    if (!mpTheme || !mpTheme->GetModelStream(mnObjectPos, *mxModelStream))
398
0
                        mxModelStream.reset();
399
0
                    else
400
0
                        mxModelStream->Seek( 0 );
401
0
                }
402
0
            }
403
0
        }
404
0
        break;
405
406
0
        case SgaObjKind::Animation:
407
0
        case SgaObjKind::Bitmap:
408
0
        case SgaObjKind::Inet:
409
0
        case SgaObjKind::Sound:
410
0
        {
411
0
            if( !mpURL )
412
0
            {
413
0
                mpURL.reset(new INetURLObject);
414
415
0
                if (!mpTheme || !mpTheme->GetURL(mnObjectPos, *mpURL))
416
0
                {
417
0
                    mpURL.reset();
418
0
                }
419
0
            }
420
421
0
            if( ( SgaObjKind::Sound != meObjectKind ) && !mpGraphicObject )
422
0
            {
423
0
                Graphic aGraphic;
424
425
0
                if (mpTheme && mpTheme->GetGraphic(mnObjectPos, aGraphic))
426
0
                    mpGraphicObject.reset(new GraphicObject( std::move(aGraphic) ));
427
0
            }
428
0
        }
429
0
        break;
430
431
0
        default:
432
0
            OSL_FAIL( "GalleryTransferable::GalleryTransferable: invalid object type" );
433
0
        break;
434
0
    }
435
0
}
436
437
void GalleryTransferable::AddSupportedFormats()
438
0
{
439
0
    if( SgaObjKind::SvDraw == meObjectKind )
440
0
    {
441
0
        AddFormat( SotClipboardFormatId::DRAWING );
442
0
        AddFormat( SotClipboardFormatId::SVXB );
443
0
        AddFormat( SotClipboardFormatId::GDIMETAFILE );
444
0
        AddFormat( SotClipboardFormatId::BITMAP );
445
0
    }
446
0
    else
447
0
    {
448
0
        if( mpURL )
449
0
            AddFormat( SotClipboardFormatId::SIMPLE_FILE );
450
451
0
        if( mpGraphicObject )
452
0
        {
453
0
            AddFormat( SotClipboardFormatId::SVXB );
454
455
0
            if( mpGraphicObject->GetType() == GraphicType::GdiMetafile )
456
0
            {
457
0
                AddFormat( SotClipboardFormatId::GDIMETAFILE );
458
0
                AddFormat( SotClipboardFormatId::BITMAP );
459
0
            }
460
0
            else
461
0
            {
462
0
                AddFormat( SotClipboardFormatId::BITMAP );
463
0
                AddFormat( SotClipboardFormatId::GDIMETAFILE );
464
0
            }
465
0
        }
466
0
    }
467
0
}
468
469
bool GalleryTransferable::GetData( const datatransfer::DataFlavor& rFlavor, const OUString& /*rDestDoc*/ )
470
0
{
471
0
    SotClipboardFormatId nFormat = SotExchange::GetFormat( rFlavor );
472
0
    bool        bRet = false;
473
474
0
    InitData( false );
475
476
0
    if( ( SotClipboardFormatId::DRAWING == nFormat ) && ( SgaObjKind::SvDraw == meObjectKind ) )
477
0
    {
478
0
        bRet = ( mxModelStream && SetObject( mxModelStream.get(), 0, rFlavor ) );
479
0
    }
480
0
    else if( ( SotClipboardFormatId::SIMPLE_FILE == nFormat ) && mpURL )
481
0
    {
482
0
        bRet = SetString( mpURL->GetMainURL( INetURLObject::DecodeMechanism::NONE ) );
483
0
    }
484
0
    else if( ( SotClipboardFormatId::SVXB == nFormat ) && mpGraphicObject )
485
0
    {
486
0
        bRet = SetGraphic( mpGraphicObject->GetGraphic() );
487
0
    }
488
0
    else if( ( SotClipboardFormatId::GDIMETAFILE == nFormat ) && mpGraphicObject )
489
0
    {
490
0
        bRet = SetGDIMetaFile( mpGraphicObject->GetGraphic().GetGDIMetaFile() );
491
0
    }
492
0
    else if( ( SotClipboardFormatId::BITMAP == nFormat || SotClipboardFormatId::PNG == nFormat)
493
0
        && mpGraphicObject )
494
0
    {
495
0
        bRet = SetBitmap(mpGraphicObject->GetGraphic().GetBitmap(), rFlavor);
496
0
    }
497
498
0
    return bRet;
499
0
}
500
501
bool GalleryTransferable::WriteObject( SvStream& rOStm, void* pUserObject,
502
                                           sal_uInt32, const datatransfer::DataFlavor& )
503
0
{
504
0
    bool bRet = false;
505
506
0
    if( pUserObject )
507
0
    {
508
0
        rOStm.WriteStream( *static_cast< SotStorageStream* >( pUserObject ) );
509
0
        bRet = ( rOStm.GetError() == ERRCODE_NONE );
510
0
    }
511
512
0
    return bRet;
513
0
}
514
515
void GalleryTransferable::DragFinished( sal_Int8 nDropAction )
516
0
{
517
0
    if (mpTheme)
518
0
    {
519
0
        mpTheme->SetDragging( false );
520
0
        mpTheme->SetDragPos( 0 );
521
0
    }
522
0
    if ( nDropAction )
523
0
    {
524
0
        vcl::Window *pFocusWindow = Application::GetFocusWindow();
525
0
        if ( pFocusWindow )
526
0
            pFocusWindow->GrabFocusToDocument();
527
0
    }
528
0
}
529
530
void GalleryTransferable::ObjectReleased()
531
0
{
532
0
    mxModelStream.reset();
533
0
    mpGraphicObject.reset();
534
0
    mpURL.reset();
535
0
}
536
537
bool GalleryTransferable::StartDrag()
538
0
{
539
0
    INetURLObject aURL;
540
0
    if (mpTheme && mpTheme->GetURL(mnObjectPos, aURL) && aURL.GetProtocol() != INetProtocol::NotValid)
541
0
    {
542
0
        mpTheme->SetDragging( true );
543
0
        mpTheme->SetDragPos( mnObjectPos );
544
0
        return false;
545
0
    }
546
0
    return true;
547
0
}
548
549
INetURLObject ImplGetURL(const GalleryObject* pObject)
550
0
{
551
0
    INetURLObject aURL;
552
553
0
    if (pObject)
554
0
        aURL = *pObject->m_oStorageUrl;
555
556
0
    return aURL;
557
0
}
558
559
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */