    //=============================================================================
    //  MuseScore
    //  Music Composition & Notation
    //
    //  Copyright (C) 2002-2017 Werner Schweer
    //
    //  This program is free software; you can redistribute it and/or modify
    //  it under the terms of the GNU General Public License version 2
    //  as published by the Free Software Foundation and appearing in
    //  the file LICENCE.GPL
    //=============================================================================

    #include "scoreview.h"
    #include "musescore.h"
    #include "libmscore/score.h"
    #include "libmscore/lasso.h"
    #include "icons.h"
    #include "libmscore/page.h"
    #include "preferences.h"
    #include "libmscore/image.h"
    #include "libmscore/mscore.h"
    #include "svggenerator.h"
    #include "inspector/inspector.h"
    #include "fotomode.h"

    namespace Ms {

    //---------------------------------------------------------
    //   startEdit
    //---------------------------------------------------------

    void FotoLasso::startEdit(EditData& ed)
          {
          ed.grips   = 8;
          ed.curGrip = Grip(0);
          QRectF view = ((ScoreView*)ed.view)->toLogical(QRect(0.0, 0.0, ed.view->geometry().width(), ed.view->geometry().height()));
          if (bbox().isEmpty() || !view.intersects(bbox())) {
                // rect not found - construct new rect with default size & relative position
                qreal w = view.width();
                qreal h = view.height();
                QRectF rect(w * .3, h * .3, w * .4, h * .4);
                // convert to absolute position
                setbbox(rect.translated(view.topLeft()));
                }
          setVisible(false);
          }

    //---------------------------------------------------------
    //   endEdit
    //---------------------------------------------------------

    void FotoLasso::endEdit(EditData&)
          {
          setVisible(false);
          }

    //---------------------------------------------------------
    //   updateGrips
    //---------------------------------------------------------

    void FotoLasso::updateGrips(EditData& ed) const
          {
          Lasso::updateGrips(ed);
          }

    //---------------------------------------------------------
    //   drawEditMode
    //---------------------------------------------------------

    void FotoLasso::drawEditMode(QPainter* p, EditData& ed)
          {
          QPointF pos(canvasPos());
          p->translate(pos);
          draw(p);
          p->translate(-pos);
          Lasso::drawEditMode(p, ed);
          }

    //---------------------------------------------------------
    //   startFotoMode
    //---------------------------------------------------------

    void ScoreView::startFotomode()
          {
          if (!_foto)
                _foto = new FotoLasso(_score);
          else
                _foto->setScore(_score);
          _foto->setVisible(true);
          _score->select(_foto);
          editData.element = _foto;
          QAction* a = getAction("fotomode");
          a->setChecked(true);
          startEdit();
          }

    //---------------------------------------------------------
    //   stopFotomode
    //---------------------------------------------------------

    void ScoreView::stopFotomode()
          {
          QAction* a = getAction("fotomode");
          a->setChecked(false);
          _foto->setVisible(false);
          endEdit();
          update();
          }

    //---------------------------------------------------------
    //   startFotoDrag
    //---------------------------------------------------------

    void ScoreView::startFotoDrag()
          {
          _score->addRefresh(_foto->abbox());
          _score->update();
          editData.grips = 0;
          }

    //---------------------------------------------------------
    //   doDragFoto
    //    drag canvas in foto mode
    //---------------------------------------------------------

    void ScoreView::doDragFoto(QMouseEvent* ev)
          {
          QPointF p = toLogical(ev->pos());
          QRectF r;
          r.setCoords(editData.startMove.x(), editData.startMove.y(), p.x(), p.y());
          _foto->setbbox(r.normalized());

          QRectF rr(_foto->bbox());
          r = _matrix.mapRect(rr);
          //QSize sz(r.size().toSize());
          //mscore->statusBar()->showMessage(QString("%1 x %2").arg(sz.width()).arg(sz.height()), 3000);

          update();
          //mscore->showMessage("drag", 2000);
          }

    //---------------------------------------------------------
    //   endFotoDrag
    //---------------------------------------------------------

    void ScoreView::endFotoDrag()
          {
          qreal w = 8.0 / _matrix.m11();
          qreal h = 8.0 / _matrix.m22();
          QRectF r(-w*.5, -h*.5, w, h);
          editData.grip.resize(8);
          for (int i = 0; i < 8; ++i)
                editData.grip[i] = r;
          editData.element = _foto;
          updateGrips();
          _score->setUpdateAll();
          _score->update();
          }

    //---------------------------------------------------------
    //   doFotoDragEdit
    //---------------------------------------------------------

    void ScoreView::doFotoDragEdit(QMouseEvent* ev)
          {
          QPointF p     = toLogical(ev->pos());
          QPointF delta = p - editData.startMove;
          score()->addRefresh(_foto->abbox());

          editData.delta   = delta;
          _foto->editDrag(editData);
          updateGrips();
          editData.startMove = p;
          _score->update();
          if (mscore->inspector())
                mscore->inspector()->update(_foto->score());
          }

    //---------------------------------------------------------
    //   endFotoDragEdit
    //---------------------------------------------------------

    void ScoreView::endFotoDragEdit()
          {
          }

    //---------------------------------------------------------
    //   fotoEditElementDragTransition
    //---------------------------------------------------------

    bool ScoreView::fotoEditElementDragTransition(QMouseEvent* ev)
          {
          editData.startMove = imatrix.map(QPointF(ev->pos()));
          int i;
          for (i = 0; i < editData.grips; ++i) {
                if (editData.grip[i].contains(editData.startMove)) {
                      editData.curGrip = Grip(i);
                      switch (int(editData.curGrip)) {
                            case 0:
                            case 2:
                                  setCursor(Qt::SizeFDiagCursor);
                                  break;
                            case 1:
                            case 3:
                                  setCursor(Qt::SizeBDiagCursor);
                                  break;
                            case 4:
                            case 6:
                                  setCursor(Qt::SizeVerCursor);
                                  break;
                            case 5:
                            case 7:
                                  setCursor(Qt::SizeHorCursor);
                                  break;
                            }
                      updateGrips();
                      score()->update();
                      break;
                      }
                }
          return i != editData.grips;
          }

    //---------------------------------------------------------
    //   fotoScoreViewDragTest
    //---------------------------------------------------------

    bool ScoreView::fotoScoreViewDragTest(QMouseEvent* me)
          {
          QPointF p(imatrix.map(QPointF(me->pos())));
          if (_foto->bbox().contains(p))
                return false;
          for (int i = 0; i < editData.grips; ++i) {
                if (editData.grip[i].contains(p))
                      return false;
                }
          editData.startMove = p;
          return true;
          }

    //---------------------------------------------------------
    //   fotoScoreViewDragRectTest
    //---------------------------------------------------------

    bool ScoreView::fotoScoreViewDragRectTest(QMouseEvent* me)
          {
          QPointF p(toLogical(me->pos()));
          if (!_foto->bbox().contains(p))
                return false;
          for (int i = 0; i < editData.grips; ++i) {
                if (editData.grip[i].contains(p))
                      return false;
                }
          editData.startMove = p;
          return true;
          }

    //---------------------------------------------------------
    //   doDragFotoRect
    //---------------------------------------------------------

    void ScoreView::doDragFotoRect(QMouseEvent* ev)
          {
          QPointF p(toLogical(ev->pos()));
          QPointF delta = p - editData.startMove;
          score()->addRefresh(_foto->abbox());
          _foto->setbbox(_foto->bbox().translated(delta));
          score()->addRefresh(_foto->abbox());
          editData.startMove = p;
          updateGrips();
          _score->update();
          if (mscore->inspector())
                mscore->inspector()->update(_foto->score());
          }

    //---------------------------------------------------------
    //   MenuEntry
    //---------------------------------------------------------

    struct MenuEntry {
          const char* text;
          const char* label;
          };

    static const MenuEntry resizeEntry[4] {
          { QT_TRANSLATE_NOOP("fotomode", "Resize to A"), "resizeA" },
          { QT_TRANSLATE_NOOP("fotomode", "Resize to B"), "resizeB" },
          { QT_TRANSLATE_NOOP("fotomode", "Resize to C"), "resizeC" },
          { QT_TRANSLATE_NOOP("fotomode", "Resize to D"), "resizeD" }
          };

    static const MenuEntry setSizeEntry[4] {
          { QT_TRANSLATE_NOOP("fotomode", "Set size A"), "setA" },
          { QT_TRANSLATE_NOOP("fotomode", "Set size B"), "setB" },
          { QT_TRANSLATE_NOOP("fotomode", "Set size C"), "setC" },
          { QT_TRANSLATE_NOOP("fotomode", "Set size D"), "setD" }
          };

    //---------------------------------------------------------
    //   fotoContextPopup
    //---------------------------------------------------------

    void ScoreView::fotoContextPopup(QContextMenuEvent* ev)
          {
          QPoint pos(ev->globalPos());
          QMenu* popup = new QMenu(this);
          popup->setSeparatorsCollapsible(false);
          QAction* a = popup->addSeparator();
          a->setText(tr("Image Capture"));

          a = getAction("copy");
          popup->addAction(a);

          popup->addSeparator();
          a = popup->addAction(tr("Resolution (%1 DPI)...").arg(preferences.pngResolution));
          a->setData("set-res");
          QAction* bgAction = popup->addAction(tr("Transparent background"));
          bgAction->setCheckable(true);
          bgAction->setChecked(preferences.pngTransparent);
          bgAction->setData("set-bg");

          popup->addSeparator();
          a = new QAction(tr("Auto-resize to page"), this);
          a->setData("resizePage");
          popup->addAction(a);
          for (int i = 0; i < 4; ++i) {
                a = new QAction(qApp->translate("fotomode", resizeEntry[i].text), this);
                a->setData(resizeEntry[i].label);
                popup->addAction(a);
                }
          QMenu* setSize = new QMenu(tr("Set Standard Size..."));
          for (int i = 0; i < 4; ++i) {
                a = new QAction(qApp->translate("fotomode", setSizeEntry[i].text), this);
                a->setData(setSizeEntry[i].label);
                setSize->addAction(a);
                }
          popup->addMenu(setSize);

          popup->addSeparator();
          a = new QAction(tr("Save As (Print Mode)..."), this);
          a->setData("print");
          popup->addAction(a);
          a = new QAction(tr("Save As (Screenshot Mode)..."), this);
          a->setData("screenshot");
          popup->addAction(a);

          a = popup->exec(pos);
          if (a == 0)
                return;
          QString cmd(a->data().toString());
          if (cmd == "print")
                saveFotoAs(true, _foto->bbox());
          else if (cmd == "screenshot")
                saveFotoAs(false, _foto->bbox());
          else if (cmd == "copy")
                ;
          else if (cmd == "set-res") {
                bool ok;
                double resolution = QInputDialog::getDouble(this,
                   tr("Set Output Resolution"),
                   tr("Set output resolution for PNG"),
                   preferences.pngResolution,
                   16.0, 2400.0, 1,
                   &ok
                   );
                if (ok) {
                      preferences.pngResolution = resolution;
                      preferences.dirty = true;
                      }
                }
          else if (cmd == "resizePage") {
                QRectF r = _foto->bbox();
                Page* page = point2page(r.center());
                if (page) {
                      r = page->tbbox().translated(page->canvasPos());
                      _foto->setbbox(r);
                      updateGrips();
                      }
                }
          else if (cmd.startsWith("resize")) {
                QString size = QSettings().value(QString("fotoSize%1").arg(cmd[6]), "50x40").toString();
                qreal w = size.split("x")[0].toDouble();
                qreal h = size.split("x")[1].toDouble();
                _foto->bbox().setSize(QSizeF(w * DPMM, h * DPMM));
                updateGrips();
                }
          else if (cmd.startsWith("set")) {
                qreal w   = _foto->bbox().width() / DPMM;
                qreal h   = _foto->bbox().height() / DPMM;
                QString val(QString("%1x%2").arg(w).arg(h));
                QSettings().setValue(QString("fotoSize%1").arg(cmd[3]), val);
                }
          if (bgAction->isChecked() != preferences.pngTransparent) {
                preferences.pngTransparent = bgAction->isChecked();
                preferences.dirty = true;
                }
          }

    //---------------------------------------------------------
    //   fotoModeCopy
    //---------------------------------------------------------

    void ScoreView::fotoModeCopy()
          {
          // oowriter wants transparent==false
          bool transparent = false; // preferences.pngTransparent;
          double convDpi   = preferences.pngResolution;
          double mag       = convDpi / DPI;

          QRectF r(_foto->bbox());

          int w = lrint(r.width()  * mag);
          int h = lrint(r.height() * mag);

          QImage::Format f;
          f = QImage::Format_ARGB32_Premultiplied;
          QImage printer(w, h, f);
          printer.setDotsPerMeterX(lrint(DPMM * 1000.0));
          printer.setDotsPerMeterY(lrint(DPMM * 1000.0));
          printer.fill(transparent ? 0 : 0xffffffff);
          QPainter p(&printer);
          paintRect(true, p, r, mag);
    #if defined(Q_OS_WIN)
          // workaround for apparent Qt 5.4 bug; corrupt clipboard when using setImage()
          QPixmap px;
          px.convertFromImage(printer);
          QApplication::clipboard()->setPixmap(px);
    #else
          QApplication::clipboard()->setImage(printer);
    #endif
          }

    //---------------------------------------------------------
    //   fotoRectHit
    //---------------------------------------------------------

    bool ScoreView::fotoRectHit(const QPoint& pos)
          {
          QPointF p = toLogical(pos);
          for (int i = 0; i < editData.grips; ++i) {
                if (editData.grip[i].contains(p))
                      return false;
                }
          editData.startMove = p;
          return _foto->bbox().contains(p);
          }

    //---------------------------------------------------------
    //   saveFotoAs
    //    return true on success
    //---------------------------------------------------------

    bool ScoreView::saveFotoAs(bool printMode, const QRectF& r)
          {
          QStringList fl;
          fl.append(tr("PNG Bitmap Graphic") + " (*.png)");
          fl.append(tr("PDF File") + " (*.pdf)");
          fl.append(tr("Scalable Vector Graphics") + " (*.svg)");

          QString selectedFilter;
          QString filter = fl.join(";;");
          QString fn = mscore->getFotoFilename(filter, &selectedFilter);

          if (fn.isEmpty())
                return false;

          QFileInfo fi(fn);
          mscore->lastSaveDirectory = fi.absolutePath();

          QString ext;
          if (selectedFilter.isEmpty()) {
                ext = fi.suffix();
                }
          else {
                int idx = fl.indexOf(selectedFilter);
                if (idx != -1) {
                      static const char* extensions[] = {
                            "png",
                            "pdf",
                            "svg"
                            };
                      ext = extensions[idx];
                      }
                }

          if (ext.isEmpty()) {
                QMessageBox::critical(mscore, tr("Save As"), tr("Cannot determine file type"));
                return false;
                }

          ext = ext.toLower();
          if (fi.suffix().toLower() != ext)
                fn += "." + ext;

          bool transparent = preferences.pngTransparent;
          double convDpi   = preferences.pngResolution;
          double mag       = convDpi / DPI;

          if (ext == "svg")
                mag = 1; // SVG is not scaled, it's scalable.

          int w = lrint(r.width()  * mag);
          int h = lrint(r.height() * mag);

          double pr = MScore::pixelRatio;
          if (ext == "pdf") {
                QPdfWriter pdfWriter(fn);
                mag = pdfWriter.logicalDpiX() / DPI;
                pdfWriter.setResolution(preferences.exportPdfDpi);
                QSizeF size(r.width() * mag, r.height() * mag);
                QPageSize ps(QPageSize::id(size, QPageSize::Inch));
                pdfWriter.setPageSize(ps);
                pdfWriter.setCreator("MuseScore Version: " VERSION);
                pdfWriter.setTitle(fn);
                MScore::pixelRatio = DPI / pdfWriter.logicalDpiX();
                QPainter p(&pdfWriter);
                paintRect(printMode, p, r, mag);
                }
          else if (ext == "svg") {
                // note that clipping is not implemented
                // (as of 4.8)
                SvgGenerator printer;
                printer.setFileName(fn);
                printer.setTitle(_score->title());
                printer.setSize(QSize(w, h));
                printer.setViewBox(QRect(0, 0, w, h));
                MScore::pixelRatio = DPI / printer.logicalDpiX();
                QPainter p(&printer);
                MScore::pdfPrinting = true;
                paintRect(printMode, p, r, mag);
                MScore::pdfPrinting = false;
                }
          else if (ext == "png") {
                QImage::Format f = QImage::Format_ARGB32_Premultiplied;
                QImage printer(w, h, f);
                printer.setDotsPerMeterX(lrint((convDpi * 1000) / INCH));
                printer.setDotsPerMeterY(lrint((convDpi * 1000) / INCH));
                printer.fill(transparent ? 0 : 0xffffffff);
                MScore::pixelRatio = 1.0 / mag;
                QPainter p(&printer);
                paintRect(printMode, p, r, mag);
                printer.save(fn, "png");
                }
          else
                qDebug("unknown extension <%s>", qPrintable(ext));
          MScore::pixelRatio = pr;
          return true;
          }

    //---------------------------------------------------------
    //   paintRect
    //---------------------------------------------------------

    void ScoreView::paintRect(bool printMode, QPainter& p, const QRectF& r, double mag)
          {
          p.scale(mag, mag);
          p.translate(-r.topLeft());
          p.setRenderHint(QPainter::Antialiasing, true);
          p.setRenderHint(QPainter::TextAntialiasing, true);

          score()->setPrinting(printMode);

          foreach (Page* page, _score->pages()) {
                // QRectF pr(page->abbox());
                QRectF pr(page->canvasBoundingRect());
                if (pr.right() < r.left())
                      continue;
                if (pr.left() > r.right())
                      break;
                p.translate(page->pos());
                QList<Element*> ell = page->items(r.translated(-page->pos()));
                qStableSort(ell.begin(), ell.end(), elementLessThan);
                drawElements(p, ell);
                p.translate(-page->pos());
                }

          score()->setPrinting(false);
          p.end();
          }

    //---------------------------------------------------------
    //   fotoDragDrop
    //---------------------------------------------------------

    void ScoreView::fotoDragDrop(QMouseEvent*)
          {
          bool printMode   = true;
          QRectF r(_foto->bbox());

          QTemporaryFile tf(QDir::tempPath() + QString("/imgXXXXXX.svg"));
          tf.setAutoRemove(false);
          tf.open();
          tf.close();
          qDebug("Temp File <%s>", qPrintable(tf.fileName()));

    //      QString fn = "/home/ws/mops.eps";
          QString fn = tf.fileName();

          int w = lrint(r.width());
          int h = lrint(r.height());
          SvgGenerator printer;
          printer.setFileName(fn);
          printer.setTitle(_score->title());
          printer.setSize(QSize(w, h));
          printer.setViewBox(QRect(0, 0, w, h));
          QPainter p(&printer);
          MScore::pdfPrinting = true;
          paintRect(printMode, p, r, 1);
          MScore::pdfPrinting = false;

          QDrag* drag = new QDrag(this);
          QMimeData* mimeData = new QMimeData;

          QUrl url = QUrl::fromLocalFile(fn);
          QList<QUrl> ul;
          ul.append(url);
          mimeData->setUrls(ul);

          drag->setMimeData(mimeData);
          drag->start(Qt::CopyAction);
          }
    }

↑ V547 Expression 'transparent' is always false.