<commit_before>// Copyright (c) 2010 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 "base/message_loop.h"
#include "base/scoped_ptr.h"
#include "base/utf_string_conversions.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/base/clipboard/clipboard.h"
#include "ui/base/clipboard/scoped_clipboard_writer.h"
#include "views/controls/textfield/textfield_views_model.h"
#include "views/test/test_views_delegate.h"
#include "views/views_delegate.h"

namespace views {

#define EXPECT_STR_EQ(ascii, utf16) \
  EXPECT_EQ(ASCIIToWide(ascii), UTF16ToWide(utf16))

TEST(TextfieldViewsModelTest, EditString) {
  TextfieldViewsModel model;
  // append two strings
  model.Append(ASCIIToUTF16("HILL"));
  EXPECT_STR_EQ("HILL", model.text());
  model.Append(ASCIIToUTF16("WORLD"));
  EXPECT_STR_EQ("HILLWORLD", model.text());

  // Insert "E" to make hello
  model.MoveCursorRight(false);
  model.Insert('E');
  EXPECT_STR_EQ("HEILLWORLD", model.text());
  // Replace "I" with "L"
  model.Replace('L');
  EXPECT_STR_EQ("HELLLWORLD", model.text());
  model.Replace('L');
  model.Replace('O');
  EXPECT_STR_EQ("HELLOWORLD", model.text());

  // Delete 6th char "W", then delete 5th char O"
  EXPECT_EQ(5U, model.cursor_pos());
  EXPECT_TRUE(model.Delete());
  EXPECT_STR_EQ("HELLOORLD", model.text());
  EXPECT_TRUE(model.Backspace());
  EXPECT_EQ(4U, model.cursor_pos());
  EXPECT_STR_EQ("HELLORLD", model.text());

  // Move the cursor to start. backspace should fail.
  model.MoveCursorToStart(false);
  EXPECT_FALSE(model.Backspace());
  EXPECT_STR_EQ("HELLORLD", model.text());
  // Move the cursor to the end. delete should fail.
  model.MoveCursorToEnd(false);
  EXPECT_FALSE(model.Delete());
  EXPECT_STR_EQ("HELLORLD", model.text());
  // but backspace should work.
  EXPECT_TRUE(model.Backspace());
  EXPECT_STR_EQ("HELLORL", model.text());
}

TEST(TextfieldViewsModelTest, EmptyString) {
  TextfieldViewsModel model;
  EXPECT_EQ(string16(), model.text());
  EXPECT_EQ(string16(), model.GetSelectedText());
  EXPECT_EQ(string16(), model.GetVisibleText());

  model.MoveCursorLeft(true);
  EXPECT_EQ(0U, model.cursor_pos());
  model.MoveCursorRight(true);
  EXPECT_EQ(0U, model.cursor_pos());

  EXPECT_EQ(string16(), model.GetSelectedText());

  EXPECT_FALSE(model.Delete());
  EXPECT_FALSE(model.Backspace());
}

TEST(TextfieldViewsModelTest, Selection) {
  TextfieldViewsModel model;
  model.Append(ASCIIToUTF16("HELLO"));
  model.MoveCursorRight(false);
  model.MoveCursorRight(true);
  EXPECT_STR_EQ("E", model.GetSelectedText());
  model.MoveCursorRight(true);
  EXPECT_STR_EQ("EL", model.GetSelectedText());

  model.MoveCursorToStart(true);
  EXPECT_STR_EQ("H", model.GetSelectedText());
  model.MoveCursorToEnd(true);
  EXPECT_STR_EQ("ELLO", model.GetSelectedText());
  model.ClearSelection();
  EXPECT_EQ(string16(), model.GetSelectedText());
  model.SelectAll();
  EXPECT_STR_EQ("HELLO", model.GetSelectedText());

  // Select and move cursor
  model.MoveCursorTo(1U, false);
  model.MoveCursorTo(3U, true);
  EXPECT_STR_EQ("EL", model.GetSelectedText());
  model.MoveCursorLeft(false);
  EXPECT_EQ(1U, model.cursor_pos());
  model.MoveCursorTo(1U, false);
  model.MoveCursorTo(3U, true);
  model.MoveCursorRight(false);
  EXPECT_EQ(3U, model.cursor_pos());

  // Select all and move cursor
  model.SelectAll();
  model.MoveCursorLeft(false);
  EXPECT_EQ(0U, model.cursor_pos());
  model.SelectAll();
  model.MoveCursorRight(false);
  EXPECT_EQ(5U, model.cursor_pos());
}

TEST(TextfieldViewsModelTest, SelectionAndEdit) {
  TextfieldViewsModel model;
  model.Append(ASCIIToUTF16("HELLO"));
  model.MoveCursorRight(false);
  model.MoveCursorRight(true);
  model.MoveCursorRight(true);  // select "EL"
  EXPECT_TRUE(model.Backspace());
  EXPECT_STR_EQ("HLO", model.text());

  model.Append(ASCIIToUTF16("ILL"));
  model.MoveCursorRight(true);
  model.MoveCursorRight(true);  // select "LO"
  EXPECT_TRUE(model.Delete());
  EXPECT_STR_EQ("HILL", model.text());
  EXPECT_EQ(1U, model.cursor_pos());
  model.MoveCursorRight(true);  // select "I"
  model.Insert('E');
  EXPECT_STR_EQ("HELL", model.text());
  model.MoveCursorToStart(false);
  model.MoveCursorRight(true);  // select "H"
  model.Replace('B');
  EXPECT_STR_EQ("BELL", model.text());
  model.MoveCursorToEnd(false);
  model.MoveCursorLeft(true);
  model.MoveCursorLeft(true);  // select ">LL"
  model.Replace('E');
  EXPECT_STR_EQ("BEE", model.text());
}

TEST(TextfieldViewsModelTest, Password) {
  TextfieldViewsModel model;
  model.set_is_password(true);
  model.Append(ASCIIToUTF16("HELLO"));
  EXPECT_STR_EQ("*****", model.GetVisibleText());
  EXPECT_STR_EQ("HELLO", model.text());
  EXPECT_TRUE(model.Delete());

  EXPECT_STR_EQ("****", model.GetVisibleText());
  EXPECT_STR_EQ("ELLO", model.text());
  EXPECT_EQ(0U, model.cursor_pos());

  model.SelectAll();
  EXPECT_STR_EQ("ELLO", model.GetSelectedText());
  EXPECT_EQ(0U, model.cursor_pos());

  model.Insert('X');
  EXPECT_STR_EQ("*", model.GetVisibleText());
  EXPECT_STR_EQ("X", model.text());
}

TEST(TextfieldViewsModelTest, Word) {
  TextfieldViewsModel model;
  model.Append(
      ASCIIToUTF16("The answer to Life, the Universe, and Everything"));
  model.MoveCursorToNextWord(false);
  EXPECT_EQ(3U, model.cursor_pos());
  model.MoveCursorToNextWord(false);
  EXPECT_EQ(10U, model.cursor_pos());
  model.MoveCursorToNextWord(false);
  model.MoveCursorToNextWord(false);
  EXPECT_EQ(18U, model.cursor_pos());

  // Should passes the non word char ','
  model.MoveCursorToNextWord(true);
  EXPECT_EQ(23U, model.cursor_pos());
  EXPECT_STR_EQ(", the", model.GetSelectedText());

  // Move to the end.
  model.MoveCursorToNextWord(true);
  model.MoveCursorToNextWord(true);
  model.MoveCursorToNextWord(true);
  EXPECT_STR_EQ(", the Universe, and Everything", model.GetSelectedText());
  // Should be safe to go next word at the end.
  model.MoveCursorToNextWord(true);
  EXPECT_STR_EQ(", the Universe, and Everything", model.GetSelectedText());
  model.Insert('2');
  EXPECT_EQ(19U, model.cursor_pos());

  // Now backwards.
  model.MoveCursorLeft(false);  // leave 2.
  model.MoveCursorToPreviousWord(true);
  EXPECT_EQ(14U, model.cursor_pos());
  EXPECT_STR_EQ("Life", model.GetSelectedText());
  model.MoveCursorToPreviousWord(true);
  EXPECT_STR_EQ("to Life", model.GetSelectedText());
  model.MoveCursorToPreviousWord(true);
  model.MoveCursorToPreviousWord(true);
  model.MoveCursorToPreviousWord(true);  // Select to the begining.
  EXPECT_STR_EQ("The answer to Life", model.GetSelectedText());
  // Should be safe to go pervious word at the begining.
  model.MoveCursorToPreviousWord(true);
  EXPECT_STR_EQ("The answer to Life", model.GetSelectedText());
  model.Replace('4');
  EXPECT_EQ(string16(), model.GetSelectedText());
  EXPECT_STR_EQ("42", model.GetVisibleText());
}

TEST(TextfieldViewsModelTest, TextFragment) {
  TextfieldViewsModel model;
  TextfieldViewsModel::TextFragments fragments;
  // Empty string
  model.GetFragments(&fragments);
  EXPECT_EQ(1U, fragments.size());
  fragments.clear();
  EXPECT_EQ(0U, fragments[0].begin);
  EXPECT_EQ(0U, fragments[0].end);
  EXPECT_FALSE(fragments[0].selected);

  // Some string
  model.Append(ASCIIToUTF16("Hello world"));
  model.GetFragments(&fragments);
  EXPECT_EQ(1U, fragments.size());
  EXPECT_EQ(0U, fragments[0].begin);
  EXPECT_EQ(11U, fragments[0].end);
  EXPECT_FALSE(fragments[0].selected);

  // Select 1st word
  model.MoveCursorToNextWord(true);
  model.GetFragments(&fragments);
  EXPECT_EQ(2U, fragments.size());
  EXPECT_EQ(0U, fragments[0].begin);
  EXPECT_EQ(5U, fragments[0].end);
  EXPECT_TRUE(fragments[0].selected);
  EXPECT_EQ(5U, fragments[1].begin);
  EXPECT_EQ(11U, fragments[1].end);
  EXPECT_FALSE(fragments[1].selected);

  // Select empty string
  model.ClearSelection();
  model.MoveCursorRight(true);
  model.GetFragments(&fragments);
  EXPECT_EQ(3U, fragments.size());
  EXPECT_EQ(0U, fragments[0].begin);
  EXPECT_EQ(5U, fragments[0].end);
  EXPECT_FALSE(fragments[0].selected);
  EXPECT_EQ(5U, fragments[1].begin);
  EXPECT_EQ(6U, fragments[1].end);
  EXPECT_TRUE(fragments[1].selected);

  EXPECT_EQ(6U, fragments[2].begin);
  EXPECT_EQ(11U, fragments[2].end);
  EXPECT_FALSE(fragments[2].selected);

  // Select to the end.
  model.MoveCursorToEnd(true);
  model.GetFragments(&fragments);
  EXPECT_EQ(2U, fragments.size());
  EXPECT_EQ(0U, fragments[0].begin);
  EXPECT_EQ(5U, fragments[0].end);
  EXPECT_FALSE(fragments[0].selected);
  EXPECT_EQ(5U, fragments[1].begin);
  EXPECT_EQ(11U, fragments[1].end);
  EXPECT_TRUE(fragments[1].selected);
}

TEST(TextfieldViewsModelTest, SetText) {
  TextfieldViewsModel model;
  model.Append(ASCIIToUTF16("HELLO"));
  model.MoveCursorToEnd(false);
  model.SetText(ASCIIToUTF16("GOODBYE"));
  EXPECT_STR_EQ("GOODBYE", model.text());
  EXPECT_EQ(5U, model.cursor_pos());
  model.SelectAll();
  EXPECT_STR_EQ("GOODBYE", model.GetSelectedText());
  // Selection move the current pos to the begining.
  EXPECT_EQ(0U, model.cursor_pos());
  model.MoveCursorToEnd(false);
  EXPECT_EQ(7U, model.cursor_pos());

  model.SetText(ASCIIToUTF16("BYE"));
  EXPECT_EQ(3U, model.cursor_pos());
  EXPECT_EQ(string16(), model.GetSelectedText());
  model.SetText(ASCIIToUTF16(""));
  EXPECT_EQ(0U, model.cursor_pos());
}

TEST(TextfieldViewsModelTest, Clipboard) {
  scoped_ptr<TestViewsDelegate> test_views_delegate(new TestViewsDelegate());
  views::ViewsDelegate::views_delegate = test_views_delegate.get();
  ui::Clipboard* clipboard
      = views::ViewsDelegate::views_delegate->GetClipboard();
  string16 initial_clipboard_text;
  clipboard->ReadText(ui::Clipboard::BUFFER_STANDARD, &initial_clipboard_text);
  string16 clipboard_text;
  TextfieldViewsModel model;
  model.Append(ASCIIToUTF16("HELLO WORLD"));
  model.MoveCursorToEnd(false);

  // Test for cut: Empty selection.
  EXPECT_FALSE(model.Cut());
  clipboard->ReadText(ui::Clipboard::BUFFER_STANDARD, &clipboard_text);
  EXPECT_STR_EQ(UTF16ToUTF8(initial_clipboard_text), clipboard_text);
  EXPECT_STR_EQ("HELLO WORLD", model.text());
  EXPECT_EQ(11U, model.cursor_pos());

  // Test for cut: Non-empty selection.
  model.MoveCursorToPreviousWord(true);
  EXPECT_TRUE(model.Cut());
  clipboard->ReadText(ui::Clipboard::BUFFER_STANDARD, &clipboard_text);
  EXPECT_STR_EQ("WORLD", clipboard_text);
  EXPECT_STR_EQ("HELLO ", model.text());
  EXPECT_EQ(6U, model.cursor_pos());

  // Test for copy: Empty selection.
  model.Copy();
  clipboard->ReadText(ui::Clipboard::BUFFER_STANDARD, &clipboard_text);
  EXPECT_STR_EQ("WORLD", clipboard_text);
  EXPECT_STR_EQ("HELLO ", model.text());
  EXPECT_EQ(6U, model.cursor_pos());

  // Test for copy: Non-empty selection.
  model.Append(ASCIIToUTF16("HELLO WORLD"));
  model.SelectAll();
  model.Copy();
  clipboard->ReadText(ui::Clipboard::BUFFER_STANDARD, &clipboard_text);
  EXPECT_STR_EQ("HELLO HELLO WORLD", clipboard_text);
  EXPECT_STR_EQ("HELLO HELLO WORLD", model.text());
  EXPECT_EQ(0U, model.cursor_pos());

  // Test for paste.
  model.ClearSelection();
  model.MoveCursorToEnd(false);
  model.MoveCursorToPreviousWord(true);
  EXPECT_TRUE(model.Paste());
  clipboard->ReadText(ui::Clipboard::BUFFER_STANDARD, &clipboard_text);
  EXPECT_STR_EQ("HELLO HELLO WORLD", clipboard_text);
  EXPECT_STR_EQ("HELLO HELLO HELLO HELLO WORLD", model.text());
  EXPECT_EQ(29U, model.cursor_pos());
}

}  // namespace views
<commit_msg>Revert 71170 - Delete test view delegate at end of test<commit_after>// Copyright (c) 2010 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 "base/message_loop.h"
#include "base/scoped_ptr.h"
#include "base/utf_string_conversions.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/base/clipboard/clipboard.h"
#include "ui/base/clipboard/scoped_clipboard_writer.h"
#include "views/controls/textfield/textfield_views_model.h"
#include "views/test/test_views_delegate.h"
#include "views/views_delegate.h"

namespace views {

#define EXPECT_STR_EQ(ascii, utf16) \
  EXPECT_EQ(ASCIIToWide(ascii), UTF16ToWide(utf16))

TEST(TextfieldViewsModelTest, EditString) {
  TextfieldViewsModel model;
  // append two strings
  model.Append(ASCIIToUTF16("HILL"));
  EXPECT_STR_EQ("HILL", model.text());
  model.Append(ASCIIToUTF16("WORLD"));
  EXPECT_STR_EQ("HILLWORLD", model.text());

  // Insert "E" to make hello
  model.MoveCursorRight(false);
  model.Insert('E');
  EXPECT_STR_EQ("HEILLWORLD", model.text());
  // Replace "I" with "L"
  model.Replace('L');
  EXPECT_STR_EQ("HELLLWORLD", model.text());
  model.Replace('L');
  model.Replace('O');
  EXPECT_STR_EQ("HELLOWORLD", model.text());

  // Delete 6th char "W", then delete 5th char O"
  EXPECT_EQ(5U, model.cursor_pos());
  EXPECT_TRUE(model.Delete());
  EXPECT_STR_EQ("HELLOORLD", model.text());
  EXPECT_TRUE(model.Backspace());
  EXPECT_EQ(4U, model.cursor_pos());
  EXPECT_STR_EQ("HELLORLD", model.text());

  // Move the cursor to start. backspace should fail.
  model.MoveCursorToStart(false);
  EXPECT_FALSE(model.Backspace());
  EXPECT_STR_EQ("HELLORLD", model.text());
  // Move the cursor to the end. delete should fail.
  model.MoveCursorToEnd(false);
  EXPECT_FALSE(model.Delete());
  EXPECT_STR_EQ("HELLORLD", model.text());
  // but backspace should work.
  EXPECT_TRUE(model.Backspace());
  EXPECT_STR_EQ("HELLORL", model.text());
}

TEST(TextfieldViewsModelTest, EmptyString) {
  TextfieldViewsModel model;
  EXPECT_EQ(string16(), model.text());
  EXPECT_EQ(string16(), model.GetSelectedText());
  EXPECT_EQ(string16(), model.GetVisibleText());

  model.MoveCursorLeft(true);
  EXPECT_EQ(0U, model.cursor_pos());
  model.MoveCursorRight(true);
  EXPECT_EQ(0U, model.cursor_pos());

  EXPECT_EQ(string16(), model.GetSelectedText());

  EXPECT_FALSE(model.Delete());
  EXPECT_FALSE(model.Backspace());
}

TEST(TextfieldViewsModelTest, Selection) {
  TextfieldViewsModel model;
  model.Append(ASCIIToUTF16("HELLO"));
  model.MoveCursorRight(false);
  model.MoveCursorRight(true);
  EXPECT_STR_EQ("E", model.GetSelectedText());
  model.MoveCursorRight(true);
  EXPECT_STR_EQ("EL", model.GetSelectedText());

  model.MoveCursorToStart(true);
  EXPECT_STR_EQ("H", model.GetSelectedText());
  model.MoveCursorToEnd(true);
  EXPECT_STR_EQ("ELLO", model.GetSelectedText());
  model.ClearSelection();
  EXPECT_EQ(string16(), model.GetSelectedText());
  model.SelectAll();
  EXPECT_STR_EQ("HELLO", model.GetSelectedText());

  // Select and move cursor
  model.MoveCursorTo(1U, false);
  model.MoveCursorTo(3U, true);
  EXPECT_STR_EQ("EL", model.GetSelectedText());
  model.MoveCursorLeft(false);
  EXPECT_EQ(1U, model.cursor_pos());
  model.MoveCursorTo(1U, false);
  model.MoveCursorTo(3U, true);
  model.MoveCursorRight(false);
  EXPECT_EQ(3U, model.cursor_pos());

  // Select all and move cursor
  model.SelectAll();
  model.MoveCursorLeft(false);
  EXPECT_EQ(0U, model.cursor_pos());
  model.SelectAll();
  model.MoveCursorRight(false);
  EXPECT_EQ(5U, model.cursor_pos());
}

TEST(TextfieldViewsModelTest, SelectionAndEdit) {
  TextfieldViewsModel model;
  model.Append(ASCIIToUTF16("HELLO"));
  model.MoveCursorRight(false);
  model.MoveCursorRight(true);
  model.MoveCursorRight(true);  // select "EL"
  EXPECT_TRUE(model.Backspace());
  EXPECT_STR_EQ("HLO", model.text());

  model.Append(ASCIIToUTF16("ILL"));
  model.MoveCursorRight(true);
  model.MoveCursorRight(true);  // select "LO"
  EXPECT_TRUE(model.Delete());
  EXPECT_STR_EQ("HILL", model.text());
  EXPECT_EQ(1U, model.cursor_pos());
  model.MoveCursorRight(true);  // select "I"
  model.Insert('E');
  EXPECT_STR_EQ("HELL", model.text());
  model.MoveCursorToStart(false);
  model.MoveCursorRight(true);  // select "H"
  model.Replace('B');
  EXPECT_STR_EQ("BELL", model.text());
  model.MoveCursorToEnd(false);
  model.MoveCursorLeft(true);
  model.MoveCursorLeft(true);  // select ">LL"
  model.Replace('E');
  EXPECT_STR_EQ("BEE", model.text());
}

TEST(TextfieldViewsModelTest, Password) {
  TextfieldViewsModel model;
  model.set_is_password(true);
  model.Append(ASCIIToUTF16("HELLO"));
  EXPECT_STR_EQ("*****", model.GetVisibleText());
  EXPECT_STR_EQ("HELLO", model.text());
  EXPECT_TRUE(model.Delete());

  EXPECT_STR_EQ("****", model.GetVisibleText());
  EXPECT_STR_EQ("ELLO", model.text());
  EXPECT_EQ(0U, model.cursor_pos());

  model.SelectAll();
  EXPECT_STR_EQ("ELLO", model.GetSelectedText());
  EXPECT_EQ(0U, model.cursor_pos());

  model.Insert('X');
  EXPECT_STR_EQ("*", model.GetVisibleText());
  EXPECT_STR_EQ("X", model.text());
}

TEST(TextfieldViewsModelTest, Word) {
  TextfieldViewsModel model;
  model.Append(
      ASCIIToUTF16("The answer to Life, the Universe, and Everything"));
  model.MoveCursorToNextWord(false);
  EXPECT_EQ(3U, model.cursor_pos());
  model.MoveCursorToNextWord(false);
  EXPECT_EQ(10U, model.cursor_pos());
  model.MoveCursorToNextWord(false);
  model.MoveCursorToNextWord(false);
  EXPECT_EQ(18U, model.cursor_pos());

  // Should passes the non word char ','
  model.MoveCursorToNextWord(true);
  EXPECT_EQ(23U, model.cursor_pos());
  EXPECT_STR_EQ(", the", model.GetSelectedText());

  // Move to the end.
  model.MoveCursorToNextWord(true);
  model.MoveCursorToNextWord(true);
  model.MoveCursorToNextWord(true);
  EXPECT_STR_EQ(", the Universe, and Everything", model.GetSelectedText());
  // Should be safe to go next word at the end.
  model.MoveCursorToNextWord(true);
  EXPECT_STR_EQ(", the Universe, and Everything", model.GetSelectedText());
  model.Insert('2');
  EXPECT_EQ(19U, model.cursor_pos());

  // Now backwards.
  model.MoveCursorLeft(false);  // leave 2.
  model.MoveCursorToPreviousWord(true);
  EXPECT_EQ(14U, model.cursor_pos());
  EXPECT_STR_EQ("Life", model.GetSelectedText());
  model.MoveCursorToPreviousWord(true);
  EXPECT_STR_EQ("to Life", model.GetSelectedText());
  model.MoveCursorToPreviousWord(true);
  model.MoveCursorToPreviousWord(true);
  model.MoveCursorToPreviousWord(true);  // Select to the begining.
  EXPECT_STR_EQ("The answer to Life", model.GetSelectedText());
  // Should be safe to go pervious word at the begining.
  model.MoveCursorToPreviousWord(true);
  EXPECT_STR_EQ("The answer to Life", model.GetSelectedText());
  model.Replace('4');
  EXPECT_EQ(string16(), model.GetSelectedText());
  EXPECT_STR_EQ("42", model.GetVisibleText());
}

TEST(TextfieldViewsModelTest, TextFragment) {
  TextfieldViewsModel model;
  TextfieldViewsModel::TextFragments fragments;
  // Empty string
  model.GetFragments(&fragments);
  EXPECT_EQ(1U, fragments.size());
  fragments.clear();
  EXPECT_EQ(0U, fragments[0].begin);
  EXPECT_EQ(0U, fragments[0].end);
  EXPECT_FALSE(fragments[0].selected);

  // Some string
  model.Append(ASCIIToUTF16("Hello world"));
  model.GetFragments(&fragments);
  EXPECT_EQ(1U, fragments.size());
  EXPECT_EQ(0U, fragments[0].begin);
  EXPECT_EQ(11U, fragments[0].end);
  EXPECT_FALSE(fragments[0].selected);

  // Select 1st word
  model.MoveCursorToNextWord(true);
  model.GetFragments(&fragments);
  EXPECT_EQ(2U, fragments.size());
  EXPECT_EQ(0U, fragments[0].begin);
  EXPECT_EQ(5U, fragments[0].end);
  EXPECT_TRUE(fragments[0].selected);
  EXPECT_EQ(5U, fragments[1].begin);
  EXPECT_EQ(11U, fragments[1].end);
  EXPECT_FALSE(fragments[1].selected);

  // Select empty string
  model.ClearSelection();
  model.MoveCursorRight(true);
  model.GetFragments(&fragments);
  EXPECT_EQ(3U, fragments.size());
  EXPECT_EQ(0U, fragments[0].begin);
  EXPECT_EQ(5U, fragments[0].end);
  EXPECT_FALSE(fragments[0].selected);
  EXPECT_EQ(5U, fragments[1].begin);
  EXPECT_EQ(6U, fragments[1].end);
  EXPECT_TRUE(fragments[1].selected);

  EXPECT_EQ(6U, fragments[2].begin);
  EXPECT_EQ(11U, fragments[2].end);
  EXPECT_FALSE(fragments[2].selected);

  // Select to the end.
  model.MoveCursorToEnd(true);
  model.GetFragments(&fragments);
  EXPECT_EQ(2U, fragments.size());
  EXPECT_EQ(0U, fragments[0].begin);
  EXPECT_EQ(5U, fragments[0].end);
  EXPECT_FALSE(fragments[0].selected);
  EXPECT_EQ(5U, fragments[1].begin);
  EXPECT_EQ(11U, fragments[1].end);
  EXPECT_TRUE(fragments[1].selected);
}

TEST(TextfieldViewsModelTest, SetText) {
  TextfieldViewsModel model;
  model.Append(ASCIIToUTF16("HELLO"));
  model.MoveCursorToEnd(false);
  model.SetText(ASCIIToUTF16("GOODBYE"));
  EXPECT_STR_EQ("GOODBYE", model.text());
  EXPECT_EQ(5U, model.cursor_pos());
  model.SelectAll();
  EXPECT_STR_EQ("GOODBYE", model.GetSelectedText());
  // Selection move the current pos to the begining.
  EXPECT_EQ(0U, model.cursor_pos());
  model.MoveCursorToEnd(false);
  EXPECT_EQ(7U, model.cursor_pos());

  model.SetText(ASCIIToUTF16("BYE"));
  EXPECT_EQ(3U, model.cursor_pos());
  EXPECT_EQ(string16(), model.GetSelectedText());
  model.SetText(ASCIIToUTF16(""));
  EXPECT_EQ(0U, model.cursor_pos());
}

TEST(TextfieldViewsModelTest, Clipboard) {
  views::ViewsDelegate::views_delegate = new TestViewsDelegate();
  ui::Clipboard* clipboard
      = views::ViewsDelegate::views_delegate->GetClipboard();
  string16 initial_clipboard_text;
  clipboard->ReadText(ui::Clipboard::BUFFER_STANDARD, &initial_clipboard_text);
  string16 clipboard_text;
  TextfieldViewsModel model;
  model.Append(ASCIIToUTF16("HELLO WORLD"));
  model.MoveCursorToEnd(false);

  // Test for cut: Empty selection.
  EXPECT_FALSE(model.Cut());
  clipboard->ReadText(ui::Clipboard::BUFFER_STANDARD, &clipboard_text);
  EXPECT_STR_EQ(UTF16ToUTF8(initial_clipboard_text), clipboard_text);
  EXPECT_STR_EQ("HELLO WORLD", model.text());
  EXPECT_EQ(11U, model.cursor_pos());

  // Test for cut: Non-empty selection.
  model.MoveCursorToPreviousWord(true);
  EXPECT_TRUE(model.Cut());
  clipboard->ReadText(ui::Clipboard::BUFFER_STANDARD, &clipboard_text);
  EXPECT_STR_EQ("WORLD", clipboard_text);
  EXPECT_STR_EQ("HELLO ", model.text());
  EXPECT_EQ(6U, model.cursor_pos());

  // Test for copy: Empty selection.
  model.Copy();
  clipboard->ReadText(ui::Clipboard::BUFFER_STANDARD, &clipboard_text);
  EXPECT_STR_EQ("WORLD", clipboard_text);
  EXPECT_STR_EQ("HELLO ", model.text());
  EXPECT_EQ(6U, model.cursor_pos());

  // Test for copy: Non-empty selection.
  model.Append(ASCIIToUTF16("HELLO WORLD"));
  model.SelectAll();
  model.Copy();
  clipboard->ReadText(ui::Clipboard::BUFFER_STANDARD, &clipboard_text);
  EXPECT_STR_EQ("HELLO HELLO WORLD", clipboard_text);
  EXPECT_STR_EQ("HELLO HELLO WORLD", model.text());
  EXPECT_EQ(0U, model.cursor_pos());

  // Test for paste.
  model.ClearSelection();
  model.MoveCursorToEnd(false);
  model.MoveCursorToPreviousWord(true);
  EXPECT_TRUE(model.Paste());
  clipboard->ReadText(ui::Clipboard::BUFFER_STANDARD, &clipboard_text);
  EXPECT_STR_EQ("HELLO HELLO WORLD", clipboard_text);
  EXPECT_STR_EQ("HELLO HELLO HELLO HELLO WORLD", model.text());
  EXPECT_EQ(29U, model.cursor_pos());
}

}  // namespace views
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: dispatchhelper.cxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-09 01:41:39 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

//_______________________________________________
// my own includes

#ifndef __FRAMEWORK_SERVICES_DISPATCHHELPER_HXX_
#include <services/dispatchhelper.hxx>
#endif

#ifndef __FRAMEWORK_THREADHELP_READGUARD_HXX_
#include <threadhelp/readguard.hxx>
#endif

#ifndef __FRAMEWORK_THREADHELP_WRITEGUARD_HXX_
#include <threadhelp/writeguard.hxx>
#endif

#ifndef __FRAMEWORK_SERVICES_H_
#include <services.h>
#endif

//_______________________________________________
// interface includes

#ifndef _COM_SUN_STAR_UTIL_XURLTRANSFORMER_HPP_
#include <com/sun/star/util/XURLTransformer.hpp>
#endif

#ifndef _COM_SUN_STAR_FRAME_XNOTIFYINGDISPATCH_HPP_
#include <com/sun/star/frame/XNotifyingDispatch.hpp>
#endif

//_______________________________________________
// includes of other projects

//_______________________________________________
// namespace

namespace framework{

//_______________________________________________
// non exported const

//_______________________________________________
// non exported definitions

//_______________________________________________
// declarations

//_______________________________________________
// XInterface, XTypeProvider, XServiceInfo

DEFINE_XINTERFACE_4(DispatchHelper                                       ,
                    OWeakObject                                          ,
                    DIRECT_INTERFACE(css::lang::XTypeProvider           ),
                    DIRECT_INTERFACE(css::lang::XServiceInfo            ),
                    DIRECT_INTERFACE(css::frame::XDispatchHelper        ),
                    DIRECT_INTERFACE(css::frame::XDispatchResultListener))

DEFINE_XTYPEPROVIDER_4(DispatchHelper                     ,
                       css::lang::XTypeProvider           ,
                       css::lang::XServiceInfo            ,
                       css::frame::XDispatchHelper        ,
                       css::frame::XDispatchResultListener)

DEFINE_XSERVICEINFO_MULTISERVICE(DispatchHelper                   ,
                                 ::cppu::OWeakObject              ,
                                 SERVICENAME_DISPATCHHELPER       ,
                                 IMPLEMENTATIONNAME_DISPATCHHELPER)

DEFINE_INIT_SERVICE( DispatchHelper, {} )

//_______________________________________________

/** ctor.

    @param xSMGR    the global uno service manager, which can be used to create own needed services.
*/
DispatchHelper::DispatchHelper( const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR )
        :   ThreadHelpBase(     )
        ,   OWeakObject   (     )
        // Init member
        ,   m_xSMGR       (xSMGR)
{
}

//_______________________________________________

/** dtor.
*/
DispatchHelper::~DispatchHelper()
{
}

//_______________________________________________

/** capsulate all steps of a dispatch request and provide so an easy way for dispatches.

    @param xDispatchProvider
                identifies the object, which provides may be valid dispatch objects for this execute.

    @param sURL
                describes the requested feature.

    @param sTargetFrameName
                points to the frame, which must be used (or may be created) for this dispatch.

    @param nSearchFlags
                in case the <var>sTargetFrameName</var> isn't unique, these flags regulate further searches.

    @param lArguments
                optional arguments for this request.

    @return An Any which capsulate a possible result of the internal wrapped dispatch.
 */
css::uno::Any SAL_CALL DispatchHelper::executeDispatch(
                                const css::uno::Reference< css::frame::XDispatchProvider >& xDispatchProvider ,
                                const ::rtl::OUString&                                      sURL              ,
                                const ::rtl::OUString&                                      sTargetFrameName  ,
                                      sal_Int32                                             nSearchFlags      ,
                                const css::uno::Sequence< css::beans::PropertyValue >&      lArguments        )
    throw(css::uno::RuntimeException)
{
    css::uno::Reference< css::uno::XInterface > xTHIS(static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY);

    // check for valid parameters
    if (
        (!xDispatchProvider.is()) ||
        (sURL.getLength()<1     )
       )
    {
        return css::uno::Any();
    }

    // parse given URL
    /* SAFE { */
    ReadGuard aReadLock(m_aLock);
    css::uno::Reference< css::util::XURLTransformer > xParser(m_xSMGR->createInstance(SERVICENAME_URLTRANSFORMER), css::uno::UNO_QUERY);
    aReadLock.unlock();
    /* } SAFE */

    css::util::URL aURL;
    aURL.Complete = sURL;
    xParser->parseStrict(aURL);

    // search dispatcher
    css::uno::Reference< css::frame::XDispatch >          xDispatch       = xDispatchProvider->queryDispatch(aURL, sTargetFrameName, nSearchFlags);
    css::uno::Reference< css::frame::XNotifyingDispatch > xNotifyDispatch (xDispatch, css::uno::UNO_QUERY);

    // make sure that synchronous execution is used (if possible)
    css::uno::Sequence< css::beans::PropertyValue > aArguments( lArguments );
    sal_Int32 nLength = lArguments.getLength();
    aArguments.realloc( nLength + 1 );
    aArguments[ nLength ].Name = ::rtl::OUString::createFromAscii("SynchronMode");
    aArguments[ nLength ].Value <<= (sal_Bool) sal_True;

    css::uno::Any aResult;
    if (xNotifyDispatch.is())
    {
        // dispatch it with guaranteed notification
        // Here we can hope for a result ... instead of the normal dispatch.
        css::uno::Reference< css::frame::XDispatchResultListener > xListener(xTHIS, css::uno::UNO_QUERY);
        /* SAFE { */
        WriteGuard aWriteLock(m_aLock);
        m_xBroadcaster = css::uno::Reference< css::uno::XInterface >(xNotifyDispatch, css::uno::UNO_QUERY);
        m_aResult      = css::uno::Any();
        m_aBlock.reset();
        aWriteLock.unlock();
        /* } SAFE */

        // dispatch it and wait for a notification
        // TODO/MBA: waiting in main thread?!
        xNotifyDispatch->dispatchWithNotification(aURL, aArguments, xListener);
        //m_aBlock.wait();
        aResult = m_aResult;
    }
    else
    if (xDispatch.is())
    {
        // dispatch it without any chance to get a result
        xDispatch->dispatch( aURL, aArguments );
    }

    return aResult;
}

//_______________________________________________

/** callback for started dispatch with guaranteed notifications.

    We must save the result, so the method executeDispatch() can return it.
    Further we must release the broadcaster (otherwhise it can't die)
    and unblock the waiting executeDispatch() request.

    @param  aResult
                describes the result of the dispatch operation
 */
void SAL_CALL DispatchHelper::dispatchFinished( const css::frame::DispatchResultEvent& aResult )
    throw(css::uno::RuntimeException)
{
    /* SAFE { */
    WriteGuard aWriteLock(m_aLock);

    m_aResult <<= aResult;
    m_aBlock.set();
    m_xBroadcaster.clear();

    /* } SAFE */
}

//_______________________________________________

/** we has to realease our broadcaster reference.

    @param aEvent
                describe the source of this event and MUST be our save broadcaster!
 */
void SAL_CALL DispatchHelper::disposing( const css::lang::EventObject& aEvent )
    throw(css::uno::RuntimeException)
{
    /* SAFE { */
    WriteGuard aWriteLock(m_aLock);

    m_aResult.clear();
    m_aBlock.set();
    m_xBroadcaster.clear();

    /* } SAFE */
}

}
<commit_msg>INTEGRATION: CWS warnings01 (1.5.32); FILE MERGED 2005/11/16 15:20:32 pl 1.5.32.1: #i55991# removed warnings<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: dispatchhelper.cxx,v $
 *
 *  $Revision: 1.6 $
 *
 *  last change: $Author: hr $ $Date: 2006-06-19 11:26:21 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

//_______________________________________________
// my own includes

#ifndef __FRAMEWORK_SERVICES_DISPATCHHELPER_HXX_
#include <services/dispatchhelper.hxx>
#endif

#ifndef __FRAMEWORK_THREADHELP_READGUARD_HXX_
#include <threadhelp/readguard.hxx>
#endif

#ifndef __FRAMEWORK_THREADHELP_WRITEGUARD_HXX_
#include <threadhelp/writeguard.hxx>
#endif

#ifndef __FRAMEWORK_SERVICES_H_
#include <services.h>
#endif

//_______________________________________________
// interface includes

#ifndef _COM_SUN_STAR_UTIL_XURLTRANSFORMER_HPP_
#include <com/sun/star/util/XURLTransformer.hpp>
#endif

#ifndef _COM_SUN_STAR_FRAME_XNOTIFYINGDISPATCH_HPP_
#include <com/sun/star/frame/XNotifyingDispatch.hpp>
#endif

//_______________________________________________
// includes of other projects

//_______________________________________________
// namespace

namespace framework{

//_______________________________________________
// non exported const

//_______________________________________________
// non exported definitions

//_______________________________________________
// declarations

//_______________________________________________
// XInterface, XTypeProvider, XServiceInfo

DEFINE_XINTERFACE_4(DispatchHelper                                       ,
                    OWeakObject                                          ,
                    DIRECT_INTERFACE(css::lang::XTypeProvider           ),
                    DIRECT_INTERFACE(css::lang::XServiceInfo            ),
                    DIRECT_INTERFACE(css::frame::XDispatchHelper        ),
                    DIRECT_INTERFACE(css::frame::XDispatchResultListener))

DEFINE_XTYPEPROVIDER_4(DispatchHelper                     ,
                       css::lang::XTypeProvider           ,
                       css::lang::XServiceInfo            ,
                       css::frame::XDispatchHelper        ,
                       css::frame::XDispatchResultListener)

DEFINE_XSERVICEINFO_MULTISERVICE(DispatchHelper                   ,
                                 ::cppu::OWeakObject              ,
                                 SERVICENAME_DISPATCHHELPER       ,
                                 IMPLEMENTATIONNAME_DISPATCHHELPER)

DEFINE_INIT_SERVICE( DispatchHelper, {} )

//_______________________________________________

/** ctor.

    @param xSMGR    the global uno service manager, which can be used to create own needed services.
*/
DispatchHelper::DispatchHelper( const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR )
        :   ThreadHelpBase(     )
        ,   OWeakObject   (     )
        // Init member
        ,   m_xSMGR       (xSMGR)
{
}

//_______________________________________________

/** dtor.
*/
DispatchHelper::~DispatchHelper()
{
}

//_______________________________________________

/** capsulate all steps of a dispatch request and provide so an easy way for dispatches.

    @param xDispatchProvider
                identifies the object, which provides may be valid dispatch objects for this execute.

    @param sURL
                describes the requested feature.

    @param sTargetFrameName
                points to the frame, which must be used (or may be created) for this dispatch.

    @param nSearchFlags
                in case the <var>sTargetFrameName</var> isn't unique, these flags regulate further searches.

    @param lArguments
                optional arguments for this request.

    @return An Any which capsulate a possible result of the internal wrapped dispatch.
 */
css::uno::Any SAL_CALL DispatchHelper::executeDispatch(
                                const css::uno::Reference< css::frame::XDispatchProvider >& xDispatchProvider ,
                                const ::rtl::OUString&                                      sURL              ,
                                const ::rtl::OUString&                                      sTargetFrameName  ,
                                      sal_Int32                                             nSearchFlags      ,
                                const css::uno::Sequence< css::beans::PropertyValue >&      lArguments        )
    throw(css::uno::RuntimeException)
{
    css::uno::Reference< css::uno::XInterface > xTHIS(static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY);

    // check for valid parameters
    if (
        (!xDispatchProvider.is()) ||
        (sURL.getLength()<1     )
       )
    {
        return css::uno::Any();
    }

    // parse given URL
    /* SAFE { */
    ReadGuard aReadLock(m_aLock);
    css::uno::Reference< css::util::XURLTransformer > xParser(m_xSMGR->createInstance(SERVICENAME_URLTRANSFORMER), css::uno::UNO_QUERY);
    aReadLock.unlock();
    /* } SAFE */

    css::util::URL aURL;
    aURL.Complete = sURL;
    xParser->parseStrict(aURL);

    // search dispatcher
    css::uno::Reference< css::frame::XDispatch >          xDispatch       = xDispatchProvider->queryDispatch(aURL, sTargetFrameName, nSearchFlags);
    css::uno::Reference< css::frame::XNotifyingDispatch > xNotifyDispatch (xDispatch, css::uno::UNO_QUERY);

    // make sure that synchronous execution is used (if possible)
    css::uno::Sequence< css::beans::PropertyValue > aArguments( lArguments );
    sal_Int32 nLength = lArguments.getLength();
    aArguments.realloc( nLength + 1 );
    aArguments[ nLength ].Name = ::rtl::OUString::createFromAscii("SynchronMode");
    aArguments[ nLength ].Value <<= (sal_Bool) sal_True;

    css::uno::Any aResult;
    if (xNotifyDispatch.is())
    {
        // dispatch it with guaranteed notification
        // Here we can hope for a result ... instead of the normal dispatch.
        css::uno::Reference< css::frame::XDispatchResultListener > xListener(xTHIS, css::uno::UNO_QUERY);
        /* SAFE { */
        WriteGuard aWriteLock(m_aLock);
        m_xBroadcaster = css::uno::Reference< css::uno::XInterface >(xNotifyDispatch, css::uno::UNO_QUERY);
        m_aResult      = css::uno::Any();
        m_aBlock.reset();
        aWriteLock.unlock();
        /* } SAFE */

        // dispatch it and wait for a notification
        // TODO/MBA: waiting in main thread?!
        xNotifyDispatch->dispatchWithNotification(aURL, aArguments, xListener);
        //m_aBlock.wait();
        aResult = m_aResult;
    }
    else
    if (xDispatch.is())
    {
        // dispatch it without any chance to get a result
        xDispatch->dispatch( aURL, aArguments );
    }

    return aResult;
}

//_______________________________________________

/** callback for started dispatch with guaranteed notifications.

    We must save the result, so the method executeDispatch() can return it.
    Further we must release the broadcaster (otherwhise it can't die)
    and unblock the waiting executeDispatch() request.

    @param  aResult
                describes the result of the dispatch operation
 */
void SAL_CALL DispatchHelper::dispatchFinished( const css::frame::DispatchResultEvent& aResult )
    throw(css::uno::RuntimeException)
{
    /* SAFE { */
    WriteGuard aWriteLock(m_aLock);

    m_aResult <<= aResult;
    m_aBlock.set();
    m_xBroadcaster.clear();

    /* } SAFE */
}

//_______________________________________________

/** we has to realease our broadcaster reference.

    @param aEvent
                describe the source of this event and MUST be our save broadcaster!
 */
void SAL_CALL DispatchHelper::disposing( const css::lang::EventObject& )
    throw(css::uno::RuntimeException)
{
    /* SAFE { */
    WriteGuard aWriteLock(m_aLock);

    m_aResult.clear();
    m_aBlock.set();
    m_xBroadcaster.clear();

    /* } SAFE */
}

}
<|endoftext|>


<commit_before>/*$Id$
 *
 * This source file is a part of the Berlin Project.
 * Copyright (C) 1999 Brent A. Fulgham <bfulgham@debian.org>
 * Copyright (C) 1999 Stefan Seefeld <seefelds@magellan.umontreal.ca>
 * http://www.berlin-consortium.org
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 675 Mass Ave, Cambridge,
 * MA 02139, USA.
 */

#ifndef _Profiler_hh
#define _Profiler_hh

#include <Prague/Sys/ntree.hh>
#include <ctime>
#include <iostream>
#include <string>
#include <iomanip.h>

namespace Prague
{

struct CheckPoint
{
  CheckPoint(const string &s) : name(s), count(0), start(0), stop(0), elapsed(0) {}
  CheckPoint(CheckPoint *cp)
    : name(cp->name),
      count(cp->count),
      start(cp->start),
      stop(cp->stop),
      elapsed(cp->elapsed)
    {}
  void indent(ostream &os, unsigned short ind) { while (ind--) os.put(' ');}
  void output(ostream &os, unsigned short ind)
    {
      indent(os, ind); os << name << ": " << setw(10) << count;
      indent(os, ind); os << " Times.  Total Time: ";
      indent(os, ind); os << setprecision(8) << setw(12);
      indent(os, ind); os.setf( ios::fixed, ios::floatfield);
      indent(os, ind); os << elapsed/CLOCKS_PER_SEC;
      indent(os, ind); os  << "  Avg/Iter.: ";
      indent(os, ind); os << setprecision(8) << setw(12);
      indent(os, ind); os << elapsed/count/CLOCKS_PER_SEC << endl;
    }
  string name;
  long count;
  clock_t start;
  clock_t stop;
  double elapsed;
};

class Profiler
{
  typedef ntree<CheckPoint *> table_t;
  typedef ntree<CheckPoint *>::node item_t;
  typedef ntree<CheckPoint *>::node::child_iterator child_iterator;
  typedef ntree<CheckPoint *>::node::const_child_iterator const_child_iterator;
  typedef ntree<CheckPoint *>::node::up_iterator up_iterator;
public:
  Profiler(const string &name)
    {
      if (!count++)
	{
	  table = new table_t(new CheckPoint("root"));
	  current = &table->root();
	  os = &cout;
	}
      child_iterator i = lookup(name);
      current = &*i;
      current->value->count++;
      current->value->start = clock();
    }
  ~Profiler()
    {
      current->value->stop = clock();
      current->value->elapsed += (current->value->stop - current->value->start);
      up_iterator i = current->up_begin();
      current = &*++i;
      if (!--count)
	{
	  dump(*current, 0);
	  clean(*current);
	}
    }
  static void setOutput(ostream &o) { os = &o;}
private:
  static child_iterator lookup(const string &name)
    {
      for (child_iterator i = current->child_begin(); i != current->child_end(); i++)
	if ((*i).value->name == name) return i;
      return current->push_back(new CheckPoint(name));
    }
  static void dump(const item_t &root, unsigned short ind)
    {
      for (const_child_iterator i = root.child_begin(); i != root.child_end(); i++)
	dump(*i, ind + 1);
      if (ind) root.value->output(*os, ind); // don't output the root
    }
  void dump() { dump(*current, 0);}
  static void clean(const item_t &root)
    {
      for (const_child_iterator i = root.child_begin(); i != root.child_end(); i++)
	clean(*i);
      delete root.value;
    }
  static long     count;
  static table_t *table;
  static item_t  *current;
  static ostream *os;
};

};

#endif /* _Profiler_hh */
<commit_msg>*** empty log message ***<commit_after>/*$Id$
 *
 * This source file is a part of the Berlin Project.
 * Copyright (C) 1999 Brent A. Fulgham <bfulgham@debian.org>
 * Copyright (C) 1999 Stefan Seefeld <seefelds@magellan.umontreal.ca>
 * http://www.berlin-consortium.org
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 675 Mass Ave, Cambridge,
 * MA 02139, USA.
 */

#ifndef _Profiler_hh
#define _Profiler_hh

#include <Prague/Sys/ntree.hh>
#include <ctime>
#include <iostream>
#include <string>
#include <iomanip.h>

namespace Prague
{

struct CheckPoint
{
  CheckPoint(const string &s) : name(s), count(0), start(0), stop(0), elapsed(0) {}
  CheckPoint(CheckPoint *cp)
    : name(cp->name),
      count(cp->count),
      start(cp->start),
      stop(cp->stop),
      elapsed(cp->elapsed)
    {}
  void indent(ostream &os, unsigned short ind) { while (ind--) os.put(' ');}
  void output(ostream &os, unsigned short ind)
    {
      indent(os, ind);
      os << name << ": " << setw(10) << count;
      os << " Times.  Total Time: ";
      os << setprecision(8) << setw(12);
      os.setf( ios::fixed, ios::floatfield);
      os << elapsed/CLOCKS_PER_SEC;
      os  << "  Avg/Iter.: ";
      os << setprecision(8) << setw(12);
      os << elapsed/count/CLOCKS_PER_SEC << endl;
    }
  string name;
  long count;
  clock_t start;
  clock_t stop;
  double elapsed;
};

class Profiler
{
  typedef ntree<CheckPoint *> table_t;
  typedef ntree<CheckPoint *>::node item_t;
  typedef ntree<CheckPoint *>::node::child_iterator child_iterator;
  typedef ntree<CheckPoint *>::node::const_child_iterator const_child_iterator;
  typedef ntree<CheckPoint *>::node::up_iterator up_iterator;
public:
  Profiler(const string &name)
    {
      if (!count++)
	{
	  table = new table_t(new CheckPoint("root"));
	  current = &table->root();
	  os = &cout;
	}
      child_iterator i = lookup(name);
      current = &*i;
      current->value->count++;
      current->value->start = clock();
    }
  ~Profiler()
    {
      current->value->stop = clock();
      current->value->elapsed += (current->value->stop - current->value->start);
      up_iterator i = current->up_begin();
      current = &*++i;
      if (!--count)
	{
	  dump(*current, 0);
	  clean(*current);
	  delete table;
	}
    }
  static void setOutput(ostream &o) { os = &o;}
  static void dump() { dump(*current, 0);}
private:
  static child_iterator lookup(const string &name)
    {
      for (child_iterator i = current->child_begin(); i != current->child_end(); i++)
	if ((*i).value->name == name) return i;
      return current->push_back(new CheckPoint(name));
    }
  static void dump(const item_t &root, unsigned short ind)
    {
      for (const_child_iterator i = root.child_begin(); i != root.child_end(); i++)
	dump(*i, ind + 1);
      if (ind) root.value->output(*os, ind); // don't output the root
    }
  static void clean(const item_t &root)
    {
      for (const_child_iterator i = root.child_begin(); i != root.child_end(); i++)
	clean(*i);
      delete root.value;
    }
  static long     count;
  static table_t *table;
  static item_t  *current;
  static ostream *os;
};

};

#endif /* _Profiler_hh */
<|endoftext|>


<commit_before>#include <gtest/gtest.h>
#include "Endian.h"

TEST(EndianTest, TestBitSwap) {
  uint64_t x = 0x0123456789abcdefull;
  uint64_t rev_x = 0xefcdab8967452301ull;
  EXPECT_EQ(rev_x, bswap_64(x));

  uint32_t y = 0x01234567;
  uint32_t rev_y = 0x67452301;
  EXPECT_EQ(rev_y, bswap_32(y));

  uint16_t z = 0x0123;
  uint16_t rev_z = 0x2301;
  EXPECT_EQ(rev_z, bswap_16(z));
}<commit_msg>added another single test<commit_after>#include <gtest/gtest.h>
#include "Endian.h"

TEST(EndianTest, TestBitSwap) {
  uint64_t x = 0x0123456789abcdefull;
  uint64_t rev_x = 0xefcdab8967452301ull;
  EXPECT_EQ(rev_x, bswap_64(x));

  uint32_t y = 0x01234567;
  uint32_t rev_y = 0x67452301;
  EXPECT_EQ(rev_y, bswap_32(y));

  uint16_t z = 0x0123;
  uint16_t rev_z = 0x2301;
  EXPECT_EQ(rev_z, bswap_16(z));

  uint64_t w = 0x0123456789abcdefull;
  EXPECT_EQ(w, bswap_64(bswap_64(w)));
}<|endoftext|>


<commit_before>#include "Test.h"

#include <string>

using namespace std;

extern "C" int test_snprintf(char *, size_t, const char *, ...);

class SnprintfTest : public evil::Test {};

TEST_F(SnprintfTest, no_args) {
    char dst[sizeof("abc")];

    EXPECT_EQ(3, test_snprintf(dst, sizeof(dst), "abc"));
    EXPECT_EQ("abc"s, string(dst));
}

TEST_F(SnprintfTest, format_invalid) {
    char dst[sizeof("%?")];
    evil::UBChecker checker{1};

    EXPECT_EQ(2, test_snprintf(dst, sizeof(dst), "%?"));
    EXPECT_EQ("%?"s, string(dst));
}

TEST_F(SnprintfTest, format_string) {
    char dst[16];

    EXPECT_EQ(5, test_snprintf(dst, sizeof(dst), "AB%s", "abc"));
    EXPECT_EQ("ABabc"s, string(dst));

    EXPECT_EQ(5, test_snprintf(dst, sizeof(dst), "A%sB", "abc"));
    EXPECT_EQ("AabcB"s, string(dst));

    EXPECT_EQ(5, test_snprintf(dst, sizeof(dst), "%sAB", "abc"));
    EXPECT_EQ("abcAB"s, string(dst));

    EXPECT_EQ(5, test_snprintf(dst, sizeof(dst), "% 5s", "abc"));
    EXPECT_EQ("  abc"s, string(dst));

    EXPECT_EQ(3, test_snprintf(dst, sizeof(dst), "%.3s", "abcde"));
    EXPECT_EQ("abc"s, string(dst));

    EXPECT_EQ(5, test_snprintf(dst, sizeof(dst), "% 5.3s", "abcde"));
    EXPECT_EQ("  abc"s, string(dst));

    {
        evil::UBChecker checker{1};

        EXPECT_EQ(6, test_snprintf(dst, sizeof(dst), "%s", NULL));
        EXPECT_EQ("(null)"s, string(dst));
    }
}

TEST_F(SnprintfTest, format_char) {
    char dst[sizeof("xAB")];

    EXPECT_EQ(3, test_snprintf(dst, sizeof(dst), "AB%c", 'a'));
    EXPECT_EQ("ABa"s, string(dst));

    EXPECT_EQ(3, test_snprintf(dst, sizeof(dst), "A%cB", 'a'));
    EXPECT_EQ("AaB"s, string(dst));

    EXPECT_EQ(3, test_snprintf(dst, sizeof(dst), "%cAB", 'a'));
    EXPECT_EQ("aAB"s, string(dst));
}

TEST_F(SnprintfTest, format_char_outside_range) {
    char dst[sizeof("A")];

    EXPECT_EQ(1, test_snprintf(dst, sizeof(dst), "%c", 'A' - 256));
    EXPECT_EQ("A"s, string(dst));

    EXPECT_EQ(1, test_snprintf(dst, sizeof(dst), "%c", 'A' + 256));
    EXPECT_EQ("A"s, string(dst));
}

TEST_F(SnprintfTest, format_int) {
    char dst[16];

    EXPECT_EQ(3, test_snprintf(dst, sizeof(dst), "%d", 123));
    EXPECT_EQ("123"s, string(dst));

    EXPECT_EQ(4, test_snprintf(dst, sizeof(dst), "%d", -123));
    EXPECT_EQ("-123"s, string(dst));
}
<commit_msg>Tests for loading width/precision from argument<commit_after>#include "Test.h"

#include <string>

using namespace std;

extern "C" int test_snprintf(char *, size_t, const char *, ...);

class SnprintfTest : public evil::Test {};

TEST_F(SnprintfTest, no_args) {
    char dst[sizeof("abc")];

    EXPECT_EQ(3, test_snprintf(dst, sizeof(dst), "abc"));
    EXPECT_EQ("abc"s, string(dst));
}

TEST_F(SnprintfTest, format_invalid) {
    char dst[sizeof("%?")];
    evil::UBChecker checker{1};

    EXPECT_EQ(2, test_snprintf(dst, sizeof(dst), "%?"));
    EXPECT_EQ("%?"s, string(dst));
}

TEST_F(SnprintfTest, format_string) {
    char dst[16];

    EXPECT_EQ(5, test_snprintf(dst, sizeof(dst), "AB%s", "abc"));
    EXPECT_EQ("ABabc"s, string(dst));

    EXPECT_EQ(5, test_snprintf(dst, sizeof(dst), "A%sB", "abc"));
    EXPECT_EQ("AabcB"s, string(dst));

    EXPECT_EQ(5, test_snprintf(dst, sizeof(dst), "%sAB", "abc"));
    EXPECT_EQ("abcAB"s, string(dst));

    EXPECT_EQ(5, test_snprintf(dst, sizeof(dst), "% 5s", "abc"));
    EXPECT_EQ("  abc"s, string(dst));

    EXPECT_EQ(3, test_snprintf(dst, sizeof(dst), "%.3s", "abcde"));
    EXPECT_EQ("abc"s, string(dst));

    EXPECT_EQ(5, test_snprintf(dst, sizeof(dst), "% 5.3s", "abcde"));
    EXPECT_EQ("  abc"s, string(dst));

    EXPECT_EQ(5, test_snprintf(dst, sizeof(dst), "% *s", 5, "abc"));
    EXPECT_EQ("  abc"s, string(dst));

    EXPECT_EQ(3, test_snprintf(dst, sizeof(dst), "%.*s", 3, "abcde"));
    EXPECT_EQ("abc"s, string(dst));

    EXPECT_EQ(5, test_snprintf(dst, sizeof(dst), "% *.*s", 5, 3, "abcde"));
    EXPECT_EQ("  abc"s, string(dst));

    {
        evil::UBChecker checker{1};

        EXPECT_EQ(6, test_snprintf(dst, sizeof(dst), "%s", NULL));
        EXPECT_EQ("(null)"s, string(dst));
    }
}

TEST_F(SnprintfTest, format_char) {
    char dst[sizeof("xAB")];

    EXPECT_EQ(3, test_snprintf(dst, sizeof(dst), "AB%c", 'a'));
    EXPECT_EQ("ABa"s, string(dst));

    EXPECT_EQ(3, test_snprintf(dst, sizeof(dst), "A%cB", 'a'));
    EXPECT_EQ("AaB"s, string(dst));

    EXPECT_EQ(3, test_snprintf(dst, sizeof(dst), "%cAB", 'a'));
    EXPECT_EQ("aAB"s, string(dst));
}

TEST_F(SnprintfTest, format_char_outside_range) {
    char dst[sizeof("A")];

    EXPECT_EQ(1, test_snprintf(dst, sizeof(dst), "%c", 'A' - 256));
    EXPECT_EQ("A"s, string(dst));

    EXPECT_EQ(1, test_snprintf(dst, sizeof(dst), "%c", 'A' + 256));
    EXPECT_EQ("A"s, string(dst));
}

TEST_F(SnprintfTest, format_int) {
    char dst[16];

    EXPECT_EQ(3, test_snprintf(dst, sizeof(dst), "%d", 123));
    EXPECT_EQ("123"s, string(dst));

    EXPECT_EQ(4, test_snprintf(dst, sizeof(dst), "%d", -123));
    EXPECT_EQ("-123"s, string(dst));
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2005-2017 Centre National d'Etudes Spatiales (CNES)
 *
 * This file is part of Orfeo Toolbox
 *
 *     https://www.orfeo-toolbox.org/
 *
 * 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 "otbWrapperQtWidgetListEditItemModel.h"

/*****************************************************************************/
/* INCLUDE SECTION                                                           */

//
// Qt includes (sorted by alphabetic order)
//// Must be included before system/custom includes.

//
// System includes (sorted by alphabetic order)

//
// ITK includes (sorted by alphabetic order)

//
// OTB includes (sorted by alphabetic order)

#include "otbWrapperStringListInterface.h"

namespace otb
{

namespace Wrapper
{

/*
  TRANSLATOR otb::Wapper::ListEditItemModel

  Necessary for lupdate to be aware of C++ namespaces.

  Context comment for translator.
*/

/*****************************************************************************/
/* CONSTANTS                                                                 */

namespace
{

const char * const
HEADERS[ ListEditItemModel::COLUMN_COUNT ] =
{
  QT_TRANSLATE_NOOP( "otb::Wrapper::ListEditItemModel", "Name" ),
  // QT_TRANSLATE_NOOP( "otb::Wrapper::ListEditItemModel", "Browse" ),
};

} // end of anonymous namespace.

/*****************************************************************************/
/* STATIC IMPLEMENTATION SECTION                                             */

/*****************************************************************************/
/* CLASS IMPLEMENTATION SECTION                                              */

/*******************************************************************************/
ListEditItemModel
::ListEditItemModel( StringListInterface * sli,
		     QObject * p ) :
  QAbstractItemModel( p ),
  m_StringList( sli )
{
  assert( sli!=nullptr );
}

/*******************************************************************************/
ListEditItemModel
::~ListEditItemModel()
{
}

/*****************************************************************************/
/* QAbstractItemModel overloads                                              */
/*****************************************************************************/
int
ListEditItemModel
::columnCount( const QModelIndex & ) const
{
  // qDebug() << this << "::columnCount(" << parent << ")";

  return COLUMN_COUNT;
}

/*****************************************************************************/
QVariant
ListEditItemModel
::data( const QModelIndex & idx, int role ) const
{
  // qDebug() << this << "::data(" << idx << "," << role << ")";

  // Get layer.
  assert( m_StringList!=NULL );

  assert( idx.isValid() );
  assert( !idx.parent().isValid() );
  assert( idx.internalPointer()!=NULL );

  const StringListInterface * stringList =
    static_cast< const StringListInterface * >( idx.internalPointer() );

  assert( stringList!=nullptr );

  // Return data given role.
  switch( role )
    {
    case Qt::CheckStateRole:
#if 0
      if( idx.column()!=COLUMN_NAME )
        return QVariant();
      else
	{
	assert( idx.row() >= 0 );
	return stringList->IsActive( idx.row() );
	}
#endif
      break;

    case Qt::EditRole:
    case Qt::DisplayRole:
      switch( idx.column() )
        {
        case COLUMN_NAME:
	  {
	  assert( idx.row() >= 0 );

	  std::string filename(
	    stringList->GetNthFileName( idx.row() )
	  );

	  // qDebug() << "Filename:" << QString( "%1" ).arg( filename.c_str() );

	  return
	    filename.empty()
	    ? ( role==Qt::EditRole ? QString() : "EMPTY" )
	    : QFile::decodeName( filename.c_str()
	    );
	  }
          break;

	default:
	  break;
        }
      break;

    case Qt::FontRole:
      break;

    case Qt::ToolTipRole:
      switch( idx.column() )
	{
	case COLUMN_NAME:
	  assert( idx.row() >= 0 );
	  return QString::fromStdString( stringList->GetToolTip( idx.row() ) );
	  break;
	}
      break;

    case USER_ROLE_DIRECTION:
      assert( idx.row()>=0 );
      return stringList->GetDirection( idx.row() );
      break;

    case USER_ROLE_FILTER:
      assert( idx.row()>=0 );
      return QString::fromStdString( stringList->GetFilenameFilter( idx.row() ) );
      break;

    default:
      break;
    }

  return QVariant();
}

/*****************************************************************************/
Qt::ItemFlags
ListEditItemModel
::flags( const QModelIndex & idx ) const
{
  if( !idx.isValid() )
    return QAbstractItemModel::flags( idx );

  Qt::ItemFlags iflags =
    QAbstractItemModel::flags( idx )
    // | Qt::ItemIsDragEnabled
    // | Qt::ItemIsDropEnabled
    ;

  if( idx.column()==COLUMN_NAME )
    iflags |=
      Qt::ItemIsEditable
      // | Qt::ItemIsUserCheckable
      // | Qt::ItemIsDragEnabled
      ;

  return iflags;
}

/*****************************************************************************/
bool
ListEditItemModel
::hasChildren( const QModelIndex & idx ) const
{
  return !idx.isValid();
}

/*****************************************************************************/
QVariant
ListEditItemModel
::headerData( int section,
              Qt::Orientation /**orientation*/,
              int role ) const
{
  // qDebug()
  //   << this << "::headerData("
  //   << section << "," << orientation << "," << role
  //   << ")";

  // assert( orientation==Qt::Horizontal );

  switch( role )
    {
    case Qt::DisplayRole:
      assert( section>=0 && section<COLUMN_COUNT );
      return tr( HEADERS[ section ] );
      break;

    default:
      break;
    }

  return QVariant();
}

/*****************************************************************************/
QModelIndex
ListEditItemModel
::index( int row,
         int column,
         const QModelIndex & p ) const
{
  // qDebug()
  //   << this << "::index(" << row << "," << column << "," << parent << ")";

  if( m_StringList == nullptr )
    return QModelIndex();

  // qDebug()
  //   << "index:" << row << "," << column << "," << m_StringList->At( row );

  assert( row>=0 && column>=0 );

#if 0
  AbstractLayerModel * layer = m_StringList->At( row );

  if( layer==NULL || p.isValid() )
    return QModelIndex();
#endif

  return
    createIndex(
      row,
      column,
      p.isValid()
      ? NULL
      : m_StringList
    );
}

/*****************************************************************************/
bool
ListEditItemModel
::insertRow( int row, const QModelIndex & parent )
{
  return insertRows( row, 1, parent );
}

/*****************************************************************************/
bool
ListEditItemModel
::insertRows( int row, int count, const QModelIndex & parent )
{
  // qDebug() << this << "::insertRows(" << row << "," << count << "," << parent << ")";

  assert( m_StringList!=nullptr );

  beginInsertRows( parent, row, count );
  {
    for( int r=row; r<row+count; ++r )
      m_StringList->Insert( "", r );
  }
  endInsertRows();

  return true;
}

/*****************************************************************************/
QModelIndex
ListEditItemModel
::parent( const QModelIndex & ) const
{
  // qDebug() << this << "::parent(" << index << ")";

  return QModelIndex();
}

/*****************************************************************************/
bool
ListEditItemModel
::removeRows( int row, int count, const QModelIndex & p )
{
  assert( !p.isValid() );
  assert( count==1 );

  if( p.isValid() || count!=1 )
    return false;

  assert( m_StringList!=nullptr );

  beginRemoveRows( p, row, row + count - 1 );
  {
    m_StringList->Erase( row, count );
  }
  endRemoveRows();

  return true;
}

/*****************************************************************************/
int
ListEditItemModel
::rowCount( const QModelIndex & p ) const
{
  // qDebug() << this << "::rowCount(" << p << ")";

  // qDebug() << "row-count:" <<
  //   ( ( m_StringList==NULL || p.isValid() )
  //     ? 0
  //     : m_StringList->GetCount()
  //   );

  return
    ( m_StringList==nullptr || p.isValid() )
    ? 0
    : m_StringList->Size();
}

/*****************************************************************************/
bool
ListEditItemModel
::setData( const QModelIndex & idx,
           const QVariant & value,
           int role )
{
  // qDebug()
  //   << this << "::setData(" << idx << "," << value << "," << role
  //   << ");";

  assert( !idx.parent().isValid() );
  assert( idx.row()>=0 );
  assert( idx.internalPointer()!=nullptr );

  StringListInterface * stringList =
    static_cast< StringListInterface * >( idx.internalPointer() );

  switch( idx.column() )
    {
    case COLUMN_NAME:
      switch( role )
	{
	case Qt::EditRole:
	  stringList->SetNthFileName(
	    idx.row(),
	    QFile::encodeName( value.toString() ).data()
	  );
	  emit dataChanged( idx, idx );
	  return true;
	  break;

	case Qt::CheckStateRole:
	  break;

	case USER_ROLE_DIRECTION:
	  break;

	default:
	  break;
	}
      break;

    default:
      break;
    }

  return false;
}

/*******************************************************************************/
bool
ListEditItemModel
::Swap( int row1, int row2 )
{
  assert( m_StringList!=nullptr );

  assert( row1>=0 );
  assert( static_cast< unsigned int >( row1 )<m_StringList->Size() );

  assert( row2>=0 );
  assert( static_cast< unsigned int >( row2 )<m_StringList->Size() );

  assert( row1!=row2 );

  emit layoutAboutToBeChanged();

  m_StringList->Swap( row1, row2 );

  emit layoutChanged();

  return true;
}

/*******************************************************************************/
bool
ListEditItemModel
::IsInput() const
{
  assert( m_StringList!=nullptr );

  return m_StringList->GetDirection()==Role_Input;
}

/*******************************************************************************/
bool
ListEditItemModel
::IsBrowsable() const
{
  assert( m_StringList!=nullptr );

  return m_StringList->IsFilename();
}

/*******************************************************************************/
QString
ListEditItemModel
::GetFilter() const
{
  assert( m_StringList!=nullptr );

  return QString::fromStdString( m_StringList->GetFilenameFilter() );
}

/*******************************************************************************/
/* SLOTS                                                                       */
/*******************************************************************************/

} // end namespace 'Wrapper'.

} // end namespace 'otb'
<commit_msg>ENH: Fixed ListEditItemModel::removeAll().<commit_after>/*
 * Copyright (C) 2005-2017 Centre National d'Etudes Spatiales (CNES)
 *
 * This file is part of Orfeo Toolbox
 *
 *     https://www.orfeo-toolbox.org/
 *
 * 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 "otbWrapperQtWidgetListEditItemModel.h"

/*****************************************************************************/
/* INCLUDE SECTION                                                           */

//
// Qt includes (sorted by alphabetic order)
//// Must be included before system/custom includes.

//
// System includes (sorted by alphabetic order)

//
// ITK includes (sorted by alphabetic order)

//
// OTB includes (sorted by alphabetic order)

#include "otbWrapperStringListInterface.h"

namespace otb
{

namespace Wrapper
{

/*
  TRANSLATOR otb::Wapper::ListEditItemModel

  Necessary for lupdate to be aware of C++ namespaces.

  Context comment for translator.
*/

/*****************************************************************************/
/* CONSTANTS                                                                 */

namespace
{

const char * const
HEADERS[ ListEditItemModel::COLUMN_COUNT ] =
{
  QT_TRANSLATE_NOOP( "otb::Wrapper::ListEditItemModel", "Name" ),
  // QT_TRANSLATE_NOOP( "otb::Wrapper::ListEditItemModel", "Browse" ),
};

} // end of anonymous namespace.

/*****************************************************************************/
/* STATIC IMPLEMENTATION SECTION                                             */

/*****************************************************************************/
/* CLASS IMPLEMENTATION SECTION                                              */

/*******************************************************************************/
ListEditItemModel
::ListEditItemModel( StringListInterface * sli,
		     QObject * p ) :
  QAbstractItemModel( p ),
  m_StringList( sli )
{
  assert( sli!=nullptr );
}

/*******************************************************************************/
ListEditItemModel
::~ListEditItemModel()
{
}

/*****************************************************************************/
/* QAbstractItemModel overloads                                              */
/*****************************************************************************/
int
ListEditItemModel
::columnCount( const QModelIndex & ) const
{
  // qDebug() << this << "::columnCount(" << parent << ")";

  return COLUMN_COUNT;
}

/*****************************************************************************/
QVariant
ListEditItemModel
::data( const QModelIndex & idx, int role ) const
{
  // qDebug() << this << "::data(" << idx << "," << role << ")";

  // Get layer.
  assert( m_StringList!=NULL );

  assert( idx.isValid() );
  assert( !idx.parent().isValid() );
  assert( idx.internalPointer()!=NULL );

  const StringListInterface * stringList =
    static_cast< const StringListInterface * >( idx.internalPointer() );

  assert( stringList!=nullptr );

  // Return data given role.
  switch( role )
    {
    case Qt::CheckStateRole:
#if 0
      if( idx.column()!=COLUMN_NAME )
        return QVariant();
      else
	{
	assert( idx.row() >= 0 );
	return stringList->IsActive( idx.row() );
	}
#endif
      break;

    case Qt::EditRole:
    case Qt::DisplayRole:
      switch( idx.column() )
        {
        case COLUMN_NAME:
	  {
	  assert( idx.row() >= 0 );

	  std::string filename(
	    stringList->GetNthFileName( idx.row() )
	  );

	  // qDebug() << "Filename:" << QString( "%1" ).arg( filename.c_str() );

	  return
	    filename.empty()
	    ? ( role==Qt::EditRole ? QString() : "EMPTY" )
	    : QFile::decodeName( filename.c_str()
	    );
	  }
          break;

	default:
	  break;
        }
      break;

    case Qt::FontRole:
      break;

    case Qt::ToolTipRole:
      switch( idx.column() )
	{
	case COLUMN_NAME:
	  assert( idx.row() >= 0 );
	  return QString::fromStdString( stringList->GetToolTip( idx.row() ) );
	  break;
	}
      break;

    case USER_ROLE_DIRECTION:
      assert( idx.row()>=0 );
      return stringList->GetDirection( idx.row() );
      break;

    case USER_ROLE_FILTER:
      assert( idx.row()>=0 );
      return QString::fromStdString( stringList->GetFilenameFilter( idx.row() ) );
      break;

    default:
      break;
    }

  return QVariant();
}

/*****************************************************************************/
Qt::ItemFlags
ListEditItemModel
::flags( const QModelIndex & idx ) const
{
  if( !idx.isValid() )
    return QAbstractItemModel::flags( idx );

  Qt::ItemFlags iflags =
    QAbstractItemModel::flags( idx )
    // | Qt::ItemIsDragEnabled
    // | Qt::ItemIsDropEnabled
    ;

  if( idx.column()==COLUMN_NAME )
    iflags |=
      Qt::ItemIsEditable
      // | Qt::ItemIsUserCheckable
      // | Qt::ItemIsDragEnabled
      ;

  return iflags;
}

/*****************************************************************************/
bool
ListEditItemModel
::hasChildren( const QModelIndex & idx ) const
{
  return !idx.isValid();
}

/*****************************************************************************/
QVariant
ListEditItemModel
::headerData( int section,
              Qt::Orientation /**orientation*/,
              int role ) const
{
  // qDebug()
  //   << this << "::headerData("
  //   << section << "," << orientation << "," << role
  //   << ")";

  // assert( orientation==Qt::Horizontal );

  switch( role )
    {
    case Qt::DisplayRole:
      assert( section>=0 && section<COLUMN_COUNT );
      return tr( HEADERS[ section ] );
      break;

    default:
      break;
    }

  return QVariant();
}

/*****************************************************************************/
QModelIndex
ListEditItemModel
::index( int row,
         int column,
         const QModelIndex & p ) const
{
  // qDebug()
  //   << this << "::index(" << row << "," << column << "," << parent << ")";

  if( m_StringList == nullptr )
    return QModelIndex();

  // qDebug()
  //   << "index:" << row << "," << column << "," << m_StringList->At( row );

  assert( row>=0 && column>=0 );

#if 0
  AbstractLayerModel * layer = m_StringList->At( row );

  if( layer==NULL || p.isValid() )
    return QModelIndex();
#endif

  return
    createIndex(
      row,
      column,
      p.isValid()
      ? NULL
      : m_StringList
    );
}

/*****************************************************************************/
bool
ListEditItemModel
::insertRow( int row, const QModelIndex & parent )
{
  return insertRows( row, 1, parent );
}

/*****************************************************************************/
bool
ListEditItemModel
::insertRows( int row, int count, const QModelIndex & parent )
{
  // qDebug() << this << "::insertRows(" << row << "," << count << "," << parent << ")";

  assert( m_StringList!=nullptr );

  beginInsertRows( parent, row, count );
  {
    for( int r=row; r<row+count; ++r )
      m_StringList->Insert( "", r );
  }
  endInsertRows();

  return true;
}

/*****************************************************************************/
QModelIndex
ListEditItemModel
::parent( const QModelIndex & ) const
{
  // qDebug() << this << "::parent(" << index << ")";

  return QModelIndex();
}

/*****************************************************************************/
bool
ListEditItemModel
::removeRows( int row, int count, const QModelIndex & p )
{
  assert( !p.isValid() );
  assert( count>=1 );

  if( p.isValid() || count<1 )
    return false;

  assert( m_StringList!=nullptr );

  beginRemoveRows( p, row, row + count - 1 );
  {
    m_StringList->Erase( row, count );
  }
  endRemoveRows();

  return true;
}

/*****************************************************************************/
int
ListEditItemModel
::rowCount( const QModelIndex & p ) const
{
  // qDebug() << this << "::rowCount(" << p << ")";

  // qDebug() << "row-count:" <<
  //   ( ( m_StringList==NULL || p.isValid() )
  //     ? 0
  //     : m_StringList->GetCount()
  //   );

  return
    ( m_StringList==nullptr || p.isValid() )
    ? 0
    : m_StringList->Size();
}

/*****************************************************************************/
bool
ListEditItemModel
::setData( const QModelIndex & idx,
           const QVariant & value,
           int role )
{
  // qDebug()
  //   << this << "::setData(" << idx << "," << value << "," << role
  //   << ");";

  assert( !idx.parent().isValid() );
  assert( idx.row()>=0 );
  assert( idx.internalPointer()!=nullptr );

  StringListInterface * stringList =
    static_cast< StringListInterface * >( idx.internalPointer() );

  switch( idx.column() )
    {
    case COLUMN_NAME:
      switch( role )
	{
	case Qt::EditRole:
	  stringList->SetNthFileName(
	    idx.row(),
	    QFile::encodeName( value.toString() ).data()
	  );
	  emit dataChanged( idx, idx );
	  return true;
	  break;

	case Qt::CheckStateRole:
	  break;

	case USER_ROLE_DIRECTION:
	  break;

	default:
	  break;
	}
      break;

    default:
      break;
    }

  return false;
}

/*******************************************************************************/
bool
ListEditItemModel
::Swap( int row1, int row2 )
{
  assert( m_StringList!=nullptr );

  assert( row1>=0 );
  assert( static_cast< unsigned int >( row1 )<m_StringList->Size() );

  assert( row2>=0 );
  assert( static_cast< unsigned int >( row2 )<m_StringList->Size() );

  assert( row1!=row2 );

  emit layoutAboutToBeChanged();

  m_StringList->Swap( row1, row2 );

  emit layoutChanged();

  return true;
}

/*******************************************************************************/
bool
ListEditItemModel
::IsInput() const
{
  assert( m_StringList!=nullptr );

  return m_StringList->GetDirection()==Role_Input;
}

/*******************************************************************************/
bool
ListEditItemModel
::IsBrowsable() const
{
  assert( m_StringList!=nullptr );

  return m_StringList->IsFilename();
}

/*******************************************************************************/
QString
ListEditItemModel
::GetFilter() const
{
  assert( m_StringList!=nullptr );

  return QString::fromStdString( m_StringList->GetFilenameFilter() );
}

/*******************************************************************************/
/* SLOTS                                                                       */
/*******************************************************************************/

} // end namespace 'Wrapper'.

} // end namespace 'otb'
<|endoftext|>


<commit_before>/*
* Copyright 2008, 2009, 2010 Free Software Foundation, Inc.
* Copyright 2010 Kestrel Signal Processing, Inc.
* Copyright 2011 Range Networks, Inc.
*
* This software is distributed under the terms of the GNU Affero Public License.
* See the COPYING file in the main directory for details.
*
* This use of this software may be subject to additional restrictions.
* See the LEGAL file in the main directory for details.

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

	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 <iostream>
#include <fstream>

#include <Configuration.h>
// Load configuration from a file.
ConfigurationTable gConfig("/etc/OpenBTS/OpenBTS.db");

#include <TRXManager.h>
#include <GSML1FEC.h>
#include <GSMConfig.h>
#include <GSMSAPMux.h>
#include <GSML3RRMessages.h>
#include <GSMLogicalChannel.h>

#include <ControlCommon.h>
#include <TransactionTable.h>

#include <SIPInterface.h>
#include <Globals.h>

#include <Logger.h>
#include <CLI.h>
#include <PowerManager.h>
#include <Configuration.h>
#include <PhysicalStatus.h>
#include <SubscriberRegistry.h>

#include <assert.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>

#ifdef HAVE_LIBREADLINE // [
//#  include <stdio.h>
#  include <readline/readline.h>
#  include <readline/history.h>
#endif // HAVE_LIBREADLINE ]

using namespace std;
using namespace GSM;

const char* gDateTime = __DATE__ " " __TIME__;

// All of the other globals that rely on the global configuration file need to
// be declared here.

// The TMSI Table.
Control::TMSITable gTMSITable(gConfig.getStr("Control.Reporting.TMSITable").c_str());

// The transaction table.
Control::TransactionTable gTransactionTable;

// Physical status reporting
GSM::PhysicalStatus gPhysStatus(gConfig.getStr("Control.Reporting.PhysStatusTable").c_str());

// The global SIPInterface object.
SIP::SIPInterface gSIPInterface;

// Configure the BTS object based on the config file.
// So don't create this until AFTER loading the config file.
GSMConfig gBTS;

// Our interface to the software-defined radio.
TransceiverManager gTRX(gConfig.getStr("TRX.IP").c_str(), gConfig.getNum("TRX.Port"));

// Subscriber registry
SubscriberRegistry gSubscriberRegistry;

/** Define a function to call any time the configuration database changes. */
void purgeConfig(void*,int,char const*, char const*, sqlite3_int64)
{
	LOG(INFO) << "purging configuration cache";
	gConfig.purge();
	gBTS.regenerateBeacon();
}

const char* transceiverPath = "./transceiver";

pid_t gTransceiverPid = 0;

void startTransceiver()
{
	// Start the transceiver binary, if the path is defined.
	// If the path is not defined, the transceiver must be started by some other process.
	char TRXnumARFCN[4];
	sprintf(TRXnumARFCN,"%1d",1);
	LOG(NOTICE) << "starting transceiver " << transceiverPath << " " << TRXnumARFCN;
	gTransceiverPid = vfork();
	LOG_ASSERT(gTransceiverPid>=0);
	if (gTransceiverPid==0) {
		// Pid==0 means this is the process that starts the transceiver.
		execlp(transceiverPath,transceiverPath,TRXnumARFCN,NULL);
		LOG(EMERG) << "cannot find " << transceiverPath;
		_exit(1);
	}
}

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

	try {

	srandom(time(NULL));

	gConfig.setUpdateHook(purgeConfig);
	gLogInit("openbts",gConfig.getStr("Log.Level").c_str(),LOG_LOCAL7);
	LOG(ALERT) << "OpenBTS starting, ver " << VERSION << " build date " << __DATE__;

	COUT("\n\n" << gOpenBTSWelcome << "\n");
	COUT("\nStarting the system...");

	startTransceiver();

	// Start the SIP interface.
	gSIPInterface.start();

	//
	// Configure the radio.
	//

	// Start the transceiver interface.
	// Sleep long enough for the USRP to bootload.
	sleep(5);
	gTRX.start();

	// Set up the interface to the radio.
	// Get a handle to the C0 transceiver interface.
	ARFCNManager* C0radio = gTRX.ARFCN();

	// Tuning.
	// Make sure its off for tuning.
	C0radio->powerOff();
	// Get the ARFCN list.
	unsigned C0 = gConfig.getNum("GSM.Radio.C0");
	// Tune the radio.
	LOG(INFO) << "tuning TRX to ARFCN " << C0;
	ARFCNManager* radio = gTRX.ARFCN();
	radio->tune(C0);

	// Set TSC same as BCC everywhere.
	C0radio->setTSC(gBTS.BCC());

	// Set maximum expected delay spread.
	C0radio->setMaxDelay(gConfig.getNum("GSM.Radio.MaxExpectedDelaySpread"));

	// Set Receiver Gain
	C0radio->setRxGain(gConfig.getNum("GSM.Radio.RxGain"));

	// Turn on and power up.
	C0radio->powerOn();
	C0radio->setPower(gConfig.getNum("GSM.Radio.PowerManager.MinAttenDB"));

	//
	// Create a C-V channel set on C0T0.
	//

	// C-V on C0T0
	C0radio->setSlot(0,5);
	// SCH
	SCHL1FEC SCH;
	SCH.downstream(C0radio);
	SCH.open();
	// FCCH
	FCCHL1FEC FCCH;
	FCCH.downstream(C0radio);
	FCCH.open();
	// BCCH
	BCCHL1FEC BCCH;
	BCCH.downstream(C0radio);
	BCCH.open();
	// RACH
	RACHL1FEC RACH(gRACHC5Mapping);
	RACH.downstream(C0radio);
	RACH.open();
	// CCCHs
	CCCHLogicalChannel CCCH0(gCCCH_0Mapping);
	CCCH0.downstream(C0radio);
	CCCH0.open();
	CCCHLogicalChannel CCCH1(gCCCH_1Mapping);
	CCCH1.downstream(C0radio);
	CCCH1.open();
	CCCHLogicalChannel CCCH2(gCCCH_2Mapping);
	CCCH2.downstream(C0radio);
	CCCH2.open();
	// use CCCHs as AGCHs
	gBTS.addAGCH(&CCCH0);
	gBTS.addAGCH(&CCCH1);
	gBTS.addAGCH(&CCCH2);

	// C-V C0T0 SDCCHs
	SDCCHLogicalChannel C0T0SDCCH[4] = {
		SDCCHLogicalChannel(0,gSDCCH_4_0),
		SDCCHLogicalChannel(0,gSDCCH_4_1),
		SDCCHLogicalChannel(0,gSDCCH_4_2),
		SDCCHLogicalChannel(0,gSDCCH_4_3),
	};
	Thread C0T0SDCCHControlThread[4];
	for (int i=0; i<4; i++) {
		C0T0SDCCH[i].downstream(C0radio);
		C0T0SDCCHControlThread[i].start((void*(*)(void*))Control::DCCHDispatcher,&C0T0SDCCH[i]);
		C0T0SDCCH[i].open();
		gBTS.addSDCCH(&C0T0SDCCH[i]);
	}

	//
	// Configure the other slots.
	//

	// Count configured slots.
	unsigned sCount = 1;

	if (gConfig.defines("GSM.Channels.C1sFirst")) {
		// Create C-I slots.
		for (int i=0; i<gConfig.getNum("GSM.Channels.NumC1s"); i++) {
			gBTS.createCombinationI(gTRX,sCount);
			sCount++;
		}
	}

	// Create C-VII slots.
	for (int i=0; i<gConfig.getNum("GSM.Channels.NumC7s"); i++) {
		gBTS.createCombinationVII(gTRX,sCount);
		sCount++;
	}

	if (!gConfig.defines("GSM.Channels.C1sFirst")) {
		// Create C-I slots.
		for (int i=0; i<gConfig.getNum("GSM.Channels.NumC1s"); i++) {
			gBTS.createCombinationI(gTRX,sCount);
			sCount++;
		}
	}

	// Set up idle filling on C0 as needed.
	while (sCount<8) {
		gBTS.createCombination0(gTRX,sCount);
		sCount++;
	}

	/*
		Note: The number of different paging subchannels on
		the CCCH is:

		MAX(1,(3 - BS-AG-BLKS-RES)) * BS-PA-MFRMS
			if CCCH-CONF = "001"
		(9 - BS-AG-BLKS-RES) * BS-PA-MFRMS
			for other values of CCCH-CONF
	*/

	// Set up the pager.
	// Set up paging channels.
	// HACK -- For now, use a single paging channel, since paging groups are broken.
	gBTS.addPCH(&CCCH2);

	// Be sure we are not over-reserving.
	LOG_ASSERT(gConfig.getNum("GSM.CCCH.PCH.Reserve")<(int)gBTS.numAGCHs());

	// OK, now it is safe to start the BTS.
	gBTS.start();

#ifdef HAVE_LIBREADLINE // [
	// start console
	using_history();

	static const char * const history_file_name = "/.openbts_history";
	char *history_name = 0;
	char *home_dir = getenv("HOME");

	if(home_dir) {
		size_t home_dir_len = strlen(home_dir);
		size_t history_file_len = strlen(history_file_name);
		size_t history_len = home_dir_len + history_file_len + 1;
		if(history_len > home_dir_len) {
			if(!(history_name = (char *)malloc(history_len))) {
				LOG(ERR) << "malloc failed: " << strerror(errno);
				exit(2);
			}
			memcpy(history_name, home_dir, home_dir_len);
			memcpy(history_name + home_dir_len, history_file_name,
			   history_file_len + 1);
			read_history(history_name);
		}
	}
#endif // HAVE_LIBREADLINE ]

	LOG(INFO) << "system ready";
	COUT("\n\nWelcome to OpenBTS.  Type \"help\" to see available commands.");
        // FIXME: We want to catch control-d (emacs keybinding for exit())

	// The logging parts were removed from this loop.
	// If we want them back, they will need to go into their own thread.
	while (1) {
#ifdef HAVE_LIBREADLINE // [
		char *inbuf = readline(gConfig.getStr("CLI.Prompt").c_str());
		if (!inbuf) break;
		if (*inbuf) {
			add_history(inbuf);
			// The parser returns -1 on exit.
			if (gParser.process(inbuf, cout, cin)<0) {
				free(inbuf);
				break;
			}
		}
		free(inbuf);
#else // HAVE_LIBREADLINE ][
		cout << endl << gConfig.getStr("CLI.Prompt");
		cout.flush();
		char inbuf[1024];
		cin.getline(inbuf,1024,'\n');
		// The parser returns -1 on exit.
		if (gParser.process(inbuf,cout,cin)<0) break;
#endif // !HAVE_LIBREADLINE ]
	}

#ifdef HAVE_LIBREADLINE // [
	if(history_name) {
		int e = write_history(history_name);
		if(e) {
			fprintf(stderr, "error: history: %s\n", strerror(e));
		}
		free(history_name);
		history_name = 0;
	}
#endif // HAVE_LIBREADLINE ]

	if (gTransceiverPid) kill(gTransceiverPid, SIGKILL);

	}

	catch (ConfigurationTableKeyNotFound e) {

		LOG(ALERT) << "configuration key " << e.key() << " not defined";
		exit(2);
	}

}

// vim: ts=4 sw=4
<commit_msg>Remedying #538 in the public release<commit_after>/*
* Copyright 2008, 2009, 2010 Free Software Foundation, Inc.
* Copyright 2010 Kestrel Signal Processing, Inc.
* Copyright 2011 Range Networks, Inc.
*
* This software is distributed under the terms of the GNU Affero Public License.
* See the COPYING file in the main directory for details.
*
* This use of this software may be subject to additional restrictions.
* See the LEGAL file in the main directory for details.

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

	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 <iostream>
#include <fstream>

#include <Configuration.h>
// Load configuration from a file.
ConfigurationTable gConfig("/etc/OpenBTS/OpenBTS.db");

#include <TRXManager.h>
#include <GSML1FEC.h>
#include <GSMConfig.h>
#include <GSMSAPMux.h>
#include <GSML3RRMessages.h>
#include <GSMLogicalChannel.h>

#include <ControlCommon.h>
#include <TransactionTable.h>

#include <SIPInterface.h>
#include <Globals.h>

#include <Logger.h>
#include <CLI.h>
#include <PowerManager.h>
#include <Configuration.h>
#include <PhysicalStatus.h>
#include <SubscriberRegistry.h>

#include <sys/wait.h>

#include <assert.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>

#ifdef HAVE_LIBREADLINE // [
//#  include <stdio.h>
#  include <readline/readline.h>
#  include <readline/history.h>
#endif // HAVE_LIBREADLINE ]

using namespace std;
using namespace GSM;

const char* gDateTime = __DATE__ " " __TIME__;

// All of the other globals that rely on the global configuration file need to
// be declared here.

// The TMSI Table.
Control::TMSITable gTMSITable(gConfig.getStr("Control.Reporting.TMSITable").c_str());

// The transaction table.
Control::TransactionTable gTransactionTable;

// Physical status reporting
GSM::PhysicalStatus gPhysStatus(gConfig.getStr("Control.Reporting.PhysStatusTable").c_str());

// The global SIPInterface object.
SIP::SIPInterface gSIPInterface;

// Configure the BTS object based on the config file.
// So don't create this until AFTER loading the config file.
GSMConfig gBTS;

// Our interface to the software-defined radio.
TransceiverManager gTRX(gConfig.getStr("TRX.IP").c_str(), gConfig.getNum("TRX.Port"));

// Subscriber registry
SubscriberRegistry gSubscriberRegistry;

/** Define a function to call any time the configuration database changes. */
void purgeConfig(void*,int,char const*, char const*, sqlite3_int64)
{
	LOG(INFO) << "purging configuration cache";
	gConfig.purge();
	gBTS.regenerateBeacon();
}

const char* transceiverPath = "./transceiver";

pid_t gTransceiverPid = 0;

void startTransceiver()
{
	// Start the transceiver binary, if the path is defined.
	// If the path is not defined, the transceiver must be started by some other process.
	char TRXnumARFCN[4];
	sprintf(TRXnumARFCN,"%1d",1);
	LOG(NOTICE) << "starting transceiver " << transceiverPath << " " << TRXnumARFCN;
	gTransceiverPid = vfork();
	LOG_ASSERT(gTransceiverPid>=0);
	if (gTransceiverPid==0) {
		// Pid==0 means this is the process that starts the transceiver.
		execlp(transceiverPath,transceiverPath,TRXnumARFCN,NULL);
		LOG(EMERG) << "cannot find " << transceiverPath;
		_exit(1);
	} else {
		int status;
		waitpid(gTransceiverPid, &status,0);
		LOG(EMERG) << "Transceiver quit with status " << status << ". Exiting.";
		exit(2);
	}
}

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

	try {

	srandom(time(NULL));

	gConfig.setUpdateHook(purgeConfig);
	gLogInit("openbts",gConfig.getStr("Log.Level").c_str(),LOG_LOCAL7);
	LOG(ALERT) << "OpenBTS starting, ver " << VERSION << " build date " << __DATE__;

	COUT("\n\n" << gOpenBTSWelcome << "\n");
	COUT("\nStarting the system...");

	Thread transceiverThread;
	transceiverThread.start((void*(*)(void*)) startTransceiver, NULL);

	// Start the SIP interface.
	gSIPInterface.start();

	//
	// Configure the radio.
	//

	// Start the transceiver interface.
	// Sleep long enough for the USRP to bootload.
	sleep(5);
	gTRX.start();

	// Set up the interface to the radio.
	// Get a handle to the C0 transceiver interface.
	ARFCNManager* C0radio = gTRX.ARFCN();

	// Tuning.
	// Make sure its off for tuning.
	C0radio->powerOff();
	// Get the ARFCN list.
	unsigned C0 = gConfig.getNum("GSM.Radio.C0");
	// Tune the radio.
	LOG(INFO) << "tuning TRX to ARFCN " << C0;
	ARFCNManager* radio = gTRX.ARFCN();
	radio->tune(C0);

	// Set TSC same as BCC everywhere.
	C0radio->setTSC(gBTS.BCC());

	// Set maximum expected delay spread.
	C0radio->setMaxDelay(gConfig.getNum("GSM.Radio.MaxExpectedDelaySpread"));

	// Set Receiver Gain
	C0radio->setRxGain(gConfig.getNum("GSM.Radio.RxGain"));

	// Turn on and power up.
	C0radio->powerOn();
	C0radio->setPower(gConfig.getNum("GSM.Radio.PowerManager.MinAttenDB"));

	//
	// Create a C-V channel set on C0T0.
	//

	// C-V on C0T0
	C0radio->setSlot(0,5);
	// SCH
	SCHL1FEC SCH;
	SCH.downstream(C0radio);
	SCH.open();
	// FCCH
	FCCHL1FEC FCCH;
	FCCH.downstream(C0radio);
	FCCH.open();
	// BCCH
	BCCHL1FEC BCCH;
	BCCH.downstream(C0radio);
	BCCH.open();
	// RACH
	RACHL1FEC RACH(gRACHC5Mapping);
	RACH.downstream(C0radio);
	RACH.open();
	// CCCHs
	CCCHLogicalChannel CCCH0(gCCCH_0Mapping);
	CCCH0.downstream(C0radio);
	CCCH0.open();
	CCCHLogicalChannel CCCH1(gCCCH_1Mapping);
	CCCH1.downstream(C0radio);
	CCCH1.open();
	CCCHLogicalChannel CCCH2(gCCCH_2Mapping);
	CCCH2.downstream(C0radio);
	CCCH2.open();
	// use CCCHs as AGCHs
	gBTS.addAGCH(&CCCH0);
	gBTS.addAGCH(&CCCH1);
	gBTS.addAGCH(&CCCH2);

	// C-V C0T0 SDCCHs
	SDCCHLogicalChannel C0T0SDCCH[4] = {
		SDCCHLogicalChannel(0,gSDCCH_4_0),
		SDCCHLogicalChannel(0,gSDCCH_4_1),
		SDCCHLogicalChannel(0,gSDCCH_4_2),
		SDCCHLogicalChannel(0,gSDCCH_4_3),
	};
	Thread C0T0SDCCHControlThread[4];
	for (int i=0; i<4; i++) {
		C0T0SDCCH[i].downstream(C0radio);
		C0T0SDCCHControlThread[i].start((void*(*)(void*))Control::DCCHDispatcher,&C0T0SDCCH[i]);
		C0T0SDCCH[i].open();
		gBTS.addSDCCH(&C0T0SDCCH[i]);
	}

	//
	// Configure the other slots.
	//

	// Count configured slots.
	unsigned sCount = 1;

	if (gConfig.defines("GSM.Channels.C1sFirst")) {
		// Create C-I slots.
		for (int i=0; i<gConfig.getNum("GSM.Channels.NumC1s"); i++) {
			gBTS.createCombinationI(gTRX,sCount);
			sCount++;
		}
	}

	// Create C-VII slots.
	for (int i=0; i<gConfig.getNum("GSM.Channels.NumC7s"); i++) {
		gBTS.createCombinationVII(gTRX,sCount);
		sCount++;
	}

	if (!gConfig.defines("GSM.Channels.C1sFirst")) {
		// Create C-I slots.
		for (int i=0; i<gConfig.getNum("GSM.Channels.NumC1s"); i++) {
			gBTS.createCombinationI(gTRX,sCount);
			sCount++;
		}
	}

	// Set up idle filling on C0 as needed.
	while (sCount<8) {
		gBTS.createCombination0(gTRX,sCount);
		sCount++;
	}

	/*
		Note: The number of different paging subchannels on
		the CCCH is:

		MAX(1,(3 - BS-AG-BLKS-RES)) * BS-PA-MFRMS
			if CCCH-CONF = "001"
		(9 - BS-AG-BLKS-RES) * BS-PA-MFRMS
			for other values of CCCH-CONF
	*/

	// Set up the pager.
	// Set up paging channels.
	// HACK -- For now, use a single paging channel, since paging groups are broken.
	gBTS.addPCH(&CCCH2);

	// Be sure we are not over-reserving.
	LOG_ASSERT(gConfig.getNum("GSM.CCCH.PCH.Reserve")<(int)gBTS.numAGCHs());

	// OK, now it is safe to start the BTS.
	gBTS.start();

#ifdef HAVE_LIBREADLINE // [
	// start console
	using_history();

	static const char * const history_file_name = "/.openbts_history";
	char *history_name = 0;
	char *home_dir = getenv("HOME");

	if(home_dir) {
		size_t home_dir_len = strlen(home_dir);
		size_t history_file_len = strlen(history_file_name);
		size_t history_len = home_dir_len + history_file_len + 1;
		if(history_len > home_dir_len) {
			if(!(history_name = (char *)malloc(history_len))) {
				LOG(ERR) << "malloc failed: " << strerror(errno);
				exit(2);
			}
			memcpy(history_name, home_dir, home_dir_len);
			memcpy(history_name + home_dir_len, history_file_name,
			   history_file_len + 1);
			read_history(history_name);
		}
	}
#endif // HAVE_LIBREADLINE ]

	LOG(INFO) << "system ready";
	COUT("\n\nWelcome to OpenBTS.  Type \"help\" to see available commands.");
        // FIXME: We want to catch control-d (emacs keybinding for exit())

	// The logging parts were removed from this loop.
	// If we want them back, they will need to go into their own thread.
	while (1) {
#ifdef HAVE_LIBREADLINE // [
		char *inbuf = readline(gConfig.getStr("CLI.Prompt").c_str());
		if (!inbuf) break;
		if (*inbuf) {
			add_history(inbuf);
			// The parser returns -1 on exit.
			if (gParser.process(inbuf, cout, cin)<0) {
				free(inbuf);
				break;
			}
		}
		free(inbuf);
#else // HAVE_LIBREADLINE ][
		cout << endl << gConfig.getStr("CLI.Prompt");
		cout.flush();
		char inbuf[1024];
		cin.getline(inbuf,1024,'\n');
		// The parser returns -1 on exit.
		if (gParser.process(inbuf,cout,cin)<0) break;
#endif // !HAVE_LIBREADLINE ]
	}

#ifdef HAVE_LIBREADLINE // [
	if(history_name) {
		int e = write_history(history_name);
		if(e) {
			fprintf(stderr, "error: history: %s\n", strerror(e));
		}
		free(history_name);
		history_name = 0;
	}
#endif // HAVE_LIBREADLINE ]

	if (gTransceiverPid) kill(gTransceiverPid, SIGKILL);

	}

	catch (ConfigurationTableKeyNotFound e) {

		LOG(ALERT) << "configuration key " << e.key() << " not defined";
		exit(2);
	}

}

// vim: ts=4 sw=4
<|endoftext|>