Rev 23294 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
4430 | cbradney | 1 | /* |
2 | For general Scribus (>=1.3.2) copyright and licensing information please refer |
||
3 | to the COPYING file provided with the program. Following this notice may exist |
||
4 | a copyright and/or license notice that predates the release of Scribus 1.3.2 |
||
5 | for which a new license (GPL+exception) is in place. |
||
6 | */ |
||
364 | Franz | 7 | /*************************************************************************** |
8 | * Copyright (C) 2004 by Riku Leino * |
||
1184 | tsoots | 9 | * tsoots@gmail.com * |
364 | Franz | 10 | * * |
11 | * This program is free software; you can redistribute it and/or modify * |
||
12 | * it under the terms of the GNU General Public License as published by * |
||
13 | * the Free Software Foundation; either version 2 of the License, or * |
||
14 | * (at your option) any later version. * |
||
15 | * * |
||
16 | * This program is distributed in the hope that it will be useful, * |
||
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * |
||
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * |
||
19 | * GNU General Public License for more details. * |
||
20 | * * |
||
21 | * You should have received a copy of the GNU General Public License * |
||
22 | * along with this program; if not, write to the * |
||
23 | * Free Software Foundation, Inc., * |
||
18122 | mrdocs | 24 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * |
364 | Franz | 25 | ***************************************************************************/ |
26 | |||
27 | #include "gtgettext.h" |
||
1665 | craig | 28 | #include "pluginmanager.h" |
1693 | craig | 29 | #include "scpaths.h" |
6132 | cbradney | 30 | #include "pageitem.h" |
5781 | cbradney | 31 | #include "scribusdoc.h" |
32 | #include "selection.h" |
||
13554 | pierre | 33 | #include "ui/gtdialogs.h" |
10601 | mrdocs | 34 | #include "gtwriter.h" |
8501 | cbradney | 35 | #include <QPixmap> |
364 | Franz | 36 | |
11933 | mrdocs | 37 | // Constructor |
5781 | cbradney | 38 | gtGetText::gtGetText(ScribusDoc* doc) |
364 | Franz | 39 | { |
22518 | craig | 40 | m_dias = nullptr; |
11933 | mrdocs | 41 | // Attach to the active document |
20913 | jghali | 42 | m_Doc = doc; |
11933 | mrdocs | 43 | // Load the plugins array. |
364 | Franz | 44 | loadImporterPlugins(); |
11933 | mrdocs | 45 | } // gtGetText::gtGetText(ScribusDoc* doc) |
364 | Franz | 46 | |
11933 | mrdocs | 47 | // Look at the results of the file selection dialog and figure out if you need to use an importer. |
48 | // Prompt the user if the importer to use isn't obvious. |
||
6132 | cbradney | 49 | void gtGetText::launchImporter(int importer, const QString& filename, bool textOnly, |
20671 | fschmid | 50 | const QString& encoding, bool append, bool prefix, PageItem* target) |
364 | Franz | 51 | { |
11933 | mrdocs | 52 | // Struct for the plugin info, we'll load this up from the array. |
364 | Franz | 53 | struct ImporterData ida; |
11933 | mrdocs | 54 | // Do we need to call an importer? Unsure what happens if this ever becomes false. |
364 | Franz | 55 | bool callImporter = true; |
11933 | mrdocs | 56 | // Check and see if the file selection dialog returned the index position of the |
57 | // importer to be used. If it isn't, try to figure out what it is. If we can't, |
||
58 | // prompt the user. |
||
364 | Franz | 59 | if (importer == -1) |
60 | { |
||
11933 | mrdocs | 61 | // Attempt to determine the importer based on the file's extension. |
62 | // Create a Qstring with what could be an extension. |
||
10427 | cbradney | 63 | QString fend = filename.right(filename.length() - filename.lastIndexOf(".") - 1); |
16445 | craig | 64 | QString fendL(fend.toLower()); |
65 | // Look for that extension in the importer QMap. |
||
20606 | craig | 66 | if (m_importerMap.find(fend) != m_importerMap.end()) |
11933 | mrdocs | 67 | // If the map is found, assign ida to the corresponding struct in the map. |
20606 | craig | 68 | ida = *m_importerMap[fend]; |
16445 | craig | 69 | // Otherwise, test for the lowercase version |
22422 | jghali | 70 | else if (m_importerMap.find(fendL) != m_importerMap.end()) |
16445 | craig | 71 | // If the map is found, assign ida to the corresponding struct in the map. |
20606 | craig | 72 | ida = *m_importerMap[fendL]; |
11933 | mrdocs | 73 | // Otherwise, try and ask the user. |
364 | Franz | 74 | else |
75 | { |
||
11933 | mrdocs | 76 | // Create a new dialog |
20606 | craig | 77 | m_dias = new gtDialogs(); |
11933 | mrdocs | 78 | // Pop up the dialog asking the user to select the type from our list (ilist) of |
79 | // importable file types. If one is not selected, set callImporter to false. |
||
22422 | jghali | 80 | callImporter = m_dias->runImporterDialog(filename, m_ilist); |
11933 | mrdocs | 81 | // If we're gonna call an importer, we need to copy it's struct to ida. |
364 | Franz | 82 | if (callImporter) |
20606 | craig | 83 | ida = m_importers[m_dias->getImporter()]; |
11933 | mrdocs | 84 | // Destroy the diag |
20606 | craig | 85 | delete m_dias; |
11933 | mrdocs | 86 | } // else - if (importerMap.find(fend) != importerMap.end()) |
364 | Franz | 87 | } |
11933 | mrdocs | 88 | else // If we know which importer to use |
364 | Franz | 89 | { |
11933 | mrdocs | 90 | // Copy the importer's struct to ida. |
20606 | craig | 91 | ida = m_importers[importer]; |
11933 | mrdocs | 92 | } // else - if (importer == -1) |
93 | |||
94 | // Create a target text frame for the imported text and assign it to the parameter "target" |
||
6132 | cbradney | 95 | PageItem* targetFrame=target; |
11933 | mrdocs | 96 | |
97 | // If the targetframe is 0 ( no frame selected/created? ) then reassign it to the |
||
98 | // (questionable interpretation here) first frame in the documentation. |
||
22600 | craig | 99 | if (targetFrame==nullptr) |
6132 | cbradney | 100 | targetFrame=m_Doc->m_Selection->itemAt(0); |
364 | Franz | 101 | |
11933 | mrdocs | 102 | // If the targetframe is not zero, and we do need to call the importer, |
103 | // Run the importer via "CallDLL" and pass it what it needs to know. |
||
22600 | craig | 104 | if (targetFrame!=nullptr && callImporter) |
20671 | fschmid | 105 | CallDLL(ida, filename, encoding, textOnly, append, prefix, targetFrame); |
11933 | mrdocs | 106 | } //void gtGetText::launchImporter(int importer, const QString& filename, bool textOnly, |
107 | // const QString& encoding, bool append, PageItem* target) |
||
364 | Franz | 108 | |
11933 | mrdocs | 109 | // Find the available plugins based on the environment, validate they load, and |
110 | // create quick lookup mappings. |
||
364 | Franz | 111 | void gtGetText::loadImporterPlugins() |
112 | { |
||
11933 | mrdocs | 113 | // Get the path to the plugins |
1693 | craig | 114 | QString gtdir = ScPaths::instance().pluginDir(); |
11933 | mrdocs | 115 | // Append the gettext path to the plugin |
872 | cbradney | 116 | gtdir += "gettext"; |
11933 | mrdocs | 117 | // Set the search parameteer for the platform specific extension for the plugins ( DLL, so, etc. ) |
1665 | craig | 118 | QString libPattern = QString("*.%1*").arg(PluginManager::platformDllExtension()); |
11933 | mrdocs | 119 | // Search for matches. |
10402 | jghali | 120 | QDir d(gtdir, libPattern, QDir::Name, (QDir::Filter) PluginManager::platformDllSearchFlags()); |
364 | Franz | 121 | |
11933 | mrdocs | 122 | // Initialize a structure for the importers found |
364 | Franz | 123 | struct ImporterData ida; |
124 | ida.fileFormatName = ""; |
||
125 | |||
11933 | mrdocs | 126 | // Check and see if the directory existed and if the count of files matching is greater than 0. |
364 | Franz | 127 | if ((d.exists()) && (d.count() != 0)) |
128 | { |
||
11933 | mrdocs | 129 | // loop through the entries. |
364 | Franz | 130 | for (uint dc = 0; dc < d.count(); ++dc) |
131 | { |
||
11933 | mrdocs | 132 | // Verify the Plugin will load. If it does, collect the info on the plugin ( Name, extension, format, etc ) |
1666 | craig | 133 | if (DLLName(d[dc], &ida.fileFormatName, &ida.fileEndings)) |
364 | Franz | 134 | { |
6361 | subik | 135 | // no plugin's "format name" marks "don't load plug" |
8461 | cbradney | 136 | if (ida.fileFormatName.isNull()) |
6361 | subik | 137 | continue; |
11933 | mrdocs | 138 | // Store the path to the plugin. |
364 | Franz | 139 | ida.soFilePath = d[dc]; |
11933 | mrdocs | 140 | // If the plugin path does not begin with /, prepend a /. |
364 | Franz | 141 | if (ida.soFilePath.left(1) != "/") |
142 | ida.soFilePath = "/" + ida.soFilePath; |
||
11933 | mrdocs | 143 | // Add the plugin data to the end of the importer's vector. |
20606 | craig | 144 | m_importers.push_back(ida); |
11933 | mrdocs | 145 | } // if (DLLName(d[dc], &ida.fileFormatName, &ida.fileEndings)) |
146 | } // for (uint dc = 0; dc < d.count(); ++dc) |
||
147 | } // if ((d.exists()) && (d.count() != 0)) |
||
148 | // Create the Importer Extension to Plugin data qmap. |
||
364 | Franz | 149 | createMap(); |
11933 | mrdocs | 150 | } // void gtGetText::loadImporterPlugins() |
364 | Franz | 151 | |
21314 | fschmid | 152 | |
153 | QStringList gtGetText::getSupportedTypes() |
||
154 | { |
||
155 | QStringList result; |
||
23294 | jghali | 156 | for (size_t i = 0; i < m_importers.size(); ++i) |
21314 | fschmid | 157 | { |
23294 | jghali | 158 | const ImporterData& importerData = m_importers[i]; |
159 | if (importerData.fileEndings.count() <= 0) |
||
160 | continue; |
||
161 | for (int j = 0; j < importerData.fileEndings.count(); ++j) |
||
162 | result.append(importerData.fileEndings[j].toLower()); |
||
21314 | fschmid | 163 | } |
164 | return result; |
||
165 | } |
||
166 | |||
11933 | mrdocs | 167 | // Creates the dialog for the user to import a file based on the supported file formats. |
6132 | cbradney | 168 | ImportSetup gtGetText::run() |
364 | Franz | 169 | { |
11933 | mrdocs | 170 | // Initialize a filters list. |
23282 | craig | 171 | QString filters; |
23294 | jghali | 172 | |
11933 | mrdocs | 173 | // Create a string for the "All supported files filter". Start with the label then loop through |
174 | // the importers vector and add all of the file extensions supported. |
||
364 | Franz | 175 | QString allSupported = QObject::tr("All Supported Formats") + " ("; |
11933 | mrdocs | 176 | // Loop through the importers vector. |
23294 | jghali | 177 | for (size_t i = 0; i < m_importers.size(); ++i) |
364 | Franz | 178 | { |
23294 | jghali | 179 | const ImporterData& importerData = m_importers[i]; |
11933 | mrdocs | 180 | // If there are any file extnsions declared by the importer |
23294 | jghali | 181 | if (importerData.fileEndings.count() <= 0) |
182 | continue; |
||
183 | // Add the importer name to the filters list |
||
184 | filters += importerData.fileFormatName + " ("; |
||
185 | // Loop though the extensions supported by the importer |
||
186 | for (int j = 0; j < importerData.fileEndings.count(); ++j) |
||
364 | Franz | 187 | { |
23294 | jghali | 188 | // Add the extension to both the filter and allSupported strings |
189 | filters += "*." + importerData.fileEndings[j] + " "; |
||
190 | allSupported += "*." + importerData.fileEndings[j] + " "; |
||
191 | } |
||
192 | // Trim the Qstring |
||
193 | filters = filters.trimmed(); |
||
194 | // Append "entry of entry" information to the end of the filter. |
||
195 | filters += ");;"; |
||
196 | } |
||
197 | |||
11933 | mrdocs | 198 | // Trim the allSupported QString and append "end of entry" data to the end of it. |
10394 | cbradney | 199 | allSupported = allSupported.trimmed(); |
364 | Franz | 200 | allSupported += ");;"; |
23294 | jghali | 201 | |
11933 | mrdocs | 202 | // Prepend allSupported to the filters Qstring. |
364 | Franz | 203 | filters = allSupported + filters; |
11933 | mrdocs | 204 | // Add an "all files" entry to the end of the filters QString |
364 | Franz | 205 | filters += QObject::tr("All Files (*)"); |
11933 | mrdocs | 206 | // Populate ilist with the file importer names. |
23294 | jghali | 207 | for (size_t i = 0; i < m_importers.size(); ++i) |
20606 | craig | 208 | m_ilist.append(m_importers[i].fileFormatName); |
23294 | jghali | 209 | |
11933 | mrdocs | 210 | // Create a new dialog. |
20606 | craig | 211 | m_dias = new gtDialogs(); |
11933 | mrdocs | 212 | // Create a new ImportSetup struct |
6132 | cbradney | 213 | ImportSetup impsetup; |
11933 | mrdocs | 214 | // INitialize runDialog to false |
6132 | cbradney | 215 | impsetup.runDialog=false; |
11933 | mrdocs | 216 | // If we get a true back from the File selection Dialog ( which we send our filters and extensions lists ) |
20606 | craig | 217 | if (m_dias->runFileDialog(filters, m_ilist)) |
364 | Franz | 218 | { |
11933 | mrdocs | 219 | // Set the runDialog to true |
20671 | fschmid | 220 | impsetup.runDialog = true; |
11933 | mrdocs | 221 | // Copy the other values for the struct from the dialog results |
20671 | fschmid | 222 | impsetup.encoding = m_dias->getEncoding(); |
223 | impsetup.filename = m_dias->getFileName(); |
||
224 | impsetup.importer = m_dias->getImporter(); |
||
225 | impsetup.textOnly = m_dias->importTextOnly(); |
||
226 | impsetup.prefixNames = m_dias->prefixStyles(); |
||
22422 | jghali | 227 | } |
11933 | mrdocs | 228 | // Destroy the dialog. |
20606 | craig | 229 | delete m_dias; |
11933 | mrdocs | 230 | // Return the ImportSetup struct. |
6132 | cbradney | 231 | return impsetup; |
11933 | mrdocs | 232 | } // ImportSetup gtGetText::run() |
364 | Franz | 233 | |
11933 | mrdocs | 234 | // Loads, validates, and executes the Importer code. |
375 | Franz | 235 | void gtGetText::CallDLL(const ImporterData& idata, const QString& filePath, |
20671 | fschmid | 236 | const QString& encoding, bool textOnly, bool append, bool prefix, PageItem* importItem) |
364 | Franz | 237 | { |
11933 | mrdocs | 238 | // Pointer for the loaded plugin. |
2831 | craig | 239 | void* gtplugin; |
11933 | mrdocs | 240 | // Type definition for GetText pointer in the function in question. |
24631 | jghali | 241 | typedef void (*gt2ptr)(const QString& filename, const QString& encoding, bool textOnly, bool prefix, bool append, PageItem *textframe); |
16699 | jghali | 242 | // Type definition for GetText pointer in the function in question. |
24631 | jghali | 243 | typedef void (*sdem)(const QString& filename, const QString& encoding, bool textOnly, gtWriter *writer); |
11933 | mrdocs | 244 | // The point to the above. |
16699 | jghali | 245 | gt2ptr fp_GetText2; |
1666 | craig | 246 | sdem fp_GetText; |
11933 | mrdocs | 247 | // Initialize Path to the "DLL" |
21942 | craig | 248 | QString pluginFilePath = QString("%1/gettext/%2").arg(ScPaths::instance().pluginDir(), idata.soFilePath); |
11933 | mrdocs | 249 | // Attempt to load the plugin, store the pointer in gtplugin |
2841 | craig | 250 | gtplugin = PluginManager::loadDLL(pluginFilePath); |
22518 | craig | 251 | // If gtplugin is nullptr we failed to load the plugin. Report an error to the user and exit the method. |
2831 | craig | 252 | if (!gtplugin) |
253 | { |
||
18194 | fschmid | 254 | qWarning("Failed to load plugin %s", pluginFilePath.toLatin1().constData()); |
2831 | craig | 255 | return; |
11933 | mrdocs | 256 | } // if (!gtplugin) |
14472 | fschmid | 257 | |
16699 | jghali | 258 | fp_GetText2 = (gt2ptr) PluginManager::resolveSym(gtplugin,"GetText2"); |
259 | if (fp_GetText2) |
||
260 | { |
||
261 | if (!append) |
||
262 | importItem->itemText.clear(); |
||
263 | // Execute the importer's "GetText2" method. |
||
21282 | fschmid | 264 | (*fp_GetText2)(filePath, encoding, textOnly, prefix, append, importItem); |
16699 | jghali | 265 | } // if (!fp_GetText2) |
266 | else |
||
267 | { |
||
268 | // Attempt to map the old GetText method to to the pointer via the PluginManager. Store the result in fp_GetText. |
||
269 | fp_GetText = (sdem) PluginManager::resolveSym(gtplugin,"GetText"); |
||
22518 | craig | 270 | // If fp_GetText is nullptr, we could not find the symbol,report the error, unload the "DLL" and exit the method. |
16699 | jghali | 271 | if (fp_GetText) |
272 | { |
||
273 | // Create a new writer object in "append"'s mode (true or false ) attached to the importItem |
||
274 | gtWriter *w = new gtWriter(append, importItem); |
||
275 | // Execute the importer's "GetText" method. |
||
276 | (*fp_GetText)(filePath, encoding, textOnly, w); |
||
277 | // Destroy the writer |
||
278 | delete w; |
||
279 | } // if (!fp_GetText) |
||
280 | else |
||
281 | { |
||
18194 | fschmid | 282 | qWarning("Failed to get GetText() from %s",pluginFilePath.toLatin1().constData()); |
16699 | jghali | 283 | } |
284 | } |
||
285 | // GetText is not quite up to date vs styles, clean char formatting already specified at paragraph level |
||
286 | importItem->itemText.fixLegacyFormatting(); |
||
287 | // Unload the plugin. |
||
288 | PluginManager::unloadDLL(gtplugin); |
||
11933 | mrdocs | 289 | } // void gtGetText::CallDLL(const ImporterData& idata, const QString& filePath, |
290 | // const QString& encoding, bool textOnly, bool append, PageItem* importItem) |
||
364 | Franz | 291 | |
11933 | mrdocs | 292 | // Loads the "DLL", validates the importer is good, populates the passed parameters with |
293 | // the plugin information. |
||
22635 | craig | 294 | bool gtGetText::DLLName(const QString& name, QString *ffName, QStringList *fEndings) |
364 | Franz | 295 | { |
11933 | mrdocs | 296 | // Pointer to the plugin, once loaded |
2831 | craig | 297 | void* gtplugin; |
11933 | mrdocs | 298 | // typedef of Qstring to map the importer name (FileFormatName) method results to. |
364 | Franz | 299 | typedef QString (*sdem0)(); |
11933 | mrdocs | 300 | // typedef of QStringList to map the file extensions supported method results to. |
364 | Franz | 301 | typedef QStringList (*sdem1)(); |
11933 | mrdocs | 302 | // The actual importer name object |
1666 | craig | 303 | sdem0 fp_FileFormatName; |
11933 | mrdocs | 304 | // The actual extensions supported object |
1666 | craig | 305 | sdem1 fp_FileExtensions; |
11933 | mrdocs | 306 | // Initialise the plugin file path ( with filename ) |
21942 | craig | 307 | QString pluginFilePath = QString("%1/gettext/%2").arg(ScPaths::instance().pluginDir(), name); |
11933 | mrdocs | 308 | // Attempt to load the plugin. |
2831 | craig | 309 | gtplugin = PluginManager::loadDLL(pluginFilePath); |
22518 | craig | 310 | // if gtplugin is nullptr we were unable to load the plugin. Return an error and exit the method. |
2831 | craig | 311 | if (!gtplugin) |
312 | { |
||
18194 | fschmid | 313 | qWarning("Failed to load plugin %s", pluginFilePath.toLatin1().constData()); |
2831 | craig | 314 | return false; |
315 | } |
||
11933 | mrdocs | 316 | // Attempt to resolve the plugin symbol to the importer name (FileFormatName) |
2831 | craig | 317 | fp_FileFormatName = (sdem0) PluginManager::resolveSym( gtplugin, "FileFormatName"); |
22518 | craig | 318 | // if fp_FileFormatName is nullptr, we could not find the FileFormatName symbol. The plugin is incomplete. |
11933 | mrdocs | 319 | // Report an error, unload the plugin, and exit the method. |
1666 | craig | 320 | if (!fp_FileFormatName) |
364 | Franz | 321 | { |
18194 | fschmid | 322 | qWarning("Failed to get FileFormatName() from %s", pluginFilePath.toLatin1().constData()); |
2831 | craig | 323 | PluginManager::unloadDLL(gtplugin); |
364 | Franz | 324 | return false; |
325 | } |
||
11933 | mrdocs | 326 | // Attempt to resolve the plugin symbol to the list of supported file extensions. |
2831 | craig | 327 | fp_FileExtensions = (sdem1) PluginManager::resolveSym( gtplugin, "FileExtensions"); |
22518 | craig | 328 | // if fp_FileExtensions is nullptr, we could not find the FileExtensions symbol. The plugin is incomplete. |
11933 | mrdocs | 329 | // Report an error, unload the plugin, and exit the method. |
1666 | craig | 330 | if (!fp_FileExtensions) |
364 | Franz | 331 | { |
18194 | fschmid | 332 | qWarning("Failed to get FileExtensions() from %s", pluginFilePath.toLatin1().constData()); |
2831 | craig | 333 | PluginManager::unloadDLL(gtplugin); |
364 | Franz | 334 | return false; |
335 | } |
||
11933 | mrdocs | 336 | // Set the format name based on the resolved method. |
1666 | craig | 337 | *ffName = (*fp_FileFormatName)(); |
11933 | mrdocs | 338 | // Set the extensions list based on the resolved method. |
1666 | craig | 339 | *fEndings = (*fp_FileExtensions)(); |
11933 | mrdocs | 340 | // Unload the plugin |
2831 | craig | 341 | PluginManager::unloadDLL(gtplugin); |
11933 | mrdocs | 342 | // Successfully return! |
364 | Franz | 343 | return true; |
11933 | mrdocs | 344 | } // bool gtGetText::DLLName(QString name, QString *ffName, QStringList *fEndings) |
364 | Franz | 345 | |
11933 | mrdocs | 346 | // Create the importer Qmap. |
364 | Franz | 347 | void gtGetText::createMap() |
348 | { |
||
11933 | mrdocs | 349 | // Loop through the importers Vector |
20606 | craig | 350 | for (uint i = 0; i < m_importers.size(); ++i) |
364 | Franz | 351 | { |
11933 | mrdocs | 352 | // Loop through each file extension the importer uses/importers and create an individual |
353 | // Qmap entry for it. |
||
20606 | craig | 354 | for (int j = 0; j < m_importers[i].fileEndings.count(); ++j) |
355 | m_importerMap.insert(m_importers[i].fileEndings[j], &m_importers[i]); |
||
11933 | mrdocs | 356 | } // for (uint i = 0; i < importers.size(); ++i) |
357 | } // void gtGetText::createMap() |
||
364 | Franz | 358 | |
11933 | mrdocs | 359 | // Destructor |
364 | Franz | 360 | gtGetText::~gtGetText() |
361 | { |
||
11933 | mrdocs | 362 | // Nothing needs to happen here. |
364 | Franz | 363 | } |