From a1433a45c470950b3f03541257ef54c4bb48d449 Mon Sep 17 00:00:00 2001 From: Alan Fitton Date: Thu, 10 Mar 2011 14:57:38 +0000 Subject: Korean support, thanks Youn! Also filter by tracker. Adding/removing trackers from the state selector every update seems like a waste of cycles, so only refresh when a torrent is added. --- po/LINGUAS | 1 + po/ko.po | 865 +++++++++++++++++++++++++++++++++++++++++++++++ src/torrent.c | 19 ++ src/torrent.h | 1 + src/trg-main-window.c | 46 ++- src/trg-main-window.h | 3 + src/trg-model.c | 6 +- src/trg-model.h | 2 +- src/trg-state-selector.c | 127 ++++++- src/trg-state-selector.h | 10 +- src/trg-torrent-model.c | 19 +- src/trg-torrent-model.h | 6 +- src/util.c | 17 + src/util.h | 3 + 14 files changed, 1102 insertions(+), 23 deletions(-) create mode 100644 po/ko.po diff --git a/po/LINGUAS b/po/LINGUAS index 7673daa..020c98b 100644 --- a/po/LINGUAS +++ b/po/LINGUAS @@ -1 +1,2 @@ de +ko diff --git a/po/ko.po b/po/ko.po new file mode 100644 index 0000000..a5290d9 --- /dev/null +++ b/po/ko.po @@ -0,0 +1,865 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2011-03-08 22:04+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Youn sok Choi \n" +"Language-Team: none\n" +"Language: Korean\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" + +#: src/trg-about-window.c:60 +msgid "A remote client to transmission-daemon." +msgstr "트랜스미션 데몬의 원격 클라이언트." + +#: src/trg-cell-renderer-wanted.c:67 +msgid "Yes" +msgstr "예" + +#: src/trg-cell-renderer-wanted.c:69 +msgid "No" +msgstr "아니오" + +#: src/trg-files-tree-view.c:253 +msgid "High Priority" +msgstr "높음" + +#: src/trg-files-tree-view.c:257 +msgid "Normal Priority" +msgstr "보통" + +#: src/trg-files-tree-view.c:262 +msgid "Low Priority" +msgstr "낮음" + +#: src/trg-files-tree-view.c:273 +msgid "Download" +msgstr "다운로드" + +#: src/trg-files-tree-view.c:282 +msgid "Skip" +msgstr "생략" + +#: src/trg-files-tree-view.c:364 src/trg-general-panel.c:229 +#: src/trg-torrent-tree-view.c:40 +msgid "Name" +msgstr "이름" + +#: src/trg-files-tree-view.c:365 src/trg-general-panel.c:232 +#: src/trg-torrent-tree-view.c:42 +msgid "Size" +msgstr "크기" + +#: src/trg-files-tree-view.c:367 src/trg-peers-tree-view.c:59 +msgid "Progress" +msgstr "진행량" + +#: src/trg-files-tree-view.c:369 +msgid "Wanted" +msgstr "필요함" + +#: src/trg-files-tree-view.c:372 +msgid "Priority" +msgstr "우선순위" + +#: src/trg-general-panel.c:158 src/trg-state-selector.c:147 src/util.c:46 +msgid "Error" +msgstr "오류" + +#: src/trg-general-panel.c:170 +msgid "N/A" +msgstr "알수없음" + +#: src/trg-general-panel.c:234 src/trg-torrent-tree-view.c:56 +msgid "ETA" +msgstr "남은 시간" + +#: src/trg-general-panel.c:236 +msgid "Completed" +msgstr "완료됨" + +#: src/trg-general-panel.c:239 +msgid "Seeders" +msgstr "시더" + +#: src/trg-general-panel.c:241 +msgid "Rate Down" +msgstr "다운로드 속도" + +#: src/trg-general-panel.c:243 src/trg-torrent-tree-view.c:60 +msgid "Downloaded" +msgstr "다운로드 됨" + +#: src/trg-general-panel.c:246 src/trg-torrent-tree-view.c:50 +msgid "Leechers" +msgstr "리쳐" + +#: src/trg-general-panel.c:248 +msgid "Rate Up" +msgstr "업로드 속도" + +#: src/trg-general-panel.c:250 src/trg-torrent-tree-view.c:58 +msgid "Uploaded" +msgstr "업로드 함" + +#: src/trg-general-panel.c:253 src/trg-torrent-tree-view.c:46 +msgid "Status" +msgstr "상태" + +#: src/trg-general-panel.c:255 src/trg-torrent-tree-view.c:62 +msgid "Ratio" +msgstr "비율" + +#: src/trg-general-panel.c:258 +msgid "Location" +msgstr "위치" + +#: src/trg-main-window.c:427 +msgid "BitTorrent Metadata" +msgstr "토렌트 파일" + +#: src/trg-main-window.c:513 +msgid "" +"Unable to retrieve connection settings from GConf. Schema not installed?" +msgstr "연결 정보를 GConf 스키마에서 얻어올 수 없습니다. 스키마를 설치하였는지 확인하십시오." + +#: src/trg-main-window.c:516 +msgid "No hostname set" +msgstr "호스트를 설정하지 않았습니다" + +#: src/trg-main-window.c:519 +msgid "Unknown error getting settings" +msgstr "설정을 얻어오는 중 알수없는 에러가 발생하였습니다" + +#: src/trg-main-window.c:537 +msgid "Connecting..." +msgstr "연결중..." + +#: src/trg-main-window.c:708 +#, c-format +msgid "Remove torrent \"%s\"?" +msgstr "\"%s\" 토렌트를 제거하시겠습니까?" + +#: src/trg-main-window.c:709 +#, c-format +msgid "Remove %d torrents?" +msgstr "%d 개의 토렌트를 제거하시겠습니까?" + +#: src/trg-main-window.c:733 +#, c-format +msgid "Remove and delete torrent \"%s\"?" +msgstr "\"%s\" 토렌트를 삭제하고 제거하시겠습니까?" + +#: src/trg-main-window.c:734 +#, c-format +msgid "Remove and delete %d torrents?" +msgstr "%d 개의 토렌트를 삭제하고 제거하시겠습니까?" + +#: src/trg-main-window.c:804 src/trg-remote-prefs-dialog.c:612 +msgid "General" +msgstr "일반" + +#: src/trg-main-window.c:812 +msgid "Trackers" +msgstr "트래커" + +#: src/trg-main-window.c:820 +msgid "Files" +msgstr "파일" + +#: src/trg-main-window.c:827 src/trg-remote-prefs-dialog.c:277 +#: src/trg-torrent-props-dialog.c:242 +msgid "Peers" +msgstr "피어" + +#: src/trg-main-window.c:929 +#, c-format +msgid "Request %d/%d failed: %s" +msgstr "%d/%d 요청 실패: %s" + +#: src/trg-main-window.c:1442 +msgid "No Limit" +msgstr "제한없음" + +#: src/trg-main-window.c:1479 src/trg-toolbar.c:238 +msgid "Properties" +msgstr "속성" + +#: src/trg-main-window.c:1482 src/trg-toolbar.c:231 +msgid "Resume" +msgstr "다시시작" + +#: src/trg-main-window.c:1485 src/trg-toolbar.c:234 +msgid "Pause" +msgstr "멈춤" + +#: src/trg-main-window.c:1488 +msgid "Verify" +msgstr "검사" + +#: src/trg-main-window.c:1491 +msgid "Re-announce" +msgstr "다시 알림" + +#: src/trg-main-window.c:1494 src/trg-torrent-move-dialog.c:99 +#: src/trg-torrent-move-dialog.c:106 +msgid "Move" +msgstr "옮기기" + +#: src/trg-main-window.c:1497 src/trg-menu-bar.c:307 src/trg-toolbar.c:242 +msgid "Remove" +msgstr "제거" + +#: src/trg-main-window.c:1500 +msgid "Remove & Delete" +msgstr "파일을 삭제하고 제거" + +#: src/trg-main-window.c:1506 src/trg-main-window.c:1550 +msgid "Down Limit" +msgstr "다운로드 속도제한" + +#: src/trg-main-window.c:1511 src/trg-main-window.c:1555 +msgid "Up Limit" +msgstr "업로드 속도제한" + +#: src/trg-main-window.c:1533 src/trg-toolbar.c:215 +msgid "Connect" +msgstr "연결" + +#: src/trg-main-window.c:1537 src/trg-toolbar.c:218 +msgid "Disconnect" +msgstr "연결 끊기" + +#: src/trg-main-window.c:1541 src/trg-toolbar.c:221 +#: src/trg-trackers-tree-view.c:251 src/trg-trackers-tree-view.c:278 +msgid "Add" +msgstr "파일 추가" + +#: src/trg-main-window.c:1544 +msgid "Add from URL" +msgstr "주소 추가" + +#: src/trg-main-window.c:1684 +msgid "Graph" +msgstr "그래프" + +#: src/trg-menu-bar.c:208 +msgid "_View" +msgstr "보기(_V)" + +#: src/trg-menu-bar.c:213 +msgid "State selector" +msgstr "상태 선택" + +#: src/trg-menu-bar.c:218 +msgid "Torrent _details" +msgstr "토렌트 상세정보(_D)" + +#: src/trg-menu-bar.c:223 +msgid "_Statistics" +msgstr "통계(_S)" + +#: src/trg-menu-bar.c:237 +msgid "_Options" +msgstr "설정(_O)" + +#: src/trg-menu-bar.c:243 +msgid "_Local Preferences" +msgstr "로컬 설정(_L)" + +#: src/trg-menu-bar.c:248 +msgid "_Remote Preferences" +msgstr "원격 설정(_R)" + +#: src/trg-menu-bar.c:257 +msgid "_File" +msgstr "파일(_F)" + +#: src/trg-menu-bar.c:262 +msgid "_Connect" +msgstr "연결(_C)" + +#: src/trg-menu-bar.c:265 +msgid "_Disconnect" +msgstr "연결 끊기(_D)" + +#: src/trg-menu-bar.c:268 +msgid "_Add" +msgstr "파일 추가(_A)" + +#: src/trg-menu-bar.c:271 +msgid "Add from _URL" +msgstr "주소 추가(_U)" + +#: src/trg-menu-bar.c:275 +msgid "_Quit" +msgstr "종료(_Q)" + +#: src/trg-menu-bar.c:284 +msgid "_Torrent" +msgstr "토렌트(_T)" + +#: src/trg-menu-bar.c:292 +msgid "_Resume" +msgstr "다시 시작(_R)" + +#: src/trg-menu-bar.c:295 +msgid "_Pause" +msgstr "일시중지(_P)" + +#: src/trg-menu-bar.c:298 +msgid "_Verify" +msgstr "검사(_V)" + +#: src/trg-menu-bar.c:302 +msgid "Re-_announce" +msgstr "다시 알림(_A)" + +#: src/trg-menu-bar.c:304 +msgid "_Move" +msgstr "위치설정(_M)" + +#: src/trg-menu-bar.c:311 +msgid "Remove and Delete" +msgstr "파일을 삭제하고 제거" + +#: src/trg-menu-bar.c:322 +msgid "_Help" +msgstr "도움말(_H)" + +#: src/trg-menu-bar.c:328 +msgid "_About" +msgstr "정보(_A)" + +#: src/trg-peers-tree-view.c:48 +msgid "IP" +msgstr "IP" + +#: src/trg-peers-tree-view.c:49 +msgid "Host" +msgstr "호스트" + +#: src/trg-peers-tree-view.c:52 +msgid "Country" +msgstr "국가" + +#: src/trg-peers-tree-view.c:55 src/trg-torrent-tree-view.c:52 +msgid "Down Speed" +msgstr "다운로드 속도" + +#: src/trg-peers-tree-view.c:57 src/trg-torrent-tree-view.c:54 +msgid "Up Speed" +msgstr "업로드 속도" + +#: src/trg-peers-tree-view.c:61 +msgid "Flags" +msgstr "플래그" + +#: src/trg-peers-tree-view.c:63 +msgid "Client" +msgstr "클라이언트" + +#: src/trg-preferences-dialog.c:235 +msgid "Features" +msgstr "기능" + +#: src/trg-preferences-dialog.c:237 +msgid "Show graph" +msgstr "그래프 보이기" + +#: src/trg-preferences-dialog.c:242 +msgid "System Tray" +msgstr "시스템 알림영역" + +#: src/trg-preferences-dialog.c:244 +msgid "Show in system tray" +msgstr "시스템 알림영역에 표시" + +#: src/trg-preferences-dialog.c:250 +msgid "Minimise to system tray" +msgstr "최소화했을 때 시스템 알림영역으로 보내기" + +#: src/trg-preferences-dialog.c:259 +msgid "Torrent added notifications" +msgstr "토렌트가 추가되면 팝업 알림 표시" + +#: src/trg-preferences-dialog.c:268 +msgid "Torrent complete notifications" +msgstr "다운로드가 완료되면 팝업 알림 표시" + +#: src/trg-preferences-dialog.c:288 +msgid "Server" +msgstr "서버" + +#: src/trg-preferences-dialog.c:291 +msgid "Host:" +msgstr "호스트:" + +#: src/trg-preferences-dialog.c:294 +msgid "Port:" +msgstr "포트:" + +#: src/trg-preferences-dialog.c:296 +msgid "Automatically connect" +msgstr "시작시 자동으로 연결" + +#: src/trg-preferences-dialog.c:300 +msgid "SSL" +msgstr "SSL" + +#: src/trg-preferences-dialog.c:306 +msgid "Update interval:" +msgstr "업데이트 주기" + +#: src/trg-preferences-dialog.c:309 +msgid "Authentication" +msgstr "인증" + +#: src/trg-preferences-dialog.c:312 +msgid "Username:" +msgstr "사용자 이름:" + +#: src/trg-preferences-dialog.c:316 +msgid "Password:" +msgstr "암호:" + +#: src/trg-preferences-dialog.c:343 src/trg-toolbar.c:257 +msgid "Local Preferences" +msgstr "로컬 설정" + +#: src/trg-preferences-dialog.c:355 +msgid "Connection" +msgstr "연결" + +#: src/trg-preferences-dialog.c:359 +msgid "Desktop" +msgstr "바탕 화면" + +#: src/trg-remote-prefs-dialog.c:218 src/trg-torrent-props-dialog.c:175 +msgid "Bandwidth" +msgstr "속도" + +#: src/trg-remote-prefs-dialog.c:221 +msgid "Limit download speed (KB/s)" +msgstr "다운로드 속도 제한 (KB/s)" + +#: src/trg-remote-prefs-dialog.c:240 +msgid "Limit upload speed (KB/s)" +msgstr "업로드 속도 제한 (KB/s)" + +#: src/trg-remote-prefs-dialog.c:257 src/trg-state-selector.c:145 +#: src/trg-torrent-props-dialog.c:219 +msgid "Seeding" +msgstr "배포" + +#: src/trg-remote-prefs-dialog.c:260 +msgid "Seed ratio limit" +msgstr "배포 비율 제한" + +#: src/trg-remote-prefs-dialog.c:284 +msgid "Global peer limit" +msgstr "전체 최대 피어" + +#: src/trg-remote-prefs-dialog.c:291 +msgid "Per torrent peer limit" +msgstr "토렌트 당 최대 피어 수" + +#: src/trg-remote-prefs-dialog.c:306 +msgid "Retest" +msgstr "다시 검사" + +#: src/trg-remote-prefs-dialog.c:316 +msgid "Port is open" +msgstr "포트가 열림" + +#: src/trg-remote-prefs-dialog.c:320 +msgid "Port is closed" +msgstr "포트가 닫힘" + +#: src/trg-remote-prefs-dialog.c:336 src/trg-remote-prefs-dialog.c:420 +msgid "Port test" +msgstr "포트 검사" + +#: src/trg-remote-prefs-dialog.c:337 +msgid "Testing..." +msgstr "검사 중..." + +#: src/trg-remote-prefs-dialog.c:359 src/trg-remote-prefs-dialog.c:451 +#, c-format +msgid "Blocklist (%ld entries)" +msgstr "차단 목록 사용 (%ld 개의 규칙 포함)" + +#: src/trg-remote-prefs-dialog.c:382 +msgid "Updating..." +msgstr "업데이트 중..." + +#: src/trg-remote-prefs-dialog.c:401 +msgid "Required" +msgstr "암호화 요구" + +#: src/trg-remote-prefs-dialog.c:402 +msgid "Preferred" +msgstr "암호화 선호" + +#: src/trg-remote-prefs-dialog.c:403 +msgid "Tolerated" +msgstr "암호화 허용" + +#: src/trg-remote-prefs-dialog.c:412 +msgid "Encryption" +msgstr "암호화 모드" + +#: src/trg-remote-prefs-dialog.c:418 +msgid "Peer port" +msgstr "피어 포트" + +#: src/trg-remote-prefs-dialog.c:421 +msgid "Test" +msgstr "테스트" + +#: src/trg-remote-prefs-dialog.c:427 +msgid "Random peer port on start" +msgstr "시작할 때 임의의 포트를 선택" + +#: src/trg-remote-prefs-dialog.c:433 +msgid "Peer port forwarding" +msgstr "피어 포트 포워딩" + +#: src/trg-remote-prefs-dialog.c:440 +msgid "Peer exchange (PEX)" +msgstr "피어 교환 (PEX)" + +#: src/trg-remote-prefs-dialog.c:446 +msgid "Local peer discovery" +msgstr "로컬 피어 검색 (LPD)" + +#: src/trg-remote-prefs-dialog.c:461 +msgid "Update" +msgstr "업데이트" + +#: src/trg-remote-prefs-dialog.c:477 +msgid "Blocklist URL:" +msgstr "차단목록 주소:" + +#: src/trg-remote-prefs-dialog.c:498 +msgid "Download directory" +msgstr "다운로드 위치" + +#: src/trg-remote-prefs-dialog.c:501 +msgid "Incomplete download dir" +msgstr "미 완료 토렌트 위치" + +#: src/trg-remote-prefs-dialog.c:517 +msgid "Torrent done script" +msgstr "토렌트가 완료되면 스크립트 불러오기" + +#: src/trg-remote-prefs-dialog.c:538 +msgid "Cache size (MB)" +msgstr "캐쉬 크기 (MB)" + +#: src/trg-remote-prefs-dialog.c:543 +msgid "Rename partial files" +msgstr "완료되지 않은 파일 이름 바꾸기" + +#: src/trg-remote-prefs-dialog.c:551 +msgid "Trash original torrent files" +msgstr "토렌트 파일을 휴지통에 버림" + +#: src/trg-remote-prefs-dialog.c:558 +msgid "Start added torrents" +msgstr "추가되면 시작하기" + +#: src/trg-remote-prefs-dialog.c:584 src/trg-toolbar.c:261 +msgid "Remote Preferences" +msgstr "원격 설정" + +#: src/trg-remote-prefs-dialog.c:617 +msgid "Connections" +msgstr "연결" + +#: src/trg-remote-prefs-dialog.c:622 src/trg-torrent-props-dialog.c:316 +msgid "Limits" +msgstr "제한" + +#: src/trg-state-selector.c:131 +msgid "All" +msgstr "모두" + +#: src/trg-state-selector.c:134 +msgid "Downloading" +msgstr "다운로드 중" + +#: src/trg-state-selector.c:137 +msgid "Paused" +msgstr "멈춤" + +#: src/trg-state-selector.c:139 +msgid "Checking" +msgstr "확인 중" + +#: src/trg-state-selector.c:141 +msgid "Complete" +msgstr "완료 됨" + +#: src/trg-state-selector.c:143 +msgid "Incomplete" +msgstr "미완료" + +#: src/trg-stats-dialog.c:267 +msgid "Statistics" +msgstr "통계" + +#: src/trg-stats-dialog.c:286 +msgid "Download Total" +msgstr "전체 다운로드량" + +#: src/trg-stats-dialog.c:288 +msgid "Upload Total" +msgstr "전체 업로드량" + +#: src/trg-stats-dialog.c:290 +msgid "Files Added" +msgstr "추가된 파일 갯수" + +#: src/trg-stats-dialog.c:292 +msgid "Session Count" +msgstr "세션 횟수" + +#: src/trg-stats-dialog.c:294 +msgid "Time Active" +msgstr "사용 시간" + +#: src/trg-stats-dialog.c:299 +msgid "Statistic" +msgstr "통계 자료 이름" + +#: src/trg-stats-dialog.c:301 +msgid "Session" +msgstr "세션" + +#: src/trg-stats-dialog.c:304 +msgid "Cumulative" +msgstr "누적" + +#: src/trg-status-bar.c:74 +#, c-format +msgid "Connected to Transmission %g, getting torrents..." +msgstr "트랜스미션에 접속됨 %g, 토렌트 정보를 받는 중" + +#: src/trg-status-bar.c:96 +#, c-format +msgid "" +"%d torrents .. Down %s, Up %s .. %d seeding, %d downloading, %d paused" +msgstr "%d 개의 토렌트 .. 다운로드 속도: %s, 업로드 속도: %s .. %d 개 배포 중, %d 개 다운로드 중, %d 개 멈춤" + +#: src/trg-toolbar.c:246 +msgid "Remove with data" +msgstr "데이터와 함께 제거" + +#: src/trg-torrent-add-url-dialog.c:89 +msgid "Start Paused" +msgstr "멈춤 상태로 시작" + +#: src/trg-torrent-add-url-dialog.c:92 +msgid "Add torrent from URL" +msgstr "주소 추가" + +#: src/trg-torrent-graph.c:398 +msgid "Total Uploading" +msgstr "전체 업로드" + +#: src/trg-torrent-graph.c:406 +msgid "Total Downloading" +msgstr "전체 다운로드" + +#: src/trg-torrent-move-dialog.c:96 +msgid "Location:" +msgstr "위치:" + +#: src/trg-torrent-move-dialog.c:154 +#, c-format +msgid "Move %s" +msgstr "%s 옮기기" + +#: src/trg-torrent-move-dialog.c:157 +#, c-format +msgid "Move %d torrents" +msgstr "%d 개의 토렌트 옮기기" + +#: src/trg-torrent-props-dialog.c:179 +msgid "Honor global limits" +msgstr "전체 제한 존중" + +#: src/trg-torrent-props-dialog.c:186 +msgid "Low" +msgstr "낮음" + +#: src/trg-torrent-props-dialog.c:187 +msgid "Normal" +msgstr "보통" + +#: src/trg-torrent-props-dialog.c:188 +msgid "High" +msgstr "높음" + +#: src/trg-torrent-props-dialog.c:191 +msgid "Torrent priority:" +msgstr "토렌트 우선 순위" + +#: src/trg-torrent-props-dialog.c:194 +msgid "Limit download speed (Kbps)" +msgstr "다운로드 속도 제한 (KB/s)" + +#: src/trg-torrent-props-dialog.c:207 +msgid "Limit upload speed (Kbps)" +msgstr "업로드 속도 제한 (KB/s)" + +#: src/trg-torrent-props-dialog.c:223 +msgid "Use global settings" +msgstr "전체 설정 사용" + +#: src/trg-torrent-props-dialog.c:225 +msgid "Stop seeding at ratio" +msgstr "비율이 다음에 도달할 때까지만 배포" + +#: src/trg-torrent-props-dialog.c:227 +msgid "Seed regardless of ratio" +msgstr "비율과 상관없이 배포" + +#: src/trg-torrent-props-dialog.c:230 +msgid "Seed ratio mode:" +msgstr "배포 비율 설정" + +#: src/trg-torrent-props-dialog.c:238 +msgid "Seed ratio limit:" +msgstr "배포 제한 비율" + +#: src/trg-torrent-props-dialog.c:249 +msgid "Peer limit:" +msgstr "최대 피어" + +#: src/trg-torrent-props-dialog.c:282 +#, c-format +msgid "Multiple (%d) torrent properties" +msgstr "%d 개의 토렌트 정보" + +#: src/trg-torrent-tree-view.c:44 +msgid "Done" +msgstr "완료" + +#: src/trg-torrent-tree-view.c:48 +msgid "Seeds" +msgstr "시더" + +#: src/trg-trackers-tree-view.c:152 +msgid "Tier" +msgstr "티어" + +#: src/trg-trackers-tree-view.c:165 +msgid "Announce URL" +msgstr "알림 주소" + +#: src/trg-trackers-tree-view.c:175 +msgid "Scrape URL" +msgstr "스크랩 주소" + +#: src/trg-trackers-tree-view.c:272 +msgid "Delete" +msgstr "삭제" + +#: src/util.c:55 +msgid "JSON decoding error." +msgstr "JSON 디코드 오류." + +#: src/util.c:60 +msgid "Server responded, but with no result." +msgstr "서버가 응답하였으나 결과가 없습니다." + +#: src/util.c:64 +#, c-format +msgid "Request failed with HTTP code %d" +msgstr "요청이 실패하였습니다. HTTP 코드 : %d" + +#: src/util.c:127 +msgid "None" +msgstr "없음" + +#: src/util.c:137 +#, c-format +msgid "%'u byte" +msgid_plural "%'u bytes" +msgstr[0] "%'u byte" +msgstr[1] "%'u bytes" + +#: src/util.c:143 +#, c-format +msgid "%'.1f KB" +msgstr "%'.1f KB" + +#: src/util.c:146 +#, c-format +msgid "%'.1f MB" +msgstr "%'.1f MB" + +#: src/util.c:149 +#, c-format +msgid "%'.1f GB" +msgstr "%'.1f GB" + +#: src/util.c:161 +#, c-format +msgid "%.1f KB/s" +msgstr "%.1f KB/s" + +#: src/util.c:163 +#, c-format +msgid "%.2f MB/s" +msgstr "%.2f MB/s" + +#: src/util.c:165 +#, c-format +msgid "%.1f MB/s" +msgstr "%.1f MB/s" + +#: src/util.c:167 +#, c-format +msgid "%.2f GB/s" +msgstr "%.2f GB/s" + +#: src/util.c:201 +#, c-format +msgid "%d day" +msgid_plural "%d days" +msgstr[0] "%d 일" +msgstr[1] "%d 일" + +#: src/util.c:202 +#, c-format +msgid "%d hour" +msgid_plural "%d hours" +msgstr[0] "%d 시간" +msgstr[1] "%d 시간" + +#: src/util.c:204 +#, c-format +msgid "%d minute" +msgid_plural "%d minutes" +msgstr[0] "%d 분" +msgstr[1] "%d 분" + +#: src/util.c:207 +#, c-format +msgid "%ld second" +msgid_plural "%ld seconds" +msgstr[0] "%ld 초" +msgstr[1] "%ld 초" diff --git a/src/torrent.c b/src/torrent.c index def9cbc..f45cc31 100644 --- a/src/torrent.c +++ b/src/torrent.c @@ -23,6 +23,7 @@ #include "torrent.h" #include "protocol-constants.h" +#include "util.h" JsonArray *torrent_get_peers(JsonObject * t) { @@ -208,6 +209,24 @@ gchar *torrent_get_status_string(gint64 value) } } +gboolean torrent_has_tracker(JsonObject *t, GRegex *rx, gchar *search) +{ + JsonArray *trackers = torrent_get_trackers(t); + int i; + + for (i = 0; i < json_array_get_length(trackers); i++) { + JsonObject *tracker = json_array_get_object_element(trackers, i); + const gchar *trackerAnnounce = tracker_get_announce(tracker); + gchar *trackerAnnounceHost = trg_uri_host_extract(rx, trackerAnnounce); + int cmpResult = g_strcmp0(trackerAnnounceHost, search); + g_free(trackerAnnounceHost); + if (cmpResult == 0) + return TRUE; + } + + return FALSE; +} + gint64 tracker_get_id(JsonObject * t) { return json_object_get_int_member(t, FIELD_ID); diff --git a/src/torrent.h b/src/torrent.h index 16102e4..226cd4e 100644 --- a/src/torrent.h +++ b/src/torrent.h @@ -68,6 +68,7 @@ gboolean torrent_get_download_limited(JsonObject * t); gdouble torrent_get_seed_ratio_limit(JsonObject * t); gint64 torrent_get_seed_ratio_mode(JsonObject * t); gint64 torrent_get_peer_limit(JsonObject * t); +gboolean torrent_has_tracker(JsonObject *t, GRegex *rx, gchar *search); JsonArray *get_torrents(JsonObject * response); diff --git a/src/trg-main-window.c b/src/trg-main-window.c index ed25791..1b67687 100644 --- a/src/trg-main-window.c +++ b/src/trg-main-window.c @@ -40,6 +40,7 @@ #include "util.h" #include "requests.h" #include "session-get.h" +#include "torrent.h" #include "protocol-constants.h" #include "trg-main-window.h" @@ -72,13 +73,13 @@ static void torrent_event_notification(TrgTorrentModel * model, gchar * icon, gchar * desc, gint tmout, gchar * prefKey, GtkTreeIter * iter, - gpointer * data); + gpointer data); static void on_torrent_completed(TrgTorrentModel * model, - GtkTreeIter * iter, gpointer * data); + GtkTreeIter * iter, gpointer data); static void on_torrent_added(TrgTorrentModel * model, GtkTreeIter * iter, - gpointer * data); + gpointer data); static gboolean delete_event(GtkWidget * w, GdkEvent * event, - gpointer * data); + gpointer data); static void destroy_window(GtkWidget * w, gpointer data); static void torrent_tv_onRowActivated(GtkTreeView * treeview, GtkTreePath * path, @@ -268,7 +269,7 @@ static gboolean update_selected_torrent_notebook(TrgMainWindow * win, static void torrent_event_notification(TrgTorrentModel * model, gchar * icon, gchar * desc, gint tmout, gchar * prefKey, - GtkTreeIter * iter, gpointer * data) + GtkTreeIter * iter, gpointer data) { TrgMainWindowPrivate *priv; gchar *name; @@ -305,24 +306,30 @@ static void torrent_event_notification(TrgTorrentModel * model, } static void on_torrent_completed(TrgTorrentModel * model, - GtkTreeIter * iter, gpointer * data) + GtkTreeIter * iter, gpointer data) { torrent_event_notification(model, GTK_STOCK_APPLY, - "This torrent has completed.", 8000, + "This torrent has completed.", TORRENT_COMPLETE_NOTIFY_TMOUT, TRG_GCONF_KEY_COMPLETE_NOTIFY, iter, data); } +static void on_torrent_addremove(TrgTorrentModel *model, gpointer data) +{ + TrgMainWindowPrivate *priv = TRG_MAIN_WINDOW_GET_PRIVATE(data); + trg_state_selector_update_trackers(priv->stateSelector, priv->client->torrents, priv->client->updateSerial); +} + static void on_torrent_added(TrgTorrentModel * model, - GtkTreeIter * iter, gpointer * data) + GtkTreeIter * iter, gpointer data) { torrent_event_notification(model, GTK_STOCK_ADD, - "This torrent has been added.", 3000, + "This torrent has been added.", TORRENT_ADD_NOTIFY_TMOUT, TRG_GCONF_KEY_ADD_NOTIFY, iter, data); } static gboolean delete_event(GtkWidget * w, GdkEvent * event G_GNUC_UNUSED, - gpointer * data G_GNUC_UNUSED) + gpointer data G_GNUC_UNUSED) { TrgMainWindowPrivate *priv = TRG_MAIN_WINDOW_GET_PRIVATE(w); int width, height; @@ -1043,9 +1050,20 @@ trg_torrent_tree_view_visible_func(GtkTreeModel * model, TORRENT_COLUMN_FLAGS, &flags, TORRENT_COLUMN_NAME, &name, -1); - if (criteria != 0 && !(flags & criteria)) { - visible = FALSE; - } else if (name != NULL) { + if (criteria != 0) { + if (criteria & FILTER_FLAG_TRACKER) { + gchar *text = trg_state_selector_get_selected_text(priv->stateSelector); + JsonObject *json = NULL; + gtk_tree_model_get(model, iter, TORRENT_COLUMN_JSON, &json, -1); + + if (!torrent_has_tracker(json, trg_state_selector_get_url_host_regex(priv->stateSelector), text)) + visible = FALSE; + } else if (!(flags & criteria)) { + visible = FALSE; + } + } + + if (visible && name != NULL) { const gchar *filterText = gtk_entry_get_text(GTK_ENTRY(priv->filterEntry)); if (strlen(filterText) > 0) { @@ -1762,6 +1780,8 @@ static GObject *trg_main_window_constructor(GType type, G_CALLBACK(on_torrent_completed), self); g_signal_connect(priv->torrentModel, "torrent-added", G_CALLBACK(on_torrent_added), self); + g_signal_connect(priv->torrentModel, "torrent-addremove", + G_CALLBACK(on_torrent_addremove), self); priv->filteredTorrentModel = gtk_tree_model_filter_new(GTK_TREE_MODEL(priv->torrentModel), diff --git a/src/trg-main-window.h b/src/trg-main-window.h index fd413c6..cdba421 100644 --- a/src/trg-main-window.h +++ b/src/trg-main-window.h @@ -57,6 +57,9 @@ typedef struct { #define TORRENT_GET_MODE_INTERACTION 1 #define TORRENT_GET_MODE_UPDATE 2 +#define TORRENT_COMPLETE_NOTIFY_TMOUT 8000 +#define TORRENT_ADD_NOTIFY_TMOUT 3000 + GType trg_main_window_get_type(void); gboolean trg_add_from_filename(TrgMainWindow * win, gchar * fileName); void on_session_set(JsonObject * response, int status, gpointer data); diff --git a/src/trg-model.c b/src/trg-model.c index e41c4b3..5796507 100644 --- a/src/trg-model.c +++ b/src/trg-model.c @@ -43,12 +43,13 @@ trg_model_remove_removed_foreachfunc(GtkTreeModel * model, return FALSE; } -void +guint trg_model_remove_removed(GtkListStore * model, gint serial_column, gint64 currentSerial) { struct trg_model_remove_removed_foreachfunc_args args; GList *li; + guint removed = 0; args.toRemove = NULL; args.currentSerial = currentSerial; @@ -60,9 +61,12 @@ trg_model_remove_removed(GtkListStore * model, gint serial_column, li = g_list_previous(li)) { gtk_list_store_remove(model, (GtkTreeIter *) li->data); gtk_tree_iter_free((GtkTreeIter *) li->data); + removed++; } g_list_free(args.toRemove); } + + return removed; } struct find_existing_item_foreach_args { diff --git a/src/trg-model.h b/src/trg-model.h index b20cbe4..987cfca 100644 --- a/src/trg-model.h +++ b/src/trg-model.h @@ -22,7 +22,7 @@ #include -void trg_model_remove_removed(GtkListStore * model, gint serial_column, +guint trg_model_remove_removed(GtkListStore * model, gint serial_column, gint64 currentSerial); gboolean diff --git a/src/trg-state-selector.c b/src/trg-state-selector.c index 1ae4247..f20a407 100644 --- a/src/trg-state-selector.c +++ b/src/trg-state-selector.c @@ -18,11 +18,13 @@ */ #include +#include #include #include #include "torrent.h" #include "trg-state-selector.h" +#include "util.h" enum { SELECTOR_STATE_CHANGED, @@ -38,8 +40,16 @@ typedef struct _TrgStateSelectorPrivate TrgStateSelectorPrivate; struct _TrgStateSelectorPrivate { guint flag; + GHashTable *trackers; + GRegex *urlHostRegex; }; +GRegex *trg_state_selector_get_url_host_regex(TrgStateSelector *s) +{ + TrgStateSelectorPrivate *priv = TRG_STATE_SELECTOR_GET_PRIVATE(s); + return priv->urlHostRegex; +} + guint32 trg_state_selector_get_flag(TrgStateSelector * s) { TrgStateSelectorPrivate *priv = TRG_STATE_SELECTOR_GET_PRIVATE(s); @@ -85,6 +95,104 @@ static void state_selection_changed(GtkTreeSelection * selection, signals[SELECTOR_STATE_CHANGED], 0, priv->flag); } +static GtkTreeRowReference *quick_tree_ref_new(GtkTreeModel *model, GtkTreeIter *iter) +{ + GtkTreePath *path = gtk_tree_model_get_path(model, iter); + GtkTreeRowReference *rr = gtk_tree_row_reference_new(model, path); + gtk_tree_path_free(path); + return rr; +} + +struct cruft_remove_args { + GHashTable *table; + gint64 serial; +}; + +static gboolean trg_state_selector_remove_cruft(gpointer key, gpointer value, gpointer data) +{ + struct cruft_remove_args *args = (struct cruft_remove_args*)data; + GtkTreeRowReference *rr = (GtkTreeRowReference*)value; + GtkTreeModel *model = gtk_tree_row_reference_get_model(rr); + GtkTreePath *path = gtk_tree_row_reference_get_path(rr); + gboolean remove; + + GtkTreeIter iter; + gint64 currentSerial; + + gtk_tree_model_get_iter(model, &iter, path); + gtk_tree_model_get(model, &iter, STATE_SELECTOR_SERIAL, ¤tSerial, -1); + + remove = (args->serial != currentSerial); + + gtk_tree_path_free(path); + + return remove; +} + +gchar *trg_state_selector_get_selected_text(TrgStateSelector *s) +{ + GtkTreeSelection *sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(s)); + GtkTreeModel *model; + GtkTreeIter iter; + gchar *name = NULL; + + if (gtk_tree_selection_get_selected(sel, &model, &iter)) + gtk_tree_model_get(model, &iter, STATE_SELECTOR_NAME, &name, -1); + + return name; +} + +void trg_state_selector_update_trackers(TrgStateSelector *s, JsonArray *torrents, gint64 serial) +{ + TrgStateSelectorPrivate *priv = TRG_STATE_SELECTOR_GET_PRIVATE(s); + GtkTreeModel *model; + GtkTreeIter iter; + int i, j; + struct cruft_remove_args cruft; + + model = gtk_tree_view_get_model(GTK_TREE_VIEW(s)); + + for (i = 0; i < json_array_get_length(torrents); i++) { + JsonObject *t = json_array_get_object_element(torrents, i); + JsonArray *trackers = torrent_get_trackers(t); + + for (j = 0; j < json_array_get_length(trackers); j++) { + JsonObject *tracker = json_array_get_object_element(trackers, j); + const gchar *announceUrl = tracker_get_announce(tracker); + gchar *announceHost = trg_uri_host_extract(priv->urlHostRegex, announceUrl); + gpointer result; + + if (!announceHost) + continue; + + result = g_hash_table_lookup(priv->trackers, announceHost); + + if (result) + { + GtkTreeRowReference *rr = (GtkTreeRowReference*)result; + GtkTreePath *path = gtk_tree_row_reference_get_path(rr); + gtk_tree_model_get_iter(model, &iter, path); + gtk_list_store_set(GTK_LIST_STORE(model), &iter, + STATE_SELECTOR_SERIAL, serial, -1); + gtk_tree_path_free(path); + } else { + gtk_list_store_append(GTK_LIST_STORE(model), &iter); + gtk_list_store_set(GTK_LIST_STORE(model), &iter, + STATE_SELECTOR_ICON, GTK_STOCK_NETWORK, + STATE_SELECTOR_NAME, announceHost, + STATE_SELECTOR_SERIAL, serial, + STATE_SELECTOR_BIT, FILTER_FLAG_TRACKER, -1); + g_hash_table_insert(priv->trackers, announceHost, quick_tree_ref_new(model, &iter)); + } + } + } + + cruft.serial = serial; + cruft.table = priv->trackers; + + g_hash_table_foreach_remove(priv->trackers, trg_state_selector_remove_cruft, &cruft); +} + static void trg_state_selector_add_state(GtkListStore * model, GtkTreeIter * iter, gchar * icon, gchar * name, guint32 flag) @@ -96,6 +204,18 @@ static void trg_state_selector_add_state(GtkListStore * model, STATE_SELECTOR_BIT, flag, -1); } +static void remove_row_ref_and_free(GtkTreeRowReference *rr) +{ + GtkTreeModel *model = gtk_tree_row_reference_get_model(rr); + GtkTreePath *path = gtk_tree_row_reference_get_path(rr); + GtkTreeIter iter; + + gtk_tree_model_get_iter(model, &iter, path); + gtk_list_store_remove(GTK_LIST_STORE(model), &iter); + gtk_tree_path_free(path); + gtk_tree_row_reference_free(rr); +} + static void trg_state_selector_init(TrgStateSelector * self) { TrgStateSelectorPrivate *priv; @@ -108,6 +228,9 @@ static void trg_state_selector_init(TrgStateSelector * self) priv = TRG_STATE_SELECTOR_GET_PRIVATE(self); priv->flag = 0; + priv->urlHostRegex = trg_uri_host_regex_new(); + priv->trackers = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, (GDestroyNotify)remove_row_ref_and_free); + gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(self), FALSE); column = gtk_tree_view_column_new(); @@ -126,7 +249,7 @@ static void trg_state_selector_init(TrgStateSelector * self) store = gtk_list_store_new(STATE_SELECTOR_COLUMNS, G_TYPE_STRING, - G_TYPE_STRING, G_TYPE_UINT); + G_TYPE_STRING, G_TYPE_UINT, G_TYPE_INT64); trg_state_selector_add_state(store, &iter, GTK_STOCK_ABOUT, _("All"), 0); @@ -145,6 +268,8 @@ static void trg_state_selector_init(TrgStateSelector * self) _("Seeding"), TORRENT_FLAG_SEEDING); trg_state_selector_add_state(store, &iter, GTK_STOCK_DIALOG_WARNING, _("Error"), TORRENT_FLAG_ERROR); + trg_state_selector_add_state(store, &iter, NULL, + NULL, 0); gtk_tree_view_set_model(GTK_TREE_VIEW(self), GTK_TREE_MODEL(store)); gtk_tree_view_set_rubber_banding(GTK_TREE_VIEW(self), TRUE); diff --git a/src/trg-state-selector.h b/src/trg-state-selector.h index 944647a..d09d76a 100644 --- a/src/trg-state-selector.h +++ b/src/trg-state-selector.h @@ -22,11 +22,13 @@ #define TRG_STATE_LIST_H_ #include +#include enum { STATE_SELECTOR_ICON, STATE_SELECTOR_NAME, STATE_SELECTOR_BIT, + STATE_SELECTOR_SERIAL, STATE_SELECTOR_COLUMNS }; @@ -49,15 +51,17 @@ G_BEGIN_DECLS typedef struct { GtkTreeViewClass parent_class; - /* SIGNALS */ - void (*torrent_state_changed) (TrgStateSelector * selector, - guint flag, gpointer data); + guint flag, gpointer data); + } TrgStateSelectorClass; GType trg_state_selector_get_type(void); TrgStateSelector *trg_state_selector_new(void); G_END_DECLS guint32 trg_state_selector_get_flag(TrgStateSelector * s); +void trg_state_selector_update_trackers(TrgStateSelector *s, JsonArray *torrents, gint64 serial); +gchar *trg_state_selector_get_selected_text(TrgStateSelector *s); +GRegex *trg_state_selector_get_url_host_regex(TrgStateSelector *s); #endif /* TRG_STATE_LIST_H_ */ diff --git a/src/trg-torrent-model.c b/src/trg-torrent-model.c index c201fa2..7fa82ae 100644 --- a/src/trg-torrent-model.c +++ b/src/trg-torrent-model.c @@ -33,6 +33,7 @@ enum { TMODEL_TORRENT_COMPLETED, TMODEL_TORRENT_ADDED, + TMODEL_TORRENT_ADDREMOVE, TMODEL_SIGNAL_COUNT }; @@ -69,6 +70,16 @@ static void trg_torrent_model_class_init(TrgTorrentModelClass * klass) torrent_added), NULL, NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER); + + signals[TMODEL_TORRENT_ADDREMOVE] = + g_signal_new("torrent-addremove", + G_TYPE_FROM_CLASS(object_class), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET(TrgTorrentModelClass, + torrent_removed), NULL, + NULL, g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + } static void trg_torrent_model_count_peers(TrgTorrentModel * model, @@ -272,6 +283,7 @@ void trg_torrent_model_update(TrgTorrentModel * model, trg_client * tc, { int i; JsonArray *newTorrents; + gboolean added = FALSE; newTorrents = get_torrents(get_arguments(response)); stats->count = json_array_get_length(newTorrents); @@ -287,8 +299,10 @@ void trg_torrent_model_update(TrgTorrentModel * model, trg_client * tc, TORRENT_COLUMN_ID, torrent_get_id(t), &iter) == FALSE) { + added = TRUE; gtk_list_store_append(GTK_LIST_STORE(model), &iter); update_torrent_iter(tc->updateSerial, model, &iter, t, stats); + if (!first) g_signal_emit(model, signals[TMODEL_TORRENT_ADDED], 0, &iter); @@ -304,7 +318,8 @@ void trg_torrent_model_update(TrgTorrentModel * model, trg_client * tc, tc->torrents = newTorrents; - trg_model_remove_removed(GTK_LIST_STORE(model), + if (trg_model_remove_removed(GTK_LIST_STORE(model), TORRENT_COLUMN_UPDATESERIAL, - tc->updateSerial); + tc->updateSerial) > 0 || added) + g_signal_emit(model, signals[TMODEL_TORRENT_ADDREMOVE], 0); } diff --git a/src/trg-torrent-model.h b/src/trg-torrent-model.h index cc8c695..ee064d2 100644 --- a/src/trg-torrent-model.h +++ b/src/trg-torrent-model.h @@ -45,11 +45,13 @@ G_BEGIN_DECLS typedef struct { GtkListStoreClass parent_class; void (*torrent_completed) (TrgTorrentModel * model, - GtkTreeIter * iter, JsonObject * t, + GtkTreeIter * iter, gpointer data); void (*torrent_added) (TrgTorrentModel * model, - GtkTreeIter * iter, JsonObject * t, + GtkTreeIter * iter, gpointer data); + + void (*torrent_removed) (TrgTorrentModel *model, gpointer data); } TrgTorrentModelClass; typedef struct { diff --git a/src/util.c b/src/util.c index 906cf90..bd20d14 100644 --- a/src/util.c +++ b/src/util.c @@ -34,6 +34,23 @@ #include "util.h" #include "dispatch.h" +GRegex *trg_uri_host_regex_new(void) +{ + return g_regex_new("^[^:/?#]+:?//([^/?#]*)", 0, 0, NULL); +} + +gchar *trg_uri_host_extract(GRegex *rx, const gchar *uri) +{ + GMatchInfo *mi = NULL; + gchar *host = NULL; + g_regex_match (rx, uri, 0, &mi); + if (mi) { + host = g_match_info_fetch(mi, 1); + g_match_info_free (mi); + } + return host; +} + void trg_error_dialog(GtkWindow * parent, int status, JsonObject * response) { diff --git a/src/util.h b/src/util.h index 3b63163..6d9e62c 100644 --- a/src/util.h +++ b/src/util.h @@ -36,6 +36,9 @@ #define MEGABYTE_FACTOR ( 1024.0 * 1024.0 ) #define GIGABYTE_FACTOR ( 1024.0 * 1024.0 * 1024.0 ) +GRegex *trg_uri_host_regex_new(void); +gchar *trg_uri_host_extract(GRegex *rx, const gchar *uri); + char *tr_strltime_long(char *buf, gint64 seconds, size_t buflen); char *tr_strltime_short(char *buf, gint64 seconds, size_t buflen); char *tr_strpercent(char *buf, double x, size_t buflen); -- cgit v1.2.3