December 15, 2011

December 04, 2011

ASP.NET/Mono + Apache2


    Примеры действий, которые необходимо выполнить для запуска ASP.NET приложения под Apache2, можно посмотреть [тут] и [тут].

November 25, 2011

JUnit + javax* : "not native or abstract in class file"

    При использовании javax-библиотек, например, таких так "javaee-web-api", "javaee-api" или "mail", в ходе выполнения JUnit-тестов может появиться сообщение об ошибке следующего характера:
Absent Code attribute in method that is not native or abstract in class file
    Для решения этой проблемы необходимо убрать из списка зависимостей в pom.xml javax-библиотеки, а вместо этого сделать следующее:

1. В список репозиториев добавить "JBoss Repository":
<repository>
   <id>repository.jboss.org</id>
   <name>JBoss Repository</name>
   <url>http://repository.jboss.org/nexus/content/groups/public-jboss/</url>
</repository>
2. В список зависимостей добавить ссылку на спецификацию jboss-javaee, например:
<dependency>
   <groupId>org.jboss.spec</groupId>
   <artifactId>jboss-javaee-6.0</artifactId>
   <version>3.0.0.Beta1</version>
   <type>pom</type>
</dependency>

November 11, 2011

Hibernatetemplate + sql-query + return-scalar + xml

   Ситуация: необходимо в xml-файле мэппинга hibernate описать native-sql запрос, возвращающий некоторый скалярный результат.
  Например, для таблицы пользователей в postgres необходимо сформировать запрос, сообщающий, занят логин или нет. При этом для его выполнения необходимо использовать Hibernatetemplate от Spring. В этом случае в файле мэппинга описание будет иметь, например, такой вид:
<sql-query name="isLoginUsedNativeSQL">
    <return-scalar column="login_used" type="true_false" />
    <![CDATA[
        select (count(usr.id)>0) as login_used from user_ usr where usr.login=?
    ]]>
</sql-query>
    Метод слоя DAO, вызывающий этот запрос:
@Override
public Boolean isLoginUsed(String login) {
    List result = getHibernateTemplate().findByNamedQuery("isLoginUsedNativeSQL", login);
    return (Boolean) DataAccessUtils.requiredSingleResult(result);
}
    где DataAccessUtils это класс
org.springframework.dao.support.DataAccessUtils

jQuery Backward Timer (Таймер обратного отсчёта)


ACHTUNG! ВНИМАНИЕ! ATTENTION!

Таймер обратного отсчета вынесен в отдельный jQuery-плагин. Всю необходимую информацию можно получить на странице плагина. Текст ниже оставлен для истории.


    Таймер обратного отсчёта, имеющий следующие возможности:
  1. установка времени отсчёта в секундах;
  2. установка названий единиц измерения;
  3. выполнение действия по истечению установленного времени.
     Пример работы:
 
    Исходный код примера:
<div style="background: #ddf; color: 77a; padding: 3px 30px; border: 1px #99a dashed; margin: 5px 0;">
    <span id="timerOutput"></span><br/>
</div>

<script type="text/javascript"
    src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js"></script>
<script type="text/javascript"
    src="http://dl.dropbox.com/u/76022516/proj/js/timerBackward.js"></script>

<script type="text/javascript">
$(document).ready(function() {
    $('#timerOutput').addAndRunBackwardTimer({
        seconds: '172800',
        timeUnitsNames: {
            h: "ч",
            m: "мин",
            s: "сек"
        },
    })
});
</script>
    Если необходимо вызвать какую-то функцию по истечении времени, то это будет выглядеть примерно так:
<script type="text/javascript">
function foo() {
//
}

$(document).ready(function() {
    $('#timerOutput').addAndRunBackwardTimer({
        seconds: '100000',
        timeUnitsNames: {
            h: "ч",
            m: "мин",
            s: "сек"
        },
        onTimerStop : foo
    })
});
</script>
   Использование "$(document).ready()" необязательно. Вообще, зависимость от jQuery очень незначительна и при необходимости можно легко переписать на чистом js.

[Ссылка на скрипт]

November 10, 2011

kdeinit4 craches on startup (kdeinit4 падает при запуске)

  Проблема: после запуска KDE появляется сообщение о падении kdeinit4. Отправить разработчикам отчет об ошибке невозможно из-за отсутствия хоть какой-то информации о проблеме. 
   Нагуглив тему с идентичной проблемой, нашел в её конце решение проблемы. Оно нашлось в смене бэк-энд библиотеки phonon-a c VCL на GStreamer.
    Для Archlinux:
sudo pacman -S phonon-gstreamer
    После этого выполнить проверку настроек:
System Settings -> Hardware -> Multimedia -> Phonon -> Backend
    Там должен быть выбран Gstreamer:

November 05, 2011

Квантовая ловушка

    "Израиль продемонстрировал миру квантовую левитацию" - заголовок статьи на mignews.
    Видео само говорит за себя:


    Подробнее в самой [статье].
    И еще одно видео:

November 02, 2011

Установка Ruby on Rails

1
Установить Git. Примеры команд для linux:
#ubuntu
sudo apt-get install git

#archlinux
sudo pacman -S git
2
Выполняем то, что написано [здесь]. В общем случае это выглядит так:
1
Загрузить свежую версию установочного скрипта RVM и выполнить его:
$ bash < <(curl -s https://raw.github.com/wayneeseguin/rvm/master/binscripts/rvm-installer )
2
Загрузить RVM в качестве функции для сессий в терминале:
$ echo '[[ -s "$HOME/.rvm/scripts/rvm" ]] && . "$HOME/.rvm/scripts/rvm" # Load RVM function' >> ~/.bash_profile
3
Перезагрузка настроек терминала:
$ source ~/.bash_profile
4
Тест функции:
$ type rvm | head -1
rvm is a function
5
Просмотр доступных версий:
$ rvm list known
6
Установка определенной версии Ruby:
$ rvm install 1.9.2
7
Использование установленной версии по умолчанию:
$ rvm use 1.9.2 --default
8
Установка Rails:
$ gem install rails
3
После этого можно создать тестовое приложение, например, как описано [здесь].



    Если при выполнении
rails server
    получается сообщение об ошибке:
Could not find a JavaScript runtime.
    то необходимо в Gemfile проекта дописать следующее:
gem 'execjs'
gem 'therubyracer'
    Для установки therubyracer необходимо наличие установленного nodejs. В директории проекта осталось выполнить:
bundle install



   Проверено на Ubuntu и Archlinux.

November 01, 2011

Tapestry: StackMapTable format error: bad class

    При использовании Tapestry можно получить сообщение об ошибке "StackMapTable format error: bad class...", которое может появиться в результате выброса некоего исключения "RequestExceptionHandler". В моем случае ошибка происходила при обыкновенной проверке на NULL параметра из HttpServletRequest-а.
     Для решения проблемы необходимо в список maven-зависимостей добавить зависимость от свежего "Javassist". Необходимую информацию можно получить [здесь].

maven-surefire-plugin: No tests were found

    Если maven-surefire-plugin не находит тесты для JUnit версий 4.х, то в pom.xml в список зависимостей плагина добавить артефакт "surefire-junit4". В общем случае описание плагина будет иметь следующий вид.
<plugin>
   <groupId>org.apache.maven.plugins</groupId>
   <artifactId>maven-surefire-plugin</artifactId>
   <version>2.8</version>
   <dependencies>
      <dependency>
         <groupId>org.apache.maven.surefire</groupId>
         <artifactId>surefire-junit4</artifactId>
         <version>2.8</version>
         </dependency>
   </dependencies>
</plugin>

October 23, 2011

Если раздел скукожился...

    Ставил на настольный РС Archlinux и столкнулся с определенной проблемой, чуть не обернувшейся катастрофой для мозга.
       На HDD была разметка разделов, изображенная на рисунке 1,А.

Рисунок 1

    Размер HDD (sda) состовляет 320 гб (625142448 секторов по 512 байт). Размеры прямоугольников, изображающих разделы, непропорциональны.

  1. sda1 ~ 42 гб - раздел для винды;
  2. sda2 ~ 128 мб - раздел /boot;
  3. sda3 ~ 278 гб - расширенный раздел;
  4. sda5 ~ 4 гб - раздел подкачки;
  5. sda6, sda10 ~ 38 и 5 гб соответственно - разделы /, /opt;
  6. sda4, sda7-9 - разделы NTFS, занимающие оставшуюся часть пространства.
    Разделы пронумерованы не по порядку, т.к. когда-то давно создавались под винду, потом уменьшались и перемещались, освобождая место для линукс.
    Проблема возникла следующая: при установке Archlinux решил я, что sda6 и sda10 необходимо объединить в один раздел. С виду задача довольно тривиальна, если судьба данных на разделах не представляет интереса. Я удалил оба раздела и на их месте создал новый. Делал я прямо из менюшки установки с помощью cfdisk. Операция прошла успешно, но я решил все же посмотреть, что вышло. При последующем запуске cfdisk он выдал довольно мрачное сообщение, касающееся /sda7 и перекрытия разделов (partitions overlapping), после чего работать отказался. Просмотр разделов с помощью fdisk показал следующее:
Disk /dev/sda: 320.1 GB, 320072933376 bytes
255 heads, 63 sectors/track, 38913 cylinders, total 625142448 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0xee4eee4e

   Device Boot      Start         End      Blocks   Id  System
/dev/sda1   *          63    81899369    40949653+   7  HPFS/NTFS
/dev/sda2        81899370    82156409      128520   83  Linux
/dev/sda3        82156534   173293222    45568344+   5  Extended
/dev/sda4       173293223   216331289    21519033+   7  HPFS/NTFS
/dev/sda5        82156536    89963999     3903732   82  Linux swap / Solaris
/dev/sda6        89964063   173293222    41664580   83  Linux
/dev/sda7       216347418   349461944    66557263+   7  HPFS/NTFS
/dev/sda8       349468623   409464719    29998048+   7  HPFS/NTFS
/dev/sda9       409464783   624992759   107763988+   7  HPFS/NTFS
    Нетрудно увидеть, что sda3 стал заканчиваться перед sda4. Это отображено на рисунке 1 Б). При этом проверка таблицы разделов с помощью fdisk выдавала следующее:
Logical partition 7 not entirely in partition 3
Logical partition 8 not entirely in partition 3
Logical partition 9 not entirely in partition 3
Remaining 172803 unallocated 512-byte sectors
    В этот момент времени действительно было видно, что присутствует некоторое перекрытие, но все еще не было понятно, почему никто не ругается на sda4, ведь он первый шел после "помятого" раздела. Во всяком случае очевидным был тот факт, что проблему решать надо, и необходимо было любой ценой спасать sda9 (по личным причинам).

При возникновении любых проблем с разметкой диска ни в коем случае нельзя производить с ним операции записи, или стараться всячески избегать этого. Результаты могут быть весьма неутешительными. По-моему, это очевидно.

    Интересно вышло с виндой. Ей вообще наплевать на ошибки в таблице разделов и она спокойно может работать дальше, что очень коварно.

    Для дальнейших операций с диском подойдет, наверное, любой *nix Live CD. У меня под рукой было несколько, но выбрал я на крайний случай Ubuntu 10.04.
    Перепробовав все известные мне методы и утилиты, а также следуя советам, разбросанным по всяким интернетам, стало ясно, что проблема просто так совсем не решится. В конце-концов появились 2 идеи. Первая пришла из одной статьи и будет рассмотрена второй по порядку, т.к. изначально она показалась мне довольно стремной. Вторая идея пришла в голову сама. Она хоть и предполагает метод "кирки и лопаты", но зато гает дает полную гарантию если и не в результате, то в своих действиях. Поэтому она будет рассмотрена первой.

    1. EDITING "MRB" MANUALLY
   Да, это редактирование MBR вручную. Да, это первое, что пришло в голову. Мазохизм? Нет. Трудно согласится, что поменять цифру, указывающую размер раздела - дело сложное. Используемые мною программы и утилиты ни при каких условиях не соглашались на такое. Что им мешает - ума не приложу. Поменять 4 байта жалко чтоли...
     Этап 1. Получаем MBR. Для этого понадобится какой-нибудь внешний носитель, например, флешка. Копируем MBR на флешку:
sudo dd if=/dev/sda of=/media/ALEXAD_ER/mbr.bak bs=512 count=1
    ALEXAND_ER - имя флешки, mbr.bak - имя файла с MBR.
    После этого делаем еще одну копию, например, mbr2.bak. Открываем её в каком-нибудь HEX-редакторе, например, в ghex. Далее переходим на 446-й байт (0х1ВЕ), к 64-байтной таблице разделов.

Рисунок 2

    Структура записей в этой таблице достаточно хорошо расписана на Вики. Интерисующая нас запись помечена зеленым, а поле, отвечающее за размер раздела, обведено красным. Поскольку таблица загружается прямо в оперативную память, то порядок байт в ней сразу изменен на обратный. Т.о. 0xB1A26E05 следует записывать как 0x056EA2B1, т.е., 91136689. В предыдущих 4-х байтах зранится адрес сектора начала раздела: 0x04E59BF6 = 82156534. Отсюда следует, что раздел заканчивается на секторе 91136689+82156534=173293223. Интересно, что sda4 именно на нем начинается. Решив изменить границу раздела до 625142448-го сектора, я в поле размера записал вместо 0x056EA2B1 число 0xBA4E5D20 (542985914 секторов по 512 байт = ~278 гб). После этого сохраняем mbr2.bak и записываем его содержимое на место MBR:
sudo dd if=/media/ALEXAD_ER/mbr2.bak of=/dev/sda bs=512 count=1
    На этом я решил закончить, но потом понял, что сильно ошибся. Под виндой Paragon Partition Manager показал следующую картину:

Рисунок 3

    И вот тут-то я два раза конкретно стормозил. Казалось бы, что до окончания проблемы оставались считанные минуты, то тут я отсрочил этот момент ещё. Я не обратил внимание на то, что последняя запись в таблице MBR не заполнена нулями, сообщая о том, что 4-й раздел не предусмотрен. На рисунке 2 явно видно, что после 3-го раздела, расширенного, идет 4-й, NTFS. Странно, но я этого не заметил. Ну это еще несколько простительно - HEX-код вполне мог просто поплыть в плазах. Но рассматривая данные Partition Manager, я стормозил конкретно. Посмотрев на invalid-раздел в конце sda, мне показалось, что это неправильно определились свободные 72 мб. Нет, я не заметил, что там было 20.5 Гб, а также, я не заметил, что внутри sda появились свободные все те же 20.5 Гб. В этот момет вполне вероятно, что достаточно было заполнить последнюю запись в MBR нулями, но нет, я стормозил и решил удалить invalid-раздел с помощью Partition Manager. И сразу же получил BSOD. Как серпом... После этого таблица разделов после sda2 совсем с ума сошла. Немного поразмыслив, решил, что после такой ошибки последняя надежда - это 2-й метод.

    2. PARTITION TABLE FROM SCRATCH
     Этот метод предполагает полную перезапись таблицы всех разделов. Его я откопал в статье "Partition-Rescue HOWTO". Хоть было очевидно, что данные с разделов никуда не делись и лежат спокойно на своих местах, идея об удалении таблицы разделов и перезаписи её по старым секторам с помощью fdisk выглядела очень стрёмной. Даже слишком. К счастью, самую первую распечатку fdisk (до редактирования MBR) я сохранил на флешку (так же как и вторую). В принципе, даже если бы я их не сохранил, можно было бы воспользоваться утилитой "gpart", которая читает MBR, ищет старые EBR и может помочь восстановить старую разметку. За угадывание старой разметки ей, конечно, спасибо, а вот восстанавливать это дело я её не доверил бы. Хотя бы потому, что она не нашла злополучный sda4 (хоть и остальные нашла). Короче говоря, с помощью fdisk я создал пустую таблицу разделов и разметил новые назделы по старым секторам, указывая типы разделов. Очень важно размечивать по секторам, а не по цилиндрам, т.к. на одном цилиндре куча секторов и на нужный невозможно будет попасть. После переразметки таблица стала выглядеть следующим образом:
Device Boot      Start         End      Blocks   Id  System
/dev/sda1   *          63    81899369    40949653+   7  HPFS/NTFS
/dev/sda2        81899370    82156409      128520   83  Linux
/dev/sda3        82156534   625142447   271492957    5  Extended
/dev/sda4       173293223   216331289    21519033+   7  HPFS/NTFS
/dev/sda5        82156536    89963999     3903732   82  Linux swap / Solaris
/dev/sda6        89964063   173293222    41664580   83  Linux
/dev/sda7       216347418   349461944    66557263+   7  HPFS/NTFS
/dev/sda8       349468623   409464719    29998048+   7  HPFS/NTFS
/dev/sda9       409464783   624992759   107763988+   7  HPFS/NTFS
    Все прошло успешно, и даже Gparted с Live LD все нормально показывал, а разделы нормально монтировались, и старые данные успешно отображались. При этом проверка таблицы разделов с помощью fdisk выдавала следующее:
Remaining 172803 unallocated 512-byte sectors
    Единственное, что пришлось сделать еще, так это с CD-диска винды запустить mbrfix, а после неё chkdsk. После этого даже винда нормально поднялась.
     Данные, естественно, никуда не пропали.

Ментальный глюк - веб-лифт

    Нужно было подняться на 5-й этаж. Захожу в лифт. Стою секунды две, после чего понимаю, что как-то медленно происходит процесс подъема, вернее не происходит вообще. Короче, превышение времени отклика с зависанием (это при том, что я просто зашел и ничего не нажимал). Смотрю на кнопки на панели и понимаю, что вижу клавишу F5. Сразу возникает мысль "надо обновить, чтоли". Нажимаю. Вуаля - все заработало. Проехав несколько этажей, осознаю, что эта клавиша совсем не "F5", и нажал я совсем не на "обновить"...
    Позже сфоткал (кнопки обычные в лифте) и на компе добавил буквы для передачи ощущений, чтобы выглядело так, как мне  сперва показалось:


Archlinux + pacman autocomplete (bash)

    Чтобы в pacman'е работало автодополнение, необходимо поставить пакет "bash-completion":
pacman -S bash-completion
    После этого в файле "~/.bashrc" добавить следующее:
complete -cf sudo
complete -cf man
     И, наконец, перезапустить терминал.

Gentoo bash color scheme

    Чтобы в терминале цветовая схема была как в Gentoo, в файл
/etc/bash.bashrc
    нужно поместить содержимое этого скрипта по [ссылке].

Archlinux + KDE + Ubuntu fonts

    Год посидел на Ubuntu. Для работы очень хороша. Правда, несколько огорчает нынешняя тенденция развития в сторону Unity. Смотришь на 11.10 - начинаешь понемного чувствовать себя блондинкой. Захотелось больше линукса, чем няшных "тыцалок и выпадалок". Поставил Archlinux. Причем вместе с х-ами и с первого раза. Хэндбук порадовал очень. На гентушный похож.
   Но дело не в этом. Захотелось мне привычные шрифты поставить, а именно, из Ubuntu Font Family.  Покопавшись в том же хендбуке, нашел то, что и хотел.
   Ставим шрифты:
pacman -S ttf-ubuntu-font-family
    Выглядят вполне хорошо. Не плывут, не размазываются. Красота.

October 22, 2011

Authentication is required to mount

    Чтобы при обращении к внешним носителям не выскакивало сообщение "Authentication is required to mount ..." необходимо сделать следующее:

1. открыть с правами администратора файл:
/usr/share/polkit-1/actions/org.freedesktop.udisks.policy
2. в секциях action, имеющих следующие id:

a) org.freedesktop.udisks.filesystem-mount
b) org.freedesktop.udisks.filesystem-mount-system-internal
c) org.freedesktop.udisks.filesystem-umount-others (не всегда обязательно)

    значение элемента <allow_active> изменить с auth_admin на yes, например:
<action id="org.freedesktop.udisks.filesystem-mount">
  <description>Mount a device</description>
  <description xml:lang="da">Montér en enhed</description>
  <message>Authentication is required to mount the device</message>
  <message xml:lang="da">Autorisering er påkrævet for at montere et fil system</message>
  <defaults>
    <allow_any>no</allow_any>
    <allow_inactive>no</allow_inactive>
    <allow_active>yes</allow_active>
  </defaults>
</action>
   
    Следует отметить, что после обновления системы, возвожно, эту операцию придется выполнить вновь.

September 16, 2011

Hello, Mono


    В универе надо делать лабы на C#, а сидеть под виндой совсем не хочется. Да и Visual Studio мне очень не нравится. Даже не смотря на то, что она у меня бесплатная, как для студента. Пришлось разбираться с Mono. Возни получилось больше не с Mono, а с gtk-sharp.

     Установка
    Поскольку под рукой у меня есть Ubuntu и Windows XP, то рассмотрим процесс установки всякого барахла именно для них (несмотря на то, что раздел скачивания на официальном сайте, а так же гугл никто не отменял).

   Установка для Ubuntu
    Установить нам надо три вещи:
  1. Непосредственно Mono
  2. Monodevelop
  3. Gtk-sharp для GUI
    Основных вариантов установки тут у нас целых три. Лично мне больше нравится 1-й.

    Вариант 1. Использование командной строки.
    Для установки вещей из пунктов 1 и 2, выполняем:
sudo apt-get remove mono-gmcs mono-gac mono-utils monodevelop monodoc-browser monodevelop-nunit monodevelop-versioncontrol mono-xsp
    Gtk-sharp можно установить так:
sudo apt-get install gtk-sharp2
    Вариант 2. Использование Ubuntu Software Center.
    В поиск вводим "monodevelop", устанавливаем и получаем почти такой же букет, как в 1-м варианте, но без gtk-sharp.  Для того, чтобы это исправить в поиск вводим "gtk sharp" и скачиваем "GTK# 2.10 suite".
    
    Вариант 3. Собери сам, "будь мужиком".
    Поповоду исходников самого Mono для Ubuntu здесь я толком ничего не нашел. Только упоминание про Synaptic. Исходники Monodevelop здесь, а gtk-sharp здесь, внизу справа.

    Установка для Windows
    Ставить Mono под Windows при существовании Visual Studio, наверное, является мазохизмом. Скачать его можно здесь, но, вероятно, максимум что понадобится, так это "Gtk# for .NET". Вот его-то и можно скачать для того, чтобы приложения с GUI, разработанными с помощью Gtk-sharp, запускались под виндой (при наличии .NET, конечно).

    Первый проект
    В качастве первого проекта будет приложение с Gtk-GUI, позволяющее выполнять простейшие операции со списком граждан, а именно добавление и удаление. Пример работы приложения на рисунке ниже.


    Компоненты, примененные в GUI:
  1. HPaned
  2. VBox
  3. Label
  4. Entry
  5. Button
  6. TreeView
  7. Dialog
  8. Menu
   Данные о гражданах хранятся в объектах класса Citizen, помещенных в System.Collections.Generic.LinkedList<Citizen>. Добавление происходит по нажатию на кнопку "Add", а удаление - по выбору пункта "Delete" в выпадающем меню. Класс Citizen:
namespace lab_01{

    public class Citizen{

        public string name;
        public string passportCode;
        public string nationality;
        
        public Citizen (
                string name,
                string passportCode,
                string nationality){
            this.name = name;
            this.passportCode = passportCode;
            this.nationality  = nationality;
        }
    }
}
   Все исходники проекта размещаются внизу сообщения, а здесь рассмотрим только основные мометны создания GUI с помощью Gtk-sharp, примененные в проекте.

     PopupMenu
    Эта штука доставила больше всего проблем. Для того, чтобы прикрутить её к TreeView пришлось потратить почти два вечера. Это правда. Я сам в шоке.
   Дело в том, что у объектов, классы которых наслебуются от Gtk.Widget есть сигнал "PopupMenu". Казалось бы, что в нем кроется решение. Но это не так, что и сбивает с толку. Этот сигнал в конечном итоге оказался вообще не при чем. Его нужно использовать, если вызывать контекстное меню по сочетанию клавиш, например, "Shift+F10". Для событий от мыши есть сигналы "ButtonPressEvent" и "ButtonReleaseEvent". Т.к. первый работать не хотел, то пришлось использовать второй.
    Добавить сигнал можно 2-мя способами:
    1. При редактировании GUI в свойствах объекта во вкладке "Signals" выбрать необходимый сигнал, указать имя обработчика событий и 2 раза нажать на название сигнала. После этого в файле класса, где описан объект появится запись наподобие этой:
this.citizensView.ButtonReleaseEvent += 
    new Gtk.ButtonReleaseEventHandler(
        this.CitizensViewButtonReleaseEventHandler);
    Сам файл класса, например "MainWindow.cs",  будет размещаться в подкаталоге проекта "gtk-gui".
     2. Сигнал так же можно добавить вручную, в каком-нибудь методе инициализации или конструкторе, записав практически то же самое, что и в строке выше ("практически", потому, что зависит от того, в каком классе строка будет размещаться).
  Здесь у нас citizensView - это Gtk.TreeView, а CitizensViewButtonReleaseEventHandler - название метода-обработчика сигнала:
    private static int MOUSE_RIGHT_BUTTON_CODE = 3;
    private PopupMenu citizensViewPopupMenu;
    
    ................

    protected virtual void CitizensViewButtonReleaseEventHandler (
            object o, Gtk.ButtonReleaseEventArgs args){
        if (RightMouseWasClicked(args.Event)){    
            citizensViewPopupMenu.doPopup();
        }
    }

    protected bool RightMouseWasClicked(Gdk.EventButton evt){
        return evt.Button==MOUSE_RIGHT_BUTTON_CODE;
    }
    MOUSE_RIGHT_BUTTON_CODE - код правой кнопки мыши.
    Класс PopupMenu:
using Gtk;
using System;

namespace lab_01{

    public class PopupMenu{

        Menu popupMenu = new Menu();
        
        public PopupMenu (){
        }
        
        public void addItemByTitleWithHandler(
                string itemTitle, EventHandler handler){
            MenuItem item = new MenuItem(itemTitle);
            item.Activated += handler;
            item.Show();
        
            popupMenu.Append(item);
        }
        
        public void doPopup(){
            popupMenu.Popup(
                null,null,null,3,Gtk.Global.CurrentEventTime);
        }
    }
}
    Инициализация PopupMenu:
    private static string TITLE_DELETE = "Delete";

    ................


    protected void CitizensViewPopupInit(){
        citizensViewPopupMenu = new PopupMenu();
        EventHandler deleteHandler = 
            new EventHandler(CitizensViewDeleteEventHandler);
        citizensViewPopupMenu.addItemByTitleWithHandler(
            TITLE_DELETE, deleteHandler);
    }

    ................

    protected void CitizensViewDeleteEventHandler(
            object sender, EventArgs e){
        DeleteSelectedCitizen();
    }
    TreeView 
   Подробное использование этого класса описано здесь. Остановимся только на основных моментах. 
     1. Инициализация.
  За инициализацию CitizensView в проекте отвечает класс "CitizensViewInitializer". В нем создается модель для TreeView, добавляются колонки, заголовки для них, а так же происходит связывание колонок с аттрибутами класа "Citizen". Рассмотрим код создания модели и инициализации колонки "Name":
    private static string COLUMN_NAME_TITLE = "Name";
    
    ................

    public void doInit(){
            CitizensViewModelInit();
            CitizensViewColumnsInit();
    }
        
    private void CitizensViewModelInit(){
        Gtk.ListStore listStoreModel = 
            new Gtk.ListStore (typeof (Citizen));
        citizensView.Model = listStoreModel;
    }
        
    private void CitizensViewColumnsInit(){
        CitizensViewColumnNameInit();
        CitizensViewColumnPassportCodeInit();
        CitizensViewColumnNationalityInit();
    }
    
    private void CitizensViewColumnNameInit(){
        Gtk.TreeViewColumn nameColumn = new Gtk.TreeViewColumn ();
        Gtk.CellRendererText nameCell = new Gtk.CellRendererText ();
        
        nameColumn.Title = COLUMN_NAME_TITLE;
            
        nameColumn.PackStart (nameCell, true);
        nameColumn.SetCellDataFunc (
            nameCell, new Gtk.TreeCellDataFunc (RenderCitizenName));
            
        citizensView.AppendColumn (nameColumn);
    }
        
    private void RenderCitizenName (
            Gtk.TreeViewColumn column,
            Gtk.CellRenderer cell,
            Gtk.TreeModel model,
            Gtk.TreeIter iter){
        Citizen citizen = (Citizen) model.GetValue (iter, 0);
        (cell as Gtk.CellRendererText).Text = citizen.name;
    }
    
    ................
     Отображение содержимого LinkedList
    protected void RefreshCitizensList(){
        Gtk.ListStore model = (Gtk.ListStore)citizensView.Model;
        model.Clear();
        ShowUpCitizensList(model);
    }
    
    protected void ShowUpCitizensList(Gtk.ListStore model){
        foreach (Citizen citizen in citizensList){
            model.AppendValues(citizen);
        }
    }
    Получение объекта по выбранной строке в TreeView
    Получение объекта по выбранной строке продемонстрировано в методе DeleteSelectedCitizen:
    private static string MESSAGE_SELECT_ITEM =
        "Select something to delete, please!";

    .................

    protected void DeleteSelectedCitizen(){
        TreeSelection selection = citizensView.Selection;
        Gtk.TreeIter iter;
        Gtk.TreeModel model;
        selection.GetSelected(out model, out iter);
            
        if (NothingIsSelected(iter)){
            MessageUI.ShowMessage(MESSAGE_SELECT_ITEM, this);
        } else {
            Citizen citizen = (Citizen)model.GetValue(iter, 0);        
            citizensList.Remove(citizen);
            RefreshCitizensList();
        }
    }
    
    protected bool NothingIsSelected(Gtk.TreeIter iter){
        return iter.Stamp==0;
    }
    Всплывающее сообщение (Notification)
    Метод "ShowMessage" я честно взял где-то после гугления. Добавил всего лишь параметр "Gtk.Window window". Вот описание метода:
public static void ShowMessage(string p, Gtk.Window window){
    Gtk.Dialog dlg =
        new Dialog("Message", window, DialogFlags.Modal);
    dlg.AddButton(Gtk.Stock.Ok, Gtk.ResponseType.Ok);
    dlg.DefaultResponse = Gtk.ResponseType.Ok;
        
    ScrolledWindow sw = new ScrolledWindow();
        
    Label l = new Label(p);
    l.WidthRequest = 285;
    l.Wrap = true;
            
    sw.AddWithViewport(l);
    
    dlg.VBox.PackStart(sw);
    dlg.SetDefaultSize(320, 160);
    
    dlg.ShowAll();
    dlg.Run();
    dlg.Destroy();
}
    Пример его работы:


Пример работы приложения под Windows: