<commit_before>#include <stdlib.h>
#include <sys/socket.h>
#include <string.h>
#include <netinet/in.h>
#include <cstring>
#include <stdio.h>
#include <string>
#include <iostream>
#include <list>
#include <map>
#include <set>

#include "server.h"
#include "duckchat.h"

// TODO Handle domain
// Server can accept connections.
// Server handles Login and Logout from users, and keeps records of which users are logged in.
// Server handles Join and Leave from users, keeps records of which channels a user belongs to,
// and keeps records of which users are in a channel.
// TODO Server handles the Say message.
// TODO Server correctly handles List and Who.
// TODO Create copies of your client and server source. Modify them to send invalid packets to your good client
// and server, to see if you can make your client or server crash. Fix any bugs you find.

//std::string user;

class Channel {
public:
  std::string name;
  std::list<User *> users;

  Channel(std::string name): name(name) {};
};

class User {
public:
  std::string name;
  in_addr_t address;
  unsigned short port;
//  std::set<Channel *> channels;

  User(std::string name, in_addr_t address, unsigned short port): name(name), address(address), port(port) {};
};

std::map<std::string, User *> kUsers;
std::map<std::string, Channel *> kChannels;

void Error(const char *msg) {
  perror(msg);
  exit(1);
}

void ProcessRequest(int server_socket, void *buffer, in_addr_t user_address, unsigned short user_port) {
  struct request current_request;
  User *current_user;
  Channel *channel;
  std::string current_channel;
  std::list<User *>::const_iterator it;
  bool is_new_channel;
  bool is_channel;

  memcpy(&current_request, buffer, sizeof(struct request));
//  std::cout << "request type: " << current_request.req_type << std::endl;
  request_t request_type = current_request.req_type;

  switch(request_type) {
    case REQ_LOGIN:
      struct request_login login_request;
      memcpy(&login_request, buffer, sizeof(struct request_login));

      current_user = new User(login_request.req_username, user_address, user_port);
      kUsers.insert({std::string(login_request.req_username), current_user});

      std::cout << "server: " << login_request.req_username << " logs in" << std::endl;
      break;

    case REQ_LOGOUT:
      struct request_logout logout_request;
      memcpy(&logout_request, buffer, sizeof(struct request_logout));

      for (auto user : kUsers) {
        unsigned short current_port = user.second->port;
        in_addr_t current_address = user.second->address;

        if (current_port == user_port && current_address == user_address) {
          std::cout << "server: " << user.first << " logs out" << std::endl;
          kUsers.erase(user.first);
          break;
        }
      }
      break;

    case REQ_LEAVE:
      struct request_leave leave_request;
      memcpy(&leave_request, buffer, sizeof(struct request_leave));
      current_channel = leave_request.req_channel;
      for (auto user : kUsers) {
        unsigned short current_port = user.second->port;
        in_addr_t current_address = user.second->address;

        if (current_port == user_port && current_address == user_address) {
          is_channel = false;
          for(auto ch : kChannels){
            if(ch.first == current_channel){
              std::cout << "channel found" << std::endl;
              is_channel = true;
              break;
            }
          }

          if(is_channel){
            channel = kChannels[current_channel];

            for (it = channel->users.begin(); it != channel->users.end(); ++it){
              if((*it)->name == user.first){
                break;
              }
            }

            if( it != channel->users.end()){
              channel->users.remove(*it);
              std::cout << user.first << " leaves channel " << channel->name << std::endl;
              if (channel->users.size() == 0) {
                kChannels.erase(channel->name);
                std::cout << "server: removing empty channel " << channel->name << std::endl;
              }
            }
            for (auto u : channel->users) {
              std::cout << "user: " << u->name << std::endl;
            }
            break;
          } else {
            std::cout << "server: " << user.first << " trying to leave non-existent channel " << channel->name << std::endl;
          }

        }
      }
      break;
    case REQ_JOIN:
      struct request_join join_request;
      memcpy(&join_request, buffer, sizeof(struct request_join));
      is_new_channel = true;

      // If channel does exists in global map, set local channel to channel from kChannels
      for (auto ch : kChannels) {
        if (join_request.req_channel == ch.second->name) {
          is_new_channel = false;
          channel = ch.second;
          break;
        }
      }

      // If channel is new create a new channel
      if (is_new_channel) {
        channel = new Channel(join_request.req_channel);
      }

      for (auto user : kUsers) {
        unsigned short current_port = user.second->port;
        in_addr_t current_address = user.second->address;

        if (current_port == user_port && current_address == user_address) {
          std::cout << "server: " << user.first << " joins channel "<< channel->name << std::endl;

          channel->users.push_back(user.second);

          // Otherwise
          if (is_new_channel) {
            kChannels.insert({channel->name, channel});
          }

          // Test print
          for (auto u : channel->users) {
            std::cout << "user: " << u->name << std::endl;
          }
          break;
        }

      }
      break;
    case REQ_SAY:
      struct request_say say_request;
      memcpy(&say_request, buffer, sizeof(struct request_say));

      std::cout << "user said: " << say_request.req_text << std::endl;
      for(auto user : kChannels[say_request.req_channel]->users){
        std::cout << "server sending message to: " << user->name << std::endl;
        struct sockaddr_in client_addr;
        struct text_say say;
        memcpy(&say, buffer, sizeof(struct text_say));

        memset(&client_addr, 0, sizeof(struct sockaddr_in));
        client_addr.sin_family = AF_INET;
        client_addr.sin_port = htons(user->port);
        client_addr.sin_addr.s_addr = htonl(user->address);

        strncpy(say.txt_channel, say_request.req_channel, CHANNEL_MAX);
        strncpy(say.txt_text, say_request.req_text, SAY_MAX);
        say.txt_type = TXT_SAY;
        strncpy(say.txt_username, user->name.c_str(), USERNAME_MAX);

        size_t message_size = sizeof(struct text_say);

        if (sendto(server_socket, &say, message_size, 0, (struct sockaddr*) &client_addr, sizeof(client_addr)) < 0) {
          Error("server: failed to send say\n");
        }

      }
      break;
    default:
      break;
  }
}

int main(int argc, char *argv[]) {
  struct sockaddr_in server_addr;

  int server_socket;
  int receive_len;
  void* buffer[kBufferSize];
  int port;
//  std::string domain;

  if (argc < 3) {
    std::cerr << "Usage: ./server domain_name port_num" << std::endl;
    exit(1);
  }

//  domain = argv[1];
  port = atoi(argv[2]);

  memset((char *) &server_addr, 0, sizeof(server_addr));
  server_addr.sin_family = AF_INET;
  server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
  server_addr.sin_port = htons(port);

  if ((server_socket = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
    Error("server: can't open socket\n");
  }

  if (bind(server_socket, (struct sockaddr *) &server_addr, sizeof(server_addr)) < 0) {
    Error("server: bind failed\n");
  }

  printf("server: waiting on port %d\n", port);
  while (1) {
    struct sockaddr_in client_addr;
    socklen_t client_addr_len = sizeof(client_addr);
//    std::cout << "before recvfrom" << std::endl;
    receive_len = recvfrom(server_socket, buffer, kBufferSize, 0, (struct sockaddr *) &client_addr, &client_addr_len);
    if (receive_len > 0) {
      buffer[receive_len] = 0;

//      std::cout << "port " << client_addr.sin_port << std::endl;

      ProcessRequest(server_socket, buffer, client_addr.sin_addr.s_addr, client_addr.sin_port);
    }
  }
}
<commit_msg>print testing<commit_after>#include <stdlib.h>
#include <sys/socket.h>
#include <string.h>
#include <netinet/in.h>
#include <cstring>
#include <stdio.h>
#include <string>
#include <iostream>
#include <list>
#include <map>
#include <set>

#include "server.h"
#include "duckchat.h"

// TODO Handle domain
// Server can accept connections.
// Server handles Login and Logout from users, and keeps records of which users are logged in.
// Server handles Join and Leave from users, keeps records of which channels a user belongs to,
// and keeps records of which users are in a channel.
// TODO Server handles the Say message.
// TODO Server correctly handles List and Who.
// TODO Create copies of your client and server source. Modify them to send invalid packets to your good client
// and server, to see if you can make your client or server crash. Fix any bugs you find.

//std::string user;

class Channel {
public:
  std::string name;
  std::list<User *> users;

  Channel(std::string name): name(name) {};
};

class User {
public:
  std::string name;
  in_addr_t address;
  unsigned short port;
//  std::set<Channel *> channels;

  User(std::string name, in_addr_t address, unsigned short port): name(name), address(address), port(port) {};
};

struct sockaddr_in most_recent_client_addr;
std::map<std::string, User *> kUsers;
std::map<std::string, Channel *> kChannels;

void Error(const char *msg) {
  perror(msg);
  exit(1);
}

void ProcessRequest(int server_socket, void *buffer, in_addr_t user_address, unsigned short user_port) {
  struct request current_request;
  User *current_user;
  Channel *channel;
  std::string current_channel;
  std::list<User *>::const_iterator it;
  bool is_new_channel;
  bool is_channel;

  memcpy(&current_request, buffer, sizeof(struct request));
//  std::cout << "request type: " << current_request.req_type << std::endl;
  request_t request_type = current_request.req_type;

  switch(request_type) {
    case REQ_LOGIN:
      struct request_login login_request;
      memcpy(&login_request, buffer, sizeof(struct request_login));

      current_user = new User(login_request.req_username, user_address, user_port);
      kUsers.insert({std::string(login_request.req_username), current_user});

      std::cout << "server: " << login_request.req_username << " logs in" << std::endl;
      break;

    case REQ_LOGOUT:
      struct request_logout logout_request;
      memcpy(&logout_request, buffer, sizeof(struct request_logout));

      for (auto user : kUsers) {
        unsigned short current_port = user.second->port;
        in_addr_t current_address = user.second->address;

        if (current_port == user_port && current_address == user_address) {
          std::cout << "server: " << user.first << " logs out" << std::endl;
          kUsers.erase(user.first);
          break;
        }
      }
      break;

    case REQ_LEAVE:
      struct request_leave leave_request;
      memcpy(&leave_request, buffer, sizeof(struct request_leave));
      current_channel = leave_request.req_channel;
      for (auto user : kUsers) {
        unsigned short current_port = user.second->port;
        in_addr_t current_address = user.second->address;

        if (current_port == user_port && current_address == user_address) {
          is_channel = false;
          for(auto ch : kChannels){
            if(ch.first == current_channel){
              std::cout << "channel found" << std::endl;
              is_channel = true;
              break;
            }
          }

          if(is_channel){
            channel = kChannels[current_channel];

            for (it = channel->users.begin(); it != channel->users.end(); ++it){
              if((*it)->name == user.first){
                break;
              }
            }

            if( it != channel->users.end()){
              channel->users.remove(*it);
              std::cout << user.first << " leaves channel " << channel->name << std::endl;
              if (channel->users.size() == 0) {
                kChannels.erase(channel->name);
                std::cout << "server: removing empty channel " << channel->name << std::endl;
              }
            }
            for (auto u : channel->users) {
              std::cout << "user: " << u->name << std::endl;
            }
            break;
          } else {
            std::cout << "server: " << user.first << " trying to leave non-existent channel " << channel->name << std::endl;
          }

        }
      }
      break;
    case REQ_JOIN:
      struct request_join join_request;
      memcpy(&join_request, buffer, sizeof(struct request_join));
      is_new_channel = true;

      // If channel does exists in global map, set local channel to channel from kChannels
      for (auto ch : kChannels) {
        if (join_request.req_channel == ch.second->name) {
          is_new_channel = false;
          channel = ch.second;
          break;
        }
      }

      // If channel is new create a new channel
      if (is_new_channel) {
        channel = new Channel(join_request.req_channel);
      }

      for (auto user : kUsers) {
        unsigned short current_port = user.second->port;
        in_addr_t current_address = user.second->address;

        if (current_port == user_port && current_address == user_address) {
          std::cout << "server: " << user.first << " joins channel "<< channel->name << std::endl;

          channel->users.push_back(user.second);

          // Otherwise
          if (is_new_channel) {
            kChannels.insert({channel->name, channel});
          }

          // Test print
          for (auto u : channel->users) {
            std::cout << "user: " << u->name << std::endl;
          }
          break;
        }

      }
      break;
    case REQ_SAY:
      struct request_say say_request;
      memcpy(&say_request, buffer, sizeof(struct request_say));

      std::cout << "user said: " << say_request.req_text << std::endl;
      for(auto user : kChannels[say_request.req_channel]->users){
        std::cout << "server sending message to: " << user->name << std::endl;
        struct sockaddr_in client_addr;
        struct text_say say;
        memcpy(&say, buffer, sizeof(struct text_say));

        memset(&client_addr, 0, sizeof(struct sockaddr_in));
        client_addr.sin_family = AF_INET;
        client_addr.sin_port = htons(user->port);
        client_addr.sin_addr.s_addr = htonl(user->address);

        strncpy(say.txt_channel, say_request.req_channel, CHANNEL_MAX);
        strncpy(say.txt_text, say_request.req_text, SAY_MAX);
        say.txt_type = TXT_SAY;
        strncpy(say.txt_username, user->name.c_str(), USERNAME_MAX);

        size_t message_size = sizeof(struct text_say);

        if (sendto(server_socket, &say, message_size, 0, (struct sockaddr*) &client_addr, sizeof(client_addr)) < 0) {
          Error("server: failed to send say\n");
        }

      }
      break;
    default:
      break;
  }
}

int main(int argc, char *argv[]) {
  struct sockaddr_in server_addr;

  int server_socket;
  int receive_len;
  void* buffer[kBufferSize];
  int port;
//  std::string domain;

  if (argc < 3) {
    std::cerr << "Usage: ./server domain_name port_num" << std::endl;
    exit(1);
  }

//  domain = argv[1];
  port = atoi(argv[2]);

  memset((char *) &server_addr, 0, sizeof(server_addr));
  server_addr.sin_family = AF_INET;
  server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
  server_addr.sin_port = htons(port);

  if ((server_socket = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
    Error("server: can't open socket\n");
  }

  if (bind(server_socket, (struct sockaddr *) &server_addr, sizeof(server_addr)) < 0) {
    Error("server: bind failed\n");
  }

  printf("server: waiting on port %d\n", port);
  while (1) {
    struct sockaddr_in client_addr;
    socklen_t client_addr_len = sizeof(client_addr);
//    std::cout << "before recvfrom" << std::endl;
    receive_len = recvfrom(server_socket, buffer, kBufferSize, 0, (struct sockaddr *) &client_addr, &client_addr_len);
    memcpy(&most_recent_client_addr, &client_addr, sizeof(most_recent_client_addr));
    std::cout << "port " << most_recent_client_addr.sin_port << std::endl;

    if (receive_len > 0) {
      buffer[receive_len] = 0;

//      std::cout << "port " << client_addr.sin_port << std::endl;

      ProcessRequest(server_socket, buffer, client_addr.sin_addr.s_addr, client_addr.sin_port);
    }
  }
}
<|endoftext|>


<commit_before>#define byte uint8_t

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <cstring>
#include <unistd.h>
#include <wiringPi.h>
#include <iostream>
#include <sys/types.h>

using namespace std;

const byte rfPin = 7;

void SelectPlus(uint32_t address) {
    int pulseWidth = 325; // Pulse width in uS
    byte repeat = 40;     // Repeat send
    uint32_t databit;
    uint32_t mask = 0x10000;
    uint32_t sendbuff;

    for (byte j = 0; j <= repeat; j++) {
        sendbuff = address;
        // send 3 HIGH pulses for syncing
        digitalWrite(rfPin, HIGH);
        delayMicroseconds(pulseWidth * 3);

        // Send command
        for (int i = 0; i < 17; i++) {  // 13+4 bits
            databit = sendbuff & mask; // Get most left bit
            sendbuff = (sendbuff << 1);// Shift left

            if (databit != mask) {                 // Write 0
                digitalWrite(rfPin, LOW);
                delayMicroseconds(pulseWidth);
                digitalWrite(rfPin, HIGH);
                delayMicroseconds(pulseWidth * 3);
            } else {                               // Write 1
                digitalWrite(rfPin, LOW);
                delayMicroseconds(pulseWidth * 3);
                digitalWrite(rfPin, HIGH);
                delayMicroseconds(pulseWidth);
            }
        }
        digitalWrite(rfPin, LOW);
        delayMicroseconds(pulseWidth * 16);
    }
}

int main(int argc, char* argv[])
{
    // Check if WiringPi is properly installed.
    if (wiringPiSetup () == -1) {
      std::cout << "Please install WiringPi first (http://wiringpi.com/download-and-install/)." << '\n';
      return 1;
    }

    // Check if an argument is present.
    if (argc < 2) {
      std::cout << "Please enter at least one argument: ./Ring white" << '\n' << "You can also use multiple arguments: ./Ring black white black." << '\n';
      return 1;
    }

    // Loop through arguments.
    for (int count=1; count < argc; ++count) {
        if (!strcmp(argv[count], "white")) {
            SelectPlus(0x1BB40); // White
            std::cout << count << " Ding Dong (White) " << '\n';
        } else {
            SelectPlus(0x1C330); // Black
            std::cout << count << " Ding Dong (Black)" << '\n';
        }
        if (count < argc) {
            std::cout << count << " Pause (5s)" << '\n';
            usleep(5000000);
        }
    }
}

/*           ___
'0':     _|   |   (T,3T)
            _
'1':    ___| |     (3T,T)
*/
<commit_msg>Update ring.cpp<commit_after>#define byte uint8_t

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <cstring>
#include <unistd.h>
#include <wiringPi.h>
#include <iostream>
#include <sys/types.h>

using namespace std;

const byte rfPin = 7;

void SelectPlus(uint32_t address) {
    int pulseWidth = 325; // Pulse width in uS
    byte repeat = 40;     // Repeat send
    uint32_t databit;
    uint32_t mask = 0x10000;
    uint32_t sendbuff;

    for (byte j = 0; j <= repeat; j++) {
        sendbuff = address;
        // send 3 HIGH pulses for syncing
        digitalWrite(rfPin, HIGH);
        delayMicroseconds(pulseWidth * 3);

        // Send command
        for (int i = 0; i < 17; i++) {  // 13+4 bits
            databit = sendbuff & mask; // Get most left bit
            sendbuff = (sendbuff << 1);// Shift left

            if (databit != mask) {                 // Write 0
                digitalWrite(rfPin, LOW);
                delayMicroseconds(pulseWidth);
                digitalWrite(rfPin, HIGH);
                delayMicroseconds(pulseWidth * 3);
            } else {                               // Write 1
                digitalWrite(rfPin, LOW);
                delayMicroseconds(pulseWidth * 3);
                digitalWrite(rfPin, HIGH);
                delayMicroseconds(pulseWidth);
            }
        }
        digitalWrite(rfPin, LOW);
        delayMicroseconds(pulseWidth * 16);
    }
}

int main(int argc, char* argv[])
{
    // Check if WiringPi is properly installed.
    if (wiringPiSetup () == -1) {
      std::cout << "Please install WiringPi first (http://wiringpi.com/download-and-install/)." << '\n';
      return 1;
    }

    // Check if an argument is present.
    if (argc < 2) {
      std::cout << "Please enter at least one argument: ./Ring white" << '\n' << "You can also use multiple arguments: ./Ring black white black." << '\n';
      return 1;
    }

    // Loop through arguments.
    for (int count=1; count < argc; ++count) {
        if (!strcmp(argv[count], "white")) {
            SelectPlus(0x3BB40); // White
            std::cout << count << " Ding Dong (White) " << '\n';
        } else {
            SelectPlus(0x3C330); // Black
            std::cout << count << " Ding Dong (Black)" << '\n';
        }
        if (count < argc) {
            std::cout << count << " Pause (5s)" << '\n';
            usleep(5000000);
        }
    }
}

/*           ___
'0':     _|   |   (T,3T)
            _
'1':    ___| |     (3T,T)
*/
<|endoftext|>


<commit_before>/* BEGIN_COMMON_COPYRIGHT_HEADER
 * (c)LGPL2+
 *
 * LXDE-Qt - a lightweight, Qt based, desktop toolset
 * http://razor-qt.org
 *
 * Copyright: 2012 Razor team
 * Authors:
 *   Alexander Sokoloff <sokoloff.a@gmail.com>
 *
 * This program or library is free software; you can redistribute it
 * and/or modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.

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

#include "plugin.h"
#include "ilxqtpanelplugin.h"
#include "pluginsettings_p.h"
#include "lxqtpanel.h"
#include <QDebug>
#include <QProcessEnvironment>
#include <QStringList>
#include <QDir>
#include <QFileInfo>
#include <QPluginLoader>
#include <QGridLayout>
#include <QDialog>
#include <QEvent>
#include <QMenu>
#include <QMouseEvent>
#include <QApplication>
#include <memory>

#include <LXQt/Settings>
#include <LXQt/Translator>
#include <XdgIcon>

// statically linked built-in plugins
#include "../plugin-clock/lxqtclock.h" // clock
extern void * loadPluginTranslation_clock_helper;
#include "../plugin-desktopswitch/desktopswitch.h" // desktopswitch
extern void * loadPluginTranslation_desktopswitch_helper;
#include "../plugin-mainmenu/lxqtmainmenu.h" // mainmenu
extern void * loadPluginTranslation_mainmenu_helper;
#include "../plugin-quicklaunch/lxqtquicklaunchplugin.h" // quicklaunch
extern void * loadPluginTranslation_quicklaunch_helper;
#include "../plugin-showdesktop/showdesktop.h" // showdesktop
extern void * loadPluginTranslation_showdesktop_helper;
#include "../plugin-spacer/spacer.h" // spacer
extern void * loadPluginTranslation_spacer_helper;
#include "../plugin-statusnotifier/statusnotifier.h" // statusnotifier
extern void * loadPluginTranslation_statusnotifier_helper;
#include "../plugin-taskbar/lxqttaskbarplugin.h" // taskbar
extern void * loadPluginTranslation_taskbar_helper;
#include "../plugin-tray/lxqttrayplugin.h" // tray
extern void * loadPluginTranslation_tray_helper;
#include "../plugin-worldclock/lxqtworldclock.h" // worldclock
extern void * loadPluginTranslation_worldclock_helper;

QColor Plugin::mMoveMarkerColor= QColor(255, 0, 0, 255);

/************************************************

 ************************************************/
Plugin::Plugin(const LXQt::PluginInfo &desktopFile, LXQt::Settings *settings, const QString &settingsGroup, LXQtPanel *panel) :
    QFrame(panel),
    mDesktopFile(desktopFile),
    mPluginLoader(0),
    mPlugin(0),
    mPluginWidget(0),
    mAlignment(AlignLeft),
    mPanel(panel)
{
    mSettings = PluginSettingsFactory::create(settings, settingsGroup);

    setWindowTitle(desktopFile.name());
    mName = desktopFile.name();

    QStringList dirs;
    dirs << QProcessEnvironment::systemEnvironment().value("LXQTPANEL_PLUGIN_PATH").split(":");
    dirs << PLUGIN_DIR;

    bool found = false;
    if(ILXQtPanelPluginLibrary const * pluginLib = findStaticPlugin(desktopFile.id()))
    {
        // this is a static plugin
        found = true;
        loadLib(pluginLib);
    }
    else {
        // this plugin is a dynamically loadable module
        QString baseName = QString("lib%1.so").arg(desktopFile.id());
        foreach(const QString &dirName, dirs)
        {
            QFileInfo fi(QDir(dirName), baseName);
            if (fi.exists())
            {
                found = true;
                if (loadModule(fi.absoluteFilePath()))
                    break;
            }
        }
    }

    if (!isLoaded())
    {
        if (!found)
            qWarning() << QString("Plugin %1 not found in the").arg(desktopFile.id()) << dirs;

        return;
    }

    setObjectName(mPlugin->themeId() + "Plugin");

    // plugin handle for easy context menu
    setProperty("NeedsHandle", mPlugin->flags().testFlag(ILXQtPanelPlugin::NeedsHandle));

    QString s = mSettings->value("alignment").toString();

    // Retrun default value
    if (s.isEmpty())
    {
        mAlignment = (mPlugin->flags().testFlag(ILXQtPanelPlugin::PreferRightAlignment)) ?
                    Plugin::AlignRight :
                    Plugin::AlignLeft;
    }
    else
    {
        mAlignment = (s.toUpper() == "RIGHT") ?
                    Plugin::AlignRight :
                    Plugin::AlignLeft;

    }

    if (mPluginWidget)
    {
        QGridLayout* layout = new QGridLayout(this);
        layout->setSpacing(0);
        layout->setContentsMargins(0, 0, 0, 0);
        setLayout(layout);
        layout->addWidget(mPluginWidget, 0, 0);
    }

    // delay the connection to settingsChanged to avoid conflicts
    // while the plugin is still being initialized
    connect(mSettings, &PluginSettings::settingsChanged,
            this, &Plugin::settingsChanged);
    saveSettings();
}

/************************************************

 ************************************************/
Plugin::~Plugin()
{
    delete mPlugin;
    delete mPluginLoader;
    delete mSettings;
}

void Plugin::setAlignment(Plugin::Alignment alignment)
{
    mAlignment = alignment;
    saveSettings();
}

/************************************************

 ************************************************/
namespace
{
    //helper types for static plugins storage & binary search
    typedef std::unique_ptr<ILXQtPanelPluginLibrary> plugin_ptr_t;
    typedef std::tuple<QString, plugin_ptr_t, void *> plugin_tuple_t;

    //NOTE: Please keep the plugins sorted by name while adding new plugins.
    //NOTE2: we need to reference some (dummy) symbol from (autogenerated) LXQtPluginTranslationLoader.cpp
    // to be not stripped (as unused/unreferenced) in static linking time
    static plugin_tuple_t const static_plugins[] = {
#if defined(WITH_CLOCK_PLUGIN)
        std::make_tuple(QLatin1String("clock"), plugin_ptr_t{new LXQtClockPluginLibrary}, loadPluginTranslation_clock_helper),// clock
#endif
#if defined(WITH_DESKTOPSWITCH_PLUGIN)
        std::make_tuple(QLatin1String("desktopswitch"), plugin_ptr_t{new DesktopSwitchPluginLibrary}, loadPluginTranslation_desktopswitch_helper),// desktopswitch
#endif
#if defined(WITH_MAINMENU_PLUGIN)
        std::make_tuple(QLatin1String("mainmenu"), plugin_ptr_t{new LXQtMainMenuPluginLibrary}, loadPluginTranslation_mainmenu_helper),// mainmenu
#endif
#if defined(WITH_QUICKLAUNCH_PLUGIN)
        std::make_tuple(QLatin1String("quicklaunch"), plugin_ptr_t{new LXQtQuickLaunchPluginLibrary}, loadPluginTranslation_quicklaunch_helper),// quicklaunch
#endif
#if defined(WITH_SHOWDESKTOP_PLUGIN)
        std::make_tuple(QLatin1String("showdesktop"), plugin_ptr_t{new ShowDesktopLibrary}, loadPluginTranslation_showdesktop_helper),// showdesktop
#endif
#if defined(WITH_SPACER_PLUGIN)
        std::make_tuple(QLatin1String("spacer"), plugin_ptr_t{new SpacerPluginLibrary}, loadPluginTranslation_spacer_helper),// spacer
#endif
#if defined(WITH_STATUSNOTIFIER_PLUGIN)
        std::make_tuple(QLatin1String("statusnotifier"), plugin_ptr_t{new StatusNotifierLibrary}, loadPluginTranslation_statusnotifier_helper),// statusnotifier
#endif
#if defined(WITH_TASKBAR_PLUGIN)
        std::make_tuple(QLatin1String("taskbar"), plugin_ptr_t{new LXQtTaskBarPluginLibrary}, loadPluginTranslation_taskbar_helper),// taskbar
#endif
#if defined(WITH_TRAY_PLUGIN)
        std::make_tuple(QLatin1String("tray"), plugin_ptr_t{new LXQtTrayPluginLibrary}, loadPluginTranslation_tray_helper),// tray
#endif
#if defined(WITH_WORLDCLOCK_PLUGIN)
        std::make_tuple(QLatin1String("worldclock"), plugin_ptr_t{new LXQtWorldClockLibrary}, loadPluginTranslation_worldclock_helper),// worldclock
#endif
    };
    static constexpr plugin_tuple_t const * const plugins_begin = static_plugins;
    static constexpr plugin_tuple_t const * const plugins_end = static_plugins + sizeof (static_plugins) / sizeof (static_plugins[0]);

    struct assert_helper
    {
        assert_helper()
        {
            Q_ASSERT(std::is_sorted(plugins_begin, plugins_end
                        , [] (plugin_tuple_t const & p1, plugin_tuple_t const & p2) -> bool { return std::get<0>(p1) < std::get<0>(p2); }));
        }
    };
    static assert_helper h;
}

ILXQtPanelPluginLibrary const * Plugin::findStaticPlugin(const QString &libraryName)
{
    // find a static plugin library by name -> binary search
    plugin_tuple_t const * plugin = std::lower_bound(plugins_begin, plugins_end, libraryName
            , [] (plugin_tuple_t const & plugin, QString const & name) -> bool { return std::get<0>(plugin) < name; });
    if (plugins_end != plugin && libraryName == std::get<0>(*plugin))
        return std::get<1>(*plugin).get();
    return nullptr;
}

// load a plugin from a library
bool Plugin::loadLib(ILXQtPanelPluginLibrary const * pluginLib)
{
    ILXQtPanelPluginStartupInfo startupInfo;
    startupInfo.settings = mSettings;
    startupInfo.desktopFile = &mDesktopFile;
    startupInfo.lxqtPanel = mPanel;

    mPlugin = pluginLib->instance(startupInfo);
    if (!mPlugin)
    {
        qWarning() << QString("Can't load plugin \"%1\". Plugin can't build ILXQtPanelPlugin.").arg(mPluginLoader->fileName());
        return false;
    }

    mPluginWidget = mPlugin->widget();
    if (mPluginWidget)
    {
        mPluginWidget->setObjectName(mPlugin->themeId());
    }
    this->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    return true;
}

// load dynamic plugin from a *.so module
bool Plugin::loadModule(const QString &libraryName)
{
    mPluginLoader = new QPluginLoader(libraryName);

    if (!mPluginLoader->load())
    {
        qWarning() << mPluginLoader->errorString();
        return false;
    }

    QObject *obj = mPluginLoader->instance();
    if (!obj)
    {
        qWarning() << mPluginLoader->errorString();
        return false;
    }

    ILXQtPanelPluginLibrary* pluginLib= qobject_cast<ILXQtPanelPluginLibrary*>(obj);
    if (!pluginLib)
    {
        qWarning() << QString("Can't load plugin \"%1\". Plugin is not a ILXQtPanelPluginLibrary.").arg(mPluginLoader->fileName());
        delete obj;
        return false;
    }
    return loadLib(pluginLib);
}

/************************************************

 ************************************************/
void Plugin::settingsChanged()
{
    mPlugin->settingsChanged();
}

/************************************************

 ************************************************/
void Plugin::saveSettings()
{
    mSettings->setValue("alignment", (mAlignment == AlignLeft) ? "Left" : "Right");
    mSettings->setValue("type", mDesktopFile.id());
    mSettings->sync();

}

/************************************************

 ************************************************/
void Plugin::contextMenuEvent(QContextMenuEvent *event)
{
    mPanel->showPopupMenu(this);
}

/************************************************

 ************************************************/
void Plugin::mousePressEvent(QMouseEvent *event)
{
    switch (event->button())
    {
    case Qt::LeftButton:
        mPlugin->activated(ILXQtPanelPlugin::Trigger);
        break;

    case Qt::MidButton:
        mPlugin->activated(ILXQtPanelPlugin::MiddleClick);
        break;

    default:
        break;
    }
}

/************************************************

 ************************************************/
void Plugin::mouseDoubleClickEvent(QMouseEvent*)
{
    mPlugin->activated(ILXQtPanelPlugin::DoubleClick);
}

/************************************************

 ************************************************/
void Plugin::showEvent(QShowEvent *)
{
    if (mPluginWidget)
        mPluginWidget->adjustSize();
}

/************************************************

 ************************************************/
QMenu *Plugin::popupMenu() const
{
    QString name = this->name().replace("&", "&&");
    QMenu* menu = new QMenu(windowTitle());

    if (mPlugin->flags().testFlag(ILXQtPanelPlugin::HaveConfigDialog))
    {
        QAction* configAction = new QAction(
            XdgIcon::fromTheme(QLatin1String("preferences-other")),
            tr("Configure \"%1\"").arg(name), menu);
        menu->addAction(configAction);
        connect(configAction, SIGNAL(triggered()), this, SLOT(showConfigureDialog()));
    }

    QAction* moveAction = new QAction(XdgIcon::fromTheme("transform-move"), tr("Move \"%1\"").arg(name), menu);
    menu->addAction(moveAction);
    connect(moveAction, SIGNAL(triggered()), this, SIGNAL(startMove()));

    menu->addSeparator();

    QAction* removeAction = new QAction(
        XdgIcon::fromTheme(QLatin1String("list-remove")),
        tr("Remove \"%1\"").arg(name), menu);
    menu->addAction(removeAction);
    connect(removeAction, SIGNAL(triggered()), this, SLOT(requestRemove()));

    return menu;
}

/************************************************

 ************************************************/
bool Plugin::isSeparate() const
{
   return mPlugin->isSeparate();
}

/************************************************

 ************************************************/
bool Plugin::isExpandable() const
{
    return mPlugin->isExpandable();
}

/************************************************

 ************************************************/
void Plugin::realign()
{
    if (mPlugin)
        mPlugin->realign();
}

/************************************************

 ************************************************/
void Plugin::showConfigureDialog()
{
    if (!mConfigDialog)
        mConfigDialog = mPlugin->configureDialog();

    if (!mConfigDialog)
        return;

    connect(this, &Plugin::destroyed, mConfigDialog, &QWidget::close);
    mPanel->willShowWindow(mConfigDialog);
    mConfigDialog->show();
    mConfigDialog->raise();
    mConfigDialog->activateWindow();
}

/************************************************

 ************************************************/
void Plugin::requestRemove()
{
    emit remove();
    deleteLater();
}
<commit_msg>plugin: Force config dialog activation/raise<commit_after>/* BEGIN_COMMON_COPYRIGHT_HEADER
 * (c)LGPL2+
 *
 * LXDE-Qt - a lightweight, Qt based, desktop toolset
 * http://razor-qt.org
 *
 * Copyright: 2012 Razor team
 * Authors:
 *   Alexander Sokoloff <sokoloff.a@gmail.com>
 *
 * This program or library is free software; you can redistribute it
 * and/or modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.

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

#include "plugin.h"
#include "ilxqtpanelplugin.h"
#include "pluginsettings_p.h"
#include "lxqtpanel.h"
#include <QDebug>
#include <QProcessEnvironment>
#include <QStringList>
#include <QDir>
#include <QFileInfo>
#include <QPluginLoader>
#include <QGridLayout>
#include <QDialog>
#include <QEvent>
#include <QMenu>
#include <QMouseEvent>
#include <QApplication>
#include <QWindow>
#include <memory>

#include <LXQt/Settings>
#include <LXQt/Translator>
#include <XdgIcon>

// statically linked built-in plugins
#include "../plugin-clock/lxqtclock.h" // clock
extern void * loadPluginTranslation_clock_helper;
#include "../plugin-desktopswitch/desktopswitch.h" // desktopswitch
extern void * loadPluginTranslation_desktopswitch_helper;
#include "../plugin-mainmenu/lxqtmainmenu.h" // mainmenu
extern void * loadPluginTranslation_mainmenu_helper;
#include "../plugin-quicklaunch/lxqtquicklaunchplugin.h" // quicklaunch
extern void * loadPluginTranslation_quicklaunch_helper;
#include "../plugin-showdesktop/showdesktop.h" // showdesktop
extern void * loadPluginTranslation_showdesktop_helper;
#include "../plugin-spacer/spacer.h" // spacer
extern void * loadPluginTranslation_spacer_helper;
#include "../plugin-statusnotifier/statusnotifier.h" // statusnotifier
extern void * loadPluginTranslation_statusnotifier_helper;
#include "../plugin-taskbar/lxqttaskbarplugin.h" // taskbar
extern void * loadPluginTranslation_taskbar_helper;
#include "../plugin-tray/lxqttrayplugin.h" // tray
extern void * loadPluginTranslation_tray_helper;
#include "../plugin-worldclock/lxqtworldclock.h" // worldclock
extern void * loadPluginTranslation_worldclock_helper;

QColor Plugin::mMoveMarkerColor= QColor(255, 0, 0, 255);

/************************************************

 ************************************************/
Plugin::Plugin(const LXQt::PluginInfo &desktopFile, LXQt::Settings *settings, const QString &settingsGroup, LXQtPanel *panel) :
    QFrame(panel),
    mDesktopFile(desktopFile),
    mPluginLoader(0),
    mPlugin(0),
    mPluginWidget(0),
    mAlignment(AlignLeft),
    mPanel(panel)
{
    mSettings = PluginSettingsFactory::create(settings, settingsGroup);

    setWindowTitle(desktopFile.name());
    mName = desktopFile.name();

    QStringList dirs;
    dirs << QProcessEnvironment::systemEnvironment().value("LXQTPANEL_PLUGIN_PATH").split(":");
    dirs << PLUGIN_DIR;

    bool found = false;
    if(ILXQtPanelPluginLibrary const * pluginLib = findStaticPlugin(desktopFile.id()))
    {
        // this is a static plugin
        found = true;
        loadLib(pluginLib);
    }
    else {
        // this plugin is a dynamically loadable module
        QString baseName = QString("lib%1.so").arg(desktopFile.id());
        foreach(const QString &dirName, dirs)
        {
            QFileInfo fi(QDir(dirName), baseName);
            if (fi.exists())
            {
                found = true;
                if (loadModule(fi.absoluteFilePath()))
                    break;
            }
        }
    }

    if (!isLoaded())
    {
        if (!found)
            qWarning() << QString("Plugin %1 not found in the").arg(desktopFile.id()) << dirs;

        return;
    }

    setObjectName(mPlugin->themeId() + "Plugin");

    // plugin handle for easy context menu
    setProperty("NeedsHandle", mPlugin->flags().testFlag(ILXQtPanelPlugin::NeedsHandle));

    QString s = mSettings->value("alignment").toString();

    // Retrun default value
    if (s.isEmpty())
    {
        mAlignment = (mPlugin->flags().testFlag(ILXQtPanelPlugin::PreferRightAlignment)) ?
                    Plugin::AlignRight :
                    Plugin::AlignLeft;
    }
    else
    {
        mAlignment = (s.toUpper() == "RIGHT") ?
                    Plugin::AlignRight :
                    Plugin::AlignLeft;

    }

    if (mPluginWidget)
    {
        QGridLayout* layout = new QGridLayout(this);
        layout->setSpacing(0);
        layout->setContentsMargins(0, 0, 0, 0);
        setLayout(layout);
        layout->addWidget(mPluginWidget, 0, 0);
    }

    // delay the connection to settingsChanged to avoid conflicts
    // while the plugin is still being initialized
    connect(mSettings, &PluginSettings::settingsChanged,
            this, &Plugin::settingsChanged);
    saveSettings();
}

/************************************************

 ************************************************/
Plugin::~Plugin()
{
    delete mPlugin;
    delete mPluginLoader;
    delete mSettings;
}

void Plugin::setAlignment(Plugin::Alignment alignment)
{
    mAlignment = alignment;
    saveSettings();
}

/************************************************

 ************************************************/
namespace
{
    //helper types for static plugins storage & binary search
    typedef std::unique_ptr<ILXQtPanelPluginLibrary> plugin_ptr_t;
    typedef std::tuple<QString, plugin_ptr_t, void *> plugin_tuple_t;

    //NOTE: Please keep the plugins sorted by name while adding new plugins.
    //NOTE2: we need to reference some (dummy) symbol from (autogenerated) LXQtPluginTranslationLoader.cpp
    // to be not stripped (as unused/unreferenced) in static linking time
    static plugin_tuple_t const static_plugins[] = {
#if defined(WITH_CLOCK_PLUGIN)
        std::make_tuple(QLatin1String("clock"), plugin_ptr_t{new LXQtClockPluginLibrary}, loadPluginTranslation_clock_helper),// clock
#endif
#if defined(WITH_DESKTOPSWITCH_PLUGIN)
        std::make_tuple(QLatin1String("desktopswitch"), plugin_ptr_t{new DesktopSwitchPluginLibrary}, loadPluginTranslation_desktopswitch_helper),// desktopswitch
#endif
#if defined(WITH_MAINMENU_PLUGIN)
        std::make_tuple(QLatin1String("mainmenu"), plugin_ptr_t{new LXQtMainMenuPluginLibrary}, loadPluginTranslation_mainmenu_helper),// mainmenu
#endif
#if defined(WITH_QUICKLAUNCH_PLUGIN)
        std::make_tuple(QLatin1String("quicklaunch"), plugin_ptr_t{new LXQtQuickLaunchPluginLibrary}, loadPluginTranslation_quicklaunch_helper),// quicklaunch
#endif
#if defined(WITH_SHOWDESKTOP_PLUGIN)
        std::make_tuple(QLatin1String("showdesktop"), plugin_ptr_t{new ShowDesktopLibrary}, loadPluginTranslation_showdesktop_helper),// showdesktop
#endif
#if defined(WITH_SPACER_PLUGIN)
        std::make_tuple(QLatin1String("spacer"), plugin_ptr_t{new SpacerPluginLibrary}, loadPluginTranslation_spacer_helper),// spacer
#endif
#if defined(WITH_STATUSNOTIFIER_PLUGIN)
        std::make_tuple(QLatin1String("statusnotifier"), plugin_ptr_t{new StatusNotifierLibrary}, loadPluginTranslation_statusnotifier_helper),// statusnotifier
#endif
#if defined(WITH_TASKBAR_PLUGIN)
        std::make_tuple(QLatin1String("taskbar"), plugin_ptr_t{new LXQtTaskBarPluginLibrary}, loadPluginTranslation_taskbar_helper),// taskbar
#endif
#if defined(WITH_TRAY_PLUGIN)
        std::make_tuple(QLatin1String("tray"), plugin_ptr_t{new LXQtTrayPluginLibrary}, loadPluginTranslation_tray_helper),// tray
#endif
#if defined(WITH_WORLDCLOCK_PLUGIN)
        std::make_tuple(QLatin1String("worldclock"), plugin_ptr_t{new LXQtWorldClockLibrary}, loadPluginTranslation_worldclock_helper),// worldclock
#endif
    };
    static constexpr plugin_tuple_t const * const plugins_begin = static_plugins;
    static constexpr plugin_tuple_t const * const plugins_end = static_plugins + sizeof (static_plugins) / sizeof (static_plugins[0]);

    struct assert_helper
    {
        assert_helper()
        {
            Q_ASSERT(std::is_sorted(plugins_begin, plugins_end
                        , [] (plugin_tuple_t const & p1, plugin_tuple_t const & p2) -> bool { return std::get<0>(p1) < std::get<0>(p2); }));
        }
    };
    static assert_helper h;
}

ILXQtPanelPluginLibrary const * Plugin::findStaticPlugin(const QString &libraryName)
{
    // find a static plugin library by name -> binary search
    plugin_tuple_t const * plugin = std::lower_bound(plugins_begin, plugins_end, libraryName
            , [] (plugin_tuple_t const & plugin, QString const & name) -> bool { return std::get<0>(plugin) < name; });
    if (plugins_end != plugin && libraryName == std::get<0>(*plugin))
        return std::get<1>(*plugin).get();
    return nullptr;
}

// load a plugin from a library
bool Plugin::loadLib(ILXQtPanelPluginLibrary const * pluginLib)
{
    ILXQtPanelPluginStartupInfo startupInfo;
    startupInfo.settings = mSettings;
    startupInfo.desktopFile = &mDesktopFile;
    startupInfo.lxqtPanel = mPanel;

    mPlugin = pluginLib->instance(startupInfo);
    if (!mPlugin)
    {
        qWarning() << QString("Can't load plugin \"%1\". Plugin can't build ILXQtPanelPlugin.").arg(mPluginLoader->fileName());
        return false;
    }

    mPluginWidget = mPlugin->widget();
    if (mPluginWidget)
    {
        mPluginWidget->setObjectName(mPlugin->themeId());
    }
    this->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    return true;
}

// load dynamic plugin from a *.so module
bool Plugin::loadModule(const QString &libraryName)
{
    mPluginLoader = new QPluginLoader(libraryName);

    if (!mPluginLoader->load())
    {
        qWarning() << mPluginLoader->errorString();
        return false;
    }

    QObject *obj = mPluginLoader->instance();
    if (!obj)
    {
        qWarning() << mPluginLoader->errorString();
        return false;
    }

    ILXQtPanelPluginLibrary* pluginLib= qobject_cast<ILXQtPanelPluginLibrary*>(obj);
    if (!pluginLib)
    {
        qWarning() << QString("Can't load plugin \"%1\". Plugin is not a ILXQtPanelPluginLibrary.").arg(mPluginLoader->fileName());
        delete obj;
        return false;
    }
    return loadLib(pluginLib);
}

/************************************************

 ************************************************/
void Plugin::settingsChanged()
{
    mPlugin->settingsChanged();
}

/************************************************

 ************************************************/
void Plugin::saveSettings()
{
    mSettings->setValue("alignment", (mAlignment == AlignLeft) ? "Left" : "Right");
    mSettings->setValue("type", mDesktopFile.id());
    mSettings->sync();

}

/************************************************

 ************************************************/
void Plugin::contextMenuEvent(QContextMenuEvent *event)
{
    mPanel->showPopupMenu(this);
}

/************************************************

 ************************************************/
void Plugin::mousePressEvent(QMouseEvent *event)
{
    switch (event->button())
    {
    case Qt::LeftButton:
        mPlugin->activated(ILXQtPanelPlugin::Trigger);
        break;

    case Qt::MidButton:
        mPlugin->activated(ILXQtPanelPlugin::MiddleClick);
        break;

    default:
        break;
    }
}

/************************************************

 ************************************************/
void Plugin::mouseDoubleClickEvent(QMouseEvent*)
{
    mPlugin->activated(ILXQtPanelPlugin::DoubleClick);
}

/************************************************

 ************************************************/
void Plugin::showEvent(QShowEvent *)
{
    if (mPluginWidget)
        mPluginWidget->adjustSize();
}

/************************************************

 ************************************************/
QMenu *Plugin::popupMenu() const
{
    QString name = this->name().replace("&", "&&");
    QMenu* menu = new QMenu(windowTitle());

    if (mPlugin->flags().testFlag(ILXQtPanelPlugin::HaveConfigDialog))
    {
        QAction* configAction = new QAction(
            XdgIcon::fromTheme(QLatin1String("preferences-other")),
            tr("Configure \"%1\"").arg(name), menu);
        menu->addAction(configAction);
        connect(configAction, SIGNAL(triggered()), this, SLOT(showConfigureDialog()));
    }

    QAction* moveAction = new QAction(XdgIcon::fromTheme("transform-move"), tr("Move \"%1\"").arg(name), menu);
    menu->addAction(moveAction);
    connect(moveAction, SIGNAL(triggered()), this, SIGNAL(startMove()));

    menu->addSeparator();

    QAction* removeAction = new QAction(
        XdgIcon::fromTheme(QLatin1String("list-remove")),
        tr("Remove \"%1\"").arg(name), menu);
    menu->addAction(removeAction);
    connect(removeAction, SIGNAL(triggered()), this, SLOT(requestRemove()));

    return menu;
}

/************************************************

 ************************************************/
bool Plugin::isSeparate() const
{
   return mPlugin->isSeparate();
}

/************************************************

 ************************************************/
bool Plugin::isExpandable() const
{
    return mPlugin->isExpandable();
}

/************************************************

 ************************************************/
void Plugin::realign()
{
    if (mPlugin)
        mPlugin->realign();
}

/************************************************

 ************************************************/
void Plugin::showConfigureDialog()
{
    if (!mConfigDialog)
        mConfigDialog = mPlugin->configureDialog();

    if (!mConfigDialog)
        return;

    connect(this, &Plugin::destroyed, mConfigDialog, &QWidget::close);
    mPanel->willShowWindow(mConfigDialog);
    mConfigDialog->show();
    mConfigDialog->raise();
    mConfigDialog->activateWindow();

    WId wid = mConfigDialog->windowHandle()->winId();
    KWindowSystem::activateWindow(wid);
    KWindowSystem::setOnDesktop(wid, KWindowSystem::currentDesktop());
}

/************************************************

 ************************************************/
void Plugin::requestRemove()
{
    emit remove();
    deleteLater();
}
<|endoftext|>


<commit_before>/*

  This program will add histograms from a list of root files and write them
  to a target root file. The target file is newly created and must not be
  identical to one of the source files.

  Syntax:

       hadd targetfile source1 source2 ...
    or
       hadd -f targetfile source1 source2 ...
         (targetfile is overwritten if it exists)

  For example assume 3 files f1, f2, f3 containing histograms hn and Trees Tn
    f1 with h1 h2 h3 T1
    f2 with h1 h4 T1 T2
    f3 with h5
   the result of
     hadd -f x.root f1.root f2.root f3.root
   will be a file x.root with
     x with h1 h2 h3 h4 h5 T1 T2
   where h1 will be the sum of the 2 histograms in f1 and f2
         T1 will be the merge of the Trees in f1 and f2

  if the source files contains histograms and Trees, one can skip
  the Trees with
       hadd -T targetfile source1 source2 ...

  Authors: Rene Brun, Dirk Geppert, Sven A. Schmidt, sven.schmidt@cern.ch

 */

#include "RConfig.h"
#include <string>
#include "TChain.h"
#include "TFile.h"
#include "TH1.h"
#include "TKey.h"
#include "TObjString.h"
#include "Riostream.h"

TList *FileList;
TFile *Target, *Source;
Bool_t noTrees;

void MergeRootfile( TDirectory *target, TList *sourcelist );

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

  if ( argc < 4 || "-h" == string(argv[1]) || "--help" == string(argv[1]) ) {
    cout << "Usage: " << argv[0] << " [-f] [-T] targetfile source1 source2 [source3 ...]" << endl;
    cout << "This program will add histograms from a list of root files and write them" << endl;
    cout << "to a target root file. The target file is newly created and must not " << endl;
    cout << "exist, or if -f (\"force\") is given, must not be one of the source files." << endl;
    cout << "Supply at least two source files for this to make sense... ;-)" << endl;
    cout << "If the first argument is -T, Trees are not merged" <<endl;
    return 1;
  }
  FileList = new TList();

  Bool_t force = (!strcmp(argv[1],"-f") || !strcmp(argv[2],"-f"));
  noTrees = (!strcmp(argv[1],"-T") || !strcmp(argv[2],"-T"));

  int ffirst = 2;
  if (force) ffirst++;
  if (noTrees) ffirst++;

  cout << "Target file: " << argv[ffirst-1] << endl;
  Target = TFile::Open( argv[ffirst-1], (force?"RECREATE":"CREATE") );
  if (!Target || Target->IsZombie()) {
     cerr << "Error opening target file (does " << argv[ffirst-1] << " exist?)." << endl;
     cerr << "Pass \"-f\" argument to force re-creation of output file." << endl;
     exit(1);
  }

  // by default hadd can merge Trees in a file that can go up to 100 Gbytes
  Long64_t maxsize = 100000000; //100GB
  maxsize *= 100;  //to bypass some compiler limitations with big constants
  TTree::SetMaxTreeSize(maxsize);

  for ( int i = ffirst; i < argc; i++ ) {
    cout << "Source file " << i-ffirst+1 << ": " << argv[i] << endl;
    Source = TFile::Open( argv[i] );
    FileList->Add(Source);
  }

  MergeRootfile( Target, FileList );

 //must delete Target to avoid a problem with dictionaries in~ TROOT
  delete Target;

  return 0;
}

void MergeRootfile( TDirectory *target, TList *sourcelist ) {

  //  cout << "Target path: " << target->GetPath() << endl;
  TString path( (char*)strstr( target->GetPath(), ":" ) );
  path.Remove( 0, 2 );

  TFile *first_source = (TFile*)sourcelist->First();
  THashList allNames;
  while(first_source) {
     first_source->cd( path );
     TDirectory *current_sourcedir = gDirectory;

     // loop over all keys in this directory
     TChain *globChain = 0;
     TIter nextkey( current_sourcedir->GetListOfKeys() );
     TKey *key, *oldkey=0;
     //gain time, do not add the objects in the list in memory
     TH1::AddDirectory(kFALSE);

     while ( (key = (TKey*)nextkey())) {

       //keep only the highest cycle number for each key
       if (oldkey && !strcmp(oldkey->GetName(),key->GetName())) continue;
       if (allNames.FindObject(key->GetName())) continue;
       allNames.Add(new TObjString(key->GetName()));

       // read object from first source file
       first_source->cd( path );
       TObject *obj = key->ReadObj();

       if ( obj->IsA()->InheritsFrom( TH1::Class() ) ) {
         // descendant of TH1 -> merge it

            //cout << "Merging histogram " << obj->GetName() << endl;
         TH1 *h1 = (TH1*)obj;
         TList listH;

         // loop over all source files and add the content of the
         // correspondant histogram to the one pointed to by "h1"
         TFile *nextsource = (TFile*)sourcelist->After( first_source );
         while ( nextsource ) {

           // make sure we are at the correct directory level by cd'ing to path
           nextsource->cd( path );
           TKey *key2 = (TKey*)gDirectory->GetListOfKeys()->FindObject(h1->GetName());
           if (key2) {
              listH.Add(key2->ReadObj());
              h1->Merge(&listH);
              listH.Delete();
           }

           nextsource = (TFile*)sourcelist->After( nextsource );
         }
       }
       else if ( obj->IsA()->InheritsFrom( "TTree" ) ) {

         // loop over all source files create a chain of Trees "globChain"
         if (!noTrees) {
            TString obj_name;
            if (path.Length()) {
               obj_name = path + "/" + obj->GetName();
            } else {
               obj_name = obj->GetName();
            }

            globChain = new TChain(obj_name);
            globChain->Add(first_source->GetName());
            TFile *nextsource = (TFile*)sourcelist->After( first_source );
            //      const char* file_name = nextsource->GetName();
            // cout << "file name  " << file_name << endl;
            while ( nextsource ) {
               //do not add to the list a file that does not contain this Tree
               TFile *curf = TFile::Open(nextsource->GetName());
               if (curf && curf->FindObject(obj_name)) {
                  globChain->Add(nextsource->GetName());
               }
               delete curf;
               nextsource = (TFile*)sourcelist->After( nextsource );
            }
         }

       } else if ( obj->IsA()->InheritsFrom( "TDirectory" ) ) {
         // it's a subdirectory

         cout << "Found subdirectory " << obj->GetName() << endl;

         // create a new subdir of same name and title in the target file
         target->cd();
         TDirectory *newdir = target->mkdir( obj->GetName(), obj->GetTitle() );

         // newdir is now the starting point of another round of merging
         // newdir still knows its depth within the target file via
         // GetPath(), so we can still figure out where we are in the recursion
         MergeRootfile( newdir, sourcelist );

       } else {

         // object is of no type that we know or can handle
         cout << "Unknown object type, name: "
              << obj->GetName() << " title: " << obj->GetTitle() << endl;
       }

       // now write the merged histogram (which is "in" obj) to the target file
       // note that this will just store obj in the current directory level,
       // which is not persistent until the complete directory itself is stored
       // by "target->Write()" below
       if ( obj ) {
          target->cd();

          //!!if the object is a tree, it is stored in globChain...
          if(obj->IsA()->InheritsFrom( "TTree" )) {
             if (!noTrees) {
                globChain->Merge(target->GetFile(),0,"keep");
                delete globChain;
             }
          } else {
             obj->Write( key->GetName() );
          }
       }
       oldkey = key;

     } // while ( ( TKey *key = (TKey*)nextkey() ) )
     sourcelist->Remove(first_source);
     first_source = (TFile*)sourcelist->First();
  }
  // save modifications to target file
  target->SaveSelf(kTRUE);

}
<commit_msg>It is now possible to specify the compression factor of the destination file. hadd -f result.root file1.root file2.root (case 1) hadd -f0 result.root file1.root file2.root (case 2) hadd -f6 result.root file1.root (case 3)<commit_after>/*

  This program will add histograms from a list of root files and write them
  to a target root file. The target file is newly created and must not be
  identical to one of the source files.

  Syntax:

       hadd targetfile source1 source2 ...
    or
       hadd -f targetfile source1 source2 ...
         (targetfile is overwritten if it exists)

  When -the -f option is specified, one can also specify the compression
  level of the target file. By default the compression level is 1, but
  if "-f0" is specified, the target file will not be compressed.
  if "-f6" is specified, the compression level 6 will be used.

  For example assume 3 files f1, f2, f3 containing histograms hn and Trees Tn
    f1 with h1 h2 h3 T1
    f2 with h1 h4 T1 T2
    f3 with h5
   the result of
     hadd -f x.root f1.root f2.root f3.root
   will be a file x.root with
     x with h1 h2 h3 h4 h5 T1 T2
   where h1 will be the sum of the 2 histograms in f1 and f2
         T1 will be the merge of the Trees in f1 and f2

  if the source files contains histograms and Trees, one can skip
  the Trees with
       hadd -T targetfile source1 source2 ...

  Authors: Rene Brun, Dirk Geppert, Sven A. Schmidt, sven.schmidt@cern.ch

 */

#include "RConfig.h"
#include <string>
#include "TChain.h"
#include "TFile.h"
#include "TH1.h"
#include "TKey.h"
#include "TObjString.h"
#include "Riostream.h"

TList *FileList;
TFile *Target, *Source;
Bool_t noTrees;

void MergeRootfile( TDirectory *target, TList *sourcelist );

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

  if ( argc < 4 || "-h" == string(argv[1]) || "--help" == string(argv[1]) ) {
    cout << "Usage: " << argv[0] << " [-f] [-T] targetfile source1 source2 [source3 ...]" << endl;
    cout << "This program will add histograms from a list of root files and write them" << endl;
    cout << "to a target root file. The target file is newly created and must not " << endl;
    cout << "exist, or if -f (\"force\") is given, must not be one of the source files." << endl;
    cout << "Supply at least two source files for this to make sense... ;-)" << endl;
    cout << "If the first argument is -T, Trees are not merged" <<endl;
    cout << "When -the -f option is specified, one can also specify the compression" <<endl;
    cout << "level of the target file. By default the compression level is 1, but" <<endl;
    cout << "if \"-f0\" is specified, the target file will not be compressed." <<endl;
    cout << "if \"-f6\" is specified, the compression level 6 will be used." <<endl;
    return 1;
  }
  FileList = new TList();

  Bool_t force = (!strcmp(argv[1],"-f") || !strcmp(argv[2],"-f"));
  noTrees = (!strcmp(argv[1],"-T") || !strcmp(argv[2],"-T"));
  Int_t newcomp = 1;
  char ft[4];
  for (int j=0;j<9;j++) {
     sprintf(ft,"-f%d",j);
     if (!strcmp(argv[1],ft) || !strcmp(argv[2],ft)) {
        force = kTRUE;
         newcomp = j;
        break;
     }
  }

  int ffirst = 2;
  if (force) ffirst++;
  if (noTrees) ffirst++;

  cout << "Target file: " << argv[ffirst-1] << endl;
  Target = TFile::Open( argv[ffirst-1], (force?"RECREATE":"CREATE") );
  if (!Target || Target->IsZombie()) {
     cerr << "Error opening target file (does " << argv[ffirst-1] << " exist?)." << endl;
     cerr << "Pass \"-f\" argument to force re-creation of output file." << endl;
     exit(1);
  }
  Target->SetCompressionLevel(newcomp);

  // by default hadd can merge Trees in a file that can go up to 100 Gbytes
  Long64_t maxsize = 100000000; //100GB
  maxsize *= 100;  //to bypass some compiler limitations with big constants
  TTree::SetMaxTreeSize(maxsize);

  for ( int i = ffirst; i < argc; i++ ) {
    cout << "Source file " << i-ffirst+1 << ": " << argv[i] << endl;
    Source = TFile::Open( argv[i] );
    FileList->Add(Source);
  }

  MergeRootfile( Target, FileList );

 //must delete Target to avoid a problem with dictionaries in~ TROOT
  delete Target;

  return 0;
}

void MergeRootfile( TDirectory *target, TList *sourcelist ) {

  //  cout << "Target path: " << target->GetPath() << endl;
  TString path( (char*)strstr( target->GetPath(), ":" ) );
  path.Remove( 0, 2 );

  TFile *first_source = (TFile*)sourcelist->First();
  THashList allNames;
  while(first_source) {
     first_source->cd( path );
     TDirectory *current_sourcedir = gDirectory;

     // loop over all keys in this directory
     TChain *globChain = 0;
     TIter nextkey( current_sourcedir->GetListOfKeys() );
     TKey *key, *oldkey=0;
     //gain time, do not add the objects in the list in memory
     TH1::AddDirectory(kFALSE);

     while ( (key = (TKey*)nextkey())) {

       //keep only the highest cycle number for each key
       if (oldkey && !strcmp(oldkey->GetName(),key->GetName())) continue;
       if (allNames.FindObject(key->GetName())) continue;
       allNames.Add(new TObjString(key->GetName()));

       // read object from first source file
       first_source->cd( path );
       TObject *obj = key->ReadObj();

       if ( obj->IsA()->InheritsFrom( TH1::Class() ) ) {
         // descendant of TH1 -> merge it

            //cout << "Merging histogram " << obj->GetName() << endl;
         TH1 *h1 = (TH1*)obj;
         TList listH;

         // loop over all source files and add the content of the
         // correspondant histogram to the one pointed to by "h1"
         TFile *nextsource = (TFile*)sourcelist->After( first_source );
         while ( nextsource ) {

           // make sure we are at the correct directory level by cd'ing to path
           nextsource->cd( path );
           TKey *key2 = (TKey*)gDirectory->GetListOfKeys()->FindObject(h1->GetName());
           if (key2) {
              listH.Add(key2->ReadObj());
              h1->Merge(&listH);
              listH.Delete();
           }

           nextsource = (TFile*)sourcelist->After( nextsource );
         }
       }
       else if ( obj->IsA()->InheritsFrom( "TTree" ) ) {

         // loop over all source files create a chain of Trees "globChain"
         if (!noTrees) {
            TString obj_name;
            if (path.Length()) {
               obj_name = path + "/" + obj->GetName();
            } else {
               obj_name = obj->GetName();
            }

            globChain = new TChain(obj_name);
            globChain->Add(first_source->GetName());
            TFile *nextsource = (TFile*)sourcelist->After( first_source );
            //      const char* file_name = nextsource->GetName();
            // cout << "file name  " << file_name << endl;
            while ( nextsource ) {
               //do not add to the list a file that does not contain this Tree
               TFile *curf = TFile::Open(nextsource->GetName());
               if (curf && curf->FindObject(obj_name)) {
                  globChain->Add(nextsource->GetName());
               }
               delete curf;
               nextsource = (TFile*)sourcelist->After( nextsource );
            }
         }

       } else if ( obj->IsA()->InheritsFrom( "TDirectory" ) ) {
         // it's a subdirectory

         cout << "Found subdirectory " << obj->GetName() << endl;

         // create a new subdir of same name and title in the target file
         target->cd();
         TDirectory *newdir = target->mkdir( obj->GetName(), obj->GetTitle() );

         // newdir is now the starting point of another round of merging
         // newdir still knows its depth within the target file via
         // GetPath(), so we can still figure out where we are in the recursion
         MergeRootfile( newdir, sourcelist );

       } else {

         // object is of no type that we know or can handle
         cout << "Unknown object type, name: "
              << obj->GetName() << " title: " << obj->GetTitle() << endl;
       }

       // now write the merged histogram (which is "in" obj) to the target file
       // note that this will just store obj in the current directory level,
       // which is not persistent until the complete directory itself is stored
       // by "target->Write()" below
       if ( obj ) {
          target->cd();

          //!!if the object is a tree, it is stored in globChain...
          if(obj->IsA()->InheritsFrom( "TTree" )) {
             if (!noTrees) {
                globChain->Merge(target->GetFile(),0,"keep");
                delete globChain;
             }
          } else {
             obj->Write( key->GetName() );
          }
       }
       oldkey = key;

     } // while ( ( TKey *key = (TKey*)nextkey() ) )
     sourcelist->Remove(first_source);
     first_source = (TFile*)sourcelist->First();
  }
  // save modifications to target file
  target->SaveSelf(kTRUE);

}
<|endoftext|>


<commit_before>/** Copyright 2008, 2009, 2010, 2011, 2012 Roland Olbricht
*
* This file is part of Overpass_API.
*
* Overpass_API is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* Overpass_API is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Overpass_API.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "output.h"
#include "web_output.h"

#include <iomanip>
#include <iostream>
#include <sstream>
#include <string>

using namespace std;

void Web_Output::add_encoding_error(const string& error)
{
  if (log_level != Error_Output::QUIET)
  {
    ostringstream out;
    out<<"encoding error: "<<error;
    display_error(out.str(), 400);
  }
  encoding_errors = true;
}

void Web_Output::add_parse_error(const string& error, int line_number)
{
  if (log_level != Error_Output::QUIET)
  {
    ostringstream out;
    out<<"line "<<line_number<<": parse error: "<<error;
    display_error(out.str(), 400);
  }
  parse_errors = true;
}

void Web_Output::add_static_error(const string& error, int line_number)
{
  if (log_level != Error_Output::QUIET)
  {
    ostringstream out;
    out<<"line "<<line_number<<": static error: "<<error;
    display_error(out.str(), 400);
  }
  static_errors = true;
}

void Web_Output::add_encoding_remark(const string& error)
{
  if (log_level == Error_Output::VERBOSE)
  {
    ostringstream out;
    out<<"encoding remark: "<<error;
    display_remark(out.str());
  }
}

void Web_Output::add_parse_remark(const string& error, int line_number)
{
  if (log_level == Error_Output::VERBOSE)
  {
    ostringstream out;
    out<<"line "<<line_number<<": parse remark: "<<error;
    display_remark(out.str());
  }
}

void Web_Output::add_static_remark(const string& error, int line_number)
{
  if (log_level == Error_Output::VERBOSE)
  {
    ostringstream out;
    out<<"line "<<line_number<<": static remark: "<<error;
    display_remark(out.str());
  }
}

void Web_Output::runtime_error(const string& error)
{
  if (log_level != Error_Output::QUIET)
  {
    ostringstream out;
    out<<"runtime error: "<<error;
    display_error(out.str(), 200);
  }
}

void Web_Output::runtime_remark(const string& error)
{
  if (log_level == Error_Output::VERBOSE)
  {
    ostringstream out;
    out<<"runtime remark: "<<error;
    display_remark(out.str());
  }
}

void Web_Output::enforce_header(uint write_mime)
{
  if (header_written == not_yet)
    write_html_header("", "", write_mime);
}

void Web_Output::write_html_header
    (const string& timestamp, const string& area_timestamp, uint write_mime, bool write_js_init,
     bool write_remarks)
{
  if (header_written != not_yet)
    return;
  header_written = html;

  if (write_mime > 0)
  {
    if (write_mime != 200)
    {
      if (write_mime == 504)
        cout<<"Status: "<<write_mime<<" Gateway Timeout\n";
      else if (write_mime == 400)
        cout<<"Status: "<<write_mime<<" Bad Request\n";
      else if (write_mime == 429)
        cout<<"Status: "<<write_mime<<" Too Many Requests\n";
      else
        cout<<"Status: "<<write_mime<<"\n";
    }
    if (allow_headers != "")
      cout<<"Access-Control-Allow-Headers: "<<allow_headers<<'\n';
    if (has_origin)
      cout<<"Access-Control-Allow-Origin: *\n"
            "Access-Control-Max-Age: 600\n";
    if (http_method == http_options)
      cout<<"Access-Control-Allow-Methods: GET, POST, OPTIONS\n"
            "Content-Length: 0\n";
    cout<<"Content-type: text/html; charset=utf-8\n\n";
    if (http_method == http_options || http_method == http_head)
      return;
  }
  cout<<
  "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
  "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\"\n"
  "    \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n"
  "\n"
  "\n"
  "  <meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\" lang=\"en\"/>\n"
  "  <title>OSM3S Response</title>\n"
  "\n";
  cout<<(write_js_init ? "\n\n" : "\n\n");
  if (write_remarks)
  {
    cout<<
    "
The data included in this document is from www.openstreetmap.org. "
    "The data is made available under ODbL.
\n";
    if (timestamp != "")
    {
      cout<<"
Data included until: "<<timestamp;
      if (area_timestamp != "")
        cout<<"
Areas based on data until: "<<area_timestamp;
      cout<<"
\n";
    }
  }
}

void Web_Output::write_xml_header
    (const string& timestamp, const string& area_timestamp, bool write_mime)
{
  if (header_written != not_yet)
    return;
  header_written = xml;

  if (write_mime)
  {
    if (allow_headers != "")
      cout<<"Access-Control-Allow-Headers: "<<allow_headers<<'\n';
    if (has_origin)
      cout<<"Access-Control-Allow-Origin: *\n"
            "Access-Control-Max-Age: 600\n";
    if (http_method == http_options)
      cout<<"Access-Control-Allow-Methods: GET, POST, OPTIONS\n"
            "Content-Length: 0\n";
    cout<<"Content-type: application/osm3s+xml\n\n";
    if (http_method == http_options || http_method == http_head)
      return;
  }

  cout<<
  "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<osm version=\"0.6\" generator=\"Overpass API\">\n"
  "<note>The data included in this document is from www.openstreetmap.org. "
  "The data is made available under ODbL.</note>\n";
  cout<<"<meta osm_base=\""<<timestamp<<'\"';
  if (area_timestamp != "")
    cout<<" areas=\""<<area_timestamp<<"\"";
  cout<<"/>\n\n";
}

void Web_Output::write_json_header
    (const string& timestamp, const string& area_timestamp, bool write_mime)
{
  if (header_written != not_yet)
    return;
  header_written = json;

  if (write_mime)
  {
    if (allow_headers != "")
      cout<<"Access-Control-Allow-Headers: "<<allow_headers<<'\n';
    if (has_origin)
      cout<<"Access-Control-Allow-Origin: *\n"
            "Access-Control-Max-Age: 600\n";
    if (http_method == http_options)
      cout<<"Access-Control-Allow-Methods: GET, POST, OPTIONS\n"
            "Content-Length: 0\n";
    cout<<"Content-type: application/json\n\n";
    if (http_method == http_options || http_method == http_head)
      return;
  }

  if (padding != "")
    cout<<padding<<"(";

  cout<<"{\n"
        "  \"version\": 0.6,\n"
        "  \"generator\": \"Overpass API\",\n"
        "  \"osm3s\": {\n"
	"    \"timestamp_osm_base\": \""<<timestamp<<"\",\n";
  if (area_timestamp != "")
    cout<<"    \"timestamp_areas_base\": \""<<area_timestamp<<"\",\n";
  cout<<"    \"copyright\": \"The data included in this document is from www.openstreetmap.org."
	" The data is made available under ODbL.\"\n"
        "  },\n"
        "  \"elements\": [\n\n";
}

void Web_Output::write_text_header
    (const string& timestamp, const string& area_timestamp, bool write_mime)
{
  if (header_written != not_yet)
    return;
  header_written = text;

  if (write_mime)
  {
    if (allow_headers != "")
      cout<<"Access-Control-Allow-Headers: "<<allow_headers<<'\n';
    if (has_origin)
      cout<<"Access-Control-Allow-Origin: *\n"
            "Access-Control-Max-Age: 600\n";
    if (http_method == http_options)
      cout<<"Access-Control-Allow-Methods: GET, POST, OPTIONS\n"
            "Content-Length: 0\n";
    cout<<"Content-type: text/plain\n\n";
    if (http_method == http_options || http_method == http_head)
      return;
  }

  cout<<timestamp<<"\n";
}

void Web_Output::write_footer()
{
  if (http_method == http_options || http_method == http_head)
    return;
  if (header_written == xml)
    cout<<"\n</osm>\n";
  else if (header_written == html)
    cout<<"\n\n\n";
  else if (header_written == json)
    cout<<"\n\n  ]"<<(messages != "" ? ",\n\"remark\": \"" + escape_cstr(messages) + "\"" : "")
        <<"\n}"<<(padding != "" ? ");\n" : "\n");
  header_written = final;
}

void Web_Output::display_remark(const string& text)
{
  enforce_header(200);
  if (http_method == http_options || http_method == http_head)
    return;
  if (header_written == xml)
    cout<<"<remark> "<<text<<" </remark>\n";
  else if (header_written == html)
    cout<<"
Remark: "
        <<text<<"
\n";
}

void Web_Output::display_error(const string& text, uint write_mime)
{
  enforce_header(write_mime);
  if (http_method == http_options || http_method == http_head)
    return;
  if (header_written == xml)
    cout<<"<remark> "<<text<<" </remark>\n";
  else if (header_written == html)
    cout<<"
Error: "
        <<text<<"
\n";
  else if (header_written == json)
    messages += text;
}
<commit_msg>Remove whitespace<commit_after>/** Copyright 2008, 2009, 2010, 2011, 2012 Roland Olbricht
*
* This file is part of Overpass_API.
*
* Overpass_API is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* Overpass_API is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Overpass_API.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "output.h"
#include "web_output.h"

#include <iomanip>
#include <iostream>
#include <sstream>
#include <string>

using namespace std;

void Web_Output::add_encoding_error(const string& error)
{
  if (log_level != Error_Output::QUIET)
  {
    ostringstream out;
    out<<"encoding error: "<<error;
    display_error(out.str(), 400);
  }
  encoding_errors = true;
}

void Web_Output::add_parse_error(const string& error, int line_number)
{
  if (log_level != Error_Output::QUIET)
  {
    ostringstream out;
    out<<"line "<<line_number<<": parse error: "<<error;
    display_error(out.str(), 400);
  }
  parse_errors = true;
}

void Web_Output::add_static_error(const string& error, int line_number)
{
  if (log_level != Error_Output::QUIET)
  {
    ostringstream out;
    out<<"line "<<line_number<<": static error: "<<error;
    display_error(out.str(), 400);
  }
  static_errors = true;
}

void Web_Output::add_encoding_remark(const string& error)
{
  if (log_level == Error_Output::VERBOSE)
  {
    ostringstream out;
    out<<"encoding remark: "<<error;
    display_remark(out.str());
  }
}

void Web_Output::add_parse_remark(const string& error, int line_number)
{
  if (log_level == Error_Output::VERBOSE)
  {
    ostringstream out;
    out<<"line "<<line_number<<": parse remark: "<<error;
    display_remark(out.str());
  }
}

void Web_Output::add_static_remark(const string& error, int line_number)
{
  if (log_level == Error_Output::VERBOSE)
  {
    ostringstream out;
    out<<"line "<<line_number<<": static remark: "<<error;
    display_remark(out.str());
  }
}

void Web_Output::runtime_error(const string& error)
{
  if (log_level != Error_Output::QUIET)
  {
    ostringstream out;
    out<<"runtime error: "<<error;
    display_error(out.str(), 200);
  }
}

void Web_Output::runtime_remark(const string& error)
{
  if (log_level == Error_Output::VERBOSE)
  {
    ostringstream out;
    out<<"runtime remark: "<<error;
    display_remark(out.str());
  }
}

void Web_Output::enforce_header(uint write_mime)
{
  if (header_written == not_yet)
    write_html_header("", "", write_mime);
}

void Web_Output::write_html_header
    (const string& timestamp, const string& area_timestamp, uint write_mime, bool write_js_init,
     bool write_remarks)
{
  if (header_written != not_yet)
    return;
  header_written = html;

  if (write_mime > 0)
  {
    if (write_mime != 200)
    {
      if (write_mime == 504)
        cout<<"Status: "<<write_mime<<" Gateway Timeout\n";
      else if (write_mime == 400)
        cout<<"Status: "<<write_mime<<" Bad Request\n";
      else if (write_mime == 429)
        cout<<"Status: "<<write_mime<<" Too Many Requests\n";
      else
        cout<<"Status: "<<write_mime<<"\n";
    }
    if (allow_headers != "")
      cout<<"Access-Control-Allow-Headers: "<<allow_headers<<'\n';
    if (has_origin)
      cout<<"Access-Control-Allow-Origin: *\n"
            "Access-Control-Max-Age: 600\n";
    if (http_method == http_options)
      cout<<"Access-Control-Allow-Methods: GET, POST, OPTIONS\n"
            "Content-Length: 0\n";
    cout<<"Content-type: text/html; charset=utf-8\n\n";
    if (http_method == http_options || http_method == http_head)
      return;
  }
  cout<<
  "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
  "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\"\n"
  "    \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n"
  "\n"
  "\n"
  "  <meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\" lang=\"en\"/>\n"
  "  <title>OSM3S Response</title>\n"
  "\n";
  cout<<(write_js_init ? "\n\n" : "\n\n");
  if (write_remarks)
  {
    cout<<
    "
The data included in this document is from www.openstreetmap.org. "
    "The data is made available under ODbL.
\n";
    if (timestamp != "")
    {
      cout<<"
Data included until: "<<timestamp;
      if (area_timestamp != "")
        cout<<"
Areas based on data until: "<<area_timestamp;
      cout<<"
\n";
    }
  }
}

void Web_Output::write_xml_header
    (const string& timestamp, const string& area_timestamp, bool write_mime)
{
  if (header_written != not_yet)
    return;
  header_written = xml;

  if (write_mime)
  {
    if (allow_headers != "")
      cout<<"Access-Control-Allow-Headers: "<<allow_headers<<'\n';
    if (has_origin)
      cout<<"Access-Control-Allow-Origin: *\n"
            "Access-Control-Max-Age: 600\n";
    if (http_method == http_options)
      cout<<"Access-Control-Allow-Methods: GET, POST, OPTIONS\n"
            "Content-Length: 0\n";
    cout<<"Content-type: application/osm3s+xml\n\n";
    if (http_method == http_options || http_method == http_head)
      return;
  }

  cout<<
  "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<osm version=\"0.6\" generator=\"Overpass API\">\n"
  "<note>The data included in this document is from www.openstreetmap.org. "
  "The data is made available under ODbL.</note>\n";
  cout<<"<meta osm_base=\""<<timestamp<<'\"';
  if (area_timestamp != "")
    cout<<" areas=\""<<area_timestamp<<"\"";
  cout<<"/>\n\n";
}

void Web_Output::write_json_header
    (const string& timestamp, const string& area_timestamp, bool write_mime)
{
  if (header_written != not_yet)
    return;
  header_written = json;

  if (write_mime)
  {
    if (allow_headers != "")
      cout<<"Access-Control-Allow-Headers: "<<allow_headers<<'\n';
    if (has_origin)
      cout<<"Access-Control-Allow-Origin: *\n"
            "Access-Control-Max-Age: 600\n";
    if (http_method == http_options)
      cout<<"Access-Control-Allow-Methods: GET, POST, OPTIONS\n"
            "Content-Length: 0\n";
    cout<<"Content-type: application/json\n\n";
    if (http_method == http_options || http_method == http_head)
      return;
  }

  if (padding != "")
    cout<<padding<<"(";

  cout<<"{\n"
        "  \"version\": 0.6,\n"
        "  \"generator\": \"Overpass API\",\n"
        "  \"osm3s\": {\n"
	"    \"timestamp_osm_base\": \""<<timestamp<<"\",\n";
  if (area_timestamp != "")
    cout<<"    \"timestamp_areas_base\": \""<<area_timestamp<<"\",\n";
  cout<<"    \"copyright\": \"The data included in this document is from www.openstreetmap.org."
	" The data is made available under ODbL.\"\n"
        "  },\n"
        "  \"elements\": [\n\n";
}

void Web_Output::write_text_header
    (const string& timestamp, const string& area_timestamp, bool write_mime)
{
  if (header_written != not_yet)
    return;
  header_written = text;

  if (write_mime)
  {
    if (allow_headers != "")
      cout<<"Access-Control-Allow-Headers: "<<allow_headers<<'\n';
    if (has_origin)
      cout<<"Access-Control-Allow-Origin: *\n"
            "Access-Control-Max-Age: 600\n";
    if (http_method == http_options)
      cout<<"Access-Control-Allow-Methods: GET, POST, OPTIONS\n"
            "Content-Length: 0\n";
    cout<<"Content-type: text/plain\n\n";
    if (http_method == http_options || http_method == http_head)
      return;
  }

  cout<<timestamp<<"\n";
}

void Web_Output::write_footer()
{
  if (http_method == http_options || http_method == http_head)
    return;
  if (header_written == xml)
    cout<<"\n</osm>\n";
  else if (header_written == html)
    cout<<"\n\n\n";
  else if (header_written == json)
    cout<<"\n\n  ]"<<(messages != "" ? ",\n\"remark\": \"" + escape_cstr(messages) + "\"" : "")
        <<"\n}"<<(padding != "" ? ");\n" : "\n");
  header_written = final;
}

void Web_Output::display_remark(const string& text)
{
  enforce_header(200);
  if (http_method == http_options || http_method == http_head)
    return;
  if (header_written == xml)
    cout<<"<remark> "<<text<<" </remark>\n";
  else if (header_written == html)
    cout<<"
Remark: "
        <<text<<"
\n";
}

void Web_Output::display_error(const string& text, uint write_mime)
{
  enforce_header(write_mime);
  if (http_method == http_options || http_method == http_head)
    return;
  if (header_written == xml)
    cout<<"<remark> "<<text<<" </remark>\n";
  else if (header_written == html)
    cout<<"
Error: "
        <<text<<"
\n";
  else if (header_written == json)
    messages += text;
}
<|endoftext|>