Pour dbuter l'utilisation du dictionnaire, slectionnez-en un a "
"partir du Dictionaires\n"
" menu.\n"
"
\n"
"
Pour installer un nouveau dictionnaire a partir d'Internet, "
"slectionnez\n"
" Grer Dictionnaires\n"
" a partir de Outils menu et choisissez Disponible"
"b> tab.
\n"
"
Pour installer nouveau dictionnaire a partir du fichier, slectionnez "
" Installer Dictionaire a partir du fichier...\n"
" A partir de Dictionnaires menu.\n"
"
\n"
"
\n"
"\n"
"\n"
#: ../lib/gui/mainwin.py:649
#, fuzzy
msgid ""
"Translation cannot be displayed using selected encoding %s. Please try "
"another encoding from View > Character Encoding menu."
msgstr ""
"Le codage selectionne n'est pas correct pour ce dictionnaire. S.V.P "
"selectionnez-en a partir de Editer menu codage de caractere"
#: ../lib/gui/mainwin.py:681
msgid "1 word matches"
msgstr "Matches de 1 mot"
#: ../lib/gui/mainwin.py:683
msgid "%d words match"
msgstr "%d mots matches"
#: ../lib/gui/mainwin.py:730
msgid "No dictionary activated"
msgstr "Pas de dictionnaire active"
#: ../lib/gui/mainwin.py:731
msgid ""
"No dictionary activated. Please select one from \"Dictionaries\" menu and "
"try again."
msgstr ""
"Pas de dictionnaire active. S.V.P selectionnez-en un a partir du menu "
"\"Dictionnaires\" et essayez a nouveau."
#: ../lib/gui/mainwin.py:734
msgid "No dictionaries installed"
msgstr "pas de dictionnaire installe"
#: ../lib/gui/mainwin.py:735
msgid ""
"There is no dictionaries installed. You can install one by selecting Tools > "
"Manage Dictionaries > Available"
msgstr ""
"IL n'y a pas de dictionnaire installe. Vous pouvez en installer un en "
"slectionant Outils > Gerer Dictionnaires > Disponible"
#: ../lib/gui/mainwin.py:748
msgid "Please enter some text and try again"
msgstr "S.V.P entrez du texte et essayez a nouveau"
#: ../lib/gui/mainwin.py:780
msgid ""
"Unable to encode text \"%s\" in %s for \"%s\". That logically means the word "
"definition does not exist in the dictionary."
msgstr ""
#: ../lib/gui/mainwin.py:868
msgid "Connect to DICT server"
msgstr "Se connecter au serveur du Dictionnaire"
#: ../lib/gui/mainwin.py:895
msgid "Choose a dictionary from \"Dictionaries\" menu"
msgstr "Choisir un dictionnaire a partir du menu \"Dictionnaires\""
#: ../lib/gui/mainwin.py:916
msgid "Failed to copy text from the clipboard"
msgstr "Echec pour copier texte a partir du presse-papier"
#: ../lib/gui/mainwin.py:918
msgid "Clipboard contains no text data"
msgstr "Le presse-papier ne contient pas de donnees texte"
#: ../lib/gui/mainwin.py:942 ../lib/gui/mainwin.py:1136
#: ../lib/gui/pluginwin.py:772
msgid "Error"
msgstr "Erreur"
#: ../lib/gui/mainwin.py:951
msgid "Groups"
msgstr "Groupes"
#: ../lib/gui/mainwin.py:963
msgid "Manage Dictionaries"
msgstr "Gerer Dictionnaires"
#: ../lib/gui/mainwin.py:977
msgid "File Register"
msgstr "Enregistrement de fichier"
#: ../lib/gui/mainwin.py:985
msgid "Create Dictionaries"
msgstr "Creer Dictionaires"
#: ../lib/gui/mainwin.py:994
msgid "Preferences"
msgstr "Preferences"
#: ../lib/gui/mainwin.py:1082
msgid "Licence Agreement Rejected"
msgstr "Accord de la licence rejete"
#: ../lib/gui/mainwin.py:1083
msgid "You cannot use dictionary \"%s\" without accepting licence agreement"
msgstr ""
"Vous ne pouvez pas utiliser le dictionnaire \"%s\" sans accepter les termes "
"de la licence"
#: ../lib/gui/mainwin.py:1097
msgid "Dictionary Index"
msgstr "Index Dictionnaire"
#: ../lib/gui/mainwin.py:1098
msgid ""
"This is the first time you use this dictionary or it has been changed on "
"disk since last indexing. Indexing is used to make search more efficient. "
"The dictionary will be indexed now. It can take a few or more seconds.\n"
"\n"
"Press OK to continue..."
msgstr ""
"Ceci est la premiere fois que vous utilisez ce dictionnaire ou ca et change "
"sur disque au dernier indexing. Indexing est utilise pour faire des "
"recherches plus efficaces.Le dictionnaire va etre indexe maintenant. Cela "
"peut prendre quelques secondes.\n"
"\n"
"Appuyez sur OK pour continuer..."
#: ../lib/gui/mainwin.py:1115
msgid "Index Creation Error"
msgstr "Erreur de creation d'Index"
#: ../lib/gui/mainwin.py:1116
#, fuzzy
msgid ""
"Error occured while indexing file. This may be because of currently selected "
"character encoding %s is not correct for this dictionary. Try selecting "
"another encoding from View > Character Encoding menu"
msgstr ""
"Le codage selectionne n'est pas correct pour ce dictionnaire. S.V.P "
"selectionnez-en a partir de Editer menu codage de caractere"
#: ../lib/gui/mainwin.py:1137
msgid "Unable to load dictionary index table. Got error: %s"
msgstr ""
#: ../lib/gui/mainwin.py:1147
msgid "Dictionary \"%s\" loaded"
msgstr "Dictionnaire \"%s\" charge"
#: ../lib/gui/mainwin.py:1199
msgid "Error: not supported dictionary type"
msgstr "Erreur: type de dictionnaire non supporte"
#: ../lib/gui/mainwin.py:1304
msgid ""
"Select dictionary format. If you can't find\n"
"the format of your dictionary, the register\n"
"system does not support it yet."
msgstr ""
"Selectionner le format de dictionnaire. Si vous ne pouvez trouver\n"
"le format de votre dictionnaire, le systeme d'enregistrement\n"
"ne le supporte pas encore."
#: ../lib/gui/mainwin.py:1309
msgid "Dictionary format"
msgstr "Format de dictionnaire"
#: ../lib/gui/mainwin.py:1326
msgid "Choose plugin file"
msgstr "Choisissez le fichier de plugin"
#: ../lib/gui/mainwin.py:1342
msgid "About"
msgstr "A propos"
#: ../lib/gui/mainwin.py:1393
msgid "Show word list"
msgstr "Afficher la liste de mot"
#: ../lib/gui/mainwin.py:1410
msgid "Hide word list"
msgstr "Cacher la liste de mot"
#: ../lib/gui/mainwin.py:1419
msgid "Failed to print"
msgstr "Echec a l'impression"
#: ../lib/gui/mainwin.py:1431
msgid "Page preview failed"
msgstr "Apercu de la page echoue"
#: ../lib/gui/miscwin.py:53
msgid "Error: unable to show licence text"
msgstr "Erreur: incapable d'afficher le texte de la licence"
#: ../lib/gui/miscwin.py:59
msgid "Do not accept"
msgstr "Ne pas accepter"
#: ../lib/gui/miscwin.py:62
msgid "Accept"
msgstr "Accepter"
#: ../lib/gui/miscwin.py:76
msgid "Licence Agreement"
msgstr "Acceptation de la licence"
#: ../lib/gui/miscwin.py:103
msgid ""
"You have directories that containt invalid dictionaries and cannot be "
"loaded. \n"
"You can try to remove these directories right now."
msgstr ""
"Vous avez des repertoires qui contiennent des dictionnaires invalides \n"
"et ne peuvent pas etre charges. \n"
"Vous pouvez essayer de retirer ces repertoires maintenant."
#: ../lib/gui/miscwin.py:142 ../lib/gui/pluginwin.py:644
msgid "Unable to remove"
msgstr "Incapable de retirer"
#: ../lib/gui/miscwin.py:143
msgid "Unable to remove directory \"%s\": %s"
msgstr "Incapable de retirer repertoire \"%s\": %s"
#: ../lib/gui/miscwin.py:151
msgid "Invalid Dictionaries"
msgstr "Dictionnaires invalides"
#: ../lib/gui/pluginwin.py:78
msgid "Installed"
msgstr "Installe"
#: ../lib/gui/pluginwin.py:82
msgid "Available"
msgstr "Disponible"
#: ../lib/gui/pluginwin.py:124
msgid ""
"Checked dictionaries are available from the menu, unchecked dictionaries \n"
"are not available from the menu."
msgstr ""
#: ../lib/gui/pluginwin.py:149
msgid "Install From File"
msgstr "Installer a partir du fichier..."
#: ../lib/gui/pluginwin.py:208
msgid "Update List"
msgstr "Mettre a jour la liste"
#: ../lib/gui/pluginwin.py:215
msgid "Install"
msgstr "Installer"
#: ../lib/gui/pluginwin.py:227
msgid "Name"
msgstr "Nom"
#: ../lib/gui/pluginwin.py:228
msgid "Size"
msgstr "Grandeur"
#: ../lib/gui/pluginwin.py:274
msgid "Information About Dictionary"
msgstr "Information a propos du dictionnaire"
#: ../lib/gui/pluginwin.py:288
msgid "Name: "
msgstr "Nom:"
#: ../lib/gui/pluginwin.py:293
msgid "Version: "
msgstr "Version:"
#: ../lib/gui/pluginwin.py:298
msgid "Maintainer: "
msgstr "Entretien:"
#: ../lib/gui/pluginwin.py:515
msgid "List updated"
msgstr "Liste mise-a-jour"
#: ../lib/gui/pluginwin.py:516
msgid "All your dictionaries are up to date."
msgstr "Tous vos dictionnares sont mis-a-jour."
#: ../lib/gui/pluginwin.py:523
msgid "Downloading List"
msgstr "Liste de telechargement"
#: ../lib/gui/pluginwin.py:558
#, fuzzy
msgid "Unable to download list from %s: %s"
msgstr "Incapable de telecharger la liste"
#: ../lib/gui/pluginwin.py:566
msgid "Unable to download list"
msgstr "Incapable de telecharger la liste"
#: ../lib/gui/pluginwin.py:645
#, fuzzy
msgid "Unable to remove dictionary \"%s\""
msgstr "Incapable de retirer repertoire \"%s\": %s"
#: ../lib/gui/pluginwin.py:686
msgid "Downloading %s..."
msgstr "Telechargement %s..."
#: ../lib/gui/pluginwin.py:743
msgid "Unable to download"
msgstr "Incapable de telecharger"
#: ../lib/gui/pluginwin.py:753
msgid "File is damaged"
msgstr "Le fichier est endommage"
#: ../lib/gui/pluginwin.py:754
msgid "Downloaded file is damaged and cannot be installed. Please try again."
msgstr ""
"Le fichier telecharge est endommage et ne peut pas etre installe. S.V.P "
"essayez a nouveau."
#: ../lib/gui/pluginwin.py:773
msgid ""
"Unable to remove old version of \"%s\". Error occured: \"%s\". New "
"version cannot be installed without removing old one."
msgstr ""
#: ../lib/gui/pluginwin.py:798
msgid "Unable to install"
msgstr "Incapable d'installer"
#: ../lib/gui/pluginwin.py:799
#, fuzzy
msgid "Unable to install dictionary \"%s\"."
msgstr "Incapable d'installer le dictionnaire"
#: ../lib/gui/prefswin.py:48
msgid "Default dictionary: "
msgstr "Dictionnaire par defaut:"
#: ../lib/gui/prefswin.py:69
msgid "Default encoding: "
msgstr "Encodage par defaut: "
#: ../lib/gui/prefswin.py:80
msgid "Default DICT server: "
msgstr "Serveur de dictionnaire par defaut:"
#: ../lib/gui/prefswin.py:86
msgid "Default DICT server port: "
msgstr "Port de serveur de dictionnaire par defaut:"
#: ../lib/gui/prefswin.py:99
msgid "Pronunciation"
msgstr ""
#: ../lib/gui/prefswin.py:107
msgid "System Command: "
msgstr ""
#: ../lib/gui/prefswin.py:115
#, fuzzy
msgid "Default"
msgstr "Port par defaut"
#: ../lib/gui/prefswin.py:121
msgid "Pronounce original word"
msgstr ""
#: ../lib/gui/prefswin.py:123
#, fuzzy
msgid "Pronounce translation"
msgstr "Changer la traduction"
#: ../lib/gui/prefswin.py:130
msgid "Save window size on exit"
msgstr "Sauvegarder la grandeur de fenetre lorsque vous quittez"
#: ../lib/gui/prefswin.py:134
msgid "Save window position on exit"
msgstr "Sauvegarder la position de fenetre lorsque vous quittez"
#: ../lib/gui/prefswin.py:138
msgid "Save sash position on exit"
msgstr "Sauvegarder la position sash lorsque vous quittez"
#: ../lib/gui/prefswin.py:143
msgid "Take words from the clipboard by default"
msgstr "Prendre les mots a partir du presse-papier par defaut"
#: ../lib/gui/registerwin.py:66 ../lib/gui/registerwin.py:105
#: ../lib/gui/registerwin.py:148
msgid "Name: %s"
msgstr "Nom: %s"
#: ../lib/gui/registerwin.py:69 ../lib/gui/registerwin.py:106
#: ../lib/gui/registerwin.py:149
msgid "Path: %s"
msgstr "Chemin: %s"
#: ../lib/gui/registerwin.py:72 ../lib/gui/registerwin.py:107
#: ../lib/gui/registerwin.py:150
msgid "Format: %s"
msgstr "Format: %s"
#: ../lib/gui/registerwin.py:75 ../lib/gui/registerwin.py:108
#: ../lib/gui/registerwin.py:151
msgid "Encoding: %s"
msgstr "Encodage: %s"
#: ../lib/gui/registerwin.py:82
msgid "Add new..."
msgstr "Ajouter nouveau..."
#: ../lib/gui/registerwin.py:86
msgid "Remove selected"
msgstr "Retirer l'element selectionne"
#: ../lib/gui/registerwin.py:130 ../lib/gui/registerwin.py:137
msgid "Error while deleting \"%s\""
msgstr "Erreur pendant la suppression\"%s\""
#: ../lib/installer.py:81
msgid "Recognition Error"
msgstr "Reconnaissance d'erreur"
#: ../lib/installer.py:82
msgid "File %s is not supported by OpenDict"
msgstr "Fichier %s n'est pas supporte par OpenDict"
#: ../lib/installer.py:108 ../lib/installer.py:110
msgid "Installation failed"
msgstr "Installation echouee"
#: ../lib/installer.py:122 ../lib/installer.py:308 ../lib/installer.py:316
msgid "Installation Error"
msgstr "Erreur d'installation"
#: ../lib/installer.py:124 ../lib/installer.py:128
msgid "Error: Installation failed"
msgstr "Erreur: Installation echouee"
#: ../lib/installer.py:132
msgid "Dictionary installed"
msgstr "Dictionnaire installe"
#: ../lib/installer.py:133
msgid ""
"Dictionary successfully installed. You can choose it from \"Dictionaries\" "
"menu now."
msgstr ""
"Dictionnaire installe avec succes. Vous pouvez le trouver a partir du menu "
"\"Dictionnaires\" maintenant."
#: ../lib/installer.py:143 ../lib/installer.py:218
msgid "File %s does not exist"
msgstr "Fichier %s n'existe pas"
#: ../lib/installer.py:146 ../lib/installer.py:222
msgid "%s is not a file"
msgstr "%s n'est pas un fichier"
#: ../lib/installer.py:160
msgid "Dictionary \"%s\" is already installed"
msgstr "Dictionnaire \"%s\" est deja installe"
#: ../lib/installer.py:226
msgid "%s is not OpenDict dictionary plugin"
msgstr "%s n'est pas le plugin du dictionnaire OpenDict"
#: ../lib/installer.py:233
msgid "File \"%s\" is not valid ZIP file"
msgstr "Fichier \"%s\" n'est pas un fichier ZIP valide"
#: ../lib/installer.py:238
msgid "Dictionary plugin file is corrupted"
msgstr "Le fichier plugin du dictionnaire est corrompu"
#: ../lib/installer.py:244
msgid "Plugin file is empty (%s)"
msgstr "Le fichier plugin est vide (%s)"
#: ../lib/installer.py:268
msgid "Selected file is not valid OpenDict plugin"
msgstr "Le fichier selectionne n'est pas un plugin OpenDict valide"
#: ../lib/installer.py:295 ../lib/installer.py:377
msgid ""
"This dictionary already installed. If you want to upgrade it, please remove "
"old version first."
msgstr ""
"Ce dictionnaire est deja installe. Si vous voulez le mettre a jour, S.V.P "
"retirer la vielle version tout d'abord."
#: ../lib/installer.py:309 ../lib/installer.py:317
msgid ""
"Installation tool for this dictionary failed to start. Please report this "
"problem to developers."
msgstr ""
"L'outil d'installation pour ce dictionnaire a echoue a dmarrer. S.V.P "
"reporter ce probleme aux developpeurs"
#: ../lib/installer.py:323
msgid "Installation Aborted"
msgstr "Installation avortee"
#: ../lib/installer.py:324
msgid "Dictionary installation has been aborted."
msgstr "L'installation du dictionnaire a ete avortee."
#: ../lib/installer.py:348 ../lib/installer.py:400
msgid ""
"Error while removing created directories after plugin installation failure. "
"This may be permission or disk space error."
msgstr ""
"Erreur pendant la suppresion des repertoires crees apres l'echec de "
"l'installation des plugin. Ceci pourrait etre une erreur de permission ou "
"une erreur d'espace disque."
#: ../lib/installer.py:352
msgid "Unable to install plugin"
msgstr "Incapable d'installer les plugins "
#: ../lib/installer.py:369
msgid "Compressed dictionary file is corrupted"
msgstr "Le fichier compresse du dictionnaire est corrompu"
#: ../lib/installer.py:404
msgid "Unable to install dictionary"
msgstr "Incapable d'installer le dictionnaire"
#: ../lib/misc.py:37
msgid "Dictionary error, please report to its author"
msgstr "Erreur dictionnaire, S.V.P reportez-la a son auteur"
#: ../lib/misc.py:38
msgid "Syntax error"
msgstr "Erreur de syntaxe"
#: ../lib/misc.py:39
msgid "You must be connected to the internet to use this dictionary"
msgstr "Vous devez etre connecte a Internet pour utiliser ce dictionnaire"
#: ../lib/misc.py:40
msgid "Time out"
msgstr "Temps d'arret"
#: ../lib/misc.py:41
msgid "Bad encoding is set for this dictionary, try another"
msgstr ""
"Un mauvais encodement est initialis pour ce dictionnaire, essayez-en un "
"autre"
#: ../lib/misc.py:48
msgid "Unicode (UTF-8)"
msgstr ""
#: ../lib/misc.py:49
msgid "Western (ISO-8859-1)"
msgstr ""
#: ../lib/misc.py:50
msgid "Central European (ISO-8859-2)"
msgstr ""
#: ../lib/misc.py:51
msgid "Nordic (ISO-8859-10)"
msgstr ""
#: ../lib/misc.py:52
msgid "South European (ISO-8859-3)"
msgstr ""
#: ../lib/misc.py:53
msgid "Greek (ISO-8859-7)"
msgstr ""
#: ../lib/misc.py:54
msgid "Baltic (ISO-8859-13)"
msgstr ""
#: ../lib/misc.py:55
msgid "Cyrillic (KOI8-R)"
msgstr ""
#: ../lib/misc.py:56
msgid "Arabic (ISO-8859-6)"
msgstr ""
#: ../lib/util.py:235
msgid "Downloading... %d%%"
msgstr "Telechargement... %d%%"
#: ../opendict.py:115
msgid "wxPython Version Error"
msgstr "wxPython version erreur"
#: ../opendict.py:116
msgid ""
"wxPython %s is installed on this system.\n"
"\n"
"OpenDict %s requires wxPython 2.6 to run smoothly.\n"
"\n"
"You can find wxPython 2.6 at http://www.wxpython.org or you can install it "
"using your system package manager."
msgstr ""
#~ msgid "&License"
#~ msgstr "&Licence"
#~ msgid "Edit Dictionaries"
#~ msgstr "Taisyti odynus"
opendict-0.6.3/po/lt.po 0000644 0001750 0001750 00000100021 10654057311 013360 0 ustar mjoc mjoc msgid ""
msgstr ""
"Project-Id-Version: OpenDict 0.6.3\n"
"POT-Creation-Date: 2007-08-01 13:21+EEST\n"
"PO-Revision-Date: 2007-08-01 13:20+0300\n"
"Last-Translator: Martynas Jocius \n"
"Language-Team: Lithuanian \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=iso-8859-13\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Poedit-Bookmarks: -1,-1,-1,-1,104,-1,-1,-1,-1,-1\n"
#: ../lib/errortype.py:57
msgid "Success"
msgstr "Skm"
#: ../lib/errortype.py:58
msgid "Search successfully finished."
msgstr "Paieka skmingai baigta"
#: ../lib/errortype.py:65 ../lib/misc.py:36
msgid "Not found"
msgstr "Nerasta"
#: ../lib/errortype.py:66
msgid "Word or phrase not found. Try less letters or fewer words."
msgstr ""
"odis arba fraz nebuvo rasti. Bandykite vesti maiau raidi arba odi."
#: ../lib/errortype.py:74
msgid "Internal error"
msgstr "Vidin klaida"
#: ../lib/errortype.py:75
msgid ""
"Internal error occured. Please send bug report to the dictionary's of "
"current use authors. Thank you."
msgstr ""
"vyko vidin klaida. Praome isisti klaidos praneim apie aktyvuoto "
"odyno klaid jo autoriams. Dkojame."
#: ../lib/errortype.py:83
msgid "Not connected"
msgstr "Nepavyko prisijungti"
#: ../lib/errortype.py:84
msgid ""
"This dictionary uses Internet connection to translate words. Please connect "
"to the Internet and try again."
msgstr ""
"is odynas paiek atlieka Internete. Prisijunkite prie Interneto ir "
"bandykite dar kart."
#: ../lib/errortype.py:93 ../lib/gui/dictconnwin.py:183
#: ../lib/gui/dictconnwin.py:199
msgid "Connection Error"
msgstr "Prisijungimo klaida"
#: ../lib/errortype.py:94
msgid "Could not connect to host. Check your Internet connection or try later."
msgstr ""
"Nepavyko prisijungti. Patikrinkite Interneto ry arba pabandykite vliau."
#: ../lib/errortype.py:102
msgid "Invalid encoding"
msgstr "Netinkama koduot"
#: ../lib/errortype.py:103
msgid ""
"Selected encoding is not correct for this dictionary. Please select another "
"from Edit > Character Encoding menu"
msgstr ""
"Pasirinkta koduot nra tinkama iam odynui. Pasirinkite kit koduot i "
"meniu Keisti > Teksto koduot"
#: ../lib/errortype.py:112
msgid "OpenDict Bug"
msgstr "OpenDict klaida"
#: ../lib/errortype.py:113
msgid ""
"Internal error occured. Please send bug report to OpenDict authors to "
"prevent this error in the future. Thank you!"
msgstr ""
"vyko vidin klaida. Kad tai nepasikartot ateityje, praome isisti "
"praneim apie klaid OpenDict autoriams. Dkojame!"
#: ../lib/errortype.py:121
msgid "Unknown Error"
msgstr "Neinoma klaida"
#: ../lib/errortype.py:122
msgid "Unknown error occured."
msgstr "vyko neinoma klaida."
#: ../lib/gui/dictaddwin.py:35
msgid "Add new dictionary"
msgstr "Pridti nauj odyn"
#: ../lib/gui/dictaddwin.py:41
msgid ""
"The file format of \"%s\" could not be \n"
"recognized by its extention. Please select one\n"
"from the list:"
msgstr ""
"Bylos formatas %s negali bti atpaintas\n"
"pagal pltin. Pasirinkite i srao: "
#: ../lib/gui/dictaddwin.py:47 ../lib/gui/dictaddwin.py:48
#: ../lib/gui/dictaddwin.py:49 ../lib/gui/dictaddwin.py:50
msgid "\"%s\" dictionary format"
msgstr "%s odyno formatas"
#: ../lib/gui/dictaddwin.py:59 ../lib/gui/dicteditorwin.py:91
#: ../lib/gui/prefswin.py:149
msgid "OK"
msgstr "Gerai"
#: ../lib/gui/dictaddwin.py:62 ../lib/gui/dictconnwin.py:133
#: ../lib/gui/dicteditorwin.py:94 ../lib/gui/dicteditorwin.py:255
#: ../lib/gui/prefswin.py:152
msgid "Cancel"
msgstr "Ataukti"
#: ../lib/gui/dictconnwin.py:55
msgid "Server: "
msgstr "Serveris: "
#: ../lib/gui/dictconnwin.py:64
msgid "Default Server"
msgstr "Numatytas serveris"
#: ../lib/gui/dictconnwin.py:70
msgid "Port: "
msgstr "Prievadas: "
#: ../lib/gui/dictconnwin.py:73
msgid "Default Port"
msgstr "Numatytas prievadas"
#: ../lib/gui/dictconnwin.py:83
msgid "Database: "
msgstr "Duomen baz: "
#: ../lib/gui/dictconnwin.py:87
msgid "Search in all databases"
msgstr "Iekoti visose duomen bazse"
#: ../lib/gui/dictconnwin.py:94
msgid "Fetch List"
msgstr "Parsisti sra"
#: ../lib/gui/dictconnwin.py:100
msgid "Character encoding: "
msgstr "Simboli koduot:"
#: ../lib/gui/dictconnwin.py:130
msgid "Connect"
msgstr "Prisijungti"
#: ../lib/gui/dictconnwin.py:174 ../lib/gui/mainwin.py:685 ../lib/util.py:240
msgid "Done"
msgstr "Atlikta"
#: ../lib/gui/dictconnwin.py:178
msgid "Receiving database list..."
msgstr "Siuniamas duomen bazi sraas..."
#: ../lib/gui/dictconnwin.py:184 ../lib/gui/dictconnwin.py:200
msgid "Unable to connect to server"
msgstr "Nepavyko prisijungti prie serverio"
#: ../lib/gui/dictconnwin.py:218
msgid "Connecting..."
msgstr "Jungiamasi..."
#: ../lib/gui/dictconnwin.py:254 ../lib/util.py:219
msgid "Connecting to %s..."
msgstr "Jungiamasi prie %s..."
#: ../lib/gui/dicteditorwin.py:53
msgid "Word: "
msgstr "odis: "
#: ../lib/gui/dicteditorwin.py:88
msgid "Add translation field"
msgstr "Pridti vertimo laukel"
#: ../lib/gui/dicteditorwin.py:111
msgid "Translation #%d: "
msgstr "Vertimas #%d: "
#: ../lib/gui/dicteditorwin.py:245
msgid "Dictionary \"%s\" has been changed"
msgstr "odynas %s buvo pakeistas"
#: ../lib/gui/dicteditorwin.py:249 ../lib/gui/dicteditorwin.py:337
msgid "Save"
msgstr "Isaugoti"
#: ../lib/gui/dicteditorwin.py:252
msgid "Do not save"
msgstr "Nesaugoti"
#: ../lib/gui/dicteditorwin.py:305
msgid "Dictionary editor"
msgstr "odyn redaktorius"
#: ../lib/gui/dicteditorwin.py:321
msgid "Add"
msgstr "Pridti"
#: ../lib/gui/dicteditorwin.py:322
msgid "Add word"
msgstr "Pridti od"
#: ../lib/gui/dicteditorwin.py:325
msgid "Edit"
msgstr "Keisti"
#: ../lib/gui/dicteditorwin.py:326
msgid "Change translation"
msgstr "Keisti vertim"
#: ../lib/gui/dicteditorwin.py:329 ../lib/gui/miscwin.py:116
#: ../lib/gui/pluginwin.py:156
msgid "Remove"
msgstr "Paalinti"
#: ../lib/gui/dicteditorwin.py:330
msgid "Remove selected word"
msgstr "Paalinti pasirinkt od"
#: ../lib/gui/dicteditorwin.py:333
msgid "Sort"
msgstr "Rikiuoti"
#: ../lib/gui/dicteditorwin.py:334
msgid "Sort word list"
msgstr "Rikiuoti odi sra"
#: ../lib/gui/dicteditorwin.py:338
msgid "Save words to file"
msgstr "Isaugoti odius byl"
#: ../lib/gui/dicteditorwin.py:341
msgid "Save As..."
msgstr "Isaugoti kaip..."
#: ../lib/gui/dicteditorwin.py:342
msgid "Save with a different file name"
msgstr "Isaugoti kitu vardu"
#: ../lib/gui/dicteditorwin.py:351 ../lib/gui/mainwin.py:1371
msgid "Word List"
msgstr "odi sraas"
#: ../lib/gui/dicteditorwin.py:370
msgid "New..."
msgstr "Naujas..."
#: ../lib/gui/dicteditorwin.py:371
msgid "Start new dictionary"
msgstr "Sukurti nauj odyn"
#: ../lib/gui/dicteditorwin.py:374
msgid "Open..."
msgstr "Atidaryti..."
#: ../lib/gui/dicteditorwin.py:375
msgid "Open dictionary file"
msgstr "Atidaryti odyno byl"
#: ../lib/gui/dicteditorwin.py:378 ../lib/gui/errorwin.py:84
#: ../lib/gui/helpwin.py:69 ../lib/gui/helpwin.py:145
#: ../lib/gui/helpwin.py:208 ../lib/gui/miscwin.py:65
#: ../lib/gui/miscwin.py:124 ../lib/gui/pluginwin.py:92
#: ../lib/gui/registerwin.py:89
msgid "Close"
msgstr "Udaryti"
#: ../lib/gui/dicteditorwin.py:379
msgid "Close editor window"
msgstr "Udaryti redaktoriaus lang"
#: ../lib/gui/dicteditorwin.py:410
msgid "New Word"
msgstr "Naujas odis"
#: ../lib/gui/dicteditorwin.py:425
msgid "Edit Word"
msgstr "Taisyti od"
#: ../lib/gui/dicteditorwin.py:457
msgid "List is empty"
msgstr "Sraas tuias"
#: ../lib/gui/dicteditorwin.py:463
msgid "List sorted"
msgstr "Sraas surikiuotas"
#: ../lib/gui/dicteditorwin.py:486
msgid "Save file"
msgstr "Isaugoti byl"
#: ../lib/gui/dicteditorwin.py:507
msgid "Dictionary saved"
msgstr "odynas isaugotas"
#: ../lib/gui/dicteditorwin.py:517
msgid "Untitled"
msgstr "Be pavadinimo"
#: ../lib/gui/dicteditorwin.py:588 ../lib/gui/dicteditorwin.py:645
msgid "Exit confirmation"
msgstr "Ijimo patvirtinimas"
#: ../lib/gui/dicteditorwin.py:600 ../lib/gui/mainwin.py:1293
#: ../lib/installer.py:61
msgid "Choose dictionary file"
msgstr "Pasirinkite odyno byl"
#: ../lib/gui/dicteditorwin.py:614
msgid "Open Failed"
msgstr "Nepavyko atidaryti"
#: ../lib/gui/dicteditorwin.py:615
msgid "Unable to open dictionary (got message: %s)"
msgstr "Nepavyko atidaryti odyno (gautas praneimas: %s)"
#: ../lib/gui/dicteditorwin.py:630
msgid "Dictionary loaded"
msgstr "odynas keltas"
#: ../lib/gui/errorwin.py:72
msgid "An error occured:"
msgstr "vyko klaida:"
#: ../lib/gui/helpwin.py:106
msgid "Written By"
msgstr "Autoriai"
#: ../lib/gui/helpwin.py:118
msgid "Translated By"
msgstr "Vertjai"
#: ../lib/gui/helpwin.py:123
msgid ""
"Ports:\n"
"\n"
msgstr ""
"Pritaikymas sistemoms:\n"
"\n"
#: ../lib/gui/helpwin.py:128
msgid "Thanks To"
msgstr "Dkojame"
#: ../lib/gui/helpwin.py:134
msgid ""
"OpenDict project is sponsored by IDILES.\n"
"Visit company's website at http://www.idiles.com.\n"
"\n"
"Report problems by email address support@idiles.com."
msgstr ""
"OpenDict projekt remia IDILES.\n"
"Apsilankykite bendrovs interneto svetainje adresu http://www.idiles.lt.\n"
"\n"
"Praome praneti apie klaidas el. pato adresu support@idiles.com."
#: ../lib/gui/helpwin.py:141
msgid "Sponsors"
msgstr "Rmjai"
#: ../lib/gui/helpwin.py:179 ../lib/gui/helpwin.py:192
msgid "OpenDict is a multiplatform dictionary."
msgstr "OpenDict yra daugiaplatformis odynas."
#: ../lib/gui/helpwin.py:202
msgid "Credits"
msgstr "Padkos"
#: ../lib/gui/helpwin.py:205 ../lib/gui/helpwin.py:234
msgid "Licence"
msgstr "Licencija"
#: ../lib/gui/mainwin.py:92 ../lib/gui/mainwin.py:774
#: ../lib/gui/mainwin.py:812
msgid "Stopped"
msgstr "Sustabdyta"
#: ../lib/gui/mainwin.py:97 ../lib/gui/mainwin.py:779
msgid "Encode Failed"
msgstr "Nepavyko ikoduoti"
#: ../lib/gui/mainwin.py:98
msgid "Unable to encode text \"%s\" in %s for \"%s\"."
msgstr "Nepavyko ukoduoti teksto %s koduote %s odynui %s."
#: ../lib/gui/mainwin.py:106 ../lib/gui/mainwin.py:757
#: ../lib/gui/mainwin.py:1355
msgid "Searching..."
msgstr "Iekoma..."
#: ../lib/gui/mainwin.py:159
msgid "Look Up\tCtrl-U"
msgstr "Iekoti\tCtrl-U"
#: ../lib/gui/mainwin.py:160
msgid "Lookup up word in the dictionary"
msgstr "Iekoti odio odyne"
#: ../lib/gui/mainwin.py:165
msgid "&Close Dictionary\tCtrl-W"
msgstr "&Udaryti odyn\tCtrl-W"
#: ../lib/gui/mainwin.py:166
msgid "Close opened dicitonary"
msgstr "Udaryti aktyv odyn"
#: ../lib/gui/mainwin.py:169
msgid "E&xit\tCtrl-Q"
msgstr "&Ieiti\tCtrl-Q"
#: ../lib/gui/mainwin.py:170
msgid "Exit program"
msgstr "Baigti darb"
#: ../lib/gui/mainwin.py:172
msgid "&File"
msgstr "&Byla"
#: ../lib/gui/mainwin.py:180
msgid "&Clear Search Entry\tCtrl-L"
msgstr "Ivalyti paiekos laukel\tCtrl-L"
#: ../lib/gui/mainwin.py:183
msgid "Clear History"
msgstr "Ivalyti istorij"
#: ../lib/gui/mainwin.py:191
msgid "Copy\tCtrl-C"
msgstr "Kopijuoti\tCtrl-C"
#: ../lib/gui/mainwin.py:192
msgid "Copy selected translation text"
msgstr "Nukopijuoti paymt vertimo tekst"
#: ../lib/gui/mainwin.py:195
msgid "Paste\tCtrl-V"
msgstr "dti\tCtrl-V"
#: ../lib/gui/mainwin.py:196
msgid "Paste clipboard text into the search entry"
msgstr "Kopijuoti ikarpins tekst paiekos laukel"
#: ../lib/gui/mainwin.py:201
msgid "Edit preferences"
msgstr "Keisti nustatymus"
#: ../lib/gui/mainwin.py:201
msgid "Preferences...\tCtrl-P"
msgstr "Nustatymai...\tCtrl-N"
#: ../lib/gui/mainwin.py:203
msgid "&Edit"
msgstr "&Keisti"
#: ../lib/gui/mainwin.py:213
msgid "Increase\tCtrl-="
msgstr "Padidinti\tCtrl-="
#: ../lib/gui/mainwin.py:214
msgid "Increase text size"
msgstr "Padidinti tekst"
#: ../lib/gui/mainwin.py:215
msgid "Decrease\tCtrl--"
msgstr "Sumainti\tCtrl--"
#: ../lib/gui/mainwin.py:216
msgid "Decrease text size"
msgstr "Sumainti tekst"
#: ../lib/gui/mainwin.py:218
msgid "Normal\tCtrl-0"
msgstr "prastas\tCtrl-0"
#: ../lib/gui/mainwin.py:219
msgid "Set normal text size"
msgstr "Nustatyti prast teksto dyd"
#: ../lib/gui/mainwin.py:220
msgid "Font Size"
msgstr "rifto dydis"
#: ../lib/gui/mainwin.py:235
msgid "Font Face"
msgstr "riftas"
#: ../lib/gui/mainwin.py:250
msgid "Character Encoding"
msgstr "Simboli koduot"
#: ../lib/gui/mainwin.py:255
msgid "Show/Hide Word List...\tCtrl-H"
msgstr "Rodyti/slpti odi sra...\tCtrl-H"
#: ../lib/gui/mainwin.py:256
msgid "Show or hide word list"
msgstr "Rodyti arba paslpti odi sra"
#: ../lib/gui/mainwin.py:259
msgid "&View"
msgstr "&Perira"
#: ../lib/gui/mainwin.py:296
msgid "&Install Dictionary From File..."
msgstr "&diegti odyn i bylos..."
#: ../lib/gui/mainwin.py:298
msgid "&Dictionaries"
msgstr "o&dynai"
#: ../lib/gui/mainwin.py:307
msgid "Manage Dictionaries...\tCtrl-M"
msgstr "Tvarkyti odynus...\tCtrl-M"
#: ../lib/gui/mainwin.py:308
msgid "Install or remove dictionaries"
msgstr "diegti arba paalinti odynus"
#: ../lib/gui/mainwin.py:310
msgid "Create Dictionaries..."
msgstr "Kurti odynus..."
#: ../lib/gui/mainwin.py:311
msgid "Create and edit dictionaries"
msgstr "Sukurti ir taisyti odynus"
#: ../lib/gui/mainwin.py:318
msgid "Take Words From Clipboard"
msgstr "Imti odius i ikarpins"
#: ../lib/gui/mainwin.py:319
msgid "Scan the clipboard for text to translate"
msgstr "Imti odius i ikarpins"
#: ../lib/gui/mainwin.py:327
msgid "Connect to DICT Server..."
msgstr "Prisijungti prie DICT serverio..."
#: ../lib/gui/mainwin.py:328
msgid "Open connection to DICT server"
msgstr "Prisijungti prie DICT serverio"
#: ../lib/gui/mainwin.py:333
msgid "Pronounce\tCtrl-E"
msgstr "Itarti balsu\tCtrl-E"
#: ../lib/gui/mainwin.py:334
msgid "Pronounce word"
msgstr "Itarti od balsu"
#: ../lib/gui/mainwin.py:337
msgid "Tools"
msgstr "rankiai"
#: ../lib/gui/mainwin.py:346
msgid "&About\tCtrl-A"
msgstr "&Apie\tCtrl-A"
#: ../lib/gui/mainwin.py:348
msgid "&Help"
msgstr "&Pagalba"
#: ../lib/gui/mainwin.py:353
msgid "Word:"
msgstr "odis: "
#: ../lib/gui/mainwin.py:358
msgid ""
"Enter some text and press \"Look Up\" button or [ENTER] key on your keyboard"
msgstr ""
"veskite tekst ir spauskite mygtuk Iekoti arba [ENTER] klavi savo "
"klaviatroje "
#: ../lib/gui/mainwin.py:364
msgid "Look Up"
msgstr "Iekoti"
#: ../lib/gui/mainwin.py:365
msgid "Click this button to look up word in the dictionary"
msgstr "Paspauskite mygtuk odio paiekai odyne"
#: ../lib/gui/mainwin.py:376
msgid "History Back"
msgstr "Atgal"
#: ../lib/gui/mainwin.py:385
msgid "History Forward"
msgstr "Pirmyn"
#: ../lib/gui/mainwin.py:395
msgid "Stop searching"
msgstr "Sustabdyti paiek"
#: ../lib/gui/mainwin.py:419
msgid "Translation"
msgstr "Vertimas"
#: ../lib/gui/mainwin.py:527
msgid ""
"\n"
"\n"
"\n"
"\n"
"\n"
"\n"
"
Welcome to OpenDict
\n"
"
Short usage information:
\n"
"
\n"
"
To start using dictionary, select one from Dictionaries\n"
" menu.\n"
"
\n"
"
To install new dictionary from the Internet, select\n"
" Manage Dictionaries\n"
" from Tools menu and choose Available tab."
"li>\n"
"
To install new dictionary from file, select Install Dictionary "
"From File...\n"
" from Dictionaries menu.\n"
"
Nordami pradti naudotis odynu, pasirinkite tinkam i "
"odynai\n"
" meniu.\n"
"
\n"
"
Nordami diegti nauj odyn i Interneto, pasirinkite\n"
" Tvarkyti odynus\n"
" i rankiai meniu, tada pasirinkite Galimi "
"kortel.
\n"
"
Nordami diegti nauj odyn i bylos, pasirinkite diegti "
"odyn i bylos...\n"
" i odynai meniu.\n"
"
\n"
"
\n"
"\n"
"\n"
#: ../lib/gui/mainwin.py:649
msgid ""
"Translation cannot be displayed using selected encoding %s. Please try "
"another encoding from View > Character Encoding menu."
msgstr ""
"Pasirinkta koduot nra tinkama iam odynui. Pasirinkite kit koduot i "
"meniu Keisti > Teksto koduot"
#: ../lib/gui/mainwin.py:681
msgid "1 word matches"
msgstr "Atitikmen skaiius: 1"
#: ../lib/gui/mainwin.py:683
msgid "%d words match"
msgstr "Atitikmen skaiius: %d"
#: ../lib/gui/mainwin.py:730
msgid "No dictionary activated"
msgstr "Neaktyvuotas joks odynas"
#: ../lib/gui/mainwin.py:731
msgid ""
"No dictionary activated. Please select one from \"Dictionaries\" menu and "
"try again."
msgstr ""
"Neaktyvuotas joks odynas. Pasirinkite odyn i odynai meniu ir "
"bandykite dar kart."
#: ../lib/gui/mainwin.py:734
msgid "No dictionaries installed"
msgstr "Nra diegt odyn"
#: ../lib/gui/mainwin.py:735
msgid ""
"There is no dictionaries installed. You can install one by selecting Tools > "
"Manage Dictionaries > Available"
msgstr ""
"Nra diegt odyn. diegti galite i meniu pasirinkdami rankiai > "
"Tvarkyti odynus > Galimi"
#: ../lib/gui/mainwin.py:748
msgid "Please enter some text and try again"
msgstr "veskite tekst ir bandykite dar kart"
#: ../lib/gui/mainwin.py:780
msgid ""
"Unable to encode text \"%s\" in %s for \"%s\". That logically means the word "
"definition does not exist in the dictionary."
msgstr ""
"Nepavyko ukoduoti teksto %s koduote %s. Tai gali reikti, jog iekomo "
"odio odyne visai nra."
#: ../lib/gui/mainwin.py:868
msgid "Connect to DICT server"
msgstr "Prisijungti prie DICT serverio"
#: ../lib/gui/mainwin.py:895
msgid "Choose a dictionary from \"Dictionaries\" menu"
msgstr "Isirinkite odyn i odynai meniu"
#: ../lib/gui/mainwin.py:916
msgid "Failed to copy text from the clipboard"
msgstr "Nepavyko paimti teksto i ikarpins"
#: ../lib/gui/mainwin.py:918
msgid "Clipboard contains no text data"
msgstr "Ikarpinje teksto nra"
#: ../lib/gui/mainwin.py:942 ../lib/gui/mainwin.py:1136
#: ../lib/gui/pluginwin.py:772
msgid "Error"
msgstr "Klaida"
#: ../lib/gui/mainwin.py:951
msgid "Groups"
msgstr "Grups"
#: ../lib/gui/mainwin.py:963
msgid "Manage Dictionaries"
msgstr "Tvarkyti odynus"
#: ../lib/gui/mainwin.py:977
msgid "File Register"
msgstr "Byl registras"
#: ../lib/gui/mainwin.py:985
msgid "Create Dictionaries"
msgstr "Kurti odynus"
#: ../lib/gui/mainwin.py:994
msgid "Preferences"
msgstr "Nustatymai"
#: ../lib/gui/mainwin.py:1082
msgid "Licence Agreement Rejected"
msgstr "Licencija atmesta"
#: ../lib/gui/mainwin.py:1083
msgid "You cannot use dictionary \"%s\" without accepting licence agreement"
msgstr ""
"Js negalite naudotis odynu %s, jei nesutinkate su licencijos slygomis"
#: ../lib/gui/mainwin.py:1097
msgid "Dictionary Index"
msgstr "odyno indeksas"
#: ../lib/gui/mainwin.py:1098
msgid ""
"This is the first time you use this dictionary or it has been changed on "
"disk since last indexing. Indexing is used to make search more efficient. "
"The dictionary will be indexed now. It can take a few or more seconds.\n"
"\n"
"Press OK to continue..."
msgstr ""
"is odynas naudojamas pirm kart arba buvo pakeistas po paskutinio "
"indeksavimo. Indeksavimas naudojamas odi paiekai odyne pagreitinti. "
"Dabar odynas bus perindeksuotas. Tai gali utrukti kelet sekudi.\n"
"\n"
"Nordami pratsti, spauskite Gerai..."
#: ../lib/gui/mainwin.py:1115
msgid "Index Creation Error"
msgstr "Indeksavimo klaida"
#: ../lib/gui/mainwin.py:1116
msgid ""
"Error occured while indexing file. This may be because of currently selected "
"character encoding %s is not correct for this dictionary. Try selecting "
"another encoding from View > Character Encoding menu"
msgstr ""
"Indeksuojant odyn vyko klaida. Tai galjo vykti dl pasirinktos "
"netinkamos iam odynui teksto koduots %s. Pabandykite pasirinkti kit "
"koduot i meniu Perira > Teksto koduot."
#: ../lib/gui/mainwin.py:1137
msgid "Unable to load dictionary index table. Got error: %s"
msgstr "Nepavyko pakrauti odyno indeks lentels. Gauta klaida: %s"
#: ../lib/gui/mainwin.py:1147
msgid "Dictionary \"%s\" loaded"
msgstr "keltas odynas %s"
#: ../lib/gui/mainwin.py:1199
msgid "Error: not supported dictionary type"
msgstr "Klaida: nepalaikomas odyno formatas"
#: ../lib/gui/mainwin.py:1304
msgid ""
"Select dictionary format. If you can't find\n"
"the format of your dictionary, the register\n"
"system does not support it yet."
msgstr ""
"Pasirinkite odyno format. Jei reikiamo\n"
"formato srae nra, registr sistema kol\n"
"kas jo nepalaiko."
#: ../lib/gui/mainwin.py:1309
msgid "Dictionary format"
msgstr "odyno formatas"
#: ../lib/gui/mainwin.py:1326
msgid "Choose plugin file"
msgstr "Pasirinkite priedo byl"
#: ../lib/gui/mainwin.py:1342
msgid "About"
msgstr "Apie"
#: ../lib/gui/mainwin.py:1393
msgid "Show word list"
msgstr "Rodyti odi sra"
#: ../lib/gui/mainwin.py:1410
msgid "Hide word list"
msgstr "Paslpti odi sra"
#: ../lib/gui/mainwin.py:1419
msgid "Failed to print"
msgstr "Nepavyko atspausdinti"
#: ../lib/gui/mainwin.py:1431
msgid "Page preview failed"
msgstr "Puslapio perira nepavyko"
#: ../lib/gui/miscwin.py:53
msgid "Error: unable to show licence text"
msgstr "Klaida: nepavyko parodyti licencijos teksto"
#: ../lib/gui/miscwin.py:59
msgid "Do not accept"
msgstr "Nesutinku"
#: ../lib/gui/miscwin.py:62
msgid "Accept"
msgstr "Sutinku"
#: ../lib/gui/miscwin.py:76
msgid "Licence Agreement"
msgstr "Licencija"
#: ../lib/gui/miscwin.py:103
msgid ""
"You have directories that containt invalid dictionaries and cannot be "
"loaded. \n"
"You can try to remove these directories right now."
msgstr ""
"Pas jus yra katalog su blogais odynais, kurie negali bti krauti. \n"
"Galite pabandyti tuojau pat paalinti tuos katalogus."
#: ../lib/gui/miscwin.py:142 ../lib/gui/pluginwin.py:644
msgid "Unable to remove"
msgstr "Nepavyko paalinti"
#: ../lib/gui/miscwin.py:143
msgid "Unable to remove directory \"%s\": %s"
msgstr "Nepavyko paalinti katalogo %s: %s"
#: ../lib/gui/miscwin.py:151
msgid "Invalid Dictionaries"
msgstr "Sugadinti odynai"
#: ../lib/gui/pluginwin.py:78
msgid "Installed"
msgstr "diegti"
#: ../lib/gui/pluginwin.py:82
msgid "Available"
msgstr "Galimi"
#: ../lib/gui/pluginwin.py:124
msgid ""
"Checked dictionaries are available from the menu, unchecked dictionaries \n"
"are not available from the menu."
msgstr "Paymti odynai yra pasiekiami i meniu, nepaymti nepasiekiami."
#: ../lib/gui/pluginwin.py:149
msgid "Install From File"
msgstr "diegti i bylos..."
#: ../lib/gui/pluginwin.py:208
msgid "Update List"
msgstr "Atnaujinti sra"
#: ../lib/gui/pluginwin.py:215
msgid "Install"
msgstr "diegti"
#: ../lib/gui/pluginwin.py:227
msgid "Name"
msgstr "Pavadinimas"
#: ../lib/gui/pluginwin.py:228
msgid "Size"
msgstr "Dydis"
#: ../lib/gui/pluginwin.py:274
msgid "Information About Dictionary"
msgstr "Informacija apie odyn"
#: ../lib/gui/pluginwin.py:288
msgid "Name: "
msgstr "Pavadinimas:"
#: ../lib/gui/pluginwin.py:293
msgid "Version: "
msgstr "Versija:"
#: ../lib/gui/pluginwin.py:298
msgid "Maintainer: "
msgstr "Priirtojas:"
#: ../lib/gui/pluginwin.py:515
msgid "List updated"
msgstr "Sraas atnaujintas"
#: ../lib/gui/pluginwin.py:516
msgid "All your dictionaries are up to date."
msgstr "Js turimi odynai yra patys naujausi."
#: ../lib/gui/pluginwin.py:523
msgid "Downloading List"
msgstr "Parsiuniamas sraas"
#: ../lib/gui/pluginwin.py:558
msgid "Unable to download list from %s: %s"
msgstr "Nepavyko parsisti odyn srao i %s: %s"
#: ../lib/gui/pluginwin.py:566
msgid "Unable to download list"
msgstr "Nepavyko parsisti srao"
#: ../lib/gui/pluginwin.py:645
msgid "Unable to remove dictionary \"%s\""
msgstr "Nepavyko paalinti odyno %s"
#: ../lib/gui/pluginwin.py:686
msgid "Downloading %s..."
msgstr "Parsiuniamas %s..."
#: ../lib/gui/pluginwin.py:743
msgid "Unable to download"
msgstr "Nepavyko parsisti"
#: ../lib/gui/pluginwin.py:753
msgid "File is damaged"
msgstr "Byla yra sugadinta"
#: ../lib/gui/pluginwin.py:754
msgid "Downloaded file is damaged and cannot be installed. Please try again."
msgstr ""
"Parsista byla yra sugadinta ir negali bti diegta. Bandykite dar kart."
#: ../lib/gui/pluginwin.py:773
msgid ""
"Unable to remove old version of \"%s\". Error occured: \"%s\". New "
"version cannot be installed without removing old one."
msgstr ""
"Nepavyko imesti senos %s versijos. vyko klaida: %s. Nauja "
"versija negali bti instaliuota tol, kol nebus imesta sena."
#: ../lib/gui/pluginwin.py:798
msgid "Unable to install"
msgstr "Nepavyko diegti"
#: ../lib/gui/pluginwin.py:799
msgid "Unable to install dictionary \"%s\"."
msgstr "Nepavyko diegti odyno %s."
#: ../lib/gui/prefswin.py:48
msgid "Default dictionary: "
msgstr "Numatytas odynas:"
#: ../lib/gui/prefswin.py:69
msgid "Default encoding: "
msgstr "Numatyta koduot: "
#: ../lib/gui/prefswin.py:80
msgid "Default DICT server: "
msgstr "Numatytas DICT serveris:"
#: ../lib/gui/prefswin.py:86
msgid "Default DICT server port: "
msgstr "Numatytas DICT serverio prievadas:"
#: ../lib/gui/prefswin.py:99
msgid "Pronunciation"
msgstr "Tarimas"
#: ../lib/gui/prefswin.py:107
msgid "System Command: "
msgstr "Sistemos komanda: "
#: ../lib/gui/prefswin.py:115
msgid "Default"
msgstr "Numatyta"
#: ../lib/gui/prefswin.py:121
msgid "Pronounce original word"
msgstr "Itarti original od"
#: ../lib/gui/prefswin.py:123
msgid "Pronounce translation"
msgstr "Itarti vertim"
#: ../lib/gui/prefswin.py:130
msgid "Save window size on exit"
msgstr "Ieinant isaugoti lango dyd"
#: ../lib/gui/prefswin.py:134
msgid "Save window position on exit"
msgstr "Ieinant isaugoti lango pozicij"
#: ../lib/gui/prefswin.py:138
msgid "Save sash position on exit"
msgstr "Ieinant isaugoti skyriklio pozicij"
#: ../lib/gui/prefswin.py:143
msgid "Take words from the clipboard by default"
msgstr "Visada imti odius i ikarpins"
#: ../lib/gui/registerwin.py:66 ../lib/gui/registerwin.py:105
#: ../lib/gui/registerwin.py:148
msgid "Name: %s"
msgstr "Pavadinimas: %s"
#: ../lib/gui/registerwin.py:69 ../lib/gui/registerwin.py:106
#: ../lib/gui/registerwin.py:149
msgid "Path: %s"
msgstr "Kelias: %s"
#: ../lib/gui/registerwin.py:72 ../lib/gui/registerwin.py:107
#: ../lib/gui/registerwin.py:150
msgid "Format: %s"
msgstr "Formatas: %s"
#: ../lib/gui/registerwin.py:75 ../lib/gui/registerwin.py:108
#: ../lib/gui/registerwin.py:151
msgid "Encoding: %s"
msgstr "Koduot: %s"
#: ../lib/gui/registerwin.py:82
msgid "Add new..."
msgstr "Pridti nauj..."
#: ../lib/gui/registerwin.py:86
msgid "Remove selected"
msgstr "Paalinti paymt"
#: ../lib/gui/registerwin.py:130 ../lib/gui/registerwin.py:137
msgid "Error while deleting \"%s\""
msgstr "Klaida paalinant %s"
#: ../lib/installer.py:81
msgid "Recognition Error"
msgstr "Atpainimo klaida"
#: ../lib/installer.py:82
msgid "File %s is not supported by OpenDict"
msgstr "Byla %s nra tinkama programai OpenDict"
#: ../lib/installer.py:108 ../lib/installer.py:110
msgid "Installation failed"
msgstr "Nepavyko diegti"
#: ../lib/installer.py:122 ../lib/installer.py:308 ../lib/installer.py:316
msgid "Installation Error"
msgstr "Diegimo klaida"
#: ../lib/installer.py:124 ../lib/installer.py:128
msgid "Error: Installation failed"
msgstr "Klaida: nepavyko diegti"
#: ../lib/installer.py:132
msgid "Dictionary installed"
msgstr "odynas diegtas"
#: ../lib/installer.py:133
msgid ""
"Dictionary successfully installed. You can choose it from \"Dictionaries\" "
"menu now."
msgstr ""
"odynas skmingai diegtas. Dabar j galite pasirinkti i odynai meniu."
#: ../lib/installer.py:143 ../lib/installer.py:218
msgid "File %s does not exist"
msgstr "Byla %s neegzistuoja"
#: ../lib/installer.py:146 ../lib/installer.py:222
msgid "%s is not a file"
msgstr "%s nra byla"
#: ../lib/installer.py:160
msgid "Dictionary \"%s\" is already installed"
msgstr "odynas %s jau diegtas"
#: ../lib/installer.py:226
msgid "%s is not OpenDict dictionary plugin"
msgstr "%s nra OpenDict skiepis"
#: ../lib/installer.py:233
msgid "File \"%s\" is not valid ZIP file"
msgstr "%s nra teisinga ZIP byla"
#: ../lib/installer.py:238
msgid "Dictionary plugin file is corrupted"
msgstr "skiepio byla yra sugadinta"
#: ../lib/installer.py:244
msgid "Plugin file is empty (%s)"
msgstr "skiepio byla tuia (%s)"
#: ../lib/installer.py:268
msgid "Selected file is not valid OpenDict plugin"
msgstr "Nurodyta byla nra teisingas OpenDict skiepis"
#: ../lib/installer.py:295 ../lib/installer.py:377
msgid ""
"This dictionary already installed. If you want to upgrade it, please remove "
"old version first."
msgstr ""
"is odynas jau diegtas. Nordami atnaujinti, pirma paalinkite senj "
"versij."
#: ../lib/installer.py:309 ../lib/installer.py:317
msgid ""
"Installation tool for this dictionary failed to start. Please report this "
"problem to developers."
msgstr ""
"iam odynui diegimo rankio paleisti nepavyko. Praome apie problem "
"praneti krjams.??"
#: ../lib/installer.py:323
msgid "Installation Aborted"
msgstr "Diegimas nutrauktas"
#: ../lib/installer.py:324
msgid "Dictionary installation has been aborted."
msgstr "odyno diegimas nutrauktas."
#: ../lib/installer.py:348 ../lib/installer.py:400
msgid ""
"Error while removing created directories after plugin installation failure. "
"This may be permission or disk space error."
msgstr ""
"Po neskms diegiant skiepius nepavyko paalinti sukurt katalog. Klaida "
"gali bti susijusi su bylos leidimais."
#: ../lib/installer.py:352
msgid "Unable to install plugin"
msgstr "Nepavyko diegti priedo "
#: ../lib/installer.py:369
msgid "Compressed dictionary file is corrupted"
msgstr "Suspausta odyno byla yra sugadinta"
#: ../lib/installer.py:404
msgid "Unable to install dictionary"
msgstr "Nepavyksta diegti odyno"
#: ../lib/misc.py:37
msgid "Dictionary error, please report to its author"
msgstr "odyno klaida, praome praneti apie tai jo autoriui"
#: ../lib/misc.py:38
msgid "Syntax error"
msgstr "Sintakss klaida"
#: ../lib/misc.py:39
msgid "You must be connected to the internet to use this dictionary"
msgstr ""
"Turite bti prisijung prie interneto, kad galtumte naudoti odyn"
#: ../lib/misc.py:40
msgid "Time out"
msgstr "Baigsi prisijungimo laikas"
#: ../lib/misc.py:41
msgid "Bad encoding is set for this dictionary, try another"
msgstr "iam odynui nustatyta neteisinga koduot, pasirinkite kit"
#: ../lib/misc.py:48
msgid "Unicode (UTF-8)"
msgstr "Unikodas (UTF-8)"
#: ../lib/misc.py:49
msgid "Western (ISO-8859-1)"
msgstr "Vakar (ISO-8859-1)"
#: ../lib/misc.py:50
msgid "Central European (ISO-8859-2)"
msgstr "Centrins Europos (ISO-8859-2)"
#: ../lib/misc.py:51
msgid "Nordic (ISO-8859-10)"
msgstr "iaurs (ISO-8859-10)"
#: ../lib/misc.py:52
msgid "South European (ISO-8859-3)"
msgstr "Piet Europos (ISO-8859-3)"
#: ../lib/misc.py:53
msgid "Greek (ISO-8859-7)"
msgstr "Graik (ISO-8859-7)"
#: ../lib/misc.py:54
msgid "Baltic (ISO-8859-13)"
msgstr "Balt (ISO-8859-13)"
#: ../lib/misc.py:55
msgid "Cyrillic (KOI8-R)"
msgstr "Kirilica (KOI8-R)"
#: ../lib/misc.py:56
msgid "Arabic (ISO-8859-6)"
msgstr "Arab (ISO-8859-6)"
#: ../lib/util.py:235
msgid "Downloading... %d%%"
msgstr "Parsiuniama... %d%%"
#: ../opendict.py:115
msgid "wxPython Version Error"
msgstr "wxPython versijos klaida"
#: ../opendict.py:116
msgid ""
"wxPython %s is installed on this system.\n"
"\n"
"OpenDict %s requires wxPython 2.6 to run smoothly.\n"
"\n"
"You can find wxPython 2.6 at http://www.wxpython.org or you can install it "
"using your system package manager."
msgstr ""
"ioje sistemoje yra suinstaliuota wxPython %s biblioteka.\n"
"\n"
"Kad gerai veikt, OpenDict %s reikalauja wxPython 2.6.\n"
"\n"
"Galite rasti wxPython 2.6 adresu http://www.python.org arba galite "
"suinstaliuoti j naudodami savo sistemos paket tvarkymo program."
#~ msgid ""
#~ "Debian/Ubuntu port:\n"
#~ " Kęstutis Biliūnas \n"
#~ "\n"
#~ "MacOS X port:\n"
#~ " Linas Valiukas "
#~ msgstr ""
#~ "Debian/Ubuntu versija:\n"
#~ " Kstutis Bilinas \n"
#~ "\n"
#~ "MacOS X versija:\n"
#~ " Linas Valiukas "
#~ msgid "&License"
#~ msgstr "Licencija"
#, fuzzy
#~ msgid "Fixed"
#~ msgstr "&Byla"
#, fuzzy
#~ msgid "Times"
#~ msgstr "Baigsi prisijungimo laikas"
#~ msgid "Edit Dictionaries"
#~ msgstr "Taisyti odynus"
opendict-0.6.3/po/opendict.pot 0000644 0000000 0000000 00000056063 10654057523 015013 0 ustar root root # SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR ORGANIZATION
# FIRST AUTHOR , YEAR.
#
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"POT-Creation-Date: 2007-08-01 13:24+EEST\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME \n"
"Language-Team: LANGUAGE \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=CHARSET\n"
"Content-Transfer-Encoding: ENCODING\n"
"Generated-By: pygettext.py 1.5\n"
#: ../lib/errortype.py:57
msgid "Success"
msgstr ""
#: ../lib/errortype.py:58
msgid "Search successfully finished."
msgstr ""
#: ../lib/errortype.py:65 ../lib/misc.py:36
msgid "Not found"
msgstr ""
#: ../lib/errortype.py:66
msgid "Word or phrase not found. Try less letters or fewer words."
msgstr ""
#: ../lib/errortype.py:74
msgid "Internal error"
msgstr ""
#: ../lib/errortype.py:75
msgid "Internal error occured. Please send bug report to the dictionary's of current use authors. Thank you."
msgstr ""
#: ../lib/errortype.py:83
msgid "Not connected"
msgstr ""
#: ../lib/errortype.py:84
msgid "This dictionary uses Internet connection to translate words. Please connect to the Internet and try again."
msgstr ""
#: ../lib/errortype.py:93 ../lib/gui/dictconnwin.py:183
#: ../lib/gui/dictconnwin.py:199
msgid "Connection Error"
msgstr ""
#: ../lib/errortype.py:94
msgid "Could not connect to host. Check your Internet connection or try later."
msgstr ""
#: ../lib/errortype.py:102
msgid "Invalid encoding"
msgstr ""
#: ../lib/errortype.py:103
msgid "Selected encoding is not correct for this dictionary. Please select another from Edit > Character Encoding menu"
msgstr ""
#: ../lib/errortype.py:112
msgid "OpenDict Bug"
msgstr ""
#: ../lib/errortype.py:113
msgid "Internal error occured. Please send bug report to OpenDict authors to prevent this error in the future. Thank you!"
msgstr ""
#: ../lib/errortype.py:121
msgid "Unknown Error"
msgstr ""
#: ../lib/errortype.py:122
msgid "Unknown error occured."
msgstr ""
#: ../lib/gui/dictaddwin.py:35
msgid "Add new dictionary"
msgstr ""
#: ../lib/gui/dictaddwin.py:41
msgid ""
"The file format of \"%s\" could not be \n"
"recognized by its extention. Please select one\n"
"from the list:"
msgstr ""
#: ../lib/gui/dictaddwin.py:47 ../lib/gui/dictaddwin.py:48
#: ../lib/gui/dictaddwin.py:49 ../lib/gui/dictaddwin.py:50
msgid "\"%s\" dictionary format"
msgstr ""
#: ../lib/gui/dictaddwin.py:59 ../lib/gui/dicteditorwin.py:91
#: ../lib/gui/prefswin.py:149
msgid "OK"
msgstr ""
#: ../lib/gui/dictaddwin.py:62 ../lib/gui/dictconnwin.py:133
#: ../lib/gui/dicteditorwin.py:94 ../lib/gui/dicteditorwin.py:255
#: ../lib/gui/prefswin.py:152
msgid "Cancel"
msgstr ""
#: ../lib/gui/dictconnwin.py:55
msgid "Server: "
msgstr ""
#: ../lib/gui/dictconnwin.py:64
msgid "Default Server"
msgstr ""
#: ../lib/gui/dictconnwin.py:70
msgid "Port: "
msgstr ""
#: ../lib/gui/dictconnwin.py:73
msgid "Default Port"
msgstr ""
#: ../lib/gui/dictconnwin.py:83
msgid "Database: "
msgstr ""
#: ../lib/gui/dictconnwin.py:87
msgid "Search in all databases"
msgstr ""
#: ../lib/gui/dictconnwin.py:94
msgid "Fetch List"
msgstr ""
#: ../lib/gui/dictconnwin.py:100
msgid "Character encoding: "
msgstr ""
#: ../lib/gui/dictconnwin.py:130
msgid "Connect"
msgstr ""
#: ../lib/gui/dictconnwin.py:174 ../lib/gui/mainwin.py:685 ../lib/util.py:240
msgid "Done"
msgstr ""
#: ../lib/gui/dictconnwin.py:178
msgid "Receiving database list..."
msgstr ""
#: ../lib/gui/dictconnwin.py:184 ../lib/gui/dictconnwin.py:200
msgid "Unable to connect to server"
msgstr ""
#: ../lib/gui/dictconnwin.py:218
msgid "Connecting..."
msgstr ""
#: ../lib/gui/dictconnwin.py:254 ../lib/util.py:219
msgid "Connecting to %s..."
msgstr ""
#: ../lib/gui/dicteditorwin.py:53
msgid "Word: "
msgstr ""
#: ../lib/gui/dicteditorwin.py:88
msgid "Add translation field"
msgstr ""
#: ../lib/gui/dicteditorwin.py:111
msgid "Translation #%d: "
msgstr ""
#: ../lib/gui/dicteditorwin.py:245
msgid "Dictionary \"%s\" has been changed"
msgstr ""
#: ../lib/gui/dicteditorwin.py:249 ../lib/gui/dicteditorwin.py:337
msgid "Save"
msgstr ""
#: ../lib/gui/dicteditorwin.py:252
msgid "Do not save"
msgstr ""
#: ../lib/gui/dicteditorwin.py:305
msgid "Dictionary editor"
msgstr ""
#: ../lib/gui/dicteditorwin.py:321
msgid "Add"
msgstr ""
#: ../lib/gui/dicteditorwin.py:322
msgid "Add word"
msgstr ""
#: ../lib/gui/dicteditorwin.py:325
msgid "Edit"
msgstr ""
#: ../lib/gui/dicteditorwin.py:326
msgid "Change translation"
msgstr ""
#: ../lib/gui/dicteditorwin.py:329 ../lib/gui/miscwin.py:116
#: ../lib/gui/pluginwin.py:156
msgid "Remove"
msgstr ""
#: ../lib/gui/dicteditorwin.py:330
msgid "Remove selected word"
msgstr ""
#: ../lib/gui/dicteditorwin.py:333
msgid "Sort"
msgstr ""
#: ../lib/gui/dicteditorwin.py:334
msgid "Sort word list"
msgstr ""
#: ../lib/gui/dicteditorwin.py:338
msgid "Save words to file"
msgstr ""
#: ../lib/gui/dicteditorwin.py:341
msgid "Save As..."
msgstr ""
#: ../lib/gui/dicteditorwin.py:342
msgid "Save with a different file name"
msgstr ""
#: ../lib/gui/dicteditorwin.py:351 ../lib/gui/mainwin.py:1371
msgid "Word List"
msgstr ""
#: ../lib/gui/dicteditorwin.py:370
msgid "New..."
msgstr ""
#: ../lib/gui/dicteditorwin.py:371
msgid "Start new dictionary"
msgstr ""
#: ../lib/gui/dicteditorwin.py:374
msgid "Open..."
msgstr ""
#: ../lib/gui/dicteditorwin.py:375
msgid "Open dictionary file"
msgstr ""
#: ../lib/gui/dicteditorwin.py:378 ../lib/gui/errorwin.py:84
#: ../lib/gui/helpwin.py:69 ../lib/gui/helpwin.py:145
#: ../lib/gui/helpwin.py:208 ../lib/gui/miscwin.py:65
#: ../lib/gui/miscwin.py:124 ../lib/gui/pluginwin.py:92
#: ../lib/gui/registerwin.py:89
msgid "Close"
msgstr ""
#: ../lib/gui/dicteditorwin.py:379
msgid "Close editor window"
msgstr ""
#: ../lib/gui/dicteditorwin.py:410
msgid "New Word"
msgstr ""
#: ../lib/gui/dicteditorwin.py:425
msgid "Edit Word"
msgstr ""
#: ../lib/gui/dicteditorwin.py:457
msgid "List is empty"
msgstr ""
#: ../lib/gui/dicteditorwin.py:463
msgid "List sorted"
msgstr ""
#: ../lib/gui/dicteditorwin.py:486
msgid "Save file"
msgstr ""
#: ../lib/gui/dicteditorwin.py:507
msgid "Dictionary saved"
msgstr ""
#: ../lib/gui/dicteditorwin.py:517
msgid "Untitled"
msgstr ""
#: ../lib/gui/dicteditorwin.py:588 ../lib/gui/dicteditorwin.py:645
msgid "Exit confirmation"
msgstr ""
#: ../lib/gui/dicteditorwin.py:600 ../lib/gui/mainwin.py:1293
#: ../lib/installer.py:61
msgid "Choose dictionary file"
msgstr ""
#: ../lib/gui/dicteditorwin.py:614
msgid "Open Failed"
msgstr ""
#: ../lib/gui/dicteditorwin.py:615
msgid "Unable to open dictionary (got message: %s)"
msgstr ""
#: ../lib/gui/dicteditorwin.py:630
msgid "Dictionary loaded"
msgstr ""
#: ../lib/gui/errorwin.py:72
msgid "An error occured:"
msgstr ""
#: ../lib/gui/helpwin.py:106
msgid "Written By"
msgstr ""
#: ../lib/gui/helpwin.py:118
msgid "Translated By"
msgstr ""
#: ../lib/gui/helpwin.py:123
msgid ""
"Ports:\n"
"\n"
msgstr ""
#: ../lib/gui/helpwin.py:128
msgid "Thanks To"
msgstr ""
#: ../lib/gui/helpwin.py:134
msgid ""
"OpenDict project is sponsored by IDILES.\n"
"Visit company's website at http://www.idiles.com.\n"
"\n"
"Report problems by email address support@idiles.com."
msgstr ""
#: ../lib/gui/helpwin.py:141
msgid "Sponsors"
msgstr ""
#: ../lib/gui/helpwin.py:179 ../lib/gui/helpwin.py:192
msgid "OpenDict is a multiplatform dictionary."
msgstr ""
#: ../lib/gui/helpwin.py:202
msgid "Credits"
msgstr ""
#: ../lib/gui/helpwin.py:205 ../lib/gui/helpwin.py:234
msgid "Licence"
msgstr ""
#: ../lib/gui/mainwin.py:92 ../lib/gui/mainwin.py:774
#: ../lib/gui/mainwin.py:812
msgid "Stopped"
msgstr ""
#: ../lib/gui/mainwin.py:97 ../lib/gui/mainwin.py:779
msgid "Encode Failed"
msgstr ""
#: ../lib/gui/mainwin.py:98
msgid "Unable to encode text \"%s\" in %s for \"%s\"."
msgstr ""
#: ../lib/gui/mainwin.py:106 ../lib/gui/mainwin.py:757
#: ../lib/gui/mainwin.py:1355
msgid "Searching..."
msgstr ""
#: ../lib/gui/mainwin.py:159
msgid "Look Up\tCtrl-U"
msgstr ""
#: ../lib/gui/mainwin.py:160
msgid "Lookup up word in the dictionary"
msgstr ""
#: ../lib/gui/mainwin.py:165
msgid "&Close Dictionary\tCtrl-W"
msgstr ""
#: ../lib/gui/mainwin.py:166
msgid "Close opened dicitonary"
msgstr ""
#: ../lib/gui/mainwin.py:169
msgid "E&xit\tCtrl-Q"
msgstr ""
#: ../lib/gui/mainwin.py:170
msgid "Exit program"
msgstr ""
#: ../lib/gui/mainwin.py:172
msgid "&File"
msgstr ""
#: ../lib/gui/mainwin.py:180
msgid "&Clear Search Entry\tCtrl-L"
msgstr ""
#: ../lib/gui/mainwin.py:183
msgid "Clear History"
msgstr ""
#: ../lib/gui/mainwin.py:191
msgid "Copy\tCtrl-C"
msgstr ""
#: ../lib/gui/mainwin.py:192
msgid "Copy selected translation text"
msgstr ""
#: ../lib/gui/mainwin.py:195
msgid "Paste\tCtrl-V"
msgstr ""
#: ../lib/gui/mainwin.py:196
msgid "Paste clipboard text into the search entry"
msgstr ""
#: ../lib/gui/mainwin.py:201
msgid "Edit preferences"
msgstr ""
#: ../lib/gui/mainwin.py:201
msgid "Preferences...\tCtrl-P"
msgstr ""
#: ../lib/gui/mainwin.py:203
msgid "&Edit"
msgstr ""
#: ../lib/gui/mainwin.py:213
msgid "Increase\tCtrl-="
msgstr ""
#: ../lib/gui/mainwin.py:214
msgid "Increase text size"
msgstr ""
#: ../lib/gui/mainwin.py:215
msgid "Decrease\tCtrl--"
msgstr ""
#: ../lib/gui/mainwin.py:216
msgid "Decrease text size"
msgstr ""
#: ../lib/gui/mainwin.py:218
msgid "Normal\tCtrl-0"
msgstr ""
#: ../lib/gui/mainwin.py:219
msgid "Set normal text size"
msgstr ""
#: ../lib/gui/mainwin.py:220
msgid "Font Size"
msgstr ""
#: ../lib/gui/mainwin.py:235
msgid "Font Face"
msgstr ""
#: ../lib/gui/mainwin.py:250
msgid "Character Encoding"
msgstr ""
#: ../lib/gui/mainwin.py:255
msgid "Show/Hide Word List...\tCtrl-H"
msgstr ""
#: ../lib/gui/mainwin.py:256
msgid "Show or hide word list"
msgstr ""
#: ../lib/gui/mainwin.py:259
msgid "&View"
msgstr ""
#: ../lib/gui/mainwin.py:296
msgid "&Install Dictionary From File..."
msgstr ""
#: ../lib/gui/mainwin.py:298
msgid "&Dictionaries"
msgstr ""
#: ../lib/gui/mainwin.py:307
msgid "Manage Dictionaries...\tCtrl-M"
msgstr ""
#: ../lib/gui/mainwin.py:308
msgid "Install or remove dictionaries"
msgstr ""
#: ../lib/gui/mainwin.py:310
msgid "Create Dictionaries..."
msgstr ""
#: ../lib/gui/mainwin.py:311
msgid "Create and edit dictionaries"
msgstr ""
#: ../lib/gui/mainwin.py:318
msgid "Take Words From Clipboard"
msgstr ""
#: ../lib/gui/mainwin.py:319
msgid "Scan the clipboard for text to translate"
msgstr ""
#: ../lib/gui/mainwin.py:327
msgid "Connect to DICT Server..."
msgstr ""
#: ../lib/gui/mainwin.py:328
msgid "Open connection to DICT server"
msgstr ""
#: ../lib/gui/mainwin.py:333
msgid "Pronounce\tCtrl-E"
msgstr ""
#: ../lib/gui/mainwin.py:334
msgid "Pronounce word"
msgstr ""
#: ../lib/gui/mainwin.py:337
msgid "Tools"
msgstr ""
#: ../lib/gui/mainwin.py:346
msgid "&About\tCtrl-A"
msgstr ""
#: ../lib/gui/mainwin.py:348
msgid "&Help"
msgstr ""
#: ../lib/gui/mainwin.py:353
msgid "Word:"
msgstr ""
#: ../lib/gui/mainwin.py:358
msgid "Enter some text and press \"Look Up\" button or [ENTER] key on your keyboard"
msgstr ""
#: ../lib/gui/mainwin.py:364
msgid "Look Up"
msgstr ""
#: ../lib/gui/mainwin.py:365
msgid "Click this button to look up word in the dictionary"
msgstr ""
#: ../lib/gui/mainwin.py:376
msgid "History Back"
msgstr ""
#: ../lib/gui/mainwin.py:385
msgid "History Forward"
msgstr ""
#: ../lib/gui/mainwin.py:395
msgid "Stop searching"
msgstr ""
#: ../lib/gui/mainwin.py:419
msgid "Translation"
msgstr ""
#: ../lib/gui/mainwin.py:527
msgid ""
"\n"
"\n"
"\n"
"\n"
"\n"
"\n"
"
Welcome to OpenDict
\n"
"
Short usage information:
\n"
"
\n"
"
To start using dictionary, select one from Dictionaries\n"
" menu.\n"
"
\n"
"
To install new dictionary from the Internet, select\n"
" Manage Dictionaries\n"
" from Tools menu and choose Available tab.
\n"
"
To install new dictionary from file, select Install Dictionary From File...\n"
" from Dictionaries menu.\n"
"
\n"
"
\n"
"\n"
"\n"
msgstr ""
#: ../lib/gui/mainwin.py:649
msgid "Translation cannot be displayed using selected encoding %s. Please try another encoding from View > Character Encoding menu."
msgstr ""
#: ../lib/gui/mainwin.py:681
msgid "1 word matches"
msgstr ""
#: ../lib/gui/mainwin.py:683
msgid "%d words match"
msgstr ""
#: ../lib/gui/mainwin.py:730
msgid "No dictionary activated"
msgstr ""
#: ../lib/gui/mainwin.py:731
msgid "No dictionary activated. Please select one from \"Dictionaries\" menu and try again."
msgstr ""
#: ../lib/gui/mainwin.py:734
msgid "No dictionaries installed"
msgstr ""
#: ../lib/gui/mainwin.py:735
msgid "There is no dictionaries installed. You can install one by selecting Tools > Manage Dictionaries > Available"
msgstr ""
#: ../lib/gui/mainwin.py:748
msgid "Please enter some text and try again"
msgstr ""
#: ../lib/gui/mainwin.py:780
msgid "Unable to encode text \"%s\" in %s for \"%s\". That logically means the word definition does not exist in the dictionary."
msgstr ""
#: ../lib/gui/mainwin.py:868
msgid "Connect to DICT server"
msgstr ""
#: ../lib/gui/mainwin.py:895
msgid "Choose a dictionary from \"Dictionaries\" menu"
msgstr ""
#: ../lib/gui/mainwin.py:916
msgid "Failed to copy text from the clipboard"
msgstr ""
#: ../lib/gui/mainwin.py:918
msgid "Clipboard contains no text data"
msgstr ""
#: ../lib/gui/mainwin.py:942 ../lib/gui/mainwin.py:1136
#: ../lib/gui/pluginwin.py:772
msgid "Error"
msgstr ""
#: ../lib/gui/mainwin.py:951
msgid "Groups"
msgstr ""
#: ../lib/gui/mainwin.py:963
msgid "Manage Dictionaries"
msgstr ""
#: ../lib/gui/mainwin.py:977
msgid "File Register"
msgstr ""
#: ../lib/gui/mainwin.py:985
msgid "Create Dictionaries"
msgstr ""
#: ../lib/gui/mainwin.py:994
msgid "Preferences"
msgstr ""
#: ../lib/gui/mainwin.py:1082
msgid "Licence Agreement Rejected"
msgstr ""
#: ../lib/gui/mainwin.py:1083
msgid "You cannot use dictionary \"%s\" without accepting licence agreement"
msgstr ""
#: ../lib/gui/mainwin.py:1097
msgid "Dictionary Index"
msgstr ""
#: ../lib/gui/mainwin.py:1098
msgid ""
"This is the first time you use this dictionary or it has been changed on disk since last indexing. Indexing is used to make search more efficient. The dictionary will be indexed now. It can take a few or more seconds.\n"
"\n"
"Press OK to continue..."
msgstr ""
#: ../lib/gui/mainwin.py:1115
msgid "Index Creation Error"
msgstr ""
#: ../lib/gui/mainwin.py:1116
msgid "Error occured while indexing file. This may be because of currently selected character encoding %s is not correct for this dictionary. Try selecting another encoding from View > Character Encoding menu"
msgstr ""
#: ../lib/gui/mainwin.py:1137
msgid "Unable to load dictionary index table. Got error: %s"
msgstr ""
#: ../lib/gui/mainwin.py:1147
msgid "Dictionary \"%s\" loaded"
msgstr ""
#: ../lib/gui/mainwin.py:1199
msgid "Error: not supported dictionary type"
msgstr ""
#: ../lib/gui/mainwin.py:1304
msgid ""
"Select dictionary format. If you can't find\n"
"the format of your dictionary, the register\n"
"system does not support it yet."
msgstr ""
#: ../lib/gui/mainwin.py:1309
msgid "Dictionary format"
msgstr ""
#: ../lib/gui/mainwin.py:1326
msgid "Choose plugin file"
msgstr ""
#: ../lib/gui/mainwin.py:1342
msgid "About"
msgstr ""
#: ../lib/gui/mainwin.py:1393
msgid "Show word list"
msgstr ""
#: ../lib/gui/mainwin.py:1410
msgid "Hide word list"
msgstr ""
#: ../lib/gui/mainwin.py:1419
msgid "Failed to print"
msgstr ""
#: ../lib/gui/mainwin.py:1431
msgid "Page preview failed"
msgstr ""
#: ../lib/gui/miscwin.py:53
msgid "Error: unable to show licence text"
msgstr ""
#: ../lib/gui/miscwin.py:59
msgid "Do not accept"
msgstr ""
#: ../lib/gui/miscwin.py:62
msgid "Accept"
msgstr ""
#: ../lib/gui/miscwin.py:76
msgid "Licence Agreement"
msgstr ""
#: ../lib/gui/miscwin.py:103
msgid ""
"You have directories that containt invalid dictionaries and cannot be loaded. \n"
"You can try to remove these directories right now."
msgstr ""
#: ../lib/gui/miscwin.py:142 ../lib/gui/pluginwin.py:644
msgid "Unable to remove"
msgstr ""
#: ../lib/gui/miscwin.py:143
msgid "Unable to remove directory \"%s\": %s"
msgstr ""
#: ../lib/gui/miscwin.py:151
msgid "Invalid Dictionaries"
msgstr ""
#: ../lib/gui/pluginwin.py:78
msgid "Installed"
msgstr ""
#: ../lib/gui/pluginwin.py:82
msgid "Available"
msgstr ""
#: ../lib/gui/pluginwin.py:124
msgid ""
"Checked dictionaries are available from the menu, unchecked dictionaries \n"
"are not available from the menu."
msgstr ""
#: ../lib/gui/pluginwin.py:149
msgid "Install From File"
msgstr ""
#: ../lib/gui/pluginwin.py:208
msgid "Update List"
msgstr ""
#: ../lib/gui/pluginwin.py:215
msgid "Install"
msgstr ""
#: ../lib/gui/pluginwin.py:227
msgid "Name"
msgstr ""
#: ../lib/gui/pluginwin.py:228
msgid "Size"
msgstr ""
#: ../lib/gui/pluginwin.py:274
msgid "Information About Dictionary"
msgstr ""
#: ../lib/gui/pluginwin.py:288
msgid "Name: "
msgstr ""
#: ../lib/gui/pluginwin.py:293
msgid "Version: "
msgstr ""
#: ../lib/gui/pluginwin.py:298
msgid "Maintainer: "
msgstr ""
#: ../lib/gui/pluginwin.py:515
msgid "List updated"
msgstr ""
#: ../lib/gui/pluginwin.py:516
msgid "All your dictionaries are up to date."
msgstr ""
#: ../lib/gui/pluginwin.py:523
msgid "Downloading List"
msgstr ""
#: ../lib/gui/pluginwin.py:558
msgid "Unable to download list from %s: %s"
msgstr ""
#: ../lib/gui/pluginwin.py:566
msgid "Unable to download list"
msgstr ""
#: ../lib/gui/pluginwin.py:645
msgid "Unable to remove dictionary \"%s\""
msgstr ""
#: ../lib/gui/pluginwin.py:686
msgid "Downloading %s..."
msgstr ""
#: ../lib/gui/pluginwin.py:743
msgid "Unable to download"
msgstr ""
#: ../lib/gui/pluginwin.py:753
msgid "File is damaged"
msgstr ""
#: ../lib/gui/pluginwin.py:754
msgid "Downloaded file is damaged and cannot be installed. Please try again."
msgstr ""
#: ../lib/gui/pluginwin.py:773
msgid "Unable to remove old version of \"%s\". Error occured: \"%s\". New version cannot be installed without removing old one."
msgstr ""
#: ../lib/gui/pluginwin.py:798
msgid "Unable to install"
msgstr ""
#: ../lib/gui/pluginwin.py:799
msgid "Unable to install dictionary \"%s\"."
msgstr ""
#: ../lib/gui/prefswin.py:48
msgid "Default dictionary: "
msgstr ""
#: ../lib/gui/prefswin.py:69
msgid "Default encoding: "
msgstr ""
#: ../lib/gui/prefswin.py:80
msgid "Default DICT server: "
msgstr ""
#: ../lib/gui/prefswin.py:86
msgid "Default DICT server port: "
msgstr ""
#: ../lib/gui/prefswin.py:99
msgid "Pronunciation"
msgstr ""
#: ../lib/gui/prefswin.py:107
msgid "System Command: "
msgstr ""
#: ../lib/gui/prefswin.py:115
msgid "Default"
msgstr ""
#: ../lib/gui/prefswin.py:121
msgid "Pronounce original word"
msgstr ""
#: ../lib/gui/prefswin.py:123
msgid "Pronounce translation"
msgstr ""
#: ../lib/gui/prefswin.py:130
msgid "Save window size on exit"
msgstr ""
#: ../lib/gui/prefswin.py:134
msgid "Save window position on exit"
msgstr ""
#: ../lib/gui/prefswin.py:138
msgid "Save sash position on exit"
msgstr ""
#: ../lib/gui/prefswin.py:143
msgid "Take words from the clipboard by default"
msgstr ""
#: ../lib/gui/registerwin.py:66 ../lib/gui/registerwin.py:105
#: ../lib/gui/registerwin.py:148
msgid "Name: %s"
msgstr ""
#: ../lib/gui/registerwin.py:69 ../lib/gui/registerwin.py:106
#: ../lib/gui/registerwin.py:149
msgid "Path: %s"
msgstr ""
#: ../lib/gui/registerwin.py:72 ../lib/gui/registerwin.py:107
#: ../lib/gui/registerwin.py:150
msgid "Format: %s"
msgstr ""
#: ../lib/gui/registerwin.py:75 ../lib/gui/registerwin.py:108
#: ../lib/gui/registerwin.py:151
msgid "Encoding: %s"
msgstr ""
#: ../lib/gui/registerwin.py:82
msgid "Add new..."
msgstr ""
#: ../lib/gui/registerwin.py:86
msgid "Remove selected"
msgstr ""
#: ../lib/gui/registerwin.py:130 ../lib/gui/registerwin.py:137
msgid "Error while deleting \"%s\""
msgstr ""
#: ../lib/installer.py:81
msgid "Recognition Error"
msgstr ""
#: ../lib/installer.py:82
msgid "File %s is not supported by OpenDict"
msgstr ""
#: ../lib/installer.py:108 ../lib/installer.py:110
msgid "Installation failed"
msgstr ""
#: ../lib/installer.py:122 ../lib/installer.py:308 ../lib/installer.py:316
msgid "Installation Error"
msgstr ""
#: ../lib/installer.py:124 ../lib/installer.py:128
msgid "Error: Installation failed"
msgstr ""
#: ../lib/installer.py:132
msgid "Dictionary installed"
msgstr ""
#: ../lib/installer.py:133
msgid "Dictionary successfully installed. You can choose it from \"Dictionaries\" menu now."
msgstr ""
#: ../lib/installer.py:143 ../lib/installer.py:218
msgid "File %s does not exist"
msgstr ""
#: ../lib/installer.py:146 ../lib/installer.py:222
msgid "%s is not a file"
msgstr ""
#: ../lib/installer.py:160
msgid "Dictionary \"%s\" is already installed"
msgstr ""
#: ../lib/installer.py:226
msgid "%s is not OpenDict dictionary plugin"
msgstr ""
#: ../lib/installer.py:233
msgid "File \"%s\" is not valid ZIP file"
msgstr ""
#: ../lib/installer.py:238
msgid "Dictionary plugin file is corrupted"
msgstr ""
#: ../lib/installer.py:244
msgid "Plugin file is empty (%s)"
msgstr ""
#: ../lib/installer.py:268
msgid "Selected file is not valid OpenDict plugin"
msgstr ""
#: ../lib/installer.py:295 ../lib/installer.py:377
msgid "This dictionary already installed. If you want to upgrade it, please remove old version first."
msgstr ""
#: ../lib/installer.py:309 ../lib/installer.py:317
msgid "Installation tool for this dictionary failed to start. Please report this problem to developers."
msgstr ""
#: ../lib/installer.py:323
msgid "Installation Aborted"
msgstr ""
#: ../lib/installer.py:324
msgid "Dictionary installation has been aborted."
msgstr ""
#: ../lib/installer.py:348 ../lib/installer.py:400
msgid "Error while removing created directories after plugin installation failure. This may be permission or disk space error."
msgstr ""
#: ../lib/installer.py:352
msgid "Unable to install plugin"
msgstr ""
#: ../lib/installer.py:369
msgid "Compressed dictionary file is corrupted"
msgstr ""
#: ../lib/installer.py:404
msgid "Unable to install dictionary"
msgstr ""
#: ../lib/misc.py:37
msgid "Dictionary error, please report to its author"
msgstr ""
#: ../lib/misc.py:38
msgid "Syntax error"
msgstr ""
#: ../lib/misc.py:39
msgid "You must be connected to the internet to use this dictionary"
msgstr ""
#: ../lib/misc.py:40
msgid "Time out"
msgstr ""
#: ../lib/misc.py:41
msgid "Bad encoding is set for this dictionary, try another"
msgstr ""
#: ../lib/misc.py:48
msgid "Unicode (UTF-8)"
msgstr ""
#: ../lib/misc.py:49
msgid "Western (ISO-8859-1)"
msgstr ""
#: ../lib/misc.py:50
msgid "Central European (ISO-8859-2)"
msgstr ""
#: ../lib/misc.py:51
msgid "Nordic (ISO-8859-10)"
msgstr ""
#: ../lib/misc.py:52
msgid "South European (ISO-8859-3)"
msgstr ""
#: ../lib/misc.py:53
msgid "Greek (ISO-8859-7)"
msgstr ""
#: ../lib/misc.py:54
msgid "Baltic (ISO-8859-13)"
msgstr ""
#: ../lib/misc.py:55
msgid "Cyrillic (KOI8-R)"
msgstr ""
#: ../lib/misc.py:56
msgid "Arabic (ISO-8859-6)"
msgstr ""
#: ../lib/util.py:235
msgid "Downloading... %d%%"
msgstr ""
#: ../opendict.py:115
msgid "wxPython Version Error"
msgstr ""
#: ../opendict.py:116
msgid ""
"wxPython %s is installed on this system.\n"
"\n"
"OpenDict %s requires wxPython 2.6 to run smoothly.\n"
"\n"
"You can find wxPython 2.6 at http://www.wxpython.org or you can install it using your system package manager."
msgstr ""
opendict-0.6.3/doc/ 0000755 0001750 0001750 00000000000 10654057460 012543 5 ustar mjoc mjoc opendict-0.6.3/doc/Plugin-HOWTO.html 0000644 0001750 0001750 00000036262 10526270664 015577 0 ustar mjoc mjoc
OpenDict Add-Ons Development HOWTO
OpenDict Add-Ons Development HOWTO
Introduction
OpenDict is free multiplatform dictionary. More information about it
can be found on OpenDict website.
This document is written for developers who want to make
easy-installable OpenDict dictionaries.
Warning: It is not necessary to make OpenDict dictionary if you
have a dictionary file in Slowo, Mova or DICT format. Such
dictionaries can be used right now by selecting Dictionaries ->
Install Dictionary from File from OpenDict menu.
Types of OpenDict Dictionaries
OpenDict has two types of dictionaries: plain (simple) dictionaries and
plugin (complex)
dictionaries. Plain dictionaries consists of dictionary file (type of
that dictionary must be supported by OpenDict) and description file in
XML format. Plugin dictionaries consists of Python module with code
that handles search process and description file in XML format; it
may also have dictionary file which is processed by Python module
mentioned above.
Plain dictionaries are simple and handy. It is very easy to install
them using OpenDict itself. If you have dictionary file (format of
that dictionary must be supported by OpenDict) and want to attach some
information to it, like the name, the author, the description, you may
want to make plain dictionary.
If you have more complex task, like search the web, etc, you may want
to make a plugin for OpenDict. The plugin is a chunk of code
written in Python programming
language that OpenDict attaches to itself at runtime.
The next sections of this document will describe how to make
plain dictionaries and plugins.
Plain Dictionary Example
Assume we have a small dictionary file named mydict.dwa in Slowo
format:
above = ant ; virš ;
abroad = visur ; užsienyje ;
acoustic = akustinis ;
acquaint = pranešti ;
Say we want to call this dictionary "My Personal Dictionary" and
attacht a description "This is my personal dictionary. It is very
small, but it is not the size that matters :)" to it.
Each plain dictionary must have XML description file named
config.xml, otherwise it will be treated as invalid dictionary. So we
write an XML file called config.xml with our favorite text or XML editor:
<?xml version='1.0' encoding='UTF-8'?>
<plain-dictionary>
<format>slowo</format>
<name>My Personal Dictionarys</name>
<version>0.1</version>
<authors>
<author name="Your Name" email="your@email.tdl"/>
</authors>
<path>mydict.dwa</path>
<md5>9c62810c32ca20fe018b79987789daef</md5>
<encoding>UTF-8</encoding>
<description><![CDATA[
This is my personal dictionary. It is very small, but it is not the
size that matters :)
]]>
</description>
</plain-dictionary>
As you can see, a little more information must be added to description
(i.e. configuration) file. Here is a short description of each section:
XML tag
Description
format
Dictionary format. OpenDict supports the following formats:
slowo -- Slowo format
mova -- Mova format
dict -- DICT format
TODO: describe all supported format somewhere
name
Name of the dictionary. It will be shown in the
Dictionaries menu in OpenDict window.
version
Version value is very important. It shows the freshness of
your dictionary. The more recent the dictionary, the greater
version value must be set. For example: 0.1, 0.2, 0.3, etc; or 1,
2, 3, etc.
author
The author of the dictionary. Notice that author tag is
inside authors tag, because there may be several
authors of the dictionary. So add as may author tags as you
want, but make them the childs of the authors tag.
This tag is a bit complicated, because you may not be the
author of the dictionary file you are using. If so, you may treat
the author tag as maintainance tag and write your as
maintainer name inside it. In addition to this, you should
write the name of the author in the description tag
mentioned below.
path
Path to the dictionary file. It may be an absolute (i.e. full)
path to the dictionary file or relative path. If you write full
path, dictionary would be taken from there. Buf if you write only
the name of the dictionary (i.e. mydict.dwa), the dictionary will
be treated to be located at $DICTDIR/file/mydict.dwa, where
$DICTDIR is directory where you dictionary is located, for example
/home/mjoc/.opendict/dictionaries/plain/mydict.dwa/file/mydict.dwa.
If you are going to distribute dictionary file with OpenDict
plain dictionary, you want to write only the file name inside
path tag.
md5
This is an MD5 checksum value of the dictionary file
(i.e. mydict.dwa). This MD5 code is used to determine changes
of the dictionary file. That means user is able to modify
dictionary file and OpenDict will recreate index table
before using that dictionary next time. If you want to get MD5
checksum value of you dictionary file, execute the following
command on your system (Linux, BSD) shell:
You can see the command and the output above. Just copy that
32-chars checksum to your XML file. This is quite unfriendly,
so I will think about easer ways some day. Nevertheless, we are
developers today.
encoding
Character encoding of the dictionary file. Examples: UTF-8,
UTF-16, ISO-8859-1, ISO-8859-13, etc.
description
Description of your dictionary. You should not remove that
<![CDATA[ ... ]]> tag, because it lets you to write
any text inside using even XML (HTML) tags like 1 + 1 <
1 or <myemail@abcdef.tdl>
The last file you need is an index file. This file contains
index table of the dictionary describing in what position what letter
begins. Index makes search a lot faster.
I do not recommend writing index file using your fingers and the
keyboard :), so we will use OpenDict to make one for ourselves. Lets
now make a directory tree containing these files and directories:
As you see, the root direcory is called mydict.dwa, the same as
dictionary file is called. This is the rule. Now move that
directory to the directory where all the plain dictionaries are
located. On my machine I would do:
After that you should start OpenDict and load the dictionary you've
just made. If everything goes well, you will be informed about
reindexing the dictionary. Press OK and, if everything goes
well, you will have index.xml file located at data/ directory. On my
machine the full path would be
/home/mjoc/.opendict/dictionaries/plain/mydict.dwa/data/index.xml.
Now the directory tree look in a way like that:
Now we have all the files needed. They are located at $DICTDIR. The
last step is to make a ZIP archive of that directory. Notice that that
ZIP file must contain the dictionary directory (i.e. mydict.dwa/)
itself, not only files inside it. To zip the directory, I would do:
mjoc@kumo:~/tmp/dict-factory$ cd ~/.opendict/dictionaries/plain/
mjoc@kumo:~/.opendict/dictionaries/plain$ zip -r MyDictionary-0.1.zip mydict.dwa/
mjoc@kumo:~/.opendict/dictionaries/plain$ mv MyDictionary-0.1.zip ~
mjoc@kumo:~/.opendict/dictionaries/plain$ cd
Now file MyDictionary-0.1.zip can be found at my home direcory
(/home/mjoc/). That's all. Now you have made a dictionary that can be
installed by everyone using OpenDict by selecting Dictionaries ->
Install Dictionary from File from the menu.
Simple Plugin Example
In this section I am going to give an example of simple OpenDict
plugin dictionary. Good example is a network dictionary plugin that
fetches translations from the web and processed them locally.
At first we have to create file called plugin.xml. The contents
of this file may be similar to this one:
As you may already noticed, some XML tags are the same as in the
previous config.xml example. There is the description of new
tags, like encoding, module, etc.
Character encoding of the result string that plugin module
returns (examples include UTF-8, ISO-8859-15, etc)
uses-word-list
This should be set to True if dictionary needs word
list to be shown, False otherwise. If dictionary uses word
list, it must return a list of alternative words in addition with
translation string (see below for more information)
opendict-version
The lowest OpenDict version plugin requires, for example
0.5.1, 0.5.7, etc. This is important when plugin structure is
different from one that old OpenDict versions provide (for example 0.5.1
and 0.5.7 plugin structure differs a lot)
python-version
The lowest Python version that plugin requires.
python-version
The lowest Python version that plugin requires.
platforms
Parent node for platform tag.
platform
This tag with attribute name value X means that this
plugin is tested and works on platform X. For example, Linux, BSD,
MacOS. Currently not used
Now we should write the main module in Python programming
language. Module file name is mydict.py as we called it in
plugin.xml. The following code might be correct OpenDict plugin:
#!/usr/bin/env python
#
# MyDict 0.1
# Copyright (c) 2005 Matynas Jocius <mjoc@akl.lt>
#
# Simple plugin dictionary for OpenDict.
#
# This code is licensed under the GNU GPL v2.
#
"""
Simple OpenDict plugin module
"""
import sys
import httplib
import urllib
def init(libraryPath):
"""Return dictionary instance"""
sys.path.insert(0, libraryPath)
return MyDict()
class MyDict:
"""MyDict plugin class"""
def __init__(self):
"""Initialize variables"""
# This trick is needed to have accessible modules from
# OpenDict library
from lib import errortype, meta
self.errorModule = errortype
self.metaModule = meta
def search(self, word):
"""Search and return HTML code."""
print type(word), len(word)
result = self.metaModule.SearchResult()
try:
self.conn = httplib.HTTPConnection("mjoc.sig.lt")
self.conn.request("GET", "/index.html")
response = self.conn.getresponse()
data = response.read()
trans = "<html><body><h3>"
if word in data:
trans += "Word <i>%s</i> was found on " \
"http://mjoc.sig.lt/index.html" % word
else:
trans += "Word <i>%s</i> was not found on " \
"http://mjoc.sig.lt/index.html" % word
trans += "</h3></body></html>"
result.setTranslation(trans)
except Exception, e:
import traceback
traceback.print_exc()
result.setError(self.errorModule.INTERNAL_ERROR)
return result
return result
TODO: describe how to write the class and other details.
To make an installable plugin file in ZIP archive format, move
plugin.xml and mydict.py into some directory
(i.e. mydict-0.1) and zip that directory. After performing
these actions your new OpenDict plugin will be ready to be installed.
Conclusion
TODO: This document is very short and fuzzy. It must be improved in
the future.
opendict-0.6.3/lib/ 0000755 0001750 0001750 00000000000 10654057460 012544 5 ustar mjoc mjoc opendict-0.6.3/lib/gui/ 0000755 0001750 0001750 00000000000 10654057460 013330 5 ustar mjoc mjoc opendict-0.6.3/lib/gui/errorwin.py 0000644 0001750 0001750 00000005060 10640522715 015545 0 ustar mjoc mjoc #
# OpenDict
# Copyright (c) 2003-2006 Martynas Jocius
# Copyright (c) 2007 IDILES SYSTEMS, UAB
#
# This program 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 2 of the License, or
# (at your opinion) any later version.
#
# This program is distributed in the hope that will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MECHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more detals.
#
# You shoud have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
# 02111-1307 USA
#
# Module: gui.errorwin
import wx
import sys
import os
import traceback
_ = wx.GetTranslation
from lib import info
def showErrorMessage(title, msg):
"""Show error message dialog"""
window = wx.MessageDialog(None,
msg,
title,
wx.OK | wx.ICON_ERROR)
window.CenterOnScreen()
window.ShowModal()
window.Destroy()
def showInfoMessage(title, msg):
"""Show info message dialog"""
window = wx.MessageDialog(None,
msg,
title,
wx.OK | wx.ICON_INFORMATION)
window.CenterOnScreen()
window.ShowModal()
window.Destroy()
class ErrorWindow(wx.Frame):
"""This window is shown when OpenDict can't start because
of some error."""
def __init__(self, parent, id, title, error, pos=wx.DefaultPosition,
size=wx.DefaultSize, style=wx.CENTRE):
wx.Frame.__init__(self, parent, id, title, pos, size, style)
raise "Deprecated"
vbox = wx.BoxSizer(wx.VERTICAL)
vbox.Add(wx.StaticText(self, -1, _("An error occured:")), 0,
wx.ALL | wx.EXPAND, 5)
errMsg = wx.TextCtrl(self, -1, size=(-1, 200),
style=wx.TE_MULTILINE | wx.TE_READONLY)
errMsg.WriteText(error)
vbox.Add(errMsg, 1,
wx.ALL | wx.EXPAND, 10)
vbox.Add(wx.StaticText(self, -1, msg), 0,
wx.ALL | wx.EXPAND, 5)
self.buttonClose = wx.Button(self, 200, _("Close"))
vbox.Add(self.buttonClose, 0, wx.ALL | wx.CENTRE, 2)
self.SetSizer(vbox)
self.Fit()
wx.EVT_CLOSE(self, self.onCloseWindow)
wx.EVT_BUTTON(self, 200, self.onExit)
opendict-0.6.3/lib/gui/mainwin.py 0000644 0001750 0001750 00000134146 10640522715 015350 0 ustar mjoc mjoc #
# OpenDict
# Copyright (c) 2003-2006 Martynas Jocius
# Copyright (c) 2007 IDILES SYSTEMS, UAB
#
# This program 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 2 of the License, or
# (at your opinion) any later version.
#
# This program is distributed in the hope that will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MECHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more detals.
#
# You shoud have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
# 02111-1307 USA
#
"""
Main window GUI module
"""
import wx
import wx.html
import os
import cStringIO
import traceback
from lib import info
from lib.gui.dictconnwin import DictConnWindow
from lib.gui.pluginwin import PluginManagerWindow
from lib.gui.dicteditorwin import DictEditorWindow
from lib.gui.dictaddwin import DictAddWindow
from lib.gui.prefswin import PrefsWindow
from lib.gui import prefswin
from lib.gui.helpwin import LicenseWindow, AboutWindow
from lib.gui import errorwin
from lib.gui import miscwin
from lib.parser import SlowoParser
from lib.parser import MovaParser
from lib.parser import TMXParser
from lib.parser import DictParser
from lib.threads import Process
from lib.history import History
from lib.installer import Installer
from lib.extra.html2text import html2text
from lib.logger import systemLog, debugLog, DEBUG, INFO, WARNING, ERROR
from lib import misc
from lib import info
from lib import util
from lib import meta
from lib import enc
from lib import errortype
from lib import dicttype
from lib import plaindict
_ = wx.GetTranslation
# Constants
titleTemplate = "OpenDict - %s"
NORMAL_FONT_SIZE = '10'
# Used to remember word when searching by entering text to the entry,
# selecting one from the list or clicking a link.
lastLookupWord = None
class HtmlWindow(wx.html.HtmlWindow):
"""Html control for showing transaltion and catching
link-clicking"""
def OnLinkClicked(self, linkInfo):
global lastLookupWord
lastLookupWord = linkInfo.GetHref()
wx.BeginBusyCursor()
parent = self.GetParent().GetParent().GetParent()
word = enc.fromWX(lastLookupWord)
try:
word = word.encode(parent.activeDictionary.getEncoding())
except Exception, e:
# FIXME: Code duplicates
traceback.print_exc()
parent.buttonStop.Disable()
parent.entry.Enable(True)
parent.timerSearch.Stop()
parent.SetStatusText(_('Stopped'))
wx.EndBusyCursor()
systemLog(ERROR, "Unable to decode '%s': %s" % (word.encode('UTF-8'),
e))
title = _("Encode Failed")
msg = _("Unable to encode text \"%s\" in %s for \"%s\".") \
% (enc.toWX(word), parent.activeDictionary.getEncoding(),
parent.activeDictionary.getName())
errorwin.showErrorMessage(title, msg)
return
parent.SetStatusText(_("Searching..."))
parent.entry.SetValue(word)
parent.timerSearch.Start(parent.delay)
parent.search = Process(parent.activeDictionary.search,
word)
class MainWindow(wx.Frame):
"""Main OpenDict window with basic controls"""
def __init__(self, parent, id, title, pos=wx.DefaultPosition,
size=wx.DefaultSize, style=wx.DEFAULT_FRAME_STYLE):
wx.Frame.__init__(self, parent, id, title, pos, size, style)
self.app = wx.GetApp()
self.printer = wx.html.HtmlEasyPrinting()
self.history = History()
self.htmlCode = ""
self.dictName = ""
self.activeDictionary = None
self.words = []
self.delay = 10 # miliseconds
self.lastInstalledDictName = None
# This var is used by onTimerSearch to recognize search method.
# If search was done by selecting a word in a list, then word list
# is not updated, otherwise is.
self.__searchedBySelecting = 0
# Box sizers
vboxMain = wx.BoxSizer(wx.VERTICAL)
self.hboxToolbar = wx.BoxSizer(wx.HORIZONTAL)
#
# Menu Bar
#
self.menuBar = wx.MenuBar()
#
# File menu
#
menuFile = wx.Menu()
idPrint = wx.NewId()
#menuFile.Append(idPrint, _("Print Translation"), "")
idPreview = wx.NewId()
#menuFile.Append(idPreview, _("Print Preview"), "")
idFind = wx.NewId()
menuFile.Append(idFind, _("Look Up\tCtrl-U"),
_("Lookup up word in the dictionary"))
menuFile.AppendSeparator()
idCloseDict = wx.NewId()
menuFile.Append(idCloseDict, _("&Close Dictionary\tCtrl-W"),
_("Close opened dicitonary"))
idExit = wx.NewId()
menuFile.Append(idExit, _("E&xit\tCtrl-Q"),
_("Exit program"))
self.menuBar.Append(menuFile, _("&File"))
menuEdit = wx.Menu()
#
# Clear functions
#
idClearEntry = wx.NewId()
menuEdit.Append(idClearEntry, _("&Clear Search Entry\tCtrl-L"))
idClearHistory = wx.NewId()
menuEdit.Append(idClearHistory, _("Clear History"))
menuEdit.AppendSeparator()
#
# Clipboard functions
#
idCopy = wx.NewId()
menuEdit.Append(idCopy, _("Copy\tCtrl-C"),
_("Copy selected translation text"))
idPaste = wx.NewId()
menuEdit.Append(idPaste, _("Paste\tCtrl-V"),
_("Paste clipboard text into the search entry"))
menuEdit.AppendSeparator()
idPrefs = wx.NewId()
menuEdit.Append(idPrefs, _("Preferences...\tCtrl-P"), _("Edit preferences"))
self.menuBar.Append(menuEdit, _("&Edit"))
#
# View menu
#
menuView = wx.Menu()
# Font size
self.menuFontSize = wx.Menu()
self.menuFontSize.Append(2007, _("Increase\tCtrl-="),
_("Increase text size"))
self.menuFontSize.Append(2008, _("Decrease\tCtrl--"),
_("Decrease text size"))
self.menuFontSize.AppendSeparator()
self.menuFontSize.Append(2009, _("Normal\tCtrl-0"),
_("Set normal text size"))
menuView.AppendMenu(2002, _("Font Size"), self.menuFontSize)
# Font face
self.menuFontFace = wx.Menu()
i = 0
keys = misc.fontFaces.keys()
keys.sort()
for face in keys:
self.menuFontFace.AppendRadioItem(2500+i, face, "")
wx.EVT_MENU(self, 2500+i, self.onDefault)
if self.app.config.get('fontFace') == misc.fontFaces[face]:
self.menuFontFace.FindItemById(2500+i).Check(1)
i+=1
menuView.AppendMenu(2001, _("Font Face"), self.menuFontFace)
# Font encoding
self.menuEncodings = wx.Menu()
i = 0
keys = misc.encodings.keys()
keys.sort()
for encoding in keys:
self.menuEncodings.AppendRadioItem(2100+i , encoding, "")
wx.EVT_MENU(self, 2100+i, self.onDefault)
if self.app.config.get('encoding') == misc.encodings[encoding]:
self.menuEncodings.FindItemById(2100+i).Check(1)
i+=1
menuView.AppendMenu(2000, _("Character Encoding"), self.menuEncodings)
menuView.AppendSeparator()
idShowHide = wx.NewId()
menuView.Append(idShowHide, _("Show/Hide Word List...\tCtrl-H"),
_("Show or hide word list"))
self.menuBar.Append(menuView, _("&View"))
#
# Dictionaries menu
#
self.menuDict = wx.Menu()
dicts = []
for dictionary in self.app.dictionaries.values():
dicts.append([dictionary.getName(), dictionary.getActive()])
dicts.sort()
for name, active in dicts:
#if not self.app.config.activedict.enabled(name):
# continue
if not active:
continue
encoded = enc.toWX(name)
itemID = self.app.config.ids.keys()[\
self.app.config.ids.values().index(name)]
try:
item = wx.MenuItem(self.menuDict,
itemID,
encoded)
self.menuDict.AppendItem(item)
wx.EVT_MENU(self, itemID, self.onDefault)
except Exception, e:
systemLog(ERROR, "Unable to create menu item for '%s' (%s)" \
% (name, e))
self.menuDict.AppendSeparator()
idAddDict = wx.NewId()
self.menuDict.Append(idAddDict, _("&Install Dictionary From File..."))
self.menuBar.Append(self.menuDict, _("&Dictionaries"))
#
# Tools menu
#
menuTools = wx.Menu()
idManageDict = wx.NewId()
menuTools.Append(idManageDict, _("Manage Dictionaries...\tCtrl-M"),
_("Install or remove dictionaries"))
menuTools.Append(5002, _("Create Dictionaries..."),
_("Create and edit dictionaries"))
menuTools.AppendSeparator()
idUseScan = wx.NewId()
item = wx.MenuItem(menuTools,
idUseScan,
_("Take Words From Clipboard"),
_("Scan the clipboard for text to translate"),
wx.ITEM_CHECK)
menuTools.AppendItem(item)
menuTools.Check(idUseScan, self.app.config.get('useClipboard') == 'True')
menuTools.AppendSeparator()
idDictServer = wx.NewId()
menuTools.Append(idDictServer, _("Connect to DICT Server..."),
_("Open connection to DICT server"))
menuTools.AppendSeparator()
idPron = wx.NewId()
menuTools.Append(idPron, _("Pronounce\tCtrl-E"),
_("Pronounce word"))
self.menuBar.Append(menuTools, _("Tools"))
#
# Help menu
#
menuHelp = wx.Menu()
idAbout = wx.NewId()
menuHelp.Append(idAbout, _("&About\tCtrl-A"))
self.menuBar.Append(menuHelp, _("&Help"))
self.SetMenuBar(self.menuBar)
# Search Bar
labelWord = wx.StaticText(self, -1, _("Word:"))
self.hboxToolbar.Add(labelWord, 0, wx.ALL | wx.CENTER | wx.ALIGN_RIGHT, 5)
self.entry = wx.ComboBox(self, 153, "", wx.Point(-1, -1),
wx.Size(-1, -1), [], wx.CB_DROPDOWN)
self.entry.SetToolTipString(_("Enter some text and press " \
"\"Look Up\" button or "
"[ENTER] key on your keyboard"))
self.hboxToolbar.Add(self.entry, 1, wx.ALL | wx.CENTER, 1)
#self.buttonSearch = wx.Button(self, wx.ID_FIND)
self.buttonSearch = wx.Button(self, idFind, _("Look Up"))
self.buttonSearch.SetToolTipString(_("Click this button to look " \
"up word in " \
"the dictionary"))
self.hboxToolbar.Add(self.buttonSearch, 0, wx.ALL | wx.CENTER, 1)
# Back button
bmp = wx.Bitmap(os.path.join(info.GLOBAL_HOME, "pixmaps", "left.png"),
wx.BITMAP_TYPE_PNG)
self.buttonBack = wx.BitmapButton(self, 2010, bmp, (24, 24),
style=wx.NO_BORDER)
self.buttonBack.SetToolTipString(_("History Back"))
self.buttonBack.Disable()
self.hboxToolbar.Add(self.buttonBack, 0, wx.ALL | wx.CENTER, 1)
# Forward button
bmp = wx.Bitmap(os.path.join(info.GLOBAL_HOME, "pixmaps", "right.png"),
wx.BITMAP_TYPE_PNG)
self.buttonForward = wx.BitmapButton(self, 2011, bmp, (24, 24),
style=wx.NO_BORDER)
self.buttonForward.SetToolTipString(_("History Forward"))
self.buttonForward.Disable()
self.hboxToolbar.Add(self.buttonForward, 0, wx.ALL | wx.CENTER, 1)
# Stop threads
# TODO: how thread can be killed?
bmp = wx.Bitmap(os.path.join(info.GLOBAL_HOME, "pixmaps", "stop.png"),
wx.BITMAP_TYPE_PNG)
self.buttonStop = wx.BitmapButton(self, 155, bmp, (16, 16),
style=wx.NO_BORDER)
self.buttonStop.SetToolTipString(_("Stop searching"))
self.buttonStop.Disable()
self.hboxToolbar.Add(self.buttonStop, 0, wx.ALL | wx.CENTER, 1)
# Word list is hidden by default
self.wlHidden = True
bmp = wx.Bitmap(os.path.join(info.GLOBAL_HOME, "pixmaps", "hide.png"),
wx.BITMAP_TYPE_PNG)
self.buttonHide = wx.BitmapButton(self, 152, bmp, (24, 24),
style=wx.NO_BORDER)
self.hboxToolbar.Add(self.buttonHide, 0, wx.ALL | wx.CENTER, 1)
vboxMain.Add(self.hboxToolbar, 0, wx.ALL | wx.EXPAND | wx.GROW, 0)
# Splitter Window
self.splitter = wx.SplitterWindow(self, -1)
# List panel
self.createListPanel()
# Html window panel
self.panelHtml = wx.Panel(self.splitter, -1)
sbSizerHtml = wx.StaticBoxSizer(wx.StaticBox(self.panelHtml, -1,
_("Translation")),
wx.VERTICAL)
self.htmlWin = HtmlWindow(self.panelHtml, -1, style=wx.SUNKEN_BORDER)
sbSizerHtml.Add(self.htmlWin, 1, wx.ALL | wx.EXPAND, 0)
self.panelHtml.SetSizer(sbSizerHtml)
self.panelHtml.SetAutoLayout(True)
sbSizerHtml.Fit(self.panelHtml)
self.splitter.SplitVertically(self.panelList, self.panelHtml,
int(self.app.config.get('sashPos')))
self.splitter.SetMinimumPaneSize(90)
self.splitter.SetSashSize(5)
if not self.activeDictionary:
self.hideWordList()
vboxMain.Add(self.splitter, 1, wx.ALL | wx.GROW | wx.EXPAND, 0)
# Status bar
self.CreateStatusBar()
# Main sizer
self.SetSizer(vboxMain)
self.timerSearch = wx.Timer(self, 5000)
self.timerLoad = wx.Timer(self, 5001)
idClipboard = wx.NewId()
self.timerClipboard = wx.Timer(self, idClipboard)
self.scanTimeout = 2000
self.search = None
self.load = None
wx.InitAllImageHandlers()
self.SetIcon(wx.Icon(os.path.join(info.GLOBAL_HOME,
"pixmaps",
"icon-32x32.png"),
wx.BITMAP_TYPE_PNG))
#
# Loading default dictionary
#
if self.app.config.get('defaultDict'):
self.loadDictionary(self.app.dictionaries.get(\
self.app.config.get('defaultDict')))
self.SetMinSize((320, 160))
#
# Events
#
# TODO: New-style event definition
# File menu events
wx.EVT_MENU(self, idPrint, self.onPrint)
wx.EVT_MENU(self, idPreview, self.onPreview)
wx.EVT_MENU(self, idCloseDict, self.onCloseDict)
wx.EVT_MENU(self, idExit, self.onExit)
# Edit menu events
wx.EVT_MENU(self, idClearHistory, self.onClearHistory)
wx.EVT_MENU(self, idCopy, self.onCopy)
wx.EVT_MENU(self, idPaste, self.onPaste)
wx.EVT_MENU(self, idClearEntry, self.onClean)
# View menu events
wx.EVT_MENU(self, 2007, self.onIncreaseFontSize)
wx.EVT_MENU(self, 2008, self.onDecreaseFontSize)
wx.EVT_MENU(self, 2009, self.onNormalFontSize)
wx.EVT_MENU(self, idShowHide, self.onHideUnhide)
# Dictionaries menu events
wx.EVT_MENU(self, idAddDict, self.onAddDict)
# Tools menu events
wx.EVT_MENU(self, idDictServer, self.onOpenDictConn)
wx.EVT_MENU(self, idUseScan, self.onUseScanClipboard)
wx.EVT_MENU(self, idManageDict, self.onShowPluginManager)
wx.EVT_MENU(self, 5002, self.onShowDictEditor)
wx.EVT_MENU(self, idPrefs, self.onShowPrefsWindow)
wx.EVT_MENU(self, idPron, self.onPronounce)
# Help menu events
wx.EVT_MENU(self, idAbout, self.onAbout)
# Other events
self.Bind(wx.EVT_BUTTON, self.onSearch, self.buttonSearch)
wx.EVT_MENU(self, idFind, self.onSearch)
wx.EVT_BUTTON(self, 2010, self.onBack)
wx.EVT_BUTTON(self, 2011, self.onForward)
wx.EVT_BUTTON(self, 155, self.onStop)
wx.EVT_BUTTON(self, 151, self.onClean)
wx.EVT_BUTTON(self, 152, self.onHideUnhide)
wx.EVT_TEXT_ENTER(self, 153, self.onSearch)
wx.EVT_LISTBOX(self, 154, self.onWordSelected)
wx.EVT_TIMER(self, 5000, self.onTimerSearch)
wx.EVT_TIMER(self, idClipboard, self.onTimerClipboard)
wx.EVT_CLOSE(self, self.onCloseWindow)
self.entry.Bind(wx.EVT_KEY_DOWN, self.onKeyDown)
# Prepare help message
self.htmlCode = _("""
Welcome to OpenDict
Short usage information:
To start using dictionary, select one from Dictionaries
menu.
To install new dictionary from the Internet, select
Manage Dictionaries
from Tools menu and choose Available tab.
To install new dictionary from file, select Install Dictionary From File...
from Dictionaries menu.
""")
if self.activeDictionary:
self.htmlCode = ""
self.updateHtmlScreen()
if self.app.invalidDictionaries:
miscwin.showInvalidDicts(self, self.app.invalidDictionaries)
if self.app.config.get('useClipboard') == 'True':
self.timerClipboard.Start(self.scanTimeout)
def onExit(self, event):
self.onCloseWindow(None)
def onCloseWindow(self, event):
self.onCloseDict(None)
self.savePreferences()
self.Destroy()
# TODO: Move aftersearch actions into separate method
def onTimerSearch(self, event):
"""Search timer. When finished, sets search results"""
if self.search != None and self.search.isDone():
self.timerSearch.Stop()
self.search.stop()
#
# Turn back active interface elements state
wx.EndBusyCursor()
self.SetStatusText("")
self.entry.Enable(1)
self.buttonStop.Disable()
global lastLookupWord
word = lastLookupWord
if self.entry.FindString(word) == -1:
self.entry.Append(word)
result = self.search()
# Check if search result is SerachResult object.
# SearchResult class is used by new-type plugins.
try:
assert result.__class__ == meta.SearchResult
except:
self.SetStatusText(errortype.INTERNAL_ERROR.getMessage())
if self.activeDictionary.getType() == dicttype.PLUGIN:
title = errortype.INTERNAL_ERROR.getMessage()
message = errortype.INTERNAL_ERROR.getLongMessage()
else:
title = errortype.OPENDICT_BUG.getMessage()
message = errortype.OPENDICT_BUG.getLongMessage()
systemLog(ERROR, "%s: %s" % (message, misc.getTraceback()))
errorwin.showErrorMessage(title, message)
return
# Check status code
if result.getError() != errortype.OK:
systemLog(ERROR, result.getError())
self.htmlWin.SetPage("")
self.wordList.Clear()
if result.getError() in \
[errortype.INTERNAL_ERROR, errortype.INVALID_ENCODING]:
errorwin.showErrorMessage(result.getError().getMessage(),
result.getError().getLongMessage())
else:
self.SetStatusText(result.getError().getMessage())
return
#
# If dictionary (plugin) does not use NOT_FOUND notification,
# check for translation and show it manually
#
if not result.getTranslation():
self.SetStatusText(errortype.NOT_FOUND.getMessage())
try:
transUnicode = unicode(result.translation,
self.activeDictionary.getEncoding())
except Exception, e:
systemLog(ERROR, "Unable to decode translation in %s (%s)" \
% (self.activeDictionary.getEncoding(),
e))
title = errortype.INVALID_ENCODING.getMessage()
msg = _("Translation cannot be displayed using selected " \
"encoding %s. Please try another encoding from " \
"View > Character Encoding menu.") \
% self.activeDictionary.getEncoding()
self.SetStatusText(title)
errorwin.showErrorMessage(title, msg)
return
transPreparedForWX = enc.toWX(transUnicode)
self.htmlWin.SetPage(transPreparedForWX)
self.history.add(transPreparedForWX)
# FIXME: Nasty names
# Where it is used? htmlWin.GetPage
self.htmlCode = transPreparedForWX
if not self.wordListHidden():
if not self.__searchedBySelecting:
self.wordList.Clear()
toUnicode = lambda s: unicode(s,
self.activeDictionary.getEncoding())
wordsInUnicode = map(toUnicode, result.words)
wordsPreparedForWX = map(enc.toWX, wordsInUnicode)
self.wordList.InsertItems(wordsPreparedForWX, 0)
self.words = wordsPreparedForWX
if not self.__searchedBySelecting:
matches = self.wordList.GetCount()
if matches == 1:
self.SetStatusText(_("1 word matches"))
elif matches > 1:
self.SetStatusText(_("%d words match") % matches)
else:
self.SetStatusText(_("Done"))
if self.history.canBack():
self.buttonBack.Enable(1)
self.search = None
def onTimerClipboard(self, event):
"""Clipboard timer, used to watch new text in a clipboard"""
def getText():
do = wx.TextDataObject()
text = None
wx.TheClipboard.Open()
if wx.TheClipboard.GetData(do):
try:
text = do.GetText().strip()
except Exception, e:
print e
wx.TheClipboard.Close()
return enc.toWX(text)
text = getText()
old_text = ''
if hasattr(self, 'old_clipboard_text'):
old_text = self.old_clipboard_text
if text and text != old_text:
self.entry.SetValue(text)
self.onSearch(None)
self.old_clipboard_text = text
def onUseScanClipboard(self, event):
"""Scan Clipboard menu item selected"""
if event and event.GetInt():
self.timerClipboard.Start(self.scanTimeout)
else:
self.timerClipboard.Stop()
def onSearch(self, event):
if self.activeDictionary == None:
if len(self.app.dictionaries):
title = _("No dictionary activated")
msg = _("No dictionary activated. Please select one from "\
"\"Dictionaries\" menu and try again.")
else:
title = _("No dictionaries installed")
msg = _("There is no dictionaries installed. You can " \
"install one by selecting Tools > Manage " \
"Dictionaries > Available")
errorwin.showErrorMessage(title, msg)
return
if self.search and not self.search.isDone():
self.onStop(None)
word = self.entry.GetValue()
if word == "":
self.SetStatusText(_("Please enter some text and try again"))
self.entry.SetFocus()
return
global lastLookupWord
lastLookupWord = word
wx.BeginBusyCursor()
self.__searchedBySelecting = 0
self.SetStatusText(_("Searching..."))
self.timerSearch.Stop()
self.search = None
self.buttonStop.Enable(1)
self.entry.Disable()
self.timerSearch.Start(self.delay)
word = enc.fromWX(word)
try:
word = word.encode(self.activeDictionary.getEncoding())
except Exception, e:
# FIXME: Code duplicates
self.buttonStop.Disable()
self.entry.Enable(True)
self.timerSearch.Stop()
self.SetStatusText(_('Stopped'))
wx.EndBusyCursor()
systemLog(ERROR, "Unable to decode '%s': %s" % (word.encode('UTF-8'),
e))
title = _("Encode Failed")
msg = _("Unable to encode text \"%s\" in %s for \"%s\". "
"That logically means the word "
"definition does not exist in the dictionary.") \
% (enc.toWX(word), self.activeDictionary.getEncoding(),
self.activeDictionary.getName())
errorwin.showErrorMessage(title, msg)
return
self.search = Process(self.activeDictionary.search, word)
def onBack(self, event):
self.buttonForward.Enable(1)
self.htmlWin.SetPage(self.history.back())
if not self.history.canBack():
self.buttonBack.Disable()
def onForward(self, event):
self.buttonBack.Enable(1)
self.htmlWin.SetPage(self.history.forward())
if not self.history.canForward():
self.buttonForward.Disable()
def onStop(self, event):
self.entry.Enable(1)
self.SetStatusText(_("Stopped"))
self.timerSearch.Stop()
self.timerLoad.Stop()
if self.search:
self.search.stop()
self.search = None
if self.load:
self.load.stop()
self.load = None
wx.EndBusyCursor()
self.buttonStop.Disable()
def onClean(self, event):
self.entry.SetValue("")
self.entry.SetFocus()
def onKeyDown(self, event):
"""Key down event handler."""
if event.GetKeyCode() == wx.WXK_ESCAPE:
self.onClean(None)
event.Skip()
def onClearHistory(self, event):
self.entry.Clear()
self.history.clear()
self.buttonBack.Disable()
self.buttonForward.Disable()
def wordListHidden(self):
"""Returns True if word list marked to be hidden, False
otherwise"""
if self.wlHidden:
return True
return False
def onHideUnhide(self, event):
if self.wordListHidden():
self.unhideWordList()
else:
self.hideWordList()
def onOpenDictConn(self, event):
window = DictConnWindow(self, -1,
_("Connect to DICT server"),
style=wx.DEFAULT_FRAME_STYLE)
window.CentreOnScreen()
window.Show(True)
def onCloseDict(self, event):
"""Clear widgets and set messages"""
# If there was a registered dict, set it's default encoding
# FIXME: new way
try:
if self.dict.name in self.app.config.registers.keys():
self.app.config.registers[self.dict.name][2] = self.app.config.encoding
except:
pass
self.wordList.Clear()
self.htmlWin.SetPage("")
self.SetTitle("OpenDict")
self.words = []
if self.activeDictionary:
self.activeDictionary.stop()
self.activeDictionary = None
self.SetStatusText(_("Choose a dictionary from \"Dictionaries\" menu"))
def onCopy(self, event):
self.do = wx.TextDataObject()
self.do.SetText(self.htmlWin.SelectionToText())
wx.TheClipboard.Open()
wx.TheClipboard.SetData(self.do)
wx.TheClipboard.Close()
def onPaste(self, event):
"""This method is invoked when Paste menu item is selected"""
do = wx.TextDataObject()
wx.TheClipboard.Open()
if wx.TheClipboard.GetData(do):
try:
self.entry.SetValue(do.GetText())
except:
self.SetStatusText(_("Failed to copy text from the clipboard"))
else:
self.SetStatusText(_("Clipboard contains no text data"))
wx.TheClipboard.Close()
def onPronounce(self, event):
"""Pronouce word using external software."""
word = self.entry.GetValue().strip()
if word:
cmd = self.app.config.get('pronunciationCommand') or prefswin.PRON_COMMAND
if self.app.config.get('pronounceTrans') == 'True':
word = html2text(self.htmlCode)
import locale
localeCharset = locale.getpreferredencoding()
try:
word = word.replace('(', '').replace(')', '').replace('\n',
'').replace('\r', '').replace('"', '\\"')
cmd = (cmd % word).encode(localeCharset)
Process(os.system, cmd)
except Exception, e:
traceback.print_exc()
title = _("Error")
msg = _("Unable to decode text using your locale charset %s" \
% localeCharset)
errorwin.showErrorMessage(title, msg)
def onShowGroupsWindow(self, event):
"""This method is invoked when Groups menu item is selected"""
self.groupsWindow = GroupsWindow(self, -1,
_("Groups"),
size=(330, 150),
style=wx.DEFAULT_FRAME_STYLE)
self.groupsWindow.CentreOnScreen()
self.groupsWindow.Show(True)
def onShowPluginManager(self, event):
"""This method is invoked when Dictionaries Manager
menu item is selected"""
try:
self.pmWindow = PluginManagerWindow(self, -1,
_("Manage Dictionaries"),
size=(500, 500),
style=wx.DEFAULT_FRAME_STYLE)
self.pmWindow.CentreOnScreen()
self.pmWindow.Show(True)
except Exception, e:
traceback.print_exc()
systemLog(ERROR, "Unable to show prefs window: %s" % e)
self.SetStatusText("Error occured, please contact developers (%s)" \
% e)
def onShowFileRegistry(self, event):
self.regWindow = FileRegistryWindow(self, -1,
_("File Register"),
size=(340, 200),
style=wx.DEFAULT_FRAME_STYLE)
self.regWindow.CentreOnScreen()
self.regWindow.Show(True)
def onShowDictEditor(self, event):
editor = DictEditorWindow(self, -1, _("Create Dictionaries"),
size=(400, 500),
style=wx.DEFAULT_FRAME_STYLE)
editor.CentreOnScreen()
editor.Show(True)
def onShowPrefsWindow(self, event):
try:
self.prefsWindow = PrefsWindow(self, -1, _("Preferences"),
size=(-1, -1),
style=wx.DEFAULT_FRAME_STYLE)
self.prefsWindow.CentreOnScreen()
self.prefsWindow.Show(True)
except Exception, e:
traceback.print_exc()
systemLog(ERROR, "Unable to show preferences window: %s" % e)
title = errortype.OPENDICT_BUG.getMessage()
msg = errortype.OPENDICT_BUG.getLongMessage()
errorwin.showErrorMessage(title, msg)
def onDefault(self, event):
# FIXME: Bad way. Try setting a few constants for each type
# of dictionary and then check this type instead of IDs.
eventID = event.GetId()
if eventID in self.app.config.ids.keys():
dictionary = self.app.dictionaries.get(self.app.config.ids.get(eventID))
self.loadDictionary(dictionary)
elif 2100 <= eventID < 2500:
label = self.menuEncodings.FindItemById(eventID).GetLabel()
self.changeEncoding(label)
elif 2500 <= eventID < 2600:
label = self.menuFontFace.FindItemById(eventID).GetLabel()
self.changeFontFace(label)
elif 2600 <= eventID < 2700:
label = self.menuFontSize.FindItemById(eventID).GetLabel()
self.changeFontSize(label)
def checkIfNeedsList(self):
"""Unhides word list if current dictionary uses it"""
if self.activeDictionary.getUsesWordList():
if self.wordListHidden():
self.unhideWordList()
else:
if not self.wordListHidden():
self.hideWordList()
def addDictionary(self, dictInstance):
"""Add dictionary to menu and updates ids"""
app = wx.GetApp()
app.dictionaries[dictInstance.getName()] = dictInstance
unid = util.generateUniqueID()
# Insert new menu item only if no same named dictionary exists
#if not dictInstance.getName() in app.config.ids.values():
app.config.ids[unid] = dictInstance.getName()
item = wx.MenuItem(self.menuDict,
unid,
dictInstance.getName())
wx.EVT_MENU(self, unid, self.onDefault)
#self.menuDict.InsertItem(self.menuDict.GetMenuItemCount()-2, item)
self.menuDict.InsertItem(0, item)
def removeDictionary(self, name):
"""Remove dictionary from the menu"""
item = self.menuDict.FindItem(name)
if item:
self.menuDict.Delete(item)
def loadDictionary(self, dictInstance):
"""Prepares main window for using dictionary"""
if not dictInstance:
systemLog(ERROR, "loadDictionary: dictInstance is False")
return
#
# Check licence agreement
#
licence = dictInstance.getLicence()
if licence \
and not self.app.agreements.getAccepted(dictInstance.getPath()):
if not miscwin.showLicenceAgreement(None, licence):
from lib.gui import errorwin
title = _("Licence Agreement Rejected")
msg = _("You cannot use dictionary \"%s\" without accepting "\
"licence agreement") % dictInstance.getName()
errorwin.showErrorMessage(title, msg)
return
else:
self.app.agreements.addAgreement(dictInstance.getPath())
self.onCloseDict(None)
self.activeDictionary = dictInstance
if dictInstance.getType() in dicttype.indexableTypes:
if plaindict.indexShouldBeMade(dictInstance):
# Notify about indexing
from lib.gui import errorwin
title = _("Dictionary Index")
msg = _("This is the first time you use this dictionary or it " \
"has been changed on disk since last indexing. " \
"Indexing is used to make search more efficient. " \
"The dictionary will be indexed now. It can take a few " \
"or more seconds.\n\n" \
"Press OK to continue...")
errorwin.showInfoMessage(title, msg)
# Make index
try:
wx.BeginBusyCursor()
plaindict.makeIndex(dictInstance,
self.app.config.get('encoding'))
wx.EndBusyCursor()
except Exception, e:
wx.EndBusyCursor()
traceback.print_exc()
title = _("Index Creation Error")
msg = _("Error occured while indexing file. " \
"This may be because of currently selected " \
"character encoding %s is not correct for this " \
"dictionary. Try selecting " \
"another encoding from View > Character Encoding " \
"menu") % self.app.config.get('encoding')
from lib.gui import errorwin
errorwin.showErrorMessage(title, msg)
return
# Load index
try:
wx.BeginBusyCursor()
index = plaindict.loadIndex(dictInstance)
self.activeDictionary.setIndex(index)
wx.EndBusyCursor()
except Exception, e:
wx.EndBusyCursor()
traceback.print_exc()
title = _("Error")
msg = _("Unable to load dictionary index table. "
"Got error: %s") % e
from lib.gui import errorwin
errorwin.showErrorMessage(title, msg)
return
wx.BeginBusyCursor()
self.activeDictionary.start()
self.checkIfNeedsList()
self.SetTitle(titleTemplate % dictInstance.getName())
self.SetStatusText(enc.toWX(_("Dictionary \"%s\" loaded") \
% dictInstance.getName()))
self.entry.SetFocus()
try:
self.checkEncMenuItem(self.activeDictionary.getEncoding())
except Exception, e:
systemLog(ERROR, "Unable to select encoding menu item: %s" % e)
wx.EndBusyCursor()
def loadPlugin(self, name):
"""Sets plugin as currently used dictionary"""
systemLog(INFO, "Loading plugin '%s'..." % name)
self.entry.Disable()
self.dictName = name
self.activeDictionary = self.app.dictionaries.get(name)
self.checkIfNeedsList()
self.SetTitle(titleTemplate % name)
self.entry.Enable(1)
self.SetStatusText("Done") # TODO: Set something more useful
self.htmlWin.SetPage("")
# FIXME: deprecated, update!
def loadRegister(self, name):
self.SetTitle(titleTemplate % name) # TODO: should be set after loading
item = self.app.config.registers[name]
self.dictName = name
self.entry.Disable()
if item[1] == "dwa":
self.timerLoad.Start(self.delay)
self.load = Process(SlowoParser, item[0], self)
elif item[1] == "mova":
self.timerLoad.Start(self.delay)
self.load = Process(MovaParser, item[0],
self)
elif item[1] == "tmx":
self.timerLoad.Start(self.delay)
self.load = Process(TMXParser, item[0],
self)
elif item[1] == "dz":
self.timerLoad.Start(self.delay)
self.load = Process(DictParser, item[0],
self)
else:
self.SetStatusText(_("Error: not supported dictionary type"))
return
self.app.config.encoding = item[2]
self.checkEncMenuItem(self.app.config.encoding)
def changeEncoding(self, name):
self.app.config.set('encoding', misc.encodings[name])
if self.activeDictionary:
print "Setting encoding %s for dictionary %s" % \
(self.app.config.get('encoding'), self.activeDictionary.name)
self.activeDictionary.setEncoding(self.app.config.get('encoding'))
systemLog(INFO, "Dictionary encoding set to %s" \
% self.activeDictionary.getEncoding())
plaindict.savePlainConfiguration(self.activeDictionary)
def changeFontFace(self, name):
"""Save font face changes"""
self.app.config.set('fontFace', misc.fontFaces[name])
self.updateHtmlScreen()
def changeFontSize(self, name):
fontSize = int(name) * 10
systemLog(INFO, "Setting font size %d" % fontSize)
self.app.config.set('fontSize', fontSize)
self.updateHtmlScreen()
def updateHtmlScreen(self):
"""Update HtmlWindow screen"""
self.htmlWin.SetFonts(self.app.config.get('fontFace'), "Fixed",
[int(self.app.config.get('fontSize'))]*5)
self.htmlWin.SetPage(self.htmlCode)
def onIncreaseFontSize(self, event):
"""Increase font size"""
self.app.config.set('fontSize', int(self.app.config.get('fontSize'))+2)
self.updateHtmlScreen()
def onDecreaseFontSize(self, event):
"""Decrease font size"""
self.app.config.set('fontSize', int(self.app.config.get('fontSize'))-2)
self.updateHtmlScreen()
def onNormalFontSize(self, event):
"""Set normal font size"""
self.app.config.set('fontSize', NORMAL_FONT_SIZE)
self.updateHtmlScreen()
def checkEncMenuItem(self, name):
"""Select menu item defined by name"""
ename = ""
for key in misc.encodings:
if name == misc.encodings[key]:
ename = key
break
if len(ename) == 0:
systemLog(ERROR, "Something wrong with encodings (name == None)")
return
self.menuEncodings.FindItemById(self.menuEncodings.FindItem(ename)).Check(1)
def getCurrentEncoding(self):
"""Return currently set encoding"""
# Is this the best way for keeping it?
return self.app.config.encoding
def onAddDict(self, event):
installer = Installer(self, self.app.config)
installer.showGUI()
def onAddFromFile(self, event):
"""Starts dictionary registration process"""
fileDialog = wx.FileDialog(self, _("Choose dictionary file"), "", "",
"", wx.OPEN|wx.MULTIPLE)
if fileDialog.ShowModal() == wx.ID_OK:
file = fileDialog.GetPaths()[0]
else:
fileDialog.Destroy()
return
flist = ["Slowo", "Mova", "TMX", "Dict"]
msg = _("Select dictionary format. If you can't find\n" \
"the format of your dictionary, the register\n" \
"system does not support it yet.")
formatDialog = wx.SingleChoiceDialog(self,
msg,
_("Dictionary format"),
flist, wx.OK|wx.CANCEL)
if formatDialog.ShowModal() == wx.ID_OK:
format = formatDialog.GetStringSelection()
else:
formatDialog.Destroy()
return
fileDialog.Destroy()
formatDialog.Destroy()
return self.app.reg.registerDictionary(file, format,
self.app.config.defaultEnc)
def onAddFromPlugin(self, event):
"""Starts plugin installation process"""
dialog = wx.FileDialog(self, _("Choose plugin file"), "", "",
"", wx.OPEN|wx.MULTIPLE)
if dialog.ShowModal() == wx.ID_OK:
plugin.installPlugin(self.app.config, dialog.GetPaths()[0])
dialog.Destroy()
def onManual(self, event):
"""Shows Manual window"""
systemLog(WARNING, "Manual function is not impelemented yet")
def onAbout(self, event):
"""Shows 'About' window"""
aboutWindow = AboutWindow(self, -1,
_("About"),
style=wx.DEFAULT_DIALOG_STYLE)
aboutWindow.CentreOnScreen()
aboutWindow.Show(True)
def onWordSelected(self, event):
"""Is called when word list item is selected"""
if self.search and not self.search.isDone():
return
self.__searchedBySelecting = 1
self.SetStatusText(_("Searching..."))
self.buttonStop.Enable(1)
self.timerSearch.Start(self.delay)
word = event.GetString()
global lastLookupWord
lastLookupWord = word
self.entry.SetValue(word)
word = enc.fromWX(word)
word = word.encode(self.activeDictionary.getEncoding())
self.search = Process(self.activeDictionary.search, word)
wx.BeginBusyCursor()
def createListPanel(self):
self.panelList = wx.Panel(self.splitter, -1)
sbSizerList = wx.StaticBoxSizer(wx.StaticBox(self.panelList, -1,
_("Word List")),
wx.VERTICAL)
self.wordList = wx.ListBox(self.panelList, 154, wx.Point(-1, -1),
wx.Size(-1, -1), self.words, wx.LB_SINGLE)
sbSizerList.Add(self.wordList, 1, wx.ALL | wx.EXPAND, 0)
self.panelList.SetSizer(sbSizerList)
self.panelList.SetAutoLayout(True)
sbSizerList.Fit(self.panelList)
def hideWordList(self):
"""Hides word list"""
systemLog(DEBUG, "Hiding word list...")
self.splitter.SetSashPosition(0)
self.splitter.Unsplit(self.panelList)
self.wlHidden = True
# And change the button pixmap
bmp = wx.Bitmap(os.path.join(info.GLOBAL_HOME, "pixmaps", "unhide.png"),
wx.BITMAP_TYPE_PNG)
self.buttonHide.SetBitmapLabel(bmp)
self.buttonHide.SetToolTipString(_("Show word list"))
self.buttonHide.Show(False)
def unhideWordList(self):
"""Shows word list"""
systemLog(DEBUG, "Showing word list...")
self.createListPanel()
self.splitter.SplitVertically(self.panelList, self.panelHtml)
self.splitter.SetSashPosition(int(self.app.config.get('sashPos')))
self.wlHidden = False
# And change the pixmap
bmp = wx.Bitmap(os.path.join(info.GLOBAL_HOME, "pixmaps", "hide.png"),
wx.BITMAP_TYPE_PNG)
self.buttonHide.SetBitmapLabel(bmp)
self.buttonHide.SetToolTipString(_("Hide word list"))
def onPrint(self, event):
"""This method is invoked when print menu item is selected"""
try:
self.printer.PrintText(self.htmlCode)
except Exception, e:
self.SetStatusText(_("Failed to print"))
systemLog(ERROR, "Unable to print translation (%s)" % e)
traceback.print_exc()
def onPreview(self, event):
"""This method is invoked when preview menu item is selected"""
try:
self.printer.PreviewText(self.htmlCode)
except Exception, e:
systemLog(ERROR, "Unable to preview translation (%s)" % e)
self.SetStatusText(_("Page preview failed"))
traceback.print_exc()
def savePreferences(self):
"""Saves window preferences when exiting"""
if self.app.config.get('saveWindowSize'):
self.app.config.set('windowWidth', self.GetSize()[0])
self.app.config.set('windowHeight', self.GetSize()[1])
if self.app.config.get('saveWindowPos'):
self.app.config.set('windowPosX', self.GetPosition()[0])
self.app.config.set('windowPosY', self.GetPosition()[1])
if self.app.config.get('saveSashPos'):
if not self.wordListHidden():
self.app.config.set('sashPos', self.splitter.GetSashPosition())
try:
self.app.config.save()
except Exception, e:
systemLog(ERROR, "Unable to save configuration: %s" % e)
opendict-0.6.3/lib/gui/miscwin.py 0000644 0001750 0001750 00000011312 10640522715 015344 0 ustar mjoc mjoc #
# OpenDict
# Copyright (c) 2003-2006 Martynas Jocius
# Copyright (c) 2007 IDILES SYSTEMS, UAB
#
# This program 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 2 of the License, or
# (at your opinion) any later version.
#
# This program is distributed in the hope that will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MECHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more detals.
#
# You shoud have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
# 02111-1307 USA
#
import wx
import wx.html
import shutil
import traceback
from lib.logger import systemLog, debugLog, DEBUG, INFO, WARNING, ERROR
from lib import enc
from lib.gui import errorwin
_ = wx.GetTranslation
class PluginLicenceWindow(wx.Dialog):
def __init__(self, parent, id, title, msg, pos=wx.DefaultPosition,
size=wx.DefaultSize, style=wx.DEFAULT_DIALOG_STYLE):
wx.Dialog.__init__(self, parent, id, title, pos, size, style)
vbox = wx.BoxSizer(wx.VERTICAL)
vboxButtons = wx.BoxSizer(wx.HORIZONTAL)
htmlWin = wx.html.HtmlWindow(self, -1, style=wx.SUNKEN_BORDER)
htmlWin.SetFonts('Helvetica', 'Fixed', [10]*5)
error = False
try:
encodedText = enc.toWX(unicode(msg, 'UTF-8'))
htmlWin.SetPage(encodedText)
except Exception, e:
systemLog(ERROR, "Unable to encode/show licence text: %s" % e)
htmlWin.SetPage(_("Error: unable to show licence text"))
error = True
vbox.Add(htmlWin, 1, wx.ALL | wx.EXPAND, 5)
if not error:
self.buttonNo = wx.Button(self, wx.ID_CANCEL, _("Do not accept"))
vboxButtons.Add(self.buttonNo, 0, wx.ALL, 2)
self.buttonYes = wx.Button(self, wx.ID_OK, _("Accept"))
vboxButtons.Add(self.buttonYes, 0, wx.ALL, 2)
else:
self.buttonNo = wx.Button(self, wx.ID_CANCEL, _("Close"))
vboxButtons.Add(self.buttonNo, 0, wx.ALL, 2)
vbox.Add(vboxButtons, 0, wx.ALL | wx.ALIGN_RIGHT, 5)
self.SetSizer(vbox)
def showLicenceAgreement(parentWindow, licenceText):
"""Show licence agreement window"""
dialog = PluginLicenceWindow(parentWindow, -1, _("Licence Agreement"),
licenceText, size=(600, 400))
result = dialog.ShowModal()
dialog.Destroy()
if result == wx.ID_OK:
return True
return False
class InvalidDictWindow(wx.Dialog):
def __init__(self, parent, id, title, dicts, pos=wx.DefaultPosition,
size=wx.DefaultSize, style=wx.DEFAULT_DIALOG_STYLE):
wx.Dialog.__init__(self, parent, id, title, pos, size, style)
self.dicts = {}
self.buttons = {}
vbox = wx.BoxSizer(wx.VERTICAL)
vboxButtons = wx.BoxSizer(wx.HORIZONTAL)
vboxDicts = wx.BoxSizer(wx.VERTICAL)
grid = wx.FlexGridSizer(2, 2, 5, 5)
msg = _("You have directories that containt invalid dictionaries " \
"and cannot be loaded. \nYou can try to remove these " \
"directories right now.")
vbox.Add(wx.StaticText(self, -1, msg),
0, wx.ALL, 5)
row = 0
for d in dicts:
grid.Add(wx.StaticText(self, -1, d),
0, wx.ALIGN_CENTER_VERTICAL)
rid = wx.NewId()
self.dicts[rid] = d
b = wx.Button(self, rid, _("Remove"))
self.buttons[rid] = b
grid.Add(b, 1, wx.ALIGN_CENTER_VERTICAL)
wx.EVT_BUTTON(self, rid, self.onRemove)
vbox.Add(grid, 0, wx.ALL, 10)
vbox.Add(wx.StaticLine(self, -1), 1, wx.ALL | wx.EXPAND, 1)
self.buttonClose = wx.Button(self, wx.ID_CANCEL, _("Close"))
vboxButtons.Add(self.buttonClose, 0, wx.ALL, 5)
vbox.Add(vboxButtons, 0, wx.ALL | wx.ALIGN_RIGHT, 5)
self.SetSizer(vbox)
self.Fit()
def onRemove(self, event):
path = self.dicts[event.GetId()]
try:
shutil.rmtree(path)
self.buttons[event.GetId()].Disable()
except Exception, e:
traceback.print_exc()
title = _("Unable to remove")
msg = _("Unable to remove directory \"%s\": %s") % (path, e)
errorwin.showErrorMessage(title, msg)
def showInvalidDicts(parentWin, invalidDicts):
"""Show licence agreement window"""
dialog = InvalidDictWindow(None, -1, _("Invalid Dictionaries"),
invalidDicts)
result = dialog.ShowModal()
dialog.Destroy()
opendict-0.6.3/lib/gui/helpwin.py 0000644 0001750 0001750 00000020320 10645177632 015351 0 ustar mjoc mjoc # -*- coding: UTF-8 -*-
# OpenDict
# Copyright (c) 2003-2006 Martynas Jocius
# Copyright (c) 2007 IDILES SYSTEMS, UAB
#
# This program 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 2 of the License, or
# (at your opinion) any later version.
#
# This program is distributed in the hope that will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MECHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more detals.
#
# You shoud have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
# 02111-1307 USA
#
# Module: gui.helpwin
#from wx import *
#from wx.html import *
import wx
import os
import sys
from lib.logger import systemLog, debugLog, DEBUG, INFO, WARNING, ERROR
from lib import enc
from lib import info
_ = wx.GetTranslation
class LicenseWindow(wx.Frame):
"""Licence window class"""
def __init__(self, parent, id, title, pos=wx.DefaultPosition,
size=wx.DefaultSize, style=wx.CENTRE):
wx.Frame.__init__(self, parent, id, title, pos, size, style)
vbox = wx.BoxSizer(wx.VERTICAL)
#
# Read licence file
#
try:
fd = open(os.path.join(info.GLOBAL_HOME, 'copying.html'))
data = fd.read()
fd.close()
except Exception, e:
systemLog(ERROR, "Unable to read licence file: %s" % e)
data = "Error: licence file not found"
scWinAbout = wx.ScrolledWindow(self, -1, wx.DefaultPosition,
wx.Size(-1, -1))
htmlWin = wx.html.HtmlWindow(scWinAbout, -1, style=wx.SUNKEN_BORDER)
htmlWin.SetFonts('Helvetica', 'Fixed', [10]*5)
htmlWin.SetPage(data)
scBox = wx.BoxSizer(wx.VERTICAL)
scBox.Add(htmlWin, 1, wx.ALL | wx.EXPAND, 1)
scWinAbout.SetSizer(scBox)
vbox.Add(scWinAbout, 1, wx.ALL | wx.EXPAND, 5)
self.buttonClose = wx.Button(self, 2002, _("Close"))
vbox.Add(self.buttonClose, 0, wx.ALL | wx.ALIGN_RIGHT, 5)
self.SetSizer(vbox)
wx.EVT_BUTTON(self, 2002, self.onClose)
def onClose(self, event):
"""This method is invoked when Close button is clicked"""
self.Destroy()
class CreditsWindow(wx.Dialog):
"""Credits window class"""
def __init__(self, parent, id, title, pos=wx.DefaultPosition,
size=wx.DefaultSize):
wx.Dialog.__init__(self, parent, id, title, pos, size)
vbox = wx.BoxSizer(wx.VERTICAL)
nb = wx.Notebook(self, -1)
# "Written by" panel
writePanel = wx.Panel(nb, -1)
vboxWrite = wx.BoxSizer(wx.VERTICAL)
writtenString = unicode("Martynas Jocius \n"
"Nerijus Baliūnas \n"
"Mantas Kriaučiūnas ",
"UTF-8")
written = enc.toWX(writtenString)
labelWrite = wx.StaticText(writePanel, -1, written)
vboxWrite.Add(labelWrite, 0, wx.ALL, 10)
writePanel.SetSizer(vboxWrite)
nb.AddPage(writePanel, _("Written By"))
# "Translations" panel
tPanel = wx.Panel(nb, -1)
vboxTP = wx.BoxSizer(wx.VERTICAL)
transString = unicode("Martynas Jocius ",
"UTF-8")
trans = enc.toWX(transString)
labelTP = wx.StaticText(tPanel, -1, trans)
vboxTP.Add(labelTP, 0, wx.ALL, 10)
tPanel.SetSizer(vboxTP)
nb.AddPage(tPanel, _("Translated By"))
# "Thanks" panel
thPanel = wx.Panel(nb, -1)
vboxThP = wx.BoxSizer(wx.VERTICAL)
thanksString = _("Ports:\n\n") + u"Debian/Ubuntu:\n Kęstutis Biliūnas \n\nMacOS X:\n Linas Valiukas "
thanks = enc.toWX(thanksString)
labelThP = wx.StaticText(thPanel, -1, thanks)
vboxThP.Add(labelThP, 0, wx.ALL, 10)
thPanel.SetSizer(vboxThP)
nb.AddPage(thPanel, _("Thanks To"))
# "Sponsor" panel
sponsorPanel = wx.Panel(nb, -1)
vboxSP = wx.BoxSizer(wx.VERTICAL)
sponsorString = _("OpenDict project is sponsored by IDILES.\n"
"Visit company's website at http://www.idiles.com.\n\n"
"Report problems by email address support@idiles.com.")
sponsor = enc.toWX(sponsorString)
labelSP = wx.StaticText(sponsorPanel, -1, sponsor)
vboxSP.Add(labelSP, 0, wx.ALL, 10)
sponsorPanel.SetSizer(vboxSP)
nb.AddPage(sponsorPanel, _("Sponsors"))
vbox.Add(nb, 1, wx.ALL | wx.EXPAND, 3)
buttonClose = wx.Button(self, 2005, _("Close"))
vbox.Add(buttonClose, 0, wx.ALL | wx.ALIGN_RIGHT, 5)
self.SetSizer(vbox)
wx.EVT_BUTTON(self, 2005, self.onClose)
def onClose(self, event):
"""This method is invoked when Close button is clicked"""
self.Destroy()
class AboutWindow(wx.Dialog):
"""Information window about OpenDict"""
def __init__(self, parent, id, title, pos=wx.DefaultPosition,
size=wx.DefaultSize, style=wx.DEFAULT_DIALOG_STYLE):
wx.Dialog.__init__(self, parent, id, title, pos, size, style)
hboxButtons = wx.BoxSizer(wx.HORIZONTAL)
vbox = wx.BoxSizer(wx.VERTICAL)
bmp = wx.Bitmap(os.path.join(info.GLOBAL_HOME,
"pixmaps", "icon-96x96.png"),
wx.BITMAP_TYPE_PNG)
vbox.Add(wx.StaticBitmap(self, -1, bmp, wx.Point(-1, -1)), 0, wx.ALL |
wx.CENTRE, 5)
title = "OpenDict %s" % info.VERSION
copy = "Copyright %(c)s 2003-2006 Martynas Jocius \n" \
"Copyright %(c)s 2007 IDILES SYSTEMS, UAB " \
% {'c': unicode("\302\251", "UTF-8")}
desc = _("OpenDict is a multiplatform dictionary.")
page = "http://opendict.idiles.com"
titleLabel = wx.StaticText(self, -1, title,
style=wx.ALIGN_CENTER)
titleLabel.SetFont(wx.Font(18, wx.SWISS, wx.NORMAL, wx.BOLD))
vbox.Add(titleLabel, 1, wx.ALL | wx.ALIGN_CENTER, 5)
copyLabel = wx.StaticText(self, -1, copy, style=wx.ALIGN_CENTER)
copyLabel.SetFont(wx.Font(8, wx.SWISS, wx.NORMAL, wx.BOLD))
vbox.Add(copyLabel, 1, wx.ALL | wx.ALIGN_CENTER, 5)
descLabel = wx.StaticText(self, -1,
_("OpenDict is a multiplatform dictionary."), style=wx.ALIGN_CENTER)
descLabel.SetFont(wx.Font(10, wx.SWISS, wx.NORMAL, wx.NORMAL))
vbox.Add(descLabel, 1, wx.ALL | wx.ALIGN_CENTER, 5)
pageLabel = wx.StaticText(self, -1, page, style=wx.ALIGN_CENTER)
pageLabel.SetFont(wx.Font(10, wx.SWISS, wx.NORMAL, wx.NORMAL))
vbox.Add(pageLabel, 1, wx.ALL | wx.ALIGN_CENTER, 5)
vbox.Add(wx.StaticLine(self, -1), 0, wx.ALL | wx.EXPAND, 5)
self.buttonCredits = wx.Button(self, 2004, _("Credits"))
hboxButtons.Add(self.buttonCredits, 0, wx.ALL | wx.ALIGN_LEFT, 3)
self.buttonLicence = wx.Button(self, 2006, _("Licence"))
hboxButtons.Add(self.buttonLicence, 0, wx.ALL | wx.ALIGN_LEFT, 3)
self.buttonOK = wx.Button(self, 2003, _("Close"))
hboxButtons.Add(self.buttonOK, 0, wx.ALL | wx.ALIGN_RIGHT, 3)
vbox.Add(hboxButtons, 0, wx.ALL | wx.ALIGN_CENTER, 5)
self.SetSizer(vbox)
vbox.Fit(self)
wx.EVT_BUTTON(self, 2003, self.onClose)
wx.EVT_BUTTON(self, 2004, self.onCredits)
wx.EVT_BUTTON(self, 2006, self.onLicence)
def onClose(self, event):
self.Destroy()
def onCredits(self, event):
creditsWindow = CreditsWindow(self, -1, "Credits",
size=(500, 240))
creditsWindow.CentreOnScreen()
creditsWindow.Show()
def onLicence(self, event):
licenseWindow = LicenseWindow(self, -1,
_("Licence"),
size=(500, 400),
style=wx.DEFAULT_FRAME_STYLE)
licenseWindow.CenterOnScreen()
licenseWindow.Show(True)
opendict-0.6.3/lib/gui/pluginwin.py 0000644 0001750 0001750 00000061230 10641023022 015677 0 ustar mjoc mjoc #
# OpenDict
# Copyright (c) 2003-2006 Martynas Jocius
# Copyright (c) 2007 IDILES SYSTEMS, UAB
#
# This program 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 2 of the License, or
# (at your opinion) any later version.
#
# This program is distributed in the hope that will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MECHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more detals.
#
# You shoud have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
# 02111-1307 USA
#
#from wx import *
#import wx.lib.mixins.listctrl as listmix
import wx
from shutil import rmtree
import os
import traceback
import time
from lib.gui import errorwin
from lib import installer
from lib import dicttype
from lib import enc
from lib import info
from lib import misc
from lib import xmltools
from lib import util
from lib.logger import systemLog, debugLog, DEBUG, INFO, WARNING, ERROR
_ = wx.GetTranslation
class DictListCtrl(wx.ListCtrl):
def __init__(self, parent, ID, pos=wx.DefaultPosition,
size=wx.DefaultSize, style=0):
wx.ListCtrl.__init__(self, parent, ID, pos, size, style)
class PluginManagerWindow(wx.Frame):
"""Plugin Manager lets install, remove and view info
about installed plugins"""
def __init__(self, parent, id, title, pos=wx.DefaultPosition,
size=wx.DefaultSize, style=wx.DEFAULT_FRAME_STYLE):
wx.Frame.__init__(self, parent, id, title, pos, size, style)
self.app = wx.GetApp()
self.mainWin = parent
self.currentInstalledItemSelection = -1
self.currentAvailItemSelection = -1
vboxMain = wx.BoxSizer(wx.VERTICAL)
self.installedDictionaries = {}
self.availDictionaries = self.app.cache.get('addons') or {}
installed = True
for dictName in self.app.dictionaries.keys():
self.installedDictionaries[dictName] = installed
tabbedPanel = wx.Notebook(self, -1)
# Add 'installed' panel
panelInstalled = self._makeInstalledPanel(tabbedPanel)
tabbedPanel.AddPage(panelInstalled, _("Installed"))
# Add 'available' panel
panelAvailable = self._makeAvailablePanel(tabbedPanel)
tabbedPanel.AddPage(panelAvailable, _("Available"))
vboxMain.Add(tabbedPanel, 1, wx.ALL | wx.EXPAND, 2)
# Add info panel
panelInfo = self._makeInfoPanel()
vboxMain.Add(panelInfo, 0, wx.ALL | wx.EXPAND, 2)
hboxButtons = wx.BoxSizer(wx.HORIZONTAL)
self.buttonClose = wx.Button(self, 163, _("Close"))
hboxButtons.Add(self.buttonClose, 0, wx.ALL | wx.ALIGN_RIGHT, 3)
vboxMain.Add(hboxButtons, 0, wx.ALL | wx.ALIGN_RIGHT, 1)
self.SetIcon(wx.Icon(os.path.join(info.GLOBAL_HOME,
"pixmaps",
"icon-24x24.png"),
wx.BITMAP_TYPE_PNG))
self.SetSizer(vboxMain)
self.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGED, self.onPageChanged)
wx.EVT_BUTTON(self, 161, self.onInstall)
wx.EVT_BUTTON(self, 162, self.onRemove)
wx.EVT_BUTTON(self, 163, self.onClose)
self.addons = self.app.cache.get("addons", {})
def _makeInstalledPanel(self, tabbedPanel):
"""Creates panel with for controlling installed dictionaries"""
#
# Boxes
#
panelInstalled = wx.Panel(tabbedPanel, -1)
vboxInstalled = wx.BoxSizer(wx.VERTICAL)
# Help message
labelHelp = wx.StaticText(panelInstalled, -1,
_("Checked dictionaries are available from the " \
"menu, unchecked dictionaries \nare not available from the menu."));
vboxInstalled.Add(labelHelp, 0, wx.ALL, 3)
#
# Installed list
#
idDictList = wx.NewId()
self.installedList = wx.CheckListBox(panelInstalled, idDictList,
style=wx.LC_REPORT
| wx.LC_SINGLE_SEL
| wx.SUNKEN_BORDER)
self.Bind(wx.EVT_CHECKLISTBOX, self.onDictionaryChecked,
self.installedList)
self.Bind(wx.EVT_LISTBOX, self.onInstalledSelected,
self.installedList)
vboxInstalled.Add(self.installedList, 1, wx.ALL | wx.EXPAND, 1)
hboxButtons = wx.BoxSizer(wx.HORIZONTAL)
#
# "Install from file" button
#
idInstallFile = wx.NewId()
self.buttonInstallFile = wx.Button(panelInstalled, idInstallFile,
_("Install From File"))
hboxButtons.Add(self.buttonInstallFile, 0, wx.ALL | wx.ALIGN_RIGHT, 2)
#
# "Remove" button
#
idRemove = wx.NewId()
self.buttonRemove = wx.Button(panelInstalled, idRemove, _("Remove"))
self.buttonRemove.Disable()
hboxButtons.Add(self.buttonRemove, 0, wx.ALL | wx.ALIGN_RIGHT, 2)
vboxInstalled.Add(hboxButtons, 0, wx.ALL | wx.ALIGN_RIGHT, 2)
panelInstalled.SetSizer(vboxInstalled)
vboxInstalled.Fit(panelInstalled)
#
# Make columns
#
dictNames = self.installedDictionaries.keys()
dictNames.sort()
self.setInstalledDicts(dictNames)
self.Bind(wx.EVT_BUTTON, self.onRemove, self.buttonRemove)
self.Bind(wx.EVT_BUTTON, self.onInstallFile, self.buttonInstallFile)
return panelInstalled
def _makeAvailablePanel(self, tabbedPanel):
"""Creates panel with for controlling installed dictionaries"""
#
# Boxes
#
panelAvailable = wx.Panel(tabbedPanel, -1)
vboxAvailable = wx.BoxSizer(wx.VERTICAL)
#
# List of available dictionaries
#
idAvailList = wx.NewId()
self.availableList = DictListCtrl(panelAvailable, idAvailList,
style=wx.LC_REPORT
| wx.LC_SINGLE_SEL
#| wx.LC_NO_HEADER
| wx.SUNKEN_BORDER)
vboxAvailable.Add(self.availableList, 1, wx.ALL | wx.EXPAND, 1)
# Horizontal box for buttons
hboxButtons = wx.BoxSizer(wx.HORIZONTAL)
#
# "Update" button
#
idUpdate = wx.NewId()
self.buttonUpdate = wx.Button(panelAvailable, idUpdate,
_("Update List"))
hboxButtons.Add(self.buttonUpdate, 0, wx.ALL | wx.ALIGN_RIGHT, 2)
#
# "Install" button
#
idInstall = wx.NewId()
self.buttonInstall = wx.Button(panelAvailable, idInstall, _("Install"))
self.buttonInstall.Disable()
hboxButtons.Add(self.buttonInstall, 0, wx.ALL | wx.ALIGN_RIGHT, 2)
vboxAvailable.Add(hboxButtons, 0, wx.ALL | wx.ALIGN_RIGHT, 1)
panelAvailable.SetSizer(vboxAvailable)
vboxAvailable.Fit(panelAvailable)
#
# Make columns
#
self.availableList.InsertColumn(0, _("Name"))
self.availableList.InsertColumn(1, _("Size"))
addons = self.app.cache.get('addons')
if not addons:
addons = {}
dictNames = addons.keys()
dictNames.sort()
for dictionary in dictNames:
index = self.availableList.InsertStringItem(0, dictionary)
sizeString = "%d KB" % addons.get(dictionary).getSize()
self.availableList.SetStringItem(index, 1,
sizeString)
self.availableList.SetItemData(index, index+1)
# Keep wide if list is empty yet
if addons:
self.availableList.SetColumnWidth(0, wx.LIST_AUTOSIZE)
self.availableList.SetColumnWidth(1, wx.LIST_AUTOSIZE)
else:
self.availableList.SetColumnWidth(0, 200)
self.availableList.SetColumnWidth(1, 120)
self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.onAvailableSelected,
self.availableList)
self.Bind(wx.EVT_BUTTON, self.onInstall, self.buttonInstall)
self.Bind(wx.EVT_BUTTON, self.onUpdate, self.buttonUpdate)
return panelAvailable
def _makeInfoPanel(self):
"""Create information panel"""
#
# Boxes
#
panelInfo = wx.Panel(self, -1)
vboxInfo = wx.BoxSizer(wx.VERTICAL)
vboxInfoBox = wx.BoxSizer(wx.VERTICAL)
sbSizerInfo = wx.StaticBoxSizer(\
wx.StaticBox(panelInfo, -1,
_("Information About Dictionary")),
wx.VERTICAL)
grid = wx.FlexGridSizer(3, 2, 1, 1)
self.labelName = wx.StaticText(panelInfo, -1, "")
self.labelVersion = wx.StaticText(panelInfo, -1, "")
self.labelFormat = wx.StaticText(panelInfo, -1, "")
self.labelAuthor = wx.StaticText(panelInfo, -1, "")
self.labelSize = wx.StaticText(panelInfo, -1, "")
self.textAbout = wx.TextCtrl(panelInfo, -1, size=(-1, 100),
style=wx.TE_MULTILINE | wx.TE_READONLY)
self.stName = wx.StaticText(panelInfo, -1, _("Name: "))
self.stName.Disable()
grid.Add(self.stName, 0, wx.ALL | wx.ALIGN_RIGHT)
grid.Add(self.labelName, 0, wx.ALL)
self.stVersion = wx.StaticText(panelInfo, -1, _("Version: "))
self.stVersion.Disable()
grid.Add(self.stVersion, 0, wx.ALL | wx.ALIGN_RIGHT)
grid.Add(self.labelVersion, 0, wx.ALL)
self.stAuthor = wx.StaticText(panelInfo, -1, _("Maintainer: "))
self.stAuthor.Disable()
grid.Add(self.stAuthor, 0, wx.ALL | wx.ALIGN_RIGHT)
grid.Add(self.labelAuthor, 0, wx.ALL)
vboxInfoBox.Add(grid, 1, wx.ALL | wx.EXPAND, 1)
vboxInfoBox.Add(self.textAbout, 0, wx.ALL | wx.EXPAND, 1)
sbSizerInfo.Add(vboxInfoBox, 1, wx.ALL | wx.EXPAND, 5)
vboxInfo.Add(sbSizerInfo, 1, wx.ALL | wx.EXPAND, 5)
panelInfo.SetSizer(vboxInfo)
vboxInfo.Fit(panelInfo)
return panelInfo
def onDictionaryChecked(self, event, *args):
index = event.GetSelection()
label = self.installedList.GetString(index)
if self.installedList.IsChecked(index):
self._addDictToMenu(label)
d = self.app.dictionaries.get(label)
d.setActive()
else:
self._removeDictFromMenu(label)
d = self.app.dictionaries.get(label)
d.setActive(active=False)
self.installedList.SetSelection(index)
def _removeDictFromMenu(self, name):
self.app.config.activedict.remove(name)
self.app.config.activedict.save()
self.app.window.removeDictionary(name)
def _addDictToMenu(self, name):
dict = None
for k, v in self.app.dictionaries.items():
if k == name:
dict = v
if dict:
self.app.config.activedict.add(name)
self.app.config.activedict.save()
self.app.window.addDictionary(dict)
def onPageChanged(self, event):
_pageInstalled = 0
_pageAvail = 1
sel = event.GetSelection()
if sel == _pageInstalled:
if self.currentInstalledItemSelection == -1:
self.clearInfo()
self.disableInfo()
else:
self.enableInfo()
self.showInstalledInfo()
elif sel == _pageAvail:
if self.currentAvailItemSelection == -1:
self.clearInfo()
self.disableInfo()
else:
self.enableInfo()
self.showAvailableInfo()
def onInstalledSelected(self, event):
"""Called when list item is selected"""
self.currentInstalledItemSelection = event.GetSelection()
self.buttonRemove.Enable(1)
self.showInstalledInfo()
def showInstalledInfo(self):
"""Show information about selected dictionary"""
dictName = self.installedList.GetString(\
self.currentInstalledItemSelection)
dictInstance = self.app.dictionaries.get(dictName)
self.showInfo(dictInstance)
def showAvailableInfo(self):
"""Show information about selected dictionary"""
dictName = self.availableList.GetItemText(\
self.currentAvailItemSelection)
dictInstance = self.addons.get(dictName)
if not dictInstance:
systemLog(ERROR, "BUG: add-on '%s' not found by name" % dictName)
return
self.showInfo(dictInstance)
def showInfo(self, dictInstance):
"""Show information about dictionary"""
self.stName.Enable(1)
self.stVersion.Enable(1)
self.stAuthor.Enable(1)
if dictInstance.getName():
dictName = enc.toWX(dictInstance.getName())
else:
dictName = '--'
self.labelName.SetLabel(dictName)
if dictInstance.getVersion():
dictVersion = enc.toWX(dictInstance.getVersion())
else:
dictVersion = '--'
self.labelVersion.SetLabel(dictVersion)
if dictInstance.getAuthors():
authors = []
for author in dictInstance.getAuthors():
if author:
authors.append("%s <%s>" % (author.get('name'),
author.get('email')))
dictAuthors = enc.toWX(', '.join(authors))
else:
dictAuthors = '--'
self.labelAuthor.SetLabel(dictAuthors)
if dictInstance.getDescription():
description = enc.toWX(dictInstance.getDescription().strip())
else:
description = ''
self.textAbout.Clear()
self.textAbout.WriteText(description)
def onAvailableSelected(self, event):
self.currentAvailItemSelection = event.m_itemIndex
self.buttonInstall.Enable(1)
self.showAvailableInfo()
def clearInfo(self):
"""Clear info fields"""
self.labelName.SetLabel('')
self.labelVersion.SetLabel('')
self.labelAuthor.SetLabel('')
self.textAbout.Clear()
def disableInfo(self):
"""Make info widgets inactive"""
self.stName.Disable()
self.stVersion.Disable()
self.stAuthor.Disable()
self.textAbout.Disable()
def enableInfo(self):
"""Make info widgets active"""
self.stName.Enable(1)
self.stVersion.Enable(1)
self.stAuthor.Enable(1)
self.textAbout.Enable(1)
def setInstalledDicts(self, dictNames):
"""Clear the list of installed dictionaries and set new items"""
for i in range(self.installedList.GetCount()):
self.installedList.Delete(i)
dictNames.sort()
i = 0
for dictionary in dictNames:
index = self.installedList.Insert(dictionary, i)
if self.app.dictionaries[dictionary].getActive():
self.installedList.Check(i)
i += 1
def setAvailDicts(self, addons):
"""Clear the list of available dictionaries and set
new items"""
self.availableList.DeleteAllItems()
names = addons.keys()
names.sort()
names.reverse()
for name in names:
addon = addons.get(name)
index = self.availableList.InsertStringItem(0, addon.getName())
self.availableList.SetStringItem(index, 1,
str(addon.getSize())+" KB")
self.availableList.SetItemData(index, index+1)
if names:
self.availableList.SetColumnWidth(0, wx.LIST_AUTOSIZE)
else:
title = _("List updated")
msg = _("All your dictionaries are up to date.")
errorwin.showInfoMessage(title, msg)
def onUpdate(self, event):
"""Update dictionaries list"""
title = _("Downloading List")
downloader = util.DownloadThread(self.app.config.get('repository-list'))
progressDialog = wx.ProgressDialog(title,
'',
maximum=100,
parent=self,
style=wx.PD_CAN_ABORT
| wx.PD_APP_MODAL)
keepGoing = True
error = None
try:
systemLog(INFO, "Opening %s..." % \
self.app.config.get('repository-list'))
downloader.start()
xmlData = ''
while keepGoing and not downloader.finished():
keepGoing = progressDialog.Update(downloader.getPercentage(),
downloader.getMessage())
if not keepGoing:
downloader.stop()
break
xmlData += downloader.getBytes()
time.sleep(0.1)
progressDialog.Destroy()
xmlData += downloader.getBytes()
systemLog(INFO, "Finished downloading list")
except Exception, e:
traceback.print_exc()
progressDialog.Destroy()
error = _("Unable to download list from %s: %s") \
% (self.app.config.get('repository-list'), e)
if not error:
error = downloader.getErrorMessage()
if error:
systemLog(ERROR, error)
title = _("Unable to download list")
errorwin.showErrorMessage(title, error)
return
if len(xmlData) == 0:
return
if hasattr(self, "addons"):
del self.addons
allAddons = xmltools.parseAddOns(xmlData)
self.addons = {}
for name, obj in allAddons.items():
if name in self.app.dictionaries.keys() \
and obj.getVersion() <= (\
self.app.dictionaries.get(name).getVersion() or ""):
continue
self.addons[name] = obj
app = wx.GetApp()
if app.cache.has_key("addons"):
del app.cache["addons"]
app.cache["addons"] = self.addons
self.setAvailDicts(self.addons)
def onInstall(self, event):
"""Install button pressed"""
name = self.availableList.GetItemText(\
self.currentAvailItemSelection)
dictInfo = self.addons.get(name)
if not dictInfo:
systemLog(ERROR, "Interal Error, add-on %s not found in list" \
% name)
return
self._fetchAddon(dictInfo)
def onInstallFile(self, event):
"""Install dictionary from file"""
inst = installer.Installer(self.mainWin, self.app.config)
inst.showGUI()
dictNames = []
for name in self.app.dictionaries.keys():
dictNames.append(enc.toWX(name))
self.setInstalledDicts(dictNames)
def onRemove(self, event):
"""Remove button pressed"""
systemLog(INFO, "Removing %s" % self.installedList.GetString(
self.currentInstalledItemSelection))
dictName = self.installedList.GetString(
self.currentInstalledItemSelection)
dictInstance = self.app.dictionaries.get(dictName)
try:
if dictInstance.getType() == dicttype.PLUGIN:
removeDictionary = installer.removePluginDictionary
else:
removeDictionary = installer.removePlainDictionary
removeDictionary(dictInstance)
except Exception, e:
traceback.print_exc()
title = _("Unable to remove")
msg = _("Unable to remove dictionary \"%s\"") % dictName
errorwin.showErrorMessage(title, msg)
return
self.installedList.Delete(self.currentInstalledItemSelection)
idDictMenuItem = None
for iid, dictionary in self.app.config.ids.items():
if dictionary == dictName:
idDictMenuItem = iid
if idDictMenuItem is not None:
self.mainWin.menuDict.Delete(idDictMenuItem)
parent = self.GetParent()
if parent.activeDictionary \
and dictName == parent.activeDictionary.getName():
parent.onCloseDict(None)
self.buttonRemove.Disable()
del self.app.dictionaries[dictName]
self.clearInfo()
self.disableInfo()
def onClose(self, event):
"""Close event occured"""
self.Destroy()
def _fetchAddon(self, dictInfo):
"""Fetch add-on using progress bar"""
downloadsDir = os.path.join(info.LOCAL_HOME, 'downloads')
if not os.path.exists(downloadsDir):
os.mkdir(downloadsDir)
localPath = os.path.join(downloadsDir,
os.path.basename(dictInfo.getLocation()))
title = _("Downloading %s...") % dictInfo.getName()
progressDialog = wx.ProgressDialog(title,
'',
maximum=100,
parent=self,
style=wx.PD_CAN_ABORT
| wx.PD_APP_MODAL)
keepGoing = True
error = None
downloader = util.DownloadThread(dictInfo.getLocation())
stopped = False
try:
fd = open(localPath, 'wb')
downloader.start()
while keepGoing and not downloader.finished():
keepGoing = progressDialog.Update(downloader.getPercentage(),
downloader.getMessage())
if not keepGoing:
stopped = True
break
chunk = downloader.getBytes()
fd.write(chunk)
time.sleep(0.1)
bytes = downloader.getBytes()
if len(bytes):
fd.write(bytes)
progressDialog.Destroy()
downloader.stop()
except Exception, e:
traceback.print_exc()
progressDialog.Destroy()
error = "Unable to fetch \"%s\" from %s: %s" \
% (dictInfo.getName(), dictInfo.getLocation(), e)
systemLog(ERROR, error)
fd.close()
if stopped:
return
if not error:
error = downloader.getErrorMessage()
if error:
systemLog(ERROR, error)
title = _("Unable to download")
errorwin.showErrorMessage(title, error)
return
md5sum = util.getMD5Sum(localPath)
#
# Check checksum
#
if md5sum != dictInfo.getChecksum():
title = _("File is damaged")
msg = _("Downloaded file is damaged and cannot be installed. " \
"Please try again.")
errorwin.showErrorMessage(title, msg)
return
#
# Remove old version if exists
#
if dictInfo.getName() in self.app.dictionaries.keys():
try:
dictInstance = self.app.dictionaries.get(dictInfo.getName())
if dictInstance.getType() == dicttype.PLUGIN:
installer.removePluginDictionary(dictInstance)
else:
installer.removePlainDictionary(dictInstance)
except Exception, e:
traceback.print_exc()
title = _("Error")
msg = _("Unable to remove old version of \"%s\". "
"Error occured: \"%s\". New version "
"cannot be installed without removing old one.") \
% (dictInstance.getName(), e)
errorwin.showErrorMessage(title, msg)
return
#
# Install
#
try:
inst = installer.Installer(self.mainWin, self.app.config)
inst.install(localPath)
if self.installedList.FindString(dictInfo.getName()) == wx.NOT_FOUND:
index = self.installedList.Insert(dictInfo.getName(), 0)
self.installedList.Check(0)
self.app.config.activedict.add(dictInfo.getName())
self.app.config.activedict.save()
# FIXME: Code-wasting. Separated duplicated code into
# functions.
except Exception, e:
traceback.print_exc()
title = _("Unable to install")
msg = _("Unable to install dictionary \"%s\".") \
% dictInfo.getName()
errorwin.showErrorMessage(title, msg)
return
self.availableList.DeleteItem(self.currentAvailItemSelection)
del self.addons[dictInfo.getName()]
self.buttonInstall.Disable()
self.clearInfo()
self.disableInfo()
opendict-0.6.3/lib/gui/prefswin.py 0000644 0001750 0001750 00000022422 10640522715 015534 0 ustar mjoc mjoc #
# OpenDict
# Copyright (c) 2003-2006 Martynas Jocius
# Copyright (c) 2007 IDILES SYSTEMS, UAB
#
# This program 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 2 of the License, or
# (at your opinion) any later version.
#
# This program is distributed in the hope that will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MECHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more detals.
#
# You shoud have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
# 02111-1307 USA
#
import wx
from lib.logger import systemLog, debugLog, DEBUG, INFO, WARNING, ERROR
from lib.misc import encodings
from lib import enc
_ = wx.GetTranslation
PRON_COMMAND = "echo \"(SayText \\\"%s\\\")\" | festival"
class PrefsWindow(wx.Dialog):
"""Preferences dialog class"""
def __init__(self, parent, id, title, pos=wx.DefaultPosition,
size=wx.DefaultSize, style=wx.DEFAULT_FRAME_STYLE):
"""Initialize preferences dialog window"""
wx.Dialog.__init__(self, parent, id, title, pos, size, style)
self.app = wx.GetApp()
vboxMain = wx.BoxSizer(wx.VERTICAL)
hboxButtons = wx.BoxSizer(wx.HORIZONTAL)
grid = wx.FlexGridSizer(2, 2, 1, 1)
grid.Add(wx.StaticText(self, -1, _("Default dictionary: ")),
0, wx.ALIGN_CENTER_VERTICAL)
dictNames = []
for name, d in self.app.dictionaries.items():
if d.getActive():
dictNames.append(name)
dictNames.sort()
dictNames.insert(0, "")
try:
map(enc.toWX, dictNames)
except Exception, e:
systemLog(ERROR, "Unable to decode titles to UTF-8 (%s)" % e)
self.dictChooser = wx.ComboBox(self, 1100,
enc.toWX(self.app.config.get('defaultDict')),
wx.Point(-1, -1),
wx.Size(-1, -1), dictNames, wx.TE_READONLY)
grid.Add(self.dictChooser, 0, wx.EXPAND)
grid.Add(wx.StaticText(self, -1, _("Default encoding: ")),
0, wx.ALIGN_CENTER_VERTICAL)
self.encChooser = wx.ComboBox(self, 1108,
encodings.keys()[encodings.values().index(self.app.config.get('encoding'))],
wx.Point(-1, -1),
wx.Size(-1, -1), encodings.keys(),
wx.TE_READONLY)
grid.Add(self.encChooser, 0, wx.EXPAND | wx.ALIGN_RIGHT)
grid.AddGrowableCol(1)
grid.Add(wx.StaticText(self, -1, _("Default DICT server: ")),
0, wx.ALIGN_CENTER_VERTICAL)
self.serverEntry = wx.TextCtrl(self, -1,
self.app.config.get('dictServer'))
grid.Add(self.serverEntry, 0, wx.EXPAND)
grid.Add(wx.StaticText(self, -1, _("Default DICT server port: ")),
0, wx.ALIGN_CENTER_VERTICAL)
self.portEntry = wx.TextCtrl(self, -1,
self.app.config.get('dictServerPort'))
grid.Add(self.portEntry, 0, wx.EXPAND)
vboxMain.Add(grid, 0, wx.ALL | wx.EXPAND, 4)
#
# Pronunciation
#
panelPron = wx.Panel(self, -1)
sbSizerPron = wx.StaticBoxSizer(wx.StaticBox(panelPron, -1,
_("Pronunciation")),
wx.VERTICAL)
panelPron.SetSizer(sbSizerPron)
panelPron.SetAutoLayout(True)
sbSizerPron.Fit(panelPron)
vboxMain.Add(panelPron, 0, wx.ALL | wx.EXPAND, 5)
hboxPronCmd = wx.BoxSizer(wx.HORIZONTAL)
hboxPronCmd.Add(wx.StaticText(panelPron, -1, _("System Command: ")), 0,
wx.ALIGN_CENTER_VERTICAL)
self.entryPron = wx.TextCtrl(panelPron, -1,
self.app.config.get('pronunciationCommand') or \
PRON_COMMAND)
hboxPronCmd.Add(self.entryPron, 1, wx.EXPAND, 0)
self.buttonDefaultPron = wx.Button(panelPron, 1106, _("Default"))
hboxPronCmd.Add(self.buttonDefaultPron, 0, wx.ALL | wx.EXPAND)
sbSizerPron.Add(hboxPronCmd, 0, wx.ALL | wx.EXPAND, 4)
hboxPronWhat = wx.BoxSizer(wx.HORIZONTAL)
self.rbPronOrig = wx.RadioButton(panelPron, -1, _("Pronounce original word"))
hboxPronWhat.Add(self.rbPronOrig, 0, wx.ALL | wx.EXPAND, 3)
self.rbPronTrans = wx.RadioButton(panelPron, -1, _("Pronounce translation"))
if self.app.config.get('pronounceTrans') == 'True':
self.rbPronTrans.SetValue(True)
hboxPronWhat.Add(self.rbPronTrans, 0, wx.ALL | wx.EXPAND, 3)
sbSizerPron.Add(hboxPronWhat, 0, wx.ALL | wx.EXPAND, 0)
self.winSize = wx.CheckBox(self, 1101, _("Save window size on exit"))
self.winSize.SetValue(self.app.config.get('saveWindowSize') == 'True')
vboxMain.Add(self.winSize, 0, wx.ALL, 3)
self.winPos = wx.CheckBox(self, 1102, _("Save window position on exit"))
self.winPos.SetValue(self.app.config.get('saveWindowPos') == 'True')
vboxMain.Add(self.winPos, 0, wx.ALL, 3)
self.sashPos = wx.CheckBox(self, 1103, _("Save sash position on exit"))
self.sashPos.SetValue(self.app.config.get('saveSashPos') == 'True')
vboxMain.Add(self.sashPos, 0, wx.ALL, 3)
self.clipboard = wx.CheckBox(self, 1103,
_("Take words from the clipboard by default"))
self.clipboard.SetValue(self.app.config.get('useClipboard') == 'True')
vboxMain.Add(self.clipboard, 0, wx.ALL, 3)
vboxMain.Add(wx.StaticLine(self, -1), 0, wx.ALL | wx.EXPAND, 5)
self.buttonOK = wx.Button(self, 1104, _("OK"))
hboxButtons.Add(self.buttonOK, 0, wx.ALL | wx.EXPAND, 1)
self.buttonCancel = wx.Button(self, 1105, _("Cancel"))
hboxButtons.Add(self.buttonCancel, 0, wx.ALL | wx.EXPAND, 1)
vboxMain.Add(hboxButtons, 0, wx.ALL | wx.ALIGN_RIGHT, 4)
self.SetSizer(vboxMain)
self.Fit()
self.SetSize((400, -1))
wx.EVT_CHECKBOX(self, 1101, self.onSaveWinSizeClicked)
wx.EVT_CHECKBOX(self, 1102, self.onSaveWinPosClicked)
wx.EVT_CHECKBOX(self, 1103, self.onSaveSashPosClicked)
wx.EVT_BUTTON(self, 1106, self.onDefaultPron)
wx.EVT_BUTTON(self, 1104, self.onOK)
wx.EVT_BUTTON(self, 1105, self.onCancel)
def onSaveWinSizeClicked(self, event):
"""This method is invoked when checkbox for window size
is clicked"""
if event.Checked() == 1:
self.app.config.winSize = self.GetParent().GetSize()
self.app.config.saveWinSize = 1
else:
self.app.config.saveWinSize = 0
def onSaveWinPosClicked(self, event):
"""This method is invoked when checkbox for window position
is clicked"""
if event.Checked() == 1:
self.app.config.winPos = self.GetParent().GetPosition()
self.app.config.saveWinPos = 1
else:
self.app.config.saveWinPos = 0
def onSaveSashPosClicked(self, event):
"""This method is invoked when checkbox for sash position
is clicked"""
if event.Checked() == 1:
self.app.config.sashPos = self.GetParent().splitter.GetSashPosition()
self.app.config.saveSashPos = 1
else:
self.app.config.saveSashPos = 0
def onDefaultPron(self, event):
"""Set pronunciation command to default value"""
self.entryPron.SetValue(PRON_COMMAND)
def onOK(self, event):
"""Save configuration in the configuration object"""
self.app.config.set('defaultDict',
enc.fromWX(self.dictChooser.GetValue()))
self.app.config.set('encoding', encodings[self.encChooser.GetValue()])
if self.app.window.activeDictionary == None:
self.app.window.checkEncMenuItem(self.app.config.get('encoding'))
self.app.config.set('dictServer', self.serverEntry.GetValue())
self.app.config.set('dictServerPort', self.portEntry.GetValue())
self.app.config.set('pronunciationCommand', self.entryPron.GetValue())
self.app.config.set('pronounceTrans', str(self.rbPronTrans.GetValue()))
self.app.config.set('saveWindowSize', str(self.winSize.GetValue()))
self.app.config.set('saveWindowPos', str(self.winPos.GetValue()))
self.app.config.set('saveSashPos', str(self.sashPos.GetValue()))
self.app.config.set('useClipboard', str(self.clipboard.GetValue()))
frame = self.GetParent()
if self.app.config.get('saveWinSize'):
self.app.config.set('windowWidth', frame.GetSize()[0])
self.app.config.set('windowHeight', frame.GetSize()[1])
if self.app.config.get('saveWindowPos'):
self.app.config.set('windowPosX', frame.GetPosition()[0])
self.app.config.set('windowPosY', frame.GetPosition()[1])
if self.app.config.get('saveSashPos'):
if not frame.wordListHidden():
self.app.config.set('sashPos', frame.splitter.GetSashPosition())
self.app.config.save()
self.Destroy()
def onCancel(self, event):
"""Close dialog window discarding changes"""
self.Destroy()
opendict-0.6.3/lib/gui/registerwin.py 0000644 0001750 0001750 00000012447 10640522715 016247 0 ustar mjoc mjoc #
# OpenDict
# Copyright (c) 2003-2006 Martynas Jocius
# Copyright (c) 2007 IDILES SYSTEMS, UAB
#
# This program 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 2 of the License, or
# (at your opinion) any later version.
#
# This program is distributed in the hope that will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MECHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more detals.
#
# You shoud have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
# 02111-1307 USA
#
# Module: gui.registerwin
import wx
import os
from info import home, uhome
_ = wx.GetTranslation
class FileRegistryWindow(wx.Frame):
def __init__(self, parent, id, title, pos=wx.DefaultPosition,
size=wx.DefaultSize, style=wx.DEFAULT_FRAME_STYLE):
wx.Frame.__init__(self, parent, id, title, pos, size, style)
self.app = wx.GetApp()
vboxMain = wx.BoxSizer(wx.VERTICAL)
self.types = {}
self.types['dwa'] = "Slowo"
self.types['mova'] = "Mova"
self.types['tmx'] = "TMX"
self.types['dz'] = "DICT"
self.fileList = wx.ListBox(self, 190,
wx.Point(-1, -1),
wx.Size(-1, -1),
self.app.config.registers.keys(),
wx.LB_SINGLE | wx.SUNKEN_BORDER)
vboxMain.Add(self.fileList, 1, wx.ALL | wx.EXPAND, 1)
vboxInfo = wx.BoxSizer(wx.VERTICAL)
if len(self.app.config.registers.keys()) > 0:
self.fileList.SetSelection(0)
name = self.fileList.GetStringSelection()
item = self.app.config.registers[name]
else:
# There's no registered dictionaries
name = ""
item = []
item.extend(["", "", ""])
self.labelName = wx.StaticText(self, -1, _("Name: %s") % name)
vboxInfo.Add(self.labelName, 0, wx.ALL, 0)
self.labelPath = wx.StaticText(self, -1, _("Path: %s") % item[0])
vboxInfo.Add(self.labelPath, 0, wx.ALL, 0)
self.labelFormat = wx.StaticText(self, -1, _("Format: %s") % item[1])
vboxInfo.Add(self.labelFormat, 0, wx.ALL, 0)
self.labelEnc = wx.StaticText(self, -1, _("Encoding: %s") % item[2])
vboxInfo.Add(self.labelEnc, 0, wx.ALL, 0)
vboxMain.Add(vboxInfo, 0, wx.ALL | wx.EXPAND, 10)
hboxButtons = wx.BoxSizer(wx.HORIZONTAL)
self.buttonInstall = wx.Button(self, 191, _("Add new..."))
# FIXME: Needs to be rewritten
#hboxButtons.Add(self.buttonInstall, 1, wx.ALL | wx.EXPAND, 1)
self.buttonRemove = wx.Button(self, 192, _("Remove selected"))
hboxButtons.Add(self.buttonRemove, 1, wx.ALL | wx.EXPAND, 1)
self.buttonClose = wx.Button(self, 193, _("Close"))
hboxButtons.Add(self.buttonClose, 1, wx.ALL | wx.EXPAND, 1)
vboxMain.Add(hboxButtons, 0, wx.ALL | wx.EXPAND, 2)
self.SetSizer(vboxMain)
self.Fit()
wx.EVT_LISTBOX(self, 190, self.onFileSelected)
wx.EVT_BUTTON(self, 191, self.onInstall)
wx.EVT_BUTTON(self, 192, self.onRemove)
wx.EVT_BUTTON(self, 193, self.onClose)
def onFileSelected(self, event):
info = self.app.config.registers[event.GetString()]
self.labelName.SetLabel(_("Name: %s") % event.GetString())
self.labelPath.SetLabel(_("Path: %s") % info[0])
self.labelFormat.SetLabel(_("Format: %s") % self.types[info[1]])
self.labelEnc.SetLabel(_("Encoding: %s") % info[2])
def onInstall(self, event):
self.fileList.Append(self.app.window.onAddFromFile(None))
def onRemove(self, event):
self.app.window.onCloseDict(None)
pos = self.fileList.GetSelection()
item = self.fileList.GetStringSelection()
if item == "":
return
self.fileList.Delete(pos)
parent = self.GetParent()
parent.menuDict.Delete(parent.menuDict.FindItem(item))
if self.app.config.registers[item][1] != "Dict":
if os.path.exists(os.path.join(uhome, "register", item+".hash")):
try:
os.remove(os.path.join(uhome, "register", item+".hash"))
except:
self.app.window.SetStatusText(_("Error while deleting \"%s\"") \
% (item+".hash"))
return
elif os.path.exists(os.path.join(home, "register", item+".hash")):
try:
os.remove(os.path.join(home, "register", item+".hash"))
except:
self.app.window.SetStatusText(_("Error while deleting \"%s\"") \
% (item+".hash"))
return
del self.app.config.ids[item]
del self.app.config.registers[item]
for list in self.app.config.groups.values():
if item in list:
list.remove(item)
self.labelName.SetLabel(_("Name: %s") % "")
self.labelPath.SetLabel(_("Path: %s") % "")
self.labelFormat.SetLabel(_("Format: %s") % "")
self.labelEnc.SetLabel(_("Encoding: %s") % "")
def onClose(self, event):
self.Destroy()
opendict-0.6.3/lib/gui/dictconnwin.py 0000644 0001750 0001750 00000025061 10640522715 016220 0 ustar mjoc mjoc #
# OpenDict
# Copyright (c) 2003-2006 Martynas Jocius
# Copyright (c) 2007 IDILES SYSTEMS, UAB
#
# This program 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 2 of the License, or
# (at your opinion) any later version.
#
# This program is distributed in the hope that will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MECHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more detals.
#
# You shoud have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
# 02111-1307 USA
#
import wx
from wx.lib.rcsizer import RowColSizer
import traceback
from lib.logger import systemLog, debugLog, DEBUG, INFO, WARNING, ERROR
from lib.parser import DictConnection
from lib.extra import dictclient
from lib.threads import Process
from lib.gui import errorwin
from lib import misc
_ = wx.GetTranslation
CONNECTION_CHECK_INTERVAL = 400
class DictConnWindow(wx.Frame):
def __init__(self, parent, id, title, pos=wx.DefaultPosition,
size=wx.DefaultSize, style=wx.DEFAULT_FRAME_STYLE):
wx.Frame.__init__(self, parent, id, title, pos, size, style)
self.parent = parent
self.app = wx.GetApp()
vboxMain = wx.BoxSizer(wx.VERTICAL)
hboxButtons = wx.BoxSizer(wx.HORIZONTAL)
hboxServer = RowColSizer()
#
# Server address row
#
hboxServer.Add(wx.StaticText(self, -1, _("Server: ")),
flag=wx.ALIGN_RIGHT | wx.ALIGN_CENTER_VERTICAL,
row=0, col=0, border=1)
servers = ['dict.org', 'localhost']
self.entryServer = wx.ComboBox(self, -1,
self.app.config.get('dictServer'), wx.Point(-1, -1),
wx.Size(-1, -1), servers, wx.CB_DROPDOWN)
hboxServer.Add(self.entryServer, flag=wx.EXPAND, row=0, col=1, border=1)
hboxServer.Add(wx.Button(self, 1000, _("Default Server")),
flag=wx.EXPAND, row=0, col=2, border=5)
#
# Port entry row
#
hboxServer.Add(wx.StaticText(self, -1, _("Port: ")),
flag=wx.ALIGN_RIGHT | wx.ALIGN_CENTER_VERTICAL,
row=1, col=0, border=1)
hboxServer.Add(wx.Button(self, 1001, _("Default Port")),
flag=wx.EXPAND, row=1, col=2, border=5)
self.entryPort = wx.TextCtrl(self, -1,
self.app.config.get('dictServerPort'))
hboxServer.Add(self.entryPort, flag=wx.EXPAND, row=1, col=1, border=1)
#
# Database selection row
#
hboxServer.Add(wx.StaticText(self, -1, _("Database: ")),
flag=wx.ALIGN_RIGHT | wx.ALIGN_CENTER_VERTICAL,
row=2, col=0, border=1)
self.msgSearchInAll = _("Search in all databases")
self.choiceDB = wx.ComboBox(self, 1002, self.msgSearchInAll,
choices=[self.msgSearchInAll],
style=wx.TE_READONLY)
self.choiceDB.SetInsertionPoint(0)
hboxServer.Add(self.choiceDB, flag=wx.EXPAND, row=2, col=1, border=1)
hboxServer.Add(wx.Button(self, 1003, _("Fetch List")), #size=(-1, 18)),
flag=wx.EXPAND, row=2, col=2, border=1)
#
# Encoding selection row
#
hboxServer.Add(wx.StaticText(self, -1, _("Character encoding: ")),
flag=wx.ALIGN_RIGHT | wx.ALIGN_CENTER_VERTICAL,
row=3, col=0, border=1)
self.entryEncoding = wx.ComboBox(self, 1006,
misc.encodings.keys()[
misc.encodings.values().index(
self.app.config.get('dict-server-encoding'))],
wx.Point(-1, -1),
wx.Size(-1, -1), misc.encodings.keys(),
wx.CB_DROPDOWN | wx.CB_READONLY)
hboxServer.Add(self.entryEncoding, flag=wx.EXPAND, row=3, col=1, border=1)
#hboxServer.Add(wx.StaticText(self, -1, _("Strategy: ")),
# flag=wx.ALIGN_RIGHT | wx.ALIGN_CENTER_VERTICAL,
# row=3, col=0, rowspan=1, border=1)
#
#self.choiceStrat = wx.ComboBox(self, 1006, #size=(-1, 20),
# choices=[])
#hboxServer.Add(self.choiceStrat, flag=wx.EXPAND, row=3, col=1,
# rowspan=1, border=1)
#
#hboxServer.Add(wx.Button(self, 1007, _("Update")), #size=(-1, 18)),
# flag=wx.EXPAND, row=3, col=2, border=5)
hboxServer.AddGrowableCol(1)
vboxMain.Add(hboxServer, 1, wx.ALL | wx.EXPAND, 4)
self.buttonOK = wx.Button(self, 1004, _("Connect"))
hboxButtons.Add(self.buttonOK, 0, wx.ALL, 1)
self.buttonCancel = wx.Button(self, 1005, _("Cancel"))
hboxButtons.Add(self.buttonCancel, 0, wx.ALL, 1)
vboxMain.Add(hboxButtons, 0, wx.ALL | wx.ALIGN_CENTER, 2)
self.CreateStatusBar()
self.SetSizer(vboxMain)
self.Fit()
self.SetSize((500, -1))
self.timerUpdateDB = wx.Timer(self, 1006)
self.timerConnect = wx.Timer(self, 1007)
self.update = None
self.connection = None
wx.EVT_BUTTON(self, 1000, self.onDefaultServer)
wx.EVT_BUTTON(self, 1001, self.onDefaultPort)
wx.EVT_BUTTON(self, 1003, self.onUpdateDB)
wx.EVT_BUTTON(self, 1007, self.onUpdateStrats)
wx.EVT_BUTTON(self, 1004, self.onOK)
wx.EVT_BUTTON(self, 1005, self.onCancel)
wx.EVT_TIMER(self, 1006, self.onTimerUpdateDB)
wx.EVT_TIMER(self, 1007, self.onTimerConnect)
def onTimerUpdateDB(self, event):
systemLog(DEBUG, "DictConnection: [IDLE] Receiving DB list...")
if self.update != None:
if self.update.isDone():
systemLog(DEBUG, "DictConnection: DB list received")
obj = self.update()
if type(obj) == type({}):
self.timerUpdateDB.Stop()
self.update = None
self.choiceDB.Clear()
self.choiceDB.Append(self.msgSearchInAll)
for name in obj.values():
self.choiceDB.Append(name)
self.SetStatusText(_("Done"))
self.choiceDB.SetValue(self.msgSearchInAll)
self.choiceDB.SetInsertionPoint(0)
elif obj != None:
self.SetStatusText(_("Receiving database list..."))
self.update = Process(obj.getdbdescs)
else:
self.timerUpdateDB.Stop()
self.SetStatusText('')
title = _("Connection Error")
msg = _("Unable to connect to server")
errorwin.showErrorMessage(title, msg)
def onTimerConnect(self, event):
if self.connection != None:
if self.connection.isDone():
systemLog(INFO, "Connection timer stopped")
self.timerConnect.Stop()
self.conn = self.connection()
if self.conn == None:
self.SetStatusText('')
title = _("Connection Error")
msg = _("Unable to connect to server")
errorwin.showErrorMessage(title, msg)
else:
self.prepareForUsing()
def onDefaultServer(self, event):
self.entryServer.SetValue("dict.org")
def onDefaultPort(self, event):
self.entryPort.SetValue("2628")
def onUpdateDB(self, event):
self.SetStatusText(_("Connecting..."))
self.timerUpdateDB.Start(CONNECTION_CHECK_INTERVAL)
self.update = Process(dictclient.Connection,
self.entryServer.GetValue(),
int(self.entryPort.GetValue()))
# not used, remove
def onUpdateStrats(self, event):
conn = dictclient.Connection()
strats = conn.getstratdescs()
for name in strats.values():
self.choiceStrat.Append(name)
# Thread is not used there, because program don't hang if can't
# connect. Otherwise, it may hang for a second depending on the
# connection speed. TODO: better solution?
def onOK(self, event):
self.server = self.entryServer.GetValue()
self.app.config.set('dictServer', self.server)
self.port = self.entryPort.GetValue()
encName = self.entryEncoding.GetValue()
try:
enc = misc.encodings[encName]
except KeyError:
print 'Error: invalid encoding name "%s", defaulting to UTF-8' % \
encName
enc = 'UTF-8'
self.encoding = (enc, encName)
self.timerConnect.Stop()
self.timerUpdateDB.Stop()
self.SetStatusText(_("Connecting to %s...") % self.server)
self.timerConnect.Start(CONNECTION_CHECK_INTERVAL)
self.connection = Process(dictclient.Connection,
self.server, int(self.port))
def prepareForUsing(self):
"""Prepare MainWindow for displaying data"""
systemLog(INFO, "DictConnection: Connected, preparing main window...")
db = self.choiceDB.GetValue()
if self.choiceDB.FindString(db) == 0:
db = "*"
db_name = ""
else:
try:
dbs = self.conn.getdbdescs()
for d in dbs.keys():
if dbs[d] == db:
db = d
db_name = dbs[db]
except:
traceback.print_exc()
self.app.window.SetStatusText(misc.errors[4])
return
self.app.window.onCloseDict(None)
self.app.window.activeDictionary = DictConnection(self.server,
int(self.port),
db, "")
self.app.config.set('dict-server-encoding', self.encoding[0])
self.parent.changeEncoding(self.encoding[1])
if db_name != "":
title = "OpenDict - %s (%s)" % (self.server, db_name)
else:
title = "OpenDict - %s" % self.server
self.app.window.SetTitle(title)
self.app.window.checkEncMenuItem(self.encoding[0])
if not self.app.window.activeDictionary.getUsesWordList():
self.app.window.hideWordList()
self.app.window.SetStatusText("")
self.timerUpdateDB.Stop()
self.Destroy()
def onCancel(self, event):
self.timerUpdateDB.Stop()
self.timerConnect.Stop()
self.Destroy()
opendict-0.6.3/lib/gui/dictaddwin.py 0000644 0001750 0001750 00000006370 10640522715 016015 0 ustar mjoc mjoc # -*- coding: utf-8 -*-
# OpenDict
# Copyright (c) 2003-2006 Martynas Jocius
# Copyright (c) 2007 IDILES SYSTEMS, UAB
#
# This program 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 2 of the License, or
# (at your opinion) any later version.
#
# This program is distributed in the hope that will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MECHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more detals.
#
# You shoud have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
# 02111-1307 USA
#
# Module: gui.dictaddwin
import wx
from lib import misc
_ = wx.GetTranslation
# IDs range: 6300-6310
class DictAddWindow(wx.Dialog):
def __init__(self, parent, fname, filePath):
wx.Dialog.__init__(self, parent, -1,
_("Add new dictionary"), wx.DefaultPosition,
wx.DefaultSize, wx.DEFAULT_DIALOG_STYLE)
self.filePath = filePath
vboxMain = wx.BoxSizer(wx.VERTICAL)
msg1 = _("The file format of \"%s\" could not be \nrecognized by its" \
" extention. Please select one\nfrom the list:") % fname
label1 = wx.StaticText(self, -1, msg1)
vboxMain.Add(label1, 0, wx.ALL | wx.EXPAND, 5)
choices = [misc.dictFormats["zip"], # OpenDict plugin
_("\"%s\" dictionary format") % misc.dictFormats["dwa"],
_("\"%s\" dictionary format") % misc.dictFormats["mova"],
_("\"%s\" dictionary format") % misc.dictFormats["tmx"],
_("\"%s\" dictionary format") % misc.dictFormats["dz"]]
self.box = wx.ListBox(self, -1, wx.Point(-1, -1),
wx.Size(-1, -1), choices, wx.LB_SINGLE)
vboxMain.Add(self.box, 1, wx.ALL | wx.EXPAND, 3)
hboxButtons = wx.BoxSizer(wx.HORIZONTAL)
buttonOK = wx.Button(self, wx.ID_OK, _("OK"))
hboxButtons.Add(buttonOK, 0, wx.ALL, 1)
buttonCancel = wx.Button(self, 6302, _("Cancel"))
hboxButtons.Add(buttonCancel, 0, wx.ALL, 1)
vboxMain.Add(hboxButtons, 0, wx.ALL | wx.CENTER, 2)
self.SetSizer(vboxMain)
self.Fit()
wx.EVT_BUTTON(self, wx.ID_OK, self.onOK)
wx.EVT_BUTTON(self, 6302, self.onCancel)
def onOK(self, event):
parent = self.GetParent()
i = self.box.GetSelection()
ext = ""
if i == 0:
ext = "zip"
elif i == 1:
ext = "dwa"
elif i == 2:
ext = "mova"
elif i == 3:
ext = "tmx"
elif i == 4:
ext == "dz"
from installer import Installer
installer = Installer(parent, parent.app.config)
installer.install(self.filePath, ext)
self.Destroy()
def onCancel(self, event):
self.GetParent().dictType = None
self.Destroy()
opendict-0.6.3/lib/gui/dicteditorwin.py 0000644 0001750 0001750 00000051111 10640522715 016544 0 ustar mjoc mjoc #
# OpenDict
# Copyright (c) 2003-2006 Martynas Jocius
# Copyright (c) 2007 IDILES SYSTEMS, UAB
#
# This program 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 2 of the License, or
# (at your opinion) any later version.
#
# This program is distributed in the hope that will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MECHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more detals.
#
# You shoud have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
# 02111-1307 USA
#
# TODO: not usable yet, needs some work with encodings, gui, etc.
from wx.lib.rcsizer import RowColSizer
import wx
import os
import codecs
import traceback
from lib.logger import systemLog, debugLog, DEBUG, INFO, WARNING, ERROR
from lib.misc import encodings, printError
from lib.parser import TMXParser
from lib.gui import errorwin
from lib import info
from lib import dicteditor
from lib import enc
_ = wx.GetTranslation
class EditWordWindow(wx.Frame):
"""Word editor window"""
def __init__(self, word, parent, id, title, pos=wx.DefaultPosition,
size=wx.DefaultSize, style=wx.DEFAULT_FRAME_STYLE):
wx.Frame.__init__(self, parent, id, title, pos, size, style)
vboxMain = wx.BoxSizer(wx.VERTICAL)
hboxButtons = wx.BoxSizer(wx.HORIZONTAL)
self.boxInfo = RowColSizer()
self.boxInfo.Add(wx.StaticText(self, -1, _("Word: "), pos=(-1, -1)),
flag=wx.ALIGN_RIGHT | wx.ALIGN_CENTER_VERTICAL,
row=0, col=0, border=1)
self.entryWord = wx.TextCtrl(self, -1, word)
self.entryWord.Disable()
self.boxInfo.Add(self.entryWord, flag=wx.EXPAND,
row=0, col=1, border=1)
self.transLabels = {}
self.textEntries = {}
unit = parent.editor.getUnit(word)
if unit:
translations = unit.getTranslations()
for trans in translations:
comment = translations[trans]
if comment:
transcomm = u"%s // %s" % (trans, comment)
else:
transcomm = trans
transcomm = enc.toWX(transcomm)
self.onAddEmptyField(None)
entry = self.textEntries.get(max(self.textEntries.keys()))
if entry:
entry.SetValue(transcomm)
self.boxInfo.AddGrowableCol(1)
vboxMain.Add(self.boxInfo, 1, wx.ALL | wx.EXPAND, 2)
idAdd = wx.NewId()
self.buttonAdd = wx.Button(self, idAdd, _("Add translation field"))
vboxMain.Add(self.buttonAdd, 0, wx.ALL | wx.ALIGN_RIGHT, 2)
self.buttonOK = wx.Button(self, 6050, _("OK"))
hboxButtons.Add(self.buttonOK, 0, wx.ALL, 1)
self.buttonCancel = wx.Button(self, 6051, _("Cancel"))
hboxButtons.Add(self.buttonCancel, 0, wx.ALL, 1)
vboxMain.Add(hboxButtons, 0, wx.ALL | wx.ALIGN_RIGHT, 2)
self.SetSizer(vboxMain)
self.Fit()
self.SetSize((500, -1))
self.Bind(wx.EVT_BUTTON, self.onAddEmptyField, self.buttonAdd)
self.Bind(wx.EVT_BUTTON, self.onSave, self.buttonOK)
self.Bind(wx.EVT_BUTTON, self.onClose, self.buttonCancel)
def onAddEmptyField(self, event):
"""Add empty translation field"""
transLabel = wx.StaticText(self, -1, _("Translation #%d: ") \
% (len(self.textEntries)+1))
self.transLabels[len(self.transLabels)] = transLabel
self.boxInfo.Add(transLabel,
flag=wx.ALIGN_RIGHT | wx.ALIGN_CENTRE_VERTICAL,
row=len(self.transLabels), col=0, border=1)
text = wx.TextCtrl(self, -1,
"",
size=(100, -1))
self.textEntries[len(self.textEntries)] = text
self.boxInfo.Add(text, flag=wx.EXPAND,
row=len(self.textEntries),
col=1, border=1)
self.Fit()
self.SetSize((500, -1))
def onSave(self, event):
"""Apply changes"""
parent = self.GetParent()
word = enc.fromWX(self.entryWord.GetValue())
translations = []
for label in self.textEntries.values():
translations.append(enc.fromWX(label.GetValue()))
transcomm = {}
for translation in translations:
if not len(translation.strip()):
continue
chunks = translation.split('//', 1)
if len(chunks) == 2:
t = chunks[0]
c = chunks[1]
else:
t = chunks[0]
c = None
transcomm[t] = c
parent.editor.getUnit(word).setTranslations(transcomm)
parent.setChanged(True)
parent.checkAllButtons()
self.Destroy()
def onClose(self, event):
"""Close window withous saveing changes"""
self.Destroy()
# IDs range: 6000-6200
class DictEditorWindow(wx.Frame):
"""Built-in dictionary editor. This tool lets user create and
manage his own dictionaries in TMX format."""
class AddWordWindow(EditWordWindow):
"""Window for adding new word"""
def __init__(self, parent, id, title, pos=wx.DefaultPosition,
size=wx.DefaultSize, style=wx.DEFAULT_FRAME_STYLE):
EditWordWindow.__init__(self, '', parent, id, title, pos,
size, style)
self.entryWord.Enable(1)
self.onAddEmptyField(None)
def onSave(self, event):
"""Apply changes"""
parent = self.GetParent()
word = enc.fromWX(self.entryWord.GetValue())
translations = []
for label in self.textEntries.values():
translations.append(enc.fromWX(label.GetValue()))
transcomm = {}
for translation in translations:
if not len(translation.strip()):
continue
chunks = translation.split('//', 1)
if len(chunks) == 2:
t = chunks[0]
c = chunks[1]
else:
t = chunks[0]
c = None
transcomm[t] = c
unit = dicteditor.Translation()
unit.setWord(word)
unit.setTranslations(transcomm)
parent.editor.addUnit(unit)
parent.list.Append(enc.toWX(word))
parent.setChanged(True)
parent.checkAllButtons()
self.Destroy()
# IDs range: 6000-6003
class ConfirmExitWindow(wx.Dialog):
"""Save confirmation dialog"""
def __init__(self, parent, id, title, pos=wx.DefaultPosition,
size=wx.DefaultSize, style=wx.DEFAULT_DIALOG_STYLE):
wx.Dialog.__init__(self, parent, id, title, pos, size, style)
self.parent = self.GetParent()
vboxMain = wx.BoxSizer(wx.VERTICAL)
hboxButtons = wx.BoxSizer(wx.HORIZONTAL)
labelMsg = wx.StaticText(self, -1,
_("Dictionary \"%s\" has been changed") \
% parent.name)
vboxMain.Add(labelMsg, 1, wx.ALL | wx.EXPAND, 15)
buttonSave = wx.Button(self, 6000, _("Save"))
hboxButtons.Add(buttonSave, 0, wx.ALL | wx.EXPAND, 3)
buttonExit = wx.Button(self, 6001, _("Do not save"))
hboxButtons.Add(buttonExit, 0, wx.ALL | wx.EXPAND, 3)
buttonCancel = wx.Button(self, 6002, _("Cancel"))
hboxButtons.Add(buttonCancel, 0, wx.ALL | wx.EXPAND, 3)
vboxMain.Add(hboxButtons, 0, wx.ALL | wx.EXPAND, 2)
self.SetSizer(vboxMain)
self.Fit()
wx.EVT_BUTTON(self, 6000, self.onSave)
wx.EVT_BUTTON(self, 6001, self.onExitParent)
wx.EVT_BUTTON(self, 6002, self.onClose)
def onSave(self, event):
if self.parent.cAction == "save":
self.parent.onSave(None)
self.parent.Destroy()
elif self.parent.cAction == "open":
self.parent.onSave(None)
self.Hide()
self.parent.open()
elif self.parent.cAction == "close":
self.parent.onSave(None)
self.parent.Destroy()
def onExitParent(self, event):
if self.parent.cAction == "save" or self.parent.cAction == "close":
self.parent.Destroy()
elif self.parent.cAction == "open":
self.Hide()
self.parent.open()
self.Destroy()
def onClose(self, event):
self.Destroy()
# -------------------------------------------------------------
def __init__(self, parent, id, title, pos=wx.DefaultPosition,
size=wx.DefaultSize, style=wx.DEFAULT_FRAME_STYLE):
wx.Frame.__init__(self, parent, id, title, pos, size, style)
self.app = wx.GetApp()
self.CreateStatusBar()
self.priTitle = _("Dictionary editor")
self.savedOnce = False
self.changed = False
self.editor = dicteditor.Editor()
self.cAction = None
vboxMain = wx.BoxSizer(wx.VERTICAL)
vboxDict = wx.BoxSizer(wx.VERTICAL)
vboxList = wx.BoxSizer(wx.VERTICAL)
hboxDict = wx.BoxSizer(wx.HORIZONTAL)
vboxEditButtons = wx.BoxSizer(wx.VERTICAL)
hboxButtons = wx.BoxSizer(wx.HORIZONTAL)
# Control buttons
self.controlButtons = []
self.buttonAdd = wx.Button(self, 6000, _("Add"))
self.buttonAdd.SetToolTipString(_("Add word"))
self.controlButtons.append(self.buttonAdd)
self.buttonEdit = wx.Button(self, 6001, _("Edit"))
self.buttonEdit.SetToolTipString(_("Change translation"))
self.controlButtons.append(self.buttonEdit)
self.buttonRemove = wx.Button(self, 6002, _("Remove"))
self.buttonRemove.SetToolTipString(_("Remove selected word"))
self.controlButtons.append(self.buttonRemove)
self.buttonSort = wx.Button(self, 6004, _("Sort"))
self.buttonSort.SetToolTipString(_("Sort word list"))
self.controlButtons.append(self.buttonSort)
self.buttonSave = wx.Button(self, 6005, _("Save"))
self.buttonSave.SetToolTipString(_("Save words to file"))
self.controlButtons.append(self.buttonSave)
self.buttonSaveAs = wx.Button(self, 6006, _("Save As..."))
self.buttonSaveAs.SetToolTipString(_("Save with a different file name"))
self.controlButtons.append(self.buttonSaveAs)
for button in self.controlButtons:
button.Disable()
vboxEditButtons.Add(button, 0, wx.ALL | wx.EXPAND, 1)
panelList = wx.Panel(self, -1)
sbSizerList = wx.StaticBoxSizer(wx.StaticBox(panelList, -1,
_("Word List")),
wx.VERTICAL)
self.list = wx.ListBox(panelList, 6020,
wx.Point(-1, -1),
wx.Size(-1, -1),
[],
wx.LB_SINGLE | wx.SUNKEN_BORDER)
sbSizerList.Add(self.list, 1, wx.ALL | wx.EXPAND, 0)
panelList.SetSizer(sbSizerList)
panelList.SetAutoLayout(True)
sbSizerList.Fit(panelList)
hboxDict.Add(panelList, 1, wx.ALL | wx.EXPAND, 0)
hboxDict.Add(vboxEditButtons, 0, wx.ALL | wx.EXPAND, 5)
vboxDict.Add(hboxDict, 1, wx.ALL | wx.EXPAND, 0)
vboxMain.Add(vboxDict, 1, wx.ALL | wx.EXPAND, 10)
self.buttonNew = wx.Button(self, 6030, _("New..."))
self.buttonNew.SetToolTipString(_("Start new dictionary"))
hboxButtons.Add(self.buttonNew, 0, wx.ALL | wx.EXPAND, 1)
self.buttonOpen = wx.Button(self, 6031, _("Open..."))
self.buttonOpen.SetToolTipString(_("Open dictionary file"))
hboxButtons.Add(self.buttonOpen, 0, wx.ALL | wx.EXPAND, 1)
self.buttonClose = wx.Button(self, 6032, _("Close"))
self.buttonClose.SetToolTipString(_("Close editor window"))
hboxButtons.Add(self.buttonClose, 0, wx.ALL | wx.EXPAND, 1)
vboxMain.Add(hboxButtons, 0, wx.ALL | wx.ALIGN_RIGHT, 2)
self.SetIcon(wx.Icon(os.path.join(info.GLOBAL_HOME,
"pixmaps",
"icon-24x24.png"),
wx.BITMAP_TYPE_PNG))
self.SetSizer(vboxMain)
self.Bind(wx.EVT_LISTBOX, self.onWordSelected, self.list)
self.Bind(wx.EVT_BUTTON, self.onCreate, self.buttonNew)
wx.EVT_BUTTON(self, 6000, self.onAddWord)
wx.EVT_BUTTON(self, 6001, self.onEdit)
wx.EVT_BUTTON(self, 6002, self.onRemove)
wx.EVT_BUTTON(self, 6003, self.onSearch)
wx.EVT_BUTTON(self, 6004, self.onSort)
wx.EVT_BUTTON(self, 6005, self.onSave)
wx.EVT_BUTTON(self, 6006, self.onSaveAs)
wx.EVT_BUTTON(self, 6031, self.onOpen)
wx.EVT_BUTTON(self, 6032, self.onClose)
wx.EVT_CLOSE(self, self.onClose)
def onAddWord(self, event):
self.SetStatusText("")
window = self.AddWordWindow(self, -1, _("New Word"),
size=(-1, -1), pos=(-1, -1),
style=wx.DEFAULT_FRAME_STYLE)
window.CentreOnScreen()
window.Show(True)
def onEdit(self, event):
self.SetStatusText("")
word = self.list.GetStringSelection()
if word == "":
return
window = EditWordWindow(word, self, -1, _("Edit Word"),
size=(-1, -1),
style=wx.DEFAULT_FRAME_STYLE)
window.CentreOnScreen()
window.Show(True)
self.checkAllButtons()
def onRemove(self, event):
self.SetStatusText("")
word = self.list.GetStringSelection()
if word != "":
self.list.Delete(self.list.FindString(word))
self.editor.removeUnit(self.editor.getUnit(word))
self.setChanged(True)
self.checkAllButtons()
def onSearch(self, event):
self.SetStatusText("")
def onSort(self, event):
words = []
for unit in self.editor.getUnits():
words.append(unit.getWord())
if len(words) == 0:
self.SetStatusText(_("List is empty"))
return
words.sort()
self.list.Clear()
self.list.InsertItems(words, 0)
self.SetStatusText(_("List sorted"))
self.setChanged(True)
self.checkAllButtons()
def onSaveAs(self, event):
self.onSave(None)
def onSave(self, event):
self.SetStatusText("")
self.cAction = "save"
wildCard = "Slowo dictionaries (*.dwa)|*.dwa"
default = 'Untitled-dictionary.dwa'
if not self.savedOnce or not event:
dialog = wx.FileDialog(self,
wildcard=wildCard,
defaultFile=default,
message=_("Save file"),
style=wx.SAVE | wx.CHANGE_DIR)
if dialog.ShowModal() == wx.ID_OK:
self.filePath = dialog.GetPaths()[0]
else:
return
if os.path.isdir(self.filePath):
if self.filePath.endswith('..'):
self.filePath = self.filePath[:-2]
self.filePath += default
if not self.filePath.endswith('.dwa'):
self.filePath += '.dwa'
self.editor.save(self.filePath)
self.setChanged(False)
self.name = os.path.basename(self.filePath)
self.savedOnce = True
self.checkAllButtons()
self.SetStatusText(_("Dictionary saved"))
self.SetTitle("%s - %s" % (self.priTitle, self.name))
def onCreate(self, event):
self.editor = dicteditor.Editor()
self.list.Clear()
self.checkAllButtons()
self.savedOnce = False
self.name = _("Untitled")
self.SetStatusText("")
self.SetTitle("%s - %s" % (self.priTitle, self.name))
def checkAddButton(self):
"""Check for add button visibility"""
if not hasattr(self, 'editor'):
self.buttonAdd.Disable()
else:
self.buttonAdd.Enable(1)
def checkEditButton(self):
"""Check for edit button visibility"""
if self.list.GetSelection() == -1:
self.buttonEdit.Disable()
else:
self.buttonEdit.Enable(1)
def checkRemoveButton(self):
"""Check for remove button visibility"""
if self.list.GetSelection() == -1:
self.buttonRemove.Disable()
else:
self.buttonRemove.Enable(1)
def checkSortButton(self):
"""Check for sort button visibility"""
if not hasattr(self, 'editor'):
self.buttonSort.Disable()
elif len(self.editor.getUnits()) < 2:
self.buttonSort.Disable()
else:
self.buttonSort.Enable(1)
def checkSaveButton(self):
"""Check for save button visibility"""
if not hasattr(self, 'editor'):
self.buttonSave.Disable()
elif not self.changed:
self.buttonSave.Disable()
else:
self.buttonSave.Enable(1)
def checkAllButtons(self):
"""Check all buttons for visibility changes"""
self.checkAddButton()
self.checkEditButton()
self.checkRemoveButton()
self.checkSortButton()
self.checkSaveButton()
self.buttonSaveAs.Enable(True)
def onOpen(self, event):
if self.editor and self.changed:
window = self.ConfirmExitWindow(self,
-1,
_("Exit confirmation"))
self.cAction = "open"
window.CentreOnScreen()
window.Show(True)
else:
self.open()
self.savedOnce = True # no need to specify file name
def open(self):
wildCard = "Slowo dictionaries (*.dwa)|*.dwa"
dialog = wx.FileDialog(self, message=_("Choose dictionary file"),
wildcard=wildCard, style=wx.OPEN|wx.MULTIPLE)
if dialog.ShowModal() == wx.ID_OK:
name = os.path.split(dialog.GetPaths()[0])[1]
self.filePath = dialog.GetPaths()[0]
self.name = os.path.split(self.filePath)[1]
wx.BeginBusyCursor()
try:
self.editor.load(self.filePath)
except Exception, e:
wx.EndBusyCursor()
traceback.print_exc()
title = _("Open Failed")
msg = _("Unable to open dictionary (got message: %s)") % e
errorwin.showErrorMessage(title, msg)
return
self.SetTitle("%s - %s" % (self.priTitle, self.name))
self.list.Clear()
words = []
for unit in self.editor.getUnits():
words.append(enc.toWX(unit.getWord()))
words.sort()
self.list.InsertItems(words, 0)
self.checkAllButtons()
self.SetStatusText(_("Dictionary loaded"))
wx.EndBusyCursor()
def onWordSelected(self, event):
"""This method is invoked when list item is selected"""
self.checkAllButtons()
def onClose(self, event):
if self.changed:
self.cAction = "close"
window = self.ConfirmExitWindow(self, -1, _("Exit confirmation"))
window.CentreOnScreen()
window.Show(True)
else:
self.Destroy()
def setChanged(self, value):
"""Set changed=value"""
self.changed = value
def getChanged(self):
"""Get if changed"""
return self.changed
opendict-0.6.3/lib/gui/__init__.py 0000644 0001750 0001750 00000000000 10500772667 015432 0 ustar mjoc mjoc opendict-0.6.3/lib/parser.py 0000644 0001750 0001750 00000055462 10640522715 014421 0 ustar mjoc mjoc #
# OpenDict
# Copyright (c) 2003-2006 Martynas Jocius
# Copyright (c) 2007 IDILES SYSTEMS, UAB
#
# This program 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 2 of the License, or
# (at your opinion) any later version.
#
# This program is distributed in the hope that will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MECHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more detals.
#
# You shoud have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
# 02111-1307 USA
#
import time
import string
import re
import os
import traceback
import xml.parsers.expat
from lib.extra import dictclient
from lib.extra import dictdlib
from lib import info
from lib import misc
from lib import errortype
from lib import meta
from lib import plaindict
from lib.logger import systemLog, debugLog, DEBUG, INFO, WARNING, ERROR
WORD_BG = "#dde2f1" # Bright blue
DICT_BG = "#b4bedb"
class SlowoParser(plaindict.PlainDictionary):
"""
Built-in Slowo Parser
Parses file in Slowo format.
"""
def __init__(self, filePath):
"""Initialize"""
self.filePath = filePath
self.needsList = True
self.name = os.path.splitext(os.path.basename(filePath))[0]
# Additional information
self.encoding = None
self.checksum = None
self.index = None
self.configChanged = False
def start(self):
"""Open file handle"""
debugLog(DEBUG, "Opening file %s" % self.filePath)
self.fd = open(self.filePath)
def stop(self):
"""Close file handle"""
try:
debugLog(DEBUG, "Closing file %s" % self.filePath)
self.fd.close()
except:
pass
def setIndex(self, index):
"""Set index table"""
self.index = index
def getPath(self):
"""Return full file path"""
return self.filePath
def setChecksum(self, newSum, first=False):
"""Set checksum. Used after checksum change"""
if self.checksum == None:
self.configChanged = True
self.checksum = newSum
def getChecksum(self):
"""Return checksum"""
return self.checksum
def getType(self):
"""Return dictionary type"""
from lib import dicttype
return dicttype.SLOWO
def setName(self, name):
"""Set new name"""
self.name = name
def getName(self):
"""Return file name"""
return self.name
def setEncoding(self, encoding):
"""Set encoding"""
self.encoding = encoding
self.configChanged = True
def getEncoding(self):
"""Return encoding set for that dictionary"""
return self.encoding
def getUsesWordList(self):
"""Return True if uses word list, False otherwise"""
return self.needsList
def _appendTranslation(self, html, orig, trans):
"""Appends HTML strings to list"""
html.append("
")
html.append("
" % WORD_BG)
html.append("%s
" % orig)
html.append("
")
html.append("
%s
" % trans)
html.append("
")
def search(self, word):
"""Lookup word"""
_start = time.time()
word_lowered = word.lower()
encodedIndex = {}
for literal in self.index:
encodedIndex[literal.encode(self.getEncoding())] = \
self.index.get(literal)
#
# Seek to the beginning of the block
#
position = 0L
if word_lowered[:2] in encodedIndex.keys():
position = encodedIndex[word_lowered[:2]]
debugLog(DEBUG, "Index: %s->%d" % (word_lowered[:2], position))
debugLog(DEBUG, "SlowoParser: Seeking to %d" % position)
self.fd.seek(position)
html = []
html.append("")
html.append("" \
% str(self.getEncoding()))
html.append("")
found = False
words = []
result = meta.SearchResult()
# DEBUG
_linesRead = 0
for line in self.fd.xreadlines():
_linesRead += 1
line = line.strip()
try:
try:
orig, end = line.split('=', 1)
except ValueError, e:
systemLog(ERROR, '%s (line %s)' % (e, line))
orig = orig.strip()
chunks = end.split(';')
translation = ["
"]
for chunk in chunks:
comment = []
trans = chunk.split('//')
if len(trans) > 1:
comment = trans[1:]
trans = trans[:1]
trans = "".join(trans).strip()
comment = "".join(comment).strip()
if len(trans) and len(comment) != 0:
translation.append("
")
translation = "".join(translation)
except:
traceback.print_exc()
continue
if line.lower().startswith(word_lowered):
if not orig.lower().startswith(word_lowered):
break
if orig.lower() == word_lowered and not found:
found = True
self._appendTranslation(html, orig, translation)
words.append(orig)
if len(words) == 1:
suggestedWord = orig
suggestedTrans = translation
elif len(words):
break
debugLog(DEBUG, "%d lines scanned" % _linesRead)
if not found:
if words:
self._appendTranslation(html, suggestedWord, suggestedTrans)
else:
result.setError(errortype.NOT_FOUND)
html.append("")
try:
translation = "".join(html)
except:
result.setError(errortype.INVALID_ENCOFING)
translation = ""
result.setTranslation(translation)
result.setWordList(words)
debugLog(DEBUG, "SlowoParser: search took %f seconds" \
% (time.time() - _start))
return result
class MovaParser(plaindict.PlainDictionary):
"""
Built-in Mova Parser
Parses file in 'Mova' dictionary format and does
the search.
"""
def __init__(self, filePath):
"""Initialize"""
self.filePath = filePath
self.needsList = True
self.name = os.path.splitext(os.path.basename(filePath))[0]
# Additional variables
self.encoding = None
self.checksum = None
self.index = None
# If this is True when closing, the new configuration will be
# written to disk
self.configChanged = False
def start(self):
"""Open file handle"""
debugLog(DEBUG, "Opening file %s" % self.filePath)
self.fd = open(self.filePath)
def stop(self):
"""Close file handle"""
try:
debugLog(DEBUG, "Closing file %s" % self.filePath)
self.fd.close()
except:
pass
def setIndex(self, index):
"""Set index table"""
self.index = index
def getPath(self):
"""Return full file path"""
return self.filePath
def setChecksum(self, newSum, first=False):
"""Set checksum. Used after chekcsum change"""
if self.checksum == None:
self.configChanged = True
self.checksum = newSum
# If checksum is set not for the first time, remember to
# update configuration
#if not first:
# self.configChanged = True
def getChecksum(self):
"""Return checksum"""
return self.checksum
def getType(self):
"""Return dictionary type"""
from lib import dicttype
return dicttype.MOVA
def setName(self, name):
"""Set new name"""
self.name = name
def getName(self):
"""Return file name"""
return self.name
def setEncoding(self, encoding):
"""Set encoding"""
self.encoding = encoding
self.configChanged = True
def getEncoding(self):
"""Return encoding set for this dictionary"""
return self.encoding
def getUsesWordList(self):
"""Return True if uses word list, False otherwise"""
return self.needsList
def _appendTranslation(self, html, orig, trans):
"""Appends HTML strings to list"""
html.append("
")
html.append("
" % WORD_BG)
html.append("%s
" % orig)
html.append("
")
html.append("
%s
" % trans)
html.append("
")
def search(self, word):
"""Lookup word"""
_start = time.time()
word_lowered = word.lower()
encodedIndex = {}
for literal in self.index:
encodedIndex[literal.encode(self.getEncoding())] = \
self.index.get(literal)
#
# Seek to the beginning of the block
#
position = 0L
if word_lowered[:2] in encodedIndex.keys():
position = encodedIndex[word_lowered[:2]]
debugLog(DEBUG, "Index: %s->%d" % (word_lowered[:2], position))
debugLog(DEBUG, "MovaParser: Seeking to %d" % position)
self.fd.seek(position)
html = []
html.append("")
html.append("" \
% str(self.getEncoding()))
html.append("")
found = False
words = []
result = meta.SearchResult()
# DEBUG
_linesRead = 0
for line in self.fd.xreadlines():
_linesRead += 1
line = line.strip()
try:
orig, trans = line.split(" ", 1)
except:
continue
if line.lower().startswith(word_lowered):
if not orig.lower().startswith(word_lowered):
break
if orig.lower() == word_lowered and not found:
found = True
self._appendTranslation(html, orig, trans)
words.append(orig)
if len(words) == 1:
suggestedWord = orig
suggestedTrans = trans
elif len(words):
break
debugLog(DEBUG, "%d lines scanned" % _linesRead)
if not found:
if words:
self._appendTranslation(html, suggestedWord, suggestedTrans)
else:
result.setError(errortype.NOT_FOUND)
html.append("")
try:
translation = "".join(html)
except:
result.setError(errortype.INVALID_ENCOFING)
translation = ""
result.setTranslation(translation)
result.setWordList(words)
debugLog(DEBUG, "MovaParser: Search took %f seconds" \
% (time.time() - _start))
return result
# FIXME: Deprecated
class TMXParser(plaindict.PlainDictionary):
"""Built-in TMX parser.
Reads TMX files and does the search.
"""
def __init__(self, filePath):
systemLog(WARNING, "***")
systemLog(WARNING, "*** WARNING:")
systemLog(WARNING, "*** TMX implementation is fuzzy and should " \
"not be used yet!")
systemLog(WARNING, "***")
self.name = os.path.splitext(os.path.basename(filePath))[0]
self.needsList = True
self.encoding = None
self.mapping = {}
self.header = {}
self.trans = []
self.inSeg = 0
self.lang = ""
def start(self):
"""Allocate resources"""
parser = xml.parsers.expat.ParserCreate()
parser.StartElementHandler = self.startElement
parser.EndElementHandler = self.endElement
parser.CharacterDataHandler = self.charData
if file != "":
fd = open(file)
parser.Parse(fd.read(), 1)
fd.close()
def getType(self):
"""Return dictionary type"""
return dicttype.TMX
def setName(self, name):
"""Set new name"""
self.name = name
def getName(self):
"""Return file name"""
return self.name
def setEncoding(self, encoding):
"""Set encoding"""
self.encoding = encoding
def getEncoding(self):
"""Return encoding set for that dictionary"""
return wx.GetApp().config.encoding
def getUsesWordList(self):
"""Return True if uses word list, False otherwise"""
return self.needsList
def startElement(self, name, attrs):
"""Part of SAX parsing method"""
if name == "tu":
self.inTu = 1
elif name == "tuv":
self.inTuv = 1
self.lang = attrs["lang"]
elif name == "seg":
self.inSeg = 1
elif name == "header":
self.header["srclang"] = attrs["srclang"]
self.header["creationtool"] = attrs["creationtool"]
self.header["creationtoolversion"] = attrs["creationtoolversion"]
self.header["o-tmf"] = attrs["o-tmf"]
self.header["adminlang"] = attrs["adminlang"]
self.header["datatype"] = attrs["datatype"]
self.header["segtype"] = attrs["segtype"]
def endElement(self, name):
"""Part of SAX parsing method"""
if name == "tu":
self.inTu = 0
self.mapping.setdefault(self.orig, []).extend(self.trans)
self.trans = []
elif name == "tuv":
self.inTuv = 0
elif name == "seg":
self.inSeg = 0
def charData(self, data):
"""Part of SAX parsing method"""
if self.inSeg:
if self.lang == self.header["srclang"]:
self.orig = data
else:
self.trans.append(data)
def search(self, word):
"""Lookup word"""
errno = 0
result = "" \
"" \
""
#"" % (self.window.encoding,
# self.window.app.config.fontFace,
# self.window.app.config.fontSize)
keys = self.mapping.keys()
avail = []
found = False
word_lowered = word.lower()
for key in keys:
if key.lower().find(word_lowered) == 0:
avail.append(key)
if not found:
result += "%s " % key
result += "
"
result += " "*3+str(" "+" "*3).join(self.mapping[key])
result += "
"
found = True
result += ""
if len(avail) == 0:
errno = 1
return (result, avail, errno)
def makeHashTable(self):
pass
class DictParser(plaindict.PlainDictionary):
"""Built-in dictd dictionaries parser.
Reads dictd dictionaries and does the search.
"""
def __init__(self, filePath):
"""Initialize"""
self.filePath = filePath
self.needsList = True
self.name = os.path.splitext(os.path.splitext(os.path.basename(filePath))[0])[0]
self.encoding = 'UTF-8'
self.checksum = None
self.configChanged = False
self.dict = None
self.definitions = None
def start(self):
"""Allocate resources"""
name = os.path.splitext(os.path.splitext(\
os.path.basename(self.filePath))[0])[0]
indexFile = os.path.join(os.path.dirname(self.filePath),
name)
self.dict = dictdlib.DictDB(indexFile)
def stop(self):
"""Free resources"""
if self.dict:
del self.dict
def getPath(self):
"""Return full file path"""
return self.filePath
def getType(self):
"""Return dictionary type"""
from lib import dicttype
return dicttype.DICT
def setName(self, name):
"""Set new name"""
self.name = name
def getName(self):
"""Return file name"""
return self.name
def setEncoding(self, encoding):
"""Set encoding"""
self.encoding = encoding
def getEncoding(self):
"""Return encoding set for that dictionary"""
return self.encoding
def setChecksum(self, newSum):
"""Set checksum. Used after chekcsum change"""
if self.checksum == None:
self.configChanged = True
self.checksum = newSum
def getUsesWordList(self):
"""Return True if uses word list, False otherwise"""
return self.needsList
def _getTranslation(self, word):
"""Return word and translation code without formatting
full HTML document"""
translations = self.dict.getdef(word)
orig = None
translation = None
for source in translations:
chunks = source.split('\n')
map(string.strip, chunks)
orig = chunks[0]
pron = re.findall("\[(.*?)\]", orig)
if len(pron) > 0:
orig = "%s [%s]" % \
(orig.replace(" [%s]" % pron[0], ""), pron[0])
else:
orig = "%s" % orig
translation = ['
']
for c in chunks[1:]:
if len(c) > 0:
translation.append("
%s
" % c)
translation.append('
')
translation = "".join(translation)
links = re.findall("{(.*?)}", translation)
for link in links:
translation = translation.replace("{%s}" % link,
"%s" \
% (link, link))
return (orig, translation)
def search(self, word):
"""Lookup word"""
_start = time.time()
result = meta.SearchResult()
word_lowered = word.lower()
if self.definitions is None:
self.definitions = self.dict.getdeflist()
self.definitions.sort()
words = []
for definition in self.definitions:
if definition.lower().startswith(word_lowered):
words.append(definition)
html = []
html.append("")
html.append("" \
% str(self.getEncoding()))
html.append("")
(orig, translation) = self._getTranslation(word)
if not translation:
if len(words):
debugLog(DEBUG, "Retrying search...")
_word = words[0]
orig, translation = self._getTranslation(_word)
if not translation:
result.setError(errortype.NOT_FOUND)
else:
result.setError(errortype.NOT_FOUND)
translation = ""
html.append("
")
html.append("
" % WORD_BG)
html.append("%s
" % orig)
html.append("
")
html.append("
%s
" % translation)
html.append("
")
html.append("")
result.setTranslation("".join(html))
result.setWordList(words)
debugLog(DEBUG, "DictParser: Search took % f seconds" \
% (time.time() - _start))
return result
# TODO:
# 1. This is not a parser, move to another module
# 2. Add needed methods
#
class DictConnection(meta.Dictionary):
"""Built-in DICT client
Connects to a DICT server abd does the search.
"""
def __init__(self, server, port, db, strategy):
self.server = server
self.port = port
self.db = db
self.strategy = strategy
self.encoding = "UTF-8"
self.needsList = 0
self.name = 'Connection to DICT server'
def getUsesWordList(self):
"""Return True if uses word list, False otherwise"""
return self.needsList
def setName(self, name):
"""Set new name"""
self.name = name
def getName(self):
"""Return name"""
return self.name
def setEncoding(self, encoding):
"""Set encoding"""
self.encoding = encoding
def getEncoding(self):
"""Return encoding"""
return self.encoding
def search(self, word):
"""Lookup word"""
result = meta.SearchResult()
try:
conn = dictclient.Connection(self.server, self.port)
except:
result.setError(errortype.CONNECTION_ERROR)
return result
html = []
html.append("" \
"" \
"" % self.getEncoding())
found = False
try:
data = conn.define(self.db, word)
except:
data = []
for d in data:
found = True
html.append("
')
translation = ' '.join(source.split('\n')[:])
links = re.findall("{(.*?)}", translation)
for link in links:
translation = translation.replace("{%s}" % link,
"%s" % (link, link))
html.append("
%s
" % translation)
html.append("
")
html.append("")
result.setTranslation(''.join(html))
if not found:
result.setError(errortype.NOT_FOUND)
return result
opendict-0.6.3/lib/extra/ 0000755 0001750 0001750 00000000000 10654057460 013667 5 ustar mjoc mjoc opendict-0.6.3/lib/extra/html2text.py 0000644 0001750 0001750 00000007764 10500772667 016215 0 ustar mjoc mjoc """
html2text.py
convert an html doc to text
"""
# system libraries
import os, sys, string, time, getopt
import re
WIDTH = 80
def tag_replace (data,center,indent, use_ansi = 0):
data = re.sub ("\s+", " ", data)
data = re.sub ("(?s)", "", data)
data = string.replace (data, "\n", " ")
output = []
# modified 6/17/99 splits on all cases of "img" tags
# imgs = re.split ("(?s)()", data)
imgs = re.split ("(?si)()", data)
for img in imgs:
if string.lower(img[:4]) == "", "\n", data)
data = re.sub ("(?i)]*>", "\n" + "-"*50 + "\n", data)
data = re.sub ("(?i)
", "\n* ", data)
if use_ansi:
data = re.sub ("(?i)", "\n[32m", data)
else:
data = re.sub ("(?i)", "\n", data)
if use_ansi:
data = re.sub ("(?i)", "[0m\n", data)
else:
data = re.sub ("(?i)", "\n", data)
data = re.sub ("(?i)
", "\n
\n", data)
data = re.sub ("(?i)
", "\n
\n", data)
data = re.sub ("(?i)
", "\n
\n", data)
data = re.sub ("(?i)
", "\n
\n", data)
data = re.sub ("(?i)", "\n", data)
if use_ansi:
data = re.sub ("(?i)", "[1m", data)
data = re.sub ("(?i)", "[0m", data)
data = re.sub ("(?i)", "[2m", data)
data = re.sub ("(?i)", "[0m", data)
data = re.sub ("(?i)", "\n
\n[31m", data)
data = re.sub ("(?i)
", "[0m\n\n", data)
else:
data = re.sub ("(?i)", "\n
\n", data)
data = re.sub ("(?i)
", "\n\n", data)
data = re.sub ("(?i)
", "\n", data)
data = re.sub ("(?i)
]*>", "\n", data)
data = re.sub ("(?i)", "\n", data)
data = re.sub ("(?i)
]*>", "\t", data)
data = re.sub ("(?i)
]*>", "\t", data)
data = re.sub (" *\n", "\n", data)
lines = string.split (data, "\n")
output = []
for line in lines:
if line == "
":
indent = indent + 1
elif line == "
":
indent = indent - 1
if indent < 0: indent = 0
elif line == "
":
center = center + 1
elif line == "
":
center = center - 1
if center < 0: center = 0
else:
if center:
line = " "*indent + string.strip(line)
nline = re.sub("\[.*?m", "", line)
nline = re.sub ("<[^>]*>", "", nline)
c = WIDTH/2 - (len (nline) / 2)
output.append (" "*c + line)
else:
output.append (" "*indent + line)
data = string.join (output, "\n")
data = re.sub (" *\n", "\n", data)
data = re.sub ("\n\n\n*", "\n\n", data)
data = re.sub ("<[^>]*>", "", data)
return (data, center, indent)
def html2text (data, use_ansi = 0, is_latin1 = 0):
pre = re.split("(?s)(
[^<]*
)", data)
out = []
indent = 0
center = 0
for part in pre:
if part[:5] != "
":
(res, center, indent) = tag_replace (part,center,indent, use_ansi)
out.append (res)
else:
part = re.sub("(?i)*pre>", "", part)
out.append (part)
data = string.join (out)
data = re.sub (">", ">", data)
data = re.sub ("<", "<", data)
data = re.sub (" ", " ", data)
return data
def usage(progname):
print "usage: %s --help " % progname
print __doc__
def main(argc, argv):
progname = argv[0]
alist, args = getopt.getopt(argv[1:], "", ["help"])
for (field, val) in alist:
if field == "--help":
usage(progname)
return
if len(args):
file = args[0]
else:
return
progname = argv[0]
fp = open (file)
data = fp.read()
fp.close()
if data:
print (html2text(data))
else:
print "Document contained no data"
if __name__ == "__main__":
main(len(sys.argv), sys.argv)
opendict-0.6.3/lib/extra/dictclient.py 0000644 0001750 0001750 00000030111 10500772667 016362 0 ustar mjoc mjoc # Client for the DICT protocol (RFC2229)
#
# Copyright (C) 2002 John Goerzen
#
# This program 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 2 of the License, or
# (at your option) any later version.
#
# This program 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.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
import socket, re
version = '1.0'
def dequote(str):
"""Will remove single or double quotes from the start and end of a string
and return the result."""
quotechars = "'\""
while len(str) and str[0] in quotechars:
str = str[1:]
while len(str) and str[-1] in quotechars:
str = str[0:-1]
return str
def enquote(str):
"""This function will put a string in double quotes, properly
escaping any existing double quotes with a backslash. It will
return the result."""
return '"' + str.replace('"', "\\\"") + '"'
class Connection:
"""This class is used to establish a connection to a database server.
You will usually use this as the first call into the dictclient library.
Instantiating it takes two optional arguments: a hostname (a string)
and a port (an int). The hostname defaults to localhost
and the port to 2628, the port specified in RFC."""
def __init__(self, hostname = 'localhost', port = 2628):
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock.connect((hostname, port))
self.rfile = self.sock.makefile("rt")
self.wfile = self.sock.makefile("wt", 0)
self.saveconnectioninfo()
def getresultcode(self):
"""Generic function to get a result code. It will return a list
consisting of two items: the integer result code and the text
following. You will not usually use this function directly."""
line = self.rfile.readline().strip()
code, text = line.split(' ', 1)
return [int(code), text]
def get200result(self):
"""Used when expecting a single line of text -- a 200-class
result. Returns [intcode, remaindertext]"""
code, text = self.getresultcode()
if code < 200 or code >= 300:
raise Exception, "Got '%s' when 200-class response expected" % \
line
return [code, text]
def get100block(self):
"""Used when expecting multiple lines of text -- gets the block
part only. Does not get any codes or anything! Returns a string."""
data = []
while 1:
line = self.rfile.readline().strip()
if line == '.':
break
data.append(line)
return "\n".join(data)
def get100result(self):
"""Used when expecting multiple lines of text, terminated by a period
and a 200 code. Returns: [initialcode, [bodytext_1lineperentry],
finalcode]"""
code, text = self.getresultcode()
if code < 100 or code >= 200:
raise Exception, "Got '%s' when 100-class response expected" % \
code
bodylines = self.get100block().split("\n")
code2 = self.get200result()[0]
return [code, bodylines, code2]
def get100dict(self):
"""Used when expecting a dictionary of results. Will read from
the initial 100 code, to a period and the 200 code."""
dict = {}
for line in self.get100result()[1]:
key, val = line.split(' ', 1)
dict[key] = dequote(val)
return dict
def saveconnectioninfo(self):
"""Called by __init__ to handle the initial connection. Will
save off the capabilities and messageid."""
code, string = self.get200result()
assert code == 220
capstr, msgid = re.search('<(.*)> (<.*>)$', string).groups()
self.capabilities = capstr.split('.')
self.messageid = msgid
def getcapabilities(self):
"""Returns a list of the capabilities advertised by the server."""
return self.capabilities
def getmessageid(self):
"""Returns the message id, including angle brackets."""
return self.messageid
def getdbdescs(self):
"""Gets a dict of available databases. The key is the db name
and the value is the db description. This command may generate
network traffic!"""
if hasattr(self, 'dbdescs'):
return self.dbdescs
self.sendcommand("SHOW DB")
self.dbdescs = self.get100dict()
return self.dbdescs
def getstratdescs(self):
"""Gets a dict of available strategies. The key is the strat
name and the value is the strat description. This call may
generate network traffic!"""
if hasattr(self, 'stratdescs'):
return self.stratdescs
self.sendcommand("SHOW STRAT")
self.stratdescs = self.get100dict()
return self.stratdescs
def getdbobj(self, dbname):
"""Gets a Database object corresponding to the database name passed
in. This function explicitly will *not* generate network traffic.
If you have not yet run getdbdescs(), it will fail."""
if not hasattr(self, 'dbobjs'):
self.dbobjs = {}
if self.dbobjs.has_key(dbname):
return self.dbobjs[dbname]
# We use self.dbdescs explicitly since we don't want to
# generate net traffic with this request!
if dbname != '*' and dbname != '!' and \
not dbname in self.dbdescs.keys():
raise Exception, "Invalid database name '%s'" % dbname
self.dbobjs[dbname] = Database(self, dbname)
return self.dbobjs[dbname]
def sendcommand(self, command):
"""Takes a command, without a newline character, and sends it to
the server."""
self.wfile.write(command + "\n")
def define(self, database, word):
"""Returns a list of Definition objects for each matching
definition. Parameters are the database name and the word
to look up. This is one of the main functions you will use
to interact with the server. Returns a list of Definition
objects. If there are no matches, an empty list is returned.
Note: database may be '*' which means to search all databases,
or '!' which means to return matches from the first database that
has a match."""
self.getdbdescs() # Prime the cache
if database != '*' and database != '!' and \
not database in self.getdbdescs():
raise Exception, "Invalid database '%s' specified" % database
self.sendcommand("DEFINE " + enquote(database) + " " + enquote(word))
code = self.getresultcode()[0]
retval = []
if code == 552:
# No definitions.
return []
if code != 150:
raise Exception, "Unknown code %d" % code
while 1:
code, text = self.getresultcode()
if code != 151:
break
resultword, resultdb = re.search('^"(.+)" (\S+)', text).groups()
defstr = self.get100block()
retval.append(Definition(self, self.getdbobj(resultdb),
resultword, defstr))
return retval
def match(self, database, strategy, word):
"""Gets matches for a query. Arguments are database name,
the strategy (see available ones in getstratdescs()), and the
pattern/word to look for. Returns a list of Definition objects.
If there is no match, an empty list is returned.
Note: database may be '*' which means to search all databases,
or '!' which means to return matches from the first database that
has a match."""
self.getstratdescs() # Prime the cache
self.getdbdescs() # Prime the cache
if not strategy in self.getstratdescs().keys():
raise Exception, "Invalid strategy '%s'" % strategy
if database != '*' and database != '!' and \
not database in self.getdbdescs().keys():
raise Exception, "Invalid database name '%s'" % database
self.sendcommand("MATCH %s %s %s" % (enquote(database),
enquote(strategy),
enquote(word)))
code = self.getresultcode()[0]
if code == 552:
# No Matches
return []
if code != 152:
raise Exception, "Unexpected code %d" % code
retval = []
for matchline in self.get100block().split("\n"):
matchdict, matchword = matchline.split(" ", 1)
retval.append(Definition(self, self.getdbobj(matchdict),
dequote(matchword)))
if self.getresultcode()[0] != 250:
raise Exception, "Unexpected end-of-list code %d" % code
return retval
class Database:
"""An object corresponding to a particular database in a server."""
def __init__(self, dictconn, dbname):
"""Initialize the object -- requires a Connection object and
a database name."""
self.conn = dictconn
self.name = dbname
def getname(self):
"""Returns the short name for this database."""
return self.name
def getdescription(self):
if hasattr(self, 'description'):
return self.description
if self.getname() == '*':
self.description = 'All Databases'
elif self.getname() == '!':
self.description = 'First matching database'
else:
self.description = self.conn.getdbdescs()[self.getname()]
return self.description
def getinfo(self):
"""Returns a string of info describing this database."""
if hasattr(self, 'info'):
return self.info
if self.getname() == '*':
self.info = "This special database will search all databases on the system."
elif self.getname() == '!':
self.info = "This special database will return matches from the first matching database."
else:
self.conn.sendcommand("SHOW INFO " + self.name)
self.info = "\n".join(self.conn.get100result()[1])
return self.info
def define(self, word):
"""Get a definition from within this database.
The argument, word, is the word to look up. The return value is the
same as from Connection.define()."""
return self.conn.define(self.getname(), word)
def match(self, strategy, word):
"""Get a match from within this database.
The argument, word, is the word to look up. The return value is
the same as from Connection.define()."""
return self.conn.match(self.getname(), strategy, word)
class Definition:
"""An object corresponding to a single definition."""
def __init__(self, dictconn, db, word, defstr = None):
"""Instantiate the object. Requires: a Connection object,
a Database object (NOT corresponding to '*' or '!' databases),
a word. Optional: a definition string. If not supplied,
it will be fetched if/when it is requested."""
self.conn = dictconn
self.db = db
self.word = word
self.defstr = defstr
def getdb(self):
"""Get the Database object corresponding to this definition."""
return self.db
def getdefstr(self):
"""Get the definition string (the actual content) of this
definition."""
if not self.defstr:
self.defstr = self.conn.define(self.getdb().getname(), self.word)[0].getdefstr()
return self.defstr
def getword(self):
"""Get the word this object describes."""
return self.word
opendict-0.6.3/lib/extra/dictdlib.py 0000644 0001750 0001750 00000033427 10500772667 016033 0 ustar mjoc mjoc # Dictionary creation library
# Copyright (C) 2002 John Goerzen
#
#
# This program 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 2 of the License, or
# (at your option) any later version.
#
# This program 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.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
import sys, string, gzip, os
b64_list = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
url_headword = "00-database-url"
short_headword = "00-database-short"
info_headword = "00-database-info"
def b64_encode(val):
"""Takes as input an integer val and returns a string of it encoded
with the base64 algorithm used by dict indexes."""
startfound = 0
retval = ""
for i in range(5, -1, -1):
thispart = (val >> (6 * i)) & ((2 ** 6) - 1)
if (not startfound) and (not thispart):
# Both zero -- keep going.
continue
startfound = 1
retval += b64_list[thispart]
if len(retval):
return retval
else:
return b64_list[0]
def b64_decode(str):
"""Takes as input a string and returns an integer value of it decoded
with the base64 algorithm used by dict indexes."""
if not len(str):
return 0
retval = 0
shiftval = 0
for i in range(len(str) - 1, -1, -1):
val = b64_list.index(str[i])
retval = retval | (val << shiftval)
shiftval += 6
return retval
validdict = {}
for x in string.ascii_letters + string.digits + " \t":
validdict[x] = 1
def sortnormalize(x):
"""Returns a value such that x is mapped to a format that sorts properly
with standard comparison."""
x2 = ''
for i in range(len(x)):
if validdict.has_key(x[i]):
x2 += x[i]
return x2.upper() + "\0" + x.upper()
def sortfunc(x, y):
"""Emulate sort -df."""
xl = x.split("\0")
yl = y.split("\0")
ret = cmp(xl[0], yl[0])
if ret != 0:
return ret
return cmp(xl[1], yl[1])
class DictDB:
def __init__(self, basename, mode = 'read', quiet = 0):
#, url = 'unknown', shortname = 'unknown',
# longinfo = 'unknown', quiet = 0):
"""Initialize a DictDB object.
Mode must be one of:
read -- read-only access
write -- write-only access, truncates existing files, does not work
with .dz. dict created if nonexistant.
update -- read/write access, dict created if nonexistant. Does not
work with .dz.
Read can read dict or dict.dz files. Write and update will NOT work
with dict.dz files.
If quiet is nonzero, status messages
will be suppressed."""
self.mode = mode
self.quiet = quiet
self.indexentries = {}
self.count = 0
self.basename = basename
self.indexfilename = self.basename + ".index"
if os.path.isfile(self.basename + ".dict.dz"):
self.dictfilename = self.basename + ".dict.dz"
self.usecompression = 1
else:
self.dictfilename = self.basename + ".dict"
self.usecompression = 0
if mode == 'read':
self.indexfile = open(self.indexfilename, "rt")
if self.usecompression:
self.dictfile = gzip.GzipFile(self.dictfilename, "rb")
else:
self.dictfile = open(self.dictfilename, "rb")
self._initindex()
elif mode == 'write':
self.indexfile = open(self.indexfilename, "wt")
if self.usecompression:
raise ValueError, "'write' mode incompatible with .dz files"
else:
self.dictfile = open(self.dictfilename, "wb")
elif mode == 'update':
try:
self.indexfile = open(self.indexfilename, "r+b")
except IOError:
self.indexfile = open(self.indexfilename, "w+b")
if self.usecompression:
# Open it read-only since we don't support mods.
self.dictfile = gzip.GzipFile(self.dictfilename, "rb")
else:
try:
self.dictfile = open(self.dictfilename, "r+b")
except IOError:
self.dictfile = open(self.dictfilename, "w+b")
self._initindex()
else:
raise ValueError, "mode must be 'read', 'write', or 'update'"
#self.writeentry(url_headword + "\n " + url, [url_headword])
#self.writeentry(short_headword + "\n " + shortname,
# [short_headword])
#self.writeentry(info_headword + "\n" + longinfo, [info_headword])
def _initindex(self):
"""Load the entire index off disk into memory."""
self.indexfile.seek(0)
for line in self.indexfile.xreadlines():
splits = line.rstrip().split("\t")
if not self.indexentries.has_key(splits[0]):
self.indexentries[splits[0]] = []
self.indexentries[splits[0]].append([b64_decode(splits[1]),
b64_decode(splits[2])])
def addindexentry(self, word, start, size):
"""Adds an entry to the index. word is the relevant word.
start is the starting position in the dictionary and size is the
size of the definition; both are integers."""
if not self.indexentries.has_key(word):
self.indexentries[word] = []
self.indexentries[word].append([start, size])
def delindexentry(self, word, start = None, size = None):
"""Removes an entry from the index; word is the word to search for.
start and size are optional. If they are specified, only index
entries matching the specified values will be removed.
For instance, if word is "foo" and start and size are not specified,
all index entries for the word foo will be removed. If start and size
are specified, only those entries matching all criteria will be
removed.
This function does not actually remove the data from the .dict file.
Therefore, information removed by this function will still
exist on-disk in the .dict file, but the dict server will just
not "see" it -- there will be no way to get to it anymore.
Returns a count of the deleted entries."""
if not self.indexentries.has_key(word):
return 0
retval = 0
entrylist = self.indexentries[word]
for i in range(len(entrylist) - 1, -1, -1):
# Go backwords so the del doesn't effect the index.
if (start == None or start == entrylist[i][0]) and \
(size == None or size == entrylist[i][1]):
del(entrylist[i])
retval += 1
if len(entrylist) == 0: # If we emptied it, del it completely
del(self.indexentries[word])
return retval
def update(self, string):
"""Writes string out, if not quiet."""
if not self.quiet:
sys.stdout.write(string)
sys.stdout.flush()
def seturl(self, url):
"""Sets the URL attribute of this database. If there was
already a URL specified, we will use delindexentry() on it
first."""
self.delindexentry(url_headword)
self.addentry(url_headword + "\n " + url, [url_headword])
def setshortname(self, shortname):
"""Sets the shortname for this database. If there was already
a shortname specified, we will use delindexentry() on it first."""
self.delindexentry(short_headword)
self.addentry(short_headword + "\n " + shortname,
[short_headword])
def setlonginfo(self, longinfo):
"""Sets the extended information for this database. If there was
already long info specified, we will use delindexentry() on it
first."""
self.delindexentry(info_headword)
self.addentry(info_headword + "\n" + longinfo, [info_headword])
def addentry(self, defstr, headwords):
"""Writes an entry. defstr holds the content of the definition.
headwords is a list specifying one or more words under which this
definition should be indexed. This function always adds \\n
to the end of defstr."""
self.dictfile.seek(0, 2) # Seek to end of file
start = self.dictfile.tell()
defstr += "\n"
self.dictfile.write(defstr)
for word in headwords:
self.addindexentry(word, start, len(defstr))
self.count += 1
if self.count % 1000 == 0:
self.update("Processed %d records\r" % self.count)
def finish(self, dosort = 1):
"""Called to finish the writing process.
**REQUIRED IF OPENED WITH 'update' OR 'write' MODES**.
This will write the index and close the files.
dosort is optional and defaults to true. If set to false,
dictlib will not sort the index file. In this case, you
MUST manually sort it through "sort -df" before it can be used."""
self.update("Processed %d records.\n" % self.count)
if dosort:
self.update("Sorting index: converting")
indexlist = []
for word, defs in self.indexentries.items():
for thisdef in defs:
indexlist.append("%s\t%s\t%s" % (word,
b64_encode(thisdef[0]),
b64_encode(thisdef[1])))
self.update(" mapping")
sortmap = {}
for entry in indexlist:
norm = sortnormalize(entry)
if sortmap.has_key(norm):
sortmap[norm].append(entry)
sortmap[norm].sort(sortfunc)
else:
sortmap[norm] = [entry]
self.update(" listing")
normalizedentries = sortmap.keys()
self.update(" sorting")
normalizedentries.sort()
self.update(" re-mapping")
indexlist = []
for normentry in normalizedentries:
for entry in sortmap[normentry]:
indexlist.append(entry)
self.update(", done.\n")
self.update("Writing index...\n")
self.indexfile.seek(0)
for entry in indexlist:
self.indexfile.write(entry + "\n")
if self.mode == 'update':
# In case things were deleted
self.indexfile.truncate()
self.indexfile.close()
self.dictfile.close()
self.update("Complete.\n")
def getdeflist(self):
"""Returns a list of strings naming all definitions contained
in this dictionary."""
return self.indexentries.keys()
def hasdef(self, word):
return self.indexentries.has_key(word)
def getdef(self, word):
"""Given a definition name, returns a list of strings with all
matching definitions. This is an *exact* match, not a
case-insensitive one. Returns [] if word is not in the dictionary."""
retval = []
if not self.hasdef(word):
return retval
for start, length in self.indexentries[word]:
self.dictfile.seek(start)
retval.append(self.dictfile.read(length))
return retval
class DictReader:
"""This object provides compatibility with earlier versions
of dictdlib. It is now deprecated."""
def __init__(self, basename):
"""Initialize a DictReader object. Provide it with the basename."""
self.dictdb = DictDB(basename, 'read')
def getdeflist(self):
"""Returns a list of strings naming all definitions contained
in this dictionary."""
return self.dictdb.getdeflist()
def getdef(self, defname):
"""Given a definition name, returns a list of strings
with all matching definitions."""
return self.dictdb.getdef(defname)
class DictWriter:
"""This object provides compatibility with earlier versions
of dictdlib. It is now deprecated."""
def __init__(self, basename, url = 'unknown', shortname = 'unknown',
longinfo = 'unknown', quiet = 0):
"""Initialize a DictWriter object. Will create 'basename.dict' and
'basename.index' files. url, shortname, and longinfo specify the
respective attributes of the database. If quiet is 1,
status messages are not printed."""
self.dictdb = DictDB(basename, 'write', quiet)
self.dictdb.seturl(url)
self.dictdb.setshortname(shortname)
self.dictdb.setlonginfo(longinfo)
def writeentry(self, defstr, headwords):
"""Writes an entry. defstr holds the content of the definition.
headwords is a list specifying one or more words under which this
definition should be indexed. This function always adds \\n
to the end of defstr."""
self.dictdb.addentry(defstr, headwords)
def finish(self, dosort = 1):
"""Called to finish the writing process. **REQUIRED**.
This will write the index and close the files.
dosort is optional and defaults to true. If set to false,
dictlib will not sort the index file. In this case, you
MUST manually sort it through "sort -df" before it can be used."""
self.dictdb.finish(dosort)
opendict-0.6.3/lib/extra/__init__.py 0000644 0001750 0001750 00000000000 10500772667 015771 0 ustar mjoc mjoc opendict-0.6.3/lib/tests/ 0000755 0001750 0001750 00000000000 10654057460 013706 5 ustar mjoc mjoc opendict-0.6.3/lib/tests/data/ 0000755 0001750 0001750 00000000000 10654057460 014617 5 ustar mjoc mjoc opendict-0.6.3/lib/tests/data/sampleplugin/ 0000755 0001750 0001750 00000000000 10654057460 017317 5 ustar mjoc mjoc opendict-0.6.3/lib/tests/data/sampleplugin/sample.py 0000644 0001750 0001750 00000003605 10500772667 021161 0 ustar mjoc mjoc #
# OpenDict
# Copyright (c) 2005 Martynas Jocius
#
# This program 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 2 of the License, or
# (at your opinion) any later version.
#
# This program is distributed in the hope that will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MECHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more detals.
#
# You shoud have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
# 02111-1307 USA
#
"""
Sample OpenDict plugin (new type)
"""
import string
import sys
def init(libraryPath):
"""This is required method for all plugins. The one and only
parameter gives OpenDict library path for requred imports. This
method returns plugin instance."""
sys.path.insert(0, libraryPath)
return SampleDictionary()
class SampleDictionary:
"""Sample dictionary"""
def __init__(self):
"""Import and save needed modules"""
from lib import errortype, meta
self.errorModule = errortype
self.metaModule = meta
def search(self, word):
"""Look up word"""
trans = []
words = []
trans.append("")
for i in range(10):
trans.append("Do you want to know what
%s
is žžčėčęė? So do I!" \
% word)
for i in range(20):
words.append("ž"+str(i)*5)
trans.append("")
result = self.metaModule.SearchResult()
result.status = self.errorModule.OK
result.translation = "".join(trans)
result.words = words
return result
opendict-0.6.3/lib/tests/data/sampleplugin/plugin.xml 0000644 0001750 0001750 00000001340 10500772667 021340 0 ustar mjoc mjoc
Unicode plugin (ąčęėįšųū„“\ž)0.1sample.pyUTF-8True0.5.82.3
This plugin only demonstrates new type OpenDict plugin facilities. And
Unicode support too: ąčęėįšųū„“\ž.
opendict-0.6.3/lib/tests/data/sampledict.dwa 0000644 0001750 0001750 00000000270 10500772667 017443 0 ustar mjoc mjoc vienas = one ;
du = two // two pieces ;
trys = three // not 'tree' ;
keturi = four // not 'for' ;
žirafa = giraphe // from africa ;
miškas= forest ; wood;
ąžuolas=oak // oak wood;
opendict-0.6.3/lib/tests/data/plugin.xml 0000644 0001750 0001750 00000001214 10500772667 016640 0 ustar mjoc mjoc
Sample plugin name ąčę1.2.3mymodule.pyUTF-8True0.5.82.3This is short or long description ąčę.
opendict-0.6.3/lib/tests/test_editor.py 0000644 0001750 0001750 00000006702 10636242135 016605 0 ustar mjoc mjoc #
# OpenDict
# Copyright (c) 2003-2006 Martynas Jocius
# Copyright (c) 2007 IDILES SYSTEMS, UAB
#
# Unit Test for editor.py
#
"""
Unit tests for editor.py
"""
import unittest
import os
import sys
sys.path.append('..')
import dicteditor
class TestTranslation(unittest.TestCase):
"""Translation test"""
translations = dicteditor.Translation()
def test_word(self):
"""Set/Get word should return correct value"""
self.translations.setWord('test')
self.assertEquals(self.translations.getWord(), 'test')
def test_translation(self):
"""Should return correct translations"""
self.translations.addTranslation('trans1')
self.translations.addTranslation('trans2', 'comment2')
self.translations.addTranslation('trans3')
self.translations.addTranslation('trans3', 'comment3')
trans = self.translations.getTranslations()
self.assertEquals(trans.has_key('trans1'), True)
self.assertEquals(len(trans.keys()), 3)
self.assertEquals(trans['trans3'], 'comment3')
trans = {'key1': 'value1', 'key2': 'value2'}
self.translations.setTranslations(trans)
self.assertEquals(len(self.translations.getTranslations()), 2)
class TestEditor(unittest.TestCase):
"""Editor test"""
def test_load(self):
"""Editor should load dictionary from file"""
editor = dicteditor.Editor()
self.assertEquals(len(editor.getUnits()), 0)
editor.load("data/sampledict.dwa")
self.assertEquals(len(editor.getUnits()), 7)
def test_save(self):
"""Editor should correctly write dictionary to disk"""
editor = dicteditor.Editor()
editor.load("data/sampledict.dwa")
units = editor.getUnits()
editor.save("data/__output.dwa")
editor.load("data/__output.dwa")
self.assertEquals(len(units), len(editor.getUnits()))
os.unlink("data/__output.dwa")
def test_getUnit(self):
"""getUnit() should return desired Translation object"""
editor = dicteditor.Editor()
editor.load("data/sampledict.dwa")
oldCount = len(editor.getUnits())
self.assert_(editor.getUnit('du') != None)
def test_addUnit(self):
"""addUnit() should add new translation unit or update old one"""
editor = dicteditor.Editor()
editor.load("data/sampledict.dwa")
oldCount = len(editor.getUnits())
newUnit = dicteditor.Translation()
newUnit.setWord("test")
newUnit.addTranslation("utiutiu")
editor.addUnit(newUnit)
self.assertEquals(len(editor.getUnits()), oldCount + 1)
def test_removeUnit(self):
"""removeUnit() should add new translation unit or update old one"""
editor = dicteditor.Editor()
editor.load("data/sampledict.dwa")
oldCount = len(editor.getUnits())
unit = editor.getUnit('vienas')
editor.removeUnit(unit)
self.assertEquals(len(editor.getUnits()), oldCount - 1)
def test_unicode(self):
"""All the strings must be unicode objects"""
editor = dicteditor.Editor()
editor.load("data/sampledict.dwa")
for unit in editor.getUnits()[:10]:
for trans in unit.getTranslations().keys():
self.assertEquals(type(trans), type(u''))
if __name__ == "__main__":
unittest.main()
opendict-0.6.3/lib/tests/test_plugin.py 0000644 0001750 0001750 00000004547 10636242135 016622 0 ustar mjoc mjoc # -*- coding: UTF-8 -*-
#
# OpenDict
# Copyright (c) 2003-2006 Martynas Jocius
# Copyright (c) 2007 IDILES SYSTEMS, UAB
#
# Unit Test for editor.py
#
"""
Unit tests for plugin.py
"""
import unittest
import os
import sys
sys.path.append('../..')
from lib import newplugin
class TestPluginInfo(unittest.TestCase):
"""PluginInfo test"""
def test_getInfo(self):
"""PluginInfo should have correct attributes"""
fd = open("data/plugin.xml")
xmlData = fd.read()
fd.close()
info = newplugin.PluginInfo(xmlData)
self.assertEquals(info.name, u"Sample plugin name ąčę")
self.assertEquals(info.version, u"1.2.3")
self.assertEquals(info.authors, [{"name": u"Sample author name ąčę",
"email": u"sample@example.com"}])
self.assertEquals(info.module, {"name": u"mymodule.py",
"lang": u"Python"})
self.assertEquals(info.encoding, u"UTF-8")
self.assertEquals(info.usesWordList, True)
self.assertEquals(info.opendictVersion, u"0.5.8")
self.assertEquals(info.pythonVersion, u"2.3")
platforms = [{"name": u"Linux"},
{"name": u"Windows"},
{"name": u"BSD"}]
platforms.sort()
self.assertEquals(info.platforms, platforms)
self.assertEquals(info.description,
u"This is short or long description ąčę.")
self.assertEquals(info.xmlData, xmlData)
class TestDictionaryPlugin(unittest.TestCase):
"""Test PluginHandler class"""
def test_class(self):
"""__init__ should load plugin info and module"""
p = newplugin.DictionaryPlugin(os.path.realpath('data/sampleplugin'))
self.assertEquals(p.__class__, newplugin.DictionaryPlugin)
self.assert_(p.info != None)
self.assert_(p.dictionary != None)
self.assert_(p.isValid() == True)
self.assertEquals(p.info.__class__, newplugin.PluginInfo)
self.assertEquals(len(p.dictionary.search('x').words), 20)
self.assertRaises(newplugin.InvalidPluginException,
newplugin.DictionaryPlugin, 'blabla')
if __name__ == "__main__":
unittest.main()
opendict-0.6.3/lib/config.py 0000644 0001750 0001750 00000012021 10640522715 014352 0 ustar mjoc mjoc # OpenDict
# Copyright (c) 2003-2006 Martynas Jocius
# Copyright (c) 2007 IDILES SYSTEMS, UAB
#
# This program 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 2 of the License, or
# (at your opinion) any later version.
#
# This program is distributed in the hope that will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MECHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more detals.
#
# You shoud have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
# 02111-1307 USA
#
# Module: config.py
import os
import string
import codecs
from lib.logger import systemLog, debugLog, DEBUG, INFO, WARNING, ERROR
from lib.misc import numVersion
from lib import info
from lib import util
from lib import parser
from lib import xmltools
class ActiveDictConfig(object):
"""Config file manager for activated dictionaries. Operates with
names of dictionaries only."""
def __init__(self):
self.filePath = os.path.join(info.LOCAL_HOME, "active.conf")
# If config file does not exist (this is the first time),
# set special attribute init=True to notify that
if not os.path.exists(self.filePath):
self.init = True
else:
self.init = False
self.dicts = []
def load(self):
"""Load list of active dictionaries."""
try:
for line in open(self.filePath):
name = line.strip()
name = unicode(name, 'UTF-8')
self.dicts.append(name)
except IOError, e:
pass
def save(self):
"""Save list of active dictionaries."""
fd = open(self.filePath, 'w')
for d in self.dicts:
name = d.encode('UTF-8')
print >> fd, name
fd.close()
def enabled(self, name):
"""Return True if this dictionary is enabled."""
if name in self.dicts:
return True
return False
def add(self, name):
"""Add new dictionary to the list."""
if type(name) == str:
name = unicode(name, 'UTF-8')
if not name in self.dicts:
self.dicts.append(name)
def remove(self, name):
"""Remove dictionary from the list."""
if type(name) == str:
name = unicode(name, 'UTF-8')
if name in self.dicts:
self.dicts.remove(name)
class Configuration:
"""This class is used for reading and writing config file.
It also takes care of installing new plugins (but shouldn't)"""
def __init__(self):
"""Initialize default values"""
self.activedict = ActiveDictConfig()
self.activedict.load()
self.filePath = os.path.join(info.LOCAL_HOME, "opendict.xml")
self.props = {}
# TODO: Should not be here after removing register part from config
import wx
self.app = wx.GetApp()
#
# Default values
#
self.set('saveWindowSize', 'True')
self.set('saveWindowPos', 'True')
self.set('saveSashPos', 'True')
self.set('defaultDict', '')
self.set('windowWidth', '550')
self.set('windowHeight', '370')
self.set('windowPosX', '-1')
self.set('windowPosY', '-1')
self.set('sashPos', '160')
# Internal variables
self.window = None
self.ids = {}
self.plugMenuIds = 200
self.regMenuIds = 300
self.groupMenuIds = 400
self.set('encoding', 'UTF-8')
self.set('fontFace', 'Fixed')
self.set('fontSize', '10')
self.set('dictServer', 'dict.org')
self.set('dictServerPort', '2628')
self.set('dict-server-encoding', 'UTF-8')
self.repository = \
'http://db.opendict.idiles.com/Data/opendict-add-ons.xml'
def get(self, name):
"""Return property value"""
return self.props.get(name)
def set(self, name, value):
"""Set property"""
self.props[name] = value
def load(self):
"""Load configuration from file to memory"""
try:
if os.path.exists(self.filePath):
self.props.update(xmltools.parseMainConfig(self.filePath))
except Exception, e:
systemLog(ERROR, "Unable to read configuration file: %s" % e)
# Old configurations may still keep outdated entry, rewrite it
self.set('repository-list', self.repository)
def save(self):
"""Write configuration to disk"""
doc = xmltools.generateMainConfig(self.props)
xmltools.writeConfig(doc, os.path.join(info.LOCAL_HOME,
self.filePath))
def checkDir(self, dir):
"""Check if directory exists. Create one if not"""
raise "Deprecated"
if not os.path.exists(os.path.join(uhome, dir)):
os.mkdir(os.path.join(uhome, dir))
opendict-0.6.3/lib/errortype.py 0000644 0001750 0001750 00000007200 10636242135 015143 0 ustar mjoc mjoc #
# OpenDict
# Copyright (c) 2003-2006 Martynas Jocius
# Copyright (c) 2007 IDILES SYSTEMS, UAB
#
# This program 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 2 of the License, or
# (at your opinion) any later version.
#
# This program is distributed in the hope that will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MECHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more detals.
#
# You shoud have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
# 02111-1307 USA
#
"""
Error types
"""
import wx
_ = wx.GetTranslation
class ErrorType:
"""Error type interface"""
shortMessage = None
longMessage = None
def getShortMessage(self):
"""Return short message"""
return self.shortMessage
def getLongMessage(self):
"""Return long message"""
return self.longMessage
def getMessage(self):
"""Alternative for getShortMessage()"""
return self.getShortMessage()
class ErrorOk(ErrorType):
"""No error class"""
shortMessage = _("Success")
longMessage = _("Search successfully finished.")
class ErrorNotFound(ErrorType):
"""Not found error class"""
shortMessage = _("Not found")
longMessage = _("Word or phrase not found. Try less letters or " \
"fewer words.")
class ErrorInternal(ErrorType):
"""Internal error class"""
shortMessage = _("Internal error")
longMessage = _("Internal error occured. Please send bug report to " \
"the dictionary's of current use authors. Thank you.")
class ErrorNotConnected(ErrorType):
"""Not connected error class"""
shortMessage = _("Not connected")
longMessage = _("This dictionary uses Internet connection " \
"to translate words. Please connect to the Internet and " \
"try again.")
class ErrorConnectionTimeout(ErrorType):
"""Not connected error class"""
shortMessage = _("Connection Error")
longMessage = _("Could not connect to host. " \
"Check your Internet connection or try later.")
class ErrorInvalidEncoding(ErrorType):
"""Invalid encoding error class"""
shortMessage = _("Invalid encoding")
longMessage = _("Selected encoding is not correct for " \
"this dictionary. Please select another from Edit > " \
"Character Encoding menu")
class ErrorOpenDict(ErrorType):
"""OpenDict bug class"""
shortMessage = _("OpenDict Bug")
longMessage = _("Internal error occured. Please send bug report to " \
"OpenDict authors to prevent this error in the future. " \
"Thank you!")
class ErrorCustom(ErrorType):
"""Custom error"""
shortMessage = _("Unknown Error")
longMessage = _("Unknown error occured.")
def setMessage(self, msg):
"""Set custom message"""
self.shortMessage = msg
def setLongMessage(self, msg):
"""Set custom descriptive message"""
self.longMessage = msg
# Error constant instances
OK = ErrorOk()
NOT_FOUND = ErrorNotFound()
INTERNAL_ERROR = ErrorInternal()
NOT_CONNECTED = ErrorNotConnected()
CONNECTION_ERROR = ErrorConnectionTimeout()
CONNECTION_TIMEOUT = CONNECTION_ERROR
INVALID_ENCODING = ErrorInvalidEncoding()
OPENDICT_BUG = ErrorOpenDict()
CUSTOM_ERROR = ErrorCustom()
opendict-0.6.3/lib/logger.py 0000644 0001750 0001750 00000004067 10636242135 014377 0 ustar mjoc mjoc #
# OpenDict
# Copyright (c) 2003-2006 Martynas Jocius
# Copyright (c) 2007 IDILES SYSTEMS, UAB
#
# This program 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 2 of the License, or
# (at your opinion) any later version.
#
# This program is distributed in the hope that will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MECHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more detals.
#
# You shoud have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
# 02111-1307 USA
#
import os
import time
from lib import info
INFO = 0
WARNING = 1
ERROR = 2
DEBUG = 3
_logDir = os.path.join(info.LOCAL_HOME, info.LOG_DIR)
_systemLogFile = os.path.join(_logDir, 'system.log')
_debugLogFile = os.path.join(_logDir, 'debug.log')
# Enable or disable logging
logging = False
def systemLog(messageType, message):
"""Write message system log"""
if not logging:
return
dateStr = time.strftime("%Y-%m-%d %H:%M:%S")
typeStr = 'ERROR'
if messageType == INFO:
typeStr = 'INFO'
elif messageType == WARNING:
typeStr = 'WARNING'
elif messageType == DEBUG:
typeStr = 'DEBUG'
try:
fd = open(_systemLogFile, 'a+')
print >> fd, dateStr, typeStr, message
fd.close()
except Exception, e:
print "LOGGER ERROR: Unable to write message '%s'" % repr(message)
def debugLog(messageType, message):
"""Write message system log"""
if not logging:
return
dateStr = time.strftime("%Y-%m-%d %H:%M:%S")
typeStr = 'ERROR'
if messageType == INFO:
typeStr = 'INFO'
elif messageType == WARNING:
typeStr = 'WARNING'
elif messageType == DEBUG:
typeStr = 'DEBUG'
print dateStr, typeStr, message
opendict-0.6.3/lib/meta.py 0000644 0001750 0001750 00000005731 10636242135 014045 0 ustar mjoc mjoc #
# OpenDict
# Copyright (c) 2003-2006 Martynas Jocius
# Copyright (c) 2007 IDILES SYSTEMS, UAB
#
# This program 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 2 of the License, or
# (at your opinion) any later version.
#
# This program is distributed in the hope that will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MECHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more detals.
#
# You shoud have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
# 02111-1307 USA
#
"""
Metaclasses
"""
from lib import errortype
class SearchResult:
"""Search result metaclass"""
def __init__(self):
"""Set default values"""
self.error = errortype.OK
self.translation = ""
self.words = []
def setError(self, err):
"""Set error object"""
self.error = err
def getError(self):
"""Get error object"""
return self.error
def setTranslation(self, trans):
"""Set translation string"""
self.translation = trans
def getTranslation(self):
"""Get translation string"""
return self.translation
def setWordList(self, words):
"""Set word list"""
self.words = words
def getWordList(self):
"""Get word list"""
return self.words
class Dictionary:
"""Dictionary interface"""
active = True
def start(self):
"""Allocate resources"""
pass
def stop(self):
"""Free resources"""
pass
def getType(self):
"""Return dictionary type"""
return None
def getName(self):
"""Return plugin name"""
return None
def getVersion(self):
"""Return version"""
return None
def getSize(self):
"""Return size in kylobites"""
return None
def getPath(self):
"""Return ditionary path"""
pass
def getAuthors(self):
"""Return list of authors"""
return None
def setEncoding(self, encoding):
"""Set encoding"""
pass
def getEncoding(self):
"""Return encoding used by dictionary"""
return None
def getUsesWordList(self):
"""Return boolean value of word list usage"""
return None
def getDescription(self):
"""Returns description text"""
return None
def getLicence(self):
"""Return licence text"""
return None
def getActive(self):
return self.active
def setActive(self, active=True):
self.active = active
def search(self, word):
"""Lookup word"""
return None
opendict-0.6.3/lib/misc.py 0000644 0001750 0001750 00000007431 10640522715 014051 0 ustar mjoc mjoc #
# OpenDict
# Copyright (c) 2003-2006 Martynas Jocius
# Copyright (c) 2007 IDILES SYSTEMS, UAB
#
# This program 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 2 of the License, or
# (at your opinion) any later version.
#
# This program is distributed in the hope that will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MECHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more detals.
#
# You shoud have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
# 02111-1307 USA
#
# Module: misc
import wx
from os.path import *
import string
import traceback
import sys
import os
_ = wx.GetTranslation
#
# FIXME: Remove
#
errors = {1: _("Not found"),
2: _("Dictionary error, please report to its author"),
3: _("Syntax error"),
4: _("You must be connected to the internet to use this dictionary"),
5: _("Time out"),
6: _("Bad encoding is set for this dictionary, try another")}
#
# Character Encodings
# FIXME: translations does not work, why?
#
encodings = {_("Unicode (UTF-8)"): "UTF-8",
_("Western (ISO-8859-1)"): "ISO-8859-1",
_("Central European (ISO-8859-2)"): "ISO-8859-2",
_("Nordic (ISO-8859-10)"): "ISO-8859-10",
_("South European (ISO-8859-3)"): "ISO-8859-3",
_("Greek (ISO-8859-7)"): "ISO-8859-7",
_("Baltic (ISO-8859-13)"): "ISO-8859-13",
_("Cyrillic (KOI8-R)"): "KOI8-R",
_("Arabic (ISO-8859-6)"): "ISO-8859-6"}
#
# Font faces
#
fontFaces = {"Fixed": "fixed",
"Helvetica": "helvetica",
"Courier": "courier",
"Times": "Times",
"Verdana": "Verdana",
"Lucida": "Lucida"}
def numVersion(str):
"""Return a float number made from x.y.z[-preV] version number"""
nver = str.split('-')[0]
numbers = nver.split('.')
try:
return (float(numbers[0]) + float(numbers[1]) * 0.1 + float(number[2]) * 0.01)
except:
return 0.0
def printError():
print string.join(traceback.format_exception(sys.exc_info()[0],
sys.exc_info()[1],
sys.exc_info()[2]), "")
def getTraceback():
return string.join(traceback.format_exception(sys.exc_info()[0],
sys.exc_info()[1],
sys.exc_info()[2]), "")
def getFileSize(path):
"""Returns the size of file in bytes"""
size = -1
try:
size = os.stat(path)[6]
except:
print "ERROR (misc.getFileSize): path '%s' does not exist" % path
return size
def getDirSize(start, followLinks, myDepth, maxDepth):
"""Return total directory size"""
total = 0L
try:
dirList = os.listdir(start)
except:
if isdir(start):
print 'ERROR: Cannot list directory %s' % start
return 0
for item in dirList:
path = '%s/%s' % (start, item)
try:
stats = os.stat(path)
except:
print 'ERROR: Cannot stat %s' % path
continue
total += stats[6]
if isdir(path) and (followLinks or \
(not followLinks and not islink(path))):
bytes = getDirSize(path, followLinks,
myDepth + 1,
maxDepth)
total += bytes
return total
opendict-0.6.3/lib/installer.py 0000644 0001750 0001750 00000034314 10640522715 015113 0 ustar mjoc mjoc #
# OpenDict
# Copyright (c) 2003-2006 Martynas Jocius
# Copyright (c) 2007 IDILES SYSTEMS, UAB
#
# This program 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 2 of the License, or
# (at your opinion) any later version.
#
# This program is distributed in the hope that will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MECHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more detals.
#
# You shoud have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
# 02111-1307 USA
#
import wx
import os
import zipfile
import shutil
import traceback
from lib.gui.dictaddwin import DictAddWindow
from lib.gui import errorwin
from lib import misc
from lib import info
from lib import dicttype
from lib import xmltools
from lib import util
from lib import enc
from lib import plaindict
from lib import newplugin
_ = wx.GetTranslation
class Installer:
"""Default class used for installing plugins and registering
dictionaries."""
def __init__(self, mainWin, config):
self.mainWin = mainWin
self.config = config
def showGUI(self):
"""Show graphical window for selecting files and formats"""
wildCard = "All files (*.*)|*.*|" \
"OpenDict plugins (*.zip)|*.zip|" \
"Slowo dictionaries (*.dwa)|*.dwa|" \
"Mova dictionaries (*.mova)|*.mova|" \
"DICT dictionaries (*.dz)|*.dz"
fileDialog = wx.FileDialog(self.mainWin,
message=_("Choose dictionary file"),
wildcard=wildCard,
style=wx.OPEN|wx.CHANGE_DIR)
fileDialog.CentreOnScreen()
if fileDialog.ShowModal() == wx.ID_OK:
filePath = fileDialog.GetPaths()[0]
else:
fileDialog.Destroy()
return
fileName = os.path.basename(filePath)
extention = os.path.splitext(fileName)[1][1:]
extMapping = {}
for t in dicttype.supportedTypes:
for ext in t.getFileExtentions():
extMapping[ext.lower()] = t
if not extention.lower() in extMapping.keys():
title = _("Recognition Error")
msg = _("File %s is not supported by OpenDict") % fileName
errorwin.showErrorMessage(title, msg)
return
else:
self.install(filePath)
def install(self, filePath):
"""Install dictionary"""
extention = os.path.splitext(filePath)[1][1:]
succeeded = False
try:
if extention.lower() in dicttype.PLUGIN.getFileExtentions():
try:
directory, dtype = installPlugin(filePath)
if directory:
if dtype.lower() == 'plugin':
dictionary = newplugin._loadDictionaryPlugin(directory)
else:
dictionary = plaindict._loadPlainDictionary(directory)
self.mainWin.addDictionary(dictionary)
succeeded = True
except Exception, e:
errorwin.showErrorMessage(_("Installation failed"),
e.args[0] or '')
self.mainWin.SetStatusText(_("Installation failed"))
return
else:
try:
directory = installPlainDictionary(filePath)
if directory:
dictionary = plaindict._loadPlainDictionary(directory)
self.mainWin.addDictionary(dictionary)
succeeded = True
except Exception, e:
traceback.print_exc()
errorwin.showErrorMessage(_("Installation Error"),
e.args[0] or '')
self.mainWin.SetStatusText(_("Error: Installation failed"))
return
except:
# Can this happen?
self.mainWin.SetStatusText(_("Error: Installation failed"))
traceback.print_exc()
if succeeded:
title = _("Dictionary installed")
msg = _("Dictionary successfully installed. You can choose it " \
"from \"Dictionaries\" menu now.")
errorwin.showInfoMessage(title, msg)
def installPlainDictionary(filePath):
"""Install plain dictionary and return directory path"""
if not os.path.exists(filePath):
raise Exception, _("File %s does not exist") % filePath
if not os.path.isfile(filePath):
raise Exception, _("%s is not a file") % filePath
util.makeDirectories()
fileName = os.path.basename(filePath)
dictionaryName = os.path.splitext(fileName)[0]
dictDir = os.path.join(info.LOCAL_HOME,
info.__DICT_DIR,
info.__PLAIN_DICT_DIR,
fileName)
# Check existance
if os.path.exists(dictDir):
raise Exception, _("Dictionary \"%s\" is already installed") \
% dictionaryName
extention = os.path.splitext(fileName)[1][1:]
dictType = None
# Determine type
for t in dicttype.supportedTypes:
for ext in t.getFileExtentions():
if ext.lower() == extention.lower():
dictType = t
break
if not dictType:
raise Exception, "Dictionary type for '%s' still unknown! " \
"This may be internal error." % fileName
# Create directories
try:
os.mkdir(dictDir)
os.mkdir(os.path.join(dictDir, info.__PLAIN_DICT_CONFIG_DIR))
os.mkdir(os.path.join(dictDir, info.__PLAIN_DICT_FILE_DIR))
os.mkdir(os.path.join(dictDir, info._PLAIN_DICT_DATA_DIR))
except Exception, e:
print "ERROR Unable to create dicrectories, aborted (%s)" % e
try:
shutil.rmtree(dictDir)
except Exception, e:
print "ERROR Unable to remove directories (%s)" % e
# Determine info
dictFormat = dictType.getIdName()
md5sum = util.getMD5Sum(filePath)
# Write configuration
doc = xmltools.generatePlainDictConfig(name=dictionaryName,
format=dictFormat,
version=None,
authors={},
path=filePath,
md5=md5sum,
encoding='UTF-8',
description=None)
xmltools.writePlainDictConfig(doc, os.path.join(dictDir,
'conf',
'config.xml'))
return dictDir
def installPlugin(filePath):
"""Install dictionary plugin and return directory path"""
# Check if file exists
if not os.path.exists(filePath):
raise Exception, _("File %s does not exist") % filePath
# Check if it is file
if not os.path.isfile(filePath):
raise Exception, _("%s is not a file") % filePath
# Check if it is ZIP archive
if os.path.splitext(filePath)[1].lower()[1:] != "zip":
raise Exception, _("%s is not OpenDict dictionary plugin") % filePath
util.makeDirectories()
try:
zipFile = zipfile.ZipFile(filePath, 'r')
except Exception, e:
raise Exception, _("File \"%s\" is not valid ZIP file") % \
os.path.basename(filePath)
# Test CRC
if zipFile.testzip():
raise Exception, _("Dictionary plugin file is corrupted")
# Check if empty
try:
topDirectory = zipFile.namelist()[0]
except Exception, e:
raise Exception, _("Plugin file is empty (%s)") % e
configFileExists = False
pluginConfigExists = False
plainConfigExists = False
topLevelDirExists = False
# Check for validity
for fileInZip in zipFile.namelist():
dirName = os.path.dirname(fileInZip)
fileName = os.path.basename(fileInZip)
if fileName == "plugin.xml":
pluginConfigExists = True
if fileName == 'config.xml':
plainConfigExists = True
if len(fileName) == 0 \
and len(dirName.split('/')) == 1:
topLevelDirExists = True
if ((not plainConfigExists) and (not pluginConfigExists)) \
or (not topLevelDirExists):
raise Exception, _("Selected file is not valid OpenDict plugin")
dtype = None
if plainConfigExists:
directory = _installPlainPlugin(filePath)
dtype = 'plain'
elif pluginConfigExists:
directory = _installNormalPlugin(filePath)
dtype = 'plugin'
return (directory, dtype)
def _installNormalPlugin(filePath):
"""Install 'normal' OpenDict plugin"""
zipFile = zipfile.ZipFile(filePath, 'r')
topDirectory = zipFile.namelist()[0]
pluginsPath = os.path.join(info.LOCAL_HOME,
info.PLUGIN_DICT_DIR)
# Check if already installed
if os.path.exists(os.path.join(info.LOCAL_HOME,
info.PLUGIN_DICT_DIR,
topDirectory)):
raise Exception, _("This dictionary already installed. " \
"If you want to upgrade it, please remove " \
"old version first.")
installFile = os.path.join(topDirectory, 'install.py')
if installFile in zipFile.namelist():
data = zipFile.read(installFile)
try:
struct = {}
exec data in struct
except Exception, e:
title = _("Installation Error")
msg = _("Installation tool for this dictionary failed to start. " \
"Please report this problem to developers.")
errorwin.showErrorMessage(title, msg)
return
install = struct.get('install')
if not install:
title = _("Installation Error")
msg = _("Installation tool for this dictionary failed to start. " \
"Please report this problem to developers.")
errorwin.showErrorMessage(title, msg)
return
if not install(info.GLOBAL_HOME, info.LOCAL_HOME):
title = _("Installation Aborted")
msg = _("Dictionary installation has been aborted.")
errorwin.showErrorMessage(title, msg)
return
# Install
try:
for fileInZip in zipFile.namelist():
dirName = os.path.dirname(fileInZip)
fileName = os.path.basename(fileInZip)
if len(fileName) == 0:
dirToCreate = os.path.join(pluginsPath, dirName)
if not os.path.exists(dirToCreate):
os.mkdir(dirToCreate)
else:
fileToWrite = os.path.join(pluginsPath, dirName, fileName)
fd = open(fileToWrite, 'wb')
fd.write(zipFile.read(fileInZip))
fd.close()
except Exception, e:
try:
shutil.rmtree(os.path.join(pluginsPath, topLevelDir))
except Exception, e:
raise _("Error while removing created directories after " \
"plugin installation failure. This may be " \
"permission or disk space error.")
raise _("Unable to install plugin")
return os.path.join(info.LOCAL_HOME,
info.PLUGIN_DICT_DIR,
topDirectory)
def _installPlainPlugin(filePath):
"""Install prepared plain dictionary and return directory path"""
zipFile = zipfile.ZipFile(filePath, 'r')
topDirectory = zipFile.namelist()[0]
# Test CRC
if zipFile.testzip():
raise Exception, _("Compressed dictionary file is corrupted")
plainDictsPath = os.path.join(info.LOCAL_HOME,
info.PLAIN_DICT_DIR)
# Check if already installed
if os.path.exists(os.path.join(plainDictsPath,
topDirectory)):
raise Exception, _("This dictionary already installed. " \
"If you want to upgrade it, please remove " \
"old version first.")
# Install
try:
for fileInZip in zipFile.namelist():
dirName = os.path.dirname(fileInZip)
fileName = os.path.basename(fileInZip)
if len(fileName) == 0:
dirToCreate = os.path.join(plainDictsPath, dirName)
if not os.path.exists(dirToCreate):
os.mkdir(dirToCreate)
else:
fileToWrite = os.path.join(plainDictsPath, dirName, fileName)
fd = open(fileToWrite, 'wb')
fd.write(zipFile.read(fileInZip))
fd.close()
except Exception, e:
try:
shutil.rmtree(os.path.join(plainDictsPath, topDirectory))
except Exception, e:
raise _("Error while removing created directories after " \
"plugin installation failure. This may be " \
"permission or disk space error.")
raise _("Unable to install dictionary")
return os.path.join(info.LOCAL_HOME,
info.PLAIN_DICT_DIR,
topDirectory)
def removePlainDictionary(dictInstance):
"""Remove dictionary configuration"""
filePath = dictInstance.getPath()
fileName = os.path.basename(filePath)
dictDir = dictInstance.getConfigDir()
try:
shutil.rmtree(dictDir)
except Exception, e:
raise Exception, str(e)
def removePluginDictionary(dictInstance):
"""Remove plugin dictionary"""
filePath = dictInstance.getPath()
fileName = os.path.basename(filePath)
dictDir = dictInstance.getPath()
try:
shutil.rmtree(dictDir)
except Exception, e:
raise Exception, str(e)
opendict-0.6.3/lib/history.py 0000644 0001750 0001750 00000003202 10636242135 014607 0 ustar mjoc mjoc # OpenDict
# Copyright (c) 2003-2006 Martynas Jocius
# Copyright (c) 2007 IDILES SYSTEMS, UAB
#
# This program 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 2 of the License, or
# (at your opinion) any later version.
#
# This program is distributed in the hope that will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MECHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more detals.
#
# You shoud have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
# 02111-1307 USA
#
# Module: history
class History:
def __init__(self):
self.pages = []
self.index = -1
def add(self, page):
self.pages.append(page)
self.index = len(self.pages) - 1
def clear(self):
self.pages = []
self.index = -1
def back(self):
if self.index > 0:
self.index -= 1
page = self.pages[self.index]
else:
page = self.pages[self.index]
return page
def forward(self):
if self.index < len(self.pages) - 1:
self.index += 1
page = self.pages[self.index]
else:
page = self.pages[self.index]
return page
def canBack(self):
return self.index > 0
def canForward(self):
return self.index < len(self.pages) - 1
opendict-0.6.3/lib/enc.py 0000644 0001750 0001750 00000002170 10636242135 013656 0 ustar mjoc mjoc #
# OpenDict
# Copyright (c) 2003-2006 Martynas Jocius
# Copyright (c) 2007 IDILES SYSTEMS, UAB
#
# This program 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 2 of the License, or
# (at your opinion) any later version.
#
# This program is distributed in the hope that will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MECHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more detals.
#
# You shoud have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
# 02111-1307 USA
#
"""
Character encodings
"""
import wx
if wx.USE_UNICODE:
toWX = fromWX = lambda s: s
else:
import locale
localeCharset = locale.getpreferredencoding()
def toWX(s):
return s.encode(localeCharset, 'replace')
def fromWX(s):
return unicode(s, localeCharset)
opendict-0.6.3/lib/dicteditor.py 0000644 0001750 0001750 00000011072 10636242135 015244 0 ustar mjoc mjoc #
# OpenDict
# Copyright (c) 2003-2006 Martynas Jocius
# Copyright (c) 2007 IDILES SYSTEMS, UAB
#
# This program 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 2 of the License, or
# (at your opinion) any later version.
#
# This program is distributed in the hope that will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MECHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more detals.
#
# You shoud have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
# 02111-1307 USA
#
"""
Dictionary editor module
"""
class Translation:
"""Translation in Slowo format
Keeps one original word and a dictionary of translations
"""
def __init__(self):
"""Initialize"""
self.word = None
self.translations = {}
def setWord(self, word):
"""Set word"""
self.word = word
def getWord(self):
"""Return word"""
return self.word
def addTranslation(self, trans, comment=None):
"""Set translation object"""
self.translations[trans] = comment
def setTranslations(self, newTrans):
"""Set translation dictionary"""
self.translations = newTrans
def getTranslations(self):
"""Return translation object"""
return self.translations
class Editor:
"""Slowo dictionary editor"""
def __init__(self, filePath=None):
"""Initialize variables and load dictionary if requested"""
self.filePath = filePath
self.units = []
self.encoding = 'UTF-8'
if filePath:
self.load(filePath)
def load(self, filePath):
"""Load dictionary into memory"""
self.filePath = filePath
self.units = []
try:
fd = open(filePath)
for line in fd:
try:
line = unicode(line, self.encoding)
except Exception, e:
raise Exception, "Unable to encode text in %s" \
% self.encoding
word, end = line.split('=')
word = word.strip()
translation = Translation()
translation.setWord(word)
chunks = end.split(';')
for chunk in chunks:
chunk = chunk.strip()
if not chunk:
continue
try:
trans, comment = chunk.split('//')
except:
trans = chunk
comment = None
trans = trans.strip()
if comment:
comment = comment.strip()
translation.addTranslation(trans, comment)
self.units.append(translation)
fd.close()
except Exception, e:
raise Exception, "Unable to read dictionary: %s" % e
def save(self, filePath=None):
"""Write data to disk"""
if not filePath:
filePath = self.filePath
try:
fd = open(filePath, 'w')
for unit in self.getUnits():
outstr = "%s = " % unit.getWord()
chunks = []
for trans, comment in unit.getTranslations().items():
if comment:
chunks.append("%s // %s" % (trans, comment))
else:
chunks.append(trans)
outstr += u' ; '.join(chunks) + u' ;'
outstr = outstr.encode(self.encoding)
print >> fd, outstr
except Exception, e:
raise Exception, "Unable to save dictionary: %s" % e
def getUnit(self, word):
"""Return Translation object for the word"""
for unit in self.units:
if unit.getWord() == word:
return unit
return None
def addUnit(self, unit):
"""Adds translation unit to dictionary"""
self.units.append(unit)
def removeUnit(self, unit):
"""Removes translation unit defined by word"""
self.units.remove(unit)
def getUnits(self):
"""Return list of translation objects"""
return self.units
opendict-0.6.3/lib/util.py 0000644 0001750 0001750 00000021321 10636242135 014065 0 ustar mjoc mjoc #
# OpenDict
# Copyright (c) 2003-2006 Martynas Jocius
# Copyright (c) 2007 IDILES SYSTEMS, UAB
#
# This program 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 2 of the License, or
# (at your opinion) any later version.
#
# This program is distributed in the hope that will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MECHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more detals.
#
# You shoud have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
# 02111-1307 USA
#
"""
Utility functions
"""
import wx
_ = wx.GetTranslation
import os
import md5
import threading
import time
import urllib2
import traceback
from lib import info
from lib.logger import systemLog, debugLog, DEBUG, INFO, WARNING, ERROR
class UniqueIdGenerator:
"""Unique ID generator (using singleton design pattern)"""
class _RealGenerator:
"""Unique ID generator"""
def __init__(self, start=0):
"""Set starting ID value"""
self.id = start
def getID(self):
"""Return unique ID"""
self.id += 1
return self.id
__instance = None
def __init__(self, start=0):
"""Create new instance if not exists yet"""
if UniqueIdGenerator.__instance is None:
UniqueIdGenerator.__instance = self._RealGenerator(start)
def getID(self):
"""Return unique ID"""
return self.__instance.getID()
def generateUniqueID():
"""Helper function for getting unique ID"""
gen = UniqueIdGenerator(7000)
return gen.getID()
def getMD5Sum(filePath):
"""Return MD5 checksum for given file"""
fd = open(filePath, 'rb')
data = fd.read()
fd.close()
generator = md5.new(data)
return generator.hexdigest()
def makeDirectories():
"""Make needed directories if not exist"""
if not os.path.exists(info.LOCAL_HOME):
os.mkdir(info.LOCAL_HOME)
logDir = os.path.join(info.LOCAL_HOME, info.LOG_DIR)
if not os.path.exists(logDir):
os.mkdir(logDir)
plainDir = os.path.join(info.LOCAL_HOME,
info.PLAIN_DICT_DIR)
pluginDir = os.path.join(info.LOCAL_HOME,
info.PLUGIN_DICT_DIR)
if not os.path.exists(info.LOCAL_HOME):
try:
systemLog(DEBUG, "%s does not exist, creating..." \
% info.LOCAL_HOME)
os.mkdir(info.LOCAL_HOME)
except Exception, e:
systemLog(ERROR, "Unable to create %s (%s)" % (info.LOCAL_HOME, e))
if not os.path.exists(os.path.join(info.LOCAL_HOME, info.__DICT_DIR)):
try:
systemLog(DEBUG, "%s does not exist, creating..." \
% os.path.join(info.LOCAL_HOME, info.__DICT_DIR))
os.mkdir(os.path.join(info.LOCAL_HOME, info.__DICT_DIR))
except Exception, e:
systemLog(ERROR, "Unable to create %s (%s)" \
% (os.path.join(info.LOCAL_HOME, info.__DICT_DIR), e))
if not os.path.exists(plainDir):
try:
systemLog(DEBUG, "%s does not exist, creating..." % plainDir)
os.mkdir(plainDir)
except Exception, e:
systemLog(ERROR, "Unable to create %s (%s)" % (plainDir, e))
if not os.path.exists(pluginDir):
try:
os.mkdir(pluginDir)
except Exception, e:
systemLog(ERROR, "Unable to create %s (%s)" % (pluginDir, e))
class DownloadThread:
"""Non-blocking download thread
Can be used to connect and download files from the Internet.
"""
def __init__(self, url):
"""Initialize variables"""
self.url = url
self.thread = threading.Thread(target=self.worker)
self.thread.setDaemon(True) # Daemonize for fast exiting
self.statusMessage = ''
self.errorMessage = None
self.percents = 0
self.stopRequested = False
self.done = False
self.buffer = ''
def start(self):
"""Start thread"""
self.thread.start()
def stop(self):
"""Request thread to stop, may hang for some time"""
self.stopRequested = True
def getMessage(self):
"""Return status message"""
return self.statusMessage
def getErrorMessage(self):
"""Return error message"""
return self.errorMessage
def getPercentage(self):
"""Return percentage"""
return self.percents
def finished(self):
"""Return True if finished, False otherwise"""
return self.done
def getBytes(self):
"""Return buffered bytes and clear the buffer"""
bytes = self.buffer
self.buffer = ''
return bytes
def worker(self):
"""Main worker method"""
try:
serverName = '/'.join(self.url.split('/')[:3])
except:
serverName = self.url
try:
self.statusMessage = _("Connecting to %s...") % serverName
self.up = urllib2.urlopen(self.url)
fileSize = int(self.up.info().getheader('Content-length'))
except Exception, e:
self.errorMessage = "Unable to connect to %s" % serverName
self.done = True
return
count = 0
try:
while not self.stopRequested and count < fileSize:
bytes = self.up.read(1024)
count += len(bytes)
self.buffer += bytes
self.percents = int(float(count) / fileSize * 100)
self.statusMessage = _("Downloading... %d%%") % self.percents
time.sleep(0.005) # To lower CPU usage
self.up.close()
self.done = True
self.statusMessage = _("Done")
except Exception, e:
self.errorMessage = "Error while fetching data from %s: %s" \
% (self.url, e)
self.done = True
class AgreementsManager:
"""Manages information about licence agreements for dictionaries"""
def __init__(self, filePath):
"""Initialize variables"""
self.filePath = filePath
self.dictPaths = []
self._load()
def addAgreement(self, dictConfigPath):
"""Mark dictionary licence as accepted"""
dictConfigPath = os.path.realpath(dictConfigPath)
if not dictConfigPath in self.dictPaths:
self.dictPaths.append(dictConfigPath)
self._updateFile()
def removeAgreement(self, dictConfigPath):
"""Mark dictionary licence as rejected,
i.e. remove from accepted list"""
dictConfigPath = os.path.realpath(dictConfigPath)
if dictConfigPath in self.dictPaths:
self.dictPaths.remove(dictConfigPath)
self._updateFile()
def getAccepted(self, dictConfigPath):
"""Return True if dictionary licence is marked as accepted"""
dictConfigPath = os.path.realpath(dictConfigPath)
if dictConfigPath in self.dictPaths:
return True
else:
return False
def _load(self):
"""Read data from file"""
try:
fd = open(self.filePath)
update = False
for line in fd:
line = line.strip()
if os.path.exists(line) and not line in self.dictPaths:
self.dictPaths.append(line)
else:
update = True
fd.close()
# Rewrite contents if non-existent directories exist
if update:
self._updateFile()
except:
pass
def _updateFile(self):
"""Write changes to file"""
fd = open(self.filePath, 'w')
for path in self.dictPaths:
print >> fd, path
fd.close()
#
# FIXME: doesn't work correctly
#
def correctDictName(dictInstance):
"""Set name to 'Name (X)', where X is Xth occurance of the name"""
return
def _nameMatches(name, nameList):
matches = 0
for n in nameList:
try:
if n.startswith(name):
matches += 1
except Exception, e:
print "WARNING:", e
return matches
import wx
dictionaries = wx.GetApp().dictionaries # Sucks!
matches = _nameMatches(dictInstance.getName(), dictionaries.keys())
if matches:
dictInstance.setName("%s (%d)" % (dictInstance.getName(), matches+1))
opendict-0.6.3/lib/xmltools.py 0000644 0001750 0001750 00000032723 10636242135 015001 0 ustar mjoc mjoc #
# OpenDict
# Copyright (c) 2003-2006 Martynas Jocius
# Copyright (c) 2007 IDILES SYSTEMS, UAB
#
# This program 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 2 of the License, or
# (at your opinion) any later version.
#
# This program is distributed in the hope that will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MECHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more detals.
#
# You shoud have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
# 02111-1307 USA
#
import xml.dom.minidom
import xml.dom.ext
from lib import meta
def _textData(element):
"""Return text data from given XML element"""
text = ''
for node in element.childNodes:
text = node.data
return text
class RegisterConfigGenerator:
"""Class for generating register configuration files"""
def generate(self, **args):
"""Generate config XML object"""
doc = xml.dom.minidom.Document()
registerElement = doc.createElement('plain-dictionary')
doc.appendChild(registerElement)
# Format element
formatElement = doc.createElement('format')
registerElement.appendChild(formatElement)
formatElement.appendChild(doc.createTextNode(args.get('format')))
# Name element
nameElement = doc.createElement('name')
registerElement.appendChild(nameElement)
nameElement.appendChild(doc.createTextNode(args.get('name')))
# Version element
versionElement = doc.createElement('version')
registerElement.appendChild(versionElement)
versionElement.appendChild(doc.createTextNode(args.get('version') \
or ''))
# Authors element
authorsElement = doc.createElement('authors')
registerElement.appendChild(authorsElement)
for author in (args.get('authors') or []):
authorElement = doc.createElement('author')
authorsElement.appendChild(authorElement)
authorElement.setAttribute('name', author.get('name'))
authorElement.setAttribute('email', author.get('email'))
# Path element
pathElement = doc.createElement('path')
registerElement.appendChild(pathElement)
pathElement.appendChild(doc.createTextNode(args.get('path')))
# MD5 element
md5Element = doc.createElement('md5')
registerElement.appendChild(md5Element)
md5Element.appendChild(doc.createTextNode(args.get('md5')))
# Encoding element
encodingElement = doc.createElement('encoding')
registerElement.appendChild(encodingElement)
encodingElement.appendChild(doc.createTextNode(args.get('encoding')))
# Licence element
licElement = doc.createElement('licence')
registerElement.appendChild(licElement)
licElement.appendChild(doc.createTextNode(args.get('licence') \
or ''))
# Description element
descElement = doc.createElement('description')
registerElement.appendChild(descElement)
descElement.appendChild(doc.createTextNode(args.get('description') \
or ''))
return doc
def generatePlainDictConfig(**args):
"""Generate configuration and return DOM object"""
generator = RegisterConfigGenerator()
doc = generator.generate(**args)
return doc
def writePlainDictConfig(doc, path):
"""Write XML file"""
fd = open(path, 'w')
xml.dom.ext.PrettyPrint(doc, fd)
fd.close()
class RegisterConfigParser:
"""Parse register configuration"""
def parse(self, xmlData):
"""Parse XML data"""
doc = xml.dom.minidom.parseString(xmlData)
name = None
format = None
version = None
authors = []
path = None
md5 = None
encoding = None
licence = None
description = None
registers = doc.getElementsByTagName('plain-dictionary')
if len(registers) == 0:
raise "Invalid configuration"
registerElement = registers[0]
for nameElement in registerElement.getElementsByTagName('name'):
for node in nameElement.childNodes:
name = node.data
for formatElement in registerElement.getElementsByTagName('format'):
for node in formatElement.childNodes:
format = node.data
for pathElement in registerElement.getElementsByTagName('path'):
for node in pathElement.childNodes:
path = node.data
for versionElement in registerElement.getElementsByTagName('version'):
for node in versionElement.childNodes:
version = node.data.strip()
for authorElement in registerElement.getElementsByTagName('author'):
authors.append({'name': authorElement.getAttribute('name'),
'email': authorElement.getAttribute('email')})
for md5Element in registerElement.getElementsByTagName('md5'):
for node in md5Element.childNodes:
md5 = node.data
for encodingElement in \
registerElement.getElementsByTagName('encoding'):
for node in encodingElement.childNodes:
encoding = node.data
for licenceElement in \
registerElement.getElementsByTagName('licence'):
for node in licenceElement.childNodes:
licence = node.data.strip()
for descElement in \
registerElement.getElementsByTagName('description'):
for node in descElement.childNodes:
description = (description or '') + node.data.strip()
result = {}
result['name'] = name
result['format'] = format
result['version'] = version
result['authors'] = authors
result['path'] = path
result['md5'] = md5
result['encoding'] = encoding
result['licence'] = licence
result['description'] = description
return result
def parsePlainDictConfig(configPath):
"""Parse configuration file and return data dictionary"""
parser = RegisterConfigParser()
fd = open(configPath)
xmlData = fd.read()
fd.close()
data = parser.parse(xmlData)
return data
class IndexFileGenerator:
"""Class for generating register configuration files"""
def generate(self, index):
"""Generate config XML object"""
doc = xml.dom.minidom.Document()
indexElement = doc.createElement("index")
doc.appendChild(indexElement)
for data, pos in index.items():
startElement = doc.createElement("element")
startElement.setAttribute("literal", data)
startElement.setAttribute("position", str(pos))
indexElement.appendChild(startElement)
return doc
def generateIndexFile(index):
"""Generate index data and return DOM object"""
generator = IndexFileGenerator()
doc = generator.generate(index)
return doc
def writeIndexFile(doc, path):
"""Write XML file"""
fd = open(path, 'wb')
xml.dom.ext.PrettyPrint(doc, fd)
fd.close()
class IndexFileParser:
"""Parse register configuration"""
def parse(self, xmlData):
"""Parse XML data"""
doc = xml.dom.minidom.parseString(xmlData)
index = {}
indexElement = doc.getElementsByTagName('index')[0]
for element in indexElement.getElementsByTagName('element'):
index[element.getAttribute("literal")] = long(element.getAttribute("position"))
return index
def parseIndexFile(indexPath):
"""Parse configuration file and return data dictionary"""
parser = IndexFileParser()
fd = open(indexPath, 'rb')
xmlData = fd.read()
fd.close()
index = parser.parse(xmlData)
return index
class AddOnsParser:
"""Parse add-ons file"""
class EmptyDictionary(meta.Dictionary):
"""Empty dictionary for representing add-on information"""
name = None
version = None
size = None
checksum = None
authors = []
location = None
desc = None
atype = None
def setType(self, t):
self.atype = t
def getType(self):
return self.atype
def setName(self, name):
self.name = name
def getName(self):
return self.name
def setVersion(self, version):
self.version = version
def getVersion(self):
return self.version
def setSize(self, size):
self.size = size
def getSize(self):
return self.size
def setChecksum(self, checksum):
self.checksum = checksum
def getChecksum(self):
return self.checksum
def addAuthor(self, author):
self.authors.append(author)
def getAuthors(self):
return self.authors
def setLocation(self, location):
self.location = location
def getLocation(self):
return self.location
def setDescription(self, desc):
self.desc = desc
def getDescription(self):
return self.desc
def parse(self, xmlData):
"""Parse XML data and return name->info dictionary object"""
doc = xml.dom.minidom.parseString(xmlData)
addons = {}
for addonElement in doc.getElementsByTagName('add-on'):
name = None
version = None
authors = []
description = None
size = None
url = None
checksum = None
addonType = addonElement.getAttribute('type')
for nameElement in addonElement.getElementsByTagName('name'):
name = _textData(nameElement)
for versionElement in addonElement.getElementsByTagName('version'):
version = _textData(versionElement)
for authorElement in addonElement.getElementsByTagName('author'):
authors.append({'name': authorElement.getAttribute('name'),
'email': authorElement.getAttribute('email')})
for descElement \
in addonElement.getElementsByTagName('description'):
description = _textData(descElement)
for urlElement in addonElement.getElementsByTagName('url'):
url = _textData(urlElement)
for sizeElement in addonElement.getElementsByTagName('size'):
size = long(_textData(sizeElement))
for sumElement in addonElement.getElementsByTagName('md5'):
checksum = _textData(sumElement)
emptyDict = self.EmptyDictionary()
emptyDict.setName(name)
emptyDict.setVersion(version)
emptyDict.authors = [] # To forget an old reference
for author in authors:
emptyDict.addAuthor(author)
emptyDict.setDescription(description)
emptyDict.setLocation(url)
emptyDict.setSize(size)
emptyDict.setChecksum(checksum)
addons[name] = emptyDict
return addons
def parseAddOns(xmlData):
"""Wrap add-ons data parsing"""
parser = AddOnsParser()
result = parser.parse(xmlData)
return result
class MainConfigParser:
"""Parse main configuration"""
def parse(self, xmlData):
"""Parse XML data"""
doc = xml.dom.minidom.parseString(xmlData)
props = {}
configs = doc.getElementsByTagName('main-config')
if len(configs) == 0:
raise "Invalid configuration"
configElement = configs[0]
for node in configElement.childNodes:
if not node.nodeType == node.ELEMENT_NODE:
continue
for cnode in node.childNodes:
name = node.nodeName
value = cnode.data.strip()
props[name] = value
return props
def parseMainConfig(configPath):
"""Parse configuration file and return data dictionary"""
parser = MainConfigParser()
fd = open(configPath)
xmlData = fd.read()
fd.close()
data = parser.parse(xmlData)
return data
class MainConfigGenerator:
"""Class for generating main configuration file"""
def generate(self, props):
"""Generate config XML object"""
doc = xml.dom.minidom.Document()
mainElement = doc.createElement("main-config")
doc.appendChild(mainElement)
for key, value in props.items():
elem = doc.createElement(key)
mainElement.appendChild(elem)
if type(value) != unicode:
value = str(value)
elem.appendChild(doc.createTextNode(value))
return doc
def generateMainConfig(props):
"""Generate configuration and return DOM object"""
generator = MainConfigGenerator()
doc = generator.generate(props)
return doc
def writeConfig(doc, path):
"""Write XML file"""
fd = open(path, 'w')
xml.dom.ext.PrettyPrint(doc, fd)
fd.close()
opendict-0.6.3/lib/plaindict.py 0000644 0001750 0001750 00000031635 10636242135 015070 0 ustar mjoc mjoc #
# OpenDict
# Copyright (c) 2003-2006 Martynas Jocius
# Copyright (c) 2007 IDILES SYSTEMS, UAB
#
# This program 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 2 of the License, or
# (at your opinion) any later version.
#
# This program is distributed in the hope that will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MECHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more detals.
#
# You shoud have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
# 02111-1307 USA
#
"""
Module for plain dictionaries
"""
import os
import traceback
from lib import info
from lib import meta
from lib import util
from lib import xmltools
from lib import util
from lib.logger import systemLog, debugLog, DEBUG, INFO, WARNING, ERROR
class PlainDictInfo:
"""Plain dictionary configuration"""
def __init__(self, directory):
"""Store configuration data"""
raise Exception, "PlainDictInfo is deprecated"
self.config = xmltools.parsePlainDictConfig(\
os.path.join(directory,
info.__PLAIN_DICT_CONFIG_DIR,
'config.xml'))
self.directory = directory
self.name = config.get('name')
self.formatString = config.get('format')
self.version = config.get('version')
self.author = config.get('author')
self.path = config.get('path')
self.checksum = config.get('md5')
self.encoding = config.get('encoding')
def getFormatString(self):
"""Return format name"""
return self.formatString
def getName(self):
"""Return name"""
return self.name
def getVersion(self):
"""Return version number"""
return self.version
def getAuthor(self):
"""Return author"""
return self.author
def getPath(self):
"""Return full file path"""
return self.path
def getChecksum(self):
"""Return checksum"""
return self.checksum
def getEncoding(self):
"""Return encoding"""
return self.encoding
def getLicence(self):
"""Return licence text"""
filePath = self.licence
if filePath:
if not os.path.exists(filePath):
filePath = os.path.join(self.directory,
info._PLAIN_DICT_DATA_DIR,
self.licence)
if not os.path.exists(filePath):
filePath = None
errMsg = "Error: licence file not found"
if not filePath:
systemLog(ERROR, "Cannot find defined licence file for %s: %" \
% (self.getName(), e))
return errMsg
try:
fd = open(filePath)
data = fd.read()
fd.close()
return data
except Exception, e:
systemLog(ERROR, "Unable to read licence file for %s: %" \
% (self.getName(), e))
return errMsg
return None
class PlainDictionary(meta.Dictionary):
"""Plain dictionary class"""
licenceFile = None
version = None
authors = []
def getConfigDir(self):
"""Return configuration directory path"""
if os.path.exists(os.path.join(info.LOCAL_HOME,
info.PLAIN_DICT_DIR,
os.path.basename(self.getPath()))):
path = os.path.join(info.LOCAL_HOME,
info.PLAIN_DICT_DIR,
os.path.basename(self.getPath()))
else:
path = os.path.join(info.GLOBAL_HOME,
info.PLAIN_DICT_DIR,
os.path.basename(self.getPath()))
return path
def setLicenceFile(self, licenceFile):
"""Set licence file path"""
self.licenceFile = licenceFile
def getLicenceFile(self):
"""Return licence file"""
return self.licenceFile
def getLicence(self):
"""Return licence text"""
filePath = self.licenceFile
if filePath:
if not os.path.exists(filePath):
filePath = os.path.join(self.getConfigDir(),
info._PLAIN_DICT_DATA_DIR,
self.licenceFile)
if not os.path.exists(filePath):
filePath = None
errMsg = "Error: licence file not found"
if not filePath:
systemLog(ERROR,
"Cannot find defined licence file '%s' for '%s'" \
% (self.licenceFile, self.getName()))
return errMsg
try:
fd = open(filePath)
data = fd.read()
fd.close()
return data
except Exception, e:
systemLog(ERROR, "Unable to read licence file for %s: %" \
% (self.getName(), e))
return errMsg
return None
def setVersion(self, version):
"""Set version number"""
self.version = version
def getVersion(self):
"""Return version number"""
return self.version
def setAuthors(self, authors):
"""Set author"""
self.authors = authors
def getAuthors(self):
"""Return author"""
return self.authors
def setDescription(self, desc):
"""Set description"""
self.description = desc
def getDescription(self):
"""Get description"""
return self.description
def _loadPlainDictionary(directory):
"""Load one dictionary and returns dictionary object"""
from lib import dicttype
dictionary = None
try:
config = xmltools.parsePlainDictConfig(\
os.path.join(directory,
info.__PLAIN_DICT_CONFIG_DIR,
'config.xml'))
for t in dicttype.supportedTypes:
if t.getIdName() == config.get('format'):
Parser = t.getClass()
if not Parser:
raise Exception, "This is internal error and should not happen: " \
"no parser class found for dictionary in %s" % directory
filePath = config.get('path')
fileName = os.path.basename(filePath)
home = info.LOCAL_HOME
if directory.startswith(info.GLOBAL_HOME):
home = info.GLOBAL_HOME
if not os.path.exists(filePath):
newPath = os.path.join(home, info.PLAIN_DICT_DIR,
fileName, info.__PLAIN_DICT_FILE_DIR,
fileName)
if os.path.exists(newPath):
filePath = newPath
else:
filePath = None
if not filePath:
raise Exception, "Dictionary file not found: %s" % fileName
dictionary = Parser(filePath)
dictionary.setEncoding(config.get('encoding'))
dictionary.setName(config.get('name'))
dictionary.setVersion(config.get('version'))
dictionary.setAuthors(config.get('authors'))
dictionary.setChecksum(config.get('md5'))
dictionary.setLicenceFile(config.get('licence'))
dictionary.setDescription(config.get('description'))
except Exception, e:
traceback.print_exc()
util.correctDictName(dictionary)
return dictionary
def loadPlainDictionaries(dictionaries):
"""Load dictionaries and return a list of dictionary objects"""
dirs = []
globalDictDir = os.path.join(info.GLOBAL_HOME,
info.PLAIN_DICT_DIR)
localDictDir = os.path.join(info.LOCAL_HOME,
info.PLAIN_DICT_DIR)
if os.path.exists(globalDictDir):
for directory in os.listdir(globalDictDir):
if os.path.isdir(os.path.join(globalDictDir, directory)):
dirs.append(os.path.join(globalDictDir, directory))
if os.path.exists(localDictDir):
for directory in os.listdir(localDictDir):
if os.path.isdir(os.path.join(localDictDir, directory)):
dirs.append(os.path.join(localDictDir, directory))
plainDicts = []
for directory in dirs:
dictionary = _loadPlainDictionary(directory)
if dictionary:
plainDicts.append(dictionary)
dictionaries[dictionary.getName()] = dictionary
return plainDicts
def indexShouldBeMade(dictionary):
"""Check if index exists and is up to date.
Return True if dictionary must be indexed.
"""
filePath = dictionary.getPath()
fileName = os.path.basename(filePath)
dictLocalHome = os.path.join(info.LOCAL_HOME,
info.PLAIN_DICT_DIR,
fileName)
dictGlobalHome = os.path.join(info.GLOBAL_HOME,
info.PLAIN_DICT_DIR,
fileName)
if not os.path.exists(os.path.join(dictGlobalHome, 'data', 'index.xml')) \
and not os.path.exists(os.path.join(dictLocalHome, 'data',
'index.xml')):
return True
debugLog(INFO, "Old checksum: %s" % dictionary.getChecksum())
newChecksum = util.getMD5Sum(filePath)
debugLog(INFO, "New checksum: %s" % newChecksum)
return dictionary.getChecksum() != newChecksum
def makeIndex(dictionary, currentlySetEncoding):
"""Index dictionary"""
filePath = dictionary.getPath()
fd = open(filePath)
index = {}
count = 0L
linenum = -1
for line in fd:
linenum += 1
try:
literal = unicode(line.strip(),
dictionary.getEncoding())[:2].lower()
except:
try:
literal = unicode(line.strip(),
currentlySetEncoding)[:2].lower()
dictionary.setEncoding(currentlySetEncoding)
except:
raise Exception, "Unable to encode data in %s nor %s " \
"at line %d" \
% (dictionary.getEncoding(), currentlySetEncoding,
linenum)
# Ignore if control character found
if literal and not literal in index.keys() and literal[0] > u'\x19':
try:
index[literal] = count
except Exception, e:
systemLog(ERROR, e)
count += len(line)
fileName = os.path.basename(filePath)
dictHome = os.path.join(info.LOCAL_HOME,
info.PLAIN_DICT_DIR,
fileName)
toUnicode = lambda s: unicode(s, dictionary.getEncoding())
doc = xmltools.generateIndexFile(index)
xmltools.writeIndexFile(doc, os.path.join(dictHome, 'data', 'index.xml'))
savePlainConfiguration(dictionary)
def loadIndex(dictionary):
"""Load index table"""
dictIndex = os.path.join(dictionary.getConfigDir(),
'data', 'index.xml')
index = None
if os.path.exists(dictIndex):
index = xmltools.parseIndexFile(dictIndex)
if not index:
raise Exception, "Index for %s does not exist" % dictionary.getName()
return index
def savePlainConfiguration(dictionary):
"""Write configuration to disk"""
from lib import dicttype
if not dictionary.getType() in dicttype.plainTypes:
systemLog(ERROR, "Request to write configuration to %s of type %s" \
% (dictionary.getName(), dictionary.getType()))
return
md5sum = util.getMD5Sum(dictionary.getPath())
dictDir = dictionary.getConfigDir()
doc = xmltools.generatePlainDictConfig(name=dictionary.getName(),
format=dictionary.getType().getIdName(),
version=dictionary.getVersion(),
authors=dictionary.getAuthors(),
path=dictionary.getPath(),
md5=md5sum,
encoding=dictionary.getEncoding(),
description=dictionary.getDescription(),
licence=dictionary.getLicenceFile())
xmltools.writePlainDictConfig(doc, os.path.join(dictDir,
'conf',
'config.xml'))
opendict-0.6.3/lib/__init__.py 0000644 0001750 0001750 00000000000 10500772667 014646 0 ustar mjoc mjoc opendict-0.6.3/lib/info.py 0000644 0001750 0001750 00000005372 10636242135 014053 0 ustar mjoc mjoc #
# OpenDict
# Copyright (c) 2003-2006 Martynas Jocius
# Copyright (c) 2007 IDILES SYSTEMS, UAB
#
# This program 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 2 of the License, or
# (at your opinion) any later version.
#
# This program is distributed in the hope that will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MECHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more detals.
#
# You shoud have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
# 02111-1307 USA
#
import sys
import os
import imp
# OpenDict version
VERSION = "0.6.3"
# File system objects
__OPENDICT_LOCAL_DIR = ".opendict"
__DICT_DIR = "dictionaries"
__PLUGIN_DICT_DIR = "plugins" # plugin dictionaries
__PLAIN_DICT_DIR = "plain" # used for downloaded dictionaries
__PLAIN_DICT_CONFIG_DIR = "conf"
__PLAIN_DICT_FILE_DIR = "file"
_PLAIN_DICT_DATA_DIR = "data"
LOG_DIR = 'log'
PLAIN_DICT_DIR = os.path.join(__DICT_DIR, __PLAIN_DICT_DIR)
PLUGIN_DICT_DIR = os.path.join(__DICT_DIR, __PLUGIN_DICT_DIR)
GLOBAL_HOME = None
LOCAL_HOME = None
## if sys.platform == "win32":
## import _winreg
## x = _winreg.ConnectRegistry(None, _winreg.HKEY_CURRENT_USER)
## try:
## y = _winreg.OpenKey(x, "SOFTWARE\OpenDict\Settings")
## GLOBAL_HOME = _winreg.QueryValueEx(y, "Path")[0]
## except:
## GLOBAL_HOME = "C:\\Program Files\\OpenDict"
## LOCAL_HOME = GLOBAL_HOME
## else:
## if not os.path.exists(os.path.join(os.environ.get("HOME"),
## __OPENDICT_LOCAL_DIR)):
## os.mkdir(os.path.join(os.environ.get("HOME"), __OPENDICT_LOCAL_DIR))
## LOCAL_HOME = os.path.join(os.environ.get("HOME"), __OPENDICT_LOCAL_DIR)
## GLOBAL_HOME = "/usr/share/opendict"
# main_is_frozen() returns True when running the exe, and False when
# running from a script.
def main_is_frozen():
return (hasattr(sys, "frozen") or # new py2exe
hasattr(sys, "importers") # old py2exe
or imp.is_frozen("__main__")) # tools/freeze
if main_is_frozen():
GLOBAL_HOME = os.path.realpath(os.path.join(os.path.dirname(\
os.path.realpath(__file__)), '../..'))
else:
GLOBAL_HOME = os.path.realpath(os.path.join(os.path.dirname(\
os.path.realpath(__file__)), '..'))
if sys.platform == 'win32':
LOCAL_HOME = GLOBAL_HOME
else:
LOCAL_HOME = os.path.join(os.environ.get('HOME', GLOBAL_HOME),
__OPENDICT_LOCAL_DIR)
opendict-0.6.3/lib/newplugin.py 0000644 0001750 0001750 00000025354 10636242135 015132 0 ustar mjoc mjoc #
# OpenDict
# Copyright (c) 2003-2006 Martynas Jocius
# Copyright (c) 2007 IDILES SYSTEMS, UAB
#
# This program 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 2 of the License, or
# (at your opinion) any later version.
#
# This program is distributed in the hope that will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MECHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more detals.
#
# You shoud have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
# 02111-1307 USA
#
# TODO: rename to "dictplugin.py"
"""
New plugin module
"""
import os
import sys
import traceback
import xml.dom.minidom
from lib import info
from lib import meta
from lib.logger import systemLog, debugLog, DEBUG, INFO, WARNING, ERROR
from lib import util
class PluginInfo:
"""Plugin information"""
def __init__(self, xmlData):
"""Parse XML data and store it into class attributes"""
self.name = None
self.version = None
self.authors = []
self.module = {}
self.encoding = None
self.usesWordList = None
self.opendictVersion = None
self.pythonVersion = None
self.platforms = []
self.description = None
self.licenceFile = None
self.xmlData = xmlData
self._parse()
def _parse(self):
"""Parse plugin information XML data"""
doc = xml.dom.minidom.parseString(self.xmlData)
pluginElement = doc.getElementsByTagName('plugin')[0]
pluginType = pluginElement.getAttribute('type')
if pluginType != 'dictionary':
raise Exception, "Plugin is not dictionary plugin"
# Get name
for nameElement in doc.getElementsByTagName('name'):
for node in nameElement.childNodes:
if node.nodeType == node.TEXT_NODE:
self.name = node.data
# Get version
for versionElement in doc.getElementsByTagName('version'):
for node in versionElement.childNodes:
if node.nodeType == node.TEXT_NODE:
self.version = node.data
# Get authors
for authorElement in doc.getElementsByTagName('author'):
authorName = authorElement.getAttribute('name')
authorEMail = authorElement.getAttribute('email')
self.authors.append({'name': authorName, 'email': authorEMail})
# Get module
for moduleElement in doc.getElementsByTagName('module'):
moduleName = None
for node in moduleElement.childNodes:
if node.nodeType == node.TEXT_NODE:
moduleName = node.data
moduleLang = moduleElement.getAttribute('lang')
self.module = {'name': moduleName, 'lang': moduleLang}
# Get encoding
for encodingElement in doc.getElementsByTagName('encoding'):
for node in encodingElement.childNodes:
if node.nodeType == node.TEXT_NODE:
self.encoding = node.data
# Get info about word list usage
for wordListElement in doc.getElementsByTagName('uses-word-list'):
for node in wordListElement.childNodes:
if node.nodeType == node.TEXT_NODE:
self.usesWordList = node.data.lower() == 'true'
# Get required OpenDict version
for odVersionElement in doc.getElementsByTagName('opendict-version'):
for node in odVersionElement.childNodes:
if node.nodeType == node.TEXT_NODE:
self.opendictVersion = node.data
# Get required Python version
for pyVersionElement in doc.getElementsByTagName('python-version'):
for node in pyVersionElement.childNodes:
if node.nodeType == node.TEXT_NODE:
self.pythonVersion = node.data
# Get supported platforms
for platformElement in doc.getElementsByTagName('platform'):
platformName = platformElement.getAttribute('name')
self.platforms.append({'name': platformName})
self.platforms.sort()
# Get description
for descElement in doc.getElementsByTagName('description'):
for node in descElement.childNodes:
if node.nodeType == node.TEXT_NODE:
self.description = node.data
# Get licence file
for licenceElement in doc.getElementsByTagName('licence'):
for node in licenceElement.childNodes:
if node.nodeType == node.TEXT_NODE:
self.licenceFile = node.data
class DictionaryPlugin(meta.Dictionary):
"""Dictionary plugin handler"""
def __init__(self, path):
"""Prepare plugin and plugin information objects"""
self.path = path
try:
self.info = self._loadInfo(path)
except Exception, e:
raise InvalidPluginException, e
try:
self.dictionary = self._loadPlugin(path)
except Exception, e:
raise InvalidPluginException, e
def getType(self):
"""Return dictionary type"""
from lib import dicttype
return dicttype.PLUGIN
def getName(self):
"""Return plugin name"""
return self.info.name
def setName(self, newName):
"""Set plugin name"""
self.info.name = newName
def getPath(self):
"""Return plugin location"""
return self.path
def getVersion(self):
"""Return version"""
return self.info.version
def getAuthors(self):
"""Return list of authors"""
return self.info.authors
def getModule(self):
"""Return module info"""
return self.info.module
def getEncoding(self):
"""Return encoding used by dictionary"""
return self.info.encoding
def getUsesWordList(self):
"""Return boolean value of word list usage"""
return self.info.usesWordList
def getOpendictVersion(self):
"""Return required min OpenDict version"""
return self.info.opendictVersion
def getPythonVersion(self):
"""Return required min Python version"""
return self.info.pythonVersion
def getPlatforms(self):
"""Return supported platforms"""
return self.info.platforms
def getDescription(self):
"""Returns description text"""
return self.info.description
def getLicence(self):
"""Return licence text (HTML format required)"""
if self.info.licenceFile:
try:
fd = open(os.path.join(self.getPath(), self.info.licenceFile))
data = fd.read()
fd.close()
except Exception, e:
systemLog(ERROR, "Unable to read licence file: %s" % e)
data = 'Error: Licence file not found'
else:
data = ''
return data
def search(self, word):
"""Lookup word"""
return self.dictionary.search(word)
def _loadInfo(self, path):
"""Load plugin information"""
try:
fd = open(os.path.join(path, "plugin.xml"))
xmlData = fd.read()
fd.close()
info = PluginInfo(xmlData)
return info
except Exception, e:
raise InvalidPluginException, \
"Unable to load plugin info (%s)" % e
def _loadPlugin(self, path):
"""Load plugin"""
moduleName = os.path.splitext(self.info.module.get('name'))[0]
fullPath = os.path.join(path, moduleName)
try:
del sys.modules[moduleName]
except:
pass
sys.path.insert(0, path)
module = __import__(moduleName)
sys.path.remove(path)
instance = module.init(info.GLOBAL_HOME)
return instance
# Usable?
def isValid(self):
"""Validate plugin. Validates both plugin and plugin info objects"""
try:
assert hasattr(self.info, "name")
assert hasattr(self.info, "version")
assert hasattr(self.info, "authors")
assert hasattr(self.info, "module")
assert hasattr(self.info, "encoding")
assert hasattr(self.info, "usesWordList")
assert hasattr(self.info, "opendictVersion")
assert hasattr(self.info, "pythonVersion")
assert hasattr(self.info, "platforms")
assert hasattr(self.info, "description")
assert hasattr(self.dictionary, "search")
assert callable(self.dictionary.search)
return True
except:
return False
def _loadDictionaryPlugin(directory):
"""Load dictionary plugin"""
plugin = None
try:
plugin = DictionaryPlugin(directory)
util.correctDictName(plugin)
except InvalidPluginException, e:
systemLog(ERROR, "Unable to load plugin from %s (%s)" % (directory, e))
return plugin
def loadDictionaryPlugins(dictionaries, invalidDictionaries):
"""Load plugins. Returns list of PluginHandler objects"""
pluginDirs = []
globalPluginPath = os.path.join(info.GLOBAL_HOME,
info.__DICT_DIR,
info.__PLUGIN_DICT_DIR)
localPluginPath = os.path.join(info.LOCAL_HOME,
info.__DICT_DIR,
info.__PLUGIN_DICT_DIR)
if os.path.exists(localPluginPath):
pluginDirs = [os.path.join(localPluginPath, fileName) \
for fileName in os.listdir(localPluginPath) \
if os.path.isdir(os.path.join(localPluginPath,
fileName))]
if os.path.exists(globalPluginPath):
for fileName in os.listdir(globalPluginPath):
if os.path.isdir(os.path.join(globalPluginPath, fileName)) \
and not fileName in pluginDirs:
pluginDirs.append(os.path.join(globalPluginPath, fileName))
plugins = []
for dirName in pluginDirs:
plugin = _loadDictionaryPlugin(dirName)
if plugin:
plugins.append(plugin)
dictionaries[plugin.getName()] = plugin
else:
invalidDictionaries.append(dirName)
return plugins
class InvalidPluginException(Exception):
"""This exception should be raised if plugin has some errors"""
if __name__ == "__main__":
loadPlugins()
opendict-0.6.3/lib/dicttype.py 0000644 0001750 0001750 00000005322 10636242135 014740 0 ustar mjoc mjoc #
# OpenDict
# Copyright (c) 2003-2006 Martynas Jocius
# Copyright (c) 2007 IDILES SYSTEMS, UAB
#
# This program 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 2 of the License, or
# (at your opinion) any later version.
#
# This program is distributed in the hope that will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MECHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more detals.
#
# You shoud have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
# 02111-1307 USA
#
"""
Dictionary types
"""
from lib import newplugin
class DictionaryType:
"""Dictionary type interface"""
dictClass = None
fileExtentions = None
name = None
shortIdName = None
def getClass(self):
"""Return dictionary class"""
return self.dictClass
def getFileExtentions(self):
"""Return file extention"""
return self.fileExtentions
def getName(self):
"""Return type name"""
return self.name
def getIdName(self):
"""Return short ID name"""
return self.shortIdName
class TypePlugin(DictionaryType):
"""Dictionary plugin"""
dictClass = newplugin.DictionaryPlugin
fileExtentions = ('zip',)
name = "OpenDict dictionary plugin"
class TypeSlowo(DictionaryType):
"""Slowo dictionary format"""
import parser
dictClass = parser.SlowoParser
fileExtentions = ('dwa',)
name = "Slowo dictionary"
shortIdName = "slowo"
class TypeMova(DictionaryType):
"""Mova dictionary format"""
import parser
dictClass = parser.MovaParser
fileExtentions = ('mova',)
name = "Mova dictionary"
shortIdName = "mova"
class TypeTMX(DictionaryType):
"""TMX dictionary format"""
import parser
dictClass = parser.TMXParser
fileExtentions = ('tmx',)
name = "TMX dictionary"
shortIdName = "tmx"
class TypeDict(DictionaryType):
"""DICT dictionary type"""
import parser
dictClass = parser.DictParser
fileExtentions = ('dict', 'dz',)
name = "DICT dictionary"
shortIdName = "dict"
# Constant instances
PLUGIN = TypePlugin()
SLOWO = TypeSlowo()
MOVA = TypeMova()
#TMX = TypeTMX()
DICT = TypeDict()
# Supported types tuple
supportedTypes = (PLUGIN, SLOWO, MOVA, DICT)
# Plain dictionary types (data file)
plainTypes = (SLOWO, MOVA, DICT)
# Types for which index table is made
indexableTypes = (SLOWO, MOVA)
opendict-0.6.3/lib/threads.py 0000644 0001750 0001750 00000004627 10636242135 014554 0 ustar mjoc mjoc #
# OpenDict
# Copyright (c) 2003-2006 Martynas Jocius
# Copyright (c) 2007 IDILES SYSTEMS, UAB
#
# This program 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 2 of the License, or
# (at your opinion) any later version.
#
# This program is distributed in the hope that will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MECHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more detals.
#
# You shoud have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
# 02111-1307 USA
#
# Module: threads
from threading import *
import sys
import os
import copy
import traceback
import string
class KThread(Thread):
"""Thread that can be killed during its run()"""
def join(self, timeout=None):
"""Kill it"""
Thread.join(self, timeout)
print "Thread killing himself"
#os._exit(0)
class Process:
def __init__(self, func, *param):
self.__done = 0
self.__result = None
self.__status = "working"
self.__C = Condition()
# Seperate thread
self.__T = Thread(target=self.Wrapper, args=(func, param))
self.__T.setName("ProcessThread")
self.__T.start()
def __repr__(self):
return ""
def __call__(self):
self.__C.acquire()
while self.__done == 0:
self.__C.wait()
self.__C.release()
result = copy.copy(self.__result)
return result
def isDone(self):
return self.__done
def stop(self):
# FIXME: this actually doesn't kill the running process
# Needs to be done. Help?
#Thread.join(self.__T, None)
self.__T.join(0)
def Wrapper(self, func, param):
self.__C.acquire()
try:
self.__result = func(*param)
except:
self.__result = None
print string.join(traceback.format_exception(sys.exc_info()[0], sys.exc_info()[1],
sys.exc_info()[2]), "")
self.__done = 1
self.__status = "self.__result"
self.__C.notify()
self.__C.release()
opendict-0.6.3/misc/ 0000755 0001750 0001750 00000000000 10654057460 012731 5 ustar mjoc mjoc opendict-0.6.3/misc/repository/ 0000755 0001750 0001750 00000000000 10654057460 015150 5 ustar mjoc mjoc opendict-0.6.3/misc/repository/Makefile 0000644 0001750 0001750 00000000134 10636242135 016601 0 ustar mjoc mjoc all:
python make-addons-list.py Dictionaries http://db.opendict.idiles.com
mv *.xml Data/
opendict-0.6.3/misc/repository/make-addons-list.py 0000755 0001750 0001750 00000020126 10636242135 020655 0 ustar mjoc mjoc #!/usr/bin/env python
import sys
import os
import zipfile
import md5
import xml.dom.minidom
import xml.dom.ext
#
# Add-ons description file generator for OpenDict
# Copyright (c) 2003-2006 Martynas Jocius
# Copyright (c) 2007 IDILES SYSTEMS, UAB
#
# Fast & dirty code
#
def parsePluginConfig(xmlData):
"""Parse plugin configuration"""
doc = xml.dom.minidom.parseString(xmlData)
name = None
version = None
authors = []
description = None
pluginElement = doc.getElementsByTagName('plugin')[0]
pluginType = pluginElement.getAttribute('type')
if pluginType != 'dictionary':
raise Exception, "Plugin is not dictionary plugin"
# Get name
for nameElement in doc.getElementsByTagName('name'):
for node in nameElement.childNodes:
if node.nodeType == node.TEXT_NODE:
name = node.data
# Get version
for versionElement in doc.getElementsByTagName('version'):
for node in versionElement.childNodes:
if node.nodeType == node.TEXT_NODE:
version = node.data
# Get authors
for authorElement in doc.getElementsByTagName('author'):
authorName = authorElement.getAttribute('name')
authorEMail = authorElement.getAttribute('email')
authors.append({'name': authorName, 'email': authorEMail})
# Get description
for descElement in doc.getElementsByTagName('description'):
for node in descElement.childNodes:
if node.nodeType == node.TEXT_NODE:
description = node.data
result = {}
result['name'] = name
result['version'] = version
result['authors'] = authors
result['description'] = description
return result
def parsePlainConfig(xmlData):
"""Parse plain dict configuration"""
doc = xml.dom.minidom.parseString(xmlData)
name = None
version = None
authors = []
description = None
registers = doc.getElementsByTagName('plain-dictionary')
if len(registers) == 0:
raise "Invalid configuration"
registerElement = registers[0]
for nameElement in registerElement.getElementsByTagName('name'):
for node in nameElement.childNodes:
name = node.data
for versionElement in registerElement.getElementsByTagName('version'):
for node in versionElement.childNodes:
version = node.data.strip()
for authorElement in registerElement.getElementsByTagName('author'):
authors.append({'name': authorElement.getAttribute('name'),
'email': authorElement.getAttribute('email')})
for descElement in \
registerElement.getElementsByTagName('description'):
for node in descElement.childNodes:
description = (description or '') + node.data.strip()
result = {}
result['name'] = name
result['version'] = version
result['authors'] = authors
result['description'] = description
return result
def generateElement(**args):
"""Generate add-on XML DOM elemente"""
doc = xml.dom.minidom.Document()
addonElement = doc.createElement('add-on')
addonElement.setAttribute('type', args.get('type'))
# Name element
nameElement = doc.createElement('name')
addonElement.appendChild(nameElement)
nameElement.appendChild(doc.createTextNode(args.get('name')))
# Version element
versionElement = doc.createElement('version')
addonElement.appendChild(versionElement)
versionElement.appendChild(doc.createTextNode(args.get('version')))
# Authors element
authorsElement = doc.createElement('authors')
addonElement.appendChild(authorsElement)
for author in (args.get('authors') or []):
authorElement = doc.createElement('author')
authorsElement.appendChild(authorElement)
authorElement.setAttribute('name', author.get('name'))
authorElement.setAttribute('email', author.get('email'))
# Description element
descElement = doc.createElement('description')
addonElement.appendChild(descElement)
descElement.appendChild(doc.createTextNode(args.get('description') \
or None))
# MD5 element
md5Element = doc.createElement('md5')
addonElement.appendChild(md5Element)
md5Element.appendChild(doc.createTextNode(args.get('md5sum')))
# URL element
urlElement = doc.createElement('url')
addonElement.appendChild(urlElement)
urlElement.appendChild(doc.createTextNode(args.get('url')))
# Size element
sizeElement = doc.createElement('size')
addonElement.appendChild(sizeElement)
sizeElement.appendChild(doc.createTextNode(str(args.get('size'))))
return addonElement
def listFiles(start, followLinks, myDepth, maxDepth):
"""Return file list"""
files = []
try:
dirList = os.listdir(start)
except:
if os.path.isdir(start):
print 'ERROR: Cannot list directory %s' % start
return files
for item in dirList:
path = os.path.join(start, item)
if os.path.isdir(path) and (followLinks or \
(not followLinks and not islink(path))):
files.extend(listFiles(path, followLinks,
myDepth + 1,
maxDepth))
else:
files.append(path)
return files
def makeDocument(addons):
"""Connect add-on elements to one XML document"""
doc = xml.dom.minidom.Document()
addonsElement = doc.createElement('opendict-add-ons')
doc.appendChild(addonsElement)
for addon in addons:
addonsElement.appendChild(addon)
return doc
def main():
"""Main procedure"""
if len(sys.argv) < 3:
print "Usage: %s " % sys.argv[0]
print "(Example: '%s . http://xxx.yyy.net/dicts')" % sys.argv[0]
sys.exit(1)
d = sys.argv[1]
baseURL = sys.argv[2]
xmlElements = []
for filePath in listFiles(d, True, 0, None):
try:
zipFile = zipfile.ZipFile(filePath, 'r')
except Exception, e:
print "ERROR: %s: %s" % (filePath, e)
continue
# Test CRC
if zipFile.testzip():
raise Exception, _("Dictionary plugin file is corrupted")
# Check if empty
try:
topDirectory = zipFile.namelist()[0]
except Exception, e:
raise Exception, _("Plugin file is empty (%s)" % e)
# Check for validity
for fileInZip in zipFile.namelist():
dirName = os.path.dirname(fileInZip)
fileName = os.path.basename(fileInZip)
topDir = zipFile.namelist()[0]
plainConfigPath = os.path.join(topDir, 'conf', 'config.xml')
pluginConfigPath = os.path.join(topDir, 'plugin.xml')
info = {}
if plainConfigPath in zipFile.namelist():
info.update(parsePlainConfig(zipFile.read(plainConfigPath)))
info['type'] = 'plain-dictionary'
elif pluginConfigPath in zipFile.namelist():
info.update(parsePluginConfig(zipFile.read(pluginConfigPath)))
info['type'] = 'plugin-dictionary'
sz = os.stat(filePath)[6] / 1000
fd = open(filePath)
m = md5.new(fd.read())
fd.close()
checksum = m.hexdigest()
location = baseURL + '/' + filePath
xmlElements.append(generateElement(type=info.get('type'),
name=info.get('name'),
version=info.get('version'),
authors=info.get('authors'),
description=info.get('description'),
url=location,
md5sum=checksum,
size=sz))
print "* %s" % filePath
doc = makeDocument(xmlElements)
fd = open('opendict-add-ons.xml', 'w')
xml.dom.ext.PrettyPrint(doc, fd)
fd.close()
if __name__ == "__main__":
main()
opendict-0.6.3/misc/repository/README.txt 0000644 0001750 0001750 00000000202 10526270664 016641 0 ustar mjoc mjoc Files here are used on the repository server to generate dictionary
lists to be installed. OpenDict end-users should ignore them. opendict-0.6.3/misc/opendict.desktop 0000644 0001750 0001750 00000000505 10537777640 016142 0 ustar mjoc mjoc [Desktop Entry]
Encoding=UTF-8
Name=Dictionary OpenDict
Name[lt]=Žodynas „OpenDict“
Comment=Lookup words in a local or Internet dictionary
Comment[lt]=Ieškoti žodžių kompiuterio arba Interneto žodyne
Exec=opendict
Icon=opendict
StartupNotify=true
Terminal=false
Type=Application
Categories=GTK;Utility;Dictionary;
opendict-0.6.3/Makefile 0000644 0001750 0001750 00000004065 10654057311 013436 0 ustar mjoc mjoc # OpenDict Makefile
#
DESTDIR = /usr
bindir = $(DESTDIR)/bin
icondir = $(DESTDIR)/share/icons/hicolor
opendictdir = $(DESTDIR)/share/opendict
install:
mkdir -p $(opendictdir)/lib/extra
mkdir -p $(opendictdir)/lib/gui
cp -r lib/*.py $(opendictdir)/lib
cp -r lib/extra/*.py $(opendictdir)/lib/extra
cp -r lib/gui/*.py $(opendictdir)/lib/gui
chmod -R a+rX $(opendictdir)/lib
mkdir -p $(opendictdir)/pixmaps
cp pixmaps/*.png $(opendictdir)/pixmaps
chmod -R a+rX $(opendictdir)/pixmaps
cp pixmaps/icon-24x24.png $(icondir)/24x24/apps/opendict.png
cp pixmaps/icon-32x32.png $(icondir)/32x32/apps/opendict.png
cp pixmaps/icon-48x48.png $(icondir)/48x48/apps/opendict.png
cp pixmaps/icon-96x96.png $(icondir)/96x96/apps/opendict.png
cp pixmaps/SVG/icon-rune.svg $(icondir)/scalable/apps/opendict.svg
$(MAKE) -C po install prefix=$(DESTDIR)
cp opendict.py $(opendictdir)
chmod a+rx $(opendictdir)/opendict.py
cp copying.html $(opendictdir)
chmod a+r $(opendictdir)/copying.html
ln -sf $(opendictdir)/opendict.py $(bindir)/opendict
cp misc/opendict.desktop $(DESTDIR)/share/applications
chmod a+r $(DESTDIR)/share/applications/opendict.desktop
uninstall:
rm -f $(DESTDIR)/share/applications/opendict.desktop
rm -f $(bindir)/opendict
rm -f $(opendictdir)/copying.html
rm -f $(opendictdir)/opendict.py
$(MAKE) -C po uninstall prefix=$(DESTDIR)
rm -f $(icondir)/24x24/apps/opendict.png
rm -f $(icondir)/32x32/apps/opendict.png
rm -f $(icondir)/48x48/apps/opendict.png
rm -f $(icondir)/96x96/apps/opendict.png
rm -f $(icondir)/scalable/apps/opendict.svg
rm -f $(opendictdir)/pixmaps/*.png
rmdir $(opendictdir)/pixmaps
rm -f $(opendictdir)/lib/gui/*.py*
rm -f $(opendictdir)/lib/extra/*.py*
rm -f $(opendictdir)/lib/*.py*
rmdir $(opendictdir)/lib/extra
rmdir $(opendictdir)/lib/gui
rmdir $(opendictdir)/lib
rmdir $(opendictdir)
clean:
for f in `find . -name '*.pyc'`; do rm $$f; done
for f in `find . -name '*.pyo'`; do rm $$f; done
for f in `find . -name '*.py~'`; do rm $$f; done
for f in `find . -name '*~'`; do rm $$f; done
$(MAKE) -C po clean
opendict-0.6.3/win32/ 0000755 0001750 0001750 00000000000 10654057460 012740 5 ustar mjoc mjoc opendict-0.6.3/win32/setup.manifest.py 0000644 0001750 0001750 00000003217 10636242135 016255 0 ustar mjoc mjoc # Copy compile.bat and setup.py to root directory and run compile.bat
from distutils.core import setup
import py2exe
import sys
import glob
# The manifest will be inserted as resource into opendict.exe. This
# gives the controls the Windows XP appearance (if run on XP ;-)
#
# Another option would be to store if in a file named
# opendict.exe.manifest, and probably copy it with the data_files
# option.
#
manifest_template = '''
%(prog)s Program
'''
RT_MANIFEST = 24
################################################################
# arguments for the setup() call
opendict = dict(
script = "opendict.py",
other_resources = [(RT_MANIFEST, 1, manifest_template % dict(prog="OpenDict"))],
)
options = {"py2exe": {"compressed": 1,
"optimize": 2}}
setup(
name="OpenDict",
version="0.6.3",
options = options,
zipfile = None,
package_dir = {"": "lib"},
windows = [opendict],
data_files=[("pixmaps", glob.glob("pixmaps/\\*.png"))],
)
opendict-0.6.3/win32/compile.bat 0000755 0001750 0001750 00000000660 10500772667 015070 0 ustar mjoc mjoc rem Copy compile.bat and setup.py to root directory and run compile.bat
C:\Python24\python.exe setup.py py2exe --packages encodings
rem Use this to get controls with the Windows XP appearance
rem C:\Python24\python.exe setup.manifest.py py2exe --packages encodings
copy copying.html dist
echo don't forget to copy msvcr71.dll from wxPython/distrib/msw/ to dist
echo before making a release
copy C:\Python24\msvcr71.dll dist
opendict-0.6.3/win32/make.py 0000644 0001750 0001750 00000001665 10640522715 014232 0 ustar mjoc mjoc # Make Win32 executable for OpenDict
import os
import sys
#sys.path = [os.path.join(os.curdir, "lib")] + sys.path
sys.path = ["C:\\Program files\\OpenDict-dev\Opendict-source\lib"] + sys.path
odlist = "wx.Python.html,shutil,zipfile,string,"
list = "encodings,codecs,xml,ConfigParser,"\
"Cookie,copy,ftplib,glob,gopherlib,gzip,htmllib,HTMLParser,httplib,"\
"locale,re,sgmllib,socket,stat,StringIO,threading,thread,"\
"urllib,urllib2,urlparse,uu,warnings,webbrowser"
command = "C:\\python24\\python.exe setup.py py2exe -w " \
"--icon ..\\pixmaps\\icon.ico -i %s " \
"--packages encodings --force-imports encodings" % (odlist+list)
#command = "C:\\python22\\python.exe setup.py py2exe --icon ..\\pixmaps\\icon.ico"
print "Command: '%s'\n" % command
out = os.popen(command)
print "\"dist\" directory will be created."
print "Compiling, will take a minute...\n", out.read()
raw_input("...")
opendict-0.6.3/win32/setup.py 0000644 0001750 0001750 00000000546 10636242135 014452 0 ustar mjoc mjoc # Copy compile.bat and setup.py to root directory and run compile.bat
from distutils.core import setup
import py2exe
import sys
import glob
setup(
name="opendict",
version="0.6.3",
zipfile=None,
package_dir = {"": "lib"},
windows=["opendict.py"],
data_files=[("pixmaps", glob.glob("pixmaps/\\*.png"))],
)
opendict-0.6.3/win32/install_script.iss 0000644 0001750 0001750 00000013644 10500772667 016525 0 ustar mjoc mjoc ; Script generated by the My Inno Setup Extensions Script Wizard.
; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!
[Setup]
AppName=OpenDict
AppVerName=OpenDict 0.5.6
AppPublisher=Martynas Jocius
;AppPublisherURL=http://opendict.sourceforge.net
;AppSupportURL=http://opendict.sourceforge.net
;AppUpdatesURL=http://opendict.sourceforge.net
DefaultDirName={pf}\OpenDict
DisableDirPage=no
DefaultGroupName=OpenDict
AllowNoIcons=yes
LicenseFile=C:\Program Files\OpenDict-dev\OpenDict-source\copying.txt
; MessagesFile=compiler:lithuanian.isl
[Tasks]
; NOTE: The following entry contains English phrases ("Create a desktop icon" and "Additional icons"). You are free to translate them into another language if required.
Name: "desktopicon"; Description: "Create a &desktop icon"; GroupDescription: "Additional icons:"
; NOTE: The following entry contains English phrases ("Create a Quick Launch icon" and "Additional icons"). You are free to translate them into another language if required.
Name: "quicklaunchicon"; Description: "Create a &Quick Launch icon"; GroupDescription: "Additional icons:"; Flags: unchecked
[Files]
Source: "C:\Program Files\OpenDict-dev\OpenDict-source\win32\dist\opendict\opendict.exe"; DestDir: "{app}"; Flags: ignoreversion
Source: "C:\Program Files\OpenDict-dev\OpenDict-source\win32\dist\opendict\_socket.pyd"; DestDir: "{app}"; Flags: ignoreversion
Source: "C:\Program Files\OpenDict-dev\OpenDict-source\win32\dist\opendict\_ssl.pyd"; DestDir: "{app}"; Flags: ignoreversion
Source: "C:\Program Files\OpenDict-dev\OpenDict-source\win32\dist\opendict\pyexpat.pyd"; DestDir: "{app}"; Flags: ignoreversion
Source: "C:\Program Files\OpenDict-dev\OpenDict-source\win32\dist\opendict\_socket.pyd"; DestDir: "{app}"; Flags: ignoreversion
Source: "C:\Program Files\OpenDict-dev\OpenDict-source\win32\dist\opendict\_sre.pyd"; DestDir: "{app}"; Flags: ignoreversion
Source: "C:\Program Files\OpenDict-dev\OpenDict-source\win32\dist\opendict\_winreg.pyd"; DestDir: "{app}"; Flags: ignoreversion
Source: "C:\Program Files\OpenDict-dev\OpenDict-source\win32\dist\opendict\htmlc.pyd"; DestDir: "{app}"; Flags: ignoreversion
Source: "C:\Program Files\OpenDict-dev\OpenDict-source\win32\dist\opendict\python23.dll"; DestDir: "{app}"; Flags: ignoreversion
Source: "C:\Program Files\OpenDict-dev\OpenDict-source\win32\dist\opendict\wxc.pyd"; DestDir: "{app}"; Flags: ignoreversion
Source: "C:\Program Files\OpenDict-dev\OpenDict-source\win32\dist\opendict\wxmsw24h.dll"; DestDir: "{app}"; Flags: ignoreversion
Source: "C:\Program Files\OpenDict-dev\OpenDict-source\win32\dist\opendict\zlib.pyd"; DestDir: "{app}"; Flags: ignoreversion
Source: "C:\Program Files\OpenDict-dev\OpenDict-source\copying.txt"; DestDir: "{app}"; Flags: ignoreversion
Source: "C:\Program Files\OpenDict-dev\OpenDict-source\OpenDict_LT_instrukcija.txt"; DestDir: "{app}"; Flags: isreadme
Source: "C:\Program Files\OpenDict-dev\OpenDict-source\po\lt\opendict.mo"; DestDir: "{app}\locale\lt\"; Flags: ignoreversion
;Source: "C:\Program Files\OpenDict-dev\OpenDict-source\todo.txt"; DestDir: "{app}"; Flags: ignoreversion
;Source: "C:\Program Files\OpenDict-dev\OpenDict-source\doc\Design.txt"; DestDir: "{app}\doc\"; Flags: ignoreversion
;Source: "C:\Program Files\OpenDict-dev\OpenDict-source\doc\Manual.html"; DestDir: "{app}\doc\"; Flags: ignoreversion
Source: "C:\Program Files\OpenDict-dev\OpenDict-source\pixmaps\clear.xpm"; DestDir: "{app}\pixmaps\"; Flags: ignoreversion
Source: "C:\Program Files\OpenDict-dev\OpenDict-source\pixmaps\hide.xpm"; DestDir: "{app}\pixmaps\"; Flags: ignoreversion
Source: "C:\Program Files\OpenDict-dev\OpenDict-source\pixmaps\logo.xpm"; DestDir: "{app}\pixmaps\"; Flags: ignoreversion
Source: "C:\Program Files\OpenDict-dev\OpenDict-source\pixmaps\icon.xpm"; DestDir: "{app}\pixmaps\"; Flags: ignoreversion
Source: "C:\Program Files\OpenDict-dev\OpenDict-source\pixmaps\icon.png"; DestDir: "{app}\pixmaps\"; Flags: ignoreversion
Source: "C:\Program Files\OpenDict-dev\OpenDict-source\pixmaps\search.xpm"; DestDir: "{app}\pixmaps\"; Flags: ignoreversion
Source: "C:\Program Files\OpenDict-dev\OpenDict-source\pixmaps\right.xpm"; DestDir: "{app}\pixmaps\"; Flags: ignoreversion
Source: "C:\Program Files\OpenDict-dev\OpenDict-source\pixmaps\left.xpm"; DestDir: "{app}\pixmaps\"; Flags: ignoreversion
Source: "C:\Program Files\OpenDict-dev\OpenDict-source\pixmaps\plugin.xpm"; DestDir: "{app}\pixmaps\"; Flags: ignoreversion
Source: "C:\Program Files\OpenDict-dev\OpenDict-source\pixmaps\register.xpm"; DestDir: "{app}\pixmaps\"; Flags: ignoreversion
Source: "C:\Program Files\OpenDict-dev\OpenDict-source\pixmaps\group.xpm"; DestDir: "{app}\pixmaps\"; Flags: ignoreversion
Source: "C:\Program Files\OpenDict-dev\OpenDict-source\pixmaps\stop.xpm"; DestDir: "{app}\pixmaps\"; Flags: ignoreversion
; NOTE: Don't use "Flags: ignoreversion" on any shared system files
[Icons]
Name: "{group}\OpenDict"; Filename: "{app}\opendict.exe"
Name: "{userdesktop}\OpenDict"; Filename: "{app}\opendict.exe"; Tasks: desktopicon
Name: "{userappdata}\Microsoft\Internet Explorer\Quick Launch\OpenDict"; Filename: "{app}\opendict.exe"; Tasks: quicklaunchicon
; [Messages]
; MessagesFile=compiler:lithuanian.isl
[Run]
; NOTE: The following entry contains an English phrase ("Launch"). You are free to translate it into another language if required.
Filename: "{app}\opendict.exe"; Description: "Launch OpenDict"; Flags: shellexec postinstall skipifsilent
[Registry]
Root: HKCU; Subkey: "Software\OpenDict"; Flags: uninsdeletekeyifempty
Root: HKCU; Subkey: "Software\OpenDict"; Flags: uninsdeletekey
Root: HKCU; Subkey: "Software\OpenDict\Settings"; ValueType: string; ValueName: "Path"; ValueData: "{app}"
;Root: HKLM; Subkey: "Software\OpenDict"; Flags: uninsdeletekeyifempty
;Root: HKLM; Subkey: "Software\OpenDict"; Flags: uninsdeletekey
;Root: HKLM; Subkey: "Software\OpenDict\Settings"; ValueType: string; ValueName: "Path"; ValueData: "{app}"
opendict-0.6.3/TODO.txt 0000644 0001750 0001750 00000001502 10500772667 013305 0 ustar mjoc mjoc TODO for OpenDict
Status:
x -- done
* -- not finished
? -- needs to be discussed
[ ] Let DICT connection be handled as a dictionary and be kept
in Dictionaries menu. Let it have user defined names. Make "Manage
DICT Connections" for that.
[ ] Ability to merge dictionaries in editor
[ ] Suggestions when search is unsuccessfull. Idea: if search gives no
results, drop the last letter of the world (i.e. to make prular to
single); drop another one if not results and repeat this for 3-4
times. Might be enough. An option for such search should be available
in prefernces dialog. This by default should be turned on. A warning
about slow search also should be added.
[ ] Remove option entries for saving window size and position.
[ ] Remember last used dictionary and load it on startup if no default
dictionary specified.
opendict-0.6.3/AUTHORS.txt 0000644 0001750 0001750 00000000653 10636242135 013663 0 ustar mjoc mjoc OpenDict Authors
================
Last updated: 2007-06-20
o Martynas Jocius
Maintainer and main developer
o Kęstutis Biliūnas
Debian developer, contributor
o Linas Valiukas
MacOS X port
o Nerijus Baliūnas
Developer of better MS Windows platform support
o Mantas Kriaučiūnas
Past developer
opendict-0.6.3/scripts/ 0000755 0001750 0001750 00000000000 10654057460 013465 5 ustar mjoc mjoc opendict-0.6.3/scripts/release.sh 0000755 0001750 0001750 00000001275 10512634712 015443 0 ustar mjoc mjoc #!/bin/sh
#
# Easy releasy script. Use before releasing software.
#
NAME=$1
INDIR=$2
OUTDIR=$3
if [[ $NAME == "" ]] || [[ $INDIR == "" ]]; then
echo "Usage: $0 "
exit 1;
fi
if [[ $UID != "0" ]]; then
echo "You should be root (or modify this script to avoid root :)"
exit 1;
fi
cd $INDIR && make clean
rm -rf "$OUTDIR/$NAME*"
cp -r "$INDIR" "$OUTDIR/$NAME"
cd $OUTDIR
rm -rf $NAME.zip
rm -rf $NAME.tar.gz
for f in `find "$NAME" -name ".svn"`; do echo Removing "$f" && rm -rf "$f"; done;
zip -r "$NAME.zip" "$NAME"
tar -cf "$NAME.tar" "$NAME"
gzip "$NAME.tar"
echo
echo "Release files created. Do not forget to create SVN TAG when tested."
opendict-0.6.3/scripts/count_code.py 0000644 0001750 0001750 00000002044 10500772667 016164 0 ustar mjoc mjoc #!/usr/bin/env python
# Count OpenDict Code Lines
# Copyright (c) Martynas Jocius
# Licensed under the GNU GPL.
import sys
import glob
def count(file):
fd = open(file)
all = 0
code = 0
for line in fd.readlines():
all += 1
if line.strip() == "":
continue
if line.find("#") > -1:
if line[0] == "#":
continue
elif line[0:line.index("#")].strip() == "":
continue
code += 1
print "%s:" % file
print " Number of lines: ", all
print " Number of code lines:", code
return (all, code)
if __name__ == "__main__":
if len(sys.argv) == 1:
print "Usage: %s [file1] [file2] ..." % sys.argv[0]
sys.exit(1)
lines = 0
code = 0
for arg in sys.argv[1:]:
for file in glob.glob(arg):
new = count(file)
lines += new[0]
code += new[1]
print "\nTotal number of lines: %d" % lines
print "Total number of code lines: %d" % code
opendict-0.6.3/scripts/slowo2mova.py 0000644 0001750 0001750 00000001036 10500772667 016152 0 ustar mjoc mjoc #!/usr/bin/env python
# slowo2mova
# Copyright (c) 2003 Martynas Jocius
import sys
def slowo2mova(sfName, mfName):
fdSlowo = open(sfName)
fdMova = open(mfName, "w")
for line in fdSlowo.readlines():
fdMova.write(line.split("=")[0].strip()+" "+line.split("=")[1].strip()+"\n")
fdSlowo.close()
fdMova.close()
if __name__ == "__main__":
if len(sys.argv) < 3:
print "Usage %s " % sys.argv[0]
sys.exit(1)
slowo2mova(sys.argv[1], sys.argv[2])
opendict-0.6.3/scripts/unzip.py 0000644 0001750 0001750 00000001040 10500772667 015202 0 ustar mjoc mjoc #!/usr/bin/env python
# learn how to use zipfile module
import sys, zipfile, os, os.path
def unzip_file_into_dir(file, dir):
os.mkdir(dir, 0777)
zfobj = zipfile.ZipFile(file)
for name in zfobj.namelist():
if name.endswith('/'):
os.mkdir(os.path.join(dir, name))
else:
outfile = open(os.path.join(dir, name), 'wb')
outfile.write(zfobj.read(name))
outfile.close()
def main():
unzip_file_into_dir(open(sys.argv[1]), sys.argv[2])
if __name__ == '__main__': main()
opendict-0.6.3/scripts/msgfmt.py 0000644 0001750 0001750 00000012576 10500772667 015352 0 ustar mjoc mjoc #! /usr/bin/env python
# Written by Martin v. Lwis
"""Generate binary message catalog from textual translation description.
This program converts a textual Uniforum-style message catalog (.po file) into
a binary GNU catalog (.mo file). This is essentially the same function as the
GNU msgfmt program, however, it is a simpler implementation.
Usage: msgfmt.py [OPTIONS] filename.po
Options:
-o file
--output-file=file
Specify the output file to write to. If omitted, output will go to a
file named filename.mo (based off the input file name).
-h
--help
Print this message and exit.
-V
--version
Display version information and exit.
"""
import sys
import os
import getopt
import struct
import array
__version__ = "1.1"
MESSAGES = {}
def usage(code, msg=''):
print >> sys.stderr, __doc__
if msg:
print >> sys.stderr, msg
sys.exit(code)
def add(id, str, fuzzy):
"Add a non-fuzzy translation to the dictionary."
global MESSAGES
if not fuzzy and str:
MESSAGES[id] = str
def generate():
"Return the generated output."
global MESSAGES
keys = MESSAGES.keys()
# the keys are sorted in the .mo file
keys.sort()
offsets = []
ids = strs = ''
for id in keys:
# For each string, we need size and file offset. Each string is NUL
# terminated; the NUL does not count into the size.
offsets.append((len(ids), len(id), len(strs), len(MESSAGES[id])))
ids += id + '\0'
strs += MESSAGES[id] + '\0'
output = ''
# The header is 7 32-bit unsigned integers. We don't use hash tables, so
# the keys start right after the index tables.
# translated string.
keystart = 7*4+16*len(keys)
# and the values start after the keys
valuestart = keystart + len(ids)
koffsets = []
voffsets = []
# The string table first has the list of keys, then the list of values.
# Each entry has first the size of the string, then the file offset.
for o1, l1, o2, l2 in offsets:
koffsets += [l1, o1+keystart]
voffsets += [l2, o2+valuestart]
offsets = koffsets + voffsets
output = struct.pack("iiiiiii",
0x950412de, # Magic
0, # Version
len(keys), # # of entries
7*4, # start of key index
7*4+len(keys)*8, # start of value index
0, 0) # size and offset of hash table
output += array.array("i", offsets).tostring()
output += ids
output += strs
return output
def make(filename, outfile):
ID = 1
STR = 2
# Compute .mo name from .po name and arguments
if filename.endswith('.po'):
infile = filename
else:
infile = filename + '.po'
if outfile is None:
outfile = os.path.splitext(infile)[0] + '.mo'
try:
lines = open(infile).readlines()
except IOError, msg:
print >> sys.stderr, msg
sys.exit(1)
section = None
fuzzy = 0
# Parse the catalog
lno = 0
for l in lines:
lno += 1
# If we get a comment line after a msgstr, this is a new entry
if l[0] == '#' and section == STR:
add(msgid, msgstr, fuzzy)
section = None
fuzzy = 0
# Record a fuzzy mark
if l[:2] == '#,' and l.find('fuzzy'):
fuzzy = 1
# Skip comments
if l[0] == '#':
continue
# Now we are in a msgid section, output previous section
if l.startswith('msgid'):
if section == STR:
add(msgid, msgstr, fuzzy)
section = ID
l = l[5:]
msgid = msgstr = ''
# Now we are in a msgstr section
elif l.startswith('msgstr'):
section = STR
l = l[6:]
# Skip empty lines
l = l.strip()
if not l:
continue
# XXX: Does this always follow Python escape semantics?
l = eval(l)
if section == ID:
msgid += l
elif section == STR:
msgstr += l
else:
print >> sys.stderr, 'Syntax error on %s:%d' % (infile, lno), \
'before:'
print >> sys.stderr, l
sys.exit(1)
# Add last entry
if section == STR:
add(msgid, msgstr, fuzzy)
# Compute output
output = generate()
try:
open(outfile,"wb").write(output)
except IOError,msg:
print >> sys.stderr, msg
def main():
try:
opts, args = getopt.getopt(sys.argv[1:], 'hVo:',
['help', 'version', 'output-file='])
except getopt.error, msg:
usage(1, msg)
outfile = None
# parse options
for opt, arg in opts:
if opt in ('-h', '--help'):
usage(0)
elif opt in ('-V', '--version'):
print >> sys.stderr, "msgfmt.py", __version__
sys.exit(0)
elif opt in ('-o', '--output-file'):
outfile = arg
# do it
if not args:
print >> sys.stderr, 'No input file given'
print >> sys.stderr, "Try `msgfmt --help' for more information."
return
for filename in args:
make(filename, outfile)
if __name__ == '__main__':
main()
opendict-0.6.3/scripts/make-addons-list.py 0000755 0001750 0001750 00000020007 10636242135 017170 0 ustar mjoc mjoc #!/usr/bin/env python
import sys
import os
import zipfile
import md5
import xml.dom.minidom
import xml.dom.ext
#
# Add-ons description file generator for OpenDict
# Copyright (c) 2005 Martynas Jocius
#
# Fast code, dirty code
#
def parsePluginConfig(xmlData):
"""Parse plugin configuration"""
doc = xml.dom.minidom.parseString(xmlData)
name = None
version = None
authors = []
description = None
pluginElement = doc.getElementsByTagName('plugin')[0]
pluginType = pluginElement.getAttribute('type')
if pluginType != 'dictionary':
raise Exception, "Plugin is not dictionary plugin"
# Get name
for nameElement in doc.getElementsByTagName('name'):
for node in nameElement.childNodes:
if node.nodeType == node.TEXT_NODE:
name = node.data
# Get version
for versionElement in doc.getElementsByTagName('version'):
for node in versionElement.childNodes:
if node.nodeType == node.TEXT_NODE:
version = node.data
# Get authors
for authorElement in doc.getElementsByTagName('author'):
authorName = authorElement.getAttribute('name')
authorEMail = authorElement.getAttribute('email')
authors.append({'name': authorName, 'email': authorEMail})
# Get description
for descElement in doc.getElementsByTagName('description'):
for node in descElement.childNodes:
if node.nodeType == node.TEXT_NODE:
description = node.data
result = {}
result['name'] = name
result['version'] = version
result['authors'] = authors
result['description'] = description
return result
def parsePlainConfig(xmlData):
"""Parse plain dict configuration"""
doc = xml.dom.minidom.parseString(xmlData)
name = None
version = None
authors = []
description = None
registers = doc.getElementsByTagName('plain-dictionary')
if len(registers) == 0:
raise "Invalid configuration"
registerElement = registers[0]
for nameElement in registerElement.getElementsByTagName('name'):
for node in nameElement.childNodes:
name = node.data
for versionElement in registerElement.getElementsByTagName('version'):
for node in versionElement.childNodes:
version = node.data.strip()
for authorElement in registerElement.getElementsByTagName('author'):
authors.append({'name': authorElement.getAttribute('name'),
'email': authorElement.getAttribute('email')})
for descElement in \
registerElement.getElementsByTagName('description'):
for node in descElement.childNodes:
description = (description or '') + node.data.strip()
result = {}
result['name'] = name
result['version'] = version
result['authors'] = authors
result['description'] = description
return result
def generateElement(**args):
"""Generate add-on XML DOM elemente"""
doc = xml.dom.minidom.Document()
addonElement = doc.createElement('add-on')
addonElement.setAttribute('type', args.get('type'))
# Name element
nameElement = doc.createElement('name')
addonElement.appendChild(nameElement)
nameElement.appendChild(doc.createTextNode(args.get('name')))
# Version element
versionElement = doc.createElement('version')
addonElement.appendChild(versionElement)
versionElement.appendChild(doc.createTextNode(args.get('version')))
# Authors element
authorsElement = doc.createElement('authors')
addonElement.appendChild(authorsElement)
for author in (args.get('authors') or []):
authorElement = doc.createElement('author')
authorsElement.appendChild(authorElement)
authorElement.setAttribute('name', author.get('name'))
authorElement.setAttribute('email', author.get('email'))
# Description element
descElement = doc.createElement('description')
addonElement.appendChild(descElement)
descEscaped = "%s" % args.get('description', '')
descElement.appendChild(doc.createTextNode(descEscaped))
# MD5 element
md5Element = doc.createElement('md5')
addonElement.appendChild(md5Element)
md5Element.appendChild(doc.createTextNode(args.get('md5sum')))
# URL element
urlElement = doc.createElement('url')
addonElement.appendChild(urlElement)
urlElement.appendChild(doc.createTextNode(args.get('url')))
# Size element
sizeElement = doc.createElement('size')
addonElement.appendChild(sizeElement)
sizeElement.appendChild(doc.createTextNode(str(args.get('size'))))
return addonElement
def listFiles(start, followLinks, myDepth, maxDepth):
"""Return file list"""
files = []
try:
dirList = os.listdir(start)
except:
if os.path.isdir(start):
print 'ERROR: Cannot list directory %s' % start
return files
for item in dirList:
path = os.path.join(start, item)
if os.path.isdir(path) and (followLinks or \
(not followLinks and not islink(path))):
files.extend(listFiles(path, followLinks,
myDepth + 1,
maxDepth))
else:
files.append(path)
return files
def makeDocument(addons):
"""Connect add-on elements to one XML document"""
doc = xml.dom.minidom.Document()
addonsElement = doc.createElement('opendict-add-ons')
doc.appendChild(addonsElement)
for addon in addons:
addonsElement.appendChild(addon)
return doc
def main():
"""Main procedure"""
if len(sys.argv) < 3:
print "Usage: %s " % sys.argv[0]
print "(Example: '%s . http://xxx.yyy.net/dicts')" % sys.argv[0]
sys.exit(1)
d = sys.argv[1]
baseURL = sys.argv[2]
xmlElements = []
for filePath in listFiles(d, True, 0, None):
try:
zipFile = zipfile.ZipFile(filePath, 'r')
except Exception, e:
print "ERROR: %s: %s" % (filePath, e)
continue
# Test CRC
if zipFile.testzip():
raise Exception, _("Dictionary plugin file is corrupted")
# Check if empty
try:
topDirectory = zipFile.namelist()[0]
except Exception, e:
raise Exception, _("Plugin file is empty (%s)" % e)
# Check for validity
for fileInZip in zipFile.namelist():
dirName = os.path.dirname(fileInZip)
fileName = os.path.basename(fileInZip)
topDir = zipFile.namelist()[0]
plainConfigPath = os.path.join(topDir, 'conf', 'config.xml')
pluginConfigPath = os.path.join(topDir, 'plugin.xml')
info = {}
if plainConfigPath in zipFile.namelist():
info.update(parsePlainConfig(zipFile.read(plainConfigPath)))
info['type'] = 'plain-dictionary'
elif pluginConfigPath in zipFile.namelist():
info.update(parsePluginConfig(zipFile.read(pluginConfigPath)))
info['type'] = 'plugin-dictionary'
sz = os.stat(filePath)[6] / 1000
fd = open(filePath)
m = md5.new(fd.read())
fd.close()
checksum = m.hexdigest()
location = baseURL + '/' + filePath
xmlElements.append(generateElement(type=info.get('type'),
name=info.get('name'),
version=info.get('version'),
authors=info.get('authors'),
description=info.get('description'),
url=location,
md5sum=checksum,
size=sz))
print "* %s" % filePath
doc = makeDocument(xmlElements)
fd = open('opendict-add-ons.xml', 'w')
xml.dom.ext.PrettyPrint(doc, fd)
fd.close()
if __name__ == "__main__":
main()
opendict-0.6.3/scripts/make_hash.py 0000644 0001750 0001750 00000001014 10500772667 015756 0 ustar mjoc mjoc #!/usr/bin/env python
# MakeHash
# Utility for dictionary hash table making
# mjoc, 2003
import sys
if len(sys.argv) < 3:
print "Usage: %s " % sys.argv[0]
sys.exit(1)
dict = open(sys.argv[1], "r")
hash = open(sys.argv[2], "w")
line = dict.readline()
l = line[0].lower()
n = 0
hash.write(l+" "+repr(n)+"\n")
n += len(line)
for line in dict.readlines():
if line[0].lower() != l:
l = line[0]
hash.write(l+" "+repr(n)+"\n")
n += len(line)
dict.close()
hash.close()
opendict-0.6.3/scripts/w2u.py 0000644 0001750 0001750 00000001255 10500772667 014562 0 ustar mjoc mjoc #!/usr/bin/env python
# w2u
# Convert windows text file to unix text file
# (by changing line end symbol)
# Martynas Jocius
import sys
import glob
def w2u(args):
files = []
for arg in args:
files.extend(glob.glob(arg))
for fname in files:
print "Working on %s..." % fname
old = open(fname)
data = ""
for line in old.readlines():
data += line.rstrip() + "\n"
new = open(fname, "w")
new.write(data)
old.close()
new.close()
if __name__ == "__main__":
if len(sys.argv) < 2:
print "Usage: %s [file2] [file3] ..." % sys.argv[0]
sys.exit(1)
w2u(sys.argv[1:])
opendict-0.6.3/scripts/zip.py 0000644 0001750 0001750 00000000770 10500772667 014650 0 ustar mjoc mjoc from zipfile import ZipFile
from glob import glob
import sys
import os
def compress(z, dir):
zip = ZipFile(z, "w")
files = glob(os.path.join(dir, "*"))
for file in files:
zip.write(file)
zip.close()
if __name__ == "__main__":
if len(sys.argv) < 3:
print "Usage: %s " % sys.argv[0]
sys.exit(1)
print "Packing '%s' to '%s'..." % (sys.argv[2], sys.argv[1]),
compress(sys.argv[1], sys.argv[2])
print "done"
opendict-0.6.3/scripts/make_hash2.py 0000644 0001750 0001750 00000001127 10500772667 016045 0 ustar mjoc mjoc #!/usr/bin/env python
# MakeHash
# Utility for dictionary hash table making
# mjoc, 2003
import sys
if len(sys.argv) < 3:
print "Usage: %s " % sys.argv[0]
sys.exit(1)
fdDict = open(sys.argv[1])
fdHash = open(sys.argv[2], "w")
print "Indexing..."
hash = {}
line = fdDict.readline()
l = line[0:2].lower()
n = 0
hash[l] = n
n += len(line)
for line in fdDict.readlines():
l = line[0:2].lower()
if not hash.has_key(l):
hash[l] = n
n += len(line)
for l, p in hash.items():
fdHash.write("%s %s\n" % (l, p))
fdDict.close()
fdHash.close()
opendict-0.6.3/scripts/install-odp.sh 0000755 0001750 0001750 00000001722 10500772667 016257 0 ustar mjoc mjoc #!/bin/bash
# OpenDict Plugin installation helper script
# Copyright (c) 2005 Martynas Jocius
#
# With this script one can install OpenDict plugins without using
# OpenDict itself. This may be handy for installing plugins from
# scripts or other automatic method.
PLUGINDIR=/home/`id -un`/.opendict/plugins
if [ ! $1 ]
then
echo "OpenDict plugin installation helper"
echo "Copyright (c) 2005 Martynas Jocius "
echo
echo "Usage: $0 [--global]"
echo
echo " --global Install plugin globally to /usr/share/opendict"
exit 1
fi
if [ ! -e $1 ]
then
echo "Error: File '$1' does not exist"
exit 1
fi
if [[ $2 = "--global" ]]
then
if [[ ! `id -u` = '0' ]]
then
echo "Error: You must be root (system administrator)" \
"to install globally"
exit 1
fi
PLUGINDIR=/usr/share/opendict/plugins
fi
mkdir -p $PLUGINDIR/$1
unzip -d $PLUGINDIR/$1 $1
echo "Done."
opendict-0.6.3/copying.html 0000644 0001750 0001750 00000044731 10500772667 014350 0 ustar mjoc mjoc
The GNU General Public License (GPL)
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
One line to give the program's name and a brief idea of what it does.
Copyright (C) <year> <name of author>
This program 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 2 of the License, or
(at your option) any later version.
This program 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.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
USA
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
signature of Ty Coon, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.
opendict-0.6.3/README.txt 0000644 0001750 0001750 00000002252 10636242135 013470 0 ustar mjoc mjoc --------
OpenDict
--------
Copyright (c) 2003-2006 Martynas Jocius
Copyright (c) 2007 IDILES SYSTEMS, UAB
About
~~~~~
OpenDict is free multiplatform dictionary program. It is made to be
universal and easy to use for desktop users and developers.
Requirements
~~~~~~~~~~~~
- Python >= 2.3
- wxPython 2.6
- python-xml (PyXML)
- gettext >= 0.14
Quick Installation
~~~~~~~~~~~~~~~~~~
OpenDict on UNIX systems can be installed in a quick & dirty way:
# make install
If you get "cp: cannot stat `messages.pot': No such file or directory"
you are missing "pygettext" or "pygettext.py". "pygettext.py" in Fedora is
provided by python-tools package.
For Microsft Windows users
~~~~~~~~~~~~~~~~~~~~~~~~~~
MS Windows users should download setup with precompiled OpenDict version.
If you want to use it from sources, download and install Python, PyXML
and wxPython packages. Then unpack compressed OpenDict ZIP archive and
click on opendict.py icon.
Help
~~~~
For more information visit http://opendict.idiles.com.
opendict-0.6.3/opendict.py 0000755 0001750 0001750 00000014334 10640522715 014160 0 ustar mjoc mjoc #!/usr/bin/env python
# -*- coding: iso-8859-1 -*-
# OpenDict
# Copyright (c) 2003-2006 Martynas Jocius
# Copyright (c) 2007 IDILES SYSTEMS, UAB
#
# This program 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 2 of the License, or
# (at your opinion) any later version.
#
# This program is distributed in the hope that will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MECHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more detals.
#
# You shoud have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
# 02111-1307 USA
import sys
import os
import imp
import traceback
import string
import time
# main_is_frozen() returns True when running the exe, and False when
# running from a script.
def main_is_frozen():
return (hasattr(sys, "frozen") or # new py2exe
hasattr(sys, "importers") # old py2exe
or imp.is_frozen("__main__")) # tools/freeze
# If application is not frozen to binary, try selecting wxPython 2.6 or 2.5
# on multiversioned wxPython installation.
if not main_is_frozen():
try:
import wxversion
wxversion.select(["2.5", "2.6-unicode", "2.8-unicode"])
except Exception, e:
print "You seem to have wxPython 2.4: %s" \
% e
try:
import wx
except ImportError:
print >> sys.stderr, "**"
print >> sys.stderr, "** Error: wxPython library not found"
print >> sys.stderr, "** Please install wxPython 2.5 or later to run OpenDict"
print >> sys.stderr, "**"
sys.exit(1)
try:
import xml.dom.ext
except ImportError:
print >> sys.stderr, "**"
print >> sys.stderr, "** Error: Python/XML library not found"
print >> sys.stderr, "** Please install python-xml (PyXML) to run OpenDict"
print >> sys.stderr, "**"
sys.exit(1)
# get_main_dir() returns the directory name of the script or the
# directory name of the exe
def get_main_dir():
if main_is_frozen():
return os.path.dirname(sys.executable)
return os.path.dirname(os.path.realpath(__file__))
# or return os.path.dirname(sys.argv[0])
#
# Initial path
#
sys.path.insert(0, get_main_dir())
# OpenDict Modules
from lib import info
from lib.gui.mainwin import MainWindow
from lib.gui.errorwin import ErrorWindow
from lib.config import Configuration
from lib.logger import systemLog, debugLog, DEBUG, INFO, WARNING, ERROR
from lib import misc
from lib import info
from lib import newplugin
from lib import plaindict
from lib import util
class OpenDictApp(wx.App):
"""Top-level class of wxWidgets application"""
locale = wx.Locale()
def OnInit(self):
_ = wx.GetTranslation
_start = time.time()
wx.Version = []
try:
wx.Version = wx.__version__
except Exception, e:
try:
wx.Version = wx.Python.__version__
except:
pass
if wx.Version.split('.') < ['2', '6']:
from lib.gui import errorwin
# Go away, wxPython 2.4!
title = _("wxPython Version Error")
msg = _("wxPython %s is installed on this system.\n\n"
"OpenDict %s requires wxPython 2.6 to run smoothly.\n\n"
"You can find wxPython 2.6 at "
"http://www.wxpython.org or you can "
"install it using your system package manager.") \
% (wx.Version, info.VERSION)
errorwin.showErrorMessage(title, msg)
return False
util.makeDirectories()
systemLog(DEBUG, "Unicode version: %s" % wx.USE_UNICODE)
# Init gettext support
wx.Locale_AddCatalogLookupPathPrefix(os.path.join(info.GLOBAL_HOME,
'po'))
self.locale.Init(wx.LANGUAGE_DEFAULT)
self.locale.AddCatalog('opendict')
# Data cache instance
self.cache = {}
# Dictionaries container
# Mapping: name -> object
self.dictionaries = {}
# Failed dictionaries.
# For error message that may be shown after creating main window
self.invalidDictionaries = []
self.config = Configuration()
self.config.load()
self.agreements = util.AgreementsManager(os.path.join(info.LOCAL_HOME,
'agreements.txt'))
# Set unique ids
for plugin in newplugin.loadDictionaryPlugins(self.dictionaries,
self.invalidDictionaries):
self.config.ids[wx.NewId()] = plugin.getName()
for plain in plaindict.loadPlainDictionaries(self.dictionaries):
self.config.ids[wx.NewId()] = plain.getName()
for d in self.dictionaries.values():
if not self.config.activedict.init:
if not self.config.activedict.enabled(d.getName()):
d.setActive(active=False)
else:
# Fill up with names if not initialized yet
self.config.activedict.add(d.getName())
windowPos = (int(self.config.get('windowPosX')),
int(self.config.get('windowPosY')))
windowSize = (int(self.config.get('windowWidth')),
int(self.config.get('windowHeight')))
self.window = MainWindow(None, -1, "OpenDict",
windowPos,
windowSize,
style=wx.DEFAULT_FRAME_STYLE)
try:
systemLog(INFO, "OpenDict %s" % info.VERSION)
systemLog(INFO, "wxPython %s" % wx.Version)
systemLog(INFO, "Global home: %s:" % info.GLOBAL_HOME)
systemLog(INFO, "Local home: %s" % info.LOCAL_HOME)
systemLog(DEBUG, "Loaded in %f seconds" % (time.time() - _start))
except Exception, e:
print "Logger Error: Unable to write to log (%s)" % e
self.window.Show(True)
return True
if __name__ == "__main__":
openDictApp = OpenDictApp(0)
openDictApp.MainLoop()
opendict-0.6.3/opendict.1 0000644 0001750 0001750 00000002075 10636242135 013664 0 ustar mjoc mjoc .TH OPENDICT 1 "2005-11-02"
.\" --------------------------------------------------------
.SH NAME
opendict \- computer dictionary with several dictionary format support
.\" --------------------------------------------------------
.SH SYNOPSIS
.B opendict
.sp
or select
.B Dictionary OpenDict
from the
.B Utility
submenu of the Applications menu if using Gnome Desktop Environment.
.\" --------------------------------------------------------
.SH DESCRIPTION
.B OpenDict
is a free cross-platform dictionary program.
It works with DICT, Slowo and Mova dictionaries. It also supports plug-in
dictionaries that may be created for almost any data source. OpenDict is a
client for DICT servers.
.\" --------------------------------------------------------
.SH SEE ALSO
.BR http://opendict.idiles.com
.\" --------------------------------------------------------
.SH AUTHORS
.B
opendict
was written by Martynas Jocius .
.ad l
This manual page was written by Kestutis Biliunas
.nh
,
.hy
for the Debian system (but may be used by others).
opendict-0.6.3/pixmaps/ 0000755 0001750 0001750 00000000000 10654057460 013457 5 ustar mjoc mjoc opendict-0.6.3/pixmaps/SVG/ 0000755 0001750 0001750 00000000000 10654057460 014116 5 ustar mjoc mjoc opendict-0.6.3/pixmaps/SVG/icon.svg 0000644 0001750 0001750 00000015715 10500772667 015603 0 ustar mjoc mjoc
opendict-0.6.3/pixmaps/SVG/icon-rune.svg 0000644 0001750 0001750 00000016064 10500772667 016550 0 ustar mjoc mjoc
opendict-0.6.3/pixmaps/icon-96x96.png 0000644 0001750 0001750 00000017621 10500772667 015732 0 ustar mjoc mjoc PNG
IHDR ` ` w8 bKGD pHYs tIME(먧 IDATxyt\w?ڵ%˶,K4[9M3=4i grN@L7K tHB =lj]Rm?$UJd[r*{~{ʚX w-I+x}B` ځN@?>
|&둸ŅtP@P eI2*T
!ohmRV5b0(blt"7M$X\UqUeKіHw,[MRlY
*ʥVgRPX@<G XP˔sLD