<commit_before>/*
 * Copyright 2017 CodiLime
 *
 * 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 <QAction>
#include <QApplication>
#include <QFileDialog>
#include <QMenuBar>
#include <QMessageBox>
#include <QUrl>
#include <QMenu>

#include "db/db.h"
#include "dbif/method.h"
#include "dbif/promise.h"
#include "dbif/types.h"
#include "dbif/universe.h"
#include "client/dbif.h"
#include "util/version.h"
#include "ui/databaseinfo.h"
#include "ui/veles_mainwindow.h"
#include "ui/hexeditwidget.h"
#include "ui/nodetreewidget.h"
#include "ui/optionsdialog.h"
#include "ui/logwidget.h"
#include "ui/nodewidget.h"

namespace veles {
namespace ui {

/*****************************************************************************/
/* VelesMainWindow - Public methods */
/*****************************************************************************/

VelesMainWindow::VelesMainWindow() : MainWindowWithDetachableDockWidgets(),
    database_dock_widget_(0), log_dock_widget_(0) {
  setAcceptDrops(true);
  resize(1024, 768);
  init();
}

void VelesMainWindow::addFile(const QString& path) {
  files_to_upload_once_connected_.push_back(path);
}

/*****************************************************************************/
/* VelesMainWindow - Protected methods */
/*****************************************************************************/

void VelesMainWindow::dropEvent(QDropEvent *ev) {
  QList<QUrl> urls = ev->mimeData()->urls();
  for (auto url : urls) {
    if (!url.isLocalFile()) {
      continue;
    }
    createFileBlob(url.toLocalFile());
  }
}

void VelesMainWindow::dragEnterEvent(QDragEnterEvent *ev) { ev->accept(); }

void VelesMainWindow::showEvent(QShowEvent* event) {
  emit shown();
}

/*****************************************************************************/
/* VelesMainWindow - Private Slots */
/*****************************************************************************/

void VelesMainWindow::open() {
  QString fileName = QFileDialog::getOpenFileName(this);
  if (!fileName.isEmpty()) {
    createFileBlob(fileName);
  }
}

void VelesMainWindow::newFile() { createFileBlob(""); }

void VelesMainWindow::about() {
  QMessageBox::about(
      this, tr("About Veles"),
      tr("This is Veles, a binary analysis tool and editor.\n"
         "Version: %1\n"
         "\n"
         "Report bugs to contact@veles.io\n"
         "https://veles.io/\n"
         "\n"
         "Copyright 2017 CodiLime\n"
         "Licensed under the Apache License, Version 2.0\n"
      ).arg(util::version::string));
}

/*****************************************************************************/
/* VelesMainWindow - Private methods */
/*****************************************************************************/

void VelesMainWindow::init() {
  connection_manager_ = new ConnectionManager(this);
  createActions();
  createMenus();
  createLogWindow();
  createDb();

  options_dialog_ = new OptionsDialog(this);

  connect(options_dialog_, &QDialog::accepted, [this]() {
    for(auto main_window : MainWindowWithDetachableDockWidgets
        ::getMainWindows()) {
      QList<View*> views = main_window->findChildren<View*>();
      for(auto view : views) {
        view->reapplySettings();
      }
    }
  });

  tool_bar_ = addToolBar("Connection");
  tool_bar_->setContextMenuPolicy(Qt::PreventContextMenu);

  ConnectionsWidget* connections_widget = new ConnectionsWidget(this);
  tool_bar_->addWidget(connections_widget);
  connect(connection_manager_, &ConnectionManager::connectionStatusChanged,
      connections_widget,
      &ConnectionsWidget::updateConnectionStatus);
  connect(connection_manager_, &ConnectionManager::connectionsChanged,
      connections_widget, &ConnectionsWidget::updateConnections);

  connection_notification_widget_ = new ConnectionNotificationWidget(this);
  connect(connection_manager_, &ConnectionManager::connectionStatusChanged,
      connection_notification_widget_,
      &ConnectionNotificationWidget::updateConnectionStatus);
  connect(connection_manager_, &ConnectionManager::connectionStatusChanged,
      this, &VelesMainWindow::updateConnectionStatus, Qt::QueuedConnection);
  tool_bar_->addWidget(connection_notification_widget_);

  bringDockWidgetToFront(log_dock_widget_);
  log_dock_widget_->setFocus(Qt::OtherFocusReason);

  connection_manager_->connectionDialogAccepted();
  connect(this, &VelesMainWindow::shown,
      connection_manager_, &ConnectionManager::raiseConnectionDialog,
      Qt::QueuedConnection);

  updateConnectionStatus(
      client::NetworkClient::ConnectionStatus::NotConnected);
}

void VelesMainWindow::createActions() {
  new_file_act_ = new QAction(tr("&New..."), this);
  new_file_act_->setShortcuts(QKeySequence::New);
  new_file_act_->setStatusTip(tr("Open a new file"));
  connect(new_file_act_, SIGNAL(triggered()), this, SLOT(newFile()));

  open_act_ = new QAction(QIcon(":/images/open.png"), tr("&Open..."), this);
  open_act_->setShortcuts(QKeySequence::Open);
  open_act_->setStatusTip(tr("Open an existing file"));
  connect(open_act_, SIGNAL(triggered()), this, SLOT(open()));

  exit_act_ = new QAction(tr("E&xit"), this);
  exit_act_->setShortcuts(QKeySequence::Quit);
  exit_act_->setStatusTip(tr("Exit the application"));
  connect(exit_act_, SIGNAL(triggered()), qApp, SLOT(closeAllWindows()));

  show_database_act_ = new QAction(tr("Show database view"), this);
  show_database_act_->setStatusTip(tr("Show database view"));
  connect(show_database_act_, SIGNAL(triggered()), this, SLOT(showDatabase()));

  show_log_act_ = new QAction(tr("Show log"), this);
  show_log_act_->setStatusTip(tr("Show log"));
  connect(show_log_act_, SIGNAL(triggered()), this, SLOT(showLog()));

  about_act_ = new QAction(tr("&About"), this);
  about_act_->setStatusTip(tr("Show the application's About box"));
  connect(about_act_, SIGNAL(triggered()), this, SLOT(about()));

  about_qt_act_ = new QAction(tr("About &Qt"), this);
  about_qt_act_->setStatusTip(tr("Show the Qt library's About box"));
  connect(about_qt_act_, SIGNAL(triggered()), qApp, SLOT(aboutQt()));

  options_act_ = new QAction(tr("&Options"), this);
  options_act_->setStatusTip(
      tr("Show the Dialog to select applications options"));
  connect(options_act_, &QAction::triggered, this,
          [this]() { options_dialog_->show(); });
}

void VelesMainWindow::createMenus() {
  file_menu_ = menuBar()->addMenu(tr("&File"));

  //Not implemented yet.
  //fileMenu->addAction(newFileAct);

  file_menu_->addAction(open_act_);
  file_menu_->addSeparator();
  file_menu_->addAction(options_act_);
  file_menu_->addSeparator();
  file_menu_->addAction(exit_act_);

  view_menu_ = menuBar()->addMenu(tr("&View"));
  view_menu_->addAction(show_database_act_);
  view_menu_->addAction(show_log_act_);

  QMenu* connection_menu = menuBar()->addMenu(tr("Connection"));
  connection_menu->addAction(
      connection_manager_->showConnectionDialogAction());
  connection_menu->addAction(connection_manager_->disconnectAction());
  connection_menu->addAction(
      connection_manager_->killLocallyCreatedServerAction());

  help_menu_ = menuBar()->addMenu(tr("&Help"));
  help_menu_->addAction(about_act_);
  help_menu_->addAction(about_qt_act_);
}

void VelesMainWindow::updateParsers(dbif::PInfoReply reply) {
  parsers_list_ = reply.dynamicCast<dbif::ParsersListRequest::ReplyType>()->parserIds;
  QList<QDockWidget*> dock_widgets = findChildren<QDockWidget*>();
  for(auto dock : dock_widgets) {
    if(auto hex_tab = dynamic_cast<HexEditWidget *>(dock->widget())) {
      hex_tab->setParserIds(parsers_list_);
    } else if(auto node_tab = dynamic_cast<NodeTreeWidget *>(dock->widget())) {
      node_tab->setParserIds(parsers_list_);
    }
  }
}

void VelesMainWindow::showDatabase() {
  if (database_dock_widget_ == nullptr) {
    createDb();
  }

  database_dock_widget_->raise();

  if (database_dock_widget_->window()->isMinimized()) {
    database_dock_widget_->window()->showNormal();
  }

  database_dock_widget_->window()->raise();
}

void VelesMainWindow::showLog() {
  if (log_dock_widget_ == nullptr) {
    createLogWindow();
  }

  log_dock_widget_->raise();

  if(log_dock_widget_->window()->isMinimized()) {
    log_dock_widget_->window()->showNormal();
  }

  log_dock_widget_->window()->raise();
}

void VelesMainWindow::updateConnectionStatus(
    client::NetworkClient::ConnectionStatus connection_status) {
  if (connection_status
      == client::NetworkClient::ConnectionStatus::NotConnected) {
    auto main_windows = MainWindowWithDetachableDockWidgets::allMainWindows();
    for (auto main_window : main_windows) {
      auto docks = main_window->findChildren<DockWidget*>();
      for(auto dock : docks) {
        if(dock != log_dock_widget_ && dock != database_dock_widget_) {
          dock->close();
        }
      }
    }

    database_dock_widget_->widget()->setEnabled(false);
    open_act_->setEnabled(false);
  } else if (connection_status
      == client::NetworkClient::ConnectionStatus::Connected) {
    database_dock_widget_->widget()->setEnabled(true);
    open_act_->setEnabled(true);

    if (!files_to_upload_once_connected_.empty()) {
      QTextStream out(LogWidget::output());
      out << "Uploading files specified as command line arguments:" << endl;

      for (const auto& path : files_to_upload_once_connected_) {
        out << "    " << path << endl;
        createFileBlob(path);
        QApplication::processEvents();
      }

      files_to_upload_once_connected_.clear();
    }
  }
}

void VelesMainWindow::createDb() {
  if (database_ == nullptr) {
#if 0
    database_ = db::create_db();
#else
    auto nc = new client::NCWrapper(
        connection_manager_->networkClient(), this);
    database_ = QSharedPointer<client::NCObjectHandle>::create(
        nc, *data::NodeID::getRootNodeId(), dbif::ObjectType::ROOT);
#endif
  }
  auto database_info = new DatabaseInfo(database_);
  DockWidget* dock_widget = new DockWidget;
  dock_widget->setAllowedAreas(Qt::AllDockWidgetAreas);
  dock_widget->setWindowTitle("Database");
  dock_widget->setFeatures(
      QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetFloatable);
  dock_widget->setWidget(database_info);
  dock_widget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
  auto children = findChildren<DockWidget*>();
  if (!children.empty()) {
    tabifyDockWidget(children.back(), dock_widget);
  } else {
    addDockWidget(Qt::LeftDockWidgetArea, dock_widget);
  }

  connect(database_info, &DatabaseInfo::goFile,
          [this](dbif::ObjectHandle fileBlob, QString fileName) {
            createHexEditTab(fileName, fileBlob);
          });

  connect(database_info, &DatabaseInfo::newFile, [this]() { open(); });

  auto promise = database_->asyncSubInfo<dbif::ParsersListRequest>(this);
  connect(promise, &dbif::InfoPromise::gotInfo, this, &VelesMainWindow::updateParsers);
  database_dock_widget_ = dock_widget;
  QApplication::processEvents();
  updateDocksAndTabs();
}

void VelesMainWindow::createFileBlob(QString fileName) {
  data::BinData data(8, 0);

  if (!fileName.isEmpty()) {
    QFile file(fileName);
    file.setFileName(fileName);
    if(!file.open(QIODevice::ReadOnly)){
      QMessageBox::warning(
          this, tr("Failed to open"),
          QString(tr("Failed to open \"%1\".")).arg(fileName));
      return;
    }
    QByteArray bytes = file.readAll();
    if(bytes.size() == 0 && file.size() != bytes.size()) {
      QMessageBox::warning(
          this, tr("File too large"),
          QString(tr("Failed to open \"%1\" due to current size limitation.")
                  ).arg(fileName));
      return;
    }
    data = data::BinData(8, bytes.size(),
                         reinterpret_cast<uint8_t *>(bytes.data()));
  }
  auto promise =
      database_->asyncRunMethod<dbif::RootCreateFileBlobFromDataRequest>(
          this, data, fileName);
  connect(promise, &dbif::MethodResultPromise::gotResult,
      [this, fileName](dbif::PMethodReply reply) {
    createHexEditTab(
        fileName.isEmpty() ? "untitled" : fileName,
        reply.dynamicCast<dbif::RootCreateFileBlobFromDataRequest::ReplyType>()
        ->object);
  });

  connect(promise, &dbif::MethodResultPromise::gotError,
          [this, fileName](dbif::PError error) {
            QMessageBox::warning(this, tr("Veles"),
                tr("Cannot load file %1.").arg(fileName));
          });
}

void VelesMainWindow::createHexEditTab(QString fileName,
    dbif::ObjectHandle fileBlob) {
  QSharedPointer<FileBlobModel> data_model(
      new FileBlobModel(fileBlob, {QFileInfo(fileName).fileName()}));
  QSharedPointer<QItemSelectionModel> selection_model(
      new QItemSelectionModel(data_model.data()));

  NodeWidget* node_widget = new NodeWidget(this, data_model, selection_model);
  addTab(node_widget, data_model->path().join(" : "), nullptr);
}

void VelesMainWindow::createLogWindow() {
  DockWidget* dock_widget = new DockWidget;
  dock_widget->setAllowedAreas(Qt::AllDockWidgetAreas);
  dock_widget->setWindowTitle("Log");
  dock_widget->setFeatures(
      QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetFloatable);
  dock_widget->setWidget(new LogWidget);
  dock_widget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);

  auto children = findChildren<DockWidget*>();
  if (!children.empty()) {
    tabifyDockWidget(children.back(), dock_widget);
  } else {
    addDockWidget(Qt::LeftDockWidgetArea, dock_widget);
  }

  log_dock_widget_ = dock_widget;
  QApplication::processEvents();
  updateDocksAndTabs();
}

}  // namespace ui
}  // namespace veles
<commit_msg>(Dis)connecting doesn't cause a crash when database tab is closed<commit_after>/*
 * Copyright 2017 CodiLime
 *
 * 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 <QAction>
#include <QApplication>
#include <QFileDialog>
#include <QMenuBar>
#include <QMessageBox>
#include <QUrl>
#include <QMenu>

#include "db/db.h"
#include "dbif/method.h"
#include "dbif/promise.h"
#include "dbif/types.h"
#include "dbif/universe.h"
#include "client/dbif.h"
#include "util/version.h"
#include "ui/databaseinfo.h"
#include "ui/veles_mainwindow.h"
#include "ui/hexeditwidget.h"
#include "ui/nodetreewidget.h"
#include "ui/optionsdialog.h"
#include "ui/logwidget.h"
#include "ui/nodewidget.h"

namespace veles {
namespace ui {

/*****************************************************************************/
/* VelesMainWindow - Public methods */
/*****************************************************************************/

VelesMainWindow::VelesMainWindow() : MainWindowWithDetachableDockWidgets(),
    database_dock_widget_(0), log_dock_widget_(0) {
  setAcceptDrops(true);
  resize(1024, 768);
  init();
}

void VelesMainWindow::addFile(const QString& path) {
  files_to_upload_once_connected_.push_back(path);
}

/*****************************************************************************/
/* VelesMainWindow - Protected methods */
/*****************************************************************************/

void VelesMainWindow::dropEvent(QDropEvent *ev) {
  QList<QUrl> urls = ev->mimeData()->urls();
  for (auto url : urls) {
    if (!url.isLocalFile()) {
      continue;
    }
    createFileBlob(url.toLocalFile());
  }
}

void VelesMainWindow::dragEnterEvent(QDragEnterEvent *ev) { ev->accept(); }

void VelesMainWindow::showEvent(QShowEvent* event) {
  emit shown();
}

/*****************************************************************************/
/* VelesMainWindow - Private Slots */
/*****************************************************************************/

void VelesMainWindow::open() {
  QString fileName = QFileDialog::getOpenFileName(this);
  if (!fileName.isEmpty()) {
    createFileBlob(fileName);
  }
}

void VelesMainWindow::newFile() { createFileBlob(""); }

void VelesMainWindow::about() {
  QMessageBox::about(
      this, tr("About Veles"),
      tr("This is Veles, a binary analysis tool and editor.\n"
         "Version: %1\n"
         "\n"
         "Report bugs to contact@veles.io\n"
         "https://veles.io/\n"
         "\n"
         "Copyright 2017 CodiLime\n"
         "Licensed under the Apache License, Version 2.0\n"
      ).arg(util::version::string));
}

/*****************************************************************************/
/* VelesMainWindow - Private methods */
/*****************************************************************************/

void VelesMainWindow::init() {
  connection_manager_ = new ConnectionManager(this);
  createActions();
  createMenus();
  createLogWindow();
  createDb();

  options_dialog_ = new OptionsDialog(this);

  connect(options_dialog_, &QDialog::accepted, [this]() {
    for(auto main_window : MainWindowWithDetachableDockWidgets
        ::getMainWindows()) {
      QList<View*> views = main_window->findChildren<View*>();
      for(auto view : views) {
        view->reapplySettings();
      }
    }
  });

  tool_bar_ = addToolBar("Connection");
  tool_bar_->setContextMenuPolicy(Qt::PreventContextMenu);

  ConnectionsWidget* connections_widget = new ConnectionsWidget(this);
  tool_bar_->addWidget(connections_widget);
  connect(connection_manager_, &ConnectionManager::connectionStatusChanged,
      connections_widget,
      &ConnectionsWidget::updateConnectionStatus);
  connect(connection_manager_, &ConnectionManager::connectionsChanged,
      connections_widget, &ConnectionsWidget::updateConnections);

  connection_notification_widget_ = new ConnectionNotificationWidget(this);
  connect(connection_manager_, &ConnectionManager::connectionStatusChanged,
      connection_notification_widget_,
      &ConnectionNotificationWidget::updateConnectionStatus);
  connect(connection_manager_, &ConnectionManager::connectionStatusChanged,
      this, &VelesMainWindow::updateConnectionStatus, Qt::QueuedConnection);
  tool_bar_->addWidget(connection_notification_widget_);

  bringDockWidgetToFront(log_dock_widget_);
  log_dock_widget_->setFocus(Qt::OtherFocusReason);

  connection_manager_->connectionDialogAccepted();
  connect(this, &VelesMainWindow::shown,
      connection_manager_, &ConnectionManager::raiseConnectionDialog,
      Qt::QueuedConnection);

  updateConnectionStatus(
      client::NetworkClient::ConnectionStatus::NotConnected);
}

void VelesMainWindow::createActions() {
  new_file_act_ = new QAction(tr("&New..."), this);
  new_file_act_->setShortcuts(QKeySequence::New);
  new_file_act_->setStatusTip(tr("Open a new file"));
  connect(new_file_act_, SIGNAL(triggered()), this, SLOT(newFile()));

  open_act_ = new QAction(QIcon(":/images/open.png"), tr("&Open..."), this);
  open_act_->setShortcuts(QKeySequence::Open);
  open_act_->setStatusTip(tr("Open an existing file"));
  connect(open_act_, SIGNAL(triggered()), this, SLOT(open()));

  exit_act_ = new QAction(tr("E&xit"), this);
  exit_act_->setShortcuts(QKeySequence::Quit);
  exit_act_->setStatusTip(tr("Exit the application"));
  connect(exit_act_, SIGNAL(triggered()), qApp, SLOT(closeAllWindows()));

  show_database_act_ = new QAction(tr("Show database view"), this);
  show_database_act_->setStatusTip(tr("Show database view"));
  connect(show_database_act_, SIGNAL(triggered()), this, SLOT(showDatabase()));

  show_log_act_ = new QAction(tr("Show log"), this);
  show_log_act_->setStatusTip(tr("Show log"));
  connect(show_log_act_, SIGNAL(triggered()), this, SLOT(showLog()));

  about_act_ = new QAction(tr("&About"), this);
  about_act_->setStatusTip(tr("Show the application's About box"));
  connect(about_act_, SIGNAL(triggered()), this, SLOT(about()));

  about_qt_act_ = new QAction(tr("About &Qt"), this);
  about_qt_act_->setStatusTip(tr("Show the Qt library's About box"));
  connect(about_qt_act_, SIGNAL(triggered()), qApp, SLOT(aboutQt()));

  options_act_ = new QAction(tr("&Options"), this);
  options_act_->setStatusTip(
      tr("Show the Dialog to select applications options"));
  connect(options_act_, &QAction::triggered, this,
          [this]() { options_dialog_->show(); });
}

void VelesMainWindow::createMenus() {
  file_menu_ = menuBar()->addMenu(tr("&File"));

  //Not implemented yet.
  //fileMenu->addAction(newFileAct);

  file_menu_->addAction(open_act_);
  file_menu_->addSeparator();
  file_menu_->addAction(options_act_);
  file_menu_->addSeparator();
  file_menu_->addAction(exit_act_);

  view_menu_ = menuBar()->addMenu(tr("&View"));
  view_menu_->addAction(show_database_act_);
  view_menu_->addAction(show_log_act_);

  QMenu* connection_menu = menuBar()->addMenu(tr("Connection"));
  connection_menu->addAction(
      connection_manager_->showConnectionDialogAction());
  connection_menu->addAction(connection_manager_->disconnectAction());
  connection_menu->addAction(
      connection_manager_->killLocallyCreatedServerAction());

  help_menu_ = menuBar()->addMenu(tr("&Help"));
  help_menu_->addAction(about_act_);
  help_menu_->addAction(about_qt_act_);
}

void VelesMainWindow::updateParsers(dbif::PInfoReply reply) {
  parsers_list_ = reply.dynamicCast<dbif::ParsersListRequest::ReplyType>()->parserIds;
  QList<QDockWidget*> dock_widgets = findChildren<QDockWidget*>();
  for(auto dock : dock_widgets) {
    if(auto hex_tab = dynamic_cast<HexEditWidget *>(dock->widget())) {
      hex_tab->setParserIds(parsers_list_);
    } else if(auto node_tab = dynamic_cast<NodeTreeWidget *>(dock->widget())) {
      node_tab->setParserIds(parsers_list_);
    }
  }
}

void VelesMainWindow::showDatabase() {
  if (database_dock_widget_ == nullptr) {
    createDb();
  }

  database_dock_widget_->raise();

  if (database_dock_widget_->window()->isMinimized()) {
    database_dock_widget_->window()->showNormal();
  }

  database_dock_widget_->window()->raise();
}

void VelesMainWindow::showLog() {
  if (log_dock_widget_ == nullptr) {
    createLogWindow();
  }

  log_dock_widget_->raise();

  if(log_dock_widget_->window()->isMinimized()) {
    log_dock_widget_->window()->showNormal();
  }

  log_dock_widget_->window()->raise();
}

void VelesMainWindow::updateConnectionStatus(
    client::NetworkClient::ConnectionStatus connection_status) {
  if (connection_status
      == client::NetworkClient::ConnectionStatus::NotConnected) {
    auto main_windows = MainWindowWithDetachableDockWidgets::allMainWindows();
    for (auto main_window : main_windows) {
      auto docks = main_window->findChildren<DockWidget*>();
      for(auto dock : docks) {
        if(dock != log_dock_widget_ && dock != database_dock_widget_) {
          dock->close();
        }
      }
    }

    if (database_dock_widget_) {
      database_dock_widget_->widget()->setEnabled(false);
    }
    open_act_->setEnabled(false);
  } else if (connection_status
      == client::NetworkClient::ConnectionStatus::Connected) {

    if (database_dock_widget_) {
      database_dock_widget_->widget()->setEnabled(true);
    }

    open_act_->setEnabled(true);

    if (!files_to_upload_once_connected_.empty()) {
      QTextStream out(LogWidget::output());
      out << "Uploading files specified as command line arguments:" << endl;

      for (const auto& path : files_to_upload_once_connected_) {
        out << "    " << path << endl;
        createFileBlob(path);
        QApplication::processEvents();
      }

      files_to_upload_once_connected_.clear();
    }
  }
}

void VelesMainWindow::createDb() {
  if (database_ == nullptr) {
#if 0
    database_ = db::create_db();
#else
    auto nc = new client::NCWrapper(
        connection_manager_->networkClient(), this);
    database_ = QSharedPointer<client::NCObjectHandle>::create(
        nc, *data::NodeID::getRootNodeId(), dbif::ObjectType::ROOT);
#endif
  }
  auto database_info = new DatabaseInfo(database_);
  DockWidget* dock_widget = new DockWidget;
  dock_widget->setAllowedAreas(Qt::AllDockWidgetAreas);
  dock_widget->setWindowTitle("Database");
  dock_widget->setFeatures(
      QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetFloatable);
  dock_widget->setWidget(database_info);
  dock_widget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
  auto children = findChildren<DockWidget*>();
  if (!children.empty()) {
    tabifyDockWidget(children.back(), dock_widget);
  } else {
    addDockWidget(Qt::LeftDockWidgetArea, dock_widget);
  }

  connect(database_info, &DatabaseInfo::goFile,
          [this](dbif::ObjectHandle fileBlob, QString fileName) {
            createHexEditTab(fileName, fileBlob);
          });

  connect(database_info, &DatabaseInfo::newFile, [this]() { open(); });

  database_info->setEnabled(
      connection_manager_->networkClient()->connectionStatus()
      == client::NetworkClient::ConnectionStatus::Connected);

  auto promise = database_->asyncSubInfo<dbif::ParsersListRequest>(this);
  connect(promise, &dbif::InfoPromise::gotInfo, this, &VelesMainWindow::updateParsers);
  database_dock_widget_ = dock_widget;
  QApplication::processEvents();
  updateDocksAndTabs();
}

void VelesMainWindow::createFileBlob(QString fileName) {
  data::BinData data(8, 0);

  if (!fileName.isEmpty()) {
    QFile file(fileName);
    file.setFileName(fileName);
    if(!file.open(QIODevice::ReadOnly)){
      QMessageBox::warning(
          this, tr("Failed to open"),
          QString(tr("Failed to open \"%1\".")).arg(fileName));
      return;
    }
    QByteArray bytes = file.readAll();
    if(bytes.size() == 0 && file.size() != bytes.size()) {
      QMessageBox::warning(
          this, tr("File too large"),
          QString(tr("Failed to open \"%1\" due to current size limitation.")
                  ).arg(fileName));
      return;
    }
    data = data::BinData(8, bytes.size(),
                         reinterpret_cast<uint8_t *>(bytes.data()));
  }
  auto promise =
      database_->asyncRunMethod<dbif::RootCreateFileBlobFromDataRequest>(
          this, data, fileName);
  connect(promise, &dbif::MethodResultPromise::gotResult,
      [this, fileName](dbif::PMethodReply reply) {
    createHexEditTab(
        fileName.isEmpty() ? "untitled" : fileName,
        reply.dynamicCast<dbif::RootCreateFileBlobFromDataRequest::ReplyType>()
        ->object);
  });

  connect(promise, &dbif::MethodResultPromise::gotError,
          [this, fileName](dbif::PError error) {
            QMessageBox::warning(this, tr("Veles"),
                tr("Cannot load file %1.").arg(fileName));
          });
}

void VelesMainWindow::createHexEditTab(QString fileName,
    dbif::ObjectHandle fileBlob) {
  QSharedPointer<FileBlobModel> data_model(
      new FileBlobModel(fileBlob, {QFileInfo(fileName).fileName()}));
  QSharedPointer<QItemSelectionModel> selection_model(
      new QItemSelectionModel(data_model.data()));

  NodeWidget* node_widget = new NodeWidget(this, data_model, selection_model);
  addTab(node_widget, data_model->path().join(" : "), nullptr);
}

void VelesMainWindow::createLogWindow() {
  DockWidget* dock_widget = new DockWidget;
  dock_widget->setAllowedAreas(Qt::AllDockWidgetAreas);
  dock_widget->setWindowTitle("Log");
  dock_widget->setFeatures(
      QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetFloatable);
  dock_widget->setWidget(new LogWidget);
  dock_widget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);

  auto children = findChildren<DockWidget*>();
  if (!children.empty()) {
    tabifyDockWidget(children.back(), dock_widget);
  } else {
    addDockWidget(Qt::LeftDockWidgetArea, dock_widget);
  }

  log_dock_widget_ = dock_widget;
  QApplication::processEvents();
  updateDocksAndTabs();
}

}  // namespace ui
}  // namespace veles
<|endoftext|>


<commit_before>#include "ezgraver.h"

#include <QSerialPort>
#include <QSerialPortInfo>
#include <QDebug>
#include <QBitmap>
#include <QBuffer>

#include <iterator>
#include <algorithm>
#include <functional>

EzGraver::EzGraver(std::shared_ptr<QSerialPort> serial) : _serial{serial} {}

void EzGraver::start(unsigned char const& burnTime) {
    _setBurnTime(burnTime);
    qDebug() << "starting engrave process";
    _transmit(0xF1);
}

void EzGraver::_setBurnTime(unsigned char const& burnTime) {
    if(burnTime < 0x01 || burnTime > 0xF0) {
        throw new std::out_of_range("burntime out of range");
    }
    qDebug() << "setting burn time to:" << qPrintable(burnTime);
    _transmit(burnTime);
}

void EzGraver::pause() {
    qDebug() << "pausing engrave process";
    _transmit(0xF2);
}

void EzGraver::reset() {
    qDebug() << "resetting";
    _transmit(0xF9);
}

void EzGraver::home() {
    qDebug() << "moving to home";
    _transmit(0xF3);
}

void EzGraver::center() {
    qDebug() << "moving to center";
    _transmit(0xFB);
}

void EzGraver::preview() {
    qDebug() << "drawing image preview";
    _transmit(0xF4);
}

void EzGraver::up() {
    qDebug() << "moving up";
    _transmit(0xF5);
}

void EzGraver::down() {
    qDebug() << "moving down";
    _transmit(0xF6);
}

void EzGraver::left() {
    qDebug() << "moving left";
    _transmit(0xF7);
}

void EzGraver::right() {
    qDebug() << "moving right";
    _transmit(0xF8);
}

void EzGraver::erase() {
    qDebug() << "erasing EEPROM";
    QByteArray bytes{8, static_cast<char>(0xFE)};
    _transmit(bytes);
}

#include <QFile>
void EzGraver::uploadImage(QImage const& originalImage) {
    qDebug() << "converting image to bitmap";
    QImage image{originalImage
            .scaled(512, 512)
            .mirrored()
            .convertToFormat(QImage::Format_Mono)};
    image.invertPixels();

    QByteArray bytes{};
    QBuffer buffer{&bytes};
    image.save(&buffer, "BMP");
    uploadImage(bytes);
}

void EzGraver::uploadImage(QByteArray const& image) {
    qDebug() << "uploading image";
    _transmit(image);
}

void EzGraver::awaitTransmission(int msecs) {
    _serial->waitForBytesWritten(msecs);
}

void EzGraver::_transmit(unsigned char const& data) {
    _transmit(QByteArray{1, static_cast<char>(data)});
}

void EzGraver::_transmit(QByteArray const& data) {
    QString hex{data.count() < 10 ? data.toHex() : ""};
    qDebug() << "transmitting" << data.length() << "bytes:" << hex;
    _serial->write(data);
}

EzGraver::~EzGraver() {
    qDebug() << "EzGraver is being destroyed, closing serial port";
    _serial->close();
}

QStringList EzGraver::availablePorts() {
    auto toPortName = [](QSerialPortInfo const& port) { return port.portName(); };
    auto ports = QSerialPortInfo::availablePorts();
    QStringList result{};

    std::transform(ports.cbegin(), ports.cend(), std::back_inserter<QStringList>(result), toPortName);
    return result;
}

std::shared_ptr<EzGraver> EzGraver::create(QString const& portName) {
    qDebug() << "instantiating EzGraver on port" << portName;

    std::shared_ptr<QSerialPort> serial{new QSerialPort(portName)};
    serial->setBaudRate(QSerialPort::Baud57600, QSerialPort::AllDirections);
    serial->setParity(QSerialPort::Parity::NoParity);
    serial->setDataBits(QSerialPort::DataBits::Data8);
    serial->setStopBits(QSerialPort::StopBits::OneStop);

    if(!serial->open(QIODevice::ReadWrite)) {
        qDebug() << "failed to establish a connection on port" << portName;
        qDebug() << serial->errorString();
        throw std::runtime_error{QString{"failed to connect to port %1 (%2)"}.arg(portName, serial->errorString()).toStdString()};
    }

    return std::shared_ptr<EzGraver>{new EzGraver(serial)};
}
<commit_msg>Fixed truncation warning on MSVC.<commit_after>#include "ezgraver.h"

#include <QSerialPort>
#include <QSerialPortInfo>
#include <QDebug>
#include <QBitmap>
#include <QBuffer>

#include <iterator>
#include <algorithm>
#include <functional>

EzGraver::EzGraver(std::shared_ptr<QSerialPort> serial) : _serial{serial} {}

void EzGraver::start(unsigned char const& burnTime) {
    _setBurnTime(burnTime);
    qDebug() << "starting engrave process";
    _transmit(0xF1);
}

void EzGraver::_setBurnTime(unsigned char const& burnTime) {
    if(burnTime < 0x01 || burnTime > 0xF0) {
        throw new std::out_of_range("burntime out of range");
    }
    qDebug() << "setting burn time to:" << qPrintable(burnTime);
    _transmit(burnTime);
}

void EzGraver::pause() {
    qDebug() << "pausing engrave process";
    _transmit(0xF2);
}

void EzGraver::reset() {
    qDebug() << "resetting";
    _transmit(0xF9);
}

void EzGraver::home() {
    qDebug() << "moving to home";
    _transmit(0xF3);
}

void EzGraver::center() {
    qDebug() << "moving to center";
    _transmit(0xFB);
}

void EzGraver::preview() {
    qDebug() << "drawing image preview";
    _transmit(0xF4);
}

void EzGraver::up() {
    qDebug() << "moving up";
    _transmit(0xF5);
}

void EzGraver::down() {
    qDebug() << "moving down";
    _transmit(0xF6);
}

void EzGraver::left() {
    qDebug() << "moving left";
    _transmit(0xF7);
}

void EzGraver::right() {
    qDebug() << "moving right";
    _transmit(0xF8);
}

void EzGraver::erase() {
    qDebug() << "erasing EEPROM";
    _transmit(QByteArray{8, '\xFE'});
}

#include <QFile>
void EzGraver::uploadImage(QImage const& originalImage) {
    qDebug() << "converting image to bitmap";
    QImage image{originalImage
            .scaled(512, 512)
            .mirrored()
            .convertToFormat(QImage::Format_Mono)};
    image.invertPixels();

    QByteArray bytes{};
    QBuffer buffer{&bytes};
    image.save(&buffer, "BMP");
    uploadImage(bytes);
}

void EzGraver::uploadImage(QByteArray const& image) {
    qDebug() << "uploading image";
    _transmit(image);
}

void EzGraver::awaitTransmission(int msecs) {
    _serial->waitForBytesWritten(msecs);
}

void EzGraver::_transmit(unsigned char const& data) {
    _transmit(QByteArray{1, static_cast<char>(data)});
}

void EzGraver::_transmit(QByteArray const& data) {
    QString hex{data.count() < 10 ? data.toHex() : ""};
    qDebug() << "transmitting" << data.length() << "bytes:" << hex;
    _serial->write(data);
}

EzGraver::~EzGraver() {
    qDebug() << "EzGraver is being destroyed, closing serial port";
    _serial->close();
}

QStringList EzGraver::availablePorts() {
    auto toPortName = [](QSerialPortInfo const& port) { return port.portName(); };
    auto ports = QSerialPortInfo::availablePorts();
    QStringList result{};

    std::transform(ports.cbegin(), ports.cend(), std::back_inserter<QStringList>(result), toPortName);
    return result;
}

std::shared_ptr<EzGraver> EzGraver::create(QString const& portName) {
    qDebug() << "instantiating EzGraver on port" << portName;

    std::shared_ptr<QSerialPort> serial{new QSerialPort(portName)};
    serial->setBaudRate(QSerialPort::Baud57600, QSerialPort::AllDirections);
    serial->setParity(QSerialPort::Parity::NoParity);
    serial->setDataBits(QSerialPort::DataBits::Data8);
    serial->setStopBits(QSerialPort::StopBits::OneStop);

    if(!serial->open(QIODevice::ReadWrite)) {
        qDebug() << "failed to establish a connection on port" << portName;
        qDebug() << serial->errorString();
        throw std::runtime_error{QString{"failed to connect to port %1 (%2)"}.arg(portName, serial->errorString()).toStdString()};
    }

    return std::shared_ptr<EzGraver>{new EzGraver(serial)};
}
<|endoftext|>


<commit_before>// @(#)root/roostats:$Id: FrequentistCalculator.cxx 37084 2010-11-29 21:37:13Z moneta $
// Author: Kyle Cranmer, Sven Kreiss   23/05/10
/*************************************************************************
 * Copyright (C) 1995-2008, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

/**
Does a frequentist hypothesis test. Nuisance parameters are fixed to their
MLEs.
*/

#include "RooStats/FrequentistCalculator.h"
#include "RooStats/ToyMCSampler.h"

ClassImp(RooStats::FrequentistCalculator)

using namespace RooStats;

int FrequentistCalculator::PreNullHook(RooArgSet *parameterPoint, double obsTestStat) const {

   // ****** any TestStatSampler ********

   // note: making nll or profile class variables can only be done in the constructor
   // as all other hooks are const (which has to be because GetHypoTest is const). However,
   // when setting it only in constructor, they would have to be changed every time SetNullModel
   // or SetAltModel is called. Simply put, converting them into class variables breaks
   // encapsulation.
   RooFit::MsgLevel msglevel = RooMsgService::instance().globalKillBelow();
   RooMsgService::instance().setGlobalKillBelow(RooFit::FATAL);

   // create profile keeping everything but nuisance parameters fixed
   RooArgSet allButNuisance(*fNullModel->GetPdf()->getParameters(*fData));
   allButNuisance.remove(*fNullModel->GetNuisanceParameters());
   // remove also the constant parameters otherwise RooProfileLL will float them
   RemoveConstantParameters(&allButNuisance);
   RooAbsReal* nll = fNullModel->GetPdf()->createNLL(*const_cast<RooAbsData*>(fData), RooFit::CloneData(kFALSE));
   RooAbsReal* profile = nll->createProfile(allButNuisance);
   profile->getVal(); // this will do fit and set nuisance parameters to profiled values
   // add nuisance parameters to parameter point
   if(fNullModel->GetNuisanceParameters())
      parameterPoint->add(*fNullModel->GetNuisanceParameters());

   delete profile;
   delete nll;
   RooMsgService::instance().setGlobalKillBelow(msglevel);

   // ***** ToyMCSampler specific *******

   // check whether TestStatSampler is a ToyMCSampler
   ToyMCSampler *toymcs = dynamic_cast<ToyMCSampler*>(GetTestStatSampler());
   if(toymcs) {
      oocoutI((TObject*)0,InputArguments) << "Using a ToyMCSampler. Now configuring for Null." << endl;

      // variable number of toys
      if(fNToysNull) toymcs->SetNToys(fNToysNull);

      // adaptive sampling
      if(fNToysNullTail) {
         oocoutI((TObject*)0,InputArguments) << "Adaptive Sampling" << endl;
         if(GetTestStatSampler()->GetTestStatistic()->PValueIsRightTail()) {
            toymcs->SetToysRightTail(fNToysNullTail, obsTestStat);
         }else{
            toymcs->SetToysLeftTail(fNToysNullTail, obsTestStat);
         }
      }else{
         toymcs->SetToysBothTails(0, 0, obsTestStat); // disable adaptive sampling
      }

      // importance sampling
      if(fNullImportanceDensity) {
         oocoutI((TObject*)0,InputArguments) << "Importance Sampling" << endl;
         toymcs->SetImportanceDensity(fNullImportanceDensity);
         if(fNullImportanceSnapshot) toymcs->SetImportanceSnapshot(*fNullImportanceSnapshot);
      }else{
         toymcs->SetImportanceDensity(NULL);       // disable importance sampling
      }
      GetNullModel()->LoadSnapshot();
   }

   return 0;
}

int FrequentistCalculator::PreAltHook(RooArgSet *parameterPoint, double obsTestStat) const {

   // ****** any TestStatSampler ********

   RooFit::MsgLevel msglevel = RooMsgService::instance().globalKillBelow();
   RooMsgService::instance().setGlobalKillBelow(RooFit::FATAL);

   // create profile keeping everything but nuisance parameters fixed
   RooArgSet allButNuisance(*fAltModel->GetPdf()->getParameters(*fData));
   allButNuisance.remove(*fAltModel->GetNuisanceParameters());
   // remove also the constant parameters otherwise RooProfileLL will float them
   RemoveConstantParameters(&allButNuisance);
   RooAbsReal* nll = fAltModel->GetPdf()->createNLL(*const_cast<RooAbsData*>(fData), RooFit::CloneData(kFALSE));
   RooAbsReal* profile = nll->createProfile(allButNuisance);
   profile->getVal(); // this will do fit and set nuisance parameters to profiled values
   // add nuisance parameters to parameter point
   if(fAltModel->GetNuisanceParameters())
      parameterPoint->add(*fAltModel->GetNuisanceParameters());

   delete profile;
   delete nll;
   RooMsgService::instance().setGlobalKillBelow(msglevel);

   // ***** ToyMCSampler specific *******

   // check whether TestStatSampler is a ToyMCSampler
   ToyMCSampler *toymcs = dynamic_cast<ToyMCSampler*>(GetTestStatSampler());
   if(toymcs) {
      oocoutI((TObject*)0,InputArguments) << "Using a ToyMCSampler. Now configuring for Alt." << endl;

      // variable number of toys
      if(fNToysAlt) toymcs->SetNToys(fNToysAlt);

      // adaptive sampling
      if(fNToysAltTail) {
         oocoutI((TObject*)0,InputArguments) << "Adaptive Sampling" << endl;
         if(GetTestStatSampler()->GetTestStatistic()->PValueIsRightTail()) {
            toymcs->SetToysLeftTail(fNToysAltTail, obsTestStat);
         }else{
            toymcs->SetToysRightTail(fNToysAltTail, obsTestStat);
         }
      }else{
         toymcs->SetToysBothTails(0, 0, obsTestStat); // disable adaptive sampling
      }

      // importance sampling
      if(fAltImportanceDensity) {
         oocoutI((TObject*)0,InputArguments) << "Importance Sampling" << endl;
         toymcs->SetImportanceDensity(fAltImportanceDensity);
         if(fAltImportanceSnapshot) toymcs->SetImportanceSnapshot(*fAltImportanceSnapshot);
      }else{
         toymcs->SetImportanceDensity(NULL);       // disable importance sampling
      }
   }

   return 0;
}

<commit_msg>add a fix from Gregory in case of a model without nuisance parameters<commit_after>// @(#)root/roostats:$Id: FrequentistCalculator.cxx 37084 2010-11-29 21:37:13Z moneta $
// Author: Kyle Cranmer, Sven Kreiss   23/05/10
/*************************************************************************
 * Copyright (C) 1995-2008, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

/**
Does a frequentist hypothesis test. Nuisance parameters are fixed to their
MLEs.
*/

#include "RooStats/FrequentistCalculator.h"
#include "RooStats/ToyMCSampler.h"

ClassImp(RooStats::FrequentistCalculator)

using namespace RooStats;

int FrequentistCalculator::PreNullHook(RooArgSet *parameterPoint, double obsTestStat) const {

   // ****** any TestStatSampler ********

   // note: making nll or profile class variables can only be done in the constructor
   // as all other hooks are const (which has to be because GetHypoTest is const). However,
   // when setting it only in constructor, they would have to be changed every time SetNullModel
   // or SetAltModel is called. Simply put, converting them into class variables breaks
   // encapsulation.
   RooFit::MsgLevel msglevel = RooMsgService::instance().globalKillBelow();
   RooMsgService::instance().setGlobalKillBelow(RooFit::FATAL);

   // create profile keeping everything but nuisance parameters fixed
   RooArgSet allButNuisance(*fNullModel->GetPdf()->getParameters(*fData));
   if (fNullModel->GetNuisanceParameters()) allButNuisance.remove(*fNullModel->GetNuisanceParameters());
   // remove also the constant parameters otherwise RooProfileLL will float them
   RemoveConstantParameters(&allButNuisance);
   RooAbsReal* nll = fNullModel->GetPdf()->createNLL(*const_cast<RooAbsData*>(fData), RooFit::CloneData(kFALSE));
   RooAbsReal* profile = nll->createProfile(allButNuisance);
   profile->getVal(); // this will do fit and set nuisance parameters to profiled values
   // add nuisance parameters to parameter point
   if(fNullModel->GetNuisanceParameters())
      parameterPoint->add(*fNullModel->GetNuisanceParameters());

   delete profile;
   delete nll;
   RooMsgService::instance().setGlobalKillBelow(msglevel);

   // ***** ToyMCSampler specific *******

   // check whether TestStatSampler is a ToyMCSampler
   ToyMCSampler *toymcs = dynamic_cast<ToyMCSampler*>(GetTestStatSampler());
   if(toymcs) {
      oocoutI((TObject*)0,InputArguments) << "Using a ToyMCSampler. Now configuring for Null." << endl;

      // variable number of toys
      if(fNToysNull) toymcs->SetNToys(fNToysNull);

      // adaptive sampling
      if(fNToysNullTail) {
         oocoutI((TObject*)0,InputArguments) << "Adaptive Sampling" << endl;
         if(GetTestStatSampler()->GetTestStatistic()->PValueIsRightTail()) {
            toymcs->SetToysRightTail(fNToysNullTail, obsTestStat);
         }else{
            toymcs->SetToysLeftTail(fNToysNullTail, obsTestStat);
         }
      }else{
         toymcs->SetToysBothTails(0, 0, obsTestStat); // disable adaptive sampling
      }

      // importance sampling
      if(fNullImportanceDensity) {
         oocoutI((TObject*)0,InputArguments) << "Importance Sampling" << endl;
         toymcs->SetImportanceDensity(fNullImportanceDensity);
         if(fNullImportanceSnapshot) toymcs->SetImportanceSnapshot(*fNullImportanceSnapshot);
      }else{
         toymcs->SetImportanceDensity(NULL);       // disable importance sampling
      }
      GetNullModel()->LoadSnapshot();
   }

   return 0;
}

int FrequentistCalculator::PreAltHook(RooArgSet *parameterPoint, double obsTestStat) const {

   // ****** any TestStatSampler ********

   RooFit::MsgLevel msglevel = RooMsgService::instance().globalKillBelow();
   RooMsgService::instance().setGlobalKillBelow(RooFit::FATAL);

   // create profile keeping everything but nuisance parameters fixed
   RooArgSet allButNuisance(*fAltModel->GetPdf()->getParameters(*fData));
   if (fAltModel->GetNuisanceParameters()) allButNuisance.remove(*fAltModel->GetNuisanceParameters());
   // remove also the constant parameters otherwise RooProfileLL will float them
   RemoveConstantParameters(&allButNuisance);
   RooAbsReal* nll = fAltModel->GetPdf()->createNLL(*const_cast<RooAbsData*>(fData), RooFit::CloneData(kFALSE));
   RooAbsReal* profile = nll->createProfile(allButNuisance);
   profile->getVal(); // this will do fit and set nuisance parameters to profiled values
   // add nuisance parameters to parameter point
   if(fAltModel->GetNuisanceParameters())
      parameterPoint->add(*fAltModel->GetNuisanceParameters());

   delete profile;
   delete nll;
   RooMsgService::instance().setGlobalKillBelow(msglevel);

   // ***** ToyMCSampler specific *******

   // check whether TestStatSampler is a ToyMCSampler
   ToyMCSampler *toymcs = dynamic_cast<ToyMCSampler*>(GetTestStatSampler());
   if(toymcs) {
      oocoutI((TObject*)0,InputArguments) << "Using a ToyMCSampler. Now configuring for Alt." << endl;

      // variable number of toys
      if(fNToysAlt) toymcs->SetNToys(fNToysAlt);

      // adaptive sampling
      if(fNToysAltTail) {
         oocoutI((TObject*)0,InputArguments) << "Adaptive Sampling" << endl;
         if(GetTestStatSampler()->GetTestStatistic()->PValueIsRightTail()) {
            toymcs->SetToysLeftTail(fNToysAltTail, obsTestStat);
         }else{
            toymcs->SetToysRightTail(fNToysAltTail, obsTestStat);
         }
      }else{
         toymcs->SetToysBothTails(0, 0, obsTestStat); // disable adaptive sampling
      }

      // importance sampling
      if(fAltImportanceDensity) {
         oocoutI((TObject*)0,InputArguments) << "Importance Sampling" << endl;
         toymcs->SetImportanceDensity(fAltImportanceDensity);
         if(fAltImportanceSnapshot) toymcs->SetImportanceSnapshot(*fAltImportanceSnapshot);
      }else{
         toymcs->SetImportanceDensity(NULL);       // disable importance sampling
      }
   }

   return 0;
}

<|endoftext|>


<commit_before>/* BEGIN_COMMON_COPYRIGHT_HEADER
 *
 * Razor - a lightweight, Qt based, desktop toolset
 * https://sourceforge.net/projects/razor-qt/
 *
 * Copyright: 2010-2011 Razor team
 * Authors:
 *   Alexander Sokoloff <sokoloff.a@gmail.ru>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation;  only version 2 of
 * the License is valid for this program.
 *
 * This program 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 General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * END_COMMON_COPYRIGHT_HEADER */

#include "razormainmenu.h"
//#include "razor.h"
#include <QDebug>
#include <QtGui/QMenu>
#include <razorqt/xdgdesktopfile.h>
#include <razorqt/xdgmenu.h>
#include <razorqt/domhelper.h>
#include <QSettings>
#include <QFileInfo>
#include <QAction>
#include <QtGui/QMessageBox>
#include <razorqt/powermanager.h>

#include <razorqt/xdgenv.h>
//#include <razorbar.h>
#include <razorqt/xdgicon.h>
#include <razorqt/xdgdesktopfile.h>
#include <razorqt/xdgmenuwidget.h>

#include <QStack>

#include <QCursor>
EXPORT_RAZOR_PANEL_PLUGIN_CPP(RazorMainMenu)

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

 ************************************************/
RazorMainMenu::RazorMainMenu(const RazorPanelPluginStartInfo* startInfo, QWidget* parent):
    RazorPanelPlugin(startInfo, parent),
    mMenu(0)
{
    setObjectName("MainMenu");

    addWidget(&mButton);
    connect(&mButton, SIGNAL(clicked()), this, SLOT(showMenu()));
    mPowerManager = new PowerManager(this);
    mPowerManager->setParentWidget(panel());

    settingsChanged();

    QSizePolicy sp = mButton.sizePolicy();
    sp.setVerticalPolicy(QSizePolicy::Minimum);
    mButton.setSizePolicy(sp);

}

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

 ************************************************/
RazorMainMenu::~RazorMainMenu()
{
    settings().setValue("text", mButton.text());
    settings().setValue("icon_size", mMenuStyle.iconSize());
    settings().setValue("top_icon_size", mTopMenuStyle.iconSize());
}

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

 ************************************************/
void RazorMainMenu::showMenu()
{
    if (!mMenu)
        buildMenu();

    int x, y;

    switch (panel()->position())
    {
        case RazorPanel::PositionTop:
            x = mButton.mapToGlobal(QPoint(0, 0)).x();
            y = panel()->mapToGlobal(QPoint(0, panel()->sizeHint().height())).y();
            break;

        case RazorPanel::PositionBottom:
            x = mButton.mapToGlobal(QPoint(0, 0)).x();
            y = panel()->mapToGlobal(QPoint(0, 0)).y() - mMenu->sizeHint().height();
            break;

        case RazorPanel::PositionLeft:
            x = panel()->mapToGlobal(QPoint(panel()->sizeHint().width(), 0)).x();
            y = mButton.mapToGlobal(QPoint(0, 0)).y();
            break;

        case RazorPanel::PositionRight:
            x = panel()->mapToGlobal(QPoint(0, 0)).x() - mMenu->sizeHint().width();
            y = mButton.mapToGlobal(QPoint(0, 0)).y();
            break;

    }

    QPoint pos(x, y);
    mMenu->exec(pos);
}

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

 ************************************************/
void RazorMainMenu::settingsChanged()
{
    mButton.setText(settings().value("text", "").toString());
    mLogDir = settings().value("log_dir", "").toString();

    mMenuStyle.setIconSize(settings().value("icon_size", 16).toInt());
    mTopMenuStyle.setIconSize(settings().value("top_icon_size", 16).toInt());

    mMenuFile = settings().value("menu_file", "").toString();
    if (mMenuFile.isEmpty())
        mMenuFile = XdgMenu::getMenuFileName();

    QIcon icon =  XdgIcon::fromTheme(settings().value("button_icon").toString());
    if (!icon.isNull())
        mButton.setIcon(icon);
}

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

 ************************************************/
void RazorMainMenu::buildMenu()
{
    XdgMenu xdgMenu(mMenuFile);
    xdgMenu.setLogDir(mLogDir);

    bool res = xdgMenu.read();
    if (res)
    {
        mMenu = new XdgMenuWidget(xdgMenu, "", this);
        mMenu->setObjectName("TopLevelMainMenu");
        mMenu->setStyle(&mTopMenuStyle);
    }
    else
    {
        QMessageBox::warning(this, "Parse error", xdgMenu.errorString());
    }

    mMenu->addSeparator();

    QMenu* leaveMenu = mMenu->addMenu(XdgIcon::fromTheme("system-shutdown"), tr("Leave"));
    leaveMenu->addActions(mPowerManager->availableActions());
}

<commit_msg>Segfault in MainMenu if xdg-menu file not found.<commit_after>/* BEGIN_COMMON_COPYRIGHT_HEADER
 *
 * Razor - a lightweight, Qt based, desktop toolset
 * https://sourceforge.net/projects/razor-qt/
 *
 * Copyright: 2010-2011 Razor team
 * Authors:
 *   Alexander Sokoloff <sokoloff.a@gmail.ru>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation;  only version 2 of
 * the License is valid for this program.
 *
 * This program 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 General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * END_COMMON_COPYRIGHT_HEADER */

#include "razormainmenu.h"
//#include "razor.h"
#include <QDebug>
#include <QtGui/QMenu>
#include <razorqt/xdgdesktopfile.h>
#include <razorqt/xdgmenu.h>
#include <razorqt/domhelper.h>
#include <QSettings>
#include <QFileInfo>
#include <QAction>
#include <QtGui/QMessageBox>
#include <razorqt/powermanager.h>

#include <razorqt/xdgenv.h>
//#include <razorbar.h>
#include <razorqt/xdgicon.h>
#include <razorqt/xdgdesktopfile.h>
#include <razorqt/xdgmenuwidget.h>

#include <QStack>

#include <QCursor>
EXPORT_RAZOR_PANEL_PLUGIN_CPP(RazorMainMenu)

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

 ************************************************/
RazorMainMenu::RazorMainMenu(const RazorPanelPluginStartInfo* startInfo, QWidget* parent):
    RazorPanelPlugin(startInfo, parent),
    mMenu(0)
{
    setObjectName("MainMenu");

    addWidget(&mButton);
    connect(&mButton, SIGNAL(clicked()), this, SLOT(showMenu()));
    mPowerManager = new PowerManager(this);
    mPowerManager->setParentWidget(panel());

    settingsChanged();

    QSizePolicy sp = mButton.sizePolicy();
    sp.setVerticalPolicy(QSizePolicy::Minimum);
    mButton.setSizePolicy(sp);

}

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

 ************************************************/
RazorMainMenu::~RazorMainMenu()
{
    settings().setValue("text", mButton.text());
    settings().setValue("icon_size", mMenuStyle.iconSize());
    settings().setValue("top_icon_size", mTopMenuStyle.iconSize());
}

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

 ************************************************/
void RazorMainMenu::showMenu()
{
    if (!mMenu)
        buildMenu();

    if (!mMenu)
        return;

    int x, y;

    switch (panel()->position())
    {
        case RazorPanel::PositionTop:
            x = mButton.mapToGlobal(QPoint(0, 0)).x();
            y = panel()->mapToGlobal(QPoint(0, panel()->sizeHint().height())).y();
            break;

        case RazorPanel::PositionBottom:
            x = mButton.mapToGlobal(QPoint(0, 0)).x();
            y = panel()->mapToGlobal(QPoint(0, 0)).y() - mMenu->sizeHint().height();
            break;

        case RazorPanel::PositionLeft:
            x = panel()->mapToGlobal(QPoint(panel()->sizeHint().width(), 0)).x();
            y = mButton.mapToGlobal(QPoint(0, 0)).y();
            break;

        case RazorPanel::PositionRight:
            x = panel()->mapToGlobal(QPoint(0, 0)).x() - mMenu->sizeHint().width();
            y = mButton.mapToGlobal(QPoint(0, 0)).y();
            break;

    }

    QPoint pos(x, y);
    mMenu->exec(pos);
}

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

 ************************************************/
void RazorMainMenu::settingsChanged()
{
    mButton.setText(settings().value("text", "").toString());
    mLogDir = settings().value("log_dir", "").toString();

    mMenuStyle.setIconSize(settings().value("icon_size", 16).toInt());
    mTopMenuStyle.setIconSize(settings().value("top_icon_size", 16).toInt());

    mMenuFile = settings().value("menu_file", "").toString();
    if (mMenuFile.isEmpty())
        mMenuFile = XdgMenu::getMenuFileName();

    QIcon icon =  XdgIcon::fromTheme(settings().value("button_icon").toString());
    if (!icon.isNull())
        mButton.setIcon(icon);
}

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

 ************************************************/
void RazorMainMenu::buildMenu()
{
    XdgMenu xdgMenu(mMenuFile);
    xdgMenu.setLogDir(mLogDir);

    bool res = xdgMenu.read();
    if (res)
    {
        mMenu = new XdgMenuWidget(xdgMenu, "", this);
        mMenu->setObjectName("TopLevelMainMenu");
        mMenu->setStyle(&mTopMenuStyle);
    }
    else
    {
        QMessageBox::warning(this, "Parse error", xdgMenu.errorString());
        return;
    }

    mMenu->addSeparator();

    QMenu* leaveMenu = mMenu->addMenu(XdgIcon::fromTheme("system-shutdown"), tr("Leave"));
    leaveMenu->addActions(mPowerManager->availableActions());
}

<|endoftext|>


<commit_before>// SkipList: A STL-map like container using skip-list

// Copyright (c) 2015 Guo Xiao <guoxiao08@gmail.com>

// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

#pragma once

#include <vector>
#include <assert.h>
#include <cstdlib>
#include <stdexcept>
#ifndef NDEBUG
#include <iostream>
#endif
namespace guoxiao {
namespace skiplist {

template <typename KeyType, typename ValueType>
struct SkipNode {
  KeyType key;
  ValueType value;
  size_t level;
  std::vector<SkipNode *> next;
  SkipNode() : level(0), next(1) {}
  SkipNode(SkipNode &&rhs) : level(rhs.level), next(std::move(rhs.next)) {}

  SkipNode(const SkipNode &) = delete;
  SkipNode &operator=(const SkipNode &) = delete;
};

template <typename T>
class Iterator {
public:
  Iterator() : ptr(nullptr){};
  explicit Iterator(T *p) : ptr(p){};
  Iterator operator=(T *p) {
    ptr = p;
    return *this;
  }

  Iterator &operator++() {
    ptr = ptr->next[0];
    return *this;
  }

  Iterator operator++(int) {
    Iterator temp = *this;
    ptr = ptr->next[0];
    return temp;
  }

  bool operator!=(const Iterator &rhs) const { return ptr != rhs.ptr; }

  bool operator==(const Iterator &rhs) const { return ptr == rhs.ptr; }

  bool operator==(const T *p) const { return ptr == p; }

  bool operator!=(const T *p) const { return ptr != p; }

  operator bool() const { return ptr != nullptr; }

  operator T *() const { return ptr; }

  T *operator->() const { return ptr; }

  T &operator*() const { return *ptr; }

private:
  T *ptr;
};

template <typename Key, typename T>
class SkipList {
public:
  typedef Key key_type;
  typedef T mapped_type;
  typedef std::pair<Key, T> value_type;
  typedef SkipNode<Key, T> node_type;
  typedef Iterator<node_type> iterator;
  typedef Iterator<node_type> const_iterator;

  SkipList() : size_(0), level_(0), head_(new node_type()) {}

  ~SkipList() noexcept {
    iterator node = head_, temp;
    while (node) {
      temp = node;
      node = node->next[0];
      delete temp;
    }
  }

  // Move Ctor
  SkipList(SkipList &&s) noexcept : size_(s.size_),
                                    level_(s.level_),
                                    head_(s.head_) {
    s.head_ = new node_type();
    s.level_ = 0;
    s.size_ = 0;
  }

  // Copy Ctor
  SkipList(const SkipList &s)
    : size_(s.size_), level_(s.level_), head_(new node_type()) {
    iterator snode = s.head_, node = head_;
    std::vector<iterator> last(level_ + 1);
    head_->level = level_;
    head_->next.resize(level_ + 1);
    for (int i = level_; i >= 0; i--) {
      last[i] = head_;
    }
    snode = snode->next[0];
    while (snode) {
      node = new node_type();
      node->key = snode->key;
      node->value = snode->value;
      node->level = snode->level;
      node->next.resize(snode->next.size());
      for (int i = snode->level; i >= 0; i--) {
        last[i]->next[i] = node;
        last[i] = node;
      }
      snode = snode->next[0];
    }
  }

  // Copy Assignment
  SkipList &operator=(const SkipList &s) {
    if (this == &s)
      return *this;
    SkipList tmp(s);
    return *this = std::move(tmp);
  }

  // Move Assignment
  SkipList &operator=(SkipList &&s) noexcept {
    this->~SkipList();
    size_ = s.size_;
    level_ = s.level_;
    head_ = s.head_;
    s.head_ = new node_type();
    s.level_ = 0;
    s.size_ = 0;
    return *this;
  }

  size_t size() const { return size_; }
  bool empty() const { return size_ == 0; }
  size_t level() const { return level_; }

  iterator begin() noexcept { return iterator(head_->next[0]); }
  const_iterator begin() const noexcept { return iterator(head_->next[0]); }

  const_iterator cbegin() noexcept { return iterator(head_->next[0]); }
  const_iterator cend() const noexcept { return iterator(); }

  iterator end() noexcept { return iterator(); }
  const_iterator end() const noexcept { return iterator(); }

  template <typename K, typename V>
  iterator emplace(K &&key, V &&value) {
    iterator node = head_;
    std::vector<iterator> update(level_ + 1 + 1);
    for (int i = level_; i >= 0; i--) {
      assert(static_cast<int>(node->level) >= i);
      while (node->next[i] && node->next[i]->key < key) {
        node = node->next[i];
      }
      update[i] = node;
      if (node->next[i] && node->next[i]->key == key) {
        throw std::runtime_error("conflict");
      }
    }

    node_type *n = new node_type();
    n->key = std::forward<K>(key);
    n->value = std::forward<V>(value);

    size_t level = getRandomLevel();
    if (level > level_) {
      level = level_ + 1;
      head_->next.resize(level + 1);
      head_->level = level;
      update[level] = head_;
      level_ = level;
    }
    n->next.resize(level + 1);
    n->level = level;

    for (int i = level; i >= 0; i--) {
      if (update[i]) {
        n->next[i] = update[i]->next[i];
        update[i]->next[i] = n;
      }
    }
    ++size_;
    return iterator(n);
  }

  iterator insert(const value_type &value) {
    return emplace(value.first, value.second);
  }

  iterator insert(value_type &&value) {
    return emplace(std::move(value.first), std::move(value.second));
  }

  iterator find(const key_type &key) const {
    iterator node = head_;
    for (int i = level_; i >= 0; i--) {
      while (node->next[i] && node->next[i]->key < key) {
        node = node->next[i];
      }
      if (node->next[i] && node->next[i]->key == key) {
        return iterator(node->next[i]);
      }
    }
    return end();
  }

  void erase(const key_type &key) {
    iterator node = head_;
    std::vector<iterator> update(level_ + 1);

    for (int i = level_; i >= 0; i--) {
      while (node->next[i] && node->next[i]->key < key) {
        node = node->next[i];
      }
      if (node->next[i] && node->next[i]->key == key) {
        update[i] = node;
      }
    }
    node = node->next[0];
    if (node == end()) {
      throw std::out_of_range("skiplist::erase");
    }
    assert(node->key == key);

    for (int i = level_; i >= 0; i--) {
      if (update[i]) {
        assert(node == iterator(update[i]->next[i]));
        update[i]->next[i] = node->next[i];
      }
    }

    delete node;
    --size_;

    if (level_ > 0 && head_->next[level_] == end()) {
      level_--;
      head_->level = level_;
      head_->next.resize(level_ + 1);
    }
  }

  void erase(iterator it) {
    erase(it->key);
  }

  mapped_type &operator[](const key_type &key) {
    iterator node = find(key);
    if (node == end()) {
      mapped_type value;
      node = emplace(key, value);
    }
    return node->value;
  }

  mapped_type &at(const key_type &key) {
    iterator node = find(key);
    if (node == end()) {
      throw std::out_of_range("skiplist::at");
    }
    return node->value;
  }

  const mapped_type &at(const key_type &key) const {
    iterator node = find(key);
    if (node == end()) {
      throw std::out_of_range("skiplist::at");
    }
    return node->value;
  }

#ifndef NDEBUG
  void dump() const {
    std::cout << "====== level: " << level_ << " size: " << size_ << std::endl;
    for (int i = level_; i >= 0; i--) {
      std::cout << "====== level " << i << std::endl;
      auto node = head_;
      while (node->next[i]) {
        std::cout << node->next[i]->key << " : " << node->next[i]->value
                  << std::endl;
        node = node->next[i];
      }
    }
  }
#endif

private:
  size_t size_;
  size_t level_;
  iterator head_;
  static size_t getRandomLevel() {
    size_t level = 0;
    while (rand() % 2) {
      ++level;
    }
    return level;
  }
};

} // namespace skiplist
} // namespace guoxiao
<commit_msg>Add count()<commit_after>// SkipList: A STL-map like container using skip-list

// Copyright (c) 2015 Guo Xiao <guoxiao08@gmail.com>

// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

#pragma once

#include <vector>
#include <assert.h>
#include <cstdlib>
#include <stdexcept>
#ifndef NDEBUG
#include <iostream>
#endif
namespace guoxiao {
namespace skiplist {

template <typename KeyType, typename ValueType>
struct SkipNode {
  KeyType key;
  ValueType value;
  size_t level;
  std::vector<SkipNode *> next;
  SkipNode() : level(0), next(1) {}
  SkipNode(SkipNode &&rhs) : level(rhs.level), next(std::move(rhs.next)) {}

  SkipNode(const SkipNode &) = delete;
  SkipNode &operator=(const SkipNode &) = delete;
};

template <typename T>
class Iterator {
public:
  Iterator() : ptr(nullptr){};
  explicit Iterator(T *p) : ptr(p){};
  Iterator operator=(T *p) {
    ptr = p;
    return *this;
  }

  Iterator &operator++() {
    ptr = ptr->next[0];
    return *this;
  }

  Iterator operator++(int) {
    Iterator temp = *this;
    ptr = ptr->next[0];
    return temp;
  }

  bool operator!=(const Iterator &rhs) const { return ptr != rhs.ptr; }

  bool operator==(const Iterator &rhs) const { return ptr == rhs.ptr; }

  bool operator==(const T *p) const { return ptr == p; }

  bool operator!=(const T *p) const { return ptr != p; }

  operator bool() const { return ptr != nullptr; }

  operator T *() const { return ptr; }

  T *operator->() const { return ptr; }

  T &operator*() const { return *ptr; }

private:
  T *ptr;
};

template <typename Key, typename T>
class SkipList {
public:
  typedef Key key_type;
  typedef T mapped_type;
  typedef std::pair<Key, T> value_type;
  typedef SkipNode<Key, T> node_type;
  typedef Iterator<node_type> iterator;
  typedef Iterator<node_type> const_iterator;

  SkipList() : size_(0), level_(0), head_(new node_type()) {}

  ~SkipList() noexcept {
    iterator node = head_, temp;
    while (node) {
      temp = node;
      node = node->next[0];
      delete temp;
    }
  }

  // Move Ctor
  SkipList(SkipList &&s) noexcept : size_(s.size_),
                                    level_(s.level_),
                                    head_(s.head_) {
    s.head_ = new node_type();
    s.level_ = 0;
    s.size_ = 0;
  }

  // Copy Ctor
  SkipList(const SkipList &s)
    : size_(s.size_), level_(s.level_), head_(new node_type()) {
    iterator snode = s.head_, node = head_;
    std::vector<iterator> last(level_ + 1);
    head_->level = level_;
    head_->next.resize(level_ + 1);
    for (int i = level_; i >= 0; i--) {
      last[i] = head_;
    }
    snode = snode->next[0];
    while (snode) {
      node = new node_type();
      node->key = snode->key;
      node->value = snode->value;
      node->level = snode->level;
      node->next.resize(snode->next.size());
      for (int i = snode->level; i >= 0; i--) {
        last[i]->next[i] = node;
        last[i] = node;
      }
      snode = snode->next[0];
    }
  }

  // Copy Assignment
  SkipList &operator=(const SkipList &s) {
    if (this == &s)
      return *this;
    SkipList tmp(s);
    return *this = std::move(tmp);
  }

  // Move Assignment
  SkipList &operator=(SkipList &&s) noexcept {
    this->~SkipList();
    size_ = s.size_;
    level_ = s.level_;
    head_ = s.head_;
    s.head_ = new node_type();
    s.level_ = 0;
    s.size_ = 0;
    return *this;
  }

  size_t size() const { return size_; }
  bool empty() const { return size_ == 0; }
  size_t level() const { return level_; }

  iterator begin() noexcept { return iterator(head_->next[0]); }
  const_iterator begin() const noexcept { return iterator(head_->next[0]); }

  const_iterator cbegin() noexcept { return iterator(head_->next[0]); }
  const_iterator cend() const noexcept { return iterator(); }

  iterator end() noexcept { return iterator(); }
  const_iterator end() const noexcept { return iterator(); }

  template <typename K, typename V>
  iterator emplace(K &&key, V &&value) {
    iterator node = head_;
    std::vector<iterator> update(level_ + 1 + 1);
    for (int i = level_; i >= 0; i--) {
      assert(static_cast<int>(node->level) >= i);
      while (node->next[i] && node->next[i]->key < key) {
        node = node->next[i];
      }
      update[i] = node;
      if (node->next[i] && node->next[i]->key == key) {
        throw std::runtime_error("conflict");
      }
    }

    node_type *n = new node_type();
    n->key = std::forward<K>(key);
    n->value = std::forward<V>(value);

    size_t level = getRandomLevel();
    if (level > level_) {
      level = level_ + 1;
      head_->next.resize(level + 1);
      head_->level = level;
      update[level] = head_;
      level_ = level;
    }
    n->next.resize(level + 1);
    n->level = level;

    for (int i = level; i >= 0; i--) {
      if (update[i]) {
        n->next[i] = update[i]->next[i];
        update[i]->next[i] = n;
      }
    }
    ++size_;
    return iterator(n);
  }

  iterator insert(const value_type &value) {
    return emplace(value.first, value.second);
  }

  iterator insert(value_type &&value) {
    return emplace(std::move(value.first), std::move(value.second));
  }

  iterator find(const key_type &key) const {
    iterator node = head_;
    for (int i = level_; i >= 0; i--) {
      while (node->next[i] && node->next[i]->key < key) {
        node = node->next[i];
      }
      if (node->next[i] && node->next[i]->key == key) {
        return iterator(node->next[i]);
      }
    }
    return end();
  }

  size_t count(const key_type &key) const {
    return find(key) ? 1 : 0;
  }

  void erase(const key_type &key) {
    iterator node = head_;
    std::vector<iterator> update(level_ + 1);

    for (int i = level_; i >= 0; i--) {
      while (node->next[i] && node->next[i]->key < key) {
        node = node->next[i];
      }
      if (node->next[i] && node->next[i]->key == key) {
        update[i] = node;
      }
    }
    node = node->next[0];
    if (node == end()) {
      throw std::out_of_range("skiplist::erase");
    }
    assert(node->key == key);

    for (int i = level_; i >= 0; i--) {
      if (update[i]) {
        assert(node == iterator(update[i]->next[i]));
        update[i]->next[i] = node->next[i];
      }
    }

    delete node;
    --size_;

    if (level_ > 0 && head_->next[level_] == end()) {
      level_--;
      head_->level = level_;
      head_->next.resize(level_ + 1);
    }
  }

  void erase(iterator it) {
    erase(it->key);
  }

  mapped_type &operator[](const key_type &key) {
    iterator node = find(key);
    if (node == end()) {
      mapped_type value;
      node = emplace(key, value);
    }
    return node->value;
  }

  mapped_type &at(const key_type &key) {
    iterator node = find(key);
    if (node == end()) {
      throw std::out_of_range("skiplist::at");
    }
    return node->value;
  }

  const mapped_type &at(const key_type &key) const {
    iterator node = find(key);
    if (node == end()) {
      throw std::out_of_range("skiplist::at");
    }
    return node->value;
  }

#ifndef NDEBUG
  void dump() const {
    std::cout << "====== level: " << level_ << " size: " << size_ << std::endl;
    for (int i = level_; i >= 0; i--) {
      std::cout << "====== level " << i << std::endl;
      auto node = head_;
      while (node->next[i]) {
        std::cout << node->next[i]->key << " : " << node->next[i]->value
                  << std::endl;
        node = node->next[i];
      }
    }
  }
#endif

private:
  size_t size_;
  size_t level_;
  iterator head_;
  static size_t getRandomLevel() {
    size_t level = 0;
    while (rand() % 2) {
      ++level;
    }
    return level;
  }
};

} // namespace skiplist
} // namespace guoxiao
<|endoftext|>


<commit_before>#define GLM_FORCE_RADIANS
#include <glm/gtc/matrix_transform.hpp>

#include <linux/input-event-codes.h>

#include <wayfire/compositor-surface.hpp>
#include <wayfire/output.hpp>
#include <wayfire/opengl.hpp>
#include <wayfire/core.hpp>
#include <wayfire/decorator.hpp>
#include <wayfire/view-transform.hpp>
#include <wayfire/signal-definitions.hpp>
#include "deco-subsurface.hpp"
#include "deco-layout.hpp"
#include "deco-theme.hpp"

#include <wayfire/plugins/common/cairo-util.hpp>

#include <cairo.h>

extern "C"
{
#define static
#include <wlr/render/wlr_renderer.h>
#include <wlr/types/wlr_matrix.h>
#include <wlr/types/wlr_xcursor_manager.h>
#undef static
}

class simple_decoration_surface : public wf::surface_interface_t,
    public wf::compositor_surface_t, public wf::decorator_frame_t_t
{
    bool _mapped = true;
    int current_thickness;
    int current_titlebar;

    wayfire_view view;
    wf::signal_callback_t title_set = [=] (wf::signal_data_t *data)
    {
        if (get_signaled_view(data) == view)
            view->damage(); // trigger re-render
    };

    void update_title(int width, int height, double scale)
    {
        int target_width = width * scale;
        int target_height = height * scale;

        if (title_texture.tex.width != target_width ||
            title_texture.tex.height != target_height ||
            title_texture.current_text != view->get_title())
        {
            auto surface = theme.render_text(view->get_title(),
                target_width, target_height);
            cairo_surface_upload_to_texture(surface, title_texture.tex);
            title_texture.current_text = view->get_title();
        }
    }

    int width = 100, height = 100;

    bool active = true; // when views are mapped, they are usually activated

    struct {
        wf::simple_texture_t tex;
        std::string current_text = "";
    } title_texture;

    wf::decor::decoration_theme_t theme;
    wf::decor::decoration_layout_t layout;
    wf::region_t cached_region;

  public:
    simple_decoration_surface(wayfire_view view) :
        theme{},
        layout{theme, [=] (wlr_box box) {this->damage_surface_box(box); }}
    {
        this->view = view;
        view->connect_signal("title-changed", &title_set);

        // make sure to hide frame if the view is fullscreen
        update_decoration_size();
    }

    virtual ~simple_decoration_surface()
    {
        _mapped = false;
        wf::emit_map_state_change(this);
        view->disconnect_signal("title-changed", &title_set);
    }

    /* wf::surface_interface_t implementation */
    virtual bool is_mapped() const final
    {
        return _mapped;
    }

    wf::point_t get_offset() final
    {
        return { -current_thickness, -current_titlebar };
    }

    virtual wf::dimensions_t get_size() const final
    {
        return {width, height};
    }

    void render_title(const wf::framebuffer_t& fb,
        wf::geometry_t geometry)
    {
        update_title(geometry.width, geometry.height, fb.scale);
        OpenGL::render_texture(title_texture.tex.tex, fb, geometry,
            glm::vec4(1.0f), OpenGL::TEXTURE_TRANSFORM_INVERT_Y);
    }

    void render_scissor_box(const wf::framebuffer_t& fb, wf::point_t origin,
        const wlr_box& scissor)
    {
        /* Clear background */
        wlr_box geometry {origin.x, origin.y, width, height};
        theme.render_background(fb, geometry, scissor, active);

        /* Draw title & buttons */
        auto renderables = layout.get_renderable_areas();
        for (auto item : renderables)
        {
            if (item->get_type() == wf::decor::DECORATION_AREA_TITLE) {
                OpenGL::render_begin(fb);
                fb.logic_scissor(scissor);
                render_title(fb, item->get_geometry() + origin);
                OpenGL::render_end();
            } else { // button
                item->as_button().render(fb,
                    item->get_geometry() + origin, scissor);
            }
        }
    }

    virtual void simple_render(const wf::framebuffer_t& fb, int x, int y,
        const wf::region_t& damage) override
    {
        wf::region_t frame = this->cached_region + wf::point_t{x, y};
        frame &= damage;

        for (const auto& box : frame)
            render_scissor_box(fb, {x, y}, wlr_box_from_pixman_box(box));
    }

    bool accepts_input(int32_t sx, int32_t sy) override
    {
        return pixman_region32_contains_point(cached_region.to_pixman(),
            sx, sy, NULL);
    }

    /* wf::compositor_surface_t implementation */
    virtual void on_pointer_enter(int x, int y) override
    { layout.handle_motion(x, y); }

    virtual void on_pointer_leave() override
    { layout.handle_focus_lost(); }

    virtual void on_pointer_motion(int x, int y) override
    { layout.handle_motion(x, y); }

    void send_move_request()
    {
        move_request_signal move_request;
        move_request.view = view;
        get_output()->emit_signal("move-request", &move_request);
    }

    void send_resize_request(uint32_t edges)
    {
        resize_request_signal resize_request;
        resize_request.view = view;
        resize_request.edges = edges;
        get_output()->emit_signal("resize-request", &resize_request);
    }

    virtual void on_pointer_button(uint32_t button, uint32_t state) override
    {
        if (button != BTN_LEFT)
            return;

        handle_action(layout.handle_press_event(state == WLR_BUTTON_PRESSED));
    }

    void handle_action(wf::decor::decoration_layout_t::action_response_t action)
    {
        switch (action.action)
        {
            case wf::decor::DECORATION_ACTION_MOVE:
                return send_move_request();
            case wf::decor::DECORATION_ACTION_RESIZE:
                return send_resize_request(action.edges);
            case wf::decor::DECORATION_ACTION_CLOSE:
                return view->close();
            case wf::decor::DECORATION_ACTION_TOGGLE_MAXIMIZE:
                if (view->tiled_edges) {
                    view->tile_request(0);
                } else {
                    view->tile_request(wf::TILED_EDGES_ALL);
                }
                break;
            case wf::decor::DECORATION_ACTION_MINIMIZE:
                view->minimize_request(true);
                break;
            default:
                break;
        }
    }

    virtual void on_touch_down(int x, int y) override
    {
        layout.handle_motion(x, y);
        handle_action(layout.handle_press_event());
    }

    virtual void on_touch_motion(int x, int y) override
    { layout.handle_motion(x, y); }

    virtual void on_touch_up() override
    {
        handle_action(layout.handle_press_event(false));
        layout.handle_focus_lost();
    }

    /* frame implementation */
    virtual wf::geometry_t expand_wm_geometry(
        wf::geometry_t contained_wm_geometry) override
    {
        contained_wm_geometry.x -= current_thickness;
        contained_wm_geometry.y -= current_titlebar;
        contained_wm_geometry.width += 2 * current_thickness;
        contained_wm_geometry.height += current_thickness + current_titlebar;

        return contained_wm_geometry;
    }

    virtual void calculate_resize_size(
        int& target_width, int& target_height) override
    {
        target_width -= 2 * current_thickness;
        target_height -= current_thickness + current_titlebar;

        target_width = std::max(target_width, 1);
        target_height = std::max(target_height, 1);
    }

    virtual void notify_view_activated(bool active) override
    {
        if (this->active != active)
            view->damage();

        this->active = active;
    }

    virtual void notify_view_resized(wf::geometry_t view_geometry) override
    {
        view->damage();
        width = view_geometry.width;
        height = view_geometry.height;

        layout.resize(width, height);
        if (!view->fullscreen)
            this->cached_region = layout.calculate_region();

        view->damage();
    };

    virtual void notify_view_tiled() override
    { }

    void update_decoration_size()
    {
        if (view->fullscreen)
        {
            current_thickness = 0;
            current_titlebar = 0;
            this->cached_region.clear();
        } else
        {
            current_thickness = theme.get_border_size();
            current_titlebar =
                theme.get_title_height() + theme.get_border_size();
            this->cached_region = layout.calculate_region();
        }
    }

    virtual void notify_view_fullscreen() override
    {
        update_decoration_size();

        if (!view->fullscreen)
            notify_view_resized(view->get_wm_geometry());
    };
};

void init_view(wayfire_view view)
{
    auto surf = std::make_unique<simple_decoration_surface>(view);
    nonstd::observer_ptr<simple_decoration_surface> ptr{surf};

    view->add_subsurface(std::move(surf), true);
    view->set_decoration(ptr.get());
    view->damage();
}
<commit_msg>decoration: fix memory leak of text texture<commit_after>#define GLM_FORCE_RADIANS
#include <glm/gtc/matrix_transform.hpp>

#include <linux/input-event-codes.h>

#include <wayfire/compositor-surface.hpp>
#include <wayfire/output.hpp>
#include <wayfire/opengl.hpp>
#include <wayfire/core.hpp>
#include <wayfire/decorator.hpp>
#include <wayfire/view-transform.hpp>
#include <wayfire/signal-definitions.hpp>
#include "deco-subsurface.hpp"
#include "deco-layout.hpp"
#include "deco-theme.hpp"

#include <wayfire/plugins/common/cairo-util.hpp>

#include <cairo.h>

extern "C"
{
#define static
#include <wlr/render/wlr_renderer.h>
#include <wlr/types/wlr_matrix.h>
#include <wlr/types/wlr_xcursor_manager.h>
#undef static
}

class simple_decoration_surface : public wf::surface_interface_t,
    public wf::compositor_surface_t, public wf::decorator_frame_t_t
{
    bool _mapped = true;
    int current_thickness;
    int current_titlebar;

    wayfire_view view;
    wf::signal_callback_t title_set = [=] (wf::signal_data_t *data)
    {
        if (get_signaled_view(data) == view)
            view->damage(); // trigger re-render
    };

    void update_title(int width, int height, double scale)
    {
        int target_width = width * scale;
        int target_height = height * scale;

        if (title_texture.tex.width != target_width ||
            title_texture.tex.height != target_height ||
            title_texture.current_text != view->get_title())
        {
            auto surface = theme.render_text(view->get_title(),
                target_width, target_height);
            cairo_surface_upload_to_texture(surface, title_texture.tex);
            cairo_surface_destroy(surface);
            title_texture.current_text = view->get_title();
        }
    }

    int width = 100, height = 100;

    bool active = true; // when views are mapped, they are usually activated

    struct {
        wf::simple_texture_t tex;
        std::string current_text = "";
    } title_texture;

    wf::decor::decoration_theme_t theme;
    wf::decor::decoration_layout_t layout;
    wf::region_t cached_region;

  public:
    simple_decoration_surface(wayfire_view view) :
        theme{},
        layout{theme, [=] (wlr_box box) {this->damage_surface_box(box); }}
    {
        this->view = view;
        view->connect_signal("title-changed", &title_set);

        // make sure to hide frame if the view is fullscreen
        update_decoration_size();
    }

    virtual ~simple_decoration_surface()
    {
        _mapped = false;
        wf::emit_map_state_change(this);
        view->disconnect_signal("title-changed", &title_set);
    }

    /* wf::surface_interface_t implementation */
    virtual bool is_mapped() const final
    {
        return _mapped;
    }

    wf::point_t get_offset() final
    {
        return { -current_thickness, -current_titlebar };
    }

    virtual wf::dimensions_t get_size() const final
    {
        return {width, height};
    }

    void render_title(const wf::framebuffer_t& fb,
        wf::geometry_t geometry)
    {
        update_title(geometry.width, geometry.height, fb.scale);
        OpenGL::render_texture(title_texture.tex.tex, fb, geometry,
            glm::vec4(1.0f), OpenGL::TEXTURE_TRANSFORM_INVERT_Y);
    }

    void render_scissor_box(const wf::framebuffer_t& fb, wf::point_t origin,
        const wlr_box& scissor)
    {
        /* Clear background */
        wlr_box geometry {origin.x, origin.y, width, height};
        theme.render_background(fb, geometry, scissor, active);

        /* Draw title & buttons */
        auto renderables = layout.get_renderable_areas();
        for (auto item : renderables)
        {
            if (item->get_type() == wf::decor::DECORATION_AREA_TITLE) {
                OpenGL::render_begin(fb);
                fb.logic_scissor(scissor);
                render_title(fb, item->get_geometry() + origin);
                OpenGL::render_end();
            } else { // button
                item->as_button().render(fb,
                    item->get_geometry() + origin, scissor);
            }
        }
    }

    virtual void simple_render(const wf::framebuffer_t& fb, int x, int y,
        const wf::region_t& damage) override
    {
        wf::region_t frame = this->cached_region + wf::point_t{x, y};
        frame &= damage;

        for (const auto& box : frame)
            render_scissor_box(fb, {x, y}, wlr_box_from_pixman_box(box));
    }

    bool accepts_input(int32_t sx, int32_t sy) override
    {
        return pixman_region32_contains_point(cached_region.to_pixman(),
            sx, sy, NULL);
    }

    /* wf::compositor_surface_t implementation */
    virtual void on_pointer_enter(int x, int y) override
    { layout.handle_motion(x, y); }

    virtual void on_pointer_leave() override
    { layout.handle_focus_lost(); }

    virtual void on_pointer_motion(int x, int y) override
    { layout.handle_motion(x, y); }

    void send_move_request()
    {
        move_request_signal move_request;
        move_request.view = view;
        get_output()->emit_signal("move-request", &move_request);
    }

    void send_resize_request(uint32_t edges)
    {
        resize_request_signal resize_request;
        resize_request.view = view;
        resize_request.edges = edges;
        get_output()->emit_signal("resize-request", &resize_request);
    }

    virtual void on_pointer_button(uint32_t button, uint32_t state) override
    {
        if (button != BTN_LEFT)
            return;

        handle_action(layout.handle_press_event(state == WLR_BUTTON_PRESSED));
    }

    void handle_action(wf::decor::decoration_layout_t::action_response_t action)
    {
        switch (action.action)
        {
            case wf::decor::DECORATION_ACTION_MOVE:
                return send_move_request();
            case wf::decor::DECORATION_ACTION_RESIZE:
                return send_resize_request(action.edges);
            case wf::decor::DECORATION_ACTION_CLOSE:
                return view->close();
            case wf::decor::DECORATION_ACTION_TOGGLE_MAXIMIZE:
                if (view->tiled_edges) {
                    view->tile_request(0);
                } else {
                    view->tile_request(wf::TILED_EDGES_ALL);
                }
                break;
            case wf::decor::DECORATION_ACTION_MINIMIZE:
                view->minimize_request(true);
                break;
            default:
                break;
        }
    }

    virtual void on_touch_down(int x, int y) override
    {
        layout.handle_motion(x, y);
        handle_action(layout.handle_press_event());
    }

    virtual void on_touch_motion(int x, int y) override
    { layout.handle_motion(x, y); }

    virtual void on_touch_up() override
    {
        handle_action(layout.handle_press_event(false));
        layout.handle_focus_lost();
    }

    /* frame implementation */
    virtual wf::geometry_t expand_wm_geometry(
        wf::geometry_t contained_wm_geometry) override
    {
        contained_wm_geometry.x -= current_thickness;
        contained_wm_geometry.y -= current_titlebar;
        contained_wm_geometry.width += 2 * current_thickness;
        contained_wm_geometry.height += current_thickness + current_titlebar;

        return contained_wm_geometry;
    }

    virtual void calculate_resize_size(
        int& target_width, int& target_height) override
    {
        target_width -= 2 * current_thickness;
        target_height -= current_thickness + current_titlebar;

        target_width = std::max(target_width, 1);
        target_height = std::max(target_height, 1);
    }

    virtual void notify_view_activated(bool active) override
    {
        if (this->active != active)
            view->damage();

        this->active = active;
    }

    virtual void notify_view_resized(wf::geometry_t view_geometry) override
    {
        view->damage();
        width = view_geometry.width;
        height = view_geometry.height;

        layout.resize(width, height);
        if (!view->fullscreen)
            this->cached_region = layout.calculate_region();

        view->damage();
    };

    virtual void notify_view_tiled() override
    { }

    void update_decoration_size()
    {
        if (view->fullscreen)
        {
            current_thickness = 0;
            current_titlebar = 0;
            this->cached_region.clear();
        } else
        {
            current_thickness = theme.get_border_size();
            current_titlebar =
                theme.get_title_height() + theme.get_border_size();
            this->cached_region = layout.calculate_region();
        }
    }

    virtual void notify_view_fullscreen() override
    {
        update_decoration_size();

        if (!view->fullscreen)
            notify_view_resized(view->get_wm_geometry());
    };
};

void init_view(wayfire_view view)
{
    auto surf = std::make_unique<simple_decoration_surface>(view);
    nonstd::observer_ptr<simple_decoration_surface> ptr{surf};

    view->add_subsurface(std::move(surf), true);
    view->set_decoration(ptr.get());
    view->damage();
}
<|endoftext|>