This commit is contained in:
John Preston 2015-01-23 12:48:36 +03:00
commit a7b4d81a11
24 changed files with 1000 additions and 28 deletions

View File

@ -452,11 +452,17 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_new_authorization" = "{name},\nWe detected a login into your account from a new device on {day}, {date} at {time}\n\nDevice: {device}\nLocation: {location}\n\nIf this wasn't you, you can go to Settings — Terminate other sessions.\n\nThanks,\nThe Telegram Team";
"lng_new_version7007" = "Telegram Desktop was updated to version {version}\n\n — Tray icon added in Ubuntu\n\nFull version history is available here:\n{link}";
"lng_new_version7009" = "Telegram Desktop was updated to version {version}\n\n — Added Korean language\n — Quick «open with» menu on Windows and OS X\n\nFull version history is available here:\n{link}";
"lng_new_version7006_appstore" = "Telegram Desktop was updated to version {version}\n\n — Stickers support\n — Local caching for voice messages\n — Added new languages\n\nFull version history is available here:\n{link}";
// Wnd specific
"lng_wnd_choose_program_menu" = "Choose default program...";
// Mac specific
"lng_mac_choose_program_menu" = "Other...";
"lng_mac_choose_app" = "Choose Application";
"lng_mac_choose_text" = "Choose an application to open the document \"{file}\".";
"lng_mac_enable_filter" = "Enable:";

View File

@ -699,8 +699,8 @@ void Application::startApp() {
QNetworkProxyFactory::setUseSystemConfiguration(true);
if (Local::oldMapVersion() < AppVersion) {
psRegisterCustomScheme();
if (Local::oldMapVersion() && Local::oldMapVersion() < 7007 && (cPlatform() == dbipLinux32 || cPlatform() == dbipLinux64)) {
QString versionFeatures(lng_new_version7007(lt_version, QString::fromStdWString(AppVersionStr), lt_link, qsl("https://desktop.telegram.org/#changelog")));
if (Local::oldMapVersion() && Local::oldMapVersion() < 7009) {
QString versionFeatures(lng_new_version7009(lt_version, QString::fromStdWString(AppVersionStr), lt_link, qsl("https://desktop.telegram.org/#changelog")));
if (!versionFeatures.isEmpty()) {
window->serviceNotification(versionFeatures);
}

View File

@ -491,7 +491,10 @@ void VideoSaveLink::doSave(bool forceSavingAs) const {
QString already = data->already(true);
if (!already.isEmpty() && !forceSavingAs) {
psOpenFile(already, true);
QPoint pos(QCursor::pos());
if (!psShowOpenWithMenu(pos.x(), pos.y(), already)) {
psOpenFile(already, true);
}
} else {
QDir alreadyDir(already.isEmpty() ? QDir() : QFileInfo(already).dir());
QString name = already.isEmpty() ? QString(".mov") : already;
@ -577,7 +580,10 @@ void AudioSaveLink::doSave(bool forceSavingAs) const {
QString already = data->already(true);
if (!already.isEmpty() && !forceSavingAs) {
psOpenFile(already, true);
QPoint pos(QCursor::pos());
if (!psShowOpenWithMenu(pos.x(), pos.y(), already)) {
psOpenFile(already, true);
}
} else {
QDir alreadyDir(already.isEmpty() ? QDir() : QFileInfo(already).dir());
QString name = already.isEmpty() ? QString(".ogg") : already;
@ -678,7 +684,10 @@ void DocumentSaveLink::doSave(bool forceSavingAs) const {
QString already = data->already(true);
if (!already.isEmpty() && !forceSavingAs) {
psOpenFile(already, true);
QPoint pos(QCursor::pos());
if (!psShowOpenWithMenu(pos.x(), pos.y(), already)) {
psOpenFile(already, true);
}
} else {
QDir alreadyDir(already.isEmpty() ? QDir() : QFileInfo(already).dir());
QString name = already.isEmpty() ? data->name : already, filter;

View File

@ -24,6 +24,7 @@ static const char *LanguageCodes[] = {
"de",
"nl",
"pt_BR",
"ko",
};
static const int languageTest = -1, languageDefault = 0, languageCount = sizeof(LanguageCodes) / sizeof(LanguageCodes[0]);

View File

@ -452,11 +452,17 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_new_authorization" = "{name},\n\nwir haben eine Anmeldung von einem neuen Gerät am {day}, {date} um {time} festgestellt. \n\nGerät: {device}\nStandort: {location}\n\nWarst du das selbst? Wenn du das nicht selbst gewesen bist, melde alle anderen Sitzungen in den Telegram Einstellungen unverzüglich ab. \n\nDanke,\nDein Telegram Team";
"lng_new_version7007" = "Telegram Desktop wurde aktualisiert auf Version {version}\n\n — Tray Icon für Ubuntu hinzugefügt. \n\nGesamter Versionsverlauf:\n{link}";
"lng_new_version7009" = "Telegram Desktop wurde auf Version {version} aktualisiert\n\n— Koreanische Sprache hinzugefügt\n— Neues \"Öffnen mit\" Menü bei Windows und OS X\n\nKompletter Versionsverlauf:\n{link}";
"lng_new_version7006_appstore" = "Telegram Desktop wurde auf Version {version} aktualisiert\n\n— Sticker werden unterstützt\n— Sprachnachrichten werden temporär lokal gespeichert\n— Neue Sprachen hinzugefügt\n\nKompletter Versionsverlauf ist hier zu finden:\n{link}";
// Wnd specific
"lng_wnd_choose_program_menu" = "Öffnen mit...";
// Mac specific
"lng_mac_choose_program_menu" = "Öffnen mit...";
"lng_mac_choose_app" = "Programm auswählen";
"lng_mac_choose_text" = "Programm auswählen, um \"{file}\" zu öffnen.";
"lng_mac_enable_filter" = "Aktivieren:";

View File

@ -452,11 +452,17 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_new_authorization" = "{name},\nDetectamos un inicio de sesión en tu cuenta desde un nuevo dispositivo el {day}, {date} a las {time}\n\nDispositivo: {device}\nUbicación: {location}\n\nSi no eras tú, puedes ir a Ajustes — Cerrar todas las otras sesiones.\n\nGracias.\nEl equipo de Telegram";
"lng_new_version7007" = "Telegram Desktop fue actualizada a la versión {version}\n\n — Se añadió el ícono en la barra de menú para Ubuntu\n\nEl historial completo está disponible aquí:\n{link}";
"lng_new_version7009" = "Telegram Desktop fue actualizada a la versión {version}\n\n Se añadió el idioma coreano\n Menú rápido para «abrir con» en Windows y OS X\n\nEl historial completo está disponible aquí:\n{link}";
"lng_new_version7006_appstore" = "Telegram Desktop fue actualizada a la versión {version}\n\n Soporte para stickers\n Caché local para mensajes de voz\n Nuevos idiomas añadidos\n\nLa versión completa del historial está disponible aquí:\n{link} ";
// Wnd specific
"lng_wnd_choose_program_menu" = "Elegir programa predeterminado...";
// Mac specific
"lng_mac_choose_program_menu" = "Otra...";
"lng_mac_choose_app" = "Elegir aplicación";
"lng_mac_choose_text" = "Elige una aplicación para abrir el archivo \"{file}\".";
"lng_mac_enable_filter" = "Habilitar:";

View File

@ -452,11 +452,17 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_new_authorization" = "{name},\nAbbiamo rilevato un accesso al tuo account da un nuovo dispositivo il {day}, {date} alle {time}\n\nDispositivo: {device}\nPosizione: {location}\n\nSe non sei tu, puoi andare su Impostazioni Termina tutte le sessioni. \n\nGrazie, \nIl Team di Telegram";
"lng_new_version7007" = "Telegram Desktop è stato aggiornato alla versione {version}\n\n— Icona tray aggiunta su Ubuntu\n\nLa cronologia degli update è disponibile qui:\n{link}";
"lng_new_version7009" = "Telegram Desktop è stato aggiornato alla versione {version}\n\n— Aggiunto il Coreano\n— Menu rapido \"Apri con\" su Windows e OS X\n\nLa cronologia degli update è disponibile qui:\n{link}";
"lng_new_version7006_appstore" = "Telegram Desktop è stato aggiornato alla versione {version}\n\n— Aggiunto il supporto agli sticker\n— Cache locale per i messaggi vocali\n— Aggiunte nuove lingue\n\nLa cronologia degli update è disponibile qui:\n{link}";
// Wnd specific
"lng_wnd_choose_program_menu" = "Programma predefinito...";
// Mac specific
"lng_mac_choose_program_menu" = "Altro...";
"lng_mac_choose_app" = "Scegli applicazione";
"lng_mac_choose_text" = "Scegli un'applicazione per aprire il file \"{file}\".";
"lng_mac_enable_filter" = "Attiva:";

View File

@ -0,0 +1,498 @@
/*
This file is part of Telegram Desktop,
the official desktop version of Telegram messaging app, see https://telegram.org
Telegram Desktop is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
It 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 General Public License for more details.
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
Copyright (c) 2014 John Preston, https://desktop.telegram.org
*/
"lng_language_name" = "한국어";
"lng_switch_to_this" = "한국어로 변경";
"lng_menu_contacts" = "주소록";
"lng_menu_settings" = "설정";
"lng_menu_about" = "정보";
"lng_menu_update" = "업데이트";
"lng_menu_restart" = "재시작";
"lng_menu_back" = "뒤로가기";
"lng_open_from_tray" = "텔레그램 실행";
"lng_minimize_to_tray" = "창을 최소화";
"lng_quit_from_tray" = "텔레그램 종료";
"lng_tray_icon_text" = "텔레그램은 아직 실행중입니다.\n설정 화면에서 실행설정을 변경하실 수 있습니다.\n\n트레이메뉴에서 이 아이콘이 사라질 경우.\n숨겨진 아이콘에서 다시 드래그하여 복원할 수 있습니다.";
"lng_month1" = "1월";
"lng_month2" = "2월";
"lng_month3" = "3월";
"lng_month4" = "4월";
"lng_month5" = "5월";
"lng_month6" = "6월";
"lng_month7" = "7월";
"lng_month8" = "8월";
"lng_month9" = "9월";
"lng_month10" = "10월";
"lng_month11" = "11월";
"lng_month12" = "12월";
"lng_weekday1" = "월";
"lng_weekday2" = "화";
"lng_weekday3" = "수";
"lng_weekday4" = "목";
"lng_weekday5" = "금";
"lng_weekday6" = "토";
"lng_weekday7" = "일";
"lng_weekday1_full" = "월요일";
"lng_weekday2_full" = "화요일";
"lng_weekday3_full" = "수요일";
"lng_weekday4_full" = "목요일";
"lng_weekday5_full" = "금요일";
"lng_weekday6_full" = "토요일";
"lng_weekday7_full" = "일요일";
"lng_month_day" = "{month} {day}";
"lng_cancel" = "취소";
"lng_continue" = "계속";
"lng_close" = "닫기";
"lng_connecting" = "연결중입니다..";
"lng_reconnecting" = "재연결중입니다 {count:현재|중 # 초|중 # 초}..";
"lng_reconnecting_try_now" = "다시 시도";
"lng_status_service_notifications" = "서비스 공지사항";
"lng_status_offline" = "마지막으로 접속한 지 오래됨";
"lng_status_recently" = "최근에 접속";
"lng_status_last_week" = "일주일 이내 마지막으로 접속";
"lng_status_last_month" = "한 달 이내 마지막으로 접속";
"lng_status_invisible" = "숨김";
"lng_status_lastseen_now" = "방금 접속";
"lng_status_lastseen_minutes" = "접속한지 {count:_not_used_|# 분|# 분} 전";
"lng_status_lastseen_hours" = "접속한지 {count:_not_used_|# 시간|# 시간} 전";
"lng_status_lastseen_today" = "오늘 {time}에 마지막으로 접속";
"lng_status_lastseen_yesterday" = "어제 {time}에 마지막으로 접속";
"lng_status_lastseen_date" = "{date}에 마지막으로 접속";
"lng_status_lastseen_date_time" = "{date} 일 {time} 에 마지막으로 접속";
"lng_status_online" = "온라인";
"lng_status_connecting" = "연결중..";
"lng_chat_status_unaccessible" = "그룹 접근 불가";
"lng_chat_status_members" = "{count:없음|# 명|# 명}";
"lng_chat_status_members_online" = "{count:_not_used_|# 명|# 명}, {count_online:_not_used_|# 온라인|# 온라인}";
"lng_server_error" = "내부 서버 오류";
"lng_flood_error" = "시도가 너무 많습니다. 나중에 다시 시도해주세요.";
"lng_deleted" = "알 수 없음";
"lng_intro" = "[a href=\"https://telegram.org/\"]텔레그램[/a] PC 공식버전에 오신 것을 환영합니다.\n[b]안전[/b]하고 [b]신속[/b]하게 사용하세요.";
"lng_start_msgs" = "시작하기";
"lng_intro_next" = "다음";
"lng_intro_finish" = "회원가입";
"lng_phone_ph" = "휴대폰 번호";
"lng_phone_title" = "전화번호";
"lng_phone_desc" = "국가번호와 전화번호를 입력하세요. \n(대한민국 국가번호: 82)";
"lng_phone_notreg" = "확인사항: 아직 텔레그램 계정이 없으실 경우 [a href=\"https://telegram.org/\"]iOS / 안드로이드[/a] 기기로 [b]회원가입[/b]을 해주시거나 {signup_start}여기 »{signup_end} 에서 회원가입을 해주세요.";
"lng_country_code" = "국가번호";
"lng_bad_country_code" = "올바른 국가번호가 아닙니다.";
"lng_country_ph" = "검색";
"lng_country_done" = "완료";
"lng_country_none" = "국가를 찾지 못하였습니다.";
"lng_country_select" = "국가 선택";
"lng_code_ph" = "코드번호";
"lng_code_desc" = "인증코드 메세지를 휴대폰으로 전송하였습니다.\n인증코드를 아래에 입력하여 주세요.";
"lng_code_call" = "텔레그램이 {minutes}:{seconds} 후에는 전화를 겁니다.";
"lng_code_calling" = "텔레그램으로부터 전화 요청을 하고 있습니다..";
"lng_code_called" = "텔레그램이 회원님의 전화번호로 전화를 걸었습니다.";
"lng_bad_phone" = "잘못된 전화번호입니다. 다시 시도해주세요.";
"lng_bad_phone_noreg" = "등록되지 않은 번호입니다.";
"lng_bad_code" = "틀린 인증코드입니다. 다시 시도해주세요.";
"lng_bad_name" = "성과 이름을 입력해주세요.";
"lng_bad_photo" = "올바르지 않은 이미지를 선택하였습니다.";
"lng_bad_image_for_photo" = "이미지를 전송할 수 없습니다.\n문서로 전송을 하겠습니까?";
"lng_signup_title" = "개인정보 및 사진";
"lng_signup_desc" = "이름을 입력해주시고,\n사진을 업로드해주세요.";
"lng_signup_firstname" = "이름";
"lng_signup_lastname" = "성";
"lng_dlg_filter" = "검색";
"lng_dlg_new_group_name" = "그룹이름";
"lng_dlg_create_group" = "만들기";
"lng_no_contacts" = "연락처가 없습니다.";
"lng_contacts_loading" = "로딩중입니다..";
"lng_contacts_not_found" = "검색결과가 없습니다.";
"lng_settings_save" = "저장";
"lng_settings_upload" = "프로필 이미지 선택";
"lng_settings_crop_profile" = "프로필 사진으로 사용할 영역을 선택하세요";
"lng_settings_uploading_photo" = "사진 업로드중..";
"lng_username_title" = "아이디 변경";
"lng_username_about" = "텔레그램 아이디를 설정할 수 있습니다. \n아이디를 설정하면 회원님의 전화번호를 몰라도 아이디로 회원님을 찾아 대화를 나눌 수 있습니다.\n아이디는 영문, 밑줄, 숫자로 a-z, _, 0-9, \n다섯 글자 이상으로 설정해 주세요.";
"lng_username_invalid" = "올바르지 않은 아이디입니다.";
"lng_username_occupied" = "사용중인 아이디입니다.";
"lng_username_too_short" = "아이디가 너무 짧습니다. (5글자 이상)";
"lng_username_bad_symbols" = "올바르지 않은 아이디입니다.";
"lng_username_available" = "사용가능한 아이디입니다.";
"lng_username_not_found" = "아이디 @{user}를 찾을 수 없습니다.";
"lng_settings_section_contact_info" = "연락처 정보";
"lng_settings_phone_number" = "전화번호";
"lng_settings_username" = "아이디";
"lng_settings_choose_username" = "아이디 설정하기";
"lng_settings_change_username" = "변경하기";
"lng_settings_section_notify" = "알림서비스";
"lng_settings_desktop_notify" = "데스크탑 알림서비스";
"lng_settings_show_name" = "발신인 표시";
"lng_settings_show_preview" = "메시지 미리보기";
"lng_settings_sound_notify" = "알림음";
"lng_notification_preview" = "새로운 메시지가 있습니다.";
"lng_settings_section_general" = "일반";
"lng_settings_change_lang" = "언어 변경";
"lng_languages" = "언어";
"lng_sure_save_language" = "언어 변경을 적용하기 위하여\n텔레그램을 재시작합니다.";
"lng_settings_auto_update" = "자동 업데이트";
"lng_settings_current_version" = "버전 {version}";
"lng_settings_check_now" = "업데이트 확인";
"lng_settings_update_checking" = "업데이트 확인 중..";
"lng_settings_latest_installed" = "최신 버전이 설치 되어져 있습니다.";
"lng_settings_downloading" = "업데이트 다운로드중..{ready} / {total} Mb..";
"lng_settings_update_ready" = "새로운 버전을 설치 할 수 있습니다.";
"lng_settings_update_now" = "재시작 합니다.";
"lng_settings_update_fail" = "업데이트 확인 실패";
"lng_settings_workmode_tray" = "트레이 아이콘 표시";
"lng_settings_workmode_window" = "테스크바 아이콘 표시";
"lng_settings_auto_start" = "시스템 시작시 자동실행";
"lng_settings_start_min" = "최소화로 시작";
"lng_settings_add_sendto" = " «보내기» 메뉴에 추가";
"lng_settings_scale_label" = "인터페이스 크기 조절";
"lng_settings_scale_auto" = "자동 ({cur})";
"lng_settings_section_chat" = "채팅 설정";
"lng_settings_replace_emojis" = "이모티콘 자동변환";
"lng_settings_view_emojis" = "리스트 보기";
"lng_settings_emoji_list" = "지원되는 이모티콘 리스트";
"lng_settings_send_enter" = "엔터키로 메시지 전송";
"lng_settings_send_ctrlenter" = " Ctrl+Enter로 메시지 전송";
"lng_settings_send_cmdenter" = "Cmd+Enter로 메시지 전송";
"lng_settings_cats_and_dogs" = "고양이와 강아지 배경문양 허용";
"lng_download_path_dont_ask" = "다운로드 경로 묻지 않기";
"lng_download_path_label" = "다운로드 경로:";
"lng_download_path_temp" = "임시 폴더";
"lng_download_path_default" = "기본 폴더";
"lng_download_path_clear" = "전체 지우기";
"lng_download_path_header" = "다운로드 경로 선택";
"lng_download_path_default_radio" = "텔레그램 기본 «다운로드» 폴더";
"lng_download_path_temp_radio" = "임시 폴더. 로그아웃 혹은 프로그램 제거시 초기화 됨";
"lng_download_path_dir_radio" = "커스텀 폴더. 수동으로만 초기화 됨.";
"lng_download_path_choose" = "다운로드 경로 선택";
"lng_sure_clear_downloads" = "임시 폴더에 다운로드 받은 모든 파일을 삭제하시겠습니까? 로그아웃 혹은 프로그램 제거시 자동으로 초기화 됩니다.";
"lng_download_path_failed" = "파일 다운로드를 시작 할 수 없습니다. 올바르지 않은 다운로드 경로가 원인 일 수도 있습니다.\n\n설정에 가시면 다운로드 경로를 변경하실 수 있습니다.";
"lng_download_path_settings" = "설정으로 이동";
"lng_download_finish_failed" = "파일 다운로드를 끝낼 수 없습니다.\n\n다시 시도하시겠습니까?";
"lng_download_path_clearing" = "초기화 중..";
"lng_download_path_cleared" = "초기화 완료!";
"lng_download_path_clear_failed" = "초기화 실패 :(";
"lng_settings_section_cache" = "로컬 저장소";
"lng_settings_no_data_cached" = "캐시 데이터를 못 찾았습니다!";
"lng_settings_images_cached" = "{count:_not_used_|# 이미지|# 이미지}, {size}";
"lng_settings_audios_cached" = "{count:_not_used_|# 음성 메시지|# 음성 메시지}, {size}";
"lng_local_storage_clear" = "전체 정리";
"lng_local_storage_clearing" = "초기화 중..";
"lng_local_storage_cleared" = "초기화 완료!";
"lng_local_storage_clear_failed" = "초기화 실패 :(";
"lng_settings_section_advanced" = "고급";
"lng_connection_type" = "연결 유형:";
"lng_connection_auto_connecting" = "기본값 (연결중..)";
"lng_connection_auto" = "기본값 ({type} 사용)";
"lng_connection_http_proxy" = "HTTP 프록시";
"lng_connection_tcp_proxy" = "TCP 프록시";
"lng_connection_header" = "연결 유형";
"lng_connection_auto_rb" = "자동 (TCP 혹은 HTTP 사용)";
"lng_connection_http_proxy_rb" = "HTTP (커스텀 http프록시)";
"lng_connection_tcp_proxy_rb" = "TCP (커스텀 socks5-proxy)";
"lng_connection_host_ph" = "호스트네임";
"lng_connection_port_ph" = "포트번호";
"lng_connection_user_ph" = "아이디";
"lng_connection_password_ph" = "비밀번호";
"lng_connection_save" = "저장";
"lng_settings_reset" = "다른 모든 세션 강제 종료";
"lng_settings_reset_sure" = "현재 기기를 제외하고 다른 기기에 로그인된 세션을 모두 종료시킬까요?";
"lng_settings_reset_button" = "종료";
"lng_settings_reset_done" = "다른 모든 세션이 강제 종료 되었습니다.";
"lng_settings_logout" = "로그아웃";
"lng_sure_logout" = "정말로 로그아웃을 하시겠습니까?";
"lng_settings_need_restart" = "새로운 설정을 적용하시려면,\n재부팅을 하셔야합니다. 재시작 할까요?";
"lng_settings_restart_now" = "재시작";
"lng_settings_restart_later" = "나중에";
"lng_profile_chat_unaccessible" = "그룹에 접근할 수 없습니다.";
"lng_topbar_info" = "정보";
"lng_profile_settings_section" = "환경설정";
"lng_profile_participants_section" = "대화상대";
"lng_profile_info" = "연락처 정보";
"lng_profile_group_info" = "그룹 정보";
"lng_profile_add_contact" = "연락처 추가";
"lng_profile_edit_contact" = "수정";
"lng_profile_enable_notifications" = "알림";
"lng_profile_clear_history" = "히스토리 초기화";
"lng_profile_send_message" = "메세지 전송";
"lng_profile_share_contact" = "연락처 공유";
"lng_profile_delete_contact" = "삭제";
"lng_profile_set_group_photo" = "사진 설정";
"lng_profile_add_participant" = "대화상대 추가";
"lng_profile_delete_and_exit" = "나가기";
"lng_profile_kick" = "추방";
"lng_profile_sure_kick" = "{user}를 그룹에서 추방하시겠습니까?";
"lng_profile_loading" = "로딩중..";
"lng_profile_shared_media" = "공유된 미디어";
"lng_profile_no_media" = "대화에 미디어가 존재하지 않습니다.";
"lng_profile_photos" = "{count:_not_used_|# 사진|# 사진} »";
"lng_profile_photos_header" = "사진 내역";
"lng_profile_videos" = "{count:_not_used_|# 비디오 파일|# 비디오 파일} »";
"lng_profile_videos_header" = "비디오 파일 내역";
"lng_profile_documents" = "{count:_not_used_|# 문서|# 문서} »";
"lng_profile_documents_header" = "문서 내역";
"lng_profile_audios" = "{count:_not_used_|# 음성 메시지|# 음성 메시지} »";
"lng_profile_audios_header" = "음성 메시지 내역";
"lng_profile_show_all_types" = "모든 유형 보기";
"lng_profile_copy_phone" = "전화번호 복사";
"lng_participant_filter" = "검색";
"lng_participant_invite" = "초대";
"lng_create_new_group" = "새로운 그룹";
"lng_create_group_next" = "다음";
"lng_create_group_title" = "새로운 그룹";
"lng_sure_delete_contact" = "정말로 {contact} 를 주소록에서 삭제하시겠습니까?";
"lng_sure_delete_history" = "정말로 {contact} 와 관련된 모든 메시지를 삭제하시겠습니까?\n\n삭제 하실 경우 취소가 불가능합니다.";
"lng_sure_delete_and_exit" = "정말로 «{group}» 을 나가고 모든 대화를 삭제하시겠습니까?\n\n삭제 하실 경우 취소가 불가능합니다.";
"lng_sure_enable_debug" = "DEBUG 모드를 화성화 시키시겠습니까?\n\n모든 네트워크 내역이 기록됩니다.";
"lng_message_empty" = "(없음)";
"lng_action_add_user" = "{from} 님께서 {user} 님을 초대하셨습니다.";
"lng_action_kick_user" = "{from} 님께서 {user} 님을 추방하셨습니다.";
"lng_action_user_left" = "{from} 님이 그룹을 나가셨습니다.";
"lng_action_user_joined" = "{from} 님이 그룹에 들어오셨습니다.";
"lng_action_user_registered" = "{from} 님이 텔레그램에 가입하셨습니다.";
"lng_action_removed_photo" = "{from} 님이 그룹사진을 삭제하셨습니다.";
"lng_action_changed_photo" = "{from} 님이 그룹사진을 변경하셨습니다.";
"lng_action_changed_title" = "{from} 님이 그룹이름을 «{title}» 로 바꾸셨습니다.";
"lng_action_created_chat" = "{from} 님이 그룹 «{title}» 을 생성하셨습니다.";
"lng_forwarded_from" = "전달받음";
"lng_attach_failed" = "실패";
"lng_attach_file" = "문서";
"lng_attach_photo" = "사진";
"lng_media_type" = "미디어 종류";
"lng_media_type_photos" = "사진";
"lng_media_type_videos" = "비디오 파일";
"lng_media_type_documents" = "문서";
"lng_media_type_audios" = "음성 메시지";
"lng_media_open_with" = "다음으로 열기";
"lng_media_download" = "다운로드";
"lng_media_cancel" = "취소";
"lng_media_video" = "비디오 파일";
"lng_media_audio" = "음성 메시지";
"lng_in_dlg_photo" = "사진";
"lng_in_dlg_video" = "비디오";
"lng_in_dlg_contact" = "연락처";
"lng_in_dlg_audio" = "음성";
"lng_in_dlg_document" = "문서";
"lng_in_dlg_sticker" = "스티커";
"lng_in_dlg_sticker_emoji" = "{emoji} (스티커)";
"lng_send_button" = "보내기";
"lng_message_ph" = "메시지 쓰기";
"lng_empty_history" = "";
"lng_willbe_history" = "대화하실 방을 선택해주세요.";
"lng_message_with_from" = "[c]{from}:[/c] {message}";
"lng_from_you" = "회원님";
"lng_typing" = "입력중";
"lng_user_typing" = "{user}님이 입력중입니다.";
"lng_users_typing" = "{user}님과 {second_user}님이 입력중입니다.";
"lng_many_typing" = "{count:_not_used_|# 명이|# 명이} 입력중입니다";
"lng_unread_bar" = "{count:_not_used_|# 읽지 않은 메시지|# 읽지 않은 메시지}";
"lng_maps_point" = "위치";
"lng_save_photo" = "사진 저장";
"lng_save_video" = "동영상 저장";
"lng_save_audio" = "음성 저장";
"lng_save_document" = "문서 저장";
"lng_save_downloaded" = "{ready} / {total} {mb}";
"lng_duration_and_size" = "{duration}, {size}";
"lng_choose_images" = "이미지 선택";
"lng_context_open_link" = "링크 열기";
"lng_context_copy_link" = "링크 복사";
"lng_context_open_email" = "이 주소로 메시지 보내기";
"lng_context_copy_email" = "이메일 복사";
"lng_context_open_hashtag" = "해시태그로 검색";
"lng_context_copy_hashtag" = "해시태그 복사";
"lng_context_open_image" = "이미지 열기";
"lng_context_save_image" = "이미지를 다른 이름으로 저장..";
"lng_context_forward_image" = "이미지 전달";
"lng_context_delete_image" = "이미지 삭제";
"lng_context_copy_image" = "이미지 복사";
"lng_context_close_image" = "이미지 닫기";
"lng_context_cancel_download" = "다운로드 취소";
"lng_context_show_in_folder" = "탐색기에서 보기";
"lng_context_show_in_finder" = "탐색기에서 보기";
"lng_context_open_video" = "비디오 열기";
"lng_context_save_video" = "비디오 이름을 다른이름으로 저장.";
"lng_context_open_audio" = "음성메시지 열기";
"lng_context_save_audio" = "음성메시지를 다른 이름으로 저장..";
"lng_context_open_document" = "파일 열기";
"lng_context_save_document" = "파일을 다른 이름으로 저장.";
"lng_context_forward_file" = "파일 전달";
"lng_context_delete_file" = "파일 삭제";
"lng_context_close_file" = "파일 닫기";
"lng_context_copy_text" = "메시지 내용 복사";
"lng_context_to_msg" = "메시지로 이동";
"lng_context_forward_msg" = "메시지 전달";
"lng_context_delete_msg" = "메시지 삭제";
"lng_context_select_msg" = "메시지 선택";
"lng_context_cancel_upload" = "업로드 취소";
"lng_context_copy_selected" = "선택한 메시지 복사";
"lng_context_forward_selected" = "선택된 메시지 전달";
"lng_context_delete_selected" = "선택된 메시지 삭제";
"lng_context_clear_selection" = "선택된 메시지 초기화";
"lng_really_send_image" = "선택한 이미지를 전송하시겠습니까?";
"lng_really_send_file" = "선택한 파일을 전송하시겠습니까?";
"lng_really_share_contact" = "선택한 연락처를 공유하시겠습니까?";
"lng_send_image_compressed" = "압축된 이미지를 전송";
"lng_forward_choose" = "수신자를 선택하세요..";
"lng_forward_confirm" = "{recipient} 님에게 전달하시겠습니까?";
"lng_forward_share_contact" = "{recipient} 님에게 연락처를 공유하시겠습니까?";
"lng_forward_send_file_confirm" = "«{name}» 을 {recipient} 님에게 보내시겠습니까?";
"lng_forward_send_files_confirm" = "선택한 파일을 {recipient} 님에게 보내시겠습니까?";
"lng_forward" = "전달";
"lng_forward_send" = "보낵";
"lng_contact_phone" = "전화번호";
"lng_enter_contact_data" = "새로운 연락처";
"lng_edit_group_title" = "그룹 이름 수정";
"lng_edit_contact_title" = "연락처 이름 수정";
"lng_edit_self_title" = "이름 수정";
"lng_confirm_contact_data" = "새로운 연락처";
"lng_add_contact" = "생성";
"lng_add_contact_button" = "연락처 추가";
"lng_contacts_header" = "연락처";
"lng_contact_not_joined" = "{name}님은 아직 텔레그램에 가입되어져 있지 않지만 초대메시지를 보낼 수 있습니다.\n\n회원님 친구분들 중 텔레그램에 새로 가입을 할 경우 알림을 드리고 있습니다.";
"lng_try_other_contact" = "다시 시도";
"lng_contacts_done" = "취소";
"lng_drag_images_here" = "이미지를 여기로 놓으세요.";
"lng_drag_photos_here" = "사진을 여기로 놓으세요.";
"lng_drag_files_here" = "파일을 여기로 놓으세요.";
"lng_drag_to_send_quick" = "빠른 방법으로 보내기";
"lng_drag_to_send_no_compression" = "압축하지 않고 보내기";
"lng_drag_to_send_documents" = "문서형태로 보내기";
"lng_selected_clear" = "취소";
"lng_selected_delete" = "삭제";
"lng_selected_forward" = "전달";
"lng_selected_count" = "{count:_not_used_|# 메시지|# 메시지}";
"lng_selected_cancel_sure_this" = "업로드를 취소하시겠습니까?";
"lng_selected_delete_sure_this" = "메시지를 삭제하시겠습니까?";
"lng_selected_delete_sure" = "{count:_not_used_|# 메시지|# 메시지}를 삭제하시겠습니까?";
"lng_selected_delete_confirm" = "삭제";
"lng_about_version" = "버전 {version}";
"lng_about_text" = "[a href=\"https://core.telegram.org/mtproto\"]MTProto[/a]와 [a href=\"https://core.telegram.org/api\"]Telegram API[/a]에 기반하고 있는 공식 무료 메시징 앱으로 빠르고 안전합니다.\n\n이 소프트웨어는 [a href=\"https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE\"]GNU GPL[/a] version 3 라이선스를 채택하고 있으며 소스코드는 [a href=\"https://github.com/telegramdesktop/tdesktop\"]GitHub[/a]에서 제공하고 있습니다.";
"lng_about_done" = "완료";
"lng_search_found_results" = "{count:메시지를 찾을 수 없습니다.|# 메시지를 찾았습니다.|# 메시지를 찾았습니다.}";
"lng_search_global_results" = "아이디 검색 결과";
"lng_mediaview_save" = "다운로드";
"lng_mediaview_forward" = "전달";
"lng_mediaview_delete" = "삭제";
"lng_mediaview_single_photo" = "단일 사진";
"lng_mediaview_group_photo" = "그룹 사진";
"lng_mediaview_profile_photo" = "프로필 사진";
"lng_mediaview_n_of_count" = "사진 {n} 중 {count}";
"lng_mediaview_doc_image" = "문서";
"lng_mediaview_today" = "오늘 {time}";
"lng_mediaview_yesterday" = "어제 {time}";
"lng_mediaview_date_time" = "{date} {time}";
"lng_mediaview_saved" = "[c]다운로드[/c] 폴더로 이미지가 저장되었습니다.";
"lng_new_authorization" = "{name}님,\n{day}, {date} {time}에 새 기기에서 회원님의 계정에 로그인하였습니다.\n\n기기: {device}\n위치: {location}\n\n본인의 접속이 아니라면 '설정'으로 가서 '다른 모든 세션 종료'를 실행하세요.\n\n감사합니다.\n텔레그램 팀 드림";
"lng_new_version7009" = "텔레그램 데스크탑은 {version} 버전으로 업데이트 되었습니다. \n\n— 한국어 추가\n— 윈도우와 윈도우와 맥에 «다음으로 실행» 퀵메뉴 추가\n\n 전체 버전 히스토리는 아래에서 확인 가능합니다: {link}";
"lng_new_version7006_appstore" = "텔레그램 데스크탑은 {version} 버전으로 업데이트 되었습니다.\n\n— 스티커 지원\n— 음성 메시지 로컬 캐싱\n— 언어 추가\n\n전체 버전 히스토리는 아래에서 확인 가능합니다:\n{link}";
// Wnd specific
"lng_wnd_choose_program_menu" = "기본 프로그램을 선택해주세요...";
// Mac specific
"lng_mac_choose_program_menu" = "이외...";
"lng_mac_choose_app" = "어플리케이션 선택";
"lng_mac_choose_text" = " \"{file}\"을 실행할 어플리케이션을 선택하세요.";
"lng_mac_enable_filter" = "활성화:";
"lng_mac_recommended_apps" = "추천 어플리케이션";
"lng_mac_all_apps" = "모든 어플리케이션";
"lng_mac_always_open_with" = "항상 실행";
"lng_mac_this_app_can_open" = "\"{file}\"을 실행할 수 있는 어플리케이션입니다.";
"lng_mac_not_known_app" = "\"{file}\"을 열수 있는 어플리케이션인지 알 수 없습니다.";
"lng_mac_menu_services" = "서비스";
"lng_mac_menu_hide_telegram" = "숨기기 {telegram}";
"lng_mac_menu_hide_others" = "나머지 숨기기";
"lng_mac_menu_show_all" = "전체 보기";
"lng_mac_menu_preferences" = "환경설정...";
"lng_mac_menu_quit_telegram" = "{telegram} 종료 ";
"lng_mac_menu_about_telegram" = "{telegram} 정보";
"lng_mac_menu_file" = "파일";
"lng_mac_menu_logout" = "로그아웃";
"lng_mac_menu_edit" = "수정";
"lng_mac_menu_undo" = "실행취소";
"lng_mac_menu_redo" = "다시실행";
"lng_mac_menu_cut" = "잘라내기";
"lng_mac_menu_copy" = "복사";
"lng_mac_menu_paste" = "붙여넣기";
"lng_mac_menu_delete" = "삭제";
"lng_mac_menu_select_all" = "전체선택";
"lng_mac_menu_window" = "윈도우";
"lng_mac_menu_contacts" = "주소록";
"lng_mac_menu_add_contact" = "연락처 추가";
"lng_mac_menu_new_group" = "새로운 그룹";
"lng_mac_menu_show" = "텔레그램 보기";
// Keys finished

View File

@ -452,11 +452,17 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_new_authorization" = "{name},\nEr is op je account ingelogd vanaf een nieuw apparaat op {day}, {date} om {time}\n\nApparaat: {device}\nLocatie: {location}\n\nAls jij dit niet was, kun je alle sessies beëindigen via Instellingen Beëindig alle andere sessies.\n\nBedankt,\nHet Telegram-Team";
"lng_new_version7007" = "Telegram is bijgewerkt naar versie {version}\n\n— Systeemvakicoon toegevoegd aan Ubuntu.\n\nVolledige versiegeschiedenis is hier te vinden:\n{link}";
"lng_new_version7009" = "Telegram is bijgewerkt naar versie {version}\n\n— Koreaans toegevoegd.\n— Snel «openen met» menu voor Windows en OS X\n\nVolledige versiegeschiedenis is hier te vinden:\n{link}";
"lng_new_version7006_appstore" = "Telegram is bijgewerkt naar versie {version}\n\n— Ondersteuning voor Stickers\n— Lokale cache voor spraakberichten\n— Nieuwe talen toegevoegd\n\nVolledige versiegeschiedenis is hier te vinden:\n{link}";
// Wnd specific
"lng_wnd_choose_program_menu" = "Standaardprogramma selecteren... ";
// Mac specific
"lng_mac_choose_program_menu" = "Andere... ";
"lng_mac_choose_app" = "Kies een programma";
"lng_mac_choose_text" = "Kies een programma voor het openen van het bestand \"{file}\".";
"lng_mac_enable_filter" = "Activeren:";

View File

@ -68,7 +68,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_reconnecting" = "Reconectar {count:agora|em # s|em # s}..";
"lng_reconnecting_try_now" = "Tentar agora";
"lng_status_service_notifications" = "notificacoes de serviço";
"lng_status_service_notifications" = "notificações de serviço";
"lng_status_offline" = "visto há muito tempo";
"lng_status_recently" = "visto recentemente";
"lng_status_last_week" = "visto há uma semana";
@ -452,11 +452,17 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_new_authorization" = "{name},\nDetectamos um acesso à sua conta de um novo dispositivo em {day}, {date} às {time}\n\nDispositivo: {device}\nLocalização: {location}\n\nCaso não tenha sido você, vá em Configurações Terminar todas as outras sessões.\n\nObrigado,\nEquipe Telegram";
"lng_new_version7007" = "Telegram Desktop foi atualizado para a versão {version}\n\n — Ícone na bandeja disponível no Ubuntu.\n\nHistórico completo da atualização disponível aqui:\n{link}";
"lng_new_version7009" = "Telegram Desktop was updated to version {version}\n\n — Added Korean language\n — Quick «open with» menu on Windows and OS X\n\nFull version history is available here:\n{link}";
"lng_new_version7006_appstore" = "Telegram Desktop foi atualizado para a versão {version}\n\n — Suporte à stickers\n — Cache local para mensagens de voz\n — Adicionadas novas linguagens\n\nHistórico completo da versão disponível aqui:\n{link}";
// Wnd specific
"lng_wnd_choose_program_menu" = "Choose default program...";
// Mac specific
"lng_mac_choose_program_menu" = "Other...";
"lng_mac_choose_app" = "Escolher Aplicação";
"lng_mac_choose_text" = "Escolher aplicação para abrir o documento \"{file}\".";
"lng_mac_enable_filter" = "Habilitar:";

View File

@ -1050,7 +1050,12 @@ void MainWidget::videoLoadProgress(mtpFileLoader *loader) {
video->finish();
QString already = video->already();
if (!already.isEmpty() && video->openOnSave) {
psOpenFile(already, video->openOnSave < 0);
QPoint pos(QCursor::pos());
if (video->openOnSave < 0 && !psShowOpenWithMenu(pos.x(), pos.y(), already)) {
psOpenFile(already, true);
} else {
psOpenFile(already, video->openOnSave < 0);
}
}
}
}
@ -1105,7 +1110,12 @@ void MainWidget::audioLoadProgress(mtpFileLoader *loader) {
audioVoice()->play(audio);
}
} else {
psOpenFile(already, audio->openOnSave < 0);
QPoint pos(QCursor::pos());
if (audio->openOnSave < 0 && !psShowOpenWithMenu(pos.x(), pos.y(), already)) {
psOpenFile(already, true);
} else {
psOpenFile(already, audio->openOnSave < 0);
}
}
}
}
@ -1164,7 +1174,12 @@ void MainWidget::documentLoadProgress(mtpFileLoader *loader) {
psOpenFile(already);
}
} else {
psOpenFile(already, document->openOnSave < 0);
QPoint pos(QCursor::pos());
if (document->openOnSave < 0 && !psShowOpenWithMenu(pos.x(), pos.y(), already)) {
psOpenFile(already, true);
} else {
psOpenFile(already, document->openOnSave < 0);
}
}
}
}

View File

@ -685,6 +685,8 @@ void MTPautoConnection::onSocketDisconnected() {
}
void MTPautoConnection::sendData(mtpBuffer &buffer) {
if (status == FinishedWork) return;
if (buffer.size() < 3) {
LOG(("TCP Error: writing bad packet, len = %1").arg(buffer.size() * sizeof(mtpPrime)));
TCP_LOG(("TCP Error: bad packet %1").arg(mb(&buffer[0], buffer.size() * sizeof(mtpPrime)).str()));
@ -722,6 +724,8 @@ void MTPautoConnection::httpSend(mtpBuffer &buffer) {
}
void MTPautoConnection::disconnectFromServer() {
if (status == FinishedWork) return;
Requests copy = requests;
requests.clear();
for (Requests::const_iterator i = copy.cbegin(), e = copy.cend(); i != e; ++i) {
@ -737,7 +741,7 @@ void MTPautoConnection::disconnectFromServer() {
sock.close();
httpStartTimer.stop();
status = WaitingBoth;
status = FinishedWork;
}
void MTPautoConnection::connectToServer(const QString &addr, int32 port) {
@ -758,10 +762,12 @@ void MTPautoConnection::connectToServer(const QString &addr, int32 port) {
}
bool MTPautoConnection::isConnected() {
return !address.isEmpty();
return status != FinishedWork && !address.isEmpty();
}
void MTPautoConnection::requestFinished(QNetworkReply *reply) {
if (status == FinishedWork) return;
reply->deleteLater();
if (reply->error() == QNetworkReply::NoError) {
requests.remove(reply);
@ -820,6 +826,8 @@ void MTPautoConnection::requestFinished(QNetworkReply *reply) {
}
void MTPautoConnection::socketPacket(mtpPrime *packet, uint32 size) {
if (status == FinishedWork) return;
mtpBuffer data = _handleTcpResponse(packet, size);
if (data.size() == 1) {
if (status == WaitingBoth) {
@ -884,6 +892,8 @@ QString MTPautoConnection::transport() const {
}
void MTPautoConnection::socketError(QAbstractSocket::SocketError e) {
if (status == FinishedWork) return;
_handleTcpError(e, sock);
if (status == WaitingBoth) {
status = WaitingHttp;
@ -2498,8 +2508,8 @@ int32 MTProtoConnectionPrivate::handleOneReceived(const mtpPrime *from, const mt
}
if (badTime) {
DEBUG_LOG(("Message Error: bad time in updates cons"));
return -1;
DEBUG_LOG(("Message Error: bad time in updates cons, must create new session"));
return -2;
}
mtpBuffer update(end - from);

View File

@ -213,6 +213,7 @@ private:
HttpReady,
UsingHttp,
UsingTcp,
FinishedWork
};
Status status;
MTPint128 tcpNonce, httpNonce;

View File

@ -1740,6 +1740,10 @@ void psExecTelegram() {
_execUpdater(false);
}
bool psShowOpenWithMenu(int x, int y, const QString &file) {
return false;
}
void psAutoStart(bool start, bool silent) {
}

View File

@ -200,6 +200,8 @@ bool psCheckReadyUpdate();
void psExecUpdater();
void psExecTelegram();
bool psShowOpenWithMenu(int x, int y, const QString &file);
void psPostprocessFile(const QString &name);
void psOpenFile(const QString &name, bool openWith = false);
void psShowInFolder(const QString &name);

View File

@ -1121,6 +1121,10 @@ bool psCheckReadyUpdate() {
return true;
}
bool psShowOpenWithMenu(int x, int y, const QString &file) {
return objc_showOpenWithMenu(x, y, file);
}
void psPostprocessFile(const QString &name) {
}

View File

@ -224,6 +224,8 @@ bool psCheckReadyUpdate();
void psExecUpdater();
void psExecTelegram();
bool psShowOpenWithMenu(int x, int y, const QString &file);
void psPostprocessFile(const QString &name);
void psOpenFile(const QString &name, bool openWith = false);
void psShowInFolder(const QString &name);

View File

@ -59,6 +59,8 @@ void objc_debugShowAlert(const QString &str);
void objc_outputDebugString(const QString &str);
int64 objc_idleTime();
bool objc_showOpenWithMenu(int x, int y, const QString &file);
void objc_showInFinder(const QString &file, const QString &path);
void objc_openFile(const QString &file, bool openwith);
void objc_start();

View File

@ -369,6 +369,209 @@ int64 objc_idleTime() { // taken from https://github.com/trueinteractions/tint/i
return (result == err) ? -1 : int64(result);
}
@interface OpenWithApp : NSObject {
NSString *fullname;
NSURL *app;
NSImage *icon;
}
@property (nonatomic, retain) NSString *fullname;
@property (nonatomic, retain) NSURL *app;
@property (nonatomic, retain) NSImage *icon;
@end
@implementation OpenWithApp
@synthesize fullname, app, icon;
- (void) dealloc {
[fullname release];
[app release];
[icon release];
[super dealloc];
}
@end
@interface OpenFileWithInterface : NSObject {
}
- (id) init:(NSString *)file;
- (BOOL) popupAtX:(int)x andY:(int)y;
- (void) itemChosen:(id)sender;
- (void) dealloc;
@end
@implementation OpenFileWithInterface {
NSString *toOpen;
NSURL *defUrl;
NSString *defBundle, *defName, *defVersion;
NSImage *defIcon;
NSMutableArray *apps;
NSMenu *menu;
}
- (void) fillAppByUrl:(NSURL*)url bundle:(NSString**)bundle name:(NSString**)name version:(NSString**)version icon:(NSImage**)icon {
NSBundle *b = [NSBundle bundleWithURL:url];
if (b) {
NSString *path = [url path];
*name = [[NSFileManager defaultManager] displayNameAtPath: path];
if (!*name) *name = (NSString*)[b objectForInfoDictionaryKey:@"CFBundleDisplayName"];
if (!*name) *name = (NSString*)[b objectForInfoDictionaryKey:@"CFBundleName"];
if (*name) {
*bundle = [b bundleIdentifier];
if (bundle) {
*version = (NSString*)[b objectForInfoDictionaryKey:@"CFBundleShortVersionString"];
*icon = [[NSWorkspace sharedWorkspace] iconForFile: path];
if (*icon && [*icon isValid]) [*icon setSize: CGSizeMake(16., 16.)];
return;
}
}
}
*bundle = *name = *version = nil;
*icon = nil;
}
- (id) init:(NSString*)file {
toOpen = file;
if (self = [super init]) {
NSURL *url = [NSURL fileURLWithPath:file];
defUrl = [[NSWorkspace sharedWorkspace] URLForApplicationToOpenURL:url];
if (defUrl) {
[self fillAppByUrl:defUrl bundle:&defBundle name:&defName version:&defVersion icon:&defIcon];
if (!defBundle || !defName) {
defUrl = nil;
}
}
NSArray *appsList = (NSArray*)LSCopyApplicationURLsForURL(CFURLRef(url), kLSRolesAll);
NSMutableDictionary *data = [NSMutableDictionary dictionaryWithCapacity:16];
int fullcount = 0;
for (id app in appsList) {
if (fullcount > 15) break;
NSString *bundle = nil, *name = nil, *version = nil;
NSImage *icon = nil;
[self fillAppByUrl:(NSURL*)app bundle:&bundle name:&name version:&version icon:&icon];
if (bundle && name) {
if ([bundle isEqualToString:defBundle] && [version isEqualToString:defVersion]) continue;
NSString *key = [[NSArray arrayWithObjects:bundle, name, nil] componentsJoinedByString:@"|"];
if (!version) version = @"";
NSMutableDictionary *versions = (NSMutableDictionary*)[data objectForKey:key];
if (!versions) {
versions = [NSMutableDictionary dictionaryWithCapacity:2];
[data setValue:versions forKey:key];
}
if (![versions objectForKey:version]) {
[versions setValue:[NSArray arrayWithObjects:name, icon, app, nil] forKey:version];
++fullcount;
}
}
}
if (fullcount || defUrl) {
apps = [NSMutableArray arrayWithCapacity:fullcount];
for (id key in data) {
NSMutableDictionary *val = (NSMutableDictionary*)[data objectForKey:key];
for (id ver in val) {
NSArray *app = (NSArray*)[val objectForKey:ver];
OpenWithApp *a = [[OpenWithApp alloc] init];
NSString *fullname = (NSString*)[app objectAtIndex:0], *version = (NSString*)ver;
BOOL showVersion = ([val count] > 1);
if (!showVersion) {
NSError *error = NULL;
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"^\\d+\\.\\d+\\.\\d+(\\.\\d+)?$" options:NSRegularExpressionCaseInsensitive error:&error];
showVersion = ![regex numberOfMatchesInString:version options:NSMatchingWithoutAnchoringBounds range:{0,[version length]}];
}
if (showVersion) fullname = [[NSArray arrayWithObjects:fullname, @" (", version, @")", nil] componentsJoinedByString:@""];
[a setFullname:fullname];
[a setIcon:(NSImage*)[app objectAtIndex:1]];
[a setApp:(NSURL*)[app objectAtIndex:2]];
[apps addObject:a];
[a release];
}
}
}
[apps sortUsingDescriptors:[NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:@"fullname" ascending:YES]]];
[appsList release];
menu = nil;
}
return self;
}
- (BOOL) popupAtX:(int)x andY:(int)y {
if (![apps count] && !defName) return NO;
menu = [[NSMenu alloc] initWithTitle:@"Open With"];
int index = 0;
if (defName) {
NSMenuItem *item = [menu insertItemWithTitle:[[NSArray arrayWithObjects:defName, @" (default)", nil] componentsJoinedByString:@""] action:@selector(itemChosen:) keyEquivalent:@"" atIndex:index++];
if (defIcon) [item setImage:defIcon];
[item setTarget:self];
[menu insertItem:[NSMenuItem separatorItem] atIndex:index++];
}
if ([apps count]) {
for (id a in apps) {
OpenWithApp *app = (OpenWithApp*)a;
NSMenuItem *item = [menu insertItemWithTitle:[a fullname] action:@selector(itemChosen:) keyEquivalent:@"" atIndex:index++];
if ([app icon]) [item setImage:[app icon]];
[item setTarget:self];
}
[menu insertItem:[NSMenuItem separatorItem] atIndex:index++];
}
NSMenuItem *item = [menu insertItemWithTitle:objc_lang(lng_mac_choose_program_menu).s() action:@selector(itemChosen:) keyEquivalent:@"" atIndex:index++];
[item setTarget:self];
[menu popUpMenuPositioningItem:nil atLocation:CGPointMake(x, y) inView:nil];
return YES;
}
- (void) itemChosen:(id)sender {
NSArray *items = [menu itemArray];
NSURL *url = nil;
for (int i = 0, l = [items count]; i < l; ++i) {
if ([items objectAtIndex:i] == sender) {
if (defName) i -= 2;
if (i < 0) {
url = defUrl;
} else if (i < int([apps count])) {
url = [(OpenWithApp*)[apps objectAtIndex:i] app];
}
break;
}
}
if (url) {
[[NSWorkspace sharedWorkspace] openFile:toOpen withApplication:[url path]];
} else {
objc_openFile(objcString(toOpen), true);
}
}
- (void) dealloc {
if (apps) [apps release];
[super dealloc];
if (menu) [menu release];
}
@end
bool objc_showOpenWithMenu(int x, int y, const QString &f) {
NSString *file = QNSString(f).s();
@try {
OpenFileWithInterface *menu = [[OpenFileWithInterface alloc] init:file];
QRect r = QApplication::desktop()->screenGeometry(QPoint(x, y));
y = r.y() + r.height() - y;
return !![menu popupAtX:x andY:y];
}
@catch (NSException *exception) {
}
@finally {
}
return false;
}
void objc_showInFinder(const QString &file, const QString &path) {
[[NSWorkspace sharedWorkspace] selectFile:QNSString(file).s() inFileViewerRootedAtPath:QNSString(path).s()];
}

View File

@ -25,6 +25,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
#include <Shobjidl.h>
#include <dbghelp.h>
#include <shellapi.h>
#include <Shlwapi.h>
#include <Strsafe.h>
#include <shlobj.h>
#include <Windowsx.h>
@ -56,6 +57,7 @@ namespace {
bool frameless = true;
bool useDWM = false;
bool useTheme = false;
bool useOpenWith = false;
bool useOpenAs = false;
bool themeInited = false;
bool finished = true;
@ -605,22 +607,31 @@ namespace {
QColor _shActive(0, 0, 0), _shInactive(0, 0, 0);
typedef BOOL (FAR STDAPICALLTYPE *f_dwmDefWindowProc)(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, _Out_ LRESULT *plResult);
f_dwmDefWindowProc dwmDefWindowProc;
f_dwmDefWindowProc dwmDefWindowProc = 0;
typedef HRESULT (FAR STDAPICALLTYPE *f_dwmSetWindowAttribute)(HWND hWnd, DWORD dwAttribute, _In_ LPCVOID pvAttribute, DWORD cbAttribute);
f_dwmSetWindowAttribute dwmSetWindowAttribute;
f_dwmSetWindowAttribute dwmSetWindowAttribute = 0;
typedef HRESULT (FAR STDAPICALLTYPE *f_dwmExtendFrameIntoClientArea)(HWND hWnd, const MARGINS *pMarInset);
f_dwmExtendFrameIntoClientArea dwmExtendFrameIntoClientArea;
f_dwmExtendFrameIntoClientArea dwmExtendFrameIntoClientArea = 0;
typedef HRESULT (FAR STDAPICALLTYPE *f_setWindowTheme)(HWND hWnd, LPCWSTR pszSubAppName, LPCWSTR pszSubIdList);
f_setWindowTheme setWindowTheme;
f_setWindowTheme setWindowTheme = 0;
typedef HRESULT (FAR STDAPICALLTYPE *f_openAs_RunDLL)(HWND hWnd, HINSTANCE hInstance, LPCWSTR lpszCmdLine, int nCmdShow);
f_openAs_RunDLL openAs_RunDLL;
f_openAs_RunDLL openAs_RunDLL = 0;
typedef HRESULT (FAR STDAPICALLTYPE *f_shOpenWithDialog)(HWND hwndParent, const OPENASINFO *poainfo);
f_shOpenWithDialog shOpenWithDialog;
f_shOpenWithDialog shOpenWithDialog = 0;
typedef HRESULT (FAR STDAPICALLTYPE *f_shAssocEnumHandlers)(PCWSTR pszExtra, ASSOC_FILTER afFilter, IEnumAssocHandlers **ppEnumHandler);
f_shAssocEnumHandlers shAssocEnumHandlers = 0;
typedef HRESULT(FAR STDAPICALLTYPE *f_shCreateItemFromParsingName)(PCWSTR pszPath, IBindCtx *pbc, REFIID riid, void **ppv);
f_shCreateItemFromParsingName shCreateItemFromParsingName = 0;
typedef HRESULT(FAR STDAPICALLTYPE *f_shLoadIndirectString)(LPCWSTR pszSource, LPWSTR pszOutBuf, UINT cchOutBuf, void **ppvReserved);
f_shLoadIndirectString shLoadIndirectString = 0;
template <typename TFunction>
bool loadFunction(HINSTANCE dll, LPCSTR name, TFunction &func) {
@ -638,7 +649,7 @@ namespace {
frameless = !useDWM;
setupUx();
setupOpenAs();
setupShell();
}
void setupDWM() {
HINSTANCE procId = LoadLibrary(L"DWMAPI.DLL");
@ -654,9 +665,20 @@ namespace {
if (!loadFunction(procId, "SetWindowTheme", setWindowTheme)) return;
useTheme = true;
}
void setupOpenAs() {
void setupShell() {
HINSTANCE procId = LoadLibrary(L"SHELL32.DLL");
setupOpenWith(procId);
setupOpenAs(procId);
}
void setupOpenWith(HINSTANCE procId) {
if (!loadFunction(procId, "SHAssocEnumHandlers", shAssocEnumHandlers)) return;
if (!loadFunction(procId, "SHCreateItemFromParsingName", shCreateItemFromParsingName)) return;
useOpenWith = true;
HINSTANCE otherProcId = LoadLibrary(L"SHLWAPI.DLL");
if (otherProcId) loadFunction(otherProcId, "SHLoadIndirectString", shLoadIndirectString);
}
void setupOpenAs(HINSTANCE procId) {
if (!loadFunction(procId, "SHOpenWithDialog", shOpenWithDialog) && !loadFunction(procId, "OpenAs_RunDLLW", openAs_RunDLL)) return;
useOpenAs = true;
}
@ -998,6 +1020,7 @@ void PsMainWindow::psUpdateWorkmode() {
}
HICON qt_pixmapToWinHICON(const QPixmap &);
HBITMAP qt_pixmapToWinHBITMAP(const QPixmap &, int hbitmapFormat);
static HICON _qt_createHIcon(const QIcon &icon, int xSize, int ySize) {
if (!icon.isNull()) {
const QPixmap pm = icon.pixmap(icon.actualSize(QSize(xSize, ySize)));
@ -2170,6 +2193,162 @@ void psPostprocessFile(const QString &name) {
}
}
namespace {
struct OpenWithApp {
OpenWithApp(const QString &name, HBITMAP icon, IAssocHandler *handler) : name(name), icon(icon), handler(handler) {
}
OpenWithApp(const QString &name, IAssocHandler *handler) : name(name), icon(0), handler(handler) {
}
void destroy() {
if (icon) DeleteBitmap(icon);
if (handler) handler->Release();
}
QString name;
HBITMAP icon;
IAssocHandler *handler;
};
bool OpenWithAppLess(const OpenWithApp &a, const OpenWithApp &b) {
return a.name < b.name;
}
HBITMAP _iconToBitmap(LPWSTR icon, int iconindex) {
if (!icon) return 0;
WCHAR tmpIcon[4096];
if (icon[0] == L'@' && shLoadIndirectString && SUCCEEDED(shLoadIndirectString(icon, tmpIcon, 4096, 0))) {
icon = tmpIcon;
}
int32 w = GetSystemMetrics(SM_CXSMICON), h = GetSystemMetrics(SM_CYSMICON);
HICON ico = ExtractIcon(0, icon, iconindex);
if (!ico) {
if (!iconindex) { // try to read image
QImage img(QString::fromWCharArray(icon));
if (!img.isNull()) {
return qt_pixmapToWinHBITMAP(QPixmap::fromImage(img.scaled(w, h, Qt::IgnoreAspectRatio, Qt::SmoothTransformation)), /* HBitmapAlpha */ 2);
}
}
return 0;
}
HDC screenDC = GetDC(0), hdc = CreateCompatibleDC(screenDC);
HBITMAP result = CreateCompatibleBitmap(screenDC, w, h);
HGDIOBJ was = SelectObject(hdc, result);
DrawIconEx(hdc, 0, 0, ico, w, h, 0, NULL, DI_NORMAL);
SelectObject(hdc, was);
DeleteDC(hdc);
ReleaseDC(0, screenDC);
DestroyIcon(ico);
return (HBITMAP)CopyImage(result, IMAGE_BITMAP, 0, 0, LR_DEFAULTSIZE | LR_CREATEDIBSECTION);
// return result;
}
}
bool psShowOpenWithMenu(int x, int y, const QString &file) {
if (!useOpenWith || !App::wnd()) return false;
bool result = false;
QList<OpenWithApp> handlers;
IShellItem* pItem = nullptr;
if (SUCCEEDED(shCreateItemFromParsingName(QDir::toNativeSeparators(file).toStdWString().c_str(), nullptr, IID_PPV_ARGS(&pItem)))) {
IEnumAssocHandlers *assocHandlers = 0;
if (SUCCEEDED(pItem->BindToHandler(nullptr, BHID_EnumAssocHandlers, IID_PPV_ARGS(&assocHandlers)))) {
HRESULT hr = S_FALSE;
do
{
IAssocHandler *handler = 0;
ULONG ulFetched = 0;
hr = assocHandlers->Next(1, &handler, &ulFetched);
if (FAILED(hr) || hr == S_FALSE || !ulFetched) break;
LPWSTR name = 0;
if (SUCCEEDED(handler->GetUIName(&name))) {
LPWSTR icon = 0;
int iconindex = 0;
if (SUCCEEDED(handler->GetIconLocation(&icon, &iconindex)) && icon) {
handlers.push_back(OpenWithApp(QString::fromWCharArray(name), _iconToBitmap(icon, iconindex), handler));
CoTaskMemFree(icon);
} else {
handlers.push_back(OpenWithApp(QString::fromWCharArray(name), handler));
}
CoTaskMemFree(name);
} else {
handler->Release();
}
} while (hr != S_FALSE);
assocHandlers->Release();
}
if (!handlers.isEmpty()) {
HMENU menu = CreatePopupMenu();
std::sort(handlers.begin(), handlers.end(), OpenWithAppLess);
for (int32 i = 0, l = handlers.size(); i < l; ++i) {
MENUITEMINFO menuInfo = { 0 };
menuInfo.cbSize = sizeof(menuInfo);
menuInfo.fMask = MIIM_STRING | MIIM_DATA | MIIM_ID;
menuInfo.fType = MFT_STRING;
menuInfo.wID = i + 1;
if (handlers.at(i).icon) {
menuInfo.fMask |= MIIM_BITMAP;
menuInfo.hbmpItem = handlers.at(i).icon;
}
QString name = handlers.at(i).name;
if (name.size() > 512) name = name.mid(0, 512);
WCHAR nameArr[1024];
name.toWCharArray(nameArr);
nameArr[name.size()] = 0;
menuInfo.dwTypeData = nameArr;
InsertMenuItem(menu, GetMenuItemCount(menu), TRUE, &menuInfo);
}
MENUITEMINFO sepInfo = { 0 };
sepInfo.cbSize = sizeof(sepInfo);
sepInfo.fMask = MIIM_STRING | MIIM_DATA;
sepInfo.fType = MFT_SEPARATOR;
InsertMenuItem(menu, GetMenuItemCount(menu), true, &sepInfo);
MENUITEMINFO menuInfo = { 0 };
menuInfo.cbSize = sizeof(menuInfo);
menuInfo.fMask = MIIM_STRING | MIIM_DATA | MIIM_ID;
menuInfo.fType = MFT_STRING;
menuInfo.wID = handlers.size() + 1;
QString name = lang(lng_wnd_choose_program_menu);
if (name.size() > 512) name = name.mid(0, 512);
WCHAR nameArr[1024];
name.toWCharArray(nameArr);
nameArr[name.size()] = 0;
menuInfo.dwTypeData = nameArr;
InsertMenuItem(menu, GetMenuItemCount(menu), TRUE, &menuInfo);
int sel = TrackPopupMenu(menu, TPM_LEFTALIGN | TPM_TOPALIGN | TPM_LEFTBUTTON | TPM_RETURNCMD, x, y, 0, App::wnd()->psHwnd(), 0);
DestroyMenu(menu);
if (sel > 0) {
if (sel <= handlers.size()) {
IDataObject *dataObj = 0;
IEnumAssocHandlers *assocHandlers = 0;
if (SUCCEEDED(pItem->BindToHandler(nullptr, BHID_DataObject, IID_PPV_ARGS(&dataObj))) && dataObj) {
handlers.at(sel - 1).handler->Invoke(dataObj);
dataObj->Release();
result = true;
}
}
} else {
result = true;
}
for (int i = 0, l = handlers.size(); i < l; ++i) {
handlers[i].destroy();
}
}
pItem->Release();
}
return result;
}
void psOpenFile(const QString &name, bool openWith) {
std::wstring wname = QDir::toNativeSeparators(name).toStdWString();

View File

@ -202,6 +202,8 @@ bool psCheckReadyUpdate();
void psExecUpdater();
void psExecTelegram();
bool psShowOpenWithMenu(int x, int y, const QString &file);
void psPostprocessFile(const QString &name);
void psOpenFile(const QString &name, bool openWith = false);
void psShowInFolder(const QString &name);

View File

@ -47,5 +47,6 @@
<file alias="lang_de.strings">langs/lang_de.strings</file>
<file alias="lang_nl.strings">langs/lang_nl.strings</file>
<file alias="lang_pt_BR.strings">langs/lang_pt_BR.strings</file>
<file alias="lang_ko.strings">langs/lang_ko.strings</file>
</qresource>
</RCC>

View File

@ -47,5 +47,6 @@
<file alias="lang_de.strings">langs/lang_de.strings</file>
<file alias="lang_nl.strings">langs/lang_nl.strings</file>
<file alias="lang_pt_BR.strings">langs/lang_pt_BR.strings</file>
<file alias="lang_ko.strings">langs/lang_ko.strings</file>
</qresource>
</RCC>

View File

@ -276,6 +276,7 @@
0771C4C94B623FC34BF62983 /* intro.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = intro.cpp; path = SourceFiles/intro/intro.cpp; sourceTree = "<absolute>"; };
078DD0241A48DD9E00DD14CC /* lang_de.strings */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = lang_de.strings; path = SourceFiles/langs/lang_de.strings; sourceTree = SOURCE_ROOT; };
078DD0251A48DD9E00DD14CC /* lang_nl.strings */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = lang_nl.strings; path = SourceFiles/langs/lang_nl.strings; sourceTree = SOURCE_ROOT; };
07A190511A723E0A004287AE /* lang_ko.strings */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = lang_ko.strings; path = SourceFiles/langs/lang_ko.strings; sourceTree = SOURCE_ROOT; };
07A69330199277BA0099CB9F /* mediaview.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = mediaview.cpp; path = SourceFiles/mediaview.cpp; sourceTree = SOURCE_ROOT; };
07A69331199277BA0099CB9F /* mediaview.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = mediaview.h; path = SourceFiles/mediaview.h; sourceTree = SOURCE_ROOT; };
07A6933419927B160099CB9F /* moc_mediaview.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = moc_mediaview.cpp; path = GeneratedFiles/Debug/moc_mediaview.cpp; sourceTree = SOURCE_ROOT; };
@ -728,6 +729,7 @@
074968CB1A44D0B800394F46 /* langs */ = {
isa = PBXGroup;
children = (
07A190511A723E0A004287AE /* lang_ko.strings */,
072E117A1A56EB9400A87ACC /* lang_pt_BR.strings */,
078DD0241A48DD9E00DD14CC /* lang_de.strings */,
078DD0251A48DD9E00DD14CC /* lang_nl.strings */,
@ -1813,7 +1815,7 @@
CODE_SIGN_IDENTITY = "";
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 0.7.8;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEBUG_INFORMATION_FORMAT = dwarf;
DYLIB_COMPATIBILITY_VERSION = 0.7;
DYLIB_CURRENT_VERSION = 0.7.8;
ENABLE_STRICT_OBJC_MSGSEND = YES;