<commit_before>//  Interface to send and receive LoRa messages, exposing a Python wrapper via Swig.
//  We compress JSON messages with MessagePack to reduce transmitted message size.

#include <msgpack.h>
#include <stdio.h>
#include "arduPiLoRa.h"  //  Include the SX1272 and SPI library.
#include "lora_interface.h"
char *decodeChannel(uint32_t code);

int e;
char my_packet[1024];
char message1 [] = "Packet 1, wanting to see if received packet is the same as sent packet";
char message2 [] = "Packet 2, broadcast test";

////
static int setupDone = 0;
static int sendCount = 0;
static int receiveCount = 0;

//  MessagePack buffer and serializer instance.
msgpack_sbuffer* buffer = NULL;
msgpack_packer* pk = NULL;

int getLoRaStatus()
{
  return e;
}

int getLoRaSetupDone()
{
  return setupDone;
}

int getLoRaSendCount()
{
  return sendCount;
}

int getLoRaReceiveCount()
{
  return receiveCount;
}

int setupLoRa(int address, int mode, uint32_t channel, char *power)
{
  //  Init the node with the specified LoRa address (1 to 255).
  if (setupDone > 0)
  {
    printf("setupLoRa ERROR: setupLoRa already called");
    return -1;
  }
  //  Test MessagePack. Create MessagePack buffer and serializer instance.
  buffer = msgpack_sbuffer_new();
  pk = msgpack_packer_new(buffer, msgpack_sbuffer_write);
  for (int j = 0; j < 5; j++)
  {
     //  NB: the buffer needs to be cleared on each iteration.
     msgpack_sbuffer_clear(buffer);

     //  Serializes ["Hello", "MessagePack"].
     msgpack_pack_array(pk, 3);
     msgpack_pack_bin(pk, 5);
     msgpack_pack_bin_body(pk, "Hello", 5);
     msgpack_pack_bin(pk, 11);
     msgpack_pack_bin_body(pk, "MessagePack", 11);
     msgpack_pack_int(pk, j);

     //  Deserializes it.
     msgpack_unpacked msg;
     msgpack_unpacked_init(&msg);
     bool success = msgpack_unpack_next(&msg, buffer->data, buffer->size, NULL);

     //  Prints the deserialized object.
     msgpack_object obj = msg.data;
     msgpack_object_print(stdout, obj);  // => ["Hello", "MessagePack"]
     puts("");
  }
  //  Cleaning.
  //msgpack_sbuffer_free(buffer);
  //msgpack_packer_free(pk);

  // Print a start message
  printf("setupLoRa: SX1272 module and Raspberry Pi: send packets without ACK\n");

  // Power ON the module
  e = sx1272.ON();
  printf("setupLoRa: Setting power ON: state %d\n", e);

  // Set transmission mode
  e = sx1272.setMode(mode);
  printf("setupLoRa: Setting Mode %d: state %d\n", mode, e);

  // Set header
  e = sx1272.setHeaderON();
  printf("setupLoRa: Setting Header ON: state %d\n", e);

  // Select frequency channel
  e = sx1272.setChannel(channel);
  printf("setupLoRa: Setting Channel %s: state %d\n", decodeChannel(channel), e);

  // Set CRC
  e = sx1272.setCRC_ON();
  printf("setupLoRa: Setting CRC ON: state %d\n", e);

  // Select output power (Max, High or Low)
  e = sx1272.setPower(*power);
  printf("setupLoRa: Setting Power %s: state %d\n", power, e);

  // Set the node address
  e = sx1272.setNodeAddress(address);
  printf("setupLoRa: Setting Node address %d: state %d\n", address, e);

  // Print a success message
  printf("setupLoRa: SX1272 successfully configured\n\n");

  ////
  setupDone++;
  printf("setupLoRa: done %d, %d, %d\n", setupDone, sendCount, receiveCount);
  return e;
}

int getLoRaSNR(void)
{
    //  Gets the SNR value in LoRa mode.
    return sx1272.getSNR();
}

int getLoRaRSSI(void)
{
    //  Gets the current value of RSSI from the channel.
    return sx1272.getRSSI();
}

int getLoRaRSSIpacket(void)
{
    //  Gets the RSSI of the last packet received in LoRa mode.
    return sx1272.getRSSIpacket();
}

int sendLoRaMessage(int address, char *msg)
{
	  // Send message and print the result
    printf("sendLoRaMessage: address=%d, msg=%s\n", address, msg);
    if (setupDone == 0)
    {
      printf("sendLoRaMessage ERROR: setupLoRa not called");
      return -1;
    }
    //  TODO: If message starts with "{", assume it's in JSON format and compress with MessagePack.
    e = sx1272.sendPacketTimeout(address, msg);
    printf("sendLoRaMessage: state=%d\n",e);

    ////
    sendCount++;
    printf("sendLoRaMessage: done %d, %d, %d\n", setupDone, sendCount, receiveCount);
    return e;
}

char *receiveLoRaMessage(int timeout)
{
  // Receive message. Wait till timeout, in milliseconds.
  printf("receiveLoRaMessage: start\n");
  if (setupDone == 0)
  {
    printf("sendLoRaMessage ERROR: setupLoRa not called");
    return (char *) "ERROR";
  }
  e = sx1272.receivePacketTimeout(timeout);
  if ( e == 0 )
  {
    printf("receiveLoRaMessage: state=%d, length=%d\n", e, sx1272.packet_received.length);
    unsigned int length = sx1272.packet_received.length;
    if (length > sizeof(my_packet) - 1) length = sizeof(my_packet) - 1;
    unsigned int i;
    for (i = 0; i < sx1272.packet_received.length; i++)
    {
      my_packet[i] = (char)sx1272.packet_received.data[i];
    }
    my_packet[i] = 0;  //  Terminate the string.
    printf("receiveLoRaMessage: message=%s\n", my_packet);
  }
  else {
    printf("receiveLoRaMessage: state=%d\n",e);
  }

  ////
  //  TODO: If message does not start with "{", assume it's in MessagePack format and uncompress to JSON format.
  receiveCount++;
  printf("receiveLoRaMessage: done %d, %d, %d\n", setupDone, sendCount, receiveCount);
  return my_packet;
}

int main() {
    const int address = 2;
    const int mode = 4;
    unsigned int channel = LORA_CH_10_868;
    char *power = (char *) "H";
    int setupStatus = setupLoRa(address, mode, channel, power);
    printf("Setup status %d\n",setupStatus);
    delay(1000);
	while(1) {
        // Send message1 to address 8 and print the result
        e = sendLoRaMessage(8, message1);
        printf("Packet sent, state %d\n",e);
        delay(4000);

        // Send message2 broadcast and print the result
        e = sendLoRaMessage(0, message2);
        printf("Packet sent, state %d\n",e);

        //  Receive a message.
        const int timeout = 10000;
        char *msg = receiveLoRaMessage(timeout);
        printf("Received message: %s\n", msg);

        //  Show the receive status.
        int status = getLoRaStatus();
        int setup_done = getLoRaSetupDone();
        int send_count = getLoRaSendCount();
        int receive_count = getLoRaReceiveCount();
        printf("Receive status: %d, %d, %d, %d\n", status, setup_done, send_count, receive_count);

        //  Show the SNR and RSSI.
        int snr = getLoRaSNR();
        int rssi = getLoRaRSSI();
        int rssi_packet = getLoRaRSSIpacket();
        printf("SNR, RSSI, RSSI packet: %d, %d, %d\n", snr, rssi, rssi_packet);
	}
	return (0);
}

char *decodeChannel(uint32_t code) {
    //  Given the channel code, return the name of the channel.
    switch(code) {
        case CH_10_868: return (char *) "LORA_CH_10_868";
        case CH_11_868: return (char *) "LORA_CH_11_868";
        case CH_12_868: return (char *) "LORA_CH_12_868";
        case CH_13_868: return (char *) "LORA_CH_13_868";
        case CH_14_868: return (char *) "LORA_CH_14_868";
        case CH_15_868: return (char *) "LORA_CH_15_868";
        case CH_16_868: return (char *) "LORA_CH_16_868";
        case CH_17_868: return (char *) "LORA_CH_17_868";
        case CH_00_900: return (char *) "LORA_CH_00_900";
        case CH_01_900: return (char *) "LORA_CH_01_900";
        case CH_02_900: return (char *) "LORA_CH_02_900";
        case CH_03_900: return (char *) "LORA_CH_03_900";
        case CH_04_900: return (char *) "LORA_CH_04_900";
        case CH_05_900: return (char *) "LORA_CH_05_900";
        case CH_06_900: return (char *) "LORA_CH_06_900";
        case CH_07_900: return (char *) "LORA_CH_07_900";
        case CH_08_900: return (char *) "LORA_CH_08_900";
        case CH_09_900: return (char *) "LORA_CH_09_900";
        case CH_10_900: return (char *) "LORA_CH_10_900";
        case CH_11_900: return (char *) "LORA_CH_11_900";
        case CH_12_900: return (char *) "LORA_CH_12_900";
    }
    return (char *) "Unknown";
}

//FREQUENCY CHANNELS:
uint32_t LORA_CH_10_868 = CH_10_868; //  0xD84CCC; // channel 10, central freq = 865.20MHz
uint32_t LORA_CH_11_868 = CH_11_868; //  0xD86000; // channel 11, central freq = 865.50MHz
uint32_t LORA_CH_12_868 = CH_12_868; //  0xD87333; // channel 12, central freq = 865.80MHz
uint32_t LORA_CH_13_868 = CH_13_868; //  0xD88666; // channel 13, central freq = 866.10MHz
uint32_t LORA_CH_14_868 = CH_14_868; //  0xD89999; // channel 14, central freq = 866.40MHz
uint32_t LORA_CH_15_868 = CH_15_868; //  0xD8ACCC; // channel 15, central freq = 866.70MHz
uint32_t LORA_CH_16_868 = CH_16_868; //  0xD8C000; // channel 16, central freq = 867.00MHz
uint32_t LORA_CH_17_868 = CH_17_868; //  0xD90000; // channel 16, central freq = 868.00MHz
uint32_t LORA_CH_00_900 = CH_00_900; //  0xE1C51E; // channel 00, central freq = 903.08MHz
uint32_t LORA_CH_01_900 = CH_01_900; //  0xE24F5C; // channel 01, central freq = 905.24MHz
uint32_t LORA_CH_02_900 = CH_02_900; //  0xE2D999; // channel 02, central freq = 907.40MHz
uint32_t LORA_CH_03_900 = CH_03_900; //  0xE363D7; // channel 03, central freq = 909.56MHz
uint32_t LORA_CH_04_900 = CH_04_900; //  0xE3EE14; // channel 04, central freq = 911.72MHz
uint32_t LORA_CH_05_900 = CH_05_900; //  0xE47851; // channel 05, central freq = 913.88MHz
uint32_t LORA_CH_06_900 = CH_06_900; //  0xE5028F; // channel 06, central freq = 916.04MHz
uint32_t LORA_CH_07_900 = CH_07_900; //  0xE58CCC; // channel 07, central freq = 918.20MHz
uint32_t LORA_CH_08_900 = CH_08_900; //  0xE6170A; // channel 08, central freq = 920.36MHz
uint32_t LORA_CH_09_900 = CH_09_900; //  0xE6A147; // channel 09, central freq = 922.52MHz
uint32_t LORA_CH_10_900 = CH_10_900; //  0xE72B85; // channel 10, central freq = 924.68MHz
uint32_t LORA_CH_11_900 = CH_11_900; //  0xE7B5C2; // channel 11, central freq = 926.84MHz
uint32_t LORA_CH_12_900 = CH_12_900; //  0xE4C000; // default channel 915MHz, the module is configured with it
<commit_msg>Blank out the message before reading<commit_after>//  Interface to send and receive LoRa messages, exposing a Python wrapper via Swig.
//  We compress JSON messages with MessagePack to reduce transmitted message size.

#include <msgpack.h>
#include <stdio.h>
#include "arduPiLoRa.h"  //  Include the SX1272 and SPI library.
#include "lora_interface.h"
char *decodeChannel(uint32_t code);

int e;
char my_packet[1024];
char message1 [] = "Packet 1, wanting to see if received packet is the same as sent packet";
char message2 [] = "Packet 2, broadcast test";

////
static int setupDone = 0;
static int sendCount = 0;
static int receiveCount = 0;

//  MessagePack buffer and serializer instance.
msgpack_sbuffer* buffer = NULL;
msgpack_packer* pk = NULL;

int getLoRaStatus()
{
  return e;
}

int getLoRaSetupDone()
{
  return setupDone;
}

int getLoRaSendCount()
{
  return sendCount;
}

int getLoRaReceiveCount()
{
  return receiveCount;
}

int setupLoRa(int address, int mode, uint32_t channel, char *power)
{
  //  Init the node with the specified LoRa address (1 to 255).
  if (setupDone > 0)
  {
    printf("setupLoRa ERROR: setupLoRa already called");
    return -1;
  }
  //  Test MessagePack. Create MessagePack buffer and serializer instance.
  buffer = msgpack_sbuffer_new();
  pk = msgpack_packer_new(buffer, msgpack_sbuffer_write);
  for (int j = 0; j < 5; j++)
  {
     //  NB: the buffer needs to be cleared on each iteration.
     msgpack_sbuffer_clear(buffer);

     //  Serializes ["Hello", "MessagePack"].
     msgpack_pack_array(pk, 3);
     msgpack_pack_bin(pk, 5);
     msgpack_pack_bin_body(pk, "Hello", 5);
     msgpack_pack_bin(pk, 11);
     msgpack_pack_bin_body(pk, "MessagePack", 11);
     msgpack_pack_int(pk, j);

     //  Deserializes it.
     msgpack_unpacked msg;
     msgpack_unpacked_init(&msg);
     bool success = msgpack_unpack_next(&msg, buffer->data, buffer->size, NULL);

     //  Prints the deserialized object.
     msgpack_object obj = msg.data;
     msgpack_object_print(stdout, obj);  // => ["Hello", "MessagePack"]
     puts("");
  }
  //  Cleaning.
  //msgpack_sbuffer_free(buffer);
  //msgpack_packer_free(pk);

  // Print a start message
  printf("setupLoRa: SX1272 module and Raspberry Pi: send packets without ACK\n");

  // Power ON the module
  e = sx1272.ON();
  printf("setupLoRa: Setting power ON: state %d\n", e);

  // Set transmission mode
  e = sx1272.setMode(mode);
  printf("setupLoRa: Setting Mode %d: state %d\n", mode, e);

  // Set header
  e = sx1272.setHeaderON();
  printf("setupLoRa: Setting Header ON: state %d\n", e);

  // Select frequency channel
  e = sx1272.setChannel(channel);
  printf("setupLoRa: Setting Channel %s: state %d\n", decodeChannel(channel), e);

  // Set CRC
  e = sx1272.setCRC_ON();
  printf("setupLoRa: Setting CRC ON: state %d\n", e);

  // Select output power (Max, High or Low)
  e = sx1272.setPower(*power);
  printf("setupLoRa: Setting Power %s: state %d\n", power, e);

  // Set the node address
  e = sx1272.setNodeAddress(address);
  printf("setupLoRa: Setting Node address %d: state %d\n", address, e);

  // Print a success message
  printf("setupLoRa: SX1272 successfully configured\n\n");

  ////
  setupDone++;
  printf("setupLoRa: done %d, %d, %d\n", setupDone, sendCount, receiveCount);
  return e;
}

int getLoRaSNR(void)
{
    //  Gets the SNR value in LoRa mode.
    return sx1272.getSNR();
}

int getLoRaRSSI(void)
{
    //  Gets the current value of RSSI from the channel.
    return sx1272.getRSSI();
}

int getLoRaRSSIpacket(void)
{
    //  Gets the RSSI of the last packet received in LoRa mode.
    return sx1272.getRSSIpacket();
}

int sendLoRaMessage(int address, char *msg)
{
	  // Send message and print the result
    printf("sendLoRaMessage: address=%d, msg=%s\n", address, msg);
    if (setupDone == 0)
    {
      printf("sendLoRaMessage ERROR: setupLoRa not called");
      return -1;
    }
    //  TODO: If message starts with "{", assume it's in JSON format and compress with MessagePack.
    e = sx1272.sendPacketTimeout(address, msg);
    printf("sendLoRaMessage: state=%d\n",e);

    ////
    sendCount++;
    printf("sendLoRaMessage: done %d, %d, %d\n", setupDone, sendCount, receiveCount);
    return e;
}

char *receiveLoRaMessage(int timeout)
{
  // Receive message. Wait till timeout, in milliseconds.
  printf("receiveLoRaMessage: start\n");
  if (setupDone == 0)
  {
    printf("sendLoRaMessage ERROR: setupLoRa not called");
    return (char *) "ERROR";
  }
  my_packet[0] = 0;  //  Empty the string.
  e = sx1272.receivePacketTimeout(timeout);
  if ( e == 0 )
  {
    printf("receiveLoRaMessage: state=%d, length=%d\n", e, sx1272.packet_received.length);
    unsigned int length = sx1272.packet_received.length;
    if (length > sizeof(my_packet) - 1) length = sizeof(my_packet) - 1;
    unsigned int i;
    for (i = 0; i < sx1272.packet_received.length; i++)
    {
      my_packet[i] = (char)sx1272.packet_received.data[i];
    }
    my_packet[i] = 0;  //  Terminate the string.
    printf("receiveLoRaMessage: message=%s\n", my_packet);
  }
  else {
    printf("receiveLoRaMessage: state=%d\n",e);
  }

  ////
  //  TODO: If message does not start with "{", assume it's in MessagePack format and uncompress to JSON format.
  receiveCount++;
  printf("receiveLoRaMessage: done %d, %d, %d\n", setupDone, sendCount, receiveCount);
  return my_packet;
}

int main() {
    const int address = 2;
    const int mode = 4;
    unsigned int channel = LORA_CH_10_868;
    char *power = (char *) "H";
    int setupStatus = setupLoRa(address, mode, channel, power);
    printf("Setup status %d\n",setupStatus);
    delay(1000);
	while(1) {
        // Send message1 to address 8 and print the result
        e = sendLoRaMessage(8, message1);
        printf("Packet sent, state %d\n",e);
        delay(4000);

        // Send message2 broadcast and print the result
        e = sendLoRaMessage(0, message2);
        printf("Packet sent, state %d\n",e);

        //  Receive a message.
        const int timeout = 10000;
        char *msg = receiveLoRaMessage(timeout);
        printf("Received message: %s\n", msg);

        //  Show the receive status.
        int status = getLoRaStatus();
        int setup_done = getLoRaSetupDone();
        int send_count = getLoRaSendCount();
        int receive_count = getLoRaReceiveCount();
        printf("Receive status: %d, %d, %d, %d\n", status, setup_done, send_count, receive_count);

        //  Show the SNR and RSSI.
        int snr = getLoRaSNR();
        int rssi = getLoRaRSSI();
        int rssi_packet = getLoRaRSSIpacket();
        printf("SNR, RSSI, RSSI packet: %d, %d, %d\n", snr, rssi, rssi_packet);
	}
	return (0);
}

char *decodeChannel(uint32_t code) {
    //  Given the channel code, return the name of the channel.
    switch(code) {
        case CH_10_868: return (char *) "LORA_CH_10_868";
        case CH_11_868: return (char *) "LORA_CH_11_868";
        case CH_12_868: return (char *) "LORA_CH_12_868";
        case CH_13_868: return (char *) "LORA_CH_13_868";
        case CH_14_868: return (char *) "LORA_CH_14_868";
        case CH_15_868: return (char *) "LORA_CH_15_868";
        case CH_16_868: return (char *) "LORA_CH_16_868";
        case CH_17_868: return (char *) "LORA_CH_17_868";
        case CH_00_900: return (char *) "LORA_CH_00_900";
        case CH_01_900: return (char *) "LORA_CH_01_900";
        case CH_02_900: return (char *) "LORA_CH_02_900";
        case CH_03_900: return (char *) "LORA_CH_03_900";
        case CH_04_900: return (char *) "LORA_CH_04_900";
        case CH_05_900: return (char *) "LORA_CH_05_900";
        case CH_06_900: return (char *) "LORA_CH_06_900";
        case CH_07_900: return (char *) "LORA_CH_07_900";
        case CH_08_900: return (char *) "LORA_CH_08_900";
        case CH_09_900: return (char *) "LORA_CH_09_900";
        case CH_10_900: return (char *) "LORA_CH_10_900";
        case CH_11_900: return (char *) "LORA_CH_11_900";
        case CH_12_900: return (char *) "LORA_CH_12_900";
    }
    return (char *) "Unknown";
}

//FREQUENCY CHANNELS:
uint32_t LORA_CH_10_868 = CH_10_868; //  0xD84CCC; // channel 10, central freq = 865.20MHz
uint32_t LORA_CH_11_868 = CH_11_868; //  0xD86000; // channel 11, central freq = 865.50MHz
uint32_t LORA_CH_12_868 = CH_12_868; //  0xD87333; // channel 12, central freq = 865.80MHz
uint32_t LORA_CH_13_868 = CH_13_868; //  0xD88666; // channel 13, central freq = 866.10MHz
uint32_t LORA_CH_14_868 = CH_14_868; //  0xD89999; // channel 14, central freq = 866.40MHz
uint32_t LORA_CH_15_868 = CH_15_868; //  0xD8ACCC; // channel 15, central freq = 866.70MHz
uint32_t LORA_CH_16_868 = CH_16_868; //  0xD8C000; // channel 16, central freq = 867.00MHz
uint32_t LORA_CH_17_868 = CH_17_868; //  0xD90000; // channel 16, central freq = 868.00MHz
uint32_t LORA_CH_00_900 = CH_00_900; //  0xE1C51E; // channel 00, central freq = 903.08MHz
uint32_t LORA_CH_01_900 = CH_01_900; //  0xE24F5C; // channel 01, central freq = 905.24MHz
uint32_t LORA_CH_02_900 = CH_02_900; //  0xE2D999; // channel 02, central freq = 907.40MHz
uint32_t LORA_CH_03_900 = CH_03_900; //  0xE363D7; // channel 03, central freq = 909.56MHz
uint32_t LORA_CH_04_900 = CH_04_900; //  0xE3EE14; // channel 04, central freq = 911.72MHz
uint32_t LORA_CH_05_900 = CH_05_900; //  0xE47851; // channel 05, central freq = 913.88MHz
uint32_t LORA_CH_06_900 = CH_06_900; //  0xE5028F; // channel 06, central freq = 916.04MHz
uint32_t LORA_CH_07_900 = CH_07_900; //  0xE58CCC; // channel 07, central freq = 918.20MHz
uint32_t LORA_CH_08_900 = CH_08_900; //  0xE6170A; // channel 08, central freq = 920.36MHz
uint32_t LORA_CH_09_900 = CH_09_900; //  0xE6A147; // channel 09, central freq = 922.52MHz
uint32_t LORA_CH_10_900 = CH_10_900; //  0xE72B85; // channel 10, central freq = 924.68MHz
uint32_t LORA_CH_11_900 = CH_11_900; //  0xE7B5C2; // channel 11, central freq = 926.84MHz
uint32_t LORA_CH_12_900 = CH_12_900; //  0xE4C000; // default channel 915MHz, the module is configured with it
<|endoftext|>


<commit_before>// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*-

/*
 * Copyright (C) 2010-2011 ZXing authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <zxing/common/StringUtils.h>
#include <zxing/DecodeHints.h>

using namespace std;
using namespace zxing;
using namespace zxing::common;

// N.B.: these are the iconv strings for at least some versions of iconv

char const* const StringUtils::PLATFORM_DEFAULT_ENCODING = "UTF-8";
char const* const StringUtils::ASCII = "ASCII";
char const* const StringUtils::SHIFT_JIS = "SHIFT_JIS";
char const* const StringUtils::GB2312 = "GBK";
char const* const StringUtils::EUC_JP = "EUC-JP";
char const* const StringUtils::UTF8 = "UTF-8";
char const* const StringUtils::ISO88591 = "ISO8859-1";
const bool StringUtils::ASSUME_SHIFT_JIS = false;

string
StringUtils::guessEncoding(unsigned char* bytes, int length, Hashtable const& hints) {
  Hashtable::const_iterator i = hints.find(DecodeHints::CHARACTER_SET);
  if (i != hints.end()) {
    return i->second;
  }
  // Does it start with the UTF-8 byte order mark? then guess it's UTF-8
  if (length > 3 &&
      bytes[0] == (unsigned char) 0xEF &&
      bytes[1] == (unsigned char) 0xBB &&
      bytes[2] == (unsigned char) 0xBF) {
    return UTF8;
  }
  // For now, merely tries to distinguish ISO-8859-1, UTF-8 and Shift_JIS,
  // which should be by far the most common encodings. ISO-8859-1
  // should not have bytes in the 0x80 - 0x9F range, while Shift_JIS
  // uses this as a first byte of a two-byte character. If we see this
  // followed by a valid second byte in Shift_JIS, assume it is Shift_JIS.
  // If we see something else in that second byte, we'll make the risky guess
  // that it's UTF-8.
  bool canBeISO88591 = true;
  bool canBeShiftJIS = true;
  bool canBeUTF8 = true;
  int utf8BytesLeft = 0;
  int maybeDoubleByteCount = 0;
  int maybeSingleByteKatakanaCount = 0;
  bool sawLatin1Supplement = false;
  bool sawUTF8Start = false;
  bool lastWasPossibleDoubleByteStart = false;

  for (int i = 0;
       i < length && (canBeISO88591 || canBeShiftJIS || canBeUTF8);
       i++) {

    int value = bytes[i] & 0xFF;

    // UTF-8 stuff
    if (value >= 0x80 && value <= 0xBF) {
      if (utf8BytesLeft > 0) {
        utf8BytesLeft--;
      }
    } else {
      if (utf8BytesLeft > 0) {
        canBeUTF8 = false;
      }
      if (value >= 0xC0 && value <= 0xFD) {
        sawUTF8Start = true;
        int valueCopy = value;
        while ((valueCopy & 0x40) != 0) {
          utf8BytesLeft++;
          valueCopy <<= 1;
        }
      }
    }

    // ISO-8859-1 stuff

    if ((value == 0xC2 || value == 0xC3) && i < length - 1) {
      // This is really a poor hack. The slightly more exotic characters people might want to put in
      // a QR Code, by which I mean the Latin-1 supplement characters (e.g. u-umlaut) have encodings
      // that start with 0xC2 followed by [0xA0,0xBF], or start with 0xC3 followed by [0x80,0xBF].
      int nextValue = bytes[i + 1] & 0xFF;
      if (nextValue <= 0xBF &&
          ((value == 0xC2 && nextValue >= 0xA0) || (value == 0xC3 && nextValue >= 0x80))) {
        sawLatin1Supplement = true;
      }
    }
    if (value >= 0x7F && value <= 0x9F) {
      canBeISO88591 = false;
    }

    // Shift_JIS stuff

    if (value >= 0xA1 && value <= 0xDF) {
      // count the number of characters that might be a Shift_JIS single-byte Katakana character
      if (!lastWasPossibleDoubleByteStart) {
        maybeSingleByteKatakanaCount++;
      }
    }
    if (!lastWasPossibleDoubleByteStart &&
        ((value >= 0xF0 && value <= 0xFF) || value == 0x80 || value == 0xA0)) {
      canBeShiftJIS = false;
    }
    if ((value >= 0x81 && value <= 0x9F) || (value >= 0xE0 && value <= 0xEF)) {
      // These start double-byte characters in Shift_JIS. Let's see if it's followed by a valid
      // second byte.
      if (lastWasPossibleDoubleByteStart) {
        // If we just checked this and the last byte for being a valid double-byte
        // char, don't check starting on this byte. If this and the last byte
        // formed a valid pair, then this shouldn't be checked to see if it starts
        // a double byte pair of course.
        lastWasPossibleDoubleByteStart = false;
      } else {
        // ... otherwise do check to see if this plus the next byte form a valid
        // double byte pair encoding a character.
        lastWasPossibleDoubleByteStart = true;
        if (i >= length - 1) {
          canBeShiftJIS = false;
        } else {
          int nextValue = bytes[i + 1] & 0xFF;
          if (nextValue < 0x40 || nextValue > 0xFC) {
            canBeShiftJIS = false;
          } else {
            maybeDoubleByteCount++;
          }
          // There is some conflicting information out there about which bytes can follow which in
          // double-byte Shift_JIS characters. The rule above seems to be the one that matches practice.
        }
      }
    } else {
      lastWasPossibleDoubleByteStart = false;
    }
  }
  if (utf8BytesLeft > 0) {
    canBeUTF8 = false;
  }

  // Easy -- if assuming Shift_JIS and no evidence it can't be, done
  if (canBeShiftJIS && ASSUME_SHIFT_JIS) {
    return SHIFT_JIS;
  }
  if (canBeUTF8 && sawUTF8Start) {
    return UTF8;
  }
  // Distinguishing Shift_JIS and ISO-8859-1 can be a little tough. The crude heuristic is:
  // - If we saw
  //   - at least 3 bytes that starts a double-byte value (bytes that are rare in ISO-8859-1), or
  //   - over 5% of bytes could be single-byte Katakana (also rare in ISO-8859-1),
  // - and, saw no sequences that are invalid in Shift_JIS, then we conclude Shift_JIS
  if (canBeShiftJIS && (maybeDoubleByteCount >= 3 || 20 * maybeSingleByteKatakanaCount > length)) {
    return SHIFT_JIS;
  }
  // Otherwise, we default to ISO-8859-1 unless we know it can't be
  if (!sawLatin1Supplement && canBeISO88591) {
    return ISO88591;
  }
  // Otherwise, we take a wild guess with platform encoding
  return PLATFORM_DEFAULT_ENCODING;
}
<commit_msg>C++ port of r2157<commit_after>// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*-

/*
 * Copyright (C) 2010-2011 ZXing authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <zxing/common/StringUtils.h>
#include <zxing/DecodeHints.h>

using namespace std;
using namespace zxing;
using namespace zxing::common;

// N.B.: these are the iconv strings for at least some versions of iconv

char const* const StringUtils::PLATFORM_DEFAULT_ENCODING = "UTF-8";
char const* const StringUtils::ASCII = "ASCII";
char const* const StringUtils::SHIFT_JIS = "SHIFT_JIS";
char const* const StringUtils::GB2312 = "GBK";
char const* const StringUtils::EUC_JP = "EUC-JP";
char const* const StringUtils::UTF8 = "UTF-8";
char const* const StringUtils::ISO88591 = "ISO8859-1";
const bool StringUtils::ASSUME_SHIFT_JIS = false;

string
StringUtils::guessEncoding(unsigned char* bytes, int length,
                           Hashtable const& hints) {
  Hashtable::const_iterator i = hints.find(DecodeHints::CHARACTER_SET);
  if (i != hints.end()) {
    return i->second;
  }
  typedef bool boolean;
  // For now, merely tries to distinguish ISO-8859-1, UTF-8 and Shift_JIS,
  // which should be by far the most common encodings.
  boolean canBeISO88591 = true;
  boolean canBeShiftJIS = true;
  boolean canBeUTF8 = true;
  int utf8BytesLeft = 0;
  //int utf8LowChars = 0;
  int utf2BytesChars = 0;
  int utf3BytesChars = 0;
  int utf4BytesChars = 0;
  int sjisBytesLeft = 0;
  //int sjisLowChars = 0;
  int sjisKatakanaChars = 0;
  //int sjisDoubleBytesChars = 0;
  int sjisCurKatakanaWordLength = 0;
  int sjisCurDoubleBytesWordLength = 0;
  int sjisMaxKatakanaWordLength = 0;
  int sjisMaxDoubleBytesWordLength = 0;
  //int isoLowChars = 0;
  //int isoHighChars = 0;
  int isoHighOther = 0;

  typedef unsigned char byte;
  boolean utf8bom = length > 3 &&
    bytes[0] == (byte) 0xEF &&
    bytes[1] == (byte) 0xBB &&
    bytes[2] == (byte) 0xBF;

  for (int i = 0;
       i < length && (canBeISO88591 || canBeShiftJIS || canBeUTF8);
       i++) {

    int value = bytes[i] & 0xFF;

    // UTF-8 stuff
    if (canBeUTF8) {
      if (utf8BytesLeft > 0) {
        if ((value & 0x80) == 0) {
          canBeUTF8 = false;
        } else {
          utf8BytesLeft--;
        }
      } else if ((value & 0x80) != 0) {
        if ((value & 0x40) == 0) {
          canBeUTF8 = false;
        } else {
          utf8BytesLeft++;
          if ((value & 0x20) == 0) {
            utf2BytesChars++;
          } else {
            utf8BytesLeft++;
            if ((value & 0x10) == 0) {
              utf3BytesChars++;
            } else {
              utf8BytesLeft++;
              if ((value & 0x08) == 0) {
                utf4BytesChars++;
              } else {
                canBeUTF8 = false;
              }
            }
          }
        }
      } //else {
      //utf8LowChars++;
      //}
    }

    // ISO-8859-1 stuff
    if (canBeISO88591) {
      if (value > 0x7F && value < 0xA0) {
        canBeISO88591 = false;
      } else if (value > 0x9F) {
        if (value < 0xC0 || value == 0xD7 || value == 0xF7) {
          isoHighOther++;
        } //else {
        //isoHighChars++;
        //}
      } //else {
      //isoLowChars++;
      //}
    }

    // Shift_JIS stuff
    if (canBeShiftJIS) {
      if (sjisBytesLeft > 0) {
        if (value < 0x40 || value == 0x7F || value > 0xFC) {
          canBeShiftJIS = false;
        } else {
          sjisBytesLeft--;
        }
      } else if (value == 0x80 || value == 0xA0 || value > 0xEF) {
        canBeShiftJIS = false;
      } else if (value > 0xA0 && value < 0xE0) {
        sjisKatakanaChars++;
        sjisCurDoubleBytesWordLength = 0;
        sjisCurKatakanaWordLength++;
        if (sjisCurKatakanaWordLength > sjisMaxKatakanaWordLength) {
          sjisMaxKatakanaWordLength = sjisCurKatakanaWordLength;
        }
      } else if (value > 0x7F) {
        sjisBytesLeft++;
        //sjisDoubleBytesChars++;
        sjisCurKatakanaWordLength = 0;
        sjisCurDoubleBytesWordLength++;
        if (sjisCurDoubleBytesWordLength > sjisMaxDoubleBytesWordLength) {
          sjisMaxDoubleBytesWordLength = sjisCurDoubleBytesWordLength;
        }
      } else {
        //sjisLowChars++;
        sjisCurKatakanaWordLength = 0;
        sjisCurDoubleBytesWordLength = 0;
      }
    }
  }

  if (canBeUTF8 && utf8BytesLeft > 0) {
    canBeUTF8 = false;
  }
  if (canBeShiftJIS && sjisBytesLeft > 0) {
    canBeShiftJIS = false;
  }

  // Easy -- if there is BOM or at least 1 valid not-single byte character (and no evidence it can't be UTF-8), done
  if (canBeUTF8 && (utf8bom || utf2BytesChars + utf3BytesChars + utf4BytesChars > 0)) {
    return UTF8;
  }
  // Easy -- if assuming Shift_JIS or at least 3 valid consecutive not-ascii characters (and no evidence it can't be), done
  if (canBeShiftJIS && (ASSUME_SHIFT_JIS || sjisMaxKatakanaWordLength >= 3 || sjisMaxDoubleBytesWordLength >= 3)) {
    return SHIFT_JIS;
  }
  // Distinguishing Shift_JIS and ISO-8859-1 can be a little tough for short words. The crude heuristic is:
  // - If we saw
  //   - only two consecutive katakana chars in the whole text, or
  //   - at least 10% of bytes that could be "upper" not-alphanumeric Latin1,
  // - then we conclude Shift_JIS, else ISO-8859-1
  if (canBeISO88591 && canBeShiftJIS) {
    return (sjisMaxKatakanaWordLength == 2 && sjisKatakanaChars == 2) || isoHighOther * 10 >= length
      ? SHIFT_JIS : ISO88591;
  }

  // Otherwise, try in order ISO-8859-1, Shift JIS, UTF-8 and fall back to default platform encoding
  if (canBeISO88591) {
    return ISO88591;
  }
  if (canBeShiftJIS) {
    return SHIFT_JIS;
  }
  if (canBeUTF8) {
    return UTF8;
  }
  // Otherwise, we take a wild guess with platform encoding
  return PLATFORM_DEFAULT_ENCODING;
}
<|endoftext|>


<commit_before><commit_msg>Fix syntax accessing enum scoped to class, to fix GCC builds. Review URL: http://codereview.chromium.org/183007<commit_after><|endoftext|>


<commit_before>// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2012 Chen-Pang He <jdh8@ms63.hinet.net>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.

#include "matrix_functions.h"

// for complex matrices, any matrix is fine
template<typename MatrixType, int IsComplex = NumTraits<typename internal::traits<MatrixType>::Scalar>::IsComplex>
struct generateSingularMatrix
{
  static void run(MatrixType& result, typename MatrixType::Index size)
  {
    result = MatrixType::Random(size, size);
    result.col(0).fill(0);
  }
};

// for real matrices, make sure none of the eigenvalues are negative
template<typename MatrixType>
struct generateSingularMatrix<MatrixType,0>
{
  static void run(MatrixType& result, typename MatrixType::Index size)
  {
    MatrixType mat = MatrixType::Random(size, size);
    mat.col(0).fill(0);
    ComplexSchur<MatrixType> schur(mat);
    typename ComplexSchur<MatrixType>::ComplexMatrixType T = schur.matrixT();

    for (typename MatrixType::Index i = 0; i < size; ++i) {
      if (T.coeff(i,i).imag() == 0 && T.coeff(i,i).real() < 0)
	T.coeffRef(i,i) = -T.coeff(i,i);
    }
    result = (schur.matrixU() * (T.template triangularView<Upper>() * schur.matrixU().adjoint())).real();
  }
};

template<typename T>
void test2dRotation(double tol)
{
  Matrix<T,2,2> A, B, C;
  T angle, c, s;

  A << 0, 1, -1, 0;
  MatrixPower<Matrix<T,2,2> > Apow(A);

  for (int i=0; i<=20; ++i) {
    angle = pow(10, (i-10) / 5.);
    c = std::cos(angle);
    s = std::sin(angle);
    B << c, s, -s, c;

    C = Apow(std::ldexp(angle,1) / M_PI);
    std::cout << "test2dRotation: i = " << i << "   error powerm = " << relerr(C,B) << '\n';
    VERIFY(C.isApprox(B, tol));
  }
}

template<typename T>
void test2dHyperbolicRotation(double tol)
{
  Matrix<std::complex<T>,2,2> A, B, C;
  T angle, ch = std::cosh((T)1);
  std::complex<T> ish(0, std::sinh((T)1));

  A << ch, ish, -ish, ch;
  MatrixPower<Matrix<std::complex<T>,2,2> > Apow(A);

  for (int i=0; i<=20; ++i) {
    angle = std::ldexp(static_cast<T>(i-10), -1);
    ch = std::cosh(angle);
    ish = std::complex<T>(0, std::sinh(angle));
    B << ch, ish, -ish, ch;

    C = Apow(angle);
    std::cout << "test2dHyperbolicRotation: i = " << i << "   error powerm = " << relerr(C,B) << '\n';
    VERIFY(C.isApprox(B, tol));
  }
}

template<typename MatrixType>
void testGeneral(const MatrixType& m, double tol)
{
  typedef typename MatrixType::RealScalar RealScalar;
  MatrixType m1, m2, m3, m4, m5;
  RealScalar x, y;

  for (int i=0; i < g_repeat; ++i) {
    generateTestMatrix<MatrixType>::run(m1, m.rows());
    MatrixPower<MatrixType> mpow(m1);

    x = internal::random<RealScalar>();
    y = internal::random<RealScalar>();
    m2 = mpow(x);
    m3 = mpow(y);

    m4 = mpow(x+y);
    m5.noalias() = m2 * m3;
    VERIFY(m4.isApprox(m5, tol));

    m4 = mpow(x*y);
    m5 = m2.pow(y);
    VERIFY(m4.isApprox(m5, tol));

    m4 = (std::abs(x) * m1).pow(y);
    m5 = std::pow(std::abs(x), y) * m3;
    VERIFY(m4.isApprox(m5, tol));
  }
}

template<typename MatrixType>
void testSingular(MatrixType m, double tol)
{
  typedef typename MatrixType::RealScalar RealScalar;
  MatrixType m1, m2, m3, m4, m5;
  RealScalar x, y;

  for (int i=0; i < g_repeat; ++i) {
    generateTestMatrix<MatrixType>::run(m1, m.rows());
    MatrixPower<MatrixType> mpow(m1);

    x = internal::random<RealScalar>(0, 1);
    y = internal::random<RealScalar>(0, 1);
    m2 = mpow(x);
    m3 = mpow(y);

    m4 = mpow(x+y);
    m5.noalias() = m2 * m3;
    VERIFY(m4.isApprox(m5, tol));

    m4 = mpow(x*y);
    m5 = m2.pow(y);
    VERIFY(m4.isApprox(m5, tol));

    m4 = (x * m1).pow(y);
    m5 = std::pow(x, y) * m3;
    VERIFY(m4.isApprox(m5, tol));
  }
}

template<typename MatrixType>
void testLogThenExp(MatrixType m, double tol)
{
  typedef typename MatrixType::Scalar Scalar;
  Scalar x;

  for (int i=0; i < g_repeat; ++i) {
    generateTestMatrix<MatrixType>::run(m, m.rows());
    x = internal::random<Scalar>();
    VERIFY(m.pow(x).isApprox((x * m.log()).exp(), tol));
  }
}

typedef Matrix<double,3,3,RowMajor>         Matrix3dRowMajor;
typedef Matrix<long double,Dynamic,Dynamic> MatrixXe;

void test_matrix_power()
{
  CALL_SUBTEST_2(test2dRotation<double>(1e-13));
  CALL_SUBTEST_1(test2dRotation<float>(2e-5));  // was 1e-5, relaxed for clang 2.8 / linux / x86-64
  CALL_SUBTEST_9(test2dRotation<long double>(1e-13));
  CALL_SUBTEST_2(test2dHyperbolicRotation<double>(1e-14));
  CALL_SUBTEST_1(test2dHyperbolicRotation<float>(1e-5));
  CALL_SUBTEST_9(test2dHyperbolicRotation<long double>(1e-14));

  CALL_SUBTEST_2(testGeneral(Matrix2d(),         1e-13));
  CALL_SUBTEST_7(testGeneral(Matrix3dRowMajor(), 1e-13));
  CALL_SUBTEST_3(testGeneral(Matrix4cd(),        1e-13));
  CALL_SUBTEST_4(testGeneral(MatrixXd(8,8),      2e-12));
  CALL_SUBTEST_1(testGeneral(Matrix2f(),         1e-4));
  CALL_SUBTEST_5(testGeneral(Matrix3cf(),        1e-4));
  CALL_SUBTEST_8(testGeneral(Matrix4f(),         1e-4));
  CALL_SUBTEST_6(testGeneral(MatrixXf(2,2),      1e-3)); // see bug 614
  CALL_SUBTEST_9(testGeneral(MatrixXe(7,7),      1e-13));

  CALL_SUBTEST_2(testSingular(Matrix2d(),         1e-13));
  CALL_SUBTEST_7(testSingular(Matrix3dRowMajor(), 1e-13));
  CALL_SUBTEST_3(testSingular(Matrix4cd(),        1e-13));
  CALL_SUBTEST_4(testSingular(MatrixXd(8,8),      2e-12));
  CALL_SUBTEST_1(testSingular(Matrix2f(),         1e-4));
  CALL_SUBTEST_5(testSingular(Matrix3cf(),        1e-4));
  CALL_SUBTEST_8(testSingular(Matrix4f(),         1e-4));
  CALL_SUBTEST_6(testSingular(MatrixXf(2,2),      1e-3));
  CALL_SUBTEST_9(testSingular(MatrixXe(7,7),      1e-13));

  CALL_SUBTEST_2(testLogThenExp(Matrix2d(),         1e-13));
  CALL_SUBTEST_7(testLogThenExp(Matrix3dRowMajor(), 1e-13));
  CALL_SUBTEST_3(testLogThenExp(Matrix4cd(),        1e-13));
  CALL_SUBTEST_4(testLogThenExp(MatrixXd(8,8),      2e-12));
  CALL_SUBTEST_1(testLogThenExp(Matrix2f(),         1e-4));
  CALL_SUBTEST_5(testLogThenExp(Matrix3cf(),        1e-4));
  CALL_SUBTEST_8(testLogThenExp(Matrix4f(),         1e-4));
  CALL_SUBTEST_6(testLogThenExp(MatrixXf(2,2),      1e-3));
  CALL_SUBTEST_9(testLogThenExp(MatrixXe(7,7),      1e-13));
}
<commit_msg>Add test3dRotation.<commit_after>// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2012 Chen-Pang He <jdh8@ms63.hinet.net>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.

#include "matrix_functions.h"

// for complex matrices, any matrix is fine
template<typename MatrixType, int IsComplex = NumTraits<typename internal::traits<MatrixType>::Scalar>::IsComplex>
struct generateSingularMatrix
{
  static void run(MatrixType& result, typename MatrixType::Index size)
  {
    result = MatrixType::Random(size, size);
    result.col(0).fill(0);
  }
};

// for real matrices, make sure none of the eigenvalues are negative
template<typename MatrixType>
struct generateSingularMatrix<MatrixType,0>
{
  static void run(MatrixType& result, typename MatrixType::Index size)
  {
    MatrixType mat = MatrixType::Random(size, size);
    mat.col(0).fill(0);
    ComplexSchur<MatrixType> schur(mat);
    typename ComplexSchur<MatrixType>::ComplexMatrixType T = schur.matrixT();

    for (typename MatrixType::Index i = 0; i < size; ++i) {
      if (T.coeff(i,i).imag() == 0 && T.coeff(i,i).real() < 0)
	T.coeffRef(i,i) = -T.coeff(i,i);
    }
    result = (schur.matrixU() * (T.template triangularView<Upper>() * schur.matrixU().adjoint())).real();
  }
};

template<typename T>
void test2dRotation(double tol)
{
  Matrix<T,2,2> A, B, C;
  T angle, c, s;

  A << 0, 1, -1, 0;
  MatrixPower<Matrix<T,2,2> > Apow(A);

  for (int i=0; i<=20; ++i) {
    angle = pow(10, (i-10) / 5.);
    c = std::cos(angle);
    s = std::sin(angle);
    B << c, s, -s, c;

    C = Apow(std::ldexp(angle,1) / M_PI);
    std::cout << "test2dRotation: i = " << i << "   error powerm = " << relerr(C,B) << '\n';
    VERIFY(C.isApprox(B, tol));
  }
}

template<typename T>
void test2dHyperbolicRotation(double tol)
{
  Matrix<std::complex<T>,2,2> A, B, C;
  T angle, ch = std::cosh((T)1);
  std::complex<T> ish(0, std::sinh((T)1));

  A << ch, ish, -ish, ch;
  MatrixPower<Matrix<std::complex<T>,2,2> > Apow(A);

  for (int i=0; i<=20; ++i) {
    angle = std::ldexp(static_cast<T>(i-10), -1);
    ch = std::cosh(angle);
    ish = std::complex<T>(0, std::sinh(angle));
    B << ch, ish, -ish, ch;

    C = Apow(angle);
    std::cout << "test2dHyperbolicRotation: i = " << i << "   error powerm = " << relerr(C,B) << '\n';
    VERIFY(C.isApprox(B, tol));
  }
}

template<typename T>
void test3dRotation(double tol)
{
  Matrix<T,3,1> v;
  T angle;

  for (int i=0; i<=20; ++i) {
    v = Matrix<T,3,1>::Random();
    v.normalize();
    angle = pow(10, (i-10) / 5.);
    VERIFY(AngleAxis<T>(angle, v).matrix().isApprox(AngleAxis<T>(1,v).matrix().pow(angle), tol));
  }
}

template<typename MatrixType>
void testGeneral(const MatrixType& m, double tol)
{
  typedef typename MatrixType::RealScalar RealScalar;
  MatrixType m1, m2, m3, m4, m5;
  RealScalar x, y;

  for (int i=0; i < g_repeat; ++i) {
    generateTestMatrix<MatrixType>::run(m1, m.rows());
    MatrixPower<MatrixType> mpow(m1);

    x = internal::random<RealScalar>();
    y = internal::random<RealScalar>();
    m2 = mpow(x);
    m3 = mpow(y);

    m4 = mpow(x+y);
    m5.noalias() = m2 * m3;
    VERIFY(m4.isApprox(m5, tol));

    m4 = mpow(x*y);
    m5 = m2.pow(y);
    VERIFY(m4.isApprox(m5, tol));

    m4 = (std::abs(x) * m1).pow(y);
    m5 = std::pow(std::abs(x), y) * m3;
    VERIFY(m4.isApprox(m5, tol));
  }
}

template<typename MatrixType>
void testSingular(MatrixType m, double tol)
{
  typedef typename MatrixType::RealScalar RealScalar;
  MatrixType m1, m2, m3, m4, m5;
  RealScalar x, y;

  for (int i=0; i < g_repeat; ++i) {
    generateTestMatrix<MatrixType>::run(m1, m.rows());
    MatrixPower<MatrixType> mpow(m1);

    x = internal::random<RealScalar>(0, 1);
    y = internal::random<RealScalar>(0, 1);
    m2 = mpow(x);
    m3 = mpow(y);

    m4 = mpow(x+y);
    m5.noalias() = m2 * m3;
    VERIFY(m4.isApprox(m5, tol));

    m4 = mpow(x*y);
    m5 = m2.pow(y);
    VERIFY(m4.isApprox(m5, tol));

    m4 = (x * m1).pow(y);
    m5 = std::pow(x, y) * m3;
    VERIFY(m4.isApprox(m5, tol));
  }
}

template<typename MatrixType>
void testLogThenExp(MatrixType m, double tol)
{
  typedef typename MatrixType::Scalar Scalar;
  Scalar x;

  for (int i=0; i < g_repeat; ++i) {
    generateTestMatrix<MatrixType>::run(m, m.rows());
    x = internal::random<Scalar>();
    VERIFY(m.pow(x).isApprox((x * m.log()).exp(), tol));
  }
}

typedef Matrix<double,3,3,RowMajor>         Matrix3dRowMajor;
typedef Matrix<long double,3,3>             Matrix3e;
typedef Matrix<long double,Dynamic,Dynamic> MatrixXe;

void test_matrix_power()
{
  CALL_SUBTEST_2(test2dRotation<double>(1e-13));
  CALL_SUBTEST_1(test2dRotation<float>(2e-5));  // was 1e-5, relaxed for clang 2.8 / linux / x86-64
  CALL_SUBTEST_9(test2dRotation<long double>(1e-13));
  CALL_SUBTEST_2(test2dHyperbolicRotation<double>(1e-14));
  CALL_SUBTEST_1(test2dHyperbolicRotation<float>(1e-5));
  CALL_SUBTEST_9(test2dHyperbolicRotation<long double>(1e-14));

  CALL_SUBTEST_10(test3dRotation<double>(1e-13));
  CALL_SUBTEST_11(test3dRotation<float>(1e-5));
  CALL_SUBTEST_12(test3dRotation<long double>(1e-13));

  CALL_SUBTEST_2(testGeneral(Matrix2d(),         1e-13));
  CALL_SUBTEST_7(testGeneral(Matrix3dRowMajor(), 1e-13));
  CALL_SUBTEST_3(testGeneral(Matrix4cd(),        1e-13));
  CALL_SUBTEST_4(testGeneral(MatrixXd(8,8),      2e-12));
  CALL_SUBTEST_1(testGeneral(Matrix2f(),         1e-4));
  CALL_SUBTEST_5(testGeneral(Matrix3cf(),        1e-4));
  CALL_SUBTEST_8(testGeneral(Matrix4f(),         1e-4));
  CALL_SUBTEST_6(testGeneral(MatrixXf(2,2),      1e-3)); // see bug 614
  CALL_SUBTEST_9(testGeneral(MatrixXe(7,7),      1e-13));
  CALL_SUBTEST_10(testGeneral(Matrix3d(),        1e-13));
  CALL_SUBTEST_11(testGeneral(Matrix3f(),        1e-4));
  CALL_SUBTEST_12(testGeneral(Matrix3e(),        1e-13));

  CALL_SUBTEST_2(testSingular(Matrix2d(),         1e-13));
  CALL_SUBTEST_7(testSingular(Matrix3dRowMajor(), 1e-13));
  CALL_SUBTEST_3(testSingular(Matrix4cd(),        1e-13));
  CALL_SUBTEST_4(testSingular(MatrixXd(8,8),      2e-12));
  CALL_SUBTEST_1(testSingular(Matrix2f(),         1e-4));
  CALL_SUBTEST_5(testSingular(Matrix3cf(),        1e-4));
  CALL_SUBTEST_8(testSingular(Matrix4f(),         1e-4));
  CALL_SUBTEST_6(testSingular(MatrixXf(2,2),      1e-3));
  CALL_SUBTEST_9(testSingular(MatrixXe(7,7),      1e-13));
  CALL_SUBTEST_10(testSingular(Matrix3d(),        1e-13));
  CALL_SUBTEST_11(testSingular(Matrix3f(),        1e-4));
  CALL_SUBTEST_12(testSingular(Matrix3e(),        1e-13));

  CALL_SUBTEST_2(testLogThenExp(Matrix2d(),         1e-13));
  CALL_SUBTEST_7(testLogThenExp(Matrix3dRowMajor(), 1e-13));
  CALL_SUBTEST_3(testLogThenExp(Matrix4cd(),        1e-13));
  CALL_SUBTEST_4(testLogThenExp(MatrixXd(8,8),      2e-12));
  CALL_SUBTEST_1(testLogThenExp(Matrix2f(),         1e-4));
  CALL_SUBTEST_5(testLogThenExp(Matrix3cf(),        1e-4));
  CALL_SUBTEST_8(testLogThenExp(Matrix4f(),         1e-4));
  CALL_SUBTEST_6(testLogThenExp(MatrixXf(2,2),      1e-3));
  CALL_SUBTEST_9(testLogThenExp(MatrixXe(7,7),      1e-13));
  CALL_SUBTEST_10(testLogThenExp(Matrix3d(),        1e-13));
  CALL_SUBTEST_11(testLogThenExp(Matrix3f(),        1e-4));
  CALL_SUBTEST_12(testLogThenExp(Matrix3e(),        1e-13));
}
<|endoftext|>


<commit_before>/*-----------------------------------------------------------------------------
 This source file is part of Hopsan NG

 Copyright (c) 2011
    Mikael Axin, Robert Braun, Alessandro Dell'Amico, Björn Eriksson,
    Peter Nordin, Karl Pettersson, Petter Krus, Ingo Staack

 This file is provided "as is", with no guarantee or warranty for the
 functionality or reliability of the contents. All contents in this file is
 the original work of the copyright holders at the Division of Fluid and
 Mechatronic Systems (Flumes) at Linköping University. Modifying, using or
 redistributing any part of this file is prohibited without explicit
 permission from the copyright holders.
-----------------------------------------------------------------------------*/

//!
//! @file   PyDockWidget.cpp
//! @author Björn Eriksson <bjorn.eriksson@liu.se>
//! @date   2010-09-21
//!
//! @brief Contains a derived QDockWidget class that contain a Python console
//!
//$Id$

#include "PyDockWidget.h"

#ifdef USEPYTHONQT

#include "global.h"
#include "PythonQt.h"
#include "PythonQt_QtAll.h"
#include "gui/PythonQtScriptingConsole.h"
#include "PythonQtConversion.h"
#include "DesktopHandler.h"

#include "PyWrapperClasses.h"

//! Create a dock for the Python console

//! Constructor
PyDockWidget::PyDockWidget(MainWindow *pMainWindow, QWidget * parent)
    : QDockWidget(tr("Python Console"), parent)
{
    PythonQt::init(PythonQt::RedirectStdOut);
    PythonQt_QtAll::init();

    //PythonQt::self()->registerCPPClass("MainWindow", "","", PythonQtCreateObject<PyMainWindowClassWrapper>);
    //PythonQt::self()->registerCPPClass("ModelObject", "","", PythonQtCreateObject<PyModelObjectClassWrapper>);
    //PythonQt::self()->registerCPPClass("Port", "","", PythonQtCreateObject<PyPortClassWrapper>);
    PythonQt::self()->registerClass(&MainWindow::staticMetaObject, NULL, PythonQtCreateObject<PyMainWindowClassWrapper>);
    PythonQt::self()->registerClass(&ModelObject::staticMetaObject, NULL, PythonQtCreateObject<PyModelObjectClassWrapper>);
    PythonQt::self()->registerClass(&Port::staticMetaObject, NULL, PythonQtCreateObject<PyPortClassWrapper>);
    PythonQt::self()->registerClass(&LogDataHandler::staticMetaObject, NULL, PythonQtCreateObject<PyLogDataHandlerClassWrapper>);
    PythonQt::self()->registerClass(&SharedVectorVariableT::staticMetaObject, NULL, PythonQtCreateObject<PyVectorVariableClassWrapper>);

    PythonQtObjectPtr  mainContext = PythonQt::self()->getMainModule();
    mainContext.addObject("hopsan", pMainWindow);

//        pyTestClass *test = new pyTestClass();
//        mainContext.addObject("test", test);

    mpPyConsole = new PythonQtScriptingConsole(NULL, mainContext);
    mpPyConsole->consoleMessage("There is an object called hopsan that allow you to interact with Hopsan.");
    mpPyConsole->appendCommandPrompt();

    mpScriptFileLineEdit = new QLineEdit();
    //mpScriptFileLineEdit->setAlignment(Qt::AlignVCenter | Qt::AlignLeft);
    //mpStartTimeLineEdit->setValidator(new QDoubleValidator(-999.0, 999.0, 6, mpStartTimeLineEdit));

    mpLoadScriptButton = new QToolButton(this);
    mpLoadScriptButton->setIcon(QIcon(QString(ICONPATH)+"Hopsan-Open.png"));
    mpLoadScriptButton->setToolTip("Load Script File");
    connect(mpLoadScriptButton, SIGNAL(clicked()), this, SLOT(loadPyScript()));

    mpInitScriptButton = new QToolButton(this);
    mpInitScriptButton->setIcon(QIcon(QString(ICONPATH)+"Hopsan-Script.png"));
    mpInitScriptButton->setToolTip("Define Initialization Script");
    connect(mpInitScriptButton, SIGNAL(clicked()), this, SLOT(openInitScriptDialog()));

    QPushButton *pPyCustomButton = new QPushButton(this);
    pPyCustomButton->setText("Run .py-file");
    pPyCustomButton->connect(pPyCustomButton,SIGNAL(clicked()), this, SLOT(runPyScript()));

    QHBoxLayout *pScriptFileLayout = new QHBoxLayout();
    pScriptFileLayout->addWidget(mpScriptFileLineEdit);
    pScriptFileLayout->addWidget(mpLoadScriptButton);
    pScriptFileLayout->addWidget(mpInitScriptButton);
    pScriptFileLayout->addWidget(pPyCustomButton);

    QVBoxLayout *pPyLayout = new QVBoxLayout();
    pPyLayout->addWidget(mpPyConsole);
    pPyLayout->setContentsMargins(4,4,4,4);
    pPyLayout->addLayout(pScriptFileLayout);

    PyWidget *pPyWidget = new PyWidget();
    pPyWidget->setLayout(pPyLayout);

    runCommand(gpConfig->getInitScript());

    mpScriptFileLineEdit->setText(gpConfig->getLastScriptFile());

    setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea | Qt::BottomDockWidgetArea);
    setWidget(pPyWidget);//->setWidget(mpPythonConsole);

    //Add script path to Python path
    QString scriptPath = QString(gpDesktopHandler->getScriptsPath());
    scriptPath.replace("\\", "/");
    scriptPath.replace("//", "/");
    runCommand("import sys");
    runCommand("sys.path.append(\""+scriptPath+"\")");

    mpPyConsole->clear();
}

void PyDockWidget::saveSettingsToDomElement(QDomElement &rDomElement)
{
    QDomElement lastscript = appendDomElement(rDomElement, "lastscript");
    lastscript.setAttribute("file", mpScriptFileLineEdit->text());

    if(!mInitScript.isEmpty())
        appendDomTextNode(rDomElement, "initscript", mInitScript);
}

QString PyDockWidget::getLastOutput()
{
    QString text = mpPyConsole->toPlainText();
    QStringList lines = text.split("\n");
    if(lines.size() > 3)
    {
        return lines[lines.size()-3];
    }

    return QString();
}

void PyDockWidget::runPyScript()
{
    PythonQtObjectPtr mainContext = PythonQt::self()->getMainModule();
    QString command = QString("execfile('").append(mpScriptFileLineEdit->text()).append("')");
    mainContext.evalScript(command);
    mpPyConsole->appendCommandPrompt();
}

void PyDockWidget::loadPyScript()
{
    QDir fileDialogOpenDir;
    QString modelFileName = QFileDialog::getOpenFileName(this, tr("Choose Script File"),
                                                         gpConfig->getScriptDir(),
                                                         tr("Python Scripts (*.py)"));
    if(!modelFileName.isEmpty())
    {
        mpScriptFileLineEdit->setText(modelFileName);
        QFileInfo fileInfo = QFileInfo(modelFileName);
        gpConfig->setScriptDir(fileInfo.absolutePath());
    }
}

void PyDockWidget::openInitScriptDialog()
{
    mpDialog = new QDialog(this);
    mpTextEdit = new QTextEdit(this);
    mpTextEdit->setPlainText(gpConfig->getInitScript());
    QPushButton *pOkButton = new QPushButton("Done", mpDialog);
    QVBoxLayout *pLayout = new QVBoxLayout();
    pLayout->addWidget(mpTextEdit);
    pLayout->addWidget(pOkButton);
    mpDialog->setLayout(pLayout);

    connect(pOkButton, SIGNAL(clicked()), this, SLOT(setInitScriptFromDialog()));

    mpDialog->exec();
}

void PyDockWidget::setInitScriptFromDialog()
{
    mInitScript = mpTextEdit->toPlainText();

    mpDialog->close();
    delete(mpTextEdit);
    delete(mpDialog);
}

void PyDockWidget::runPyScript(QString path)
{
    if(path.isEmpty()) return;
    PythonQtObjectPtr mainContext = PythonQt::self()->getMainModule();
    QString command = QString("execfile('").append(path).append("')");
    mainContext.evalScript(command);
    mpPyConsole->appendCommandPrompt();
}

void PyDockWidget::runMultipleCommands(QString command, int n)
{
    PythonQtObjectPtr mainContext = PythonQt::self()->getMainModule();
    for(int i=0; i<n; ++i)
    {
        mainContext.evalScript(command);
        mpPyConsole->appendCommandPrompt();
        //gpPlotWidget->mpPlotVariableTree->getPlotWindow(0)->getCurrentPlotTab()->getCurves(0).last()->updateToNewGeneration();
        qApp->processEvents();
    }
}

QString PyDockWidget::runCommand(QString command)
{
    //PythonQtObjectPtr mainContext = PythonQt::self()->getMainModule();
    //QVariant output = mainContext.evalScript(command);
    //mpPyConsole->appendCommandPrompt();

    mpPyConsole->append("py> "+command);
    mpPyConsole->executeLine(false);

    qApp->processEvents();

    //QVariant test = mainContext.getVariable("j11");
    //qDebug() << test;
    //qDebug() << test.toString();

    return getLastOutput();
}

//! @todo Remove this! It is just a stupid test function, but I am too lazy to fix it now...
void PyDockWidget::optimize()
{
    runMultipleCommands("iterate()", 100);
}

PyWidget::PyWidget(QWidget *parent)
    : QWidget(parent)
{
    //Nothing to do...
}

//! @brief Reimplementation of QWidget::sizeHint(), used to reduce the size of the plot widget when docked
QSize PyWidget::sizeHint() const
{
    QSize size = QWidget::sizeHint();
    //Set very small height. A minimum apperantly stops at resonable size.
    size.rheight() = 1; //pixels
    return size;
}

#endif
<commit_msg>revers merged accidental commit<commit_after>/*-----------------------------------------------------------------------------
 This source file is part of Hopsan NG

 Copyright (c) 2011
    Mikael Axin, Robert Braun, Alessandro Dell'Amico, Björn Eriksson,
    Peter Nordin, Karl Pettersson, Petter Krus, Ingo Staack

 This file is provided "as is", with no guarantee or warranty for the
 functionality or reliability of the contents. All contents in this file is
 the original work of the copyright holders at the Division of Fluid and
 Mechatronic Systems (Flumes) at Linköping University. Modifying, using or
 redistributing any part of this file is prohibited without explicit
 permission from the copyright holders.
-----------------------------------------------------------------------------*/

//!
//! @file   PyDockWidget.cpp
//! @author Björn Eriksson <bjorn.eriksson@liu.se>
//! @date   2010-09-21
//!
//! @brief Contains a derived QDockWidget class that contain a Python console
//!
//$Id$

#include "PyDockWidget.h"

#ifdef USEPYTHONQT

#include "global.h"
#include "PythonQt.h"
#include "PythonQt_QtAll.h"
#include "gui/PythonQtScriptingConsole.h"
#include "PythonQtConversion.h"
#include "DesktopHandler.h"

#include "PyWrapperClasses.h"

//! Create a dock for the Python console

//! Constructor
PyDockWidget::PyDockWidget(MainWindow *pMainWindow, QWidget * parent)
    : QDockWidget(tr("Python Console"), parent)
{
    PythonQt::init(PythonQt::RedirectStdOut);
    PythonQt_QtAll::init();

    //PythonQt::self()->registerCPPClass("MainWindow", "","", PythonQtCreateObject<PyMainWindowClassWrapper>);
    //PythonQt::self()->registerCPPClass("ModelObject", "","", PythonQtCreateObject<PyModelObjectClassWrapper>);
    //PythonQt::self()->registerCPPClass("Port", "","", PythonQtCreateObject<PyPortClassWrapper>);
    PythonQt::self()->registerClass(&MainWindow::staticMetaObject, NULL, PythonQtCreateObject<PyMainWindowClassWrapper>);
    PythonQt::self()->registerClass(&ModelObject::staticMetaObject, NULL, PythonQtCreateObject<PyModelObjectClassWrapper>);
    PythonQt::self()->registerClass(&Port::staticMetaObject, NULL, PythonQtCreateObject<PyPortClassWrapper>);
    PythonQt::self()->registerClass(&LogDataHandler::staticMetaObject, NULL, PythonQtCreateObject<PyLogDataHandlerClassWrapper>);

    PythonQtObjectPtr  mainContext = PythonQt::self()->getMainModule();
    mainContext.addObject("hopsan", pMainWindow);

//        pyTestClass *test = new pyTestClass();
//        mainContext.addObject("test", test);

    mpPyConsole = new PythonQtScriptingConsole(NULL, mainContext);
    mpPyConsole->consoleMessage("There is an object called hopsan that allow you to interact with Hopsan.");
    mpPyConsole->appendCommandPrompt();

    mpScriptFileLineEdit = new QLineEdit();
    //mpScriptFileLineEdit->setAlignment(Qt::AlignVCenter | Qt::AlignLeft);
    //mpStartTimeLineEdit->setValidator(new QDoubleValidator(-999.0, 999.0, 6, mpStartTimeLineEdit));

    mpLoadScriptButton = new QToolButton(this);
    mpLoadScriptButton->setIcon(QIcon(QString(ICONPATH)+"Hopsan-Open.png"));
    mpLoadScriptButton->setToolTip("Load Script File");
    connect(mpLoadScriptButton, SIGNAL(clicked()), this, SLOT(loadPyScript()));

    mpInitScriptButton = new QToolButton(this);
    mpInitScriptButton->setIcon(QIcon(QString(ICONPATH)+"Hopsan-Script.png"));
    mpInitScriptButton->setToolTip("Define Initialization Script");
    connect(mpInitScriptButton, SIGNAL(clicked()), this, SLOT(openInitScriptDialog()));

    QPushButton *pPyCustomButton = new QPushButton(this);
    pPyCustomButton->setText("Run .py-file");
    pPyCustomButton->connect(pPyCustomButton,SIGNAL(clicked()), this, SLOT(runPyScript()));

    QHBoxLayout *pScriptFileLayout = new QHBoxLayout();
    pScriptFileLayout->addWidget(mpScriptFileLineEdit);
    pScriptFileLayout->addWidget(mpLoadScriptButton);
    pScriptFileLayout->addWidget(mpInitScriptButton);
    pScriptFileLayout->addWidget(pPyCustomButton);

    QVBoxLayout *pPyLayout = new QVBoxLayout();
    pPyLayout->addWidget(mpPyConsole);
    pPyLayout->setContentsMargins(4,4,4,4);
    pPyLayout->addLayout(pScriptFileLayout);

    PyWidget *pPyWidget = new PyWidget();
    pPyWidget->setLayout(pPyLayout);

    runCommand(gpConfig->getInitScript());

    mpScriptFileLineEdit->setText(gpConfig->getLastScriptFile());

    setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea | Qt::BottomDockWidgetArea);
    setWidget(pPyWidget);//->setWidget(mpPythonConsole);

    //Add script path to Python path
    QString scriptPath = QString(gpDesktopHandler->getScriptsPath());
    scriptPath.replace("\\", "/");
    scriptPath.replace("//", "/");
    runCommand("import sys");
    runCommand("sys.path.append(\""+scriptPath+"\")");

    mpPyConsole->clear();
}

void PyDockWidget::saveSettingsToDomElement(QDomElement &rDomElement)
{
    QDomElement lastscript = appendDomElement(rDomElement, "lastscript");
    lastscript.setAttribute("file", mpScriptFileLineEdit->text());

    if(!mInitScript.isEmpty())
        appendDomTextNode(rDomElement, "initscript", mInitScript);
}

QString PyDockWidget::getLastOutput()
{
    QString text = mpPyConsole->toPlainText();
    QStringList lines = text.split("\n");
    if(lines.size() > 3)
    {
        return lines[lines.size()-3];
    }

    return QString();
}

void PyDockWidget::runPyScript()
{
    PythonQtObjectPtr mainContext = PythonQt::self()->getMainModule();
    QString command = QString("execfile('").append(mpScriptFileLineEdit->text()).append("')");
    mainContext.evalScript(command);
    mpPyConsole->appendCommandPrompt();
}

void PyDockWidget::loadPyScript()
{
    QDir fileDialogOpenDir;
    QString modelFileName = QFileDialog::getOpenFileName(this, tr("Choose Script File"),
                                                         gpConfig->getScriptDir(),
                                                         tr("Python Scripts (*.py)"));
    if(!modelFileName.isEmpty())
    {
        mpScriptFileLineEdit->setText(modelFileName);
        QFileInfo fileInfo = QFileInfo(modelFileName);
        gpConfig->setScriptDir(fileInfo.absolutePath());
    }
}

void PyDockWidget::openInitScriptDialog()
{
    mpDialog = new QDialog(this);
    mpTextEdit = new QTextEdit(this);
    mpTextEdit->setPlainText(gpConfig->getInitScript());
    QPushButton *pOkButton = new QPushButton("Done", mpDialog);
    QVBoxLayout *pLayout = new QVBoxLayout();
    pLayout->addWidget(mpTextEdit);
    pLayout->addWidget(pOkButton);
    mpDialog->setLayout(pLayout);

    connect(pOkButton, SIGNAL(clicked()), this, SLOT(setInitScriptFromDialog()));

    mpDialog->exec();
}

void PyDockWidget::setInitScriptFromDialog()
{
    mInitScript = mpTextEdit->toPlainText();

    mpDialog->close();
    delete(mpTextEdit);
    delete(mpDialog);
}

void PyDockWidget::runPyScript(QString path)
{
    if(path.isEmpty()) return;
    PythonQtObjectPtr mainContext = PythonQt::self()->getMainModule();
    QString command = QString("execfile('").append(path).append("')");
    mainContext.evalScript(command);
    mpPyConsole->appendCommandPrompt();
}

void PyDockWidget::runMultipleCommands(QString command, int n)
{
    PythonQtObjectPtr mainContext = PythonQt::self()->getMainModule();
    for(int i=0; i<n; ++i)
    {
        mainContext.evalScript(command);
        mpPyConsole->appendCommandPrompt();
        //gpPlotWidget->mpPlotVariableTree->getPlotWindow(0)->getCurrentPlotTab()->getCurves(0).last()->updateToNewGeneration();
        qApp->processEvents();
    }
}

QString PyDockWidget::runCommand(QString command)
{
    //PythonQtObjectPtr mainContext = PythonQt::self()->getMainModule();
    //QVariant output = mainContext.evalScript(command);
    //mpPyConsole->appendCommandPrompt();

    mpPyConsole->append("py> "+command);
    mpPyConsole->executeLine(false);

    qApp->processEvents();

    //QVariant test = mainContext.getVariable("j11");
    //qDebug() << test;
    //qDebug() << test.toString();

    return getLastOutput();
}

//! @todo Remove this! It is just a stupid test function, but I am too lazy to fix it now...
void PyDockWidget::optimize()
{
    runMultipleCommands("iterate()", 100);
}

PyWidget::PyWidget(QWidget *parent)
    : QWidget(parent)
{
    //Nothing to do...
}

//! @brief Reimplementation of QWidget::sizeHint(), used to reduce the size of the plot widget when docked
QSize PyWidget::sizeHint() const
{
    QSize size = QWidget::sizeHint();
    //Set very small height. A minimum apperantly stops at resonable size.
    size.rheight() = 1; //pixels
    return size;
}

#endif
<|endoftext|>


<commit_before>/*
   Copyright 2012 Tzvetan Mikov <tmikov@gmail.com>
   All rights reserved.

   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.
*/

#ifndef P1_SMALLS_AST_SCHEMEAST_HPP
#define	P1_SMALLS_AST_SCHEMEAST_HPP

#include "AstFrame.hpp"
#include "p1/smalls/common/SourceCoords.hpp"
#include "p1/adt/LinkedList.hpp"
#include <vector>

namespace p1 {
namespace smalls {
  class Syntax;
}}

namespace p1 {
namespace smalls {

#define _DEF_AST_CODES \
  _MK_ENUM(NONE) \
  _MK_ENUM(UNSPECIFIED) \
  _MK_ENUM(VAR) \
  _MK_ENUM(DATUM) \
  _MK_ENUM(SET) \
  _MK_ENUM(APPLY) \
  _MK_ENUM(IF) \
  _MK_ENUM(CLOSURE) \
  _MK_ENUM(LET) \
  _MK_ENUM(FIX) \

struct AstKind
{
  #define _MK_ENUM(x)  x,
  enum Enum
  {
    _DEF_AST_CODES
  };
  #undef _MK_ENUM

  static const char * name ( Enum x )  { return s_names[x]; }
private:
  static const char * s_names[];
};

class Ast : public gc
{
public:
  AstKind::Enum const kind;
  SourceCoords const coords;

  Ast ( AstKind::Enum kind_, const SourceCoords & coords_ ) : kind(kind_), coords(coords_)
  {
    this->m_prev = this->m_next = NULL;
  };

  virtual void toStream ( std::ostream & os ) const;

  struct LinkAccessor
  {
    static Ast * & prev ( Ast * item ) { return item->m_prev; }
    static Ast * & next ( Ast * item ) { return item->m_next; }
    static Ast * prev ( const Ast * item ) { return item->m_prev; }
    static Ast * next ( const Ast * item ) { return item->m_next; }
  };

private:
  Ast * m_prev, * m_next;
};

typedef p1::LinkedList<Ast,Ast::LinkAccessor> ListOfAst;

inline ListOfAst makeListOfAst ( Ast * ast )
{
  return ListOfAst( ast );
}

typedef std::vector<ListOfAst, gc_allocator<ListOfAst> > VectorOfListOfAst;

std::ostream & operator<< ( std::ostream & os, const ListOfAst & lst );

inline std::ostream & operator << ( std::ostream & os, const Ast & ast )
{
  ast.toStream( os );
  return os;
}

class AstVar : public Ast
{
public:
  AstVariable * const var;

  AstVar ( const SourceCoords & coords_, AstVariable * var_ )
    : Ast( AstKind::VAR, coords_ ), var( var_ )
  {}

  virtual void toStream ( std::ostream & os ) const;
};

class AstDatum : public Ast
{
public:
  Syntax * const datum; // FIXME: should not depend on this

  AstDatum ( const SourceCoords & coords_, Syntax * datum_ )
    : Ast ( AstKind::DATUM, coords_ ), datum( datum_ )
  {}

  virtual void toStream ( std::ostream & os ) const;
};

class AstSet : public Ast
{
public:
  AstVariable * const target;
  ListOfAst const rvalue;

  AstSet ( const SourceCoords & coords_, AstVariable * target_, const ListOfAst & rvalue_ )
    : Ast( AstKind::SET, coords_ ), target(target_), rvalue(rvalue_)
  {}

  virtual void toStream ( std::ostream & os ) const;
};

class AstApply : public Ast
{
public:
  ListOfAst const target;
  VectorOfListOfAst * const params;
  ListOfAst * const listParam;

  AstApply ( const SourceCoords & coords_,
             const ListOfAst & target_, VectorOfListOfAst * params_, ListOfAst * listParam_ )
    : Ast( AstKind::APPLY, coords_ ), target(target_), params(params_), listParam(listParam_)
  {}

  virtual void toStream ( std::ostream & os ) const;
};

class AstIf : public Ast
{
public:
  ListOfAst const cond;
  ListOfAst const thenAst;
  ListOfAst const elseAst;

  AstIf ( const SourceCoords & coords_,
          const ListOfAst & cond_, const ListOfAst & thenAst_, const ListOfAst & elseAst_ )
    : Ast( AstKind::IF, coords_ ), cond(cond_),thenAst(thenAst_),elseAst(elseAst_)
  {}

  virtual void toStream ( std::ostream & os ) const;
};

typedef std::vector<AstVariable *, gc_allocator<AstVariable *> > VectorOfVariable;

class AstClosure : public Ast
{
public:
  AstFrame * const enclosingFrame;
  VectorOfVariable * const params;
  AstVariable * const listParam;
  AstFrame * const paramFrame;
  AstFrame * const bodyFrame;
  ListOfAst const body;

  AstClosure (
    const SourceCoords & coords_,
    AstFrame * enclosingFrame_,
    VectorOfVariable * params_,
    AstVariable * listParam_,
    AstFrame * paramFrame_,
    AstFrame * bodyFrame_,
    const ListOfAst & body_
  ) : Ast( AstKind::CLOSURE, coords_ ),
      enclosingFrame( enclosingFrame_ ),
      params( params_ ),
      listParam( listParam_ ),
      paramFrame( paramFrame_ ),
      bodyFrame( bodyFrame_ ),
      body( body_ )
  {}

  virtual void toStream ( std::ostream & os ) const;
};

class AstLet : public Ast
{
public:
  AstFrame * enclosingFrame;
  VectorOfVariable * params;
  AstFrame * paramFrame;
  AstFrame * bodyFrame;
  ListOfAst body;
  VectorOfListOfAst * values;

  AstLet (
    const SourceCoords & coords_,
    AstFrame * enclosingFrame_,
    VectorOfVariable * params_,
    AstFrame * paramFrame_,
    AstFrame * bodyFrame_,
    const ListOfAst & body_,
    VectorOfListOfAst * values_
  ) : Ast( AstKind::LET, coords_ ),
      enclosingFrame( enclosingFrame_ ),
      params( params_ ),
      paramFrame( paramFrame_ ),
      bodyFrame( bodyFrame_ ),
      body( body_ ),
      values( values_ )
  {}

  virtual void toStream ( std::ostream & os ) const;

protected:
  AstLet (
    AstKind::Enum code,
    const SourceCoords & coords_,
    AstFrame * enclosingFrame_,
    VectorOfVariable * params_,
    AstFrame * paramFrame_,
    AstFrame * bodyFrame_,
    const ListOfAst & body_,
    VectorOfListOfAst * values_
  ) : Ast( code, coords_ ),
      enclosingFrame( enclosingFrame_ ),
      params( params_ ),
      paramFrame( paramFrame_ ),
      bodyFrame( bodyFrame_ ),
      body( body_ ),
      values( values_ )
  {}
};

/**
 * A restricted form of let where the variables are unassigned (never modified), and the init
 * expressions are all lambdas.
 */
class AstFix : public AstLet
{
public:
  AstFix (
    const SourceCoords & coords_,
    AstFrame * enclosingFrame_,
    VectorOfVariable * params_,
    AstFrame * paramFrame_,
    AstFrame * bodyFrame_,
    const ListOfAst & body_,
    VectorOfListOfAst * values_
  );
};

}} // namespaces

#endif	/* P1_SMALLS_AST_SCHEMEAST_HPP */

<commit_msg>smalls/ast/SchemeAST: implement ::classof for custom RTTI<commit_after>/*
   Copyright 2012 Tzvetan Mikov <tmikov@gmail.com>
   All rights reserved.

   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.
*/

#ifndef P1_SMALLS_AST_SCHEMEAST_HPP
#define	P1_SMALLS_AST_SCHEMEAST_HPP

#include "AstFrame.hpp"
#include "p1/smalls/common/SourceCoords.hpp"
#include "p1/adt/LinkedList.hpp"
#include "p1/util/casting.hpp"
#include <vector>

namespace p1 {
namespace smalls {
  class Syntax;
}}

namespace p1 {
namespace smalls {

#define _DEF_AST_CODES \
  _MK_ENUM(NONE) \
  _MK_ENUM(UNSPECIFIED) \
  _MK_ENUM(VAR) \
  _MK_ENUM(DATUM) \
  _MK_ENUM(SET) \
  _MK_ENUM(APPLY) \
  _MK_ENUM(IF) \
  _MK_ENUM(CLOSURE) \
  _MK_ENUM(LET) \
  _MK_ENUM(FIX) \

struct AstKind
{
  #define _MK_ENUM(x)  x,
  enum Enum
  {
    _DEF_AST_CODES
  };
  #undef _MK_ENUM

  static const char * name ( Enum x )  { return s_names[x]; }
private:
  static const char * s_names[];
};

class Ast : public gc
{
public:
  AstKind::Enum const kind;
  SourceCoords const coords;

  Ast ( AstKind::Enum kind_, const SourceCoords & coords_ ) : kind(kind_), coords(coords_)
  {
    this->m_prev = this->m_next = NULL;
  };

  static bool classof ( const Ast * ) { return true; }

  virtual void toStream ( std::ostream & os ) const;

  struct LinkAccessor
  {
    static Ast * & prev ( Ast * item ) { return item->m_prev; }
    static Ast * & next ( Ast * item ) { return item->m_next; }
    static Ast * prev ( const Ast * item ) { return item->m_prev; }
    static Ast * next ( const Ast * item ) { return item->m_next; }
  };

private:
  Ast * m_prev, * m_next;
};

typedef p1::LinkedList<Ast,Ast::LinkAccessor> ListOfAst;

inline ListOfAst makeListOfAst ( Ast * ast )
{
  return ListOfAst( ast );
}

typedef std::vector<ListOfAst, gc_allocator<ListOfAst> > VectorOfListOfAst;

std::ostream & operator<< ( std::ostream & os, const ListOfAst & lst );

inline std::ostream & operator << ( std::ostream & os, const Ast & ast )
{
  ast.toStream( os );
  return os;
}

class AstVar : public Ast
{
public:
  AstVariable * const var;

  AstVar ( const SourceCoords & coords_, AstVariable * var_ )
    : Ast( AstKind::VAR, coords_ ), var( var_ )
  {}

  static bool classof ( const AstVar * ) { return true; }
  static bool classof ( const Ast * t ) { return t->kind == AstKind::VAR; }

  virtual void toStream ( std::ostream & os ) const;
};

class AstDatum : public Ast
{
public:
  Syntax * const datum; // FIXME: should not depend on this

  AstDatum ( const SourceCoords & coords_, Syntax * datum_ )
    : Ast ( AstKind::DATUM, coords_ ), datum( datum_ )
  {}

  static bool classof ( const AstDatum * ) { return true; }
  static bool classof ( const Ast * t ) { return t->kind == AstKind::DATUM; }

  virtual void toStream ( std::ostream & os ) const;
};

class AstSet : public Ast
{
public:
  AstVariable * const target;
  ListOfAst const rvalue;

  AstSet ( const SourceCoords & coords_, AstVariable * target_, const ListOfAst & rvalue_ )
    : Ast( AstKind::SET, coords_ ), target(target_), rvalue(rvalue_)
  {}

  static bool classof ( const AstSet * ) { return true; }
  static bool classof ( const Ast * t ) { return t->kind == AstKind::SET; }

  virtual void toStream ( std::ostream & os ) const;
};

class AstApply : public Ast
{
public:
  ListOfAst const target;
  VectorOfListOfAst * const params;
  ListOfAst * const listParam;

  AstApply ( const SourceCoords & coords_,
             const ListOfAst & target_, VectorOfListOfAst * params_, ListOfAst * listParam_ )
    : Ast( AstKind::APPLY, coords_ ), target(target_), params(params_), listParam(listParam_)
  {}

  static bool classof ( const AstApply * ) { return true; }
  static bool classof ( const Ast * t ) { return t->kind == AstKind::APPLY; }

  virtual void toStream ( std::ostream & os ) const;
};

class AstIf : public Ast
{
public:
  ListOfAst const cond;
  ListOfAst const thenAst;
  ListOfAst const elseAst;

  AstIf ( const SourceCoords & coords_,
          const ListOfAst & cond_, const ListOfAst & thenAst_, const ListOfAst & elseAst_ )
    : Ast( AstKind::IF, coords_ ), cond(cond_),thenAst(thenAst_),elseAst(elseAst_)
  {}

  static bool classof ( const AstIf * ) { return true; }
  static bool classof ( const Ast * t ) { return t->kind == AstKind::IF; }

  virtual void toStream ( std::ostream & os ) const;
};

typedef std::vector<AstVariable *, gc_allocator<AstVariable *> > VectorOfVariable;

class AstClosure : public Ast
{
public:
  AstFrame * const enclosingFrame;
  VectorOfVariable * const params;
  AstVariable * const listParam;
  AstFrame * const paramFrame;
  AstFrame * const bodyFrame;
  ListOfAst const body;

  AstClosure (
    const SourceCoords & coords_,
    AstFrame * enclosingFrame_,
    VectorOfVariable * params_,
    AstVariable * listParam_,
    AstFrame * paramFrame_,
    AstFrame * bodyFrame_,
    const ListOfAst & body_
  ) : Ast( AstKind::CLOSURE, coords_ ),
      enclosingFrame( enclosingFrame_ ),
      params( params_ ),
      listParam( listParam_ ),
      paramFrame( paramFrame_ ),
      bodyFrame( bodyFrame_ ),
      body( body_ )
  {}

  static bool classof ( const AstClosure * ) { return true; }
  static bool classof ( const Ast * t ) { return t->kind == AstKind::CLOSURE; }

  virtual void toStream ( std::ostream & os ) const;
};

class AstLet : public Ast
{
public:
  AstFrame * enclosingFrame;
  VectorOfVariable * params;
  AstFrame * paramFrame;
  AstFrame * bodyFrame;
  ListOfAst body;
  VectorOfListOfAst * values;

  AstLet (
    const SourceCoords & coords_,
    AstFrame * enclosingFrame_,
    VectorOfVariable * params_,
    AstFrame * paramFrame_,
    AstFrame * bodyFrame_,
    const ListOfAst & body_,
    VectorOfListOfAst * values_
  ) : Ast( AstKind::LET, coords_ ),
      enclosingFrame( enclosingFrame_ ),
      params( params_ ),
      paramFrame( paramFrame_ ),
      bodyFrame( bodyFrame_ ),
      body( body_ ),
      values( values_ )
  {}

  static bool classof ( const AstLet * ) { return true; }
  static bool classof ( const Ast * t ) { return t->kind == AstKind::LET; }

  virtual void toStream ( std::ostream & os ) const;

protected:
  AstLet (
    AstKind::Enum code,
    const SourceCoords & coords_,
    AstFrame * enclosingFrame_,
    VectorOfVariable * params_,
    AstFrame * paramFrame_,
    AstFrame * bodyFrame_,
    const ListOfAst & body_,
    VectorOfListOfAst * values_
  ) : Ast( code, coords_ ),
      enclosingFrame( enclosingFrame_ ),
      params( params_ ),
      paramFrame( paramFrame_ ),
      bodyFrame( bodyFrame_ ),
      body( body_ ),
      values( values_ )
  {}
};

/**
 * A restricted form of let where the variables are unassigned (never modified), and the init
 * expressions are all lambdas. This is a synthetic construct - it is never constructed directly
 * from source but is re-constructed from letrec.
 */
class AstFix : public AstLet
{
public:
  AstFix (
    const SourceCoords & coords_,
    AstFrame * enclosingFrame_,
    VectorOfVariable * params_,
    AstFrame * paramFrame_,
    AstFrame * bodyFrame_,
    const ListOfAst & body_,
    VectorOfListOfAst * values_
  );

  static bool classof ( const AstFix * ) { return true; }
  static bool classof ( const Ast * t ) { return t->kind == AstKind::FIX; }

};

}} // namespaces

#endif	/* P1_SMALLS_AST_SCHEMEAST_HPP */

<|endoftext|>


<commit_before>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/

#include "targetsettingspanel.h"

#include "addtargetdialog.h"
#include "buildsettingspropertiespage.h"
#include "project.h"
#include "projectwindow.h"
#include "runsettingspropertiespage.h"
#include "target.h"
#include "targetsettingswidget.h"

#include <extensionsystem/pluginmanager.h>

#include <QtCore/QCoreApplication>
#include <QtGui/QLabel>
#include <QtGui/QMessageBox>
#include <QtGui/QVBoxLayout>

using namespace ProjectExplorer;
using namespace ProjectExplorer::Internal;

///
// TargetSettingsPanelFactory
///

QString TargetSettingsPanelFactory::id() const
{
    return QLatin1String(TARGETSETTINGS_PANEL_ID);
}

QString TargetSettingsPanelFactory::displayName() const
{
    return QCoreApplication::translate("TargetSettingsPanelFactory", "Targets");
}

bool TargetSettingsPanelFactory::supports(Project *project)
{
    Q_UNUSED(project);
    return true;
}

bool TargetSettingsPanelFactory::supports(Target *target)
{
    Q_UNUSED(target);
    return false;
}

IPropertiesPanel *TargetSettingsPanelFactory::createPanel(Project *project)
{
    return new TargetSettingsPanel(project);
}

IPropertiesPanel *TargetSettingsPanelFactory::createPanel(Target *target)
{
    Q_UNUSED(target);
    return 0;
}

///
// TargetSettingsPanel
///

TargetSettingsPanel::TargetSettingsPanel(Project *project) :
    m_widget(new TargetSettingsPanelWidget(project))
{
}

TargetSettingsPanel::~TargetSettingsPanel()
{
    delete m_widget;
}

QString TargetSettingsPanel::displayName() const
{
    return QCoreApplication::translate("TargetSettingsPanel", "Targets");
}

QWidget *TargetSettingsPanel::widget() const
{
    return m_widget;
}

QIcon TargetSettingsPanel::icon() const
{
    return QIcon();
}

///
// TargetSettingsWidget
///

TargetSettingsPanelWidget::TargetSettingsPanelWidget(Project *project) :
    m_currentIndex(-1),
    m_project(project),
    m_selector(0),
    m_centralWidget(0)
{
    m_panelWidgets[0] = 0;
    m_panelWidgets[1] = 0;

    setupUi();

    connect(m_project, SIGNAL(addedTarget(ProjectExplorer::Target*)),
            this, SLOT(targetAdded(ProjectExplorer::Target*)));
    connect(m_project, SIGNAL(aboutToRemoveTarget(ProjectExplorer::Target*)),
            this, SLOT(aboutToRemoveTarget(ProjectExplorer::Target*)));
    connect(m_project, SIGNAL(activeTargetChanged(ProjectExplorer::Target*)),
            this, SLOT(activeTargetChanged(ProjectExplorer::Target*)));
}

TargetSettingsPanelWidget::~TargetSettingsPanelWidget()
{
}

void TargetSettingsPanelWidget::setupUi()
{
    QVBoxLayout *viewLayout = new QVBoxLayout(this);
    viewLayout->setMargin(0);
    viewLayout->setSpacing(0);

    m_selector = new TargetSettingsWidget(this);
    viewLayout->addWidget(m_selector);

    // Setup our container for the contents:
    m_centralWidget = new QStackedWidget(this);
    m_selector->setCentralWidget(m_centralWidget);

    // no projects label:
    m_noTargetLabel = new QWidget;
    QVBoxLayout *noTargetLayout = new QVBoxLayout;
    noTargetLayout->setMargin(0);
    QLabel *label = new QLabel(m_noTargetLabel);
    label->setText(tr("No target defined."));
    {
        QFont f = label->font();
        f.setPointSizeF(f.pointSizeF() * 1.4);
        f.setBold(true);
        label->setFont(f);
    }
    label->setMargin(10);
    label->setAlignment(Qt::AlignTop);
    noTargetLayout->addWidget(label);
    noTargetLayout->addStretch(10);
    m_centralWidget->addWidget(m_noTargetLabel);

    foreach (Target *t, m_project->targets())
        targetAdded(t);
    m_selector->markActive(m_targets.indexOf(m_project->activeTarget()));

    connect(m_selector, SIGNAL(currentIndexChanged(int,int)),
            this, SLOT(currentTargetIndexChanged(int,int)));
    connect(m_selector, SIGNAL(addButtonClicked()),
            this, SLOT(addTarget()));
    connect(m_selector, SIGNAL(removeButtonClicked()),
            this, SLOT(removeTarget()));

    if (m_project->targets().count())
        currentTargetIndexChanged(m_targets.indexOf(m_project->activeTarget()), 0);
}

void TargetSettingsPanelWidget::currentTargetIndexChanged(int targetIndex, int subIndex)
{
    if (targetIndex < -1 || targetIndex >= m_targets.count())
        return;
    if (subIndex < -1 || subIndex >= 2)
        return;
    m_selector->setCurrentIndex(targetIndex);
    m_selector->setCurrentSubIndex(subIndex);

    Target *target(m_targets.at(targetIndex));

    // Target was not actually changed:
    if (m_currentIndex == targetIndex) {
        if (m_panelWidgets[subIndex])
            m_centralWidget->setCurrentWidget(m_panelWidgets[subIndex]);
        else
            m_centralWidget->setCurrentWidget(m_noTargetLabel);
        return;
    }

    m_currentIndex = targetIndex;

    // Target has changed:
    if (targetIndex == -1) { // no more targets!
        m_centralWidget->setCurrentWidget(m_noTargetLabel);
        return;
    }

    PanelsWidget *buildPanel(new PanelsWidget(m_centralWidget));
    PanelsWidget *runPanel(new PanelsWidget(m_centralWidget));

    foreach (IPanelFactory *panelFactory, ExtensionSystem::PluginManager::instance()->getObjects<IPanelFactory>()) {
        if (panelFactory->id() == QLatin1String(BUILDSETTINGS_PANEL_ID)) {
            IPropertiesPanel *panel = panelFactory->createPanel(target);
            buildPanel->addPropertiesPanel(panel);
            continue;
        }
        if (panelFactory->id() == QLatin1String(RUNSETTINGS_PANEL_ID)) {
            IPropertiesPanel *panel = panelFactory->createPanel(target);
            runPanel->addPropertiesPanel(panel);
            continue;
        }
    }
    m_centralWidget->addWidget(buildPanel);
    m_centralWidget->addWidget(runPanel);

    m_centralWidget->setCurrentWidget(subIndex == 0 ? buildPanel : runPanel);

    delete m_panelWidgets[0];
    m_panelWidgets[0] = buildPanel;
    delete m_panelWidgets[1];
    m_panelWidgets[1] = runPanel;
}

void TargetSettingsPanelWidget::addTarget()
{
    AddTargetDialog dialog(m_project);
    dialog.exec();
}

void TargetSettingsPanelWidget::removeTarget()
{
    int index = m_selector->currentIndex();
    Target *t = m_targets.at(index);
    int ret = QMessageBox::warning(this, tr("Qt Creator"),
                                   tr("Do you really want to remove the\n"
                                      "\"%1\" target?").arg(t->displayName()),
                                    QMessageBox::Yes | QMessageBox::No,
                                    QMessageBox::No);
    if (ret == QMessageBox::Yes)
        m_project->removeTarget(t);
}

void TargetSettingsPanelWidget::targetAdded(ProjectExplorer::Target *target)
{
    Q_ASSERT(m_project == target->project());
    Q_ASSERT(m_selector);

    for (int pos = 0; pos <= m_targets.count(); ++pos) {
        if (m_targets.count() == pos ||
            m_targets.at(pos)->displayName() > target->displayName()) {
            m_targets.insert(pos, target);
            m_selector->insertTarget(pos, target->displayName());
            break;
        }
    }

    m_selector->setAddButtonEnabled(m_project->possibleTargetIds().count() > 0);
    m_selector->setRemoveButtonEnabled(m_project->targets().count() > 1);
}

void TargetSettingsPanelWidget::aboutToRemoveTarget(ProjectExplorer::Target *target)
{
    Q_ASSERT(m_project == target->project());
    Q_ASSERT(m_selector);

    int index(m_targets.indexOf(target));
    if (index < 0)
        return;
    m_targets.removeAt(index);

    m_selector->removeTarget(index);
    m_selector->setAddButtonEnabled(m_project->possibleTargetIds().count() > 0);
    m_selector->setRemoveButtonEnabled(m_project->targets().count() > 2); // target is not yet removed!
}

void TargetSettingsPanelWidget::activeTargetChanged(ProjectExplorer::Target *target)
{
    Q_ASSERT(m_project == target->project());
    Q_ASSERT(m_selector);

    int index(m_targets.indexOf(target));
    m_selector->markActive(index);
}
<commit_msg>Fix and simplify enabling/disabling of target add/remove buttons<commit_after>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/

#include "targetsettingspanel.h"

#include "addtargetdialog.h"
#include "buildsettingspropertiespage.h"
#include "project.h"
#include "projectwindow.h"
#include "runsettingspropertiespage.h"
#include "target.h"
#include "targetsettingswidget.h"

#include <extensionsystem/pluginmanager.h>

#include <QtCore/QCoreApplication>
#include <QtGui/QLabel>
#include <QtGui/QMessageBox>
#include <QtGui/QVBoxLayout>

using namespace ProjectExplorer;
using namespace ProjectExplorer::Internal;

///
// TargetSettingsPanelFactory
///

QString TargetSettingsPanelFactory::id() const
{
    return QLatin1String(TARGETSETTINGS_PANEL_ID);
}

QString TargetSettingsPanelFactory::displayName() const
{
    return QCoreApplication::translate("TargetSettingsPanelFactory", "Targets");
}

bool TargetSettingsPanelFactory::supports(Project *project)
{
    Q_UNUSED(project);
    return true;
}

bool TargetSettingsPanelFactory::supports(Target *target)
{
    Q_UNUSED(target);
    return false;
}

IPropertiesPanel *TargetSettingsPanelFactory::createPanel(Project *project)
{
    return new TargetSettingsPanel(project);
}

IPropertiesPanel *TargetSettingsPanelFactory::createPanel(Target *target)
{
    Q_UNUSED(target);
    return 0;
}

///
// TargetSettingsPanel
///

TargetSettingsPanel::TargetSettingsPanel(Project *project) :
    m_widget(new TargetSettingsPanelWidget(project))
{
}

TargetSettingsPanel::~TargetSettingsPanel()
{
    delete m_widget;
}

QString TargetSettingsPanel::displayName() const
{
    return QCoreApplication::translate("TargetSettingsPanel", "Targets");
}

QWidget *TargetSettingsPanel::widget() const
{
    return m_widget;
}

QIcon TargetSettingsPanel::icon() const
{
    return QIcon();
}

///
// TargetSettingsWidget
///

TargetSettingsPanelWidget::TargetSettingsPanelWidget(Project *project) :
    m_currentIndex(-1),
    m_project(project),
    m_selector(0),
    m_centralWidget(0)
{
    m_panelWidgets[0] = 0;
    m_panelWidgets[1] = 0;

    setupUi();

    connect(m_project, SIGNAL(addedTarget(ProjectExplorer::Target*)),
            this, SLOT(targetAdded(ProjectExplorer::Target*)));
    connect(m_project, SIGNAL(aboutToRemoveTarget(ProjectExplorer::Target*)),
            this, SLOT(aboutToRemoveTarget(ProjectExplorer::Target*)));
    connect(m_project, SIGNAL(activeTargetChanged(ProjectExplorer::Target*)),
            this, SLOT(activeTargetChanged(ProjectExplorer::Target*)));
}

TargetSettingsPanelWidget::~TargetSettingsPanelWidget()
{
}

void TargetSettingsPanelWidget::setupUi()
{
    QVBoxLayout *viewLayout = new QVBoxLayout(this);
    viewLayout->setMargin(0);
    viewLayout->setSpacing(0);

    m_selector = new TargetSettingsWidget(this);
    viewLayout->addWidget(m_selector);

    // Setup our container for the contents:
    m_centralWidget = new QStackedWidget(this);
    m_selector->setCentralWidget(m_centralWidget);

    // no projects label:
    m_noTargetLabel = new QWidget;
    QVBoxLayout *noTargetLayout = new QVBoxLayout;
    noTargetLayout->setMargin(0);
    QLabel *label = new QLabel(m_noTargetLabel);
    label->setText(tr("No target defined."));
    {
        QFont f = label->font();
        f.setPointSizeF(f.pointSizeF() * 1.4);
        f.setBold(true);
        label->setFont(f);
    }
    label->setMargin(10);
    label->setAlignment(Qt::AlignTop);
    noTargetLayout->addWidget(label);
    noTargetLayout->addStretch(10);
    m_centralWidget->addWidget(m_noTargetLabel);

    foreach (Target *t, m_project->targets())
        targetAdded(t);
    m_selector->markActive(m_targets.indexOf(m_project->activeTarget()));

    connect(m_selector, SIGNAL(currentIndexChanged(int,int)),
            this, SLOT(currentTargetIndexChanged(int,int)));
    connect(m_selector, SIGNAL(addButtonClicked()),
            this, SLOT(addTarget()));
    connect(m_selector, SIGNAL(removeButtonClicked()),
            this, SLOT(removeTarget()));

    if (m_project->targets().count())
        currentTargetIndexChanged(m_targets.indexOf(m_project->activeTarget()), 0);
}

void TargetSettingsPanelWidget::currentTargetIndexChanged(int targetIndex, int subIndex)
{
    if (targetIndex < -1 || targetIndex >= m_targets.count())
        return;
    if (subIndex < -1 || subIndex >= 2)
        return;
    m_selector->setCurrentIndex(targetIndex);
    m_selector->setCurrentSubIndex(subIndex);

    Target *target(m_targets.at(targetIndex));

    // Target was not actually changed:
    if (m_currentIndex == targetIndex) {
        if (m_panelWidgets[subIndex])
            m_centralWidget->setCurrentWidget(m_panelWidgets[subIndex]);
        else
            m_centralWidget->setCurrentWidget(m_noTargetLabel);
        return;
    }

    m_currentIndex = targetIndex;

    // Target has changed:
    if (targetIndex == -1) { // no more targets!
        m_centralWidget->setCurrentWidget(m_noTargetLabel);
        return;
    }

    PanelsWidget *buildPanel(new PanelsWidget(m_centralWidget));
    PanelsWidget *runPanel(new PanelsWidget(m_centralWidget));

    foreach (IPanelFactory *panelFactory, ExtensionSystem::PluginManager::instance()->getObjects<IPanelFactory>()) {
        if (panelFactory->id() == QLatin1String(BUILDSETTINGS_PANEL_ID)) {
            IPropertiesPanel *panel = panelFactory->createPanel(target);
            buildPanel->addPropertiesPanel(panel);
            continue;
        }
        if (panelFactory->id() == QLatin1String(RUNSETTINGS_PANEL_ID)) {
            IPropertiesPanel *panel = panelFactory->createPanel(target);
            runPanel->addPropertiesPanel(panel);
            continue;
        }
    }
    m_centralWidget->addWidget(buildPanel);
    m_centralWidget->addWidget(runPanel);

    m_centralWidget->setCurrentWidget(subIndex == 0 ? buildPanel : runPanel);

    delete m_panelWidgets[0];
    m_panelWidgets[0] = buildPanel;
    delete m_panelWidgets[1];
    m_panelWidgets[1] = runPanel;
}

void TargetSettingsPanelWidget::addTarget()
{
    AddTargetDialog dialog(m_project);
    dialog.exec();
}

void TargetSettingsPanelWidget::removeTarget()
{
    int index = m_selector->currentIndex();
    Target *t = m_targets.at(index);
    int ret = QMessageBox::warning(this, tr("Qt Creator"),
                                   tr("Do you really want to remove the\n"
                                      "\"%1\" target?").arg(t->displayName()),
                                    QMessageBox::Yes | QMessageBox::No,
                                    QMessageBox::No);
    if (ret == QMessageBox::Yes)
        m_project->removeTarget(t);
}

void TargetSettingsPanelWidget::targetAdded(ProjectExplorer::Target *target)
{
    Q_ASSERT(m_project == target->project());
    Q_ASSERT(m_selector);

    for (int pos = 0; pos <= m_targets.count(); ++pos) {
        if (m_targets.count() == pos ||
            m_targets.at(pos)->displayName() > target->displayName()) {
            m_targets.insert(pos, target);
            m_selector->insertTarget(pos, target->displayName());
            break;
        }
    }

    m_selector->setAddButtonEnabled(m_project->supportedTargetIds().count() != m_targets.count());
    m_selector->setRemoveButtonEnabled(m_project->targets().count() > 1);
}

void TargetSettingsPanelWidget::aboutToRemoveTarget(ProjectExplorer::Target *target)
{
    Q_ASSERT(m_project == target->project());
    Q_ASSERT(m_selector);

    int index(m_targets.indexOf(target));
    if (index < 0)
        return;
    m_targets.removeAt(index);

    m_selector->removeTarget(index);
    m_selector->setAddButtonEnabled(m_project->supportedTargetIds().count() != m_targets.count());
    m_selector->setRemoveButtonEnabled(m_targets.count() > 1);
}

void TargetSettingsPanelWidget::activeTargetChanged(ProjectExplorer::Target *target)
{
    Q_ASSERT(m_project == target->project());
    Q_ASSERT(m_selector);

    int index(m_targets.indexOf(target));
    m_selector->markActive(index);
}
<|endoftext|>