<commit_before>/*
    Copyright (C) 2013  Martin Klapetek <mklapetek@kde.org>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
*/

#include "kpeopletranslationproxy.h"

#include <KPeople/PersonsModel>

#include <kpeople/personpluginmanager.h>

#include "KTp/im-persons-data-source.h"
#include "KTp/types.h"

#include <KDebug>
#include <KIconLoader>

#include <QPixmapCache>

using namespace KPeople;

KPeopleTranslationProxy::KPeopleTranslationProxy(QObject *parent)
    : QIdentityProxyModel(parent)
{
}

KPeopleTranslationProxy::~KPeopleTranslationProxy()
{
}

QVariant KPeopleTranslationProxy::data(const QModelIndex &proxyIndex, int role) const
{
    if (!proxyIndex.isValid()) {
        return QVariant();
    }

    IMPersonsDataSource *imPlugin = qobject_cast<IMPersonsDataSource*>(PersonPluginManager::presencePlugin());

    if (!imPlugin) {
        kWarning() << "No imPlugin";
        return QVariant();
    }

    switch (role) {
        case KTp::ContactPresenceTypeRole:
            return translatePresence(mapToSource(proxyIndex).data(PersonsModel::PresenceTypeRole));
        case KTp::ContactPresenceIconRole:
            return mapToSource(proxyIndex).data(PersonsModel::PresenceIconNameRole);
        case KTp::ContactPresenceNameRole:
            return mapToSource(proxyIndex).data(PersonsModel::PresenceDisplayRole);
        case Qt::DisplayRole:
            return mapToSource(proxyIndex).data(Qt::DisplayRole);
        case KTp::RowTypeRole:
            //PersonsModel has only persons and contacts
            if (mapToSource(proxyIndex).parent().isValid()) {
                return KTp::ContactRowType;
            } else {
                return KTp::PersonRowType;
            }
        case KTp::ContactAvatarPathRole:
            return mapToSource(proxyIndex).data(PersonsModel::PhotosRole);
        case KTp::ContactAvatarPixmapRole:
            return contactPixmap(proxyIndex);
        case KTp::IdRole:
            return mapToSource(proxyIndex).data(PersonsModel::IMsRole);
        case KTp::HeaderTotalUsersRole:
            return sourceModel()->rowCount(mapToSource(proxyIndex));
        case KTp::ContactGroupsRole:
            return mapToSource(proxyIndex).data(PersonsModel::GroupsRole);
        case KTp::NepomukUriRole:
            return mapToSource(proxyIndex).data(PersonsModel::UriRole);
    }

    int j = sourceModel()->rowCount(mapToSource(proxyIndex));

    KTp::ContactPtr contact;

    if (j > 0) {
        KTp::ContactPtr mostOnlineContact;

        Q_FOREACH(const QVariant &v, mapToSource(proxyIndex).data(PersonsModel::IMsRole).toList()) {
            KTp::ContactPtr c = imPlugin->contactForContactId(v.toString());
            if (mostOnlineContact.isNull() && !c.isNull()) {
                mostOnlineContact = c;
                continue;
            }
            if (!c.isNull()) {
                if (c->presence() < mostOnlineContact->presence()) {
                    mostOnlineContact = c;
                }
            }
        }
        contact = mostOnlineContact;
    } else if (j == 0) {
        contact = imPlugin->contactForContactId(mapToSource(proxyIndex).data(PersonsModel::IMsRole).toString());
    }

    if (!contact.isNull()) {
        switch (role) {
            case KTp::ContactRole:
                return QVariant::fromValue<KTp::ContactPtr>(contact);
                break;
            case KTp::AccountRole:
                return QVariant::fromValue<Tp::AccountPtr>(imPlugin->accountForContact(contact));
                break;
            case KTp::ContactPresenceMessageRole:
                return contact->presence().statusMessage();
                break;
            case KTp::ContactIsBlockedRole:
                return contact->isBlocked();
                break;
            case KTp::ContactCanTextChatRole:
                return true;
                break;
            case KTp::ContactCanAudioCallRole:
                return contact->audioCallCapability();
                break;
            case KTp::ContactCanVideoCallRole:
                return contact->videoCallCapability();
                break;
            case KTp::ContactCanFileTransferRole:
                return contact->fileTransferCapability();
                break;
            case KTp::ContactClientTypesRole:
                return contact->clientTypes();
                break;
        }
    } else if (contact.isNull() && role == KTp::AccountRole) {
        //if the KTp contact is null, we still need the Tp account for that contact
        //so we can either group it properly or bring that account online if user
        //starts a chat with a contact that belongs to offline account
        QString contactId = j > 0 ? mapToSource(proxyIndex).data(PersonsModel::IMsRole).toList().first().toString()
                                  : mapToSource(proxyIndex).data(PersonsModel::IMsRole).toString();
        return QVariant::fromValue<Tp::AccountPtr>(imPlugin->accountForContactId(contactId));
    }
//     }

    return mapToSource(proxyIndex).data(role);
}

QVariant KPeopleTranslationProxy::translatePresence(const QVariant &presenceName) const
{
    if (presenceName == QLatin1String("available")) {
        return Tp::ConnectionPresenceTypeAvailable;
    }

    if (presenceName == QLatin1String("away")) {
        return Tp::ConnectionPresenceTypeAway;
    }

    if (presenceName == QLatin1String("busy") || presenceName == QLatin1String("dnd")) {
        return Tp::ConnectionPresenceTypeBusy;
    }

    if (presenceName == QLatin1String("xa")) {
        return Tp::ConnectionPresenceTypeExtendedAway;
    }

    if (presenceName == QLatin1String("hidden")) {
        return Tp::ConnectionPresenceTypeHidden;
    }

    return Tp::ConnectionPresenceTypeOffline;
}

QPixmap KPeopleTranslationProxy::contactPixmap(const QModelIndex &index) const
{
    QPixmap avatar;

    int presenceType = index.data(KTp::ContactPresenceTypeRole).toInt();
    //we need contact's ID to generate proper cache key for this contact
    QString id;
    if (index.data(KTp::RowTypeRole).toInt() == KTp::PersonRowType) {
        //persons return ids as list of child contacts ids
        const QVariantList ids = index.data(KTp::IdRole).toList();
        if (!ids.isEmpty()) {
            id = ids.first().toString();
        }
    } else {
        //contact returns id as string
        id = index.data(KTp::IdRole).toString();
    }

    //key for the pixmap cache, so we can look up the avatar
    const QString keyCache = id + (presenceType == Tp::ConnectionPresenceTypeOffline ? QLatin1String("-offline") : QLatin1String("-online"));

    //check pixmap cache for the avatar, if not present, load the avatar
    if (!QPixmapCache::find(keyCache, avatar)){
        const QVariantList files = index.data(KTp::ContactAvatarPathRole).toList();
        QString file;
        if (!files.isEmpty()) {
            file = files.first().toUrl().toLocalFile();
        }

        //QPixmap::load() checks for empty path
        avatar.load(file);

        //if the above didn't succeed, we need to load the generic icon
        if (avatar.isNull()) {
            avatar = KIconLoader::global()->loadIcon(QLatin1String("im-user"), KIconLoader::NoGroup, 96);
        }

        //if the contact is offline, gray it out
        if (presenceType == Tp::ConnectionPresenceTypeOffline) {
            QImage image = avatar.toImage();
            const QPixmap alpha = avatar.alphaChannel();
            for (int i = 0; i < image.width(); ++i) {
                for (int j = 0; j < image.height(); ++j) {
                    int colour = qGray(image.pixel(i, j));
                    image.setPixel(i, j, qRgb(colour, colour, colour));
                }
            }
            avatar = avatar.fromImage(image);
            avatar.setAlphaChannel(alpha);
        }

        //insert the contact into pixmap cache for faster lookup
        QPixmapCache::insert(keyCache, avatar);
    }

    return avatar;
}
<commit_msg>Use item's URI as the id for the pixmap cache<commit_after>/*
    Copyright (C) 2013  Martin Klapetek <mklapetek@kde.org>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
*/

#include "kpeopletranslationproxy.h"

#include <KPeople/PersonsModel>

#include <kpeople/personpluginmanager.h>

#include "KTp/im-persons-data-source.h"
#include "KTp/types.h"

#include <KDebug>
#include <KIconLoader>

#include <QPixmapCache>

using namespace KPeople;

KPeopleTranslationProxy::KPeopleTranslationProxy(QObject *parent)
    : QIdentityProxyModel(parent)
{
}

KPeopleTranslationProxy::~KPeopleTranslationProxy()
{
}

QVariant KPeopleTranslationProxy::data(const QModelIndex &proxyIndex, int role) const
{
    if (!proxyIndex.isValid()) {
        return QVariant();
    }

    IMPersonsDataSource *imPlugin = qobject_cast<IMPersonsDataSource*>(PersonPluginManager::presencePlugin());

    if (!imPlugin) {
        kWarning() << "No imPlugin";
        return QVariant();
    }

    switch (role) {
        case KTp::ContactPresenceTypeRole:
            return translatePresence(mapToSource(proxyIndex).data(PersonsModel::PresenceTypeRole));
        case KTp::ContactPresenceIconRole:
            return mapToSource(proxyIndex).data(PersonsModel::PresenceIconNameRole);
        case KTp::ContactPresenceNameRole:
            return mapToSource(proxyIndex).data(PersonsModel::PresenceDisplayRole);
        case Qt::DisplayRole:
            return mapToSource(proxyIndex).data(Qt::DisplayRole);
        case KTp::RowTypeRole:
            //PersonsModel has only persons and contacts
            if (mapToSource(proxyIndex).parent().isValid()) {
                return KTp::ContactRowType;
            } else {
                return KTp::PersonRowType;
            }
        case KTp::ContactAvatarPathRole:
            return mapToSource(proxyIndex).data(PersonsModel::PhotosRole);
        case KTp::ContactAvatarPixmapRole:
            return contactPixmap(proxyIndex);
        case KTp::IdRole:
            return mapToSource(proxyIndex).data(PersonsModel::IMsRole);
        case KTp::HeaderTotalUsersRole:
            return sourceModel()->rowCount(mapToSource(proxyIndex));
        case KTp::ContactGroupsRole:
            return mapToSource(proxyIndex).data(PersonsModel::GroupsRole);
        case KTp::NepomukUriRole:
            return mapToSource(proxyIndex).data(PersonsModel::UriRole);
    }

    int j = sourceModel()->rowCount(mapToSource(proxyIndex));

    KTp::ContactPtr contact;

    if (j > 0) {
        KTp::ContactPtr mostOnlineContact;

        Q_FOREACH(const QVariant &v, mapToSource(proxyIndex).data(PersonsModel::IMsRole).toList()) {
            KTp::ContactPtr c = imPlugin->contactForContactId(v.toString());
            if (mostOnlineContact.isNull() && !c.isNull()) {
                mostOnlineContact = c;
                continue;
            }
            if (!c.isNull()) {
                if (c->presence() < mostOnlineContact->presence()) {
                    mostOnlineContact = c;
                }
            }
        }
        contact = mostOnlineContact;
    } else if (j == 0) {
        contact = imPlugin->contactForContactId(mapToSource(proxyIndex).data(PersonsModel::IMsRole).toString());
    }

    if (!contact.isNull()) {
        switch (role) {
            case KTp::ContactRole:
                return QVariant::fromValue<KTp::ContactPtr>(contact);
                break;
            case KTp::AccountRole:
                return QVariant::fromValue<Tp::AccountPtr>(imPlugin->accountForContact(contact));
                break;
            case KTp::ContactPresenceMessageRole:
                return contact->presence().statusMessage();
                break;
            case KTp::ContactIsBlockedRole:
                return contact->isBlocked();
                break;
            case KTp::ContactCanTextChatRole:
                return true;
                break;
            case KTp::ContactCanAudioCallRole:
                return contact->audioCallCapability();
                break;
            case KTp::ContactCanVideoCallRole:
                return contact->videoCallCapability();
                break;
            case KTp::ContactCanFileTransferRole:
                return contact->fileTransferCapability();
                break;
            case KTp::ContactClientTypesRole:
                return contact->clientTypes();
                break;
        }
    } else if (contact.isNull() && role == KTp::AccountRole) {
        //if the KTp contact is null, we still need the Tp account for that contact
        //so we can either group it properly or bring that account online if user
        //starts a chat with a contact that belongs to offline account
        QString contactId = j > 0 ? mapToSource(proxyIndex).data(PersonsModel::IMsRole).toList().first().toString()
                                  : mapToSource(proxyIndex).data(PersonsModel::IMsRole).toString();
        return QVariant::fromValue<Tp::AccountPtr>(imPlugin->accountForContactId(contactId));
    }
//     }

    return mapToSource(proxyIndex).data(role);
}

QVariant KPeopleTranslationProxy::translatePresence(const QVariant &presenceName) const
{
    if (presenceName == QLatin1String("available")) {
        return Tp::ConnectionPresenceTypeAvailable;
    }

    if (presenceName == QLatin1String("away")) {
        return Tp::ConnectionPresenceTypeAway;
    }

    if (presenceName == QLatin1String("busy") || presenceName == QLatin1String("dnd")) {
        return Tp::ConnectionPresenceTypeBusy;
    }

    if (presenceName == QLatin1String("xa")) {
        return Tp::ConnectionPresenceTypeExtendedAway;
    }

    if (presenceName == QLatin1String("hidden")) {
        return Tp::ConnectionPresenceTypeHidden;
    }

    return Tp::ConnectionPresenceTypeOffline;
}

QPixmap KPeopleTranslationProxy::contactPixmap(const QModelIndex &index) const
{
    QPixmap avatar;

    int presenceType = index.data(KTp::ContactPresenceTypeRole).toInt();
    //we need some ID to generate proper cache key for this contact
    //so we'll use the contact's uri
    const QString id = index.data(KTp::NepomukUriRole).toString();

    //key for the pixmap cache, so we can look up the avatar
    const QString keyCache = id + (presenceType == Tp::ConnectionPresenceTypeOffline ? QLatin1String("-offline") : QLatin1String("-online"));

    //check pixmap cache for the avatar, if not present, load the avatar
    if (!QPixmapCache::find(keyCache, avatar)){
        const QVariantList files = index.data(KTp::ContactAvatarPathRole).toList();
        QString file;
        if (!files.isEmpty()) {
            file = files.first().toUrl().toLocalFile();
        }

        //QPixmap::load() checks for empty path
        avatar.load(file);

        //if the above didn't succeed, we need to load the generic icon
        if (avatar.isNull()) {
            avatar = KIconLoader::global()->loadIcon(QLatin1String("im-user"), KIconLoader::NoGroup, 96);
        }

        //if the contact is offline, gray it out
        if (presenceType == Tp::ConnectionPresenceTypeOffline) {
            QImage image = avatar.toImage();
            const QPixmap alpha = avatar.alphaChannel();
            for (int i = 0; i < image.width(); ++i) {
                for (int j = 0; j < image.height(); ++j) {
                    int colour = qGray(image.pixel(i, j));
                    image.setPixel(i, j, qRgb(colour, colour, colour));
                }
            }
            avatar = avatar.fromImage(image);
            avatar.setAlphaChannel(alpha);
        }

        //insert the contact into pixmap cache for faster lookup
        QPixmapCache::insert(keyCache, avatar);
    }

    return avatar;
}
<|endoftext|>


<commit_before>/*
A zero-indexed array A consisting of N integers is given. The dominator of array A is the value that occurs in more than half of the elements of A.
For example, consider array A such that
A[0] = 3    A[1] = 4    A[2] =  3
A[3] = 2    A[4] = 3    A[5] = -1
A[6] = 3    A[7] = 3
The dominator of A is 3 because it occurs in 5 out of 8 elements of A (namely in those with indices 0, 2, 4, 6 and 7) and 5 is more than a half of 8.
Write a function
int solution(vector<int> &A);
that, given a zero-indexed array A consisting of N integers, returns index of any element of array A in which the dominator of A occurs. The function should return −1 if array A does not have a dominator.
Assume that:
N is an integer within the range [0..100,000];
each element of array A is an integer within the range [−2,147,483,648..2,147,483,647].
For example, given array A such that
A[0] = 3    A[1] = 4    A[2] =  3
A[3] = 2    A[4] = 3    A[5] = -1
A[6] = 3    A[7] = 3
the function may return 0, 2, 4, 6 or 7, as explained above.
Complexity:
expected worst-case time complexity is O(N);
expected worst-case space complexity is O(1), beyond input storage (not counting the storage required for input arguments).
Elements of input arrays can be modified.
Copyright 2009–2015 by Codility Limited. All Rights Reserved. Unauthorized copying, publication or disclosure prohibited.
*/

// you can use includes, for example:
// #include <algorithm>

// you can write to stdout for debugging purposes, e.g.
// cout << "this is a debug message" << endl;

int solution(vector<int> &A) {
    // write your code in C++11
    int size(0);
    int value(0);
    for(unsigned int i=0; i<A.size(); ++i) {
        if( size==0 ) {
            size++;
            value = A[i];
        }
        else {
            if( A[i]==value )
                size++;
            else
                size--;
        }
    }
    if( size<=0 )
        return -1;

    int count(0);
    int j(-1);
    for(unsigned int i=0; i<A.size(); ++i) {
        if( A[i]==value ) {
            count++;
            j = i;
        }
    }
    if( count<=A.size()/2 )
        return -1;
    else
        return j;
}
<commit_msg>Update solution.cpp<commit_after>// you can use includes, for example:
// #include <algorithm>

// you can write to stdout for debugging purposes, e.g.
// cout << "this is a debug message" << endl;

int solution(vector<int> &A) {
    // write your code in C++11
    int size(0);
    int value(0);
    for(unsigned int i=0; i<A.size(); ++i) {
        if( size==0 ) {
            size++;
            value = A[i];
        }
        else {
            if( A[i]==value )
                size++;
            else
                size--;
        }
    }
    if( size<=0 )
        return -1;

    int count(0);
    int j(-1);
    for(unsigned int i=0; i<A.size(); ++i) {
        if( A[i]==value ) {
            count++;
            j = i;
        }
    }
    if( count<=A.size()/2 )
        return -1;
    else
        return j;
}
<|endoftext|>


<commit_before>//
//  Macintosh.cpp
//  Clock Signal
//
//  Created by Thomas Harte on 03/05/2019.
//  Copyright © 2019 Thomas Harte. All rights reserved.
//

#include "Macintosh.hpp"

#include <array>

#include "Video.hpp"

#include "../../CRTMachine.hpp"

#include "../../../Processors/68000/68000.hpp"
#include "../../../Components/6522/6522.hpp"
#include "../../../Components/DiskII/IWM.hpp"

#include "../../Utility/MemoryPacker.hpp"

namespace Apple {
namespace Macintosh {

class ConcreteMachine:
	public Machine,
	public CRTMachine::Machine,
	public CPU::MC68000::BusHandler {
	public:
		ConcreteMachine(const ROMMachine::ROMFetcher &rom_fetcher) :
		 	mc68000_(*this),
		 	video_(ram_.data()),
		 	via_(via_port_handler_),
		 	via_port_handler_(*this),
		 	iwm_(7833600) {

			// Grab a copy of the ROM and convert it into big-endian data.
			const auto roms = rom_fetcher("Macintosh", { "mac128k.rom" });
			if(!roms[0]) {
				throw ROMMachine::Error::MissingROMs;
			}
			roms[0]->resize(64*1024);
			Memory::PackBigEndian16(*roms[0], rom_.data());

			// The Mac runs at 7.8336mHz.
			set_clock_rate(7833600.0);
		}

		void set_scan_target(Outputs::Display::ScanTarget *scan_target) override {
			video_.set_scan_target(scan_target);
		}

		Outputs::Speaker::Speaker *get_speaker() override {
			return nullptr;
		}

		void run_for(const Cycles cycles) override {
			mc68000_.run_for(cycles);
		}

		using Microcycle = CPU::MC68000::Microcycle;

		HalfCycles perform_bus_operation(const Microcycle &cycle, int is_supervisor) {
			time_since_video_update_ += cycle.length;
			time_since_iwm_update_ += cycle.length;

			// Assumption here: it's a divide by ten to derive the 6522 clock, i.e.
			// it runs off the 68000's E clock.
			via_clock_ += cycle.length;
			via_.run_for(via_clock_.divide(HalfCycles(10)));

			// SCC is a divide-by-two.

			// A null cycle leaves nothing else to do.
			if(cycle.operation) {
				auto word_address = cycle.word_address();

				// Hardware devices begin at 0x800000 and accesses to 'them' (i.e. at lest the 6522,
				// and the other two are a guess) is via the synchronous bus.
				mc68000_.set_is_peripheral_address(word_address >= 0x400000);
				if(word_address >= 0x400000) {
					if(cycle.data_select_active()) {
//						printf("IO access to %06x: ", word_address << 1);

						const int register_address = word_address >> 8;

						switch(word_address & 0x7ff0ff) {
							case 0x77f0ff:
								// VIA accesses are via address 0xefe1fe + register*512,
								// which at word precision is 0x77f0ff + register*256.
								if(cycle.operation & Microcycle::Read) {
									cycle.value->halves.low = via_.get_register(register_address);
									if(cycle.operation & Microcycle::SelectWord) cycle.value->halves.high = 0xff;
								} else {
									via_.set_register(register_address, cycle.value->halves.low);
								}
							break;

							case 0x6ff0ff:
								// The IWM; this is a purely polled device, so can be run on demand.
								iwm_.run_for(time_since_iwm_update_.flush_cycles());
								if(cycle.operation & Microcycle::Read) {
									cycle.value->halves.low = iwm_.read(register_address);
									if(cycle.operation & Microcycle::SelectWord) cycle.value->halves.high = 0xff;
								} else {
									iwm_.write(register_address, cycle.value->halves.low);
								}
								printf("IWM %d %c [%02x]\n", register_address & 0xf, (cycle.operation & Microcycle::Read) ? 'r' : 'w', cycle.value->halves.low);
							break;
						}

//						printf("\n");
					}
				} else {
					if(cycle.data_select_active()) {
						uint16_t *memory_base = nullptr;

						// When ROM overlay is enabled, the ROM begins at both $000000 and $400000,
						// and RAM is available at $600000.
						//
						// Otherwise RAM is mapped at $000000 and ROM from $400000.
						//
						// Writes to the RAM area, at least, seem to go to RAM regardless of the ROM
						// overlay setting, so for now I'm gambling below that writes just always go to RAM.
						if(
							!(cycle.operation & Microcycle::Read) ||
							(
								(ROM_is_overlay_ && word_address >= 0x300000) ||
								(!ROM_is_overlay_ && !(word_address & 0x200000))
							)
						) {
							memory_base = ram_.data();
							word_address %= ram_.size();
						} else {
							memory_base = rom_.data();
							word_address %= rom_.size();
						}

						switch(cycle.operation & (Microcycle::SelectWord | Microcycle::SelectByte | Microcycle::Read | Microcycle::InterruptAcknowledge)) {
							default: break;

							case Microcycle::SelectWord | Microcycle::Read:
								cycle.value->full = memory_base[word_address];
//								printf("[%06x] -> %04x\n", word_address << 1, cycle.value->full);
							break;
							case Microcycle::SelectByte | Microcycle::Read:
								cycle.value->halves.low = uint8_t(memory_base[word_address] >> cycle.byte_shift());
//								printf("[%06x] -> %02x\n", (*cycle.address) & 0xffffff, cycle.value->halves.low);
							break;
							case Microcycle::SelectWord:
//								printf("%04x -> [%06x]\n", cycle.value->full, word_address << 1);
								memory_base[word_address] = cycle.value->full;
							break;
							case Microcycle::SelectByte:
//								printf("%02x -> [%06x]\n", cycle.value->halves.low, (*cycle.address) & 0xffffff);
								memory_base[word_address] = uint16_t(
									(cycle.value->halves.low << cycle.byte_shift()) |
									(memory_base[word_address] & cycle.untouched_byte_mask())
								);
							break;
						}
					} else {
						// TODO: add delay if this is a RAM access and video blocks it momentarily.
						// "Each [video] fetch took two cycles out of eight"
					}
				}
			}

			/*
				Normal memory map:

				000000: 	RAM
				400000: 	ROM
				9FFFF8+:	SCC read operations
				BFFFF8+:	SCC write operations
				DFE1FF+:	IWM
				EFE1FE+:	VIA
			*/

			return HalfCycles(0);
		}

		void flush() {
			video_.run_for(time_since_video_update_.flush());
		}

		void set_rom_is_overlay(bool rom_is_overlay) {
			ROM_is_overlay_ = rom_is_overlay;
		}

		void set_use_alternate_screen_buffer(bool use_alternate_screen_buffer) {
			video_.set_use_alternate_screen_buffer(use_alternate_screen_buffer);
		}

	private:
		class VIAPortHandler: public MOS::MOS6522::PortHandler {
			public:
				VIAPortHandler(ConcreteMachine &machine) : machine_(machine) {}

				using Port = MOS::MOS6522::Port;
				using Line = MOS::MOS6522::Line;

				void set_port_output(Port port, uint8_t value, uint8_t direction_mask) {
					/*
						Peripheral lines: keyboard data, interrupt configuration.
						(See p176 [/215])
					*/
					switch(port) {
						case Port::A:
							/*
								Port A:
									b7:	[input] SCC wait/request (/W/REQA and /W/REQB wired together for a logical OR)
									b6:	0 = alternate screen buffer, 1 = main screen buffer
									b5:	floppy disk SEL state control (upper/lower head "among other things")
									b4:	1 = use ROM overlay memory map, 0 = use ordinary memory map
									b3:	0 = use alternate sound buffer, 1 = use ordinary sound buffer
									b2–b0:	audio output volume
							*/
							printf("6522 A: %02x\n", value);
							machine_.set_rom_is_overlay(!!(value & 0x10));
							machine_.set_use_alternate_screen_buffer(!(value & 0x40));
						break;

						case Port::B:
							/*
								Port B:
									b7:	0 = sound enabled, 1 = sound disabled
									b6:	[input] 0 = video beam in visible portion of line, 1 = outside
									b5:	[input] mouse y2
									b4:	[input] mouse x2
									b3:	[input] 0 = mouse button down, 1 = up
									b2:	0 = real-time clock enabled, 1 = disabled
									b1:	clock's data-clock line
									b0:	clock's serial data line
							*/
							printf("6522 B: %02x\n", value);
						break;
					}
				}

				uint8_t get_port_input(Port port) {
					switch(port) {
						case Port::A:
							printf("6522 r A\n");
						return 0xff;

						case Port::B:
							printf("6522 r B\n");
						return 0x00;
					}
				}

				void set_control_line_output(Port port, Line line, bool value) {
					printf("6522 line %c%d: %c\n", port ? 'B' : 'A', int(line), value ? 't' : 'f');
				}

			private:
				ConcreteMachine &machine_;

		};

		std::array<uint16_t, 32*1024> rom_;
		std::array<uint16_t, 64*1024> ram_;

		CPU::MC68000::Processor<ConcreteMachine, true> mc68000_;
		Video video_;

		MOS::MOS6522::MOS6522<VIAPortHandler> via_;
 		VIAPortHandler via_port_handler_;

		Apple::IWM iwm_;

 		HalfCycles via_clock_;
 		HalfCycles time_since_video_update_;
 		HalfCycles time_since_iwm_update_;

		bool ROM_is_overlay_ = true;
};

}
}

using namespace Apple::Macintosh;

Machine *Machine::Macintosh(const Analyser::Static::Target *target, const ROMMachine::ROMFetcher &rom_fetcher) {
	return new ConcreteMachine(rom_fetcher);
}

Machine::~Machine() {}
<commit_msg>I now believe only the 6522 is on the synchronous bus.<commit_after>//
//  Macintosh.cpp
//  Clock Signal
//
//  Created by Thomas Harte on 03/05/2019.
//  Copyright © 2019 Thomas Harte. All rights reserved.
//

#include "Macintosh.hpp"

#include <array>

#include "Video.hpp"

#include "../../CRTMachine.hpp"

#include "../../../Processors/68000/68000.hpp"
#include "../../../Components/6522/6522.hpp"
#include "../../../Components/DiskII/IWM.hpp"

#include "../../Utility/MemoryPacker.hpp"

namespace Apple {
namespace Macintosh {

class ConcreteMachine:
	public Machine,
	public CRTMachine::Machine,
	public CPU::MC68000::BusHandler {
	public:
		ConcreteMachine(const ROMMachine::ROMFetcher &rom_fetcher) :
		 	mc68000_(*this),
		 	video_(ram_.data()),
		 	via_(via_port_handler_),
		 	via_port_handler_(*this),
		 	iwm_(7833600) {

			// Grab a copy of the ROM and convert it into big-endian data.
			const auto roms = rom_fetcher("Macintosh", { "mac128k.rom" });
			if(!roms[0]) {
				throw ROMMachine::Error::MissingROMs;
			}
			roms[0]->resize(64*1024);
			Memory::PackBigEndian16(*roms[0], rom_.data());

			// The Mac runs at 7.8336mHz.
			set_clock_rate(7833600.0);
		}

		void set_scan_target(Outputs::Display::ScanTarget *scan_target) override {
			video_.set_scan_target(scan_target);
		}

		Outputs::Speaker::Speaker *get_speaker() override {
			return nullptr;
		}

		void run_for(const Cycles cycles) override {
			mc68000_.run_for(cycles);
		}

		using Microcycle = CPU::MC68000::Microcycle;

		HalfCycles perform_bus_operation(const Microcycle &cycle, int is_supervisor) {
			time_since_video_update_ += cycle.length;
			time_since_iwm_update_ += cycle.length;

			// Assumption here: it's a divide by ten to derive the 6522 clock, i.e.
			// it runs off the 68000's E clock.
			via_clock_ += cycle.length;
			via_.run_for(via_clock_.divide(HalfCycles(10)));

			// SCC is a divide-by-two.

			// A null cycle leaves nothing else to do.
			if(cycle.operation) {
				auto word_address = cycle.word_address();

				// The 6522 is accessed via the synchronous bus.
				mc68000_.set_is_peripheral_address((word_address & 0x7ff0ff) == 0x77f0ff);

				if(word_address >= 0x400000) {
					if(cycle.data_select_active()) {
//						printf("IO access to %06x: ", word_address << 1);

						const int register_address = word_address >> 8;

						switch(word_address & 0x7ff0ff) {
							case 0x77f0ff:
								// VIA accesses are via address 0xefe1fe + register*512,
								// which at word precision is 0x77f0ff + register*256.
								if(cycle.operation & Microcycle::Read) {
									cycle.value->halves.low = via_.get_register(register_address);
									if(cycle.operation & Microcycle::SelectWord) cycle.value->halves.high = 0xff;
								} else {
									via_.set_register(register_address, cycle.value->halves.low);
								}
							break;

							case 0x6ff0ff:
								// The IWM; this is a purely polled device, so can be run on demand.
								iwm_.run_for(time_since_iwm_update_.flush_cycles());
								if(cycle.operation & Microcycle::Read) {
									cycle.value->halves.low = iwm_.read(register_address);
									if(cycle.operation & Microcycle::SelectWord) cycle.value->halves.high = 0xff;
								} else {
									iwm_.write(register_address, cycle.value->halves.low);
								}
								printf("IWM %d %c [%02x]\n", register_address & 0xf, (cycle.operation & Microcycle::Read) ? 'r' : 'w', cycle.value->halves.low);
							break;
						}

//						printf("\n");
					}
				} else {
					if(cycle.data_select_active()) {
						uint16_t *memory_base = nullptr;

						// When ROM overlay is enabled, the ROM begins at both $000000 and $400000,
						// and RAM is available at $600000.
						//
						// Otherwise RAM is mapped at $000000 and ROM from $400000.
						//
						// Writes to the RAM area, at least, seem to go to RAM regardless of the ROM
						// overlay setting, so for now I'm gambling below that writes just always go to RAM.
						if(
							!(cycle.operation & Microcycle::Read) ||
							(
								(ROM_is_overlay_ && word_address >= 0x300000) ||
								(!ROM_is_overlay_ && !(word_address & 0x200000))
							)
						) {
							memory_base = ram_.data();
							word_address %= ram_.size();
						} else {
							memory_base = rom_.data();
							word_address %= rom_.size();
						}

						switch(cycle.operation & (Microcycle::SelectWord | Microcycle::SelectByte | Microcycle::Read | Microcycle::InterruptAcknowledge)) {
							default: break;

							case Microcycle::SelectWord | Microcycle::Read:
								cycle.value->full = memory_base[word_address];
//								printf("[%06x] -> %04x\n", word_address << 1, cycle.value->full);
							break;
							case Microcycle::SelectByte | Microcycle::Read:
								cycle.value->halves.low = uint8_t(memory_base[word_address] >> cycle.byte_shift());
//								printf("[%06x] -> %02x\n", (*cycle.address) & 0xffffff, cycle.value->halves.low);
							break;
							case Microcycle::SelectWord:
//								printf("%04x -> [%06x]\n", cycle.value->full, word_address << 1);
								memory_base[word_address] = cycle.value->full;
							break;
							case Microcycle::SelectByte:
//								printf("%02x -> [%06x]\n", cycle.value->halves.low, (*cycle.address) & 0xffffff);
								memory_base[word_address] = uint16_t(
									(cycle.value->halves.low << cycle.byte_shift()) |
									(memory_base[word_address] & cycle.untouched_byte_mask())
								);
							break;
						}
					} else {
						// TODO: add delay if this is a RAM access and video blocks it momentarily.
						// "Each [video] fetch took two cycles out of eight"
					}
				}
			}

			/*
				Normal memory map:

				000000: 	RAM
				400000: 	ROM
				9FFFF8+:	SCC read operations
				BFFFF8+:	SCC write operations
				DFE1FF+:	IWM
				EFE1FE+:	VIA
			*/

			return HalfCycles(0);
		}

		void flush() {
			video_.run_for(time_since_video_update_.flush());
		}

		void set_rom_is_overlay(bool rom_is_overlay) {
			ROM_is_overlay_ = rom_is_overlay;
		}

		void set_use_alternate_screen_buffer(bool use_alternate_screen_buffer) {
			video_.set_use_alternate_screen_buffer(use_alternate_screen_buffer);
		}

	private:
		class VIAPortHandler: public MOS::MOS6522::PortHandler {
			public:
				VIAPortHandler(ConcreteMachine &machine) : machine_(machine) {}

				using Port = MOS::MOS6522::Port;
				using Line = MOS::MOS6522::Line;

				void set_port_output(Port port, uint8_t value, uint8_t direction_mask) {
					/*
						Peripheral lines: keyboard data, interrupt configuration.
						(See p176 [/215])
					*/
					switch(port) {
						case Port::A:
							/*
								Port A:
									b7:	[input] SCC wait/request (/W/REQA and /W/REQB wired together for a logical OR)
									b6:	0 = alternate screen buffer, 1 = main screen buffer
									b5:	floppy disk SEL state control (upper/lower head "among other things")
									b4:	1 = use ROM overlay memory map, 0 = use ordinary memory map
									b3:	0 = use alternate sound buffer, 1 = use ordinary sound buffer
									b2–b0:	audio output volume
							*/
							printf("6522 A: %02x\n", value);
							machine_.set_rom_is_overlay(!!(value & 0x10));
							machine_.set_use_alternate_screen_buffer(!(value & 0x40));
						break;

						case Port::B:
							/*
								Port B:
									b7:	0 = sound enabled, 1 = sound disabled
									b6:	[input] 0 = video beam in visible portion of line, 1 = outside
									b5:	[input] mouse y2
									b4:	[input] mouse x2
									b3:	[input] 0 = mouse button down, 1 = up
									b2:	0 = real-time clock enabled, 1 = disabled
									b1:	clock's data-clock line
									b0:	clock's serial data line
							*/
							printf("6522 B: %02x\n", value);
						break;
					}
				}

				uint8_t get_port_input(Port port) {
					switch(port) {
						case Port::A:
							printf("6522 r A\n");
						return 0xff;

						case Port::B:
							printf("6522 r B\n");
						return 0x00;
					}
				}

				void set_control_line_output(Port port, Line line, bool value) {
					printf("6522 line %c%d: %c\n", port ? 'B' : 'A', int(line), value ? 't' : 'f');
				}

			private:
				ConcreteMachine &machine_;

		};

		std::array<uint16_t, 32*1024> rom_;
		std::array<uint16_t, 64*1024> ram_;

		CPU::MC68000::Processor<ConcreteMachine, true> mc68000_;
		Video video_;

		MOS::MOS6522::MOS6522<VIAPortHandler> via_;
 		VIAPortHandler via_port_handler_;

		Apple::IWM iwm_;

 		HalfCycles via_clock_;
 		HalfCycles time_since_video_update_;
 		HalfCycles time_since_iwm_update_;

		bool ROM_is_overlay_ = true;
};

}
}

using namespace Apple::Macintosh;

Machine *Machine::Macintosh(const Analyser::Static::Target *target, const ROMMachine::ROMFetcher &rom_fetcher) {
	return new ConcreteMachine(rom_fetcher);
}

Machine::~Machine() {}
<|endoftext|>


<commit_before>#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
typedef vector < ll > vl;

vl arr(3);
/*
	returs gcd(a,b) and find the coeficcients of bezout
	such that d = ax + by
	arr[0] gcd
	arr[1] x
	arr[2] y
*/
void extended(ll a, ll b){
	ll y =0;
	ll x =1;
	ll xx =0;
	ll yy =1;
	while(b){
		ll	 q = a / b;
		ll t = b;
		b = a%b;
		a = t;

		t = xx;
		xx = x-q*xx;
		x = t;

		t = yy;
		yy = y -q*yy;
		y = t;
	}
	arr[0] = a;
	arr[1] = x;
	arr[2] = y;
}

int main(){
	ll a = 20, b = 50;
	extended(a,b);
	printf("gcd(%lld, %lld) = %lld = %lld * %lld + %lld * %lld\n", a, b, arr[0], a,arr[1], b, arr[2]);
	return 0;
}
<commit_msg>Add Bezouts identity, very useful.<commit_after>#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
typedef vector < ll > vl;

vl arr(3);
/*
	returs gcd(a,b) and find the coeficcients of bezout
	such that d = ax + by
	arr[0] gcd
	arr[1] x
	arr[2] y
*/
void extended(ll a, ll b){
	ll y =0;
	ll x =1;
	ll xx =0;
	ll yy =1;
	while(b){
		ll	 q = a / b;
		ll t = b;
		b = a%b;
		a = t;

		t = xx;
		xx = x-q*xx;
		x = t;

		t = yy;
		yy = y -q*yy;
		y = t;
	}
	arr[0] = a;
	arr[1] = x;
	arr[2] = y;
}
/*

	ax + by  = c
	mcd(a,b) = d
	ax0 + by0 = d
	c = d * c'

	Bezouts identity

		X = x0 * c' - (b/d) * k
		Y = y0 * c' + (a/d) * k

*/

int main(){
	ll a = 20, b = 50;
	extended(a,b);
	printf("gcd(%lld, %lld) = %lld = %lld * %lld + %lld * %lld\n", a, b, arr[0], a,arr[1], b, arr[2]);
	return 0;
}
<|endoftext|>


<commit_before>void AddTaskPWG4HighPtTrackQAAll(char *prodType = "LHC10h",Bool_t isPbPb=kTRUE, Int_t iAODanalysis = 0)
{
  int cent = 10;

  AliPWG4HighPtTrackQA *taskTrackQA00cent10 = AddTaskPWG4HighPtTrackQA(prodType,isPbPb,iAODanalysis,cent,0,0);
  AliPWG4HighPtTrackQA *taskTrackQA01cent10 = AddTaskPWG4HighPtTrackQA(prodType,isPbPb,iAODanalysis,cent,0,1);
  AliPWG4HighPtTrackQA *taskTrackQA02cent10 = AddTaskPWG4HighPtTrackQA(prodType,isPbPb,iAODanalysis,cent,0,2);
  AliPWG4HighPtTrackQA *taskTrackQA10cent10 = AddTaskPWG4HighPtTrackQA(prodType,isPbPb,iAODanalysis,cent,1,0);
  AliPWG4HighPtTrackQA *taskTrackQA11cent10 = AddTaskPWG4HighPtTrackQA(prodType,isPbPb,iAODanalysis,cent,1,1);
  AliPWG4HighPtTrackQA *taskTrackQA20cent10 = AddTaskPWG4HighPtTrackQA(prodType,isPbPb,iAODanalysis,cent,2,0);
  AliPWG4HighPtTrackQA *taskTrackQA21cent10 = AddTaskPWG4HighPtTrackQA(prodType,isPbPb,iAODanalysis,cent,2,1);
  AliPWG4HighPtTrackQA *taskTrackQA20cent10 = AddTaskPWG4HighPtTrackQA(prodType,isPbPb,iAODanalysis,cent,4,0);
  AliPWG4HighPtTrackQA *taskTrackQA20cent10 = AddTaskPWG4HighPtTrackQA(prodType,isPbPb,iAODanalysis,cent,4,1);

  if(isPbPb) {
    for(cent=0; cent<4; cent++) {
      AliPWG4HighPtTrackQA *taskTrackQA00 = AddTaskPWG4HighPtTrackQA(prodType,isPbPb,iAODanalysis,cent,0,0);
      AliPWG4HighPtTrackQA *taskTrackQA01 = AddTaskPWG4HighPtTrackQA(prodType,isPbPb,iAODanalysis,cent,0,1);
      AliPWG4HighPtTrackQA *taskTrackQA02 = AddTaskPWG4HighPtTrackQA(prodType,isPbPb,iAODanalysis,cent,0,2);
      AliPWG4HighPtTrackQA *taskTrackQA10 = AddTaskPWG4HighPtTrackQA(prodType,isPbPb,iAODanalysis,cent,1,0);
      AliPWG4HighPtTrackQA *taskTrackQA11 = AddTaskPWG4HighPtTrackQA(prodType,isPbPb,iAODanalysis,cent,1,1);
      AliPWG4HighPtTrackQA *taskTrackQA20 = AddTaskPWG4HighPtTrackQA(prodType,isPbPb,iAODanalysis,cent,2,0);
      AliPWG4HighPtTrackQA *taskTrackQA21 = AddTaskPWG4HighPtTrackQA(prodType,isPbPb,iAODanalysis,cent,2,1);
      AliPWG4HighPtTrackQA *taskTrackQA40 = AddTaskPWG4HighPtTrackQA(prodType,isPbPb,iAODanalysis,cent,4,0);
      AliPWG4HighPtTrackQA *taskTrackQA41 = AddTaskPWG4HighPtTrackQA(prodType,isPbPb,iAODanalysis,cent,4,1);
    }
  }

}

AliPWG4HighPtTrackQA* AddTaskPWG4HighPtTrackQA(char *prodType = "LHC10e14",Bool_t isPbPb=kTRUE,Int_t iAODanalysis = 0, Int_t centClass = 0, Int_t trackType = 0, Int_t cuts = 0)
{
  /*
    trackType: 0 = global
               1 = TPC stand alone
               2 = TPC stand alone constrained to SPD vertex
               3 = global w/o SPD layer requirements
               4 = TPC stand alone constrained to SPD vertex with QA track selection on global tracks
    cuts:      0 (global) = standard ITSTPC2010
               1 (global) = ITSrefit, no SPD requirements
               2 (global) = SPD || SDD
               0 (TPC)    = standard TPC + NClusters>70
               1 (TPC)    = standard TPC + NClusters>0 --> to study new TPC QA recommendations
   */

  // Creates HighPtTrackQA analysis task and adds it to the analysis manager.

  // A. Get the pointer to the existing analysis manager via the static access method.
  //==============================================================================
  AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
  if (!mgr) {
    Error("AddTaskPWG4HighPtQMC", "No analysis manager to connect to.");
    return NULL;
  }

  // B. Check the analysis type using the event handlers connected to the analysis
  //    manager. The availability of MC handler can also be checked here.
  //==============================================================================
  if (!mgr->GetInputEventHandler()) {
    ::Error("AddPWG4TaskHighPtTrackQA", "This task requires an input event handler");
    return NULL;
  }

  // C. Create the task, add it to manager.
  //===========================================================================

  //CREATE THE  CUTS -----------------------------------------------
  //Use AliESDtrackCuts
  AliESDtrackCuts *trackCuts = new AliESDtrackCuts("AliESDtrackCuts","Standard Cuts");
  //Standard Cuts
  //Set track cuts for global tracks
  if(trackType==0 && cuts==0) {
    trackCuts = trackCuts->GetStandardITSTPCTrackCuts2010(kTRUE);//Primary Track Selection
    trackCuts->SetRequireITSRefit(kTRUE);
  }
  if(trackType==0 && cuts==1) {
    //Cuts global tracks with ITSrefit requirement
    // TPC
    trackCuts->SetMinNClustersTPC(70);
    trackCuts->SetMaxChi2PerClusterTPC(4);
    trackCuts->SetAcceptKinkDaughters(kFALSE);
    trackCuts->SetRequireTPCRefit(kTRUE);
    // ITS
    trackCuts->SetRequireITSRefit(kTRUE);

    trackCuts->SetMaxDCAToVertexXYPtDep("0.0182+0.0350/pt^1.01");
    trackCuts->SetMaxDCAToVertexZ(2);
    trackCuts->SetDCAToVertex2D(kFALSE);
    trackCuts->SetRequireSigmaToVertex(kFALSE);
  }
  if(trackType==0 && cuts==2) {
    trackCuts = new AliESDtrackCuts("AliESDtrackCuts","Standard Cuts with SPD or SDD");
    //Cuts SPD || SDD
    // TPC
    trackCuts->SetMinNClustersTPC(70);
    trackCuts->SetMaxChi2PerClusterTPC(4);
    trackCuts->SetAcceptKinkDaughters(kFALSE);
    trackCuts->SetRequireTPCRefit(kTRUE);
    // ITS
    trackCuts->SetRequireITSRefit(kTRUE);
    trackCuts->SetClusterRequirementITS(AliESDtrackCuts::kSPD, AliESDtrackCuts::kNone);
    trackCuts->SetClusterRequirementITS(AliESDtrackCuts::kSDD, AliESDtrackCuts::kFirst);

    trackCuts->SetMaxDCAToVertexXYPtDep("0.0182+0.0350/pt^1.01");
    trackCuts->SetMaxDCAToVertexZ(2);
    trackCuts->SetDCAToVertex2D(kFALSE);
    trackCuts->SetRequireSigmaToVertex(kFALSE);

    trackCuts->SetRequireITSRefit(kTRUE);
  }
  if(trackType==1 && cuts==0) {
    //Set track cuts for TPConly tracks
    trackCuts = trackCuts->GetStandardTPCOnlyTrackCuts();
    trackCuts->SetMinNClustersTPC(70);
  }
  if(trackType==1 && cuts==1) {
    //Set track cuts for TPConly tracks
    trackCuts = trackCuts->GetStandardTPCOnlyTrackCuts();
    trackCuts->SetMinNClustersTPC(0);
  }

  if(trackType==2 && cuts==0) {
     //	      Set track cuts for TPConly constrained tracks
    trackCuts = trackCuts->GetStandardTPCOnlyTrackCuts();
    trackCuts->SetMinNClustersTPC(70);
  }
  if(trackType==2 && cuts==1) {
    //Set track cuts for TPConly constrained tracks
    trackCuts = trackCuts->GetStandardTPCOnlyTrackCuts();
    trackCuts->SetMinNClustersTPC(0);
  }

  if(trackType==4 && cuts==0) {
     //	      Set track cuts for TPConly constrained tracks
    trackCuts = trackCuts->GetStandardTPCOnlyTrackCuts();
    trackCuts->SetMinNClustersTPC(70);
  }
  if(trackType==4 && cuts==1) {
     //	      Set track cuts for TPConly constrained tracks
    trackCuts = trackCuts->GetStandardTPCOnlyTrackCuts();
    trackCuts->SetMinNClustersTPC(0);
  }

  trackCuts->SetEtaRange(-0.9,0.9);
  trackCuts->SetPtRange(0.15, 1e10);

  //Create the task
  AliPWG4HighPtTrackQA *taskPWG4TrackQA = new AliPWG4HighPtTrackQA(Form("AliPWG4HighPtTrackQACent%dTrack%dCuts%d",centClass,trackType,cuts));
  taskPWG4TrackQA->SetCuts(trackCuts);
  taskPWG4TrackQA->SetTrackType(trackType);

  taskPWG4TrackQA->SetPtMax(100.);

  if(iAODanalysis)
    taskPWG4TrackQA->SetDataType(AliPWG4HighPtTrackQA::kAOD);
  else
    taskPWG4TrackQA->SetDataType(AliPWG4HighPtTrackQA::kESD);

  if(isPbPb) {
    taskPWG4TrackQA->SetIsPbPb(kTRUE);
    taskPWG4TrackQA->SetCentralityClass(centClass);
  }
  //  taskPWG4TrackQA->SetSigmaConstrainedMax(5.);

  taskPWG4TrackQA->SelectCollisionCandidates();

  // E. Create ONLY the output containers for the data produced by the task.
  // Get and connect other common input/output containers via the manager as below
  //==============================================================================

  TString outputfile = AliAnalysisManager::GetCommonFileName();
  outputfile += Form(":PWG4_HighPtTrackQACent%dTrackType%dCuts%d",centClass,trackType,cuts);

  AliAnalysisDataContainer *cout_histQAtrack = mgr->CreateContainer(Form("qa_histsQAtrackCent%dType%dcuts%d",centClass,trackType,cuts), TList::Class(), AliAnalysisManager::kOutputContainer,outputfile);

  mgr->AddTask(taskPWG4TrackQA);
  mgr->ConnectInput(taskPWG4TrackQA,0,mgr->GetCommonInputContainer());
  mgr->ConnectOutput(taskPWG4TrackQA,1,cout_histQAtrack);

  // Return task pointer at the end
  return taskPWG4TrackQA;
}
<commit_msg>added protections, modified addtask macro for Track QA (M. Verweij)<commit_after>void AddTaskPWG4HighPtTrackQAAll(char *prodType = "LHC10h",Bool_t isPbPb=kTRUE, Int_t iAODanalysis = 0)
{
  int cent = 10;

  AliPWG4HighPtTrackQA *taskTrackQA00cent10 = AddTaskPWG4HighPtTrackQA(prodType,isPbPb,iAODanalysis,cent,0,0);
  //  AliPWG4HighPtTrackQA *taskTrackQA01cent10 = AddTaskPWG4HighPtTrackQA(prodType,isPbPb,iAODanalysis,cent,0,1);
  //  AliPWG4HighPtTrackQA *taskTrackQA02cent10 = AddTaskPWG4HighPtTrackQA(prodType,isPbPb,iAODanalysis,cent,0,2);
  AliPWG4HighPtTrackQA *taskTrackQA03cent10 = AddTaskPWG4HighPtTrackQA(prodType,isPbPb,iAODanalysis,cent,0,3);
  AliPWG4HighPtTrackQA *taskTrackQA10cent10 = AddTaskPWG4HighPtTrackQA(prodType,isPbPb,iAODanalysis,cent,1,0);
  AliPWG4HighPtTrackQA *taskTrackQA11cent10 = AddTaskPWG4HighPtTrackQA(prodType,isPbPb,iAODanalysis,cent,1,1);
  AliPWG4HighPtTrackQA *taskTrackQA20cent10 = AddTaskPWG4HighPtTrackQA(prodType,isPbPb,iAODanalysis,cent,2,0);
  AliPWG4HighPtTrackQA *taskTrackQA21cent10 = AddTaskPWG4HighPtTrackQA(prodType,isPbPb,iAODanalysis,cent,2,1);
  AliPWG4HighPtTrackQA *taskTrackQA40cent10 = AddTaskPWG4HighPtTrackQA(prodType,isPbPb,iAODanalysis,cent,4,0);
  AliPWG4HighPtTrackQA *taskTrackQA41cent10 = AddTaskPWG4HighPtTrackQA(prodType,isPbPb,iAODanalysis,cent,4,1);
  AliPWG4HighPtTrackQA *taskTrackQA50cent10 = AddTaskPWG4HighPtTrackQA(prodType,isPbPb,iAODanalysis,cent,5,0);
  AliPWG4HighPtTrackQA *taskTrackQA60cent10 = AddTaskPWG4HighPtTrackQA(prodType,isPbPb,iAODanalysis,cent,6,0);

  if(isPbPb) {
    for(cent=0; cent<4; cent++) {
      AliPWG4HighPtTrackQA *taskTrackQA00 = AddTaskPWG4HighPtTrackQA(prodType,isPbPb,iAODanalysis,cent,0,0);
      // AliPWG4HighPtTrackQA *taskTrackQA01 = AddTaskPWG4HighPtTrackQA(prodType,isPbPb,iAODanalysis,cent,0,1);
      // AliPWG4HighPtTrackQA *taskTrackQA02 = AddTaskPWG4HighPtTrackQA(prodType,isPbPb,iAODanalysis,cent,0,2);
      AliPWG4HighPtTrackQA *taskTrackQA03 = AddTaskPWG4HighPtTrackQA(prodType,isPbPb,iAODanalysis,cent,0,3);
      AliPWG4HighPtTrackQA *taskTrackQA10 = AddTaskPWG4HighPtTrackQA(prodType,isPbPb,iAODanalysis,cent,1,0);
      AliPWG4HighPtTrackQA *taskTrackQA11 = AddTaskPWG4HighPtTrackQA(prodType,isPbPb,iAODanalysis,cent,1,1);
      AliPWG4HighPtTrackQA *taskTrackQA20 = AddTaskPWG4HighPtTrackQA(prodType,isPbPb,iAODanalysis,cent,2,0);
      AliPWG4HighPtTrackQA *taskTrackQA21 = AddTaskPWG4HighPtTrackQA(prodType,isPbPb,iAODanalysis,cent,2,1);
      AliPWG4HighPtTrackQA *taskTrackQA40 = AddTaskPWG4HighPtTrackQA(prodType,isPbPb,iAODanalysis,cent,4,0);
      AliPWG4HighPtTrackQA *taskTrackQA41 = AddTaskPWG4HighPtTrackQA(prodType,isPbPb,iAODanalysis,cent,4,1);
      AliPWG4HighPtTrackQA *taskTrackQA50 = AddTaskPWG4HighPtTrackQA(prodType,isPbPb,iAODanalysis,cent,5,0);
      AliPWG4HighPtTrackQA *taskTrackQA60 = AddTaskPWG4HighPtTrackQA(prodType,isPbPb,iAODanalysis,cent,6,0);
    }
  }

}

AliPWG4HighPtTrackQA* AddTaskPWG4HighPtTrackQA(char *prodType = "LHC10e14",Bool_t isPbPb=kTRUE,Int_t iAODanalysis = 0, Int_t centClass = 0, Int_t trackType = 0, Int_t cuts = 0)
{
  /*
    trackType: 0 = global
               1 = TPC stand alone
               2 = TPC stand alone constrained to SPD vertex
               3 = global w/o SPD layer requirements
               4 = TPC stand alone constrained to SPD vertex with QA track selection on global tracks
	       5 = Hybrid tracks: constrained TPConly for which no tight ITS is available
               6 = Hybrid tracks: constrained loose global for which no tight ITS is available
    cuts:      0 (global) = standard ITSTPC2010
               1 (global) = ITSrefit, no SPD requirements
               2 (global) = SPD || SDD
	       3 (global) = standard ITS tight cuts with nCrossed rows cut
               0 (TPC)    = standard TPC + NClusters>70
               1 (TPC)    = standard TPC + NClusters>0 --> to study new TPC QA recommendations
               0 (hybrid 5) = constrained TPConly for which no tight ITS is available
               0 (hybrid 6) = constrained loose global for which no tight ITS is available
   */

  // Creates HighPtTrackQA analysis task and adds it to the analysis manager.

  // A. Get the pointer to the existing analysis manager via the static access method.
  //==============================================================================
  AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
  if (!mgr) {
    Error("AddTaskPWG4HighPtQMC", "No analysis manager to connect to.");
    return NULL;
  }

  // B. Check the analysis type using the event handlers connected to the analysis
  //    manager. The availability of MC handler can also be checked here.
  //==============================================================================
  if (!mgr->GetInputEventHandler()) {
    ::Error("AddPWG4TaskHighPtTrackQA", "This task requires an input event handler");
    return NULL;
  }

  // C. Create the task, add it to manager.
  //===========================================================================

  //CREATE THE  CUTS -----------------------------------------------
  //Use AliESDtrackCuts
  AliESDtrackCuts *trackCuts = new AliESDtrackCuts("AliESDtrackCuts","Standard Cuts");
  AliESDtrackCuts *trackCutsITSLoose = 0x0;
  AliESDtrackCuts *trackCutsTPConly = new AliESDtrackCuts("AliESDtrackCutsTPConly","TPC only Cuts");

  //Standard Cuts
  //Set track cuts for global tracks
  if(trackType==0 && cuts==0) {
    trackCuts = trackCuts->GetStandardITSTPCTrackCuts2010(kTRUE);//Primary Track Selection
    trackCuts->SetRequireITSRefit(kTRUE);
  }
  if(trackType==0 && cuts==1) {
    //Cuts global tracks with ITSrefit requirement
    // TPC
    trackCuts->SetMinNClustersTPC(70);
    trackCuts->SetMaxChi2PerClusterTPC(4);
    trackCuts->SetAcceptKinkDaughters(kFALSE);
    trackCuts->SetRequireTPCRefit(kTRUE);
    // ITS
    trackCuts->SetRequireITSRefit(kTRUE);

    trackCuts->SetMaxDCAToVertexXYPtDep("0.0182+0.0350/pt^1.01");
    trackCuts->SetMaxDCAToVertexZ(2);
    trackCuts->SetDCAToVertex2D(kFALSE);
    trackCuts->SetRequireSigmaToVertex(kFALSE);
  }
  if(trackType==0 && cuts==2) {
    trackCuts = new AliESDtrackCuts("AliESDtrackCuts","Standard Cuts with SPD or SDD");
    //Cuts SPD || SDD
    // TPC
    trackCuts->SetMinNClustersTPC(70);
    trackCuts->SetMaxChi2PerClusterTPC(4);
    trackCuts->SetAcceptKinkDaughters(kFALSE);
    trackCuts->SetRequireTPCRefit(kTRUE);
    // ITS
    trackCuts->SetRequireITSRefit(kTRUE);
    trackCuts->SetClusterRequirementITS(AliESDtrackCuts::kSPD, AliESDtrackCuts::kNone);
    trackCuts->SetClusterRequirementITS(AliESDtrackCuts::kSDD, AliESDtrackCuts::kFirst);

    trackCuts->SetMaxDCAToVertexXYPtDep("0.0182+0.0350/pt^1.01");
    trackCuts->SetMaxDCAToVertexZ(2);
    trackCuts->SetDCAToVertex2D(kFALSE);
    trackCuts->SetRequireSigmaToVertex(kFALSE);

    trackCuts->SetRequireITSRefit(kTRUE);
  }
  if(trackType==0 && cuts==3) {
    // tight global tracks
    trackCuts = AliESDtrackCuts::GetStandardITSTPCTrackCuts2010(kFALSE,1);
    trackCuts->SetMinNCrossedRowsTPC(120);
    trackCuts->SetMinRatioCrossedRowsOverFindableClustersTPC(0.1);// essentially swittches it off
    trackCuts->SetMaxDCAToVertexXY(2.4);
    trackCuts->SetMaxDCAToVertexZ(3.2);
    trackCuts->SetDCAToVertex2D(kTRUE);
    trackCuts->SetMaxChi2PerClusterITS(32);
  }

  if(trackType==1 && cuts==0) {
    //Set track cuts for TPConly tracks
    trackCuts = trackCuts->GetStandardTPCOnlyTrackCuts();
    trackCuts->SetMinNClustersTPC(70);
  }
  if(trackType==1 && cuts==1) {
    //Set track cuts for TPConly tracks
    trackCuts = trackCuts->GetStandardTPCOnlyTrackCuts();
    trackCuts->SetMinNClustersTPC(0);
  }

  if(trackType==2 && cuts==0) {
     //	      Set track cuts for TPConly constrained tracks
    trackCuts = trackCuts->GetStandardTPCOnlyTrackCuts();
    trackCuts->SetMinNClustersTPC(70);
  }
  if(trackType==2 && cuts==1) {
    //Set track cuts for TPConly constrained tracks
    trackCuts = trackCuts->GetStandardTPCOnlyTrackCuts();
    trackCuts->SetMinNClustersTPC(0);
  }

  if(trackType==4 && cuts==0) {
     //	      Set track cuts for TPConly constrained tracks
    trackCuts = trackCuts->GetStandardTPCOnlyTrackCuts();
    trackCuts->SetMinNClustersTPC(70);
  }
  if(trackType==4 && cuts==1) {
     //	      Set track cuts for TPConly constrained tracks
    trackCuts = trackCuts->GetStandardTPCOnlyTrackCuts();
    trackCuts->SetMinNClustersTPC(0);
  }
  if(trackType==5 || trackType==6) {
    // tight global tracks
    trackCuts = AliESDtrackCuts::GetStandardITSTPCTrackCuts2010(kFALSE,1);
    trackCuts->SetMinNCrossedRowsTPC(120);
    trackCuts->SetMinRatioCrossedRowsOverFindableClustersTPC(0.1);// essentially swittches it off
    trackCuts->SetMaxDCAToVertexXY(2.4);
    trackCuts->SetMaxDCAToVertexZ(3.2);
    trackCuts->SetDCAToVertex2D(kTRUE);
    trackCuts->SetMaxChi2PerClusterITS(32);

    trackCutsITSLoose  = new AliESDtrackCuts(*trackCuts);
    trackCutsITSLoose->SetName("loose ITS fake cuts");
    trackCutsITSLoose->SetMaxChi2PerClusterITS(1E10);

    trackCutsTPConly = trackCutsTPConly->GetStandardTPCOnlyTrackCuts();
    trackCutsTPConly->SetMinNCrossedRowsTPC(120);
    trackCutsTPConly->SetMinRatioCrossedRowsOverFindableClustersTPC(0.1);// essentially switches it off
  }

  trackCuts->SetEtaRange(-0.9,0.9);
  trackCuts->SetPtRange(0.15, 1e10);

  //Create the task
  AliPWG4HighPtTrackQA *taskPWG4TrackQA = new AliPWG4HighPtTrackQA(Form("AliPWG4HighPtTrackQACent%dTrack%dCuts%d",centClass,trackType,cuts));
  taskPWG4TrackQA->SetTrackType(trackType);
  taskPWG4TrackQA->SetCuts(trackCuts);
  taskPWG4TrackQA->SetCutsITSLoose(trackCutsITSLoose);
  taskPWG4TrackQA->SetCutsTPConly(trackCutsTPConly);

  taskPWG4TrackQA->SetPtMax(100.);

  if(iAODanalysis)
    taskPWG4TrackQA->SetDataType(AliPWG4HighPtTrackQA::kAOD);
  else
    taskPWG4TrackQA->SetDataType(AliPWG4HighPtTrackQA::kESD);

  if(isPbPb) {
    taskPWG4TrackQA->SetIsPbPb(kTRUE);
    taskPWG4TrackQA->SetCentralityClass(centClass);
  }
  //  taskPWG4TrackQA->SetSigmaConstrainedMax(5.);

  taskPWG4TrackQA->SelectCollisionCandidates();

  // E. Create ONLY the output containers for the data produced by the task.
  // Get and connect other common input/output containers via the manager as below
  //==============================================================================

  TString outputfile = AliAnalysisManager::GetCommonFileName();
  outputfile += Form(":PWG4_HighPtTrackQACent%dTrackType%dCuts%d",centClass,trackType,cuts);

  AliAnalysisDataContainer *cout_histQAtrack = mgr->CreateContainer(Form("qa_histsQAtrackCent%dType%dcuts%d",centClass,trackType,cuts), TList::Class(), AliAnalysisManager::kOutputContainer,outputfile);

  mgr->AddTask(taskPWG4TrackQA);
  mgr->ConnectInput(taskPWG4TrackQA,0,mgr->GetCommonInputContainer());
  mgr->ConnectOutput(taskPWG4TrackQA,1,cout_histQAtrack);

  // Return task pointer at the end
  return taskPWG4TrackQA;
}
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the plugins of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** 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.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qdeclarativecamerapreviewprovider_p.h"
#include <QtCore/qmutex.h>
#include <QtCore/qdebug.h>

QT_BEGIN_NAMESPACE

struct QDeclarativeCameraPreviewProviderPrivate
{
    QString id;
    QImage image;
    QMutex mutex;
};

Q_GLOBAL_STATIC(QDeclarativeCameraPreviewProviderPrivate, qDeclarativeCameraPreviewProviderPrivate)

QDeclarativeCameraPreviewProvider::QDeclarativeCameraPreviewProvider()
{
}

QDeclarativeCameraPreviewProvider::~QDeclarativeCameraPreviewProvider()
{
    QDeclarativeCameraPreviewProviderPrivate *d = qDeclarativeCameraPreviewProviderPrivate();
    QMutexLocker lock(&d->mutex);
    d->id.clear();
    d->image = QImage();
}

QImage QDeclarativeCameraPreviewProvider::request(const QString &id, QSize *size, const QSize& requestedSize)
{
    QDeclarativeCameraPreviewProviderPrivate *d = qDeclarativeCameraPreviewProviderPrivate();
    QMutexLocker lock(&d->mutex);

    if (d->id != id)
        return QImage();

    QImage res = d->image;
    if (!requestedSize.isEmpty())
        res = res.scaled(requestedSize, Qt::KeepAspectRatio, Qt::SmoothTransformation);

    if (size)
        *size = res.size();

    return res;
}

void QDeclarativeCameraPreviewProvider::registerPreview(const QString &id, const QImage &preview)
{
    //only the last preview is kept
    QDeclarativeCameraPreviewProviderPrivate *d = qDeclarativeCameraPreviewProviderPrivate();
    QMutexLocker lock(&d->mutex);
    d->id = id;
    d->image = preview;
}

QT_END_NAMESPACE
<commit_msg>Fix previous fix to multimedia declarative plugin<commit_after>/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the plugins of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** 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.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qdeclarativecamerapreviewprovider_p.h"
#include <QtCore/qmutex.h>
#include <QtCore/qdebug.h>

QT_BEGIN_NAMESPACE

struct QDeclarativeCameraPreviewProviderPrivate
{
    QString id;
    QImage image;
    QMutex mutex;
};

Q_GLOBAL_STATIC(QDeclarativeCameraPreviewProviderPrivate, qDeclarativeCameraPreviewProviderPrivate)

QDeclarativeCameraPreviewProvider::QDeclarativeCameraPreviewProvider()
: QDeclarativeImageProvider(QDeclarativeImageProvider::Image)
{
}

QDeclarativeCameraPreviewProvider::~QDeclarativeCameraPreviewProvider()
{
    QDeclarativeCameraPreviewProviderPrivate *d = qDeclarativeCameraPreviewProviderPrivate();
    QMutexLocker lock(&d->mutex);
    d->id.clear();
    d->image = QImage();
}

QImage QDeclarativeCameraPreviewProvider::request(const QString &id, QSize *size, const QSize& requestedSize)
{
    QDeclarativeCameraPreviewProviderPrivate *d = qDeclarativeCameraPreviewProviderPrivate();
    QMutexLocker lock(&d->mutex);

    if (d->id != id)
        return QImage();

    QImage res = d->image;
    if (!requestedSize.isEmpty())
        res = res.scaled(requestedSize, Qt::KeepAspectRatio, Qt::SmoothTransformation);

    if (size)
        *size = res.size();

    return res;
}

void QDeclarativeCameraPreviewProvider::registerPreview(const QString &id, const QImage &preview)
{
    //only the last preview is kept
    QDeclarativeCameraPreviewProviderPrivate *d = qDeclarativeCameraPreviewProviderPrivate();
    QMutexLocker lock(&d->mutex);
    d->id = id;
    d->image = preview;
}

QT_END_NAMESPACE
<|endoftext|>


<commit_before>////////////////////////////////////////////////////////////////////////////////
/// DISCLAIMER
///
/// Copyright 2014-2016 ArangoDB GmbH, Cologne, Germany
/// Copyright 2004-2014 triAGENS GmbH, Cologne, Germany
///
/// 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.
///
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
///
/// @author Dr. Frank Celler
////////////////////////////////////////////////////////////////////////////////

#include "SchedulerFeature.h"

#ifdef _WIN32
#include <stdio.h>
#include <windows.h>
#endif

#include "ApplicationFeatures/ApplicationServer.h"
#include "Basics/ArangoGlobalContext.h"
#include "Basics/WorkMonitor.h"
#include "Logger/LogAppender.h"
#include "ProgramOptions/ProgramOptions.h"
#include "ProgramOptions/Section.h"
#include "RestServer/ServerFeature.h"
#include "Scheduler/Scheduler.h"
#include "V8Server/V8DealerFeature.h"
#include "V8Server/v8-dispatcher.h"

using namespace arangodb;
using namespace arangodb::application_features;
using namespace arangodb::basics;
using namespace arangodb::options;
using namespace arangodb::rest;

Scheduler* SchedulerFeature::SCHEDULER = nullptr;

SchedulerFeature::SchedulerFeature(
    application_features::ApplicationServer* server)
    : ApplicationFeature(server, "Scheduler"), _scheduler(nullptr) {
  setOptional(true);
  requiresElevatedPrivileges(false);
  startsAfter("Database");
  startsAfter("FileDescriptors");
  startsAfter("Logger");
  startsAfter("WorkMonitor");
}

SchedulerFeature::~SchedulerFeature() {}

void SchedulerFeature::collectOptions(
    std::shared_ptr<options::ProgramOptions> options) {
  options->addSection("scheduler", "Configure the I/O scheduler");

  options->addOption("--server.threads", "number of threads",
                     new UInt64Parameter(&_nrServerThreads));

  options->addHiddenOption("--server.minimal-threads",
                           "minimal number of threads",
                           new UInt64Parameter(&_nrMinimalThreads));

  options->addHiddenOption("--server.maximal-threads",
                           "maximal number of threads",
                           new UInt64Parameter(&_nrMaximalThreads));

  options->addOption("--server.maximal-queue-size",
                     "maximum queue length for asynchronous operations",
                     new UInt64Parameter(&_queueSize));

  options->addOldOption("scheduler.threads", "server.threads");
}

void SchedulerFeature::validateOptions(
    std::shared_ptr<options::ProgramOptions>) {
  if (_nrServerThreads == 0) {
    _nrServerThreads = TRI_numberProcessors();
    LOG_TOPIC(DEBUG, arangodb::Logger::FIXME) << "Detected number of processors: " << _nrServerThreads;
  }

  if (_queueSize < 128) {
    LOG_TOPIC(FATAL, arangodb::Logger::FIXME)
        << "invalid value for `--server.maximal-queue-size', need at least 128";
    FATAL_ERROR_EXIT();
  }

  if (_nrMinimalThreads < 2) {
    _nrMinimalThreads = 2;
  }

  if (_nrServerThreads <= _nrMinimalThreads) {
    _nrServerThreads = _nrMinimalThreads;
  }

  if (_nrMaximalThreads == 0) {
    _nrMaximalThreads = 4 * _nrServerThreads;
  }

  if (_nrMaximalThreads < 64) {
    _nrMaximalThreads = 64;
  }

  if (_nrMinimalThreads > _nrMaximalThreads) {
    _nrMaximalThreads = _nrMinimalThreads;
  }

  TRI_ASSERT(0 < _nrMinimalThreads);
  TRI_ASSERT(_nrMinimalThreads <= _nrServerThreads);
  TRI_ASSERT(_nrServerThreads <= _nrMaximalThreads);
}

void SchedulerFeature::start() {
  ArangoGlobalContext::CONTEXT->maskAllSignals();
  buildScheduler();

  bool ok = _scheduler->start(nullptr);

  if (!ok) {
    LOG_TOPIC(FATAL, arangodb::Logger::FIXME) << "the scheduler cannot be started";
    FATAL_ERROR_EXIT();
  }

  buildHangupHandler();

  LOG_TOPIC(DEBUG, Logger::STARTUP) << "scheduler has started";

  V8DealerFeature* dealer =
      ApplicationServer::getFeature<V8DealerFeature>("V8Dealer");

  dealer->defineContextUpdate(
      [](v8::Isolate* isolate, v8::Handle<v8::Context> context, size_t) {
        TRI_InitV8Dispatcher(isolate, context);
      },
      nullptr);
}

void SchedulerFeature::stop() {
  static size_t const MAX_TRIES = 10;

  // shutdown user jobs (needs the scheduler)
  TRI_ShutdownV8Dispatcher();

  // cancel signals
  if (_exitSignals != nullptr) {
    _exitSignals->cancel();
    _exitSignals.reset();
  }

#ifndef WIN32
  if (_hangupSignals != nullptr) {
    _hangupSignals->cancel();
    _hangupSignals.reset();
  }
#endif

  // clear the handlers stuck in the WorkMonitor
  WorkMonitor::clearHandlers();

  // shut-down scheduler
  _scheduler->beginShutdown();

  for (size_t count = 0; count < MAX_TRIES && _scheduler->isRunning();
       ++count) {
    LOG_TOPIC(TRACE, Logger::STARTUP) << "waiting for scheduler to stop";
    usleep(100000);
  }
}

void SchedulerFeature::unprepare() {
  _scheduler->shutdown();
  SCHEDULER = nullptr;
}

#ifdef _WIN32
bool CtrlHandler(DWORD eventType) {
  bool shutdown = false;
  std::string shutdownMessage;

  switch (eventType) {
    case CTRL_BREAK_EVENT: {
      shutdown = true;
      shutdownMessage = "control-break received";
      break;
    }

    case CTRL_C_EVENT: {
      shutdown = true;
      shutdownMessage = "control-c received";
      break;
    }

    case CTRL_CLOSE_EVENT: {
      shutdown = true;
      shutdownMessage = "window-close received";
      break;
    }

    case CTRL_LOGOFF_EVENT: {
      shutdown = true;
      shutdownMessage = "user-logoff received";
      break;
    }

    case CTRL_SHUTDOWN_EVENT: {
      shutdown = true;
      shutdownMessage = "system-shutdown received";
      break;
    }

    default: {
      shutdown = false;
      break;
    }
  }

  if (shutdown == false) {
    LOG_TOPIC(ERR, arangodb::Logger::FIXME) << "Invalid CTRL HANDLER event received - ignoring event";
    return true;
  }

  static bool seen = false;

  if (!seen) {
    LOG_TOPIC(INFO, arangodb::Logger::FIXME) << "" << shutdownMessage << ", beginning shut down sequence";

    if (application_features::ApplicationServer::server != nullptr) {
      application_features::ApplicationServer::server->beginShutdown();
    }

    seen = true;
    return true;
  }

  // ........................................................................
  // user is desperate to kill the server!
  // ........................................................................

  LOG_TOPIC(INFO, arangodb::Logger::FIXME) << "" << shutdownMessage << ", terminating";
  _exit(EXIT_FAILURE);  // quick exit for windows
  return true;
}

#endif

void SchedulerFeature::buildScheduler() {
  _scheduler =
      std::make_unique<Scheduler>(static_cast<uint64_t>(_nrMinimalThreads),
                                  static_cast<uint64_t>(_nrServerThreads),
                                  static_cast<uint64_t>(_nrMaximalThreads),
                                  static_cast<uint64_t>(_queueSize));

  SCHEDULER = _scheduler.get();
}

void SchedulerFeature::buildControlCHandler() {
#ifdef WIN32
  {
    int result = SetConsoleCtrlHandler((PHANDLER_ROUTINE)CtrlHandler, true);

    if (result == 0) {
      LOG_TOPIC(WARN, arangodb::Logger::FIXME) << "unable to install control-c handler";
    }
  }
#else

  auto ioService = _scheduler->managerService();
  _exitSignals = std::make_shared<boost::asio::signal_set>(*ioService, SIGINT,
                                                           SIGTERM, SIGQUIT);

  _signalHandler = [this](const boost::system::error_code& error, int number) {
    if (error) {
      return;
    }

    LOG_TOPIC(INFO, arangodb::Logger::FIXME) << "control-c received, beginning shut down sequence";
    server()->beginShutdown();
    _exitSignals->async_wait(_exitHandler);
  };

  _exitHandler = [](const boost::system::error_code& error, int number) {
    if (error) {
      return;
    }

    LOG_TOPIC(FATAL, arangodb::Logger::FIXME) << "control-c received (again!), terminating";
    FATAL_ERROR_EXIT();
  };

  _exitSignals->async_wait(_signalHandler);
#endif
}

void SchedulerFeature::buildHangupHandler() {
#ifndef WIN32
  auto ioService = _scheduler->managerService();

  _hangupSignals =
      std::make_shared<boost::asio::signal_set>(*ioService, SIGHUP);

  _hangupHandler = [this](const boost::system::error_code& error, int number) {
    if (error) {
      return;
    }

    LOG_TOPIC(INFO, arangodb::Logger::FIXME) << "hangup received, about to reopen logfile";
    LogAppender::reopen();
    LOG_TOPIC(INFO, arangodb::Logger::FIXME) << "hangup received, reopened logfile";

    _hangupSignals->async_wait(_hangupHandler);
  };

  _hangupSignals->async_wait(_hangupHandler);
#endif
}
<commit_msg>wait longer before scheduler shutdown<commit_after>////////////////////////////////////////////////////////////////////////////////
/// DISCLAIMER
///
/// Copyright 2014-2016 ArangoDB GmbH, Cologne, Germany
/// Copyright 2004-2014 triAGENS GmbH, Cologne, Germany
///
/// 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.
///
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
///
/// @author Dr. Frank Celler
////////////////////////////////////////////////////////////////////////////////

#include "SchedulerFeature.h"

#ifdef _WIN32
#include <stdio.h>
#include <windows.h>
#endif

#include "ApplicationFeatures/ApplicationServer.h"
#include "Basics/ArangoGlobalContext.h"
#include "Basics/WorkMonitor.h"
#include "Logger/LogAppender.h"
#include "ProgramOptions/ProgramOptions.h"
#include "ProgramOptions/Section.h"
#include "RestServer/ServerFeature.h"
#include "Scheduler/Scheduler.h"
#include "V8Server/V8DealerFeature.h"
#include "V8Server/v8-dispatcher.h"

using namespace arangodb;
using namespace arangodb::application_features;
using namespace arangodb::basics;
using namespace arangodb::options;
using namespace arangodb::rest;

Scheduler* SchedulerFeature::SCHEDULER = nullptr;

SchedulerFeature::SchedulerFeature(
    application_features::ApplicationServer* server)
    : ApplicationFeature(server, "Scheduler"), _scheduler(nullptr) {
  setOptional(true);
  requiresElevatedPrivileges(false);
  startsAfter("Database");
  startsAfter("FileDescriptors");
  startsAfter("Logger");
  startsAfter("WorkMonitor");
}

SchedulerFeature::~SchedulerFeature() {}

void SchedulerFeature::collectOptions(
    std::shared_ptr<options::ProgramOptions> options) {
  options->addSection("scheduler", "Configure the I/O scheduler");

  options->addOption("--server.threads", "number of threads",
                     new UInt64Parameter(&_nrServerThreads));

  options->addHiddenOption("--server.minimal-threads",
                           "minimal number of threads",
                           new UInt64Parameter(&_nrMinimalThreads));

  options->addHiddenOption("--server.maximal-threads",
                           "maximal number of threads",
                           new UInt64Parameter(&_nrMaximalThreads));

  options->addOption("--server.maximal-queue-size",
                     "maximum queue length for asynchronous operations",
                     new UInt64Parameter(&_queueSize));

  options->addOldOption("scheduler.threads", "server.threads");
}

void SchedulerFeature::validateOptions(
    std::shared_ptr<options::ProgramOptions>) {
  if (_nrServerThreads == 0) {
    _nrServerThreads = TRI_numberProcessors();
    LOG_TOPIC(DEBUG, arangodb::Logger::FIXME) << "Detected number of processors: " << _nrServerThreads;
  }

  if (_queueSize < 128) {
    LOG_TOPIC(FATAL, arangodb::Logger::FIXME)
        << "invalid value for `--server.maximal-queue-size', need at least 128";
    FATAL_ERROR_EXIT();
  }

  if (_nrMinimalThreads < 2) {
    _nrMinimalThreads = 2;
  }

  if (_nrServerThreads <= _nrMinimalThreads) {
    _nrServerThreads = _nrMinimalThreads;
  }

  if (_nrMaximalThreads == 0) {
    _nrMaximalThreads = 4 * _nrServerThreads;
  }

  if (_nrMaximalThreads < 64) {
    _nrMaximalThreads = 64;
  }

  if (_nrMinimalThreads > _nrMaximalThreads) {
    _nrMaximalThreads = _nrMinimalThreads;
  }

  TRI_ASSERT(0 < _nrMinimalThreads);
  TRI_ASSERT(_nrMinimalThreads <= _nrServerThreads);
  TRI_ASSERT(_nrServerThreads <= _nrMaximalThreads);
}

void SchedulerFeature::start() {
  ArangoGlobalContext::CONTEXT->maskAllSignals();
  buildScheduler();

  bool ok = _scheduler->start(nullptr);

  if (!ok) {
    LOG_TOPIC(FATAL, arangodb::Logger::FIXME) << "the scheduler cannot be started";
    FATAL_ERROR_EXIT();
  }

  buildHangupHandler();

  LOG_TOPIC(DEBUG, Logger::STARTUP) << "scheduler has started";

  V8DealerFeature* dealer =
      ApplicationServer::getFeature<V8DealerFeature>("V8Dealer");

  dealer->defineContextUpdate(
      [](v8::Isolate* isolate, v8::Handle<v8::Context> context, size_t) {
        TRI_InitV8Dispatcher(isolate, context);
      },
      nullptr);
}

void SchedulerFeature::stop() {
  static size_t const MAX_TRIES = 100;

  // shutdown user jobs (needs the scheduler)
  TRI_ShutdownV8Dispatcher();

  // cancel signals
  if (_exitSignals != nullptr) {
    _exitSignals->cancel();
    _exitSignals.reset();
  }

#ifndef WIN32
  if (_hangupSignals != nullptr) {
    _hangupSignals->cancel();
    _hangupSignals.reset();
  }
#endif

  // clear the handlers stuck in the WorkMonitor
  WorkMonitor::clearHandlers();

  // shut-down scheduler
  _scheduler->beginShutdown();

  for (size_t count = 0; count < MAX_TRIES && _scheduler->isRunning();
       ++count) {
    LOG_TOPIC(TRACE, Logger::STARTUP) << "waiting for scheduler to stop";
    usleep(100000);
  }
}

void SchedulerFeature::unprepare() {
  _scheduler->shutdown();
  SCHEDULER = nullptr;
}

#ifdef _WIN32
bool CtrlHandler(DWORD eventType) {
  bool shutdown = false;
  std::string shutdownMessage;

  switch (eventType) {
    case CTRL_BREAK_EVENT: {
      shutdown = true;
      shutdownMessage = "control-break received";
      break;
    }

    case CTRL_C_EVENT: {
      shutdown = true;
      shutdownMessage = "control-c received";
      break;
    }

    case CTRL_CLOSE_EVENT: {
      shutdown = true;
      shutdownMessage = "window-close received";
      break;
    }

    case CTRL_LOGOFF_EVENT: {
      shutdown = true;
      shutdownMessage = "user-logoff received";
      break;
    }

    case CTRL_SHUTDOWN_EVENT: {
      shutdown = true;
      shutdownMessage = "system-shutdown received";
      break;
    }

    default: {
      shutdown = false;
      break;
    }
  }

  if (shutdown == false) {
    LOG_TOPIC(ERR, arangodb::Logger::FIXME) << "Invalid CTRL HANDLER event received - ignoring event";
    return true;
  }

  static bool seen = false;

  if (!seen) {
    LOG_TOPIC(INFO, arangodb::Logger::FIXME) << "" << shutdownMessage << ", beginning shut down sequence";

    if (application_features::ApplicationServer::server != nullptr) {
      application_features::ApplicationServer::server->beginShutdown();
    }

    seen = true;
    return true;
  }

  // ........................................................................
  // user is desperate to kill the server!
  // ........................................................................

  LOG_TOPIC(INFO, arangodb::Logger::FIXME) << "" << shutdownMessage << ", terminating";
  _exit(EXIT_FAILURE);  // quick exit for windows
  return true;
}

#endif

void SchedulerFeature::buildScheduler() {
  _scheduler =
      std::make_unique<Scheduler>(static_cast<uint64_t>(_nrMinimalThreads),
                                  static_cast<uint64_t>(_nrServerThreads),
                                  static_cast<uint64_t>(_nrMaximalThreads),
                                  static_cast<uint64_t>(_queueSize));

  SCHEDULER = _scheduler.get();
}

void SchedulerFeature::buildControlCHandler() {
#ifdef WIN32
  {
    int result = SetConsoleCtrlHandler((PHANDLER_ROUTINE)CtrlHandler, true);

    if (result == 0) {
      LOG_TOPIC(WARN, arangodb::Logger::FIXME) << "unable to install control-c handler";
    }
  }
#else

  auto ioService = _scheduler->managerService();
  _exitSignals = std::make_shared<boost::asio::signal_set>(*ioService, SIGINT,
                                                           SIGTERM, SIGQUIT);

  _signalHandler = [this](const boost::system::error_code& error, int number) {
    if (error) {
      return;
    }

    LOG_TOPIC(INFO, arangodb::Logger::FIXME) << "control-c received, beginning shut down sequence";
    server()->beginShutdown();
    _exitSignals->async_wait(_exitHandler);
  };

  _exitHandler = [](const boost::system::error_code& error, int number) {
    if (error) {
      return;
    }

    LOG_TOPIC(FATAL, arangodb::Logger::FIXME) << "control-c received (again!), terminating";
    FATAL_ERROR_EXIT();
  };

  _exitSignals->async_wait(_signalHandler);
#endif
}

void SchedulerFeature::buildHangupHandler() {
#ifndef WIN32
  auto ioService = _scheduler->managerService();

  _hangupSignals =
      std::make_shared<boost::asio::signal_set>(*ioService, SIGHUP);

  _hangupHandler = [this](const boost::system::error_code& error, int number) {
    if (error) {
      return;
    }

    LOG_TOPIC(INFO, arangodb::Logger::FIXME) << "hangup received, about to reopen logfile";
    LogAppender::reopen();
    LOG_TOPIC(INFO, arangodb::Logger::FIXME) << "hangup received, reopened logfile";

    _hangupSignals->async_wait(_hangupHandler);
  };

  _hangupSignals->async_wait(_hangupHandler);
#endif
}
<|endoftext|>


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

#include "boundingrecthighlighter.h"
#include "qdeclarativeviewinspector.h"
#include "qmlinspectorconstants.h"

#include <QGraphicsPolygonItem>

#include <QTimer>
#include <QObject>
#include <QDebug>

namespace QmlJSDebugger {

BoundingBox::BoundingBox(QGraphicsObject *itemToHighlight, QGraphicsItem *parentItem,
                         QObject *parent)
    : QObject(parent),
      highlightedObject(itemToHighlight),
      highlightPolygon(0),
      highlightPolygonEdge(0)
{
    highlightPolygon = new BoundingBoxPolygonItem(parentItem);
    highlightPolygonEdge = new BoundingBoxPolygonItem(parentItem);

    highlightPolygon->setPen(QPen(QColor(0, 22, 159)));
    highlightPolygonEdge->setPen(QPen(QColor(158, 199, 255)));

    highlightPolygon->setFlag(QGraphicsItem::ItemIsSelectable, false);
    highlightPolygonEdge->setFlag(QGraphicsItem::ItemIsSelectable, false);
}

BoundingBox::~BoundingBox()
{
    highlightedObject.clear();
}

BoundingBoxPolygonItem::BoundingBoxPolygonItem(QGraphicsItem *item) : QGraphicsPolygonItem(item)
{
    QPen pen;
    pen.setColor(QColor(108, 141, 221));
    pen.setWidth(1);
    setPen(pen);
}

int BoundingBoxPolygonItem::type() const
{
    return Constants::EditorItemType;
}

BoundingRectHighlighter::BoundingRectHighlighter(QDeclarativeViewInspector *view) :
    LiveLayerItem(view->declarativeView()->scene()),
    m_view(view)
{
}

BoundingRectHighlighter::~BoundingRectHighlighter()
{

}

void BoundingRectHighlighter::clear()
{
    foreach (BoundingBox *box, m_boxes)
        freeBoundingBox(box);
}

BoundingBox *BoundingRectHighlighter::boxFor(QGraphicsObject *item) const
{
    foreach (BoundingBox *box, m_boxes) {
        if (box->highlightedObject.data() == item)
            return box;
    }
    return 0;
}

void BoundingRectHighlighter::highlight(QList<QGraphicsObject*> items)
{
    if (items.isEmpty())
        return;

    QList<BoundingBox *> newBoxes;
    foreach (QGraphicsObject *itemToHighlight, items) {
        BoundingBox *box = boxFor(itemToHighlight);
        if (!box)
            box = createBoundingBox(itemToHighlight);

        newBoxes << box;
    }
    qSort(newBoxes);

    if (newBoxes != m_boxes) {
        clear();
        m_boxes << newBoxes;
    }

    highlightAll();
}

void BoundingRectHighlighter::highlight(QGraphicsObject* itemToHighlight)
{
    if (!itemToHighlight)
        return;

    BoundingBox *box = boxFor(itemToHighlight);
    if (!box) {
        box = createBoundingBox(itemToHighlight);
        m_boxes << box;
        qSort(m_boxes);
    }

    highlightAll();
}

BoundingBox *BoundingRectHighlighter::createBoundingBox(QGraphicsObject *itemToHighlight)
{
    if (!m_freeBoxes.isEmpty()) {
        BoundingBox *box = m_freeBoxes.last();
        if (box->highlightedObject.isNull()) {
            box->highlightedObject = itemToHighlight;
            box->highlightPolygon->show();
            box->highlightPolygonEdge->show();
            m_freeBoxes.removeLast();
            return box;
        }
    }

    BoundingBox *box = new BoundingBox(itemToHighlight, this, this);

    connect(itemToHighlight, SIGNAL(xChanged()), this, SLOT(refresh()));
    connect(itemToHighlight, SIGNAL(yChanged()), this, SLOT(refresh()));
    connect(itemToHighlight, SIGNAL(widthChanged()), this, SLOT(refresh()));
    connect(itemToHighlight, SIGNAL(heightChanged()), this, SLOT(refresh()));
    connect(itemToHighlight, SIGNAL(rotationChanged()), this, SLOT(refresh()));
    connect(itemToHighlight, SIGNAL(destroyed(QObject*)), this, SLOT(itemDestroyed(QObject*)));

    return box;
}

void BoundingRectHighlighter::removeBoundingBox(BoundingBox *box)
{
    delete box;
    box = 0;
}

void BoundingRectHighlighter::freeBoundingBox(BoundingBox *box)
{
    if (!box->highlightedObject.isNull()) {
        disconnect(box->highlightedObject.data(), SIGNAL(xChanged()), this, SLOT(refresh()));
        disconnect(box->highlightedObject.data(), SIGNAL(yChanged()), this, SLOT(refresh()));
        disconnect(box->highlightedObject.data(), SIGNAL(widthChanged()), this, SLOT(refresh()));
        disconnect(box->highlightedObject.data(), SIGNAL(heightChanged()), this, SLOT(refresh()));
        disconnect(box->highlightedObject.data(), SIGNAL(rotationChanged()), this, SLOT(refresh()));
    }

    box->highlightedObject.clear();
    box->highlightPolygon->hide();
    box->highlightPolygonEdge->hide();
    m_boxes.removeOne(box);
    m_freeBoxes << box;
}

void BoundingRectHighlighter::itemDestroyed(QObject *obj)
{
    foreach (BoundingBox *box, m_boxes) {
        if (box->highlightedObject.data() == obj) {
            freeBoundingBox(box);
            break;
        }
    }
}

void BoundingRectHighlighter::highlightAll()
{
    foreach (BoundingBox *box, m_boxes) {
        if (box && box->highlightedObject.isNull()) {
            // clear all highlights
            clear();
            return;
        }
        QGraphicsObject *item = box->highlightedObject.data();

        QRectF boundingRectInSceneSpace(item->mapToScene(item->boundingRect()).boundingRect());
        QRectF boundingRectInLayerItemSpace = mapRectFromScene(boundingRectInSceneSpace);
        QRectF bboxRect = m_view->adjustToScreenBoundaries(boundingRectInLayerItemSpace);
        QRectF edgeRect = bboxRect;
        edgeRect.adjust(-1, -1, 1, 1);

        box->highlightPolygon->setPolygon(QPolygonF(bboxRect));
        box->highlightPolygonEdge->setPolygon(QPolygonF(edgeRect));
    }
}

void BoundingRectHighlighter::refresh()
{
    if (!m_boxes.isEmpty())
        highlightAll();
}

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

#include "boundingrecthighlighter.h"
#include "qdeclarativeviewinspector.h"
#include "qmlinspectorconstants.h"

#include <QGraphicsPolygonItem>

#include <QTimer>
#include <QObject>
#include <QDebug>

namespace QmlJSDebugger {

BoundingBox::BoundingBox(QGraphicsObject *itemToHighlight, QGraphicsItem *parentItem,
                         QObject *parent)
    : QObject(parent),
      highlightedObject(itemToHighlight),
      highlightPolygon(0),
      highlightPolygonEdge(0)
{
    highlightPolygon = new BoundingBoxPolygonItem(parentItem);
    highlightPolygonEdge = new BoundingBoxPolygonItem(parentItem);

    highlightPolygon->setPen(QPen(QColor(0, 22, 159)));
    highlightPolygonEdge->setPen(QPen(QColor(158, 199, 255)));

    highlightPolygon->setFlag(QGraphicsItem::ItemIsSelectable, false);
    highlightPolygonEdge->setFlag(QGraphicsItem::ItemIsSelectable, false);
}

BoundingBox::~BoundingBox()
{
    highlightedObject.clear();
}

BoundingBoxPolygonItem::BoundingBoxPolygonItem(QGraphicsItem *item) : QGraphicsPolygonItem(item)
{
    QPen pen;
    pen.setColor(QColor(108, 141, 221));
    pen.setWidth(1);
    setPen(pen);
}

int BoundingBoxPolygonItem::type() const
{
    return Constants::EditorItemType;
}

BoundingRectHighlighter::BoundingRectHighlighter(QDeclarativeViewInspector *view) :
    LiveLayerItem(view->declarativeView()->scene()),
    m_view(view)
{
}

BoundingRectHighlighter::~BoundingRectHighlighter()
{

}

void BoundingRectHighlighter::clear()
{
    foreach (BoundingBox *box, m_boxes)
        freeBoundingBox(box);
}

BoundingBox *BoundingRectHighlighter::boxFor(QGraphicsObject *item) const
{
    foreach (BoundingBox *box, m_boxes) {
        if (box->highlightedObject.data() == item)
            return box;
    }
    return 0;
}

void BoundingRectHighlighter::highlight(QList<QGraphicsObject*> items)
{
    if (items.isEmpty())
        return;

    QList<BoundingBox *> newBoxes;
    foreach (QGraphicsObject *itemToHighlight, items) {
        BoundingBox *box = boxFor(itemToHighlight);
        if (!box)
            box = createBoundingBox(itemToHighlight);

        newBoxes << box;
    }
    qSort(newBoxes);

    if (newBoxes != m_boxes) {
        clear();
        m_boxes << newBoxes;
    }

    highlightAll();
}

void BoundingRectHighlighter::highlight(QGraphicsObject* itemToHighlight)
{
    if (!itemToHighlight)
        return;

    BoundingBox *box = boxFor(itemToHighlight);
    if (!box) {
        box = createBoundingBox(itemToHighlight);
        m_boxes << box;
        qSort(m_boxes);
    }

    highlightAll();
}

BoundingBox *BoundingRectHighlighter::createBoundingBox(QGraphicsObject *itemToHighlight)
{
    if (!m_freeBoxes.isEmpty()) {
        BoundingBox *box = m_freeBoxes.last();
        if (box->highlightedObject.isNull()) {
            box->highlightedObject = itemToHighlight;
            box->highlightPolygon->show();
            box->highlightPolygonEdge->show();
            m_freeBoxes.removeLast();
            return box;
        }
    }

    BoundingBox *box = new BoundingBox(itemToHighlight, this, this);

    connect(itemToHighlight, SIGNAL(xChanged()), this, SLOT(refresh()));
    connect(itemToHighlight, SIGNAL(yChanged()), this, SLOT(refresh()));
    connect(itemToHighlight, SIGNAL(widthChanged()), this, SLOT(refresh()));
    connect(itemToHighlight, SIGNAL(heightChanged()), this, SLOT(refresh()));
    connect(itemToHighlight, SIGNAL(rotationChanged()), this, SLOT(refresh()));
    connect(itemToHighlight, SIGNAL(destroyed(QObject*)), this, SLOT(itemDestroyed(QObject*)));

    return box;
}

void BoundingRectHighlighter::removeBoundingBox(BoundingBox *box)
{
    delete box;
    box = 0;
}

void BoundingRectHighlighter::freeBoundingBox(BoundingBox *box)
{
    if (!box->highlightedObject.isNull()) {
        disconnect(box->highlightedObject.data(), SIGNAL(xChanged()), this, SLOT(refresh()));
        disconnect(box->highlightedObject.data(), SIGNAL(yChanged()), this, SLOT(refresh()));
        disconnect(box->highlightedObject.data(), SIGNAL(widthChanged()), this, SLOT(refresh()));
        disconnect(box->highlightedObject.data(), SIGNAL(heightChanged()), this, SLOT(refresh()));
        disconnect(box->highlightedObject.data(), SIGNAL(rotationChanged()), this, SLOT(refresh()));
    }

    box->highlightedObject.clear();
    box->highlightPolygon->hide();
    box->highlightPolygonEdge->hide();
    m_boxes.removeOne(box);
    m_freeBoxes << box;
}

void BoundingRectHighlighter::itemDestroyed(QObject *obj)
{
    foreach (BoundingBox *box, m_boxes) {
        if (box->highlightedObject.data() == obj) {
            freeBoundingBox(box);
            break;
        }
    }
}

void BoundingRectHighlighter::highlightAll()
{
    foreach (BoundingBox *box, m_boxes) {
        Q_ASSERT(box);
        if (box->highlightedObject.isNull()) {
            // clear all highlights
            clear();
            return;
        }
        QGraphicsObject *item = box->highlightedObject.data();

        QRectF boundingRectInSceneSpace(item->mapToScene(item->boundingRect()).boundingRect());
        QRectF boundingRectInLayerItemSpace = mapRectFromScene(boundingRectInSceneSpace);
        QRectF bboxRect = m_view->adjustToScreenBoundaries(boundingRectInLayerItemSpace);
        QRectF edgeRect = bboxRect;
        edgeRect.adjust(-1, -1, 1, 1);

        box->highlightPolygon->setPolygon(QPolygonF(bboxRect));
        box->highlightPolygonEdge->setPolygon(QPolygonF(edgeRect));
    }
}

void BoundingRectHighlighter::refresh()
{
    if (!m_boxes.isEmpty())
        highlightAll();
}

} // namespace QmlJSDebugger
<|endoftext|>