summaryrefslogtreecommitdiffstats
path: root/sfx2/source/dialog/versdlg.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sfx2/source/dialog/versdlg.cxx')
-rw-r--r--sfx2/source/dialog/versdlg.cxx473
1 files changed, 473 insertions, 0 deletions
diff --git a/sfx2/source/dialog/versdlg.cxx b/sfx2/source/dialog/versdlg.cxx
new file mode 100644
index 000000000..47f33b634
--- /dev/null
+++ b/sfx2/source/dialog/versdlg.cxx
@@ -0,0 +1,473 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+
+#include <com/sun/star/document/XCmisDocument.hpp>
+#include <com/sun/star/frame/XModel.hpp>
+#include <com/sun/star/util/RevisionTag.hpp>
+#include <com/sun/star/beans/NamedValue.hpp>
+
+#include <officecfg/Office/Common.hxx>
+#include <unotools/localedatawrapper.hxx>
+#include <svl/intitem.hxx>
+#include <svl/stritem.hxx>
+#include <svl/itemset.hxx>
+#include <unotools/useroptions.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/settings.hxx>
+#include <tools/datetime.hxx>
+
+#include <versdlg.hxx>
+#include <sfx2/strings.hrc>
+#include <sfx2/dialoghelper.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <sfx2/sfxresid.hxx>
+#include <sfx2/docfile.hxx>
+#include <sfx2/objsh.hxx>
+#include <sfx2/sfxsids.hrc>
+#include <sfx2/dispatch.hxx>
+
+#include <sfx2/sfxuno.hxx>
+#include <memory>
+#include <vector>
+
+using namespace com::sun::star;
+
+struct SfxVersionInfo
+{
+ OUString aName;
+ OUString aComment;
+ OUString aAuthor;
+ DateTime aCreationDate;
+
+ SfxVersionInfo();
+};
+
+class SfxVersionTableDtor
+{
+private:
+ std::vector<std::unique_ptr<SfxVersionInfo>> aTableList;
+public:
+ explicit SfxVersionTableDtor( const uno::Sequence < util::RevisionTag >& rInfo );
+ explicit SfxVersionTableDtor( const uno::Sequence < document::CmisVersion > & rInfo );
+ SfxVersionTableDtor(const SfxVersionTableDtor&) = delete;
+ SfxVersionTableDtor& operator=(const SfxVersionTableDtor&) = delete;
+
+ size_t size() const
+ { return aTableList.size(); }
+
+ SfxVersionInfo* at( size_t i ) const
+ { return aTableList[ i ].get(); }
+};
+
+SfxVersionTableDtor::SfxVersionTableDtor( const uno::Sequence < util::RevisionTag >& rInfo )
+{
+ for ( const auto& rItem : rInfo )
+ {
+ std::unique_ptr<SfxVersionInfo> pInfo(new SfxVersionInfo);
+ pInfo->aName = rItem.Identifier;
+ pInfo->aComment = rItem.Comment;
+ pInfo->aAuthor = rItem.Author;
+
+ pInfo->aCreationDate = DateTime( rItem.TimeStamp );
+ aTableList.push_back( std::move(pInfo) );
+ }
+}
+
+SfxVersionTableDtor::SfxVersionTableDtor( const uno::Sequence < document::CmisVersion >& rInfo )
+{
+ for ( const auto& rItem : rInfo )
+ {
+ std::unique_ptr<SfxVersionInfo> pInfo(new SfxVersionInfo);
+ pInfo->aName = rItem.Id;
+ pInfo->aComment = rItem.Comment;
+ pInfo->aAuthor = rItem.Author;
+
+ pInfo->aCreationDate = DateTime( rItem.TimeStamp );
+ aTableList.push_back( std::move(pInfo) );
+ }
+}
+
+SfxVersionInfo::SfxVersionInfo()
+ : aCreationDate( DateTime::EMPTY )
+{
+}
+
+namespace
+{
+ void setColSizes(weld::TreeView& rVersionBox)
+ {
+ // recalculate the datetime column width
+ int nWidestTime(rVersionBox.get_pixel_size(getWidestDateTime(Application::GetSettings().GetLocaleDataWrapper(), false)).Width());
+ int nW1 = rVersionBox.get_pixel_size(rVersionBox.get_column_title(1)).Width();
+
+ int nMax = std::max(nWidestTime, nW1) + 12; // max width + a little offset
+ const int nRest = rVersionBox.get_preferred_size().Width() - nMax;
+
+ std::set<OUString> aAuthors;
+ aAuthors.insert(SvtUserOptions().GetFullName());
+
+ for (int i = 0; i < rVersionBox.n_children(); ++i)
+ {
+ aAuthors.insert(weld::fromId<SfxVersionInfo*>(rVersionBox.get_id(i))->aAuthor);
+ }
+
+ int nMaxAuthorWidth = nRest/4;
+ for (auto const& author : aAuthors)
+ {
+ nMaxAuthorWidth = std::max<int>(nMaxAuthorWidth, rVersionBox.get_pixel_size(author).Width());
+ if (nMaxAuthorWidth > nRest/2)
+ {
+ nMaxAuthorWidth = nRest/2;
+ break;
+ }
+ }
+
+ rVersionBox.set_column_fixed_widths({ nMax, nMaxAuthorWidth });
+ }
+}
+
+SfxVersionDialog::SfxVersionDialog(weld::Window* pParent, SfxViewFrame* pVwFrame, bool bIsSaveVersionOnClose)
+ : SfxDialogController(pParent, "sfx/ui/versionsofdialog.ui", "VersionsOfDialog")
+ , m_pViewFrame(pVwFrame)
+ , m_bIsSaveVersionOnClose(bIsSaveVersionOnClose)
+ , m_xSaveButton(m_xBuilder->weld_button("save"))
+ , m_xSaveCheckBox(m_xBuilder->weld_check_button("always"))
+ , m_xOpenButton(m_xBuilder->weld_button("open"))
+ , m_xViewButton(m_xBuilder->weld_button("show"))
+ , m_xDeleteButton(m_xBuilder->weld_button("delete"))
+ , m_xCompareButton(m_xBuilder->weld_button("compare"))
+ , m_xCmisButton(m_xBuilder->weld_button("cmis"))
+ , m_xVersionBox(m_xBuilder->weld_tree_view("versions"))
+{
+ m_xVersionBox->set_size_request(m_xVersionBox->get_approximate_digit_width() * 90,
+ m_xVersionBox->get_height_rows(15));
+ setColSizes(*m_xVersionBox);
+
+ Link<weld::Button&,void> aClickLink = LINK( this, SfxVersionDialog, ButtonHdl_Impl );
+ m_xViewButton->connect_clicked( aClickLink );
+ m_xSaveButton->connect_clicked( aClickLink );
+ m_xDeleteButton->connect_clicked( aClickLink );
+ m_xCompareButton->connect_clicked( aClickLink );
+ m_xOpenButton->connect_clicked( aClickLink );
+ m_xSaveCheckBox->connect_toggled(LINK(this, SfxVersionDialog, ToggleHdl_Impl));
+ m_xCmisButton->connect_clicked( aClickLink );
+
+ m_xVersionBox->connect_changed( LINK( this, SfxVersionDialog, SelectHdl_Impl ) );
+ m_xVersionBox->connect_row_activated( LINK( this, SfxVersionDialog, DClickHdl_Impl ) );
+
+ m_xVersionBox->grab_focus();
+
+ // set dialog title (filename or docinfo title)
+ OUString sText = m_xDialog->get_title() +
+ " " + m_pViewFrame->GetObjectShell()->GetTitle();
+ m_xDialog->set_title(sText);
+
+ Init_Impl();
+}
+
+static OUString ConvertWhiteSpaces_Impl( const OUString& rText )
+{
+ // converted linebreaks and tabs to blanks; it's necessary for the display
+ OUStringBuffer sConverted;
+ const sal_Unicode* pChars = rText.getStr();
+ while ( *pChars )
+ {
+ switch ( *pChars )
+ {
+ case '\n' :
+ case '\t' :
+ sConverted.append(' ');
+ break;
+
+ default:
+ sConverted.append(*pChars);
+ }
+
+ ++pChars;
+ }
+
+ return sConverted.makeStringAndClear();
+}
+
+void SfxVersionDialog::Init_Impl()
+{
+ SfxObjectShell *pObjShell = m_pViewFrame->GetObjectShell();
+ SfxMedium* pMedium = pObjShell->GetMedium();
+ uno::Sequence < util::RevisionTag > aVersions = pMedium->GetVersionList( true );
+ m_pTable.reset(new SfxVersionTableDtor( aVersions ));
+ m_xVersionBox->freeze();
+ for (size_t n = 0; n < m_pTable->size(); ++n)
+ {
+ SfxVersionInfo *pInfo = m_pTable->at( n );
+ OUString aEntry = formatDateTime(pInfo->aCreationDate, Application::GetSettings().GetLocaleDataWrapper(), false);
+ m_xVersionBox->append(weld::toId(pInfo), aEntry);
+ auto nLastRow = m_xVersionBox->n_children() - 1;
+ m_xVersionBox->set_text(nLastRow, pInfo->aAuthor, 1);
+ m_xVersionBox->set_text(nLastRow, ConvertWhiteSpaces_Impl(pInfo->aComment), 2);
+ }
+ m_xVersionBox->thaw();
+
+ if (auto nCount = m_pTable->size())
+ m_xVersionBox->select(nCount - 1);
+
+ m_xSaveCheckBox->set_active(m_bIsSaveVersionOnClose);
+
+ bool bEnable = !pObjShell->IsReadOnly();
+ m_xSaveButton->set_sensitive( bEnable );
+ m_xSaveCheckBox->set_sensitive( bEnable );
+
+ m_xOpenButton->set_sensitive(false);
+ m_xViewButton->set_sensitive(false);
+ m_xDeleteButton->set_sensitive(false);
+ m_xCompareButton->set_sensitive(false);
+
+ if ( !officecfg::Office::Common::Misc::ExperimentalMode::get() )
+ m_xCmisButton->hide( );
+ uno::Reference<document::XCmisDocument> xCmisDoc(pObjShell->GetModel(), uno::UNO_QUERY);
+ if (xCmisDoc && xCmisDoc->isVersionable())
+ m_xCmisButton->set_sensitive(true);
+ else
+ m_xCmisButton->set_sensitive(false);
+
+ SelectHdl_Impl(*m_xVersionBox);
+}
+
+SfxVersionDialog::~SfxVersionDialog()
+{
+}
+
+void SfxVersionDialog::Open_Impl()
+{
+ SfxObjectShell *pObjShell = m_pViewFrame->GetObjectShell();
+
+ auto nPos = m_xVersionBox->get_selected_index();
+ SfxInt16Item aItem( SID_VERSION, nPos + 1);
+ SfxStringItem aTarget( SID_TARGETNAME, "_blank" );
+ SfxStringItem aReferer( SID_REFERER, "private:user" );
+ SfxStringItem aFile( SID_FILE_NAME, pObjShell->GetMedium()->GetName() );
+
+ uno::Sequence< beans::NamedValue > aEncryptionData;
+ if ( GetEncryptionData_Impl( pObjShell->GetMedium()->GetItemSet(), aEncryptionData ) )
+ {
+ // there is a password, it should be used during the opening
+ SfxUnoAnyItem aEncryptionDataItem( SID_ENCRYPTIONDATA, uno::Any( aEncryptionData ) );
+ m_pViewFrame->GetDispatcher()->ExecuteList(
+ SID_OPENDOC, SfxCallMode::ASYNCHRON,
+ { &aFile, &aItem, &aTarget, &aReferer, &aEncryptionDataItem });
+ }
+ else
+ {
+ m_pViewFrame->GetDispatcher()->ExecuteList(
+ SID_OPENDOC, SfxCallMode::ASYNCHRON,
+ { &aFile, &aItem, &aTarget, &aReferer });
+ }
+
+ m_xDialog->response(RET_OK);
+}
+
+IMPL_LINK_NOARG(SfxVersionDialog, DClickHdl_Impl, weld::TreeView&, bool)
+{
+ Open_Impl();
+ return true;
+}
+
+IMPL_LINK_NOARG(SfxVersionDialog, SelectHdl_Impl, weld::TreeView&, void)
+{
+ bool bEnable = m_xVersionBox->get_selected_index() != -1;
+ SfxObjectShell* pObjShell = m_pViewFrame->GetObjectShell();
+ m_xDeleteButton->set_sensitive(bEnable && !pObjShell->IsReadOnly());
+ m_xOpenButton->set_sensitive(bEnable);
+ m_xViewButton->set_sensitive(bEnable);
+
+ const SfxPoolItem *pDummy=nullptr;
+ m_pViewFrame->GetDispatcher()->QueryState( SID_DOCUMENT_MERGE, pDummy );
+ SfxItemState eState = m_pViewFrame->GetDispatcher()->QueryState( SID_DOCUMENT_COMPARE, pDummy );
+ m_xCompareButton->set_sensitive(bEnable && eState >= SfxItemState::DEFAULT);
+}
+
+IMPL_LINK(SfxVersionDialog, ButtonHdl_Impl, weld::Button&, rButton, void)
+{
+ SfxObjectShell *pObjShell = m_pViewFrame->GetObjectShell();
+
+ int nEntry = m_xVersionBox->get_selected_index();
+
+ if (&rButton == m_xSaveButton.get())
+ {
+ SfxVersionInfo aInfo;
+ aInfo.aAuthor = SvtUserOptions().GetFullName();
+ SfxViewVersionDialog_Impl aDlg(m_xDialog.get(), aInfo, true);
+ short nRet = aDlg.run();
+ if (nRet == RET_OK)
+ {
+ SfxStringItem aComment( SID_DOCINFO_COMMENTS, aInfo.aComment );
+ pObjShell->SetModified();
+ const SfxPoolItem* aItems[2];
+ aItems[0] = &aComment;
+ aItems[1] = nullptr;
+ m_pViewFrame->GetBindings().ExecuteSynchron( SID_SAVEDOC, aItems );
+ m_xVersionBox->freeze();
+ m_xVersionBox->clear();
+ m_xVersionBox->thaw();
+ Init_Impl();
+ }
+ }
+ else if (&rButton == m_xDeleteButton.get() && nEntry != -1)
+ {
+ SfxVersionInfo* pInfo = weld::fromId<SfxVersionInfo*>(m_xVersionBox->get_id(nEntry));
+ pObjShell->GetMedium()->RemoveVersion_Impl(pInfo->aName);
+ pObjShell->SetModified();
+ m_xVersionBox->freeze();
+ m_xVersionBox->clear();
+ m_xVersionBox->thaw();
+ Init_Impl();
+ }
+ else if (&rButton == m_xOpenButton.get() && nEntry != -1)
+ {
+ Open_Impl();
+ }
+ else if (&rButton == m_xViewButton.get() && nEntry != -1)
+ {
+ SfxVersionInfo* pInfo = weld::fromId<SfxVersionInfo*>(m_xVersionBox->get_id(nEntry));
+ SfxViewVersionDialog_Impl aDlg(m_xDialog.get(), *pInfo, false);
+ aDlg.run();
+ }
+ else if (&rButton == m_xCompareButton.get() && nEntry != -1)
+ {
+ SfxAllItemSet aSet( pObjShell->GetPool() );
+ aSet.Put(SfxInt16Item(SID_VERSION, nEntry + 1));
+ aSet.Put(SfxStringItem(SID_FILE_NAME, pObjShell->GetMedium()->GetName()));
+
+ SfxItemSet* pSet = pObjShell->GetMedium()->GetItemSet();
+ const SfxStringItem* pFilterItem = SfxItemSet::GetItem<SfxStringItem>(pSet, SID_FILTER_NAME, false);
+ const SfxStringItem* pFilterOptItem = SfxItemSet::GetItem<SfxStringItem>(pSet, SID_FILE_FILTEROPTIONS, false);
+ if ( pFilterItem )
+ aSet.Put( *pFilterItem );
+ if ( pFilterOptItem )
+ aSet.Put( *pFilterOptItem );
+
+ m_pViewFrame->GetDispatcher()->Execute( SID_DOCUMENT_COMPARE, SfxCallMode::ASYNCHRON, aSet );
+ m_xDialog->response(RET_CLOSE);
+ }
+ else if (&rButton == m_xCmisButton.get())
+ {
+ SfxCmisVersionsDialog aDlg(m_xDialog.get(), m_pViewFrame);
+ aDlg.run();
+ }
+}
+
+IMPL_LINK(SfxVersionDialog, ToggleHdl_Impl, weld::Toggleable&, rButton, void)
+{
+ if (&rButton == m_xSaveCheckBox.get())
+ {
+ m_bIsSaveVersionOnClose = m_xSaveCheckBox->get_active();
+ }
+}
+
+SfxViewVersionDialog_Impl::SfxViewVersionDialog_Impl(weld::Window *pParent, SfxVersionInfo& rInfo, bool bEdit)
+ : SfxDialogController(pParent, "sfx/ui/versioncommentdialog.ui", "VersionCommentDialog")
+ , m_rInfo(rInfo)
+ , m_xDateTimeText(m_xBuilder->weld_label("timestamp"))
+ , m_xSavedByText(m_xBuilder->weld_label("author"))
+ , m_xEdit(m_xBuilder->weld_text_view("textview"))
+ , m_xOKButton(m_xBuilder->weld_button("ok"))
+ , m_xCancelButton(m_xBuilder->weld_button("cancel"))
+ , m_xCloseButton(m_xBuilder->weld_button("close"))
+{
+ OUString sAuthor = rInfo.aAuthor.isEmpty() ? SfxResId(STR_NO_NAME_SET) : rInfo.aAuthor;
+
+ const LocaleDataWrapper& rLocaleWrapper( Application::GetSettings().GetLocaleDataWrapper() );
+ m_xDateTimeText->set_label(m_xDateTimeText->get_label() + formatDateTime(rInfo.aCreationDate, rLocaleWrapper, false));
+ m_xSavedByText->set_label(m_xSavedByText->get_label() + sAuthor);
+ m_xEdit->set_text(rInfo.aComment);
+ m_xEdit->set_size_request(40 * m_xEdit->get_approximate_digit_width(),
+ 7 * m_xEdit->get_text_height());
+ m_xOKButton->connect_clicked(LINK(this, SfxViewVersionDialog_Impl, ButtonHdl));
+
+ if (!bEdit)
+ {
+ m_xOKButton->hide();
+ m_xCancelButton->hide();
+ m_xEdit->set_editable(false);
+ m_xDialog->set_title(SfxResId(STR_VIEWVERSIONCOMMENT));
+ m_xCloseButton->grab_focus();
+ }
+ else
+ {
+ m_xDateTimeText->hide();
+ m_xCloseButton->hide();
+ m_xEdit->grab_focus();
+ }
+}
+
+IMPL_LINK(SfxViewVersionDialog_Impl, ButtonHdl, weld::Button&, rButton, void)
+{
+ assert(&rButton == m_xOKButton.get());
+ (void)rButton;
+ m_rInfo.aComment = m_xEdit->get_text();
+ m_xDialog->response(RET_OK);
+}
+
+SfxCmisVersionsDialog::SfxCmisVersionsDialog(weld::Window* pParent, SfxViewFrame* pVwFrame)
+ : SfxDialogController(pParent, "sfx/ui/versionscmis.ui", "VersionsCmisDialog")
+ , m_pViewFrame(pVwFrame)
+ , m_xOpenButton(m_xBuilder->weld_button("open"))
+ , m_xViewButton(m_xBuilder->weld_button("show"))
+ , m_xDeleteButton(m_xBuilder->weld_button("delete"))
+ , m_xCompareButton(m_xBuilder->weld_button("compare"))
+ , m_xVersionBox(m_xBuilder->weld_tree_view("versions"))
+{
+ m_xVersionBox->set_size_request(m_xVersionBox->get_approximate_digit_width() * 90,
+ m_xVersionBox->get_height_rows(15));
+ setColSizes(*m_xVersionBox);
+
+ m_xVersionBox->grab_focus();
+
+ OUString sText = m_xDialog->get_title() +
+ " " + m_pViewFrame->GetObjectShell()->GetTitle();
+ m_xDialog->set_title(sText);
+
+ LoadVersions();
+}
+
+SfxCmisVersionsDialog::~SfxCmisVersionsDialog()
+{
+}
+
+void SfxCmisVersionsDialog::LoadVersions()
+{
+ SfxObjectShell *pObjShell = m_pViewFrame->GetObjectShell();
+ uno::Sequence < document::CmisVersion > aVersions = pObjShell->GetCmisVersions( );
+ m_pTable.reset(new SfxVersionTableDtor( aVersions ));
+ for (size_t n = 0; n < m_pTable->size(); ++n)
+ {
+ SfxVersionInfo *pInfo = m_pTable->at( n );
+ OUString aEntry = formatDateTime(pInfo->aCreationDate, Application::GetSettings().GetLocaleDataWrapper(), false);
+ m_xVersionBox->append(weld::toId(pInfo), aEntry);
+ auto nLastRow = m_xVersionBox->n_children() - 1;
+ m_xVersionBox->set_text(nLastRow, pInfo->aAuthor, 1);
+ m_xVersionBox->set_text(nLastRow, ConvertWhiteSpaces_Impl(pInfo->aComment), 2);
+ }
+
+ if (auto nCount = m_pTable->size())
+ m_xVersionBox->select(nCount - 1);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */