<commit_before>/*************************************************************************
 *
 *  $RCSfile: unovwcrs.cxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: obo $ $Date: 2004-01-20 12:36:52 $
 *
 *  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 _COM_SUN_STAR_TEXT_XTEXTVIEWCURSOR_HPP_
#include <com/sun/star/text/XTextViewCursor.hpp>
#endif
#ifndef _COM_SUN_STAR_VIEW_XSCREENCURSOR_HPP_
#include <com/sun/star/view/XScreenCursor.hpp>
#endif

#ifndef _SFXREQUEST_HXX
#include <sfx2/request.hxx>
#endif

#ifndef _VOS_MUTEX_HXX_ //autogen
#include <vos/mutex.hxx>
#endif

#ifndef SD_VIEW_HXX
#include "View.hxx"
#endif
#ifndef SVX_LIGHT
#ifndef SD_DRAW_DOC_SHELL_HXX
#include "DrawDocShell.hxx"
#endif
#endif
#ifndef SD_VIEW_SHELL_HXX
#include "ViewShell.hxx"
#endif
#ifndef SD_FU_SLIDE_SHOW_HXX
#include "fuslshow.hxx"
#endif

#include <cppuhelper/implbase2.hxx>

using namespace ::vos;
using namespace ::rtl;
using namespace ::com::sun::star;

class SdXTextViewCursor
    : public ::cppu::WeakImplHelper2<
    text::XTextViewCursor,
    view::XScreenCursor >
{
public:
    SdXTextViewCursor(::sd::View* pVw) throw();
    virtual ~SdXTextViewCursor() throw();

    //XTextViewCursor
    virtual sal_Bool SAL_CALL isVisible(void) throw( uno::RuntimeException );
    virtual void SAL_CALL setVisible(sal_Bool bVisible) throw( uno::RuntimeException );
    virtual awt::Point SAL_CALL getPosition(void) throw( uno::RuntimeException );

    //XTextCursor
    virtual void SAL_CALL collapseToStart(void) throw( uno::RuntimeException );
    virtual void SAL_CALL collapseToEnd(void) throw( uno::RuntimeException );
    virtual sal_Bool SAL_CALL isCollapsed(void) throw( uno::RuntimeException );
    virtual sal_Bool SAL_CALL goLeft(sal_Int16 nCount, sal_Bool Expand) throw( uno::RuntimeException );
    virtual sal_Bool SAL_CALL goRight(sal_Int16 nCount, sal_Bool Expand) throw( uno::RuntimeException );
    virtual void SAL_CALL gotoStart(sal_Bool Expand) throw( uno::RuntimeException );
    virtual void SAL_CALL gotoEnd(sal_Bool Expand) throw( uno::RuntimeException );
    virtual void SAL_CALL gotoRange(const uno::Reference< text::XTextRange > & rRange, sal_Bool bExpand ) throw (::com::sun::star::uno::RuntimeException);

    //XTextRange
    virtual uno::Reference< text::XText >  SAL_CALL getText(void) throw( uno::RuntimeException );
    virtual uno::Reference< text::XTextRange >  SAL_CALL getStart(void) throw( uno::RuntimeException );
    virtual uno::Reference< text::XTextRange >  SAL_CALL getEnd(void) throw( uno::RuntimeException );
    virtual OUString SAL_CALL getString(void) throw( uno::RuntimeException );
    virtual void SAL_CALL setString(const OUString& aString) throw( uno::RuntimeException );

    //XScreenCursor
    virtual sal_Bool SAL_CALL screenDown(void) throw( uno::RuntimeException );
    virtual sal_Bool SAL_CALL screenUp(void) throw( uno::RuntimeException );

    void    Invalidate()    { mpView = 0; }

private:
    ::sd::View* mpView;
};

text::XTextViewCursor* CreateSdXTextViewCursor(::sd::View* mpView )
{
    return new SdXTextViewCursor( mpView );
}

SdXTextViewCursor::SdXTextViewCursor(::sd::View* pSdView ) throw()
    :   mpView(pSdView)
{

}

SdXTextViewCursor::~SdXTextViewCursor() throw()
{
}

sal_Bool SdXTextViewCursor::isVisible(void) throw( uno::RuntimeException )
{
    DBG_WARNING("not implemented")
    return sal_True;
}

void SdXTextViewCursor::setVisible(sal_Bool bVisible) throw( uno::RuntimeException )
{
    DBG_WARNING("not implemented")
}

awt::Point SdXTextViewCursor::getPosition(void) throw( uno::RuntimeException )
{
    DBG_WARNING("not implemented")
    return awt::Point();
}

void SdXTextViewCursor::collapseToStart(void) throw( uno::RuntimeException )
{
    DBG_WARNING("not implemented")
}

void SdXTextViewCursor::collapseToEnd(void) throw( uno::RuntimeException )
{
    DBG_WARNING("not implemented")
}

sal_Bool SdXTextViewCursor::isCollapsed(void) throw( uno::RuntimeException )
{
    DBG_WARNING("not implemented")
    return sal_True;

}

sal_Bool SdXTextViewCursor::goLeft(sal_Int16 nCount, sal_Bool bExpand) throw( uno::RuntimeException )
{
    DBG_WARNING("not implemented")
    return sal_False;
}

sal_Bool SdXTextViewCursor::goRight(sal_Int16 nCount, sal_Bool bExpand) throw( uno::RuntimeException )
{
    DBG_WARNING("not implemented")
    return sal_False;
}

void SdXTextViewCursor::gotoRange(const uno::Reference< text::XTextRange > & xRange, sal_Bool bExpand) throw (::com::sun::star::uno::RuntimeException)
{
    DBG_WARNING("not implemented")
}

void SdXTextViewCursor::gotoStart(sal_Bool bExpand) throw( uno::RuntimeException )
{
    DBG_WARNING("not implemented")
}

void SdXTextViewCursor::gotoEnd(sal_Bool bExpand) throw( uno::RuntimeException )
{
    DBG_WARNING("not implemented")
}

sal_Bool SdXTextViewCursor::screenDown(void) throw( uno::RuntimeException )
{
    OGuard aGuard(Application::GetSolarMutex());
    sal_Bool bRet = sal_False;

    if( mpView && mpView->GetDocSh() )
    {
        ::sd::ViewShell* pViewSh = mpView->GetDocSh()->GetViewShell();
        if( pViewSh )
        {
            ::sd::FuSlideShow* pShow = pViewSh->GetSlideShow();
            if( pShow )
            {
                pShow->KeyInput( KeyEvent( 32, KeyCode( KEY_SPACE ) ) );
                return sal_True;
            }
        }
    }
    return sal_False;
}

sal_Bool SdXTextViewCursor::screenUp(void) throw( uno::RuntimeException )
{
    OGuard aGuard(Application::GetSolarMutex());
    sal_Bool bRet = sal_False;

    if( mpView && mpView->GetDocSh() )
    {
        ::sd::ViewShell* pViewSh = mpView->GetDocSh()->GetViewShell();
        if( pViewSh )
        {
            ::sd::FuSlideShow* pShow = pViewSh->GetSlideShow();
            if( pShow )
            {
                pShow->KeyInput( KeyEvent( 32, KeyCode( KEY_BACKSPACE ) ) );
                return sal_True;
            }
        }
    }
    return sal_False;
}

uno::Reference< text::XText >  SdXTextViewCursor::getText(void) throw( uno::RuntimeException )
{
    DBG_WARNING("not implemented")
    return uno::Reference< text::XText > ();
}

uno::Reference< text::XTextRange >  SdXTextViewCursor::getStart(void) throw( uno::RuntimeException )
{
    DBG_WARNING("not implemented")
    return uno::Reference< text::XTextRange > ();
}

uno::Reference< text::XTextRange >  SdXTextViewCursor::getEnd(void) throw( uno::RuntimeException )
{
    DBG_WARNING("not implemented")
    return uno::Reference< text::XTextRange > ();
}

OUString SdXTextViewCursor::getString(void) throw( uno::RuntimeException )
{
    DBG_WARNING("not implemented")
    return OUString();
}

void SdXTextViewCursor::setString(const OUString& aString) throw( uno::RuntimeException )
{
    DBG_WARNING("not implemented")
}

<commit_msg>INTEGRATION: CWS presentationengine01 (1.4.10); FILE MERGED 2004/08/25 16:32:23 cl 1.4.10.1: replaced old FuSlideShow with new SlideShow<commit_after>/*************************************************************************
 *
 *  $RCSfile: unovwcrs.cxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: rt $ $Date: 2004-11-26 20:29: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 _COM_SUN_STAR_TEXT_XTEXTVIEWCURSOR_HPP_
#include <com/sun/star/text/XTextViewCursor.hpp>
#endif
#ifndef _COM_SUN_STAR_VIEW_XSCREENCURSOR_HPP_
#include <com/sun/star/view/XScreenCursor.hpp>
#endif

#ifndef _SFXREQUEST_HXX
#include <sfx2/request.hxx>
#endif

#ifndef _VOS_MUTEX_HXX_ //autogen
#include <vos/mutex.hxx>
#endif

#ifndef SD_VIEW_HXX
#include "View.hxx"
#endif
#ifndef SVX_LIGHT
#ifndef SD_DRAW_DOC_SHELL_HXX
#include "DrawDocShell.hxx"
#endif
#endif
#ifndef SD_VIEW_SHELL_HXX
#include "ViewShell.hxx"
#endif
#ifndef _SD_SLIDESHOW_HXX
#include "slideshow.hxx"
#endif

#include <cppuhelper/implbase2.hxx>

using namespace ::vos;
using namespace ::rtl;
using namespace ::com::sun::star;

class SdXTextViewCursor
    : public ::cppu::WeakImplHelper2<
    text::XTextViewCursor,
    view::XScreenCursor >
{
public:
    SdXTextViewCursor(::sd::View* pVw) throw();
    virtual ~SdXTextViewCursor() throw();

    //XTextViewCursor
    virtual sal_Bool SAL_CALL isVisible(void) throw( uno::RuntimeException );
    virtual void SAL_CALL setVisible(sal_Bool bVisible) throw( uno::RuntimeException );
    virtual awt::Point SAL_CALL getPosition(void) throw( uno::RuntimeException );

    //XTextCursor
    virtual void SAL_CALL collapseToStart(void) throw( uno::RuntimeException );
    virtual void SAL_CALL collapseToEnd(void) throw( uno::RuntimeException );
    virtual sal_Bool SAL_CALL isCollapsed(void) throw( uno::RuntimeException );
    virtual sal_Bool SAL_CALL goLeft(sal_Int16 nCount, sal_Bool Expand) throw( uno::RuntimeException );
    virtual sal_Bool SAL_CALL goRight(sal_Int16 nCount, sal_Bool Expand) throw( uno::RuntimeException );
    virtual void SAL_CALL gotoStart(sal_Bool Expand) throw( uno::RuntimeException );
    virtual void SAL_CALL gotoEnd(sal_Bool Expand) throw( uno::RuntimeException );
    virtual void SAL_CALL gotoRange(const uno::Reference< text::XTextRange > & rRange, sal_Bool bExpand ) throw (::com::sun::star::uno::RuntimeException);

    //XTextRange
    virtual uno::Reference< text::XText >  SAL_CALL getText(void) throw( uno::RuntimeException );
    virtual uno::Reference< text::XTextRange >  SAL_CALL getStart(void) throw( uno::RuntimeException );
    virtual uno::Reference< text::XTextRange >  SAL_CALL getEnd(void) throw( uno::RuntimeException );
    virtual OUString SAL_CALL getString(void) throw( uno::RuntimeException );
    virtual void SAL_CALL setString(const OUString& aString) throw( uno::RuntimeException );

    //XScreenCursor
    virtual sal_Bool SAL_CALL screenDown(void) throw( uno::RuntimeException );
    virtual sal_Bool SAL_CALL screenUp(void) throw( uno::RuntimeException );

    void    Invalidate()    { mpView = 0; }

private:
    ::sd::View* mpView;
};

text::XTextViewCursor* CreateSdXTextViewCursor(::sd::View* mpView )
{
    return new SdXTextViewCursor( mpView );
}

SdXTextViewCursor::SdXTextViewCursor(::sd::View* pSdView ) throw()
    :   mpView(pSdView)
{

}

SdXTextViewCursor::~SdXTextViewCursor() throw()
{
}

sal_Bool SdXTextViewCursor::isVisible(void) throw( uno::RuntimeException )
{
    DBG_WARNING("not implemented")
    return sal_True;
}

void SdXTextViewCursor::setVisible(sal_Bool bVisible) throw( uno::RuntimeException )
{
    DBG_WARNING("not implemented")
}

awt::Point SdXTextViewCursor::getPosition(void) throw( uno::RuntimeException )
{
    DBG_WARNING("not implemented")
    return awt::Point();
}

void SdXTextViewCursor::collapseToStart(void) throw( uno::RuntimeException )
{
    DBG_WARNING("not implemented")
}

void SdXTextViewCursor::collapseToEnd(void) throw( uno::RuntimeException )
{
    DBG_WARNING("not implemented")
}

sal_Bool SdXTextViewCursor::isCollapsed(void) throw( uno::RuntimeException )
{
    DBG_WARNING("not implemented")
    return sal_True;

}

sal_Bool SdXTextViewCursor::goLeft(sal_Int16 nCount, sal_Bool bExpand) throw( uno::RuntimeException )
{
    DBG_WARNING("not implemented")
    return sal_False;
}

sal_Bool SdXTextViewCursor::goRight(sal_Int16 nCount, sal_Bool bExpand) throw( uno::RuntimeException )
{
    DBG_WARNING("not implemented")
    return sal_False;
}

void SdXTextViewCursor::gotoRange(const uno::Reference< text::XTextRange > & xRange, sal_Bool bExpand) throw (::com::sun::star::uno::RuntimeException)
{
    DBG_WARNING("not implemented")
}

void SdXTextViewCursor::gotoStart(sal_Bool bExpand) throw( uno::RuntimeException )
{
    DBG_WARNING("not implemented")
}

void SdXTextViewCursor::gotoEnd(sal_Bool bExpand) throw( uno::RuntimeException )
{
    DBG_WARNING("not implemented")
}

sal_Bool SdXTextViewCursor::screenDown(void) throw( uno::RuntimeException )
{
    OGuard aGuard(Application::GetSolarMutex());
    sal_Bool bRet = sal_False;

/*

    if( mpView && mpView->GetDocSh() )
    {
        ::sd::ViewShell* pViewSh = mpView->GetDocSh()->GetViewShell();
        if( pViewSh )
        {
            ::sd::FuSlideShow* pShow = pViewSh->GetSlideShow();
            if( pShow )
            {
                pShow->KeyInput( KeyEvent( 32, KeyCode( KEY_SPACE ) ) );
                return sal_True;
            }
        }
    }
*/
    return sal_False;
}

sal_Bool SdXTextViewCursor::screenUp(void) throw( uno::RuntimeException )
{
    OGuard aGuard(Application::GetSolarMutex());
/*
    sal_Bool bRet = sal_False;

    if( mpView && mpView->GetDocSh() )
    {
        ::sd::ViewShell* pViewSh = mpView->GetDocSh()->GetViewShell();
        if( pViewSh )
        {
            ::sd::FuSlideShow* pShow = pViewSh->GetSlideShow();
            if( pShow )
            {
                pShow->KeyInput( KeyEvent( 32, KeyCode( KEY_BACKSPACE ) ) );
                return sal_True;
            }
        }
    }
*/
    return sal_False;
}

uno::Reference< text::XText >  SdXTextViewCursor::getText(void) throw( uno::RuntimeException )
{
    DBG_WARNING("not implemented")
    return uno::Reference< text::XText > ();
}

uno::Reference< text::XTextRange >  SdXTextViewCursor::getStart(void) throw( uno::RuntimeException )
{
    DBG_WARNING("not implemented")
    return uno::Reference< text::XTextRange > ();
}

uno::Reference< text::XTextRange >  SdXTextViewCursor::getEnd(void) throw( uno::RuntimeException )
{
    DBG_WARNING("not implemented")
    return uno::Reference< text::XTextRange > ();
}

OUString SdXTextViewCursor::getString(void) throw( uno::RuntimeException )
{
    DBG_WARNING("not implemented")
    return OUString();
}

void SdXTextViewCursor::setString(const OUString& aString) throw( uno::RuntimeException )
{
    DBG_WARNING("not implemented")
}

<|endoftext|>


<commit_before>#include <QDebug>
#include <QJsonDocument>
#include <QJsonObject>
#include <QLabel>
#include <QPushButton>
#include <QStackedWidget>
#include <QTimer>
#include <QVBoxLayout>

#include "QrCode.hpp"
#include "api.hpp"
#include "common/params.h"
#include "setup.hpp"

using qrcodegen::QrCode;

PairingQRWidget::PairingQRWidget(QWidget* parent) : QWidget(parent) {
  qrCode = new QLabel;
  qrCode->setScaledContents(true);
  QVBoxLayout* v = new QVBoxLayout;
  v->addWidget(qrCode, 0, Qt::AlignCenter);
  setLayout(v);

  QTimer* timer = new QTimer(this);
  timer->start(30 * 1000);
  connect(timer, SIGNAL(timeout()), this, SLOT(refresh()));
  refresh(); // don't wait for the first refresh
}

void PairingQRWidget::refresh(){
  QString IMEI = QString::fromStdString(Params().get("IMEI"));
  QString serial = QString::fromStdString(Params().get("HardwareSerial"));

  if (std::min(IMEI.length(), serial.length()) <= 5) {
    qrCode->setText("Error getting serial: contact support");
    qrCode->setWordWrap(true);
    qrCode->setStyleSheet(R"(font-size: 60px;)");
    return;
  }
  QString pairToken = CommaApi::create_jwt({{"pair", true}});

  QString qrString = IMEI + "--" + serial + "--" + pairToken;
  this->updateQrCode(qrString);
}

void PairingQRWidget::updateQrCode(QString text) {
  QrCode qr = QrCode::encodeText(text.toUtf8().data(), QrCode::Ecc::LOW);
  qint32 sz = qr.getSize();
  // make the image larger so we can have a white border
  QImage im(sz + 2, sz + 2, QImage::Format_RGB32);
  QRgb black = qRgb(0, 0, 0);
  QRgb white = qRgb(255, 255, 255);

  for (int y = 0; y < sz + 2; y++) {
    for (int x = 0; x < sz + 2; x++) {
      im.setPixel(x, y, white);
    }
  }
  for (int y = 0; y < sz; y++) {
    for (int x = 0; x < sz; x++) {
      im.setPixel(x + 1, y + 1, qr.getModule(x, y) ? black : white);
    }
  }
  // Integer division to prevent anti-aliasing
  int approx500 = (500 / (sz + 2)) * (sz + 2);
  qrCode->setPixmap(QPixmap::fromImage(im.scaled(approx500, approx500, Qt::KeepAspectRatio, Qt::FastTransformation), Qt::MonoOnly));
  qrCode->setFixedSize(approx500, approx500);
}

PrimeUserWidget::PrimeUserWidget(QWidget* parent) : QWidget(parent) {
  mainLayout = new QVBoxLayout;
  mainLayout->setMargin(30);

  QLabel* commaPrime = new QLabel("COMMA PRIME");
  mainLayout->addWidget(commaPrime, 0, Qt::AlignTop);

  username = new QLabel();
  username->setStyleSheet("font-size: 55px;"); // TODO: fit width
  mainLayout->addWidget(username, 0, Qt::AlignTop);

  mainLayout->addSpacing(100);

  QLabel* commaPoints = new QLabel("COMMA POINTS");
  commaPoints->setStyleSheet(R"(
    color: #b8b8b8;
  )");
  mainLayout->addWidget(commaPoints, 0, Qt::AlignTop);

  points = new QLabel();
  mainLayout->addWidget(points, 0, Qt::AlignTop);

  setLayout(mainLayout);
  setStyleSheet(R"(
    QLabel {
      font-size: 70px;
      font-weight: 500;
    }
  )");

  // set up API requests
  QString dongleId = QString::fromStdString(Params().get("DongleId"));
  if (!dongleId.length()) {
    return;
  }

  // TODO: only send the request when widget is shown
  QString url = "https://api.commadotai.com/v1/devices/" + dongleId + "/owner";
  RequestRepeater* repeater = new RequestRepeater(this, url, 6, "ApiCache_Owner");
  QObject::connect(repeater, SIGNAL(receivedResponse(QString)), this, SLOT(replyFinished(QString)));
}

void PrimeUserWidget::replyFinished(QString response) {
  QJsonDocument doc = QJsonDocument::fromJson(response.toUtf8());
  if (doc.isNull()) {
    qDebug() << "JSON Parse failed on getting username and points";
    return;
  }

  QJsonObject json = doc.object();
  QString points_str = QString::number(json["points"].toInt());
  QString username_str = json["username"].toString();
  if (username_str.length()) {
    username_str = "@" + username_str;
  }

  username->setText(username_str);
  points->setText(points_str);
}

PrimeAdWidget::PrimeAdWidget(QWidget* parent) : QWidget(parent) {
  QVBoxLayout* vlayout = new QVBoxLayout;
  vlayout->setMargin(30);
  vlayout->setSpacing(15);

  vlayout->addWidget(new QLabel("Upgrade now"), 1, Qt::AlignTop);

  QLabel* description = new QLabel("Become a comma prime member in the comma connect app and get premium features!");
  description->setStyleSheet(R"(
    font-size: 50px;
    color: #b8b8b8;
  )");
  description->setWordWrap(true);
  vlayout->addWidget(description, 2, Qt::AlignTop);

  QVector<QString> features = {"✓ REMOTE ACCESS", "✓ 14 DAYS OF STORAGE", "✓ DEVELOPER PERKS"};
  for (auto &f: features) {
    QLabel* feature = new QLabel(f);
    feature->setStyleSheet(R"(font-size: 40px;)");
    vlayout->addWidget(feature, 0, Qt::AlignBottom);
  }

  setLayout(vlayout);
}

SetupWidget::SetupWidget(QWidget* parent) : QFrame(parent) {
  mainLayout = new QStackedWidget;

  // Unpaired, registration prompt layout

  QVBoxLayout* finishRegistationLayout = new QVBoxLayout;
  finishRegistationLayout->setMargin(30);

  QLabel* registrationDescription = new QLabel("Pair your device with the comma connect app");
  registrationDescription->setWordWrap(true);
  registrationDescription->setAlignment(Qt::AlignCenter);
  registrationDescription->setStyleSheet(R"(
    font-size: 55px;
    font-weight: 400;
  )");

  finishRegistationLayout->addWidget(registrationDescription);

  QPushButton* finishButton = new QPushButton("Finish setup");
  finishButton->setFixedHeight(200);
  finishButton->setStyleSheet(R"(
    border-radius: 30px;
    font-size: 55px;
    font-weight: 500;
    background: #585858;
  )");
  finishRegistationLayout->addWidget(finishButton);
  QObject::connect(finishButton, SIGNAL(released()), this, SLOT(showQrCode()));

  QWidget* finishRegistration = new QWidget;
  finishRegistration->setLayout(finishRegistationLayout);
  mainLayout->addWidget(finishRegistration);

  // Pairing QR code layout

  QVBoxLayout* qrLayout = new QVBoxLayout;

  qrLayout->addSpacing(40);
  QLabel* qrLabel = new QLabel("Scan with comma connect!");
  qrLabel->setWordWrap(true);
  qrLabel->setAlignment(Qt::AlignHCenter);
  qrLabel->setStyleSheet(R"(
    font-size: 55px;
    font-weight: 400;
  )");
  qrLayout->addWidget(qrLabel, 0, Qt::AlignTop);

  qrLayout->addWidget(new PairingQRWidget, 1);

  QWidget* q = new QWidget;
  q->setLayout(qrLayout);
  mainLayout->addWidget(q);

  primeAd = new PrimeAdWidget;
  mainLayout->addWidget(primeAd);

  primeUser = new PrimeUserWidget;
  mainLayout->addWidget(primeUser);

  mainLayout->setCurrentWidget(primeAd);

  QVBoxLayout *layout = new QVBoxLayout;
  layout->addWidget(mainLayout);
  setLayout(layout);

  setStyleSheet(R"(
    SetupWidget {
      background-color: #292929;
    }
    * {
      font-size: 90px;
      font-weight: 500;
      border-radius: 40px;
    }
  )");

  // Retain size while hidden
  QSizePolicy sp_retain = sizePolicy();
  sp_retain.setRetainSizeWhenHidden(true);
  setSizePolicy(sp_retain);

  // set up API requests
  QString dongleId = QString::fromStdString(Params().get("DongleId"));
  QString url = "https://api.commadotai.com/v1.1/devices/" + dongleId + "/";
  RequestRepeater* repeater = new RequestRepeater(this, url, 5, "ApiCache_Device");

  QObject::connect(repeater, SIGNAL(receivedResponse(QString)), this, SLOT(replyFinished(QString)));
  QObject::connect(repeater, SIGNAL(failedResponse(QString)), this, SLOT(parseError(QString)));
  hide(); // Only show when first request comes back
}

void SetupWidget::parseError(QString response) {
  show();
  showQr = false;
  mainLayout->setCurrentIndex(0);
}

void SetupWidget::showQrCode(){
  showQr = true;
  mainLayout->setCurrentIndex(1);
}

void SetupWidget::replyFinished(QString response) {
  show();
  QJsonDocument doc = QJsonDocument::fromJson(response.toUtf8());
  if (doc.isNull()) {
    qDebug() << "JSON Parse failed on getting pairing and prime status";
    return;
  }

  QJsonObject json = doc.object();
  bool is_paired = json["is_paired"].toBool();
  bool is_prime = json["prime"].toBool();

  if (!is_paired) {
    mainLayout->setCurrentIndex(showQr);
  } else if (!is_prime) {
    showQr = false;
    mainLayout->setCurrentWidget(primeAd);
  } else {
    showQr = false;
    mainLayout->setCurrentWidget(primeUser);
  }
}
<commit_msg>fix cut off qr code<commit_after>#include <QDebug>
#include <QJsonDocument>
#include <QJsonObject>
#include <QLabel>
#include <QPushButton>
#include <QStackedWidget>
#include <QTimer>
#include <QVBoxLayout>

#include "QrCode.hpp"
#include "api.hpp"
#include "common/params.h"
#include "setup.hpp"

using qrcodegen::QrCode;

PairingQRWidget::PairingQRWidget(QWidget* parent) : QWidget(parent) {
  qrCode = new QLabel;
  qrCode->setScaledContents(true);
  QVBoxLayout* v = new QVBoxLayout;
  v->addWidget(qrCode, 0, Qt::AlignCenter);
  setLayout(v);

  QTimer* timer = new QTimer(this);
  timer->start(30 * 1000);
  connect(timer, SIGNAL(timeout()), this, SLOT(refresh()));
  refresh(); // don't wait for the first refresh
}

void PairingQRWidget::refresh(){
  QString IMEI = QString::fromStdString(Params().get("IMEI"));
  QString serial = QString::fromStdString(Params().get("HardwareSerial"));

  if (std::min(IMEI.length(), serial.length()) <= 5) {
    qrCode->setText("Error getting serial: contact support");
    qrCode->setWordWrap(true);
    qrCode->setStyleSheet(R"(font-size: 60px;)");
    return;
  }
  QString pairToken = CommaApi::create_jwt({{"pair", true}});

  QString qrString = IMEI + "--" + serial + "--" + pairToken;
  this->updateQrCode(qrString);
}

void PairingQRWidget::updateQrCode(QString text) {
  QrCode qr = QrCode::encodeText(text.toUtf8().data(), QrCode::Ecc::LOW);
  qint32 sz = qr.getSize();
  // make the image larger so we can have a white border
  QImage im(sz + 2, sz + 2, QImage::Format_RGB32);
  QRgb black = qRgb(0, 0, 0);
  QRgb white = qRgb(255, 255, 255);

  for (int y = 0; y < sz + 2; y++) {
    for (int x = 0; x < sz + 2; x++) {
      im.setPixel(x, y, white);
    }
  }
  for (int y = 0; y < sz; y++) {
    for (int x = 0; x < sz; x++) {
      im.setPixel(x + 1, y + 1, qr.getModule(x, y) ? black : white);
    }
  }
  // Integer division to prevent anti-aliasing
  int approx500 = (500 / (sz + 2)) * (sz + 2);
  qrCode->setPixmap(QPixmap::fromImage(im.scaled(approx500, approx500, Qt::KeepAspectRatio, Qt::FastTransformation), Qt::MonoOnly));
  qrCode->setFixedSize(approx500, approx500);
}

PrimeUserWidget::PrimeUserWidget(QWidget* parent) : QWidget(parent) {
  mainLayout = new QVBoxLayout;
  mainLayout->setMargin(30);

  QLabel* commaPrime = new QLabel("COMMA PRIME");
  mainLayout->addWidget(commaPrime, 0, Qt::AlignTop);

  username = new QLabel();
  username->setStyleSheet("font-size: 55px;"); // TODO: fit width
  mainLayout->addWidget(username, 0, Qt::AlignTop);

  mainLayout->addSpacing(100);

  QLabel* commaPoints = new QLabel("COMMA POINTS");
  commaPoints->setStyleSheet(R"(
    color: #b8b8b8;
  )");
  mainLayout->addWidget(commaPoints, 0, Qt::AlignTop);

  points = new QLabel();
  mainLayout->addWidget(points, 0, Qt::AlignTop);

  setLayout(mainLayout);
  setStyleSheet(R"(
    QLabel {
      font-size: 70px;
      font-weight: 500;
    }
  )");

  // set up API requests
  QString dongleId = QString::fromStdString(Params().get("DongleId"));
  if (!dongleId.length()) {
    return;
  }

  QString url = "https://api.commadotai.com/v1/devices/" + dongleId + "/owner";
  RequestRepeater* repeater = new RequestRepeater(this, url, 6, "ApiCache_Owner");
  QObject::connect(repeater, SIGNAL(receivedResponse(QString)), this, SLOT(replyFinished(QString)));
}

void PrimeUserWidget::replyFinished(QString response) {
  QJsonDocument doc = QJsonDocument::fromJson(response.toUtf8());
  if (doc.isNull()) {
    qDebug() << "JSON Parse failed on getting username and points";
    return;
  }

  QJsonObject json = doc.object();
  QString points_str = QString::number(json["points"].toInt());
  QString username_str = json["username"].toString();
  if (username_str.length()) {
    username_str = "@" + username_str;
  }

  username->setText(username_str);
  points->setText(points_str);
}

PrimeAdWidget::PrimeAdWidget(QWidget* parent) : QWidget(parent) {
  QVBoxLayout* vlayout = new QVBoxLayout;
  vlayout->setMargin(30);
  vlayout->setSpacing(15);

  vlayout->addWidget(new QLabel("Upgrade now"), 1, Qt::AlignTop);

  QLabel* description = new QLabel("Become a comma prime member in the comma connect app and get premium features!");
  description->setStyleSheet(R"(
    font-size: 50px;
    color: #b8b8b8;
  )");
  description->setWordWrap(true);
  vlayout->addWidget(description, 2, Qt::AlignTop);

  QVector<QString> features = {"✓ REMOTE ACCESS", "✓ 14 DAYS OF STORAGE", "✓ DEVELOPER PERKS"};
  for (auto &f: features) {
    QLabel* feature = new QLabel(f);
    feature->setStyleSheet(R"(font-size: 40px;)");
    vlayout->addWidget(feature, 0, Qt::AlignBottom);
  }

  setLayout(vlayout);
}

SetupWidget::SetupWidget(QWidget* parent) : QFrame(parent) {
  mainLayout = new QStackedWidget;

  // Unpaired, registration prompt layout

  QVBoxLayout* finishRegistationLayout = new QVBoxLayout;
  finishRegistationLayout->setMargin(30);

  QLabel* registrationDescription = new QLabel("Pair your device with the comma connect app");
  registrationDescription->setWordWrap(true);
  registrationDescription->setAlignment(Qt::AlignCenter);
  registrationDescription->setStyleSheet(R"(
    font-size: 55px;
    font-weight: 400;
  )");

  finishRegistationLayout->addWidget(registrationDescription);

  QPushButton* finishButton = new QPushButton("Finish setup");
  finishButton->setFixedHeight(200);
  finishButton->setStyleSheet(R"(
    border-radius: 30px;
    font-size: 55px;
    font-weight: 500;
    background: #585858;
  )");
  finishRegistationLayout->addWidget(finishButton);
  QObject::connect(finishButton, SIGNAL(released()), this, SLOT(showQrCode()));

  QWidget* finishRegistration = new QWidget;
  finishRegistration->setLayout(finishRegistationLayout);
  mainLayout->addWidget(finishRegistration);

  // Pairing QR code layout

  QVBoxLayout* qrLayout = new QVBoxLayout;

  qrLayout->addSpacing(30);
  QLabel* qrLabel = new QLabel("Scan with comma connect!");
  qrLabel->setWordWrap(true);
  qrLabel->setAlignment(Qt::AlignHCenter);
  qrLabel->setStyleSheet(R"(
    font-size: 55px;
    font-weight: 400;
  )");
  qrLayout->addWidget(qrLabel, 0, Qt::AlignTop);

  qrLayout->addWidget(new PairingQRWidget, 1);

  QWidget* q = new QWidget;
  q->setLayout(qrLayout);
  mainLayout->addWidget(q);

  primeAd = new PrimeAdWidget;
  mainLayout->addWidget(primeAd);

  primeUser = new PrimeUserWidget;
  mainLayout->addWidget(primeUser);

  mainLayout->setCurrentWidget(primeAd);

  QVBoxLayout *layout = new QVBoxLayout;
  layout->addWidget(mainLayout);
  setLayout(layout);

  setStyleSheet(R"(
    SetupWidget {
      background-color: #292929;
    }
    * {
      font-size: 90px;
      font-weight: 500;
      border-radius: 40px;
    }
  )");

  // Retain size while hidden
  QSizePolicy sp_retain = sizePolicy();
  sp_retain.setRetainSizeWhenHidden(true);
  setSizePolicy(sp_retain);

  // set up API requests
  QString dongleId = QString::fromStdString(Params().get("DongleId"));
  QString url = "https://api.commadotai.com/v1.1/devices/" + dongleId + "/";
  RequestRepeater* repeater = new RequestRepeater(this, url, 5, "ApiCache_Device");

  QObject::connect(repeater, SIGNAL(receivedResponse(QString)), this, SLOT(replyFinished(QString)));
  QObject::connect(repeater, SIGNAL(failedResponse(QString)), this, SLOT(parseError(QString)));
  hide(); // Only show when first request comes back
}

void SetupWidget::parseError(QString response) {
  show();
  showQr = false;
  mainLayout->setCurrentIndex(0);
}

void SetupWidget::showQrCode(){
  showQr = true;
  mainLayout->setCurrentIndex(1);
}

void SetupWidget::replyFinished(QString response) {
  show();
  QJsonDocument doc = QJsonDocument::fromJson(response.toUtf8());
  if (doc.isNull()) {
    qDebug() << "JSON Parse failed on getting pairing and prime status";
    return;
  }

  QJsonObject json = doc.object();
  bool is_paired = json["is_paired"].toBool();
  bool is_prime = json["prime"].toBool();

  if (!is_paired) {
    mainLayout->setCurrentIndex(showQr);
  } else if (!is_prime) {
    showQr = false;
    mainLayout->setCurrentWidget(primeAd);
  } else {
    showQr = false;
    mainLayout->setCurrentWidget(primeUser);
  }
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2003-2009, John Wiegley.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 * - Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in the
 *   documentation and/or other materials provided with the distribution.
 *
 * - Neither the name of New Artisans LLC nor the names of its
 *   contributors may be used to endorse or promote products derived from
 *   this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <system.hh>

#include "derive.h"
#include "xact.h"
#include "post.h"
#include "account.h"
#include "journal.h"
#include "session.h"
#include "report.h"
#include "output.h"

namespace ledger {

namespace {
  struct xact_template_t
  {
    optional<date_t> date;
    optional<string> code;
    optional<string> note;
    mask_t           payee_mask;

    struct post_template_t {
      bool               from;
      optional<mask_t>   account_mask;
      optional<amount_t> amount;

      post_template_t() : from(false) {}
    };

    std::list<post_template_t> posts;

    xact_template_t() {}

    void dump(std::ostream& out) const
    {
      if (date)
	out << _("Date:       ") << *date << std::endl;
      else
	out << _("Date:       <today>") << std::endl;

      if (code)
	out << _("Code:       ") << *code << std::endl;
      if (note)
	out << _("Note:       ") << *note << std::endl;

      if (payee_mask.empty())
	out << _("Payee mask: INVALID (template expression will cause an error)")
	    << std::endl;
      else
	out << _("Payee mask: ") << payee_mask << std::endl;

      if (posts.empty()) {
	out << std::endl
	    << _("<Posting copied from last related transaction>")
	    << std::endl;
      } else {
	bool has_only_from = true;
	bool has_only_to   = true;

	foreach (const post_template_t& post, posts) {
	  if (post.from)
	    has_only_to = false;
	  else
	    has_only_from = false;
	}

	foreach (const post_template_t& post, posts) {
	  straccstream accum;
	  out << std::endl
	      << ACCUM(accum << _("[Posting \"%1\"]_")
		       << (post.from ? _("from") : _("to")))
	      << std::endl;

	  if (post.account_mask)
	    out << _("  Account mask: ") << *post.account_mask << std::endl;
	  else if (post.from)
	    out << _("  Account mask: <use last of last related accounts>") << std::endl;
	  else
	    out << _("  Account mask: <use first of last related accounts>") << std::endl;

	  if (post.amount)
	    out << _("  Amount:       ") << *post.amount << std::endl;
	}
      }
    }
  };

  xact_template_t
  args_to_xact_template(value_t::sequence_t::const_iterator begin,
			 value_t::sequence_t::const_iterator end)
  {
    regex  date_mask(_("([0-9]+(?:[-/.][0-9]+)?(?:[-/.][0-9]+))?"));
    smatch what;

    xact_template_t tmpl;
    bool	    check_for_date = true;

    optional<date_time::weekdays>      weekday;
    xact_template_t::post_template_t * post = NULL;

    for (; begin != end; begin++) {
      if (check_for_date &&
	  regex_match((*begin).to_string(), what, date_mask)) {
	tmpl.date = parse_date(what[0]);
	check_for_date = false;
      }
      else if (check_for_date &&
	       bool(weekday = string_to_day_of_week(what[0]))) {
	short  dow  = static_cast<short>(*weekday);
	date_t date = CURRENT_DATE() - date_duration(1);
	while (date.day_of_week() != dow)
	  date -= date_duration(1);
	tmpl.date = date;
	check_for_date = false;
      }
      else {
	string arg = (*begin).to_string();

	if (arg == "at") {
	  tmpl.payee_mask = (*++begin).to_string();
	}
	else if (arg == "to" || arg == "from") {
	  if (! post || post->account_mask) {
	    tmpl.posts.push_back(xact_template_t::post_template_t());
	    post = &tmpl.posts.back();
	  }
	  post->account_mask = mask_t((*++begin).to_string());
	  post->from = arg == "from";
	}
	else if (arg == "on") {
	  tmpl.date = parse_date((*++begin).to_string());
	  check_for_date = false;
	}
	else if (arg == "code") {
	  tmpl.code = (*++begin).to_string();
	}
	else if (arg == "note") {
	  tmpl.note = (*++begin).to_string();
	}
	else if (arg == "rest") {
	  ;			// just ignore this argument
	}
	else {
	  // Without a preposition, it is either:
	  //
	  //  A payee, if we have not seen one
	  //  An account or an amount, if we have
	  //  An account if an amount has just been seen
	  //  An amount if an account has just been seen

	  if (tmpl.payee_mask.empty()) {
	    tmpl.payee_mask = arg;
	  }
	  else {
	    amount_t	     amt;
	    optional<mask_t> account;

	    if (! amt.parse(arg, amount_t::PARSE_SOFT_FAIL |
			    amount_t::PARSE_NO_MIGRATE))
	      account = mask_t(arg);

	    if (! post ||
		(account && post->account_mask) ||
		(! account && post->amount)) {
	      tmpl.posts.push_back(xact_template_t::post_template_t());
	      post = &tmpl.posts.back();
	    }

	    if (account) {
	      post->from = false;
	      post->account_mask = account;
	    } else {
	      post->amount = amt;
	    }
	  }
	}
      }
    }

    if (! tmpl.posts.empty()) {
      bool has_only_from = true;
      bool has_only_to   = true;

      // A single account at the end of the line is the "from" account
      if (tmpl.posts.size() > 1 &&
	  tmpl.posts.back().account_mask && ! tmpl.posts.back().amount)
	tmpl.posts.back().from = true;

      foreach (xact_template_t::post_template_t& post, tmpl.posts) {
	if (post.from)
	  has_only_to = false;
	else
	  has_only_from = false;
      }

      if (has_only_from) {
	tmpl.posts.push_front(xact_template_t::post_template_t());
      }
      else if (has_only_to) {
	tmpl.posts.push_back(xact_template_t::post_template_t());
	tmpl.posts.back().from = true;
      }
    }

    return tmpl;
  }

  xact_t * derive_xact_from_template(xact_template_t& tmpl,
				     report_t&	      report)
  {
    if (tmpl.payee_mask.empty())
      throw std::runtime_error(_("'xact' command requires at least a payee"));

    xact_t *  matching = NULL;
    journal_t& journal(*report.session.journal.get());

    std::auto_ptr<xact_t> added(new xact_t);

    xacts_list::reverse_iterator j;

    for (j = journal.xacts.rbegin();
	 j != journal.xacts.rend();
	 j++) {
      if (tmpl.payee_mask.match((*j)->payee)) {
	matching = *j;
	break;
      }
    }

    if (! tmpl.date)
      added->_date = CURRENT_DATE();
    else
      added->_date = tmpl.date;

    added->set_state(item_t::UNCLEARED);

    if (matching) {
      added->payee = matching->payee;
      added->code  = matching->code;
      added->note  = matching->note;
    } else {
      added->payee = tmpl.payee_mask.expr.str();
    }

    if (tmpl.code)
      added->code = tmpl.code;
    if (tmpl.note)
      added->note = tmpl.note;

    if (tmpl.posts.empty()) {
      if (matching) {
	foreach (post_t * post, matching->posts) {
	  added->add_post(new post_t(*post));
	  added->posts.back()->set_state(item_t::UNCLEARED);
	}
      } else {
	throw_(std::runtime_error,
	       _("No accounts, and no past transaction matching '%1'")
	       << tmpl.payee_mask);
      }
    } else {
      bool any_post_has_amount = false;
      foreach (xact_template_t::post_template_t& post, tmpl.posts) {
	if (post.amount) {
	  any_post_has_amount = true;
	  break;
	}
      }

      foreach (xact_template_t::post_template_t& post, tmpl.posts) {
	std::auto_ptr<post_t> new_post;

	commodity_t * found_commodity = NULL;

	if (matching) {
	  if (post.account_mask) {
	    foreach (post_t * x, matching->posts) {
	      if (post.account_mask->match(x->account->fullname())) {
		new_post.reset(new post_t(*x));
		break;
	      }
	    }
	  } else {
	    if (post.from)
	      new_post.reset(new post_t(*matching->posts.back()));
	    else
	      new_post.reset(new post_t(*matching->posts.front()));
	  }
	}

	if (! new_post.get())
	  new_post.reset(new post_t);

	if (! new_post->account) {
	  if (post.account_mask) {
	    account_t * acct = NULL;
	    if (! acct)
	      acct = journal.find_account_re(post.account_mask->expr.str());
	    if (! acct)
	      acct = journal.find_account(post.account_mask->expr.str());

	    // Find out the default commodity to use by looking at the last
	    // commodity used in that account
	    xacts_list::reverse_iterator j;

	    for (j = journal.xacts.rbegin();
		 j != journal.xacts.rend();
		 j++) {
	      foreach (post_t * x, (*j)->posts) {
		if (x->account == acct && ! x->amount.is_null()) {
		  new_post.reset(new post_t(*x));
		  break;
		}
	      }
	    }
	    if (! new_post.get())
	      new_post.reset(new post_t);

	    new_post->account = acct;
	  } else {

	    if (post.from)
	      new_post->account = journal.find_account(_("Liabilities:Unknown"));
	    else
	      new_post->account = journal.find_account(_("Expenses:Unknown"));
	  }
	}

	if (new_post.get() && ! new_post->amount.is_null()) {
	  found_commodity = &new_post->amount.commodity();

	  if (any_post_has_amount)
	    new_post->amount = amount_t();
	  else
	    any_post_has_amount = true;
	}

	if (post.amount) {
	  new_post->amount = *post.amount;
	  if (post.from)
	    new_post->amount.in_place_negate();
	}

	if (found_commodity &&
	    ! new_post->amount.is_null() &&
	    ! new_post->amount.has_commodity()) {
	  new_post->amount.set_commodity(*found_commodity);
	  new_post->amount = new_post->amount.rounded();
	}

	added->add_post(new_post.release());
	added->posts.back()->set_state(item_t::UNCLEARED);
      }
    }

    if (! journal.xact_finalize_hooks.run_hooks(*added.get(), false) ||
	! added->finalize() ||
	! journal.xact_finalize_hooks.run_hooks(*added.get(), true))
      throw_(std::runtime_error,
	     _("Failed to finalize derived transaction (check commodities)"));

    return added.release();
  }
}

value_t template_command(call_scope_t& args)
{
  report_t& report(find_scope<report_t>(args));
  std::ostream& out(report.output_stream);

  value_t::sequence_t::const_iterator begin = args.value().begin();
  value_t::sequence_t::const_iterator end   = args.value().end();

  out << _("--- Input arguments ---") << std::endl;
  args.value().dump(out);
  out << std::endl << std::endl;

  xact_template_t tmpl = args_to_xact_template(begin, end);

  out << _("--- Transaction template ---") << std::endl;
  tmpl.dump(out);

  return true;
}

value_t xact_command(call_scope_t& args)
{
  value_t::sequence_t::const_iterator begin = args.value().begin();
  value_t::sequence_t::const_iterator end   = args.value().end();

  report_t&		report(find_scope<report_t>(args));
  xact_template_t	tmpl = args_to_xact_template(begin, end);
  std::auto_ptr<xact_t> new_xact(derive_xact_from_template(tmpl, report));

  // jww (2009-02-27): make this more general
  report.HANDLER(limit_).on(string("#xact"), "actual");

  report.xact_report(post_handler_ptr
		      (new format_posts(report,
					report.HANDLER(print_format_).str())),
		      *new_xact.get());
  return true;
}

} // namespace ledger
<commit_msg>Corrected a minor typo<commit_after>/*
 * Copyright (c) 2003-2009, John Wiegley.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 * - Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in the
 *   documentation and/or other materials provided with the distribution.
 *
 * - Neither the name of New Artisans LLC nor the names of its
 *   contributors may be used to endorse or promote products derived from
 *   this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <system.hh>

#include "derive.h"
#include "xact.h"
#include "post.h"
#include "account.h"
#include "journal.h"
#include "session.h"
#include "report.h"
#include "output.h"

namespace ledger {

namespace {
  struct xact_template_t
  {
    optional<date_t> date;
    optional<string> code;
    optional<string> note;
    mask_t           payee_mask;

    struct post_template_t {
      bool               from;
      optional<mask_t>   account_mask;
      optional<amount_t> amount;

      post_template_t() : from(false) {}
    };

    std::list<post_template_t> posts;

    xact_template_t() {}

    void dump(std::ostream& out) const
    {
      if (date)
	out << _("Date:       ") << *date << std::endl;
      else
	out << _("Date:       <today>") << std::endl;

      if (code)
	out << _("Code:       ") << *code << std::endl;
      if (note)
	out << _("Note:       ") << *note << std::endl;

      if (payee_mask.empty())
	out << _("Payee mask: INVALID (template expression will cause an error)")
	    << std::endl;
      else
	out << _("Payee mask: ") << payee_mask << std::endl;

      if (posts.empty()) {
	out << std::endl
	    << _("<Posting copied from last related transaction>")
	    << std::endl;
      } else {
	bool has_only_from = true;
	bool has_only_to   = true;

	foreach (const post_template_t& post, posts) {
	  if (post.from)
	    has_only_to = false;
	  else
	    has_only_from = false;
	}

	foreach (const post_template_t& post, posts) {
	  straccstream accum;
	  out << std::endl
	      << ACCUM(accum << _("[Posting \"%1\"]")
		       << (post.from ? _("from") : _("to")))
	      << std::endl;

	  if (post.account_mask)
	    out << _("  Account mask: ") << *post.account_mask << std::endl;
	  else if (post.from)
	    out << _("  Account mask: <use last of last related accounts>") << std::endl;
	  else
	    out << _("  Account mask: <use first of last related accounts>") << std::endl;

	  if (post.amount)
	    out << _("  Amount:       ") << *post.amount << std::endl;
	}
      }
    }
  };

  xact_template_t
  args_to_xact_template(value_t::sequence_t::const_iterator begin,
			 value_t::sequence_t::const_iterator end)
  {
    regex  date_mask(_("([0-9]+(?:[-/.][0-9]+)?(?:[-/.][0-9]+))?"));
    smatch what;

    xact_template_t tmpl;
    bool	    check_for_date = true;

    optional<date_time::weekdays>      weekday;
    xact_template_t::post_template_t * post = NULL;

    for (; begin != end; begin++) {
      if (check_for_date &&
	  regex_match((*begin).to_string(), what, date_mask)) {
	tmpl.date = parse_date(what[0]);
	check_for_date = false;
      }
      else if (check_for_date &&
	       bool(weekday = string_to_day_of_week(what[0]))) {
	short  dow  = static_cast<short>(*weekday);
	date_t date = CURRENT_DATE() - date_duration(1);
	while (date.day_of_week() != dow)
	  date -= date_duration(1);
	tmpl.date = date;
	check_for_date = false;
      }
      else {
	string arg = (*begin).to_string();

	if (arg == "at") {
	  tmpl.payee_mask = (*++begin).to_string();
	}
	else if (arg == "to" || arg == "from") {
	  if (! post || post->account_mask) {
	    tmpl.posts.push_back(xact_template_t::post_template_t());
	    post = &tmpl.posts.back();
	  }
	  post->account_mask = mask_t((*++begin).to_string());
	  post->from = arg == "from";
	}
	else if (arg == "on") {
	  tmpl.date = parse_date((*++begin).to_string());
	  check_for_date = false;
	}
	else if (arg == "code") {
	  tmpl.code = (*++begin).to_string();
	}
	else if (arg == "note") {
	  tmpl.note = (*++begin).to_string();
	}
	else if (arg == "rest") {
	  ;			// just ignore this argument
	}
	else {
	  // Without a preposition, it is either:
	  //
	  //  A payee, if we have not seen one
	  //  An account or an amount, if we have
	  //  An account if an amount has just been seen
	  //  An amount if an account has just been seen

	  if (tmpl.payee_mask.empty()) {
	    tmpl.payee_mask = arg;
	  }
	  else {
	    amount_t	     amt;
	    optional<mask_t> account;

	    if (! amt.parse(arg, amount_t::PARSE_SOFT_FAIL |
			    amount_t::PARSE_NO_MIGRATE))
	      account = mask_t(arg);

	    if (! post ||
		(account && post->account_mask) ||
		(! account && post->amount)) {
	      tmpl.posts.push_back(xact_template_t::post_template_t());
	      post = &tmpl.posts.back();
	    }

	    if (account) {
	      post->from = false;
	      post->account_mask = account;
	    } else {
	      post->amount = amt;
	    }
	  }
	}
      }
    }

    if (! tmpl.posts.empty()) {
      bool has_only_from = true;
      bool has_only_to   = true;

      // A single account at the end of the line is the "from" account
      if (tmpl.posts.size() > 1 &&
	  tmpl.posts.back().account_mask && ! tmpl.posts.back().amount)
	tmpl.posts.back().from = true;

      foreach (xact_template_t::post_template_t& post, tmpl.posts) {
	if (post.from)
	  has_only_to = false;
	else
	  has_only_from = false;
      }

      if (has_only_from) {
	tmpl.posts.push_front(xact_template_t::post_template_t());
      }
      else if (has_only_to) {
	tmpl.posts.push_back(xact_template_t::post_template_t());
	tmpl.posts.back().from = true;
      }
    }

    return tmpl;
  }

  xact_t * derive_xact_from_template(xact_template_t& tmpl,
				     report_t&	      report)
  {
    if (tmpl.payee_mask.empty())
      throw std::runtime_error(_("'xact' command requires at least a payee"));

    xact_t *  matching = NULL;
    journal_t& journal(*report.session.journal.get());

    std::auto_ptr<xact_t> added(new xact_t);

    xacts_list::reverse_iterator j;

    for (j = journal.xacts.rbegin();
	 j != journal.xacts.rend();
	 j++) {
      if (tmpl.payee_mask.match((*j)->payee)) {
	matching = *j;
	break;
      }
    }

    if (! tmpl.date)
      added->_date = CURRENT_DATE();
    else
      added->_date = tmpl.date;

    added->set_state(item_t::UNCLEARED);

    if (matching) {
      added->payee = matching->payee;
      added->code  = matching->code;
      added->note  = matching->note;
    } else {
      added->payee = tmpl.payee_mask.expr.str();
    }

    if (tmpl.code)
      added->code = tmpl.code;
    if (tmpl.note)
      added->note = tmpl.note;

    if (tmpl.posts.empty()) {
      if (matching) {
	foreach (post_t * post, matching->posts) {
	  added->add_post(new post_t(*post));
	  added->posts.back()->set_state(item_t::UNCLEARED);
	}
      } else {
	throw_(std::runtime_error,
	       _("No accounts, and no past transaction matching '%1'")
	       << tmpl.payee_mask);
      }
    } else {
      bool any_post_has_amount = false;
      foreach (xact_template_t::post_template_t& post, tmpl.posts) {
	if (post.amount) {
	  any_post_has_amount = true;
	  break;
	}
      }

      foreach (xact_template_t::post_template_t& post, tmpl.posts) {
	std::auto_ptr<post_t> new_post;

	commodity_t * found_commodity = NULL;

	if (matching) {
	  if (post.account_mask) {
	    foreach (post_t * x, matching->posts) {
	      if (post.account_mask->match(x->account->fullname())) {
		new_post.reset(new post_t(*x));
		break;
	      }
	    }
	  } else {
	    if (post.from)
	      new_post.reset(new post_t(*matching->posts.back()));
	    else
	      new_post.reset(new post_t(*matching->posts.front()));
	  }
	}

	if (! new_post.get())
	  new_post.reset(new post_t);

	if (! new_post->account) {
	  if (post.account_mask) {
	    account_t * acct = NULL;
	    if (! acct)
	      acct = journal.find_account_re(post.account_mask->expr.str());
	    if (! acct)
	      acct = journal.find_account(post.account_mask->expr.str());

	    // Find out the default commodity to use by looking at the last
	    // commodity used in that account
	    xacts_list::reverse_iterator j;

	    for (j = journal.xacts.rbegin();
		 j != journal.xacts.rend();
		 j++) {
	      foreach (post_t * x, (*j)->posts) {
		if (x->account == acct && ! x->amount.is_null()) {
		  new_post.reset(new post_t(*x));
		  break;
		}
	      }
	    }
	    if (! new_post.get())
	      new_post.reset(new post_t);

	    new_post->account = acct;
	  } else {

	    if (post.from)
	      new_post->account = journal.find_account(_("Liabilities:Unknown"));
	    else
	      new_post->account = journal.find_account(_("Expenses:Unknown"));
	  }
	}

	if (new_post.get() && ! new_post->amount.is_null()) {
	  found_commodity = &new_post->amount.commodity();

	  if (any_post_has_amount)
	    new_post->amount = amount_t();
	  else
	    any_post_has_amount = true;
	}

	if (post.amount) {
	  new_post->amount = *post.amount;
	  if (post.from)
	    new_post->amount.in_place_negate();
	}

	if (found_commodity &&
	    ! new_post->amount.is_null() &&
	    ! new_post->amount.has_commodity()) {
	  new_post->amount.set_commodity(*found_commodity);
	  new_post->amount = new_post->amount.rounded();
	}

	added->add_post(new_post.release());
	added->posts.back()->set_state(item_t::UNCLEARED);
      }
    }

    if (! journal.xact_finalize_hooks.run_hooks(*added.get(), false) ||
	! added->finalize() ||
	! journal.xact_finalize_hooks.run_hooks(*added.get(), true))
      throw_(std::runtime_error,
	     _("Failed to finalize derived transaction (check commodities)"));

    return added.release();
  }
}

value_t template_command(call_scope_t& args)
{
  report_t& report(find_scope<report_t>(args));
  std::ostream& out(report.output_stream);

  value_t::sequence_t::const_iterator begin = args.value().begin();
  value_t::sequence_t::const_iterator end   = args.value().end();

  out << _("--- Input arguments ---") << std::endl;
  args.value().dump(out);
  out << std::endl << std::endl;

  xact_template_t tmpl = args_to_xact_template(begin, end);

  out << _("--- Transaction template ---") << std::endl;
  tmpl.dump(out);

  return true;
}

value_t xact_command(call_scope_t& args)
{
  value_t::sequence_t::const_iterator begin = args.value().begin();
  value_t::sequence_t::const_iterator end   = args.value().end();

  report_t&		report(find_scope<report_t>(args));
  xact_template_t	tmpl = args_to_xact_template(begin, end);
  std::auto_ptr<xact_t> new_xact(derive_xact_from_template(tmpl, report));

  // jww (2009-02-27): make this more general
  report.HANDLER(limit_).on(string("#xact"), "actual");

  report.xact_report(post_handler_ptr
		      (new format_posts(report,
					report.HANDLER(print_format_).str())),
		      *new_xact.get());
  return true;
}

} // namespace ledger
<|endoftext|>


<commit_before>#include "general.hpp"
#include "course.hpp"
#include "student.hpp"
using namespace std;

vector<Course> all_courses;
Student user;

void loadCourses(string filename) {
	ifstream infile(filename.c_str());
	string str; // read in the header line
	getline(infile, str);
	while (infile.peek() != -1){
		Course incourse(infile);
		all_courses.push_back(incourse);
		// cout << incourse << endl;
	}

	// for (vector<Course>::iterator c = all_courses.begin(); c != all_courses.end(); ++c) {
	// 	if (c->getProfessor()[1] == ' ')
	// 		if (c->getProfessor()[2] == '0' || c->getProfessor()[2] == '1')
	// 			cout << *c << endl;
	// 	if (c->getDepartment(0) == NONE)
	// 		cout << *c << endl;
	// }
}

void readData() {
	loadCourses("data/2012-13-s2.csv");
	loadCourses("data/2012-13-interim.csv");
	loadCourses("data/2012-13-s1.csv");

	loadCourses("data/2011-12-s2.csv");
	loadCourses("data/2011-12-interim.csv");
	loadCourses("data/2011-12-s1.csv");

	loadCourses("data/2010-11-s2.csv");
	loadCourses("data/2010-11-interim.csv");
	loadCourses("data/2010-11-s1.csv");
}

void welcome() {
	string name, yearS = "", yearE = "", majors;
	cout << "Welcome!" << endl;
	cout << "What is your name? ";
	getline(cin, name);
	cout << "What year do you graduate? ";
	getline(cin, yearE);
	cout << "What are your majors (ex. CSCI, ASIAN) ";
	getline(cin, majors);
	user = Student(name, yearS, yearE, majors);
}

void requestCourses() {
	string courses;
	cout << "What are some courses that you have taken? (ex. CSCI125, STAT 110)" << endl;
	getline(cin, courses);
	user.addCourses(courses);
}

int main(int argc, const char *argv[]) {
	readData();

	// Method 1: Dynamic.
	// welcome();
	// requestCourses();

	// Method 2: Hard-coded file path.
	user = Student("data/example.txt");

	// Method 3: File path as an argument.
	// Student user(argv[1]);

	user.updateStanding();
	user.display();

	return 0;
}
<commit_msg>Add some command-line arguments to the program<commit_after>#include "general.hpp"
#include "course.hpp"
#include "student.hpp"
using namespace std;

vector<Course> all_courses;
Student user;

void loadCourses(string filename) {
	ifstream infile(filename.c_str());
	string str; // read in the header line
	getline(infile, str);
	while (infile.peek() != -1){
		Course incourse(infile);
		all_courses.push_back(incourse);
		// cout << incourse << endl;
	}
}

void readData() {
	loadCourses("data/2012-13-s2.csv");
	loadCourses("data/2012-13-interim.csv");
	loadCourses("data/2012-13-s1.csv");

	loadCourses("data/2011-12-s2.csv");
	loadCourses("data/2011-12-interim.csv");
	loadCourses("data/2011-12-s1.csv");

	loadCourses("data/2010-11-s2.csv");
	loadCourses("data/2010-11-interim.csv");
	loadCourses("data/2010-11-s1.csv");
}

vector<string> parseArguments(int argc, const char* argv[]) {
//	cout << argc << endl;
	vector<string> arguments;
	for (int i = 1; i < argc; i++) {
//		cout << argv[i] << endl;
		arguments.push_back(argv[i]);
	}
	return arguments;
}

int main(int argc, const char *argv[]) {
	vector<string> arguments = parseArguments(argc, argv);
	readData();

	if (arguments.size() > 0) {
		string arg0 = arguments.at(0);
		if (arg0 == "--find" || arg0 == "-f") {
			if (arguments.size() == 2) {
				Course c = Course(arguments.at(1));
				c.display();
			}
		}

		else if (arg0 == "--load" || arg0 == "-l") {
			if (arguments.size() == 2) {
				user = Student(arguments.at(1));
				user.display();
			}
		}

		else if (arg0 == "--demo") {
			user = Student("data/example.txt");
			user.display();
		}

		else if (arg0 == "--stress") {
			user = Student("data/stress.txt");
			user.display();
		}

		else if (arg0 == "--debug") {
			for (vector<Course>::iterator c = all_courses.begin(); c != all_courses.end(); ++c) {
				if (c->getProfessor()[1] == ' ')
					if (c->getProfessor()[2] == '0' || c->getProfessor()[2] == '1')
						cout << *c << endl;
				if (c->getDepartment(0) == NONE)
					cout << *c << endl;
			}
		}

		else if (arg0 == "--interactive" || arg0 == "-i") {
			string name, yearS = "", yearE = "", majors;
			cout << "Welcome!" << endl;
			cout << "What is your name? ";
			getline(cin, name);
			cout << "What year do you graduate? ";
			getline(cin, yearE);
			cout << "What are your majors (ex. CSCI, ASIAN) ";
			getline(cin, majors);
			user = Student(name, yearS, yearE, majors);

			string courses;
			cout << "What are some courses that you have taken? (ex. CSCI125, STAT 110)" << endl;
			getline(cin, courses);
			user.addCourses(courses);

			user.display();
		}
	}
	else {
		cout << "This program works best if you give it some data ;)" << endl;
		cout << "However, we have some example stuff to show you anyway." << endl;
		user = Student("data/example.txt");
		user.display();
	}

	return 0;
}
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/
**
** This file is part of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qgstreamermetadataprovider.h"
#include "qgstreamerplayersession.h"
#include <QDebug>

#include <gst/gstversion.h>

QT_BEGIN_NAMESPACE

struct QGstreamerMetaDataKeyLookup
{
    QString key;
    const char *token;
};

static const QGstreamerMetaDataKeyLookup qt_gstreamerMetaDataKeys[] =
{
    { QtMultimedia::MetaData::Title, GST_TAG_TITLE },
    //{ QtMultimedia::MetaData::SubTitle, 0 },
    //{ QtMultimedia::MetaData::Author, 0 },
    { QtMultimedia::MetaData::Comment, GST_TAG_COMMENT },
    { QtMultimedia::MetaData::Description, GST_TAG_DESCRIPTION },
    //{ QtMultimedia::MetaData::Category, 0 },
    { QtMultimedia::MetaData::Genre, GST_TAG_GENRE },
    { QtMultimedia::MetaData::Year, "year" },
    //{ QtMultimedia::MetaData::UserRating, 0 },

    { QtMultimedia::MetaData::Language, GST_TAG_LANGUAGE_CODE },

    { QtMultimedia::MetaData::Publisher, GST_TAG_ORGANIZATION },
    { QtMultimedia::MetaData::Copyright, GST_TAG_COPYRIGHT },
    //{ QtMultimedia::MetaData::ParentalRating, 0 },
    //{ QtMultimedia::MetaData::RatingOrganisation, 0 },

    // Media
    //{ QtMultimedia::MetaData::Size, 0 },
    //{ QtMultimedia::MetaData::MediaType, 0 },
    { QtMultimedia::MetaData::Duration, GST_TAG_DURATION },

    // Audio
    { QtMultimedia::MetaData::AudioBitRate, GST_TAG_BITRATE },
    { QtMultimedia::MetaData::AudioCodec, GST_TAG_AUDIO_CODEC },
    //{ QtMultimedia::MetaData::ChannelCount, 0 },
    //{ QtMultimedia::MetaData::SampleRate, 0 },

    // Music
    { QtMultimedia::MetaData::AlbumTitle, GST_TAG_ALBUM },
    { QtMultimedia::MetaData::AlbumArtist,  GST_TAG_ARTIST},
    { QtMultimedia::MetaData::ContributingArtist, GST_TAG_PERFORMER },
#if (GST_VERSION_MAJOR >= 0) && (GST_VERSION_MINOR >= 10) && (GST_VERSION_MICRO >= 19)
    { QtMultimedia::MetaData::Composer, GST_TAG_COMPOSER },
#endif
    //{ QtMultimedia::MetaData::Conductor, 0 },
    //{ QtMultimedia::MetaData::Lyrics, 0 },
    //{ QtMultimedia::MetaData::Mood, 0 },
    { QtMultimedia::MetaData::TrackNumber, GST_TAG_TRACK_NUMBER },

    //{ QtMultimedia::MetaData::CoverArtUrlSmall, 0 },
    //{ QtMultimedia::MetaData::CoverArtUrlLarge, 0 },

    // Image/Video
    { QtMultimedia::MetaData::Resolution, "resolution" },
    { QtMultimedia::MetaData::PixelAspectRatio, "pixel-aspect-ratio" },

    // Video
    //{ QtMultimedia::MetaData::VideoFrameRate, 0 },
    //{ QtMultimedia::MetaData::VideoBitRate, 0 },
    { QtMultimedia::MetaData::VideoCodec, GST_TAG_VIDEO_CODEC },

    //{ QtMultimedia::MetaData::PosterUrl, 0 },

    // Movie
    //{ QtMultimedia::MetaData::ChapterNumber, 0 },
    //{ QtMultimedia::MetaData::Director, 0 },
    { QtMultimedia::MetaData::LeadPerformer, GST_TAG_PERFORMER },
    //{ QtMultimedia::MetaData::Writer, 0 },

    // Photos
    //{ QtMultimedia::MetaData::CameraManufacturer, 0 },
    //{ QtMultimedia::MetaData::CameraModel, 0 },
    //{ QtMultimedia::MetaData::Event, 0 },
    //{ QtMultimedia::MetaData::Subject, 0 }
};

QGstreamerMetaDataProvider::QGstreamerMetaDataProvider(QGstreamerPlayerSession *session, QObject *parent)
    :QMetaDataReaderControl(parent), m_session(session)
{
    connect(m_session, SIGNAL(tagsChanged()), SLOT(updateTags()));

    const int count = sizeof(qt_gstreamerMetaDataKeys) / sizeof(QGstreamerMetaDataKeyLookup);
    for (int i = 0; i < count; ++i) {
        m_keysMap[QByteArray(qt_gstreamerMetaDataKeys[i].token)] = qt_gstreamerMetaDataKeys[i].key;
    }
}

QGstreamerMetaDataProvider::~QGstreamerMetaDataProvider()
{
}

bool QGstreamerMetaDataProvider::isMetaDataAvailable() const
{
    return !m_session->tags().isEmpty();
}

bool QGstreamerMetaDataProvider::isWritable() const
{
    return false;
}

QVariant QGstreamerMetaDataProvider::metaData(const QString &key) const
{
    return m_tags.value(key);
}

QStringList QGstreamerMetaDataProvider::availableMetaData() const
{
    return m_tags.keys();
}

void QGstreamerMetaDataProvider::updateTags()
{
    QVariantMap oldTags = m_tags;
    m_tags.clear();

    QSet<QString> allTags = QSet<QString>::fromList(m_tags.keys());

    QMapIterator<QByteArray ,QVariant> i(m_session->tags());
    while (i.hasNext()) {
         i.next();
         //use gstreamer native keys for elements not in m_keysMap
         QString key = m_keysMap.value(i.key(), i.key());
         m_tags[key] = i.value();
         allTags.insert(i.key());
    }

    bool changed = false;
    foreach (const QString &key, allTags) {
        const QVariant value = m_tags.value(key);
        if (value != oldTags.value(key)) {
            changed = true;
            emit metaDataChanged(key, value);
        }
    }

    if (changed)
        emit metaDataChanged();
}

QT_END_NAMESPACE
<commit_msg>QGstreamerMetaDataProvider: fix keys not mapped properly.<commit_after>/****************************************************************************
**
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/
**
** This file is part of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qgstreamermetadataprovider.h"
#include "qgstreamerplayersession.h"
#include <QDebug>

#include <gst/gstversion.h>

QT_BEGIN_NAMESPACE

struct QGstreamerMetaDataKeyLookup
{
    QString key;
    const char *token;
};

static const QGstreamerMetaDataKeyLookup qt_gstreamerMetaDataKeys[] =
{
    { QtMultimedia::MetaData::Title, GST_TAG_TITLE },
    //{ QtMultimedia::MetaData::SubTitle, 0 },
    //{ QtMultimedia::MetaData::Author, 0 },
    { QtMultimedia::MetaData::Comment, GST_TAG_COMMENT },
    { QtMultimedia::MetaData::Description, GST_TAG_DESCRIPTION },
    //{ QtMultimedia::MetaData::Category, 0 },
    { QtMultimedia::MetaData::Genre, GST_TAG_GENRE },
    { QtMultimedia::MetaData::Year, "year" },
    //{ QtMultimedia::MetaData::UserRating, 0 },

    { QtMultimedia::MetaData::Language, GST_TAG_LANGUAGE_CODE },

    { QtMultimedia::MetaData::Publisher, GST_TAG_ORGANIZATION },
    { QtMultimedia::MetaData::Copyright, GST_TAG_COPYRIGHT },
    //{ QtMultimedia::MetaData::ParentalRating, 0 },
    //{ QtMultimedia::MetaData::RatingOrganisation, 0 },

    // Media
    //{ QtMultimedia::MetaData::Size, 0 },
    //{ QtMultimedia::MetaData::MediaType, 0 },
    { QtMultimedia::MetaData::Duration, GST_TAG_DURATION },

    // Audio
    { QtMultimedia::MetaData::AudioBitRate, GST_TAG_BITRATE },
    { QtMultimedia::MetaData::AudioCodec, GST_TAG_AUDIO_CODEC },
    //{ QtMultimedia::MetaData::ChannelCount, 0 },
    //{ QtMultimedia::MetaData::SampleRate, 0 },

    // Music
    { QtMultimedia::MetaData::AlbumTitle, GST_TAG_ALBUM },
    { QtMultimedia::MetaData::AlbumArtist,  GST_TAG_ARTIST},
    { QtMultimedia::MetaData::ContributingArtist, GST_TAG_PERFORMER },
#if (GST_VERSION_MAJOR >= 0) && (GST_VERSION_MINOR >= 10) && (GST_VERSION_MICRO >= 19)
    { QtMultimedia::MetaData::Composer, GST_TAG_COMPOSER },
#endif
    //{ QtMultimedia::MetaData::Conductor, 0 },
    //{ QtMultimedia::MetaData::Lyrics, 0 },
    //{ QtMultimedia::MetaData::Mood, 0 },
    { QtMultimedia::MetaData::TrackNumber, GST_TAG_TRACK_NUMBER },

    //{ QtMultimedia::MetaData::CoverArtUrlSmall, 0 },
    //{ QtMultimedia::MetaData::CoverArtUrlLarge, 0 },

    // Image/Video
    { QtMultimedia::MetaData::Resolution, "resolution" },
    { QtMultimedia::MetaData::PixelAspectRatio, "pixel-aspect-ratio" },

    // Video
    //{ QtMultimedia::MetaData::VideoFrameRate, 0 },
    //{ QtMultimedia::MetaData::VideoBitRate, 0 },
    { QtMultimedia::MetaData::VideoCodec, GST_TAG_VIDEO_CODEC },

    //{ QtMultimedia::MetaData::PosterUrl, 0 },

    // Movie
    //{ QtMultimedia::MetaData::ChapterNumber, 0 },
    //{ QtMultimedia::MetaData::Director, 0 },
    { QtMultimedia::MetaData::LeadPerformer, GST_TAG_PERFORMER },
    //{ QtMultimedia::MetaData::Writer, 0 },

    // Photos
    //{ QtMultimedia::MetaData::CameraManufacturer, 0 },
    //{ QtMultimedia::MetaData::CameraModel, 0 },
    //{ QtMultimedia::MetaData::Event, 0 },
    //{ QtMultimedia::MetaData::Subject, 0 }
};

QGstreamerMetaDataProvider::QGstreamerMetaDataProvider(QGstreamerPlayerSession *session, QObject *parent)
    :QMetaDataReaderControl(parent), m_session(session)
{
    connect(m_session, SIGNAL(tagsChanged()), SLOT(updateTags()));

    const int count = sizeof(qt_gstreamerMetaDataKeys) / sizeof(QGstreamerMetaDataKeyLookup);
    for (int i = 0; i < count; ++i) {
        m_keysMap[QByteArray(qt_gstreamerMetaDataKeys[i].token)] = qt_gstreamerMetaDataKeys[i].key;
    }
}

QGstreamerMetaDataProvider::~QGstreamerMetaDataProvider()
{
}

bool QGstreamerMetaDataProvider::isMetaDataAvailable() const
{
    return !m_session->tags().isEmpty();
}

bool QGstreamerMetaDataProvider::isWritable() const
{
    return false;
}

QVariant QGstreamerMetaDataProvider::metaData(const QString &key) const
{
    return m_tags.value(key);
}

QStringList QGstreamerMetaDataProvider::availableMetaData() const
{
    return m_tags.keys();
}

void QGstreamerMetaDataProvider::updateTags()
{
    QVariantMap oldTags = m_tags;
    m_tags.clear();

    QSet<QString> allTags = QSet<QString>::fromList(m_tags.keys());

    QMapIterator<QByteArray ,QVariant> i(m_session->tags());
    while (i.hasNext()) {
         i.next();
         //use gstreamer native keys for elements not in m_keysMap
         QString key = m_keysMap.value(i.key(), i.key());
         m_tags[key] = i.value();
         allTags.insert(key);
    }

    bool changed = false;
    foreach (const QString &key, allTags) {
        const QVariant value = m_tags.value(key);
        if (value != oldTags.value(key)) {
            changed = true;
            emit metaDataChanged(key, value);
        }
    }

    if (changed)
        emit metaDataChanged();
}

QT_END_NAMESPACE
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company.  For licensing terms and
** conditions see http://www.qt.io/terms-conditions.  For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file.  Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, The Qt Company gives you certain additional
** rights.  These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/

#include "functionhintproposalwidget.h"
#include "ifunctionhintproposalmodel.h"
#include "codeassistant.h"

#include <utils/faketooltip.h>
#include <utils/hostosinfo.h>

#include <QDebug>
#include <QApplication>
#include <QLabel>
#include <QToolButton>
#include <QHBoxLayout>
#include <QDesktopWidget>
#include <QKeyEvent>

namespace TextEditor {

// -------------------------
// HintProposalWidgetPrivate
// -------------------------
struct FunctionHintProposalWidgetPrivate
{
    FunctionHintProposalWidgetPrivate();

    const QWidget *m_underlyingWidget;
    CodeAssistant *m_assistant;
    IFunctionHintProposalModel *m_model;
    Utils::FakeToolTip *m_popupFrame;
    QLabel *m_numberLabel;
    QLabel *m_hintLabel;
    QWidget *m_pager;
    QRect m_displayRect;
    int m_currentHint;
    int m_totalHints;
    int m_currentArgument;
    bool m_escapePressed;
};

FunctionHintProposalWidgetPrivate::FunctionHintProposalWidgetPrivate()
    : m_underlyingWidget(0)
    , m_assistant(0)
    , m_model(0)
    , m_popupFrame(new Utils::FakeToolTip)
    , m_numberLabel(new QLabel)
    , m_hintLabel(new QLabel)
    , m_pager(new QWidget)
    , m_currentHint(-1)
    , m_totalHints(0)
    , m_currentArgument(-1)
    , m_escapePressed(false)
{
    m_hintLabel->setTextFormat(Qt::RichText);
}

// ------------------
// HintProposalWidget
// ------------------
FunctionHintProposalWidget::FunctionHintProposalWidget()
    : d(new FunctionHintProposalWidgetPrivate)
{
    QToolButton *downArrow = new QToolButton;
    downArrow->setArrowType(Qt::DownArrow);
    downArrow->setFixedSize(16, 16);
    downArrow->setAutoRaise(true);

    QToolButton *upArrow = new QToolButton;
    upArrow->setArrowType(Qt::UpArrow);
    upArrow->setFixedSize(16, 16);
    upArrow->setAutoRaise(true);

    QHBoxLayout *pagerLayout = new QHBoxLayout(d->m_pager);
    pagerLayout->setMargin(0);
    pagerLayout->setSpacing(0);
    pagerLayout->addWidget(upArrow);
    pagerLayout->addWidget(d->m_numberLabel);
    pagerLayout->addWidget(downArrow);

    QHBoxLayout *popupLayout = new QHBoxLayout(d->m_popupFrame);
    popupLayout->setMargin(0);
    popupLayout->setSpacing(0);
    popupLayout->addWidget(d->m_pager);
    popupLayout->addWidget(d->m_hintLabel);

    connect(upArrow, SIGNAL(clicked()), SLOT(previousPage()));
    connect(downArrow, SIGNAL(clicked()), SLOT(nextPage()));

    qApp->installEventFilter(this);

    setFocusPolicy(Qt::NoFocus);
}

FunctionHintProposalWidget::~FunctionHintProposalWidget()
{
    delete d->m_model;
    delete d;
}

void FunctionHintProposalWidget::setAssistant(CodeAssistant *assistant)
{
    d->m_assistant = assistant;
}

void FunctionHintProposalWidget::setReason(AssistReason)
{}

void FunctionHintProposalWidget::setKind(AssistKind)
{}

void FunctionHintProposalWidget::setUnderlyingWidget(const QWidget *underlyingWidget)
{
    d->m_underlyingWidget = underlyingWidget;
}

void FunctionHintProposalWidget::setModel(IAssistProposalModel *model)
{
    d->m_model = static_cast<IFunctionHintProposalModel *>(model);
}

void FunctionHintProposalWidget::setDisplayRect(const QRect &rect)
{
    d->m_displayRect = rect;
}

void FunctionHintProposalWidget::setIsSynchronized(bool)
{}

void FunctionHintProposalWidget::showProposal(const QString &prefix)
{
    d->m_totalHints = d->m_model->size();
    if (d->m_totalHints == 0) {
        abort();
        return;
    }
    d->m_pager->setVisible(d->m_totalHints > 1);
    d->m_currentHint = 0;
    if (!updateAndCheck(prefix)) {
        abort();
        return;
    }
    d->m_popupFrame->show();
}

void FunctionHintProposalWidget::updateProposal(const QString &prefix)
{
    updateAndCheck(prefix);
}

void FunctionHintProposalWidget::closeProposal()
{
    abort();
}

void FunctionHintProposalWidget::abort()
{
    if (d->m_popupFrame->isVisible())
        d->m_popupFrame->close();
    deleteLater();
}

bool FunctionHintProposalWidget::eventFilter(QObject *obj, QEvent *e)
{
    switch (e->type()) {
    case QEvent::ShortcutOverride:
        if (static_cast<QKeyEvent*>(e)->key() == Qt::Key_Escape) {
            d->m_escapePressed = true;
            e->accept();
        }
        break;
    case QEvent::KeyPress:
        if (static_cast<QKeyEvent*>(e)->key() == Qt::Key_Escape) {
            d->m_escapePressed = true;
            e->accept();
        }
        if (d->m_model->size() > 1) {
            QKeyEvent *ke = static_cast<QKeyEvent*>(e);
            if (ke->key() == Qt::Key_Up) {
                previousPage();
                return true;
            } else if (ke->key() == Qt::Key_Down) {
                nextPage();
                return true;
            }
            return false;
        }
        break;
    case QEvent::KeyRelease: {
            QKeyEvent *ke = static_cast<QKeyEvent*>(e);
            if (ke->key() == Qt::Key_Escape && d->m_escapePressed) {
                abort();
                emit explicitlyAborted();
                return false;
            } else if (ke->key() == Qt::Key_Up || ke->key() == Qt::Key_Down) {
                if (d->m_model->size() > 1)
                    return false;
            }
            d->m_assistant->notifyChange();
        }
        break;
    case QEvent::WindowDeactivate:
    case QEvent::FocusOut:
        if (obj != d->m_underlyingWidget)
            break;
        abort();
        break;
    case QEvent::MouseButtonPress:
    case QEvent::MouseButtonRelease:
    case QEvent::MouseButtonDblClick:
    case QEvent::Wheel: {
            QWidget *widget = qobject_cast<QWidget *>(obj);
            if (!d->m_popupFrame->isAncestorOf(widget)) {
                abort();
            } else if (e->type() == QEvent::Wheel) {
                if (static_cast<QWheelEvent*>(e)->delta() > 0)
                    previousPage();
                else
                    nextPage();
                return true;
            }
        }
        break;
    default:
        break;
    }
    return false;
}

void FunctionHintProposalWidget::nextPage()
{
    d->m_currentHint = (d->m_currentHint + 1) % d->m_totalHints;
    updateContent();
}

void FunctionHintProposalWidget::previousPage()
{
    if (d->m_currentHint == 0)
        d->m_currentHint = d->m_totalHints - 1;
    else
        --d->m_currentHint;
    updateContent();
}

bool FunctionHintProposalWidget::updateAndCheck(const QString &prefix)
{
    const int activeArgument = d->m_model->activeArgument(prefix);
    if (activeArgument == -1) {
        abort();
        return false;
    } else if (activeArgument != d->m_currentArgument) {
        d->m_currentArgument = activeArgument;
        updateContent();
    }

    return true;
}

void FunctionHintProposalWidget::updateContent()
{
    d->m_hintLabel->setText(d->m_model->text(d->m_currentHint));
    d->m_numberLabel->setText(tr("%1 of %2").arg(d->m_currentHint + 1).arg(d->m_totalHints));
    updatePosition();
}

void FunctionHintProposalWidget::updatePosition()
{
    const QDesktopWidget *desktop = QApplication::desktop();
    const QRect &screen = Utils::HostOsInfo::isMacHost()
            ? desktop->availableGeometry(desktop->screenNumber(d->m_underlyingWidget))
            : desktop->screenGeometry(desktop->screenNumber(d->m_underlyingWidget));

    d->m_pager->setFixedWidth(d->m_pager->minimumSizeHint().width());

    d->m_hintLabel->setWordWrap(false);
    const int maxDesiredWidth = screen.width() - 10;
    const QSize &minHint = d->m_popupFrame->minimumSizeHint();
    if (minHint.width() > maxDesiredWidth) {
        d->m_hintLabel->setWordWrap(true);
        d->m_popupFrame->setFixedWidth(maxDesiredWidth);
        const int extra = d->m_popupFrame->contentsMargins().bottom() +
            d->m_popupFrame->contentsMargins().top();
        d->m_popupFrame->setFixedHeight(
            d->m_hintLabel->heightForWidth(maxDesiredWidth - d->m_pager->width()) + extra);
    } else {
        d->m_popupFrame->setFixedSize(minHint);
    }

    const QSize &sz = d->m_popupFrame->size();
    QPoint pos = d->m_displayRect.topLeft();
    pos.setY(pos.y() - sz.height() - 1);
    if (pos.x() + sz.width() > screen.right())
        pos.setX(screen.right() - sz.width());
    d->m_popupFrame->move(pos);
}

} // TextEditor
<commit_msg>Editors/Function hint: Guard against potential crashes<commit_after>/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company.  For licensing terms and
** conditions see http://www.qt.io/terms-conditions.  For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file.  Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, The Qt Company gives you certain additional
** rights.  These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/

#include "functionhintproposalwidget.h"
#include "ifunctionhintproposalmodel.h"
#include "codeassistant.h"

#include <utils/faketooltip.h>
#include <utils/hostosinfo.h>
#include <utils/qtcassert.h>

#include <QDebug>
#include <QApplication>
#include <QLabel>
#include <QToolButton>
#include <QHBoxLayout>
#include <QDesktopWidget>
#include <QKeyEvent>

namespace TextEditor {

// -------------------------
// HintProposalWidgetPrivate
// -------------------------
struct FunctionHintProposalWidgetPrivate
{
    FunctionHintProposalWidgetPrivate();

    const QWidget *m_underlyingWidget;
    CodeAssistant *m_assistant;
    IFunctionHintProposalModel *m_model;
    Utils::FakeToolTip *m_popupFrame;
    QLabel *m_numberLabel;
    QLabel *m_hintLabel;
    QWidget *m_pager;
    QRect m_displayRect;
    int m_currentHint;
    int m_totalHints;
    int m_currentArgument;
    bool m_escapePressed;
};

FunctionHintProposalWidgetPrivate::FunctionHintProposalWidgetPrivate()
    : m_underlyingWidget(0)
    , m_assistant(0)
    , m_model(0)
    , m_popupFrame(new Utils::FakeToolTip)
    , m_numberLabel(new QLabel)
    , m_hintLabel(new QLabel)
    , m_pager(new QWidget)
    , m_currentHint(-1)
    , m_totalHints(0)
    , m_currentArgument(-1)
    , m_escapePressed(false)
{
    m_hintLabel->setTextFormat(Qt::RichText);
}

// ------------------
// HintProposalWidget
// ------------------
FunctionHintProposalWidget::FunctionHintProposalWidget()
    : d(new FunctionHintProposalWidgetPrivate)
{
    QToolButton *downArrow = new QToolButton;
    downArrow->setArrowType(Qt::DownArrow);
    downArrow->setFixedSize(16, 16);
    downArrow->setAutoRaise(true);

    QToolButton *upArrow = new QToolButton;
    upArrow->setArrowType(Qt::UpArrow);
    upArrow->setFixedSize(16, 16);
    upArrow->setAutoRaise(true);

    QHBoxLayout *pagerLayout = new QHBoxLayout(d->m_pager);
    pagerLayout->setMargin(0);
    pagerLayout->setSpacing(0);
    pagerLayout->addWidget(upArrow);
    pagerLayout->addWidget(d->m_numberLabel);
    pagerLayout->addWidget(downArrow);

    QHBoxLayout *popupLayout = new QHBoxLayout(d->m_popupFrame);
    popupLayout->setMargin(0);
    popupLayout->setSpacing(0);
    popupLayout->addWidget(d->m_pager);
    popupLayout->addWidget(d->m_hintLabel);

    connect(upArrow, SIGNAL(clicked()), SLOT(previousPage()));
    connect(downArrow, SIGNAL(clicked()), SLOT(nextPage()));

    qApp->installEventFilter(this);

    setFocusPolicy(Qt::NoFocus);
}

FunctionHintProposalWidget::~FunctionHintProposalWidget()
{
    delete d->m_model;
    delete d;
}

void FunctionHintProposalWidget::setAssistant(CodeAssistant *assistant)
{
    d->m_assistant = assistant;
}

void FunctionHintProposalWidget::setReason(AssistReason)
{}

void FunctionHintProposalWidget::setKind(AssistKind)
{}

void FunctionHintProposalWidget::setUnderlyingWidget(const QWidget *underlyingWidget)
{
    d->m_underlyingWidget = underlyingWidget;
}

void FunctionHintProposalWidget::setModel(IAssistProposalModel *model)
{
    d->m_model = static_cast<IFunctionHintProposalModel *>(model);
}

void FunctionHintProposalWidget::setDisplayRect(const QRect &rect)
{
    d->m_displayRect = rect;
}

void FunctionHintProposalWidget::setIsSynchronized(bool)
{}

void FunctionHintProposalWidget::showProposal(const QString &prefix)
{
    d->m_totalHints = d->m_model->size();
    if (d->m_totalHints == 0) {
        abort();
        return;
    }
    d->m_pager->setVisible(d->m_totalHints > 1);
    d->m_currentHint = 0;
    if (!updateAndCheck(prefix)) {
        abort();
        return;
    }
    d->m_popupFrame->show();
}

void FunctionHintProposalWidget::updateProposal(const QString &prefix)
{
    updateAndCheck(prefix);
}

void FunctionHintProposalWidget::closeProposal()
{
    abort();
}

void FunctionHintProposalWidget::abort()
{
    if (d->m_popupFrame->isVisible())
        d->m_popupFrame->close();
    deleteLater();
}

bool FunctionHintProposalWidget::eventFilter(QObject *obj, QEvent *e)
{
    switch (e->type()) {
    case QEvent::ShortcutOverride:
        if (static_cast<QKeyEvent*>(e)->key() == Qt::Key_Escape) {
            d->m_escapePressed = true;
            e->accept();
        }
        break;
    case QEvent::KeyPress:
        if (static_cast<QKeyEvent*>(e)->key() == Qt::Key_Escape) {
            d->m_escapePressed = true;
            e->accept();
        }
        QTC_CHECK(d->m_model);
        if (d->m_model && d->m_model->size() > 1) {
            QKeyEvent *ke = static_cast<QKeyEvent*>(e);
            if (ke->key() == Qt::Key_Up) {
                previousPage();
                return true;
            } else if (ke->key() == Qt::Key_Down) {
                nextPage();
                return true;
            }
            return false;
        }
        break;
    case QEvent::KeyRelease: {
            QKeyEvent *ke = static_cast<QKeyEvent*>(e);
            if (ke->key() == Qt::Key_Escape && d->m_escapePressed) {
                abort();
                emit explicitlyAborted();
                return false;
            } else if (ke->key() == Qt::Key_Up || ke->key() == Qt::Key_Down) {
                QTC_CHECK(d->m_model);
                if (d->m_model && d->m_model->size() > 1)
                    return false;
            }
            QTC_CHECK(d->m_assistant);
            if (d->m_assistant)
                d->m_assistant->notifyChange();
        }
        break;
    case QEvent::WindowDeactivate:
    case QEvent::FocusOut:
        if (obj != d->m_underlyingWidget)
            break;
        abort();
        break;
    case QEvent::MouseButtonPress:
    case QEvent::MouseButtonRelease:
    case QEvent::MouseButtonDblClick:
    case QEvent::Wheel: {
            QWidget *widget = qobject_cast<QWidget *>(obj);
            if (!d->m_popupFrame->isAncestorOf(widget)) {
                abort();
            } else if (e->type() == QEvent::Wheel) {
                if (static_cast<QWheelEvent*>(e)->delta() > 0)
                    previousPage();
                else
                    nextPage();
                return true;
            }
        }
        break;
    default:
        break;
    }
    return false;
}

void FunctionHintProposalWidget::nextPage()
{
    d->m_currentHint = (d->m_currentHint + 1) % d->m_totalHints;
    updateContent();
}

void FunctionHintProposalWidget::previousPage()
{
    if (d->m_currentHint == 0)
        d->m_currentHint = d->m_totalHints - 1;
    else
        --d->m_currentHint;
    updateContent();
}

bool FunctionHintProposalWidget::updateAndCheck(const QString &prefix)
{
    const int activeArgument = d->m_model->activeArgument(prefix);
    if (activeArgument == -1) {
        abort();
        return false;
    } else if (activeArgument != d->m_currentArgument) {
        d->m_currentArgument = activeArgument;
        updateContent();
    }

    return true;
}

void FunctionHintProposalWidget::updateContent()
{
    d->m_hintLabel->setText(d->m_model->text(d->m_currentHint));
    d->m_numberLabel->setText(tr("%1 of %2").arg(d->m_currentHint + 1).arg(d->m_totalHints));
    updatePosition();
}

void FunctionHintProposalWidget::updatePosition()
{
    const QDesktopWidget *desktop = QApplication::desktop();
    const QRect &screen = Utils::HostOsInfo::isMacHost()
            ? desktop->availableGeometry(desktop->screenNumber(d->m_underlyingWidget))
            : desktop->screenGeometry(desktop->screenNumber(d->m_underlyingWidget));

    d->m_pager->setFixedWidth(d->m_pager->minimumSizeHint().width());

    d->m_hintLabel->setWordWrap(false);
    const int maxDesiredWidth = screen.width() - 10;
    const QSize &minHint = d->m_popupFrame->minimumSizeHint();
    if (minHint.width() > maxDesiredWidth) {
        d->m_hintLabel->setWordWrap(true);
        d->m_popupFrame->setFixedWidth(maxDesiredWidth);
        const int extra = d->m_popupFrame->contentsMargins().bottom() +
            d->m_popupFrame->contentsMargins().top();
        d->m_popupFrame->setFixedHeight(
            d->m_hintLabel->heightForWidth(maxDesiredWidth - d->m_pager->width()) + extra);
    } else {
        d->m_popupFrame->setFixedSize(minHint);
    }

    const QSize &sz = d->m_popupFrame->size();
    QPoint pos = d->m_displayRect.topLeft();
    pos.setY(pos.y() - sz.height() - 1);
    if (pos.x() + sz.width() > screen.right())
        pos.setX(screen.right() - sz.width());
    d->m_popupFrame->move(pos);
}

} // TextEditor
<|endoftext|>