Changeset 162 in tspsg-svn


Ignore:
Timestamp:
Apr 14, 2011, 9:30:23 PM (13 years ago)
Author:
laleppa
Message:
  • NEW: Solution graph size can now be controlled using Output/GraphWidth? setting in tspsg.ini (see ticket:8). Value is in centimeters.
  • NEW: Support for embedded base64 encoded images when saving solution as HTML (closed ticket:4).
  • Renamed Output/ShowGraph? setting to Output/GenerateGraph?.
  • Made some other small tweaks and fixes.
  • FIX: Solution graph is still exported to HTML when graph generation is disabled (fixed bug:9).
Location:
trunk
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/defaults.h

    r161 r162  
    5353 * \brief Default for "Use translucency effects"
    5454 */
    55 #ifdef Q_WS_WIN
     55#ifdef Q_WS_WIN32
    5656#   define DEF_USE_TRANSLUCENCY true
    5757#else
     
    7878//////// OUTPUT
    7979
    80 //! Default for "Show solution graph"
    81 #define DEF_SHOW_GRAPH true
     80//! Default for "Generate solution graph"
     81#define DEF_GENERATE_GRAPH true
    8282//! Default for "Save solution graph as"
    8383#define DEF_GRAPH_IMAGE_FORMAT "png"
    8484//! Default for "Draw solution graph in higher quality"
    8585#define DEF_HQ_GRAPH false
     86//! Default for "Embed solution graph into HTML"
     87#define DEF_EMBED_GRAPH_INTO_HTML false
     88//! Default solution graph size in centimeters (HQ size is this size * HQ_FACTOR)
     89#define DEF_GRAPH_WIDTH 4.5
    8690//! Default for "Show solution steps' matrices for every solution step"
    8791#define DEF_SHOW_MATRIX true
  • trunk/src/globals.h

    r158 r162  
    102102#define INFSTR "---"
    103103
     104//! Number of centimeters in 1 inch
     105#define CM_IN_INCH 2.54
     106//! Factor for high quality graph generation
     107#define HQ_FACTOR 2
     108
    104109// FUNCTIONS
    105110/*!
  • trunk/src/mainwindow.cpp

    r161 r162  
    180180    tabWidget->setCurrentIndex(0);
    181181    solutionText->clear();
     182    graph = QPicture();
    182183    toggleSolutionActions(false);
    183184    QApplication::restoreOverrideCursor();
     
    274275    QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
    275276#ifndef QT_NO_PRINTER
    276     if (selectedFile.endsWith(".pdf",Qt::CaseInsensitive)) {
    277 QPrinter printer(QPrinter::HighResolution);
    278         printer.setOutputFormat(QPrinter::PdfFormat);
    279         printer.setOutputFileName(selectedFile);
    280         solutionText->document()->print(&printer);
     277    if (selectedFile.endsWith(".pdf", Qt::CaseInsensitive)) {
     278        printer->setOutputFileName(selectedFile);
     279        solutionText->document()->print(printer);
     280        printer->setOutputFileName(QString());
    281281        QApplication::restoreOverrideCursor();
    282282        return;
     
    293293QString format = settings->value("Output/GraphImageFormat", DEF_GRAPH_IMAGE_FORMAT).toString();
    294294#if !defined(NOSVG)
    295     if (!QImageWriter::supportedImageFormats().contains(format.toAscii()) && (format != "svg")) {
     295        if (!QImageWriter::supportedImageFormats().contains(format.toAscii()) && (format != "svg")) {
    296296#else // NOSVG
    297     if (!QImageWriter::supportedImageFormats().contains(format.toAscii())) {
     297        if (!QImageWriter::supportedImageFormats().contains(format.toAscii())) {
    298298#endif // NOSVG
    299         format = DEF_GRAPH_IMAGE_FORMAT;
    300         settings->remove("Output/GraphImageFormat");
    301     }
    302 QString html = solutionText->document()->toHtml("UTF-8"),
    303         img =  fi.completeBaseName() + "." + format;
     299            format = DEF_GRAPH_IMAGE_FORMAT;
     300            settings->remove("Output/GraphImageFormat");
     301        }
     302QString html = solutionText->document()->toHtml("UTF-8");
     303
    304304        html.replace(QRegExp("font-family:([^;]*);"), "font-family:\\1, 'DejaVu Sans Mono', 'Courier New', Courier, monospace;");
    305         html.replace(QRegExp("<img\\s+src=\"tspsg://graph.pic\""), QString("<img src=\"%1\" alt=\"%2\"").arg(img, tr("Solution Graph")));
    306 
     305
     306        if (!graph.isNull()) {
     307            QString img =  fi.completeBaseName() + "." + format;
     308            bool embed = settings->value("Output/EmbedGraphIntoHTML", DEF_EMBED_GRAPH_INTO_HTML).toBool();
     309            QByteArray data;
     310            QBuffer buf(&data);
     311            if (!embed) {
     312                html.replace(QRegExp("<img\\s+src=\"tspsg://graph.pic\""), QString("<img src=\"%1\" alt=\"%2\"").arg(img, tr("Solution Graph")));
     313            }
     314
     315            // Saving solution graph in SVG or supported raster format (depending on settings and SVG support)
     316#if !defined(NOSVG)
     317            if (format == "svg") {
     318                QSvgGenerator svg;
     319                svg.setSize(QSize(graph.width() + 2, graph.height() + 2));
     320                svg.setResolution(graph.logicalDpiX());
     321                svg.setFileName(fi.path() + "/" + img);
     322                svg.setTitle(tr("Solution Graph"));
     323                svg.setDescription(tr("Generated with %1").arg(QCoreApplication::applicationName()));
     324                QPainter p;
     325                p.begin(&svg);
     326                p.drawPicture(1, 1, graph);
     327                p.end();
     328            } else {
     329#endif // NOSVG
     330                QImage i(graph.width() + 2, graph.height() + 2, QImage::Format_ARGB32);
     331                i.fill(0x00FFFFFF);
     332                QPainter p;
     333                p.begin(&i);
     334                p.drawPicture(1, 1, graph);
     335                p.end();
     336                QImageWriter pic;
     337                if (embed) {
     338                    pic.setDevice(&buf);
     339                    pic.setFormat(format.toAscii());
     340                } else {
     341                    pic.setFileName(fi.path() + "/" + img);
     342                }
     343                if (pic.supportsOption(QImageIOHandler::Description)) {
     344                    pic.setText("Title", "Solution Graph");
     345                    pic.setText("Software", QCoreApplication::applicationName());
     346                }
     347                if (format == "png")
     348                    pic.setQuality(5);
     349                else if (format == "jpeg")
     350                    pic.setQuality(80);
     351                if (!pic.write(i)) {
     352                    QApplication::restoreOverrideCursor();
     353                    QMessageBox::critical(this, tr("Solution Save"), tr("Unable to save the solution graph.\nError: %1").arg(pic.errorString()));
     354                    return;
     355                }
     356#if !defined(NOSVG)
     357            }
     358#endif // NOSVG
     359            if (embed) {
     360                html.replace(QRegExp("<img\\s+src=\"tspsg://graph.pic\""), QString("<img src=\"data:image/%1;base64,%2\" alt=\"%3\"").arg(format, data.toBase64(), tr("Solution Graph")));
     361            }
     362        }
    307363        // Saving solution text as HTML
    308364QTextStream ts(&file);
     
    310366        ts << html;
    311367        file.close();
    312 
    313         // Saving solution graph as SVG or PNG (depending on settings and SVG support)
    314 #if !defined(NOSVG)
    315         if (format == "svg") {
    316 QSvgGenerator svg;
    317             svg.setSize(QSize(graph.width() + 2, graph.height() + 2));
    318             svg.setResolution(graph.logicalDpiX());
    319             svg.setFileName(fi.path() + "/" + img);
    320             svg.setTitle(tr("Solution Graph"));
    321             svg.setDescription(tr("Generated with %1").arg(QCoreApplication::applicationName()));
    322 QPainter p;
    323             p.begin(&svg);
    324             p.drawPicture(1, 1, graph);
    325             p.end();
    326         } else {
    327 #endif // NOSVG
    328 QImage i(graph.width() + 2, graph.height() + 2, QImage::Format_ARGB32);
    329             i.fill(0x00FFFFFF);
    330 QPainter p;
    331             p.begin(&i);
    332             p.drawPicture(1, 1, graph);
    333             p.end();
    334 QImageWriter pic(fi.path() + "/" + img);
    335             if (pic.supportsOption(QImageIOHandler::Description)) {
    336                 pic.setText("Title", "Solution Graph");
    337                 pic.setText("Software", QCoreApplication::applicationName());
    338             }
    339             if (format == "png")
    340                 pic.setQuality(5);
    341             else if (format == "jpeg")
    342                 pic.setQuality(80);
    343             if (!pic.write(i)) {
    344                 QApplication::restoreOverrideCursor();
    345                 QMessageBox::critical(this, tr("Solution Save"), tr("Unable to save the solution graph.\nError: %1").arg(pic.errorString()));
    346                 return;
    347             }
    348 #if !defined(NOSVG)
    349         }
    350 #endif // NOSVG
    351368    } else {
    352369QTextDocumentWriter dw(selectedFile);
     
    743760            tl = NULL;
    744761        } else {
    745 //                      tl->SetProgressState(winId(), TBPF_INDETERMINATE);
    746762            tl->SetProgressValue(winId(), 0, n * 2);
    747763        }
     
    769785#ifdef Q_WS_WIN32
    770786            if (tl != NULL) {
    771 //                              tl->SetProgressValue(winId(), n, n * 2);
    772787                tl->SetProgressState(winId(), TBPF_ERROR);
    773788            }
     
    818833
    819834QPainter pic;
    820     if (settings->value("Output/ShowGraph", DEF_SHOW_GRAPH).toBool()) {
     835bool dograph = settings->value("Output/GenerateGraph", DEF_GENERATE_GRAPH).toBool();
     836    if (dograph) {
    821837        pic.begin(&graph);
    822838        pic.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
    823839QFont font = qvariant_cast<QFont>(settings->value("Output/Font", QFont(DEF_FONT_FACE)));
    824         //! \todo FIXME: Get rid of the "magic number" in the code.
    825         font.setPixelSize(logicalDpiX() / 7);
     840        font.setStyleHint(QFont::Monospace);
     841        // Font size in pixels = graph node radius / 2.75.
     842        // See MainWindow::drawNode() for graph node radius calcualtion description.
     843        font.setPixelSize(logicalDpiX() * (settings->value("Output/GraphWidth", DEF_GRAPH_WIDTH).toReal() / CM_IN_INCH) / 4.5 / 2.75);
    826844        if (settings->value("Output/HQGraph", DEF_HQ_GRAPH).toBool()) {
    827845            font.setWeight(QFont::DemiBold);
    828             font.setPixelSize(font.pixelSize() * 2);
     846            font.setPixelSize(font.pixelSize() * HQ_FACTOR);
    829847        }
    830848        pic.setFont(font);
     
    832850        if (settings->value("Output/HQGraph", DEF_HQ_GRAPH).toBool()) {
    833851QPen pen = pic.pen();
    834             pen.setWidth(2);
     852            pen.setWidth(HQ_FACTOR);
    835853            pic.setPen(pen);
    836854        }
    837855        pic.setBackgroundMode(Qt::OpaqueMode);
     856    } else {
     857        graph = QPicture();
    838858    }
    839859
     
    847867    cur.insertText(tr("Task:"), fmt_default);
    848868    outputMatrix(cur, matrix);
    849     if (settings->value("Output/ShowGraph", DEF_SHOW_GRAPH).toBool()) {
     869    if (dograph) {
    850870#ifdef _T_T_L_
    851871        _b_ _i_ _z_ _a_ _r_ _r_ _e_
     
    904924            outputMatrix(cur, *step);
    905925        }
    906         cur.insertBlock(fmt_paragraph);
     926        if (step->alts.empty())
     927            cur.insertBlock(fmt_lastparagraph);
     928        else
     929            cur.insertBlock(fmt_paragraph);
    907930        cur.insertText(tr("Selected route %1 %2 part.").arg((step->next == SStep::RightBranch) ? tr("with") : tr("without")).arg(tr("(%1;%2)").arg(step->candidate.nRow + 1).arg(step->candidate.nCol + 1)), fmt_default);
    908931        if (!step->alts.empty()) {
     
    914937                alts += tr("(%1;%2)").arg(cand.nRow + 1).arg(cand.nCol + 1);
    915938            }
    916             cur.insertBlock(fmt_paragraph);
     939            cur.insertBlock(fmt_lastparagraph);
    917940            cur.insertText(tr("%n alternate candidate(s) for branching: %1.", "", step->alts.count()).arg(alts), fmt_altlist);
    918941        }
    919         cur.insertBlock(fmt_paragraph);
    920         cur.insertText(" ", fmt_default);
    921942        cur.endEditBlock();
    922943
    923         if (settings->value("Output/ShowGraph", DEF_SHOW_GRAPH).toBool()) {
     944        if (dograph) {
    924945            if (step->prNode != NULL)
    925946                drawNode(pic, n, false, step->prNode);
     
    947968    cur.insertBlock(fmt_paragraph);
    948969    if (solver.isOptimal())
    949         cur.insertText(tr("Optimal path:"));
     970        cur.insertText(tr("Optimal path:"), fmt_default);
    950971    else
    951         cur.insertText(tr("Resulting path:"));
     972        cur.insertText(tr("Resulting path:"), fmt_default);
    952973
    953974    cur.insertBlock(fmt_paragraph);
    954975    cur.insertText("  " + solver.getSortedPath(tr("City %1")));
    955976
    956     cur.insertBlock(fmt_paragraph);
     977    if (solver.isOptimal())
     978        cur.insertBlock(fmt_paragraph);
     979    else
     980        cur.insertBlock(fmt_lastparagraph);
    957981    if (isInteger(step->price))
    958982        cur.insertHtml("<p>" + tr("The price is <b>%n</b> unit(s).", "", qRound(step->price)) + "</p>");
     
    961985    if (!solver.isOptimal()) {
    962986        cur.insertBlock(fmt_paragraph);
    963         cur.insertText(" ");
    964         cur.insertBlock(fmt_paragraph);
    965987        cur.insertHtml("<p>" + tr("<b>WARNING!!!</b><br>This result is a record, but it may not be optimal.<br>Iterations need to be continued to check whether this result is optimal or get an optimal one.") + "</p>");
    966988    }
    967989    cur.endEditBlock();
    968990
    969     if (settings->value("Output/ShowGraph", DEF_SHOW_GRAPH).toBool()) {
     991    if (dograph) {
    970992        pic.end();
    971993
     
    9801002        img.setName("tspsg://graph.pic");
    9811003        if (settings->value("Output/HQGraph", DEF_HQ_GRAPH).toBool()) {
    982             img.setWidth(i.width() / 2);
    983             img.setHeight(i.height() / 2);
     1004            img.setWidth(i.width() / HQ_FACTOR);
     1005            img.setHeight(i.height() / HQ_FACTOR);
    9841006        } else {
    9851007            img.setWidth(i.width());
     
    11671189void MainWindow::drawNode(QPainter &pic, int nstep, bool left, SStep *step)
    11681190{
    1169 qreal r;
    1170     //! \todo FIXME: Get rid of the "magic numbers" in the code.
     1191qreal r; // Radius of graph node
     1192    // We calculate r from the full graph width in centimeters:
     1193    //   r = width in pixels / 4.5.
     1194    //   width in pixels = DPI * width in inches.
     1195    //   width in inches = width in cm / cm in inch.
     1196    r = logicalDpiX() * (settings->value("Output/GraphWidth", DEF_GRAPH_WIDTH).toReal() / CM_IN_INCH) / 4.5;
    11711197    if (settings->value("Output/HQGraph", DEF_HQ_GRAPH).toBool())
    1172         r = logicalDpiX() / 1.27;
    1173     else
    1174         r = logicalDpiX() / 2.54;
     1198        r *= HQ_FACTOR;
    11751199#ifdef Q_WS_S60
    11761200    /*! \hack HACK: Solution graph on Symbian is visually larger than on
     
    12471271    fmt_paragraph.setBottomMargin(0);
    12481272    fmt_paragraph.setLeftMargin(10);
     1273
     1274    fmt_lastparagraph.setTopMargin(5);
     1275    fmt_lastparagraph.setRightMargin(10);
     1276    fmt_lastparagraph.setBottomMargin(15);
     1277    fmt_lastparagraph.setLeftMargin(10);
    12491278
    12501279    fmt_table.setTopMargin(5);
  • trunk/src/mainwindow.h

    r161 r162  
    133133    QTextTableFormat fmt_table;
    134134    QTextBlockFormat fmt_paragraph,
     135        fmt_lastparagraph,
    135136        fmt_cell;
    136137    QTextCharFormat fmt_default,
  • trunk/src/settingsdialog.cpp

    r151 r162  
    7676    hbox->addSpacing(10);
    7777    hbox->addWidget(cbHQGraph);
    78     box->insertLayout(box->indexOf(cbShowGraph) + 1, hbox);
    79     connect(cbShowGraph, SIGNAL(toggled(bool)), cbHQGraph, SLOT(setEnabled(bool)));
     78    box->insertLayout(box->indexOf(cbGenerateGraph) + 2, hbox);
     79    connect(cbGenerateGraph, SIGNAL(toggled(bool)), cbHQGraph, SLOT(setEnabled(bool)));
    8080#endif
    8181
     
    147147        cbUseTranslucency->setObjectName("cbUseTranslucency");
    148148#ifndef QT_NO_STATUSTIP
    149         cbUseTranslucency->setStatusTip(tr("Use translucent effect on the Main Window under Windows Vista and 7"));
     149        cbUseTranslucency->setStatusTip(tr("Make Main Window background translucent"));
    150150#endif // QT_NO_STATUSTIP
    151151        cbUseTranslucency->setText(tr("Use translucency effects"));
     
    174174    labelHint->setObjectName("labelHint");
    175175    labelHint->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Preferred);
    176 //      labelHint->setMinimumSize(QSize(190,28));
    177     labelHint->setMinimumSize(QSize(0,28));
    178     labelHint->setMaximumSize(QSize(QWIDGETSIZE_MAX,28));
     176    labelHint->setMinimumSize(QSize(250, 28));
     177    labelHint->setMaximumSize(QSize(QWIDGETSIZE_MAX, 28));
    179178    labelHint->setTextFormat(Qt::PlainText);
    180179//      labelHint->setAlignment(Qt::AlignLeft | Qt::AlignTop);
     
    260259
    261260    settings->beginGroup("Output");
    262     cbShowGraph->setChecked(settings->value("ShowGraph", DEF_SHOW_GRAPH).toBool());
     261    cbGenerateGraph->setChecked(settings->value("GenerateGraph", DEF_GENERATE_GRAPH).toBool());
    263262
    264263#ifndef QT_NO_PRINTER
    265     cbHQGraph->setEnabled(cbShowGraph->isChecked());
    266     cbHQGraph->setChecked(settings->value("HQGraph", DEF_HQ_GRAPH && cbShowGraph->isChecked()).toBool());
     264    cbHQGraph->setEnabled(cbGenerateGraph->isChecked());
     265    cbHQGraph->setChecked(settings->value("HQGraph", DEF_HQ_GRAPH).toBool());
    267266#endif
    268267
     
    283282    if (comboGraphImageFormat->currentIndex() < 0)
    284283        comboGraphImageFormat->setCurrentIndex(comboGraphImageFormat->findText(DEF_GRAPH_IMAGE_FORMAT, Qt::MatchFixedString));
    285     labelGraphImageFormat->setEnabled(cbShowGraph->isChecked());
    286     comboGraphImageFormat->setEnabled(cbShowGraph->isChecked());
     284    labelGraphImageFormat->setEnabled(cbGenerateGraph->isChecked());
     285    comboGraphImageFormat->setEnabled(cbGenerateGraph->isChecked());
     286    cbEmbedGraphIntoHTML->setChecked(settings->value("EmbedGraphIntoHTML", DEF_EMBED_GRAPH_INTO_HTML).toBool());
     287    cbEmbedGraphIntoHTML->setEnabled(cbGenerateGraph->isChecked());
    287288
    288289    cbShowMatrix->setChecked(settings->value("ShowMatrix", DEF_SHOW_MATRIX).toBool());
     
    326327 * \brief Indicates whether and how the translucency setting was changed
    327328 * \retval -1 the translucency was \em disabled.
    328  * \retval  0 the translucency was <em>not changed</em>.
     329 * \retval  0 the translucency <em>didn't change</em>.
    329330 * \retval  1 the translucency was \em enabled.
    330331 */
     
    381382
    382383    settings->beginGroup("Output");
    383     settings->setValue("ShowGraph", cbShowGraph->isChecked());
     384    settings->setValue("GenerateGraph", cbGenerateGraph->isChecked());
     385    if (cbGenerateGraph->isChecked()) {
    384386#ifndef QT_NO_PRINTER
    385     settings->setValue("HQGraph", cbShowGraph->isChecked() && cbHQGraph->isChecked());
     387        settings->setValue("HQGraph", cbHQGraph->isChecked());
    386388#endif
    387     if (cbShowGraph->isChecked()) {
    388         if (comboGraphImageFormat->currentIndex() >= 0)
    389             settings->setValue("GraphImageFormat", comboGraphImageFormat->currentText());
    390         else
    391             settings->setValue("GraphImageFormat", DEF_GRAPH_IMAGE_FORMAT);
     389        if (cbGenerateGraph->isChecked()) {
     390            if (comboGraphImageFormat->currentIndex() >= 0)
     391                settings->setValue("GraphImageFormat", comboGraphImageFormat->currentText());
     392            else
     393                settings->setValue("GraphImageFormat", DEF_GRAPH_IMAGE_FORMAT);
     394        }
     395        settings->setValue("EmbedGraphIntoHTML", cbEmbedGraphIntoHTML->isChecked());
    392396    }
    393397    settings->setValue("ShowMatrix", cbShowMatrix->isChecked());
  • trunk/ui/settingsdialog.ui

    r128 r162  
    297297       <layout class="QVBoxLayout" name="_6">
    298298        <item>
    299          <widget class="QCheckBox" name="cbShowGraph">
     299         <widget class="QCheckBox" name="cbGenerateGraph">
    300300          <property name="cursor">
    301301           <cursorShape>PointingHandCursor</cursorShape>
    302302          </property>
    303303          <property name="statusTip">
    304            <string>Show graphical representation of the solution</string>
     304           <string>Generate graphical representation of the solution</string>
    305305          </property>
    306306          <property name="text">
    307            <string>Show solution graph</string>
     307           <string>Generate solution graph</string>
    308308          </property>
    309309         </widget>
     
    362362            </property>
    363363           </spacer>
     364          </item>
     365         </layout>
     366        </item>
     367        <item>
     368         <layout class="QHBoxLayout" name="_14">
     369          <item>
     370           <spacer name="spacer_8">
     371            <property name="orientation">
     372             <enum>Qt::Horizontal</enum>
     373            </property>
     374            <property name="sizeType">
     375             <enum>QSizePolicy::Fixed</enum>
     376            </property>
     377            <property name="sizeHint" stdset="0">
     378             <size>
     379              <width>10</width>
     380              <height>0</height>
     381             </size>
     382            </property>
     383           </spacer>
     384          </item>
     385          <item>
     386           <widget class="QCheckBox" name="cbEmbedGraphIntoHTML">
     387            <property name="cursor">
     388             <cursorShape>PointingHandCursor</cursorShape>
     389            </property>
     390            <property name="statusTip">
     391             <string>Use data URI scheme to save solution graph in HTML (not supported by IE 7 and lower)</string>
     392            </property>
     393            <property name="text">
     394             <string>Embed solution graph into HTML</string>
     395            </property>
     396           </widget>
    364397          </item>
    365398         </layout>
     
    611644  </connection>
    612645  <connection>
    613    <sender>cbShowGraph</sender>
     646   <sender>cbGenerateGraph</sender>
    614647   <signal>toggled(bool)</signal>
    615648   <receiver>labelGraphImageFormat</receiver>
     
    627660  </connection>
    628661  <connection>
    629    <sender>cbShowGraph</sender>
     662   <sender>cbGenerateGraph</sender>
    630663   <signal>toggled(bool)</signal>
    631664   <receiver>comboGraphImageFormat</receiver>
     
    642675   </hints>
    643676  </connection>
     677  <connection>
     678   <sender>cbGenerateGraph</sender>
     679   <signal>toggled(bool)</signal>
     680   <receiver>cbEmbedGraphIntoHTML</receiver>
     681   <slot>setEnabled(bool)</slot>
     682   <hints>
     683    <hint type="sourcelabel">
     684     <x>128</x>
     685     <y>45</y>
     686    </hint>
     687    <hint type="destinationlabel">
     688     <x>136</x>
     689     <y>103</y>
     690    </hint>
     691   </hints>
     692  </connection>
    644693 </connections>
    645694</ui>
Note: See TracChangeset for help on using the changeset viewer.