<?xml version="1.0" encoding="utf-8"?>
<page xmlns="http://projectmallard.org/1.0/" xmlns:its="http://www.w3.org/2005/11/its" xmlns:e="http://projectmallard.org/experimental/" type="guide" style="task" id="model-view-controller.py" xml:lang="ko">

<info>
    <title type="text">모델/뷰/컨트롤러 설계(Python)</title>
  <link type="guide" xref="beginner.py#theory"/>
  <link type="next" xref="combobox_multicolumn.py"/>
  <revision version="0.1" date="2012-06-30" status="stub"/>

  <desc>MessageDialog</desc>
  <credit type="author copyright">
    <name>Sebastian Pölsterl</name>
    <email its:translate="no">sebp@k-d-w.org</email>
    <years>2011</years>
  </credit>
  <credit type="author copyright editor">
    <name>Marta Maria Casetti</name>
    <email its:translate="no">mmcasetti@gmail.com</email>
    <years>2012</years>
  </credit>

    <mal:credit xmlns:mal="http://projectmallard.org/1.0/" type="translator copyright">
      <mal:name>조성호</mal:name>
      <mal:email>shcho@gnome.org</mal:email>
      <mal:years>2017, 2018</mal:years>
    </mal:credit>
  </info>

<title>MessageDialog</title>

<links type="section"/>

<section id="overview">
<title>개요</title>

<p><link xref="treeview_simple_liststore.py">TreeView</link> 와 <link xref="combobox.py">ComboBox</link> 위젯은 <em>모델/뷰/컨트롤러</em> 디자인을 기반으로 만들었습니다. <em>모델</em>(<code>Gtk.TreeModel</code> 구현체는 보통 <code>Gtk.TreeStore</code> 또는 <code>Gtk.ListStore</code> 입니다)은 데이터를 저장하고, <em>뷰</em>(예를 들어 <code>Gtk.TreeView</code>, <code>Gtk.ComboBox</code>, <code>Gtk.ComboBoxText</code>가 있습니다)는 바뀐 알림을 보여주고 모델 내용을 보여줍니다. 마지막으로 <em>Controller</em>는 모델의 상태를 (<code>append()</code> 또는 <code>remote()</code> 같은 모델 구현체의 일부 메서드로) 바꾸며, 이 바꾼 내용의 뷰를 (<code>"changed"</code> 같은 시그널)로 알립니다.</p>

</section>

<section id="model">
<title>모델</title>

<p><code>Gtk.TreeModel</code>의 주요 구현체 두가지에 대한 차이점은 <code>Gtk.ListStore</code>에 하위 요소 없이 데이터 한 줄이 있지만, <code>Gtk.TreeStore</code>에는 데이터 한 줄이 들어있고, 각 줄에 하위 줄(이 하위 줄에 하위 줄을 또 넣을 수 있습니다)이 있습니다.</p>

<p>모델의 데이터는 TreeIter나 열 인덱스, <code>Gtk.TreeIter</code>, <code>Gtk.TreePath</code>를 사용하여 가져오거나 수정할 수 있습니다.</p>

<p>파이썬 내장 목록 객체에서 마찬가지로 값을 가져오거나 설정할 수많은 행 갯수를 가져올 <code>len()</code>을 사용하거나 슬라이스를 사용할 수 있습니다. 아니면 <code>append()</code> 메서드에서 새로 삽입한 행 위치를 가리키는 <code>Gtk.TreeIter</code> 인스턴스를 반환합니다. 또한 <code>get_iter()</code>를 호출하여 <code>Gtk.TreeIter</code>를 가져올 수 있습니다.</p>

<p>각각의 노드는 하위 노드를 둘 수 없어 <code>Gtk.ListStore</code>에 한 계층만 넣을 수 있기에, 각 노드의 경로는 접근하고자 하는 행의 인덱스입니다. <code>Gtk.TreeStore</code>의 경우 경로는 인덱스 목록 또는 문자열입니다. 문자열로 된 모양새는 쉼표로 구분한 숫자 목록입니다. 각 숫자는 해당 레벨의 오프셋입니다. 따라서 <code>"0"</code>번째 경로는 최상위(루트) 노드이며, <code>"2:4"</code> 경로는 세번째 노드의 다섯번째 하위 노드입니다.</p>

<p><code>Gtk.TreeModel</code>에 쓸만한 메서드:</p>
<list>
  <item><p><code>get_iter(path)</code>는 <code>path</code>를 가리키는 <code>Gtk.TreeIter</code> 인스턴스를 반환합니다. 콜론으로 구분한 숫자 목록 또는 튜플 값을 넣습니다. 예를 들어 <code>"10:4:0"</code> 문자열은 <code>(10, 4, 0)</code> 튜플과 동일하며, 두 값으로 루트로부터 11번째 떨어진 하위 노드를 가리키도록 깊이 3의 경로를 만듭니다. 11번째의 하위 노드는 5번째 노드, 5번째 하위 노드는 첫번째 노드입니다.</p></item>
  <item><p><code>iter_next(treeiter)</code>는 현재 레벨의 treeiter를 따르는 노드를 가리키는 <code>Gtk.TreeIter</code> 인스턴스를 반환하거나 다음 iter가 없으면 <code>Node</code> 합니다.</p></item>
  <item><p><code>iter_has_child(treeiter)</code>는 <code>treeiter</code>에 하위 구성요소가 있으면 <code>True</code>를, 그렇지 않으면 <code>False</code>를 반환합니다.</p></item>
  <item><p><code>iter_children(treeiter)</code> <code>treeiter</code>의 첫 하위 노드를 가리키는 <code>Gtk.TreeIter</code> 인스턴스를 반환합니다. <code>treeiter</code>에 하위 노드가 없으면 <code>None</code>을 반환합니다.</p></item>
  <item><p><code>get_iter_first()</code>는 트리(경로의 <code>"0"</code>번째)의 첫 Iterator를 가리키는 <code>Gtk.TreeIter</code> 인스턴스를 반환하며 트리가 비어있을 경우는 <code>None</code>을 반환합니다.</p></item>
</list>

<p><code>Gtk.ListStore</code>에 쓸만한 메서드:</p>
<list>
  <item><p><code>append(row)</code>는 리스트 스토어에 각각의 열에 대한 목록 값이 될 수 있는 새 <code>row</code>를 붙입니다. <code>row</code> 값은 생략하거나 <code>None</code> 값을 넣을 수 있으며, 어떨 때는 빈 row를 붙일 수 있습니다. 메서드에서는 붙인 row를 가리키는 <code>Gtk.TreeIter</code>를 반환합니다.</p></item>
  <item><p><code>remove(iter)</code>는 <code>Gtk.ListStore</code>의 <code>iter</code>를 제거하며, iter 값이 유효하면 <code>True</code>를, 그렇지 않으면 <code>False</code>를 반환합니다. 제거하고 나면 <code>iter</code>를 다음 유효 행이 되도록 설정합니다.</p></item>
</list>

<p><code>Gtk.TreeStore</code>에 쓸만한 메서드:</p>
<list>
  <item><p><code>append(parent, row)</code>는 트리 스토어에 새 행을 붙입니다. <code>parent</code>는 올바른 Gtk.TreeIter여야 합니다. 상위 요소가 <code>None</code>이면, 상위 요소의 마지막 하위 요소 다음에 새 행을 붙이며, 상위요소가 <code>None</code>이 아니면, 최상위 레벨에 행을 붙입니다. <code>row</code>은 각 열에 대한 값 목록이거나, 생략하거나, <code>None</code>값일 수 있습니다. 마지막의 경우 빈 행을 붙입니다. 메서드는 붙인 행을 가리키는 <code>Gtk.TreeIter</code>를 반환합니다.</p></item>
  <item><p><code>remove(iter)</code>는 <code>Gtk.ListStore</code>의 <code>iter</code>를 제거하며, iter 값이 유효하면 <code>True</code>를, 그렇지 않으면 <code>False</code>를 반환합니다. 제거하고 나면 <code>iter</code>를 다음 유효 행이 되도록 설정합니다.</p></item>
</list>

</section>

<section id="treeview">
<title>뷰: TreeView의 경우</title>

<p>트리뷰는 하위 구성 요소와 상위 항목을 트리로 보여줍니다. 예시를 보려면 <link xref="treeview_treestore.py">이 예제</link>를 참고하십시오.</p>

<p><code>Gtk.TreeViewColumn</code>는 수직 방향 열을 모아 보여줄 때 사용합니다.</p>

<p><code>Gtk.TreeView</code>에 쓸만한 메서드:</p>
<list>
  <item><p><code>set_model(model)</code>은 이 트리뷰의 모델을 설정합니다. 이 트리뷰가 이미 모델 세트을 들고 있다면, 새 모델을 설정하기 전에 제거랍니다. 모델이 <code>None</code> 상태라면 이전 모델의 설정을 해제합니다.</p></item>
  <item><p><code>get_model()</code>은 이 트리 뷰의 기반 모델을 반환합니다. 모델이 없으면 <code>None</code>을 반환합니다.</p></item>
  <item><p><code>append_column(column)</code>은 열 목록에 <code>column</code>을 추가합니다.</p></item>
  <item><p><code>get_selection()</code>은 트리뷰 관련  <code>Gtk.TreeSelection</code>을 가져옵니다.</p></item>
</list>

<p><code>Gtk.TreeViewColumn</code>에 쓸만한 메서드:</p>
<list>
  <item><p><code>add_attribute(renderer, attribute, value)</code>는 이 열에 속성 매핑을 추가합니다. <code>attribute</code>는 <code>value</code>에서 설정할 <code>renderer</code>의 매개변수입니다.</p></item>
  <item><p><code>pack_start(renderer, expand)</code>는 이 열의 시작 부분에 <code>renderer</code>를 패킹합니다. <code>expand</code> 값이 <code>False</code>면, <code>renderer</code>는 필요한 만큼보다 적은 공간을 할당합니다. 활용하지 않은 공간은 expand 값이 <code>True</code>인 각각의 셀을 균등하게 나눕니다.</p></item>
  <item><p><code>pack_end(renderer, expand)</code>는 열의 마지막 부분의 <code>renderer</code>를 추가합니다. <code>expand</code>값이 <code>False</code>면, <code>renderer</code>는 필요한 만큼보다 적은 공간을 할당합니다. 활용하지 않은 공간은 expand 값이 <code>True</code>인 각각의 셀을 균등하게 나눕니다.</p></item>
  <item><p><code>set_sort_column_id(sort_column_id)</code>는 정렬할 (뷰의) 열 기준으로 모델 열을 설정합니다. 열 헤더를 누를 수 있게 합니다.</p></item>
  <item><p><code>set_sort_indicator(setting)</code>는 열 헤더에 작은 화살표를 나타낼 지 여부를 설정합니다. <code>setting</code> 값은 <code>True</code>(화살표가 나타남) 또는 <code>False</code>일 수 있습니다.</p></item>
  <item><p><code>set_sort_order(order)</code>는 어떤 열을 정렬할 지 정렬 기준을 바꿉니다. <code>order</code> 값은 <code>Gtk.SortType.ASCENDING</code> 또는 <code>Gtk.SortType.DESCENDING</code> 일 수 있습니다.</p></item>
</list>

</section>

<section id="combobox">
<title>뷰: ComboBox의 경우</title>

<p><code>Gtk.ComboBox</code> 는 드롭 다운 메뉴의 항목 섹션을 허용합니다. 예시는 <link xref="combobox.py">이 예제</link>를 참고하십시오. 텍스트 방식의 목록을 선택한다면 더 단순한 <code>Gtk.ComboBoxText</code>를 활용할 수 있습니다. <code>Gtk.ComboBox</code> 와 <code>Gtk.ComboBoxText</code>에는 항목을 넣을 수 있습니다.</p>

<p><code>Gtk.ComboBox</code>에 쓸만한 메서드:</p>
<list>
  <item><p><code>new_with_entry()</code> 정적 메서드에서는 항목으로 비어있는 새 <code>Gtk.ComboBox</code> 를 만들며, <code>new_with_model(model)</code> 정적 메서드에서는 <code>model</code>로 초기화 한 새 모델로 만듭니다. 그리고 <code>new_with_model_and_entry(model)</code> 정적 메서드는 이 두가지 경우를 모두 수행합니다.</p></item>
  <item><p><code>get_active_iter()</code>는 현재 활성 항목을 가리키는 <code>Gtk.TreeIter</code>를 반환합니다. 활성 항목이 없으면 <code>None</code>을 반환합니다.</p></item>
  <item><p><code>set_model(model)</code> 는 콤보 상자의 모델을 <code>model</code>로 설정하며, 이전에 설정한 모델(이 있다면) 설정을 해제합니다. <code>model</code> 값이 <code>None</code>이면, 이미 있던 모델 설정을 해제합니다. 참고로 이 함수는 셀 렌더러 자체를 지우지 않습니다.</p></item>
  <item><p><code>set_entry_text_column(text_column)</code>은 문자열을 가져올 콤보 상자 모델 열을 <code>text_column</code>으로 설정합니다. 이 콤보 상자 모델의 <code>text_column</code>은 <code>str</code> 형식이어야합니다(이 콤보 상자의 “has-entry” 속성을 True로 설정했을 때만 해당합니다).</p></item>
  <item><p><code>set_wrap_width(width)</code> 함수는 콤보 박스의 줄바꿈 너비를 <code>width</code>로 설정합니다. 줄바꿈 너비는 기본적으로 그리드에 팝업을 두고자 할 때 원하는 열 갯수입니다.</p></item>
</list>

<p><code>Gtk.ComboBoxText</code>에 쓸만한 메서드:</p>
<list>
  <item><p><code>new_with_entry()</code> 정적 메서드는 비어있는 새 <code>Gtk.ComboBoxText</code>를 항목을 넣어 만듭니다.</p></item>
  <item><p><code>append_text(text)</code>는 콤보 박스에 저장한 문자열 목록에 <code>text</code>를 추가합니다.</p></item>
  <item><p><code>get_active_text()</code>는 콤보 박스의 현재 활성 문자열을 반환하거나 선택한 항목이 없을 경우는 <code>None</code>을 반환합니다. 콤보 박스에 항목이 있다면 이 함수는 항목의 내용을 반환합니다(꼭 목록 항목일 필요는 없습니다).</p></item>
</list>

</section>

<section id="cellrenderer">
<title>뷰: CellRenderer의 경우</title>

<p>다양한 형식의 <code>Gtk.CellRenderer</code>를 활용하여 데이터를 그리는 뷰입니다.</p>

<p><code>Gtk.CellRenderer</code> 구현체와 쓸만한 메서드:</p>
<list>
  <item><p><code>Gtk.CellRendererText</code> - 셀에 텍스트를 보여줍니다.</p></item>
  <item><p><code>Gtk.CellRendererToggle</code> - 토글 단추 또는 라디오 단추를 셀에 보여줍니다 쓸만한 메서드는:</p>
    <list>
    <item><p><code>set_active(setting)</code> - 셀 렌더러를 활성 처리하거나 비활성 처리합니다.</p></item>
    <item><p><code>get_active()</code> - 셀 렌더러 활성화 혀부를 반환합니다.</p></item>
    <item><p><code>set_radio(radio)</code> - radio가 참이면 셀 렌더러는 라디오 토글을 나타냅니다(예: 그룹 단위로 상호 배타적으로 토글). <code>False</code> 값을 설정하면 확인 상자로 나타냅니다(단독 부울린 옵션).</p></item>
    <item><p><code>get_radio()</code> - 확인 상자 대신 라디오 토글을 보여줄 지 여부를 반환합니다.</p></item>
    </list>
  </item>
  <item><p><code>Gtk.CellRendererPixbuf</code> - 셀 그림을 보여줍니다</p></item>
  <item><p><code>Gtk.CellRendererCombo</code> - 셀 텍스트를 보여줍니다만 <code>Gtk.CellRendererText</code>는 텍스트를 편집할 간단한 항목을 제공하지만 <code>Gtk.CellRendererCombo</code> 에는 텍스트를 편집할 <code>Gtk.ComboBox</code>  위젯도 들어있습니다. 관련 Gtk.Entry 위젯을 넣든 아니든 사용할 수 있으며,  “has-entry” 속성 값에 따라 다릅니다.</p></item>
  <item><p><code>Gtk.CellRendererProgress</code> - 셀에서 진행 표시줄처럼 숫자 값을 나타냅니다. 진행 표시줄의 상단 텍스트로 표시할 수 있습니다</p></item>
  <item><p><code>Gtk.CellRendererSpinner</code> - 셀에서 스핀 움직임 동작을 나타냅니다</p></item>
  <item><p><code>Gtk.CellRendererSpin</code> - 셀에서 스핀 단추를 나타냅니다</p></item>
  <item><p><code>Gtk.CellRendererAccel</code>- 셀에서 키보드 바로 가기 키를 나타냅니다</p></item>
</list>

</section>

<section id="selection">
<title>컨트롤러: Selection</title>

<p>대부분 프로글매에서는 데이터를 표시할 뿐만 아니라 사용자로부터 입력 이벤트를 받아 처리합니다. 이 때, 간단하게 선택 객체 참조를 가져온 후 <code>"changed"</code> 시그널에 연결합니다.</p>

<code mime="text/x-python">
select = tree.get_selection()
select.connect("changed", on_tree_selection_changed)
</code>

<p>그 다음 선택한 행 데이터를 가져오려면:</p>

<code mime="text/x-python">
def on_tree_selection_changed(selection):
    model, treeiter = selection.get_selected()
    if treeiter != None:
        print "You selected", model[treeiter][0]
</code>

<p><code>Gtk.TreeSelection</code>에 쓸만한 메서드:</p>

<list>
  <item><p><code>set_mode(type)</code>는 다음 중 선택 형식을 설정합니다</p>
  <list>
    <item><p><code>Gtk.SelectionMode.NONE</code> - 가능하면 아무것도 선택하지 않음</p></item>
    <item><p><code>Gtk.SelectionMode.SINGLE</code> - 한 개 이하로 선택할 수 있음</p></item>
    <item><p><code>Gtk.SelectionMode.BROWSE</code> - 정확히 요소 한개만 선택합니다. 검색 동작 초기 또는 진행 단계인 경우, 아무것도 선택하지 않을 수도 있습니다. 다른 요소를 선택할 때를 제외하고는 현재 선택한 요소의 선택 상태를 해제할 수 없도록 강제합니다.</p></item>
    <item><p><code>Gtk.SelectionMode.MULTIPLE</code> - 몇가지든 선택할 수 있습니다. 항목을 누를 때마다 선택 상태를 바꿉니다. Ctrl키로 선택 갯수를 늘릴 수 있고, Shift키로 현재 선택한 항목 부터 다음 선택한 하위 항목까지 쭉 선택할 수 있습니다. 일부 위젯에서는 눌러서 끄는 방식으로 일정 범위 항목을 선택할 수 있습니다.</p></item>
  </list>
  </item>
  <item><p><code>get_selected()</code>는 현재 모델을 의미하는 <code>model</code>과 현재 선택한 행을 가리키는 <code>Gtk.TreeIter</code>인 <code>treeiter</code> 또는 아무 행도 선택하지 않았을 경우 None 값이 들어가는 <code>(model, treeiter)</code> 튜플을 반환합니다. 이 메서드는 선택 모드를 <code>Gtk.SelectionMode.MULTIPLE</code>로 선택했을 때는 동작하지 않습니다. 이 경우, 선택한 행의 <code>Gtk.TreePath</code> 안스턴스 목록을 반환하는 <code>get_selected_rows()</code>를 대신 사용하십시오.</p></item>
</list>

</section>

<section id="references">
<title>참고 자료</title>

<list>
  <item><p><link href="http://developer.gnome.org/gtk3/unstable/GtkTreeModel.html">GtkTreeModel</link></p></item>
  <item><p><link href="http://developer.gnome.org/gtk3/unstable/GtkTreeView.html">GtkTreeView</link></p></item>
  <item><p><link href="http://developer.gnome.org/gtk3/unstable/GtkTreeViewColumn.html">GtkTreeViewColumn</link></p></item>
  <item><p><link href="http://developer.gnome.org/gtk3/unstable/GtkComboBox.html">GtkComboBox</link></p></item>
  <item><p><link href="http://developer.gnome.org/gtk3/unstable/GtkCellRenderer.html">GtkCellRenderer</link></p></item>
</list>

</section>

</page>
