Root/Software/sie_cg/mainwindow.cpp

1/****************************************************************************
2**
3** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation (qt-info@nokia.com)
6**
7** This file is part of the examples of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at qt-info@nokia.com.
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include <QtGui>
43#include <QLabel>
44
45#include "mainwindow.h"
46
47const int InsertTextButton = 100000;
48
49MainWindow::MainWindow()
50{
51    domElementsByName=0;
52    buttonGroup=0;
53    toolBox=0;
54    statusBar = new QStatusBar(this);
55    createActions();
56    createMenus();
57    scene = new DiagramScene(itemMenu,this);
58    scene->setSceneRect(QRectF(0, 0, 5000, 5000));
59    connect(scene, SIGNAL(itemInserted(DiagramItem*)),
60            this, SLOT(itemInserted(DiagramItem*)));
61    connect(scene, SIGNAL(textInserted(QGraphicsTextItem*)),
62        this, SLOT(textInserted(QGraphicsTextItem*)));
63    createToolBox();
64    createToolbars();
65    setDefaultOptions();
66
67    setWindowTitle(tr("SIE Code Generator (Diagram Editor)"));
68    setUnifiedTitleAndToolBarOnMac(true);
69    myFilePath = "";
70    libDialog=0;
71    cgDialog=0;
72    optionsDialog=0;
73    sieSSH=0;
74    compile=0;
75    sshReady=0;
76    dontDelete=0;
77    if(QApplication::argc()>1)
78        {newDiagram(QString(QApplication::argv()[1]));}
79    else
80        newDiagram();
81    statusBar->showMessage("Ready...");
82    this->setStatusBar(statusBar);
83}
84
85void MainWindow::backgroundButtonGroupClicked(QAbstractButton *button)
86{
87    QList<QAbstractButton *> buttons = backgroundButtonGroup->buttons();
88    foreach (QAbstractButton *myButton, buttons) {
89    if (myButton != button)
90        button->setChecked(false);
91    }
92    QString text = button->text();
93    if (text == tr("Blue Grid"))
94        scene->setBackgroundBrush(QPixmap(":/images/background1.png"));
95    else if (text == tr("White Grid"))
96        scene->setBackgroundBrush(QPixmap(":/images/background2.png"));
97    else if (text == tr("Gray Grid"))
98        scene->setBackgroundBrush(QPixmap(":/images/background3.png"));
99    else
100        scene->setBackgroundBrush(QPixmap(":/images/background4.png"));
101
102    scene->update();
103    view->update();
104}
105
106void MainWindow::buttonGroupClicked(int id)
107{
108    QList<QAbstractButton *> buttons = buttonGroup->buttons();
109    foreach (QAbstractButton *button, buttons) {
110    if (buttonGroup->button(id) != button)
111        button->setChecked(false);
112    }
113    if (id == InsertTextButton) {
114        scene->setMode(DiagramScene::InsertText);
115    } else {
116        scene->setItemType(buttonGroup->button(id)->text()); //Block name
117        scene->setMode(DiagramScene::InsertItem);
118    }
119}
120
121void MainWindow::deleteItem()
122{
123  if(!dontDelete)
124  {
125    if(!scene->selectedItems().isEmpty())
126        scene->saveUndoState();
127    //List od items
128    QList<DiagramItem *> Items;
129    QList<Arrow *> Arrows;
130    QList<lineItem *> Lines;
131    QList<DiagramTextItem *> TextItems;
132    foreach(QGraphicsItem *item, scene->selectedItems())
133    {
134        if(item->type() == DiagramItem::Type)
135            Items.append(qgraphicsitem_cast<DiagramItem *>(item));
136        else if(item->type() == Arrow::Type)
137            Arrows.append(qgraphicsitem_cast<Arrow *>(item));
138        else if(item->type() == lineItem::Type)
139            Lines.append(qgraphicsitem_cast<lineItem *>(item));
140        else if(item->type() == DiagramTextItem::Type)
141            if(qgraphicsitem_cast<DiagramTextItem *>(item)->ownerItem() == 0)
142                TextItems.append(qgraphicsitem_cast<DiagramTextItem *>(item));
143    }
144
145    foreach(DiagramItem * item, Items){
146        item->removeArrows();
147        item->removeTextItems();
148        scene->removeDiagramItem(item);
149        scene->removeItem(item);
150        delete(item);
151    }
152
153    foreach(Arrow * item, Arrows){
154        if(scene->items().contains(item))
155        {
156            item->removeLines();
157            item->startItem()->ownerItem()->removeArrow(item);
158            item->endItem()->ownerItem()->removeArrow(item);
159            scene->removeItem(item);
160            delete(item);
161        }
162    }
163
164    foreach(lineItem * item, Lines){
165        if(!item->itemIsMovable() && scene->items().contains(item))
166        {
167            item->myOwner()->removeLine(item);
168            item->myOwner()->updatePosition();
169            scene->removeItem(item);
170            delete(item);
171        }
172    }
173
174    foreach(DiagramTextItem * item, TextItems){
175        scene->removeItem(item);
176        delete(item);
177    }
178
179  }
180}
181
182void MainWindow::pointerGroupClicked(int)
183{
184    scene->setMode(DiagramScene::Mode(pointerTypeGroup->checkedId()));
185}
186
187void MainWindow::cgGroupClicked()
188{
189    QList<DiagramItem *> allItems;
190    QList<DiagramItem *> headItems;
191    QList<DiagramItem *> passItems;
192    QList<Arrow *> passArrows;
193    QString headerCode;
194    QString initCode;
195    QString blockCode;
196    QString extraCode;
197    QString mainCode;
198    QString iosCode;
199    QString warnings;
200    QString mainSCode;
201
202    // Find all Diagram Items and select the "heads" (has no inputs)
203    foreach (QGraphicsItem *item, scene->items()) {
204        if (item->type() == DiagramItem::Type)
205        {
206            allItems.append(qgraphicsitem_cast<DiagramItem *>(item));
207            if(itemIsHead(qgraphicsitem_cast<DiagramItem *>(item)))
208                headItems.append(qgraphicsitem_cast<DiagramItem *>(item));
209        }
210    }
211    // Get code for segments with heads-ends
212    foreach(DiagramItem * item, headItems)
213    {
214        passItem(item,passItems,passArrows, headerCode, initCode, blockCode,
215                 extraCode, mainCode, iosCode, warnings, mainSCode);
216    }
217    // Get code for items in segments with no heads-ends
218    foreach(DiagramItem * item, allItems)
219    {
220        if(!passItems.contains(item))
221            passItem(item,passItems,passArrows,headerCode,initCode,
222                 blockCode,extraCode,mainCode,iosCode,warnings,mainSCode);
223    }
224
225    if(mainSCode.contains("/***![SYSTEM WHILE]***/"))
226        mainSCode = mainSCode.replace("/***![SYSTEM WHILE]***/",mainCode);
227    else if(mainSCode.contains("/***![SYSTEM TIMER]***/"))
228        mainSCode = mainSCode.replace("/***![SYSTEM TIMER]***/",mainCode);
229    else
230        mainSCode = mainCode;
231
232    // create work dir
233    QString tempWorkDir = workDir+"/"+executableFile;
234    if(!QDir(tempWorkDir).exists())
235    {
236        warnings += tr("\nExecuting command: mkdir ") +
237                      tempWorkDir + tr("/") + tr("\n");
238        warnings += callexternapp("mkdir ",workDir + tr("\n"));
239        warnings += callexternapp("mkdir ",tempWorkDir + tr("\n"));
240    }
241    // Copy files from template
242    if(QDir(templateDir).exists())
243    {
244        warnings += tr("\nExecuting command: cp -fR ") +
245                    templateDir+tr("/. ")+
246                    tempWorkDir+tr("/");
247        warnings += callexternapp(tr("cp -fR ") +
248                    templateDir+tr("/. ")+
249                    tempWorkDir+tr("/"),"");
250    }
251    else
252    {
253        warnings += tr("\nWARNING*** Could not found template files");
254    }
255
256    //TODO: Makefile creation!!!
257
258
259    //Open main code template
260    QString protoCode,tempTemplateFile;
261    tempTemplateFile = tempWorkDir+tr("/")+templateFile;
262    if(!QFileInfo(tempTemplateFile).isReadable())
263    {
264        warnings +="\nERROR***: "
265                   "Main code template file is not readable or not exists.";
266        protoCode+="Main code template file is not readable or not exists.";
267    }
268    else
269    {
270        warnings +=tr("\nOpening File: ") + tempTemplateFile;
271        QFile file(tempTemplateFile);
272        if(file.open(QIODevice::ReadOnly | QIODevice::Text))
273        {
274            QByteArray text = file.readAll();
275            protoCode = text.data();
276            file.close();
277        }
278        else
279            warnings += "\nERROR***: "
280                        "Could not open main code template file for read.";
281
282        warnings +=tr("\nReplacing code on main code template");
283        protoCode.replace("/***![HEADER SECTION]***/",headerCode);
284        protoCode.replace("/***![BLOCK SECTION]***/",blockCode);
285        protoCode.replace("/***![INIT SECTION]***/",initCode);
286        protoCode.replace("/***![IO SECTION]***/",iosCode);
287        protoCode.replace("/***![MAIN SECTION]***/",mainSCode);
288        protoCode.replace("/***![EXTRA SECTION]***/",extraCode);
289    }
290
291
292    //Open Makefile template
293    QString protoMake,tempMakeFile;
294    tempMakeFile = tempWorkDir+tr("/")+makeFile;
295    if(!QFileInfo(makeFile).isReadable())
296    {
297        warnings +="\nERROR***: "
298                   "Makefile template file is not readable or not exists.";
299        protoMake+="Makefile template file is not readable or not exists.";
300    }
301    else
302    {
303        warnings +=tr("\nOpening File: ") + tempMakeFile;
304        QFile file(tempMakeFile);
305        if(file.open(QIODevice::ReadOnly | QIODevice::Text))
306        {
307            QByteArray text = file.readAll();
308            protoMake = text.data();
309            file.close();
310        }
311        else
312            warnings +="\nERROR***: "
313                       "Could not open Makefile template file for read.";
314        warnings +=tr("\nReplacing code on Makefile template");
315        protoMake.replace("![MIPS TOOLCHAIN]",mipsToolChainDir);
316        protoMake.replace("![MIPS TOOLCHAIN BASE]",mipsToolChain);
317        protoMake.replace("![SIE APP NAME]",executableFile);
318        protoMake.replace("![MAIN TEMPLATE]",templateFile);
319        protoMake.replace("![MAIN OBJECT]",
320                          QFileInfo(templateFile).baseName()+".o");
321
322    }
323
324    //Open code generator form
325    codeForm();
326
327    // Update form:
328    cgUi->codeTextEdit->setPlainText(protoCode);
329    cgUi->makeTextEdit->setPlainText(protoMake);
330    saveTemplates();
331    cgUi->logTextEdit->append(warnings);
332    cgUi->codesTab->setCurrentIndex(0);
333    cgUi->outputsTab->setCurrentIndex(0);
334}
335
336void MainWindow::saveTemplates()
337{
338    QString tempWorkDir = workDir+"/"+executableFile;
339    //Save files from templates
340    QFile file(tempWorkDir+"/"+templateFile);
341    if(file.open(QIODevice::WriteOnly | QIODevice::Text))
342    {
343        QTextStream out(&file);
344        out.setCodec("UTF-8");
345        out << cgUi->codeTextEdit->toPlainText();
346        file.close();
347    }
348    else
349        cgUi->logTextEdit->append(
350                "ERROR*** Could not open main code file for write.");
351
352    file.setFileName(tempWorkDir+tr("/")+makeFile);
353    if(file.open(QIODevice::WriteOnly | QIODevice::Text))
354    {
355        QTextStream out(&file);
356        out.setCodec("UTF-8");
357        out << cgUi->makeTextEdit->toPlainText();
358        file.close();
359    }
360    else
361        cgUi->logTextEdit->append(
362                "ERROR*** Could not open Makefile for write.");
363}
364
365QString MainWindow::passItem(DiagramItem * item,
366                             QList<DiagramItem *> &passItems,
367                             QList<Arrow *> &passArrows,
368                             QString &headerCode,
369                             QString &initCode,
370                             QString &blockCode,
371                             QString &extraCode,
372                             QString &mainCode,
373                             QString &iosCode,
374                             QString &warnings,
375                             QString &mainSCode)
376{
377if(!passItems.contains(item))
378{
379    QHash<int , DiagramItem *> DiagramsID = scene->getDiagramsID();
380    // Get Dom Element: From item
381    QDomElement * itemDomElement = item->getDomElement();
382    // Get basic information
383    QString blockID = QString::number(DiagramsID.key(item));
384
385    QString blockName = itemDomElement->attribute("BlockName");
386
387    QList<DiagramTextItem *> TextItems =item->getTextItems();
388
389    // Create list de ios and values, and get function prototye
390    QList <QString> ioTypes;
391    QList <QString> ioNames;
392    QList <QString> valueNames;
393    QList <QString> values;
394    QList <DiagramTextItem *> inputs;
395    QList <DiagramTextItem *> outputs;
396
397    QString protoFunction = createPrototype(
398       TextItems,ioTypes,ioNames,valueNames,values,
399       blockName+blockID,inputs,outputs);
400
401    // Read Code:
402    int codeIdx = 0;
403    QString headerCodet;
404    QString initCodet;
405    QString blockCodet;
406    QString extraCodet;
407    for (QDomNode node = itemDomElement->firstChild() ;
408        !node.isNull() ;
409        node = node.nextSibling())
410    {
411     if(node.isCDATASection())
412     {
413         QDomCDATASection Code = node.toCDATASection();
414         switch(codeIdx)
415         {
416           case 0:
417               headerCodet=(Code.data());
418               break;
419           case 1:
420               initCodet=(Code.data());
421               break;
422           case 2:
423               blockCodet=(Code.data());
424               break;
425           case 3:
426               extraCodet=(Code.data());
427               break;
428           default:;
429         }
430         codeIdx++;
431     }
432    }
433    // Replace values:
434    for(int i = 0; i<values.count(); i++)
435    {
436       headerCodet=headerCodet.replace(valueNames[i],values[i]);
437       initCodet=initCodet.replace(valueNames[i],values[i]);
438       blockCodet=blockCodet.replace(valueNames[i],values[i]);
439       extraCodet=extraCodet.replace(valueNames[i],values[i]);
440    }
441
442    if(blockName == "System While" ||
443       blockName == "System Timer")
444    {
445        foreach(QString ioName, ioNames)
446            blockCodet.replace(ioName,ioName+"_"+blockID);
447
448        mainSCode += blockCodet;
449    }
450    else
451    {
452        headerCode+= headerCodet;
453        initCode+= initCodet ;
454        blockCode+= tr("\n")+protoFunction+tr("\n{\n")+blockCodet + tr("\n}\n");
455        extraCode+= extraCodet;
456    }
457
458    iosCode += tr("\t//Inputs/Outputs: Block: <") + blockName +
459               tr("> with ID[") + blockID + tr("] \n");
460    // Generate inputs/outputs and function declaration
461    QString prototype = tr("\t") + QString(blockName + blockID)
462                        .replace(' ','_') + tr(" (");
463    int first = 0;
464    for(int i = 0; i<ioNames.count(); i++)
465    {
466        iosCode += tr("\t") + ioTypes.at(i) +
467                  ioNames.at(i) + tr("_")+blockID + tr("=0;\n");
468        prototype += first? tr(", "):tr(" ");
469        prototype += ioNames.at(i) + tr("_") + blockID;
470        first =1;
471    }
472    prototype += tr(");\n");
473
474    // Connect the inputs to outputs
475    QList<DiagramTextItem *> connectedInputs;
476    QList<DiagramTextItem *> connectedOutputs;
477    foreach(Arrow *arrow, item->getArrows()){
478        if(item == arrow->endOwner())
479        {
480            mainCode += tr("\tin_") +
481                        QString::number(arrow->endItem()->textID()) +
482                        tr("_") +
483                        QString::number(arrow->endOwner()->getID()) +
484                        tr(" = out_") +
485                        QString::number(arrow->startItem()->textID()) +
486                        tr("_") +
487                        QString::number(arrow->startOwner()->getID()) +
488                        tr(";\n");
489            connectedInputs.append(arrow->endItem());
490        }
491    }
492    // Find unconnected inputs
493    foreach(DiagramTextItem * item, inputs){
494        if(!connectedInputs.contains(item))
495            warnings += tr("\nWARNING** Unconnected input[") +
496                        QString::number(item->textID()) +
497                        tr("] in block ") + blockName +
498                        tr(" with ID [") + blockID + tr("]\n");
499    }
500
501    if(blockName != "System While" &&
502       blockName != "System Timer")
503    {
504        mainCode += prototype;
505    }
506
507    passItems.append(item);
508
509    // Apply passItem to items connected to the outputs
510    foreach(Arrow *arrow, item->getArrows()){
511        if(item == arrow->startOwner())
512        {
513            passItem(arrow->endOwner(),passItems,passArrows,
514                     headerCode, initCode, blockCode,
515                     extraCode, mainCode, iosCode,
516                      warnings, mainSCode);
517            connectedOutputs.append(arrow->startItem());
518        }
519    }
520    // Find unconnected outputs
521    foreach(DiagramTextItem * item, outputs){
522        if(!connectedOutputs.contains(item))
523            warnings += tr("\nWARNING** Unconnected output[") +
524                        QString::number(item->textID()) +
525                        tr("] in block ") + blockName +
526                        tr(" with ID [") + blockID + tr("]\n");
527    }
528}
529
530    return 0;
531}
532
533bool MainWindow::itemIsHead(DiagramItem * item)
534{
535    foreach (DiagramTextItem *text, item->getTextItems())
536    {
537        if(text->styleIO()>>7)
538            return 0;
539    }
540    return 1;
541}
542
543bool MainWindow::itemIsEnd(DiagramItem * item)
544{
545    foreach (DiagramTextItem *text, item->getTextItems())
546    {
547        if(!text->styleIO()>>7)
548            return 0;
549    }
550    return 1;
551}
552
553QString MainWindow::getIoType(DiagramTextItem * item)
554{
555    QString ioType;
556    switch(item->styleIO()&127)
557    {
558        case 1:
559            ioType += "bool ";
560            break;
561        case 2:
562            ioType += "char ";
563            break;
564        case 3:
565            ioType += "int ";
566            break;
567        case 4:
568            ioType += "double ";
569            break;
570        case 5:
571            ioType += "float ";
572            break;
573        case 6:
574            ioType += "short int ";
575            break;
576        case 7:
577            ioType += "long int ";
578            break;
579        case 8:
580            ioType += "unsigned char ";
581            break;
582        case 9:
583            ioType += "unsigned int ";
584            break;
585        case 10:
586            ioType += "unsigned short int ";
587            break;
588        case 11:
589            ioType += "unsigned long int ";
590            break;
591        default:
592            ioType += "<unknow type> ";;
593    }
594    return ioType;
595}
596
597QString MainWindow::createPrototype(QList <DiagramTextItem *> &textItems,
598                                    QList <QString> &ioTypes,
599                                    QList <QString> &ioNames,
600                                    QList <QString> &valueNames,
601                                    QList <QString> &values,
602                                    QString blockNameID,
603                                    QList <DiagramTextItem *> &inputs,
604                                    QList <DiagramTextItem *> &outputs)
605{
606    foreach (DiagramTextItem *item, textItems) {
607        int styleIO = item->styleIO();
608        if(styleIO<256 && styleIO>0)
609        {
610          QString ioType, ioName;
611          int ioID = item->textID();
612          ioType = getIoType(item);
613          ioName = ((styleIO>>7)? tr("in"):tr("out")) + "_" +
614                    QString::number(ioID);
615          if(styleIO>>7)
616          {
617                ioName = tr("in") + "_" + QString::number(ioID);
618                inputs.append(item);
619          }
620          else
621          {
622                ioName = tr("out") + "_" + QString::number(ioID);
623                outputs.append(item);
624          }
625          ioTypes.append(ioType);
626          ioNames.append(ioName);
627        }
628        else if(item->isEditable())
629        {
630          QString valueName = tr("value_") + QString::number(item->textID());
631          values.append(item->toPlainText());
632          valueNames.append(valueName);
633        }
634    }
635
636
637    QString prototype = tr("void ") + blockNameID.replace(' ','_') + tr(" (");
638    if(!ioNames.isEmpty())
639    {
640        int first = 0;
641        for(int i = 0; i<ioNames.count(); i++)
642        {
643            prototype += first? tr(", "):tr(" ");
644
645            prototype += ioTypes.at(i);
646            if(ioNames.at(i).contains("out"))
647                 prototype += tr("&") + ioNames.at(i);
648            else
649                 prototype += ioNames.at(i);
650
651            first =1;
652        }
653    }
654    prototype += ")";
655    return prototype;
656}
657
658void MainWindow::bringToFront()
659{
660    sendTo(1);
661}
662
663void MainWindow::sendToBack()
664{
665    sendTo(0);
666}
667
668void MainWindow::sendTo(bool value)
669{
670    if (scene->selectedItems().isEmpty())
671        return;
672
673    QGraphicsItem *selectedItem = scene->selectedItems().first();
674    QList<QGraphicsItem *> overlapItems = selectedItem->collidingItems();
675
676    qreal zValue = 0;
677    foreach (QGraphicsItem *item, overlapItems) {
678        if (item->zValue() <= zValue &&
679            item->type() == DiagramItem::Type)
680        {
681            if(value)
682                zValue = item->zValue() + 0.1;
683            else
684                zValue = item->zValue() - 0.1;
685        }
686    }
687    selectedItem->setZValue(zValue);
688    if(selectedItem->type() == DiagramItem::Type)
689        foreach (DiagramTextItem *texts,
690                qgraphicsitem_cast<DiagramItem *>(selectedItem)->getTextItems())
691        {
692            texts->updatePosition();
693        }
694
695}
696
697void MainWindow::itemInserted(DiagramItem *item)
698{
699    pointerTypeGroup->button(int(DiagramScene::MoveItem))->setChecked(true);
700    scene->setMode(DiagramScene::Mode(pointerTypeGroup->checkedId()));
701    buttonGroup->button(buttonIdByName.value(item->diagramType()))->setChecked(false);
702}
703
704void MainWindow::textInserted(QGraphicsTextItem *)
705{
706    buttonGroup->button(InsertTextButton)->setChecked(false);
707    scene->setMode(DiagramScene::Mode(pointerTypeGroup->checkedId()));
708}
709
710void MainWindow::currentFontChanged(const QFont &)
711{
712    handleFontChange();
713}
714
715void MainWindow::fontSizeChanged(const QString &)
716{
717    handleFontChange();
718}
719
720void MainWindow::sceneScaleChanged(const QString &scale)
721{
722    double newScale = scale.left(scale.indexOf(tr("%"))).toDouble() / 100.0;
723    QMatrix oldMatrix = view->matrix();
724    view->resetMatrix();
725    view->translate(oldMatrix.dx(), oldMatrix.dy());
726    view->scale(newScale, newScale);
727}
728
729void MainWindow::textColorChanged()
730{
731    textAction = qobject_cast<QAction *>(sender());
732    fontColorToolButton->setIcon(createColorToolButtonIcon(
733                ":/images/textpointer.png",
734                qVariantValue<QColor>(textAction->data())));
735    textButtonTriggered();
736}
737
738void MainWindow::itemColorChanged()
739{
740    fillAction = qobject_cast<QAction *>(sender());
741    fillColorToolButton->setIcon(createColorToolButtonIcon(
742                 ":/images/floodfill.png",
743                 qVariantValue<QColor>(fillAction->data())));
744    fillButtonTriggered();
745}
746
747void MainWindow::lineColorChanged()
748{
749    lineAction = qobject_cast<QAction *>(sender());
750    lineColorToolButton->setIcon(createColorToolButtonIcon(
751                 ":/images/linecolor.png",
752                 qVariantValue<QColor>(lineAction->data())));
753    lineButtonTriggered();
754}
755
756void MainWindow::textButtonTriggered()
757{
758    scene->setTextColor(qVariantValue<QColor>(textAction->data()));
759}
760
761void MainWindow::fillButtonTriggered()
762{
763    scene->setItemColor(qVariantValue<QColor>(fillAction->data()));
764}
765
766void MainWindow::lineButtonTriggered()
767{
768    scene->setLineColor(qVariantValue<QColor>(lineAction->data()));
769}
770
771void MainWindow::handleFontChange()
772{
773    QFont font = fontCombo->currentFont();
774    font.setPointSize(fontSizeCombo->currentText().toInt());
775    font.setBold(boldAction->isChecked());
776    font.setItalic(italicAction->isChecked());
777    font.setUnderline(underlineAction->isChecked());
778
779    scene->setFont(font);
780}
781
782void MainWindow::setFontSettings(QFont font)
783{
784    fontSizeCombo->setEditText(QString::number(font.pointSize()));
785    font.bold()? boldAction->setChecked(true): boldAction->setChecked(false);
786    font.italic()? italicAction->setChecked(true):
787                    italicAction->setChecked(false);
788    font.underline()? underlineAction->setChecked(true):
789                        underlineAction->setChecked(false);
790    fontCombo->setEditText(font.family());
791}
792
793void MainWindow::about()
794{
795    QMessageBox::question(this, tr("About SIE Code Generator"),
796                       tr("TODO <b>:)</b>"));
797}
798
799void MainWindow::cleanDomElementsByName()
800{
801    if(domElementsByName!=0)
802    {
803        foreach(QDomElement * domElement,domElementsByName->values())
804            {delete(domElement);}
805        delete(domElementsByName);
806    }
807}
808
809void MainWindow::addLibrariesButtons(QGridLayout *layout)
810{
811    int i = 1;
812    cleanDomElementsByName();
813    domElementsByName = new QHash<QString , QDomElement*>;
814    buttonIdByName.clear();
815    QDomDocument customItems;
816    foreach(QString filepath, libraryList)
817    {
818        customItems = parseDocument(filepath);
819        for (QDomNode node = customItems.firstChild() ;
820             !node.isNull() ;
821             node = node.nextSibling())
822        {
823            QDomElement *customItem = new QDomElement(node.toElement());
824            if(customItem->tagName()=="CustomItem")
825            {
826                if(domElementsByName->contains(
827                        customItem->attribute("BlockName")))
828                {
829                    QMessageBox::warning(this,"Block name in use.",
830                                         "The library " + filepath +
831                                         " has one block called" +
832                                         customItem->attribute("BlockName") +
833                                         " that is already in use. Only the "
834                                         " first Block loaded can be used, this"
835                                         " library will be ignored.");
836                }
837                else
838                {
839                    domElementsByName->insert(customItem->attribute("BlockName"),
840                                             customItem);
841                    buttonIdByName.insert(customItem->attribute("BlockName"),i-1);
842                    scene->setDomElementsByName(domElementsByName);
843                    scene->setButtonIdByName(buttonIdByName);
844
845                    layout->addWidget(createCellWidget(
846                            customItem->attribute("BlockName"),
847                            domElementsByName->
848                            value(customItem->attribute("BlockName"))),i/2,i&1);
849                    i++;
850                }
851            }
852        }
853    }
854}
855
856
857
858void MainWindow::createToolBox()
859{
860    if(buttonGroup!=0) delete(buttonGroup);
861    if(toolBox!=0) delete(toolBox);
862    buttonGroup = new QButtonGroup;
863    buttonGroup->setExclusive(false);
864    connect(buttonGroup, SIGNAL(buttonClicked(int)),
865            this, SLOT(buttonGroupClicked(int)));
866
867    QGridLayout *layout = new QGridLayout;
868
869    addLibrariesButtons(layout);
870
871    QToolButton *textButton = new QToolButton;
872    textButton->setCheckable(true);
873    buttonGroup->addButton(textButton, InsertTextButton);
874    textButton->setIcon(QIcon(QPixmap(":/images/textpointer.png")
875                        .scaled(30, 30)));
876    textButton->setIconSize(QSize(50, 50));
877    QGridLayout *textLayout = new QGridLayout;
878    textLayout->addWidget(textButton, 0, 0, Qt::AlignHCenter);
879    textLayout->addWidget(new QLabel(tr("Text")), 1, 0, Qt::AlignCenter);
880    QWidget *textWidget = new QWidget;
881    textWidget->setLayout(textLayout);
882    layout->addWidget(textWidget, 0, 0);
883
884    layout->setRowStretch(3, 10);
885    layout->setColumnStretch(2, 10);
886
887    QWidget *itemWidget = new QWidget;
888    itemWidget->setLayout(layout);
889
890    toolBox = new QToolBox;
891    toolBox->setSizePolicy(QSizePolicy(QSizePolicy::Maximum, QSizePolicy::Ignored));
892    toolBox->setMinimumWidth(itemWidget->sizeHint().width());
893    toolBox->addItem(itemWidget, tr("Basic blocks"));
894    //toolBox->addItem(backgroundWidget, tr("Backgrounds"));
895
896    //Add tool box to window
897    QGridLayout *newLayout = new QGridLayout;
898    newLayout->addWidget(toolBox,0,0);
899    view = new QGraphicsView(scene);
900    newLayout->addWidget(view,0,1);
901
902    QWidget *widget = new QWidget;
903    widget->setLayout(newLayout);
904
905    setCentralWidget(widget);
906}
907
908void MainWindow::createActions()
909{
910    toFrontAction = new QAction(QIcon(":/images/bringtofront.png"),
911                                tr("Bring to &Front"), this);
912    toFrontAction->setShortcut(tr("Ctrl+F"));
913    toFrontAction->setStatusTip(tr("Bring item to front"));
914    connect(toFrontAction, SIGNAL(triggered()),
915            this, SLOT(bringToFront()));
916
917    sendBackAction = new QAction(QIcon(":/images/sendtoback.png"),
918                                 tr("Send to &Back"), this);
919    sendBackAction->setShortcut(tr("Ctrl+B"));
920    sendBackAction->setStatusTip(tr("Send item to back"));
921    connect(sendBackAction, SIGNAL(triggered()),
922        this, SLOT(sendToBack()));
923
924    deleteAction = new QAction(QIcon(":/images/delete.png"),
925                               tr("&Delete"), this);
926    deleteAction->setShortcut(tr("Ctrl+Delete"));
927    deleteAction->setStatusTip(tr("Delete item from diagram"));
928    connect(deleteAction, SIGNAL(triggered()),
929        this, SLOT(deleteItem()));
930
931
932    newAction = new QAction(QIcon(":/images/new.png"),tr("&New"),this);
933    newAction->setShortcuts(QKeySequence::New);
934    newAction->setStatusTip("New diagram");
935    connect(newAction,SIGNAL(triggered()),this,SLOT(newDiagram()));
936
937    saveAction = new QAction(QIcon(":/images/save.png"),tr("&Save"),this);
938    saveAction->setShortcuts(QKeySequence::Save);
939    saveAction->setStatusTip("Save current diagram");
940    connect(saveAction,SIGNAL(triggered()),this,SLOT(saveDiagram()));
941
942    saveAsAction = new QAction(QIcon(":/images/save_as.png"),
943                               tr("Save &As..."),this);
944    saveAsAction->setShortcuts(QKeySequence::SaveAs);
945    saveAsAction->setStatusTip("Save current diagram with another name");
946    connect(saveAsAction,SIGNAL(triggered()),this,SLOT(saveAsDiagram()));
947
948    openAction = new QAction(QIcon(":/images/open.png"),tr("&Open"),this);
949    openAction->setShortcuts(QKeySequence::Open);
950    openAction->setStatusTip("Open diagram");
951    connect(openAction,SIGNAL(triggered()),this,SLOT(openDiagram()));
952
953    exportImgAction = new QAction(tr("&Export to ..."),this);
954    exportImgAction->setStatusTip("Export current diagram to picture");
955    connect(exportImgAction,SIGNAL(triggered()),this,SLOT(exportDiagram()));
956
957
958    redoAction = new QAction(QIcon(":/images/redo.png"),tr("&Redo"),this);
959    redoAction->setShortcuts(QKeySequence::Redo);
960    redoAction->setStatusTip("Redo changes on diagram");
961    connect(redoAction,SIGNAL(triggered()),this,SLOT(redoDiagram()));
962
963    undoAction = new QAction(QIcon(":/images/undo.png"),tr("&Undo"),this);
964    undoAction->setShortcuts(QKeySequence::Undo);
965    undoAction->setStatusTip("Undo changes on diagram");
966    connect(undoAction,SIGNAL(triggered()),this,SLOT(undoDiagram()));
967
968
969    exitAction = new QAction(tr("E&xit"), this);
970    exitAction->setShortcuts(QKeySequence::Quit);
971    exitAction->setStatusTip(tr("Quit diagram editor"));
972    connect(exitAction, SIGNAL(triggered()), this, SLOT(close()));
973
974    boldAction = new QAction(QIcon(":/images/bold.png"),tr("Bold"), this);
975    boldAction->setCheckable(true);
976    boldAction->setShortcut(tr("Ctrl+B"));
977    connect(boldAction, SIGNAL(triggered()),
978            this, SLOT(handleFontChange()));
979
980    italicAction = new QAction(QIcon(":/images/italic.png"),
981                               tr("Italic"), this);
982    italicAction->setCheckable(true);
983    italicAction->setShortcut(tr("Ctrl+I"));
984    connect(italicAction, SIGNAL(triggered(bool)),
985            this, SLOT(handleFontChange()));
986
987    underlineAction = new QAction(QIcon(":/images/underline.png"),
988                                  tr("Underline"), this);
989    underlineAction->setCheckable(true);
990    underlineAction->setShortcut(tr("Ctrl+U"));
991    connect(underlineAction, SIGNAL(triggered(bool)),
992            this, SLOT(handleFontChange()));
993
994
995
996    libraryAction = new QAction(tr("&Library..."),this);
997    libraryAction->setStatusTip(tr("Add, Remove or edit libraries"));
998    connect(libraryAction, SIGNAL(triggered()),
999            this, SLOT(libraryForm()));
1000
1001    optionsAction = new QAction(tr("&Options"),this);
1002    optionsAction->setShortcuts(QKeySequence::Preferences);
1003    optionsAction->setStatusTip(tr("Edit options"));
1004    connect(optionsAction, SIGNAL(triggered()),
1005            this, SLOT(optionsForm()));
1006
1007    aboutAction = new QAction(tr("A&bout"), this);
1008    connect(aboutAction, SIGNAL(triggered()),
1009            this, SLOT(about()));
1010}
1011
1012void MainWindow::createMenus()
1013{
1014    fileMenu = menuBar()->addMenu(tr("&File"));
1015    fileMenu->addAction(newAction);
1016    fileMenu->addAction(openAction);
1017    fileMenu->addSeparator();
1018    fileMenu->addAction(saveAction);
1019    fileMenu->addAction(saveAsAction);
1020    fileMenu->addAction(exportImgAction);
1021    fileMenu->addSeparator();
1022    fileMenu->addAction(exitAction);
1023
1024    itemMenu = menuBar()->addMenu(tr("&Item"));
1025    itemMenu->addAction(deleteAction);
1026    itemMenu->addSeparator();
1027    itemMenu->addAction(toFrontAction);
1028    itemMenu->addAction(sendBackAction);
1029
1030    preferencesMenu= menuBar()->addMenu(tr("&Preferences"));
1031    preferencesMenu->addAction(libraryAction);
1032    preferencesMenu->addAction(optionsAction);
1033
1034    aboutMenu = menuBar()->addMenu(tr("&Help"));
1035    aboutMenu->addAction(aboutAction);
1036}
1037
1038void MainWindow::createToolbars()
1039{
1040    fileToolBar = addToolBar(tr("File"));
1041    fileToolBar->addAction(newAction);
1042    fileToolBar->addAction(openAction);
1043    fileToolBar->addAction(saveAction);
1044
1045    QToolButton *cgButton = new QToolButton;
1046    cgButton->setCheckable(false);
1047    cgButton->setIcon(QIcon(":/images/cg.png"));
1048    cgButton->setToolTip("Generate code for SIE");
1049
1050    cgGroup = new QButtonGroup;
1051    cgGroup->addButton(cgButton,0);
1052
1053    connect(cgGroup, SIGNAL(buttonClicked(int)),
1054            this, SLOT(cgGroupClicked()));
1055
1056    cgToolbar = addToolBar(tr("Code Generator"));
1057    cgToolbar->addWidget(cgButton);
1058
1059    editToolBar = addToolBar(tr("Edit"));
1060    editToolBar->addAction(deleteAction);
1061    editToolBar->addAction(toFrontAction);
1062    editToolBar->addAction(sendBackAction);
1063    editToolBar->addAction(undoAction);
1064    editToolBar->addAction(redoAction);
1065
1066    fontCombo = new QFontComboBox();
1067    fontSizeCombo = new QComboBox();
1068    connect(fontCombo, SIGNAL(currentFontChanged(QFont)),
1069            this, SLOT(currentFontChanged(QFont)));
1070
1071    fontSizeCombo = new QComboBox;
1072    fontSizeCombo->setEditable(true);
1073    for (int i = 8; i < 30; i = i + 2)
1074        fontSizeCombo->addItem(QString().setNum(i));
1075    QIntValidator *validator = new QIntValidator(2, 64, this);
1076    fontSizeCombo->setValidator(validator);
1077    connect(fontSizeCombo, SIGNAL(currentIndexChanged(QString)),
1078            this, SLOT(fontSizeChanged(QString)));
1079
1080    fontColorToolButton = new QToolButton;
1081    fontColorToolButton->setPopupMode(QToolButton::MenuButtonPopup);
1082    fontColorToolButton->setMenu(createColorMenu(SLOT(textColorChanged()),
1083                                                 Qt::black));
1084    textAction = fontColorToolButton->menu()->defaultAction();
1085    fontColorToolButton->setIcon(createColorToolButtonIcon(
1086    ":/images/textpointer.png", Qt::black));
1087    fontColorToolButton->setAutoFillBackground(true);
1088    connect(fontColorToolButton, SIGNAL(clicked()),
1089            this, SLOT(textButtonTriggered()));
1090
1091    fillColorToolButton = new QToolButton;
1092    fillColorToolButton->setPopupMode(QToolButton::MenuButtonPopup);
1093    fillColorToolButton->setMenu(createColorMenu(SLOT(itemColorChanged()),
1094                         Qt::white));
1095    fillAction = fillColorToolButton->menu()->defaultAction();
1096    fillColorToolButton->setIcon(createColorToolButtonIcon(
1097    ":/images/floodfill.png", Qt::white));
1098    connect(fillColorToolButton, SIGNAL(clicked()),
1099            this, SLOT(fillButtonTriggered()));
1100
1101    lineColorToolButton = new QToolButton;
1102    lineColorToolButton->setPopupMode(QToolButton::MenuButtonPopup);
1103    lineColorToolButton->setMenu(createColorMenu(SLOT(lineColorChanged()),
1104                                 Qt::black));
1105    lineAction = lineColorToolButton->menu()->defaultAction();
1106    lineColorToolButton->setIcon(createColorToolButtonIcon(
1107        ":/images/linecolor.png", Qt::black));
1108    connect(lineColorToolButton, SIGNAL(clicked()),
1109            this, SLOT(lineButtonTriggered()));
1110
1111    QToolButton *pointerButton = new QToolButton;
1112    pointerButton->setCheckable(true);
1113    pointerButton->setChecked(true);
1114    pointerButton->setIcon(QIcon(":/images/pointer.png"));
1115    QToolButton *linePointerButton = new QToolButton;
1116    linePointerButton->setCheckable(true);
1117    linePointerButton->setIcon(QIcon(":/images/linepointer.png"));
1118
1119    pointerTypeGroup = new QButtonGroup;
1120    pointerTypeGroup->addButton(pointerButton, int(DiagramScene::MoveItem));
1121    pointerTypeGroup->addButton(linePointerButton,
1122                                int(DiagramScene::InsertLine));
1123    connect(pointerTypeGroup, SIGNAL(buttonClicked(int)),
1124            this, SLOT(pointerGroupClicked(int)));
1125
1126    sceneScaleCombo = new QComboBox;
1127    QStringList scales;
1128    scales << tr("50%") << tr("75%") << tr("100%") << tr("125%") << tr("150%");
1129    sceneScaleCombo->addItems(scales);
1130    sceneScaleCombo->setCurrentIndex(2);
1131    connect(sceneScaleCombo, SIGNAL(currentIndexChanged(QString)),
1132            this, SLOT(sceneScaleChanged(QString)));
1133
1134
1135    pointerToolbar = addToolBar(tr("Pointer type"));
1136    pointerToolbar->addWidget(pointerButton);
1137    pointerToolbar->addWidget(linePointerButton);
1138    pointerToolbar->addWidget(sceneScaleCombo);
1139
1140    gridButton = new QToolButton;
1141    gridButton->setCheckable(true);
1142    gridButton->setChecked(false);
1143    gridButton->setIcon(QIcon(":/images/grid.png"));
1144
1145    connect(gridButton,SIGNAL(clicked()),this,SLOT(setGridState()));
1146
1147    colorToolBar = addToolBar(tr("Color"));
1148    colorToolBar->addWidget(fontColorToolButton);
1149    colorToolBar->addWidget(fillColorToolButton);
1150    colorToolBar->addWidget(lineColorToolButton);
1151    colorToolBar->addWidget(gridButton);
1152
1153    textToolBar = addToolBar(tr("Font"));
1154    textToolBar->addWidget(fontCombo);
1155    textToolBar->addWidget(fontSizeCombo);
1156    textToolBar->addAction(boldAction);
1157    textToolBar->addAction(italicAction);
1158    textToolBar->addAction(underlineAction);
1159
1160}
1161
1162void MainWindow::setGridState()
1163{
1164    scene->setDawGrid(gridButton->isChecked());
1165    scene->update();
1166}
1167
1168QWidget *MainWindow::createCellWidget(QString text, QDomElement *customItem)
1169{
1170    DiagramItem item(itemMenu,text,customItem);
1171    QIcon icon(item.image());
1172
1173    QToolButton *button = new QToolButton;
1174    button->setText(text);
1175    button->setIcon(icon);
1176    button->setIconSize(QSize(50, 50));
1177    button->setCheckable(true);
1178    buttonGroup->addButton(button, buttonIdByName.value(text));
1179
1180    QGridLayout *layout = new QGridLayout;
1181    layout->addWidget(button, 0, 0, Qt::AlignHCenter);
1182    layout->addWidget(new QLabel(text), 1, 0, Qt::AlignCenter);
1183
1184    QWidget *widget = new QWidget;
1185    widget->setLayout(layout);
1186
1187    return widget;
1188}
1189
1190QMenu *MainWindow::createColorMenu(const char *slot, QColor defaultColor)
1191{
1192    QList<QColor> colors;
1193    colors << Qt::black << Qt::white << Qt::magenta << Qt::gray
1194            << Qt::cyan << Qt::red << Qt::blue << Qt::yellow << Qt::green
1195            << Qt::darkMagenta << Qt::darkCyan << Qt::darkRed << Qt::darkBlue
1196            << Qt::darkYellow << Qt::darkGreen << Qt::darkGray;
1197
1198    QStringList names;
1199    names << tr("Black") << tr("White") << tr("Magenta") << tr("Gray")
1200          << tr("Cyan") << tr("Red") << tr("Blue") << tr("Yellow")
1201          << tr("Green") << tr("Dark Magenta") << tr("Dark Cyan")
1202          << tr("Dark Red") << tr("Dark Blue") << tr("Dark Yellow")
1203          << tr("Dark Green") << tr("Dark Gray") ;
1204
1205    QMenu *colorMenu = new QMenu;
1206    for (int i = 0; i < colors.count(); ++i) {
1207        QAction *action = new QAction(names.at(i), this);
1208        action->setData(colors.at(i));
1209        action->setIcon(createColorIcon(colors.at(i)));
1210        connect(action, SIGNAL(triggered()),
1211                this, slot);
1212        colorMenu->addAction(action);
1213        if (colors.at(i) == defaultColor) {
1214            colorMenu->setDefaultAction(action);
1215        }
1216    }
1217    return colorMenu;
1218}
1219
1220QIcon MainWindow::createColorToolButtonIcon(const QString &imageFile,
1221                        QColor color)
1222{
1223    QPixmap pixmap(50, 80);
1224    pixmap.fill(Qt::transparent);
1225    QPainter painter(&pixmap);
1226    QPixmap image(imageFile);
1227    QRect target(0, 0, 50, 60);
1228    QRect source(0, 0, 42, 42);
1229    painter.fillRect(QRect(0, 60, 50, 80), color);
1230    painter.drawPixmap(target, image, source);
1231
1232    return QIcon(pixmap);
1233}
1234
1235QIcon MainWindow::createColorIcon(QColor color)
1236{
1237    QPixmap pixmap(20, 20);
1238    QPainter painter(&pixmap);
1239    painter.setPen(Qt::NoPen);
1240    painter.fillRect(QRect(0, 0, 20, 20), color);
1241
1242    return QIcon(pixmap);
1243}
1244
1245int MainWindow::newDiagram(QString filePath)
1246{
1247    saveIfNeeded();
1248    undoList.clear();
1249    redoList.clear();
1250    scene->cleanScene();
1251    libraryList.clear(); //or set defaults
1252    buttonIdByName.clear();//or set defaults
1253    scene->setLibList(libraryList);
1254    updateLibraries();
1255    myFilePath="";
1256    setDefaultOptions();
1257
1258    if(filePath=="")
1259        return 0;
1260
1261    myFilePath=filePath;
1262    if(!scene->fromXmlFormat(parseDocument(myFilePath)))
1263        newDiagram();
1264
1265    return 1;
1266}
1267
1268QDomDocument MainWindow::parseDocument(QString filePath)
1269{
1270    QDomDocument document;
1271    QFile file(filePath);
1272    if(file.open(QIODevice::ReadOnly | QIODevice::Text))
1273    {
1274        bool parsing=document.setContent(&file);
1275        file.close();
1276        if(!parsing)
1277        {
1278            QMessageBox::warning(this,"Parsing warning","Invalid or void "
1279                                 " element found in file.");
1280        }
1281    }
1282    else
1283        QMessageBox::critical(this,"Error","Could not open file for read.");
1284
1285    return document;
1286}
1287
1288
1289
1290int MainWindow::saveIfNeeded()
1291{
1292    if(myFilePath!="" || scene->items().count()>0)
1293    {}//TODO save opened or modified diagram
1294    return 0;
1295}
1296
1297int MainWindow::openDiagram()
1298{
1299    QString
1300    filePath = QFileDialog::getOpenFileName(this,"Open",
1301               currentDir(),"Diagram for SIE code generator (*.sie)");
1302
1303    if(filePath.isEmpty())
1304        return 0;
1305
1306    if(!QFileInfo(filePath).isReadable())
1307    {
1308        QMessageBox::critical(this,"Error","File is not readable "
1309                                           " or not exists.");
1310        return 0;
1311    }
1312
1313    newDiagram(filePath);
1314    return 0;
1315}
1316
1317int MainWindow::saveDiagram()
1318{
1319    if(myFilePath=="")
1320    {
1321        saveAsDiagram();
1322        return 0;
1323    }
1324    if(!QFileInfo(myFilePath).isWritable() && QFileInfo(myFilePath).exists())
1325    {
1326        QMessageBox::critical(this,"Error","File is not writable.");
1327        return 0;
1328    }
1329    QFile file(myFilePath);
1330    if(file.open(QIODevice::WriteOnly | QIODevice::Text))
1331    {
1332        scene->setLibList(libraryList);
1333        QDomDocument document = scene->toXmlFormat();
1334        QTextStream out(&file);
1335        out.setCodec("UTF-8");
1336        out << document.toString(4);
1337        file.close();
1338        return 1;
1339    }
1340    else
1341        QMessageBox::critical(this,"Error","Could not open file for write.");
1342    return 0;
1343}
1344
1345int MainWindow::saveAsDiagram()
1346{
1347    QString filePath = QFileDialog::getSaveFileName(this,"Save as...",
1348                 currentDir(),"Diagram for SIE code generator (*.sie)");
1349
1350    if(!filePath.isEmpty())
1351    {
1352        myFilePath = filePath;
1353        saveDiagram();
1354        return 1;
1355    }
1356    return 0;
1357}
1358
1359int MainWindow::exportDiagram()
1360{
1361    QString picturePath = QFileDialog::getSaveFileName(this,"Export",
1362                            currentDir(),"Portable Network Graphics (*.png)");
1363
1364    if(picturePath.isEmpty()) return 0;
1365
1366    if(!QFileInfo(picturePath).isWritable() && QFileInfo(picturePath).exists())
1367    {
1368        QMessageBox::critical(this,"Error","File is not writable.");
1369        return 0;
1370    }
1371    scene->setDawGrid(0);
1372    QSize sizeScene= scene->sceneRect().size().toSize();
1373    QImage img(sizeScene,QImage::Format_ARGB32_Premultiplied);
1374    QPainter p(&img);
1375    scene->render(&p,
1376                  scene->sceneRect(),
1377                  scene->itemsBoundingRect(),
1378                  Qt::KeepAspectRatio);
1379    p.end();
1380    img.save(picturePath, "png");
1381    scene->setDawGrid(gridButton->isChecked()); //TODO : set correct value
1382    return 1;
1383}
1384
1385int MainWindow::libraryForm()
1386{
1387    if(!libDialog)
1388        createLibraryDialog();
1389    libDialog->setModal(1);
1390    libUi->listLib->clear();
1391    libUi->listLib->addItems(libraryList);
1392    libDialog->setWindowTitle(tr("Library paths..."));
1393    QStringList oldLibraryList=libraryList;
1394    libDialog->exec();
1395
1396    if (libDialog->result() == QDialog::Rejected)
1397        libraryList = oldLibraryList;
1398    else
1399    {
1400        scene->setLibList(libraryList);
1401        QDomDocument backUp = scene->toXmlFormat();
1402        updateLibraries();
1403        scene->cleanScene();
1404        scene->fromXmlFormat(backUp);
1405    }
1406    libDialog->close();
1407    return 0;
1408}
1409
1410void MainWindow::createLibraryDialog()
1411{
1412    libDialog = new QDialog(this);
1413    libUi = new Ui_libraryDialog;
1414    libUi->setupUi(libDialog);
1415
1416    connect(libUi->addLib,SIGNAL(clicked()),this,SLOT(addLibPath()));
1417    connect(libUi->delLib,SIGNAL(clicked()),this,SLOT(delLibPath()));
1418    connect(libUi->editLib,SIGNAL(clicked()),this,SLOT(editLibPath()));
1419    connect(libUi->upLib,SIGNAL(clicked()),this,SLOT(upLibPath()));
1420    connect(libUi->downLib,SIGNAL(clicked()),this,SLOT(downLibPath()));
1421}
1422
1423int MainWindow::codeForm()
1424{
1425    if(!cgDialog)
1426    {
1427        createCgDialog();
1428    }
1429    cgDialog->show(); cgDialog->show(); //Dummy
1430    return 0;
1431}
1432
1433void MainWindow::createCgDialog()
1434{
1435    cgDialog = new QMainWindow(this);
1436    cgUi = new Ui_codeDialog;
1437    cgUi->setupUi(cgDialog);
1438    connect(cgUi->updateButton,SIGNAL(clicked()),this,SLOT(cgGroupClicked()));
1439    connect(cgUi->compileButton,SIGNAL(clicked()),this,SLOT(executeCompile()));
1440    connect(cgUi->connectButton,SIGNAL(clicked()),this,SLOT(executeSSH()));
1441    connect(cgUi->sendButton,SIGNAL(clicked()),this,SLOT(sendCommand()));
1442    connect(cgUi->commandEdit,SIGNAL(returnPressed()),this,SLOT(sendCommand()));
1443    connect(cgUi->fpgaButton,SIGNAL(clicked()),this,SLOT(configFPGA()));
1444    connect(cgUi->exeButton,SIGNAL(clicked()),this,SLOT(exeOnSie()));
1445    connect(cgUi->saveButton,SIGNAL(clicked()),this,SLOT(saveTemplates()));
1446    connect(cgUi->killButton,SIGNAL(clicked()),this,SLOT(killProcess()));
1447    connect(cgUi->lcdOnButton,SIGNAL(clicked()),this,SLOT(lcdOn()));
1448    connect(cgUi->lcdOffButton,SIGNAL(clicked()),this,SLOT(lcdOff()));
1449
1450    cgDialog->setWindowTitle(tr("Code Generator..."));
1451    cgUi->codeTextEdit->setAcceptRichText(true);
1452    cgUi->logTextEdit->setAcceptRichText(true);
1453    cgUi->compileTextEdit->setAcceptRichText(true);
1454    cgUi->sshTextEdit->setAcceptRichText(true);
1455    cgUi->logTextEdit->setReadOnly(true);
1456    cgUi->compileTextEdit->setReadOnly(true);
1457    cgUi->sshTextEdit->setReadOnly(true);
1458}
1459
1460void MainWindow::addLibPath()
1461{
1462    QString
1463    filePath = QFileDialog::getOpenFileName(this,"Open",
1464               currentDir(),"Custom block for SIE code generator (*.die)");
1465
1466    if(filePath.isEmpty())
1467        return;
1468
1469    if(!QFileInfo(filePath).isReadable())
1470    {
1471        QMessageBox::critical(this,"Error","File is not readable "
1472                                           " or not exists.");
1473        return;
1474    }
1475    QDir myCurrentDir = this->currentDir();
1476    QString relativePath= myCurrentDir.relativeFilePath(filePath);
1477    if(libUi->listLib->findItems(relativePath,Qt::MatchExactly).count()==0)
1478    {
1479        libraryList.append(relativePath);
1480        libUi->listLib->addItem(relativePath);
1481    }
1482    else
1483        QMessageBox::information(this,"Information","Library already exist.");
1484}
1485
1486void MainWindow::delLibPath()
1487{
1488    QList<QListWidgetItem *> selected = libUi->listLib->selectedItems();
1489    if(selected.count()>0)
1490    {
1491        libraryList.removeOne(selected.at(0)->text());
1492        libUi->listLib->clear();
1493        libUi->listLib->addItems(libraryList);
1494    }
1495}
1496
1497void MainWindow::editLibPath()
1498{
1499    QList<QListWidgetItem *> selected = libUi->listLib->selectedItems();
1500    if(selected.count()>0)
1501    {
1502        QEventLoop waitToFinish;
1503        callApp *openBlockEditor = new callApp(
1504                tr("block_editor/blockeditor ") + selected.at(0)->text());
1505        connect(openBlockEditor, SIGNAL(appClosed()),
1506                &waitToFinish, SLOT(quit()));
1507        libDialog->setEnabled(false);
1508        waitToFinish.exec();
1509        libDialog->setEnabled(true);
1510        openBlockEditor->deleteProcess();
1511        openBlockEditor->deleteLater();
1512    }
1513}
1514
1515void MainWindow::upLibPath()
1516{
1517    QList<QListWidgetItem *> selected = libUi->listLib->selectedItems();
1518    if(selected.count()>0)
1519    {
1520        int idx = libraryList.indexOf(selected.first()->text());
1521        if(idx>0)
1522        {
1523            libraryList.move(idx,idx-1);
1524            libUi->listLib->clear();
1525            libUi->listLib->addItems(libraryList);
1526            libUi->listLib->setCurrentRow(idx-1);
1527        }
1528    }
1529}
1530
1531void MainWindow::downLibPath()
1532{
1533    QList<QListWidgetItem *> selected = libUi->listLib->selectedItems();
1534    if(selected.count()>0)
1535    {
1536        int idx = libraryList.indexOf(selected.first()->text());
1537        if(idx<libraryList.count())
1538        {
1539            libraryList.move(idx,idx+1);
1540            libUi->listLib->clear();
1541            libUi->listLib->addItems(libraryList);
1542            libUi->listLib->setCurrentRow(idx+1);
1543        }
1544    }
1545}
1546
1547
1548int MainWindow::updateLibraries()
1549{
1550    // TODO: the update lib generate segmentartion fault on CG process
1551    // update the DomElement of each block is needed.
1552    libraryList=scene->getLibList();
1553    createToolBox();
1554    return 0;
1555}
1556
1557
1558int MainWindow::optionsForm()
1559{
1560    if(!optionsDialog)
1561        createOptionsDialog();
1562    optionsDialog->setModal(1);
1563    optUi->templateDir->setText(templateDir);
1564    optUi->templateFile->setText(templateFile);
1565    optUi->makeFile->setText(makeFile);
1566    optUi->workDir->setText(workDir);
1567    optUi->executableFile->setText(executableFile);
1568    optUi->mipsToolChainDir->setText(mipsToolChainDir);
1569    optUi->mipsToolChain->setText(mipsToolChain);
1570    optUi->sieWorkDir->setText(sieWorkDir);
1571    optUi->fpgaFile->setText(fpgaFile);
1572    optUi->sieIP->setText(sieIP);
1573    optUi->configApp->setText(configApp);
1574    optionsDialog->exec();
1575    if(optionsDialog->result() == QDialog::Accepted)
1576    {
1577        templateDir = optUi->templateDir->text();
1578        templateFile = optUi->templateFile->text();
1579        makeFile = optUi->makeFile->text();
1580        workDir = optUi->workDir->text();
1581        executableFile = optUi->executableFile->text();
1582        mipsToolChainDir = optUi->mipsToolChainDir->text();
1583        mipsToolChain = optUi->mipsToolChain->text();
1584        sieWorkDir = optUi->sieWorkDir->text();
1585        fpgaFile = optUi->fpgaFile->text();
1586        sieIP = optUi->sieIP->text();
1587        configApp = optUi->configApp->text();
1588    }
1589    optionsDialog->close();
1590    return 0;
1591}
1592
1593void MainWindow::createOptionsDialog()
1594{
1595    optionsDialog = new QDialog(this);
1596    optUi = new Ui_optionsDialog;
1597    optUi->setupUi(optionsDialog);
1598    connect(optUi->templateButton,SIGNAL(clicked()),SLOT(editTemplateDir()));
1599    connect(optUi->workButton,SIGNAL(clicked()),SLOT(editWorkDir()));
1600    connect(optUi->fpgaButton,SIGNAL(clicked()),SLOT(editFPGABinary()));
1601    connect(optUi->toolchainButton,SIGNAL(clicked()),this,SLOT(editToolChain()));
1602}
1603
1604void MainWindow::editToolChain()
1605{
1606    QString
1607            filePath = QFileDialog::getExistingDirectory(this,
1608                "Select the toolchain directory...",
1609                optUi->mipsToolChainDir->text());
1610
1611    if(filePath.isEmpty())
1612        return;
1613
1614    QDir myCurrentDir = this->currentDir();
1615    QString relativePath= myCurrentDir.relativeFilePath(filePath);
1616    optUi->mipsToolChainDir->setText(relativePath);
1617}
1618
1619void MainWindow::editTemplateDir()
1620{
1621    QString
1622            filePath = QFileDialog::getExistingDirectory(this,
1623                "Select the template directory",
1624                optUi->templateDir->text());
1625
1626    if(filePath.isEmpty())
1627        return;
1628
1629    QDir myCurrentDir = this->currentDir();
1630    QString relativePath= myCurrentDir.relativeFilePath(filePath);
1631    optUi->templateDir->setText(relativePath);
1632}
1633
1634
1635void MainWindow::editWorkDir()
1636{
1637    QString
1638            filePath = QFileDialog::getExistingDirectory(this,
1639                "Select the work directory",
1640                optUi->workDir->text());
1641
1642    if(filePath.isEmpty())
1643        return;
1644
1645    QDir myCurrentDir = this->currentDir();
1646    QString relativePath= myCurrentDir.relativeFilePath(filePath);
1647    optUi->workDir->setText(relativePath);
1648}
1649
1650void MainWindow::editFPGABinary()
1651{
1652    QString
1653    filePath = QFileDialog::getOpenFileName(this,
1654                "Select the FPGA binary file",
1655                optUi->fpgaFile->text(),
1656                "Binary file for SIE FPGA (*.bit)");
1657
1658    if(filePath.isEmpty())
1659        return;
1660
1661    if(!QFileInfo(filePath).isReadable())
1662    {
1663        QMessageBox::critical(this,"Error","File is not readable "
1664                                           " or not exists.");
1665        return;
1666    }
1667
1668    QDir myCurrentDir = this->currentDir();
1669    QString relativePath= myCurrentDir.relativeFilePath(filePath);
1670    optUi->fpgaFile->setText(relativePath);
1671}
1672
1673QString MainWindow::callexternapp(QString xexecFile, QString xexecParm)
1674{
1675    QEventLoop cxaw;
1676    callexternappT cxat;
1677    connect(&cxat, SIGNAL(finished()), &cxaw, SLOT(quit()));
1678    cxat.execFile = xexecFile;
1679    cxat.execParm = xexecParm;
1680    cxat.start();
1681    cxaw.exec();
1682    return cxat.retnValu;
1683}
1684
1685void MainWindow::finishSSH()
1686{
1687    if(sieSSH!=0)
1688        sieSSH->deleteProcess();
1689    sieSSH->deleteLater();
1690    sieSSH=0;
1691    sshReady=0;
1692    cgUi->exeButton->setEnabled(false);
1693    cgUi->fpgaButton->setEnabled(false);
1694    cgUi->sendButton->setEnabled(false);
1695    cgUi->commandEdit->setEnabled(false);
1696    cgUi->killButton->setEnabled(false);
1697    cgUi->lcdOnButton->setEnabled(false);
1698    cgUi->lcdOffButton->setEnabled(false);
1699    cgUi->connectButton->setText("Init SS&H on SIE");
1700    cgUi->logTextEdit->append(tr("SSH process killed"));
1701    cgUi->outputsTab->setCurrentIndex(0);
1702}
1703
1704void MainWindow::executeSSH()
1705{
1706    if(sieSSH!=0)
1707        finishSSH();
1708    sieSSH = new callApp(tr("ssh root@") + sieIP);
1709    connect(sieSSH,SIGNAL(newData()),this,SLOT(readSSH()));
1710    connect(sieSSH,SIGNAL(appClosed()),this,SLOT(finishSSH()));
1711    cgUi->logTextEdit->append(tr("Executing command: ") +
1712                              tr("ssh root@") + sieIP);
1713    cgUi->logTextEdit->append(tr("WARNING*** You have to configure SIE Ethernet"
1714                                 " Gadget connection previously (USB0)."));
1715    cgUi->outputsTab->setCurrentIndex(2);
1716    sshReady=0;
1717    cgUi->connectButton->setText("Connecting...");
1718}
1719
1720void MainWindow::readSSH()
1721{
1722    if(sieSSH!=0)
1723    {
1724        QString newData = sieSSH->readData();
1725        cgUi->sshTextEdit->append(newData);
1726        //TODO: Another better metode to detect ssh terminal ready?
1727        if(newData.contains("|__| W I R E L E S S F R E E D O M"))
1728        {
1729            sshReady=1;
1730            cgUi->logTextEdit->append(tr("Creating work directory on SIE"));
1731            writeSSH(tr("mkdir ") + sieWorkDir + "\n");
1732            writeSSH(tr("mkdir ") + sieWorkDir +
1733                              "/" +executableFile + "/ \n");
1734            //TODO: find another better metode to mkdir!
1735            QString command = tr("cd ") + sieWorkDir + tr("/") +
1736                              executableFile + tr("/");
1737            writeSSH("echo \"root@host: "+command+tr("\"\n"));
1738            writeSSH(command + tr("\n"));
1739            cgUi->exeButton->setEnabled(true);
1740            cgUi->fpgaButton->setEnabled(true);
1741            cgUi->sendButton->setEnabled(true);
1742            cgUi->commandEdit->setEnabled(true);
1743            cgUi->killButton->setEnabled(true);
1744            cgUi->lcdOnButton->setEnabled(true);
1745            cgUi->lcdOffButton->setEnabled(true);
1746            cgUi->connectButton->setText("Stop SS&H on SIE");
1747        } else if(newData.contains("s password:"))
1748        {
1749            writeSSH(tr("\n"));
1750        }
1751    }
1752}
1753
1754void MainWindow::sendCommand()
1755{
1756    writeSSH("echo \"root@host: "+cgUi->commandEdit->text()+tr("\"\n"));
1757    writeSSH(cgUi->commandEdit->text()+tr(" &\n"));
1758    cgUi->commandEdit->setText("");
1759}
1760
1761void MainWindow::writeSSH(QString data)
1762{
1763    if(sieSSH!=0)
1764        sieSSH->writeData(data);
1765}
1766
1767void MainWindow::finishCompile()
1768{
1769    if(compile!=0)
1770        compile->deleteProcess();
1771    compile->deleteLater();
1772    compile=0;
1773    cgUi->compileButton->setEnabled(true);
1774}
1775
1776void MainWindow::executeCompile()
1777{
1778    if(compile!=0)
1779        finishCompile();
1780    QString tempWorkDir = workDir+"/"+executableFile+"/";
1781    QString command =
1782            tr("make -C ") + tempWorkDir + tr(" -f ") + makeFile + " clean";
1783    cgUi->logTextEdit->append(tr("Executing command: ") + command );
1784    compile = new callApp(command);
1785    usleep(1000000); //1s delay
1786    command = tr("make -C ") + tempWorkDir + tr(" -f ") + makeFile;
1787    cgUi->logTextEdit->append(tr("Executing command: ") + command );
1788    compile = new callApp(command);
1789    connect(compile,SIGNAL(newData()),this,SLOT(readCompile()));
1790    connect(compile,SIGNAL(appClosed()),this,SLOT(finishCompile()));
1791    cgUi->compileButton->setEnabled(false);
1792    cgUi->outputsTab->setCurrentIndex(1);
1793}
1794
1795void MainWindow::readCompile()
1796{
1797    if(compile!=0)
1798        cgUi->compileTextEdit->append(compile->readData());
1799}
1800
1801void MainWindow::configFPGA()
1802{
1803    QString tempFPGAFile = fpgaFile;
1804    cgUi->logTextEdit->append(tr("WARNING*** Make sure before that the "
1805                                 "SIE processor is not too loaded."));
1806    cgUi->fpgaButton->setEnabled(false);
1807    cgUi->connectButton->setEnabled(false);
1808    cgUi->exeButton->setEnabled(false);
1809    cgUi->fpgaButton->setText("Configuring...");
1810    if(!copyFileToSie(tempFPGAFile))
1811    {
1812        cgUi->logTextEdit->append(tr("ERROR*** FPGA binary file could not "
1813                                     "be found. Make sure that this file {") +
1814                                  tempFPGAFile + tr("} exists."));
1815        cgUi->outputsTab->setCurrentIndex(0);
1816    }
1817    else
1818    {
1819        cgUi->logTextEdit->append(tr("Programming FPGA with file ")
1820                                  + tempFPGAFile );
1821        QString configCommand = configApp;
1822        configCommand=configCommand.replace("$FPGA_BINARY",
1823                      QFileInfo(fpgaFile).fileName());
1824        writeSSH("echo \"root@host: "+configCommand+tr("\"\n"));
1825        writeSSH(configCommand + tr("\n"));
1826        cgUi->outputsTab->setCurrentIndex(2);
1827    }
1828    cgUi->fpgaButton->setEnabled(true);
1829    cgUi->connectButton->setEnabled(true);
1830    cgUi->exeButton->setEnabled(true);
1831    cgUi->fpgaButton->setText("Configure &FPGA");
1832}
1833
1834int MainWindow::copyFileToSie(QString filepath)
1835{
1836
1837    if(QFileInfo(filepath).exists())
1838    {
1839        QEventLoop waitToFinish;
1840        cgUi->logTextEdit->append(tr("Executing command: ") +
1841                                  tr("scp ") + filepath + tr(" root@") +
1842                                  sieIP + tr(":") + sieWorkDir +
1843                                  "/"+executableFile + "/");
1844
1845        callApp copyFile(tr("scp ") + filepath + tr(" root@") + sieIP +
1846                         tr(":") + sieWorkDir + "/" + executableFile + "/");
1847
1848        connect(&copyFile, SIGNAL(appClosed()), &waitToFinish, SLOT(quit()));
1849        waitToFinish.exec();
1850        cgUi->logTextEdit->append(copyFile.readData());
1851        copyFile.deleteProcess();
1852        return 1;
1853    }
1854    return 0;
1855}
1856
1857void MainWindow::exeOnSie()
1858{
1859    QString tempSieApp = workDir + "/" + executableFile + "/" + executableFile;
1860
1861    cgUi->fpgaButton->setEnabled(false);
1862    cgUi->connectButton->setEnabled(false);
1863    cgUi->exeButton->setEnabled(false);
1864    cgUi->exeButton->setText("Running ...");
1865    killProcess();
1866    if(!copyFileToSie(tempSieApp))
1867    {
1868        cgUi->logTextEdit->append(tr("ERROR*** SIE binary file could not "
1869                                     "be found. Make sure that the application"
1870                                     " was compiled."));
1871        cgUi->outputsTab->setCurrentIndex(0);
1872    }
1873    else
1874    {
1875        cgUi->logTextEdit->append(tr("Executing binary file on SIE.")
1876                                  + tempSieApp );
1877        QString Command = "./" + executableFile + " &";
1878        writeSSH("echo \"root@host: "+Command+tr("\"\n"));
1879        writeSSH(Command + tr("\n"));
1880        cgUi->outputsTab->setCurrentIndex(2);
1881    }
1882    cgUi->fpgaButton->setEnabled(true);
1883    cgUi->connectButton->setEnabled(true);
1884    cgUi->exeButton->setEnabled(true);
1885    cgUi->exeButton->setText("&Excecute on SIE");
1886}
1887
1888void MainWindow::killProcess()
1889{
1890    cgUi->logTextEdit->append(tr("Stoping all running process..."));
1891    writeSSH("killall -9 " + executableFile + tr("\n"));
1892    usleep(200000); //wait 200ms
1893}
1894
1895void MainWindow::lcdOn()
1896{
1897    cgUi->logTextEdit->append(tr("Turning On LCD..."));
1898    writeSSH(tr("echo 0 > /sys/class/graphics/fb0/blank \n"));
1899    usleep(200000); //wait 200ms
1900}
1901
1902void MainWindow::lcdOff()
1903{
1904    cgUi->logTextEdit->append(tr("Turning Off LCD..."));
1905    writeSSH(tr("echo 4 > /sys/class/graphics/fb0/blank \n"));
1906    usleep(200000); //wait 200ms
1907}
1908
1909//TODO: Change list for pointer list for consumption memory reduction
1910
1911void MainWindow::undoDiagram()
1912{
1913    if(!undoList.isEmpty())
1914    {
1915        redoList.append(scene->toXmlFormat());
1916        scene->cleanScene();
1917        scene->fromXmlFormat(undoList.last());
1918        undoList.removeLast();
1919    }
1920    fflush(stdout);
1921}
1922
1923
1924void MainWindow::redoDiagram()
1925{
1926    if(!redoList.isEmpty())
1927    {
1928        undoList.append(scene->toXmlFormat());
1929        scene->cleanScene();
1930        scene->fromXmlFormat(redoList.last());
1931        redoList.removeLast();
1932    }
1933    fflush(stdout);
1934}
1935

Archive Download this file

Branches:
master



interactive