Commit c9089f31 authored by Pino Toscano's avatar Pino Toscano

Add the possibility to save a copy of the document with the changes to it...

Add the possibility to save a copy of the document with the changes to it (only for form fields at the moment).

On the Document/Generator side, introduce a proper interface for the purpouse.

On the GUI side, add a new "Save As" function that save the changed document to a location.
The action is enabled only if the current backend can provide the functionality.

svn path=/trunk/KDE/kdegraphics/okular/; revision=784661
parent 903956de
......@@ -57,6 +57,7 @@
#include "interfaces/configinterface.h"
#include "interfaces/guiinterface.h"
#include "interfaces/printinterface.h"
#include "interfaces/saveinterface.h"
#include "observer.h"
#include "page.h"
#include "page_p.h"
......@@ -484,6 +485,16 @@ ConfigInterface* DocumentPrivate::generatorConfig( GeneratorInfo& info )
return info.config;
}
SaveInterface* DocumentPrivate::generatorSave( GeneratorInfo& info )
{
if ( info.saveChecked )
return info.save;
info.save = qobject_cast< Okular::SaveInterface * >( info.generator );
info.saveChecked = true;
return info.save;
}
void DocumentPrivate::saveDocumentInfo() const
{
if ( m_xmlFileName.isEmpty() )
......@@ -2646,6 +2657,36 @@ const KComponentData* Document::componentData() const
return kcd;
}
bool Document::canSaveChanges() const
{
if ( !d->m_generator )
return false;
Q_ASSERT( !d->m_generatorName.isEmpty() );
QHash< QString, GeneratorInfo >::iterator genIt = d->m_loadedGenerators.find( d->m_generatorName );
Q_ASSERT( genIt != d->m_loadedGenerators.end() );
SaveInterface* saveIface = d->generatorSave( genIt.value() );
if ( !saveIface )
return false;
return saveIface->supportsOption( SaveInterface::SaveChanges );
}
bool Document::saveChanges( const QString &fileName )
{
if ( !d->m_generator || fileName.isEmpty() )
return false;
Q_ASSERT( !d->m_generatorName.isEmpty() );
QHash< QString, GeneratorInfo >::iterator genIt = d->m_loadedGenerators.find( d->m_generatorName );
Q_ASSERT( genIt != d->m_loadedGenerators.end() );
SaveInterface* saveIface = d->generatorSave( genIt.value() );
if ( !saveIface || !saveIface->supportsOption( SaveInterface::SaveChanges ) )
return false;
return saveIface->save( fileName, SaveInterface::SaveChanges );
}
void DocumentPrivate::requestDone( PixmapRequest * req )
{
if ( !req )
......
......@@ -510,6 +510,22 @@ class OKULAR_EXPORT Document : public QObject
*/
const KComponentData* componentData() const;
/**
* Returns whether the changes to the document (modified annotations,
* values in form fields, etc) can be saved to another document.
*
* @since 0.7 (KDE 4.1)
*/
bool canSaveChanges() const;
/**
* Save the document and the optional changes to it to the specified
* @p fileName.
*
* @since 0.7 (KDE 4.1)
*/
bool saveChanges( const QString &fileName );
public Q_SLOTS:
/**
* This slot is called whenever the user changes the @p rotation of
......
......@@ -35,19 +35,24 @@ struct RunningSearch;
namespace Okular {
class ConfigInterface;
class SaveInterface;
}
struct GeneratorInfo
{
GeneratorInfo( const KComponentData &_data )
: generator( 0 ), data( _data ), config( 0 ), configChecked( false )
: generator( 0 ), data( _data ),
config( 0 ), save( 0 ),
configChecked( false ), saveChecked( false )
{}
Okular::Generator * generator;
KComponentData data;
QString catalogName;
Okular::ConfigInterface * config;
Okular::SaveInterface * save;
bool configChecked : 1;
bool saveChecked : 1;
};
namespace Okular {
......@@ -92,6 +97,7 @@ class DocumentPrivate
void cacheExportFormats();
void setRotationInternal( int r, bool notify );
ConfigInterface* generatorConfig( GeneratorInfo& info );
SaveInterface* generatorSave( GeneratorInfo& info );
// private slots
void saveDocumentInfo() const;
......
/***************************************************************************
* Copyright (C) 2008 by Pino Toscano <pino@kde.org> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
***************************************************************************/
#ifndef _OKULAR_SAVEINTERFACE_H_
#define _OKULAR_SAVEINTERFACE_H_
#include <okular/core/okular_export.h>
#include <QtCore/QObject>
namespace Okular {
class AnnotationProxy;
/**
* @short Abstract interface for saving
*
* This interface defines a way to save (or help saving) the document opened
* by the Generator.
*
* How to use it in a custom Generator:
* @code
class MyGenerator : public Okular::Generator, public Okular::SaveInterface
{
Q_OBJECT
Q_INTERFACES( Okular::SaveInterface )
...
};
* @endcode
* and - of course - implementing its methods.
*/
class OKULAR_EXPORT SaveInterface
{
public:
/**
* The possible options for the saving.
*/
enum SaveOption
{
NoOption = 0,
SaveChanges = 1 ///< The possibility to save with the current changes to the document.
};
Q_DECLARE_FLAGS( SaveOptions, SaveOption )
/**
* Destroys the save interface.
*/
virtual ~SaveInterface() {}
/**
* Query for the supported saving options.
*
* @note NoOption is never queried
*/
virtual bool supportsOption( SaveOption option ) const = 0;
/**
* Save to the specified @p fileName with the specified @p options.
*/
virtual bool save( const QString &fileName, SaveOptions options ) = 0;
};
}
Q_DECLARE_INTERFACE( Okular::SaveInterface, "org.kde.okular.SaveInterface/0.1" )
Q_DECLARE_OPERATORS_FOR_FLAGS( Okular::SaveInterface::SaveOptions )
#endif
......@@ -358,9 +358,12 @@ m_cliPresentation(false), m_generatorGuiClient(0)
m_findNext = KStandardAction::findNext( this, SLOT( slotFindNext() ), ac);
m_findNext->setEnabled( false );
m_saveCopyAs = KStandardAction::saveAs( this, SLOT( slotSaveCopyAs() ), ac );
m_saveCopyAs->setText( i18n( "Save &Copy As..." ) );
ac->addAction( "file_save_copy", m_saveCopyAs );
m_saveCopyAs->setEnabled( false );
m_saveAs = KStandardAction::saveAs( this, SLOT( slotSaveFileAs() ), ac );
m_saveAs->setText( i18n( "Save &Copy As..." ) );
ac->addAction("save",m_saveAs);
m_saveAs->setEnabled( false );
QAction * prefs = KStandardAction::preferences( this, SLOT( slotPreferences() ), ac);
......@@ -760,7 +763,8 @@ bool Part::openFile()
// update one-time actions
m_find->setEnabled( ok && canSearch );
m_findNext->setEnabled( ok && canSearch );
m_saveAs->setEnabled( ok );
m_saveAs->setEnabled( ok && m_document->canSaveChanges() );
m_saveCopyAs->setEnabled( ok );
m_printPreview->setEnabled( ok && m_document->printingSupport() != Okular::Document::NoPrinting );
m_showProperties->setEnabled( ok );
bool hasEmbeddedFiles = ok && m_document->embeddedFiles() && m_document->embeddedFiles()->count() > 0;
......@@ -851,6 +855,7 @@ bool Part::closeUrl()
m_find->setEnabled( false );
m_findNext->setEnabled( false );
m_saveAs->setEnabled( false );
m_saveCopyAs->setEnabled( false );
m_printPreview->setEnabled( false );
m_showProperties->setEnabled( false );
m_showEmbeddedFiles->setEnabled( false );
......@@ -1222,6 +1227,60 @@ void Part::slotSaveFileAs()
{
if (m_dummyMode) return;
KUrl saveUrl = KFileDialog::getSaveUrl( url().isLocalFile() ? url().url() : url().fileName(), QString(), widget() );
if ( !saveUrl.isValid() || saveUrl.isEmpty() )
return;
if ( saveUrl.isLocalFile() )
{
const QString fileName = saveUrl.toLocalFile();
if ( QFile::exists( fileName ) )
{
if (KMessageBox::warningContinueCancel( widget(), i18n("A file named \"%1\" already exists. Are you sure you want to overwrite it?", saveUrl.fileName()), QString(), KGuiItem(i18n("Overwrite"))) != KMessageBox::Continue)
return;
}
if ( !m_document->saveChanges( fileName ) )
{
KMessageBox::information( widget(), i18n("File could not be saved in '%1'. Try to save it to another location.", fileName ) );
return;
}
}
else
{
if ( KIO::NetAccess::exists( saveUrl, KIO::NetAccess::DestinationSide, widget() ) )
{
if (KMessageBox::warningContinueCancel( widget(), i18n("A file named \"%1\" already exists. Are you sure you want to overwrite it?", saveUrl.fileName()), QString(), KGuiItem(i18n("Overwrite"))) != KMessageBox::Continue)
return;
}
KTemporaryFile tf;
QString fileName;
if ( !tf.open() )
{
KMessageBox::information( widget(), i18n("File could not open the temporary file for saving." ) );
return;
}
fileName = tf.fileName();
tf.close();
if ( !m_document->saveChanges( fileName ) )
{
KMessageBox::information( widget(), i18n("File could not be saved in '%1'. Try to save it to another location.", fileName ) );
return;
}
KIO::Job *copyJob = KIO::file_copy( fileName, saveUrl, -1, KIO::Overwrite );
if ( !KIO::NetAccess::synchronousRun( copyJob, widget() ) )
KMessageBox::information( widget(), i18n("File could not be saved in '%1'. Try to save it to another location.", saveUrl.prettyUrl() ) );
}
}
void Part::slotSaveCopyAs()
{
if (m_dummyMode) return;
KUrl saveUrl = KFileDialog::getSaveUrl( url().isLocalFile() ? url().url() : url().fileName(), QString(), widget() );
if ( saveUrl.isValid() && !saveUrl.isEmpty() )
{
......
......@@ -129,6 +129,7 @@ class Part : public KParts::ReadOnlyPart, public Okular::DocumentObserver, publi
void slotNextBookmark();
void slotFindNext();
void slotSaveFileAs();
void slotSaveCopyAs();
void slotGetNewStuff();
void slotNewConfig();
void slotNewGeneratorConfig();
......@@ -219,6 +220,7 @@ class Part : public KParts::ReadOnlyPart, public Okular::DocumentObserver, publi
QAction *m_find;
QAction *m_findNext;
QAction *m_saveAs;
QAction *m_saveCopyAs;
QAction *m_printPreview;
QAction *m_showProperties;
QAction *m_showEmbeddedFiles;
......
<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
<kpartgui name="okular_part" version="24">
<kpartgui name="okular_part" version="25">
<MenuBar>
<Menu name="file"><text>&amp;File</text>
<Action name="get_new_stuff" group="file_open"/>
<Action name="import_ps" group="file_open"/>
<Action name="save" group="file_save"/>
<Action name="file_save_as" group="file_save"/>
<Action name="file_save_copy" group="file_save"/>
<Action name="file_reload" group="file_save"/>
<Action name="file_print" group="file_print"/>
<Action name="file_print_preview" group="file_print"/>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment