~ubuntu-branches/ubuntu/wily/ktexteditor/wily-proposed

« back to all changes in this revision

Viewing changes to src/syntax/katesyntaxdocument.cpp

  • Committer: Package Import Robot
  • Author(s): Jonathan Riddell, Jonathan Riddell, Scarlett Clark
  • Date: 2014-09-22 19:37:47 UTC
  • mfrom: (1.1.2)
  • Revision ID: package-import@ubuntu.com-20140922193747-6vhh92mz3ci4fxu1
Tags: 5.2.0-0ubuntu1
[ Jonathan Riddell ]
* New upstream release
* Use pkg-kde-tools version 3 scripts

[ Scarlett Clark ]
* Add missing dependency libqt5xmlpatterns5-dev.
* Cleanup copyright + move copyright extra details to comment to silence
  space-in-std-shortname-in-dep5-copyright lintian error.  

Show diffs side-by-side

added added

removed removed

Lines of Context:
32
32
 
33
33
#include <QApplication>
34
34
#include <QFile>
35
 
#include <QDir>
36
 
#include <QJsonDocument>
37
35
 
38
36
// use this to turn on over verbose debug output...
39
37
#undef KSD_OVER_VERBOSE
40
38
 
41
39
KateSyntaxDocument::KateSyntaxDocument()
42
 
    : QDomDocument()
43
40
{
44
 
    // Let's build the Mode List
45
 
    setupModeList();
46
41
}
47
42
 
48
43
KateSyntaxDocument::~KateSyntaxDocument()
49
44
{
50
 
    for (int i = 0; i < myModeList.size(); i++) {
51
 
        delete myModeList[i];
52
 
    }
 
45
    // cleanup, else we have a memory leak!
 
46
    clearCache();
53
47
}
54
48
 
55
49
/** If the open hl file is different from the one needed, it opens
58
52
*/
59
53
bool KateSyntaxDocument::setIdentifier(const QString &identifier)
60
54
{
61
 
    // if the current file is the same as the new one don't do anything.
62
 
    if (currentFile != identifier) {
63
 
        // let's open the new file
64
 
        QFile f(identifier);
65
 
 
66
 
        if (f.open(QIODevice::ReadOnly)) {
67
 
            // Let's parse the contets of the xml file
68
 
            /* The result of this function should be check for robustness,
69
 
               a false returned means a parse error */
70
 
            QString errorMsg;
71
 
            int line, col;
72
 
            bool success = setContent(&f, &errorMsg, &line, &col);
73
 
 
74
 
            // Ok, now the current file is the pretended one (identifier)
75
 
            currentFile = identifier;
76
 
 
77
 
            // Close the file, is not longer needed
78
 
            f.close();
79
 
 
80
 
            if (!success) {
81
 
                KMessageBox::error(QApplication::activeWindow(), i18n("<qt>The error <b>%4</b><br /> has been detected in the file %1 at %2/%3</qt>", identifier,
 
55
    // already existing in cache? be done
 
56
    if (m_domDocuments.contains(identifier)) {
 
57
        currentFile = identifier;
 
58
        return true;
 
59
    }
 
60
    
 
61
    // else: try to open
 
62
    QFile f(identifier);
 
63
    if (!f.open(QIODevice::ReadOnly)) {
 
64
         // Oh o, we couldn't open the file.
 
65
        KMessageBox::error(QApplication::activeWindow(), i18n("Unable to open %1", identifier));
 
66
        return false;
 
67
    }
 
68
    
 
69
    // try to parse
 
70
    QDomDocument *document = new QDomDocument();
 
71
    QString errorMsg;
 
72
    int line, col;
 
73
    if (!document->setContent(&f, &errorMsg, &line, &col)) {
 
74
        KMessageBox::error(QApplication::activeWindow(), i18n("<qt>The error <b>%4</b><br /> has been detected in the file %1 at %2/%3</qt>", identifier,
82
75
                                   line, col, i18nc("QXml", errorMsg.toUtf8().data())));
83
 
                return false;
84
 
            }
85
 
        } else {
86
 
            // Oh o, we couldn't open the file.
87
 
            KMessageBox::error(QApplication::activeWindow(), i18n("Unable to open %1", identifier));
88
 
            return false;
89
 
        }
 
76
        delete document;
 
77
        return false;
90
78
    }
 
79
   
 
80
    // cache and be done
 
81
    currentFile = identifier;
 
82
    m_domDocuments[currentFile] = document;
91
83
    return true;
92
84
}
93
85
 
 
86
void KateSyntaxDocument::clearCache()
 
87
{
 
88
    qDeleteAll(m_domDocuments);
 
89
    m_domDocuments.clear();
 
90
    currentFile.clear();
 
91
    m_data.clear();
 
92
}
 
93
 
94
94
/**
95
95
 * Jump to the next group, KateSyntaxContextData::currentGroup will point to the next group
96
96
 */
209
209
    qCDebug(LOG_PART) << "Looking for \"" << mainGroupName << "\" -> \"" << config << "\".";
210
210
#endif
211
211
 
212
 
    QDomNodeList nodes = documentElement().childNodes();
 
212
    QDomNodeList nodes;
 
213
    if (m_domDocuments.contains(currentFile))
 
214
        nodes = m_domDocuments[currentFile]->documentElement().childNodes();
213
215
 
214
216
    // Loop over all these child nodes looking for mainGroupName
215
217
    for (int i = 0; i < nodes.count(); i++) {
285
287
    if (clearList) {
286
288
        m_data.clear();
287
289
    }
 
290
    
 
291
    if (!m_domDocuments.contains(currentFile))
 
292
        return m_data;
288
293
 
289
 
    for (QDomNode node = documentElement().firstChild(); !node.isNull(); node = node.nextSibling()) {
 
294
    for (QDomNode node = m_domDocuments[currentFile]->documentElement().firstChild(); !node.isNull(); node = node.nextSibling()) {
290
295
        QDomElement elem = node.toElement();
291
296
        if (elem.tagName() == mainGroup) {
292
297
#ifdef KSD_OVER_VERBOSE
329
334
 
330
335
    return m_data;
331
336
}
332
 
 
333
 
// Private
334
 
/** Generate the list of hl modes, store them in myModeList
335
 
    force: if true forces to rebuild the Mode List from the xml files (instead of katesyntax...rc)
336
 
*/
337
 
void KateSyntaxDocument::setupModeList()
338
 
{
339
 
    // If there's something in myModeList the Mode List was already built so, don't do it again
340
 
    if (!myModeList.isEmpty()) {
341
 
        return;
342
 
    }
343
 
 
344
 
    // Let's get a list of all the index & xml files for hl
345
 
    QStringList dirsWithIndexFiles;
346
 
    QStringList xmlFiles;
347
 
 
348
 
    const QStringList dirs = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QLatin1String("katepart5/syntax"), QStandardPaths::LocateDirectory);
349
 
    foreach (const QString &dir, dirs) {
350
 
        QDir d(dir);
351
 
 
352
 
        // if dir has index json, only take that into account!
353
 
        if (d.exists(QStringLiteral("index.json"))) {
354
 
            dirsWithIndexFiles.append(dir);
355
 
            continue;
356
 
        }
357
 
        
358
 
        // else get all xml files
359
 
        const QStringList fileNames = d.entryList(QStringList() << QStringLiteral("*.xml"));
360
 
        foreach (const QString &file, fileNames) {
361
 
            xmlFiles.append(dir + QLatin1Char('/') + file);
362
 
        }
363
 
    }
364
 
    
365
 
    // only allow each name once!
366
 
    QSet<QString> hlNames;
367
 
    
368
 
    // preference: xml files, to allow users to overwrite system files with index!
369
 
    Q_FOREACH (const QString xmlFile, xmlFiles) {
370
 
        // We're forced to read the xml files or the mode doesn't exist in the katesyntax...rc
371
 
        QFile f(xmlFile);
372
 
        if (!f.open(QIODevice::ReadOnly))
373
 
            continue;
374
 
        
375
 
        // Ok we opened the file, let's read the contents and close the file
376
 
        /* the return of setContent should be checked because a false return shows a parsing error */
377
 
        QString errMsg;
378
 
        int line, col;
379
 
        if (!setContent(&f, &errMsg, &line, &col))
380
 
            continue;
381
 
 
382
 
        QDomElement root = documentElement();
383
 
        if (root.isNull())
384
 
            continue;
385
 
        
386
 
        // If the 'first' tag is language, go on
387
 
        if (root.tagName() != QLatin1String("language"))
388
 
            continue;
389
 
        
390
 
        // get name, only allow hls once!
391
 
        const QString name = root.attribute(QLatin1String("name"));
392
 
        if (hlNames.contains(name))
393
 
            continue;
394
 
        
395
 
        // let's make the mode list item.
396
 
        KateSyntaxModeListItem *mli = new KateSyntaxModeListItem;
397
 
 
398
 
        mli->name      = name;
399
 
        mli->section   = root.attribute(QLatin1String("section"));
400
 
        mli->mimetype  = root.attribute(QLatin1String("mimetype"));
401
 
        mli->extension = root.attribute(QLatin1String("extensions"));
402
 
        mli->version   = root.attribute(QLatin1String("version"));
403
 
        mli->priority  = root.attribute(QLatin1String("priority"));
404
 
        mli->style     = root.attribute(QLatin1String("style"));
405
 
        mli->author    = root.attribute(QLatin1String("author"));
406
 
        mli->license   = root.attribute(QLatin1String("license"));
407
 
        mli->indenter  = root.attribute(QLatin1String("indenter"));
408
 
 
409
 
        QString hidden = root.attribute(QLatin1String("hidden"));
410
 
        mli->hidden    = (hidden == QLatin1String("true") || hidden == QLatin1String("TRUE"));
411
 
 
412
 
        mli->identifier = xmlFile;
413
 
        
414
 
        // translate section + name
415
 
        mli->section    = i18nc("Language Section", mli->section.toUtf8().data());
416
 
        mli->nameTranslated = i18nc("Language", mli->name.toUtf8().data());
417
 
 
418
 
        // Append the new item to the list.
419
 
        myModeList.append(mli);
420
 
        hlNames.insert(name);
421
 
    }
422
 
    
423
 
    // now: index files
424
 
    Q_FOREACH (const QString dir, dirsWithIndexFiles) {
425
 
        /**
426
 
         * open the file for reading, bail out on error!
427
 
         */
428
 
        QFile file (dir + QStringLiteral("/index.json"));
429
 
        if (!file.open (QFile::ReadOnly))
430
 
            continue;
431
 
 
432
 
        /**
433
 
         * parse the whole file, bail out again on error!
434
 
         */
435
 
        const QJsonDocument index (QJsonDocument::fromBinaryData(file.readAll()));
436
 
        if (index.isNull())
437
 
            continue;
438
 
        
439
 
        /**
440
 
         * iterate over all hls in the index
441
 
         */
442
 
        QMapIterator<QString, QVariant> i(index.toVariant().toMap());
443
 
        while (i.hasNext()) {
444
 
            i.next();
445
 
            
446
 
            // get map
447
 
            QVariantMap map = i.value().toMap();
448
 
            
449
 
            // get name, only allow hls once!
450
 
            const QString name = map[QLatin1String("name")].toString();
451
 
            if (hlNames.contains(name))
452
 
                continue;
453
 
            
454
 
            // let's make the mode list item.
455
 
            KateSyntaxModeListItem *mli = new KateSyntaxModeListItem;
456
 
 
457
 
            mli->name      = name;
458
 
            mli->section   = map[QLatin1String("section")].toString();
459
 
            mli->mimetype  = map[QLatin1String("mimetype")].toString();
460
 
            mli->extension = map[QLatin1String("extensions")].toString();
461
 
            mli->version   = map[QLatin1String("version")].toString();
462
 
            mli->priority  = map[QLatin1String("priority")].toString();
463
 
            mli->style     = map[QLatin1String("style")].toString();
464
 
            mli->author    = map[QLatin1String("author")].toString();
465
 
            mli->license   = map[QLatin1String("license")].toString();
466
 
            mli->indenter  = map[QLatin1String("indenter")].toString();
467
 
            mli->hidden    = map[QLatin1String("hidden")].toBool();
468
 
 
469
 
            mli->identifier = dir + QLatin1Char('/') + i.key();
470
 
            
471
 
            // translate section + name
472
 
            mli->section    = i18nc("Language Section", mli->section.toUtf8().data());
473
 
            mli->nameTranslated = i18nc("Language", mli->name.toUtf8().data());
474
 
 
475
 
            // Append the new item to the list.
476
 
            myModeList.append(mli);
477
 
            hlNames.insert(name);
478
 
        }
479
 
    }
480
 
}
481