1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <sal/config.h>
22 #include <com/sun/star/document/XCmisDocument.hpp>
23 #include <com/sun/star/frame/XModel.hpp>
24 #include <com/sun/star/util/RevisionTag.hpp>
25 #include <com/sun/star/beans/NamedValue.hpp>
27 #include <officecfg/Office/Common.hxx>
28 #include <unotools/localedatawrapper.hxx>
29 #include <svl/intitem.hxx>
30 #include <svl/stritem.hxx>
31 #include <svl/itemset.hxx>
32 #include <unotools/useroptions.hxx>
33 #include <vcl/svapp.hxx>
34 #include <vcl/settings.hxx>
35 #include <tools/datetime.hxx>
37 #include <versdlg.hxx>
38 #include <sfx2/strings.hrc>
39 #include <sfx2/dialoghelper.hxx>
40 #include <sfx2/viewfrm.hxx>
41 #include <sfx2/sfxresid.hxx>
42 #include <sfx2/docfile.hxx>
43 #include <sfx2/objsh.hxx>
44 #include <sfx2/sfxsids.hrc>
45 #include <sfx2/dispatch.hxx>
47 #include <sfx2/sfxuno.hxx>
51 using namespace com::sun::star
;
58 DateTime aCreationDate
;
63 class SfxVersionTableDtor
66 std::vector
<std::unique_ptr
<SfxVersionInfo
>> aTableList
;
68 explicit SfxVersionTableDtor( const uno::Sequence
< util::RevisionTag
>& rInfo
);
69 explicit SfxVersionTableDtor( const uno::Sequence
< document::CmisVersion
> & rInfo
);
70 SfxVersionTableDtor(const SfxVersionTableDtor
&) = delete;
71 SfxVersionTableDtor
& operator=(const SfxVersionTableDtor
&) = delete;
74 { return aTableList
.size(); }
76 SfxVersionInfo
* at( size_t i
) const
77 { return aTableList
[ i
].get(); }
80 SfxVersionTableDtor::SfxVersionTableDtor( const uno::Sequence
< util::RevisionTag
>& rInfo
)
82 for ( const auto& rItem
: rInfo
)
84 std::unique_ptr
<SfxVersionInfo
> pInfo(new SfxVersionInfo
);
85 pInfo
->aName
= rItem
.Identifier
;
86 pInfo
->aComment
= rItem
.Comment
;
87 pInfo
->aAuthor
= rItem
.Author
;
89 pInfo
->aCreationDate
= DateTime( rItem
.TimeStamp
);
90 aTableList
.push_back( std::move(pInfo
) );
94 SfxVersionTableDtor::SfxVersionTableDtor( const uno::Sequence
< document::CmisVersion
>& rInfo
)
96 for ( const auto& rItem
: rInfo
)
98 std::unique_ptr
<SfxVersionInfo
> pInfo(new SfxVersionInfo
);
99 pInfo
->aName
= rItem
.Id
;
100 pInfo
->aComment
= rItem
.Comment
;
101 pInfo
->aAuthor
= rItem
.Author
;
103 pInfo
->aCreationDate
= DateTime( rItem
.TimeStamp
);
104 aTableList
.push_back( std::move(pInfo
) );
108 SfxVersionInfo::SfxVersionInfo()
109 : aCreationDate( DateTime::EMPTY
)
115 void setColSizes(weld::TreeView
& rVersionBox
)
117 // recalculate the datetime column width
118 int nWidestTime(rVersionBox
.get_pixel_size(getWidestDateTime(Application::GetSettings().GetLocaleDataWrapper(), false)).Width());
119 int nW1
= rVersionBox
.get_pixel_size(rVersionBox
.get_column_title(1)).Width();
121 int nMax
= std::max(nWidestTime
, nW1
) + 12; // max width + a little offset
122 const int nRest
= rVersionBox
.get_preferred_size().Width() - nMax
;
124 std::set
<OUString
> aAuthors
;
125 aAuthors
.insert(SvtUserOptions().GetFullName());
127 for (int i
= 0; i
< rVersionBox
.n_children(); ++i
)
129 aAuthors
.insert(reinterpret_cast<SfxVersionInfo
*>(rVersionBox
.get_id(i
).toInt64())->aAuthor
);
132 int nMaxAuthorWidth
= nRest
/4;
133 for (auto const& author
: aAuthors
)
135 nMaxAuthorWidth
= std::max
<int>(nMaxAuthorWidth
, rVersionBox
.get_pixel_size(author
).Width());
136 if (nMaxAuthorWidth
> nRest
/2)
138 nMaxAuthorWidth
= nRest
/2;
143 rVersionBox
.set_column_fixed_widths({ nMax
, nMaxAuthorWidth
});
147 SfxVersionDialog::SfxVersionDialog(weld::Window
* pParent
, SfxViewFrame
* pVwFrame
, bool bIsSaveVersionOnClose
)
148 : SfxDialogController(pParent
, "sfx/ui/versionsofdialog.ui", "VersionsOfDialog")
149 , m_pViewFrame(pVwFrame
)
150 , m_bIsSaveVersionOnClose(bIsSaveVersionOnClose
)
151 , m_xSaveButton(m_xBuilder
->weld_button("save"))
152 , m_xSaveCheckBox(m_xBuilder
->weld_check_button("always"))
153 , m_xOpenButton(m_xBuilder
->weld_button("open"))
154 , m_xViewButton(m_xBuilder
->weld_button("show"))
155 , m_xDeleteButton(m_xBuilder
->weld_button("delete"))
156 , m_xCompareButton(m_xBuilder
->weld_button("compare"))
157 , m_xCmisButton(m_xBuilder
->weld_button("cmis"))
158 , m_xVersionBox(m_xBuilder
->weld_tree_view("versions"))
160 m_xVersionBox
->set_size_request(m_xVersionBox
->get_approximate_digit_width() * 90,
161 m_xVersionBox
->get_height_rows(15));
162 setColSizes(*m_xVersionBox
);
164 Link
<weld::Button
&,void> aClickLink
= LINK( this, SfxVersionDialog
, ButtonHdl_Impl
);
165 m_xViewButton
->connect_clicked( aClickLink
);
166 m_xSaveButton
->connect_clicked( aClickLink
);
167 m_xDeleteButton
->connect_clicked( aClickLink
);
168 m_xCompareButton
->connect_clicked( aClickLink
);
169 m_xOpenButton
->connect_clicked( aClickLink
);
170 m_xSaveCheckBox
->connect_toggled(LINK(this, SfxVersionDialog
, ToggleHdl_Impl
));
171 m_xCmisButton
->connect_clicked( aClickLink
);
173 m_xVersionBox
->connect_changed( LINK( this, SfxVersionDialog
, SelectHdl_Impl
) );
174 m_xVersionBox
->connect_row_activated( LINK( this, SfxVersionDialog
, DClickHdl_Impl
) );
176 m_xVersionBox
->grab_focus();
178 // set dialog title (filename or docinfo title)
179 OUString sText
= m_xDialog
->get_title() +
180 " " + m_pViewFrame
->GetObjectShell()->GetTitle();
181 m_xDialog
->set_title(sText
);
186 static OUString
ConvertWhiteSpaces_Impl( const OUString
& rText
)
188 // converted linebreaks and tabs to blanks; it's necessary for the display
189 OUStringBuffer sConverted
;
190 const sal_Unicode
* pChars
= rText
.getStr();
197 sConverted
.append(' ');
201 sConverted
.append(*pChars
);
207 return sConverted
.makeStringAndClear();
210 void SfxVersionDialog::Init_Impl()
212 SfxObjectShell
*pObjShell
= m_pViewFrame
->GetObjectShell();
213 SfxMedium
* pMedium
= pObjShell
->GetMedium();
214 uno::Sequence
< util::RevisionTag
> aVersions
= pMedium
->GetVersionList( true );
215 m_pTable
.reset(new SfxVersionTableDtor( aVersions
));
216 m_xVersionBox
->freeze();
217 for (size_t n
= 0; n
< m_pTable
->size(); ++n
)
219 SfxVersionInfo
*pInfo
= m_pTable
->at( n
);
220 OUString aEntry
= formatDateTime(pInfo
->aCreationDate
, Application::GetSettings().GetLocaleDataWrapper(), false);
221 m_xVersionBox
->append(OUString::number(reinterpret_cast<sal_Int64
>(pInfo
)), aEntry
);
222 auto nLastRow
= m_xVersionBox
->n_children() - 1;
223 m_xVersionBox
->set_text(nLastRow
, pInfo
->aAuthor
, 1);
224 m_xVersionBox
->set_text(nLastRow
, ConvertWhiteSpaces_Impl(pInfo
->aComment
), 2);
226 m_xVersionBox
->thaw();
228 if (auto nCount
= m_pTable
->size())
229 m_xVersionBox
->select(nCount
- 1);
231 m_xSaveCheckBox
->set_active(m_bIsSaveVersionOnClose
);
233 bool bEnable
= !pObjShell
->IsReadOnly();
234 m_xSaveButton
->set_sensitive( bEnable
);
235 m_xSaveCheckBox
->set_sensitive( bEnable
);
237 m_xOpenButton
->set_sensitive(false);
238 m_xViewButton
->set_sensitive(false);
239 m_xDeleteButton
->set_sensitive(false);
240 m_xCompareButton
->set_sensitive(false);
242 if ( !officecfg::Office::Common::Misc::ExperimentalMode::get() )
243 m_xCmisButton
->hide( );
244 uno::Reference
<document::XCmisDocument
> xCmisDoc(pObjShell
->GetModel(), uno::UNO_QUERY
);
245 if (xCmisDoc
&& xCmisDoc
->isVersionable())
246 m_xCmisButton
->set_sensitive(true);
248 m_xCmisButton
->set_sensitive(false);
250 SelectHdl_Impl(*m_xVersionBox
);
253 SfxVersionDialog::~SfxVersionDialog()
257 void SfxVersionDialog::Open_Impl()
259 SfxObjectShell
*pObjShell
= m_pViewFrame
->GetObjectShell();
261 auto nPos
= m_xVersionBox
->get_selected_index();
262 SfxInt16Item
aItem( SID_VERSION
, nPos
+ 1);
263 SfxStringItem
aTarget( SID_TARGETNAME
, "_blank" );
264 SfxStringItem
aReferer( SID_REFERER
, "private:user" );
265 SfxStringItem
aFile( SID_FILE_NAME
, pObjShell
->GetMedium()->GetName() );
267 uno::Sequence
< beans::NamedValue
> aEncryptionData
;
268 if ( GetEncryptionData_Impl( pObjShell
->GetMedium()->GetItemSet(), aEncryptionData
) )
270 // there is a password, it should be used during the opening
271 SfxUnoAnyItem
aEncryptionDataItem( SID_ENCRYPTIONDATA
, uno::makeAny( aEncryptionData
) );
272 m_pViewFrame
->GetDispatcher()->ExecuteList(
273 SID_OPENDOC
, SfxCallMode::ASYNCHRON
,
274 { &aFile
, &aItem
, &aTarget
, &aReferer
, &aEncryptionDataItem
});
278 m_pViewFrame
->GetDispatcher()->ExecuteList(
279 SID_OPENDOC
, SfxCallMode::ASYNCHRON
,
280 { &aFile
, &aItem
, &aTarget
, &aReferer
});
283 m_xDialog
->response(RET_OK
);
286 IMPL_LINK_NOARG(SfxVersionDialog
, DClickHdl_Impl
, weld::TreeView
&, bool)
292 IMPL_LINK_NOARG(SfxVersionDialog
, SelectHdl_Impl
, weld::TreeView
&, void)
294 bool bEnable
= m_xVersionBox
->get_selected_index() != -1;
295 SfxObjectShell
* pObjShell
= m_pViewFrame
->GetObjectShell();
296 m_xDeleteButton
->set_sensitive(bEnable
&& !pObjShell
->IsReadOnly());
297 m_xOpenButton
->set_sensitive(bEnable
);
298 m_xViewButton
->set_sensitive(bEnable
);
300 const SfxPoolItem
*pDummy
=nullptr;
301 m_pViewFrame
->GetDispatcher()->QueryState( SID_DOCUMENT_MERGE
, pDummy
);
302 SfxItemState eState
= m_pViewFrame
->GetDispatcher()->QueryState( SID_DOCUMENT_COMPARE
, pDummy
);
303 m_xCompareButton
->set_sensitive(bEnable
&& eState
>= SfxItemState::DEFAULT
);
306 IMPL_LINK(SfxVersionDialog
, ButtonHdl_Impl
, weld::Button
&, rButton
, void)
308 SfxObjectShell
*pObjShell
= m_pViewFrame
->GetObjectShell();
310 int nEntry
= m_xVersionBox
->get_selected_index();
312 if (&rButton
== m_xSaveButton
.get())
314 SfxVersionInfo aInfo
;
315 aInfo
.aAuthor
= SvtUserOptions().GetFullName();
316 SfxViewVersionDialog_Impl
aDlg(m_xDialog
.get(), aInfo
, true);
317 short nRet
= aDlg
.run();
320 SfxStringItem
aComment( SID_DOCINFO_COMMENTS
, aInfo
.aComment
);
321 pObjShell
->SetModified();
322 const SfxPoolItem
* aItems
[2];
323 aItems
[0] = &aComment
;
325 m_pViewFrame
->GetBindings().ExecuteSynchron( SID_SAVEDOC
, aItems
);
326 m_xVersionBox
->freeze();
327 m_xVersionBox
->clear();
328 m_xVersionBox
->thaw();
332 else if (&rButton
== m_xDeleteButton
.get() && nEntry
!= -1)
334 SfxVersionInfo
* pInfo
= reinterpret_cast<SfxVersionInfo
*>(m_xVersionBox
->get_id(nEntry
).toInt64());
335 pObjShell
->GetMedium()->RemoveVersion_Impl(pInfo
->aName
);
336 pObjShell
->SetModified();
337 m_xVersionBox
->freeze();
338 m_xVersionBox
->clear();
339 m_xVersionBox
->thaw();
342 else if (&rButton
== m_xOpenButton
.get() && nEntry
!= -1)
346 else if (&rButton
== m_xViewButton
.get() && nEntry
!= -1)
348 SfxVersionInfo
* pInfo
= reinterpret_cast<SfxVersionInfo
*>(m_xVersionBox
->get_id(nEntry
).toInt64());
349 SfxViewVersionDialog_Impl
aDlg(m_xDialog
.get(), *pInfo
, false);
352 else if (&rButton
== m_xCompareButton
.get() && nEntry
!= -1)
354 SfxAllItemSet
aSet( pObjShell
->GetPool() );
355 aSet
.Put(SfxInt16Item(SID_VERSION
, nEntry
+ 1));
356 aSet
.Put(SfxStringItem(SID_FILE_NAME
, pObjShell
->GetMedium()->GetName()));
358 SfxItemSet
* pSet
= pObjShell
->GetMedium()->GetItemSet();
359 const SfxStringItem
* pFilterItem
= SfxItemSet::GetItem
<SfxStringItem
>(pSet
, SID_FILTER_NAME
, false);
360 const SfxStringItem
* pFilterOptItem
= SfxItemSet::GetItem
<SfxStringItem
>(pSet
, SID_FILE_FILTEROPTIONS
, false);
362 aSet
.Put( *pFilterItem
);
363 if ( pFilterOptItem
)
364 aSet
.Put( *pFilterOptItem
);
366 m_pViewFrame
->GetDispatcher()->Execute( SID_DOCUMENT_COMPARE
, SfxCallMode::ASYNCHRON
, aSet
);
367 m_xDialog
->response(RET_CLOSE
);
369 else if (&rButton
== m_xCmisButton
.get())
371 SfxCmisVersionsDialog
aDlg(m_xDialog
.get(), m_pViewFrame
);
376 IMPL_LINK(SfxVersionDialog
, ToggleHdl_Impl
, weld::Toggleable
&, rButton
, void)
378 if (&rButton
== m_xSaveCheckBox
.get())
380 m_bIsSaveVersionOnClose
= m_xSaveCheckBox
->get_active();
384 SfxViewVersionDialog_Impl::SfxViewVersionDialog_Impl(weld::Window
*pParent
, SfxVersionInfo
& rInfo
, bool bEdit
)
385 : SfxDialogController(pParent
, "sfx/ui/versioncommentdialog.ui", "VersionCommentDialog")
387 , m_xDateTimeText(m_xBuilder
->weld_label("timestamp"))
388 , m_xSavedByText(m_xBuilder
->weld_label("author"))
389 , m_xEdit(m_xBuilder
->weld_text_view("textview"))
390 , m_xOKButton(m_xBuilder
->weld_button("ok"))
391 , m_xCancelButton(m_xBuilder
->weld_button("cancel"))
392 , m_xCloseButton(m_xBuilder
->weld_button("close"))
394 OUString sAuthor
= rInfo
.aAuthor
.isEmpty() ? SfxResId(STR_NO_NAME_SET
) : rInfo
.aAuthor
;
396 const LocaleDataWrapper
& rLocaleWrapper( Application::GetSettings().GetLocaleDataWrapper() );
397 m_xDateTimeText
->set_label(m_xDateTimeText
->get_label() + formatDateTime(rInfo
.aCreationDate
, rLocaleWrapper
, false));
398 m_xSavedByText
->set_label(m_xSavedByText
->get_label() + sAuthor
);
399 m_xEdit
->set_text(rInfo
.aComment
);
400 m_xEdit
->set_size_request(40 * m_xEdit
->get_approximate_digit_width(),
401 7 * m_xEdit
->get_text_height());
402 m_xOKButton
->connect_clicked(LINK(this, SfxViewVersionDialog_Impl
, ButtonHdl
));
407 m_xCancelButton
->hide();
408 m_xEdit
->set_editable(false);
409 m_xDialog
->set_title(SfxResId(STR_VIEWVERSIONCOMMENT
));
410 m_xCloseButton
->grab_focus();
414 m_xDateTimeText
->hide();
415 m_xCloseButton
->hide();
416 m_xEdit
->grab_focus();
420 IMPL_LINK(SfxViewVersionDialog_Impl
, ButtonHdl
, weld::Button
&, rButton
, void)
422 assert(&rButton
== m_xOKButton
.get());
424 m_rInfo
.aComment
= m_xEdit
->get_text();
425 m_xDialog
->response(RET_OK
);
428 SfxCmisVersionsDialog::SfxCmisVersionsDialog(weld::Window
* pParent
, SfxViewFrame
* pVwFrame
)
429 : SfxDialogController(pParent
, "sfx/ui/versionscmis.ui", "VersionsCmisDialog")
430 , m_pViewFrame(pVwFrame
)
431 , m_xOpenButton(m_xBuilder
->weld_button("open"))
432 , m_xViewButton(m_xBuilder
->weld_button("show"))
433 , m_xDeleteButton(m_xBuilder
->weld_button("delete"))
434 , m_xCompareButton(m_xBuilder
->weld_button("compare"))
435 , m_xVersionBox(m_xBuilder
->weld_tree_view("versions"))
437 m_xVersionBox
->set_size_request(m_xVersionBox
->get_approximate_digit_width() * 90,
438 m_xVersionBox
->get_height_rows(15));
439 setColSizes(*m_xVersionBox
);
441 m_xVersionBox
->grab_focus();
443 OUString sText
= m_xDialog
->get_title() +
444 " " + m_pViewFrame
->GetObjectShell()->GetTitle();
445 m_xDialog
->set_title(sText
);
450 SfxCmisVersionsDialog::~SfxCmisVersionsDialog()
454 void SfxCmisVersionsDialog::LoadVersions()
456 SfxObjectShell
*pObjShell
= m_pViewFrame
->GetObjectShell();
457 uno::Sequence
< document::CmisVersion
> aVersions
= pObjShell
->GetCmisVersions( );
458 m_pTable
.reset(new SfxVersionTableDtor( aVersions
));
459 for (size_t n
= 0; n
< m_pTable
->size(); ++n
)
461 SfxVersionInfo
*pInfo
= m_pTable
->at( n
);
462 OUString aEntry
= formatDateTime(pInfo
->aCreationDate
, Application::GetSettings().GetLocaleDataWrapper(), false);
463 m_xVersionBox
->append(OUString::number(reinterpret_cast<sal_Int64
>(pInfo
)), aEntry
);
464 auto nLastRow
= m_xVersionBox
->n_children() - 1;
465 m_xVersionBox
->set_text(nLastRow
, pInfo
->aAuthor
, 1);
466 m_xVersionBox
->set_text(nLastRow
, ConvertWhiteSpaces_Impl(pInfo
->aComment
), 2);
469 if (auto nCount
= m_pTable
->size())
470 m_xVersionBox
->select(nCount
- 1);
473 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */