<commit_before>/*
 *            Copyright 2009-2017 The VOTCA Development Team
 *                       (http://www.votca.org)
 *
 *      Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

#include <votca/xtp/gwbse.h>

#include <boost/format.hpp>
#include <boost/filesystem.hpp>
#include <boost/numeric/ublas/operation.hpp>
#include <votca/xtp/aomatrix.h>
#include <votca/xtp/threecenters.h>
// #include <votca/xtp/logger.h>
#include <votca/xtp/qmpackagefactory.h>
#include <boost/math/constants/constants.hpp>
#include <boost/numeric/ublas/symmetric.hpp>
#include <votca/xtp/aoshell.h>

using boost::format;
using namespace boost::filesystem;

namespace votca {
    namespace xtp {
        namespace ub = boost::numeric::ublas;

        void GWBSE::PPM_construct_parameters(const ub::matrix<double>& _overlap_cholesky_inverse) {

            // multiply with L-1^t from the right

            ub::matrix<double> _temp = ub::prod(_epsilon[0], ub::trans(_overlap_cholesky_inverse));
            // multiply with L-1 from the left

            _temp = ub::prod(_overlap_cholesky_inverse, _temp);

            // get eigenvalues and eigenvectors of this matrix
            ub::vector<double> _eigenvalues;
            ub::matrix<double> _eigenvectors;

            linalg_eigenvalues(_temp, _eigenvalues, _eigenvectors);
            _eigenvectors=ub::trans(_eigenvectors);
            // multiply eigenvectors with overlap_cholesky_inverse and store as eigenvalues of epsilon
            _ppm_phi = ub::prod(_eigenvectors, ub::trans(_overlap_cholesky_inverse));

            // store PPM weights from eigenvalues
            _ppm_weight.resize(_eigenvalues.size());
            for (unsigned _i = 0; _i < _eigenvalues.size(); _i++) {
                _ppm_weight(_i) = 1.0 - 1.0 / _eigenvalues(_i);
            }

            // determine PPM frequencies
            _ppm_freq.resize(_eigenvalues.size());
            // a) phi^t * epsilon(1) * phi

            _temp = ub::prod(_ppm_phi, _epsilon[1]);

            _eigenvectors = ub::prod(_temp, ub::trans(_ppm_phi));
            // b) invert

            linalg_invert(_eigenvectors, _temp);
            // c) PPM parameters -> diagonal elements

            #pragma omp parallel for
            for (unsigned _i = 0; _i < _eigenvalues.size(); _i++) {

                if (_screening_freq(1, 0) == 0.0) {
                    if (_ppm_weight(_i) < 1.e-5) {
                        _ppm_weight(_i) = 0.0;
                        _ppm_freq(_i) = 0.5;//Hartree
                        continue;
                    } else {
                        double _nom = _temp(_i, _i) - 1.0;
                        double _frac = -1.0 * _nom / (_nom + _ppm_weight(_i)) * _screening_freq(1, 1) * _screening_freq(1, 1);
                        _ppm_freq(_i) = sqrt(std::abs(_frac));
                    }

                } else {
                    // only purely imaginary frequency assumed
                    cerr << " mixed frequency! real part: " << _screening_freq(1, 0) << " imaginary part: " << _screening_freq(1, 1) << flush;
                    exit(1);
                }

            }

            // epsilon can be deleted
            _epsilon[0].resize(0, 0);
            _epsilon[1].resize(0, 0);

            return;
        }

        //imaginary
        ub::matrix<double> GWBSE::RPA_imaginary(const TCMatrix& _Mmn_RPA,const double screening_freq) {
            const int _size = _Mmn_RPA.get_beta(); // size of gwbasis
            const int index_n = _Mmn_RPA.get_nmin();
            const int index_m = _Mmn_RPA.get_mmin();
            const double screenf2=screening_freq * screening_freq;

            std::vector<ub::matrix<double> > result_thread;
            unsigned nthreads = 1;
            #ifdef _OPENMP
               nthreads = omp_get_max_threads();
            #endif
            const ub::vector<double>& qp_energies=   _qp_energies;

            for(unsigned i=0;i<nthreads;++i){
                result_thread.push_back(ub::zero_matrix<double>(_size));
            }

            #pragma omp parallel for
            for(unsigned thread=0;thread<nthreads;++thread){
            for (int _m_level = thread; _m_level < _Mmn_RPA.get_mtot(); _m_level+=nthreads) {
                const double _qp_energy_m=qp_energies(_m_level + index_m);
#if (GWBSE_DOUBLE)
                const ub::matrix<double>& Mmn_RPA = _Mmn_RPA[ _m_level ];
#else
                const ub::matrix<double> Mmn_RPA = _Mmn_RPA[ _m_level ];
#endif
                // a temporary matrix, that will get filled in empty levels loop
                ub::matrix<double> _temp = ub::matrix<double>(_Mmn_RPA.get_ntot(), _size);

                // loop over empty levels
                for (int _n_level = 0; _n_level < _Mmn_RPA.get_ntot(); _n_level++) {

                    const double _deltaE = qp_energies(_n_level + index_n) -_qp_energy_m ; // get indices and units right!!!

                    // this only works, if we have either purely real or purely imaginary frequencies

                    // purely imaginary
                    const double _energy_factor = 4.0 * _deltaE / (_deltaE * _deltaE + screenf2);//hartree
                    for (int _i_gw = 0; _i_gw < _size; _i_gw++) {
                        _temp(_n_level, _i_gw) = _energy_factor * Mmn_RPA(_i_gw, _n_level);
                    } // matrix size

                } // empty levels

                // now multiply and add to epsilon
                result_thread[thread] += ub::prod(Mmn_RPA, _temp);
            } // occupied levels
            }
            ub::matrix<double> result=ub::zero_matrix<double>(_size);
               for(unsigned thread=0;thread<nthreads;++thread){
                   result+=result_thread[thread];
               }
            return result;
        }
        //real

        ub::matrix<double> GWBSE::RPA_real(const TCMatrix& _Mmn_RPA, const double screening_freq) {
            const int _size = _Mmn_RPA.get_beta(); // size of gwbasis
            const int index_n = _Mmn_RPA.get_nmin();
            const int index_m = _Mmn_RPA.get_mmin();
            const ub::vector<double>& qp_energies=   _qp_energies;

            std::vector<ub::matrix<double> > result_thread;
            unsigned nthreads = 1;
            #ifdef _OPENMP
               nthreads = omp_get_max_threads();
            #endif

            for(unsigned i=0;i<nthreads;++i){
                result_thread.push_back(ub::zero_matrix<double>(_size));
            }

            #pragma omp parallel for
            for(unsigned thread=0;thread<nthreads;++thread){
            for (int _m_level = thread; _m_level < _Mmn_RPA.get_mtot(); _m_level+=nthreads) {
                const double _qp_energy_m=qp_energies(_m_level + index_m);

#if (GWBSE_DOUBLE)
                const ub::matrix<double>& Mmn_RPA = _Mmn_RPA[ _m_level ];
#else
                const ub::matrix<double> Mmn_RPA = _Mmn_RPA[ _m_level ];
#endif

                // a temporary matrix, that will get filled in empty levels loop
                ub::matrix<double> _temp = ub::matrix<double>(_Mmn_RPA.get_ntot(), _size);

                // loop over empty levels
                for (int _n_level = 0; _n_level < _Mmn_RPA.get_ntot(); _n_level++) {
                    int index_n = _Mmn_RPA.get_nmin();

                    const double _deltaE = qp_energies(_n_level + index_n) - _qp_energy_m; // get indices and units right!!!

                    // this only works, if we have either purely real or purely imaginary frequencies

                    // purely real
                    const double _energy_factor =2.0*  (1.0 / (_deltaE - screening_freq) + 1.0 / (_deltaE + screening_freq));//hartree

                    for (int _i_gw = 0; _i_gw < _size; _i_gw++) {
                        _temp(_n_level, _i_gw) = _energy_factor * Mmn_RPA(_i_gw, _n_level);
                    } // matrix size

                } // empty levels

                // now multiply and add to epsilon

                result_thread[thread] += ub::prod(Mmn_RPA, _temp);

            } // occupied levels
            }
               ub::matrix<double> result=ub::zero_matrix<double>(_size);
               for(unsigned thread=0;thread<nthreads;++thread){
                   result+=result_thread[thread];
               }

            return result;
        }

    void GWBSE::RPA_calculate_epsilon(const TCMatrix& _Mmn_RPA){

        // loop over frequencies
        for ( unsigned _i_freq = 0 ; _i_freq < _screening_freq.size1() ; _i_freq++ ){

             if ( _screening_freq( _i_freq, 0) == 0.0 ) {
                 _epsilon[ _i_freq ]+=RPA_imaginary(_Mmn_RPA, _screening_freq( _i_freq, 1));
             }

             else if ( _screening_freq( _i_freq, 1) == 0.0  ) {
                  // purely real
                 _epsilon[ _i_freq ]+= RPA_real(_Mmn_RPA, _screening_freq( _i_freq, 0));
                    }
             else {
                    // mixed -> FAIL
                    cerr << " mixed frequency! real part: " << _screening_freq( _i_freq, 0 ) << " imaginary part: "  << _screening_freq( _i_freq, 1 ) << flush;
                    exit(1);
                    }

        } // loop over frequencies

        return;
    }

    void GWBSE::RPA_prepare_threecenters(TCMatrix& _Mmn_RPA,const TCMatrix& _Mmn_full){

        ub::range full=ub::range(0, _Mmn_full.get_beta());
        ub::range RPA_cut=ub::range(_Mmn_RPA.get_nmin() - _Mmn_full.get_nmin(), _Mmn_RPA.get_nmax() - _Mmn_full.get_nmin() + 1);
            // loop over m-levels in _Mmn_RPA
            #pragma omp parallel for
            for (int _m_level = 0; _m_level < _Mmn_RPA.size(); _m_level++) {

                // copy to _Mmn_RPA
                _Mmn_RPA[ _m_level ] = ub::project(_Mmn_full[ _m_level ], full, RPA_cut);

            }// loop m-levels
     return;
    }

}};
<commit_msg>bug fixed, now correct<commit_after>/*
 *            Copyright 2009-2017 The VOTCA Development Team
 *                       (http://www.votca.org)
 *
 *      Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

#include <votca/xtp/gwbse.h>

#include <boost/format.hpp>
#include <boost/filesystem.hpp>
#include <boost/numeric/ublas/operation.hpp>
#include <votca/xtp/aomatrix.h>
#include <votca/xtp/threecenters.h>
// #include <votca/xtp/logger.h>
#include <votca/xtp/qmpackagefactory.h>
#include <boost/math/constants/constants.hpp>
#include <boost/numeric/ublas/symmetric.hpp>
#include <votca/xtp/aoshell.h>

using boost::format;
using namespace boost::filesystem;

namespace votca {
    namespace xtp {
        namespace ub = boost::numeric::ublas;

        void GWBSE::PPM_construct_parameters(const ub::matrix<double>& _overlap_cholesky_inverse) {

            // multiply with L-1^t from the right

            ub::matrix<double> _temp = ub::prod(_epsilon[0], ub::trans(_overlap_cholesky_inverse));
            // multiply with L-1 from the left

            _temp = ub::prod(_overlap_cholesky_inverse, _temp);

            // get eigenvalues and eigenvectors of this matrix
            ub::vector<double> _eigenvalues;
            ub::matrix<double> _eigenvectors;

            linalg_eigenvalues(_temp, _eigenvalues, _eigenvectors);
            _eigenvectors=ub::trans(_eigenvectors);
            // multiply eigenvectors with overlap_cholesky_inverse and store as eigenvalues of epsilon
            _ppm_phi = ub::prod(_eigenvectors, _overlap_cholesky_inverse);

            // store PPM weights from eigenvalues
            _ppm_weight.resize(_eigenvalues.size());
            for (unsigned _i = 0; _i < _eigenvalues.size(); _i++) {
                _ppm_weight(_i) = 1.0 - 1.0 / _eigenvalues(_i);
            }

            // determine PPM frequencies
            _ppm_freq.resize(_eigenvalues.size());
            // a) phi^t * epsilon(1) * phi

            _temp = ub::prod(_ppm_phi, _epsilon[1]);

            _eigenvectors = ub::prod(_temp, ub::trans(_ppm_phi));
            // b) invert

            linalg_invert(_eigenvectors, _temp);
            // c) PPM parameters -> diagonal elements

            #pragma omp parallel for
            for (unsigned _i = 0; _i < _eigenvalues.size(); _i++) {

                if (_screening_freq(1, 0) == 0.0) {
                    if (_ppm_weight(_i) < 1.e-5) {
                        _ppm_weight(_i) = 0.0;
                        _ppm_freq(_i) = 0.5;//Hartree
                        continue;
                    } else {
                        double _nom = _temp(_i, _i) - 1.0;
                        double _frac = -1.0 * _nom / (_nom + _ppm_weight(_i)) * _screening_freq(1, 1) * _screening_freq(1, 1);
                        _ppm_freq(_i) = sqrt(std::abs(_frac));
                    }

                } else {
                    // only purely imaginary frequency assumed
                    cerr << " mixed frequency! real part: " << _screening_freq(1, 0) << " imaginary part: " << _screening_freq(1, 1) << flush;
                    exit(1);
                }

            }

            // epsilon can be deleted
            _epsilon[0].resize(0, 0);
            _epsilon[1].resize(0, 0);

            return;
        }

        //imaginary
        ub::matrix<double> GWBSE::RPA_imaginary(const TCMatrix& _Mmn_RPA,const double screening_freq) {
            const int _size = _Mmn_RPA.get_beta(); // size of gwbasis
            const int index_n = _Mmn_RPA.get_nmin();
            const int index_m = _Mmn_RPA.get_mmin();
            const double screenf2=screening_freq * screening_freq;

            std::vector<ub::matrix<double> > result_thread;
            unsigned nthreads = 1;
            #ifdef _OPENMP
               nthreads = omp_get_max_threads();
            #endif
            const ub::vector<double>& qp_energies=   _qp_energies;

            for(unsigned i=0;i<nthreads;++i){
                result_thread.push_back(ub::zero_matrix<double>(_size));
            }

            #pragma omp parallel for
            for(unsigned thread=0;thread<nthreads;++thread){
            for (int _m_level = thread; _m_level < _Mmn_RPA.get_mtot(); _m_level+=nthreads) {
                const double _qp_energy_m=qp_energies(_m_level + index_m);
#if (GWBSE_DOUBLE)
                const ub::matrix<double>& Mmn_RPA = _Mmn_RPA[ _m_level ];
#else
                const ub::matrix<double> Mmn_RPA = _Mmn_RPA[ _m_level ];
#endif
                // a temporary matrix, that will get filled in empty levels loop
                ub::matrix<double> _temp = ub::matrix<double>(_Mmn_RPA.get_ntot(), _size);

                // loop over empty levels
                for (int _n_level = 0; _n_level < _Mmn_RPA.get_ntot(); _n_level++) {

                    const double _deltaE = qp_energies(_n_level + index_n) -_qp_energy_m ; // get indices and units right!!!

                    // this only works, if we have either purely real or purely imaginary frequencies

                    // purely imaginary
                    const double _energy_factor = 4.0 * _deltaE / (_deltaE * _deltaE + screenf2);//hartree
                    for (int _i_gw = 0; _i_gw < _size; _i_gw++) {
                        _temp(_n_level, _i_gw) = _energy_factor * Mmn_RPA(_i_gw, _n_level);
                    } // matrix size

                } // empty levels

                // now multiply and add to epsilon
                result_thread[thread] += ub::prod(Mmn_RPA, _temp);
            } // occupied levels
            }
            ub::matrix<double> result=ub::zero_matrix<double>(_size);
               for(unsigned thread=0;thread<nthreads;++thread){
                   result+=result_thread[thread];
               }
            return result;
        }
        //real

        ub::matrix<double> GWBSE::RPA_real(const TCMatrix& _Mmn_RPA, const double screening_freq) {
            const int _size = _Mmn_RPA.get_beta(); // size of gwbasis
            const int index_n = _Mmn_RPA.get_nmin();
            const int index_m = _Mmn_RPA.get_mmin();
            const ub::vector<double>& qp_energies=   _qp_energies;

            std::vector<ub::matrix<double> > result_thread;
            unsigned nthreads = 1;
            #ifdef _OPENMP
               nthreads = omp_get_max_threads();
            #endif

            for(unsigned i=0;i<nthreads;++i){
                result_thread.push_back(ub::zero_matrix<double>(_size));
            }

            #pragma omp parallel for
            for(unsigned thread=0;thread<nthreads;++thread){
            for (int _m_level = thread; _m_level < _Mmn_RPA.get_mtot(); _m_level+=nthreads) {
                const double _qp_energy_m=qp_energies(_m_level + index_m);

#if (GWBSE_DOUBLE)
                const ub::matrix<double>& Mmn_RPA = _Mmn_RPA[ _m_level ];
#else
                const ub::matrix<double> Mmn_RPA = _Mmn_RPA[ _m_level ];
#endif

                // a temporary matrix, that will get filled in empty levels loop
                ub::matrix<double> _temp = ub::matrix<double>(_Mmn_RPA.get_ntot(), _size);

                // loop over empty levels
                for (int _n_level = 0; _n_level < _Mmn_RPA.get_ntot(); _n_level++) {
                    int index_n = _Mmn_RPA.get_nmin();

                    const double _deltaE = qp_energies(_n_level + index_n) - _qp_energy_m; // get indices and units right!!!

                    // this only works, if we have either purely real or purely imaginary frequencies

                    // purely real
                    const double _energy_factor =2.0*  (1.0 / (_deltaE - screening_freq) + 1.0 / (_deltaE + screening_freq));//hartree

                    for (int _i_gw = 0; _i_gw < _size; _i_gw++) {
                        _temp(_n_level, _i_gw) = _energy_factor * Mmn_RPA(_i_gw, _n_level);
                    } // matrix size

                } // empty levels

                // now multiply and add to epsilon

                result_thread[thread] += ub::prod(Mmn_RPA, _temp);

            } // occupied levels
            }
               ub::matrix<double> result=ub::zero_matrix<double>(_size);
               for(unsigned thread=0;thread<nthreads;++thread){
                   result+=result_thread[thread];
               }

            return result;
        }

    void GWBSE::RPA_calculate_epsilon(const TCMatrix& _Mmn_RPA){

        // loop over frequencies
        for ( unsigned _i_freq = 0 ; _i_freq < _screening_freq.size1() ; _i_freq++ ){

             if ( _screening_freq( _i_freq, 0) == 0.0 ) {
                 _epsilon[ _i_freq ]+=RPA_imaginary(_Mmn_RPA, _screening_freq( _i_freq, 1));
             }

             else if ( _screening_freq( _i_freq, 1) == 0.0  ) {
                  // purely real
                 _epsilon[ _i_freq ]+= RPA_real(_Mmn_RPA, _screening_freq( _i_freq, 0));
                    }
             else {
                    // mixed -> FAIL
                    cerr << " mixed frequency! real part: " << _screening_freq( _i_freq, 0 ) << " imaginary part: "  << _screening_freq( _i_freq, 1 ) << flush;
                    exit(1);
                    }

        } // loop over frequencies

        return;
    }

    void GWBSE::RPA_prepare_threecenters(TCMatrix& _Mmn_RPA,const TCMatrix& _Mmn_full){

        ub::range full=ub::range(0, _Mmn_full.get_beta());
        ub::range RPA_cut=ub::range(_Mmn_RPA.get_nmin() - _Mmn_full.get_nmin(), _Mmn_RPA.get_nmax() - _Mmn_full.get_nmin() + 1);
            // loop over m-levels in _Mmn_RPA
            #pragma omp parallel for
            for (int _m_level = 0; _m_level < _Mmn_RPA.size(); _m_level++) {

                // copy to _Mmn_RPA
                _Mmn_RPA[ _m_level ] = ub::project(_Mmn_full[ _m_level ], full, RPA_cut);

            }// loop m-levels
     return;
    }

}};
<|endoftext|>


<commit_before>#include "kwm.h"

CFMachPortRef EventTap;

kwm_code KWMCode;
std::string KwmFilePath;
std::string HotkeySOFullFilePath;
bool KwmUseBuiltinHotkeys;

uint32_t MaxDisplayCount = 5;
uint32_t ActiveDisplaysCount;
CGDirectDisplayID ActiveDisplays[5];

screen_info *Screen;
int DefaultPaddingTop = 40, DefaultPaddingBottom = 20;
int DefaultPaddingLeft = 20, DefaultPaddingRight = 20;
int DefaultGapVertical = 10, DefaultGapHorizontal = 10;

std::map<unsigned int, screen_info> DisplayMap;
std::vector<window_info> WindowLst;
std::vector<int> FloatingSpaceLst;
std::vector<std::string> FloatingAppLst;
std::vector<int> FloatingWindowLst;

ProcessSerialNumber FocusedPSN;
window_info *FocusedWindow;
focus_option KwmFocusMode;
int KwmSplitMode = -1;
int MarkedWindowID = -1;

pthread_t BackgroundThread;
pthread_t DaemonThread;

pthread_mutex_t BackgroundLock;

CGEventRef CGEventCallback(CGEventTapProxy Proxy, CGEventType Type, CGEventRef Event, void *Refcon)
{
    pthread_mutex_lock(&BackgroundLock);

    switch(Type)
    {
        case kCGEventTapDisabledByTimeout:
        case kCGEventTapDisabledByUserInput:
        {
            DEBUG("Restarting Event Tap")
            CGEventTapEnable(EventTap, true);
        } break;
        case kCGEventKeyDown:
        {
            if(KwmUseBuiltinHotkeys)
            {
                CGEventFlags Flags = CGEventGetFlags(Event);
                bool CmdKey = (Flags & kCGEventFlagMaskCommand) == kCGEventFlagMaskCommand;
                bool AltKey = (Flags & kCGEventFlagMaskAlternate) == kCGEventFlagMaskAlternate;
                bool CtrlKey = (Flags & kCGEventFlagMaskControl) == kCGEventFlagMaskControl;
                bool ShiftKey = (Flags & kCGEventFlagMaskShift) == kCGEventFlagMaskShift;

                CGKeyCode Keycode = (CGKeyCode)CGEventGetIntegerValueField(Event, kCGKeyboardEventKeycode);

                std::string NewHotkeySOFileTime = KwmGetFileTime(HotkeySOFullFilePath.c_str());
                if(NewHotkeySOFileTime != KWMCode.HotkeySOFileTime)
                {
                    DEBUG("Reloading hotkeys.so")
                    UnloadKwmCode(&KWMCode);
                    KWMCode = LoadKwmCode();
                }

                if(KWMCode.IsValid)
                {
                    // Hotkeys specific to Kwms functionality
                    if(KWMCode.KWMHotkeyCommands(CmdKey, CtrlKey, AltKey, Keycode))
                    {
                        pthread_mutex_unlock(&BackgroundLock);
                        return NULL;
                    }

                    // Capture custom hotkeys specified by the user
                    if(KWMCode.CustomHotkeyCommands(CmdKey, CtrlKey, AltKey, Keycode))
                    {
                        pthread_mutex_unlock(&BackgroundLock);
                        return NULL;
                    }

                    // Let system hotkeys pass through as normal
                    if(KWMCode.SystemHotkeyCommands(CmdKey, CtrlKey, AltKey, Keycode))
                    {
                        pthread_mutex_unlock(&BackgroundLock);
                        return Event;
                    }

                    int NewKeycode;
                    KWMCode.RemapKeys(Event, &CmdKey, &CtrlKey, &AltKey, &ShiftKey, Keycode, &NewKeycode);
                    if(NewKeycode != -1)
                    {
                        CGEventSetFlags(Event, 0);

                        if(CmdKey)
                            CGEventSetFlags(Event, kCGEventFlagMaskCommand);

                        if(AltKey)
                            CGEventSetFlags(Event, kCGEventFlagMaskAlternate);

                        if(CtrlKey)
                            CGEventSetFlags(Event, kCGEventFlagMaskControl);

                        if(ShiftKey)
                            CGEventSetFlags(Event, kCGEventFlagMaskShift);

                        CGEventSetIntegerValueField(Event, kCGKeyboardEventKeycode, NewKeycode);
                    }
                }
            }

            if(KwmFocusMode == FocusModeAutofocus)
            {
                CGEventSetIntegerValueField(Event, kCGKeyboardEventAutorepeat, 0);
                CGEventPostToPSN(&FocusedPSN, Event);
                pthread_mutex_unlock(&BackgroundLock);
                return NULL;
            }
        } break;
        case kCGEventMouseMoved:
        {
            if(KwmFocusMode != FocusModeDisabled)
                FocusWindowBelowCursor();
        } break;
    }

    pthread_mutex_unlock(&BackgroundLock);
    return Event;
}

kwm_code LoadKwmCode()
{
    kwm_code Code = {};

    Code.HotkeySOFileTime = KwmGetFileTime(HotkeySOFullFilePath.c_str());
    Code.KwmHotkeySO = dlopen(HotkeySOFullFilePath.c_str(),  RTLD_LAZY);
    if(Code.KwmHotkeySO)
    {
        Code.KWMHotkeyCommands = (kwm_hotkey_commands*) dlsym(Code.KwmHotkeySO, "KWMHotkeyCommands");
        Code.SystemHotkeyCommands = (kwm_hotkey_commands*) dlsym(Code.KwmHotkeySO, "SystemHotkeyCommands");
        Code.CustomHotkeyCommands = (kwm_hotkey_commands*) dlsym(Code.KwmHotkeySO, "CustomHotkeyCommands");
        Code.RemapKeys = (kwm_key_remap*) dlsym(Code.KwmHotkeySO, "RemapKeys");
    }
    else
    {
        DEBUG("LoadKwmCode() Could not open '" << HotkeySOFullFilePath << "'")
    }

    Code.IsValid = (Code.KWMHotkeyCommands && Code.SystemHotkeyCommands && Code.CustomHotkeyCommands && Code.RemapKeys);
    return Code;
}

void UnloadKwmCode(kwm_code *Code)
{
    if(Code->KwmHotkeySO)
        dlclose(Code->KwmHotkeySO);

    Code->HotkeySOFileTime = "";
    Code->KWMHotkeyCommands = 0;
    Code->SystemHotkeyCommands = 0;
    Code->CustomHotkeyCommands = 0;
    Code->RemapKeys = 0;
    Code->IsValid = 0;
}

std::string KwmGetFileTime(const char *File)
{
    struct stat attr;
    stat(File, &attr);

    return ctime(&attr.st_mtime);
}

void KwmQuit()
{
    exit(0);
}

void * KwmWindowMonitor(void*)
{
    while(1)
    {
        pthread_mutex_lock(&BackgroundLock);
        if(KwmFocusMode != FocusModeDisabled)
            UpdateWindowTree();

        pthread_mutex_unlock(&BackgroundLock);
        usleep(200000);
    }
}

void KwmExecuteConfig()
{
    char *HomeP = std::getenv("HOME");
    if(!HomeP)
    {
        DEBUG("Failed to get environment variable 'HOME'")
        return;
    }

    std::string ENV_HOME = HomeP;
    std::string KWM_CONFIG_FILE = ".kwmrc";

    std::ifstream ConfigFD(ENV_HOME + "/" + KWM_CONFIG_FILE);
    if(ConfigFD.fail())
    {
        DEBUG("Could not open " << ENV_HOME << "/" << KWM_CONFIG_FILE
              << ", make sure the file exists." << std::endl)
        return;
    }

    std::string Line;
    while(std::getline(ConfigFD, Line))
    {
        if(!Line.empty() && Line[0] != '#')
            system(Line.c_str());
    }
}

void KwmInit()
{
    if(!CheckPrivileges())
        Fatal("Could not access OSX Accessibility!");

    if (pthread_mutex_init(&BackgroundLock, NULL) != 0)
        Fatal("Could not create mutex!");

    if(KwmStartDaemon())
        pthread_create(&DaemonThread, NULL, &KwmDaemonHandleConnectionBG, NULL);
    else
        Fatal("Kwm: Could not start daemon..");

    KwmFocusMode = FocusModeAutoraise;
    KwmFilePath = getcwd(NULL, 0);
    HotkeySOFullFilePath = KwmFilePath + "/hotkeys.so";
    KwmUseBuiltinHotkeys = true;

    KwmExecuteConfig();
    KWMCode = LoadKwmCode();

    GetActiveDisplays();
    pthread_create(&BackgroundThread, NULL, &KwmWindowMonitor, NULL);
}

bool CheckPrivileges()
{
    const void * Keys[] = { kAXTrustedCheckOptionPrompt };
    const void * Values[] = { kCFBooleanTrue };

    CFDictionaryRef Options;
    Options = CFDictionaryCreate(kCFAllocatorDefault,
            Keys, Values, sizeof(Keys) / sizeof(*Keys),
            &kCFCopyStringDictionaryKeyCallBacks,
            &kCFTypeDictionaryValueCallBacks);

    return AXIsProcessTrustedWithOptions(Options);
}

void Fatal(const std::string &Err)
{
    std::cout << Err << std::endl;
    exit(1);
}

int main(int argc, char **argv)
{
    KwmInit();

    CGEventMask EventMask;
    CFRunLoopSourceRef RunLoopSource;

    EventMask = ((1 << kCGEventKeyDown) | (1 << kCGEventMouseMoved));
    EventTap = CGEventTapCreate(kCGSessionEventTap, kCGHeadInsertEventTap, 0, EventMask, CGEventCallback, NULL);

    if(!EventTap || !CGEventTapIsEnabled(EventTap))
        Fatal("ERROR: Could not create event-tap!");

    RunLoopSource = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, EventTap, 0);
    CFRunLoopAddSource(CFRunLoopGetCurrent(), RunLoopSource, kCFRunLoopCommonModes);
    CGEventTapEnable(EventTap, true);
    NSApplicationLoad();
    CFRunLoopRun();
    return 0;
}
<commit_msg>should no longer segfault if hotkeys.so becomes unavailable while kwm is running<commit_after>#include "kwm.h"

CFMachPortRef EventTap;

kwm_code KWMCode;
std::string KwmFilePath;
std::string HotkeySOFullFilePath;
bool KwmUseBuiltinHotkeys;

uint32_t MaxDisplayCount = 5;
uint32_t ActiveDisplaysCount;
CGDirectDisplayID ActiveDisplays[5];

screen_info *Screen;
int DefaultPaddingTop = 40, DefaultPaddingBottom = 20;
int DefaultPaddingLeft = 20, DefaultPaddingRight = 20;
int DefaultGapVertical = 10, DefaultGapHorizontal = 10;

std::map<unsigned int, screen_info> DisplayMap;
std::vector<window_info> WindowLst;
std::vector<int> FloatingSpaceLst;
std::vector<std::string> FloatingAppLst;
std::vector<int> FloatingWindowLst;

ProcessSerialNumber FocusedPSN;
window_info *FocusedWindow;
focus_option KwmFocusMode;
int KwmSplitMode = -1;
int MarkedWindowID = -1;

pthread_t BackgroundThread;
pthread_t DaemonThread;

pthread_mutex_t BackgroundLock;

CGEventRef CGEventCallback(CGEventTapProxy Proxy, CGEventType Type, CGEventRef Event, void *Refcon)
{
    pthread_mutex_lock(&BackgroundLock);

    switch(Type)
    {
        case kCGEventTapDisabledByTimeout:
        case kCGEventTapDisabledByUserInput:
        {
            DEBUG("Restarting Event Tap")
            CGEventTapEnable(EventTap, true);
        } break;
        case kCGEventKeyDown:
        {
            if(KwmUseBuiltinHotkeys)
            {
                CGEventFlags Flags = CGEventGetFlags(Event);
                bool CmdKey = (Flags & kCGEventFlagMaskCommand) == kCGEventFlagMaskCommand;
                bool AltKey = (Flags & kCGEventFlagMaskAlternate) == kCGEventFlagMaskAlternate;
                bool CtrlKey = (Flags & kCGEventFlagMaskControl) == kCGEventFlagMaskControl;
                bool ShiftKey = (Flags & kCGEventFlagMaskShift) == kCGEventFlagMaskShift;

                CGKeyCode Keycode = (CGKeyCode)CGEventGetIntegerValueField(Event, kCGKeyboardEventKeycode);

                std::string NewHotkeySOFileTime = KwmGetFileTime(HotkeySOFullFilePath.c_str());
                if(NewHotkeySOFileTime != "" &&
                   NewHotkeySOFileTime != KWMCode.HotkeySOFileTime)
                {
                    DEBUG("Reloading hotkeys.so")
                    UnloadKwmCode(&KWMCode);
                    KWMCode = LoadKwmCode();
                }

                if(KWMCode.IsValid)
                {
                    // Hotkeys specific to Kwms functionality
                    if(KWMCode.KWMHotkeyCommands(CmdKey, CtrlKey, AltKey, Keycode))
                    {
                        pthread_mutex_unlock(&BackgroundLock);
                        return NULL;
                    }

                    // Capture custom hotkeys specified by the user
                    if(KWMCode.CustomHotkeyCommands(CmdKey, CtrlKey, AltKey, Keycode))
                    {
                        pthread_mutex_unlock(&BackgroundLock);
                        return NULL;
                    }

                    // Let system hotkeys pass through as normal
                    if(KWMCode.SystemHotkeyCommands(CmdKey, CtrlKey, AltKey, Keycode))
                    {
                        pthread_mutex_unlock(&BackgroundLock);
                        return Event;
                    }

                    int NewKeycode;
                    KWMCode.RemapKeys(Event, &CmdKey, &CtrlKey, &AltKey, &ShiftKey, Keycode, &NewKeycode);
                    if(NewKeycode != -1)
                    {
                        CGEventSetFlags(Event, 0);

                        if(CmdKey)
                            CGEventSetFlags(Event, kCGEventFlagMaskCommand);

                        if(AltKey)
                            CGEventSetFlags(Event, kCGEventFlagMaskAlternate);

                        if(CtrlKey)
                            CGEventSetFlags(Event, kCGEventFlagMaskControl);

                        if(ShiftKey)
                            CGEventSetFlags(Event, kCGEventFlagMaskShift);

                        CGEventSetIntegerValueField(Event, kCGKeyboardEventKeycode, NewKeycode);
                    }
                }
            }

            if(KwmFocusMode == FocusModeAutofocus)
            {
                CGEventSetIntegerValueField(Event, kCGKeyboardEventAutorepeat, 0);
                CGEventPostToPSN(&FocusedPSN, Event);
                pthread_mutex_unlock(&BackgroundLock);
                return NULL;
            }
        } break;
        case kCGEventMouseMoved:
        {
            if(KwmFocusMode != FocusModeDisabled)
                FocusWindowBelowCursor();
        } break;
    }

    pthread_mutex_unlock(&BackgroundLock);
    return Event;
}

kwm_code LoadKwmCode()
{
    kwm_code Code = {};

    Code.HotkeySOFileTime = KwmGetFileTime(HotkeySOFullFilePath.c_str());
    Code.KwmHotkeySO = dlopen(HotkeySOFullFilePath.c_str(),  RTLD_LAZY);
    if(Code.KwmHotkeySO)
    {
        Code.KWMHotkeyCommands = (kwm_hotkey_commands*) dlsym(Code.KwmHotkeySO, "KWMHotkeyCommands");
        Code.SystemHotkeyCommands = (kwm_hotkey_commands*) dlsym(Code.KwmHotkeySO, "SystemHotkeyCommands");
        Code.CustomHotkeyCommands = (kwm_hotkey_commands*) dlsym(Code.KwmHotkeySO, "CustomHotkeyCommands");
        Code.RemapKeys = (kwm_key_remap*) dlsym(Code.KwmHotkeySO, "RemapKeys");
    }
    else
    {
        DEBUG("LoadKwmCode() Could not open '" << HotkeySOFullFilePath << "'")
    }

    Code.IsValid = (Code.KWMHotkeyCommands && Code.SystemHotkeyCommands && Code.CustomHotkeyCommands && Code.RemapKeys);
    return Code;
}

void UnloadKwmCode(kwm_code *Code)
{
    if(Code->KwmHotkeySO)
        dlclose(Code->KwmHotkeySO);

    Code->HotkeySOFileTime = "";
    Code->KWMHotkeyCommands = 0;
    Code->SystemHotkeyCommands = 0;
    Code->CustomHotkeyCommands = 0;
    Code->RemapKeys = 0;
    Code->IsValid = 0;
}

std::string KwmGetFileTime(const char *File)
{
    struct stat attr;
    return stat(File, &attr) ? ctime(&attr.st_mtime) : "file not found";
}

void KwmQuit()
{
    exit(0);
}

void * KwmWindowMonitor(void*)
{
    while(1)
    {
        pthread_mutex_lock(&BackgroundLock);
        if(KwmFocusMode != FocusModeDisabled)
            UpdateWindowTree();

        pthread_mutex_unlock(&BackgroundLock);
        usleep(200000);
    }
}

void KwmExecuteConfig()
{
    char *HomeP = std::getenv("HOME");
    if(!HomeP)
    {
        DEBUG("Failed to get environment variable 'HOME'")
        return;
    }

    std::string ENV_HOME = HomeP;
    std::string KWM_CONFIG_FILE = ".kwmrc";

    std::ifstream ConfigFD(ENV_HOME + "/" + KWM_CONFIG_FILE);
    if(ConfigFD.fail())
    {
        DEBUG("Could not open " << ENV_HOME << "/" << KWM_CONFIG_FILE
              << ", make sure the file exists." << std::endl)
        return;
    }

    std::string Line;
    while(std::getline(ConfigFD, Line))
    {
        if(!Line.empty() && Line[0] != '#')
            system(Line.c_str());
    }
}

void KwmInit()
{
    if(!CheckPrivileges())
        Fatal("Could not access OSX Accessibility!");

    if (pthread_mutex_init(&BackgroundLock, NULL) != 0)
        Fatal("Could not create mutex!");

    if(KwmStartDaemon())
        pthread_create(&DaemonThread, NULL, &KwmDaemonHandleConnectionBG, NULL);
    else
        Fatal("Kwm: Could not start daemon..");

    KwmFocusMode = FocusModeAutoraise;
    KwmFilePath = getcwd(NULL, 0);
    HotkeySOFullFilePath = KwmFilePath + "/hotkeys.so";
    KwmUseBuiltinHotkeys = true;

    KwmExecuteConfig();
    KWMCode = LoadKwmCode();

    GetActiveDisplays();
    pthread_create(&BackgroundThread, NULL, &KwmWindowMonitor, NULL);
}

bool CheckPrivileges()
{
    const void * Keys[] = { kAXTrustedCheckOptionPrompt };
    const void * Values[] = { kCFBooleanTrue };

    CFDictionaryRef Options;
    Options = CFDictionaryCreate(kCFAllocatorDefault,
            Keys, Values, sizeof(Keys) / sizeof(*Keys),
            &kCFCopyStringDictionaryKeyCallBacks,
            &kCFTypeDictionaryValueCallBacks);

    return AXIsProcessTrustedWithOptions(Options);
}

void Fatal(const std::string &Err)
{
    std::cout << Err << std::endl;
    exit(1);
}

int main(int argc, char **argv)
{
    KwmInit();

    CGEventMask EventMask;
    CFRunLoopSourceRef RunLoopSource;

    EventMask = ((1 << kCGEventKeyDown) | (1 << kCGEventMouseMoved));
    EventTap = CGEventTapCreate(kCGSessionEventTap, kCGHeadInsertEventTap, 0, EventMask, CGEventCallback, NULL);

    if(!EventTap || !CGEventTapIsEnabled(EventTap))
        Fatal("ERROR: Could not create event-tap!");

    RunLoopSource = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, EventTap, 0);
    CFRunLoopAddSource(CFRunLoopGetCurrent(), RunLoopSource, kCFRunLoopCommonModes);
    CGEventTapEnable(EventTap, true);
    NSApplicationLoad();
    CFRunLoopRun();
    return 0;
}
<|endoftext|>


<commit_before>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** 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 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.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/

#include "easingcontextpane.h"
#include "ui_easingcontextpane.h"
#include <qmljs/qmljspropertyreader.h>

#include <QGraphicsPixmapItem>
#include <QGraphicsScene>
#include <QPropertyAnimation>
#include <QSequentialAnimationGroup>

namespace QmlEditorWidgets {

class PixmapItem : public QObject, public QGraphicsPixmapItem
{
    Q_OBJECT
    Q_PROPERTY(QPointF pos READ pos WRITE setPos)
public:
    PixmapItem(const QPixmap &pix) : QGraphicsPixmapItem(pix) { }
};

class EasingSimulation : public QObject
{
    Q_OBJECT
public:
    QGraphicsView *m_g;
    EasingSimulation(QObject *parent=0, QGraphicsView *v=0):QObject(parent) {
        m_qtLogo = new PixmapItem(QPixmap(":/qt_logo.png"));
        m_scene.addItem(m_qtLogo);
        m_scene.setSceneRect(0,0,v->viewport()->width(),m_qtLogo->boundingRect().height());
        m_qtLogo->hide();
        m_sequential = 0;
        m_g = v;
        m_g->setScene(&m_scene);
    }

    ~EasingSimulation() { delete m_qtLogo; }

    QGraphicsScene *scene() { return &m_scene; }
    void show() { m_qtLogo->show(); }
    void hide() { m_qtLogo->hide(); }
    void reset() {
        m_qtLogo->setPos(0,0);
        m_scene.setSceneRect(0,0,m_g->viewport()->width(),m_qtLogo->boundingRect().height());
    }
    void stop() {
        if (m_sequential) {
            m_sequential->stop();
            reset();
            emit finished();
        }
    }
    bool running() {
        if (m_sequential)
            return m_sequential->state()==QAbstractAnimation::Running;
        else
            return false;
    }
    void updateCurve(QEasingCurve newCurve, int newDuration) {
        if (running()) {
            m_sequential->pause();
            static_cast<QPropertyAnimation *>(m_sequential->animationAt(1))->setEasingCurve(newCurve);
            static_cast<QPropertyAnimation *>(m_sequential->animationAt(1))->setDuration(newDuration);
            m_sequential->resume();
        }
    }
    void animate(int duration, QEasingCurve curve) {
        reset();
        m_sequential = new QSequentialAnimationGroup;
        connect(m_sequential,SIGNAL(finished()),this,SIGNAL(finished()));
        m_sequential->addPause(150);
        QPropertyAnimation *m_anim = new QPropertyAnimation (m_qtLogo, "pos");
        m_anim->setStartValue(QPointF(0, 0));
        m_anim->setEndValue(QPointF(m_scene.sceneRect().width() - m_qtLogo->boundingRect().width(), 0));
        m_anim->setDuration(duration);
        m_anim->setEasingCurve(curve);
        m_sequential->addAnimation(m_anim);
        m_sequential->addPause(300);
        m_sequential->start();
    }

signals:
    void finished();

private:
    PixmapItem *m_qtLogo;
    QGraphicsScene m_scene;
    QSequentialAnimationGroup *m_sequential;
};

EasingContextPane::EasingContextPane(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::EasingContextPane)
{
    ui->setupUi(this);

    m_simulation = new EasingSimulation(this,ui->graphicsView);

    m_easingGraph = new EasingGraph(this);
    m_easingGraph->raise();
    setLinear();

    ui->playButton->setIcon(QIcon(QLatin1String(":/playicon.png")));

    setGraphDisplayMode(GraphMode);

    connect(m_simulation,SIGNAL(finished()),this,SLOT(switchToGraph()));
}

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

bool EasingContextPane::acceptsType(const QStringList &types)
{
    return types.contains("NumberAnimation") ||
            types.contains("PropertyAnimation") ||
            types.contains("ColorAnimation") ||
            types.contains("RotationAnimation");
}

void EasingContextPane::setProperties(QmlJS::PropertyReader *propertyReader)
{
    m_easingGraph->setGeometry(ui->graphicsView->geometry().adjusted(2,2,-2,-2));
    QString newEasingType = QString("Linear");
    if (propertyReader->hasProperty(QLatin1String("easing.type"))) {
        newEasingType = propertyReader->readProperty(QLatin1String("easing.type")).toString();
        if (newEasingType.contains("."))
            newEasingType = newEasingType.right(newEasingType.length() - newEasingType.indexOf(".") - 1);
    }

    m_easingGraph->setEasingName(newEasingType);
    ui->easingShapeComboBox->setCurrentIndex(ui->easingShapeComboBox->findText(m_easingGraph->easingShape()));
    ui->easingExtremesComboBox->setCurrentIndex(ui->easingExtremesComboBox->findText(m_easingGraph->easingExtremes()));

    if (propertyReader->hasProperty(QLatin1String("easing.period"))) {
        qreal period = propertyReader->readProperty(QLatin1String("easing.period")).toDouble();
        if (period < ui->periodSpinBox->minimum() || period > ui->periodSpinBox->maximum())
            ui->periodSpinBox->setValue(ui->periodSpinBox->minimum());
        else
            ui->periodSpinBox->setValue(period);
    }
    else
        ui->periodSpinBox->setValue(0.3);

    if (propertyReader->hasProperty(QLatin1String("easing.amplitude"))) {
        qreal amplitude = propertyReader->readProperty(QLatin1String("easing.amplitude")).toDouble();
        if (amplitude < ui->amplitudeSpinBox->minimum() || amplitude > ui->amplitudeSpinBox->maximum())
            ui->amplitudeSpinBox->setValue(ui->amplitudeSpinBox->minimum());
        else
            ui->amplitudeSpinBox->setValue(amplitude);
    }
    else
        ui->amplitudeSpinBox->setValue(1.0);

    if (propertyReader->hasProperty(QLatin1String("easing.overshoot"))) {
        qreal overshoot = propertyReader->readProperty(QLatin1String("easing.overshoot")).toDouble();
        if (overshoot < ui->overshootSpinBox->minimum() || overshoot > ui->overshootSpinBox->maximum())
            ui->overshootSpinBox->setValue(ui->overshootSpinBox->minimum());
        else
            ui->overshootSpinBox->setValue(overshoot);
    }
    else
        ui->overshootSpinBox->setValue(1.70158);

    if (propertyReader->hasProperty(QLatin1String("duration"))) {
        qreal duration = propertyReader->readProperty(QLatin1String("duration")).toInt();
        if (duration < ui->durationSpinBox->minimum() || duration > ui->durationSpinBox->maximum())
            ui->durationSpinBox->setValue(ui->durationSpinBox->minimum());
        else
            ui->durationSpinBox->setValue(duration);
    }
    else
        ui->durationSpinBox->setValue(250);
}

void EasingContextPane::changeEvent(QEvent *e)
{
    QWidget::changeEvent(e);
    switch (e->type()) {
    case QEvent::LanguageChange:
        ui->retranslateUi(this);
        break;
    default:
        break;
    }
}

void EasingContextPane::setGraphDisplayMode(GraphDisplayMode newMode)
{
    m_displayMode = newMode;
    switch (newMode) {
    case GraphMode: {
            m_simulation->hide();
            m_easingGraph->show();
            break;
        }
    case SimulationMode: {
            m_simulation->show();
            m_easingGraph->hide();
            break;
        }
    default: break;
    }

}

void EasingContextPane::startAnimation()
{
    if (m_simulation->running())
        m_simulation->stop();
    else {
        m_simulation->animate(ui->durationSpinBox->value(), m_easingGraph->easingCurve());
        ui->playButton->setIcon(QIcon(QLatin1String(":/stopicon.png")));
    }

}

void EasingContextPane::switchToGraph()
{
    ui->playButton->setIcon(QIcon(QLatin1String(":/playicon.png")));
    setGraphDisplayMode(GraphMode);
}

void EasingContextPane::setOthers()
{
    ui->easingExtremesComboBox->setEnabled(true);
    ui->amplitudeSpinBox->setEnabled(false);
    ui->overshootSpinBox->setEnabled(false);
    ui->overshootSpinBox->setEnabled(false);
    ui->periodSpinBox->setEnabled(false);
}

void EasingContextPane::setLinear()
{
    ui->easingExtremesComboBox->setEnabled(false);
    ui->amplitudeSpinBox->setEnabled(false);
    ui->overshootSpinBox->setEnabled(false);
    ui->periodSpinBox->setEnabled(false);
}

void EasingContextPane::setBack()
{
    ui->easingExtremesComboBox->setEnabled(true);
    ui->amplitudeSpinBox->setEnabled(false);
    ui->overshootSpinBox->setEnabled(true);
    ui->periodSpinBox->setEnabled(false);
}

void EasingContextPane::setElastic()
{
    ui->easingExtremesComboBox->setEnabled(true);
    ui->amplitudeSpinBox->setEnabled(true);
    ui->overshootSpinBox->setEnabled(false);
    ui->periodSpinBox->setEnabled(true);
}

void EasingContextPane::setBounce()
{
    ui->easingExtremesComboBox->setEnabled(true);
    ui->amplitudeSpinBox->setEnabled(true);
    ui->overshootSpinBox->setEnabled(false);
    ui->periodSpinBox->setEnabled(false);
}

} //QmlDesigner

void QmlEditorWidgets::EasingContextPane::on_durationSpinBox_valueChanged(int newValue)
{
    m_simulation->updateCurve(m_easingGraph->easingCurve(),ui->durationSpinBox->value());
    emit propertyChanged(QLatin1String("duration"), newValue);
}

void QmlEditorWidgets::EasingContextPane::on_easingShapeComboBox_currentIndexChanged(QString newShape)
{
    if (newShape=="Linear")
        setLinear();
    else if (newShape=="Bounce")
        setBounce();
    else if (newShape=="Elastic")
        setElastic();
    else if (newShape=="Back")
        setBack();
    else
        setOthers();

    if (m_easingGraph->easingShape() != newShape) {
        m_easingGraph->setEasingShape(newShape);
        // reload easing parameters
        m_easingGraph->setAmplitude(ui->amplitudeSpinBox->value());
        m_easingGraph->setPeriod(ui->periodSpinBox->value());
        m_easingGraph->setOvershoot(ui->overshootSpinBox->value());
        m_simulation->updateCurve(m_easingGraph->easingCurve(),ui->durationSpinBox->value());
        emit propertyChanged(QLatin1String("easing.type"), QVariant("\""+m_easingGraph->easingName()+"\""));
    }
}

void QmlEditorWidgets::EasingContextPane::on_easingExtremesComboBox_currentIndexChanged(QString newExtremes)
{
    if (m_easingGraph->easingExtremes() != newExtremes) {
        m_easingGraph->setEasingExtremes(newExtremes);
        m_easingGraph->setAmplitude(ui->amplitudeSpinBox->value());
        m_easingGraph->setPeriod(ui->periodSpinBox->value());
        m_easingGraph->setOvershoot(ui->overshootSpinBox->value());
        m_simulation->updateCurve(m_easingGraph->easingCurve(),ui->durationSpinBox->value());
        emit propertyChanged(QLatin1String("easing.type"), QVariant("\""+m_easingGraph->easingName()+"\""));
    }
}

void QmlEditorWidgets::EasingContextPane::on_amplitudeSpinBox_valueChanged(double newAmplitude)
{
    if ((newAmplitude != m_easingGraph->amplitude()) &&
        (m_easingGraph->easingShape()=="Bounce" || m_easingGraph->easingShape()=="Elastic")) {
        m_easingGraph->setAmplitude(newAmplitude);
        m_simulation->updateCurve(m_easingGraph->easingCurve(),ui->durationSpinBox->value());
        emit propertyChanged(QLatin1String("easing.amplitude"), newAmplitude);
    }
}

void QmlEditorWidgets::EasingContextPane::on_periodSpinBox_valueChanged(double newPeriod)
{
    if ((newPeriod != m_easingGraph->period()) && (m_easingGraph->easingShape()=="Elastic")) {
        m_easingGraph->setPeriod(newPeriod);
        m_simulation->updateCurve(m_easingGraph->easingCurve(),ui->durationSpinBox->value());
        emit propertyChanged(QLatin1String("easing.period"), newPeriod);
    }

}

void QmlEditorWidgets::EasingContextPane::on_overshootSpinBox_valueChanged(double newOvershoot)
{
    if ((newOvershoot != m_easingGraph->overshoot()) && (m_easingGraph->easingShape()=="Back")) {
        m_easingGraph->setOvershoot(newOvershoot);
        m_simulation->updateCurve(m_easingGraph->easingCurve(),ui->durationSpinBox->value());
        emit propertyChanged(QLatin1String("easing.overshoot"), newOvershoot);
    }
}

void QmlEditorWidgets::EasingContextPane::on_playButton_clicked()
{
    setGraphDisplayMode(SimulationMode);
    startAnimation();
}

#include "easingcontextpane.moc"
<commit_msg>QmlDesiger:  fixed format for the easing parameters in the easing dialog Reviewed by: Thomas Hartmann<commit_after>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** 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 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.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/

#include "easingcontextpane.h"
#include "ui_easingcontextpane.h"
#include <qmljs/qmljspropertyreader.h>

#include <QGraphicsPixmapItem>
#include <QGraphicsScene>
#include <QPropertyAnimation>
#include <QSequentialAnimationGroup>

namespace QmlEditorWidgets {

class PixmapItem : public QObject, public QGraphicsPixmapItem
{
    Q_OBJECT
    Q_PROPERTY(QPointF pos READ pos WRITE setPos)
public:
    PixmapItem(const QPixmap &pix) : QGraphicsPixmapItem(pix) { }
};

class EasingSimulation : public QObject
{
    Q_OBJECT
public:
    QGraphicsView *m_g;
    EasingSimulation(QObject *parent=0, QGraphicsView *v=0):QObject(parent) {
        m_qtLogo = new PixmapItem(QPixmap(":/qt_logo.png"));
        m_scene.addItem(m_qtLogo);
        m_scene.setSceneRect(0,0,v->viewport()->width(),m_qtLogo->boundingRect().height());
        m_qtLogo->hide();
        m_sequential = 0;
        m_g = v;
        m_g->setScene(&m_scene);
    }

    ~EasingSimulation() { delete m_qtLogo; }

    QGraphicsScene *scene() { return &m_scene; }
    void show() { m_qtLogo->show(); }
    void hide() { m_qtLogo->hide(); }
    void reset() {
        m_qtLogo->setPos(0,0);
        m_scene.setSceneRect(0,0,m_g->viewport()->width(),m_qtLogo->boundingRect().height());
    }
    void stop() {
        if (m_sequential) {
            m_sequential->stop();
            reset();
            emit finished();
        }
    }
    bool running() {
        if (m_sequential)
            return m_sequential->state()==QAbstractAnimation::Running;
        else
            return false;
    }
    void updateCurve(QEasingCurve newCurve, int newDuration) {
        if (running()) {
            m_sequential->pause();
            static_cast<QPropertyAnimation *>(m_sequential->animationAt(1))->setEasingCurve(newCurve);
            static_cast<QPropertyAnimation *>(m_sequential->animationAt(1))->setDuration(newDuration);
            m_sequential->resume();
        }
    }
    void animate(int duration, QEasingCurve curve) {
        reset();
        m_sequential = new QSequentialAnimationGroup;
        connect(m_sequential,SIGNAL(finished()),this,SIGNAL(finished()));
        m_sequential->addPause(150);
        QPropertyAnimation *m_anim = new QPropertyAnimation (m_qtLogo, "pos");
        m_anim->setStartValue(QPointF(0, 0));
        m_anim->setEndValue(QPointF(m_scene.sceneRect().width() - m_qtLogo->boundingRect().width(), 0));
        m_anim->setDuration(duration);
        m_anim->setEasingCurve(curve);
        m_sequential->addAnimation(m_anim);
        m_sequential->addPause(300);
        m_sequential->start();
    }

signals:
    void finished();

private:
    PixmapItem *m_qtLogo;
    QGraphicsScene m_scene;
    QSequentialAnimationGroup *m_sequential;
};

EasingContextPane::EasingContextPane(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::EasingContextPane)
{
    ui->setupUi(this);

    m_simulation = new EasingSimulation(this,ui->graphicsView);

    m_easingGraph = new EasingGraph(this);
    m_easingGraph->raise();
    setLinear();

    ui->playButton->setIcon(QIcon(QLatin1String(":/playicon.png")));

    setGraphDisplayMode(GraphMode);

    connect(m_simulation,SIGNAL(finished()),this,SLOT(switchToGraph()));
}

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

bool EasingContextPane::acceptsType(const QStringList &types)
{
    return types.contains("NumberAnimation") ||
            types.contains("PropertyAnimation") ||
            types.contains("ColorAnimation") ||
            types.contains("RotationAnimation");
}

void EasingContextPane::setProperties(QmlJS::PropertyReader *propertyReader)
{
    m_easingGraph->setGeometry(ui->graphicsView->geometry().adjusted(2,2,-2,-2));
    QString newEasingType = QString("Linear");
    if (propertyReader->hasProperty(QLatin1String("easing.type"))) {
        newEasingType = propertyReader->readProperty(QLatin1String("easing.type")).toString();
        if (newEasingType.contains("."))
            newEasingType = newEasingType.right(newEasingType.length() - newEasingType.indexOf(".") - 1);
    }

    m_easingGraph->setEasingName(newEasingType);
    ui->easingShapeComboBox->setCurrentIndex(ui->easingShapeComboBox->findText(m_easingGraph->easingShape()));
    ui->easingExtremesComboBox->setCurrentIndex(ui->easingExtremesComboBox->findText(m_easingGraph->easingExtremes()));

    if (propertyReader->hasProperty(QLatin1String("easing.period"))) {
        qreal period = propertyReader->readProperty(QLatin1String("easing.period")).toDouble();
        if (period < ui->periodSpinBox->minimum() || period > ui->periodSpinBox->maximum())
            ui->periodSpinBox->setValue(ui->periodSpinBox->minimum());
        else
            ui->periodSpinBox->setValue(period);
    }
    else
        ui->periodSpinBox->setValue(0.3);

    if (propertyReader->hasProperty(QLatin1String("easing.amplitude"))) {
        qreal amplitude = propertyReader->readProperty(QLatin1String("easing.amplitude")).toDouble();
        if (amplitude < ui->amplitudeSpinBox->minimum() || amplitude > ui->amplitudeSpinBox->maximum())
            ui->amplitudeSpinBox->setValue(ui->amplitudeSpinBox->minimum());
        else
            ui->amplitudeSpinBox->setValue(amplitude);
    }
    else
        ui->amplitudeSpinBox->setValue(1.0);

    if (propertyReader->hasProperty(QLatin1String("easing.overshoot"))) {
        qreal overshoot = propertyReader->readProperty(QLatin1String("easing.overshoot")).toDouble();
        if (overshoot < ui->overshootSpinBox->minimum() || overshoot > ui->overshootSpinBox->maximum())
            ui->overshootSpinBox->setValue(ui->overshootSpinBox->minimum());
        else
            ui->overshootSpinBox->setValue(overshoot);
    }
    else
        ui->overshootSpinBox->setValue(1.70158);

    if (propertyReader->hasProperty(QLatin1String("duration"))) {
        qreal duration = propertyReader->readProperty(QLatin1String("duration")).toInt();
        if (duration < ui->durationSpinBox->minimum() || duration > ui->durationSpinBox->maximum())
            ui->durationSpinBox->setValue(ui->durationSpinBox->minimum());
        else
            ui->durationSpinBox->setValue(duration);
    }
    else
        ui->durationSpinBox->setValue(250);
}

void EasingContextPane::changeEvent(QEvent *e)
{
    QWidget::changeEvent(e);
    switch (e->type()) {
    case QEvent::LanguageChange:
        ui->retranslateUi(this);
        break;
    default:
        break;
    }
}

void EasingContextPane::setGraphDisplayMode(GraphDisplayMode newMode)
{
    m_displayMode = newMode;
    switch (newMode) {
    case GraphMode: {
            m_simulation->hide();
            m_easingGraph->show();
            break;
        }
    case SimulationMode: {
            m_simulation->show();
            m_easingGraph->hide();
            break;
        }
    default: break;
    }

}

void EasingContextPane::startAnimation()
{
    if (m_simulation->running())
        m_simulation->stop();
    else {
        m_simulation->animate(ui->durationSpinBox->value(), m_easingGraph->easingCurve());
        ui->playButton->setIcon(QIcon(QLatin1String(":/stopicon.png")));
    }

}

void EasingContextPane::switchToGraph()
{
    ui->playButton->setIcon(QIcon(QLatin1String(":/playicon.png")));
    setGraphDisplayMode(GraphMode);
}

void EasingContextPane::setOthers()
{
    ui->easingExtremesComboBox->setEnabled(true);
    ui->amplitudeSpinBox->setEnabled(false);
    ui->overshootSpinBox->setEnabled(false);
    ui->overshootSpinBox->setEnabled(false);
    ui->periodSpinBox->setEnabled(false);
}

void EasingContextPane::setLinear()
{
    ui->easingExtremesComboBox->setEnabled(false);
    ui->amplitudeSpinBox->setEnabled(false);
    ui->overshootSpinBox->setEnabled(false);
    ui->periodSpinBox->setEnabled(false);
}

void EasingContextPane::setBack()
{
    ui->easingExtremesComboBox->setEnabled(true);
    ui->amplitudeSpinBox->setEnabled(false);
    ui->overshootSpinBox->setEnabled(true);
    ui->periodSpinBox->setEnabled(false);
}

void EasingContextPane::setElastic()
{
    ui->easingExtremesComboBox->setEnabled(true);
    ui->amplitudeSpinBox->setEnabled(true);
    ui->overshootSpinBox->setEnabled(false);
    ui->periodSpinBox->setEnabled(true);
}

void EasingContextPane::setBounce()
{
    ui->easingExtremesComboBox->setEnabled(true);
    ui->amplitudeSpinBox->setEnabled(true);
    ui->overshootSpinBox->setEnabled(false);
    ui->periodSpinBox->setEnabled(false);
}

} //QmlDesigner

void QmlEditorWidgets::EasingContextPane::on_durationSpinBox_valueChanged(int newValue)
{
    m_simulation->updateCurve(m_easingGraph->easingCurve(),ui->durationSpinBox->value());
    emit propertyChanged(QLatin1String("duration"), newValue);
}

void QmlEditorWidgets::EasingContextPane::on_easingShapeComboBox_currentIndexChanged(QString newShape)
{
    if (newShape=="Linear")
        setLinear();
    else if (newShape=="Bounce")
        setBounce();
    else if (newShape=="Elastic")
        setElastic();
    else if (newShape=="Back")
        setBack();
    else
        setOthers();

    if (m_easingGraph->easingShape() != newShape) {
        m_easingGraph->setEasingShape(newShape);
        // reload easing parameters
        m_easingGraph->setAmplitude(ui->amplitudeSpinBox->value());
        m_easingGraph->setPeriod(ui->periodSpinBox->value());
        m_easingGraph->setOvershoot(ui->overshootSpinBox->value());
        m_simulation->updateCurve(m_easingGraph->easingCurve(),ui->durationSpinBox->value());
        emit propertyChanged(QLatin1String("easing.type"), QVariant(QLatin1String("Easing.")+m_easingGraph->easingName()));
    }
}

void QmlEditorWidgets::EasingContextPane::on_easingExtremesComboBox_currentIndexChanged(QString newExtremes)
{
    if (m_easingGraph->easingExtremes() != newExtremes) {
        m_easingGraph->setEasingExtremes(newExtremes);
        m_easingGraph->setAmplitude(ui->amplitudeSpinBox->value());
        m_easingGraph->setPeriod(ui->periodSpinBox->value());
        m_easingGraph->setOvershoot(ui->overshootSpinBox->value());
        m_simulation->updateCurve(m_easingGraph->easingCurve(),ui->durationSpinBox->value());
        emit propertyChanged(QLatin1String("easing.type"), QVariant(QLatin1String("Easing.")+m_easingGraph->easingName()));
    }
}

void QmlEditorWidgets::EasingContextPane::on_amplitudeSpinBox_valueChanged(double newAmplitude)
{
    if ((newAmplitude != m_easingGraph->amplitude()) &&
        (m_easingGraph->easingShape()=="Bounce" || m_easingGraph->easingShape()=="Elastic")) {
        m_easingGraph->setAmplitude(newAmplitude);
        m_simulation->updateCurve(m_easingGraph->easingCurve(),ui->durationSpinBox->value());
        emit propertyChanged(QLatin1String("easing.amplitude"), newAmplitude);
    }
}

void QmlEditorWidgets::EasingContextPane::on_periodSpinBox_valueChanged(double newPeriod)
{
    if ((newPeriod != m_easingGraph->period()) && (m_easingGraph->easingShape()=="Elastic")) {
        m_easingGraph->setPeriod(newPeriod);
        m_simulation->updateCurve(m_easingGraph->easingCurve(),ui->durationSpinBox->value());
        emit propertyChanged(QLatin1String("easing.period"), newPeriod);
    }

}

void QmlEditorWidgets::EasingContextPane::on_overshootSpinBox_valueChanged(double newOvershoot)
{
    if ((newOvershoot != m_easingGraph->overshoot()) && (m_easingGraph->easingShape()=="Back")) {
        m_easingGraph->setOvershoot(newOvershoot);
        m_simulation->updateCurve(m_easingGraph->easingCurve(),ui->durationSpinBox->value());
        emit propertyChanged(QLatin1String("easing.overshoot"), newOvershoot);
    }
}

void QmlEditorWidgets::EasingContextPane::on_playButton_clicked()
{
    setGraphDisplayMode(SimulationMode);
    startAnimation();
}

#include "easingcontextpane.moc"
<|endoftext|>


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

#include "main.h"
#include "masternode-sync.h"
#include "masternode-payments.h"
#include "masternode.h"
#include "masternodeman.h"
#include "util.h"
#include "addrman.h"

class CMasternodeSync;
CMasternodeSync masternodeSync;

CMasternodeSync::CMasternodeSync()
{
    lastMasternodeList = 0;
    lastMasternodeWinner = 0;
    lastBudgetItem = 0;
    RequestedMasternodeAssets = MASTERNODE_SYNC_INITIAL;
    RequestedMasternodeAttempt = 0;
}

bool CMasternodeSync::IsSynced()
{
    return (RequestedMasternodeAssets == MASTERNODE_SYNC_FINISHED);
}

void CMasternodeSync::AddedMasternodeList()
{
    lastMasternodeList = GetTime();
}

void CMasternodeSync::AddedMasternodeWinner()
{
    lastMasternodeWinner = GetTime();
}

void CMasternodeSync::AddedBudgetItem()
{
    lastBudgetItem = GetTime();
}

void CMasternodeSync::GetNextAsset()
{
    switch(RequestedMasternodeAssets)
    {
        case(MASTERNODE_SYNC_INITIAL):
            lastMasternodeList = 0;
            lastMasternodeWinner = 0;
            lastBudgetItem = 0;
            RequestedMasternodeAssets = MASTERNODE_SYNC_SPORKS;
            break;
        case(MASTERNODE_SYNC_SPORKS):
            RequestedMasternodeAssets = MASTERNODE_SYNC_LIST;
            break;
        case(MASTERNODE_SYNC_LIST):
            RequestedMasternodeAssets = MASTERNODE_SYNC_MNW;
            break;
        case(MASTERNODE_SYNC_MNW):
            RequestedMasternodeAssets = MASTERNODE_SYNC_BUDGET;
            break;
        case(MASTERNODE_SYNC_BUDGET):
            LogPrintf("CMasternodeSync::GetNextAsset - Sync has finished\n");
            RequestedMasternodeAssets = MASTERNODE_SYNC_FINISHED;
            break;
    }
    RequestedMasternodeAttempt = 0;
}

void CMasternodeSync::Process()
{
    static int c = 0;

    if(IsSynced()) {
        /*
            Resync if we lose all masternodes from sleep/wake or failure to sync originally
        */
        if(mnodeman.CountEnabled() == 0) {
            RequestedMasternodeAssets = MASTERNODE_SYNC_INITIAL;
            GetNextAsset();
        }
        return;
    }

    if(c++ % MASTERNODE_SYNC_TIMEOUT != 0) return;

    if(fDebug) LogPrintf("CMasternodeSync::Process() - RequestedMasternodeAssets %d c %d\n", RequestedMasternodeAssets, c);

    if(RequestedMasternodeAssets == MASTERNODE_SYNC_INITIAL) GetNextAsset();

    CBlockIndex* pindexPrev = chainActive.Tip();
    if(pindexPrev == NULL) return;

    LOCK(cs_vNodes);
    BOOST_FOREACH(CNode* pnode, vNodes)
    {

        //set to synced
        if(Params().NetworkID() == CBaseChainParams::REGTEST && c >= 10) {
            LogPrintf("CMasternodeSync::Process - Sync has finished\n");
            RequestedMasternodeAssets = MASTERNODE_SYNC_FINISHED;
            RequestedMasternodeAttempt = 0;
        }

        if(RequestedMasternodeAssets == MASTERNODE_SYNC_SPORKS){
            if(pnode->HasFulfilledRequest("getspork")) continue;
            pnode->FulfilledRequest("getspork");

            if(RequestedMasternodeAttempt <= 2){
                pnode->PushMessage("getsporks"); //get current network sporks
                if(RequestedMasternodeAttempt == 2) GetNextAsset();
                RequestedMasternodeAttempt++;
            }
            return;
        }

        //don't begin syncing until we're at a recent block
        if(pindexPrev->nHeight < pindexBestHeader->nHeight) return;

        if (pnode->nVersion >= nMasternodeMinProtocol) {

            if(RequestedMasternodeAssets == MASTERNODE_SYNC_LIST) {
                if(fDebug) LogPrintf("CMasternodeSync::Process() - lastMasternodeList %lld (GetTime() - MASTERNODE_SYNC_TIMEOUT) %lld\n", lastMasternodeList, GetTime() - MASTERNODE_SYNC_TIMEOUT);
                if(lastMasternodeList > 0 && lastMasternodeList < GetTime() - MASTERNODE_SYNC_TIMEOUT){ //hasn't received a new item in the last five seconds, so we'll move to the
                    GetNextAsset();
                    return;
                }

                if(pnode->HasFulfilledRequest("mnsync")) continue;
                pnode->FulfilledRequest("mnsync");

                if((lastMasternodeList == 0 || lastMasternodeList > GetTime() - MASTERNODE_SYNC_TIMEOUT)
                        && RequestedMasternodeAttempt <= 2){
                    mnodeman.DsegUpdate(pnode);
                    RequestedMasternodeAttempt++;
                }
                return;
            }
        }

        if (pnode->nVersion >= masternodePayments.GetMinMasternodePaymentsProto()) {
            if(RequestedMasternodeAssets == MASTERNODE_SYNC_MNW) {
                if(lastMasternodeWinner > 0 && lastMasternodeWinner < GetTime() - MASTERNODE_SYNC_TIMEOUT){ //hasn't received a new item in the last five seconds, so we'll move to the
                    GetNextAsset();
                    return;
                }

                if(pnode->HasFulfilledRequest("mnwsync")) continue;
                pnode->FulfilledRequest("mnwsync");

                if((lastMasternodeWinner == 0 || lastMasternodeWinner > GetTime() - MASTERNODE_SYNC_TIMEOUT)
                        && RequestedMasternodeAttempt <= 2){
                    pnode->PushMessage("mnget"); //sync payees
                    RequestedMasternodeAttempt++;
                }
                return;
            }
        }

        if (pnode->nVersion >= MIN_BUDGET_PEER_PROTO_VERSION) {

            if(RequestedMasternodeAssets == MASTERNODE_SYNC_BUDGET){
                if(lastBudgetItem > 0 && lastBudgetItem < GetTime() - MASTERNODE_SYNC_TIMEOUT){ //hasn't received a new item in the last five seconds, so we'll move to the
                    GetNextAsset();
                    return;
                }

                if(pnode->HasFulfilledRequest("busync")) continue;
                pnode->FulfilledRequest("busync");

                if((lastBudgetItem == 0 || lastBudgetItem > GetTime() - MASTERNODE_SYNC_TIMEOUT)
                        && RequestedMasternodeAttempt <= 2){
                    uint256 n = 0;

                    pnode->PushMessage("mnvs", n); //sync masternode votes
                    RequestedMasternodeAttempt++;
                }
                return;
            }

        }
    }
}
<commit_msg>slightly refactor<commit_after>// Copyright (c) 2014-2015 The Dash developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "main.h"
#include "masternode-sync.h"
#include "masternode-payments.h"
#include "masternode.h"
#include "masternodeman.h"
#include "util.h"
#include "addrman.h"

class CMasternodeSync;
CMasternodeSync masternodeSync;

CMasternodeSync::CMasternodeSync()
{
    lastMasternodeList = 0;
    lastMasternodeWinner = 0;
    lastBudgetItem = 0;
    RequestedMasternodeAssets = MASTERNODE_SYNC_INITIAL;
    RequestedMasternodeAttempt = 0;
}

bool CMasternodeSync::IsSynced()
{
    return (RequestedMasternodeAssets == MASTERNODE_SYNC_FINISHED);
}

void CMasternodeSync::AddedMasternodeList()
{
    lastMasternodeList = GetTime();
}

void CMasternodeSync::AddedMasternodeWinner()
{
    lastMasternodeWinner = GetTime();
}

void CMasternodeSync::AddedBudgetItem()
{
    lastBudgetItem = GetTime();
}

void CMasternodeSync::GetNextAsset()
{
    switch(RequestedMasternodeAssets)
    {
        case(MASTERNODE_SYNC_INITIAL):
            lastMasternodeList = 0;
            lastMasternodeWinner = 0;
            lastBudgetItem = 0;
            RequestedMasternodeAssets = MASTERNODE_SYNC_SPORKS;
            break;
        case(MASTERNODE_SYNC_SPORKS):
            RequestedMasternodeAssets = MASTERNODE_SYNC_LIST;
            break;
        case(MASTERNODE_SYNC_LIST):
            RequestedMasternodeAssets = MASTERNODE_SYNC_MNW;
            break;
        case(MASTERNODE_SYNC_MNW):
            RequestedMasternodeAssets = MASTERNODE_SYNC_BUDGET;
            break;
        case(MASTERNODE_SYNC_BUDGET):
            LogPrintf("CMasternodeSync::GetNextAsset - Sync has finished\n");
            RequestedMasternodeAssets = MASTERNODE_SYNC_FINISHED;
            break;
    }
    RequestedMasternodeAttempt = 0;
}

void CMasternodeSync::Process()
{
    static int tick = 0;

    if(tick++ % MASTERNODE_SYNC_TIMEOUT != 0) return;

    CBlockIndex* pindexPrev = chainActive.Tip();
    if(pindexPrev == NULL) return;

    if(IsSynced()) {
        /*
            Resync if we lose all masternodes from sleep/wake or failure to sync originally
        */
        if(mnodeman.CountEnabled() == 0) {
            RequestedMasternodeAssets = MASTERNODE_SYNC_INITIAL;
        } else
            return;
    }

    if(fDebug) LogPrintf("CMasternodeSync::Process() - tick %d RequestedMasternodeAssets %d\n", tick, RequestedMasternodeAssets);

    if(RequestedMasternodeAssets == MASTERNODE_SYNC_INITIAL) GetNextAsset();

    LOCK(cs_vNodes);
    BOOST_FOREACH(CNode* pnode, vNodes)
    {

        //set to synced
        if(Params().NetworkID() == CBaseChainParams::REGTEST && c >= 10) {
            LogPrintf("CMasternodeSync::Process - Sync has finished\n");
            RequestedMasternodeAssets = MASTERNODE_SYNC_FINISHED;
            RequestedMasternodeAttempt = 0;
        }

        if(RequestedMasternodeAssets == MASTERNODE_SYNC_SPORKS){
            if(pnode->HasFulfilledRequest("getspork")) continue;
            pnode->FulfilledRequest("getspork");

            if(RequestedMasternodeAttempt <= 2){
                pnode->PushMessage("getsporks"); //get current network sporks
                if(RequestedMasternodeAttempt == 2) GetNextAsset();
                RequestedMasternodeAttempt++;
            }
            return;
        }

        //don't begin syncing until we're almost at a recent block
        if(pindexPrev->nHeight + 4 < pindexBestHeader->nHeight || pindexPrev->nTime + 600 < GetTime()) return;

        if (pnode->nVersion >= nMasternodeMinProtocol) {

            if(RequestedMasternodeAssets == MASTERNODE_SYNC_LIST) {
                if(fDebug) LogPrintf("CMasternodeSync::Process() - lastMasternodeList %lld (GetTime() - MASTERNODE_SYNC_TIMEOUT) %lld\n", lastMasternodeList, GetTime() - MASTERNODE_SYNC_TIMEOUT);
                if(lastMasternodeList > 0 && lastMasternodeList < GetTime() - MASTERNODE_SYNC_TIMEOUT){ //hasn't received a new item in the last five seconds, so we'll move to the
                    GetNextAsset();
                    return;
                }

                if(pnode->HasFulfilledRequest("mnsync")) continue;
                pnode->FulfilledRequest("mnsync");

                if((lastMasternodeList == 0 || lastMasternodeList > GetTime() - MASTERNODE_SYNC_TIMEOUT)
                        && RequestedMasternodeAttempt <= 2){
                    mnodeman.DsegUpdate(pnode);
                    RequestedMasternodeAttempt++;
                }
                return;
            }
        }

        if (pnode->nVersion >= masternodePayments.GetMinMasternodePaymentsProto()) {
            if(RequestedMasternodeAssets == MASTERNODE_SYNC_MNW) {
                if(lastMasternodeWinner > 0 && lastMasternodeWinner < GetTime() - MASTERNODE_SYNC_TIMEOUT){ //hasn't received a new item in the last five seconds, so we'll move to the
                    GetNextAsset();
                    return;
                }

                if(pnode->HasFulfilledRequest("mnwsync")) continue;
                pnode->FulfilledRequest("mnwsync");

                if((lastMasternodeWinner == 0 || lastMasternodeWinner > GetTime() - MASTERNODE_SYNC_TIMEOUT)
                        && RequestedMasternodeAttempt <= 2){
                    pnode->PushMessage("mnget"); //sync payees
                    RequestedMasternodeAttempt++;
                }
                return;
            }
        }

        if (pnode->nVersion >= MIN_BUDGET_PEER_PROTO_VERSION) {

            if(RequestedMasternodeAssets == MASTERNODE_SYNC_BUDGET){
                if(lastBudgetItem > 0 && lastBudgetItem < GetTime() - MASTERNODE_SYNC_TIMEOUT){ //hasn't received a new item in the last five seconds, so we'll move to the
                    GetNextAsset();
                    return;
                }

                if(pnode->HasFulfilledRequest("busync")) continue;
                pnode->FulfilledRequest("busync");

                if((lastBudgetItem == 0 || lastBudgetItem > GetTime() - MASTERNODE_SYNC_TIMEOUT)
                        && RequestedMasternodeAttempt <= 2){
                    uint256 n = 0;

                    pnode->PushMessage("mnvs", n); //sync masternode votes
                    RequestedMasternodeAttempt++;
                }
                return;
            }

        }
    }
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2014 Cloudius Systems, Ltd.
 */

#ifndef ASYNC_ACTION_HH_
#define ASYNC_ACTION_HH_

#include "future.hh"
#include "reactor.hh"

// The AsyncAction concept represents an action which can complete later than
// the actual function invocation. It is represented by a function which
// returns a future which resolves when the action is done.

template<typename AsyncAction, typename StopCondition>
static inline
void do_until_continued(StopCondition&& stop_cond, AsyncAction&& action, promise<> p) {
    while (!stop_cond()) {
        auto&& f = action();
        if (!f.available()) {
            f.then([action = std::forward<AsyncAction>(action),
                    stop_cond = std::forward<StopCondition>(stop_cond), p = std::move(p)]() mutable {
                do_until_continued(stop_cond, action, std::move(p));
            });
            return;
        }

        if (f.failed()) {
            f.forward_to(std::move(p));
            return;
        }
    }

    p.set_value();
}

// Invokes given action until it fails or given condition evaluates to true.
template<typename AsyncAction, typename StopCondition>
static inline
future<> do_until(StopCondition&& stop_cond, AsyncAction&& action) {
    promise<> p;
    auto f = p.get_future();
    do_until_continued(std::forward<StopCondition>(stop_cond),
        std::forward<AsyncAction>(action), std::move(p));
    return f;
}

// Invoke given action undefinitely. Next invocation starts when previous completes or fails.
template<typename AsyncAction>
static inline
void keep_doing(AsyncAction&& action) {
    while (true) {
        auto f = action();
        if (!f.available()) {
            f.then([action = std::forward<AsyncAction>(action)] () mutable {
                 keep_doing(std::forward<AsyncAction>(action));
            });
            return;
        }
    }
}

template<typename Iterator, typename AsyncAction>
static inline
future<> do_for_each(Iterator begin, Iterator end, AsyncAction&& action) {
    while (begin != end) {
        auto f = action(*begin++);
        if (!f.available()) {
            return f.then([action = std::forward<AsyncAction>(action),
                    begin = std::move(begin), end = std::move(end)] () mutable {
                return do_for_each(std::move(begin), std::move(end), std::forward<AsyncAction>(action));
            });
        }
    }
    return make_ready_future<>();
}

#endif
<commit_msg>core: make keep_doing() propagate failure<commit_after>/*
 * Copyright (C) 2014 Cloudius Systems, Ltd.
 */

#ifndef ASYNC_ACTION_HH_
#define ASYNC_ACTION_HH_

#include "future.hh"
#include "reactor.hh"

// The AsyncAction concept represents an action which can complete later than
// the actual function invocation. It is represented by a function which
// returns a future which resolves when the action is done.

template<typename AsyncAction, typename StopCondition>
static inline
void do_until_continued(StopCondition&& stop_cond, AsyncAction&& action, promise<> p) {
    while (!stop_cond()) {
        auto&& f = action();
        if (!f.available()) {
            f.then([action = std::forward<AsyncAction>(action),
                    stop_cond = std::forward<StopCondition>(stop_cond), p = std::move(p)]() mutable {
                do_until_continued(stop_cond, action, std::move(p));
            });
            return;
        }

        if (f.failed()) {
            f.forward_to(std::move(p));
            return;
        }
    }

    p.set_value();
}

// Invokes given action until it fails or given condition evaluates to true.
template<typename AsyncAction, typename StopCondition>
static inline
future<> do_until(StopCondition&& stop_cond, AsyncAction&& action) {
    promise<> p;
    auto f = p.get_future();
    do_until_continued(std::forward<StopCondition>(stop_cond),
        std::forward<AsyncAction>(action), std::move(p));
    return f;
}

// Invoke given action until it fails.
template<typename AsyncAction>
static inline
future<> keep_doing(AsyncAction&& action) {
    while (true) {
        auto f = action();
        if (!f.available()) {
            return f.then([action = std::forward<AsyncAction>(action)] () mutable {
                 return keep_doing(std::forward<AsyncAction>(action));
            });
        }

        if (f.failed()) {
            return std::move(f);
        }
    }
}

template<typename Iterator, typename AsyncAction>
static inline
future<> do_for_each(Iterator begin, Iterator end, AsyncAction&& action) {
    while (begin != end) {
        auto f = action(*begin++);
        if (!f.available()) {
            return f.then([action = std::forward<AsyncAction>(action),
                    begin = std::move(begin), end = std::move(end)] () mutable {
                return do_for_each(std::move(begin), std::move(end), std::forward<AsyncAction>(action));
            });
        }
    }
    return make_ready_future<>();
}

#endif
<|endoftext|>