Subversion Repositories Scribus

Rev

Rev 12562 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
10620 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
*/
7
/***************************************************************************
8
                                                latexeditor.cpp  -  description
9
                                                -------------------
10
copyright            : Scribus Team
11
***************************************************************************/
12
 
13
/***************************************************************************
14
*                                                                         *
15
*   This program is free software; you can redistribute it and/or modify  *
16
*   it under the terms of the GNU General Public License as published by  *
17
*   the Free Software Foundation; either version 2 of the License, or     *
18
*   (at your option) any later version.                                   *
19
*                                                                         *
20
***************************************************************************/
21
#include "latexeditor.h"
11504 mrdocs 22
#include "latexhelpers.h"
10620 cbradney 23
#include "pageitem_latexframe.h"
11012 mrdocs 24
#include "prefsmanager.h"
25
 
10620 cbradney 26
#include <QDebug>
11012 mrdocs 27
#include <QFile>
28
#include <QFrame>
29
#include <QFontComboBox>
30
#include <QLineEdit>
31
#include <QPushButton>
32
#include <QListWidget>
11504 mrdocs 33
#include <QMessageBox>
12562 herm 34
#include <QTemporaryFile>
11012 mrdocs 35
#include <math.h>
12562 herm 36
#include "filewatcher.h"
37
#include "util.h"
10620 cbradney 38
 
39
LatexEditor::LatexEditor(PageItem_LatexFrame *frame):QDialog(), frame(frame)
40
{
41
        setupUi(this);
11504 mrdocs 42
 
43
        //Fill application list
44
        programComboBox->clear();
45
        QStringList configs = PrefsManager::instance()->latexConfigs();
46
        foreach (QString config, configs) {
47
                QString name = LatexConfigCache::instance()->parser(config)->description();
48
                programComboBox->addItem(name, config);
49
                QString iconname = LatexConfigCache::instance()->parser(config)->icon();
50
                if (!iconname.isEmpty()) {
51
                        programComboBox->setItemIcon(programComboBox->count()-1,
52
                                icon(config, iconname));
53
                }
54
        }
55
 
10620 cbradney 56
        highlighter = new LatexHighlighter(sourceTextEdit->document());
11012 mrdocs 57
        connect(buttonBox, SIGNAL(accepted()),
58
                        this, SLOT(okClicked()));
59
        connect(buttonBox, SIGNAL(rejected()),
60
                        this, SLOT(cancelClicked()));
61
        connect(updatePushButton, SIGNAL(clicked(bool)),
62
                        this, SLOT(updateClicked(bool)));
63
        connect(revertPushButton, SIGNAL(clicked(bool)),
64
                        this, SLOT(revertClicked(bool)));
65
        connect(killPushButton, SIGNAL(clicked(bool)),
66
                        frame, SLOT(killProcess()));
12562 herm 67
        connect(externalEditorPushButton, SIGNAL(clicked(bool)),
68
                        this, SLOT(extEditorClicked()));
11012 mrdocs 69
        connect(frame, SIGNAL(formulaAutoUpdate(QString, QString)),
70
                        this, SLOT(formulaChanged(QString, QString)));
71
        connect(frame, SIGNAL(latexFinished()),
72
                        this, SLOT(latexFinished()));
10620 cbradney 73
        connect(frame, SIGNAL(stateChanged(QProcess::ProcessState)),
74
                        this, SLOT(stateChanged(QProcess::ProcessState)));
11504 mrdocs 75
        connect(frame, SIGNAL(applicationChanged()),
76
                        this, SLOT(updateConfigFile()));
77
        updateConfigFile();
12562 herm 78
 
79
        extEditor = new QProcess();
80
        connect(extEditor, SIGNAL(finished(int, QProcess::ExitStatus)),
81
                this, SLOT(extEditorFinished(int, QProcess::ExitStatus)));
82
        connect(extEditor, SIGNAL(error(QProcess::ProcessError)),
83
                this, SLOT(extEditorError(QProcess::ProcessError)));   
84
        extEditor->setProcessChannelMode(QProcess::MergedChannels);
85
 
86
        fileWatcher = new FileWatcher(this);
87
        fileWatcher->stop();
88
        fileWatcher->setTimeOut(1500);
10620 cbradney 89
}
90
 
91
LatexEditor::~LatexEditor()
92
{
12562 herm 93
        //IMPORTANT: Make sure no signals are emitted which
94
        // would cause crashes because the handlers access undefined memory.
95
        fileWatcher->disconnect();
96
        delete fileWatcher;
97
 
98
        extEditor->disconnect();
99
        //No need to kill the editor
100
        delete extEditor;
101
 
102
        QDir dir;
103
        if (!extEditorFile.isEmpty() && !dir.remove(extEditorFile)) {
104
                qCritical() << "RENDER FRAME: Failed to remove editorfile" << qPrintable(extEditorFile);
105
        }
106
 
107
 
10620 cbradney 108
        buttonBox->disconnect();
109
        exitEditor();
110
        delete highlighter;
111
}
112
 
113
void LatexEditor::startEditor()
114
{
115
        revert();
11012 mrdocs 116
        initialize();
10620 cbradney 117
        show();
118
}
119
 
12562 herm 120
void LatexEditor::extEditorClicked()
121
{
122
        if (extEditor->state() != QProcess::NotRunning) {
123
                QMessageBox::information(0, tr("Information"),
124
                "<qt>" + tr("An editor for this frame is already running!") +
125
                "</qt>", 1, 0, 0);
126
                return;
127
        }
128
        externalEditorPushButton->setEnabled(false);
129
        externalEditorPushButton->setText(tr("Editor running!"));
130
 
131
        QString full_command = PrefsManager::instance()->latexEditorExecutable();
132
        if (full_command.isEmpty()) {
133
                QMessageBox::information(0, tr("Information"),
134
                "<qt>" + tr("Please specify an editor in the preferences!") +
135
                "</qt>",1, 0, 0);
136
                return;
137
        }
138
 
139
        writeExternalEditorFile(); //This command must be at this position, because it sets editorFile
140
 
141
        QString editorFilePath = QString("\"%1\"").arg(extEditorFile);
142
        QString tempFilePath   = getLongPathName(QDir::tempPath());
143
        if (full_command.contains("%file")) {
144
                full_command.replace("%file", QDir::toNativeSeparators(editorFilePath));
145
        } else {
146
                full_command += " " + QDir::toNativeSeparators(editorFilePath);
147
        }
148
        full_command.replace("%dir", QDir::toNativeSeparators(tempFilePath));
149
        extEditor->setWorkingDirectory(QDir::tempPath());
150
 
151
        extEditor->start(full_command);
152
}
153
 
154
void LatexEditor::writeExternalEditorFile()
155
{
156
        fileWatcher->stop();
157
        fileWatcher->disconnect(); //Avoid triggering false updates
158
 
159
        //First create a temp file name
160
        if (extEditorFile.isEmpty()) {
161
                QTemporaryFile *editortempfile = new QTemporaryFile(
162
                        QDir::tempPath() + "/scribus_temp_editor_XXXXXX");
163
                if (!editortempfile->open()) {
164
                        QMessageBox::critical(0, tr("Error"), "<qt>" +
165
                                tr("Could not create a temporary file to run the external editor!")
166
                                + "</qt>", 1, 0, 0);
167
                }
168
                extEditorFile = getLongPathName(editortempfile->fileName());
169
                editortempfile->setAutoRemove(false);
170
                editortempfile->close();
171
                delete editortempfile;
172
                fileWatcher->addFile(extEditorFile);
173
        }
174
        QFile f(extEditorFile);
175
        f.open(QIODevice::WriteOnly);
176
        f.write(frame->formula().toUtf8());
177
        f.close();
178
        fileWatcher->forceScan();
179
        connect(fileWatcher, SIGNAL(fileChanged(QString)),
180
                this, SLOT(extEditorFileChanged(QString)));
181
        fileWatcher->start();
182
}
183
 
184
void LatexEditor::loadExternalEditorFile()
185
{
186
        QString new_formula;
187
        QFile f(extEditorFile);
188
        f.open(QIODevice::ReadOnly);
189
        new_formula = QString::fromUtf8(f.readAll());
190
        f.close();
191
        if (!new_formula.isEmpty()) {
192
                frame->setFormula(new_formula);
193
                sourceTextEdit->setPlainText(new_formula);
194
        }
195
        this->update();
196
}
197
 
198
void LatexEditor::extEditorFinished(int exitCode, QProcess::ExitStatus exitStatus)
199
{
200
        externalEditorPushButton->setEnabled(true);
12611 cbradney 201
        externalEditorPushButton->setText( tr("Run External Editor...") );
12562 herm 202
        if (exitCode && extEditor) {
203
                qCritical() << "RENDER FRAME: Editor failed. Output was: " <<
204
                        qPrintable(QString(extEditor->readAllStandardOutput()));
205
                QMessageBox::critical(0, tr("Error"), "<qt>" +
206
                        tr("Running the editor failed with exitcode %d!").arg(exitCode) +
207
                        "</qt>", 1, 0, 0);
208
                return;
209
        }
210
}
211
 
212
void LatexEditor::extEditorFileChanged(QString filename)
213
{
214
        loadExternalEditorFile();
215
        frame->rerunApplication();
216
}
217
 
218
void LatexEditor::extEditorError(QProcess::ProcessError error)
219
{
220
        externalEditorPushButton->setEnabled(true);
12611 cbradney 221
        externalEditorPushButton->setText( tr("Run External Editor...") );
12562 herm 222
        QMessageBox::critical(0, tr("Error"), "<qt>" +
223
                tr("Running the editor \"%1\" failed!").
224
                arg(PrefsManager::instance()->latexEditorExecutable()) +
225
                "</qt>", 1, 0, 0);
226
}
227
 
10620 cbradney 228
void LatexEditor::exitEditor()
229
{
230
        hide();
231
}
232
 
233
void LatexEditor::revert()
234
{
11504 mrdocs 235
        sourceTextEdit->setPlainText(frame->formula());
10620 cbradney 236
}
237
 
11012 mrdocs 238
void LatexEditor::initialize()
239
{
11504 mrdocs 240
        preambleCheckBox->setChecked(frame->usePreamble());
241
        dpiSpinBox->setValue(frame->dpi());
242
        stateChanged(frame->state());
243
        messagesTextEdit->setPlainText(frame->output());
11012 mrdocs 244
}
245
 
11386 mrdocs 246
void LatexEditor::apply(bool force)
10620 cbradney 247
{
11504 mrdocs 248
        bool changed = frame->setFormula(sourceTextEdit->toPlainText());
249
 
250
        QString newConfig = programComboBox->itemData(programComboBox->currentIndex()).toString();
251
        if (newConfig != frame->configFile()) {
11413 mrdocs 252
                changed = true;
11504 mrdocs 253
                frame->setConfigFile(newConfig);
254
        }
255
 
256
        if (frame->usePreamble() != preambleCheckBox->isChecked() ||
257
                frame->dpi() != dpiSpinBox->value()) {
258
                changed = true;
11413 mrdocs 259
                frame->setUsePreamble(preambleCheckBox->isChecked());
260
                frame->setDpi(dpiSpinBox->value());
261
        }
11012 mrdocs 262
        QString key;
263
        QString value;
264
 
265
        QMapIterator<QString, XmlWidget *> i(widgetMap);
266
        while (i.hasNext()) {
267
                i.next();
268
                key = i.key();
269
                value = i.value()->toString();
270
                if (frame->editorProperties[key] != value) {
271
                        changed = true;
272
                        frame->editorProperties[key] = value;
273
                }
274
        }
275
 
11504 mrdocs 276
        if (changed || force) {
10620 cbradney 277
                frame->rerunApplication(true);
278
        }
279
}
280
 
281
void LatexEditor::formulaChanged(QString oldText, QString newText)
282
{
283
        sourceTextEdit->setPlainText(newText);
284
}
285
 
286
void LatexEditor::okClicked()
287
{
288
        apply();
289
        exitEditor();
290
}
291
 
292
void LatexEditor::cancelClicked()
293
{
294
        revert();
295
        exitEditor();
296
}
297
 
298
void LatexEditor::revertClicked(bool unused)
299
{
300
        revert();
301
}
302
 
303
void LatexEditor::updateClicked(bool unused)
304
{
11386 mrdocs 305
        apply(true);
10620 cbradney 306
}
307
 
308
void LatexEditor::latexFinished()
309
{
11504 mrdocs 310
        messagesTextEdit->setPlainText(frame->output());
10620 cbradney 311
}
312
 
313
void LatexEditor::stateChanged(QProcess::ProcessState state)
314
{
315
        if (state == QProcess::Starting) {
316
                messagesTextEdit->setPlainText("");
317
        }
12611 cbradney 318
        QString text( tr("Status: ") );
319
        if (state == QProcess::NotRunning)
320
        {
321
                if (frame->error())
11012 mrdocs 322
                        text += tr("Error");
12611 cbradney 323
                else
11386 mrdocs 324
                        text += tr("Finished");
12611 cbradney 325
        }
326
        else
11012 mrdocs 327
                text += tr("Running");
12611 cbradney 328
 
11012 mrdocs 329
        statusLabel->setText(text);
10620 cbradney 330
        killPushButton->setEnabled(state != QProcess::NotRunning);
331
}
332
 
11504 mrdocs 333
QIcon LatexEditor::icon(QString config, QString fn)
11012 mrdocs 334
{
11504 mrdocs 335
        QFileInfo fiConfig(config);
336
        QFileInfo fiIcon(fiConfig.path()+"/"+fn);
337
        if (fiIcon.exists() && fiIcon.isReadable()) {
338
                return QIcon(fiConfig.path()+"/"+fn);
339
        } else {
340
                QIcon *tmp = IconBuffer::instance()->icon(
341
                        fiConfig.path() + "/" + fiConfig.completeBaseName() + ".tar", fn);
342
                if (tmp) return *tmp; else return QIcon();
343
        }
344
}
345
 
346
 
347
QString LatexEditor::iconFile(QString config)
348
{
349
        QFileInfo fiConfig(config);
350
        return fiConfig.path() + "/" + fiConfig.completeBaseName() + ".tar";
351
}
352
 
353
void LatexEditor::updateConfigFile()
354
{
355
        if (currentConfigFile == frame->configFile()) return;
356
        currentConfigFile = frame->configFile();
357
        currentIconFile = iconFile(currentConfigFile);
358
        QFileInfo fi(currentConfigFile);
359
 
360
        if (!fi.exists() || !fi.isReadable()) {
361
                QMessageBox::critical(0, QObject::tr("Error"), "<qt>" +
362
                                QObject::tr("Configfile %1 not found or the file is not readable").
363
                                arg(currentConfigFile) + "</qt>", 1, 0, 0);
364
                return;
365
        }
366
 
11012 mrdocs 367
        loadSettings();
368
 
369
        QMapIterator<QString, XmlWidget *> i(widgetMap);
370
        while (i.hasNext()) {
371
                i.next();
372
                QString key = i.key();
373
                XmlWidget *value = i.value();
374
                if (frame->editorProperties.contains(key)) {
375
                        value->fromString(frame->editorProperties[key]);
376
                }
377
        }
378
}
379
 
12370 herm 380
#define xmlError() qWarning() << "XML-ERROR:" << xml->lineNumber() \
11012 mrdocs 381
        << ":" << xml->columnNumber() << ":"
382
 
383
void LatexEditor::loadSettings()
384
{
385
        while (tabWidget->count()>1) {
386
                QWidget *widget = tabWidget->widget(1);
387
                tabWidget->removeTab(1);
388
                delete widget;
389
        }
390
        widgetMap.clear();
391
 
11504 mrdocs 392
        QFile f(frame->configFile());
11012 mrdocs 393
        f.open(QIODevice::ReadOnly);
11504 mrdocs 394
        I18nXmlStreamReader xml(&f);
11012 mrdocs 395
        while (!xml.atEnd()) {
396
                xml.readNext();
397
                if (xml.isWhitespace() || xml.isComment()) continue;
398
                if (xml.isStartElement() && xml.name() == "tab") {
399
                        if (xml.attributes().value("type") == "settings") {
400
                                createNewSettingsTab(&xml);
401
                        } else if (xml.attributes().value("type") == "items") {
402
                                createNewItemsTab(&xml);
403
                        } else {
12370 herm 404
                                qWarning() << "XML-ERROR: " << xml.lineNumber() << ":"
11012 mrdocs 405
                                                << xml.columnNumber() << ":" << "Unknow tab type"
406
                                                << xml.attributes().value("type").toString();
407
                        }
408
                }
409
        }
410
        if (xml.hasError()) {
12370 herm 411
                qWarning() << "XML-ERROR: " << xml.lineNumber() << ":"
11012 mrdocs 412
                                << xml.columnNumber() << ":" << xml.errorString();
413
        }
11504 mrdocs 414
        f.close();
11012 mrdocs 415
}
416
 
11504 mrdocs 417
void LatexEditor::createNewSettingsTab(I18nXmlStreamReader *xml)
11012 mrdocs 418
{
419
        QStringRef tagname;
420
        QFrame *newTab = new QFrame();
421
        newTab->setFrameShape(QFrame::NoFrame);
422
        QGridLayout *layout = new QGridLayout(newTab);
423
        layout->setColumnStretch(1, 10);
424
        QString type = xml->attributes().value("type").toString();
425
 
426
        QString title = "No Title";
427
 
428
        while (!xml->atEnd()) {
429
                xml->readNext();
430
                if (xml->isWhitespace() || xml->isComment()) continue;
431
                tagname = xml->name();
432
                if (xml->isEndElement() && (tagname == "tab")) {
433
                        break;
434
                }
435
                if (!xml->isStartElement()) {
436
                        xmlError() << "Unexpected element (not a start element)!";
437
                        continue;
438
                }
439
 
440
                if (tagname == "comment") {
11504 mrdocs 441
                        QLabel *label = new QLabel(xml->readI18nText());
11012 mrdocs 442
                        int row = layout->rowCount();
11386 mrdocs 443
                        label->setWordWrap(true);
11012 mrdocs 444
                        layout->addWidget(label, row, 0, 1, 3);
445
                } else if (tagname == "title") {
11504 mrdocs 446
                        title = xml->readI18nText();
11012 mrdocs 447
                } else {
448
                        XmlWidget *widget = XmlWidget::fromXml(xml);
449
                        if (dynamic_cast<QWidget *>(widget)) {
450
                                QLabel *label = new QLabel(widget->description());
11386 mrdocs 451
                                label->setWordWrap(true);
11012 mrdocs 452
                                QString name = widget->name();
453
 
454
                                int row = layout->rowCount();
455
                                layout->addWidget(label, row, 0);
456
                                layout->addWidget(dynamic_cast<QWidget *>(widget), row, 1);
457
 
11386 mrdocs 458
                                /* Commented out, because it doesn't make much sense. All
459
                                   the options should be handled in the preamble. Keeping this
460
                                   around as a reference for future widgets.
11012 mrdocs 461
                                StringPushButton *button = new StringPushButton(
462
                                                tr("Insert"), name);
463
                                connect(button, SIGNAL(clickedWithData(QString)),
464
                                                this, SLOT(tagButtonClicked(QString)));
11386 mrdocs 465
                                layout->addWidget(button, row, 2);*/
11012 mrdocs 466
 
467
                                if (widgetMap.contains(name)) {
468
                                        xmlError() << "There is already an widget with name" <<
469
                                                name << "!";
470
                                }
471
                                widgetMap[name] = widget;
472
                        } else {
473
                                xmlError() << "Unexpected tag" << tagname.toString() <<
474
                                                "in settings tab";
475
                        }
476
                }
477
        }
478
        layout->setRowStretch(layout->rowCount(), 10);
479
        tabWidget->addTab(newTab, title);
480
}
481
 
11504 mrdocs 482
void LatexEditor::createNewItemsTab(I18nXmlStreamReader *xml)
11012 mrdocs 483
{
484
        QString title = "No Title!";
485
 
486
 
487
        QFrame *newTab = new QFrame();
488
        newTab->setFrameShape(QFrame::NoFrame);
489
        QVBoxLayout *vLayout = new QVBoxLayout(newTab);
490
 
491
        QListWidget *iconList = new QListWidget();
492
        iconList->setViewMode(QListView::IconMode);
493
        iconList->setGridSize(QSize(55, 55));
494
        iconList->setMovement(QListView::Static);
11504 mrdocs 495
        iconList->setFlow(QListView::LeftToRight);
496
        iconList->setWrapping(true);
497
        iconList->setResizeMode(QListView::Adjust);
498
 
11012 mrdocs 499
        connect(iconList, SIGNAL(currentItemChanged(QListWidgetItem *, QListWidgetItem *)),
500
                        this,     SLOT  (newItemSelected   (QListWidgetItem *, QListWidgetItem *)));
501
        connect(iconList, SIGNAL(itemDoubleClicked (QListWidgetItem *)),
502
                        this,     SLOT  (itemDoubleClicked (QListWidgetItem *)));
503
 
504
        QHBoxLayout *hLayout = new QHBoxLayout();
505
        QLabel *statusLabel = new QLabel(tr("No item selected!"));
506
        DataPushButton *insertPushButton = new DataPushButton(
507
                        tr("Insert symbol"), iconList);
508
        connect(insertPushButton, SIGNAL(clickedWithData(QObject *)),
509
                        this, SLOT(insertButtonClicked(QObject *)));
510
        hLayout->addWidget(statusLabel, 100);
511
        hLayout->addWidget(insertPushButton, 0);
512
 
513
        vLayout->addWidget(iconList, 100);
514
        vLayout->addLayout(hLayout, 0);
515
 
516
        QStringRef tagname;
517
        while (!xml->atEnd()) {
518
                xml->readNext();
519
                if (xml->isWhitespace() || xml->isComment()) continue;
520
                tagname = xml->name();
521
                if (xml->isEndElement() && (tagname == "tab")) {
522
                        break;
523
                }
524
                if (!xml->isStartElement()) {
525
                        xmlError() << "Unexpected end element "
526
                                        <<tagname.toString()<<"in item tab";
527
                        continue;
528
                }
529
                if (tagname == "title") {
11504 mrdocs 530
                        title = xml->readI18nText();
11012 mrdocs 531
                } else if (tagname == "item") {
532
                        QString value = xml->attributes().value("value").toString();
533
                        QString img = xml->attributes().value("image").toString();
11504 mrdocs 534
                        QString text = xml->readI18nText();
11012 mrdocs 535
 
536
                        QString status = value;
537
                        if (text.isEmpty()) {
538
                                text = value;
539
                        } else if (text != value) {
540
                                status = text + "(" + value +")";
541
                        }
542
 
543
                        QIcon *icon = 0;
544
                        if (!img.isEmpty()) {
11504 mrdocs 545
                                icon = IconBuffer::instance()->icon(currentIconFile, img);
11012 mrdocs 546
                        }
547
                        QListWidgetItem *item;
548
                        if (!icon) {
549
                                item = new QListWidgetItem(text, iconList);
550
                        } else {
551
                                item = new QListWidgetItem(*icon, "", iconList);
552
                        }
553
                        item->setData(Qt::UserRole, value);
554
                        item->setData(Qt::UserRole + 1,
555
                                qVariantFromValue((void *) statusLabel)); //UGLY
556
                        item->setToolTip(text);
557
                        item->setStatusTip(status);
558
                } else {
559
                        xmlError() << "Unexpected tag" << tagname.toString() <<
560
                                "in item tab!";
561
                        continue;
562
                }
563
        }
564
        tabWidget->addTab(newTab, title);
565
}
566
 
567
void LatexEditor::tagButtonClicked(QString tagname)
568
{
569
        sourceTextEdit->insertPlainText("$scribus_"+tagname+"$");
570
}
571
 
572
void LatexEditor::newItemSelected(QListWidgetItem *newItem, QListWidgetItem *)
573
{
574
        QLabel *label = (QLabel *)(newItem->data(Qt::UserRole + 1).value<void *>());
575
        label->setText(newItem->statusTip());
576
}
577
 
578
void LatexEditor::itemDoubleClicked(QListWidgetItem *item)
579
{
580
        sourceTextEdit->insertPlainText(item->data(Qt::UserRole).toString());
581
}
582
 
583
void LatexEditor::insertButtonClicked(QObject *widget)
584
{
585
        QListWidget *list = dynamic_cast<QListWidget*>(widget);
586
        Q_ASSERT(list);
587
        sourceTextEdit->insertPlainText(
588
                list->currentItem()->data(Qt::UserRole).toString());
589
}
590
 
591
 
592
class SCRIBUS_API XmlFontComboBox : public XmlWidget, public QFontComboBox
593
{
594
        public:
11504 mrdocs 595
                XmlFontComboBox(I18nXmlStreamReader *xml) : XmlWidget(xml), QFontComboBox()
11012 mrdocs 596
                {
597
                        fromString(m_defaultValue);
598
                }
599
 
600
                QString toString() const {
601
                        return currentFont().toString();
602
                }
603
 
604
                void fromString(QString str) {
605
                        QFont font;
606
                        font.fromString(str);
607
                        this->setCurrentFont(font);
608
                }
609
};
610
 
611
class SCRIBUS_API XmlSpinBox : public XmlWidget, public QSpinBox
612
{
613
        public:
11504 mrdocs 614
                XmlSpinBox(I18nXmlStreamReader *xml) :  XmlWidget(xml, false), QSpinBox() {
11012 mrdocs 615
                        setRange(
616
                                xml->attributes().value("min").toString().toInt(),
617
                                xml->attributes().value("max").toString().toInt()
618
                        );
619
                        setSingleStep(xml->attributes().value("step").toString().toInt());
11413 mrdocs 620
                        setSpecialValueText(xml->attributes().value("special").toString());
11012 mrdocs 621
                        fromString(m_defaultValue);
11504 mrdocs 622
                        m_description = xml->readI18nText();
11012 mrdocs 623
                }
624
 
625
                QString toString() const {
11413 mrdocs 626
                        if (value() == minimum() && !specialValueText().isEmpty()) {
627
                                return specialValueText();
628
                        } else {
629
                                return QString::number(value());
630
                        }
11012 mrdocs 631
                }
632
 
633
                void fromString(QString str) {
11413 mrdocs 634
                        if (str == specialValueText()) {
635
                                setValue(minimum());
636
                        } else {
637
                                setValue(str.toInt());
638
                        }
11012 mrdocs 639
                }
640
};
641
 
642
class SCRIBUS_API XmlDoubleSpinBox : public XmlWidget, public QDoubleSpinBox
643
{
644
        public:
11504 mrdocs 645
                XmlDoubleSpinBox(I18nXmlStreamReader *xml) :
11012 mrdocs 646
                        XmlWidget(xml, false), QDoubleSpinBox() {
647
                        setRange(
648
                                xml->attributes().value("min").toString().toDouble(),
649
                                xml->attributes().value("max").toString().toDouble()
650
                        );
651
                        setSingleStep(
652
                                xml->attributes().value("step").toString().toDouble());
11413 mrdocs 653
                        setSpecialValueText(xml->attributes().value("special").toString());
11012 mrdocs 654
                        fromString(m_defaultValue);
11504 mrdocs 655
                        m_description = xml->readI18nText();
11012 mrdocs 656
                }
657
 
658
                QString toString() const {
11413 mrdocs 659
                        if (value() == minimum() && !specialValueText().isEmpty()) {
660
                                return specialValueText();
661
                        } else {
662
                                return QString::number(value());
663
                        }
11012 mrdocs 664
                }
665
 
666
                void fromString(QString str) {
11413 mrdocs 667
                        if (str == specialValueText()) {
668
                                setValue(minimum());
669
                        } else {
670
                                setValue(str.toDouble());
671
                        }
11012 mrdocs 672
                }
673
};
674
 
675
class SCRIBUS_API XmlLineEdit : public XmlWidget, public QLineEdit
676
{
677
        public:
11504 mrdocs 678
                XmlLineEdit(I18nXmlStreamReader *xml) :  XmlWidget(xml), QLineEdit() {
11012 mrdocs 679
                        fromString(m_defaultValue);
680
                }
681
 
682
                QString toString() const {
683
                        return text();
684
                }
685
 
686
                void fromString(QString str) {
687
                        setText(str);
688
                }
689
};
690
 
691
class SCRIBUS_API XmlTextEdit : public XmlWidget, public QTextEdit
692
{
693
        public:
11504 mrdocs 694
                XmlTextEdit(I18nXmlStreamReader *xml) :  XmlWidget(xml), QTextEdit() {
11012 mrdocs 695
                        fromString(m_defaultValue);
696
                }
697
 
698
                QString toString() const {
699
                        return toPlainText();
700
                }
701
 
702
                void fromString(QString str) {
703
                        setPlainText(str);
704
                }
705
};
706
 
707
class SCRIBUS_API XmlColorPicker : public XmlWidget, public QLabel
708
{
709
        public:
11504 mrdocs 710
                XmlColorPicker(I18nXmlStreamReader *xml) :  XmlWidget(xml),
12611 cbradney 711
                        QLabel("Color pickers are not implemented yet!")
11012 mrdocs 712
                {
11386 mrdocs 713
                        setWordWrap(true);
11012 mrdocs 714
                        fromString(m_defaultValue);
715
                }
716
 
717
                QString toString() const {
718
                        return "Not implemented!";
719
                }
720
 
721
                void fromString(QString str) {
722
                        qDebug() << "Color pickers are not implemented yet!";
723
                }
724
};
725
 
726
class SCRIBUS_API XmlComboBox : public XmlWidget, public QComboBox
727
{
728
        public:
11504 mrdocs 729
                XmlComboBox(I18nXmlStreamReader *xml) :  XmlWidget(xml, false), QComboBox()
11012 mrdocs 730
                {
731
                        QStringRef tagname;
732
                        while (!xml->atEnd()) {
733
                                xml->readNext();
734
                                if (xml->isWhitespace() || xml->isComment()) continue;
735
                                tagname = xml->name();
736
                                if (xml->isEndElement() && (tagname == "list")) {
737
                                        fromString(m_defaultValue);
738
                                        return;
739
                                }
740
                                if (xml->isEndElement()) {
741
                                        xmlError() << "Unexpected end element" << tagname.toString();
742
                                        continue;
743
                                }
744
                                if (tagname == "title") {
11504 mrdocs 745
                                        m_description = xml->readI18nText();
11012 mrdocs 746
                                } else if (tagname == "option") {
747
                                        QString value = xml->attributes().value("value").toString();
11504 mrdocs 748
                                        QString text = xml->readI18nText();
11012 mrdocs 749
                                        addItem(text, value);
750
                                } else {
751
                                        xmlError() << "Unexpected tag" << tagname.toString() <<
752
                                                "in list!";
753
                                }
754
                        }
755
                }
756
 
757
                QString toString() const {
758
                        return itemData(currentIndex()).toString();
759
                }
760
 
761
                void fromString(QString str) {
762
                        setCurrentIndex(findData(str));
763
                }
764
};
765
 
11504 mrdocs 766
XmlWidget* XmlWidget::fromXml(I18nXmlStreamReader *xml)
11012 mrdocs 767
{
768
        QStringRef tagname = xml->name();
769
        if (tagname == "font") {
770
                return new XmlFontComboBox(xml);
771
        }
772
        if (tagname == "spinbox") {
773
                if (xml->attributes().value("type") == "double")
774
                        return new XmlDoubleSpinBox(xml);
775
                else
776
                        return new XmlSpinBox(xml);
777
        }
778
        if (tagname == "color") {
779
                return new XmlColorPicker(xml);
780
        }
781
        if (tagname == "text") {
782
                if (xml->attributes().value("type") == "long")
783
                        return new XmlTextEdit(xml);
784
                else
785
                        return new XmlLineEdit(xml);
786
        }
787
        if (tagname == "list") {
788
                return new XmlComboBox(xml);
789
        }
790
        return 0;
791
}
792
 
11504 mrdocs 793
XmlWidget::XmlWidget(I18nXmlStreamReader *xml, bool readDescription)
11012 mrdocs 794
{
795
        m_name = xml->attributes().value("name").toString();
796
        m_defaultValue = xml->attributes().value("default").toString();
797
        if (readDescription)
11504 mrdocs 798
                m_description = xml->readI18nText();
11012 mrdocs 799
}
800
 
801
void IconBuffer::loadFile(QString filename)
802
{
803
        if (loadedFiles.contains(filename)) return;
804
        loadedFiles << filename;
805
        file = new QFile(filename);
806
        file->open(QIODevice::ReadOnly);
807
        basePos = 0;
808
        while (!file->atEnd()) {
809
                QString name = readHeader();
810
                if (name.isEmpty()) break;
811
                if (!len) continue;
812
                icons.insert(filename + ":" + name, readData());
813
        }
814
        file->close();
815
        delete file;
816
        file = 0;
817
}
818
 
11504 mrdocs 819
QIcon *IconBuffer::icon(QString filename, QString name)
11012 mrdocs 820
{
821
        loadFile(filename);
822
        QString cname = filename + ":" + name;
823
        if (icons.contains(cname)) {
824
                return &(icons[cname]);
825
        } else {
12370 herm 826
                qWarning() << "Icon" << cname << "not found!";
11012 mrdocs 827
                return 0;
828
        }
829
}
830
 
831
QString IconBuffer::readHeader()
832
{
833
        //TODO: Error checking
834
        Q_ASSERT(file);
835
        char buffer[101];
836
        file->seek(basePos);
837
        file->read(buffer, 100);
838
        buffer[100] = 0;
839
        QString name = QString::fromAscii(buffer);
840
        file->seek(basePos + 124);
841
        file->read(buffer, 12);
842
        buffer[12] = 0;
843
        bool ok;
844
        len = QString::fromAscii(buffer).toInt(&ok, 8);
845
        basePos += 512;
846
        return name;
847
}
848
 
849
QIcon IconBuffer::readData()
850
{
851
        file->seek(basePos);
852
        QByteArray data = file->read(len);
853
        QPixmap pixmap;
854
        pixmap.loadFromData(data);
11229 fschmid 855
        basePos += static_cast<int>(ceil(len/512.0) * 512);
11012 mrdocs 856
        return QIcon(pixmap);
857
}
858
 
859
IconBuffer *IconBuffer::_instance = 0;
860
IconBuffer *IconBuffer::instance()
861
{
862
        if (!_instance) {
863
                _instance = new IconBuffer();
864
        }
865
        return _instance;
866
}