lib

KoFilterChain.h

00001 /* This file is part of the KOffice libraries
00002    Copyright (C) 2001 Werner Trobin <trobin@kde.org>
00003 
00004    This library is free software; you can redistribute it and/or
00005    modify it under the terms of the GNU Library General Public
00006    License version 2 as published by the Free Software Foundation.
00007 
00008    This library is distributed in the hope that it will be useful,
00009    but WITHOUT ANY WARRANTY; without even the implied warranty of
00010    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00011    Library General Public License for more details.
00012 
00013    You should have received a copy of the GNU Library General Public License
00014    along with this library; see the file COPYING.LIB.  If not, write to
00015    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00016  * Boston, MA 02110-1301, USA.
00017 */
00018 
00019 #ifndef __koffice_filter_chain_h__
00020 #define __koffice_filter_chain_h__
00021 
00022 #include <qcstring.h>
00023 #include <qasciidict.h>
00024 #include <qptrlist.h>
00025 #include <qstringlist.h>
00026 
00027 #include <KoFilter.h>
00028 #include <KoQueryTrader.h>
00029 #include <KoStoreDevice.h>
00030 #include <koffice_export.h>
00031 
00032 class KTempFile;
00033 class KoFilterManager;
00034 class KoDocument;
00035 class QStrList;
00036 
00037 namespace KOffice {
00038     class Graph;
00039 }
00040 
00050 class KOFFICECORE_EXPORT KoFilterChain : public KShared
00051 {
00052     // Only KOffice::Graph is allowed to construct instances and
00053     // add chain links.
00054     friend class KOffice::Graph;
00055     friend class KoFilterManager;
00056 
00057 public:
00058     typedef KSharedPtr<KoFilterChain> Ptr;
00059 
00060     virtual ~KoFilterChain();
00061 
00065     const KoFilterManager* manager() const { return m_manager; }
00066 
00072     KoFilter::ConversionStatus invokeChain();
00073 
00079     QString chainOutput() const;
00080 
00085     QString inputFile();
00090     QString outputFile();
00091 
00102     KoStoreDevice* storageFile( const QString& name = "root", KoStore::Mode mode = KoStore::Read );
00103 
00110     KoDocument* inputDocument();
00117     KoDocument* outputDocument();
00118 
00119 
00120     // debugging
00121     void dump() const;
00122 
00123 private:
00124     // ### API for KOffice::Graph:
00125     // Construct a filter chain belonging to some KoFilterManager.
00126     // The parent filter manager may be 0.
00127     KoFilterChain( const KoFilterManager* manager );
00128 
00129     void appendChainLink( KoFilterEntry::Ptr filterEntry, const QCString& from, const QCString& to );
00130     void prependChainLink( KoFilterEntry::Ptr filterEntry, const QCString& from, const QCString& to );
00131 
00132     // ### API for KoEmbeddingFilter
00133     // This is needed as the embedding filter might have to influence
00134     // the way we change directories (e.g. in the olefilter case)
00135     // The ugly friend methods are needed, but I'd welcome and suggestions for
00136     // better design :}
00137     friend void KoEmbeddingFilter::filterChainEnterDirectory( const QString& directory ) const;
00138     void enterDirectory( const QString& directory );
00139     friend void KoEmbeddingFilter::filterChainLeaveDirectory() const;
00140     void leaveDirectory();
00141 
00142     // These methods are friends of KoFilterManager and provide access
00143     // to a private part of its API. As I don't want to include
00144     // koFilterManager.h in this header the direction is "int" here.
00145     QString filterManagerImportFile() const;
00146     QString filterManagerExportFile() const;
00147     KoDocument* filterManagerKoDocument() const;
00148     int filterManagerDirection() const;
00149     KoFilterChain* const filterManagerParentChain() const;
00150 
00151 
00152     // Helper methods which keep track of all the temp files, documents,
00153     // storages,... and properly delete them as soon as they are not
00154     // needed anymore.
00155     void manageIO();
00156     void finalizeIO();
00157 
00158     bool createTempFile( KTempFile** tempFile, bool autoDelete = true );
00159 
00160     void inputFileHelper( KoDocument* document, const QString& alternativeFile );
00161     void outputFileHelper( bool autoDelete );
00162     KoStoreDevice* storageNewStreamHelper( KoStore** storage, KoStoreDevice** device, const QString& name );
00163     KoStoreDevice* storageHelper( const QString& file, const QString& streamName,
00164                                   KoStore::Mode mode, KoStore** storage, KoStoreDevice** device );
00165     void storageInit( const QString& file, KoStore::Mode mode, KoStore** storage );
00166     KoStoreDevice* storageInitEmbedding( const QString& name );
00167     KoStoreDevice* storageCreateFirstStream( const QString& streamName, KoStore** storage, KoStoreDevice** device );
00168     KoStoreDevice* storageCleanupHelper( KoStore** storage );
00169 
00170     KoDocument* createDocument( const QString& file );
00171     KoDocument* createDocument( const QCString& mimeType );
00172 
00178     class ChainLink
00179     {
00180 
00181     public:
00182         ChainLink( KoFilterChain* chain, KoFilterEntry::Ptr filterEntry,
00183                    const QCString& from, const QCString& to );
00184 
00185         KoFilter::ConversionStatus invokeFilter( const ChainLink* const parentChainLink );
00186 
00187         QCString from() const { return m_from; }
00188         QCString to() const { return m_to; }
00189 
00190         // debugging
00191         void dump() const;
00192 
00193         // This hack is only needed due to crappy Microsoft design and
00194         // circular dependencies in their embedded files :}
00195         int lruPartIndex() const;
00196 
00197     private:
00198         ChainLink( const ChainLink& rhs );
00199         ChainLink& operator=( const ChainLink& rhs );
00200 
00201         void setupCommunication( const KoFilter* const parentFilter ) const;
00202         void setupConnections( const KoFilter* sender, const QStrList& sigs,
00203                                const KoFilter* receiver, const QStrList& sl0ts ) const;
00204 
00205         KoFilterChain* m_chain;
00206         KoFilterEntry::Ptr m_filterEntry;
00207         QCString m_from, m_to;
00208 
00209         // This hack is only needed due to crappy Microsoft design and
00210         // circular dependencies in their embedded files :}
00211         KoFilter* m_filter;
00212 
00213         class Private;
00214         Private* d;
00215     };
00216 
00217     // "A whole is that which has beginning, middle, and end" - Aristotle
00218     // ...but we also need to signal "Done" state, Mr. Aristotle
00219     enum Whole { Beginning = 1, Middle = 2, End = 4, Done = 8 };
00220 
00221     // Don't copy or assign filter chains
00222     KoFilterChain( const KoFilterChain& rhs );
00223     KoFilterChain& operator=( const KoFilterChain& rhs );
00224 
00225     const KoFilterManager* const m_manager;
00226     QPtrList<ChainLink> m_chainLinks;
00227 
00228     // stuff needed for bookkeeping
00229     int m_state;
00230 
00231     QString m_inputFile;              // Did we pass around plain files?
00232     QString m_outputFile;
00233 
00234     KoStore* m_inputStorage;          // ...or was it a storage+device?
00235     KoStoreDevice* m_inputStorageDevice;
00236     KoStore* m_outputStorage;
00237     KoStoreDevice* m_outputStorageDevice;
00238 
00239     KoDocument* m_inputDocument;      // ...or even documents?
00240     KoDocument* m_outputDocument;
00241 
00242     KTempFile* m_inputTempFile;
00243     KTempFile* m_outputTempFile;
00244 
00245     // These two flags keep track of the input/output the
00246     // filter (=user) asked for
00247     enum IOState { Nil, File, Storage, Document };
00248     IOState m_inputQueried, m_outputQueried;
00249 
00250     // This stack keeps track of directories we have to enter and
00251     // leave due to internal embedding a la OLE filters. This serves
00252     // as a kind of "memory" even if we didn't initialize the store yet.
00253     // I know that it's ugly, and I'll try to clean up that hack
00254     // sooner or later (Werner)
00255     QStringList m_internalEmbeddingDirectories;
00256 
00257     class Private;
00258     Private* d;
00259 };
00260 
00261 
00262 // As we use quite generic classnames...
00263 namespace KOffice
00264 {
00265     class Vertex;
00266     template<class T> class PriorityQueue;
00267 
00272     class Edge
00273     {
00274 
00275     public:
00276         // creates a new edge to "vertex" with the given weight.
00277         Edge( Vertex* vertex, KoFilterEntry::Ptr filterEntry );
00278         ~Edge() {}
00279 
00280         unsigned int weight() const { return m_filterEntry ? m_filterEntry->weight : 0; }
00281         KoFilterEntry::Ptr filterEntry() const { return m_filterEntry; }
00282         const Vertex* vertex() const { return m_vertex; }
00283 
00284         // Relaxes the "connected" vertex (i.e. the weight of the
00285         // connected vertex = "predec.->key()" (parameter) + weight of this edge
00286         // As this will only be called once we calculate the weight
00287         // of the edge "on the fly"
00288         // Note: We have to pass the queue as we have to call keyDecreased :}
00289         void relax( const Vertex* predecessor, PriorityQueue<Vertex>& queue );
00290 
00291         // debugging
00292         void dump( const QCString& indent ) const;
00293 
00294     private:
00295         Edge( const Edge& rhs );
00296         Edge& operator=( const Edge& rhs );
00297 
00298         Vertex* m_vertex;
00299         KoFilterEntry::Ptr m_filterEntry;
00300 
00301         class Private;
00302         Private* d;
00303     };
00304 
00305 
00310     class Vertex
00311     {
00312 
00313     public:
00314         Vertex( const QCString& mimeType );
00315         ~Vertex() {}
00316 
00317         QCString mimeType() const { return m_mimeType; }
00318 
00319         // Current "weight" of the vertex - will be "relaxed" when
00320         // running the shortest path algorithm. Returns true if it
00321         // really has been "relaxed"
00322         bool setKey( unsigned int key );
00323         unsigned int key() const { return m_weight; }
00324         // Can be used to set the key back to "Infinity" (UINT_MAX)
00325         // and reset the predecessor of this vertex
00326         void reset();
00327 
00328         // Position in the heap, needed for a fast keyDecreased operation
00329         void setIndex( int index ) { m_index=index; }
00330         int index() const { return m_index; }
00331 
00332         // predecessor on the way from the source to the destination,
00333         // needed for the shortest path algorithm
00334         void setPredecessor( const Vertex* predecessor ) { m_predecessor=predecessor; }
00335         const Vertex* predecessor() const { return m_predecessor; }
00336 
00337         // Adds an outgoing edge to the vertex, transfers ownership
00338         void addEdge( const Edge* edge );
00339         // Finds the lightest(!) edge pointing to the given vertex, if any (0 if not found)
00340         // This means it will always search the whole list of edges
00341         const Edge* findEdge( const Vertex* vertex ) const;
00342 
00343         // This method is called when we need to relax all "our" edges.
00344         // We need to pass the queue as we have to notify it about key changes - ugly :(
00345         void relaxVertices( PriorityQueue<Vertex>& queue );
00346 
00347         // debugging
00348         void dump( const QCString& indent ) const;
00349 
00350     private:
00351         Vertex( const Vertex& rhs );
00352         Vertex& operator=( const Vertex& rhs );
00353 
00354         QPtrList<Edge> m_edges;
00355         const Vertex* m_predecessor;
00356         QCString m_mimeType;
00357         unsigned int m_weight; // "key" inside the queue
00358         int m_index; // position inside the queue, needed for a fast keyDecreased()
00359 
00360         class Private;
00361         Private* d;
00362     };
00363 
00364 
00370     class Graph
00371     {
00372 
00373     public:
00374         Graph( const QCString& from );
00375         ~Graph() {}
00376 
00377         bool isValid() const { return m_graphValid; }
00378 
00379         QCString sourceMimeType() const { return m_from; }
00380         void setSourceMimeType( const QCString& from );
00381 
00382         // Creates a chain from "from" to the "to" mimetype
00383         // If the "to" mimetype isEmpty() then we try to find the
00384         // closest KOffice mimetype and use that as destination.
00385         // After such a search "to" will contain the dest. mimetype (return value)
00386         // if the search was successful. Might return 0!
00387         KoFilterChain::Ptr chain( const KoFilterManager* manager, QCString& to ) const;
00388 
00389         // debugging
00390         void dump() const;
00391 
00392     private:
00393         Graph( const Graph& rhs );
00394         Graph& operator=( const Graph& rhs );
00395 
00396         void buildGraph();
00397         void shortestPaths();
00398         QCString findKOfficePart() const;
00399 
00400         QAsciiDict<Vertex> m_vertices;
00401         QCString m_from;
00402         bool m_graphValid;
00403 
00404         class Private;
00405         Private* d;
00406     };
00407 
00408 } // namespace KOffice
00409 
00410 #endif // __koffice_filter_chain_h__
KDE Home | KDE Accessibility Home | Description of Access Keys