<commit_before>// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/metrics/chrome_browser_main_extra_parts_metrics.h"

#include <string>

#include "base/bind.h"
#include "base/command_line.h"
#include "base/cpu.h"
#include "base/metrics/histogram.h"
#include "base/metrics/sparse_histogram.h"
#include "base/sys_info.h"
#include "base/threading/sequenced_worker_pool.h"
#include "base/time/time.h"
#include "chrome/browser/about_flags.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chrome_browser_main.h"
#include "chrome/browser/chrome_browser_metrics_service_observer.h"
#include "chrome/browser/mac/bluetooth_utility.h"
#include "chrome/browser/pref_service_flags_storage.h"
#include "chrome/browser/shell_integration.h"
#include "content/public/browser/browser_thread.h"
#include "ui/base/touch/touch_device.h"
#include "ui/base/ui_base_switches.h"
#include "ui/events/event_switches.h"

#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
#include <gnu/libc-version.h>

#include "base/version.h"
#include "ui/base/x/x11_util.h"
#endif  // defined(OS_LINUX) && !defined(OS_CHROMEOS)

#if defined(OS_WIN)
#include "chrome/installer/util/google_update_settings.h"
#endif  // defined(OS_WIN)

namespace {

enum UMALinuxGlibcVersion {
  UMA_LINUX_GLIBC_NOT_PARSEABLE,
  UMA_LINUX_GLIBC_UNKNOWN,
  UMA_LINUX_GLIBC_2_11,
  UMA_LINUX_GLIBC_2_19 = UMA_LINUX_GLIBC_2_11 + 8,
  // NOTE: Add new version above this line and update the enum list in
  // tools/metrics/histograms/histograms.xml accordingly.
  UMA_LINUX_GLIBC_VERSION_COUNT
};

enum UMALinuxWindowManager {
  UMA_LINUX_WINDOW_MANAGER_OTHER,
  UMA_LINUX_WINDOW_MANAGER_BLACKBOX,
  UMA_LINUX_WINDOW_MANAGER_CHROME_OS,
  UMA_LINUX_WINDOW_MANAGER_COMPIZ,
  UMA_LINUX_WINDOW_MANAGER_ENLIGHTENMENT,
  UMA_LINUX_WINDOW_MANAGER_ICE_WM,
  UMA_LINUX_WINDOW_MANAGER_KWIN,
  UMA_LINUX_WINDOW_MANAGER_METACITY,
  UMA_LINUX_WINDOW_MANAGER_MUFFIN,
  UMA_LINUX_WINDOW_MANAGER_MUTTER,
  UMA_LINUX_WINDOW_MANAGER_OPENBOX,
  UMA_LINUX_WINDOW_MANAGER_XFWM4,
  // NOTE: Add new window managers above this line and update the enum list in
  // tools/metrics/histograms/histograms.xml accordingly.
  UMA_LINUX_WINDOW_MANAGER_COUNT
};

enum UMATouchEventsState {
  UMA_TOUCH_EVENTS_ENABLED,
  UMA_TOUCH_EVENTS_AUTO_ENABLED,
  UMA_TOUCH_EVENTS_AUTO_DISABLED,
  UMA_TOUCH_EVENTS_DISABLED,
  // NOTE: Add states only immediately above this line. Make sure to
  // update the enum list in tools/metrics/histograms/histograms.xml
  // accordingly.
  UMA_TOUCH_EVENTS_STATE_COUNT
};

void RecordMicroArchitectureStats() {
#if defined(ARCH_CPU_X86_FAMILY)
  base::CPU cpu;
  base::CPU::IntelMicroArchitecture arch = cpu.GetIntelMicroArchitecture();
  UMA_HISTOGRAM_ENUMERATION("Platform.IntelMaxMicroArchitecture", arch,
                            base::CPU::MAX_INTEL_MICRO_ARCHITECTURE);
#endif  // defined(ARCH_CPU_X86_FAMILY)
  UMA_HISTOGRAM_SPARSE_SLOWLY("Platform.LogicalCpuCount",
                              base::SysInfo::NumberOfProcessors());
}

// Called on the blocking pool some time after startup to avoid slowing down
// startup with metrics that aren't trivial to compute.
void RecordStartupMetricsOnBlockingPool() {
#if defined(OS_WIN)
  GoogleUpdateSettings::RecordChromeUpdatePolicyHistograms();
#endif  // defined(OS_WIN)

#if defined(OS_MACOSX) && !defined(OS_IOS)
  bluetooth_utility::BluetoothAvailability availability =
      bluetooth_utility::GetBluetoothAvailability();
  UMA_HISTOGRAM_ENUMERATION("OSX.BluetoothAvailability",
                            availability,
                            bluetooth_utility::BLUETOOTH_AVAILABILITY_COUNT);
#endif  // defined(OS_MACOSX) && !defined(OS_IOS)
}

void RecordLinuxGlibcVersion() {
#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
  Version version(gnu_get_libc_version());

  UMALinuxGlibcVersion glibc_version_result = UMA_LINUX_GLIBC_NOT_PARSEABLE;
  if (version.IsValid() && version.components().size() == 2) {
    glibc_version_result = UMA_LINUX_GLIBC_UNKNOWN;
    int glibc_major_version = version.components()[0];
    int glibc_minor_version = version.components()[1];
    if (glibc_major_version == 2) {
      // A constant to translate glibc 2.x minor versions to their
      // equivalent UMALinuxGlibcVersion values.
      const int kGlibcMinorVersionTranslationOffset = 11 - UMA_LINUX_GLIBC_2_11;
      int translated_glibc_minor_version =
          glibc_minor_version - kGlibcMinorVersionTranslationOffset;
      if (translated_glibc_minor_version >= UMA_LINUX_GLIBC_2_11 &&
          translated_glibc_minor_version <= UMA_LINUX_GLIBC_2_19) {
        glibc_version_result =
            static_cast<UMALinuxGlibcVersion>(translated_glibc_minor_version);
      }
    }
  }
  UMA_HISTOGRAM_ENUMERATION("Linux.GlibcVersion", glibc_version_result,
                            UMA_LINUX_GLIBC_VERSION_COUNT);
#endif
}

void RecordLinuxWindowManager() {
#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
  ui::WindowManagerName name = ui::GuessWindowManager();
  UMALinuxWindowManager uma_name = UMA_LINUX_WINDOW_MANAGER_OTHER;
  switch (name) {
    case ui::WM_UNKNOWN:
      uma_name = UMA_LINUX_WINDOW_MANAGER_OTHER;
      break;
    case ui::WM_BLACKBOX:
      uma_name = UMA_LINUX_WINDOW_MANAGER_BLACKBOX;
      break;
    case ui::WM_CHROME_OS:
      uma_name = UMA_LINUX_WINDOW_MANAGER_CHROME_OS;
      break;
    case ui::WM_COMPIZ:
      uma_name = UMA_LINUX_WINDOW_MANAGER_COMPIZ;
      break;
    case ui::WM_ENLIGHTENMENT:
      uma_name = UMA_LINUX_WINDOW_MANAGER_ENLIGHTENMENT;
      break;
    case ui::WM_ICE_WM:
      uma_name = UMA_LINUX_WINDOW_MANAGER_ICE_WM;
      break;
    case ui::WM_KWIN:
      uma_name = UMA_LINUX_WINDOW_MANAGER_KWIN;
      break;
    case ui::WM_METACITY:
      uma_name = UMA_LINUX_WINDOW_MANAGER_METACITY;
      break;
    case ui::WM_MUFFIN:
      uma_name = UMA_LINUX_WINDOW_MANAGER_MUFFIN;
      break;
    case ui::WM_MUTTER:
      uma_name = UMA_LINUX_WINDOW_MANAGER_MUTTER;
      break;
    case ui::WM_OPENBOX:
      uma_name = UMA_LINUX_WINDOW_MANAGER_OPENBOX;
      break;
    case ui::WM_XFWM4:
      uma_name = UMA_LINUX_WINDOW_MANAGER_XFWM4;
      break;
  }
  UMA_HISTOGRAM_ENUMERATION("Linux.WindowManager", uma_name,
                            UMA_LINUX_WINDOW_MANAGER_COUNT);
#endif
}

void RecordTouchEventState() {
  const CommandLine& command_line = *CommandLine::ForCurrentProcess();
  const std::string touch_enabled_switch =
      command_line.HasSwitch(switches::kTouchEvents) ?
      command_line.GetSwitchValueASCII(switches::kTouchEvents) :
      switches::kTouchEventsAuto;

  UMATouchEventsState state;
  if (touch_enabled_switch.empty() ||
      touch_enabled_switch == switches::kTouchEventsEnabled) {
    state = UMA_TOUCH_EVENTS_ENABLED;
  } else if (touch_enabled_switch == switches::kTouchEventsAuto) {
    state = ui::IsTouchDevicePresent() ?
        UMA_TOUCH_EVENTS_AUTO_ENABLED : UMA_TOUCH_EVENTS_AUTO_DISABLED;
  } else if (touch_enabled_switch == switches::kTouchEventsDisabled) {
    state = UMA_TOUCH_EVENTS_DISABLED;
  } else {
    NOTREACHED();
    return;
  }

  UMA_HISTOGRAM_ENUMERATION("Touchscreen.TouchEventsEnabled", state,
                            UMA_TOUCH_EVENTS_STATE_COUNT);
}

}  // namespace

ChromeBrowserMainExtraPartsMetrics::ChromeBrowserMainExtraPartsMetrics() {
}

ChromeBrowserMainExtraPartsMetrics::~ChromeBrowserMainExtraPartsMetrics() {
}

void ChromeBrowserMainExtraPartsMetrics::PreProfileInit() {
  RecordMicroArchitectureStats();
}

void ChromeBrowserMainExtraPartsMetrics::PreBrowserStart() {
  about_flags::PrefServiceFlagsStorage flags_storage_(
      g_browser_process->local_state());
  about_flags::RecordUMAStatistics(&flags_storage_);
}

void ChromeBrowserMainExtraPartsMetrics::PostBrowserStart() {
  RecordLinuxGlibcVersion();
  RecordLinuxWindowManager();
  RecordTouchEventState();

  const int kStartupMetricsGatheringDelaySeconds = 45;
  content::BrowserThread::GetBlockingPool()->PostDelayedTask(
      FROM_HERE,
      base::Bind(&RecordStartupMetricsOnBlockingPool),
      base::TimeDelta::FromSeconds(kStartupMetricsGatheringDelaySeconds));

  // Create the metrics log observer.
  // We only need this for Android for now.
#if defined(ANDROID)
  metrics_service_observer_.reset(new ChromeBrowserMetricsServiceObserver());
#endif
}

namespace chrome {

void AddMetricsExtraParts(ChromeBrowserMainParts* main_parts) {
  main_parts->AddParts(new ChromeBrowserMainExtraPartsMetrics());
}

}  // namespace chrome
<commit_msg>GuessWindowManager is defined only on x11 platform. This CL changes the platform check from Linux to X11.<commit_after>// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/metrics/chrome_browser_main_extra_parts_metrics.h"

#include <string>

#include "base/bind.h"
#include "base/command_line.h"
#include "base/cpu.h"
#include "base/metrics/histogram.h"
#include "base/metrics/sparse_histogram.h"
#include "base/sys_info.h"
#include "base/threading/sequenced_worker_pool.h"
#include "base/time/time.h"
#include "chrome/browser/about_flags.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chrome_browser_main.h"
#include "chrome/browser/chrome_browser_metrics_service_observer.h"
#include "chrome/browser/mac/bluetooth_utility.h"
#include "chrome/browser/pref_service_flags_storage.h"
#include "chrome/browser/shell_integration.h"
#include "content/public/browser/browser_thread.h"
#include "ui/base/touch/touch_device.h"
#include "ui/base/ui_base_switches.h"
#include "ui/events/event_switches.h"

#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
#include <gnu/libc-version.h>

#include "base/version.h"
#if defined(USE_X11)
#include "ui/base/x/x11_util.h"
#endif
#endif  // defined(OS_LINUX) && !defined(OS_CHROMEOS)

#if defined(OS_WIN)
#include "chrome/installer/util/google_update_settings.h"
#endif  // defined(OS_WIN)

namespace {

enum UMALinuxGlibcVersion {
  UMA_LINUX_GLIBC_NOT_PARSEABLE,
  UMA_LINUX_GLIBC_UNKNOWN,
  UMA_LINUX_GLIBC_2_11,
  UMA_LINUX_GLIBC_2_19 = UMA_LINUX_GLIBC_2_11 + 8,
  // NOTE: Add new version above this line and update the enum list in
  // tools/metrics/histograms/histograms.xml accordingly.
  UMA_LINUX_GLIBC_VERSION_COUNT
};

enum UMALinuxWindowManager {
  UMA_LINUX_WINDOW_MANAGER_OTHER,
  UMA_LINUX_WINDOW_MANAGER_BLACKBOX,
  UMA_LINUX_WINDOW_MANAGER_CHROME_OS,
  UMA_LINUX_WINDOW_MANAGER_COMPIZ,
  UMA_LINUX_WINDOW_MANAGER_ENLIGHTENMENT,
  UMA_LINUX_WINDOW_MANAGER_ICE_WM,
  UMA_LINUX_WINDOW_MANAGER_KWIN,
  UMA_LINUX_WINDOW_MANAGER_METACITY,
  UMA_LINUX_WINDOW_MANAGER_MUFFIN,
  UMA_LINUX_WINDOW_MANAGER_MUTTER,
  UMA_LINUX_WINDOW_MANAGER_OPENBOX,
  UMA_LINUX_WINDOW_MANAGER_XFWM4,
  // NOTE: Add new window managers above this line and update the enum list in
  // tools/metrics/histograms/histograms.xml accordingly.
  UMA_LINUX_WINDOW_MANAGER_COUNT
};

enum UMATouchEventsState {
  UMA_TOUCH_EVENTS_ENABLED,
  UMA_TOUCH_EVENTS_AUTO_ENABLED,
  UMA_TOUCH_EVENTS_AUTO_DISABLED,
  UMA_TOUCH_EVENTS_DISABLED,
  // NOTE: Add states only immediately above this line. Make sure to
  // update the enum list in tools/metrics/histograms/histograms.xml
  // accordingly.
  UMA_TOUCH_EVENTS_STATE_COUNT
};

void RecordMicroArchitectureStats() {
#if defined(ARCH_CPU_X86_FAMILY)
  base::CPU cpu;
  base::CPU::IntelMicroArchitecture arch = cpu.GetIntelMicroArchitecture();
  UMA_HISTOGRAM_ENUMERATION("Platform.IntelMaxMicroArchitecture", arch,
                            base::CPU::MAX_INTEL_MICRO_ARCHITECTURE);
#endif  // defined(ARCH_CPU_X86_FAMILY)
  UMA_HISTOGRAM_SPARSE_SLOWLY("Platform.LogicalCpuCount",
                              base::SysInfo::NumberOfProcessors());
}

// Called on the blocking pool some time after startup to avoid slowing down
// startup with metrics that aren't trivial to compute.
void RecordStartupMetricsOnBlockingPool() {
#if defined(OS_WIN)
  GoogleUpdateSettings::RecordChromeUpdatePolicyHistograms();
#endif  // defined(OS_WIN)

#if defined(OS_MACOSX) && !defined(OS_IOS)
  bluetooth_utility::BluetoothAvailability availability =
      bluetooth_utility::GetBluetoothAvailability();
  UMA_HISTOGRAM_ENUMERATION("OSX.BluetoothAvailability",
                            availability,
                            bluetooth_utility::BLUETOOTH_AVAILABILITY_COUNT);
#endif  // defined(OS_MACOSX) && !defined(OS_IOS)
}

void RecordLinuxGlibcVersion() {
#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
  Version version(gnu_get_libc_version());

  UMALinuxGlibcVersion glibc_version_result = UMA_LINUX_GLIBC_NOT_PARSEABLE;
  if (version.IsValid() && version.components().size() == 2) {
    glibc_version_result = UMA_LINUX_GLIBC_UNKNOWN;
    int glibc_major_version = version.components()[0];
    int glibc_minor_version = version.components()[1];
    if (glibc_major_version == 2) {
      // A constant to translate glibc 2.x minor versions to their
      // equivalent UMALinuxGlibcVersion values.
      const int kGlibcMinorVersionTranslationOffset = 11 - UMA_LINUX_GLIBC_2_11;
      int translated_glibc_minor_version =
          glibc_minor_version - kGlibcMinorVersionTranslationOffset;
      if (translated_glibc_minor_version >= UMA_LINUX_GLIBC_2_11 &&
          translated_glibc_minor_version <= UMA_LINUX_GLIBC_2_19) {
        glibc_version_result =
            static_cast<UMALinuxGlibcVersion>(translated_glibc_minor_version);
      }
    }
  }
  UMA_HISTOGRAM_ENUMERATION("Linux.GlibcVersion", glibc_version_result,
                            UMA_LINUX_GLIBC_VERSION_COUNT);
#endif
}

void RecordLinuxWindowManager() {
#if defined(USE_X11) && !defined(OS_CHROMEOS)
  ui::WindowManagerName name = ui::GuessWindowManager();
  UMALinuxWindowManager uma_name = UMA_LINUX_WINDOW_MANAGER_OTHER;
  switch (name) {
    case ui::WM_UNKNOWN:
      uma_name = UMA_LINUX_WINDOW_MANAGER_OTHER;
      break;
    case ui::WM_BLACKBOX:
      uma_name = UMA_LINUX_WINDOW_MANAGER_BLACKBOX;
      break;
    case ui::WM_CHROME_OS:
      uma_name = UMA_LINUX_WINDOW_MANAGER_CHROME_OS;
      break;
    case ui::WM_COMPIZ:
      uma_name = UMA_LINUX_WINDOW_MANAGER_COMPIZ;
      break;
    case ui::WM_ENLIGHTENMENT:
      uma_name = UMA_LINUX_WINDOW_MANAGER_ENLIGHTENMENT;
      break;
    case ui::WM_ICE_WM:
      uma_name = UMA_LINUX_WINDOW_MANAGER_ICE_WM;
      break;
    case ui::WM_KWIN:
      uma_name = UMA_LINUX_WINDOW_MANAGER_KWIN;
      break;
    case ui::WM_METACITY:
      uma_name = UMA_LINUX_WINDOW_MANAGER_METACITY;
      break;
    case ui::WM_MUFFIN:
      uma_name = UMA_LINUX_WINDOW_MANAGER_MUFFIN;
      break;
    case ui::WM_MUTTER:
      uma_name = UMA_LINUX_WINDOW_MANAGER_MUTTER;
      break;
    case ui::WM_OPENBOX:
      uma_name = UMA_LINUX_WINDOW_MANAGER_OPENBOX;
      break;
    case ui::WM_XFWM4:
      uma_name = UMA_LINUX_WINDOW_MANAGER_XFWM4;
      break;
  }
  UMA_HISTOGRAM_ENUMERATION("Linux.WindowManager", uma_name,
                            UMA_LINUX_WINDOW_MANAGER_COUNT);
#endif
}

void RecordTouchEventState() {
  const CommandLine& command_line = *CommandLine::ForCurrentProcess();
  const std::string touch_enabled_switch =
      command_line.HasSwitch(switches::kTouchEvents) ?
      command_line.GetSwitchValueASCII(switches::kTouchEvents) :
      switches::kTouchEventsAuto;

  UMATouchEventsState state;
  if (touch_enabled_switch.empty() ||
      touch_enabled_switch == switches::kTouchEventsEnabled) {
    state = UMA_TOUCH_EVENTS_ENABLED;
  } else if (touch_enabled_switch == switches::kTouchEventsAuto) {
    state = ui::IsTouchDevicePresent() ?
        UMA_TOUCH_EVENTS_AUTO_ENABLED : UMA_TOUCH_EVENTS_AUTO_DISABLED;
  } else if (touch_enabled_switch == switches::kTouchEventsDisabled) {
    state = UMA_TOUCH_EVENTS_DISABLED;
  } else {
    NOTREACHED();
    return;
  }

  UMA_HISTOGRAM_ENUMERATION("Touchscreen.TouchEventsEnabled", state,
                            UMA_TOUCH_EVENTS_STATE_COUNT);
}

}  // namespace

ChromeBrowserMainExtraPartsMetrics::ChromeBrowserMainExtraPartsMetrics() {
}

ChromeBrowserMainExtraPartsMetrics::~ChromeBrowserMainExtraPartsMetrics() {
}

void ChromeBrowserMainExtraPartsMetrics::PreProfileInit() {
  RecordMicroArchitectureStats();
}

void ChromeBrowserMainExtraPartsMetrics::PreBrowserStart() {
  about_flags::PrefServiceFlagsStorage flags_storage_(
      g_browser_process->local_state());
  about_flags::RecordUMAStatistics(&flags_storage_);
}

void ChromeBrowserMainExtraPartsMetrics::PostBrowserStart() {
  RecordLinuxGlibcVersion();
  RecordLinuxWindowManager();
  RecordTouchEventState();

  const int kStartupMetricsGatheringDelaySeconds = 45;
  content::BrowserThread::GetBlockingPool()->PostDelayedTask(
      FROM_HERE,
      base::Bind(&RecordStartupMetricsOnBlockingPool),
      base::TimeDelta::FromSeconds(kStartupMetricsGatheringDelaySeconds));

  // Create the metrics log observer.
  // We only need this for Android for now.
#if defined(ANDROID)
  metrics_service_observer_.reset(new ChromeBrowserMetricsServiceObserver());
#endif
}

namespace chrome {

void AddMetricsExtraParts(ChromeBrowserMainParts* main_parts) {
  main_parts->AddParts(new ChromeBrowserMainExtraPartsMetrics());
}

}  // namespace chrome
<|endoftext|>


<commit_before>// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/renderer_host/gtk_key_bindings_handler.h"

#include <gdk/gdkkeysyms.h>
#include <string>
#include <utility>
#include <vector>

#include "base/basictypes.h"
#include "base/file_util.h"
#include "base/path_service.h"
#include "base/string_util.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/edit_command.h"
#include "chrome/common/native_web_keyboard_event.h"
#include "testing/gtest/include/gtest/gtest.h"

class GtkKeyBindingsHandlerTest : public testing::Test {
 protected:
  struct EditCommand {
    const char* name;
    const char* value;
  };

  GtkKeyBindingsHandlerTest()
      : window_(gtk_window_new(GTK_WINDOW_TOPLEVEL)),
        handler_(NULL) {
    FilePath gtkrc;
    PathService::Get(chrome::DIR_TEST_DATA, &gtkrc);
    gtkrc = gtkrc.AppendASCII("gtk_key_bindings_test_gtkrc");
    gtk_rc_parse(gtkrc.value().c_str());

    GtkWidget* fixed = gtk_fixed_new();
    handler_ = new GtkKeyBindingsHandler(fixed);
    gtk_container_add(GTK_CONTAINER(window_), fixed);
    gtk_widget_show(fixed);
    gtk_widget_show(window_);
  }
  ~GtkKeyBindingsHandlerTest() {
    gtk_widget_destroy(window_);
    delete handler_;
  }

  NativeWebKeyboardEvent NewNativeWebKeyboardEvent(guint keyval, guint state) {
    GdkKeymap* keymap =
        gdk_keymap_get_for_display(gtk_widget_get_display(window_));

    GdkKeymapKey *keys = NULL;
    gint n_keys = 0;
    if (gdk_keymap_get_entries_for_keyval(keymap, keyval, &keys, &n_keys)) {
      GdkEventKey event;
      event.type = GDK_KEY_PRESS;
      event.window = NULL;
      event.send_event = 0;
      event.time = 0;
      event.state = state;
      event.keyval = keyval;
      event.length = 0;
      event.string = NULL;
      event.hardware_keycode = keys[0].keycode;
      event.group = keys[0].group;
      event.is_modifier = 0;
      g_free(keys);
      return NativeWebKeyboardEvent(&event);
    }
    return NativeWebKeyboardEvent();
  }

  void TestKeyBinding(const NativeWebKeyboardEvent& event,
                      const EditCommand expected_result[],
                      size_t size) {
    EditCommands result;
    ASSERT_TRUE(handler_->Match(event, &result));
    ASSERT_EQ(size, result.size());
    for (size_t i = 0; i < size; ++i) {
      ASSERT_STREQ(expected_result[i].name, result[i].name.c_str());
      ASSERT_STREQ(expected_result[i].value, result[i].value.c_str());
    }
  }

 protected:
  GtkWidget* window_;
  GtkKeyBindingsHandler* handler_;
};

TEST_F(GtkKeyBindingsHandlerTest, MoveCursor) {
  static const EditCommand kEditCommands[] = {
    // "move-cursor" (logical-positions, -2, 0)
    { "MoveBackward", "" },
    { "MoveBackward", "" },
    // "move-cursor" (logical-positions, 2, 0)
    { "MoveForward", "" },
    { "MoveForward", "" },
    // "move-cursor" (visual-positions, -1, 1)
    { "MoveLeftAndModifySelection", "" },
    // "move-cursor" (visual-positions, 1, 1)
    { "MoveRightAndModifySelection", "" },
    // "move-cursor" (words, -1, 0)
    { "MoveWordBackward", "" },
    // "move-cursor" (words, 1, 0)
    { "MoveWordForward", "" },
    // "move-cursor" (display-lines, -1, 0)
    { "MoveUp", "" },
    // "move-cursor" (display-lines, 1, 0)
    { "MoveDown", "" },
    // "move-cursor" (display-line-ends, -1, 0)
    { "MoveToBeginningOfLine", "" },
    // "move-cursor" (display-line-ends, 1, 0)
    { "MoveToEndOfLine", "" },
    // "move-cursor" (paragraph-ends, -1, 0)
    { "MoveToBeginningOfParagraph", "" },
    // "move-cursor" (paragraph-ends, 1, 0)
    { "MoveToEndOfParagraph", "" },
    // "move-cursor" (pages, -1, 0)
    { "MovePageUp", "" },
    // "move-cursor" (pages, 1, 0)
    { "MovePageDown", "" },
    // "move-cursor" (buffer-ends, -1, 0)
    { "MoveToBeginningOfDocument", "" },
    // "move-cursor" (buffer-ends, 1, 0)
    { "MoveToEndOfDocument", "" }
  };

  TestKeyBinding(NewNativeWebKeyboardEvent(GDK_1, GDK_CONTROL_MASK),
                 kEditCommands, arraysize(kEditCommands));
}

TEST_F(GtkKeyBindingsHandlerTest, DeleteFromCursor) {
  static const EditCommand kEditCommands[] = {
    // "delete-from-cursor" (chars, -2)
    { "DeleteBackward", "" },
    { "DeleteBackward", "" },
    // "delete-from-cursor" (chars, 2)
    { "DeleteForward", "" },
    { "DeleteForward", "" },
    // "delete-from-cursor" (word-ends, -1)
    { "DeleteWordBackward", "" },
    // "delete-from-cursor" (word-ends, 1)
    { "DeleteWordForward", "" },
    // "delete-from-cursor" (words, -1)
    { "MoveWordBackward", "" },
    { "DeleteWordForward", "" },
    // "delete-from-cursor" (words, 1)
    { "MoveWordForward", "" },
    { "DeleteWordBackward", "" },
    // "delete-from-cursor" (display-lines, -1)
    { "MoveToBeginningOfLine", "" },
    { "DeleteToEndOfLine", "" },
    // "delete-from-cursor" (display-lines, 1)
    { "MoveToBeginningOfLine", "" },
    { "DeleteToEndOfLine", "" },
    // "delete-from-cursor" (display-line-ends, -1)
    { "DeleteToBeginningOfLine", "" },
    // "delete-from-cursor" (display-line-ends, 1)
    { "DeleteToEndOfLine", "" },
    // "delete-from-cursor" (paragraph-ends, -1)
    { "DeleteToBeginningOfParagraph", "" },
    // "delete-from-cursor" (paragraph-ends, 1)
    { "DeleteToEndOfParagraph", "" },
    // "delete-from-cursor" (paragraphs, -1)
    { "MoveToBeginningOfParagraph", "" },
    { "DeleteToEndOfParagraph", "" },
    // "delete-from-cursor" (paragraphs, 1)
    { "MoveToBeginningOfParagraph", "" },
    { "DeleteToEndOfParagraph", "" },
  };

  TestKeyBinding(NewNativeWebKeyboardEvent(GDK_2, GDK_CONTROL_MASK),
                 kEditCommands, arraysize(kEditCommands));
}

TEST_F(GtkKeyBindingsHandlerTest, OtherActions) {
  static const EditCommand kBackspace[] = {
    { "DeleteBackward", "" }
  };
  TestKeyBinding(NewNativeWebKeyboardEvent(GDK_3, GDK_CONTROL_MASK),
                 kBackspace, arraysize(kBackspace));

  static const EditCommand kCopyClipboard[] = {
    { "Copy", "" }
  };
  TestKeyBinding(NewNativeWebKeyboardEvent(GDK_4, GDK_CONTROL_MASK),
                 kCopyClipboard, arraysize(kCopyClipboard));

  static const EditCommand kCutClipboard[] = {
    { "Cut", "" }
  };
  TestKeyBinding(NewNativeWebKeyboardEvent(GDK_5, GDK_CONTROL_MASK),
                 kCutClipboard, arraysize(kCutClipboard));

  static const EditCommand kInsertAtCursor[] = {
    { "InsertText", "hello" }
  };
  TestKeyBinding(NewNativeWebKeyboardEvent(GDK_6, GDK_CONTROL_MASK),
                 kInsertAtCursor, arraysize(kInsertAtCursor));

  static const EditCommand kPasteClipboard[] = {
    { "Paste", "" }
  };
  TestKeyBinding(NewNativeWebKeyboardEvent(GDK_7, GDK_CONTROL_MASK),
                 kPasteClipboard, arraysize(kPasteClipboard));

  static const EditCommand kSelectAll[] = {
    { "Unselect", "" },
    { "SelectAll", "" }
  };
  TestKeyBinding(NewNativeWebKeyboardEvent(GDK_8, GDK_CONTROL_MASK),
                 kSelectAll, arraysize(kSelectAll));

  static const EditCommand kSetAnchor[] = {
    { "SetMark", "" }
  };
  TestKeyBinding(NewNativeWebKeyboardEvent(GDK_9, GDK_CONTROL_MASK),
                 kSetAnchor, arraysize(kSetAnchor));
}
<commit_msg>Mark the GtkKeyBindingsHandlerTest  tests as flaky since they don't work in a chroot.<commit_after>// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/renderer_host/gtk_key_bindings_handler.h"

#include <gdk/gdkkeysyms.h>
#include <string>
#include <utility>
#include <vector>

#include "base/basictypes.h"
#include "base/file_util.h"
#include "base/path_service.h"
#include "base/string_util.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/edit_command.h"
#include "chrome/common/native_web_keyboard_event.h"
#include "testing/gtest/include/gtest/gtest.h"

class GtkKeyBindingsHandlerTest : public testing::Test {
 protected:
  struct EditCommand {
    const char* name;
    const char* value;
  };

  GtkKeyBindingsHandlerTest()
      : window_(gtk_window_new(GTK_WINDOW_TOPLEVEL)),
        handler_(NULL) {
    FilePath gtkrc;
    PathService::Get(chrome::DIR_TEST_DATA, &gtkrc);
    gtkrc = gtkrc.AppendASCII("gtk_key_bindings_test_gtkrc");
    gtk_rc_parse(gtkrc.value().c_str());

    GtkWidget* fixed = gtk_fixed_new();
    handler_ = new GtkKeyBindingsHandler(fixed);
    gtk_container_add(GTK_CONTAINER(window_), fixed);
    gtk_widget_show(fixed);
    gtk_widget_show(window_);
  }
  ~GtkKeyBindingsHandlerTest() {
    gtk_widget_destroy(window_);
    delete handler_;
  }

  NativeWebKeyboardEvent NewNativeWebKeyboardEvent(guint keyval, guint state) {
    GdkKeymap* keymap =
        gdk_keymap_get_for_display(gtk_widget_get_display(window_));

    GdkKeymapKey *keys = NULL;
    gint n_keys = 0;
    if (gdk_keymap_get_entries_for_keyval(keymap, keyval, &keys, &n_keys)) {
      GdkEventKey event;
      event.type = GDK_KEY_PRESS;
      event.window = NULL;
      event.send_event = 0;
      event.time = 0;
      event.state = state;
      event.keyval = keyval;
      event.length = 0;
      event.string = NULL;
      event.hardware_keycode = keys[0].keycode;
      event.group = keys[0].group;
      event.is_modifier = 0;
      g_free(keys);
      return NativeWebKeyboardEvent(&event);
    }
    return NativeWebKeyboardEvent();
  }

  void TestKeyBinding(const NativeWebKeyboardEvent& event,
                      const EditCommand expected_result[],
                      size_t size) {
    EditCommands result;
    ASSERT_TRUE(handler_->Match(event, &result));
    ASSERT_EQ(size, result.size());
    for (size_t i = 0; i < size; ++i) {
      ASSERT_STREQ(expected_result[i].name, result[i].name.c_str());
      ASSERT_STREQ(expected_result[i].value, result[i].value.c_str());
    }
  }

 protected:
  GtkWidget* window_;
  GtkKeyBindingsHandler* handler_;
};

// Does not work in a chroot. See bug 60363.
TEST_F(GtkKeyBindingsHandlerTest, FLAKY_MoveCursor) {
  static const EditCommand kEditCommands[] = {
    // "move-cursor" (logical-positions, -2, 0)
    { "MoveBackward", "" },
    { "MoveBackward", "" },
    // "move-cursor" (logical-positions, 2, 0)
    { "MoveForward", "" },
    { "MoveForward", "" },
    // "move-cursor" (visual-positions, -1, 1)
    { "MoveLeftAndModifySelection", "" },
    // "move-cursor" (visual-positions, 1, 1)
    { "MoveRightAndModifySelection", "" },
    // "move-cursor" (words, -1, 0)
    { "MoveWordBackward", "" },
    // "move-cursor" (words, 1, 0)
    { "MoveWordForward", "" },
    // "move-cursor" (display-lines, -1, 0)
    { "MoveUp", "" },
    // "move-cursor" (display-lines, 1, 0)
    { "MoveDown", "" },
    // "move-cursor" (display-line-ends, -1, 0)
    { "MoveToBeginningOfLine", "" },
    // "move-cursor" (display-line-ends, 1, 0)
    { "MoveToEndOfLine", "" },
    // "move-cursor" (paragraph-ends, -1, 0)
    { "MoveToBeginningOfParagraph", "" },
    // "move-cursor" (paragraph-ends, 1, 0)
    { "MoveToEndOfParagraph", "" },
    // "move-cursor" (pages, -1, 0)
    { "MovePageUp", "" },
    // "move-cursor" (pages, 1, 0)
    { "MovePageDown", "" },
    // "move-cursor" (buffer-ends, -1, 0)
    { "MoveToBeginningOfDocument", "" },
    // "move-cursor" (buffer-ends, 1, 0)
    { "MoveToEndOfDocument", "" }
  };

  TestKeyBinding(NewNativeWebKeyboardEvent(GDK_1, GDK_CONTROL_MASK),
                 kEditCommands, arraysize(kEditCommands));
}

// Does not work in a chroot. See bug 60363.
TEST_F(GtkKeyBindingsHandlerTest, FLAKY_DeleteFromCursor) {
  static const EditCommand kEditCommands[] = {
    // "delete-from-cursor" (chars, -2)
    { "DeleteBackward", "" },
    { "DeleteBackward", "" },
    // "delete-from-cursor" (chars, 2)
    { "DeleteForward", "" },
    { "DeleteForward", "" },
    // "delete-from-cursor" (word-ends, -1)
    { "DeleteWordBackward", "" },
    // "delete-from-cursor" (word-ends, 1)
    { "DeleteWordForward", "" },
    // "delete-from-cursor" (words, -1)
    { "MoveWordBackward", "" },
    { "DeleteWordForward", "" },
    // "delete-from-cursor" (words, 1)
    { "MoveWordForward", "" },
    { "DeleteWordBackward", "" },
    // "delete-from-cursor" (display-lines, -1)
    { "MoveToBeginningOfLine", "" },
    { "DeleteToEndOfLine", "" },
    // "delete-from-cursor" (display-lines, 1)
    { "MoveToBeginningOfLine", "" },
    { "DeleteToEndOfLine", "" },
    // "delete-from-cursor" (display-line-ends, -1)
    { "DeleteToBeginningOfLine", "" },
    // "delete-from-cursor" (display-line-ends, 1)
    { "DeleteToEndOfLine", "" },
    // "delete-from-cursor" (paragraph-ends, -1)
    { "DeleteToBeginningOfParagraph", "" },
    // "delete-from-cursor" (paragraph-ends, 1)
    { "DeleteToEndOfParagraph", "" },
    // "delete-from-cursor" (paragraphs, -1)
    { "MoveToBeginningOfParagraph", "" },
    { "DeleteToEndOfParagraph", "" },
    // "delete-from-cursor" (paragraphs, 1)
    { "MoveToBeginningOfParagraph", "" },
    { "DeleteToEndOfParagraph", "" },
  };

  TestKeyBinding(NewNativeWebKeyboardEvent(GDK_2, GDK_CONTROL_MASK),
                 kEditCommands, arraysize(kEditCommands));
}

// Does not work in a chroot. See bug 60363.
TEST_F(GtkKeyBindingsHandlerTest, FLAKY_OtherActions) {
  static const EditCommand kBackspace[] = {
    { "DeleteBackward", "" }
  };
  TestKeyBinding(NewNativeWebKeyboardEvent(GDK_3, GDK_CONTROL_MASK),
                 kBackspace, arraysize(kBackspace));

  static const EditCommand kCopyClipboard[] = {
    { "Copy", "" }
  };
  TestKeyBinding(NewNativeWebKeyboardEvent(GDK_4, GDK_CONTROL_MASK),
                 kCopyClipboard, arraysize(kCopyClipboard));

  static const EditCommand kCutClipboard[] = {
    { "Cut", "" }
  };
  TestKeyBinding(NewNativeWebKeyboardEvent(GDK_5, GDK_CONTROL_MASK),
                 kCutClipboard, arraysize(kCutClipboard));

  static const EditCommand kInsertAtCursor[] = {
    { "InsertText", "hello" }
  };
  TestKeyBinding(NewNativeWebKeyboardEvent(GDK_6, GDK_CONTROL_MASK),
                 kInsertAtCursor, arraysize(kInsertAtCursor));

  static const EditCommand kPasteClipboard[] = {
    { "Paste", "" }
  };
  TestKeyBinding(NewNativeWebKeyboardEvent(GDK_7, GDK_CONTROL_MASK),
                 kPasteClipboard, arraysize(kPasteClipboard));

  static const EditCommand kSelectAll[] = {
    { "Unselect", "" },
    { "SelectAll", "" }
  };
  TestKeyBinding(NewNativeWebKeyboardEvent(GDK_8, GDK_CONTROL_MASK),
                 kSelectAll, arraysize(kSelectAll));

  static const EditCommand kSetAnchor[] = {
    { "SetMark", "" }
  };
  TestKeyBinding(NewNativeWebKeyboardEvent(GDK_9, GDK_CONTROL_MASK),
                 kSetAnchor, arraysize(kSetAnchor));
}
<|endoftext|>


<commit_before>#include <QtWidgets>
#include "mainwindow.h"
#include <fts_fuzzy_match.h>
#include <glob.h>
#include <string>
#include <map>
#include <database.h>

Window::Window(QWidget *parent) : QMainWindow(parent)
{
    // Initalise database
    db.setDatabaseName("recipes.db");

    // Initialise widgets
    searchBox = new SearchBox();
    searchBox->setPlaceholderText("Search for recipes");
    recipeBox = new QComboBox();
    QStringList recipeCategories;
    recipeCategories << "All Recipes" << "Beef" << "Chicken" << "Dessert" << "Lamb" << "Pork" << "Seafood" << "Turkey" << "Veggie";
    recipeBox->addItems(recipeCategories);
    createRecipeList();
    numResults = new QLabel();

    // Set layout
    centralWidget = new QWidget();
    QGridLayout *mainLayout = new QGridLayout(centralWidget);
    mainLayout->addWidget(searchBox, 0, 0, 1, 6);
    mainLayout->addWidget(numResults, 0, 6, 1, 1);
    mainLayout->addWidget(recipeBox, 0, 7, 1, 1);
    mainLayout->addWidget(recipeList, 1, 0, 1, 8);
    centralWidget->setLayout(mainLayout);
    centralWidget->show();
    setCentralWidget(centralWidget);

    // Create menus
    optionsMenu = new QMenu("Options");
    updateDb = new QAction("Update database", this);
    connect(updateDb, &QAction::triggered, this, &Window::updateDatabase);
    cleanDb = new QAction("Clean database", this);
    connect(cleanDb, &QAction::triggered, this, &Window::cleanDatabase);
    optionsMenu->addAction(updateDb);
    optionsMenu->addAction(cleanDb);
    menuBar()->addMenu(optionsMenu);

    // Set window paramters
    setWindowTitle(tr("Find Recipes"));
    setMinimumSize(600, 400);

    // Set signals
    connect(recipeList, &QListWidget::itemDoubleClicked, this, &Window::openFile);
    connect(searchBox, SIGNAL(inputText(QString)), this, SLOT(updateRecipesDiplay(QString)));
    connect(searchBox, SIGNAL(returnPressed()), recipeList, SLOT(setFocus()));
    connect(recipeBox, SIGNAL(currentTextChanged(QString)), searchBox, SLOT(recipeFiterChanged(QString)));

    // Populate list on start up
    updateRecipesDiplay("");
}

// Get list of files according to glob patternn
QStringList globVector(const std::string& pattern){
    glob_t glob_result;
    glob(pattern.c_str(),GLOB_TILDE,NULL,&glob_result);
    QStringList files;
    for(unsigned int i=0; i<glob_result.gl_pathc; ++i){
        files << QString(glob_result.gl_pathv[i]);
    }
    globfree(&glob_result);
    return files;
}

void SearchBox::recipeFiterChanged(QString newFilter){
    // When the recipe filter changes, emit this signal to call updateRecipeDisplay
    emit inputText(text());
}

void SearchBox::keyPressEvent(QKeyEvent *evt){
    QLineEdit::keyPressEvent(evt);
    setPlaceholderText("Search for recipes");
    // When the search changes, emit this signal to call updateRecipeDisplay
    emit inputText(text());
}

void Window::updateRecipesDiplay(QString searchText){
    recipeList->clear();

    QList<QListWidgetItem*> recipes = getRecipeList(searchText);
    for (int i=0; i<recipes.size(); ++i){
        recipeList->addItem(recipes[i]);
    }

    if(searchText.isEmpty()){
        recipeList->sortItems();
    }

    QString text = QString("%1 recipes").arg(recipes.size());
    if (recipes.size() == 1){
        text = "1 recipe";
    }
    numResults->setText(text);
}

QList<QListWidgetItem*> Window::getRecipeList(QString searchText){
    QList<QListWidgetItem*> recipes;
    if (searchText.isEmpty()) {
        recipes = getAllRecipes();
    }else{
        recipes = getMatchingRecipes(searchText);
    }
    return recipes;
}

QList<QListWidgetItem*> Window::getAllRecipes(){
    QList<QListWidgetItem*> recipes;

    // Open database and execute query
    db.open();
    // Prepare query based on filter
    QSqlQuery query = QSqlQuery();
    if(recipeBox->currentText() != "All Recipes"){
        QString category = recipeBox->currentText();
        query.prepare("select TITLE, IMG_PATH, HTML_PATH from RECIPES where CATEGORY = :category");
        query.bindValue(":category", category);
        query.setForwardOnly(true);
    }else{
        query.prepare("select TITLE, IMG_PATH, HTML_PATH from RECIPES");
        query.setForwardOnly(true);
    }
    // Execute query
    query.exec();

    while(query.next()){
        // Extract info from query results
        QString title = query.value(0).toString();
        QString img_path = query.value(1).toString();
        QString html_path = query.value(2).toString();

        // Create QListWidgetItems
        QListWidgetItem *recipe = new QListWidgetItem;
        recipe->setText(title);
        recipe->setData(Qt::UserRole, html_path);

        QImage *img = new QImage();
        bool loaded = img->load(img_path);
        if (loaded){
            recipe->setIcon(QPixmap::fromImage(*img));
        }else{
            // If image doesn't exist, use placeholder image
            bool loaded = img->load("./images/Placeholder.jpg");
            if (loaded){
                recipe->setIcon(QPixmap::fromImage(*img));
            }
        }
        recipes.append(recipe);
    }
    db.close();
    return recipes;
}

QList<QListWidgetItem*> Window::getMatchingRecipes(QString searchText){
    QList<QListWidgetItem*> recipes;

    // Get matching recipes and their scores. The QStringList contains title, img_path, file_path in order.
    std::map<double, QStringList> matchingRecipes = findMatches(searchText);
    // Build QListWidgetItems and add to QList
    // By default the map should be in ascending order, so use reverse iterator to get highest matches first
    for (auto iter = matchingRecipes.rbegin(); iter != matchingRecipes.rend(); ++iter){

        QString title = iter->second[0];
        QString img_path = iter->second[1];
        QString html_path = iter->second[2];

        QListWidgetItem *recipe = new QListWidgetItem;
        recipe->setText(title);
        recipe->setData(Qt::UserRole, html_path);

        QImage *img = new QImage();
        bool loaded = img->load(img_path);
        if (loaded){
            recipe->setIcon(QPixmap::fromImage(*img));
        }else{
            // If image doesn't exist, use placeholder image
            bool loaded = img->load("./Images/Placeholder.jpg");
            if (loaded){
                recipe->setIcon(QPixmap::fromImage(*img));
            }
        }
        recipes.append(recipe);
    }

    return recipes;
}

std::map<double, QStringList> Window::findMatches(QString text)
{
    // Open database
    db.open();
    // Prepare query based on filter
    QSqlQuery query = QSqlQuery();
    if(recipeBox->currentText() != "All Recipes"){
        QString category = recipeBox->currentText();
        query.prepare("select TITLE, IMG_PATH, HTML_PATH from RECIPES where CATEGORY = :category");
        query.bindValue(":category", category);
        query.setForwardOnly(true);
    }else{
        query.prepare("select TITLE, IMG_PATH, HTML_PATH from RECIPES");
        query.setForwardOnly(true);
    }
    // Execute query
    query.exec();

    // Get matching files and their scores
    std::map<double, QStringList> matchingFiles;
    std::string txtstr = text.toStdString();
    while(query.next()){
        int score;
        QString title = query.value(0).toString();
        QString img_path = query.value(1).toString().replace("\'", "").replace(",", "");
        QString file_path = query.value(2).toString();

        std::string titlestr = title.toStdString();
        if (fts::fuzzy_match_score(txtstr.c_str(), titlestr.c_str(), score)){
            // If a map entry already has the current score, increase score by 0.01.
            double dbscore = (double)score;
            if (matchingFiles.count(dbscore) > 0){
                dbscore += 0.01;
            }
            matchingFiles[dbscore] = QStringList() << title << img_path << file_path;
        }
    }
    db.close();
    return matchingFiles;
}

void Window::createRecipeList()
{
    recipeList = new QListWidget();
    recipeList->setViewMode(QListView::IconMode);
    recipeList->setIconSize(QSize(267, 150));
    recipeList->setGridSize(QSize(280, 185));
    recipeList->setWordWrap(true);
    recipeList->setTextElideMode(Qt::ElideNone);
}

void Window::openFile(QListWidgetItem *recipe)
{
    // Read hidden data to find full file path
    QString path = recipe->data(Qt::UserRole).toString();
    QDesktopServices::openUrl(QUrl::fromLocalFile(currentDir.absoluteFilePath(path)));
}

void Window::updateDatabase(){
    db_ops::update_database(&db);
    searchBox->setPlaceholderText("Search for recipes - Updated!");
    // Repopulate list
    updateRecipesDiplay("");
}

void Window::cleanDatabase(){
    db_ops::clean_database(&db);
    searchBox->setPlaceholderText("Search for recipes - Cleaned!");
}

void Window::resizeEvent(QResizeEvent *event){
    int iconWidth, iconHeight, gridWidth, gridHeight, columns;
    double gridRatio = 280.0/185.0;
    double iconRatio = 267.0/150.0;
    QSize recipeListSize = recipeList->size();

    if(recipeListSize.width()<=587){
        // Set defaults for minimum size
        columns = 2;
        iconWidth = 267;
        iconHeight = 150;
        gridWidth = 280;
        gridHeight = 185;
    }else{
        // Icons should never go larger than default, so set number of columns to round up
        columns = ceil(recipeListSize.width()/280.0);
        // Width of grid is widget_width/columns, with extra width removed to allow for scrollbar
        gridWidth = int(recipeListSize.width()/columns) - ceil(18.0/columns);
        // Calculate other parameters based on ratios of default values.
        gridHeight = int(gridWidth/gridRatio);
        iconWidth = gridWidth - 13;
        iconHeight = int(iconWidth/iconRatio);
    }

    recipeList->setIconSize(QSize(iconWidth, iconHeight));
    recipeList->setGridSize(QSize(gridWidth, gridHeight));
}

<commit_msg>Fix placeholder image not appearing when searching<commit_after>#include <QtWidgets>
#include "mainwindow.h"
#include <fts_fuzzy_match.h>
#include <glob.h>
#include <string>
#include <map>
#include <database.h>

Window::Window(QWidget *parent) : QMainWindow(parent)
{
    // Initalise database
    db.setDatabaseName("recipes.db");

    // Initialise widgets
    searchBox = new SearchBox();
    searchBox->setPlaceholderText("Search for recipes");
    recipeBox = new QComboBox();
    QStringList recipeCategories;
    recipeCategories << "All Recipes" << "Beef" << "Chicken" << "Dessert" << "Lamb" << "Pork" << "Seafood" << "Turkey" << "Veggie";
    recipeBox->addItems(recipeCategories);
    createRecipeList();
    numResults = new QLabel();

    // Set layout
    centralWidget = new QWidget();
    QGridLayout *mainLayout = new QGridLayout(centralWidget);
    mainLayout->addWidget(searchBox, 0, 0, 1, 6);
    mainLayout->addWidget(numResults, 0, 6, 1, 1);
    mainLayout->addWidget(recipeBox, 0, 7, 1, 1);
    mainLayout->addWidget(recipeList, 1, 0, 1, 8);
    centralWidget->setLayout(mainLayout);
    centralWidget->show();
    setCentralWidget(centralWidget);

    // Create menus
    optionsMenu = new QMenu("Options");
    updateDb = new QAction("Update database", this);
    connect(updateDb, &QAction::triggered, this, &Window::updateDatabase);
    cleanDb = new QAction("Clean database", this);
    connect(cleanDb, &QAction::triggered, this, &Window::cleanDatabase);
    optionsMenu->addAction(updateDb);
    optionsMenu->addAction(cleanDb);
    menuBar()->addMenu(optionsMenu);

    // Set window paramters
    setWindowTitle(tr("Find Recipes"));
    setMinimumSize(600, 400);

    // Set signals
    connect(recipeList, &QListWidget::itemDoubleClicked, this, &Window::openFile);
    connect(searchBox, SIGNAL(inputText(QString)), this, SLOT(updateRecipesDiplay(QString)));
    connect(searchBox, SIGNAL(returnPressed()), recipeList, SLOT(setFocus()));
    connect(recipeBox, SIGNAL(currentTextChanged(QString)), searchBox, SLOT(recipeFiterChanged(QString)));

    // Populate list on start up
    updateRecipesDiplay("");
}

// Get list of files according to glob patternn
QStringList globVector(const std::string& pattern){
    glob_t glob_result;
    glob(pattern.c_str(),GLOB_TILDE,NULL,&glob_result);
    QStringList files;
    for(unsigned int i=0; i<glob_result.gl_pathc; ++i){
        files << QString(glob_result.gl_pathv[i]);
    }
    globfree(&glob_result);
    return files;
}

void SearchBox::recipeFiterChanged(QString newFilter){
    // When the recipe filter changes, emit this signal to call updateRecipeDisplay
    emit inputText(text());
}

void SearchBox::keyPressEvent(QKeyEvent *evt){
    QLineEdit::keyPressEvent(evt);
    setPlaceholderText("Search for recipes");
    // When the search changes, emit this signal to call updateRecipeDisplay
    emit inputText(text());
}

void Window::updateRecipesDiplay(QString searchText){
    recipeList->clear();

    QList<QListWidgetItem*> recipes = getRecipeList(searchText);
    for (int i=0; i<recipes.size(); ++i){
        recipeList->addItem(recipes[i]);
    }

    if(searchText.isEmpty()){
        recipeList->sortItems();
    }

    QString text = QString("%1 recipes").arg(recipes.size());
    if (recipes.size() == 1){
        text = "1 recipe";
    }
    numResults->setText(text);
}

QList<QListWidgetItem*> Window::getRecipeList(QString searchText){
    QList<QListWidgetItem*> recipes;
    if (searchText.isEmpty()) {
        recipes = getAllRecipes();
    }else{
        recipes = getMatchingRecipes(searchText);
    }
    return recipes;
}

QList<QListWidgetItem*> Window::getAllRecipes(){
    QList<QListWidgetItem*> recipes;

    // Open database and execute query
    db.open();
    // Prepare query based on filter
    QSqlQuery query = QSqlQuery();
    if(recipeBox->currentText() != "All Recipes"){
        QString category = recipeBox->currentText();
        query.prepare("select TITLE, IMG_PATH, HTML_PATH from RECIPES where CATEGORY = :category");
        query.bindValue(":category", category);
        query.setForwardOnly(true);
    }else{
        query.prepare("select TITLE, IMG_PATH, HTML_PATH from RECIPES");
        query.setForwardOnly(true);
    }
    // Execute query
    query.exec();

    while(query.next()){
        // Extract info from query results
        QString title = query.value(0).toString();
        QString img_path = query.value(1).toString();
        QString html_path = query.value(2).toString();

        // Create QListWidgetItems
        QListWidgetItem *recipe = new QListWidgetItem;
        recipe->setText(title);
        recipe->setData(Qt::UserRole, html_path);

        QImage *img = new QImage();
        bool loaded = img->load(img_path);
        if (loaded){
            recipe->setIcon(QPixmap::fromImage(*img));
        }else{
            // If image doesn't exist, use placeholder image
            bool loaded = img->load("./images/Placeholder.jpg");
            if (loaded){
                recipe->setIcon(QPixmap::fromImage(*img));
            }
        }
        recipes.append(recipe);
    }
    db.close();
    return recipes;
}

QList<QListWidgetItem*> Window::getMatchingRecipes(QString searchText){
    QList<QListWidgetItem*> recipes;

    // Get matching recipes and their scores. The QStringList contains title, img_path, file_path in order.
    std::map<double, QStringList> matchingRecipes = findMatches(searchText);
    // Build QListWidgetItems and add to QList
    // By default the map should be in ascending order, so use reverse iterator to get highest matches first
    for (auto iter = matchingRecipes.rbegin(); iter != matchingRecipes.rend(); ++iter){

        QString title = iter->second[0];
        QString img_path = iter->second[1];
        QString html_path = iter->second[2];

        QListWidgetItem *recipe = new QListWidgetItem;
        recipe->setText(title);
        recipe->setData(Qt::UserRole, html_path);

        QImage *img = new QImage();
        bool loaded = img->load(img_path);
        if (loaded){
            recipe->setIcon(QPixmap::fromImage(*img));
        }else{
            // If image doesn't exist, use placeholder image
            bool loaded = img->load("./images/Placeholder.jpg");
            if (loaded){
                recipe->setIcon(QPixmap::fromImage(*img));
            }
        }
        recipes.append(recipe);
    }

    return recipes;
}

std::map<double, QStringList> Window::findMatches(QString text)
{
    // Open database
    db.open();
    // Prepare query based on filter
    QSqlQuery query = QSqlQuery();
    if(recipeBox->currentText() != "All Recipes"){
        QString category = recipeBox->currentText();
        query.prepare("select TITLE, IMG_PATH, HTML_PATH from RECIPES where CATEGORY = :category");
        query.bindValue(":category", category);
        query.setForwardOnly(true);
    }else{
        query.prepare("select TITLE, IMG_PATH, HTML_PATH from RECIPES");
        query.setForwardOnly(true);
    }
    // Execute query
    query.exec();

    // Get matching files and their scores
    std::map<double, QStringList> matchingFiles;
    std::string txtstr = text.toStdString();
    while(query.next()){
        int score;
        QString title = query.value(0).toString();
        QString img_path = query.value(1).toString().replace("\'", "").replace(",", "");
        QString file_path = query.value(2).toString();

        std::string titlestr = title.toStdString();
        if (fts::fuzzy_match_score(txtstr.c_str(), titlestr.c_str(), score)){
            // If a map entry already has the current score, increase score by 0.01.
            double dbscore = (double)score;
            if (matchingFiles.count(dbscore) > 0){
                dbscore += 0.01;
            }
            matchingFiles[dbscore] = QStringList() << title << img_path << file_path;
        }
    }
    db.close();
    return matchingFiles;
}

void Window::createRecipeList()
{
    recipeList = new QListWidget();
    recipeList->setViewMode(QListView::IconMode);
    recipeList->setIconSize(QSize(267, 150));
    recipeList->setGridSize(QSize(280, 185));
    recipeList->setWordWrap(true);
    recipeList->setTextElideMode(Qt::ElideNone);
}

void Window::openFile(QListWidgetItem *recipe)
{
    // Read hidden data to find full file path
    QString path = recipe->data(Qt::UserRole).toString();
    QDesktopServices::openUrl(QUrl::fromLocalFile(currentDir.absoluteFilePath(path)));
}

void Window::updateDatabase(){
    db_ops::update_database(&db);
    searchBox->setPlaceholderText("Search for recipes - Updated!");
    // Repopulate list
    updateRecipesDiplay("");
}

void Window::cleanDatabase(){
    db_ops::clean_database(&db);
    searchBox->setPlaceholderText("Search for recipes - Cleaned!");
}

void Window::resizeEvent(QResizeEvent *event){
    int iconWidth, iconHeight, gridWidth, gridHeight, columns;
    double gridRatio = 280.0/185.0;
    double iconRatio = 267.0/150.0;
    QSize recipeListSize = recipeList->size();

    if(recipeListSize.width()<=587){
        // Set defaults for minimum size
        columns = 2;
        iconWidth = 267;
        iconHeight = 150;
        gridWidth = 280;
        gridHeight = 185;
    }else{
        // Icons should never go larger than default, so set number of columns to round up
        columns = ceil(recipeListSize.width()/280.0);
        // Width of grid is widget_width/columns, with extra width removed to allow for scrollbar
        gridWidth = int(recipeListSize.width()/columns) - ceil(18.0/columns);
        // Calculate other parameters based on ratios of default values.
        gridHeight = int(gridWidth/gridRatio);
        iconWidth = gridWidth - 13;
        iconHeight = int(iconWidth/iconRatio);
    }

    recipeList->setIconSize(QSize(iconWidth, iconHeight));
    recipeList->setGridSize(QSize(gridWidth, gridHeight));
}

<|endoftext|>


<commit_before>/*
Copyright (C) 2012 Kolibre

This file is part of kolibre-player.

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

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

You should have received a copy of the GNU Lesser General Public License
along with kolibre-player. If not, see <http://www.gnu.org/licenses/>.
*/

#include <cstdlib>
#include "PlayerImpl.h"

#include "setup_logging.h"

bool playerMessageSlot( Player::playerMessage message )
{
    std::cout << "Got player message " << message << std::endl;
    switch (message)
    {
    case Player::PLAYER_CONTINUE:
        return false;
    case Player::PLAYER_ERROR:
        return true;
    }
}

int main(int argc, char *argv[])
{
    setup_logging();

    PlayerImpl Player;

    Player.doOnPlayerMessage(playerMessageSlot);

    bool res = Player.sendERRORSignal();
    assert(res);

    res = Player.sendCONTSignal();
    assert(!res);

    return 0;
}

<commit_msg>Add more signaltests<commit_after>/*
Copyright (C) 2012 Kolibre

This file is part of kolibre-player.

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

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

You should have received a copy of the GNU Lesser General Public License
along with kolibre-player. If not, see <http://www.gnu.org/licenses/>.
*/

#include <cstdlib>
#include "PlayerImpl.h"

#include "setup_logging.h"

bool playerMessageSlot( Player::playerMessage message )
{
    std::cout << "Got player message " << message << std::endl;
    switch (message)
    {
    case Player::PLAYER_CONTINUE:
        return false;
    case Player::PLAYER_ERROR:
        return true;
    }
}

int main(int argc, char *argv[])
{
    setup_logging();

    PlayerImpl Player;

    //Test sending a message with no slots
    bool res = Player.sendERRORSignal();
    assert(!res);
    res = Player.sendBUFFERINGSignal();
    assert(!res);
    res = Player.sendCONTSignal();
    assert(!res);
    res = Player.sendEOSSignal();
    assert(!res);

    Player.doOnPlayerMessage(playerMessageSlot);

    res = Player.sendERRORSignal();
    assert(res);

    res = Player.sendCONTSignal();
    assert(!res);

    return 0;
}

<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include <glog/logging.h>

#include "cnetlink.h"
#include "nbi_impl.h"
#include "tap_manager.h"

#include "netlink/ctapdev.h"
#include "utils/utils.h"

namespace basebox {

nbi_impl::nbi_impl(std::shared_ptr<cnetlink> nl,
                   std::shared_ptr<tap_manager> tap_man)
    : nl(nl), tap_man(tap_man) {
  nl->set_tapmanager(tap_man);
}

nbi_impl::~nbi_impl() { nl->stop(); }

void nbi_impl::resend_state() noexcept { nl->resend_state(); }

void nbi_impl::register_switch(switch_interface *swi) noexcept {
  this->swi = swi;
  nl->register_switch(swi);
}

void nbi_impl::switch_state_notification(enum switch_state state) noexcept {
  switch (state) {
  case SWITCH_STATE_UP:
    nl->start();
    break;
  case SWITCH_STATE_DOWN:
  case SWITCH_STATE_FAILED:
  case SWITCH_STATE_UNKNOWN:
    nl->stop();
    break;
  default:
    LOG(FATAL) << __FUNCTION__ << ": invalid state";
    break;
  }
}

void nbi_impl::port_notification(
    std::deque<port_notification_data> &notifications) noexcept {

  for (auto &&ntfy : notifications) {
    switch (ntfy.ev) {
    case PORT_EVENT_MODIFY:
      switch (get_port_type(ntfy.port_id)) {
      case nbi::port_type_physical:
        LOG(INFO) << __FUNCTION__ << ": port state changed, continuing";
        break;
      default:
        LOG(ERROR) << __FUNCTION__ << ": unknown port";
        break;
      }
      break;
    case PORT_EVENT_ADD:
      switch (get_port_type(ntfy.port_id)) {
      case nbi::port_type_physical:
        if (tap_man->create_tapdev(ntfy.port_id, ntfy.name, *this) == -EEXIST) {
          LOG(INFO) << __FUNCTION__ << ": port already exists";
          break;
        }
        tap_man->change_port_status(ntfy.name, ntfy.status);
        break;
      case nbi::port_type_vxlan:
        // XXX TODO notify this?
        LOG(INFO) << __FUNCTION__ << ": port_type_vxlan added";
        break;
      default:
        LOG(ERROR) << __FUNCTION__ << ": unknown port";
        break;
      }
      break;
    case PORT_EVENT_DEL:
      switch (get_port_type(ntfy.port_id)) {
      case nbi::port_type_physical:
        tap_man->destroy_tapdev(ntfy.port_id, ntfy.name);
        break;
      case nbi::port_type_vxlan:
        // XXX TODO notify this?
        LOG(INFO) << __FUNCTION__ << ": port_type_vxlan removed";
        break;
      default:
        LOG(ERROR) << __FUNCTION__ << ": unknown port";
        break;
      }
      break;
    default:
      break;
    }
  }
}

int nbi_impl::enqueue_to_switch(uint32_t port_id, basebox::packet *packet) {
  swi->enqueue(port_id, packet);
  return 0;
}

int nbi_impl::enqueue(uint32_t port_id, basebox::packet *pkt) noexcept {
  int rv = 0;
  assert(pkt);
  try {
    // detour via netlink to learn the source mac
    int fd = tap_man->get_fd(port_id);
    nl->learn_l2(port_id, fd, pkt);
  } catch (std::exception &e) {
    LOG(ERROR) << __FUNCTION__
               << ": failed to enqueue packet for port_id=" << port_id << ": "
               << e.what();
    std::free(pkt);
    rv = -1;
  }
  return rv;
}

int nbi_impl::fdb_timeout(uint32_t port_id, uint16_t vid,
                          const rofl::caddress_ll &mac) noexcept {
  nl->fdb_timeout(port_id, vid, mac);
  return 0;
}

} // namespace basebox
<commit_msg>nbi_impl: start netlink handling as early as possible<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include <glog/logging.h>

#include "cnetlink.h"
#include "nbi_impl.h"
#include "tap_manager.h"

#include "netlink/ctapdev.h"
#include "utils/utils.h"

namespace basebox {

nbi_impl::nbi_impl(std::shared_ptr<cnetlink> nl,
                   std::shared_ptr<tap_manager> tap_man)
    : nl(nl), tap_man(tap_man) {
  nl->set_tapmanager(tap_man);
  nl->start();
}

nbi_impl::~nbi_impl() { nl->stop(); }

void nbi_impl::resend_state() noexcept { nl->resend_state(); }

void nbi_impl::register_switch(switch_interface *swi) noexcept {
  this->swi = swi;
  nl->register_switch(swi);
}

void nbi_impl::switch_state_notification(enum switch_state state) noexcept {
  switch (state) {
  case SWITCH_STATE_UP:
  case SWITCH_STATE_DOWN:
  case SWITCH_STATE_FAILED:
  case SWITCH_STATE_UNKNOWN:
    break;
  default:
    LOG(FATAL) << __FUNCTION__ << ": invalid state";
    break;
  }
}

void nbi_impl::port_notification(
    std::deque<port_notification_data> &notifications) noexcept {

  for (auto &&ntfy : notifications) {
    switch (ntfy.ev) {
    case PORT_EVENT_MODIFY:
      switch (get_port_type(ntfy.port_id)) {
      case nbi::port_type_physical:
        LOG(INFO) << __FUNCTION__ << ": port state changed, continuing";
        break;
      default:
        LOG(ERROR) << __FUNCTION__ << ": unknown port";
        break;
      }
      break;
    case PORT_EVENT_ADD:
      switch (get_port_type(ntfy.port_id)) {
      case nbi::port_type_physical:
        if (tap_man->create_tapdev(ntfy.port_id, ntfy.name, *this) == -EEXIST) {
          LOG(INFO) << __FUNCTION__ << ": port already exists";
          break;
        }
        tap_man->change_port_status(ntfy.name, ntfy.status);
        break;
      case nbi::port_type_vxlan:
        // XXX TODO notify this?
        LOG(INFO) << __FUNCTION__ << ": port_type_vxlan added";
        break;
      default:
        LOG(ERROR) << __FUNCTION__ << ": unknown port";
        break;
      }
      break;
    case PORT_EVENT_DEL:
      switch (get_port_type(ntfy.port_id)) {
      case nbi::port_type_physical:
        tap_man->destroy_tapdev(ntfy.port_id, ntfy.name);
        break;
      case nbi::port_type_vxlan:
        // XXX TODO notify this?
        LOG(INFO) << __FUNCTION__ << ": port_type_vxlan removed";
        break;
      default:
        LOG(ERROR) << __FUNCTION__ << ": unknown port";
        break;
      }
      break;
    default:
      break;
    }
  }
}

int nbi_impl::enqueue_to_switch(uint32_t port_id, basebox::packet *packet) {
  swi->enqueue(port_id, packet);
  return 0;
}

int nbi_impl::enqueue(uint32_t port_id, basebox::packet *pkt) noexcept {
  int rv = 0;
  assert(pkt);
  try {
    // detour via netlink to learn the source mac
    int fd = tap_man->get_fd(port_id);
    nl->learn_l2(port_id, fd, pkt);
  } catch (std::exception &e) {
    LOG(ERROR) << __FUNCTION__
               << ": failed to enqueue packet for port_id=" << port_id << ": "
               << e.what();
    std::free(pkt);
    rv = -1;
  }
  return rv;
}

int nbi_impl::fdb_timeout(uint32_t port_id, uint16_t vid,
                          const rofl::caddress_ll &mac) noexcept {
  nl->fdb_timeout(port_id, vid, mac);
  return 0;
}

} // namespace basebox
<|endoftext|>


<commit_before>/**
 * Copyright (c) 2011-2018 libbitcoin developers (see AUTHORS)
 *
 * This file is part of libbitcoin.
 *
 * libbitcoin is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License with
 * additional permissions to the one published by the Free Software
 * Foundation, either version 3 of the License, or (at your option)
 * any later version. For more information see LICENSE.
 *
 * 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
#include <bitcoin/bitcoin/network/channel.hpp>

#include <bitcoin/bitcoin/network/authority.hpp>
#include <bitcoin/bitcoin/network/channel_proxy.hpp>
#include <bitcoin/bitcoin/primitives.hpp>

namespace libbitcoin {
namespace network {

channel::channel(channel_proxy_ptr proxy)
  : weak_proxy_(proxy)
{
}

channel::~channel()
{
    stop();
}

void channel::stop() const
{
    const auto proxy = weak_proxy_.lock();
    if (proxy)
        proxy->stop();
}

bool channel::stopped() const
{
    const auto proxy = weak_proxy_.lock();
    if (proxy)
        return proxy->stopped();

    return true;
}

authority channel::address() const
{
    const auto proxy = weak_proxy_.lock();
    if (proxy)
        return proxy->address();

    return address();
}

void channel::send_raw(const header_type& packet_header,
    const data_chunk& payload, channel_proxy::send_handler handle_send)
{
    const auto proxy = weak_proxy_.lock();
    if (proxy)
        proxy->send_raw(packet_header, payload, handle_send);
    else
        handle_send(error::service_stopped);
}

void channel::subscribe_version(
    channel_proxy::receive_version_handler handle_receive)
{
    const auto proxy = weak_proxy_.lock();
    if (proxy)
        proxy->subscribe_version(handle_receive);
    else
        handle_receive(error::service_stopped, version_type());
}

void channel::subscribe_verack(
    channel_proxy::receive_verack_handler handle_receive)
{
    const auto proxy = weak_proxy_.lock();
    if (proxy)
        proxy->subscribe_verack(handle_receive);
    else
        handle_receive(error::service_stopped, verack_type());
}

void channel::subscribe_address(
    channel_proxy::receive_address_handler handle_receive)
{
    const auto proxy = weak_proxy_.lock();
    if (proxy)
        proxy->subscribe_address(handle_receive);
    else
        handle_receive(error::service_stopped, address_type());
}

void channel::subscribe_get_address(
    channel_proxy::receive_get_address_handler handle_receive)
{
    const auto proxy = weak_proxy_.lock();
    if (proxy)
        proxy->subscribe_get_address(handle_receive);
    else
        handle_receive(error::service_stopped, get_address_type());
}

void channel::subscribe_inventory(
    channel_proxy::receive_inventory_handler handle_receive)
{
    const auto proxy = weak_proxy_.lock();
    if (proxy)
        proxy->subscribe_inventory(handle_receive);
    else
        handle_receive(error::service_stopped, inventory_type());
}

void channel::subscribe_get_data(
    channel_proxy::receive_get_data_handler handle_receive)
{
    const auto proxy = weak_proxy_.lock();
    if (proxy)
        proxy->subscribe_get_data(handle_receive);
    else
        handle_receive(error::service_stopped, get_data_type());
}

void channel::subscribe_get_blocks(
    channel_proxy::receive_get_blocks_handler handle_receive)
{
    const auto proxy = weak_proxy_.lock();
    if (proxy)
        proxy->subscribe_get_blocks(handle_receive);
    else
        handle_receive(error::service_stopped, get_blocks_type());
}

void channel::subscribe_transaction(
    channel_proxy::receive_transaction_handler handle_receive)
{
    const auto proxy = weak_proxy_.lock();
    if (proxy)
        proxy->subscribe_transaction(handle_receive);
    else
        handle_receive(error::service_stopped, transaction_type());
}

void channel::subscribe_block(
    channel_proxy::receive_block_handler handle_receive)
{
    const auto proxy = weak_proxy_.lock();
    if (proxy)
        proxy->subscribe_block(handle_receive);
    else
        handle_receive(error::service_stopped, block_type());
}

void channel::subscribe_raw(
    channel_proxy::receive_raw_handler handle_receive)
{
    const auto proxy = weak_proxy_.lock();
    if (proxy)
        proxy->subscribe_raw(handle_receive);
    else
        handle_receive(error::service_stopped, header_type(), data_chunk());
}

void channel::subscribe_stop(
    channel_proxy::stop_handler handle_stop)
{
    const auto proxy = weak_proxy_.lock();
    if (proxy)
        proxy->subscribe_stop(handle_stop);
    else
        handle_stop(error::service_stopped);
}

} // namespace network
} // namespace libbitcoin
<commit_msg>Oops, fix infinite recursion from partially-applied coincidental name change.<commit_after>/**
 * Copyright (c) 2011-2018 libbitcoin developers (see AUTHORS)
 *
 * This file is part of libbitcoin.
 *
 * libbitcoin is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License with
 * additional permissions to the one published by the Free Software
 * Foundation, either version 3 of the License, or (at your option)
 * any later version. For more information see LICENSE.
 *
 * 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
#include <bitcoin/bitcoin/network/channel.hpp>

#include <bitcoin/bitcoin/network/authority.hpp>
#include <bitcoin/bitcoin/network/channel_proxy.hpp>
#include <bitcoin/bitcoin/primitives.hpp>

namespace libbitcoin {
namespace network {

channel::channel(channel_proxy_ptr proxy)
  : weak_proxy_(proxy)
{
}

channel::~channel()
{
    stop();
}

void channel::stop() const
{
    const auto proxy = weak_proxy_.lock();
    if (proxy)
        proxy->stop();
}

bool channel::stopped() const
{
    const auto proxy = weak_proxy_.lock();
    if (proxy)
        return proxy->stopped();

    return true;
}

authority channel::address() const
{
    const auto proxy = weak_proxy_.lock();
    if (proxy)
        return proxy->address();

    return authority();
}

void channel::send_raw(const header_type& packet_header,
    const data_chunk& payload, channel_proxy::send_handler handle_send)
{
    const auto proxy = weak_proxy_.lock();
    if (proxy)
        proxy->send_raw(packet_header, payload, handle_send);
    else
        handle_send(error::service_stopped);
}

void channel::subscribe_version(
    channel_proxy::receive_version_handler handle_receive)
{
    const auto proxy = weak_proxy_.lock();
    if (proxy)
        proxy->subscribe_version(handle_receive);
    else
        handle_receive(error::service_stopped, version_type());
}

void channel::subscribe_verack(
    channel_proxy::receive_verack_handler handle_receive)
{
    const auto proxy = weak_proxy_.lock();
    if (proxy)
        proxy->subscribe_verack(handle_receive);
    else
        handle_receive(error::service_stopped, verack_type());
}

void channel::subscribe_address(
    channel_proxy::receive_address_handler handle_receive)
{
    const auto proxy = weak_proxy_.lock();
    if (proxy)
        proxy->subscribe_address(handle_receive);
    else
        handle_receive(error::service_stopped, address_type());
}

void channel::subscribe_get_address(
    channel_proxy::receive_get_address_handler handle_receive)
{
    const auto proxy = weak_proxy_.lock();
    if (proxy)
        proxy->subscribe_get_address(handle_receive);
    else
        handle_receive(error::service_stopped, get_address_type());
}

void channel::subscribe_inventory(
    channel_proxy::receive_inventory_handler handle_receive)
{
    const auto proxy = weak_proxy_.lock();
    if (proxy)
        proxy->subscribe_inventory(handle_receive);
    else
        handle_receive(error::service_stopped, inventory_type());
}

void channel::subscribe_get_data(
    channel_proxy::receive_get_data_handler handle_receive)
{
    const auto proxy = weak_proxy_.lock();
    if (proxy)
        proxy->subscribe_get_data(handle_receive);
    else
        handle_receive(error::service_stopped, get_data_type());
}

void channel::subscribe_get_blocks(
    channel_proxy::receive_get_blocks_handler handle_receive)
{
    const auto proxy = weak_proxy_.lock();
    if (proxy)
        proxy->subscribe_get_blocks(handle_receive);
    else
        handle_receive(error::service_stopped, get_blocks_type());
}

void channel::subscribe_transaction(
    channel_proxy::receive_transaction_handler handle_receive)
{
    const auto proxy = weak_proxy_.lock();
    if (proxy)
        proxy->subscribe_transaction(handle_receive);
    else
        handle_receive(error::service_stopped, transaction_type());
}

void channel::subscribe_block(
    channel_proxy::receive_block_handler handle_receive)
{
    const auto proxy = weak_proxy_.lock();
    if (proxy)
        proxy->subscribe_block(handle_receive);
    else
        handle_receive(error::service_stopped, block_type());
}

void channel::subscribe_raw(
    channel_proxy::receive_raw_handler handle_receive)
{
    const auto proxy = weak_proxy_.lock();
    if (proxy)
        proxy->subscribe_raw(handle_receive);
    else
        handle_receive(error::service_stopped, header_type(), data_chunk());
}

void channel::subscribe_stop(
    channel_proxy::stop_handler handle_stop)
{
    const auto proxy = weak_proxy_.lock();
    if (proxy)
        proxy->subscribe_stop(handle_stop);
    else
        handle_stop(error::service_stopped);
}

} // namespace network
} // namespace libbitcoin
<|endoftext|>


<commit_before>// @(#)root/qtgsi:$Id$
// Author: Denis Bertini, M. Al-Turany  01/11/2000

/*************************************************************************
 * Copyright (C) 1995-2006, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#include "Riostream.h"
#include "qevent.h"
#include "qdialog.h"
#include "qpushbutton.h"
#include "qlabel.h"
#include "qpainter.h"
#if  (QT_VERSION > 0x039999) // Added by cholm@nbi.dk - for Qt 4
# include "qmenu.h"
# include "q3popupmenu.h"
typedef Q3PopupMenu QPopupMenu;
#else
# include "qpopupmenu.h"
#endif

#include "TQCanvasMenu.h"
#include "TClass.h"
#include "TROOT.h"
#include "TMethod.h"
#include "TMethodCall.h"
#include "TMethodArg.h"
#include "TCanvas.h"
#include "TDataType.h"
#include "TQRootDialog.h"

ClassImp(TQCanvasMenu)

//______________________________________________________________________________
TQCanvasMenu::TQCanvasMenu(QWidget* parent, TCanvas *canvas)
{
   // ctor, create the popup menu

   fc       = canvas;
   fPopup   = new QPopupMenu;
   fCurrObj = 0;
   fParent  = parent;
   fTabWin  = 0;
   fDialog  = 0;
   fMousePosX = fMousePosY = 0;
}

//______________________________________________________________________________
TQCanvasMenu::TQCanvasMenu(QWidget* parent, QWidget *tabWin, TCanvas *canvas)
{
   // ctor, create the popup menu

   fc       = canvas;
   fPopup   = new QPopupMenu;
   fParent  = parent;
   fTabWin  = tabWin;
   fCurrObj = 0;
   fDialog  = 0;
   fMousePosX = fMousePosY = 0;
}

//______________________________________________________________________________
TQCanvasMenu::~TQCanvasMenu()
{
   // dtor

   if (fPopup) delete fPopup;
}

//______________________________________________________________________________
char *TQCanvasMenu::CreateDialogTitle( TObject *object, TMethod *method )
{
   // Create title for dialog box retrieving argument values.

   static char methodTitle[128];

   if (object && method)
      snprintf(methodTitle, 127, "%s::%s", object->ClassName(), method->GetName());
   else
      *methodTitle = 0;
   return methodTitle;

}

//______________________________________________________________________________
char *TQCanvasMenu::CreateArgumentTitle(TMethodArg *argument)
{
   // Create string describing argument (for use in dialog box).

   static Char_t argTitle[128];
   if (argument) {
      snprintf(argTitle, 127, "(%s)  %s", argument->GetTitle(), argument->GetName());
      const char *arg_def = argument->GetDefault();
      if (arg_def && *arg_def) {
         strncat(argTitle, "  [default: ", 127 - strlen(argTitle));
         strncat(argTitle, arg_def, 127 - strlen(argTitle));
         strncat(argTitle, "]", 127 - strlen(argTitle));
      }
   }
   else
      *argTitle = 0;

   return argTitle;
}

//______________________________________________________________________________
void TQCanvasMenu::Popup(TObject *obj, double x, double y, QMouseEvent *e)
{
   // Perform the corresponding selected TObject  popup
   // in the position defined
   // by x, y coordinates (in user coordinate system).
   // @param obj (TObject*)
   // @param p (QPoint&)

   TClass *klass=obj->IsA();
   Int_t curId=-1;

   fCurrObj=obj;
   fPopup->clear();
   fMethods.Clear();

   QString buffer=klass->GetName();
   buffer+="::";
   buffer+=obj->GetName();
   fPopup->insertItem(buffer, this, SLOT( Execute(int) ), 0,curId); curId++;
   klass->GetMenuItems(&fMethods);
   fPopup->insertSeparator();
   TIter iter(&fMethods);
   TMethod *method=0;
   while ( (method = dynamic_cast<TMethod*>(iter())) != 0) {
      buffer=method->GetName();
      fPopup->insertItem(buffer, this, SLOT( Execute(int) ), 0,curId);
      curId++;
   }
   // hold the position where the mouse was clicked
   fMousePosX= x;
   fMousePosY= y;

   // let Qt decide how to draw the popup Menu otherwise we have a problem that
   // the visible rectangle can get outside the screen (M.T. 03.06.02)
   fPopup->popup(e->globalPos(), 0);

}

//______________________________________________________________________________
void TQCanvasMenu::Execute(int id)
{
   // Slot defined to execute a method from a selected TObject
   // using TObject::Execute() function.

   QString text="";

   TVirtualPad  *psave = gROOT->GetSelectedPad();
   TMethod *method=(TMethod *)fMethods.At(id);
   fc->HandleInput(kButton3Up,gPad->XtoAbsPixel(fMousePosX), gPad->YtoAbsPixel(fMousePosY) );
   if (  method->GetListOfMethodArgs()->First() ) {
      Dialog(fCurrObj,method);
   }
   else {
      gROOT->SetFromPopUp(kTRUE);
      fCurrObj->Execute((char *) method->GetName(), "");
   }
   fc->GetPadSave()->Update();
   fc->GetPadSave()->Modified();
   gROOT->SetSelectedPad(psave);
   gROOT->GetSelectedPad()->Update();
   gROOT->GetSelectedPad()->Modified();
   fc->Modified();
   fc->ForceUpdate();
   gROOT->SetFromPopUp( kFALSE );
}

//______________________________________________________________________________
void TQCanvasMenu::Dialog(TObject* object, TMethod* method)
{
   // Create dialog object with OK and Cancel buttons. This dialog
   // prompts for the arguments of "method".

   if (!(object && method)) return;
   fDialog = new TQRootDialog(fParent,CreateDialogTitle(object, method),0,object ,method);
   fDialog->SetTCanvas(fc);
   // iterate through all arguments and create apropriate input-data objects:
   // inputlines, option menus...
   TMethodArg *argument = 0;
   TIter next(method->GetListOfMethodArgs());
   while ((argument = (TMethodArg *) next())) {
      char       *argname    = CreateArgumentTitle(argument);
      const char *type       = argument->GetTypeName();
      TDataType    *datatype   = gROOT->GetType(type);
      const char *charstar   = "char*";
      char        basictype [32];

      if (datatype) {
         strlcpy(basictype, datatype->GetTypeName(),32);
      }
      else {
         if (strncmp(type, "enum", 4) != 0)
         cout << "*** Warning in Dialog(): data type is not basic type, assuming (int)\n";
         strcpy(basictype, "int");
      }

      if (strchr(argname, '*')) {
         strcat(basictype, "*");
         type = charstar;
      }

      TDataMember *m = argument->GetDataMember();
      if (m && m->GetterMethod()) {
         char gettername[256] = "";
         strlcpy(gettername, m->GetterMethod()->GetMethodName(),256);
         m->GetterMethod()->Init(object->IsA(), gettername, "");
         // Get the current value and form it as a text:
         char val[256];
         if (!strncmp(basictype, "char*", 5)) {
            char *tdefval;
            m->GetterMethod()->Execute(object, "", &tdefval);
            strlcpy(val, tdefval, 256);
         }
         else if (!strncmp(basictype, "float", 5) ||
            !strncmp(basictype, "double", 6)) {
            Double_t ddefval;
            m->GetterMethod()->Execute(object, "", ddefval);
            snprintf(val, 255, "%g", ddefval);
         }
         else if (!strncmp(basictype, "char", 4) ||
             !strncmp(basictype, "int", 3)  ||
             !strncmp(basictype, "long", 4) ||
             !strncmp(basictype, "short", 5)) {
            Long_t ldefval;
            m->GetterMethod()->Execute(object, "", ldefval);
            snprintf(val, 255, "%li", ldefval);
         }
         // Find out whether we have options ...
         TList *opt;
         if ((opt = m->GetOptions())) {
            cout << "*** Warning in Dialog(): option menu not yet implemented " << opt << endl;
            // should stop dialog
            return;
         }
         else {
            // we haven't got options - textfield ...
            fDialog->Add(argname, val, type);
         }
      }
      else {    // if m not found ...
         char val[256] = "";
         const char *tval = argument->GetDefault();
         if (tval) strlcpy(val, tval, 256);
         fDialog->Add(argname, val, type);
      }
   } //end while

   fDialog->Popup();
}
<commit_msg>Fix coverity reports #32499 & #32500 (uninitialized scalar variables)<commit_after>// @(#)root/qtgsi:$Id$
// Author: Denis Bertini, M. Al-Turany  01/11/2000

/*************************************************************************
 * Copyright (C) 1995-2006, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#include "Riostream.h"
#include "qevent.h"
#include "qdialog.h"
#include "qpushbutton.h"
#include "qlabel.h"
#include "qpainter.h"
#if  (QT_VERSION > 0x039999) // Added by cholm@nbi.dk - for Qt 4
# include "qmenu.h"
# include "q3popupmenu.h"
typedef Q3PopupMenu QPopupMenu;
#else
# include "qpopupmenu.h"
#endif

#include "TQCanvasMenu.h"
#include "TClass.h"
#include "TROOT.h"
#include "TMethod.h"
#include "TMethodCall.h"
#include "TMethodArg.h"
#include "TCanvas.h"
#include "TDataType.h"
#include "TQRootDialog.h"

ClassImp(TQCanvasMenu)

//______________________________________________________________________________
TQCanvasMenu::TQCanvasMenu(QWidget* parent, TCanvas *canvas)
{
   // ctor, create the popup menu

   fc       = canvas;
   fPopup   = new QPopupMenu;
   fCurrObj = 0;
   fParent  = parent;
   fTabWin  = 0;
   fDialog  = 0;
   fMousePosX = fMousePosY = 0;
}

//______________________________________________________________________________
TQCanvasMenu::TQCanvasMenu(QWidget* parent, QWidget *tabWin, TCanvas *canvas)
{
   // ctor, create the popup menu

   fc       = canvas;
   fPopup   = new QPopupMenu;
   fParent  = parent;
   fTabWin  = tabWin;
   fCurrObj = 0;
   fDialog  = 0;
   fMousePosX = fMousePosY = 0;
}

//______________________________________________________________________________
TQCanvasMenu::~TQCanvasMenu()
{
   // dtor

   if (fPopup) delete fPopup;
}

//______________________________________________________________________________
char *TQCanvasMenu::CreateDialogTitle( TObject *object, TMethod *method )
{
   // Create title for dialog box retrieving argument values.

   static char methodTitle[128];

   if (object && method)
      snprintf(methodTitle, 127, "%s::%s", object->ClassName(), method->GetName());
   else
      *methodTitle = 0;
   return methodTitle;

}

//______________________________________________________________________________
char *TQCanvasMenu::CreateArgumentTitle(TMethodArg *argument)
{
   // Create string describing argument (for use in dialog box).

   static Char_t argTitle[128];
   if (argument) {
      snprintf(argTitle, 127, "(%s)  %s", argument->GetTitle(), argument->GetName());
      const char *arg_def = argument->GetDefault();
      if (arg_def && *arg_def) {
         strncat(argTitle, "  [default: ", 127 - strlen(argTitle));
         strncat(argTitle, arg_def, 127 - strlen(argTitle));
         strncat(argTitle, "]", 127 - strlen(argTitle));
      }
   }
   else
      *argTitle = 0;

   return argTitle;
}

//______________________________________________________________________________
void TQCanvasMenu::Popup(TObject *obj, double x, double y, QMouseEvent *e)
{
   // Perform the corresponding selected TObject  popup
   // in the position defined
   // by x, y coordinates (in user coordinate system).
   // @param obj (TObject*)
   // @param p (QPoint&)

   TClass *klass=obj->IsA();
   Int_t curId=-1;

   fCurrObj=obj;
   fPopup->clear();
   fMethods.Clear();

   QString buffer=klass->GetName();
   buffer+="::";
   buffer+=obj->GetName();
   fPopup->insertItem(buffer, this, SLOT( Execute(int) ), 0,curId); curId++;
   klass->GetMenuItems(&fMethods);
   fPopup->insertSeparator();
   TIter iter(&fMethods);
   TMethod *method=0;
   while ( (method = dynamic_cast<TMethod*>(iter())) != 0) {
      buffer=method->GetName();
      fPopup->insertItem(buffer, this, SLOT( Execute(int) ), 0,curId);
      curId++;
   }
   // hold the position where the mouse was clicked
   fMousePosX= x;
   fMousePosY= y;

   // let Qt decide how to draw the popup Menu otherwise we have a problem that
   // the visible rectangle can get outside the screen (M.T. 03.06.02)
   fPopup->popup(e->globalPos(), 0);

}

//______________________________________________________________________________
void TQCanvasMenu::Execute(int id)
{
   // Slot defined to execute a method from a selected TObject
   // using TObject::Execute() function.

   QString text="";

   TVirtualPad  *psave = gROOT->GetSelectedPad();
   TMethod *method=(TMethod *)fMethods.At(id);
   fc->HandleInput(kButton3Up,gPad->XtoAbsPixel(fMousePosX), gPad->YtoAbsPixel(fMousePosY) );
   if (  method->GetListOfMethodArgs()->First() ) {
      Dialog(fCurrObj,method);
   }
   else {
      gROOT->SetFromPopUp(kTRUE);
      fCurrObj->Execute((char *) method->GetName(), "");
   }
   fc->GetPadSave()->Update();
   fc->GetPadSave()->Modified();
   gROOT->SetSelectedPad(psave);
   gROOT->GetSelectedPad()->Update();
   gROOT->GetSelectedPad()->Modified();
   fc->Modified();
   fc->ForceUpdate();
   gROOT->SetFromPopUp( kFALSE );
}

//______________________________________________________________________________
void TQCanvasMenu::Dialog(TObject* object, TMethod* method)
{
   // Create dialog object with OK and Cancel buttons. This dialog
   // prompts for the arguments of "method".

   if (!(object && method)) return;
   fDialog = new TQRootDialog(fParent,CreateDialogTitle(object, method),0,object ,method);
   fDialog->SetTCanvas(fc);
   // iterate through all arguments and create apropriate input-data objects:
   // inputlines, option menus...
   TMethodArg *argument = 0;
   TIter next(method->GetListOfMethodArgs());
   while ((argument = (TMethodArg *) next())) {
      char       *argname    = CreateArgumentTitle(argument);
      const char *type       = argument->GetTypeName();
      TDataType    *datatype   = gROOT->GetType(type);
      const char *charstar   = "char*";
      char        basictype [32];

      if (datatype) {
         strlcpy(basictype, datatype->GetTypeName(),32);
      }
      else {
         if (strncmp(type, "enum", 4) != 0)
         cout << "*** Warning in Dialog(): data type is not basic type, assuming (int)\n";
         strcpy(basictype, "int");
      }

      if (strchr(argname, '*')) {
         strcat(basictype, "*");
         type = charstar;
      }

      TDataMember *m = argument->GetDataMember();
      if (m && m->GetterMethod()) {
         char gettername[256] = "";
         strlcpy(gettername, m->GetterMethod()->GetMethodName(),256);
         m->GetterMethod()->Init(object->IsA(), gettername, "");
         // Get the current value and form it as a text:
         char val[256];
         if (!strncmp(basictype, "char*", 5)) {
            char *tdefval;
            m->GetterMethod()->Execute(object, "", &tdefval);
            strlcpy(val, tdefval, 256);
         }
         else if (!strncmp(basictype, "float", 5) ||
            !strncmp(basictype, "double", 6)) {
            Double_t ddefval = 0.0;
            m->GetterMethod()->Execute(object, "", ddefval);
            snprintf(val, 255, "%g", ddefval);
         }
         else if (!strncmp(basictype, "char", 4) ||
             !strncmp(basictype, "int", 3)  ||
             !strncmp(basictype, "long", 4) ||
             !strncmp(basictype, "short", 5)) {
            Long_t ldefval = 0L;
            m->GetterMethod()->Execute(object, "", ldefval);
            snprintf(val, 255, "%li", ldefval);
         }
         // Find out whether we have options ...
         TList *opt;
         if ((opt = m->GetOptions())) {
            cout << "*** Warning in Dialog(): option menu not yet implemented " << opt << endl;
            // should stop dialog
            return;
         }
         else {
            // we haven't got options - textfield ...
            fDialog->Add(argname, val, type);
         }
      }
      else {    // if m not found ...
         char val[256] = "";
         const char *tval = argument->GetDefault();
         if (tval) strlcpy(val, tval, 256);
         fDialog->Add(argname, val, type);
      }
   } //end while

   fDialog->Popup();
}
<|endoftext|>