diff options
Diffstat (limited to 'sfx2/source/dialog/versdlg.cxx')
-rw-r--r-- | sfx2/source/dialog/versdlg.cxx | 472 |
1 files changed, 472 insertions, 0 deletions
diff --git a/sfx2/source/dialog/versdlg.cxx b/sfx2/source/dialog/versdlg.cxx new file mode 100644 index 000000000..68abca31b --- /dev/null +++ b/sfx2/source/dialog/versdlg.cxx @@ -0,0 +1,472 @@ +/* -*- 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 <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 <svtools/miscopt.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(getWidestTime(Application::GetSettings().GetLocaleDataWrapper())).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(reinterpret_cast<SfxVersionInfo*>(rVersionBox.get_id(i).toInt64())->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; + } + } + + std::vector<int> aWidths; + aWidths.push_back(nMax); + aWidths.push_back(nMaxAuthorWidth); + rVersionBox.set_column_fixed_widths(aWidths); + } +} + +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_clicked( aClickLink ); + 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 = formatTime(pInfo->aCreationDate, Application::GetSettings().GetLocaleDataWrapper()); + m_xVersionBox->append(OUString::number(reinterpret_cast<sal_Int64>(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); + + SvtMiscOptions miscOptions; + if ( !miscOptions.IsExperimentalMode() ) + 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::makeAny( 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_xSaveCheckBox.get()) + { + m_bIsSaveVersionOnClose = m_xSaveCheckBox->get_active(); + } + else 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 = reinterpret_cast<SfxVersionInfo*>(m_xVersionBox->get_id(nEntry).toInt64()); + 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 = reinterpret_cast<SfxVersionInfo*>(m_xVersionBox->get_id(nEntry).toInt64()); + 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(); + } +} + +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() + formatTime(rInfo.aCreationDate, rLocaleWrapper)); + 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->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 = formatTime(pInfo->aCreationDate, Application::GetSettings().GetLocaleDataWrapper()); + m_xVersionBox->append(OUString::number(reinterpret_cast<sal_Int64>(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: */ |