<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: unmovss.cxx,v $
 *
 *  $Revision: 1.7 $
 *
 *  last change: $Author: rt $ $Date: 2008-03-12 11:41:25 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sd.hxx"

#include "unmovss.hxx"
#include "DrawDocShell.hxx"
#include "drawdoc.hxx"
#include "stlsheet.hxx"
#include "stlpool.hxx"

SdMoveStyleSheetsUndoAction::SdMoveStyleSheetsUndoAction( SdDrawDocument* pTheDoc, SdStyleSheetVector& rTheStyles, bool bInserted)
: SdUndoAction(pTheDoc)
, mbMySheets( !bInserted )
{
    maStyles.swap( rTheStyles );

    maListOfChildLists.resize( maStyles.size() );
    // Liste mit den Listen der StyleSheet-Kinder erstellen
    std::size_t i = 0;
    for(SdStyleSheetVector::iterator iter = maStyles.begin(); iter != maStyles.end(); iter++ )
    {
        maListOfChildLists[i++] = SdStyleSheetPool::CreateChildList( (*iter).get() );
    }
}

/*************************************************************************
|*
|* Undo()
|*
\************************************************************************/

void SdMoveStyleSheetsUndoAction::Undo()
{
    SfxStyleSheetBasePool* pPool  = mpDoc->GetStyleSheetPool();

    if (mbMySheets)
    {
        // the styles have to be inserted in the pool

        // first insert all styles to the pool
        for(SdStyleSheetVector::iterator iter = maStyles.begin(); iter != maStyles.end(); iter++ )
        {
            pPool->Insert((*iter).get());
        }

        // now assign the childs again
        std::vector< SdStyleSheetVector >::iterator childlistiter( maListOfChildLists.begin() );
        for(SdStyleSheetVector::iterator iter = maStyles.begin(); iter != maStyles.end(); iter++, childlistiter++ )
        {
            String aParent((*iter)->GetName());
            for( SdStyleSheetVector::iterator childiter = (*childlistiter).begin(); childiter != (*childlistiter).end(); childiter++ )
            {
                (*childiter)->SetParent(aParent);
            }
        }
    }
    else
    {
        // remove the styles again from the pool
        for(SdStyleSheetVector::iterator iter = maStyles.begin(); iter != maStyles.end(); iter++ )
        {
            pPool->Remove((*iter).get());
        }
    }
    mbMySheets = !mbMySheets;
}

void SdMoveStyleSheetsUndoAction::Redo()
{
    Undo();
}

SdMoveStyleSheetsUndoAction::~SdMoveStyleSheetsUndoAction()
{
}

String SdMoveStyleSheetsUndoAction::GetComment() const
{
    return String();
}

<commit_msg>INTEGRATION: CWS changefileheader (1.7.16); FILE MERGED 2008/03/31 13:58:07 rt 1.7.16.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: unmovss.cxx,v $
 * $Revision: 1.8 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sd.hxx"

#include "unmovss.hxx"
#include "DrawDocShell.hxx"
#include "drawdoc.hxx"
#include "stlsheet.hxx"
#include "stlpool.hxx"

SdMoveStyleSheetsUndoAction::SdMoveStyleSheetsUndoAction( SdDrawDocument* pTheDoc, SdStyleSheetVector& rTheStyles, bool bInserted)
: SdUndoAction(pTheDoc)
, mbMySheets( !bInserted )
{
    maStyles.swap( rTheStyles );

    maListOfChildLists.resize( maStyles.size() );
    // Liste mit den Listen der StyleSheet-Kinder erstellen
    std::size_t i = 0;
    for(SdStyleSheetVector::iterator iter = maStyles.begin(); iter != maStyles.end(); iter++ )
    {
        maListOfChildLists[i++] = SdStyleSheetPool::CreateChildList( (*iter).get() );
    }
}

/*************************************************************************
|*
|* Undo()
|*
\************************************************************************/

void SdMoveStyleSheetsUndoAction::Undo()
{
    SfxStyleSheetBasePool* pPool  = mpDoc->GetStyleSheetPool();

    if (mbMySheets)
    {
        // the styles have to be inserted in the pool

        // first insert all styles to the pool
        for(SdStyleSheetVector::iterator iter = maStyles.begin(); iter != maStyles.end(); iter++ )
        {
            pPool->Insert((*iter).get());
        }

        // now assign the childs again
        std::vector< SdStyleSheetVector >::iterator childlistiter( maListOfChildLists.begin() );
        for(SdStyleSheetVector::iterator iter = maStyles.begin(); iter != maStyles.end(); iter++, childlistiter++ )
        {
            String aParent((*iter)->GetName());
            for( SdStyleSheetVector::iterator childiter = (*childlistiter).begin(); childiter != (*childlistiter).end(); childiter++ )
            {
                (*childiter)->SetParent(aParent);
            }
        }
    }
    else
    {
        // remove the styles again from the pool
        for(SdStyleSheetVector::iterator iter = maStyles.begin(); iter != maStyles.end(); iter++ )
        {
            pPool->Remove((*iter).get());
        }
    }
    mbMySheets = !mbMySheets;
}

void SdMoveStyleSheetsUndoAction::Redo()
{
    Undo();
}

SdMoveStyleSheetsUndoAction::~SdMoveStyleSheetsUndoAction()
{
}

String SdMoveStyleSheetsUndoAction::GetComment() const
{
    return String();
}

<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: fuconbez.hxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: aw $ $Date: 2002-02-15 17:02:42 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _SD_FUCONBEZ_HXX
#define _SD_FUCONBEZ_HXX

#ifndef _SD_FUCONSTR_HXX
#include "fuconstr.hxx"
#endif

class SdDrawViewShell;
class SdWindow;
class SdDrawView;
class SdDrawDocument;

/*************************************************************************
|*
|* Basisklasse fuer alle Funktionen
|*
\************************************************************************/

class FuConstBezPoly : public FuConstruct
{
 protected:
    USHORT      nEditMode;

 public:
    TYPEINFO();

    FuConstBezPoly(SdViewShell* pViewSh, SdWindow* pWin, SdView* pView,
                   SdDrawDocument* pDoc, SfxRequest& rReq);

    virtual ~FuConstBezPoly();
                                       // Mouse- & Key-Events
    virtual BOOL KeyInput(const KeyEvent& rKEvt);
    virtual BOOL MouseMove(const MouseEvent& rMEvt);
    virtual BOOL MouseButtonUp(const MouseEvent& rMEvt);
    virtual BOOL MouseButtonDown(const MouseEvent& rMEvt);

    virtual void Activate();           // Function aktivieren
    virtual void Deactivate();         // Function deaktivieren

    virtual void SelectionHasChanged();

    void    SetEditMode(USHORT nMode);
    USHORT  GetEditMode() { return nEditMode; }

    // #97016#
    virtual SdrObject* CreateDefaultObject(const sal_uInt16 nID, const Rectangle& rRectangle);
};

#endif      // _FUCONBEZ_HXX

<commit_msg>INTEGRATION: CWS impress1 (1.2.226); FILE MERGED 2003/09/16 13:35:50 af 1.2.226.1: #111996# Introduction of namespace sd. Use of sub-shells.<commit_after>/*************************************************************************
 *
 *  $RCSfile: fuconbez.hxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: obo $ $Date: 2004-01-20 11:56:47 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef SD_FU_CONSTRUCT_BEZIER_HXX
#define SD_FU_CONSTRUCT_BEZIER_HXX

#ifndef SD_FU_CONSTRUCT_HXX
#include "fuconstr.hxx"
#endif

class SdDrawDocument;

namespace sd {

class DrawView;
class DrawViewShell;
class Window;

class FuConstructBezierPolygon
    : public FuConstruct
{
public:
    TYPEINFO();

    FuConstructBezierPolygon (
        ViewShell* pViewSh,
        ::sd::Window* pWin,
        ::sd::View* pView,
        SdDrawDocument* pDoc,
        SfxRequest& rReq);
    virtual ~FuConstructBezierPolygon (void);

    // Mouse- & Key-Events
    virtual BOOL KeyInput(const KeyEvent& rKEvt);
    virtual BOOL MouseMove(const MouseEvent& rMEvt);
    virtual BOOL MouseButtonUp(const MouseEvent& rMEvt);
    virtual BOOL MouseButtonDown(const MouseEvent& rMEvt);

    virtual void Activate();           // Function aktivieren
    virtual void Deactivate();         // Function deaktivieren

    virtual void SelectionHasChanged();

    void    SetEditMode(USHORT nMode);
    USHORT  GetEditMode() { return nEditMode; }

    // #97016#
    virtual SdrObject* CreateDefaultObject(const sal_uInt16 nID, const Rectangle& rRectangle);

protected:
    USHORT      nEditMode;
};

} // end of namespace sd

#endif

<|endoftext|>


<commit_before>#include "selfdrive/ui/qt/onroad.h"

#include <iostream>

#include "selfdrive/common/swaglog.h"
#include "selfdrive/common/timing.h"
#include "selfdrive/ui/paint.h"
#include "selfdrive/ui/qt/util.h"

#ifdef ENABLE_MAPS
#include "selfdrive/ui/qt/maps/map.h"
#endif

OnroadWindow::OnroadWindow(QWidget *parent) : QWidget(parent) {
  main_layout = new QStackedLayout(this);
  main_layout->setStackingMode(QStackedLayout::StackAll);

  // old UI on bottom
  nvg = new NvgWindow(this);
  QObject::connect(this, &OnroadWindow::update, nvg, &NvgWindow::update);

  QWidget * split_wrapper = new QWidget;
  split = new QHBoxLayout(split_wrapper);
  split->setContentsMargins(0, 0, 0, 0);
  split->setSpacing(0);
  split->addWidget(nvg);

  main_layout->addWidget(split_wrapper);

  alerts = new OnroadAlerts(this);
  alerts->setAttribute(Qt::WA_TransparentForMouseEvents, true);
  QObject::connect(this, &OnroadWindow::update, alerts, &OnroadAlerts::updateState);
  QObject::connect(this, &OnroadWindow::offroadTransitionSignal, alerts, &OnroadAlerts::offroadTransition);
  QObject::connect(this, &OnroadWindow::offroadTransitionSignal, this, &OnroadWindow::offroadTransition);
  main_layout->addWidget(alerts);

  // setup stacking order
  alerts->raise();

  setAttribute(Qt::WA_OpaquePaintEvent);
}

void OnroadWindow::offroadTransition(bool offroad) {
#ifdef ENABLE_MAPS
  if (!offroad) {
    QString token = QString::fromStdString(Params().get("MapboxToken"));
    if (map == nullptr && !token.isEmpty()) {
      QMapboxGLSettings settings;
      if (!Hardware::PC()) {
        settings.setCacheDatabasePath("/data/mbgl-cache.db");
      }
      settings.setCacheDatabaseMaximumSize(20 * 1024 * 1024);
      settings.setAccessToken(token.trimmed());

      MapWindow * m = new MapWindow(settings);
      QObject::connect(this, &OnroadWindow::offroadTransitionSignal, m, &MapWindow::offroadTransition);
      split->addWidget(m);

      map = m;
    }

  }
#endif
}

// ***** onroad widgets *****

OnroadAlerts::OnroadAlerts(QWidget *parent) : QWidget(parent) {
  for (auto &kv : sound_map) {
    auto path = QUrl::fromLocalFile(kv.second.first);
    sounds[kv.first].setSource(path);
  }
}

void OnroadAlerts::updateState(const UIState &s) {
  SubMaster &sm = *(s.sm);
  if (sm.updated("carState")) {
    // scale volume with speed
    volume = util::map_val(sm["carState"].getCarState().getVEgo(), 0.f, 20.f,
                           Hardware::MIN_VOLUME, Hardware::MAX_VOLUME);
  }
  if (sm["deviceState"].getDeviceState().getStarted()) {
    if (sm.updated("controlsState")) {
      const cereal::ControlsState::Reader &cs = sm["controlsState"].getControlsState();
      updateAlert(QString::fromStdString(cs.getAlertText1()), QString::fromStdString(cs.getAlertText2()),
                  cs.getAlertBlinkingRate(), cs.getAlertType(), cs.getAlertSize(), cs.getAlertSound());
    } else if ((sm.frame - s.scene.started_frame) > 10 * UI_FREQ) {
      // Handle controls timeout
      if (sm.rcv_frame("controlsState") < s.scene.started_frame) {
        // car is started, but controlsState hasn't been seen at all
        updateAlert("openpilot Unavailable", "Waiting for controls to start", 0,
                    "controlsWaiting", cereal::ControlsState::AlertSize::MID, AudibleAlert::NONE);
      } else if ((sm.frame - sm.rcv_frame("controlsState")) > 5 * UI_FREQ) {
        // car is started, but controls is lagging or died
        updateAlert("TAKE CONTROL IMMEDIATELY", "Controls Unresponsive", 0,
                    "controlsUnresponsive", cereal::ControlsState::AlertSize::FULL, AudibleAlert::CHIME_WARNING_REPEAT);

        // TODO: clean this up once Qt handles the border
        QUIState::ui_state.status = STATUS_ALERT;
      }
    }
  }

  // TODO: add blinking back if performant
  //float alpha = 0.375 * cos((millis_since_boot() / 1000) * 2 * M_PI * blinking_rate) + 0.625;
  bg = bg_colors[s.status];
}

void OnroadAlerts::offroadTransition(bool offroad) {
  updateAlert("", "", 0, "", cereal::ControlsState::AlertSize::NONE, AudibleAlert::NONE);
}

void OnroadAlerts::updateAlert(const QString &t1, const QString &t2, float blink_rate,
                               const std::string &type, cereal::ControlsState::AlertSize size, AudibleAlert sound) {
  if (alert_type.compare(type) == 0 && text1.compare(t1) == 0 && text2.compare(t2) == 0) {
    return;
  }

  stopSounds();
  if (sound != AudibleAlert::NONE) {
    playSound(sound);
  }

  text1 = t1;
  text2 = t2;
  alert_type = type;
  alert_size = size;
  blinking_rate = blink_rate;

  update();
}

void OnroadAlerts::playSound(AudibleAlert alert) {
  int loops = sound_map[alert].second ? QSoundEffect::Infinite : 0;
  sounds[alert].setLoopCount(loops);
  sounds[alert].setVolume(volume);
  sounds[alert].play();
}

void OnroadAlerts::stopSounds() {
  for (auto &kv : sounds) {
    // Only stop repeating sounds
    if (kv.second.loopsRemaining() == QSoundEffect::Infinite) {
      kv.second.stop();
    }
  }
}

void OnroadAlerts::paintEvent(QPaintEvent *event) {
  QPainter p(this);

  if (alert_size == cereal::ControlsState::AlertSize::NONE) {
    return;
  }
  static std::map<cereal::ControlsState::AlertSize, const int> alert_sizes = {
    {cereal::ControlsState::AlertSize::SMALL, 271},
    {cereal::ControlsState::AlertSize::MID, 420},
    {cereal::ControlsState::AlertSize::FULL, height()},
  };
  int h = alert_sizes[alert_size];
  QRect r = QRect(0, height() - h, width(), h);

  // draw background + gradient
  p.setPen(Qt::NoPen);
  p.setCompositionMode(QPainter::CompositionMode_SourceOver);

  p.setBrush(QBrush(bg));
  p.drawRect(r);

  QLinearGradient g(0, r.y(), 0, r.bottom());
  g.setColorAt(0, QColor::fromRgbF(0, 0, 0, 0.05));
  g.setColorAt(1, QColor::fromRgbF(0, 0, 0, 0.35));

  p.setCompositionMode(QPainter::CompositionMode_DestinationOver);
  p.setBrush(QBrush(g));
  p.fillRect(r, g);
  p.setCompositionMode(QPainter::CompositionMode_SourceOver);

  // remove bottom border
  r = QRect(0, height() - h, width(), h - 30);

  // text
  const QPoint c = r.center();
  p.setPen(QColor(0xff, 0xff, 0xff));
  p.setRenderHint(QPainter::TextAntialiasing);
  if (alert_size == cereal::ControlsState::AlertSize::SMALL) {
    configFont(p, "Open Sans", 74, "SemiBold");
    p.drawText(r, Qt::AlignCenter, text1);
  } else if (alert_size == cereal::ControlsState::AlertSize::MID) {
    configFont(p, "Open Sans", 88, "Bold");
    p.drawText(QRect(0, c.y() - 125, width(), 150), Qt::AlignHCenter | Qt::AlignTop, text1);
    configFont(p, "Open Sans", 66, "Regular");
    p.drawText(QRect(0, c.y() + 21, width(), 90), Qt::AlignHCenter, text2);
  } else if (alert_size == cereal::ControlsState::AlertSize::FULL) {
    bool l = text1.length() > 15;
    configFont(p, "Open Sans", l ? 132 : 177, "Bold");
    p.drawText(QRect(0, r.y() + (l ? 240 : 270), width(), 600), Qt::AlignHCenter | Qt::TextWordWrap, text1);
    configFont(p, "Open Sans", 88, "Regular");
    p.drawText(QRect(0, r.height() - (l ? 361 : 420), width(), 300), Qt::AlignHCenter | Qt::TextWordWrap, text2);
  }
}

NvgWindow::NvgWindow(QWidget *parent) : QOpenGLWidget(parent) {
  setAttribute(Qt::WA_OpaquePaintEvent);
}

NvgWindow::~NvgWindow() {
  makeCurrent();
  doneCurrent();
}

void NvgWindow::initializeGL() {
  initializeOpenGLFunctions();
  std::cout << "OpenGL version: " << glGetString(GL_VERSION) << std::endl;
  std::cout << "OpenGL vendor: " << glGetString(GL_VENDOR) << std::endl;
  std::cout << "OpenGL renderer: " << glGetString(GL_RENDERER) << std::endl;
  std::cout << "OpenGL language version: " << glGetString(GL_SHADING_LANGUAGE_VERSION) << std::endl;

  ui_nvg_init(&QUIState::ui_state);
  prev_draw_t = millis_since_boot();
}

void NvgWindow::update(const UIState &s) {
  // Connecting to visionIPC requires opengl to be current
  if (s.vipc_client->connected) {
    makeCurrent();
  }
  repaint();
}

void NvgWindow::resizeGL(int w, int h) {
  ui_resize(&QUIState::ui_state, w, h);
}

void NvgWindow::paintGL() {
  ui_draw(&QUIState::ui_state, width(), height());

  double cur_draw_t = millis_since_boot();
  double dt = cur_draw_t - prev_draw_t;
  if (dt > 66) {
    // warn on sub 15fps
    LOGW("slow frame time: %.2f", dt);
  }
  prev_draw_t = cur_draw_t;
}
<commit_msg>OnroadAlerts: construct QPainter only when needed (#21260)<commit_after>#include "selfdrive/ui/qt/onroad.h"

#include <iostream>

#include "selfdrive/common/swaglog.h"
#include "selfdrive/common/timing.h"
#include "selfdrive/ui/paint.h"
#include "selfdrive/ui/qt/util.h"

#ifdef ENABLE_MAPS
#include "selfdrive/ui/qt/maps/map.h"
#endif

OnroadWindow::OnroadWindow(QWidget *parent) : QWidget(parent) {
  main_layout = new QStackedLayout(this);
  main_layout->setStackingMode(QStackedLayout::StackAll);

  // old UI on bottom
  nvg = new NvgWindow(this);
  QObject::connect(this, &OnroadWindow::update, nvg, &NvgWindow::update);

  QWidget * split_wrapper = new QWidget;
  split = new QHBoxLayout(split_wrapper);
  split->setContentsMargins(0, 0, 0, 0);
  split->setSpacing(0);
  split->addWidget(nvg);

  main_layout->addWidget(split_wrapper);

  alerts = new OnroadAlerts(this);
  alerts->setAttribute(Qt::WA_TransparentForMouseEvents, true);
  QObject::connect(this, &OnroadWindow::update, alerts, &OnroadAlerts::updateState);
  QObject::connect(this, &OnroadWindow::offroadTransitionSignal, alerts, &OnroadAlerts::offroadTransition);
  QObject::connect(this, &OnroadWindow::offroadTransitionSignal, this, &OnroadWindow::offroadTransition);
  main_layout->addWidget(alerts);

  // setup stacking order
  alerts->raise();

  setAttribute(Qt::WA_OpaquePaintEvent);
}

void OnroadWindow::offroadTransition(bool offroad) {
#ifdef ENABLE_MAPS
  if (!offroad) {
    QString token = QString::fromStdString(Params().get("MapboxToken"));
    if (map == nullptr && !token.isEmpty()) {
      QMapboxGLSettings settings;
      if (!Hardware::PC()) {
        settings.setCacheDatabasePath("/data/mbgl-cache.db");
      }
      settings.setCacheDatabaseMaximumSize(20 * 1024 * 1024);
      settings.setAccessToken(token.trimmed());

      MapWindow * m = new MapWindow(settings);
      QObject::connect(this, &OnroadWindow::offroadTransitionSignal, m, &MapWindow::offroadTransition);
      split->addWidget(m);

      map = m;
    }

  }
#endif
}

// ***** onroad widgets *****

OnroadAlerts::OnroadAlerts(QWidget *parent) : QWidget(parent) {
  for (auto &kv : sound_map) {
    auto path = QUrl::fromLocalFile(kv.second.first);
    sounds[kv.first].setSource(path);
  }
}

void OnroadAlerts::updateState(const UIState &s) {
  SubMaster &sm = *(s.sm);
  if (sm.updated("carState")) {
    // scale volume with speed
    volume = util::map_val(sm["carState"].getCarState().getVEgo(), 0.f, 20.f,
                           Hardware::MIN_VOLUME, Hardware::MAX_VOLUME);
  }
  if (sm["deviceState"].getDeviceState().getStarted()) {
    if (sm.updated("controlsState")) {
      const cereal::ControlsState::Reader &cs = sm["controlsState"].getControlsState();
      updateAlert(QString::fromStdString(cs.getAlertText1()), QString::fromStdString(cs.getAlertText2()),
                  cs.getAlertBlinkingRate(), cs.getAlertType(), cs.getAlertSize(), cs.getAlertSound());
    } else if ((sm.frame - s.scene.started_frame) > 10 * UI_FREQ) {
      // Handle controls timeout
      if (sm.rcv_frame("controlsState") < s.scene.started_frame) {
        // car is started, but controlsState hasn't been seen at all
        updateAlert("openpilot Unavailable", "Waiting for controls to start", 0,
                    "controlsWaiting", cereal::ControlsState::AlertSize::MID, AudibleAlert::NONE);
      } else if ((sm.frame - sm.rcv_frame("controlsState")) > 5 * UI_FREQ) {
        // car is started, but controls is lagging or died
        updateAlert("TAKE CONTROL IMMEDIATELY", "Controls Unresponsive", 0,
                    "controlsUnresponsive", cereal::ControlsState::AlertSize::FULL, AudibleAlert::CHIME_WARNING_REPEAT);

        // TODO: clean this up once Qt handles the border
        QUIState::ui_state.status = STATUS_ALERT;
      }
    }
  }

  // TODO: add blinking back if performant
  //float alpha = 0.375 * cos((millis_since_boot() / 1000) * 2 * M_PI * blinking_rate) + 0.625;
  bg = bg_colors[s.status];
}

void OnroadAlerts::offroadTransition(bool offroad) {
  updateAlert("", "", 0, "", cereal::ControlsState::AlertSize::NONE, AudibleAlert::NONE);
}

void OnroadAlerts::updateAlert(const QString &t1, const QString &t2, float blink_rate,
                               const std::string &type, cereal::ControlsState::AlertSize size, AudibleAlert sound) {
  if (alert_type.compare(type) == 0 && text1.compare(t1) == 0 && text2.compare(t2) == 0) {
    return;
  }

  stopSounds();
  if (sound != AudibleAlert::NONE) {
    playSound(sound);
  }

  text1 = t1;
  text2 = t2;
  alert_type = type;
  alert_size = size;
  blinking_rate = blink_rate;

  update();
}

void OnroadAlerts::playSound(AudibleAlert alert) {
  int loops = sound_map[alert].second ? QSoundEffect::Infinite : 0;
  sounds[alert].setLoopCount(loops);
  sounds[alert].setVolume(volume);
  sounds[alert].play();
}

void OnroadAlerts::stopSounds() {
  for (auto &kv : sounds) {
    // Only stop repeating sounds
    if (kv.second.loopsRemaining() == QSoundEffect::Infinite) {
      kv.second.stop();
    }
  }
}

void OnroadAlerts::paintEvent(QPaintEvent *event) {
  if (alert_size == cereal::ControlsState::AlertSize::NONE) {
    return;
  }
  static std::map<cereal::ControlsState::AlertSize, const int> alert_sizes = {
    {cereal::ControlsState::AlertSize::SMALL, 271},
    {cereal::ControlsState::AlertSize::MID, 420},
    {cereal::ControlsState::AlertSize::FULL, height()},
  };
  int h = alert_sizes[alert_size];
  QRect r = QRect(0, height() - h, width(), h);

  QPainter p(this);

  // draw background + gradient
  p.setPen(Qt::NoPen);
  p.setCompositionMode(QPainter::CompositionMode_SourceOver);

  p.setBrush(QBrush(bg));
  p.drawRect(r);

  QLinearGradient g(0, r.y(), 0, r.bottom());
  g.setColorAt(0, QColor::fromRgbF(0, 0, 0, 0.05));
  g.setColorAt(1, QColor::fromRgbF(0, 0, 0, 0.35));

  p.setCompositionMode(QPainter::CompositionMode_DestinationOver);
  p.setBrush(QBrush(g));
  p.fillRect(r, g);
  p.setCompositionMode(QPainter::CompositionMode_SourceOver);

  // remove bottom border
  r = QRect(0, height() - h, width(), h - 30);

  // text
  const QPoint c = r.center();
  p.setPen(QColor(0xff, 0xff, 0xff));
  p.setRenderHint(QPainter::TextAntialiasing);
  if (alert_size == cereal::ControlsState::AlertSize::SMALL) {
    configFont(p, "Open Sans", 74, "SemiBold");
    p.drawText(r, Qt::AlignCenter, text1);
  } else if (alert_size == cereal::ControlsState::AlertSize::MID) {
    configFont(p, "Open Sans", 88, "Bold");
    p.drawText(QRect(0, c.y() - 125, width(), 150), Qt::AlignHCenter | Qt::AlignTop, text1);
    configFont(p, "Open Sans", 66, "Regular");
    p.drawText(QRect(0, c.y() + 21, width(), 90), Qt::AlignHCenter, text2);
  } else if (alert_size == cereal::ControlsState::AlertSize::FULL) {
    bool l = text1.length() > 15;
    configFont(p, "Open Sans", l ? 132 : 177, "Bold");
    p.drawText(QRect(0, r.y() + (l ? 240 : 270), width(), 600), Qt::AlignHCenter | Qt::TextWordWrap, text1);
    configFont(p, "Open Sans", 88, "Regular");
    p.drawText(QRect(0, r.height() - (l ? 361 : 420), width(), 300), Qt::AlignHCenter | Qt::TextWordWrap, text2);
  }
}

NvgWindow::NvgWindow(QWidget *parent) : QOpenGLWidget(parent) {
  setAttribute(Qt::WA_OpaquePaintEvent);
}

NvgWindow::~NvgWindow() {
  makeCurrent();
  doneCurrent();
}

void NvgWindow::initializeGL() {
  initializeOpenGLFunctions();
  std::cout << "OpenGL version: " << glGetString(GL_VERSION) << std::endl;
  std::cout << "OpenGL vendor: " << glGetString(GL_VENDOR) << std::endl;
  std::cout << "OpenGL renderer: " << glGetString(GL_RENDERER) << std::endl;
  std::cout << "OpenGL language version: " << glGetString(GL_SHADING_LANGUAGE_VERSION) << std::endl;

  ui_nvg_init(&QUIState::ui_state);
  prev_draw_t = millis_since_boot();
}

void NvgWindow::update(const UIState &s) {
  // Connecting to visionIPC requires opengl to be current
  if (s.vipc_client->connected) {
    makeCurrent();
  }
  repaint();
}

void NvgWindow::resizeGL(int w, int h) {
  ui_resize(&QUIState::ui_state, w, h);
}

void NvgWindow::paintGL() {
  ui_draw(&QUIState::ui_state, width(), height());

  double cur_draw_t = millis_since_boot();
  double dt = cur_draw_t - prev_draw_t;
  if (dt > 66) {
    // warn on sub 15fps
    LOGW("slow frame time: %.2f", dt);
  }
  prev_draw_t = cur_draw_t;
}
<|endoftext|>


<commit_before>#include <hdmarker/subpattern.hpp>
#include <ucalib/ucalib.hpp>
#include <cliini/cliini.hpp>

#include <opencv2/highgui.hpp>

#include <metamat/mat.hpp>
#include <ucalib/proxy.hpp>

#include <iostream>

using namespace cv;
using namespace cliini;
using namespace hdmarker;

cliini_opt opts[] = {
  {
    "help",
    0, //argcount
    0, //argcount
    CLIINI_NONE, //type
    0, //flags
    'h'
  },
  {
    "imgs",
    1, //argcount min
    CLIINI_ARGCOUNT_ANY, //argcount max
    CLIINI_STRING, //type
    0, //flags
    'i',
    NULL,
    "read imgs and detect calibration points with HDMarkers",
    "[file1] [file2] ..."
  },
  {
    "store",
    1, //argcount min
    1, //argcount max
    CLIINI_STRING, //type
    0, //flags
    's',
    NULL,
    "store detected calibration points",
    "<file>"
  },
  {
    "load",
    1, //argcount min
    1, //argcount max
    CLIINI_STRING, //type
    0, //flags
    'l',
    NULL,
    "load stored calibration points and execute calibration",
    "<file>"
  }
};

cliini_optgroup group = {
  opts,
  NULL,
  sizeof(opts)/sizeof(*opts),
  0,
  0
};

int main(int argc, const char *argv[])
{
  Marker::init();

  cliargs args(argc, argv, &group);

  std::vector<Corner> corners_rough;
  std::vector<Corner> corners;

  double unit_size = 39.94; //marker size in mm

  MetaMat::Mat_<float> proxy({2, 33, 25, args["imgs"].count()});
  MetaMat::Mat_<float> jacobian({2, 2, 33, 25, args["imgs"].count()});

  std::string img_f = args["imgs"].str(0);
  Mat ex_img = imread(img_f, CV_LOAD_IMAGE_GRAYSCALE);

  for(int i=0;i<args["imgs"].count();i++) {
    img_f = args["imgs"].str(i);

    std::vector<Point2f> ipoints_v;
    std::vector<Point3f> wpoints_v;

    if (boost::filesystem::exists(img_f+".pointcache.yaml")) {
      FileStorage fs(img_f+".pointcache.yaml", FileStorage::READ);
      fs["img_points"] >> ipoints_v;
      fs["world_points"] >> wpoints_v;

      printf("%d points\n", ipoints_v.size());
    }
    else {
      std::cout << img_f+".pointcache.yaml" << "does not exist!\n";
      Mat img = imread(img_f, CV_LOAD_IMAGE_GRAYSCALE);
      printf("detect img %s\n", args["imgs"].str(i).c_str());
      corners_rough.resize(0);
      Marker::detect(img, corners_rough, false, 0, 100, 3);
      Mat debug;
      corners.resize(0);
      double unit_size_res = unit_size;
      hdmarker_detect_subpattern(img, corners_rough, corners, 3, &unit_size_res, &debug, NULL, 0);
      imwrite((img_f+".detect.png").c_str(), debug);

      ipoints_v.resize(corners.size());
      wpoints_v.resize(corners.size());

      for(int ci=0;ci<corners.size();ci++) {
        ipoints_v[ci] = corners[ci].p;
        Point2f w_2d = unit_size_res*Point2f(corners[ci].id.x, corners[ci].id.y);
        wpoints_v[ci] = Point3f(w_2d.x, w_2d.y, 0);
      }

      std::cout << "write " << img_f+".pointcache.yaml" << "\n";
      FileStorage fs(img_f+".pointcache.yaml", FileStorage::WRITE);
      fs << "img_points" << ipoints_v;
      fs << "world_points" << wpoints_v;
    }

    if (boost::filesystem::exists(img_f+".proxycache.yaml")) {
      cv::Mat sub_proxy;
      cv::Mat sub_j;

      FileStorage fs(img_f+".proxycache.yaml", FileStorage::READ);
      fs["proxy"] >> sub_proxy;
      fs["jacobian"] >> sub_j;

      sub_proxy.copyTo(cvMat(proxy.bind(3, i)));
      sub_j.copyTo(cvMat(jacobian.bind(4, i)));
    }
    else {
      MetaMat::Mat_<float> sub_proxy = proxy.bind(3, i);
      MetaMat::Mat_<float> sub_j = jacobian.bind(4, i);
      ucalib::proxy_backwards_pers_poly_generate<0,0>(sub_proxy, ipoints_v, wpoints_v, ex_img.size(), 0, 0, &sub_j);

      FileStorage fs(img_f+".proxycache.yaml", FileStorage::WRITE);
      fs << "proxy" << cvMat(sub_proxy);
      fs << "jacobian" << cvMat(sub_j);
    }

  }

  ucalib::calibrate_rays(proxy, jacobian, ex_img.size(), MetaMat::DimSpec(-1), ucalib::LIVE | ucalib::SHOW_TARGET);

  //TODO calibration...

  return EXIT_SUCCESS;
}
<commit_msg>implement undistortion example<commit_after>#include <hdmarker/subpattern.hpp>
#include <ucalib/ucalib.hpp>
#include <cliini/cliini.hpp>

#include <opencv2/highgui.hpp>

#include <metamat/mat.hpp>
#include <ucalib/proxy.hpp>

#include <iostream>

using namespace cv;
using namespace cliini;
using namespace hdmarker;

cliini_opt opts[] = {
  {
    "help",
    0, //argcount
    0, //argcount
    CLIINI_NONE, //type
    0, //flags
    'h'
  },
  {
    "imgs",
    1, //argcount min
    CLIINI_ARGCOUNT_ANY, //argcount max
    CLIINI_STRING, //type
    0, //flags
    'i',
    NULL,
    "read imgs and detect calibration points with HDMarkers",
    "[file1] [file2] ..."
  },
  {
    "store",
    1, //argcount min
    1, //argcount max
    CLIINI_STRING, //type
    0, //flags
    's',
    NULL,
    "store calibration",
    "<file>"
  },
  {
    "load",
    1, //argcount min
    1, //argcount max
    CLIINI_STRING, //type
    0, //flags
    'l',
    NULL,
    "load calibration",
    "<file>"
  },
  {
    "undistort",
    1, //argcount min
    CLIINI_ARGCOUNT_ANY, //argcount max
    CLIINI_STRING, //type
    0, //flags
    'u',
    NULL,
    "undistort image with calibration model",
    "[file1] [file2] ..."
  },
  {
    "z",
    1, //argcount min
    1, //argcount max
    CLIINI_DOUBLE, //type
    0, //flags
    'z',
    NULL,
    "z distance for undistortion",
    "<depth>"
  }
};

cliini_optgroup group = {
  opts,
  NULL,
  sizeof(opts)/sizeof(*opts),
  0,
  0
};

std::string replace_all(std::string str, const std::string& search, const std::string& replace) {
    size_t pos = 0;
    while ((pos = str.find(search, pos)) != std::string::npos) {
         str.replace(pos, search.length(), replace);
         pos += replace.length();
    }
    return str;
}

void save_mat(boost::filesystem::path path, MetaMat::Mat m, FileStorage &fs)
{
  fs << replace_all(path.generic_string(),"/","_S_") << cvMat(m);
}

void save_str(boost::filesystem::path path, const char* str, FileStorage &fs)
{
  fs << replace_all(path.generic_string(),"/","_S_") << str;
}

MetaMat::Mat load_mat(boost::filesystem::path path, FileStorage &fs)
{
  cv::Mat m;
  fs[replace_all(path.generic_string(),"/","_S_")] >> m;
  return MetaMat::Mat(m);
}

const char *load_str(boost::filesystem::path path, FileStorage &fs)
{
  std::string str;
  fs[replace_all(path.generic_string(),"/","_S_")] >> str;
  return strdup(str.c_str());
}

int main(int argc, const char *argv[])
{
  Marker::init();

  cliargs args(argc, argv, &group);

  std::vector<Corner> corners_rough;
  std::vector<Corner> corners;

  double unit_size = 39.94; //marker size in mm

  ucalib::Calib *calib = NULL;

  if (args["imgs"].valid()) {
    MetaMat::Mat_<float> proxy({2, 33, 25, args["imgs"].count()});
    MetaMat::Mat_<float> jacobian({2, 2, 33, 25, args["imgs"].count()});

    std::string img_f = args["imgs"].str(0);
    Mat ex_img = imread(img_f, CV_LOAD_IMAGE_GRAYSCALE);

    for(int i=0;i<args["imgs"].count();i++) {
      img_f = args["imgs"].str(i);

      std::vector<Point2f> ipoints_v;
      std::vector<Point3f> wpoints_v;

      if (boost::filesystem::exists(img_f+".pointcache.yaml")) {
        FileStorage fs(img_f+".pointcache.yaml", FileStorage::READ);
        fs["img_points"] >> ipoints_v;
        fs["world_points"] >> wpoints_v;

        printf("%d points\n", ipoints_v.size());
      }
      else {
        std::cout << img_f+".pointcache.yaml" << "does not exist!\n";
        Mat img = imread(img_f, CV_LOAD_IMAGE_GRAYSCALE);
        printf("detect img %s\n", args["imgs"].str(i).c_str());
        corners_rough.resize(0);
        Marker::detect(img, corners_rough, false, 0, 100, 3);
        Mat debug;
        corners.resize(0);
        double unit_size_res = unit_size;
        hdmarker_detect_subpattern(img, corners_rough, corners, 3, &unit_size_res, &debug, NULL, 0);
        imwrite((img_f+".detect.png").c_str(), debug);

        ipoints_v.resize(corners.size());
        wpoints_v.resize(corners.size());

        for(int ci=0;ci<corners.size();ci++) {
          ipoints_v[ci] = corners[ci].p;
          Point2f w_2d = unit_size_res*Point2f(corners[ci].id.x, corners[ci].id.y);
          wpoints_v[ci] = Point3f(w_2d.x, w_2d.y, 0);
        }

        std::cout << "write " << img_f+".pointcache.yaml" << "\n";
        FileStorage fs(img_f+".pointcache.yaml", FileStorage::WRITE);
        fs << "img_points" << ipoints_v;
        fs << "world_points" << wpoints_v;
      }

      if (boost::filesystem::exists(img_f+".proxycache.yaml")) {
        cv::Mat sub_proxy;
        cv::Mat sub_j;

        FileStorage fs(img_f+".proxycache.yaml", FileStorage::READ);
        fs["proxy"] >> sub_proxy;
        fs["jacobian"] >> sub_j;

        sub_proxy.copyTo(cvMat(proxy.bind(3, i)));
        sub_j.copyTo(cvMat(jacobian.bind(4, i)));
      }
      else {
        MetaMat::Mat_<float> sub_proxy = proxy.bind(3, i);
        MetaMat::Mat_<float> sub_j = jacobian.bind(4, i);
        ucalib::proxy_backwards_pers_poly_generate<0,0>(sub_proxy, ipoints_v, wpoints_v, ex_img.size(), 0, 0, &sub_j);

        FileStorage fs(img_f+".proxycache.yaml", FileStorage::WRITE);
        fs << "proxy" << cvMat(sub_proxy);
        fs << "jacobian" << cvMat(sub_j);
      }

    }

    calib = ucalib::calibrate_rays(proxy, jacobian, ex_img.size(), MetaMat::DimSpec(-1), ucalib::LIVE | ucalib::SHOW_TARGET);

  }

  if (args["load"]) {
    FileStorage fs(args["load"].str(), FileStorage::READ);
    std::function<ucalib::Mat(ucalib::cpath)> _l_m = std::bind(load_mat,std::placeholders::_1, fs);
    std::function<const char*(ucalib::cpath)> _l_y = std::bind(load_str,std::placeholders::_1, fs);
    calib = ucalib::load(_l_m, _l_y);
  }

  if (args["store"]) {
    FileStorage fs(args["store"].str(), FileStorage::WRITE);
    std::function<void(ucalib::cpath,ucalib::Mat)> _s_m = std::bind(save_mat,std::placeholders::_1, std::placeholders::_2, fs);
    std::function<void(ucalib::cpath,const char*)> _s_y = std::bind(save_str,std::placeholders::_1, std::placeholders::_2, fs);
    calib->save(_s_m, _s_y);
  }

  if (calib && args["undistort"]) {
    double z = 1000;

    if (args["z"])
      z = args["z"];

    printf("z depth : %f\n", z);

    //FIXME should also work with empty idx!
    calib->set_ref_cam(calib->cam({0,0}));

    for(int i=0;i<args["undistort"].count();i++) {
      std::string img_f = args["undistort"].str(i);
      cv::Mat img = imread(img_f, CV_LOAD_IMAGE_GRAYSCALE);
      cv::Mat undist = imread(img_f, CV_LOAD_IMAGE_GRAYSCALE);
      calib->rectify(MetaMat::Mat(img), MetaMat::Mat(undist), {0}, z);
      imwrite(img_f+".undist.png", undist);
    }
  }

  return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>// Copyright (c) 2011-2013 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "bitcoinamountfield.h"

#include "qvaluecombobox.h"
#include "bitcoinunits.h"
#include "guiconstants.h"

#include <QHBoxLayout>
#include <QKeyEvent>
#include <QDoubleSpinBox>
#include <QApplication>
#include <qmath.h> // for qPow()

BitcoinAmountField::BitcoinAmountField(QWidget *parent):
        QWidget(parent), amount(0), currentUnit(-1)
{
    amount = new QDoubleSpinBox(this);
    amount->setLocale(QLocale::c());
    amount->setDecimals(8);
    amount->installEventFilter(this);
    amount->setMaximumWidth(170);
    amount->setSingleStep(0.001);

    QHBoxLayout *layout = new QHBoxLayout(this);
    layout->addWidget(amount);
    unit = new QValueComboBox(this);
    unit->setModel(new BitcoinUnits(this));
    layout->addWidget(unit);
    layout->addStretch(1);
    layout->setContentsMargins(0,0,0,0);

    setLayout(layout);

    setFocusPolicy(Qt::TabFocus);
    setFocusProxy(amount);

    // If one if the widgets changes, the combined content changes as well
    connect(amount, SIGNAL(valueChanged(QString)), this, SIGNAL(textChanged()));
    connect(unit, SIGNAL(currentIndexChanged(int)), this, SLOT(unitChanged(int)));

    // Set default based on configuration
    unitChanged(unit->currentIndex());
}

void BitcoinAmountField::setText(const QString &text)
{
    if (text.isEmpty())
        amount->clear();
    else
        amount->setValue(text.toDouble());
}

void BitcoinAmountField::clear()
{
    amount->clear();
    unit->setCurrentIndex(0);
}

bool BitcoinAmountField::validate()
{
    bool valid = true;
    if (amount->value() == 0.0)
        valid = false;
    if (valid && !BitcoinUnits::parse(currentUnit, text(), 0))
        valid = false;

    setValid(valid);

    return valid;
}

void BitcoinAmountField::setValid(bool valid)
{
    if (valid)
        amount->setStyleSheet("");
    else
        amount->setStyleSheet(STYLE_INVALID);
}

QString BitcoinAmountField::text() const
{
    if (amount->text().isEmpty())
        return QString();
    else
        return amount->text();
}

bool BitcoinAmountField::eventFilter(QObject *object, QEvent *event)
{
    if (event->type() == QEvent::FocusIn)
    {
        // Clear invalid flag on focus
        setValid(true);
    }
    else if (event->type() == QEvent::KeyPress || event->type() == QEvent::KeyRelease)
    {
        QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
        if (keyEvent->key() == Qt::Key_Comma)
        {
            // Translate a comma into a period
            QKeyEvent periodKeyEvent(event->type(), Qt::Key_Period, keyEvent->modifiers(), ".", keyEvent->isAutoRepeat(), keyEvent->count());
            QApplication::sendEvent(object, &periodKeyEvent);
            return true;
        }
    }
    return QWidget::eventFilter(object, event);
}

QWidget *BitcoinAmountField::setupTabChain(QWidget *prev)
{
    QWidget::setTabOrder(prev, amount);
    return amount;
}

qint64 BitcoinAmountField::value(bool *valid_out) const
{
    qint64 val_out = 0;
    bool valid = BitcoinUnits::parse(currentUnit, text(), &val_out);
    if(valid_out)
    {
        *valid_out = valid;
    }
    return val_out;
}

void BitcoinAmountField::setValue(qint64 value)
{
    setText(BitcoinUnits::format(currentUnit, value));
}

void BitcoinAmountField::unitChanged(int idx)
{
    // Use description tooltip for current unit for the combobox
    unit->setToolTip(unit->itemData(idx, Qt::ToolTipRole).toString());

    // Determine new unit ID
    int newUnit = unit->itemData(idx, BitcoinUnits::UnitRole).toInt();

    // Parse current value and convert to new unit
    bool valid = false;
    qint64 currentValue = value(&valid);

    currentUnit = newUnit;

    // Set max length after retrieving the value, to prevent truncation
    amount->setDecimals(BitcoinUnits::decimals(currentUnit));
    amount->setMaximum(qPow(10, BitcoinUnits::amountDigits(currentUnit)) - qPow(10, -amount->decimals()));

    if(currentUnit == BitcoinUnits::uBTC)
        amount->setSingleStep(0.01);
    else
        amount->setSingleStep(0.001);

    if(valid)
    {
        // If value was valid, re-place it in the widget with the new unit
        setValue(currentValue);
    }
    else
    {
        // If current value is invalid, just clear field
        setText("");
    }
    setValid(true);
}

void BitcoinAmountField::setDisplayUnit(int newUnit)
{
    unit->setValue(newUnit);
}
<commit_msg>Fix bug in Qt wallet when parsing large amount in Reddcoin URI.<commit_after>// Copyright (c) 2011-2013 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "bitcoinamountfield.h"

#include "util.h"
#include "qvaluecombobox.h"
#include "bitcoinunits.h"
#include "guiconstants.h"

#include <QHBoxLayout>
#include <QKeyEvent>
#include <QDoubleSpinBox>
#include <QApplication>
#include <qmath.h> // for qPow()

BitcoinAmountField::BitcoinAmountField(QWidget *parent):
        QWidget(parent), amount(0), currentUnit(-1)
{
    amount = new QDoubleSpinBox(this);
    amount->setLocale(QLocale::c());
    amount->setDecimals(8);
    amount->installEventFilter(this);
    amount->setMaximumWidth(170);
    amount->setSingleStep(0.001);

    QHBoxLayout *layout = new QHBoxLayout(this);
    layout->addWidget(amount);
    unit = new QValueComboBox(this);
    unit->setModel(new BitcoinUnits(this));
    layout->addWidget(unit);
    layout->addStretch(1);
    layout->setContentsMargins(0,0,0,0);

    setLayout(layout);

    setFocusPolicy(Qt::TabFocus);
    setFocusProxy(amount);

    // If one if the widgets changes, the combined content changes as well
    connect(amount, SIGNAL(valueChanged(QString)), this, SIGNAL(textChanged()));
    connect(unit, SIGNAL(currentIndexChanged(int)), this, SLOT(unitChanged(int)));

    // Set default based on configuration
    unitChanged(unit->currentIndex());
}

void BitcoinAmountField::setText(const QString &text)
{
    if (text.isEmpty())
    {
        amount->clear();
    }
    else
    {
        // remove the space delimiter for every 3 digits
        QString value = text;
        amount->setValue(value.replace(" ", "").toDouble());
    }
}

void BitcoinAmountField::clear()
{
    amount->clear();
    unit->setCurrentIndex(0);
}

bool BitcoinAmountField::validate()
{
    bool valid = true;
    if (amount->value() == 0.0)
        valid = false;
    if (valid && !BitcoinUnits::parse(currentUnit, text(), 0))
        valid = false;

    setValid(valid);

    return valid;
}

void BitcoinAmountField::setValid(bool valid)
{
    if (valid)
        amount->setStyleSheet("");
    else
        amount->setStyleSheet(STYLE_INVALID);
}

QString BitcoinAmountField::text() const
{
    if (amount->text().isEmpty())
        return QString();
    else
        return amount->text();
}

bool BitcoinAmountField::eventFilter(QObject *object, QEvent *event)
{
    if (event->type() == QEvent::FocusIn)
    {
        // Clear invalid flag on focus
        setValid(true);
    }
    else if (event->type() == QEvent::KeyPress || event->type() == QEvent::KeyRelease)
    {
        QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
        if (keyEvent->key() == Qt::Key_Comma)
        {
            // Translate a comma into a period
            QKeyEvent periodKeyEvent(event->type(), Qt::Key_Period, keyEvent->modifiers(), ".", keyEvent->isAutoRepeat(), keyEvent->count());
            QApplication::sendEvent(object, &periodKeyEvent);
            return true;
        }
    }
    return QWidget::eventFilter(object, event);
}

QWidget *BitcoinAmountField::setupTabChain(QWidget *prev)
{
    QWidget::setTabOrder(prev, amount);
    return amount;
}

qint64 BitcoinAmountField::value(bool *valid_out) const
{
    qint64 val_out = 0;
    bool valid = BitcoinUnits::parse(currentUnit, text(), &val_out);
    if(valid_out)
    {
        *valid_out = valid;
    }
    return val_out;
}

void BitcoinAmountField::setValue(qint64 value)
{
    setText(BitcoinUnits::format(currentUnit, value));
}

void BitcoinAmountField::unitChanged(int idx)
{
    // Use description tooltip for current unit for the combobox
    unit->setToolTip(unit->itemData(idx, Qt::ToolTipRole).toString());

    // Determine new unit ID
    int newUnit = unit->itemData(idx, BitcoinUnits::UnitRole).toInt();

    // Parse current value and convert to new unit
    bool valid = false;
    qint64 currentValue = value(&valid);

    currentUnit = newUnit;

    // Set max length after retrieving the value, to prevent truncation
    amount->setDecimals(BitcoinUnits::decimals(currentUnit));
    amount->setMaximum(qPow(10, BitcoinUnits::amountDigits(currentUnit)) - qPow(10, -amount->decimals()));

    if(currentUnit == BitcoinUnits::uBTC)
        amount->setSingleStep(0.01);
    else
        amount->setSingleStep(0.001);

    if(valid)
    {
        // If value was valid, re-place it in the widget with the new unit
        setValue(currentValue);
    }
    else
    {
        // If current value is invalid, just clear field
        setText("");
    }
    setValid(true);
}

void BitcoinAmountField::setDisplayUnit(int newUnit)
{
    unit->setValue(newUnit);
}
<|endoftext|>


<commit_before>// Copyright (c) 2011-2015 The Bitcoin Core developers
// Copyright (c) 2015-2017 The Bitcoin Unlimited developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "receivecoinsdialog.h"
#include "ui_receivecoinsdialog.h"

#include "addressbookpage.h"
#include "addresstablemodel.h"
#include "bitcoinunits.h"
#include "guiutil.h"
#include "optionsmodel.h"
#include "platformstyle.h"
#include "receivefreezedialog.h"
#include "receiverequestdialog.h"
#include "recentrequeststablemodel.h"
#include "unlimited.h"

ReceiveFreezeDialog *freezeDialog;

#include <QAction>
#include <QCheckBox>
#include <QCursor>
#include <QItemSelection>
#include <QMessageBox>
#include <QScrollBar>
#include <QTextDocument>

ReceiveCoinsDialog::ReceiveCoinsDialog(const PlatformStyle *platformStyle, QWidget *parent)
    : QDialog(parent), ui(new Ui::ReceiveCoinsDialog), model(0), platformStyle(platformStyle)
{
    ui->setupUi(this);

    if (!platformStyle->getImagesOnButtons())
    {
        ui->clearButton->setIcon(QIcon());
        ui->receiveButton->setIcon(QIcon());
        ui->showRequestButton->setIcon(QIcon());
        ui->removeRequestButton->setIcon(QIcon());
    }
    else
    {
        ui->clearButton->setIcon(platformStyle->SingleColorIcon(":/icons/remove"));
        ui->receiveButton->setIcon(platformStyle->SingleColorIcon(":/icons/receiving_addresses"));
        ui->showRequestButton->setIcon(platformStyle->SingleColorIcon(":/icons/edit"));
        ui->removeRequestButton->setIcon(platformStyle->SingleColorIcon(":/icons/remove"));
    }

    // context menu actions
    QAction *copyAddressAction = new QAction(tr("Copy address"), this);
    QAction *copyLabelAction = new QAction(tr("Copy label"), this);
    QAction *copyMessageAction = new QAction(tr("Copy message"), this);
    QAction *copyAmountAction = new QAction(tr("Copy amount"), this);

    // context menu
    contextMenu = new QMenu();
    contextMenu->addAction(copyAddressAction);
    contextMenu->addAction(copyLabelAction);
    contextMenu->addAction(copyMessageAction);
    contextMenu->addAction(copyAmountAction);

    // context menu signals
    connect(ui->recentRequestsView, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(showMenu(QPoint)));
    connect(copyAddressAction, SIGNAL(triggered()), this, SLOT(copyAddress()));
    connect(copyLabelAction, SIGNAL(triggered()), this, SLOT(copyLabel()));
    connect(copyMessageAction, SIGNAL(triggered()), this, SLOT(copyMessage()));
    connect(copyAmountAction, SIGNAL(triggered()), this, SLOT(copyAmount()));

    connect(ui->clearButton, SIGNAL(clicked()), this, SLOT(clear()));

    // initialize freeze
    nFreezeLockTime = CScriptNum(0);
}

void ReceiveCoinsDialog::setModel(WalletModel *model)
{
    this->model = model;

    if (model && model->getOptionsModel())
    {
        model->getRecentRequestsTableModel()->sort(RecentRequestsTableModel::Date, Qt::DescendingOrder);
        connect(model->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(updateDisplayUnit()));
        updateDisplayUnit();

        QTableView *tableView = ui->recentRequestsView;

        tableView->verticalHeader()->hide();
        tableView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
        tableView->setModel(model->getRecentRequestsTableModel());
        tableView->setAlternatingRowColors(true);
        tableView->setSelectionBehavior(QAbstractItemView::SelectRows);
        tableView->setSelectionMode(QAbstractItemView::ContiguousSelection);
        tableView->setColumnWidth(RecentRequestsTableModel::Date, DATE_COLUMN_WIDTH);
        tableView->setColumnWidth(RecentRequestsTableModel::Label, LABEL_COLUMN_WIDTH);

        connect(tableView->selectionModel(), SIGNAL(selectionChanged(QItemSelection, QItemSelection)), this,
            SLOT(recentRequestsView_selectionChanged(QItemSelection, QItemSelection)));
        // Last 2 columns are set by the columnResizingFixer, when the table geometry is ready.
        columnResizingFixer =
            new GUIUtil::TableViewLastColumnResizingFixer(tableView, AMOUNT_MINIMUM_COLUMN_WIDTH, DATE_COLUMN_WIDTH);
    }
}

ReceiveCoinsDialog::~ReceiveCoinsDialog() { delete ui; }
void ReceiveCoinsDialog::clear()
{
    ui->reqAmount->clear();
    ui->reqLabel->setText("");
    ui->reqMessage->setText("");
    ui->reuseAddress->setChecked(false);
    ui->freezeCheck->setChecked(false);
    ui->freezeCheck->setText("Coin &Freeze");
    nFreezeLockTime = CScriptNum(0);
    freezeDialog = NULL;
    updateDisplayUnit();
}

void ReceiveCoinsDialog::reject() { clear(); }
void ReceiveCoinsDialog::accept() { clear(); }
void ReceiveCoinsDialog::updateDisplayUnit()
{
    if (model && model->getOptionsModel())
    {
        ui->reqAmount->setDisplayUnit(model->getOptionsModel()->getDisplayUnit());
    }
}

void ReceiveCoinsDialog::on_freezeDialog_hide()
{
    freezeDialog->getFreezeLockTime(nFreezeLockTime);

    if (nFreezeLockTime == 0)
    {
        // user cancelled freeze
        ui->freezeCheck->setChecked(false);
        ui->freezeCheck->setText("Coin Freeze");
    }
    else
    {
        // user selected freeze
        ui->freezeCheck->setChecked(true);

        QString freezeLabel;
        if (nFreezeLockTime.getint64() < LOCKTIME_THRESHOLD)

        {
            uint64_t height = GetBlockchainHeight();
            uint64_t freezeHeight = nFreezeLockTime.getint();
            uint64_t approxTimeMs =
                ((freezeHeight - height) * 10 * 60 * 1000) + QDateTime::currentDateTime().toMSecsSinceEpoch();

            freezeLabel = (QString)("block: ") + QString::number(freezeHeight) + (QString)(" (approximately: ") +
                          QDateTime::fromMSecsSinceEpoch(approxTimeMs).date().toString() + ")";
        }
        else
            freezeLabel =
                QDateTime::fromMSecsSinceEpoch(nFreezeLockTime.getint64() * 1000).toString("yyyy/MM/dd hh:mm");
        ui->freezeCheck->setText("Coin freeze until " + freezeLabel);
    }
}

void ReceiveCoinsDialog::on_freezeCheck_clicked()
{
    if (ui->freezeCheck->isChecked()) // If the user clicked on coin freeze, bring up the freeze dialog box
    {
        if (!freezeDialog)
        {
            freezeDialog = new ReceiveFreezeDialog(this);
            freezeDialog->setModel(model->getOptionsModel());
        }
        freezeDialog->show();
    }
    else // if the user unchecked, then hide the freeze dialog if its still showing
    {
        if (freezeDialog)
            freezeDialog->hide();
    }
}

void ReceiveCoinsDialog::on_receiveButton_clicked()
{
    if (!model || !model->getOptionsModel() || !model->getAddressTableModel() || !model->getRecentRequestsTableModel())
        return;

    QString address;
    QString label = ui->reqLabel->text();
    QString sFreezeLockTime = "";

    if (ui->reuseAddress->isChecked())
    {
        /* Choose existing receiving address */
        AddressBookPage dlg(platformStyle, AddressBookPage::ForSelection, AddressBookPage::ReceivingTab, this);
        dlg.setModel(model->getAddressTableModel());
        if (dlg.exec())
        {
            address = dlg.getReturnValue();
            if (label.isEmpty()) /* If no label provided, use the previously used label */
            {
                label = model->getAddressTableModel()->labelForAddress(address);
            }
        }
        else
        {
            return;
        }
    }
    else
    {
        /* Generate new receiving address and add to the address table */
        address = model->getAddressTableModel()->addRow(AddressTableModel::Receive, label, "", CScriptNum(0));

        // only use coin freeze if the freeze value is valid and the check box is still set
        if ((nFreezeLockTime > 0) && (ui->freezeCheck) && (ui->freezeCheck->isChecked()))
        {
            /* Generate the freeze redeemScript and add to the address table.
             * The address variable needs to show the freeze P2SH public key  */
            address = model->getAddressTableModel()->addRow(AddressTableModel::Receive, label, "", nFreezeLockTime);
            sFreezeLockTime = model->getAddressTableModel()->labelForFreeze(address);
        }
    }
    SendCoinsRecipient info(address, label, ui->reqAmount->value(), ui->reqMessage->text(), sFreezeLockTime, "");
    ReceiveRequestDialog *dialog = new ReceiveRequestDialog(this);
    dialog->setAttribute(Qt::WA_DeleteOnClose);
    dialog->setModel(model->getOptionsModel());
    dialog->setInfo(info);
    dialog->show();
    clear();

    /* Store request for later reference */
    model->getRecentRequestsTableModel()->addNewRequest(info);
}

void ReceiveCoinsDialog::on_recentRequestsView_doubleClicked(const QModelIndex &index)
{
    const RecentRequestsTableModel *submodel = model->getRecentRequestsTableModel();
    ReceiveRequestDialog *dialog = new ReceiveRequestDialog(this);
    dialog->setModel(model->getOptionsModel());
    dialog->setInfo(submodel->entry(index.row()).recipient);
    dialog->setAttribute(Qt::WA_DeleteOnClose);
    dialog->show();
}

void ReceiveCoinsDialog::recentRequestsView_selectionChanged(const QItemSelection &selected,
    const QItemSelection &deselected)
{
    // Enable Show/Remove buttons only if anything is selected.
    bool enable = !ui->recentRequestsView->selectionModel()->selectedRows().isEmpty();
    ui->showRequestButton->setEnabled(enable);
    ui->removeRequestButton->setEnabled(enable);
}

void ReceiveCoinsDialog::on_showRequestButton_clicked()
{
    if (!model || !model->getRecentRequestsTableModel() || !ui->recentRequestsView->selectionModel())
        return;
    QModelIndexList selection = ui->recentRequestsView->selectionModel()->selectedRows();

    Q_FOREACH (const QModelIndex &index, selection)
    {
        on_recentRequestsView_doubleClicked(index);
    }
}

void ReceiveCoinsDialog::on_removeRequestButton_clicked()
{
    if (!model || !model->getRecentRequestsTableModel() || !ui->recentRequestsView->selectionModel())
        return;
    QModelIndexList selection = ui->recentRequestsView->selectionModel()->selectedRows();
    if (selection.empty())
        return;
    // correct for selection mode ContiguousSelection
    QModelIndex firstIndex = selection.at(0);
    model->getRecentRequestsTableModel()->removeRows(firstIndex.row(), selection.length(), firstIndex.parent());
}

// We override the virtual resizeEvent of the QWidget to adjust tables column
// sizes as the tables width is proportional to the dialogs width.
void ReceiveCoinsDialog::resizeEvent(QResizeEvent *event)
{
    QWidget::resizeEvent(event);
    columnResizingFixer->stretchColumnWidth(RecentRequestsTableModel::Message);
}

void ReceiveCoinsDialog::keyPressEvent(QKeyEvent *event)
{
    if (event->key() == Qt::Key_Return)
    {
        // press return -> submit form
        if (ui->reqLabel->hasFocus() || ui->reqAmount->hasFocus() || ui->reqMessage->hasFocus())
        {
            event->ignore();
            on_receiveButton_clicked();
            return;
        }
    }

    this->QDialog::keyPressEvent(event);
}

// copy column of selected row to clipboard
void ReceiveCoinsDialog::copyColumnToClipboard(int column)
{
    if (!model || !model->getRecentRequestsTableModel() || !ui->recentRequestsView->selectionModel())
        return;
    QModelIndexList selection = ui->recentRequestsView->selectionModel()->selectedRows();
    if (selection.empty())
        return;
    // correct for selection mode ContiguousSelection
    QModelIndex firstIndex = selection.at(0);
    GUIUtil::setClipboard(model->getRecentRequestsTableModel()
                              ->data(firstIndex.child(firstIndex.row(), column), Qt::EditRole)
                              .toString());
}

// context menu
void ReceiveCoinsDialog::showMenu(const QPoint &point)
{
    if (!model || !model->getRecentRequestsTableModel() || !ui->recentRequestsView->selectionModel())
        return;
    QModelIndexList selection = ui->recentRequestsView->selectionModel()->selectedRows();
    if (selection.empty())
        return;
    contextMenu->exec(QCursor::pos());
}

// context menu action: copy address
void ReceiveCoinsDialog::copyAddress() { copyColumnToClipboard(RecentRequestsTableModel::Address); }
// context menu action: copy label
void ReceiveCoinsDialog::copyLabel() { copyColumnToClipboard(RecentRequestsTableModel::Label); }
// context menu action: copy message
void ReceiveCoinsDialog::copyMessage() { copyColumnToClipboard(RecentRequestsTableModel::Message); }
// context menu action: copy amount
void ReceiveCoinsDialog::copyAmount() { copyColumnToClipboard(RecentRequestsTableModel::Amount); }
<commit_msg>Bug Fix for Coin Freeze when making payment request (#875)<commit_after>// Copyright (c) 2011-2015 The Bitcoin Core developers
// Copyright (c) 2015-2017 The Bitcoin Unlimited developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "receivecoinsdialog.h"
#include "ui_receivecoinsdialog.h"

#include "addressbookpage.h"
#include "addresstablemodel.h"
#include "bitcoinunits.h"
#include "guiutil.h"
#include "optionsmodel.h"
#include "platformstyle.h"
#include "receivefreezedialog.h"
#include "receiverequestdialog.h"
#include "recentrequeststablemodel.h"
#include "unlimited.h"

ReceiveFreezeDialog *freezeDialog;

#include <QAction>
#include <QCheckBox>
#include <QCursor>
#include <QItemSelection>
#include <QMessageBox>
#include <QScrollBar>
#include <QTextDocument>

ReceiveCoinsDialog::ReceiveCoinsDialog(const PlatformStyle *platformStyle, QWidget *parent)
    : QDialog(parent), ui(new Ui::ReceiveCoinsDialog), model(0), platformStyle(platformStyle)
{
    ui->setupUi(this);

    if (!platformStyle->getImagesOnButtons())
    {
        ui->clearButton->setIcon(QIcon());
        ui->receiveButton->setIcon(QIcon());
        ui->showRequestButton->setIcon(QIcon());
        ui->removeRequestButton->setIcon(QIcon());
    }
    else
    {
        ui->clearButton->setIcon(platformStyle->SingleColorIcon(":/icons/remove"));
        ui->receiveButton->setIcon(platformStyle->SingleColorIcon(":/icons/receiving_addresses"));
        ui->showRequestButton->setIcon(platformStyle->SingleColorIcon(":/icons/edit"));
        ui->removeRequestButton->setIcon(platformStyle->SingleColorIcon(":/icons/remove"));
    }

    // context menu actions
    QAction *copyAddressAction = new QAction(tr("Copy address"), this);
    QAction *copyLabelAction = new QAction(tr("Copy label"), this);
    QAction *copyMessageAction = new QAction(tr("Copy message"), this);
    QAction *copyAmountAction = new QAction(tr("Copy amount"), this);

    // context menu
    contextMenu = new QMenu();
    contextMenu->addAction(copyAddressAction);
    contextMenu->addAction(copyLabelAction);
    contextMenu->addAction(copyMessageAction);
    contextMenu->addAction(copyAmountAction);

    // context menu signals
    connect(ui->recentRequestsView, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(showMenu(QPoint)));
    connect(copyAddressAction, SIGNAL(triggered()), this, SLOT(copyAddress()));
    connect(copyLabelAction, SIGNAL(triggered()), this, SLOT(copyLabel()));
    connect(copyMessageAction, SIGNAL(triggered()), this, SLOT(copyMessage()));
    connect(copyAmountAction, SIGNAL(triggered()), this, SLOT(copyAmount()));

    connect(ui->clearButton, SIGNAL(clicked()), this, SLOT(clear()));

    // initialize freeze
    nFreezeLockTime = CScriptNum(0);
}

void ReceiveCoinsDialog::setModel(WalletModel *model)
{
    this->model = model;

    if (model && model->getOptionsModel())
    {
        model->getRecentRequestsTableModel()->sort(RecentRequestsTableModel::Date, Qt::DescendingOrder);
        connect(model->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(updateDisplayUnit()));
        updateDisplayUnit();

        QTableView *tableView = ui->recentRequestsView;

        tableView->verticalHeader()->hide();
        tableView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
        tableView->setModel(model->getRecentRequestsTableModel());
        tableView->setAlternatingRowColors(true);
        tableView->setSelectionBehavior(QAbstractItemView::SelectRows);
        tableView->setSelectionMode(QAbstractItemView::ContiguousSelection);
        tableView->setColumnWidth(RecentRequestsTableModel::Date, DATE_COLUMN_WIDTH);
        tableView->setColumnWidth(RecentRequestsTableModel::Label, LABEL_COLUMN_WIDTH);

        connect(tableView->selectionModel(), SIGNAL(selectionChanged(QItemSelection, QItemSelection)), this,
            SLOT(recentRequestsView_selectionChanged(QItemSelection, QItemSelection)));
        // Last 2 columns are set by the columnResizingFixer, when the table geometry is ready.
        columnResizingFixer =
            new GUIUtil::TableViewLastColumnResizingFixer(tableView, AMOUNT_MINIMUM_COLUMN_WIDTH, DATE_COLUMN_WIDTH);
    }
}

ReceiveCoinsDialog::~ReceiveCoinsDialog() { delete ui; }
void ReceiveCoinsDialog::clear()
{
    ui->reqAmount->clear();
    ui->reqLabel->setText("");
    ui->reqMessage->setText("");
    ui->reuseAddress->setChecked(false);
    ui->freezeCheck->setChecked(false);
    ui->freezeCheck->setText("Coin &Freeze");
    nFreezeLockTime = CScriptNum(0);
    freezeDialog = NULL;
    updateDisplayUnit();
}

void ReceiveCoinsDialog::reject() { clear(); }
void ReceiveCoinsDialog::accept() { clear(); }
void ReceiveCoinsDialog::updateDisplayUnit()
{
    if (model && model->getOptionsModel())
    {
        ui->reqAmount->setDisplayUnit(model->getOptionsModel()->getDisplayUnit());
    }
}

void ReceiveCoinsDialog::on_freezeDialog_hide()
{
    freezeDialog->getFreezeLockTime(nFreezeLockTime);

    if (nFreezeLockTime == 0)
    {
        // user cancelled freeze
        ui->freezeCheck->setChecked(false);
        ui->freezeCheck->setText("Coin Freeze");
    }
    else
    {
        // user selected freeze
        ui->freezeCheck->setChecked(true);

        QString freezeLabel;
        if (nFreezeLockTime.getint64() < LOCKTIME_THRESHOLD)

        {
            uint64_t height = GetBlockchainHeight();
            uint64_t freezeHeight = nFreezeLockTime.getint();
            uint64_t approxTimeMs =
                ((freezeHeight - height) * 10 * 60 * 1000) + QDateTime::currentDateTime().toMSecsSinceEpoch();

            freezeLabel = (QString)("block: ") + QString::number(freezeHeight) + (QString)(" (approximately: ") +
                          QDateTime::fromMSecsSinceEpoch(approxTimeMs).date().toString() + ")";
        }
        else
            freezeLabel =
                QDateTime::fromMSecsSinceEpoch(nFreezeLockTime.getint64() * 1000).toString("yyyy/MM/dd hh:mm");
        ui->freezeCheck->setText("Coin freeze until " + freezeLabel);
    }
}

void ReceiveCoinsDialog::on_freezeCheck_clicked()
{
    if (ui->freezeCheck->isChecked()) // If the user clicked on coin freeze, bring up the freeze dialog box
    {
        if (!freezeDialog)
        {
            freezeDialog = new ReceiveFreezeDialog(this);
            freezeDialog->setModel(model->getOptionsModel());
        }
        freezeDialog->show();
    }
    else // if the user unchecked, then hide the freeze dialog if its still showing
    {
        if (freezeDialog)
            freezeDialog->hide();
    }
}

void ReceiveCoinsDialog::on_receiveButton_clicked()
{
    if (!model || !model->getOptionsModel() || !model->getAddressTableModel() || !model->getRecentRequestsTableModel())
        return;

    QString address;
    QString label = ui->reqLabel->text();
    QString sFreezeLockTime = "";

    if (ui->reuseAddress->isChecked())
    {
        /* Choose existing receiving address */
        AddressBookPage dlg(platformStyle, AddressBookPage::ForSelection, AddressBookPage::ReceivingTab, this);
        dlg.setModel(model->getAddressTableModel());
        if (dlg.exec())
        {
            address = dlg.getReturnValue();
            if (label.isEmpty()) /* If no label provided, use the previously used label */
            {
                label = model->getAddressTableModel()->labelForAddress(address);
            }
        }
        else
        {
            return;
        }
    }
    else
    {
        // only use coin freeze if the freeze value is valid and the check box is still set
        if ((nFreezeLockTime > 0) && (ui->freezeCheck) && (ui->freezeCheck->isChecked()))
        {
            /* Generate the freeze redeemScript and add to the address table.
             * The address variable needs to show the freeze P2SH public key  */
            address = model->getAddressTableModel()->addRow(AddressTableModel::Receive, label, "", nFreezeLockTime);
            sFreezeLockTime = model->getAddressTableModel()->labelForFreeze(address);
        }
        else
        {
            /* Generate new receiving address and add to the address table */
            address = model->getAddressTableModel()->addRow(AddressTableModel::Receive, label, "", CScriptNum(0));
        }
    }
    SendCoinsRecipient info(address, label, ui->reqAmount->value(), ui->reqMessage->text(), sFreezeLockTime, "");
    ReceiveRequestDialog *dialog = new ReceiveRequestDialog(this);
    dialog->setAttribute(Qt::WA_DeleteOnClose);
    dialog->setModel(model->getOptionsModel());
    dialog->setInfo(info);
    dialog->show();
    clear();

    /* Store request for later reference */
    model->getRecentRequestsTableModel()->addNewRequest(info);
}

void ReceiveCoinsDialog::on_recentRequestsView_doubleClicked(const QModelIndex &index)
{
    const RecentRequestsTableModel *submodel = model->getRecentRequestsTableModel();
    ReceiveRequestDialog *dialog = new ReceiveRequestDialog(this);
    dialog->setModel(model->getOptionsModel());
    dialog->setInfo(submodel->entry(index.row()).recipient);
    dialog->setAttribute(Qt::WA_DeleteOnClose);
    dialog->show();
}

void ReceiveCoinsDialog::recentRequestsView_selectionChanged(const QItemSelection &selected,
    const QItemSelection &deselected)
{
    // Enable Show/Remove buttons only if anything is selected.
    bool enable = !ui->recentRequestsView->selectionModel()->selectedRows().isEmpty();
    ui->showRequestButton->setEnabled(enable);
    ui->removeRequestButton->setEnabled(enable);
}

void ReceiveCoinsDialog::on_showRequestButton_clicked()
{
    if (!model || !model->getRecentRequestsTableModel() || !ui->recentRequestsView->selectionModel())
        return;
    QModelIndexList selection = ui->recentRequestsView->selectionModel()->selectedRows();

    Q_FOREACH (const QModelIndex &index, selection)
    {
        on_recentRequestsView_doubleClicked(index);
    }
}

void ReceiveCoinsDialog::on_removeRequestButton_clicked()
{
    if (!model || !model->getRecentRequestsTableModel() || !ui->recentRequestsView->selectionModel())
        return;
    QModelIndexList selection = ui->recentRequestsView->selectionModel()->selectedRows();
    if (selection.empty())
        return;
    // correct for selection mode ContiguousSelection
    QModelIndex firstIndex = selection.at(0);
    model->getRecentRequestsTableModel()->removeRows(firstIndex.row(), selection.length(), firstIndex.parent());
}

// We override the virtual resizeEvent of the QWidget to adjust tables column
// sizes as the tables width is proportional to the dialogs width.
void ReceiveCoinsDialog::resizeEvent(QResizeEvent *event)
{
    QWidget::resizeEvent(event);
    columnResizingFixer->stretchColumnWidth(RecentRequestsTableModel::Message);
}

void ReceiveCoinsDialog::keyPressEvent(QKeyEvent *event)
{
    if (event->key() == Qt::Key_Return)
    {
        // press return -> submit form
        if (ui->reqLabel->hasFocus() || ui->reqAmount->hasFocus() || ui->reqMessage->hasFocus())
        {
            event->ignore();
            on_receiveButton_clicked();
            return;
        }
    }

    this->QDialog::keyPressEvent(event);
}

// copy column of selected row to clipboard
void ReceiveCoinsDialog::copyColumnToClipboard(int column)
{
    if (!model || !model->getRecentRequestsTableModel() || !ui->recentRequestsView->selectionModel())
        return;
    QModelIndexList selection = ui->recentRequestsView->selectionModel()->selectedRows();
    if (selection.empty())
        return;
    // correct for selection mode ContiguousSelection
    QModelIndex firstIndex = selection.at(0);
    GUIUtil::setClipboard(model->getRecentRequestsTableModel()
                              ->data(firstIndex.child(firstIndex.row(), column), Qt::EditRole)
                              .toString());
}

// context menu
void ReceiveCoinsDialog::showMenu(const QPoint &point)
{
    if (!model || !model->getRecentRequestsTableModel() || !ui->recentRequestsView->selectionModel())
        return;
    QModelIndexList selection = ui->recentRequestsView->selectionModel()->selectedRows();
    if (selection.empty())
        return;
    contextMenu->exec(QCursor::pos());
}

// context menu action: copy address
void ReceiveCoinsDialog::copyAddress() { copyColumnToClipboard(RecentRequestsTableModel::Address); }
// context menu action: copy label
void ReceiveCoinsDialog::copyLabel() { copyColumnToClipboard(RecentRequestsTableModel::Label); }
// context menu action: copy message
void ReceiveCoinsDialog::copyMessage() { copyColumnToClipboard(RecentRequestsTableModel::Message); }
// context menu action: copy amount
void ReceiveCoinsDialog::copyAmount() { copyColumnToClipboard(RecentRequestsTableModel::Amount); }
<|endoftext|>


<commit_before>#include "sendmessagesdialog.h"
#include "ui_sendmessagesdialog.h"
//#include "init.h"
#include "walletmodel.h"
#include "messagemodel.h"
#include "addressbookpage.h"
#include "optionsmodel.h"
#include "sendmessagesentry.h"
//#include "guiutil.h"

#include <QMessageBox>
#include <QLocale>
#include <QTextDocument>
#include <QScrollBar>
#include <QClipboard>
#include <QDataWidgetMapper>

SendMessagesDialog::SendMessagesDialog(Mode mode, Type type, QWidget *parent) :
    QDialog(parent),
    ui(new Ui::SendMessagesDialog),
    model(0),
    mode(mode),
    type(type)
{

    ui->setupUi(this);

#ifdef Q_OS_MAC // Icons on push buttons are very uncommon on Mac
    ui->addButton->setIcon(QIcon());
    ui->clearButton->setIcon(QIcon());
    ui->sendButton->setIcon(QIcon());
#endif

#if QT_VERSION >= 0x040700
     /* Do not move this to the XML file, Qt before 4.7 will choke on it */
    if(mode == SendMessagesDialog::Encrypted)
        ui->addressFrom->setPlaceholderText(tr("Enter a DarkCoin address (e.g. FECqNjwb99MC7nTHM1iQKpL9RGZAAiVPnz)"));
 #endif
    addEntry();

    connect(ui->addButton, SIGNAL(clicked()), this, SLOT(addEntry()));
    connect(ui->clearButton, SIGNAL(clicked()), this, SLOT(clear()));
    connect(ui->closeButton, SIGNAL(clicked()), this, SLOT(reject()));

    fNewRecipientAllowed = true;

    if(mode == SendMessagesDialog::Anonymous)
        ui->frameAddressFrom->hide();

    if(type == SendMessagesDialog::Page)
        ui->closeButton->hide();
}

void SendMessagesDialog::setModel(MessageModel *model)
{
    this->model = model;

    for(int i = 0; i < ui->entries->count(); ++i)
    {
        SendMessagesEntry *entry = qobject_cast<SendMessagesEntry*>(ui->entries->itemAt(i)->widget());

        if(entry)
            entry->setModel(model);
    }
}

void SendMessagesDialog::loadRow(int row)
{
    if(model->data(model->index(row, model->Type, QModelIndex()), Qt::DisplayRole).toString() == MessageModel::Received)
        ui->addressFrom->setText(model->data(model->index(row, model->ToAddress, QModelIndex()), Qt::DisplayRole).toString());
    else
        ui->addressFrom->setText(model->data(model->index(row, model->FromAddress, QModelIndex()), Qt::DisplayRole).toString());

    for(int i = 0; i < ui->entries->count(); ++i)
    {
        SendMessagesEntry *entry = qobject_cast<SendMessagesEntry*>(ui->entries->itemAt(i)->widget());

        if(entry)
            entry->loadRow(row);
    }
}

bool SendMessagesDialog::checkMode(Mode mode)
{
    return (mode == this->mode);
}

bool SendMessagesDialog::validate()
{
    if(mode == SendMessagesDialog::Encrypted && ui->addressFrom->text() == "")
    {
        ui->addressFrom->setValid(false);

        return false;
    }

    return true;
}

SendMessagesDialog::~SendMessagesDialog()
{
    delete ui;
}

void SendMessagesDialog::on_pasteButton_clicked()
{
    // Paste text from clipboard into recipient field
    ui->addressFrom->setText(QApplication::clipboard()->text());
}

void SendMessagesDialog::on_addressBookButton_clicked()
{
    if(!model)
        return;

    AddressBookPage dlg(AddressBookPage::ForSending, AddressBookPage::ReceivingTab, this);

    dlg.setModel(model->getWalletModel()->getAddressTableModel());

    if(dlg.exec())
    {
        ui->addressFrom->setText(dlg.getReturnValue());
        SendMessagesEntry *entry = qobject_cast<SendMessagesEntry*>(ui->entries->itemAt(0)->widget());
        entry->setFocus();
               // findChild( const QString "sentTo")->setFocus();
    }
}

void SendMessagesDialog::on_sendButton_clicked()
{
    QList<SendMessagesRecipient> recipients;
    bool valid = true;

    if(!model)
        return;

    valid = validate();

    for(int i = 0; i < ui->entries->count(); ++i)
    {
        SendMessagesEntry *entry = qobject_cast<SendMessagesEntry*>(ui->entries->itemAt(i)->widget());
        if(entry)
        {
            if(entry->validate())
                recipients.append(entry->getValue());
            else
                valid = false;
        }
    }

    if(!valid || recipients.isEmpty())
        return;

    // Format confirmation message
    QStringList formatted;
    foreach(const SendMessagesRecipient &rcp, recipients)
    {
        formatted.append(tr("%1 to %2 (%3)").arg(rcp.message, Qt::escape(rcp.label), rcp.address));
    }

    fNewRecipientAllowed = false;

    QMessageBox::StandardButton retval = QMessageBox::question(this, tr("Confirm send messages"),
                          tr("Are you sure you want to send %1?").arg(formatted.join(tr(" and "))),
          QMessageBox::Yes|QMessageBox::Cancel,
          QMessageBox::Cancel);

    if(retval != QMessageBox::Yes)
    {
        fNewRecipientAllowed = true;
        return;
    }

    MessageModel::StatusCode sendstatus;

    if(mode == SendMessagesDialog::Anonymous)
        sendstatus = model->sendMessages(recipients);
    else
        sendstatus = model->sendMessages(recipients, ui->addressFrom->text());

    switch(sendstatus)
    {
    case MessageModel::InvalidAddress:
        QMessageBox::warning(this, tr("Send Message"),
            tr("The recipient address is not valid, please recheck."),
            QMessageBox::Ok, QMessageBox::Ok);
        break;
    case MessageModel::InvalidMessage:
        QMessageBox::warning(this, tr("Send Message"),
            tr("The message can't be empty."),
            QMessageBox::Ok, QMessageBox::Ok);
        break;
    case MessageModel::DuplicateAddress:
        QMessageBox::warning(this, tr("Send Message"),
            tr("Duplicate address found, can only send to each address once per send operation."),
            QMessageBox::Ok, QMessageBox::Ok);
        break;
    case MessageModel::MessageCreationFailed:
        QMessageBox::warning(this, tr("Send Message"),
            tr("Error: Message creation failed."),
            QMessageBox::Ok, QMessageBox::Ok);
        break;
    case MessageModel::MessageCommitFailed:
        QMessageBox::warning(this, tr("Send Message"),
            tr("Error: The message was rejected."),
            QMessageBox::Ok, QMessageBox::Ok);
        break;
    case MessageModel::Aborted:             // User aborted, nothing to do
        break;
    case MessageModel::FailedErrorShown:    // Send failed, error message was displayed
        break;
    case MessageModel::OK:
        accept();
        break;
    }

    fNewRecipientAllowed = true;
}

void SendMessagesDialog::clear()
{
    // Remove entries until only one left
    while(ui->entries->count())
        delete ui->entries->takeAt(0)->widget();

    addEntry();

    updateRemoveEnabled();

    ui->sendButton->setDefault(true);
}

void SendMessagesDialog::reject()
{
    if(type == SendMessagesDialog::Dialog)
        done(1);
    else
        clear();
}

void SendMessagesDialog::accept()
{
    if(type == SendMessagesDialog::Dialog)
        done(0);
    else
        clear();

}

void SendMessagesDialog::done(int retval)
{
    if(type == SendMessagesDialog::Dialog)
        QDialog::done(retval);
    else
        clear();
}

SendMessagesEntry *SendMessagesDialog::addEntry()
{
    SendMessagesEntry *entry = new SendMessagesEntry(this);

    entry->setModel(model);
    ui->entries->addWidget(entry);
    connect(entry, SIGNAL(removeEntry(SendMessagesEntry*)), this, SLOT(removeEntry(SendMessagesEntry*)));
    updateRemoveEnabled();

    // Focus the field, so that entry can start immediately
    entry->clear();
    entry->setFocus();

    ui->scrollAreaWidgetContents->resize(ui->scrollAreaWidgetContents->sizeHint());
    QCoreApplication::instance()->processEvents();
    QScrollBar* bar = ui->scrollArea->verticalScrollBar();

    if(bar)
        bar->setSliderPosition(bar->maximum());

    return entry;
}

void SendMessagesDialog::updateRemoveEnabled()
{
    // Remove buttons are enabled as soon as there is more than one send-entry
    bool enabled = (ui->entries->count() > 1);

    for(int i = 0; i < ui->entries->count(); ++i)
    {
        SendMessagesEntry *entry = qobject_cast<SendMessagesEntry*>(ui->entries->itemAt(i)->widget());
        if(entry)
            entry->setRemoveEnabled(enabled);
    }

    setupTabChain(0);
}

void SendMessagesDialog::removeEntry(SendMessagesEntry* entry)
{
    delete entry;

    updateRemoveEnabled();
}

QWidget *SendMessagesDialog::setupTabChain(QWidget *prev)
{
    for(int i = 0; i < ui->entries->count(); ++i)
    {
        SendMessagesEntry *entry = qobject_cast<SendMessagesEntry*>(ui->entries->itemAt(i)->widget());
        if(entry)
        {
            prev = entry->setupTabChain(prev);
        }
    }

    QWidget::setTabOrder(prev, ui->addButton);
    QWidget::setTabOrder(ui->addButton, ui->sendButton);

    return ui->sendButton;
}

void SendMessagesDialog::pasteEntry(const SendMessagesRecipient &rv)
{
    if(!fNewRecipientAllowed)
        return;

    SendMessagesEntry *entry = 0;
    // Replace the first entry if it is still unused
    if(ui->entries->count() == 1)
    {
        SendMessagesEntry *first = qobject_cast<SendMessagesEntry*>(ui->entries->itemAt(0)->widget());

        if(first->isClear())
            entry = first;
    }

    if(!entry)
        entry = addEntry();

    entry->setValue(rv);
}
<commit_msg>Fixed sendmessagesdialog.cpp for Qt5<commit_after>#include "sendmessagesdialog.h"
#include "ui_sendmessagesdialog.h"
//#include "init.h"
#include "walletmodel.h"
#include "messagemodel.h"
#include "addressbookpage.h"
#include "optionsmodel.h"
#include "sendmessagesentry.h"
//#include "guiutil.h"

#include <QMessageBox>
#include <QLocale>
#include <QTextDocument>
#include <QScrollBar>
#include <QClipboard>
#include <QDataWidgetMapper>

SendMessagesDialog::SendMessagesDialog(Mode mode, Type type, QWidget *parent) :
    QDialog(parent),
    ui(new Ui::SendMessagesDialog),
    model(0),
    mode(mode),
    type(type)
{

    ui->setupUi(this);

#ifdef Q_OS_MAC // Icons on push buttons are very uncommon on Mac
    ui->addButton->setIcon(QIcon());
    ui->clearButton->setIcon(QIcon());
    ui->sendButton->setIcon(QIcon());
#endif

#if QT_VERSION >= 0x040700
     /* Do not move this to the XML file, Qt before 4.7 will choke on it */
    if(mode == SendMessagesDialog::Encrypted)
        ui->addressFrom->setPlaceholderText(tr("Enter a DarkCoin address (e.g. FECqNjwb99MC7nTHM1iQKpL9RGZAAiVPnz)"));
 #endif
    addEntry();

    connect(ui->addButton, SIGNAL(clicked()), this, SLOT(addEntry()));
    connect(ui->clearButton, SIGNAL(clicked()), this, SLOT(clear()));
    connect(ui->closeButton, SIGNAL(clicked()), this, SLOT(reject()));

    fNewRecipientAllowed = true;

    if(mode == SendMessagesDialog::Anonymous)
        ui->frameAddressFrom->hide();

    if(type == SendMessagesDialog::Page)
        ui->closeButton->hide();
}

void SendMessagesDialog::setModel(MessageModel *model)
{
    this->model = model;

    for(int i = 0; i < ui->entries->count(); ++i)
    {
        SendMessagesEntry *entry = qobject_cast<SendMessagesEntry*>(ui->entries->itemAt(i)->widget());

        if(entry)
            entry->setModel(model);
    }
}

void SendMessagesDialog::loadRow(int row)
{
    if(model->data(model->index(row, model->Type, QModelIndex()), Qt::DisplayRole).toString() == MessageModel::Received)
        ui->addressFrom->setText(model->data(model->index(row, model->ToAddress, QModelIndex()), Qt::DisplayRole).toString());
    else
        ui->addressFrom->setText(model->data(model->index(row, model->FromAddress, QModelIndex()), Qt::DisplayRole).toString());

    for(int i = 0; i < ui->entries->count(); ++i)
    {
        SendMessagesEntry *entry = qobject_cast<SendMessagesEntry*>(ui->entries->itemAt(i)->widget());

        if(entry)
            entry->loadRow(row);
    }
}

bool SendMessagesDialog::checkMode(Mode mode)
{
    return (mode == this->mode);
}

bool SendMessagesDialog::validate()
{
    if(mode == SendMessagesDialog::Encrypted && ui->addressFrom->text() == "")
    {
        ui->addressFrom->setValid(false);

        return false;
    }

    return true;
}

SendMessagesDialog::~SendMessagesDialog()
{
    delete ui;
}

void SendMessagesDialog::on_pasteButton_clicked()
{
    // Paste text from clipboard into recipient field
    ui->addressFrom->setText(QApplication::clipboard()->text());
}

void SendMessagesDialog::on_addressBookButton_clicked()
{
    if(!model)
        return;

    AddressBookPage dlg(AddressBookPage::ForSending, AddressBookPage::ReceivingTab, this);

    dlg.setModel(model->getWalletModel()->getAddressTableModel());

    if(dlg.exec())
    {
        ui->addressFrom->setText(dlg.getReturnValue());
        SendMessagesEntry *entry = qobject_cast<SendMessagesEntry*>(ui->entries->itemAt(0)->widget());
        entry->setFocus();
               // findChild( const QString "sentTo")->setFocus();
    }
}

void SendMessagesDialog::on_sendButton_clicked()
{
    QList<SendMessagesRecipient> recipients;
    bool valid = true;

    if(!model)
        return;

    valid = validate();

    for(int i = 0; i < ui->entries->count(); ++i)
    {
        SendMessagesEntry *entry = qobject_cast<SendMessagesEntry*>(ui->entries->itemAt(i)->widget());
        if(entry)
        {
            if(entry->validate())
                recipients.append(entry->getValue());
            else
                valid = false;
        }
    }

    if(!valid || recipients.isEmpty())
        return;

    // Format confirmation message
    QStringList formatted;
    foreach(const SendMessagesRecipient &rcp, recipients)
    {
#if QT_VERSION < 0x050000
        formatted.append(tr("%1 to %2 (%3)").arg(rcp.message, Qt::escape(rcp.label), rcp.address));
#else
        formatted.append(tr("%1 to %2 (%3)").arg(rcp.message, rcp.label.toHtmlEscaped(), rcp.address));
#endif
    }

    fNewRecipientAllowed = false;

    QMessageBox::StandardButton retval = QMessageBox::question(this, tr("Confirm send messages"),
                          tr("Are you sure you want to send %1?").arg(formatted.join(tr(" and "))),
          QMessageBox::Yes|QMessageBox::Cancel,
          QMessageBox::Cancel);

    if(retval != QMessageBox::Yes)
    {
        fNewRecipientAllowed = true;
        return;
    }

    MessageModel::StatusCode sendstatus;

    if(mode == SendMessagesDialog::Anonymous)
        sendstatus = model->sendMessages(recipients);
    else
        sendstatus = model->sendMessages(recipients, ui->addressFrom->text());

    switch(sendstatus)
    {
    case MessageModel::InvalidAddress:
        QMessageBox::warning(this, tr("Send Message"),
            tr("The recipient address is not valid, please recheck."),
            QMessageBox::Ok, QMessageBox::Ok);
        break;
    case MessageModel::InvalidMessage:
        QMessageBox::warning(this, tr("Send Message"),
            tr("The message can't be empty."),
            QMessageBox::Ok, QMessageBox::Ok);
        break;
    case MessageModel::DuplicateAddress:
        QMessageBox::warning(this, tr("Send Message"),
            tr("Duplicate address found, can only send to each address once per send operation."),
            QMessageBox::Ok, QMessageBox::Ok);
        break;
    case MessageModel::MessageCreationFailed:
        QMessageBox::warning(this, tr("Send Message"),
            tr("Error: Message creation failed."),
            QMessageBox::Ok, QMessageBox::Ok);
        break;
    case MessageModel::MessageCommitFailed:
        QMessageBox::warning(this, tr("Send Message"),
            tr("Error: The message was rejected."),
            QMessageBox::Ok, QMessageBox::Ok);
        break;
    case MessageModel::Aborted:             // User aborted, nothing to do
        break;
    case MessageModel::FailedErrorShown:    // Send failed, error message was displayed
        break;
    case MessageModel::OK:
        accept();
        break;
    }

    fNewRecipientAllowed = true;
}

void SendMessagesDialog::clear()
{
    // Remove entries until only one left
    while(ui->entries->count())
        delete ui->entries->takeAt(0)->widget();

    addEntry();

    updateRemoveEnabled();

    ui->sendButton->setDefault(true);
}

void SendMessagesDialog::reject()
{
    if(type == SendMessagesDialog::Dialog)
        done(1);
    else
        clear();
}

void SendMessagesDialog::accept()
{
    if(type == SendMessagesDialog::Dialog)
        done(0);
    else
        clear();

}

void SendMessagesDialog::done(int retval)
{
    if(type == SendMessagesDialog::Dialog)
        QDialog::done(retval);
    else
        clear();
}

SendMessagesEntry *SendMessagesDialog::addEntry()
{
    SendMessagesEntry *entry = new SendMessagesEntry(this);

    entry->setModel(model);
    ui->entries->addWidget(entry);
    connect(entry, SIGNAL(removeEntry(SendMessagesEntry*)), this, SLOT(removeEntry(SendMessagesEntry*)));
    updateRemoveEnabled();

    // Focus the field, so that entry can start immediately
    entry->clear();
    entry->setFocus();

    ui->scrollAreaWidgetContents->resize(ui->scrollAreaWidgetContents->sizeHint());
    QCoreApplication::instance()->processEvents();
    QScrollBar* bar = ui->scrollArea->verticalScrollBar();

    if(bar)
        bar->setSliderPosition(bar->maximum());

    return entry;
}

void SendMessagesDialog::updateRemoveEnabled()
{
    // Remove buttons are enabled as soon as there is more than one send-entry
    bool enabled = (ui->entries->count() > 1);

    for(int i = 0; i < ui->entries->count(); ++i)
    {
        SendMessagesEntry *entry = qobject_cast<SendMessagesEntry*>(ui->entries->itemAt(i)->widget());
        if(entry)
            entry->setRemoveEnabled(enabled);
    }

    setupTabChain(0);
}

void SendMessagesDialog::removeEntry(SendMessagesEntry* entry)
{
    delete entry;

    updateRemoveEnabled();
}

QWidget *SendMessagesDialog::setupTabChain(QWidget *prev)
{
    for(int i = 0; i < ui->entries->count(); ++i)
    {
        SendMessagesEntry *entry = qobject_cast<SendMessagesEntry*>(ui->entries->itemAt(i)->widget());
        if(entry)
        {
            prev = entry->setupTabChain(prev);
        }
    }

    QWidget::setTabOrder(prev, ui->addButton);
    QWidget::setTabOrder(ui->addButton, ui->sendButton);

    return ui->sendButton;
}

void SendMessagesDialog::pasteEntry(const SendMessagesRecipient &rv)
{
    if(!fNewRecipientAllowed)
        return;

    SendMessagesEntry *entry = 0;
    // Replace the first entry if it is still unused
    if(ui->entries->count() == 1)
    {
        SendMessagesEntry *first = qobject_cast<SendMessagesEntry*>(ui->entries->itemAt(0)->widget());

        if(first->isClear())
            entry = first;
    }

    if(!entry)
        entry = addEntry();

    entry->setValue(rv);
}
<|endoftext|>