1 /* This file is part of the Calligra libraries
2    Copyright (C) 2001 Werner Trobin <trobin@kde.org>
3 
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License as published by the Free Software Foundation; either
7 version 2 of the License, or (at your option) any later version.
8 
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 Library General Public License for more details.
13 
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB.  If not, write to
16 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 Boston, MA 02110-1301, USA.
18 */
19 // clazy:excludeall=qstring-arg
20 #include "KoFilterChainLink.h"
21 #include <QMetaMethod>
22 #include <QPluginLoader>
23 #include <MainDebug.h>
24 #include "KoFilterEntry.h"
25 #include "KoFilterManager.h"
26 #include "KoProgressUpdater.h"
27 #include "KoUpdater.h"
28 
29 namespace
30 {
31     const char SIGNAL_PREFIX[] = "commSignal";
32     const int SIGNAL_PREFIX_LEN = 10;
33     const char SLOT_PREFIX[] = "commSlot";
34     const int SLOT_PREFIX_LEN = 8;
35 
createUpdater(KoFilterChain * chain)36     KoUpdater *createUpdater(KoFilterChain *chain)
37     {
38         QPointer<KoUpdater> updater = 0;
39         Q_ASSERT(chain);
40         Q_ASSERT(chain->manager());
41         KoProgressUpdater *pu = chain->manager()->progressUpdater();
42         if (pu) {
43             updater = pu->startSubtask(1, "filter");
44             updater->setProgress(0);
45         }
46 
47         return updater;
48     }
49 }
50 
51 namespace CalligraFilter {
52 
ChainLink(KoFilterChain * chain,KoFilterEntry::Ptr filterEntry,const QByteArray & from,const QByteArray & to)53     ChainLink::ChainLink(KoFilterChain *chain, KoFilterEntry::Ptr filterEntry,
54                          const QByteArray& from, const QByteArray& to)
55         : m_chain(chain)
56         , m_filterEntry(filterEntry)
57         , m_from(from)
58         , m_to(to)
59         , m_filter(0)
60         , m_updater(createUpdater(chain))
61     {
62     }
63 
~ChainLink()64     ChainLink::~ChainLink() {
65     }
66 
invokeFilter(const ChainLink * const parentChainLink)67     KoFilter::ConversionStatus ChainLink::invokeFilter(const ChainLink *const parentChainLink)
68     {
69         if (!m_filterEntry) {
70             errorFilter << "This filter entry is null. Strange stuff going on." << endl;
71             return KoFilter::FilterEntryNull;
72         }
73 
74         m_filter = m_filterEntry->createFilter(m_chain);
75 
76         if (!m_filter) {
77             errorFilter << "Couldn't create the filter." << endl;
78             return KoFilter::FilterCreationError;
79         }
80 
81         if (m_updater) {
82             // if there is an updater, use that for progress reporting
83             m_filter->setUpdater(m_updater);
84         }
85 
86         if (parentChainLink) {
87             setupCommunication(parentChainLink->m_filter);
88         }
89 
90         KoFilter::ConversionStatus status = m_filter->convert(m_from, m_to);
91         delete m_filter;
92         m_filter = 0;
93         if (m_updater) {
94             m_updater->setProgress(100);
95         }
96         return status;
97     }
98 
dump() const99     void ChainLink::dump() const
100     {
101         debugFilter << "   Link:" << m_filterEntry->fileName();
102     }
103 
setupCommunication(const KoFilter * const parentFilter) const104     void ChainLink::setupCommunication(const KoFilter *const parentFilter) const
105     {
106         if (!parentFilter)
107             return;
108 
109         const QMetaObject *const parent = parentFilter->metaObject();
110         const QMetaObject *const child = m_filter->metaObject();
111         if (!parent || !child)
112             return;
113 
114         setupConnections(parentFilter, m_filter);
115         setupConnections(m_filter, parentFilter);
116     }
117 
setupConnections(const KoFilter * sender,const KoFilter * receiver) const118     void ChainLink::setupConnections(const KoFilter *sender, const KoFilter *receiver) const
119     {
120         const QMetaObject * const parent = sender->metaObject();
121         const QMetaObject * const child = receiver->metaObject();
122         if (!parent || !child)
123             return;
124 
125         int senderMethodCount = parent->methodCount();
126         for (int i = 0; i < senderMethodCount; ++i) {
127             QMetaMethod metaMethodSignal = parent->method(i);
128             if (metaMethodSignal.methodType() != QMetaMethod::Signal)
129                 continue;
130             // ### untested (QMetaMethod::signature())
131             if (strncmp(metaMethodSignal.methodSignature(), SIGNAL_PREFIX, SIGNAL_PREFIX_LEN) == 0) {
132                 int receiverMethodCount = child->methodCount();
133                 for (int j = 0; j < receiverMethodCount; ++j) {
134                     QMetaMethod metaMethodSlot = child->method(j);
135                     if (metaMethodSlot.methodType() != QMetaMethod::Slot)
136                         continue;
137                     if (strncmp(metaMethodSlot.methodSignature().constData(), SLOT_PREFIX, SLOT_PREFIX_LEN) == 0) {
138                         if (strcmp(metaMethodSignal.methodSignature().constData() + SIGNAL_PREFIX_LEN, metaMethodSlot.methodSignature().constData() + SLOT_PREFIX_LEN) == 0) {
139                             QByteArray signalString;
140                             signalString.setNum(QSIGNAL_CODE);
141                             signalString += metaMethodSignal.methodSignature();
142                             QByteArray slotString;
143                             slotString.setNum(QSLOT_CODE);
144                             slotString += metaMethodSlot.methodSignature();
145                             QObject::connect(sender, signalString, receiver, slotString);
146                         }
147                     }
148                 }
149             }
150         }
151     }
152 
153 }
154