Coverage Report

Created: 2025-11-16 09:57

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/sfx2/source/appl/sfxpicklist.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 <comphelper/lok.hxx>
21
#include <comphelper/base64.hxx>
22
#include <com/sun/star/document/XDocumentProperties.hpp>
23
#include <unotools/historyoptions.hxx>
24
#include <unotools/useroptions.hxx>
25
#include <tools/datetime.hxx>
26
#include <tools/urlobj.hxx>
27
#include <svl/inethist.hxx>
28
#include <vcl/filter/PngImageWriter.hxx>
29
#include <vcl/svapp.hxx>
30
#include <officecfg/Office/Common.hxx>
31
32
33
#include <sfx2/app.hxx>
34
#include <sfxpicklist.hxx>
35
#include <sfx2/sfxsids.hrc>
36
#include <sfx2/event.hxx>
37
#include <sfx2/objsh.hxx>
38
#include <sfx2/docfile.hxx>
39
#include <openurlhint.hxx>
40
#include <sfx2/docfilt.hxx>
41
#include <sfx2/viewfrm.hxx>
42
43
44
using namespace ::com::sun::star::uno;
45
46
class SfxPickListImpl : public SfxListener
47
{
48
    /**
49
     * Adds the given document to the pick list (recent documents) if it satisfies
50
       certain requirements, e.g. being writable. Check implementation for requirement
51
       details.
52
     */
53
    static void AddDocumentToPickList(const SfxObjectShell* pDocShell, bool bNoThumbnail = false);
54
55
public:
56
    SfxPickListImpl(SfxApplication& rApp);
57
    virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) override;
58
};
59
60
void SfxPickListImpl::AddDocumentToPickList(const SfxObjectShell* pDocSh, bool bNoThumbnail)
61
0
{
62
0
    if (pDocSh->IsAvoidRecentDocs() || comphelper::LibreOfficeKit::isActive())
63
0
        return;
64
65
0
    SfxMedium *pMed = pDocSh->GetMedium();
66
0
    if( !pMed )
67
0
        return;
68
69
    // Unnamed Documents and embedded-Documents not in Picklist
70
0
    if ( !pDocSh->HasName() ||
71
0
            SfxObjectCreateMode::STANDARD != pDocSh->GetCreateMode() )
72
0
        return;
73
74
    // Help not in History
75
0
    INetURLObject aURL( pDocSh->IsDocShared() ? pDocSh->GetSharedFileURL() : pMed->GetOrigURL() );
76
0
    if ( aURL.GetProtocol() == INetProtocol::VndSunStarHelp )
77
0
        return;
78
79
    // add no document that forbids this
80
0
    if ( !pMed->IsUpdatePickList() )
81
0
        return;
82
83
    // ignore hidden documents
84
0
    if ( !SfxViewFrame::GetFirst( pDocSh ) )
85
0
        return;
86
87
0
    OUString  aTitle = pDocSh->GetTitle(SFX_TITLE_PICKLIST);
88
0
    OUString  aFilter;
89
0
    std::shared_ptr<const SfxFilter> pFilter = pMed->GetFilter();
90
0
    if ( pFilter )
91
0
        aFilter = pFilter->GetFilterName();
92
93
0
    std::optional<OUString> aThumbnail;
94
95
    // generate the thumbnail
96
    //fdo#74834: only generate thumbnail for history if the corresponding option is not disabled in the configuration
97
0
    if (!bNoThumbnail && !pDocSh->IsModified() && !Application::IsHeadlessModeEnabled() &&
98
0
            officecfg::Office::Common::History::RecentDocsThumbnail::get())
99
0
    {
100
        // not modified => the document matches what is in the shell
101
0
        const SfxUnoAnyItem* pEncryptionDataItem = pMed->GetItemSet().GetItem(SID_ENCRYPTIONDATA, false);
102
0
        if ( pEncryptionDataItem )
103
0
        {
104
            // encrypted document, will show a generic document icon instead
105
0
            aThumbnail = OUString();
106
0
        }
107
0
        else
108
0
        {
109
0
            Bitmap aResultBitmap = pDocSh->GetPreviewBitmap();
110
0
            if (!aResultBitmap.IsEmpty())
111
0
            {
112
0
                SvMemoryStream aStream(65535, 65535);
113
0
                vcl::PngImageWriter aWriter(aStream);
114
0
                if (aWriter.write(aResultBitmap))
115
0
                {
116
0
                    Sequence<sal_Int8> aSequence(static_cast<const sal_Int8*>(aStream.GetData()), aStream.Tell());
117
0
                    OUStringBuffer aBuffer;
118
0
                    ::comphelper::Base64::encode(aBuffer, aSequence);
119
0
                    aThumbnail = aBuffer.makeStringAndClear();
120
0
                }
121
0
            }
122
0
        }
123
0
    }
124
0
    ::std::optional<bool> const oIsReadOnly(pMed->IsOriginallyLoadedReadOnly());
125
126
    // add to svtool history options
127
0
    SvtHistoryOptions::AppendItem( EHistoryType::PickList,
128
0
            aURL.GetURLNoPass( INetURLObject::DecodeMechanism::NONE ),
129
0
            aFilter,
130
0
            aTitle,
131
0
            aThumbnail,
132
0
            oIsReadOnly);
133
134
0
    if ( aURL.GetProtocol() == INetProtocol::File )
135
0
        Application::AddToRecentDocumentList( aURL.GetURLNoPass( INetURLObject::DecodeMechanism::NONE ),
136
0
                                                                 pFilter ? pFilter->GetMimeType() : OUString(),
137
0
                                                                 pFilter ? pFilter->GetServiceName() : OUString() );
138
0
}
139
140
SfxPickList::SfxPickList(SfxApplication& rApp)
141
0
    : mxImpl(new SfxPickListImpl(rApp))
142
0
{
143
0
}
144
145
SfxPickList::~SfxPickList()
146
0
{
147
0
}
148
149
SfxPickListImpl::SfxPickListImpl(SfxApplication& rApp)
150
0
{
151
0
    StartListening(rApp);
152
0
}
153
154
void SfxPickListImpl::Notify( SfxBroadcaster&, const SfxHint& rHint )
155
0
{
156
0
    if (rHint.GetId() == SfxHintId::SfxOpenUrl)
157
0
    {
158
0
        const SfxOpenUrlHint* pOpenUrlHint = static_cast<const SfxOpenUrlHint*>(&rHint);
159
0
        INetURLHistory::GetOrCreate()->PutUrl( INetURLObject( pOpenUrlHint->GetDocumentURL() ));
160
0
    }
161
162
0
    if (rHint.GetId() != SfxHintId::ThisIsAnSfxEventHint)
163
0
        return;
164
165
0
    const SfxEventHint& rEventHint = static_cast<const SfxEventHint&>(rHint);
166
    // only ObjectShell-related events with media interest
167
0
    rtl::Reference<SfxObjectShell> pDocSh = rEventHint.GetObjShell();
168
0
    if( !pDocSh )
169
0
        return;
170
171
0
    switch (rEventHint.GetEventId())
172
0
    {
173
0
        case SfxEventHintId::CreateDoc:
174
0
        {
175
0
            bool bAllowModif = pDocSh->IsEnableSetModified();
176
0
            if ( bAllowModif )
177
0
                pDocSh->EnableSetModified( false );
178
179
0
            using namespace ::com::sun::star;
180
0
            uno::Reference<document::XDocumentProperties> xDocProps(
181
0
                pDocSh->getDocProperties());
182
0
            if (xDocProps.is()) {
183
0
                xDocProps->setAuthor( SvtUserOptions().GetFullName() );
184
0
                ::DateTime now( ::DateTime::SYSTEM );
185
0
                xDocProps->setCreationDate( now.GetUNODateTime() );
186
0
            }
187
188
0
            if ( bAllowModif )
189
0
                pDocSh->EnableSetModified( bAllowModif );
190
0
        }
191
0
        break;
192
193
0
        case SfxEventHintId::OpenDoc:
194
0
        case SfxEventHintId::SaveDocDone:
195
0
        case SfxEventHintId::SaveAsDocDone:
196
0
        case SfxEventHintId::SaveToDocDone:
197
0
        case SfxEventHintId::CloseDoc:
198
0
        {
199
0
            const bool bNoThumbnail = rEventHint.GetEventId() == SfxEventHintId::CloseDoc;
200
0
            AddDocumentToPickList(pDocSh.get(), bNoThumbnail);
201
0
        }
202
0
        break;
203
204
0
        case SfxEventHintId::SaveAsDoc:
205
0
        {
206
0
            SfxMedium *pMedium = pDocSh->GetMedium();
207
0
            if (!pMedium)
208
0
                return;
209
210
            // We're starting a "Save As". Add the current document (if it's
211
            // not a "new" document) to the "Recent Documents" list before we
212
            // switch to the new path.
213
            // If the current document is new, path will be empty.
214
0
            OUString path = pMedium->GetOrigURL();
215
0
            if (!path.isEmpty())
216
0
            {
217
0
                AddDocumentToPickList(pDocSh.get());
218
0
            }
219
0
        }
220
0
        break;
221
0
        default: break;
222
0
    }
223
0
}
224
225
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */