<commit_before>#include "MainWindow.h"
#include "NotifySingletons.h"
#include "MqPublisher.h"
#include <iostream>
using namespace std;

MainWindow::MainWindow(QObject *parent /*= 0*/)
: QObject(parent)
, oContacts (this)
, oInbox (this)
, checkCounter (0)
{
    initLogging ();

    qRegisterMetaType<ContactInfo>("ContactInfo");

    GVAccess &webPage = Singletons::getRef().getGVAccess ();
    // webPage status
    QObject::connect (&webPage, SIGNAL (status(const QString &, int)),
                       this   , SLOT   (setStatus(const QString &, int)));
    // Status from contacts object
    QObject::connect (&oContacts, SIGNAL (status   (const QString &, int)),
                       this     , SLOT   (setStatus(const QString &, int)));
    // oContacts.allContacts -> this.getContactsDone
    QObject::connect (&oContacts, SIGNAL (allContacts (bool, bool)),
                      this      , SLOT   (getContactsDone (bool, bool)));
    // Status from inbox object
    QObject::connect (&oInbox, SIGNAL (status   (const QString &, int)),
                       this  , SLOT   (setStatus(const QString &, int)));
    // Inbox has updated
    QObject::connect (&oInbox, SIGNAL (inboxChanged ()),
                       this  , SLOT   (inboxChanged ()));
    // Timer tick
    QObject::connect (&mainTimer, SIGNAL(timeout()), this, SLOT(doWork()));

    webPage.setEmitLog (false);

    if (!checkParams ()) {
        qApp->quit();
        return;
    }

    QTimer::singleShot (100, this, SLOT(doWork ()));
}//MainWindow::MainWindow

void
MainWindow::initLogging ()
{
    QString strLogfile = baseDir ();
    strLogfile += QDir::separator();
    strLogfile += "notify.log";
    fLogfile.setFileName (strLogfile);
    fLogfile.open (QIODevice::WriteOnly | QIODevice::Append);
}//MainWindow::initLogging

/** Log information to console and to log file
 * This function is invoked from the qDebug handler that is installed in main.
 * @param strText Text to be logged
 * @param level Log level
 */
void
MainWindow::log (const QString &strText, int level /*= 10*/)
{
    QString strDisp;
    QRegExp regex("^\"(.*)\"\\s*");
    if (strText.indexOf (regex) != -1) {
        strDisp = regex.cap (1);
    } else {
        strDisp = strText;
    }

    QDateTime dt = QDateTime::currentDateTime ();
    QString strLog = QString("%1 : %2 : %3")
                     .arg(dt.toString ("yyyy-MM-dd hh:mm:ss.zzz"))
                     .arg(level)
                     .arg(strDisp);

    // Send to standard output
    cout << strLog.toStdString () << endl;

    // Send to log file
    if (fLogfile.isOpen ()) {
        QTextStream streamLog(&fLogfile);
        streamLog << strLog << endl;
    }
}//MainWindow::log

void
MainWindow::setStatus(const QString &strText, int /*timeout = 3000*/)
{
    qDebug () << strText;
}//MainWindow::setStatus

QString
MainWindow::baseDir()
{
    QString strBasedir = QDir::homePath();
    QDir baseDir(strBasedir);
    if (!baseDir.exists (".qgvdial")) {
        baseDir.mkdir (".qgvdial");
    }
    strBasedir += QDir::separator();
    strBasedir += ".qgvdial";
    return strBasedir;
}//MainWindow::baseDir

void
MainWindow::doWork ()
{
    if (strSelfNumber.isEmpty ()) {
        doLogin ();
        return;
    }

    checkCounter++;
    if (0 == checkCounter % 100) {
        qDebug() << "Checked" << checkCounter << "times";
    }

    // Get the contacts
    oContacts.refreshContacts ();
    // Get inbox
    oInbox.refresh ();
}//MainWindow::doWork

bool
MainWindow::checkParams ()
{
    bool rv = false;
    QString strIni = baseDir ();
    strIni += QDir::separator();
    strIni += "notify.ini";

    do { // Begin cleanup block (not a loop)
        QSettings settings (strIni, QSettings::IniFormat, this);

        QByteArray byD;
        QTextStream in(stdin);
        if (!settings.contains ("user")) {
            qWarning ("Ini file does not contain a username");
            cout << "Enter username:";
            in >> strUser;
            settings.setValue ("user", strUser);
        } else {
            strUser = settings.value ("user").toString ();
        }

        if (!settings.contains ("password")) {
            qWarning ("Ini file does not contain a password");
            cout << "Enter password:";
            in >> strPass;
            cipher (strPass.toLocal8Bit (), byD, true);
            settings.setValue ("password", QString(byD.toHex ()));
        } else {
            byD = settings.value("password").toByteArray();
            cipher (QByteArray::fromHex (byD), byD, false);
            strPass = byD;
        }

        if (!settings.contains ("mqserver")) {
            qWarning ("Ini file does not contain the mq server hostname");
            cout << "Enter server hostname:";
            in >> m_strMqServer;
            settings.setValue ("mqserver", m_strMqServer);
        } else {
            m_strMqServer = settings.value ("mqserver").toString ();
        }

        if (!settings.contains ("mqport")) {
            qWarning ("Ini file does not contain the mq server port");
            cout << "Enter server port:";
            in >> m_mqPort;
            if (0 == m_mqPort) m_mqPort = 1883;
            settings.setValue ("mqport", m_mqPort);
        } else {
            m_mqPort = settings.value ("mqport").toInt (&rv);
            if (!rv) break;
            if (0 == m_mqPort) m_mqPort = 1883;
            settings.setValue ("mqport", m_mqPort);
            rv = false;
        }

        if (!settings.contains ("mqtopic")) {
            qWarning ("Ini file does not contain the mq topic");
            cout << "Enter topic:";
            in >> m_strMqTopic;
            settings.setValue ("mqtopic", m_strMqTopic);
        } else {
            m_strMqTopic = settings.value ("mqtopic").toString ();
        }

        rv = true;
    } while (0); // End cleanup block (not a loop)

    return rv;
}//MainWindow::checkParams

bool
MainWindow::cipher(const QByteArray &byIn, QByteArray &byOut, bool bEncrypt)
{
    int iEVP, inl, outl, c;
    EVP_CIPHER_CTX cipherCtx;
    char cipherIv[16], cipherIn[16], cipherOut[16 + EVP_MAX_BLOCK_LENGTH];
    memset (&cipherCtx, 0, sizeof cipherCtx);
    memset (&cipherIv, 0xFA, sizeof cipherIv);

#define QGV_CIPHER_KEY "01234567890123456789012345678901"
    EVP_CIPHER_CTX_init (&cipherCtx);
    iEVP = EVP_CipherInit_ex (&cipherCtx, EVP_aes_256_cbc (), NULL, NULL, NULL,
                              bEncrypt?1:0);
    if (1 != iEVP) return false;
    EVP_CIPHER_CTX_set_key_length(&cipherCtx, sizeof(QGV_CIPHER_KEY)-1);
    iEVP = EVP_CipherInit_ex (&cipherCtx, EVP_aes_256_cbc (), NULL,
                              (quint8 *) QGV_CIPHER_KEY, (quint8 *) cipherIv,
                               bEncrypt?1:0);
    if (1 != iEVP) return false;

    byOut.clear ();
    c = 0;
    while (c < byIn.size ()) {
        inl = byIn.size () - c;
        inl = (uint)inl > sizeof (cipherIn) ? sizeof (cipherIn) : inl;
        memcpy (cipherIn, &(byIn.constData()[c]), inl);
        memset (&cipherOut, 0, sizeof cipherOut);
        outl = sizeof cipherOut;
        iEVP = EVP_CipherUpdate (&cipherCtx,
                                (quint8 *) &cipherOut, &outl,
                                 (quint8 *) &cipherIn , inl);
        if (1 != iEVP) {
            qWarning ("Cipher update failed. Aborting");
            break;
        }
        byOut += QByteArray(cipherOut, outl);
        c += inl;
    }

    if (1 == iEVP) {
        outl = sizeof cipherOut;
        memset (&cipherOut, 0, sizeof cipherOut);
        iEVP = EVP_CipherFinal_ex (&cipherCtx, (quint8 *) &cipherOut, &outl);
        if (1 == iEVP) {
            byOut += QByteArray(cipherOut, outl);
        }
    }

    EVP_CIPHER_CTX_cleanup(&cipherCtx);

    return (1 == iEVP);
}//MainWindow::cipher

/** Invoked to begin the login process.
 * We already have the username and password, so just start the login to the GV
 * website. The async completion routine is loginCompleted.
 */
void
MainWindow::doLogin ()
{
    GVAccess &webPage = Singletons::getRef().getGVAccess ();
    QVariantList l;

    bool bOk = false;
    do { // Begin cleanup block (not a loop)
        webPage.setTimeout(60);

        l += strUser;
        l += strPass;

        qDebug ("Logging in...");

        // webPage.workCompleted -> this.loginCompleted
        if (!webPage.enqueueWork (GVAW_login, l, this,
                SLOT (loginCompleted (bool, const QVariantList &))))
        {
            qCritical ("Login returned immediately with failure!");
            break;
        }

        bOk = true;
    } while (0); // End cleanup block (not a loop)

    if (!bOk)
    {
        webPage.setTimeout(20);
        // Cleanup if any
        strUser.clear ();
        strPass.clear ();

        l.clear ();
        logoutCompleted (true, l);

        qApp->quit ();
    }
}//MainWindow::doLogin

void
MainWindow::loginCompleted (bool bOk, const QVariantList &varList)
{
    strSelfNumber.clear ();
    GVAccess &webPage = Singletons::getRef().getGVAccess ();
    webPage.setTimeout(20);

    if (!bOk)
    {
        QVariantList l;
        logoutCompleted (true, l);

        qCritical ("User login failed");
        qApp->quit ();
    }
    else
    {
        qDebug ("User logged in");

        // Save the users GV number returned by the login completion
        strSelfNumber = varList[varList.size()-1].toString ();

        oContacts.setUserPass (strUser, strPass);
        oContacts.loginSuccess ();
        oInbox.loginSuccess ();

        QTimer::singleShot (100, this, SLOT(doWork ()));
    }
}//MainWindow::loginCompleted

void
MainWindow::doLogout ()
{
    GVAccess &webPage = Singletons::getRef().getGVAccess ();
    QVariantList l;
    webPage.enqueueWork (GVAW_logout, l, this,
                         SLOT (logoutCompleted (bool, const QVariantList &)));
}//MainWindow::doLogout

void
MainWindow::logoutCompleted (bool, const QVariantList &)
{
    // This clears out the table and the view as well
    oContacts.loggedOut ();
    oInbox.loggedOut ();
}//MainWindow::logoutCompleted

void
MainWindow::getContactsDone (bool bChanges, bool bOK)
{
    if (bOK && bChanges) {
        qDebug ("Contacts changed, update mosquitto");

        MqPublisher pub(QString("qgvnotify:%1").arg(QHostInfo::localHostName()),
                        m_strMqServer, m_mqPort, m_strMqTopic,
                        this);
        pub.publish ("contact");
    }

    startTimer ();
}//MainWindow::getContactsDone

void
MainWindow::inboxChanged ()
{
    qDebug ("Inbox changed, update mosquitto");

    MqPublisher pub(QString("qgvnotify:%1").arg(QHostInfo::localHostName()),
                    m_strMqServer, m_mqPort, m_strMqTopic,
                    this);
    pub.publish ("inbox");

    startTimer ();
}//MainWindow::inboxChanged

void
MainWindow::startTimer ()
{
    mainTimer.stop ();
    mainTimer.setSingleShot (true);
    mainTimer.setInterval (5 * 1000);
    mainTimer.start ();
}//MainWindow::startTimer
<commit_msg>Add proxy support to notify<commit_after>#include "MainWindow.h"
#include "NotifySingletons.h"
#include "MqPublisher.h"
#include <iostream>
using namespace std;

MainWindow::MainWindow(QObject *parent /*= 0*/)
: QObject(parent)
, oContacts (this)
, oInbox (this)
, checkCounter (0)
{
    initLogging ();

    qRegisterMetaType<ContactInfo>("ContactInfo");

    GVAccess &webPage = Singletons::getRef().getGVAccess ();
    // webPage status
    QObject::connect (&webPage, SIGNAL (status(const QString &, int)),
                       this   , SLOT   (setStatus(const QString &, int)));
    // Status from contacts object
    QObject::connect (&oContacts, SIGNAL (status   (const QString &, int)),
                       this     , SLOT   (setStatus(const QString &, int)));
    // oContacts.allContacts -> this.getContactsDone
    QObject::connect (&oContacts, SIGNAL (allContacts (bool, bool)),
                      this      , SLOT   (getContactsDone (bool, bool)));
    // Status from inbox object
    QObject::connect (&oInbox, SIGNAL (status   (const QString &, int)),
                       this  , SLOT   (setStatus(const QString &, int)));
    // Inbox has updated
    QObject::connect (&oInbox, SIGNAL (inboxChanged ()),
                       this  , SLOT   (inboxChanged ()));
    // Timer tick
    QObject::connect (&mainTimer, SIGNAL(timeout()), this, SLOT(doWork()));

    webPage.setEmitLog (false);

    if (!checkParams ()) {
        qApp->quit();
        return;
    }

    QTimer::singleShot (100, this, SLOT(doWork ()));
}//MainWindow::MainWindow

void
MainWindow::initLogging ()
{
    QString strLogfile = baseDir ();
    strLogfile += QDir::separator();
    strLogfile += "notify.log";
    fLogfile.setFileName (strLogfile);
    fLogfile.open (QIODevice::WriteOnly | QIODevice::Append);
}//MainWindow::initLogging

/** Log information to console and to log file
 * This function is invoked from the qDebug handler that is installed in main.
 * @param strText Text to be logged
 * @param level Log level
 */
void
MainWindow::log (const QString &strText, int level /*= 10*/)
{
    QString strDisp;
    QRegExp regex("^\"(.*)\"\\s*");
    if (strText.indexOf (regex) != -1) {
        strDisp = regex.cap (1);
    } else {
        strDisp = strText;
    }

    QDateTime dt = QDateTime::currentDateTime ();
    QString strLog = QString("%1 : %2 : %3")
                     .arg(dt.toString ("yyyy-MM-dd hh:mm:ss.zzz"))
                     .arg(level)
                     .arg(strDisp);

    // Send to standard output
    cout << strLog.toStdString () << endl;

    // Send to log file
    if (fLogfile.isOpen ()) {
        QTextStream streamLog(&fLogfile);
        streamLog << strLog << endl;
    }
}//MainWindow::log

void
MainWindow::setStatus(const QString &strText, int /*timeout = 3000*/)
{
    qDebug () << strText;
}//MainWindow::setStatus

QString
MainWindow::baseDir()
{
    QString strBasedir = QDir::homePath();
    QDir baseDir(strBasedir);
    if (!baseDir.exists (".qgvdial")) {
        baseDir.mkdir (".qgvdial");
    }
    strBasedir += QDir::separator();
    strBasedir += ".qgvdial";
    return strBasedir;
}//MainWindow::baseDir

void
MainWindow::doWork ()
{
    if (strSelfNumber.isEmpty ()) {
        doLogin ();
        return;
    }

    checkCounter++;
    if (0 == checkCounter % 100) {
        qDebug() << "Checked" << checkCounter << "times";
    }

    // Get the contacts
    oContacts.refreshContacts ();
    // Get inbox
    oInbox.refresh ();
}//MainWindow::doWork

bool
MainWindow::checkParams ()
{
    bool rv = false;
    QString strIni = baseDir ();
    strIni += QDir::separator();
    strIni += "notify.ini";

    bool bUseProxy = false, bUseSystemProxy = false, bProxyAuth = false;
    QString strProxy, strProxyUser, strProxyPass;
    int proxyport;

    do { // Begin cleanup block (not a loop)
        QSettings settings (strIni, QSettings::IniFormat, this);

        QByteArray byD;
        QTextStream in(stdin);
        if (!settings.contains ("user")) {
            qWarning ("Ini file does not contain a username");
            cout << "Enter username:";
            in >> strUser;
            settings.setValue ("user", strUser);
        } else {
            strUser = settings.value ("user").toString ();
        }

        if (!settings.contains ("password")) {
            qWarning ("Ini file does not contain a password");
            cout << "Enter password:";
            in >> strPass;
            cipher (strPass.toLocal8Bit (), byD, true);
            settings.setValue ("password", QString(byD.toHex ()));
        } else {
            byD = settings.value("password").toByteArray();
            cipher (QByteArray::fromHex (byD), byD, false);
            strPass = byD;
        }

        if (!settings.contains ("mqserver")) {
            qWarning ("Ini file does not contain the mq server hostname");
            cout << "Enter server hostname:";
            in >> m_strMqServer;
            settings.setValue ("mqserver", m_strMqServer);
        } else {
            m_strMqServer = settings.value ("mqserver").toString ();
        }

        if (!settings.contains ("mqport")) {
            qWarning ("Ini file does not contain the mq server port");
            cout << "Enter server port:";
            in >> m_mqPort;
            if (0 == m_mqPort) m_mqPort = 1883;
            settings.setValue ("mqport", m_mqPort);
        } else {
            m_mqPort = settings.value ("mqport").toInt (&rv);
            if (!rv) break;
            if (0 == m_mqPort) m_mqPort = 1883;
            settings.setValue ("mqport", m_mqPort);
            rv = false;
        }

        if (!settings.contains ("mqtopic")) {
            qWarning ("Ini file does not contain the mq topic");
            cout << "Enter topic:";
            in >> m_strMqTopic;
            settings.setValue ("mqtopic", m_strMqTopic);
        } else {
            m_strMqTopic = settings.value ("mqtopic").toString ();
        }

        if (!settings.contains ("useproxy")) {
            settings.setValue ("useproxy", false);
            bUseProxy = false;
        } else {
            bUseProxy = settings.value ("useproxy", false).toBool ();
        }

        if (!settings.contains ("usesystemproxy")) {
            settings.setValue ("usesystemproxy", false);
            bUseSystemProxy = false;
        } else {
            bUseSystemProxy = settings.value ("usesystemproxy", false).toBool();
        }

        if (!settings.contains ("proxyserver")) {
            settings.setValue ("proxyserver", "proxy.example.com");
        } else {
            strProxy = settings.value ("proxyserver", "").toString ();
        }

        if (!settings.contains ("proxyport")) {
            settings.setValue ("proxyport", 80);
            proxyport = 80;
        } else {
            proxyport = settings.value ("proxyport", 80).toInt ();
        }

        if (!settings.contains ("proxyauth")) {
            settings.setValue ("proxyauth", false);
            bProxyAuth = false;
        } else {
            bProxyAuth = settings.value ("proxyauth", false).toBool ();
        }

        if (!settings.contains ("proxyuser")) {
            if (bUseProxy & !bUseSystemProxy && bProxyAuth) {
                qWarning ("Ini file needs proxy authentication user");
                cout << "Enter proxy user:";
                in >> strProxyUser;
                settings.setValue ("proxyuser", "proxy_user");
            }
        } else {
            strProxyUser = settings.value ("proxyuser", "").toString ();
        }

        if (!settings.contains ("proxypass")) {
            if (bUseProxy & !bUseSystemProxy && bProxyAuth) {
                qWarning ("Ini file needs proxy authentication password");
                cout << "Enter proxy password:";
                in >> strProxyPass;
                cipher (strPass.toLocal8Bit (), byD, true);
                settings.setValue ("proxypass", QString(byD.toHex ()));
            }
        } else {
            byD = settings.value("proxypass", "").toByteArray ();
            cipher (QByteArray::fromHex (byD), byD, false);
            strProxyPass = byD;
        }

        if (bUseProxy) {
            GVAccess &webPage = Singletons::getRef().getGVAccess ();
            webPage.setProxySettings (bUseProxy, bUseSystemProxy,
                                      strProxy, proxyport,
                                      bProxyAuth,
                                      strProxyUser, strProxyPass);
        }
        rv = true;
    } while (0); // End cleanup block (not a loop)

    return rv;
}//MainWindow::checkParams

bool
MainWindow::cipher(const QByteArray &byIn, QByteArray &byOut, bool bEncrypt)
{
    int iEVP, inl, outl, c;
    EVP_CIPHER_CTX cipherCtx;
    char cipherIv[16], cipherIn[16], cipherOut[16 + EVP_MAX_BLOCK_LENGTH];
    memset (&cipherCtx, 0, sizeof cipherCtx);
    memset (&cipherIv, 0xFA, sizeof cipherIv);

#define QGV_CIPHER_KEY "01234567890123456789012345678901"
    EVP_CIPHER_CTX_init (&cipherCtx);
    iEVP = EVP_CipherInit_ex (&cipherCtx, EVP_aes_256_cbc (), NULL, NULL, NULL,
                              bEncrypt?1:0);
    if (1 != iEVP) return false;
    EVP_CIPHER_CTX_set_key_length(&cipherCtx, sizeof(QGV_CIPHER_KEY)-1);
    iEVP = EVP_CipherInit_ex (&cipherCtx, EVP_aes_256_cbc (), NULL,
                              (quint8 *) QGV_CIPHER_KEY, (quint8 *) cipherIv,
                               bEncrypt?1:0);
    if (1 != iEVP) return false;

    byOut.clear ();
    c = 0;
    while (c < byIn.size ()) {
        inl = byIn.size () - c;
        inl = (uint)inl > sizeof (cipherIn) ? sizeof (cipherIn) : inl;
        memcpy (cipherIn, &(byIn.constData()[c]), inl);
        memset (&cipherOut, 0, sizeof cipherOut);
        outl = sizeof cipherOut;
        iEVP = EVP_CipherUpdate (&cipherCtx,
                                (quint8 *) &cipherOut, &outl,
                                 (quint8 *) &cipherIn , inl);
        if (1 != iEVP) {
            qWarning ("Cipher update failed. Aborting");
            break;
        }
        byOut += QByteArray(cipherOut, outl);
        c += inl;
    }

    if (1 == iEVP) {
        outl = sizeof cipherOut;
        memset (&cipherOut, 0, sizeof cipherOut);
        iEVP = EVP_CipherFinal_ex (&cipherCtx, (quint8 *) &cipherOut, &outl);
        if (1 == iEVP) {
            byOut += QByteArray(cipherOut, outl);
        }
    }

    EVP_CIPHER_CTX_cleanup(&cipherCtx);

    return (1 == iEVP);
}//MainWindow::cipher

/** Invoked to begin the login process.
 * We already have the username and password, so just start the login to the GV
 * website. The async completion routine is loginCompleted.
 */
void
MainWindow::doLogin ()
{
    GVAccess &webPage = Singletons::getRef().getGVAccess ();
    QVariantList l;

    bool bOk = false;
    do { // Begin cleanup block (not a loop)
        webPage.setTimeout(60);

        l += strUser;
        l += strPass;

        qDebug ("Logging in...");

        // webPage.workCompleted -> this.loginCompleted
        if (!webPage.enqueueWork (GVAW_login, l, this,
                SLOT (loginCompleted (bool, const QVariantList &))))
        {
            qCritical ("Login returned immediately with failure!");
            break;
        }

        bOk = true;
    } while (0); // End cleanup block (not a loop)

    if (!bOk)
    {
        webPage.setTimeout(20);
        // Cleanup if any
        strUser.clear ();
        strPass.clear ();

        l.clear ();
        logoutCompleted (true, l);

        qApp->quit ();
    }
}//MainWindow::doLogin

void
MainWindow::loginCompleted (bool bOk, const QVariantList &varList)
{
    strSelfNumber.clear ();
    GVAccess &webPage = Singletons::getRef().getGVAccess ();
    webPage.setTimeout(20);

    if (!bOk)
    {
        QVariantList l;
        logoutCompleted (true, l);

        qCritical ("User login failed");
        qApp->quit ();
    }
    else
    {
        qDebug ("User logged in");

        // Save the users GV number returned by the login completion
        strSelfNumber = varList[varList.size()-1].toString ();

        oContacts.setUserPass (strUser, strPass);
        oContacts.loginSuccess ();
        oInbox.loginSuccess ();

        QTimer::singleShot (100, this, SLOT(doWork ()));
    }
}//MainWindow::loginCompleted

void
MainWindow::doLogout ()
{
    GVAccess &webPage = Singletons::getRef().getGVAccess ();
    QVariantList l;
    webPage.enqueueWork (GVAW_logout, l, this,
                         SLOT (logoutCompleted (bool, const QVariantList &)));
}//MainWindow::doLogout

void
MainWindow::logoutCompleted (bool, const QVariantList &)
{
    // This clears out the table and the view as well
    oContacts.loggedOut ();
    oInbox.loggedOut ();
}//MainWindow::logoutCompleted

void
MainWindow::getContactsDone (bool bChanges, bool bOK)
{
    if (bOK && bChanges) {
        qDebug ("Contacts changed, update mosquitto");

        MqPublisher pub(QString("qgvnotify:%1").arg(QHostInfo::localHostName()),
                        m_strMqServer, m_mqPort, m_strMqTopic,
                        this);
        pub.publish ("contact");
    }

    startTimer ();
}//MainWindow::getContactsDone

void
MainWindow::inboxChanged ()
{
    qDebug ("Inbox changed, update mosquitto");

    MqPublisher pub(QString("qgvnotify:%1").arg(QHostInfo::localHostName()),
                    m_strMqServer, m_mqPort, m_strMqTopic,
                    this);
    pub.publish ("inbox");

    startTimer ();
}//MainWindow::inboxChanged

void
MainWindow::startTimer ()
{
    mainTimer.stop ();
    mainTimer.setSingleShot (true);
    mainTimer.setInterval (5 * 1000);
    mainTimer.start ();
}//MainWindow::startTimer
<|endoftext|>


<commit_before>//-------------------------------------------------------------------------------------------------------
// Copyright (C) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
//-------------------------------------------------------------------------------------------------------
#include "Backend.h"

CodeGenAllocators::CodeGenAllocators(AllocationPolicyManager * policyManager, Js::ScriptContext * scriptContext)
: pageAllocator(policyManager, Js::Configuration::Global.flags, PageAllocatorType_BGJIT,
                (AutoSystemInfo::Data.IsLowMemoryProcess() ?
                 PageAllocator::DefaultLowMaxFreePageCount :
                 PageAllocator::DefaultMaxFreePageCount))
, allocator(L"NativeCode", &pageAllocator, Js::Throw::OutOfMemory)
, emitBufferManager(&allocator, scriptContext->GetThreadContext()->GetCodePageAllocators(), scriptContext, L"JIT code buffer")
#if !_M_X64_OR_ARM64 && _CONTROL_FLOW_GUARD
, canCreatePreReservedSegment(false)
#endif
{
}

CodeGenAllocators::~CodeGenAllocators()
{
}

#if DBG
void
CodeGenAllocators::ClearConcurrentThreadId()
{
    this->pageAllocator.ClearConcurrentThreadId();
}
#endif
<commit_msg>Page allocator used by CustomHeap's metadata don't need standing free page<commit_after>//-------------------------------------------------------------------------------------------------------
// Copyright (C) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
//-------------------------------------------------------------------------------------------------------
#include "Backend.h"

CodeGenAllocators::CodeGenAllocators(AllocationPolicyManager * policyManager, Js::ScriptContext * scriptContext)
: pageAllocator(policyManager, Js::Configuration::Global.flags, PageAllocatorType_BGJIT, 0)
, allocator(L"NativeCode", &pageAllocator, Js::Throw::OutOfMemory)
, emitBufferManager(&allocator, scriptContext->GetThreadContext()->GetCodePageAllocators(), scriptContext, L"JIT code buffer")
#if !_M_X64_OR_ARM64 && _CONTROL_FLOW_GUARD
, canCreatePreReservedSegment(false)
#endif
{
}

CodeGenAllocators::~CodeGenAllocators()
{
}

#if DBG
void
CodeGenAllocators::ClearConcurrentThreadId()
{
    this->pageAllocator.ClearConcurrentThreadId();
}
#endif
<|endoftext|>


<commit_before>//------------------------------------------------------------------------------
// CLING - the C++ LLVM-based InterpreterG :)
// author:  Vassil Vassilev <vvasilev@cern.ch>
//
// This file is dual-licensed: you can choose to license it under the University
// of Illinois Open Source License or the GNU Lesser General Public License. See
// LICENSE.TXT for details.
//------------------------------------------------------------------------------

#include "BackendPasses.h"

#include "llvm/Analysis/InlineCost.h"
#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/Analysis/TargetTransformInfo.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Verifier.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Transforms/IPO.h"
#include "llvm/Transforms/IPO/InlinerPass.h"
#include "llvm/Transforms/IPO/PassManagerBuilder.h"
#include "llvm/Transforms/Scalar.h"

//#include "clang/Basic/LangOptions.h"
//#include "clang/Basic/TargetOptions.h"
#include "clang/Frontend/CodeGenOptions.h"

using namespace cling;
using namespace clang;
using namespace llvm;
using namespace llvm::legacy;

namespace {
  class KeepLocalGVPass: public ModulePass {
    static char ID;

    bool runOnGlobal(GlobalValue& GV) {
      if (GV.isDeclaration())
        return false; // no change.

      // GV is a definition.

      llvm::GlobalValue::LinkageTypes LT = GV.getLinkage();
      if (!GV.isDiscardableIfUnused(LT))
        return false;

      if (LT == llvm::GlobalValue::InternalLinkage
          || LT == llvm::GlobalValue::PrivateLinkage) {
        GV.setLinkage(llvm::GlobalValue::ExternalLinkage);
        return true; // a change!
      }
      return false;
    }

  public:
    KeepLocalGVPass() : ModulePass(ID) {}

    bool runOnModule(Module &M) override {
      bool ret = false;
      for (auto &&F: M)
        ret |= runOnGlobal(F);
      for (auto &&G: M.globals())
        ret |= runOnGlobal(G);
      return ret;
    }
  };
}

char KeepLocalGVPass::ID = 0;

BackendPasses::~BackendPasses() {
  //delete m_PMBuilder->Inliner;
}

void BackendPasses::CreatePasses(llvm::Module& M, int OptLevel)
{
  // From BackEndUtil's clang::EmitAssemblyHelper::CreatePasses().

  CodeGenOptions::InliningMethod Inlining = m_CGOpts.getInlining();

#if 0
  CodeGenOptions& CGOpts_ = const_cast<CodeGenOptions&>(m_CGOpts);
  // DON'T: we will not find our symbols...
  //CGOpts_.CXXCtorDtorAliases = 1;

  // Default clang -O2 on Linux 64bit also has the following, but see
  // CIFactory.cpp.
  CGOpts_.DisableFPElim = 0;
  CGOpts_.DiscardValueNames = 1;
  CGOpts_.OmitLeafFramePointer = 1;
  CGOpts_.OptimizationLevel = 2;
  CGOpts_.RelaxAll = 0;
  CGOpts_.UnrollLoops = 1;
  CGOpts_.VectorizeLoop = 1;
  CGOpts_.VectorizeSLP = 1;
#endif

#ifdef __GNUC__
  // Better inlining is pending https://bugs.llvm.org//show_bug.cgi?id=19668
  // and its consequence https://sft.its.cern.ch/jira/browse/ROOT-7111
  // shown e.g. by roottest/cling/stl/map/badstringMap
  if (Inlining > CodeGenOptions::NormalInlining)
    Inlining = CodeGenOptions::NormalInlining;
#endif

  // Handle disabling of LLVM optimization, where we want to preserve the
  // internal module before any optimization.
  if (m_CGOpts.DisableLLVMOpts) {
    OptLevel = 0;
    // Always keep at least ForceInline - NoInlining is deadly for libc++.
    // Inlining = CGOpts.NoInlining;
  }

  llvm::PassManagerBuilder PMBuilder;
  PMBuilder.OptLevel = OptLevel;
  PMBuilder.SizeLevel = m_CGOpts.OptimizeSize;
  PMBuilder.BBVectorize = 0; // m_CGOpts.VectorizeBB;
  PMBuilder.SLPVectorize = OptLevel > 1 ? 1 : 0; // m_CGOpts.VectorizeSLP
  PMBuilder.LoopVectorize = OptLevel > 1 ? 1 : 0; // m_CGOpts.VectorizeLoop

  PMBuilder.DisableTailCalls = m_CGOpts.DisableTailCalls;
  PMBuilder.DisableUnitAtATime = OptLevel == 2 ? !m_CGOpts.UnitAtATime : 1;
  PMBuilder.DisableUnrollLoops = !m_CGOpts.UnrollLoops;
  PMBuilder.MergeFunctions = m_CGOpts.MergeFunctions;
  PMBuilder.RerollLoops = m_CGOpts.RerollLoops;

  PMBuilder.LibraryInfo = new TargetLibraryInfoImpl(m_TM.getTargetTriple());

  switch (Inlining) {
  case CodeGenOptions::OnlyHintInlining: // fall-through:
    case CodeGenOptions::NoInlining: {
      assert(0 && "libc++ requires at least OnlyAlwaysInlining!");
      break;
    }
    case CodeGenOptions::NormalInlining: {
      PMBuilder.Inliner =
        createFunctionInliningPass(OptLevel, m_CGOpts.OptimizeSize);
      break;
    }
    case CodeGenOptions::OnlyAlwaysInlining:
      // Respect always_inline.
      if (OptLevel == 0)
        // Do not insert lifetime intrinsics at -O0.
        PMBuilder.Inliner = createAlwaysInlinerPass(false);
      else
        PMBuilder.Inliner = createAlwaysInlinerPass();
      break;
  }

  // Set up the per-module pass manager.
  m_MPM[OptLevel].reset(new legacy::PassManager());

  m_MPM[OptLevel]->add(new KeepLocalGVPass());
  m_MPM[OptLevel]->add(createTargetTransformInfoWrapperPass(
                                                   m_TM.getTargetIRAnalysis()));

  // Add target-specific passes that need to run as early as possible.
  PMBuilder.addExtension(
                         PassManagerBuilder::EP_EarlyAsPossible,
                         [&](const PassManagerBuilder &,
                             legacy::PassManagerBase &PM) {
                           m_TM.addEarlyAsPossiblePasses(PM);
                         });

  PMBuilder.addExtension(PassManagerBuilder::EP_EarlyAsPossible,
                         [&](const PassManagerBuilder &,
                             legacy::PassManagerBase &PM) {
                              PM.add(createAddDiscriminatorsPass());
                            });

  //if (!CGOpts.RewriteMapFiles.empty())
  //  addSymbolRewriterPass(CGOpts, m_MPM);

  PMBuilder.populateModulePassManager(*m_MPM[OptLevel]);

  m_FPM[OptLevel].reset(new legacy::FunctionPassManager(&M));
  m_FPM[OptLevel]->add(createTargetTransformInfoWrapperPass(
                                                   m_TM.getTargetIRAnalysis()));
  if (m_CGOpts.VerifyModule)
      m_FPM[OptLevel]->add(createVerifierPass());
  PMBuilder.populateFunctionPassManager(*m_FPM[OptLevel]);
}

void BackendPasses::runOnModule(Module& M, int OptLevel) {

  if (OptLevel < 0)
    OptLevel = 0;
  if (OptLevel > 3)
    OptLevel = 3;

  if (!m_MPM[OptLevel])
    CreatePasses(M, OptLevel);

  static constexpr std::array<llvm::CodeGenOpt::Level, 4> CGOptLevel {
    llvm::CodeGenOpt::None,
    llvm::CodeGenOpt::Less,
    llvm::CodeGenOpt::Default,
    llvm::CodeGenOpt::Aggressive
  };
  // TM's OptLevel is used to build orc::SimpleCompiler passes for every Module.
  m_TM.setOptLevel(CGOptLevel[OptLevel]);

  // Run the per-function passes on the module.
  m_FPM[OptLevel]->doInitialization();
  for (auto&& I: M.functions())
    if (!I.isDeclaration())
      m_FPM[OptLevel]->run(I);
  m_FPM[OptLevel]->doFinalization();

  m_MPM[OptLevel]->run(M);
}
<commit_msg>With the fix for llvm bug 19668: enable inlining also for GCC!<commit_after>//------------------------------------------------------------------------------
// CLING - the C++ LLVM-based InterpreterG :)
// author:  Vassil Vassilev <vvasilev@cern.ch>
//
// This file is dual-licensed: you can choose to license it under the University
// of Illinois Open Source License or the GNU Lesser General Public License. See
// LICENSE.TXT for details.
//------------------------------------------------------------------------------

#include "BackendPasses.h"

#include "llvm/Analysis/InlineCost.h"
#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/Analysis/TargetTransformInfo.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Verifier.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Transforms/IPO.h"
#include "llvm/Transforms/IPO/InlinerPass.h"
#include "llvm/Transforms/IPO/PassManagerBuilder.h"
#include "llvm/Transforms/Scalar.h"

//#include "clang/Basic/LangOptions.h"
//#include "clang/Basic/TargetOptions.h"
#include "clang/Frontend/CodeGenOptions.h"

using namespace cling;
using namespace clang;
using namespace llvm;
using namespace llvm::legacy;

namespace {
  class KeepLocalGVPass: public ModulePass {
    static char ID;

    bool runOnGlobal(GlobalValue& GV) {
      if (GV.isDeclaration())
        return false; // no change.

      // GV is a definition.

      llvm::GlobalValue::LinkageTypes LT = GV.getLinkage();
      if (!GV.isDiscardableIfUnused(LT))
        return false;

      if (LT == llvm::GlobalValue::InternalLinkage
          || LT == llvm::GlobalValue::PrivateLinkage) {
        GV.setLinkage(llvm::GlobalValue::ExternalLinkage);
        return true; // a change!
      }
      return false;
    }

  public:
    KeepLocalGVPass() : ModulePass(ID) {}

    bool runOnModule(Module &M) override {
      bool ret = false;
      for (auto &&F: M)
        ret |= runOnGlobal(F);
      for (auto &&G: M.globals())
        ret |= runOnGlobal(G);
      return ret;
    }
  };
}

char KeepLocalGVPass::ID = 0;

BackendPasses::~BackendPasses() {
  //delete m_PMBuilder->Inliner;
}

void BackendPasses::CreatePasses(llvm::Module& M, int OptLevel)
{
  // From BackEndUtil's clang::EmitAssemblyHelper::CreatePasses().

  CodeGenOptions::InliningMethod Inlining = m_CGOpts.getInlining();

#if 0
  CodeGenOptions& CGOpts_ = const_cast<CodeGenOptions&>(m_CGOpts);
  // DON'T: we will not find our symbols...
  //CGOpts_.CXXCtorDtorAliases = 1;

  // Default clang -O2 on Linux 64bit also has the following, but see
  // CIFactory.cpp.
  CGOpts_.DisableFPElim = 0;
  CGOpts_.DiscardValueNames = 1;
  CGOpts_.OmitLeafFramePointer = 1;
  CGOpts_.OptimizationLevel = 2;
  CGOpts_.RelaxAll = 0;
  CGOpts_.UnrollLoops = 1;
  CGOpts_.VectorizeLoop = 1;
  CGOpts_.VectorizeSLP = 1;
#endif

#if 0 // def __GNUC__
  // Better inlining is pending https://bugs.llvm.org//show_bug.cgi?id=19668
  // and its consequence https://sft.its.cern.ch/jira/browse/ROOT-7111
  // shown e.g. by roottest/cling/stl/map/badstringMap
  if (Inlining > CodeGenOptions::NormalInlining)
    Inlining = CodeGenOptions::NormalInlining;
#endif

  // Handle disabling of LLVM optimization, where we want to preserve the
  // internal module before any optimization.
  if (m_CGOpts.DisableLLVMOpts) {
    OptLevel = 0;
    // Always keep at least ForceInline - NoInlining is deadly for libc++.
    // Inlining = CGOpts.NoInlining;
  }

  llvm::PassManagerBuilder PMBuilder;
  PMBuilder.OptLevel = OptLevel;
  PMBuilder.SizeLevel = m_CGOpts.OptimizeSize;
  PMBuilder.BBVectorize = 0; // m_CGOpts.VectorizeBB;
  PMBuilder.SLPVectorize = OptLevel > 1 ? 1 : 0; // m_CGOpts.VectorizeSLP
  PMBuilder.LoopVectorize = OptLevel > 1 ? 1 : 0; // m_CGOpts.VectorizeLoop

  PMBuilder.DisableTailCalls = m_CGOpts.DisableTailCalls;
  PMBuilder.DisableUnitAtATime = OptLevel == 2 ? !m_CGOpts.UnitAtATime : 1;
  PMBuilder.DisableUnrollLoops = !m_CGOpts.UnrollLoops;
  PMBuilder.MergeFunctions = m_CGOpts.MergeFunctions;
  PMBuilder.RerollLoops = m_CGOpts.RerollLoops;

  PMBuilder.LibraryInfo = new TargetLibraryInfoImpl(m_TM.getTargetTriple());

  switch (Inlining) {
  case CodeGenOptions::OnlyHintInlining: // fall-through:
    case CodeGenOptions::NoInlining: {
      assert(0 && "libc++ requires at least OnlyAlwaysInlining!");
      break;
    }
    case CodeGenOptions::NormalInlining: {
      PMBuilder.Inliner =
        createFunctionInliningPass(OptLevel, m_CGOpts.OptimizeSize);
      break;
    }
    case CodeGenOptions::OnlyAlwaysInlining:
      // Respect always_inline.
      if (OptLevel == 0)
        // Do not insert lifetime intrinsics at -O0.
        PMBuilder.Inliner = createAlwaysInlinerPass(false);
      else
        PMBuilder.Inliner = createAlwaysInlinerPass();
      break;
  }

  // Set up the per-module pass manager.
  m_MPM[OptLevel].reset(new legacy::PassManager());

  m_MPM[OptLevel]->add(new KeepLocalGVPass());
  m_MPM[OptLevel]->add(createTargetTransformInfoWrapperPass(
                                                   m_TM.getTargetIRAnalysis()));

  // Add target-specific passes that need to run as early as possible.
  PMBuilder.addExtension(
                         PassManagerBuilder::EP_EarlyAsPossible,
                         [&](const PassManagerBuilder &,
                             legacy::PassManagerBase &PM) {
                           m_TM.addEarlyAsPossiblePasses(PM);
                         });

  PMBuilder.addExtension(PassManagerBuilder::EP_EarlyAsPossible,
                         [&](const PassManagerBuilder &,
                             legacy::PassManagerBase &PM) {
                              PM.add(createAddDiscriminatorsPass());
                            });

  //if (!CGOpts.RewriteMapFiles.empty())
  //  addSymbolRewriterPass(CGOpts, m_MPM);

  PMBuilder.populateModulePassManager(*m_MPM[OptLevel]);

  m_FPM[OptLevel].reset(new legacy::FunctionPassManager(&M));
  m_FPM[OptLevel]->add(createTargetTransformInfoWrapperPass(
                                                   m_TM.getTargetIRAnalysis()));
  if (m_CGOpts.VerifyModule)
      m_FPM[OptLevel]->add(createVerifierPass());
  PMBuilder.populateFunctionPassManager(*m_FPM[OptLevel]);
}

void BackendPasses::runOnModule(Module& M, int OptLevel) {

  if (OptLevel < 0)
    OptLevel = 0;
  if (OptLevel > 3)
    OptLevel = 3;

  if (!m_MPM[OptLevel])
    CreatePasses(M, OptLevel);

  static constexpr std::array<llvm::CodeGenOpt::Level, 4> CGOptLevel {
    llvm::CodeGenOpt::None,
    llvm::CodeGenOpt::Less,
    llvm::CodeGenOpt::Default,
    llvm::CodeGenOpt::Aggressive
  };
  // TM's OptLevel is used to build orc::SimpleCompiler passes for every Module.
  m_TM.setOptLevel(CGOptLevel[OptLevel]);

  // Run the per-function passes on the module.
  m_FPM[OptLevel]->doInitialization();
  for (auto&& I: M.functions())
    if (!I.isDeclaration())
      m_FPM[OptLevel]->run(I);
  m_FPM[OptLevel]->doFinalization();

  m_MPM[OptLevel]->run(M);
}
<|endoftext|>


<commit_before>#include "warnings-disable.h"

WARNINGS_DISABLE
#include <QtTest/QtTest>

#include "ui_jobstabwidget.h"
#include "ui_jobwidget.h"
WARNINGS_ENABLE

#include "../qtest-platform.h"

#include <TSettings.h>

#include "jobstabwidget.h"
#include "jobwidget.h"

class TestJobsTabWidget : public QObject
{
    Q_OBJECT

private slots:
    void initTestCase();
    void cleanupTestCase();

    // Test JobWidget in isolation
    void jobWidget();
    // This one needs to be before other JobsTabWidget tests
    void defaultJobs();
    void createJob();
    void displayJobDetails();
    void jobListWidget();
};

void TestJobsTabWidget::initTestCase()
{
    QCoreApplication::setOrganizationName(TEST_NAME);

    IF_NOT_VISUAL
    {
        // Use a custom message handler to filter out unwanted messages
        orig_message_handler = qInstallMessageHandler(offscreenMessageOutput);
    }

    // Deal with PersistentStore
    PersistentStore::initializePersistentStore();
    PersistentStore &store = PersistentStore::instance();
    int              ok    = store.init();
    QVERIFY(ok);
}

void TestJobsTabWidget::cleanupTestCase()
{
    PersistentStore::destroy();
    TSettings::destroy();
    // Wait to (probably?) allow something within QWidgetLineControl to
    // get freed.  (Randomly occurring memorty leak.)
    QTest::qWait(100);
}

void TestJobsTabWidget::jobWidget()
{
    JobWidget *jobWidget = new JobWidget();
    delete jobWidget;
}

void TestJobsTabWidget::defaultJobs()
{
    JobsTabWidget *    jobstabwidget = new JobsTabWidget();
    Ui::JobsTabWidget *ui            = jobstabwidget->_ui;
    QSignalSpy         sig_jobAdded(jobstabwidget, SIGNAL(jobAdded(JobPtr)));

    VISUAL_INIT(jobstabwidget);

    // We start off showing the default jobs prompt
    QVERIFY(ui->defaultJobs->isVisibleTo(jobstabwidget) == true);

    // Don't create the default jobs; no more prompt
    ui->dismissButton->clicked();
    QVERIFY(ui->defaultJobs->isVisibleTo(jobstabwidget) == false);
    QVERIFY(sig_jobAdded.count() == 0);
    VISUAL_WAIT;

    delete jobstabwidget;
}

void TestJobsTabWidget::createJob()
{
    JobsTabWidget *    jobstabwidget = new JobsTabWidget();
    Ui::JobsTabWidget *ui            = jobstabwidget->_ui;
    JobWidget *        jobWidget     = jobstabwidget->_ui->jobDetailsWidget;
    Ui::JobWidget *    jobWidget_ui  = jobWidget->_ui;
    QSignalSpy         sig_jobAdded(jobstabwidget, SIGNAL(jobAdded(JobPtr)));

    VISUAL_INIT(jobstabwidget);

    // Start out without the button being enabled
    QVERIFY(ui->addJobButton->text() == QString("Add job"));
    QVERIFY(sig_jobAdded.count() == 0);
    VISUAL_WAIT;

    // Create a job
    jobstabwidget->createNewJob(QList<QUrl>() << QUrl("file://" TEST_DIR),
                                QString("test-job"));
    QVERIFY(ui->addJobButton->text() == QString("Save"));
    QVERIFY(ui->addJobButton->isEnabled());
    QVERIFY(jobWidget_ui->infoLabel->text() == "");
    VISUAL_WAIT;

    // Adds the job to the list; makes the button ready to add again
    jobstabwidget->addJobClicked();
    QVERIFY(ui->addJobButton->text() == QString("Add job"));
    QVERIFY(sig_jobAdded.count() == 1);
    VISUAL_WAIT;

    delete jobstabwidget;
}

void TestJobsTabWidget::displayJobDetails()
{
    JobsTabWidget *    jobstabwidget = new JobsTabWidget();
    Ui::JobsTabWidget *ui            = jobstabwidget->_ui;
    QSignalSpy         sig_jobAdded(jobstabwidget, SIGNAL(jobAdded(JobPtr)));
    QSignalSpy sig_backupNow(jobstabwidget, SIGNAL(backupNow(BackupTaskPtr)));

    VISUAL_INIT(jobstabwidget);

    // Create a job
    jobstabwidget->createNewJob(QList<QUrl>() << QUrl("file://" TEST_DIR),
                                QString("test-job-display"));
    jobstabwidget->addJobClicked();
    JobPtr job = sig_jobAdded.takeFirst().at(0).value<JobPtr>();
    VISUAL_WAIT;

    // Don't show the job
    jobstabwidget->hideJobDetails();
    QVERIFY(ui->jobDetailsWidget->isVisibleTo(jobstabwidget) == false);
    VISUAL_WAIT;

    // Show the job
    jobstabwidget->displayJobDetails(job);
    QVERIFY(ui->jobDetailsWidget->isVisibleTo(jobstabwidget) == true);
    VISUAL_WAIT;

    // Create a new archive for the job
    QVERIFY(sig_backupNow.count() == 0);
    ui->jobDetailsWidget->backupButtonClicked();
    QVERIFY(sig_backupNow.count() == 1);
    VISUAL_WAIT;

    delete jobstabwidget;
}

void TestJobsTabWidget::jobListWidget()
{
    JobsTabWidget *    jobstabwidget = new JobsTabWidget();
    Ui::JobsTabWidget *ui            = jobstabwidget->_ui;
    QSignalSpy         sig_jobAdded(jobstabwidget, SIGNAL(jobAdded(JobPtr)));
    QSignalSpy sig_deleteJob(jobstabwidget, SIGNAL(deleteJob(JobPtr, bool)));

    VISUAL_INIT(jobstabwidget);

    // Create a job
    jobstabwidget->createNewJob(QList<QUrl>() << QUrl("file://" TEST_DIR),
                                QString("test-job-joblistwidget"));
    jobstabwidget->addJobClicked();
    JobPtr job = sig_jobAdded.takeFirst().at(0).value<JobPtr>();
    QVERIFY(ui->jobListWidget->count() == 1);
    VISUAL_WAIT;

    // Don't show the job
    jobstabwidget->hideJobDetails();
    QVERIFY(ui->jobDetailsWidget->isVisibleTo(jobstabwidget) == false);
    VISUAL_WAIT;

    // Show the job with the joblistwidget
    jobstabwidget->jobInspectByRef("test-job-joblistwidget");
    QVERIFY(ui->jobDetailsWidget->isVisibleTo(jobstabwidget) == true);
    VISUAL_WAIT;

    delete jobstabwidget;
}

QTEST_MAIN(TestJobsTabWidget)
#include "test-jobstabwidget.moc"
<commit_msg>tests/jobstabwidget: add a second job<commit_after>#include "warnings-disable.h"

WARNINGS_DISABLE
#include <QtTest/QtTest>

#include "ui_jobstabwidget.h"
#include "ui_jobwidget.h"
WARNINGS_ENABLE

#include "../qtest-platform.h"

#include <TSettings.h>

#include "jobstabwidget.h"
#include "jobwidget.h"

class TestJobsTabWidget : public QObject
{
    Q_OBJECT

private slots:
    void initTestCase();
    void cleanupTestCase();

    // Test JobWidget in isolation
    void jobWidget();
    // This one needs to be before other JobsTabWidget tests
    void defaultJobs();
    void createJob();
    void displayJobDetails();
    void jobListWidget();
};

void TestJobsTabWidget::initTestCase()
{
    QCoreApplication::setOrganizationName(TEST_NAME);

    IF_NOT_VISUAL
    {
        // Use a custom message handler to filter out unwanted messages
        orig_message_handler = qInstallMessageHandler(offscreenMessageOutput);
    }

    // Deal with PersistentStore
    PersistentStore::initializePersistentStore();
    PersistentStore &store = PersistentStore::instance();
    int              ok    = store.init();
    QVERIFY(ok);
}

void TestJobsTabWidget::cleanupTestCase()
{
    PersistentStore::destroy();
    TSettings::destroy();
    // Wait to (probably?) allow something within QWidgetLineControl to
    // get freed.  (Randomly occurring memorty leak.)
    QTest::qWait(100);
}

void TestJobsTabWidget::jobWidget()
{
    JobWidget *jobWidget = new JobWidget();
    delete jobWidget;
}

void TestJobsTabWidget::defaultJobs()
{
    JobsTabWidget *    jobstabwidget = new JobsTabWidget();
    Ui::JobsTabWidget *ui            = jobstabwidget->_ui;
    QSignalSpy         sig_jobAdded(jobstabwidget, SIGNAL(jobAdded(JobPtr)));

    VISUAL_INIT(jobstabwidget);

    // We start off showing the default jobs prompt
    QVERIFY(ui->defaultJobs->isVisibleTo(jobstabwidget) == true);

    // Don't create the default jobs; no more prompt
    ui->dismissButton->clicked();
    QVERIFY(ui->defaultJobs->isVisibleTo(jobstabwidget) == false);
    QVERIFY(sig_jobAdded.count() == 0);
    VISUAL_WAIT;

    delete jobstabwidget;
}

void TestJobsTabWidget::createJob()
{
    JobsTabWidget *    jobstabwidget = new JobsTabWidget();
    Ui::JobsTabWidget *ui            = jobstabwidget->_ui;
    JobWidget *        jobWidget     = jobstabwidget->_ui->jobDetailsWidget;
    Ui::JobWidget *    jobWidget_ui  = jobWidget->_ui;
    QSignalSpy         sig_jobAdded(jobstabwidget, SIGNAL(jobAdded(JobPtr)));

    VISUAL_INIT(jobstabwidget);

    // Start out without the button being enabled
    QVERIFY(ui->addJobButton->text() == QString("Add job"));
    QVERIFY(sig_jobAdded.count() == 0);
    VISUAL_WAIT;

    // Create a job
    jobstabwidget->createNewJob(QList<QUrl>() << QUrl("file://" TEST_DIR),
                                QString("test-job"));
    QVERIFY(ui->addJobButton->text() == QString("Save"));
    QVERIFY(ui->addJobButton->isEnabled());
    QVERIFY(jobWidget_ui->infoLabel->text() == "");
    VISUAL_WAIT;

    // Adds the job to the list; makes the button ready to add again
    jobstabwidget->addJobClicked();
    QVERIFY(ui->addJobButton->text() == QString("Add job"));
    QVERIFY(sig_jobAdded.count() == 1);
    VISUAL_WAIT;

    // Create a second job
    jobstabwidget->createNewJob(QList<QUrl>() << QUrl("file://" TEST_DIR),
                                QString("test-job-2"));
    QVERIFY(ui->addJobButton->text() == QString("Save"));
    QVERIFY(ui->addJobButton->isEnabled());
    QVERIFY(jobWidget_ui->infoLabel->text() == "");
    VISUAL_WAIT;

    // Adds the job to the list; makes the button ready to add again
    jobstabwidget->addJobClicked();
    QVERIFY(ui->addJobButton->text() == QString("Add job"));
    QVERIFY(sig_jobAdded.count() == 2);
    VISUAL_WAIT;

    delete jobstabwidget;
}

void TestJobsTabWidget::displayJobDetails()
{
    JobsTabWidget *    jobstabwidget = new JobsTabWidget();
    Ui::JobsTabWidget *ui            = jobstabwidget->_ui;
    QSignalSpy         sig_jobAdded(jobstabwidget, SIGNAL(jobAdded(JobPtr)));
    QSignalSpy sig_backupNow(jobstabwidget, SIGNAL(backupNow(BackupTaskPtr)));

    VISUAL_INIT(jobstabwidget);

    // Create a job
    jobstabwidget->createNewJob(QList<QUrl>() << QUrl("file://" TEST_DIR),
                                QString("test-job-display"));
    jobstabwidget->addJobClicked();
    JobPtr job = sig_jobAdded.takeFirst().at(0).value<JobPtr>();
    VISUAL_WAIT;

    // Don't show the job
    jobstabwidget->hideJobDetails();
    QVERIFY(ui->jobDetailsWidget->isVisibleTo(jobstabwidget) == false);
    VISUAL_WAIT;

    // Show the job
    jobstabwidget->displayJobDetails(job);
    QVERIFY(ui->jobDetailsWidget->isVisibleTo(jobstabwidget) == true);
    VISUAL_WAIT;

    // Create a new archive for the job
    QVERIFY(sig_backupNow.count() == 0);
    ui->jobDetailsWidget->backupButtonClicked();
    QVERIFY(sig_backupNow.count() == 1);
    VISUAL_WAIT;

    delete jobstabwidget;
}

void TestJobsTabWidget::jobListWidget()
{
    JobsTabWidget *    jobstabwidget = new JobsTabWidget();
    Ui::JobsTabWidget *ui            = jobstabwidget->_ui;
    QSignalSpy         sig_jobAdded(jobstabwidget, SIGNAL(jobAdded(JobPtr)));
    QSignalSpy sig_deleteJob(jobstabwidget, SIGNAL(deleteJob(JobPtr, bool)));

    VISUAL_INIT(jobstabwidget);

    // Create a job
    jobstabwidget->createNewJob(QList<QUrl>() << QUrl("file://" TEST_DIR),
                                QString("test-job-joblistwidget"));
    jobstabwidget->addJobClicked();
    JobPtr job = sig_jobAdded.takeFirst().at(0).value<JobPtr>();
    QVERIFY(ui->jobListWidget->count() == 1);
    VISUAL_WAIT;

    // Don't show the job
    jobstabwidget->hideJobDetails();
    QVERIFY(ui->jobDetailsWidget->isVisibleTo(jobstabwidget) == false);
    VISUAL_WAIT;

    // Show the job with the joblistwidget
    jobstabwidget->jobInspectByRef("test-job-joblistwidget");
    QVERIFY(ui->jobDetailsWidget->isVisibleTo(jobstabwidget) == true);
    VISUAL_WAIT;

    delete jobstabwidget;
}

QTEST_MAIN(TestJobsTabWidget)
#include "test-jobstabwidget.moc"
<|endoftext|>


<commit_before>#include <YCommon/Headers/stdincludes.h>
#include "ThreadPool.h"

#include <YCommon/Headers/Atomics.h>
#include <YCommon/YPlatform/Timer.h>

namespace YCommon { namespace YContainers {

void ThreadPool::ThreadData::Initialize(size_t num_threads, void* buffer,
                                       size_t buffer_size) {
  mRunState = kRunState_Stopped;
  mSemaphore.Initialize(static_cast<int>(num_threads),
                        static_cast<int>(num_threads));
  mRunQueue.Initialize(static_cast<ThreadPool::ThreadData::RunArgs*>(buffer),
                       buffer_size,
                       buffer_size / sizeof(ThreadPool::ThreadData::RunArgs));
}

ThreadPool::ThreadPool(size_t num_threads, void* buffer, size_t buffer_size)
    : mThreads(NULL),
      mNumThreads(0) {
  const size_t thread_size = sizeof(YPlatform::Thread) * num_threads;
  YASSERT(buffer_size > thread_size,
          "Buffer size is not big enough to contain ThreadPool");

  const size_t num_run_args = ((buffer_size - thread_size) /
                               sizeof(ThreadPool::ThreadData::RunArgs));
  YASSERT(num_run_args > 0,
          "Number of run arguments must be greater than 0");

  mThreads = new (buffer) YPlatform::Thread[num_threads];
  mNumThreads = num_threads;
  mThreadData.Initialize(num_threads,
                         static_cast<uint8_t*>(buffer) + thread_size,
                         buffer_size - thread_size);
}

ThreadPool::~ThreadPool() {
  Stop();

  const size_t num_threads = mNumThreads;
  for (size_t i = 0; i < num_threads; ++i) {
    // Explicitly call destructor for placement new.
    mThreads[i].~Thread();
  }
}

bool ThreadPool::EnqueueRun(YPlatform::ThreadRoutine thread_routine,
                            void* thread_args) {
  ThreadData::RunArgs run_args = {
    thread_routine,
    thread_args,
  };
  if (mThreadData.mRunQueue.Enqueue(run_args)) {
    if (mThreadData.mRunState == ThreadData::kRunState_Running)
      mThreadData.mSemaphore.Release();
    return true;
  }

  return false;
}

bool ThreadPool::Start() {
  const ThreadData::RunState prev_run_state = mThreadData.mRunState;
  if (prev_run_state == ThreadData::kRunState_Running) {
    return false;
  }

  mThreadData.mRunState = ThreadData::kRunState_Running;
  MemoryBarrier();

  const size_t num_threads = mNumThreads;
  for (size_t i = 0; i < num_threads; ++i) {
    if (prev_run_state == ThreadData::kRunState_Stopped) {
      mThreads[i].Initialize(ThreadPool::ThreadPoolThread, &mThreadData);
      mThreads[i].Run();
    } else {
      mThreadData.mSemaphore.Release();
    }
  }
  return true;
}

bool ThreadPool::Pause() {
  if (mThreadData.mRunState != ThreadData::kRunState_Running)
    return false;

  mThreadData.mRunState = ThreadData::kRunState_Paused;
  MemoryBarrier();
  return true;
}

bool ThreadPool::Stop(size_t milliseconds) {
  mThreadData.mRunState = ThreadData::kRunState_Stopped;
  MemoryBarrier();

  const size_t num_threads = mNumThreads;
  mThreadData.mSemaphore.Release(static_cast<int>(num_threads));

  if (milliseconds == static_cast<size_t>(-1)) {
    for (size_t i = 0; i < num_threads; ++i) {
      mThreads[i].Join();
    }
  } else {
    YPlatform::Timer timer;
    timer.Start();

    const uint64_t milli64 = static_cast<uint64_t>(milliseconds);
    for (size_t i = 0; i < num_threads; ++i) {
      timer.Pulse();
      const uint64_t waited = timer.GetPulsedTimeMilli();
      if (waited >= milli64 ||
          !mThreads[i].Join(static_cast<size_t>(milli64 - waited))) {
        return false;
      }
    }
  }

  return true;
}

uintptr_t ThreadPool::ThreadPoolThread(void* arg) {
  ThreadData* thread_data = static_cast<ThreadData*>(arg);

  ThreadData::RunArgs run_arg;
  for (;;) {
    const ThreadData::RunState run_state = thread_data->mRunState;
    MemoryBarrier();

    if (run_state == ThreadData::kRunState_Stopped) {
      break;
    } else if (run_state == ThreadData::kRunState_Running &&
               thread_data->mRunQueue.Dequeue(run_arg)) {
      run_arg.thread_routine(run_arg.thread_args);
      continue;
    }

    // Idle, Stopped, or nothing enqueued
    thread_data->mSemaphore.Wait();
  }
  return 0;
}

}} // namespace YCommon { namespace YContainers {
<commit_msg>Fixed platinum build<commit_after>#include <YCommon/Headers/stdincludes.h>
#include "ThreadPool.h"

#include <YCommon/Headers/Atomics.h>
#include <YCommon/YPlatform/Timer.h>

namespace YCommon { namespace YContainers {

void ThreadPool::ThreadData::Initialize(size_t num_threads, void* buffer,
                                       size_t buffer_size) {
  mRunState = kRunState_Stopped;
  mSemaphore.Initialize(static_cast<int>(num_threads),
                        static_cast<int>(num_threads));
  mRunQueue.Initialize(static_cast<ThreadPool::ThreadData::RunArgs*>(buffer),
                       buffer_size,
                       buffer_size / sizeof(ThreadPool::ThreadData::RunArgs));
}

ThreadPool::ThreadPool(size_t num_threads, void* buffer, size_t buffer_size)
    : mThreads(NULL),
      mNumThreads(0) {
  const size_t thread_size = sizeof(YPlatform::Thread) * num_threads;
  YASSERT(buffer_size > thread_size,
          "Buffer size is not big enough to contain ThreadPool");

  YASSERT(((buffer_size - thread_size) /
            sizeof(ThreadPool::ThreadData::RunArgs)) > 0,
          "Number of run arguments must be greater than 0");

  mThreads = new (buffer) YPlatform::Thread[num_threads];
  mNumThreads = num_threads;
  mThreadData.Initialize(num_threads,
                         static_cast<uint8_t*>(buffer) + thread_size,
                         buffer_size - thread_size);
}

ThreadPool::~ThreadPool() {
  Stop();

  const size_t num_threads = mNumThreads;
  for (size_t i = 0; i < num_threads; ++i) {
    // Explicitly call destructor for placement new.
    mThreads[i].~Thread();
  }
}

bool ThreadPool::EnqueueRun(YPlatform::ThreadRoutine thread_routine,
                            void* thread_args) {
  ThreadData::RunArgs run_args = {
    thread_routine,
    thread_args,
  };
  if (mThreadData.mRunQueue.Enqueue(run_args)) {
    if (mThreadData.mRunState == ThreadData::kRunState_Running)
      mThreadData.mSemaphore.Release();
    return true;
  }

  return false;
}

bool ThreadPool::Start() {
  const ThreadData::RunState prev_run_state = mThreadData.mRunState;
  if (prev_run_state == ThreadData::kRunState_Running) {
    return false;
  }

  mThreadData.mRunState = ThreadData::kRunState_Running;
  MemoryBarrier();

  const size_t num_threads = mNumThreads;
  for (size_t i = 0; i < num_threads; ++i) {
    if (prev_run_state == ThreadData::kRunState_Stopped) {
      mThreads[i].Initialize(ThreadPool::ThreadPoolThread, &mThreadData);
      mThreads[i].Run();
    } else {
      mThreadData.mSemaphore.Release();
    }
  }
  return true;
}

bool ThreadPool::Pause() {
  if (mThreadData.mRunState != ThreadData::kRunState_Running)
    return false;

  mThreadData.mRunState = ThreadData::kRunState_Paused;
  MemoryBarrier();
  return true;
}

bool ThreadPool::Stop(size_t milliseconds) {
  mThreadData.mRunState = ThreadData::kRunState_Stopped;
  MemoryBarrier();

  const size_t num_threads = mNumThreads;
  mThreadData.mSemaphore.Release(static_cast<int>(num_threads));

  if (milliseconds == static_cast<size_t>(-1)) {
    for (size_t i = 0; i < num_threads; ++i) {
      mThreads[i].Join();
    }
  } else {
    YPlatform::Timer timer;
    timer.Start();

    const uint64_t milli64 = static_cast<uint64_t>(milliseconds);
    for (size_t i = 0; i < num_threads; ++i) {
      timer.Pulse();
      const uint64_t waited = timer.GetPulsedTimeMilli();
      if (waited >= milli64 ||
          !mThreads[i].Join(static_cast<size_t>(milli64 - waited))) {
        return false;
      }
    }
  }

  return true;
}

uintptr_t ThreadPool::ThreadPoolThread(void* arg) {
  ThreadData* thread_data = static_cast<ThreadData*>(arg);

  ThreadData::RunArgs run_arg;
  for (;;) {
    const ThreadData::RunState run_state = thread_data->mRunState;
    MemoryBarrier();

    if (run_state == ThreadData::kRunState_Stopped) {
      break;
    } else if (run_state == ThreadData::kRunState_Running &&
               thread_data->mRunQueue.Dequeue(run_arg)) {
      run_arg.thread_routine(run_arg.thread_args);
      continue;
    }

    // Idle, Stopped, or nothing enqueued
    thread_data->mSemaphore.Wait();
  }
  return 0;
}

}} // namespace YCommon { namespace YContainers {
<|endoftext|>


<commit_before>/******************************************************************************\
* File:          stc.cpp
* Purpose:       Implementation of class 'wxExSTCWithFrame'
* Author:        Anton van Wezenbeek
* RCS-ID:        $Id$
*
* Copyright (c) 1998-2009 Anton van Wezenbeek
* All rights are reserved. Reproduction in whole or part is prohibited
* without the written consent of the copyright owner.
\******************************************************************************/

#include <wx/config.h>
#include <wx/extension/filedlg.h>
#include <wx/extension/header.h>
#include <wx/extension/vcs.h>
#include <wx/extension/util.h>
#include <wx/extension/report/stc.h>
#include <wx/extension/report/defs.h>
#include <wx/extension/report/frame.h>
#include <wx/extension/report/textfile.h>
#include <wx/extension/report/util.h>

BEGIN_EVENT_TABLE(wxExSTCWithFrame, wxExSTC)
  EVT_MENU_RANGE(
    ID_EDIT_VCS_LOWEST,
    ID_EDIT_VCS_HIGHEST,
    wxExSTCWithFrame::OnCommand)
  EVT_MENU_RANGE(ID_STC_LOWEST, ID_STC_HIGHEST, wxExSTCWithFrame::OnCommand)
  EVT_MENU_RANGE(ID_TOOL_LOWEST, ID_TOOL_HIGHEST, wxExSTCWithFrame::OnCommand)
END_EVENT_TABLE()

wxExSTCWithFrame::wxExSTCWithFrame(wxWindow* parent,
  wxExFrameWithHistory* frame,
  const wxString& value,
  long flags,
  const wxString& title,
  long type,
  wxWindowID id,
  const wxPoint& pos,
  const wxSize& size,
  long style)
  : wxExSTC(parent, value, flags, title, type, id, pos, size, style)
  , m_Frame(frame)
{
}

wxExSTCWithFrame::wxExSTCWithFrame(wxWindow* parent,
  wxExFrameWithHistory* frame,
  const wxExFileName& filename,
  int line_number,
  const wxString& match,
  long flags,
  long type,
  wxWindowID id,
  const wxPoint& pos,
  const wxSize& size,
  long style)
  : wxExSTC(
      parent,
      filename,
      line_number,
      match,
      flags,
      type,
      id,
      pos,
      size,
      style)
  , m_Frame(frame)
{
  m_Frame->SetRecentFile(GetFileName().GetFullPath());
}

wxExSTCWithFrame::wxExSTCWithFrame(
  const wxExSTC& stc,
  wxExFrameWithHistory* frame)
  : wxExSTC(stc)
  , m_Frame(frame)
{
}

void wxExSTCWithFrame::BuildPopupMenu(wxExMenu& menu)
{
  wxExSTC::BuildPopupMenu(menu);

  // Add tools if we have at least some text, the tool flag,
  // and a lexer.
  if (GetSelectedText().empty() && GetTextLength() > 0 &&
     (GetMenuFlags() & STC_MENU_TOOL) &&
      !GetFileName().GetLexer().GetScintillaLexer().empty())
  {
    menu.AppendSeparator();
    menu.AppendTools();
  }

  if (GetMenuFlags() & (STC_MENU_REPORT_FIND | STC_MENU_REPORT_REPLACE))
  {
    menu.AppendSeparator();

    if (GetMenuFlags() & STC_MENU_REPORT_FIND)
    {
      menu.Append(ID_FIND_IN_FILES, wxExEllipsed(_("Find &In Files")));
    }

    if (GetMenuFlags() & STC_MENU_REPORT_REPLACE)
    {
      menu.Append(ID_REPLACE_IN_FILES, wxExEllipsed(_("&Replace In Files")));
    }
  }

  if ( GetFileName().FileExists() && GetSelectedText().empty() &&
      (GetMenuFlags() & STC_MENU_COMPARE_OR_VCS))
  {
    if (wxExVCS::Get()->DirExists(GetFileName()))
    {
      menu.AppendVCS();
    }
    else if (!wxConfigBase::Get()->Read(_("Comparator")).empty())
    {
      menu.AppendSeparator();
      menu.Append(ID_STC_COMPARE, wxExEllipsed(_("&Compare Recent Version")));
    }
  }

  if (!GetReadOnly())
  {
    menu.AppendSeparator();
    menu.Append(ID_STC_ADD_HEADER, wxExEllipsed(_("&Add Header")));
  }
}

void wxExSTCWithFrame::OnCommand(wxCommandEvent& command)
{
  wxExFileDialog dlg(this, this);

  if (dlg.ShowModalIfChanged() == wxID_CANCEL)
  {
    return;
  }

  if (command.GetId() > ID_TOOL_LOWEST && command.GetId() < ID_TOOL_HIGHEST)
  {
    const wxExTool tool(command.GetId());

    if (wxExTextFileWithListView::SetupTool(tool, m_Frame))
    {
      wxExTextFileWithListView report(GetFileName(), tool);
      report.RunTool();
      tool.Log(&report.GetStatistics().GetElements(), GetFileName().GetFullPath());

      if (tool.IsCount())
      {
        m_Frame->OpenFile(
          tool.GetLogfileName(), 0, wxEmptyString, STC_OPEN_FROM_OTHER);
      }
    }

    return;
  }

  if (command.GetId() > ID_EDIT_VCS_LOWEST &&
      command.GetId() < ID_EDIT_VCS_HIGHEST)
  {
    wxExVCS vcs(command.GetId(), GetFileName().GetFullPath());

    if (command.GetId() == ID_EDIT_VCS_CAT ||
        command.GetId() == ID_EDIT_VCS_BLAME)
    {
      if (vcs.ExecuteDialog(this) == wxID_OK)
      {
        m_Frame->OpenFile(
          GetFileName(),
          vcs.GetCommandWithFlags(),
          vcs.GetOutput(),
          wxExSTC::STC_OPEN_READ_ONLY);
      }
    }
    else
    {
      vcs.Request(this);
    }

    return;
  }

  switch (command.GetId())
  {
  case ID_STC_ADD_HEADER:
    {
      const wxExHeader header;

      if (header.ShowDialog(this) != wxID_CANCEL)
      {
        if (GetFileName().GetLexer().GetScintillaLexer() == "hypertext")
        {
          GotoLine(1);
        }
        else
        {
          DocumentStart();
        }

        AddText(header.Get(&GetFileName()));
      }
    }
    break;

  case ID_STC_COMPARE:
    {
      wxFileName lastfile;

      if (wxExFindOtherFileName(GetFileName(), NULL, &lastfile))
      {
        wxExCompareFile(GetFileName(), lastfile);
      }
    }
    break;

  default: wxFAIL;
    break;
  }
}

bool wxExSTCWithFrame::Open(
  const wxExFileName& filename,
  int line_number,
  const wxString& match,
  long flags)
{
  bool retValue;

  if (flags & STC_OPEN_FROM_OTHER)
  {
    retValue = m_Frame->OpenFile(filename, line_number, match, flags);
  }
  else
  {
    retValue = wxExSTC::Open(filename, line_number, match, flags);

    if (retValue)
    {
      m_Frame->SetRecentFile(filename.GetFullPath());
    }
  }

  return retValue;
}

void wxExSTCWithFrame::PropertiesMessage() const
{
  wxExSTC::PropertiesMessage();

  m_Frame->SetTitle(
    GetName() +
      (GetReadOnly() ? " [" + _("Readonly") + "]": wxString(wxEmptyString)),
    wxEmptyString);
}
<commit_msg>use stc lexer instead of filename lexer<commit_after>/******************************************************************************\
* File:          stc.cpp
* Purpose:       Implementation of class 'wxExSTCWithFrame'
* Author:        Anton van Wezenbeek
* RCS-ID:        $Id$
*
* Copyright (c) 1998-2009 Anton van Wezenbeek
* All rights are reserved. Reproduction in whole or part is prohibited
* without the written consent of the copyright owner.
\******************************************************************************/

#include <wx/config.h>
#include <wx/extension/filedlg.h>
#include <wx/extension/header.h>
#include <wx/extension/vcs.h>
#include <wx/extension/util.h>
#include <wx/extension/report/stc.h>
#include <wx/extension/report/defs.h>
#include <wx/extension/report/frame.h>
#include <wx/extension/report/textfile.h>
#include <wx/extension/report/util.h>

BEGIN_EVENT_TABLE(wxExSTCWithFrame, wxExSTC)
  EVT_MENU_RANGE(
    ID_EDIT_VCS_LOWEST,
    ID_EDIT_VCS_HIGHEST,
    wxExSTCWithFrame::OnCommand)
  EVT_MENU_RANGE(ID_STC_LOWEST, ID_STC_HIGHEST, wxExSTCWithFrame::OnCommand)
  EVT_MENU_RANGE(ID_TOOL_LOWEST, ID_TOOL_HIGHEST, wxExSTCWithFrame::OnCommand)
END_EVENT_TABLE()

wxExSTCWithFrame::wxExSTCWithFrame(wxWindow* parent,
  wxExFrameWithHistory* frame,
  const wxString& value,
  long flags,
  const wxString& title,
  long type,
  wxWindowID id,
  const wxPoint& pos,
  const wxSize& size,
  long style)
  : wxExSTC(parent, value, flags, title, type, id, pos, size, style)
  , m_Frame(frame)
{
}

wxExSTCWithFrame::wxExSTCWithFrame(wxWindow* parent,
  wxExFrameWithHistory* frame,
  const wxExFileName& filename,
  int line_number,
  const wxString& match,
  long flags,
  long type,
  wxWindowID id,
  const wxPoint& pos,
  const wxSize& size,
  long style)
  : wxExSTC(
      parent,
      filename,
      line_number,
      match,
      flags,
      type,
      id,
      pos,
      size,
      style)
  , m_Frame(frame)
{
  m_Frame->SetRecentFile(GetFileName().GetFullPath());
}

wxExSTCWithFrame::wxExSTCWithFrame(
  const wxExSTC& stc,
  wxExFrameWithHistory* frame)
  : wxExSTC(stc)
  , m_Frame(frame)
{
}

void wxExSTCWithFrame::BuildPopupMenu(wxExMenu& menu)
{
  wxExSTC::BuildPopupMenu(menu);

  // Add tools if we have at least some text, the tool flag,
  // and a lexer.
  if (GetSelectedText().empty() && GetTextLength() > 0 &&
     (GetMenuFlags() & STC_MENU_TOOL) &&
      !GetLexer().GetScintillaLexer().empty())
  {
    menu.AppendSeparator();
    menu.AppendTools();
  }

  if (GetMenuFlags() & (STC_MENU_REPORT_FIND | STC_MENU_REPORT_REPLACE))
  {
    menu.AppendSeparator();

    if (GetMenuFlags() & STC_MENU_REPORT_FIND)
    {
      menu.Append(ID_FIND_IN_FILES, wxExEllipsed(_("Find &In Files")));
    }

    if (GetMenuFlags() & STC_MENU_REPORT_REPLACE)
    {
      menu.Append(ID_REPLACE_IN_FILES, wxExEllipsed(_("&Replace In Files")));
    }
  }

  if ( GetFileName().FileExists() && GetSelectedText().empty() &&
      (GetMenuFlags() & STC_MENU_COMPARE_OR_VCS))
  {
    if (wxExVCS::Get()->DirExists(GetFileName()))
    {
      menu.AppendVCS();
    }
    else if (!wxConfigBase::Get()->Read(_("Comparator")).empty())
    {
      menu.AppendSeparator();
      menu.Append(ID_STC_COMPARE, wxExEllipsed(_("&Compare Recent Version")));
    }
  }

  if (!GetReadOnly())
  {
    menu.AppendSeparator();
    menu.Append(ID_STC_ADD_HEADER, wxExEllipsed(_("&Add Header")));
  }
}

void wxExSTCWithFrame::OnCommand(wxCommandEvent& command)
{
  wxExFileDialog dlg(this, this);

  if (dlg.ShowModalIfChanged() == wxID_CANCEL)
  {
    return;
  }

  if (command.GetId() > ID_TOOL_LOWEST && command.GetId() < ID_TOOL_HIGHEST)
  {
    const wxExTool tool(command.GetId());

    if (wxExTextFileWithListView::SetupTool(tool, m_Frame))
    {
      wxExTextFileWithListView report(GetFileName(), tool);
      report.RunTool();
      tool.Log(&report.GetStatistics().GetElements(), GetFileName().GetFullPath());

      if (tool.IsCount())
      {
        m_Frame->OpenFile(
          tool.GetLogfileName(), 0, wxEmptyString, STC_OPEN_FROM_OTHER);
      }
    }

    return;
  }

  if (command.GetId() > ID_EDIT_VCS_LOWEST &&
      command.GetId() < ID_EDIT_VCS_HIGHEST)
  {
    wxExVCS vcs(command.GetId(), GetFileName().GetFullPath());

    if (command.GetId() == ID_EDIT_VCS_CAT ||
        command.GetId() == ID_EDIT_VCS_BLAME)
    {
      if (vcs.ExecuteDialog(this) == wxID_OK)
      {
        m_Frame->OpenFile(
          GetFileName(),
          vcs.GetCommandWithFlags(),
          vcs.GetOutput(),
          wxExSTC::STC_OPEN_READ_ONLY);
      }
    }
    else
    {
      vcs.Request(this);
    }

    return;
  }

  switch (command.GetId())
  {
  case ID_STC_ADD_HEADER:
    {
      const wxExHeader header;

      if (header.ShowDialog(this) != wxID_CANCEL)
      {
        if (GetLexer().GetScintillaLexer() == "hypertext")
        {
          GotoLine(1);
        }
        else
        {
          DocumentStart();
        }

        AddText(header.Get(&GetFileName()));
      }
    }
    break;

  case ID_STC_COMPARE:
    {
      wxFileName lastfile;

      if (wxExFindOtherFileName(GetFileName(), NULL, &lastfile))
      {
        wxExCompareFile(GetFileName(), lastfile);
      }
    }
    break;

  default: wxFAIL;
    break;
  }
}

bool wxExSTCWithFrame::Open(
  const wxExFileName& filename,
  int line_number,
  const wxString& match,
  long flags)
{
  bool retValue;

  if (flags & STC_OPEN_FROM_OTHER)
  {
    retValue = m_Frame->OpenFile(filename, line_number, match, flags);
  }
  else
  {
    retValue = wxExSTC::Open(filename, line_number, match, flags);

    if (retValue)
    {
      m_Frame->SetRecentFile(filename.GetFullPath());
    }
  }

  return retValue;
}

void wxExSTCWithFrame::PropertiesMessage() const
{
  wxExSTC::PropertiesMessage();

  m_Frame->SetTitle(
    GetName() +
      (GetReadOnly() ? " [" + _("Readonly") + "]": wxString(wxEmptyString)),
    wxEmptyString);
}
<|endoftext|>


<commit_before>/******************************************************************************\
* File:          test.cpp
* Purpose:       Implementation for wxExtension cpp unit testing
* Author:        Anton van Wezenbeek
* RCS-ID:        $Id$
* Created:       za 17 jan 2009 11:51:20 CET
*
* Copyright (c) 2009 Anton van Wezenbeek
* All rights are reserved. Reproduction in whole or part is prohibited
* without the written consent of the copyright owner.
\******************************************************************************/

#include <TestCaller.h>
#include <wx/extension/extension.h>
#include "test.h"

#define TEST_FILE "./test.h"
#define TEST_BIN "./test.bin"

class wxExFileTest: public wxExFile
{
public :
  wxExFileTest(const wxString& filename) : wxExFile(filename) {;};
private:
  virtual bool GetContentsChanged() const {return false;};
  virtual void ResetContentsChanged() {;};
  virtual void DoFileLoad(bool) {;};
  virtual void DoFileSave(bool) {;};
};

void wxExTestFixture::testFile()
{
  wxExFileTest file(TEST_FILE);

  CPPUNIT_ASSERT(file.GetStat().IsOk());
  CPPUNIT_ASSERT(file.GetStat().GetFullPath() == file.GetFileName().GetFullPath());
  // The fullpath should be normalized, test it.
  CPPUNIT_ASSERT(file.GetFileName().GetFullPath() != TEST_FILE);
  CPPUNIT_ASSERT(!file.GetStat().IsReadOnly());
  file.CheckSync();
  CPPUNIT_ASSERT(!file.GetStat().IsReadOnly());
  CPPUNIT_ASSERT(file.FileLoad(TEST_BIN));
  CPPUNIT_ASSERT(!file.IsOpened());
  CPPUNIT_ASSERT(file.Open(wxExFileName(TEST_BIN).GetFullPath()));
  wxCharBuffer buffer = file.Read();
  CPPUNIT_ASSERT(buffer.length() == 40);
}

void wxExTestFixture::testFileName()
{
  wxExFileName fileName(TEST_FILE);

  CPPUNIT_ASSERT(fileName.GetLexer().GetScintillaLexer().empty());
  CPPUNIT_ASSERT(fileName.GetStat().IsOk());
  fileName.Assign("xxx");
  CPPUNIT_ASSERT(fileName.GetStat().IsOk());
}

void wxExTestFixture::testFileStatistics()
{
  wxExFileStatistics fileStatistics;

  CPPUNIT_ASSERT(fileStatistics.Get().empty());
  CPPUNIT_ASSERT(fileStatistics.Get("xx") == 0);
}

void wxExTestFixture::testRCS()
{
  wxExRCS rcs;
  CPPUNIT_ASSERT(rcs.GetDescription().empty());
  CPPUNIT_ASSERT(rcs.GetUser().empty());
}

void wxExTestFixture::testStat()
{
  wxExStat stat(TEST_FILE);
  CPPUNIT_ASSERT(stat.IsOk());
  CPPUNIT_ASSERT(!stat.IsReadOnly());
  CPPUNIT_ASSERT(stat.Sync("./test-base.link"));
}

void wxExTestFixture::testStatistics()
{
  wxExStatistics<long> statistics;
  statistics.Inc("test");
  CPPUNIT_ASSERT(statistics.Get("test") == 1);
  statistics.Inc("test");
  CPPUNIT_ASSERT(statistics.Get("test") == 2);
  statistics.Set("test", 13);
  CPPUNIT_ASSERT(statistics.Get("test") == 13);
  statistics.Dec("test");
  CPPUNIT_ASSERT(statistics.Get("test") == 12);
  statistics.Inc("test2");
  CPPUNIT_ASSERT(statistics.Get("test2") == 1);
  wxExStatistics<long> copy(statistics);
  CPPUNIT_ASSERT(copy.Get("test2") == 1);
  statistics.Clear();
  CPPUNIT_ASSERT(statistics.GetItems().empty());
}

void wxExTestFixture::testTextFile()
{
  wxExTextFile textFile(wxExFileName(TEST_FILE), ID_TOOL_REPORT_COUNT);
  CPPUNIT_ASSERT(textFile.RunTool());
  CPPUNIT_ASSERT(!textFile.GetStatistics().GetElements().GetItems().empty());
  CPPUNIT_ASSERT(!textFile.IsOpened()); // file should be closed after running tool

  CPPUNIT_ASSERT(textFile.RunTool()); // do the same test
  CPPUNIT_ASSERT(!textFile.GetStatistics().GetElements().GetItems().empty());
  CPPUNIT_ASSERT(!textFile.IsOpened()); // file should be closed after running tool

  wxExTextFile textFile2(wxExFileName(TEST_FILE), ID_TOOL_REPORT_KEYWORD);
  CPPUNIT_ASSERT(textFile2.RunTool());
//  CPPUNIT_ASSERT(!m_TextFile->GetStatistics().GetKeywords().GetItems().empty());
}

void wxExTestFixture::testTiming()
{
  wxExFileTest file(TEST_FILE);

  CPPUNIT_ASSERT(file.IsOpened());

  wxStopWatch sw;

  const int max = 10000;

  for (int i = 0; i < max; i++)
  {
    CPPUNIT_ASSERT(file.Read().length() > 0);
  }

  const long exfile_read = sw.Time();

  sw.Start();

  wxFile wxfile(TEST_FILE);

  for (int j = 0; j < max; j++)
  {
    char* charbuffer = new char[wxfile.Length()];
    wxfile.Read(charbuffer, wxfile.Length());
    wxString* buffer = new wxString(charbuffer, wxfile.Length());
    CPPUNIT_ASSERT(buffer->length() > 0);
    delete charbuffer;
    delete buffer;
  }

  const long file_read = sw.Time();

  printf(
    "wxExFile::Read:%ld wxFile::Read:%ld\n",
    exfile_read,
    file_read);
}

void wxExTestFixture::testTimingAttrib()
{
  const int max = 1000;

  wxStopWatch sw;

  const wxExFileName exfile(TEST_FILE);

  int checked = 0;

  for (int i = 0; i < max; i++)
  {
    checked += exfile.GetStat().IsReadOnly();
  }

  const long exfile_time = sw.Time();

  sw.Start();

  const wxFileName file(TEST_FILE);

  for (int j = 0; j < max; j++)
  {
    checked += file.IsFileWritable();
  }

  const long file_time = sw.Time();

  printf(
    "wxExFileName::IsReadOnly:%ld wxFileName::IsFileWritable:%ld\n",
    exfile_time,
    file_time);
}

void wxExTestFixture::testTool()
{
  CPPUNIT_ASSERT(wxExTool(ID_TOOL_REPORT_COUNT).IsCount());
  CPPUNIT_ASSERT(wxExTool(ID_TOOL_REPORT_FIND).IsFindType());
  CPPUNIT_ASSERT(wxExTool(ID_TOOL_REPORT_REPLACE).IsFindType());
  CPPUNIT_ASSERT(wxExTool(ID_TOOL_REPORT_COUNT).IsStatisticsType());
  CPPUNIT_ASSERT(wxExTool(ID_TOOL_REPORT_COUNT).IsReportType());
}

wxExTestSuite::wxExTestSuite()
  : CppUnit::TestSuite("wxExtension test suite")
{
  addTest(new CppUnit::TestCaller<wxExTestFixture>(
    "testFile",
    &wxExTestFixture::testFile));

  addTest(new CppUnit::TestCaller<wxExTestFixture>(
    "testFileName",
    &wxExTestFixture::testFileName));

  addTest(new CppUnit::TestCaller<wxExTestFixture>(
    "testFileStatistics",
    &wxExTestFixture::testFileStatistics));

  addTest(new CppUnit::TestCaller<wxExTestFixture>(
    "testRCS",
    &wxExTestFixture::testRCS));

  addTest(new CppUnit::TestCaller<wxExTestFixture>(
    "testStat",
    &wxExTestFixture::testStat));

  addTest(new CppUnit::TestCaller<wxExTestFixture>(
    "testStatistics",
    &wxExTestFixture::testStatistics));

  addTest(new CppUnit::TestCaller<wxExTestFixture>(
    "testTiming",
    &wxExTestFixture::testTiming));

  addTest(new CppUnit::TestCaller<wxExTestFixture>(
    "testTimingAttrib",
    &wxExTestFixture::testTimingAttrib));

  addTest(new CppUnit::TestCaller<wxExTestFixture>(
    "testTool",
    &wxExTestFixture::testTool));
}
<commit_msg>so class wxExFileTest is no longer necessary<commit_after>/******************************************************************************\
* File:          test.cpp
* Purpose:       Implementation for wxExtension cpp unit testing
* Author:        Anton van Wezenbeek
* RCS-ID:        $Id$
* Created:       za 17 jan 2009 11:51:20 CET
*
* Copyright (c) 2009 Anton van Wezenbeek
* All rights are reserved. Reproduction in whole or part is prohibited
* without the written consent of the copyright owner.
\******************************************************************************/

#include <TestCaller.h>
#include <wx/extension/extension.h>
#include "test.h"

#define TEST_FILE "./test.h"
#define TEST_BIN "./test.bin"

void wxExTestFixture::testFile()
{
  wxExFile file(TEST_FILE);

  CPPUNIT_ASSERT(file.GetStat().IsOk());
  CPPUNIT_ASSERT(file.GetStat().GetFullPath() == file.GetFileName().GetFullPath());
  // The fullpath should be normalized, test it.
  CPPUNIT_ASSERT(file.GetFileName().GetFullPath() != TEST_FILE);
  CPPUNIT_ASSERT(!file.GetStat().IsReadOnly());
  file.CheckSync();
  CPPUNIT_ASSERT(!file.GetStat().IsReadOnly());
  CPPUNIT_ASSERT(file.FileLoad(TEST_BIN));
  CPPUNIT_ASSERT(!file.IsOpened());
  CPPUNIT_ASSERT(file.Open(wxExFileName(TEST_BIN).GetFullPath()));
  wxCharBuffer buffer = file.Read();
  CPPUNIT_ASSERT(buffer.length() == 40);
}

void wxExTestFixture::testFileName()
{
  wxExFileName fileName(TEST_FILE);

  CPPUNIT_ASSERT(fileName.GetLexer().GetScintillaLexer().empty());
  CPPUNIT_ASSERT(fileName.GetStat().IsOk());
  fileName.Assign("xxx");
  CPPUNIT_ASSERT(fileName.GetStat().IsOk());
}

void wxExTestFixture::testFileStatistics()
{
  wxExFileStatistics fileStatistics;

  CPPUNIT_ASSERT(fileStatistics.Get().empty());
  CPPUNIT_ASSERT(fileStatistics.Get("xx") == 0);
}

void wxExTestFixture::testRCS()
{
  wxExRCS rcs;
  CPPUNIT_ASSERT(rcs.GetDescription().empty());
  CPPUNIT_ASSERT(rcs.GetUser().empty());
}

void wxExTestFixture::testStat()
{
  wxExStat stat(TEST_FILE);
  CPPUNIT_ASSERT(stat.IsOk());
  CPPUNIT_ASSERT(!stat.IsReadOnly());
  CPPUNIT_ASSERT(stat.Sync("./test-base.link"));
}

void wxExTestFixture::testStatistics()
{
  wxExStatistics<long> statistics;
  statistics.Inc("test");
  CPPUNIT_ASSERT(statistics.Get("test") == 1);
  statistics.Inc("test");
  CPPUNIT_ASSERT(statistics.Get("test") == 2);
  statistics.Set("test", 13);
  CPPUNIT_ASSERT(statistics.Get("test") == 13);
  statistics.Dec("test");
  CPPUNIT_ASSERT(statistics.Get("test") == 12);
  statistics.Inc("test2");
  CPPUNIT_ASSERT(statistics.Get("test2") == 1);
  wxExStatistics<long> copy(statistics);
  CPPUNIT_ASSERT(copy.Get("test2") == 1);
  statistics.Clear();
  CPPUNIT_ASSERT(statistics.GetItems().empty());
}

void wxExTestFixture::testTextFile()
{
  wxExTextFile textFile(wxExFileName(TEST_FILE), ID_TOOL_REPORT_COUNT);
  CPPUNIT_ASSERT(textFile.RunTool());
  CPPUNIT_ASSERT(!textFile.GetStatistics().GetElements().GetItems().empty());
  CPPUNIT_ASSERT(!textFile.IsOpened()); // file should be closed after running tool

  CPPUNIT_ASSERT(textFile.RunTool()); // do the same test
  CPPUNIT_ASSERT(!textFile.GetStatistics().GetElements().GetItems().empty());
  CPPUNIT_ASSERT(!textFile.IsOpened()); // file should be closed after running tool

  wxExTextFile textFile2(wxExFileName(TEST_FILE), ID_TOOL_REPORT_KEYWORD);
  CPPUNIT_ASSERT(textFile2.RunTool());
//  CPPUNIT_ASSERT(!m_TextFile->GetStatistics().GetKeywords().GetItems().empty());
}

void wxExTestFixture::testTiming()
{
  wxExFile file(TEST_FILE);

  CPPUNIT_ASSERT(file.IsOpened());

  wxStopWatch sw;

  const int max = 10000;

  for (int i = 0; i < max; i++)
  {
    CPPUNIT_ASSERT(file.Read().length() > 0);
  }

  const long exfile_read = sw.Time();

  sw.Start();

  wxFile wxfile(TEST_FILE);

  for (int j = 0; j < max; j++)
  {
    char* charbuffer = new char[wxfile.Length()];
    wxfile.Read(charbuffer, wxfile.Length());
    wxString* buffer = new wxString(charbuffer, wxfile.Length());
    CPPUNIT_ASSERT(buffer->length() > 0);
    delete charbuffer;
    delete buffer;
  }

  const long file_read = sw.Time();

  printf(
    "wxExFile::Read:%ld wxFile::Read:%ld\n",
    exfile_read,
    file_read);
}

void wxExTestFixture::testTimingAttrib()
{
  const int max = 1000;

  wxStopWatch sw;

  const wxExFileName exfile(TEST_FILE);

  int checked = 0;

  for (int i = 0; i < max; i++)
  {
    checked += exfile.GetStat().IsReadOnly();
  }

  const long exfile_time = sw.Time();

  sw.Start();

  const wxFileName file(TEST_FILE);

  for (int j = 0; j < max; j++)
  {
    checked += file.IsFileWritable();
  }

  const long file_time = sw.Time();

  printf(
    "wxExFileName::IsReadOnly:%ld wxFileName::IsFileWritable:%ld\n",
    exfile_time,
    file_time);
}

void wxExTestFixture::testTool()
{
  CPPUNIT_ASSERT(wxExTool(ID_TOOL_REPORT_COUNT).IsCount());
  CPPUNIT_ASSERT(wxExTool(ID_TOOL_REPORT_FIND).IsFindType());
  CPPUNIT_ASSERT(wxExTool(ID_TOOL_REPORT_REPLACE).IsFindType());
  CPPUNIT_ASSERT(wxExTool(ID_TOOL_REPORT_COUNT).IsStatisticsType());
  CPPUNIT_ASSERT(wxExTool(ID_TOOL_REPORT_COUNT).IsReportType());
}

wxExTestSuite::wxExTestSuite()
  : CppUnit::TestSuite("wxExtension test suite")
{
  addTest(new CppUnit::TestCaller<wxExTestFixture>(
    "testFile",
    &wxExTestFixture::testFile));

  addTest(new CppUnit::TestCaller<wxExTestFixture>(
    "testFileName",
    &wxExTestFixture::testFileName));

  addTest(new CppUnit::TestCaller<wxExTestFixture>(
    "testFileStatistics",
    &wxExTestFixture::testFileStatistics));

  addTest(new CppUnit::TestCaller<wxExTestFixture>(
    "testRCS",
    &wxExTestFixture::testRCS));

  addTest(new CppUnit::TestCaller<wxExTestFixture>(
    "testStat",
    &wxExTestFixture::testStat));

  addTest(new CppUnit::TestCaller<wxExTestFixture>(
    "testStatistics",
    &wxExTestFixture::testStatistics));

  addTest(new CppUnit::TestCaller<wxExTestFixture>(
    "testTiming",
    &wxExTestFixture::testTiming));

  addTest(new CppUnit::TestCaller<wxExTestFixture>(
    "testTimingAttrib",
    &wxExTestFixture::testTimingAttrib));

  addTest(new CppUnit::TestCaller<wxExTestFixture>(
    "testTool",
    &wxExTestFixture::testTool));
}
<|endoftext|>