В этом посте я расскажу о простом блокноте на языке программирования Vala. Программа создавалась с использованием среды разработки GNOME Builder и редактора интерфейсов Glade.

Внешний вид

Вот так приложение выглядит:

Слева можно видеть список всех заметок, которые автоматически сохраняются в специальной папке. Имя по умолчанию для любой заметки имеет вид даты и времени ее создания. Нажав на последнюю кнопку в хидербаре, можно назначить другое имя. Исходный код приложения находится здесь.

Иерархия элементов интерфейса в редакторе Glade:

Создание заметки

Нажав на первую кнопку, пользователь сразу же создает заметку с именем по умолчанию. За это отвечает следующий метод:

private void on_add_clicked(){
        GLib.File file = GLib.File.new_for_path(directory_path+"/"+date_time());
        try {
            FileUtils.set_contents (file.get_path(), "");//создаем пустой файл
        } catch (Error e) {
            stderr.printf ("Error: %s\n", e.message);
        }
        if(!is_empty(text_view.buffer.text)){
              text_view.buffer.text = "";
        }
         show_notes();//показываем список заметок
      }

Метод date_time, который дает имя заметке:

private string date_time(){
         var now = new DateTime.now_local ();
         return now.format("%d")+"."+now.format("%m")+"."+now.format("%Y")+"  "+now.format("%H")+":"+now.format("%M")+":"+now.format("%S");
    }

Идем дальше. Метод для показа списка:

private void show_notes () {
           list_store.clear();
           list = new GLib.List<string> ();
            try {
            Dir dir = Dir.open (directory_path, 0);
            string? file_name = null;
            while ((file_name = dir.read_name ()) != null) {
                list.append(file_name);
            }
        } catch (FileError err) {
            stderr.printf (err.message);
        }
         Gtk.TreeIter iter;
           foreach (string item in list) {
               list_store.append(out iter);
               list_store.set(iter, Columns.TEXT, item);
           }
       }

Метод вызывается каждый раз, когда нужно обновить список.

Удаление заметки

За удаление заметок отвечает вот такой метод:

private void on_delete_clicked(){
         var selection = tree_view.get_selection();
           selection.set_mode(Gtk.SelectionMode.SINGLE);
           Gtk.TreeModel model;
           Gtk.TreeIter iter;
           if (!selection.get_selected(out model, out iter)) {
               alert("Choose a note");
               return;
           }
           GLib.File file = GLib.File.new_for_path(directory_path+"/"+item);
         var dialog_delete_file = new Gtk.MessageDialog(this, Gtk.DialogFlags.MODAL,Gtk.MessageType.QUESTION, Gtk.ButtonsType.OK_CANCEL, "Delete note "+file.get_basename()+" ?");
         dialog_delete_file.set_title("Question");
         Gtk.ResponseType result = (Gtk.ResponseType)dialog_delete_file.run ();
         dialog_delete_file.destroy();
         if(result==Gtk.ResponseType.OK){
         FileUtils.remove (directory_path+"/"+item);//удаляем файл
         if(file.query_exists()){
            alert("Delete failed");//не получилось удалить
         }else{
             show_notes();
             text_view.buffer.text = "";//очищаем текстовую область
         }
      }
   }

Удаление происходит только после подтверждения этого действия пользователем.

Сохранение заметок

Для сохранение заметок существует следующий код:

private void on_save_clicked(){
         var selection = tree_view.get_selection();
           selection.set_mode(Gtk.SelectionMode.SINGLE);
           Gtk.TreeModel model;
           Gtk.TreeIter iter;
           if (!selection.get_selected(out model, out iter)) {
               alert("Choose a note");
               return;
           }
         if(is_empty(text_view.buffer.text)){
             alert("Nothing to save");
             return;
         }
         GLib.File file = GLib.File.new_for_path(directory_path+"/"+item);
        var dialog_save_file = new Gtk.MessageDialog(this, Gtk.DialogFlags.MODAL,Gtk.MessageType.QUESTION, Gtk.ButtonsType.OK_CANCEL, "Save note "+file.get_basename()+" ?");
         dialog_save_file.set_title("Question");
         Gtk.ResponseType result = (Gtk.ResponseType)dialog_save_file.run ();
         if(result==Gtk.ResponseType.OK){
         try {
            FileUtils.set_contents (file.get_path(), text_view.buffer.text);//записываем в файл содержимое текстовой области
        } catch (Error e) {
            stderr.printf ("Error: %s\n", e.message);
        }
          show_notes();
      }
      dialog_save_file.destroy();
      }

Здесь, при сохранении сначала идет проверка, а есть ли вообще, что сохранять. В случае, если текст не обнаружен, пользователь получает соответствующее сообщение.

Сохранение заметок под другим именем

Для того чтобы поменять имя заметки используется такой метод:

private void on_save_as_clicked(){
        var selection = tree_view.get_selection();
           selection.set_mode(Gtk.SelectionMode.SINGLE);
           Gtk.TreeModel model;
           Gtk.TreeIter iter;
           if (!selection.get_selected(out model, out iter)) {
               alert("Choose a note");//нужно выбрать заметку из списка
               return;
           }
        if(is_empty(text_view.buffer.text)){
             alert("Nothing to save");//нечего сохранять
             return;
         }
        var dialog_save_note = new Gtk.Dialog.with_buttons ("Save note", this, Gtk.DialogFlags.MODAL);
		var content_area = dialog_save_note.get_content_area ();
        entry_name = new Gtk.Entry();
        var label_name = new Gtk.Label.with_mnemonic ("_Name:");
        var hbox = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 20);
        hbox.set_border_width(15);
        hbox.pack_start (label_name, false, true, 0);
        hbox.pack_start (entry_name, true, true, 0);
		content_area.add (hbox);
		dialog_save_note.add_button ("OK", Gtk.ResponseType.OK);
		dialog_save_note.add_button ("CLOSE", Gtk.ResponseType.CLOSE);
		dialog_save_note.response.connect (on_save_response);
		dialog_save_note.show_all ();
      }

В вышеприведенном коде создается простенькое диалоговое окно для ввода нового имени заметки:

Для обработки нажатий на кнопки OK и CLOSE понадобится метод on_save_response:

private void on_save_response (Gtk.Dialog dialog, int response_id) {
        switch (response_id) {
		case Gtk.ResponseType.OK:
		if(is_empty(entry_name.get_text())){
		    alert("Enter the name");//нужно ввести имя
        entry_name.grab_focus();
        return;
		}
		GLib.File select_file = GLib.File.new_for_path(directory_path+"/"+item);
		GLib.File edit_file = GLib.File.new_for_path(directory_path+"/"+entry_name.get_text().strip());
		if (select_file.get_basename() != edit_file.get_basename() && !edit_file.query_exists()){
                FileUtils.rename(select_file.get_path(), edit_file.get_path());//переименовываем файл
                if(!edit_file.query_exists()){
                    alert("Rename failed");//не получилось переименовать
                    return;
                }
                try {
                 FileUtils.set_contents (edit_file.get_path(), text_view.buffer.text);
              } catch (Error e) {
                     stderr.printf ("Error: %s\n", e.message);
            }
            }else{
                if (select_file.get_basename() != edit_file.get_basename()) {
                    alert("A note with the same name already exists");//такое имя уже есть
                    entry_name.grab_focus();
                    return;
                }
                try {
                 FileUtils.set_contents (edit_file.get_path(), text_view.buffer.text);
              } catch (Error e) {
                     stderr.printf ("Error: %s\n", e.message);
             }
            }
            show_notes();
        dialog.destroy();
		break;
	case Gtk.ResponseType.CLOSE:
	        dialog.destroy();
	        break;
	case Gtk.ResponseType.DELETE_EVENT:
		dialog.destroy();
		break;
		}
}

Обязательно нужно проверить существует ли заметка с таким же именем и если существует, то предложить пользователю ввести другое имя.

Отображение текста заметки

Чтобы показать содержимое заметки используется такой код:

private void on_select_item () {
           var selection = tree_view.get_selection();
           selection.set_mode(Gtk.SelectionMode.SINGLE);
           Gtk.TreeModel model;
           Gtk.TreeIter iter;
           if (!selection.get_selected(out model, out iter)) {
               return;
           }
           Gtk.TreePath path = model.get_path(iter);
           var index = int.parse(path.to_string());
           if (index >= 0) {
               item = list.nth_data(index);
           }
          string text;
            try {
                FileUtils.get_contents (directory_path+"/"+item, out text);
            } catch (Error e) {
               stderr.printf ("Error: %s\n", e.message);
            }
            text_view.buffer.text = text;//показываем текст заметки
       }

На этом все! До встречи в следующих постах!


Дата-центр ITSOFT — размещение и аренда серверов и стоек в двух дата-центрах в Москве. За последние годы UPTIME 100%. Размещение GPU-ферм и ASIC-майнеров, аренда GPU-серверов, лицензии связи, SSL-сертификаты, администрирование серверов и поддержка сайтов.